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

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


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

  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(6,'("pp: ",I16)') pp

        !        write(6,'("Y_R: ",E17.10)') Y(:,1)
        !      write(6,'("Y_PHI: ",E17.10)') Y(:,2)
        !      write(6,'("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(6,'("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(6,'("R*B_R: ",E17.10)') A(pp,1)

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

           A(pp,1) = 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(6,'("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) = -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(6,'("pp: ",I16)') pp

        !        write(6,'("Y_R: ",E17.10)') Y(:,1)
        !      write(6,'("Y_PHI: ",E17.10)') Y(:,2)
        !      write(6,'("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(6,'("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(6,'("R*B_R: ",E17.10)') A(pp,1)

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

           A(pp,1) = 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(6,'("R*B_Z: ",E17.10)') A(pp,3)

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

           A(pp,3) = -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(6,'("calculate_fields")')
  
!  write(6,'("B_R: ",E17.10)') A(:,1)
!  write(6,'("B_PHI: ",E17.10)') A(:,2)
!  write(6,'("B_Z: ",E17.10)') A(:,3)

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