Evaluate the magnetic field of a current loop discretized via line-segments.
The segments are defined by a list of coil_points, each segment being defined between points (i,i+1).
For a closed loop, the last point in the list is a repetition of the first point.
Each line segment is evaluated via the analytic compact Biot-Savart expression from
Hanson and Hirshman (2002) (https://doi.org/10.1063/1.1507589).
This implementation parallelizes over the number of evaluation positions n_positions.
RidotRf = SUM(R_iR_f) ; RixRf(:) = CROSS(R_i, R_f) segment_factor = (mod_R_i+mod_R_f)/(mod_R_imod_R_f(mod_R_imod_R_f+RidotRf)) B(:,iPosition) = B(:,iPosition)+segment_factor*RixRf
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | n_positions |
number of positions where the magnetic field is evaluated |
||
| real(kind=wp), | intent(in) | :: | xyz(3,n_positions) |
x,y,z positions where the magnetic field is evaluated |
||
| integer, | intent(in) | :: | n_points |
number of points representing the segmented coil |
||
| real(kind=wp), | intent(in) | :: | coil_points(3,n_points) |
x,y,z positions of the segment chain (=polygon), n_segments=n_points-1 |
||
| real(kind=wp), | intent(in) | :: | prefactor |
factor applied to the final magnetic field |
||
| real(kind=wp), | intent(out) | :: | B(3,n_positions) |
magnetic field evaluated at xyz positions. |
SUBROUTINE BiotSavart(n_positions, xyz, n_points, coil_points, prefactor, B) ! MODULES USE MODgvec_Globals, ONLY: TWOPI,CROSS,wp ! INPUT VARIABLES -----------------------------------------------------------------------------------------------------------! INTEGER, INTENT(IN) :: n_positions !! number of positions where the magnetic field is evaluated REAL(wp), INTENT(IN) :: xyz(3,n_positions) !! x,y,z positions where the magnetic field is evaluated INTEGER, INTENT(IN) :: n_points !! number of points representing the segmented coil REAL(wp), INTENT(IN) :: coil_points(3,n_points) !! x,y,z positions of the segment chain (=polygon), n_segments=n_points-1 REAL(wp), INTENT(IN) :: prefactor !! factor applied to the final magnetic field ! OUTPUT VARIABLES ----------------------------------------------------------------------------------------------------------! REAL(wp), INTENT(OUT):: B(3,n_positions) !! magnetic field evaluated at xyz positions. ! LOCAL VARIABLES -----------------------------------------------------------------------------------------------------------! INTEGER :: iPosition,iSegment,n_segments REAL(wp) :: R_i(3) !! vector from current position to starting point of segment REAL(wp) :: R_f(3) !! vector from current position to end point of segment (=starting point of next segment) REAL(wp) :: mod_R_i,mod_R_f ! CODE ----------------------------------------------------------------------------------------------------------------------! n_segments = n_points-1 B = 0.0_wp !$OMP PARALLEL DO & !$OMP SCHEDULE(STATIC) DEFAULT(PRIVATE) SHARED(xyz, coil_points, n_positions, n_segments) & !$OMP REDUCTION(+:B) DO iPosition=1,n_positions R_f = xyz(:,iPosition)-coil_points(:,1) mod_R_f= SQRT(SUM(R_f*R_f)) DO iSegment=1,n_segments R_i = R_f mod_R_i = mod_R_f R_f = xyz(:,iPosition)-coil_points(:,iSegment+1) mod_R_f = SQRT(SUM(R_f*R_f)) !! RidotRf = SUM(R_i*R_f) ; RixRf(:) = CROSS(R_i, R_f) !! segment_factor = (mod_R_i+mod_R_f)/(mod_R_i*mod_R_f*(mod_R_i*mod_R_f+RidotRf)) !! B(:,iPosition) = B(:,iPosition)+segment_factor*RixRf B(:,iPosition) = B(:,iPosition)+((mod_R_i+mod_R_f)/(mod_R_i*mod_R_f*(mod_R_i*mod_R_f+SUM(R_i*R_f))))*CROSS(R_i, R_f) END DO !iSegment END DO !iPosition !$OMP END PARALLEL DO B = prefactor*B END SUBROUTINE BiotSavart