calculate_magnetic_field Subroutine

public subroutine calculate_magnetic_field(params, Y, F, B, E, PSI_P, flag)

@brief Subroutine that calculates the axisymmetric magnetic field to the particles' position using the poloidal magnetic flux. @details When the poloidal magnetic flux is used in a KORC simulation, the magnetic field components are calculated as it follows:

where and are the radial position of the magnetic axis and the magnetic field as measured at the magnetic axis, respectively. First, the derivatives of the poloidal magnetic flux are calculated at the particles' position using the PSPLINE interpolant of the poloidal magnetic flux. Then, we calculate the cylindrical components of the magnetic field, and finally we calculate its Cartesian components that will be used in the particle pusher.

@param[in] Y Particles' position in cylindrical coordinates, Y(1,:) = , Y(2,:) = , and Y(3,:) = . @param[in] F An instance of KORC's derived type FIELDS containing all the information about the fields used in the simulation. See korc_types.f90 and korc_fields.f90. @param[in,out] B Cartesian components of interpolated magnetic field components. B(1,:)=, B(2,:)=, and B(3,:)=. @param flag Flag that indicates whether particles are followed in the simulation (flag=1), or not (flag=0). @param A Variable containing the partial derivatives of the poloidal magnetic flux and the cylindrical components of the magnetic field (its value changes through the subroutine). @param pp Particle iterator. @param ss Species iterator.

Arguments

Type IntentOptional AttributesName
type(KORC_PARAMS), intent(in) :: params
real(kind=rp), intent(in), DIMENSION(:,:), ALLOCATABLE:: Y
type(FIELDS), intent(in) :: F
real(kind=rp), intent(inout), DIMENSION(:,:), ALLOCATABLE:: B
real(kind=rp), intent(inout), DIMENSION(:,:), ALLOCATABLE:: E
real(kind=rp), intent(inout), DIMENSION(:), ALLOCATABLE:: PSI_P
integer(kind=is), intent(inout), DIMENSION(:), ALLOCATABLE:: flag

Calls

proc~~calculate_magnetic_field~~CallsGraph proc~calculate_magnetic_field calculate_magnetic_field ezspline_error ezspline_error proc~calculate_magnetic_field->ezspline_error

Called by

proc~~calculate_magnetic_field~~CalledByGraph proc~calculate_magnetic_field calculate_magnetic_field proc~interp_fields interp_fields proc~interp_fields->proc~calculate_magnetic_field proc~get_fields get_fields proc~get_fields->proc~interp_fields proc~mh_psi MH_psi proc~mh_psi->proc~get_fields proc~sample_hollmann_distribution_3d_psi sample_Hollmann_distribution_3D_psi proc~sample_hollmann_distribution_3d_psi->proc~get_fields proc~unitvectors unitVectors proc~unitvectors->proc~get_fields proc~get_hollmann_distribution_3d_psi get_Hollmann_distribution_3D_psi proc~get_hollmann_distribution_3d_psi->proc~sample_hollmann_distribution_3d_psi proc~gyro_distribution gyro_distribution proc~gyro_distribution->proc~unitvectors

Contents


Source Code

subroutine calculate_magnetic_field(params,Y,F,B,E,PSI_P,flag)
  TYPE(KORC_PARAMS), INTENT(IN)      :: params
  REAL(rp), DIMENSION(:,:), ALLOCATABLE, INTENT(IN)      :: Y
  TYPE(FIELDS), INTENT(IN)                               :: F
  REAL(rp), DIMENSION(:,:), ALLOCATABLE, INTENT(INOUT)   :: B
  REAL(rp), DIMENSION(:,:), ALLOCATABLE, INTENT(INOUT)   :: E
  REAL(rp), DIMENSION(:), ALLOCATABLE, INTENT(INOUT)   :: PSI_P
  INTEGER(is), DIMENSION(:), ALLOCATABLE, INTENT(INOUT)  :: flag
  REAL(rp), DIMENSION(:,:), ALLOCATABLE                  :: A
  INTEGER                                                :: pp
  INTEGER                                                :: ss
  REAL(rp)  :: psip_conv

  psip_conv=F%psip_conv
  
  if (size(Y,1).eq.1) then
     ss = size(Y,1)
  else
     if (Y(2,1).eq.0) then
        ss=1_idef
     else
        ss = size(Y,1)
     end if
  endif

  ALLOCATE(A(ss,3))
  A=0._rp

  if(F%Dim2x1t.and.(.not.F%ReInterp_2x1t)) then
     !$OMP PARALLEL DO FIRSTPRIVATE(ss) PRIVATE(pp,ezerr) &
     !$OMP& SHARED(F,Y,A,B,flag,bfield_2X1T,PSI_P)
     do pp=1_idef,ss


        !        write(output_unit_write,'("pp: ",I16)') pp

        !        write(output_unit_write,'("Y_R: ",E17.10)') Y(:,1)
        !      write(output_unit_write,'("Y_PHI: ",E17.10)') Y(:,2)
        !      write(output_unit_write,'("Y_Z: ",E17.10)') Y(:,3)


        call EZspline_interp(bfield_2X1T%A, Y(pp,1), F%t0_2x1t, Y(pp,3), &
             PSI_P(pp), ezerr)
        call EZspline_error(ezerr)

        !        write(output_unit_write,'("PSI_P: ",E17.10)') PSI_P(1)

        ! FR = (dA/dZ)/R
        call EZspline_derivative(bfield_2X1T%A, 0, 0, 1, Y(pp,1), F%t0_2x1t, &
             Y(pp,3), A(pp,1), ezerr)
        !			call EZspline_error(ezerr)

        if (ezerr .NE. 0) then ! We flag the particle as lost
           flag(pp) = 0_is
        else

           !           write(output_unit_write,'("R*B_R: ",E17.10)') A(pp,1)

           !if(params%SC_E) A(pp,1)=A(pp,1)/(2*C_PI)

           A(pp,1) = psip_conv*A(pp,1)/Y(pp,1)

           ! FPHI = Fo*Ro/R
           A(pp,2) = -F%Bo*F%Ro/Y(pp,1)

           ! FR = -(dA/dR)/R
           call EZspline_derivative(bfield_2X1T%A, 1, 0, 0, Y(pp,1), &
                F%t0_2x1t, Y(pp,3), A(pp,3), ezerr)
           call EZspline_error(ezerr)

           !           write(output_unit_write,'("R*B_Z: ",E17.10)') A(pp,3)

           !if(params%SC_E) A(pp,3)=A(pp,3)/(2*C_PI)

           call EZspline_derivative(bfield_2X1T%A, 0, 1, 0, Y(pp,1), &
                F%t0_2x1t, Y(pp,3), E(pp,2), ezerr)           

           E(pp,2) = E(pp,2)/(2*C_PI*Y(pp,1)) 
           
           A(pp,3) = -psip_conv*A(pp,3)/Y(pp,1)                    

           if (.not.params%GC_coords) then
              B(pp,1) = A(pp,1)*COS(Y(pp,2)) - A(pp,2)*SIN(Y(pp,2))
              B(pp,2) = A(pp,1)*SIN(Y(pp,2)) + A(pp,2)*COS(Y(pp,2))
              B(pp,3) = A(pp,3)

              E(pp,1) = -E(pp,2)*sin(Y(pp,2))
              E(pp,2) = E(pp,2)*cos(Y(pp,2))
           else
              B(pp,1) = A(pp,1)
              B(pp,2) = A(pp,2)
              B(pp,3) = A(pp,3)              
           end if


        end if
     end do
     !$OMP END PARALLEL DO

     
  else
     !$OMP PARALLEL DO FIRSTPRIVATE(ss) PRIVATE(pp,ezerr) &
     !$OMP& SHARED(F,Y,A,B,flag,bfield_2d,PSI_P)
     do pp=1_idef,ss


        !        write(output_unit_write,'("pp: ",I16)') pp

        !        write(output_unit_write,'("Y_R: ",E17.10)') Y(:,1)
        !      write(output_unit_write,'("Y_PHI: ",E17.10)') Y(:,2)
        !      write(output_unit_write,'("Y_Z: ",E17.10)') Y(:,3)


        call EZspline_interp(bfield_2d%A, Y(pp,1), Y(pp,3), &
             PSI_P(pp), ezerr)
        call EZspline_error(ezerr)

        !        write(output_unit_write,'("PSI_P: ",E17.10)') PSI_P(1)

        ! FR = (dA/dZ)/R
        call EZspline_derivative(bfield_2d%A, 0, 1, Y(pp,1), Y(pp,3), &
             A(pp,1), ezerr)
        !			call EZspline_error(ezerr)

        if (ezerr .NE. 0) then ! We flag the particle as lost
           flag(pp) = 0_is
        else

           !           write(output_unit_write,'("R*B_R: ",E17.10)') A(pp,1)

           !if(params%SC_E) A(pp,1)=A(pp,1)/(2*C_PI)

           A(pp,1) = psip_conv*A(pp,1)/Y(pp,1)

           ! FPHI = Fo*Ro/R
           A(pp,2) = -F%Bo*F%Ro/Y(pp,1)

           ! FR = -(dA/dR)/R
           call EZspline_derivative(bfield_2d%A, 1, 0, Y(pp,1), Y(pp,3), &
                A(pp,3), ezerr)
           call EZspline_error(ezerr)

           !           write(output_unit_write,'("R*B_Z: ",E17.10)') A(pp,3)

           !if(params%SC_E) A(pp,3)=A(pp,3)/(2*C_PI)

           A(pp,3) = -psip_conv*A(pp,3)/Y(pp,1)                    

           if (.not.params%GC_coords) then
              B(pp,1) = A(pp,1)*COS(Y(pp,2)) - A(pp,2)*SIN(Y(pp,2))
              B(pp,2) = A(pp,1)*SIN(Y(pp,2)) + A(pp,2)*COS(Y(pp,2))
              B(pp,3) = A(pp,3)
           else
              B(pp,1) = A(pp,1)
              B(pp,2) = A(pp,2)
              B(pp,3) = A(pp,3)
           end if


        end if
     end do
     !$OMP END PARALLEL DO
  end if

!  write(output_unit_write,'("calculate_fields")')
  
!  write(output_unit_write,'("B_R: ",E17.10)') A(:,1)
!  write(output_unit_write,'("B_PHI: ",E17.10)') A(:,2)
!  write(output_unit_write,'("B_Z: ",E17.10)') A(:,3)

!  write(output_unit_write,'("B_X: ",E17.10)') B(:,1)
!  write(output_unit_write,'("B_Y: ",E17.10)') B(:,2)
!  write(output_unit_write,'("B_Z: ",E17.10)') B(:,3)
  
  DEALLOCATE(A)
end subroutine calculate_magnetic_field