-
Antoine Cyril David Hoffmann authoredAntoine Cyril David Hoffmann authored
solve_EM_fields.F90 4.98 KiB
SUBROUTINE solve_EM_fields
! Solve Poisson and Ampere equations
USE model, ONLY : beta
USE basic
USE prec_const
IMPLICIT NONE
CALL poisson
IF(beta .GT. 0._xp) &
CALL ampere
CONTAINS
SUBROUTINE poisson
! Solve poisson equation to get phi
USE time_integration, ONLY: updatetlevel
USE array, ONLY: kernel, inv_poisson_op, inv_pol_ion
USE fields, ONLY: phi, moments
USE grid, ONLY: local_na, local_nky, local_nkx, local_nz,ngz, SOLVE_POISSON,&
kyarray, contains_kx0, contains_ky0,ikx0,iky0, zweights_SR, ieven,&
ip0, total_nj, ngj
USE calculus, ONLY: simpson_rule_z
USE parallel, ONLY: manual_3D_bcast
USE model, ONLY: lambdaD, ADIAB_E , tau_i
use species, ONLY: q
USE processing, ONLY: compute_density
USE geometry, ONLY: iInt_Jacobian, Jacobian
IMPLICIT NONE
INTEGER :: ij, ia, ikx, iky, iz, izi, iji
COMPLEX(xp) :: fsa_phi, intf_ ! current flux averaged phi
COMPLEX(xp), DIMENSION(local_nz) :: rho, integrant ! charge density q_a n_a and aux var
!! Poisson can be solved only for process containng p=0
IF ( SOLVE_POISSON ) THEN
x:DO ikx = 1,local_nkx
y:DO iky = 1,local_nky
!!!!!!!!!!!!!!! Compute particle charge density q_a n_a for each evolved species
DO iz = 1,local_nz
izi = iz+ngz/2
rho(iz) = 0._xp
DO ij = 1,total_nj
iji = ij+ngj/2
DO ia = 1,local_na
rho(iz) = rho(iz) + q(ia)*kernel(ia,iji,iky,ikx,izi,ieven)&
*moments(ia,ip0,iji,iky,ikx,izi,updatetlevel)
END DO
END DO
END DO
!!!!!!!!!!!!!!! adiabatic electron contribution if asked
! Adiabatic charge density (linked to flux surface averaged phi)
! We compute the flux surface average solving a flux surface averaged
! Poisson equation, i.e.
! [qi^2(1-sum_j K_j^2)/tau_i] <phi>_psi = <q_i n_i >_psi
! inv_pol_ion^-1 fsa_phi = simpson(Jacobian rho_i ) * iInt_Jacobian
IF (ADIAB_E) THEN
fsa_phi = 0._xp
IF(kyarray(iky).EQ.0._xp) THEN ! take ky=0 mode (y-average)
! Prepare integrant for z-average
DO iz = 1,local_nz
izi = iz+ngz/2
integrant(iz) = Jacobian(izi,ieven)*rho(iz)*inv_pol_ion(iky,ikx,iz)
ENDDO
call simpson_rule_z(local_nz,zweights_SR,integrant,intf_) ! get the flux averaged phi
fsa_phi = intf_ * iInt_Jacobian !Normalize by 1/int(Jxyz)dz
ENDIF
rho = rho + fsa_phi
ENDIF
!!!!!!!!!!!!!!! Inverting the poisson equation
DO iz = 1,local_nz
izi = iz+ngz/2
phi(iky,ikx,izi) = inv_poisson_op(iky,ikx,iz)*rho(iz)
ENDDO
ENDDO y
ENDDO x
! Cancel origin singularity
IF (contains_kx0 .AND. contains_ky0) phi(iky0,ikx0,:) = 0._xp
ENDIF
! Transfer phi to all the others process along p
CALL manual_3D_bcast(phi,local_nky,local_nkx,local_nz+ngz)
END SUBROUTINE poisson
SUBROUTINE ampere
! Solve ampere equation to get psi
USE time_integration, ONLY: updatetlevel
USE array, ONLY: kernel, inv_ampere_op
USE fields, ONLY: moments, psi
USE grid, ONLY: local_na, local_nky, local_nkx, local_nz,ngz, SOLVE_AMPERE,&
contains_kx0, contains_ky0,ikx0,iky0, iodd,&
ip1, total_nj, ngj
USE parallel, ONLY: manual_3D_bcast
use species, ONLY: sqrt_tau_o_sigma, q
use model, ONLY: beta
IMPLICIT NONE
COMPLEX(xp) :: j_a ! current density
INTEGER :: ij, ia, ikx, iky, iz, iji, izi
!! Ampere can be solved only with beta > 0 and for process containng p=1 moments
IF ( SOLVE_AMPERE ) THEN
z:DO iz = 1,local_nz
izi = iz+ngz/2
x:DO ikx = 1,local_nkx
y:DO iky = 1,local_nky
!!!!!!!!!!!!!!! compute current density contribution "j_a = q_a u_a" for each species
j_a = 0._xp
n:DO ij=1,total_nj
iji = ij+ngj/2
a:DO ia = 1,local_na
j_a = j_a &
+q(ia)*sqrt_tau_o_sigma(ia)*kernel(ia,iji,iky,ikx,izi,iodd)*moments(ia,ip1,iji,iky,ikx,izi,updatetlevel)
ENDDO a
ENDDO n
!!!!!!!!!!!!!!! Inverting the Ampere equation
psi(iky,ikx,iz+ngz/2) = beta*inv_ampere_op(iky,ikx,iz)*j_a
ENDDO y
ENDDO x
ENDDO z
ENDIF
! Cancel origin singularity
IF (contains_kx0 .AND. contains_ky0) psi(iky0,ikx0,:) = 0._xp
! Transfer phi to all the others process along p
CALL manual_3D_bcast(psi,local_nky,local_nkx,local_nz+ngz)
END SUBROUTINE ampere
END SUBROUTINE solve_EM_fields