Compare commits
13 commits
developmen
...
feature/se
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f4e44459d | |||
| 94ff12b1cb | |||
| b171f801fc | |||
| db804bebc1 | |||
| 4701321dcf | |||
| 51f2726c3d | |||
| 541a6ff97a | |||
| e1009a21df | |||
| cc3e28e5e7 | |||
| 38fa37c995 | |||
| 0f7d9919ec | |||
| e369bccf78 | |||
| 21184e91d3 |
9 changed files with 251 additions and 9 deletions
4
data/see/constant.dat
Normal file
4
data/see/constant.dat
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
#Relative energy (eV) yield ()
|
||||||
|
0.000 1.000E-01
|
||||||
|
1.000 1.000E-01
|
||||||
|
|
||||||
3
data/see/constant_energy.dat
Normal file
3
data/see/constant_energy.dat
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#Secondary energy (eV) Probability (a. u.)
|
||||||
|
0.1 0.5
|
||||||
|
1.0 0.5
|
||||||
1
doc/user-manual/.gitignore
vendored
1
doc/user-manual/.gitignore
vendored
|
|
@ -20,3 +20,4 @@ fpakc_UserManual-blx.bib
|
||||||
*.gls
|
*.gls
|
||||||
*.ist
|
*.ist
|
||||||
fpakc_UserManual.run.xml
|
fpakc_UserManual.run.xml
|
||||||
|
*.bib.sav
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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() /)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue