Rename of boundary module as I start with EM
This commit is contained in:
parent
f566776af2
commit
0ae121e3b1
1 changed files with 2 additions and 2 deletions
|
|
@ -1,505 +0,0 @@
|
|||
!moduleMeshBoundary: Boundary functions for the mesh edges
|
||||
submodule(moduleMesh) boundary
|
||||
contains
|
||||
module function boundaryParticleName_to_Index(boundaryName) result(bp)
|
||||
use moduleErrors
|
||||
implicit none
|
||||
|
||||
character(:), allocatable:: boundaryName
|
||||
integer:: bp
|
||||
integer:: b
|
||||
|
||||
bp = 0
|
||||
do b = 1, nBoundaries
|
||||
if (boundaryName == boundariesParticle(b)%obj%name) then
|
||||
bp = boundariesParticle(b)%obj%n
|
||||
|
||||
end if
|
||||
|
||||
end do
|
||||
|
||||
if (bp == 0) then
|
||||
call criticalError('Boundary ' // boundaryName // ' not found', 'boundaryName2Index')
|
||||
|
||||
end if
|
||||
|
||||
end function boundaryParticleName_to_Index
|
||||
|
||||
module subroutine initBoundary(self, config, object, b)
|
||||
use json_module
|
||||
use moduleRefParam, only: m_ref
|
||||
use moduleConstParam, only: me
|
||||
implicit none
|
||||
|
||||
class(boundaryGeneric), allocatable, intent(out):: self
|
||||
type(json_file), intent(inout):: config
|
||||
character(:), allocatable, intent(in):: object
|
||||
integer, intent(in):: b
|
||||
character(:), allocatable:: bType
|
||||
logical:: found
|
||||
real(8):: Tw, cw !Wall temperature and specific heat
|
||||
!neutral Properties
|
||||
real(8):: m0, n0, T0
|
||||
real(8), dimension(:), allocatable:: v0
|
||||
real(8):: effTime
|
||||
real(8):: eThreshold !Energy threshold
|
||||
integer:: speciesID, electronSecondaryID
|
||||
character(:), allocatable:: speciesName, crossSection, electronSecondary
|
||||
|
||||
self%n = b
|
||||
CALL config%get(object // '.name', self%name, found)
|
||||
CALL config%get(object // '.type', bType, found)
|
||||
SELECT CASE(bType)
|
||||
CASE('reflection')
|
||||
ALLOCATE(boundaryReflection:: self)
|
||||
|
||||
CASE('absorption')
|
||||
ALLOCATE(boundaryAbsorption:: self)
|
||||
|
||||
CASE('transparent')
|
||||
ALLOCATE(boundaryTransparent:: self)
|
||||
|
||||
CASE('axis')
|
||||
ALLOCATE(boundaryAxis:: self)
|
||||
|
||||
CASE('wallTemperature')
|
||||
CALL config%get(object // '.temperature', Tw, found)
|
||||
IF (.NOT. found) CALL criticalError("temperature not found for wallTemperature boundary type", 'readBoundary')
|
||||
CALL config%get(object // '.specificHeat', cw, found)
|
||||
IF (.NOT. found) CALL criticalError("specificHeat not found for wallTemperature boundary type", 'readBoundary')
|
||||
|
||||
CALL initWallTemperature(self, Tw, cw)
|
||||
|
||||
CASE('ionization')
|
||||
!Neutral parameters
|
||||
CALL config%get(object // '.neutral.ion', speciesName, found)
|
||||
IF (.NOT. found) CALL criticalError("missing parameter 'ion' for neutrals in ionization", 'readBoundary')
|
||||
speciesID = speciesName2Index(speciesName)
|
||||
CALL config%get(object // '.neutral.mass', m0, found)
|
||||
IF (.NOT. found) CALL criticalError("missing parameter 'mass' for neutrals in ionization", 'readBoundary')
|
||||
CALL config%get(object // '.neutral.density', n0, found)
|
||||
IF (.NOT. found) CALL criticalError("missing parameter 'density' for neutrals in ionization", 'readBoundary')
|
||||
CALL config%get(object // '.neutral.velocity', v0, found)
|
||||
IF (.NOT. found) CALL criticalError("missing parameter 'velocity' for neutrals in ionization", 'readBoundary')
|
||||
CALL config%get(object // '.neutral.temperature', T0, found)
|
||||
IF (.NOT. found) CALL criticalError("missing parameter 'temperature' for neutrals in ionization", 'readBoundary')
|
||||
|
||||
CALL config%get(object // '.effectiveTime', effTime, found)
|
||||
IF (.NOT. found) CALL criticalError("missing parameter 'effectiveTime' for ionization", 'readBoundary')
|
||||
|
||||
CALL config%get(object // '.energyThreshold', eThreshold, found)
|
||||
IF (.NOT. found) CALL criticalError("missing parameter 'eThreshold' in ionization", 'readBoundary')
|
||||
|
||||
CALL config%get(object // '.crossSection', crossSection, found)
|
||||
IF (.NOT. found) CALL criticalError("missing parameter 'crossSection' for neutrals in ionization", 'readBoundary')
|
||||
|
||||
CALL config%get(object // '.electronSecondary', electronSecondary, found)
|
||||
electronSecondaryID = speciesName2Index(electronSecondary)
|
||||
IF (found) THEN
|
||||
CALL initIonization(self, me/m_ref, m0, n0, v0, T0, &
|
||||
speciesID, effTime, crossSection, eThreshold,electronSecondaryID)
|
||||
|
||||
|
||||
ELSE
|
||||
CALL initIonization(self, me/m_ref, m0, n0, v0, T0, &
|
||||
speciesID, effTime, crossSection, eThreshold)
|
||||
|
||||
END IF
|
||||
|
||||
case('quasiNeutrality')
|
||||
call initQuasiNeutrality(self)
|
||||
|
||||
CASE DEFAULT
|
||||
CALL criticalError('Boundary type ' // bType // ' undefined', 'readBoundary')
|
||||
|
||||
END SELECT
|
||||
|
||||
end subroutine initBoundary
|
||||
|
||||
SUBROUTINE initWallTemperature(boundary, T, c)
|
||||
USE moduleRefParam
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(boundaryGeneric), ALLOCATABLE, INTENT(out):: boundary
|
||||
REAL(8), INTENT(in):: T, c !Wall temperature and specific heat
|
||||
REAL(8):: vTh
|
||||
|
||||
vTh = DSQRT(c * T) / v_ref
|
||||
allocate(boundaryWallTemperature:: boundary)
|
||||
|
||||
select type(boundary)
|
||||
type is(boundaryWallTemperature)
|
||||
boundary%vTh = vTh
|
||||
|
||||
end select
|
||||
|
||||
END SUBROUTINE initWallTemperature
|
||||
|
||||
SUBROUTINE initIonization(boundary, mImpact, m0, n0, v0, T0, ion, effTime, crossSection, eThreshold, electronSecondary)
|
||||
USE moduleRefParam
|
||||
USE moduleSpecies
|
||||
USE moduleCaseParam
|
||||
USE moduleConstParam
|
||||
USE moduleErrors
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(boundaryGeneric), ALLOCATABLE, INTENT(out):: boundary
|
||||
real(8), intent(in):: mImpact
|
||||
REAL(8), INTENT(in):: m0, n0, v0(1:3), T0 !Neutral properties
|
||||
INTEGER, INTENT(in):: ion
|
||||
INTEGER, OPTIONAL, INTENT(in):: electronSecondary
|
||||
REAL(8):: effTime
|
||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: crossSection
|
||||
REAL(8), INTENT(in):: eThreshold
|
||||
|
||||
ALLOCATE(boundaryIonization:: boundary)
|
||||
|
||||
SELECT TYPE(boundary)
|
||||
TYPE IS(boundaryIonization)
|
||||
boundary%m0 = m0 / m_ref
|
||||
boundary%n0 = n0 * Vol_ref
|
||||
boundary%v0 = v0 / v_ref
|
||||
boundary%vTh = DSQRT(kb*T0/m0)/v_ref
|
||||
boundary%species => species(ion)%obj
|
||||
IF (PRESENT(electronSecondary)) THEN
|
||||
SELECT TYPE(sp => species(electronSecondary)%obj)
|
||||
TYPE IS(speciesCharged)
|
||||
boundary%electronSecondary => sp
|
||||
|
||||
CLASS DEFAULT
|
||||
CALL criticalError("Species " // sp%name // " chosen for " // &
|
||||
"secondary electron is not a charged species", 'initIonization')
|
||||
|
||||
END SELECT
|
||||
|
||||
ELSE
|
||||
boundary%electronSecondary => NULL()
|
||||
|
||||
END IF
|
||||
boundary%effectiveTime = effTime / ti_ref
|
||||
CALL boundary%crossSection%init(crossSection)
|
||||
CALL boundary%crossSection%convert(eV2J/(m_ref*v_ref**2), 1.D0/L_ref**2)
|
||||
boundary%eThreshold = eThreshold*eV2J/(m_ref*v_ref**2)
|
||||
boundary%deltaV = DSQRT(boundary%eThreshold/mImpact)
|
||||
|
||||
END SELECT
|
||||
|
||||
END SUBROUTINE initIonization
|
||||
|
||||
subroutine initQuasiNeutrality(boundary)
|
||||
implicit none
|
||||
|
||||
class(boundaryGeneric), allocatable, intent(out):: boundary
|
||||
integer:: e, et
|
||||
|
||||
allocate(boundaryQuasiNeutrality:: boundary)
|
||||
|
||||
select type(boundary)
|
||||
type is(boundaryQuasiNeutrality)
|
||||
boundary%alpha = 0.d0
|
||||
|
||||
end select
|
||||
|
||||
end subroutine initQuasiNeutrality
|
||||
|
||||
module SUBROUTINE reflection(self, edge, part)
|
||||
USE moduleCaseParam
|
||||
USE moduleSpecies
|
||||
IMPLICIT NONE
|
||||
|
||||
class(boundaryReflection), intent(in):: self
|
||||
CLASS(meshEdge), INTENT(inout):: edge
|
||||
CLASS(particle), INTENT(inout):: part
|
||||
!rp = intersection between particle and edge
|
||||
!rpp = final position of particle
|
||||
!vpp = final velocity of particle
|
||||
REAL(8), DIMENSION(1:3):: rp, vpp
|
||||
|
||||
!Reflect particle velocity
|
||||
vpp = part%v - 2.D0*DOT_PRODUCT(part%v, edge%normal)*edge%normal
|
||||
part%v = vpp
|
||||
|
||||
rp = edge%intersection(part%r)
|
||||
|
||||
part%r = 2.D0*(rp - part%r) + part%r
|
||||
|
||||
!particle is assumed to be inside
|
||||
part%n_in = .TRUE.
|
||||
|
||||
END SUBROUTINE reflection
|
||||
|
||||
!Absoption in a surface
|
||||
SUBROUTINE absorption(self, edge, part)
|
||||
USE moduleCaseParam
|
||||
USE moduleSpecies
|
||||
IMPLICIT NONE
|
||||
|
||||
class(boundaryAbsorption), intent(in):: self
|
||||
CLASS(meshEdge), INTENT(inout):: edge
|
||||
CLASS(particle), INTENT(inout):: part
|
||||
REAL(8):: rpp(1:3) !Position of particle projected to the edge
|
||||
REAL(8):: d !Distance from particle to edge
|
||||
|
||||
rpp = edge%intersection(part%r)
|
||||
|
||||
d = NORM2(rpp - part%r)
|
||||
|
||||
IF (d >= 0.D0) THEN
|
||||
part%weight = part%weight/d
|
||||
|
||||
END IF
|
||||
|
||||
!Assign new position to particle
|
||||
part%r = rpp
|
||||
!Remove particle from the domain
|
||||
part%n_in = .FALSE.
|
||||
|
||||
!Scatter particle in associated volume
|
||||
IF (ASSOCIATED(edge%e1)) THEN
|
||||
CALL edge%e1%scatter(edge%e1%nNodes, part)
|
||||
|
||||
ELSE
|
||||
CALL edge%e2%scatter(edge%e2%nNodes, part)
|
||||
|
||||
END IF
|
||||
|
||||
END SUBROUTINE absorption
|
||||
|
||||
!Transparent boundary condition
|
||||
SUBROUTINE transparent(self, edge, part)
|
||||
USE moduleSpecies
|
||||
IMPLICIT NONE
|
||||
|
||||
class(boundaryTransparent), intent(in):: self
|
||||
CLASS(meshEdge), INTENT(inout):: edge
|
||||
CLASS(particle), INTENT(inout):: part
|
||||
|
||||
!Removes particle from domain
|
||||
part%n_in = .FALSE.
|
||||
|
||||
END SUBROUTINE transparent
|
||||
|
||||
!Symmetry axis. Reflects particles.
|
||||
!Although this function should never be called, it is set as a reflective boundary
|
||||
!to properly deal with possible particles reaching a corner and selecting this boundary.
|
||||
SUBROUTINE symmetryAxis(self, edge, part)
|
||||
USE moduleSpecies
|
||||
IMPLICIT NONE
|
||||
|
||||
class(boundaryAxis), intent(in):: self
|
||||
CLASS(meshEdge), INTENT(inout):: edge
|
||||
CLASS(particle), INTENT(inout):: part
|
||||
|
||||
CALL genericReflection(edge, part)
|
||||
|
||||
END SUBROUTINE symmetryAxis
|
||||
|
||||
!Wall with temperature
|
||||
SUBROUTINE wallTemperature(self, edge, part)
|
||||
USE moduleSpecies
|
||||
USE moduleRandom
|
||||
IMPLICIT NONE
|
||||
|
||||
class(boundaryWallTemperature), intent(in):: self
|
||||
CLASS(meshEdge), INTENT(inout):: edge
|
||||
CLASS(particle), INTENT(inout):: part
|
||||
INTEGER:: i
|
||||
|
||||
!Modifies particle velocity according to wall temperature
|
||||
DO i = 1, 3
|
||||
part%v(i) = part%v(i) + self%vTh*randomMaxwellian()
|
||||
|
||||
END DO
|
||||
|
||||
CALL genericReflection(edge, part)
|
||||
|
||||
END SUBROUTINE wallTemperature
|
||||
|
||||
!Ionization surface: an electron will pass through the surface
|
||||
! and create an ion-electron pair based on a neutral background
|
||||
SUBROUTINE ionization(self, edge, part)
|
||||
USE moduleList
|
||||
USE moduleSpecies
|
||||
USE moduleMesh
|
||||
USE moduleRefParam
|
||||
USE moduleRandom
|
||||
USE moduleMath
|
||||
IMPLICIT NONE
|
||||
|
||||
class(boundaryIonization), intent(in):: self
|
||||
CLASS(meshEdge), INTENT(inout):: edge
|
||||
CLASS(particle), INTENT(inout):: part
|
||||
REAL(8):: vRel, eRel, mRel !relative velocity, energy and mass
|
||||
INTEGER:: nIonizations !Number of ionizations based on eRel
|
||||
REAL(8):: pIonization !Probability of ionization of each event
|
||||
INTEGER:: p
|
||||
REAL(8):: v0(1:3) !random velocity of neutral
|
||||
TYPE(particle), POINTER:: newElectron
|
||||
TYPE(particle), POINTER:: newIon
|
||||
|
||||
mRel = reducedMass(self%m0, part%species%m)
|
||||
vRel = SUM(DABS(part%v-self%v0))
|
||||
eRel = mRel*vRel**2*5.D-1
|
||||
|
||||
!Maximum number of possible ionizations based on relative energy
|
||||
nIonizations = FLOOR(eRel/self%eThreshold)
|
||||
|
||||
DO p = 1, nIonizations
|
||||
!Get probability of ionization
|
||||
pIonization = 1.D0 - DEXP(-self%n0*self%crossSection%get(eRel)*vRel*self%effectiveTime/REAL(nIonizations))
|
||||
|
||||
!If a random number is below the probability of ionization, create new pair of ion-electron
|
||||
IF (random() < pIonization) THEN
|
||||
!Assign random velocity to the neutral
|
||||
v0(1) = self%v0(1) + self%vTh*randomMaxwellian()
|
||||
v0(2) = self%v0(2) + self%vTh*randomMaxwellian()
|
||||
v0(3) = self%v0(3) + self%vTh*randomMaxwellian()
|
||||
|
||||
!Allocates the new particles
|
||||
ALLOCATE(newElectron)
|
||||
ALLOCATE(newIon)
|
||||
|
||||
IF (ASSOCIATED(self%electronSecondary)) THEN
|
||||
newElectron%species => self%electronSecondary
|
||||
|
||||
ELSE
|
||||
newElectron%species => part%species
|
||||
|
||||
END IF
|
||||
newIon%species => self%species
|
||||
|
||||
newElectron%v = v0 + (1.D0 + self%deltaV*v0/NORM2(v0))
|
||||
newIon%v = v0
|
||||
|
||||
newElectron%r = edge%randPos()
|
||||
newIon%r = newElectron%r
|
||||
|
||||
IF (ASSOCIATED(edge%e1)) THEN
|
||||
newElectron%cell = edge%e1%n
|
||||
|
||||
ELSEIF (ASSOCIATED(edge%e2)) THEN
|
||||
newElectron%cell = edge%e2%n
|
||||
|
||||
END IF
|
||||
newIon%cell = newElectron%cell
|
||||
|
||||
newElectron%Xi = mesh%cells(part%cell)%obj%phy2log(newElectron%r)
|
||||
newIon%Xi = newElectron%Xi
|
||||
|
||||
newElectron%weight = part%weight
|
||||
newIon%weight = newElectron%weight
|
||||
|
||||
newElectron%n_in = .TRUE.
|
||||
newIon%n_in = .TRUE.
|
||||
|
||||
!Add particles to list
|
||||
CALL partSurfaces%setLock()
|
||||
CALL partSurfaces%add(newElectron)
|
||||
CALL partSurfaces%add(newIon)
|
||||
CALL partSurfaces%unsetLock()
|
||||
|
||||
!Electron loses energy due to ionization
|
||||
eRel = eRel - self%eThreshold
|
||||
vRel = 2.D0*DSQRT(eRel)/mRel
|
||||
|
||||
!Reduce number of possible ionizations
|
||||
nIonizations = nIonizations - 1
|
||||
|
||||
END IF
|
||||
|
||||
END DO
|
||||
|
||||
!Removes ionizing electron regardless the number of pair created
|
||||
part%n_in = .FALSE.
|
||||
|
||||
END SUBROUTINE ionization
|
||||
|
||||
subroutine quasiNeutrality(self, edge, part)
|
||||
use moduleRandom
|
||||
implicit none
|
||||
|
||||
class(boundaryQuasiNeutrality), intent(in):: self
|
||||
class(meshEdge), intent(inout):: edge
|
||||
class(particle), intent(inout):: part
|
||||
real(8), allocatable:: density(:)
|
||||
class(meshCell), pointer:: cell
|
||||
real(8):: EF_dir
|
||||
real(8):: alpha
|
||||
|
||||
|
||||
if (associated(edge%e1)) then
|
||||
cell => edge%e1
|
||||
|
||||
else
|
||||
cell => edge%e2
|
||||
|
||||
end if
|
||||
|
||||
if (random() <= alpha) then
|
||||
call genericReflection(edge, part)
|
||||
|
||||
else
|
||||
call genericTransparent(edge, part)
|
||||
|
||||
end if
|
||||
|
||||
end subroutine quasiNeutrality
|
||||
|
||||
! Generic boundary conditions for internal use
|
||||
module subroutine genericReflection(edge, part)
|
||||
use moduleCaseParam
|
||||
use moduleSpecies
|
||||
implicit none
|
||||
|
||||
class(meshEdge), intent(inout):: edge
|
||||
class(particle), intent(inout):: part
|
||||
!rp = intersection between particle and edge
|
||||
!rpp = final position of particle
|
||||
!vpp = final velocity of particle
|
||||
real(8), dimension(1:3):: rp, vpp
|
||||
|
||||
!Reflect particle velocity
|
||||
vpp = part%v - 2.D0*dot_product(part%v, edge%normal)*edge%normal
|
||||
part%v = vpp
|
||||
|
||||
rp = edge%intersection(part%r)
|
||||
|
||||
part%r = 2.D0*(rp - part%r) + part%r
|
||||
|
||||
!particle is assumed to be inside
|
||||
part%n_in = .TRUE.
|
||||
|
||||
end subroutine genericReflection
|
||||
|
||||
subroutine genericTransparent(edge, part)
|
||||
use moduleSpecies
|
||||
implicit none
|
||||
|
||||
class(meshEdge), intent(inout):: edge
|
||||
class(particle), intent(inout):: part
|
||||
|
||||
!Removes particle from domain
|
||||
part%n_in = .FALSE.
|
||||
|
||||
end subroutine genericTransparent
|
||||
|
||||
function physicalSurface_to_id(physicalSurface) result(b)
|
||||
implicit none
|
||||
|
||||
integer:: physicalSurface
|
||||
integer:: b
|
||||
integer:: bt
|
||||
|
||||
do bt=1, nPhysicalSurfaces
|
||||
if (boundariesParticleLinking(bt)%physicalSurface == physicalSurface) then
|
||||
b = bt
|
||||
|
||||
exit
|
||||
|
||||
end if
|
||||
|
||||
end do
|
||||
|
||||
end function physicalSurface_to_id
|
||||
|
||||
end submodule boundary
|
||||
Loading…
Add table
Add a link
Reference in a new issue