First EM pusher

First implementation of Electromagnetic pusher.

Some testing is still required.

Documentation needs to be upgraded to match the changes in this branch.
This commit is contained in:
Jorge Gonzalez 2022-04-09 08:57:06 +02:00
commit 8006f9d768
13 changed files with 331 additions and 57 deletions

View file

@ -27,7 +27,7 @@ MODULE moduleSolver
INTERFACE
!Push a particle
PURE SUBROUTINE push_interafece(part, tauIn)
SUBROUTINE push_interafece(part, tauIn)
USE moduleSpecies
TYPE(particle), INTENT(inout):: part
@ -80,7 +80,10 @@ MODULE moduleSolver
self%pushParticle => pushCartNeutral
CASE('Electrostatic')
self%pushParticle => pushCartCharged
self%pushParticle => pushCartElectrostatic
CASE('Electromagnetic')
self%pushParticle => pushCartElectromagnetic
CASE DEFAULT
CALL criticalError('Pusher ' // pusherType // ' not found for Cart','initPusher')
@ -88,22 +91,17 @@ MODULE moduleSolver
END SELECT
CASE('Cyl')
IF (self%dimen == 2) THEN
SELECT CASE(pusherType)
CASE('Neutral')
self%pushParticle => push2DCylNeutral
SELECT CASE(pusherType)
CASE('Neutral')
self%pushParticle => push2DCylNeutral
CASE('Electrostatic')
self%pushParticle => push2DCylCharged
CASE('Electrostatic')
self%pushParticle => push2DCylElectrostatic
CASE DEFAULT
CALL criticalError('Pusher ' // pusherType // ' not found for Cyl','initPusher')
CASE DEFAULT
CALL criticalError('Pusher ' // pusherType // ' not found for Cyl','initPusher')
END SELECT
END IF
END SELECT
END SELECT
CASE('Rad')
SELECT CASE(pusherType)
@ -111,7 +109,7 @@ MODULE moduleSolver
self%pushParticle => push1DRadNeutral
CASE('Electrostatic')
self%pushParticle => push1DRadCharged
self%pushParticle => push1DRadElectrostatic
CASE DEFAULT
CALL criticalError('Pusher ' // pusherType // ' not found for Rad','initPusher')
@ -134,7 +132,7 @@ MODULE moduleSolver
CHARACTER(:), ALLOCATABLE:: EMType
SELECT CASE(EMType)
CASE('Electrostatic')
CASE('Electrostatic','ConstantB')
self%solveEM => solveElecField
END SELECT
@ -191,56 +189,71 @@ MODULE moduleSolver
TYPE(particle), INTENT(inout):: part
REAL(8), INTENT(in):: tauIn
TYPE(particle):: part_temp
part_temp = part
!x
part_temp%v(1) = part%v(1)
part_temp%r(1) = part%r(1) + part_temp%v(1)*tauIn
!y
part_temp%v(2) = part%v(2)
part_temp%r(2) = part%r(2) + part_temp%v(2)*tauIn
!z
part_temp%v(3) = part%v(3)
part_temp%r(3) = part%r(3) + part_temp%v(3)*tauIn
part = part_temp
part%r = part%r + part%v*tauIn
END SUBROUTINE pushCartNeutral
!Push charged particles in 3D cartesian coordinates
PURE SUBROUTINE pushCartCharged(part, tauIn)
PURE SUBROUTINE pushCartElectrostatic(part, tauIn)
USE moduleSPecies
USE moduleEM
IMPLICIT NONE
TYPE(particle), INTENT(inout):: part
REAL(8), INTENT(in):: tauIn
TYPE(particle):: part_temp
REAL(8):: qmEFt(1:3)
part_temp = part
!Get the electric field at particle position
qmEFt = part_temp%qm*gatherElecField(part_temp)*tauIn
qmEFt = part%qm*gatherElecField(part)*tauIn
!x
part_temp%v(1) = part%v(1) + qmEFt(1)
part_temp%r(1) = part%r(1) + part_temp%v(1)*tauIn
!Update velocity
part%v = part%v + qmEFt
!y
part_temp%v(2) = part%v(2) + qmEFt(2)
part_temp%r(2) = part%r(2) + part_temp%v(2)*tauIn
!Update position
part%r = part%r + part%v*tauIn
!z
part_temp%v(3) = part%v(3) + qmEFt(3)
part_temp%r(3) = part%r(3) + part_temp%v(3)*tauIn
END SUBROUTINE pushCartElectrostatic
part = part_temp
SUBROUTINE pushCartElectromagnetic(part, tauIn)
USE moduleSPecies
USE moduleEM
USE moduleMath
IMPLICIT NONE
END SUBROUTINE pushCartCharged
TYPE(particle), INTENT(inout):: part
REAL(8), INTENT(in):: tauIn
REAL(8):: tauInHalf
REAL(8):: qmEFt(1:3)
REAL(8):: B(1:3), BNorm
REAL(8):: fn
REAL(8):: v_minus(1:3), v_prime(1:3), v_plus(1:3)
tauInHalf = tauIn *0.5D0
!Half of the force o f the electric field
qmEFt = part%qm*gatherElecField(part)*tauInHalf
!Half step for electrostatic
v_minus = part%v + qmEFt
!Full step rotation
B = gatherMagnField(part)
BNorm = NORM2(B)
IF (BNorm > 0.D0) THEN
fn = DTAN(part%qm * tauInHalf*BNorm) / Bnorm
v_prime = v_minus + fn * crossProduct(v_minus, B)
v_plus = v_minus + 2.D0 * fn / (1.D0 + fn**2 * B**2)*crossProduct(v_prime, B)
PRINT *, v_minus, v_plus
END IF
!Half step for electrostatic
part%v = v_plus + qmEFt
!Update position
part%r = part%r + part%v*tauIn
END SUBROUTINE pushCartElectromagnetic
!Push one particle. Boris pusher for 2D Cyl Neutral particle
PURE SUBROUTINE push2DCylNeutral(part, tauIn)
@ -279,8 +292,8 @@ MODULE moduleSolver
END SUBROUTINE push2DCylNeutral
!Push one particle. Boris pusher for 2D Cyl Charged particle
PURE SUBROUTINE push2DCylCharged(part, tauIn)
!Push one particle. Boris pusher for 2D Cyl Electrostatic particle
PURE SUBROUTINE push2DCylElectrostatic(part, tauIn)
USE moduleSpecies
USE moduleEM
IMPLICIT NONE
@ -318,7 +331,7 @@ MODULE moduleSolver
!Copy temporal particle to particle
part=part_temp
END SUBROUTINE push2DCylCharged
END SUBROUTINE push2DCylElectrostatic
!Push one particle. Boris pusher for 1D Radial Neutral particle
PURE SUBROUTINE push1DRadNeutral(part, tauIn)
@ -355,8 +368,8 @@ MODULE moduleSolver
END SUBROUTINE push1DRadNeutral
!Push one particle. Boris pusher for 1D Radial Charged particle
PURE SUBROUTINE push1DRadCharged(part, tauIn)
!Push one particle. Boris pusher for 1D Radial Electrostatic particle
PURE SUBROUTINE push1DRadElectrostatic(part, tauIn)
USE moduleSpecies
USE moduleEM
IMPLICIT NONE
@ -391,7 +404,7 @@ MODULE moduleSolver
!Copy temporal particle to particle
part=part_temp
END SUBROUTINE push1DRadCharged
END SUBROUTINE push1DRadElectrostatic
!Dummy pusher for 0D geometry
PURE SUBROUTINE push0D(part, tauIn)