Calculating magnetic field outside a solenoid

AI Thread Summary
The discussion revolves around calculating the magnetic field outside a solenoid using Python code based on the Biot-Savart law. Participants highlight a potential error in the code regarding the z-coordinates of segment endpoints, suggesting that the z_turn variable should change for each segment. The calculated magnetic field values are significantly lower than theoretical predictions, with discrepancies noted as high as 600%. Suggestions include checking the calibration of measurement devices and ensuring proper alignment with the solenoid's magnetic field direction. Overall, the conversation emphasizes the importance of accuracy in both coding and experimental measurements.
Jesper12
Messages
6
Reaction score
1
Homework Statement
Hello, for my Physics project I have to make a python code to calculate the magnetic field intensity outside a solenoid that works in a real life scenario. I used the Biot Savart law but I seem to get results that are higher than experimental results and I cant find whats wrong with my code. Does anyone know if someone has ever done this before?
Relevant Equations
Biot savart law
1739991129363.png

Python:
import numpy as np
# Constants
mu_0 = 4 * np.pi * 1e-7  # Vacuum permeability (T m/A)
# Solenoid Parameters
R = 0.007  # Radius of the solenoid (meters)
L = 0.074  # Length of solenoid (meters)
N = 1709  # Number of turns
num_segments = 500  # Increased for better accuracy
I = 1.01  # Current in Amperes
def biot_savart_element(dl, r_vec):
    """
    Computes the magnetic field contribution dB from a small current segment using Biot-Savart law.
    """
    r_mag = np.linalg.norm(r_vec)
    if r_mag < 1e-9:  # Avoid division by zero
        return np.array([0.0, 0.0, 0.0])
    
    # Compute cross product and magnetic field contribution
    dB = (mu_0 * I / (4 * np.pi)) * np.cross(dl, r_vec) / (r_mag**3)
    return dB
def total_magnetic_field(x_p, y_p, z_p):
    """
    Numerically sums contributions from discrete current elements along the helical solenoid.
    """
    B_total = np.array([0.0, 0.0, 0.0])
    dz_per_turn = L / N  # Vertical spacing per turn
    dphi = 2 * np.pi / num_segments  # Angular step per segment
    
    for n in range(N):  # Loop over turns
        z_turn = -L / 2 + n * dz_per_turn  # Z-position of the turn
        
        for i in range(num_segments):  # Loop over segments in the turn
            phi = i * dphi  # Angular position of the segment
            next_phi = (i + 1) * dphi
            
            # Start and end points of the segment
            start = np.array([
                R * np.cos(phi),
                R * np.sin(phi),
                z_turn
            ])
            end = np.array([
                R * np.cos(next_phi),
                R * np.sin(next_phi),
                z_turn
            ])
            
            dl = end - start  # Differential length vector
            
            # Vector from the segment to the observation point
            r_vec = np.array([x_p, y_p, z_p]) - start
            r_mag = np.linalg.norm(r_vec)
            
            if r_mag < 1e-9:  # Avoid division by zero
                continue
            
            # Add contribution to total magnetic field
            B_total += biot_savart_element(dl, r_vec)
    
    return B_total
# Example: Compute B-field at a point near the solenoid
point = (0.08, 0.125, 0)  # Observation point (x, y, z) in meters
B_vector = total_magnetic_field(*point)
B_magnitude = np.linalg.norm(B_vector)
# Convert to microteslas
B_x, B_y, B_z = B_vector * 1e6  # Convert components to microteslas
B_magnitude_microtesla = B_magnitude * 1e6
print(f"Magnetic field at {point}:")
print(f"Vector form: [{B_x:.2f}, {B_y:.2f}, {B_z:.2f}] μT")
print(f"Magnitude: {B_magnitude_microtesla:.2f} μT")
 
Last edited by a moderator:
Physics news on Phys.org
Jesper12 said:
# Start and end points of the segment
start = np.array([
R * np.cos(phi),
R * np.sin(phi),
z_turn
])
end = np.array([
R * np.cos(next_phi),
R * np.sin(next_phi),
z_turn
])
Shouldn't z_turn change?
 
Steve4Physics said:
Shouldn't z_turn change?
Not sure, I'm not good at coding but asking friends they told me its good like that
 
As a partial check, use your program to compute B at the center of the solenoid (x, y, z) = (0, 0, 0). Compare that to the formula for the B field inside a very long, ideal solenoid with the same number of turns per unit length as your solenoid.
 
  • Like
Likes Steve4Physics
Please use Latex for easier reading.
 
Jesper12 said:
Not sure, I'm not good at coding but asking friends they told me its good like that
But in Post #1 you said "For my Physics project I have to make a python code to calculate..."! Who wrote the code?

It appears that the program calculates the individual field-contributions from lots of individual current-elements ('segments'). Each segment is treated as a vector with:
- the coordinates of one end: (R * np.cos(phi), R * np.sin(phi), z_turn)
- the coordinates of the other end: (R * np.cos(next_phi), R * np.sin(next_phi), z_turn)

Assuming the solenoid's axis is the z axis, this doesn’t seem correct because the z-coordinates of the two ends will be different. Don’t rely on friends – it’s your project.

However, the effect of this on the final answer may be small, so this may be an error but not the main cause of your problem.
______________

@TSny's suggestion in Post #4 is good practice. Checking your program agasinst experimental results has risks - the experimental results may not be accurate.

It would be interesting to know how big the discrepancy is - a few percent or larger?
 
Hello Jesper, :welcome:

First of all: you want to enclose your python with ##[##code=python##]## .... ##[##/code##]##
so that spacing is conserved. It took me several hours to get it fixed from what you posted.
As a check, I ran your program with a few changes in the parameters:
Python:
...
# Solenoid Parameters
R = 0.007 # Radius of the solenoid (meters)
L = 0.0 # Length of solenoid (meters)
N = 1709 # Number of turns
num_segments = 100 # Increased for better accuracy
I = 1.01# Current in Amperes
...
# Example: Compute B-field at origin
point = (0.0, 0.0, 0) # Observation point (x, y, z) in meters

to get something I could compare with a formula for the field at the center of a current loop ##\displaystyle B = {\mu_0 NI\over 2 R}##, 0.155 Tesla

It came back with
Code:
Magnetic field at (0.0, 0.0, 0):
Vector form: [0.00, 0.00, 154831.55] μT
Magnitude: 154831.55 μT

So that's not bad at all !

You example has
Python:
# Solenoid Parameters
R = 0.007 # Radius of the solenoid (meters)
L = 0.074 # Length of solenoid (meters)
N = 1709 # Number of turns
num_segments = 100 # Increased for better accuracy
I = 1.01# Current in Amperes
....
# Example: Compute B-field at a point near the solenoid
point = (0.08, 0.125, 0) # Observation point (x, y, z) in meters
...
Which isn't really close to the solenoid at all ! It yields
Code:
Magnetic field at (0.08, 0.125, 0):
Vector form: [0.00, 0.00, -7.44] μT
Magnitude: 7.44 μT
which may well be correct, theoretically.
But it's a lot less than the earth magnetic field (##\approx## 50 μT) so I find it
very strange that your measurements show even less ...

a few more runs:
Code:
Magnetic field at (0.0, 0.0, 0.1):
Vector form: [0.00, 0.00, 70.44] μT
Magnitude: 70.44 μT

Magnetic field at (0.0, 0.0, 0.0):
Vector form: [0.00, 0.00, 28781.90] μT
Magnitude: 28781.90 μT


##\ ##
 
Last edited:
Steve4Physics said:
Shouldn't z_turn change?
It does !
Python:
    for n in range(N): # Loop over turns
        z_turn = -L / 2 + n * dz_per_turn # Z-position of the turn

##\ ##
 
BvU said:
It does !
Python:
    for n in range(N): # Loop over turns
        z_turn = -L / 2 + n * dz_per_turn # Z-position of the turn
Yes, that loop increments z_turn. But then, in the following nested loop:
Python:
for i in range(num_segments)
z_turn is constant and is incorrectly used as the z-cooordinate of the ends of each segment of the turn, which I believe is incorrect.

Ideally there should be 2 variables for the z-coordinates of the start and end of a segment. And these should be incremented inside the inner loop. But the single value of z_turn, from the outer loop, is incorrectly used for each segment.

However, this will only introduce a small error for closely spaced coils - it could even be a deliberate simplification since the z-coodinates of segments on the same turn are very similar (if the turns are closely spaced).

EDIT. It might be better to have variables z_segment and dz_per_segment. Then it would be consistent with the way phi is handled.
 
Last edited:
  • #10
Steve4Physics said:
But in Post #1 you said "For my Physics project I have to make a python code to calculate..."! Who wrote the code?

It appears that the program calculates the individual field-contributions from lots of individual current-elements ('segments'). Each segment is treated as a vector with:
- the coordinates of one end: (R * np.cos(phi), R * np.sin(phi), z_turn)
- the coordinates of the other end: (R * np.cos(next_phi), R * np.sin(next_phi), z_turn)

Assuming the solenoid's axis is the z axis, this doesn’t seem correct because the z-coordinates of the two ends will be different. Don’t rely on friends – it’s your project.

However, the effect of this on the final answer may be small, so this may be an error but not the main cause of your problem.
______________

@TSny's suggestion in Post #4 is good practice. Checking your program agasinst experimental results has risks - the experimental results may not be accurate.

It would be interesting to know how big the discrepancy is - a few percent or larger?
Discrepancy is six times lower than the theoretical value so 600%. It's consistent though, so I guess if I can't find a solution I could call it a systematic error, but I can't seem to understand why.
 
  • #11
Jesper12 said:
Discrepancy is six times lower than the theoretical value so 600%. It's consistent though, so I guess if I can't find a solution I could call it a systematic error, but I can't seem to understand why.
This description confuses me... For clarity: can you confirm you calculate 7.4 μT with the program in #1, and that you measure 1.2 μT ?

Perhaps you have more measurements (along the z-axis, for example, where the field is stronger) ?
And: what do you do to eliminate (or compensate for) the earth magnetic field ?

##\ ##
 
  • #12
BvU said:
This description confuses me... For clarity: can you confirm you calculate 7.4 μT with the program in #1, and that you measure 1.2 μT ?

Perhaps you have more measurements (along the z-axis, for example, where the field is stronger) ?
And: what do you do to eliminate (or compensate for) the earth magnetic field ?

##\ ##
To compensate earths magnetic field im just taking the difference of the intial intensity and final intensity. I do get 1.22 μT with this measurement, I'm not doing measurements along the z axis because I'm just stuyding the effect in 2D, so x and y. The solenoid is lying on its side and im measuring in the same plane. I think thats where the issue could be but I can't find a way to tackle it, the fact that its 6 times higher in every measurement throws me off. For every other measurement where the y distance is changed and x is kept constant theoretical values are always 6 times higher.
 
  • #13
@Jesper12, a couple of thoughts.

Can you check the calibration of your detector (some sort of Hall probe?)? Or maybe try with a different detector?

Are you aligning the axis of the detector with the (estimated) direction of the solenoid's field at the position of interest? If not, you will only be measuring a component of the solenoid's field.
 
  • #14
Steve4Physics said:
@Jesper12, a couple of thoughts.

Can you check the calibration of your detector (some sort of Hall probe?)? Or maybe try with a different detector?

Are you aligning the axis of the detector with the (estimated) direction of the solenoid's field at the position of interest? If not, you will only be measuring a component of the solenoid's field.
I used my phone and phyphox since the magnetometer has a 0,01 μT accuracy. Distance may be a few milimeters off since I measured distance to the front of the phone and magnetometer is in the front camera piece, exact placement isnt released to the public. I dont think its an experimental issue since the error should vary when taking different measurements if I'm not mistaken. The solenoid is on its side and the phone is looking at its side. I used the absolute value measurement it gives but didn't check whether or not the individual components aligned with the ones in the code. I will experiment again and check that.
 
Last edited:
  • #15
Jesper12 said:
I used my phone and phyphox since the magnetometer has a 0,01 μT accuracy. Distance may be a few milimeters off since I measured distance to the front of the phone and magnetometer is in the front camera piece,
The radius of your solenoid is 7mm, so a few mm error can introoduce a significant error (though probably not a consistent factor of 6).

Make sure there are no ferrous objects or sources of unwanted magnetic fields near you.

Look-up the magnitude and direction of the earth's field at your location (Google search). Try different orientations of your phone to measure the earth's field at your location. The orientation which gives the largest reading is needed (and that roughly tells you the direction of your magnetometer axis). See if your largest reading agrees with the looked-up value. Maybe the reading will be out by a factor of 6-ish indicating the absolute calibration of your phone's magnetometer is incorrect (quite possible IMO).

Jesper12 said:
exact placement isnt released to the public. I dont think its an experimental issue since the error should vary when taking different measurements if I'm not mistaken. The solenoid is on its side and the phone is looking at its side.
The solenoid's field is something like this:

1740064766748.gif

(from ar.inspiredpencil.com)

Your phone's magnetometer needs to be correctly aligned parallel with the field. You might be 90-ish degrees off if you simply point the phone at the side of the solenoid. You need to check.

Note that if the earth's field and the solenoid's field at the position of interest have different directions, you need to allow for this: you need the difference in readings (solenoid on/off) taken with the phone aligned with the solenoid's field.

If all that makes sense!
 
  • #16
Steve4Physics said:
The radius of your solenoid is 7mm, so a few mm error can introoduce a significant error (though probably not a consistent factor of 6).

Make sure there are no ferrous objects or sources of unwanted magnetic fields near you.

Look-up the magnitude and direction of the earth's field at your location (Google search). Try different orientations of your phone to measure the earth's field at your location. The orientation which gives the largest reading is needed (and that roughly tells you the direction of your magnetometer axis). See if your largest reading agrees with the looked-up value. Maybe the reading will be out by a factor of 6-ish indicating the absolute calibration of your phone's magnetometer is incorrect (quite possible IMO).


The solenoid's field is something like this:

View attachment 357569
(from ar.inspiredpencil.com)

Your phone's magnetometer needs to be correctly aligned parallel with the field. You might be 90-ish degrees off if you simply point the phone at the side of the solenoid. You need to check.

Note that if the earth's field and the solenoid's field at the position of interest have different directions, you need to allow for this: you need the difference in readings (solenoid on/off) taken with the phone aligned with the solenoid's field.

If all that makes sense!
Thank you! That does make a lot of sense actually, when I did the measurements earth's magnetic field was arond 38 microteslas and It could get up to 65, so maybe that has to do with it. Also, it is true that when tilting the phone when testing with earth's field it went up or down depending on the orientation (absolute value), I didn't think of that. I will definitely check that, thank you for the help!
 

Similar threads

Back
Top