First version with possibility for charged particles to be included.
Now, the solver needs to be an input parameter of the case, to select if it is for charged or neutral particles. Resolution of Poisson equation with Dirichlet boundary conditions is possible. The source vector is the charge density. This resolution is done in two steps to save computational time: 1. When reading the mesh, the PLU factorization of the K matrix is computed. 2. In each iteration, the system K*u = f is solved, in which f is the source vector (charge density) and u is the solution (potential) in each node. No case has been added to the repository. This will be done in next commit. The 'non-analog' scheme has been commented. It still needs to split the particle to avoid 'overweight' particles.
This commit is contained in:
parent
73fc9f69c1
commit
c82279f5c5
20 changed files with 859 additions and 227 deletions
|
|
@ -1,5 +1,44 @@
|
|||
MODULE moduleSolver
|
||||
|
||||
TYPE, PUBLIC, ABSTRACT:: solverGeneric
|
||||
CONTAINS
|
||||
PROCEDURE(push_interafece), DEFERRED, NOPASS:: push
|
||||
PROCEDURE(solveEM_interface), DEFERRED, NOPASS:: solveEMField
|
||||
|
||||
END TYPE solverGeneric
|
||||
|
||||
ABSTRACT INTERFACE
|
||||
!Push a particle
|
||||
PURE SUBROUTINE push_interafece(part)
|
||||
USE moduleSpecies
|
||||
|
||||
TYPE(particle), INTENT(inout):: part
|
||||
|
||||
END SUBROUTINE push_interafece
|
||||
|
||||
!Solve the electromagnetic field
|
||||
SUBROUTINE solveEM_interface()
|
||||
|
||||
END SUBROUTINE solveEM_interface
|
||||
|
||||
END INTERFACE
|
||||
|
||||
TYPE, PUBLIC, EXTENDS(solverGeneric):: solverCylNeutral
|
||||
CONTAINS
|
||||
PROCEDURE, NOPASS:: push => pushCylNeutral
|
||||
PROCEDURE, NOPASS:: solveEMField => noEMField
|
||||
|
||||
END TYPE solverCylNeutral
|
||||
|
||||
TYPE, PUBLIC, EXTENDS(solverGeneric):: solverCylCharged
|
||||
CONTAINS
|
||||
PROCEDURE, NOPASS:: push => pushCylCharged
|
||||
PROCEDURE, NOPASS:: solveEMField => solveElecField
|
||||
|
||||
END TYPE solverCylCharged
|
||||
|
||||
CLASS(solverGeneric), ALLOCATABLE:: solver
|
||||
|
||||
CONTAINS
|
||||
SUBROUTINE doPushes()
|
||||
USE moduleSpecies
|
||||
|
|
@ -10,7 +49,9 @@ MODULE moduleSolver
|
|||
|
||||
!$OMP DO
|
||||
DO n=1, nPartOld
|
||||
CALL push(partOld(n))
|
||||
!Push particle
|
||||
CALL solver%push(partOld(n))
|
||||
!Find cell in wich particle reside
|
||||
CALL mesh%vols(partOld(n)%e_p)%obj%findCell(partOld(n))
|
||||
|
||||
END DO
|
||||
|
|
@ -18,16 +59,15 @@ MODULE moduleSolver
|
|||
|
||||
END SUBROUTINE doPushes
|
||||
|
||||
!Push one particle. Boris pusher for 2D Cyl
|
||||
!TODO: make general for any pusher
|
||||
PURE SUBROUTINE push(part)
|
||||
!Push one particle. Boris pusher for 2D Cyl Neutral particle
|
||||
PURE SUBROUTINE pushCylNeutral(part)
|
||||
USE moduleSpecies
|
||||
USE moduleMesh
|
||||
IMPLICIT NONE
|
||||
|
||||
TYPE(particle), INTENT(inout):: part
|
||||
REAL(8):: v_p_oh_star(2:3)
|
||||
TYPE(particle):: part_temp
|
||||
REAL(8):: x_new, y_new, r, sin_alpha, cos_alpha, alpha
|
||||
REAL(8):: x_new, y_new, r, sin_alpha, cos_alpha
|
||||
|
||||
part_temp = part
|
||||
!z
|
||||
|
|
@ -40,8 +80,6 @@ MODULE moduleSolver
|
|||
y_new = v_p_oh_star(3)*tau
|
||||
r = DSQRT(x_new**2+y_new**2)
|
||||
part_temp%r(2) = r
|
||||
alpha = 0.D0!ATAN2(y_new,x_new) !0 in 2D problem
|
||||
part_temp%r(3) = part%r(3) + alpha
|
||||
IF (r > 0.D0) THEN
|
||||
sin_alpha = y_new/r
|
||||
cos_alpha = x_new/r
|
||||
|
|
@ -57,7 +95,47 @@ MODULE moduleSolver
|
|||
!Copy temporal particle to particle
|
||||
part=part_temp
|
||||
|
||||
END SUBROUTINE push
|
||||
END SUBROUTINE pushCylNeutral
|
||||
|
||||
!Push one particle. Boris pusher for 2D Cyl Charged particle
|
||||
PURE SUBROUTINE pushCylCharged(part)
|
||||
USE moduleSpecies
|
||||
USE moduleEM
|
||||
IMPLICIT NONE
|
||||
|
||||
TYPE(particle), INTENT(inout):: part
|
||||
REAL(8):: v_p_oh_star(2:3)
|
||||
TYPE(particle):: part_temp
|
||||
REAL(8):: x_new, y_new, r, sin_alpha, cos_alpha
|
||||
REAL(8):: qmEFt(1:3)!charge*tau*EF/mass
|
||||
|
||||
part_temp = part
|
||||
!Get electric field at particle position
|
||||
qmEFt = part_temp%qm*gatherElecField(part_temp)*tau
|
||||
!z
|
||||
part_temp%v(1) = part%v(1) + qmEFt(1)
|
||||
part_temp%r(1) = part%r(1) + part_temp%v(1)*tau
|
||||
!r,theta
|
||||
v_p_oh_star(2) = part%v(2) + qmEFt(2)
|
||||
x_new = part%r(2) + v_p_oh_star(2)*tau
|
||||
v_p_oh_star(3) = part%v(3) + qmEFt(3)
|
||||
y_new = v_p_oh_star(3)*tau
|
||||
r = DSQRT(x_new**2+y_new**2)
|
||||
part_temp%r(2) = r
|
||||
IF (r > 0.D0) THEN
|
||||
sin_alpha = y_new/r
|
||||
cos_alpha = x_new/r
|
||||
ELSE
|
||||
sin_alpha = 0.D0
|
||||
cos_alpha = 1.D0
|
||||
END IF
|
||||
part_temp%v(2) = cos_alpha*v_p_oh_star(2)+sin_alpha*v_p_oh_star(3)
|
||||
part_temp%v(3) = -sin_alpha*v_p_oh_star(2)+cos_alpha*v_p_oh_star(3)
|
||||
part_temp%n_in = .FALSE. !Assume particle is outside until cell is found
|
||||
!Copy temporal particle to particle
|
||||
part=part_temp
|
||||
|
||||
END SUBROUTINE pushCylCharged
|
||||
|
||||
!Do the collisions in all the cells
|
||||
SUBROUTINE doCollisions()
|
||||
|
|
@ -153,6 +231,64 @@ MODULE moduleSolver
|
|||
|
||||
END SUBROUTINE doScatter
|
||||
|
||||
SUBROUTINE doEMField()
|
||||
IMPLICIT NONE
|
||||
|
||||
CALL solver%solveEMField()
|
||||
|
||||
END SUBROUTINE doEMField
|
||||
|
||||
!Solving the Poisson equation for electrostatic potential
|
||||
SUBROUTINE solveElecField()
|
||||
USE moduleEM
|
||||
USE moduleMesh
|
||||
USE moduleErrors
|
||||
IMPLICIT NONE
|
||||
|
||||
INTEGER, SAVE:: INFO
|
||||
INTEGER:: n
|
||||
REAL(8), ALLOCATABLE, SAVE:: tempF(:)
|
||||
EXTERNAL:: dgetrs
|
||||
|
||||
!$OMP SINGLE
|
||||
ALLOCATE(tempF(1:mesh%numNodes))
|
||||
!$OMP END SINGLE
|
||||
|
||||
CALL assembleSourceVector(tempF)
|
||||
|
||||
!$OMP SINGLE
|
||||
CALL dgetrs('N', mesh%numNodes, 1, mesh%K, mesh%numNodes, &
|
||||
mesh%IPIV, tempF, mesh%numNodes, info)
|
||||
!$OMP END SINGLE
|
||||
|
||||
IF (info == 0) THEN
|
||||
!Suscessful resolution of Poission equation
|
||||
!$OMP DO
|
||||
DO n = 1, mesh%numNodes
|
||||
mesh%nodes(n)%obj%emData%phi = tempF(n)
|
||||
|
||||
END DO
|
||||
!$OMP END DO
|
||||
|
||||
ELSE
|
||||
!$OMP SINGLE
|
||||
CALL criticalError('Poisson equation failed', 'solveElecField')
|
||||
!$OMP END SINGLE
|
||||
|
||||
END IF
|
||||
|
||||
!$OMP SINGLE
|
||||
DEALLOCATE(tempF)
|
||||
!$OMP END SINGLE
|
||||
|
||||
END SUBROUTINE solveElecField
|
||||
|
||||
!Empty module that does no computation of EM field for neutral cases
|
||||
SUBROUTINE noEMField()
|
||||
IMPLICIT NONE
|
||||
|
||||
END SUBROUTINE noEMField
|
||||
|
||||
SUBROUTINE doOutput(t)
|
||||
USE moduleMesh
|
||||
USE moduleOutput
|
||||
|
|
@ -172,8 +308,9 @@ MODULE moduleSolver
|
|||
CALL mesh%printOutput(t)
|
||||
CALL printTime(t, t == 0)
|
||||
CALL mesh%printColl(t)
|
||||
WRITE(*, "(5X,A21,I10,A1,I8)") "t/tmax: ", t, "/", tmax
|
||||
WRITE(*, "(5X,A21,I10)") "Particles: ", nPartOld
|
||||
CALL mesh%printEM(t)
|
||||
WRITE(*, "(5X,A21,I10,A1,I10)") "t/tmax: ", t, "/", tmax
|
||||
WRITE(*, "(5X,A21,I10)") "Particles: ", nPartOld
|
||||
IF (t == 0) THEN
|
||||
WRITE(*, "(5X,A21,F8.1,A2)") " init time: ", 1.D3*tStep, "ms"
|
||||
|
||||
|
|
@ -183,7 +320,7 @@ MODULE moduleSolver
|
|||
END IF
|
||||
|
||||
IF (nPartOld > 0) THEN
|
||||
WRITE(*, "(5X,A21,F8.1,A2)") "avg t/particle: ", 1.D9*(tPush+tReset+tColl+tWeight)/DBLE(nPartOld), "ns"
|
||||
WRITE(*, "(5X,A21,F8.1,A2)") "avg t/particle: ", 1.D9*tStep/DBLE(nPartOld), "ns"
|
||||
|
||||
END IF
|
||||
WRITE(*,*)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue