Compare commits

...
Sign in to create a new pull request.

10 commits

Author SHA1 Message Date
0c49723848 NOT WORKING
I need to fix something in another place and make some test, so this
commit does not comile.
2023-11-21 09:23:18 +01:00
286e858d66 Intermediate push
I still have to figure out how to do this properly, but I am tired of
working on my laptop.
2023-09-22 18:18:46 +02:00
b73c8531e8 Fix an issue with different time steps
Sometimes the division between number of steps and time step was not
giving the right results.

Nevertheless, this just indicates that the species have to be in
separated arrays so that the assignment of particles in list, pushing
and scattering can be dealt independently.

Thus, this is the first step in creating separate arrays of particles
per species.
2023-08-06 19:45:48 +02:00
541a6ff97a Correction to injection velocity
Small correction to injection velocity. Still not fully satisfied with
it. I have to find a way to ensure that velocity is injected in the
right direction and fulfills the distribution functions in each
direction regardless the direction of injection, mean velocity or
distribution function.
2023-07-30 12:55:52 +02:00
e1009a21df Correction due to angle
Moving forward to a complete model for SEE. Now the yield has a
correction for the incident angle on the surface (still to check if this
 is correct)

Velocity distribution is still a dummy one.
2023-07-18 15:35:16 +02:00
cc3e28e5e7 Input done
The input is done and testing.

WARNING: Velocity of secondary electrons is still a dummy one!
2023-07-17 22:48:52 +02:00
38fa37c995 Dummy velocity for testing
I have set the velocity of the particle to be a dummy Maxwellian
distribution to start testing things.

Also I added a constant yield table for testing.

Next step is to do the user input and run some tests.
2023-07-17 16:29:52 +02:00
0f7d9919ec Ignore backups of bibliography
Sorry that this change is in this branch, but I just noticed that the
backups from jabref were not being ignored.
2023-07-17 16:18:51 +02:00
e369bccf78 Function to create electrons
Still required to assign velocity:
  - In the direction normal to the surface
  - Which energy?
2023-07-17 13:58:57 +02:00
21184e91d3 Type for SEE
Implementation of the type for Secondary Electron Emission (SEE)
2023-07-17 12:02:24 +02:00
15 changed files with 372 additions and 154 deletions

View file

@ -0,0 +1,4 @@
#Relative energy (eV) yield ()
0.000 1.000E-01
1.000 1.000E-01

View file

@ -19,3 +19,4 @@ fpakc_UserManual-blx.bib
*.gls
*.ist
fpakc_UserManual.run.xml
*.bib.sav

View file

@ -66,6 +66,24 @@ MODULE moduleRandom
END FUNCTION randomMaxwellian
FUNCTION randomHalfMaxwellian() RESULT(rnd)
USE moduleConstParam, ONLY: PI
IMPLICIT NONE
REAL(8):: rnd
REAL(8):: x, y
rnd = 0.D0
x = 0.D0
DO WHILE (x == 0.D0)
CALL RANDOM_NUMBER(x)
END DO
y = random(-PI, PI)
rnd = DSQRT(-2.D0*DLOG(x))*DCOS(y)
END FUNCTION randomHalfMaxwellian
!Returns a random number weighted with the cumWeight array
FUNCTION randomWeighted(cumWeight, sumWeight) RESULT(rnd)
IMPLICIT NONE

View file

@ -30,6 +30,8 @@ MODULE moduleTable
READ(id, '(A)', iostat = stat) dummy
!If EOF or error, exit file
IF (stat /= 0) EXIT
!If empty line, exit file
IF (dummy == "") EXIT
!Skip comment
IF (INDEX(dummy,'#') /= 0) CYCLE
!Add row
@ -55,6 +57,7 @@ MODULE moduleTable
!TODO: Make this a function
IF (INDEX(dummy,'#') /= 0) CYCLE
IF (stat /= 0) EXIT
IF (dummy == "") EXIT
!Add data
!TODO: substitute with extracting information from dummy
BACKSPACE(id)

View file

@ -339,10 +339,9 @@ MODULE moduleInput
!Mean velocity and temperature at particle position
REAL(8):: velocityXi(1:3), temperatureXi
INTEGER:: nNewPart = 0.D0
CLASS(meshCell), POINTER:: cell
TYPE(particle), POINTER:: partNew
CLASS(meshCell), POINTER:: cell
REAL(8):: vTh
TYPE(lNode), POINTER:: partCurr, partNext
CALL config%info('solver.initial', found, n_children = nInitial)
@ -371,9 +370,12 @@ MODULE moduleInput
!Calculate number of particles
nNewPart = INT(densityCen * (mesh%cells(e)%obj%volume*Vol_ref) / species(sp)%obj%weight)
!Allocate new particles
!Allocate array of particles for this species
ALLOCATE(partOld(sp)%p(1:nNewPart))
!Create new particles
DO p = 1, nNewPart
ALLOCATE(partNew)
partNew = partOld(sp)%p(p)
partNew%species => species(sp)%obj
partNew%r = mesh%cells(e)%obj%randPos()
partNew%Xi = mesh%cells(e)%obj%phy2log(partNew%r)
@ -408,9 +410,6 @@ MODULE moduleInput
partNew%weight = species(sp)%obj%weight
!Assign particle to temporal list of particles
CALL partInitial%add(partNew)
!Assign particle to list in volume
IF (listInCells) THEN
cell => meshforMCC%cells(partNew%cellColl)%obj
@ -430,30 +429,10 @@ MODULE moduleInput
END DO
END DO
!Convert temporal list of particles into initial partOld array
!Deallocate the list of initial particles
nNewPart = partInitial%amount
IF (nNewPart > 0) THEN
ALLOCATE(partOld(1:nNewPart))
partCurr => partInitial%head
DO p = 1, nNewPart
partNext => partCurr%next
partOld(p) = partCurr%part
DEALLOCATE(partCurr)
partCurr => partNext
nPartOld(sp) = SIZE(partOld(sp)%p)
END DO
IF (ASSOCIATED(partInitial%head)) NULLIFY(partInitial%head)
IF (ASSOCIATED(partInitial%tail)) NULLIFY(partInitial%tail)
partInitial%amount = 0
END IF
nPartOld = SIZE(partOld)
END IF
END SUBROUTINE readInitial
@ -600,7 +579,10 @@ MODULE moduleInput
END DO
!Allocate the wrapper array that contains particles
ALLOCATE(partOld(1:nSpecies))
!Set number of particles to 0 for init state
ALLOCATE(nPartOld(1:nSpecies))
nPartOld = 0
!Initialize the lock for the non-analogue (NA) list of particles
@ -806,7 +788,7 @@ MODULE moduleInput
REAL(8):: effTime
REAL(8):: eThreshold !Energy threshold
INTEGER:: speciesID
CHARACTER(:), ALLOCATABLE:: speciesName, crossSection
CHARACTER(:), ALLOCATABLE:: speciesName, crossSection, yield
LOGICAL:: found
INTEGER:: nTypes
@ -872,6 +854,15 @@ MODULE moduleInput
CALL initWallTemperature(boundary(i)%bTypes(s)%obj, Tw, cw)
CASE('secondaryEmission')
CALL config%get(object // '.yield', yield, found)
IF (.NOT. found) CALL criticalError("missing parameter 'yield' for secondary emission", 'readBoundary')
CALL config%get(object // '.electron', speciesName, found)
IF (.NOT. found) CALL criticalError("missing parameter 'electron' for secondary emission", 'readBoundary')
speciesID = speciesName2Index(speciesName)
CALL initSEE(boundary(i)%bTypes(s)%obj, yield, speciesID)
CASE('axis')
ALLOCATE(boundaryAxis:: boundary(i)%bTypes(s)%obj)

View file

@ -816,9 +816,8 @@ MODULE moduleMesh
IF (MOD(t, everyColl) == 0) THEN
!Collisions need to be performed in this iteration
!$OMP DO SCHEDULE(DYNAMIC) PRIVATE(part_i, part_j, partTemp_i, partTemp_j)
!$OMP DO SCHEDULE(DYNAMIC) PRIVATE(part_i, part_j, partTemp_i, partTemp_j, cell)
DO e=1, self%numCells
cell => self%cells(e)%obj
!TODO: Simplify this, to many sublevels
@ -885,7 +884,7 @@ MODULE moduleMesh
!Obtain the cross sections for the different processes
!TODO: From here it might be a procedure in interactionMatrix
vRel = NORM2(part_i%v-part_j%v)
rMass = reducedMass(part_i%weight*part_i%species%m, part_j%weight*part_j%species%m)
rMass = reducedMass(part_i%weight*part_i%species%mass, part_j%weight*part_j%species%mass)
eRel = rMass*vRel**2
CALL interactionMatrix(k)%getSigmaVrel(vRel, eRel, sigmaVrelTotal, sigmaVrel)
@ -1080,7 +1079,7 @@ MODULE moduleMesh
!Compute changes in velocity for each particle
deltaV_ij(p,1:3) = MATMUL(rotation, W) + velocity - partTemp%part%v
mass_ij(p) = pair%sp_i%m*partTemp%part%weight
mass_ij(p) = pair%sp_i%mass*partTemp%part%weight
p_ij(p,1:3) = mass_ij(p)*partTemp%part%v
!Move to the next particle in the list
@ -1163,7 +1162,7 @@ MODULE moduleMesh
!Compute changes in velocity for each particle
deltaV_ji(p,1:3) = MATMUL(rotation, W) + velocity - partTemp%part%v
mass_ji(p) = pair%sp_j%m*partTemp%part%weight
mass_ji(p) = pair%sp_j%mass*partTemp%part%weight
p_ji(p,1:3) = mass_ji(p)*partTemp%part%v
!Move to the next particle in the list

View file

@ -125,7 +125,7 @@ MODULE moduleMeshBoundary
SELECT TYPE(bound => edge%boundary%bTypes(part%species%n)%obj)
TYPE IS(boundaryIonization)
mRel = reducedMass(bound%m0, part%species%m)
mRel = reducedMass(bound%m0, part%species%mass)
vRel = SUM(DABS(part%v-bound%v0))
eRel = mRel*vRel**2*5.D-1
@ -193,7 +193,7 @@ MODULE moduleMeshBoundary
END SELECT
!Removes ionizing electron regardless the number of pair created
!Removes ionizing electron regardless the number of pairs created
part%n_in = .FALSE.
END SUBROUTINE ionization
@ -212,6 +212,116 @@ MODULE moduleMeshBoundary
END SUBROUTINE symmetryAxis
!Secondary emission of electrons by impacting particle.
SUBROUTINE secondaryEmission(edge, part)
USE moduleSpecies
USE moduleRandom
USE moduleConstParam
IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
REAL(8):: vRel, eRel
REAL(8), DIMENSION(1:3):: rElectron, XiElectron!Position of new electrons (impacting particle)
REAL(8), DIMENSION(1:3):: rIncident !Vector from imapcting particle position to particle position
REAL(8):: theta !incident angle
REAL(8):: yield
REAL(8):: energy !incident energy corrected by threshold and
INTEGER:: nNewElectrons
REAL(8), ALLOCATABLE:: weight(:)
INTEGER:: p
INTEGER:: cell
TYPE(particle), POINTER:: secondaryElectron
SELECT TYPE(bound => edge%boundary%bTypes(part%species%n)%obj)
TYPE IS(boundarySEE)
!Get relative velocity
vRel = NORM2(part%v)
!Convert to relative energy
eRel = part%species%mass*vRel**2*5.D-1
!If energy is abound threshold calculate secondary electrons
IF (eRel >= bound%energyThreshold) THEN
!position of impacting ion
rElectron = edge%intersection(part%r)
XiElectron = mesh%cells(part%cell)%obj%phy2log(rElectron)
!Calculate incident angle
rIncident = part%r - rElectron
theta = ACOS(DOT_PRODUCT(rIncident, edge%normal) / (NORM2(rIncident) * NORM2(edge%normal)))
!Calculate incident energy
energy = (eRel - bound%energyThreshold) * PI2 / (PI2 + theta**2) + bound%energyThreshold
!Get number of secondary electrons particles
yield = part%weight*bound%yield%get(eRel) * (1.D0 * theta**2 / PI2) !Check equation!
!Convert the number to macro-particles
nNewElectrons = FLOOR(yield / bound%electron%weight)
!If the weight of new macro-particles is below the yield, correct adding a particle
IF (REAL(nNewElectrons) * bound%electron%weight < yield) THEN
nNewElectrons = nNewElectrons + 1
ALLOCATE(weight(1:nNewElectrons))
weight(1:nNewElectrons-1) = bound%electron%weight
weight(nNewElectrons) = yield - SUM(weight(1:nNewElectrons-1))
ELSE
ALLOCATE(weight(1:nNewElectrons))
weight(1:nNewElectrons) = bound%electron%weight
END IF
!New cell of origin
IF (ASSOCIATED(edge%e1)) THEN
cell = edge%e1%n
ELSEIF (ASSOCIATED(edge%e2)) THEN
cell = edge%e2%n
END IF
!Create the new electron macro-particles
DO p = 1, nNewElectrons
!Create new macro-particle
ALLOCATE(secondaryElectron)
!Assign species to electron
secondaryElectron%species => bound%electron
!Assign position to particle
secondaryElectron%r = rElectron
secondaryElectron%Xi = XiElectron
!Assign cell to electron
secondaryElectron%cell = cell
!Assign weight
secondaryElectron%weight = weight(p)
!Assume particle is inside the numerical domain
secondaryElectron%n_in = .TRUE.
!Assign velocity
secondaryElectron%v = 2.D0 * edge%normal + 1.D-1 * (/ randomMaxwellian(), randomMaxwellian(), randomMaxwellian() /)
!Add particle to list
CALL partSurfaces%setLock()
CALL partSurfaces%add(secondaryElectron)
CALL partSurfaces%unsetLock()
END DO
END IF
!Absorb impacting particle
CALL absorption(edge, part)
END SELECT
END SUBROUTINE secondaryEmission
!Points the boundary function to specific type
SUBROUTINE pointBoundaryFunction(edge, s)
USE moduleErrors
@ -239,6 +349,9 @@ MODULE moduleMeshBoundary
TYPE IS(boundaryAxis)
edge%fBoundary(s)%apply => symmetryAxis
TYPE IS(boundarySEE)
edge%fBoundary(s)%apply => secondaryEmission
CLASS DEFAULT
CALL criticalError("Boundary type not defined in this geometry", 'pointBoundaryFunction')

View file

@ -46,6 +46,16 @@ MODULE moduleBoundary
END TYPE boundaryIonization
!Secondary electron emission (by ion impact)
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundarySEE
!Yield as a function of ion energy
TYPE(table1D):: yield
CLASS(speciesGeneric), POINTER:: electron !Electron species for secondary emission
REAL(8):: energyThreshold
CONTAINS
END TYPE boundarySEE
!Symmetry axis
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAxis
CONTAINS
@ -137,4 +147,36 @@ MODULE moduleBoundary
END SUBROUTINE initIonization
SUBROUTINE initSEE(boundary, tableFile, speciesID)
USE moduleRefParam
USE moduleConstParam
USE moduleSpecies
IMPLICIT NONE
CLASS(boundaryGeneric), ALLOCATABLE, INTENT(out):: boundary
CHARACTER(:), ALLOCATABLE, INTENT(in):: tableFile
INTEGER:: speciesID
INTEGER:: i
ALLOCATE(boundarySEE:: boundary)
SELECT TYPE(boundary)
TYPE IS(boundarySEE)
CALL boundary%yield%init(tableFile)
CALL boundary%yield%convert(eV2J/(m_ref*v_ref**2), 1.D0)
boundary%electron => species(speciesID)%obj
!Search for the threshold energy in the table
DO i = 1, SIZE(boundary%yield%f)
IF (boundary%yield%f(i) > 0.D0) THEN
boundary%energyThreshold = boundary%yield%x(i)
EXIT
END IF
END DO
END SELECT
END SUBROUTINE initSEE
END MODULE moduleBoundary

View file

@ -164,8 +164,8 @@ MODULE moduleCollisions
self%amount = amount
mass_i = species(i)%obj%m
mass_j = species(j)%obj%m
mass_i = species(i)%obj%mass
mass_j = species(j)%obj%mass
ALLOCATE(self%collisions(1:self%amount))
@ -227,8 +227,8 @@ MODULE moduleCollisions
REAL(8):: m_i, m_j
REAL(8), DIMENSION(1:3):: vCM, vp
m_i = part_i%species%m
m_j = part_j%species%m
m_i = part_i%species%mass
m_j = part_j%species%mass
!Applies the collision
vCM = velocityCM(part_i%weight*m_i, part_i%v, part_j%weight*m_j, part_j%v)
vp = vRel*randomDirectionVHS()
@ -283,7 +283,7 @@ MODULE moduleCollisions
END SELECT
!momentum change per ionization process
collision%deltaV = sqrt(collision%eThreshold / collision%electron%m)
collision%deltaV = sqrt(collision%eThreshold / collision%electron%mass)
END SELECT
@ -307,7 +307,7 @@ MODULE moduleCollisions
REAL(8), DIMENSION(1:3):: vChange
TYPE(particle), POINTER:: newElectron => NULL(), remainingNeutral => NULL()
rMass = reducedMass(part_i%weight*part_i%species%m, part_j%weight*part_j%species%m)
rMass = reducedMass(part_i%weight*part_i%species%mass, part_j%weight*part_j%species%mass)
eRel = rMass*vRel**2
!Relative energy must be higher than threshold
IF (eRel > self%eThreshold) THEN

View file

@ -61,7 +61,7 @@ MODULE moduleCoulomb
self%sp_i => species(i)%obj
self%sp_j => species(j)%obj
self%one_plus_massRatio_ij = 1.D0 + self%sp_i%m/self%sp_j%m
self%one_plus_massRatio_ij = 1.D0 + self%sp_i%mass/self%sp_j%mass
Z_i = 0.D0
Z_j = 0.D0
@ -87,11 +87,11 @@ MODULE moduleCoulomb
scaleFactor = (n_ref * qe**4 * ti_ref) / (eps_0**2 * m_ref**2 * v_ref**3)
self%A_i = Z_i**2*Z_j**2*self%lnCoulomb / (2.D0 * PI**2 * self%sp_i%m**2) * scaleFactor !Missing density because it's cell dependent
self%A_j = Z_j**2*Z_i**2*self%lnCoulomb / (2.D0 * PI**2 * self%sp_j%m**2) * scaleFactor !Missing density because it's cell dependent
self%A_i = Z_i**2*Z_j**2*self%lnCoulomb / (2.D0 * PI**2 * self%sp_i%mass**2) * scaleFactor !Missing density because it's cell dependent
self%A_j = Z_j**2*Z_i**2*self%lnCoulomb / (2.D0 * PI**2 * self%sp_j%mass**2) * scaleFactor !Missing density because it's cell dependent
self%l2_j = self%sp_j%m / 2.D0 !Missing temperature because it's cell dependent
self%l2_i = self%sp_i%m / 2.D0 !Missing temperature because it's cell dependent
self%l2_j = self%sp_j%mass / 2.D0 !Missing temperature because it's cell dependent
self%l2_i = self%sp_i%mass / 2.D0 !Missing temperature because it's cell dependent
END SUBROUTINE initInteractionCoulomb

View file

@ -179,16 +179,21 @@ MODULE moduleInject
IMPLICIT NONE
INTEGER:: i
INTEGER, DIMENSION(1:nInject):: nMin, nMax
!$OMP SINGLE
nPartInj = 0
DO i = 1, nInject
IF (solver%pusher(inject(i)%species%n)%pushSpecies) THEN
nMin(i) = nPartInj + 1
nPartInj = nPartInj + inject(i)%nParticles
nMax(i) = nPartInj
END IF
END DO
PRINT *, nMin
PRINT *, nMax
IF (ALLOCATED(partInj)) DEALLOCATE(partInj)
ALLOCATE(partInj(1:nPartInj))
@ -196,7 +201,7 @@ MODULE moduleInject
DO i=1, nInject
IF (solver%pusher(inject(i)%species%n)%pushSpecies) THEN
CALL inject(i)%addParticles()
CALL inject(i)%addParticles(nMin(i), nMax(i))
END IF
END DO
@ -254,10 +259,7 @@ MODULE moduleInject
REAL(8):: v
v = 0.D0
DO WHILE (v <= 0.D0)
v = self%vTh*randomMaxwellian()
END DO
v = self%vTh*randomHalfMaxwellian()
END FUNCTION randomVelHalfMaxwellian
@ -282,8 +284,8 @@ MODULE moduleInject
IMPLICIT NONE
CLASS(injectGeneric), INTENT(in):: self
INTEGER, INTENT(in):: nMin, nMax !Min and Max index in partInj array
INTEGER:: randomX
INTEGER, SAVE:: nMin, nMax !Min and Max index in partInj array
INTEGER:: i
INTEGER:: n, sp
CLASS(meshEdge), POINTER:: randomEdge
@ -291,17 +293,6 @@ MODULE moduleInject
!Insert particles
!$OMP SINGLE
nMin = 0
DO i = 1, self%id -1
IF (solver%pusher(inject(i)%species%n)%pushSpecies) THEN
nMin = nMin + inject(i)%nParticles
END IF
END DO
nMin = nMin + 1
nMax = nMin + self%nParticles - 1
!Assign weight to particle.
partInj(nMin:nMax)%weight = self%species%weight
!Particle is considered to be outside the domain
@ -334,17 +325,19 @@ MODULE moduleInject
direction = self%n
partInj(n)%v = 0.D0
!Sample initial velocity
partInj(n)%v = self%vMod*direction + (/ self%v(1)%obj%randomVel(), &
self%v(2)%obj%randomVel(), &
self%v(3)%obj%randomVel() /)
!If velocity is not in the right direction, invert it
IF (DOT_PRODUCT(direction, partInj(n)%v) < 0.D0) THEN
partInj(n)%v = - partInj(n)%v
!For each direction, velocities have to agree with the direction of injection
DO i = 1, 3
DO WHILE (partInj(n)%v(i)*direction(i) < 0)
partInj(n)%v(i) = self%vMod*direction(i) + self%v(i)%obj%randomVel()
END IF
END DO
END DO
!Obtain natural coordinates of particle in cell
partInj(n)%Xi = mesh%cells(partInj(n)%cell)%obj%phy2log(partInj(n)%r)

View file

@ -4,12 +4,54 @@ MODULE moduleSpecies
USE OMP_LIB
IMPLICIT NONE
!Basic type that defines a macro-particle
TYPE:: particle
REAL(8):: r(1:3) !Position
REAL(8):: v(1:3) !Velocity
CLASS(speciesGeneric), POINTER:: species !Pointer to particle's species
INTEGER:: cell !Index of element in which the particle is located TODO: Make these pointers
INTEGER:: cellColl !Index of element in which the particle is located in the Collision Mesh
REAL(8):: Xi(1:3) !Logical coordinates of particle in cell
LOGICAL:: n_in !Flag that indicates if a particle is in the domain
REAL(8):: weight=0.D0 !weight of particle
END TYPE particle
!Wrapper to store the particles per species
TYPE:: particleArray
TYPE(particle), ALLOCATABLE, DIMENSION(:):: p
END TYPE particleArray
!Array of pointers for the particles to be pushed
TYPE:: particlePointer
TYPE(particle), POINTER:: p
END TYPE particlePointer
!Arrays that contain the particles
TYPE(particleArray), ALLOCATABLE, TARGET, DIMENSION(:):: particles !array of particles in the domain
TYPE(particle), ALLOCATABLE, TARGET, DIMENSION(:):: particlesInjection !array of inject particles
TYPE(particlePointer), ALLOCATABLE, DIMENSION(:):: particlesToPush !particles pushed in each iteration
!Integers to track number of particles in domain
INTEGER, ALLOCATABLE, DIMENSION(:):: nParticles
INTEGER:: nParticlesTotal
!Number of injected particles
INTEGER, ALLOCATABLE, DIMENSION(:):: nParticlesInject
INTEGER:: nPariclesInjectTotal
!Generic species type
TYPE, ABSTRACT:: speciesGeneric
CHARACTER(:), ALLOCATABLE:: name
REAL(8):: m=0.D0, weight=0.D0, qm=0.D0
INTEGER:: n=0
INTEGER:: n=0 !Index of species
CHARACTER(:), ALLOCATABLE:: name !Name of species
!Mass, default weight of species and charge over mass
REAL(8):: mass=0.D0, weight=0.D0, qm=0.D0
INTEGER:: every !How many interations between advancing the species
LOGICAL:: pushSpecies !Boolean to indicate if the species is moved in the iteration
END TYPE speciesGeneric
!Neutral species
TYPE, EXTENDS(speciesGeneric):: speciesNeutral
CLASS(speciesGeneric), POINTER:: ion => NULL()
CONTAINS
@ -17,6 +59,7 @@ MODULE moduleSpecies
END TYPE speciesNeutral
!Charged species
TYPE, EXTENDS(speciesGeneric):: speciesCharged
REAL(8):: q=0.D0
CLASS(speciesGeneric), POINTER:: ion => NULL(), neutral => NULL()
@ -26,34 +69,17 @@ MODULE moduleSpecies
END TYPE speciesCharged
!Wrapper for species
TYPE:: speciesCont
CLASS(speciesGeneric), ALLOCATABLE:: obj
END TYPE
!Number of species
INTEGER:: nSpecies
!Array for species
TYPE(speciesCont), ALLOCATABLE, TARGET:: species(:)
TYPE particle
REAL(8):: r(1:3) !Position
REAL(8):: v(1:3) !Velocity
CLASS(speciesGeneric), POINTER:: species !Pointer to species associated with this particle
INTEGER:: cell !Index of element in which the particle is located
INTEGER:: cellColl !Index of element in which the particle is located in the Collision Mesh
REAL(8):: Xi(1:3) !Logical coordinates of particle in element e_p.
LOGICAL:: n_in !Flag that indicates if a particle is in the domain
REAL(8):: weight=0.D0 !weight of particle
END TYPE particle
!Number of old particles
INTEGER:: nPartOld
!Number of injected particles
INTEGER:: nPartInj
!Arrays that contain the particles
TYPE(particle), ALLOCATABLE, DIMENSION(:), TARGET:: partOld !array of particles from previous iteration
TYPE(particle), ALLOCATABLE, DIMENSION(:), TARGET:: partInj !array of inject particles
CONTAINS
FUNCTION speciesName2Index(speciesName) RESULT(sp)
USE moduleErrors

View file

@ -148,7 +148,7 @@ MODULE moduleOutput
formatValues%density = rawValues%den*tempVol
formatValues%velocity(:) = tempVel
IF (tensorTrace(tensorTemp) > 0.D0) THEN
formatValues%pressure = speciesIn%m*tensorTrace(tensorTemp)*tempVol/3.D0
formatValues%pressure = speciesIn%mass*tensorTrace(tensorTemp)*tempVol/3.D0
formatValues%temperature = formatValues%pressure/(formatValues%density*kb)
END IF
@ -187,7 +187,7 @@ MODULE moduleOutput
OPEN(20, file = path // folder // '/' // fileName, position = 'append', action = 'write')
WRITE (20, "(I10, I10, 7(ES20.6E3))") t, nPartOld, tStep, tPush, tReset, tColl, tCoul, tWeight, tEMField
WRITE (20, "(I10, I10, 7(ES20.6E3))") t, nParticlesTotal, tStep, tPush, tReset, tColl, tCoul, tWeight, tEMField
CLOSE(20)

View file

@ -3,7 +3,7 @@ MODULE moduleSolver
!Generic type for pusher of particles
TYPE, PUBLIC:: pusherGeneric
PROCEDURE(push_interafece), POINTER, NOPASS:: pushParticle => NULL()
PROCEDURE(push_interface), POINTER, NOPASS:: pushParticle => NULL()
!Boolean to indicate if the species is moved in the iteration
LOGICAL:: pushSpecies
!How many interations between advancing the species
@ -29,13 +29,13 @@ MODULE moduleSolver
INTERFACE
!Push a particle
PURE SUBROUTINE push_interafece(part, tauIn)
PURE SUBROUTINE push_interface(part, tauIn)
USE moduleSpecies
TYPE(particle), INTENT(inout):: part
REAL(8), INTENT(in):: tauIn
END SUBROUTINE push_interafece
END SUBROUTINE push_interface
!Solve the electromagnetic field
SUBROUTINE solveEM_interface()
@ -123,7 +123,12 @@ MODULE moduleSolver
END SELECT
self%pushSpecies = .FALSE.
self%every = INT(tauSp/tau)
self%every = FLOOR(tauSp/tau)
!Correct value if not fulfilled
IF (tau*REAL(self%every) < tauSp) THEN
self%every = self%every + 1
END IF
END SUBROUTINE initPusher
@ -164,24 +169,75 @@ MODULE moduleSolver
USE moduleMesh
IMPLICIT NONE
INTEGER:: n
INTEGER:: sp
INTEGER:: p
INTEGER:: s, sp
INTEGER:: e
!$OMP DO
DO n = 1, nPartOld
!Select species type
sp = partOld(n)%species%n
!$OMP SINGLE
!Allocate the array of particles to push
nSpeciesToPush = COUNT(solver%pusher(:)%pushSpecies)
ALLOCATE(particlesToPush(1:nSpeciesToPush))
ALLOCATE(nPartOldToPush(1:nSpeciesToPush))
!Point the arrays to the location of the particles
sp = 0
DO s = 1, nSpecies
!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))
sp = sp + 1
particlesToPush(sp)%p = partOld(s)%p
nPartOldToPush(sp) = nPartOld(s)
END IF
END DO
!$OMP END DO
!Delete list of particles in cells for collisions if the particle is pushed
IF (listInCells) THEN
DO e = 1, mesh%numCells
DO s = 1, nSpecies
IF (solver%pusher(s)%pushSpecies) THEN
CALL mesh%cells(e)%obj%listPart_in(s)%erase()
mesh%cells(e)%obj%totalWeight(s) = 0.D0
END IF
END DO
END DO
END IF
!Erase the list of particles inside the cell in coll mesh if the particle is pushed
IF (doubleMesh) THEN
DO e = 1, meshColl%numCells
DO s = 1, nSpecies
IF (solver%pusher(s)%pushSpecies) THEN
CALL meshColl%cells(e)%obj%listPart_in(s)%erase()
meshColl%cells(e)%obj%totalWeight(s) = 0.D0
END IF
END DO
END DO
END IF
!$OMP END SINGLE
!Now, push particles
!$OMP DO
DO sp = 1, nSpeciesToPush
DO p = 1, nPartOldToPush(sp)
!Push particle
CALL solver%pusher(sp)%pushParticle(particlesToPush(sp)%p(p), tau(sp))
!Find cell in which particle reside
CALL solver%updateParticleCell(particlesToPush(sp)%p(p))
END DO
END DO
!$END OMP DO
END SUBROUTINE doPushes
@ -242,7 +298,10 @@ MODULE moduleSolver
!$OMP SECTION
nOldIn = 0
IF (ALLOCATED(partOld)) THEN
nOldIn = COUNT(partOld%n_in)
DO s = 1, nSpecies
nOldIn = nOldin + COUNT(partOld(s)%p(:)%n_in)
END DO
END IF
!$OMP SECTION
@ -319,40 +378,6 @@ MODULE moduleSolver
END DO
!$OMP SECTION
!Erase the list of particles inside the cell if particles have been pushed
IF (listInCells) THEN
DO s = 1, nSpecies
DO e = 1, mesh%numCells
IF (solver%pusher(s)%pushSpecies) THEN
CALL mesh%cells(e)%obj%listPart_in(s)%erase()
mesh%cells(e)%obj%totalWeight(s) = 0.D0
END IF
END DO
END DO
END IF
!$OMP SECTION
!Erase the list of particles inside the cell in coll mesh
IF (doubleMesh) THEN
DO s = 1, nSpecies
DO e = 1, meshColl%numCells
IF (solver%pusher(s)%pushSpecies) THEN
CALL meshColl%cells(e)%obj%listPart_in(s)%erase()
meshColl%cells(e)%obj%totalWeight(s) = 0.D0
END IF
END DO
END DO
END IF
!$OMP END SECTIONS
!$OMP SINGLE
@ -367,14 +392,17 @@ MODULE moduleSolver
USE moduleMesh
IMPLICIT NONE
INTEGER:: n
INTEGER:: n, sp
CLASS(meshCell), POINTER:: cell
!Loops over the particles to scatter them
!$OMP DO
DO n = 1, nPartOld
cell => mesh%cells(partOld(n)%cell)%obj
CALL cell%scatter(cell%nNodes, partOld(n))
DO sp = 1, nSpeciesToPush
DO n = 1, nPartOldToPush(sp)
cell => mesh%cells(particlesToPush(sp)%p(n)%cell)%obj
CALL cell%scatter(cell%nNodes, particlesToPush(sp)%p(n))
END DO
END DO
!$OMP END DO
@ -544,8 +572,8 @@ MODULE moduleSolver
END IF
IF (nPartOld > 0) THEN
WRITE(*, "(5X,A21,F8.1,A2)") "avg t/particle: ", 1.D9*tStep/DBLE(nPartOld), "ns"
IF (nPartOldTotal > 0) THEN
WRITE(*, "(5X,A21,F8.1,A2)") "avg t/particle: ", 1.D9*tStep/DBLE(nPartOldTotal), "ns"
END IF
WRITE(*,*)

View file

@ -14,7 +14,7 @@ MODULE modulePusher
END SUBROUTINE pushCartNeutral
PURE SUBROUTINE pushCartElectrostatic(part, tauIn)
USE moduleSPecies
USE moduleSpecies
USE moduleMesh
IMPLICIT NONE