656 lines
17 KiB
Fortran
656 lines
17 KiB
Fortran
MODULE moduleSolver
|
|
|
|
!Generic type for pusher of particles
|
|
TYPE, PUBLIC:: pusherGeneric
|
|
PROCEDURE(push_interafece), POINTER, NOPASS:: pushParticle => NULL()
|
|
!Boolean to indicate if the species is moved in the iteration
|
|
LOGICAL:: pushSpecies
|
|
!How many interations between advancing the species
|
|
INTEGER:: every
|
|
CONTAINS
|
|
PROCEDURE, PASS:: init => initPusher
|
|
|
|
END TYPE pusherGeneric
|
|
|
|
!Generic type for solver
|
|
TYPE, PUBLIC:: solverGeneric
|
|
TYPE(pusherGeneric), ALLOCATABLE:: pusher(:)
|
|
PROCEDURE(solveEM_interface), POINTER, NOPASS:: solveEM => NULL()
|
|
PROCEDURE(weightingScheme_interface), POINTER, NOPASS:: weightingScheme => NULL()
|
|
CONTAINS
|
|
PROCEDURE, PASS:: initEM
|
|
PROCEDURE, PASS:: initWS
|
|
PROCEDURE, PASS:: updateParticleCell
|
|
PROCEDURE, PASS:: updatePushSpecies
|
|
|
|
END TYPE solverGeneric
|
|
|
|
INTERFACE
|
|
!Push a particle
|
|
PURE SUBROUTINE push_interafece(part, tauIn)
|
|
USE moduleSpecies
|
|
|
|
TYPE(particle), INTENT(inout):: part
|
|
REAL(8), INTENT(in):: tauIn
|
|
|
|
END SUBROUTINE push_interafece
|
|
|
|
!Solve the electromagnetic field
|
|
SUBROUTINE solveEM_interface()
|
|
|
|
END SUBROUTINE solveEM_interface
|
|
|
|
!Apply nonAnalogue scheme to a particle
|
|
SUBROUTINE weightingScheme_interface(part, volOld, volNew)
|
|
USE moduleSpecies
|
|
USE moduleMesh
|
|
IMPLICIT NONE
|
|
|
|
TYPE(particle), INTENT(inout):: part
|
|
CLASS(meshVol), POINTER, INTENT(in):: volOld
|
|
CLASS(meshVol), POINTER, INTENT(inout):: volNew
|
|
|
|
END SUBROUTINE weightingScheme_interface
|
|
|
|
END INTERFACE
|
|
|
|
TYPE(solverGeneric):: solver
|
|
|
|
CONTAINS
|
|
!Init Pusher
|
|
SUBROUTINE initPusher(self, pusherType, tau, tauSp)
|
|
USE moduleErrors
|
|
IMPLICIT NONE
|
|
|
|
CLASS(pusherGeneric), INTENT(out):: self
|
|
CHARACTER(:), ALLOCATABLE:: pusherType
|
|
REAL(8):: tau, tauSp
|
|
|
|
SELECT CASE(pusherType)
|
|
CASE('2DCylNeutral')
|
|
self%pushParticle => pushCylNeutral
|
|
|
|
CASE('2DCylCharged')
|
|
self%pushParticle => pushCylCharged
|
|
|
|
CASE('1DCartCharged')
|
|
self%pushParticle => push1DCartCharged
|
|
|
|
CASE('1DRadCharged')
|
|
self%pushParticle => push1DRadCharged
|
|
|
|
CASE DEFAULT
|
|
CALL criticalError('Pusher ' // pusherType // ' not found','initPusher')
|
|
|
|
END SELECT
|
|
|
|
self%pushSpecies = .FALSE.
|
|
self%every = INT(tauSp/tau)
|
|
|
|
END SUBROUTINE initPusher
|
|
|
|
SUBROUTINE initEM(self, EMType)
|
|
IMPLICIT NONE
|
|
|
|
CLASS(solverGeneric), INTENT(inout):: self
|
|
CHARACTER(:), ALLOCATABLE:: EMType
|
|
|
|
SELECT CASE(EMType)
|
|
CASE('Electrostatic')
|
|
self%solveEM => solveElecField
|
|
|
|
END SELECT
|
|
|
|
END SUBROUTINE initEM
|
|
|
|
!Initialize the non-analogue scheme
|
|
SUBROUTINE initWS(self, NAType)
|
|
USE moduleMesh
|
|
IMPLICIT NONE
|
|
|
|
CLASS(solverGeneric), INTENT(inout):: self
|
|
CHARACTER(:), ALLOCATABLE:: NAType
|
|
|
|
SELECT CASE(NAType)
|
|
CASE ('Volume')
|
|
self%weightingScheme => volumeWScheme
|
|
|
|
END SELECT
|
|
|
|
END SUBROUTINE initWS
|
|
|
|
!Do all pushes for particles
|
|
SUBROUTINE doPushes()
|
|
USE moduleSpecies
|
|
USE moduleMesh
|
|
IMPLICIT NONE
|
|
|
|
INTEGER:: n
|
|
INTEGER:: sp
|
|
|
|
!$OMP DO
|
|
DO n=1, nPartOld
|
|
!Select species type
|
|
sp = partOld(n)%sp
|
|
!Checks if the species sp is update this iteration
|
|
IF (solver%pusher(sp)%pushSpecies) THEN
|
|
!Push particle
|
|
CALL solver%pusher(sp)%pushParticle(partOld(n), tau(sp))
|
|
!Find cell in wich particle reside
|
|
CALL solver%updateParticleCell(partOld(n))
|
|
|
|
END IF
|
|
|
|
END DO
|
|
!$OMP END DO
|
|
|
|
END SUBROUTINE doPushes
|
|
|
|
!Push one particle. Boris pusher for 2D Cyl Neutral particle
|
|
PURE SUBROUTINE pushCylNeutral(part, tauIn)
|
|
USE moduleSpecies
|
|
IMPLICIT NONE
|
|
|
|
TYPE(particle), INTENT(inout):: part
|
|
REAL(8), INTENT(in):: tauIn
|
|
TYPE(particle):: part_temp
|
|
REAL(8):: x_new, y_new, r, sin_alpha, cos_alpha
|
|
REAL(8):: v_p_oh_star(2:3)
|
|
|
|
part_temp = part
|
|
!z
|
|
part_temp%v(1) = part%v(1)
|
|
part_temp%r(1) = part%r(1) + part_temp%v(1)*tauIn
|
|
!r,theta
|
|
v_p_oh_star(2) = part%v(2)
|
|
x_new = part%r(2) + v_p_oh_star(2)*tauIn
|
|
v_p_oh_star(3) = part%v(3)
|
|
y_new = v_p_oh_star(3)*tauIn
|
|
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 pushCylNeutral
|
|
|
|
!Push one particle. Boris pusher for 2D Cyl Charged particle
|
|
PURE SUBROUTINE pushCylCharged(part, tauIn)
|
|
USE moduleSpecies
|
|
USE moduleEM
|
|
IMPLICIT NONE
|
|
|
|
TYPE(particle), INTENT(inout):: part
|
|
REAL(8), INTENT(in):: tauIn
|
|
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*tauIn*EF/mass
|
|
|
|
part_temp = part
|
|
!Get electric field at particle position
|
|
qmEFt = part_temp%qm*gatherElecField(part_temp)*tauIn
|
|
!z
|
|
part_temp%v(1) = part%v(1) + qmEFt(1)
|
|
part_temp%r(1) = part%r(1) + part_temp%v(1)*tauIn
|
|
!r,theta
|
|
v_p_oh_star(2) = part%v(2) + qmEFt(2)
|
|
x_new = part%r(2) + v_p_oh_star(2)*tauIn
|
|
v_p_oh_star(3) = part%v(3) + qmEFt(3)
|
|
y_new = v_p_oh_star(3)*tauIn
|
|
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
|
|
|
|
!Push charged particles in 1D cartesian coordinates
|
|
PURE SUBROUTINE push1DCartCharged(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
|
|
|
|
!x
|
|
part_temp%v(1) = part%v(1) + qmEFt(1)
|
|
part_temp%r(1) = part%r(1) + part_temp%v(1)*tauIn
|
|
|
|
part_temp%n_in = .FALSE.
|
|
|
|
part = part_temp
|
|
|
|
END SUBROUTINE push1DCartCharged
|
|
|
|
!Push one particle. Boris pusher for 1D Radial Charged particle
|
|
PURE SUBROUTINE push1DRadCharged(part, tauIn)
|
|
USE moduleSpecies
|
|
USE moduleEM
|
|
IMPLICIT NONE
|
|
|
|
TYPE(particle), INTENT(inout):: part
|
|
REAL(8), INTENT(in):: tauIn
|
|
REAL(8):: v_p_oh_star(1:2)
|
|
TYPE(particle):: part_temp
|
|
REAL(8):: x_new, y_new, r, sin_alpha, cos_alpha
|
|
REAL(8):: qmEFt(1:3)!charge*tauIn*EF/mass
|
|
|
|
part_temp = part
|
|
!Time step for the species
|
|
!Get electric field at particle position
|
|
qmEFt = part_temp%qm*gatherElecField(part_temp)*tauMin
|
|
!r,theta
|
|
v_p_oh_star(1) = part%v(1) + qmEFt(1)
|
|
x_new = part%r(1) + v_p_oh_star(1)*tauIn
|
|
v_p_oh_star(2) = part%v(2) + qmEFt(2)
|
|
y_new = v_p_oh_star(2)*tauIn
|
|
r = DSQRT(x_new**2+y_new**2)
|
|
part_temp%r(1) = 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(1) = cos_alpha*v_p_oh_star(1)+sin_alpha*v_p_oh_star(2)
|
|
part_temp%v(2) = -sin_alpha*v_p_oh_star(1)+cos_alpha*v_p_oh_star(2)
|
|
part_temp%n_in = .FALSE. !Assume particle is outside until cell is found
|
|
!Copy temporal particle to particle
|
|
part=part_temp
|
|
|
|
END SUBROUTINE push1DRadCharged
|
|
|
|
!Do the collisions in all the cells
|
|
SUBROUTINE doCollisions()
|
|
USE moduleMesh
|
|
IMPLICIT NONE
|
|
|
|
INTEGER:: e
|
|
|
|
!$OMP DO SCHEDULE(DYNAMIC)
|
|
DO e=1, mesh%numVols
|
|
CALL mesh%vols(e)%obj%collision()
|
|
END DO
|
|
!$OMP END DO
|
|
|
|
END SUBROUTINE doCollisions
|
|
|
|
SUBROUTINE doReset()
|
|
USE moduleSpecies
|
|
USE moduleMesh
|
|
USE moduleList
|
|
IMPLICIT NONE
|
|
|
|
INTEGER:: nn, n, e
|
|
INTEGER, SAVE:: nPartNew
|
|
INTEGER, SAVE:: nInjIn, nOldIn, nWScheme, nCollisions
|
|
TYPE(particle), ALLOCATABLE, SAVE:: partTemp(:)
|
|
TYPE(lNode), POINTER:: partCurr, partNext
|
|
|
|
!$OMP SECTIONS
|
|
!$OMP SECTION
|
|
nInjIn = 0
|
|
IF (ALLOCATED(partInj)) THEN
|
|
nInjIn = COUNT(partInj%n_in)
|
|
|
|
END IF
|
|
!$OMP SECTION
|
|
nOldIn = 0
|
|
IF (ALLOCATED(partOld)) THEN
|
|
nOldIn = COUNT(partOld%n_in)
|
|
|
|
END IF
|
|
!$OMP SECTION
|
|
nWScheme = partWScheme%amount
|
|
!$OMP SECTION
|
|
nCollisions = partCollisions%amount
|
|
!$OMP END SECTIONS
|
|
|
|
!$OMP BARRIER
|
|
|
|
!$OMP SINGLE
|
|
CALL MOVE_ALLOC(partOld, partTemp)
|
|
nPartNew = nInjIn + nOldIn + nWScheme + nCollisions
|
|
ALLOCATE(partOld(1:nPartNew))
|
|
!$OMP END SINGLE
|
|
|
|
!$OMP SECTIONS
|
|
!$OMP SECTION
|
|
!Reset particles from injection
|
|
nn = 0
|
|
DO n = 1, nPartInj
|
|
IF (partInj(n)%n_in) THEN
|
|
nn = nn + 1
|
|
partOld(nn) = partInj(n)
|
|
|
|
END IF
|
|
|
|
END DO
|
|
|
|
!$OMP SECTION
|
|
!Reset particles from previous iteration
|
|
nn = nInjIn
|
|
DO n = 1, nPartOld
|
|
IF (partTemp(n)%n_in) THEN
|
|
nn = nn + 1
|
|
partOld(nn) = partTemp(n)
|
|
|
|
END IF
|
|
|
|
END DO
|
|
!$OMP SECTION
|
|
!Reset particles from weighting scheme
|
|
nn = nInjIn + nOldIn
|
|
partCurr => partWScheme%head
|
|
DO n = 1, nWScheme
|
|
partNext => partCurr%next
|
|
partOld(nn+n) = partCurr%part
|
|
DEALLOCATE(partCurr)
|
|
partCurr => partNext
|
|
|
|
END DO
|
|
IF (ASSOCIATED(partWScheme%head)) NULLIFY(partWScheme%head)
|
|
IF (ASSOCIATED(partWScheme%tail)) NULLIFY(partWScheme%tail)
|
|
partWScheme%amount = 0
|
|
|
|
!$OMP SECTION
|
|
!Reset particles from collisional process
|
|
nn = nInjIn + nOldIn + nWScheme
|
|
partCurr => partCollisions%head
|
|
DO n = 1, nCollisions
|
|
partNext => partCurr%next
|
|
partOld(nn+n) = partCurr%part
|
|
DEALLOCATE(partCurr)
|
|
partCurr => partNext
|
|
|
|
END DO
|
|
IF (ASSOCIATED(partCollisions%head)) NULLIFY(partCollisions%head)
|
|
IF (ASSOCIATED(partCollisions%tail)) NULLIFY(partCollisions%tail)
|
|
partCollisions%amount = 0
|
|
|
|
!$OMP SECTION
|
|
!Reset output in nodes
|
|
DO e = 1, mesh%numNodes
|
|
CALL mesh%nodes(e)%obj%resetOutput()
|
|
|
|
END DO
|
|
|
|
!$OMP SECTION
|
|
!Erase the list of particles inside the cell
|
|
DO e = 1, mesh%numVols
|
|
mesh%vols(e)%obj%totalWeight = 0.D0
|
|
CALL mesh%vols(e)%obj%listPart_in%erase()
|
|
|
|
END DO
|
|
|
|
!$OMP END SECTIONS
|
|
|
|
!$OMP SINGLE
|
|
nPartOld = nPartNew
|
|
!$OMP END SINGLE
|
|
|
|
END SUBROUTINE doReset
|
|
|
|
!Scatter particles in the grid
|
|
SUBROUTINE doScatter
|
|
USE moduleSpecies
|
|
USE moduleMesh
|
|
IMPLICIT NONE
|
|
|
|
INTEGER:: n
|
|
|
|
!Loops over the particles to scatter them
|
|
!$OMP DO
|
|
DO n=1, nPartOld
|
|
CALL mesh%vols(partOld(n)%vol)%obj%scatter(partOld(n))
|
|
|
|
END DO
|
|
!$OMP END DO
|
|
|
|
END SUBROUTINE doScatter
|
|
|
|
SUBROUTINE doEMField()
|
|
IMPLICIT NONE
|
|
|
|
IF (ASSOCIATED(solver%solveEM)) THEN
|
|
CALL solver%solveEM()
|
|
|
|
END IF
|
|
|
|
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
|
|
|
|
!Modify particle weight as a function of cell volume and splits particle
|
|
SUBROUTINE volumeWScheme(part, volOld, volNew)
|
|
USE moduleSpecies
|
|
USE moduleMesh
|
|
IMPLICIT NONE
|
|
|
|
TYPE(particle), INTENT(inout):: part
|
|
CLASS(meshVol), POINTER, INTENT(in):: volOld
|
|
CLASS(meshVol), POINTER, INTENT(inout):: volNew
|
|
REAL(8):: fractionVolume, fractionWeight
|
|
INTEGER:: nSplit
|
|
|
|
!If particle has change cell, call Weighting scheme
|
|
IF (volOld%n /= volNew%n) THEN
|
|
fractionVolume = volOld%volume/volNew%volume
|
|
|
|
part%weight = part%weight * fractionVolume
|
|
|
|
fractionWeight = part%weight / species(part%sp)%obj%weight
|
|
|
|
IF (fractionWeight >= 2.D0) THEN
|
|
nSplit = FLOOR(fractionWeight)
|
|
CALL splitParticle(part, nSplit, volNew)
|
|
|
|
ELSEIF (part%weight < 1.D0) THEN
|
|
!Particle has lost statistical meaning and will be terminated
|
|
part%n_in = .FALSE.
|
|
|
|
END IF
|
|
|
|
END IF
|
|
|
|
END SUBROUTINE volumeWScheme
|
|
|
|
!Subroutine to split the particle 'part' into a number 'nSplit' of particles.
|
|
!'nSplit-1' particles are added to the partNAScheme list
|
|
SUBROUTINE splitParticle(part, nSplit, vol)
|
|
USE moduleSpecies
|
|
USE moduleList
|
|
USE moduleMesh
|
|
USE OMP_LIB
|
|
IMPLICIT NONE
|
|
|
|
TYPE(particle), INTENT(inout):: part
|
|
INTEGER, INTENT(in):: nSplit
|
|
CLASS(meshVol), INTENT(inout):: vol
|
|
REAL(8):: newWeight
|
|
TYPE(particle), POINTER:: newPart
|
|
INTEGER:: p
|
|
|
|
newWeight = part%weight / nSplit
|
|
|
|
!Assign new weight to original particle
|
|
part%weight = newWeight
|
|
|
|
!Add new particles to list of NA particles
|
|
DO p = 2, nSplit
|
|
!Allocate the pointer for the new particles
|
|
ALLOCATE(newPart)
|
|
!Copy data from original particle
|
|
newPart = part
|
|
CALL OMP_SET_LOCK(lockWScheme)
|
|
CALL partWScheme%add(newPart)
|
|
CALL OMP_UNSET_LOCK(lockWScheme)
|
|
!Add particle to cell list
|
|
CALL OMP_SET_lock(vol%lock)
|
|
CALL vol%listPart_in%add(newPart)
|
|
CALL OMP_UNSET_lock(vol%lock)
|
|
|
|
END DO
|
|
|
|
END SUBROUTINE splitParticle
|
|
|
|
SUBROUTINE updateParticleCell(self, part)
|
|
USE moduleSpecies
|
|
USE moduleMesh
|
|
IMPLICIT NONE
|
|
|
|
CLASS(solverGeneric), INTENT(in):: self
|
|
TYPE(particle), INTENT(inout):: part
|
|
CLASS(meshVol), POINTER:: volOld, volNew
|
|
|
|
volOld => mesh%vols(part%vol)%obj
|
|
CALL volOld%findCell(part)
|
|
volNew => mesh%vols(part%vol)%obj
|
|
!Call the NA shcme
|
|
IF (ASSOCIATED(self%weightingScheme)) THEN
|
|
CALL self%weightingScheme(part, volOld, volNew)
|
|
|
|
END IF
|
|
|
|
END SUBROUTINE updateParticleCell
|
|
|
|
!Update the information about if a species needs to be moved this iteration
|
|
SUBROUTINE updatePushSpecies(self, t)
|
|
USE moduleSpecies
|
|
IMPLICIT NONE
|
|
|
|
CLASS(solverGeneric), INTENT(inout):: self
|
|
INTEGER, INTENT(in):: t
|
|
INTEGER:: s
|
|
|
|
DO s=1, nSpecies
|
|
self%pusher(s)%pushSpecies = MOD(t, self%pusher(s)%every) == 0
|
|
|
|
END DO
|
|
|
|
END SUBROUTINE updatePushSpecies
|
|
|
|
!Output the different data and information
|
|
SUBROUTINE doOutput(t)
|
|
USE moduleMesh
|
|
USE moduleOutput
|
|
USE moduleSpecies
|
|
USE moduleCompTime
|
|
IMPLICIT NONE
|
|
|
|
INTEGER, INTENT(in):: t
|
|
|
|
counterOutput = counterOutput + 1
|
|
IF (counterOutput >= triggerOutput .OR. &
|
|
t == tmax .OR. t == 0) THEN
|
|
|
|
!Resets output counter
|
|
counterOutput=0
|
|
|
|
CALL mesh%printOutput(t)
|
|
CALL mesh%printColl(t)
|
|
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"
|
|
|
|
ELSE
|
|
WRITE(*, "(5X,A21,F8.1,A2)") "iteration time: ", 1.D3*tStep, "ms"
|
|
|
|
END IF
|
|
|
|
IF (nPartOld > 0) THEN
|
|
WRITE(*, "(5X,A21,F8.1,A2)") "avg t/particle: ", 1.D9*tStep/DBLE(nPartOld), "ns"
|
|
|
|
END IF
|
|
WRITE(*,*)
|
|
|
|
END IF
|
|
|
|
counterCPUTime = counterCPUTime + 1
|
|
IF (counterCPUTime >= triggerCPUTime .OR. &
|
|
t == tmax .OR. t == 0) THEN
|
|
|
|
!Reset CPU Time counter
|
|
counterCPUTime = 0
|
|
|
|
CALL printTime(t, t == 0)
|
|
|
|
END IF
|
|
|
|
END SUBROUTINE doOutput
|
|
|
|
END MODULE moduleSolver
|
|
|