Compare commits

..

3 commits

Author SHA1 Message Date
6b72dbb108 Organized injection 2026-04-04 22:49:14 +02:00
ed79eb018e Import only what you need 2026-04-04 20:24:16 +02:00
cf4488976a Finally, the right values for velocity distributions 2026-04-04 20:03:20 +02:00
9 changed files with 120 additions and 139 deletions

View file

@ -1,15 +1,39 @@
! FPAKC main program ! FPAKC main program
PROGRAM fpakc PROGRAM fpakc
USE moduleCompTime use moduleCompTime, only: tStep, &
USE moduleCaseParam tEMField, &
USE moduleInput tCoul, &
USE moduleInject tColl, &
USE moduleSolver tPush, &
USE moduleMesh tReset, &
USE moduleProbe tWeight
USE moduleErrors use omp_lib, only: omp_get_wtime
USE OMP_LIB use moduleErrors, only: criticalError, &
IMPLICIT NONE verboseError
use moduleInput, only: readCOnfig, &
initOutput
use moduleCaseParam, only: timeStep, &
tInitial, &
tFinal
use moduleProbe, only: resetProbes
use moduleSolver, only: doScatter, &
doEMField, &
doOutput, &
solver, &
doPushes, &
doReset, &
doAverage, &
doInjects
use moduleMesh, only: boundariesEM_update, &
boundariesEM_update, &
boundariesParticle_update, &
mesh, &
meshForMCC, &
doMCCollisions, &
doCollisions, &
doCoulombScattering
use moduleInject, only: updateInjects
implicit none
! arg1 = Input argument 1 (input file) ! arg1 = Input argument 1 (input file)
CHARACTER(200):: arg1 CHARACTER(200):: arg1

View file

@ -67,19 +67,20 @@ MODULE moduleRandom
end function randomMaxwellian end function randomMaxwellian
!Returns a random number in a Maxwellian distribution of mean 0 and width 1 !Returns a random number in a Maxwellian distribution of mean 0 and width 1
FUNCTION randomHalfMaxwellian() RESULT(rnd) function randomHalfMaxwellian() result(rnd)
IMPLICIT NONE IMPLICIT NONE
REAL(8):: rnd real(8):: rnd
REAL(8):: x real(8):: v1
rnd = 0.D0 rnd = 0.D0
x = 0.D0 v1 = 0.D0
DO WHILE (x == 0.D0) do while (v1 == 0.D0)
CALL RANDOM_NUMBER(x) v1 = random()
END DO
rnd = DSQRT(-DLOG(x)) end do
rnd = sqrt(-2.d0*log(v1))
END FUNCTION randomHalfMaxwellian END FUNCTION randomHalfMaxwellian

View file

@ -53,12 +53,11 @@ module velocityDistribution
function randomVelMaxwellian(self) result (v) function randomVelMaxwellian(self) result (v)
use moduleRandom use moduleRandom
implicit none implicit none
class(velDistMaxwellian), intent(in):: self class(velDistMaxwellian), intent(in):: self
real(8):: v real(8):: v
v = 0.D0 v = 0.D0
v = self%vTh*randomMaxwellian()/sqrt(2.d0) v = self%vTh*randomMaxwellian()
end function randomVelMaxwellian end function randomVelMaxwellian

View file

@ -1431,7 +1431,6 @@ MODULE moduleInput
CALL config%info('inject', found, n_children = nInject) CALL config%info('inject', found, n_children = nInject)
ALLOCATE(injects(1:nInject)) ALLOCATE(injects(1:nInject))
nPartInj = 0
DO i = 1, nInject DO i = 1, nInject
WRITE(iString, '(i2)') i WRITE(iString, '(i2)') i
object = 'inject(' // trim(iString) // ')' object = 'inject(' // trim(iString) // ')'
@ -1442,12 +1441,6 @@ MODULE moduleInput
END DO END DO
!Allocate array for injected particles
IF (nPartInj > 0) THEN
ALLOCATE(partInj(1:nPartInj))
END IF
END SUBROUTINE readInject END SUBROUTINE readInject
SUBROUTINE readAverage(config) SUBROUTINE readAverage(config)

View file

@ -14,7 +14,7 @@ output.o: moduleSpecies.o common.o
mesh.o: moduleList.o moduleSpecies.o moduleCollisions.o moduleCoulomb.o output.o common.o mesh.o: moduleList.o moduleSpecies.o moduleCollisions.o moduleCoulomb.o output.o common.o
$(MAKE) -C mesh all $(MAKE) -C mesh all
solver.o: moduleSpecies.o moduleProbe.o common.o output.o mesh.o solver.o: moduleInject.o moduleSpecies.o moduleProbe.o common.o output.o mesh.o
$(MAKE) -C solver all $(MAKE) -C solver all
init.o: common.o solver.o moduleInject.o init.o: common.o solver.o moduleInject.o

View file

@ -12,7 +12,7 @@ MODULE moduleInject
REAL(8):: temperature(1:3) !Temperature REAL(8):: temperature(1:3) !Temperature
REAL(8):: n(1:3) !Direction of injection REAL(8):: n(1:3) !Direction of injection
LOGICAL:: fixDirection !The injection of particles has a fix direction defined by n LOGICAL:: fixDirection !The injection of particles has a fix direction defined by n
INTEGER:: nParticles !Number of particles to introduce each time step INTEGER:: nParticles !Number of particles to inject each time step
CLASS(speciesGeneric), POINTER:: species !Species of injection CLASS(speciesGeneric), POINTER:: species !Species of injection
INTEGER:: nEdges INTEGER:: nEdges
type(meshEdgePointer), allocatable:: edges(:) type(meshEdgePointer), allocatable:: edges(:)
@ -72,7 +72,6 @@ MODULE moduleInject
USE moduleRefParam USE moduleRefParam
USE moduleConstParam USE moduleConstParam
USE moduleSpecies USE moduleSpecies
USE moduleSolver
USE moduleErrors USE moduleErrors
use json_module use json_module
IMPLICIT NONE IMPLICIT NONE
@ -211,8 +210,6 @@ MODULE moduleInject
END DO END DO
self%nParticles = SUM(self%particlesPerEdge)
ELSE ELSE
! No particles assigned per edge, use the species weight ! No particles assigned per edge, use the species weight
self%weightPerEdge = self%species%weight self%weightPerEdge = self%species%weight
@ -220,13 +217,14 @@ MODULE moduleInject
self%particlesPerEdge(e) = max(1,FLOOR(fluxPerStep*self%edges(e)%obj%surface / self%species%weight)) self%particlesPerEdge(e) = max(1,FLOOR(fluxPerStep*self%edges(e)%obj%surface / self%species%weight))
END DO END DO
self%nParticles = SUM(self%particlesPerEdge)
!Rescale weight to match flux !Rescale weight to match flux
self%weightPerEdge = fluxPerStep * self%surface / (real(self%nParticles)) self%weightPerEdge = fluxPerStep * self%surface / (real(self%nParticles))
END IF END IF
! Total number of particles to inject
self%nParticles = SUM(self%particlesPerEdge)
!Scale particles for different species steps !Scale particles for different species steps
IF (self%nParticles == 0) CALL criticalError("The number of particles for inject is 0.", 'initInject') IF (self%nParticles == 0) CALL criticalError("The number of particles for inject is 0.", 'initInject')
@ -314,126 +312,85 @@ MODULE moduleInject
end subroutine updateQuasiNeutral end subroutine updateQuasiNeutral
!Injection of particles
SUBROUTINE doInjects()
USE moduleSpecies
USE moduleSolver
IMPLICIT NONE
INTEGER:: i
!$OMP SINGLE
nPartInj = 0
DO i = 1, nInject
IF (solver%pusher(injects(i)%obj%species%n)%pushSpecies) THEN
nPartInj = nPartInj + injects(i)%obj%nParticles
END IF
END DO
IF (ALLOCATED(partInj)) DEALLOCATE(partInj)
ALLOCATE(partInj(1:nPartInj))
!$OMP END SINGLE
DO i=1, nInject
IF (solver%pusher(injects(i)%obj%species%n)%pushSpecies) THEN
CALL injects(i)%obj%addParticles()
END IF
END DO
END SUBROUTINE doInjects
!Add particles for the injection !Add particles for the injection
SUBROUTINE addParticles(self) SUBROUTINE addParticles(self)
USE moduleSpecies USE moduleSpecies
USE moduleSolver
USE moduleMesh USE moduleMesh
USE moduleRandom USE moduleRandom
USE moduleErrors USE moduleErrors
use moduleList, only: partInj
IMPLICIT NONE IMPLICIT NONE
CLASS(injectGeneric), INTENT(in):: self CLASS(injectGeneric), INTENT(in):: self
INTEGER, SAVE:: nMin type(particle), pointer:: part
INTEGER:: i, e INTEGER:: i, e
INTEGER:: n, sp INTEGER:: sp
CLASS(meshEdge), POINTER:: randomEdge CLASS(meshEdge), POINTER:: edge
REAL(8):: direction(1:3) REAL(8):: direction(1:3)
!Insert particles !Insert particles
!$OMP SINGLE
nMin = 0
DO i = 1, self%id -1
IF (solver%pusher(injects(i)%obj%species%n)%pushSpecies) THEN
nMin = nMin + injects(i)%obj%nParticles
END IF
END DO
nMin = nMin + 1
!$OMP END SINGLE
!$OMP DO !$OMP DO
DO e = 1, self%nEdges DO e = 1, self%nEdges
! Select edge for injection ! Select edge for injection
randomEdge => self%edges(e)%obj edge => self%edges(e)%obj
! Inject particles in edge ! Inject particles in edge
DO i = 1, self%particlesPerEdge(e) DO i = 1, self%particlesPerEdge(e)
! Index in the global partInj array allocate(part)
n = nMin - 1 + SUM(self%particlesPerEdge(1:e-1)) + i ! Index in the partInj array
!Particle is considered to be outside the domain !Particle is considered to be inside the domain
partInj(n)%n_in = .FALSE. part%n_in = .true.
!Random position in edge !Random position in edge
partInj(n)%r = randomEdge%randPos() part%r = edge%randPos()
!Assign weight to particle. !Assign weight to particle.
partInj(n)%weight = self%weightPerEdge(e) part%weight = self%weightPerEdge(e)
!Volume associated to the edge: !Volume associated to the edge:
IF (ASSOCIATED(randomEdge%e1)) THEN IF (ASSOCIATED(edge%e1)) THEN
partInj(n)%cell = randomEdge%e1%n part%cell = edge%e1%n
ELSEIF (ASSOCIATED(randomEdge%e2)) THEN ELSEIF (ASSOCIATED(edge%e2)) THEN
partInj(n)%cell = randomEdge%e2%n part%cell = edge%e2%n
ELSE ELSE
CALL criticalError("No Volume associated to edge", 'addParticles') CALL criticalError("No Volume associated to edge", 'addParticles')
END IF END IF
partInj(n)%cellColl = randomEdge%eColl%n part%cellColl = edge%eColl%n
sp = self%species%n sp = self%species%n
!Assign particle type !Assign particle type
partInj(n)%species => self%species part%species => self%species
if (all(self%n == 0.D0)) then if (all(self%n == 0.D0)) then
direction = randomEdge%normal direction = edge%normal
else else
direction = self%n direction = self%n
end if end if
partInj(n)%v = 0.D0 part%v = 0.D0
do while(dot_product(partInj(n)%v, direction) <= 0.d0) ! do while(dot_product(partInj(n)%v, direction) <= 0.d0)
partInj(n)%v = self%vMod*direction + (/ self%v(1)%obj%randomVel(), & part%v = self%vMod*direction + (/ self%v(1)%obj%randomVel(), &
self%v(2)%obj%randomVel(), & self%v(2)%obj%randomVel(), &
self%v(3)%obj%randomVel() /) self%v(3)%obj%randomVel() /)
!If injecting a no-drift distribution and velocity is negative, reflect !If injecting a no-drift distribution and velocity is negative, reflect
if ((self%vMod == 0.D0) .and. & if ((self%vMod == 0.D0) .and. &
(dot_product(partInj(n)%v, direction) <= 0.D0)) then (dot_product(part%v, direction) <= 0.D0)) then
partInj(n)%v = - partInj(n)%v part%v = - part%v
end if end if
end do ! end do
!Obtain natural coordinates of particle in cell !Obtain natural coordinates of particle in cell
partInj(n)%Xi = mesh%cells(partInj(n)%cell)%obj%phy2log(partInj(n)%r) part%Xi = mesh%cells(part%cell)%obj%phy2log(part%r)
!Push new particle with the minimum time step
CALL solver%pusher(sp)%pushParticle(partInj(n), tau(sp)) ! Add particle to global list
!Assign cell to new particle call partInj%setLock()
CALL solver%updateParticleCell(partInj(n)) call partInj%add(part)
call partInj%unsetLock()
END DO END DO
@ -500,7 +457,7 @@ MODULE moduleInject
CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist
REAL(8), INTENT(in):: temperature, m REAL(8), INTENT(in):: temperature, m
velDist = velDistMaxwellian(vTh = DSQRT(2.d0*temperature/m)) velDist = velDistMaxwellian(vTh = DSQRT(temperature/m))
END SUBROUTINE initVelDistMaxwellian END SUBROUTINE initVelDistMaxwellian
@ -510,7 +467,7 @@ MODULE moduleInject
CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist
REAL(8), INTENT(in):: temperature, m REAL(8), INTENT(in):: temperature, m
velDist = velDistHalfMaxwellian(vTh = DSQRT(2.d0*temperature/m)) velDist = velDistHalfMaxwellian(vTh = DSQRT(temperature/m))
END SUBROUTINE initVelDistHalfMaxwellian END SUBROUTINE initVelDistHalfMaxwellian

View file

@ -23,6 +23,7 @@ MODULE moduleList
END TYPE listNode END TYPE listNode
TYPE(listNode):: partInj !Particles comming from injections
TYPE(listNode):: partWScheme !Particles comming from the nonAnalogue scheme TYPE(listNode):: partWScheme !Particles comming from the nonAnalogue scheme
TYPE(listNode):: partCollisions !Particles created in collisional process TYPE(listNode):: partCollisions !Particles created in collisional process
TYPE(listNode):: partSurfaces !Particles created in surface interactions TYPE(listNode):: partSurfaces !Particles created in surface interactions

View file

@ -48,11 +48,8 @@ MODULE moduleSpecies
!Number of old particles !Number of old particles
INTEGER:: nPartOld INTEGER:: nPartOld
!Number of injected particles
INTEGER:: nPartInj
!Arrays that contain the particles !Arrays that contain the particles
TYPE(particle), ALLOCATABLE, DIMENSION(:), TARGET:: partOld !array of particles from previous iteration TYPE(particle), ALLOCATABLE, DIMENSION(:), TARGET:: partOld !array of particles from previous iteration
TYPE(particle), ALLOCATABLE, DIMENSION(:), TARGET:: partInj !array of inject particles
CONTAINS CONTAINS
FUNCTION speciesName2Index(speciesName) RESULT(sp) FUNCTION speciesName2Index(speciesName) RESULT(sp)

View file

@ -235,23 +235,21 @@ MODULE moduleSolver
INTEGER:: nn, n, e INTEGER:: nn, n, e
INTEGER, SAVE:: nPartNew INTEGER, SAVE:: nPartNew
INTEGER, SAVE:: nInjIn, nOldIn, nWScheme, nCollisions, nSurfaces INTEGER, SAVE:: nOldIn, nInj, nWScheme, nCollisions, nSurfaces
TYPE(particle), ALLOCATABLE, SAVE:: partTemp(:) TYPE(particle), ALLOCATABLE, SAVE:: partTemp(:)
INTEGER:: s INTEGER:: s
!$OMP SECTIONS !$OMP SECTIONS
!$OMP SECTION !$OMP SECTION
nInjIn = 0
IF (ALLOCATED(partInj)) THEN
nInjIn = COUNT(partInj%n_in)
END IF
!$OMP SECTION
nOldIn = 0 nOldIn = 0
IF (ALLOCATED(partOld)) THEN IF (ALLOCATED(partOld)) THEN
nOldIn = COUNT(partOld%n_in) nOldIn = COUNT(partOld%n_in)
END IF END IF
!$OMP SECTION
nInj = partInj%amount
!$OMP SECTION !$OMP SECTION
nWScheme = partWScheme%amount nWScheme = partWScheme%amount
@ -267,30 +265,14 @@ MODULE moduleSolver
!$OMP SINGLE !$OMP SINGLE
CALL MOVE_ALLOC(partOld, partTemp) CALL MOVE_ALLOC(partOld, partTemp)
nPartNew = nInjIn + nOldIn + nWScheme + nCollisions + nSurfaces nPartNew = nInj + nOldIn + nWScheme + nCollisions + nSurfaces
ALLOCATE(partOld(1:nPartNew)) ALLOCATE(partOld(1:nPartNew))
!$OMP END SINGLE !$OMP END SINGLE
!$OMP SECTIONS !$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)
IF (nProbes > 0) THEN
CALL doProbes(partOld(nn))
END IF
END IF
END DO
!$OMP SECTION !$OMP SECTION
!Reset particles from previous iteration !Reset particles from previous iteration
nn = nInjIn nn = 0
DO n = 1, nPartOld DO n = 1, nPartOld
IF (partTemp(n)%n_in) THEN IF (partTemp(n)%n_in) THEN
nn = nn + 1 nn = nn + 1
@ -304,19 +286,24 @@ MODULE moduleSolver
END DO END DO
!$OMP SECTION
!Reset particles from injection
nn = nOldIn
call resetList(partInj, partOld, nn)
!$OMP SECTION !$OMP SECTION
!Reset particles from weighting scheme !Reset particles from weighting scheme
nn = nInjIn + nOldIn nn = nOldIn + nInj
CALL resetList(partWScheme, partOld, nn) CALL resetList(partWScheme, partOld, nn)
!$OMP SECTION !$OMP SECTION
!Reset particles from collisional process !Reset particles from collisional process
nn = nInjIn + nOldIn + nWScheme nn = nOldIn + nInj + nWScheme
CALL resetList(partCollisions, partOld, nn) CALL resetList(partCollisions, partOld, nn)
!$OMP SECTION !$OMP SECTION
!Reset particles from surface process !Reset particles from surface process
nn = nInjIn + nOldIn + nWScheme + nCollisions nn = nOldIn + nInj + nWScheme + nCollisions
CALL resetList(partSurfaces, partOld, nn) CALL resetList(partSurfaces, partOld, nn)
!$OMP SECTION !$OMP SECTION
@ -473,6 +460,28 @@ MODULE moduleSolver
END SUBROUTINE splitParticle END SUBROUTINE splitParticle
!Injection of particles
SUBROUTINE doInjects()
USE moduleSpecies
use moduleInject
IMPLICIT NONE
INTEGER:: i, n, sp
DO i=1, nInject
associate(inject => injects(i)%obj)
sp = inject%species%n
IF (solver%pusher(sp)%pushSpecies) THEN
CALL inject%addParticles()
END IF
end associate
END DO
END SUBROUTINE doInjects
SUBROUTINE updateParticleCell(self, part) SUBROUTINE updateParticleCell(self, part)
USE moduleSpecies USE moduleSpecies
USE moduleMesh USE moduleMesh