Compare commits

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

13 commits

Author SHA1 Message Date
0f4e44459d Making some progress
Things are better organized.
2024-10-13 17:22:47 +02:00
94ff12b1cb New subroutines in table
These allow to invert the x and f arrays and make the X axis cumulative
sum.
2024-07-27 21:06:59 +02:00
b171f801fc Remove old code from moduleRandom
This should not be here.
2024-07-27 21:04:48 +02:00
db804bebc1 Identifying issues
I need a way to compute the energy (velocity) for the emitted particles.

I think I also need a better way to calculate the velocity distribution
of particles being injected or emitted from a surface.
2024-07-13 23:34:43 +02:00
4701321dcf Merge branch 'development' into feature/see 2024-07-13 13:02:51 +02:00
51f2726c3d Merge branch 'development' into feature/see 2024-07-11 19:11:52 +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
9 changed files with 251 additions and 9 deletions

4
data/see/constant.dat Normal file
View file

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

View file

@ -0,0 +1,3 @@
#Secondary energy (eV) Probability (a. u.)
0.1 0.5
1.0 0.5

View file

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

View file

@ -66,6 +66,24 @@ MODULE moduleRandom
END FUNCTION randomMaxwellian 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 !Returns a random number weighted with the cumWeight array
FUNCTION randomWeighted(cumWeight, sumWeight) RESULT(rnd) FUNCTION randomWeighted(cumWeight, sumWeight) RESULT(rnd)
IMPLICIT NONE IMPLICIT NONE
@ -87,7 +105,6 @@ MODULE moduleRandom
END IF END IF
END DO END DO
! rnd = MINLOC(DABS(rnd0b - cumWeight), 1)
END FUNCTION randomWeighted END FUNCTION randomWeighted

View file

@ -8,6 +8,8 @@ MODULE moduleTable
PROCEDURE, PASS:: init => initTable1D PROCEDURE, PASS:: init => initTable1D
PROCEDURE, PASS:: get => getValueTable1D PROCEDURE, PASS:: get => getValueTable1D
PROCEDURE, PASS:: convert => convertUnits PROCEDURE, PASS:: convert => convertUnits
PROCEDURE, PASS:: invertXF
PROCEDURE, PASS:: cumsumX
END TYPE table1D END TYPE table1D
@ -30,6 +32,8 @@ MODULE moduleTable
READ(id, '(A)', iostat = stat) dummy READ(id, '(A)', iostat = stat) dummy
!If EOF or error, exit file !If EOF or error, exit file
IF (stat /= 0) EXIT IF (stat /= 0) EXIT
!If empty line, exit file
IF (dummy == "") EXIT
!Skip comment !Skip comment
IF (INDEX(dummy,'#') /= 0) CYCLE IF (INDEX(dummy,'#') /= 0) CYCLE
!Add row !Add row
@ -55,6 +59,7 @@ MODULE moduleTable
!TODO: Make this a function !TODO: Make this a function
IF (INDEX(dummy,'#') /= 0) CYCLE IF (INDEX(dummy,'#') /= 0) CYCLE
IF (stat /= 0) EXIT IF (stat /= 0) EXIT
IF (dummy == "") EXIT
!Add data !Add data
!TODO: substitute with extracting information from dummy !TODO: substitute with extracting information from dummy
BACKSPACE(id) BACKSPACE(id)
@ -123,4 +128,50 @@ MODULE moduleTable
END SUBROUTINE convertUnits END SUBROUTINE convertUnits
! Invert the arrays of x and f
SUBROUTINE invertXF(self)
IMPLICIT NONE
CLASS(table1D), INTENT(inout):: self
REAL(8), ALLOCATABLE:: xTemp(:)
REAL(8):: xTempMin, xTempMax
! Store temporal x data
xTemp = self%x
xTempMin = self%xMin
xTempMax = self%xMax
! Replace x data with f data
self%x = self%f
self%xMin = self%fMin
self%xMax = self%fMax
! Put temporal x data in f data
self%f = xTemp
self%fMin = xTempMin
self%fMax = xTempMax
END SUBROUTINE invertXF
! Makes the x axis its cumulative sum
SUBROUTINE cumSumX(self)
IMPLICIT NONE
CLASS(table1D), INTENT(inout):: self
INTEGER:: nTotal, n
REAL(8), ALLOCATABLE:: cumX(:)
nTotal = SIZE(self%x)
ALLOCATE(cumX(1:nTotal))
cumX(1) = self%x(1)
DO n = 2, nTotal
cumX(n) = self%x(n) + cumX(n-1)
END DO
self%x = cumX / cumX(nTotal)
DEALLOCATE(cumX)
END SUBROUTINE cumSumX
END MODULE moduleTable END MODULE moduleTable

View file

@ -95,7 +95,10 @@ MODULE moduleInput
TYPE(json_file), INTENT(inout):: config TYPE(json_file), INTENT(inout):: config
CHARACTER(LEN=*), INTENT(in):: step CHARACTER(LEN=*), INTENT(in):: step
IF (config%failed()) CALL criticalError("Error reading the JSON input file", TRIM(step)) IF (config%failed()) THEN
CALL criticalError("Error reading the JSON input file", TRIM(step))
END IF
END SUBROUTINE checkStatus END SUBROUTINE checkStatus
@ -808,7 +811,7 @@ MODULE moduleInput
REAL(8):: effTime REAL(8):: effTime
REAL(8):: eThreshold !Energy threshold REAL(8):: eThreshold !Energy threshold
INTEGER:: speciesID, electronSecondaryID INTEGER:: speciesID, electronSecondaryID
CHARACTER(:), ALLOCATABLE:: speciesName, crossSection, electronSecondary CHARACTER(:), ALLOCATABLE:: speciesName, crossSection, yield, energySpectrum, electronSecondary
LOGICAL:: found LOGICAL:: found
INTEGER:: nTypes INTEGER:: nTypes
@ -883,6 +886,17 @@ MODULE moduleInput
CALL initWallTemperature(boundary(i)%bTypes(s)%obj, Tw, cw) 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 // '.energySpectrum', energySpectrum, found)
IF (.NOT. found) CALL criticalError("missing parameter 'energySpectrum' 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, energySpectrum, speciesID)
CASE('axis') CASE('axis')
ALLOCATE(boundaryAxis:: boundary(i)%bTypes(s)%obj) ALLOCATE(boundaryAxis:: boundary(i)%bTypes(s)%obj)

View file

@ -199,7 +199,7 @@ MODULE moduleMeshBoundary
END SELECT END SELECT
!Removes ionizing electron regardless the number of pair created !Removes ionizing electron regardless the number of pairs created
part%n_in = .FALSE. part%n_in = .FALSE.
END SUBROUTINE ionization END SUBROUTINE ionization
@ -218,6 +218,118 @@ MODULE moduleMeshBoundary
END SUBROUTINE symmetryAxis 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):: energyIncident !incident energy corrected by threshold
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%m*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
energyIncident = (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)
!Convert the number to macro-particles
nNewElectrons = FLOOR(yield / bound%electron%weight)
!If the weight of new macro-particles is below the yield, add an additional particle with less weight
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
!TODO: Calculate energy and velocity
!TODO: Better way to inject particles from surface. For this and for general injection
secondaryElectron%v = 1.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 !Points the boundary function to specific type
SUBROUTINE pointBoundaryFunction(edge, s) SUBROUTINE pointBoundaryFunction(edge, s)
USE moduleErrors USE moduleErrors
@ -245,6 +357,9 @@ MODULE moduleMeshBoundary
TYPE IS(boundaryAxis) TYPE IS(boundaryAxis)
edge%fBoundary(s)%apply => symmetryAxis edge%fBoundary(s)%apply => symmetryAxis
TYPE IS(boundarySEE)
edge%fBoundary(s)%apply => secondaryEmission
CLASS DEFAULT CLASS DEFAULT
CALL criticalError("Boundary type not defined in this geometry", 'pointBoundaryFunction') CALL criticalError("Boundary type not defined in this geometry", 'pointBoundaryFunction')

View file

@ -47,6 +47,16 @@ MODULE moduleBoundary
END TYPE boundaryIonization END TYPE boundaryIonization
!Secondary electron emission (by ion impact)
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundarySEE
TYPE(table1D):: yield !Yield as a function of ion energy
TYPE(table1D):: energySpectrum !Spectrum of secondary particle emitted
CLASS(speciesGeneric), POINTER:: electron !Electron species for secondary emission
REAL(8):: energyThreshold
CONTAINS
END TYPE boundarySEE
!Symmetry axis !Symmetry axis
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAxis TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAxis
CONTAINS CONTAINS
@ -155,4 +165,33 @@ MODULE moduleBoundary
END SUBROUTINE initIonization END SUBROUTINE initIonization
SUBROUTINE initSEE(boundary, yieldFile, energySpectrumFile, speciesID)
USE moduleRefParam
USE moduleConstParam
USE moduleSpecies
IMPLICIT NONE
CLASS(boundaryGeneric), ALLOCATABLE, INTENT(out):: boundary
CHARACTER(:), ALLOCATABLE, INTENT(in):: yieldFile
CHARACTER(:), ALLOCATABLE, INTENT(in):: energySpectrumFile
INTEGER:: speciesID
INTEGER:: i
ALLOCATE(boundarySEE:: boundary)
SELECT TYPE(boundary)
TYPE IS(boundarySEE)
CALL boundary%yield%init(yieldFile)
CALL boundary%yield%convert(eV2J/(m_ref*v_ref**2), 1.D0)
boundary%electron => species(speciesID)%obj
! Use first value from table as threshold
boundary%energyThreshold = boundary%yield%xMin
CALL boundary%energySpectrum%init(energySpectrumFile)
CALL boundary%energySpectrum%convert(eV2J/(m_ref*v_ref**2), 1.D0)
CALL boundary%energySpectrum%invertXF()
CALL boundary%energySpectrum%cumSumX()
END SELECT
END SUBROUTINE initSEE
END MODULE moduleBoundary END MODULE moduleBoundary

View file

@ -283,10 +283,7 @@ MODULE moduleInject
REAL(8):: v REAL(8):: v
v = 0.D0 v = 0.D0
DO WHILE (v <= 0.D0) v = self%vTh*randomHalfMaxwellian()
v = self%vTh*randomMaxwellian()
END DO
END FUNCTION randomVelHalfMaxwellian END FUNCTION randomVelHalfMaxwellian
@ -312,7 +309,7 @@ MODULE moduleInject
CLASS(injectGeneric), INTENT(in):: self CLASS(injectGeneric), INTENT(in):: self
INTEGER, SAVE:: nMin INTEGER, SAVE:: nMin
INTEGER:: i, e INTEGER:: i, j, e
INTEGER:: n, sp INTEGER:: n, sp
CLASS(meshEdge), POINTER:: randomEdge CLASS(meshEdge), POINTER:: randomEdge
REAL(8):: direction(1:3) REAL(8):: direction(1:3)
@ -365,6 +362,7 @@ MODULE moduleInject
partInj(n)%v = 0.D0 partInj(n)%v = 0.D0
!Sample initial velocity
partInj(n)%v = self%vMod*direction + (/ self%v(1)%obj%randomVel(), & partInj(n)%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() /)