BiotSavart Subroutine

public subroutine BiotSavart(n_positions, xyz, n_points, coil_points, prefactor, B)

Uses

  • proc~~biotsavart~~UsesGraph proc~biotsavart BiotSavart module~modgvec_globals MODgvec_Globals proc~biotsavart->module~modgvec_globals iso_fortran_env iso_fortran_env module~modgvec_globals->iso_fortran_env

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

Arguments

Type IntentOptional 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.


Calls

proc~~biotsavart~~CallsGraph proc~biotsavart BiotSavart interface~cross CROSS proc~biotsavart->interface~cross interface~cross->interface~cross

Source Code

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