Boundaries done. Now to change the input and edges

This commit is contained in:
Jorge Gonzalez 2026-02-09 18:43:59 +01:00
commit 0ccf455986
5 changed files with 239 additions and 221 deletions

View file

@ -10,6 +10,7 @@ MODULE moduleConstParam
REAL(8), PARAMETER:: PI8 = 8.D0*PI !8*pi REAL(8), PARAMETER:: PI8 = 8.D0*PI !8*pi
REAL(8), PARAMETER:: sccm2atomPerS = 4.5D17 !sccm to atom s^-1 REAL(8), PARAMETER:: sccm2atomPerS = 4.5D17 !sccm to atom s^-1
REAL(8), PARAMETER:: qe = 1.60217662D-19 !Elementary charge REAL(8), PARAMETER:: qe = 1.60217662D-19 !Elementary charge
real(8), parameter:: me = 9.1093837d-31 !electron mass
REAL(8), PARAMETER:: kb = 1.38064852D-23 !Boltzmann constants SI REAL(8), PARAMETER:: kb = 1.38064852D-23 !Boltzmann constants SI
REAL(8), PARAMETER:: eV2J = qe !Electron volt to Joule conversion REAL(8), PARAMETER:: eV2J = qe !Electron volt to Joule conversion
REAL(8), PARAMETER:: eps_0 = 8.8542D-12 !Epsilon_0 REAL(8), PARAMETER:: eps_0 = 8.8542D-12 !Epsilon_0

View file

@ -795,7 +795,6 @@ MODULE moduleInput
use moduleMesh use moduleMesh
USE moduleErrors USE moduleErrors
USE moduleSpecies USE moduleSpecies
USE moduleRefParam
USE moduleList, ONLY: partSurfaces USE moduleList, ONLY: partSurfaces
USE json_module USE json_module
IMPLICIT NONE IMPLICIT NONE

View file

@ -86,8 +86,8 @@ MODULE moduleMesh
REAL(8):: normal(1:3) REAL(8):: normal(1:3)
! Surface of edge ! Surface of edge
REAL(8):: surface = 0.D0 REAL(8):: surface = 0.D0
!Pointer to boundary type !Pointer to boundary per species
TYPE(boundaryCont), POINTER:: boundaries(:) TYPE(boundaryCont), POINTER:: boundariesParticle(:)
!Physical surface for the edge !Physical surface for the edge
INTEGER:: physicalSurface INTEGER:: physicalSurface
CONTAINS CONTAINS
@ -587,36 +587,33 @@ MODULE moduleMesh
! Boundary Particle Definitions ! Boundary Particle Definitions
!Generic type for boundaries !Generic type for boundaries
TYPE, abstract, PUBLIC:: boundaryGeneric TYPE, abstract, PUBLIC:: boundaryGeneric
integer:: n = 0
character(:), allocatable:: name character(:), allocatable:: name
integer:: physicalSurface = 0 !Physical surface as defined in the mesh file
contains contains
procedure, pass:: initBoundary procedure, pass:: init => initBoundary
procedure(boundary_interface), deferred, pass:: apply procedure(boundary_interface), deferred, nopass:: apply
END TYPE boundaryGeneric END TYPE boundaryGeneric
interface interface
module subroutine initBoundary(self, config, object, i) module subroutine initBoundary(self, config, object)
use json_module use json_module
class(boundaryGeneric), intent(out):: self class(boundaryGeneric), intent(out):: self
type(json_file), intent(inout):: config type(json_file), intent(inout):: config
character(:), allocatable, intent(in):: object character(:), allocatable, intent(in):: object
integer, intent(in):: i
end subroutine initBoundary end subroutine initBoundary
end interface end interface
abstract interface abstract interface
subroutine boundary_interface(self, edge, part) subroutine boundary_interface(edge, part, self)
use moduleSpecies use moduleSpecies
import boundaryGeneric, meshEdge import boundaryGeneric, meshEdge
class(boundaryGeneric), intent(in):: self class(meshEdge), intent(inout):: edge
class(meshEdge), intent(inout):: edge class(particle), intent(inout):: part
class(particle), intent(inout):: part class(boundaryGeneric), optional, intent(in):: self
end subroutine end subroutine
@ -625,28 +622,28 @@ MODULE moduleMesh
!Reflecting boundary !Reflecting boundary
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryReflection TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryReflection
CONTAINS CONTAINS
procedure, pass:: apply => reflection procedure, nopass:: apply => reflection
END TYPE boundaryReflection END TYPE boundaryReflection
!Absorption boundary !Absorption boundary
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAbsorption TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAbsorption
CONTAINS CONTAINS
procedure, pass:: apply => absorption procedure, nopass:: apply => absorption
END TYPE boundaryAbsorption END TYPE boundaryAbsorption
!Transparent boundary !Transparent boundary
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryTransparent TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryTransparent
CONTAINS CONTAINS
procedure, pass:: apply => transparent procedure, nopass:: apply => transparent
END TYPE boundaryTransparent END TYPE boundaryTransparent
!Symmetry axis !Symmetry axis
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAxis TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAxis
CONTAINS CONTAINS
procedure, pass:: apply => axis procedure, nopass:: apply => axis
END TYPE boundaryAxis END TYPE boundaryAxis
@ -655,7 +652,7 @@ MODULE moduleMesh
!Thermal velocity of the wall: square root(Wall temperature X specific heat) !Thermal velocity of the wall: square root(Wall temperature X specific heat)
REAL(8):: vTh REAL(8):: vTh
CONTAINS CONTAINS
procedure, pass:: apply => wallTemperature procedure, nopass:: apply => wallTemperature
END TYPE boundaryWallTemperature END TYPE boundaryWallTemperature
@ -669,7 +666,7 @@ MODULE moduleMesh
REAL(8):: eThreshold REAL(8):: eThreshold
REAL(8):: deltaV REAL(8):: deltaV
CONTAINS CONTAINS
procedure, pass:: apply => ionization procedure, nopass:: apply => ionization
END TYPE boundaryIonization END TYPE boundaryIonization
@ -678,17 +675,11 @@ MODULE moduleMesh
real(8):: alpha ! Reflection parameter real(8):: alpha ! Reflection parameter
integer, allocatable:: edges(:) !Array with edges integer, allocatable:: edges(:) !Array with edges
contains contains
procedure, pass:: apply => quasiNeutrality procedure, nopass:: apply => quasiNeutrality
end type boundaryQuasiNeutrality end type boundaryQuasiNeutrality
!Wrapper for boundary types (one per species) !Wrapper for boundary types (one per species)
TYPE:: bTypesCont
CLASS(boundaryGeneric), ALLOCATABLE:: obj
CONTAINS
END TYPE bTypesCont
interface interface
module subroutine pointBoundaryFunction(edge, s) module subroutine pointBoundaryFunction(edge, s)
class(meshEdge), intent(inout):: edge class(meshEdge), intent(inout):: edge
@ -696,36 +687,73 @@ MODULE moduleMesh
end subroutine pointBoundaryFunction end subroutine pointBoundaryFunction
module function getBoundaryId(physicalSurface) result(id) module subroutine reflection(edge, part, self)
integer:: physicalSurface
end function getBoundaryId
module subroutine reflection(self, edge, part)
use moduleSpecies use moduleSpecies
class(boundaryReflection), intent(in):: self class(meshEdge), intent(inout):: edge
class(meshEdge), intent(inout):: edge class(particle), intent(inout):: part
class(particle), intent(inout):: part class(boundaryGeneric), optional, intent(in):: self
end subroutine reflection end subroutine reflection
module subroutine absorption(self, edge, part) module subroutine absorption(edge, part, self)
use moduleSpecies use moduleSpecies
class(boundaryAbsorption), intent(in):: self class(meshEdge), intent(inout):: edge
class(meshEdge), intent(inout):: edge class(particle), intent(inout):: part
class(particle), intent(inout):: part class(boundaryGeneric), optional, intent(in):: self
end subroutine absorption end subroutine absorption
module subroutine transparent(edge, part, self)
use moduleSpecies
class(meshEdge), intent(inout):: edge
class(particle), intent(inout):: part
class(boundaryGeneric), optional, intent(in):: self
end subroutine transparent
module subroutine axis(edge, part, self)
use moduleSpecies
class(meshEdge), intent(inout):: edge
class(particle), intent(inout):: part
class(boundaryGeneric), optional, intent(in):: self
end subroutine axis
module subroutine wallTemperature(edge, part, self)
use moduleSpecies
class(meshEdge), intent(inout):: edge
class(particle), intent(inout):: part
class(boundaryGeneric), optional, intent(in):: self
end subroutine wallTemperature
module subroutine ionization(edge, part, self)
use moduleSpecies
class(meshEdge), intent(inout):: edge
class(particle), intent(inout):: part
class(boundaryGeneric), optional, intent(in):: self
end subroutine ionization
module subroutine quasiNeutrality(edge, part, self)
use moduleSpecies
class(meshEdge), intent(inout):: edge
class(particle), intent(inout):: part
class(boundaryGeneric), optional, intent(in):: self
end subroutine quasiNeutrality
end interface end interface
TYPE:: boundaryCont TYPE:: boundaryCont
INTEGER:: n = 0 CLASS(boundaryGeneric), ALLOCATABLE:: obj
CHARACTER(:), ALLOCATABLE:: name
INTEGER:: physicalSurface = 0 !Physical surface as defined in the mesh file
CLASS(bTypesCont), ALLOCATABLE:: bTypes(:) !Array for boundary per species
CONTAINS CONTAINS
END TYPE boundaryCont END TYPE boundaryCont
@ -733,6 +761,6 @@ MODULE moduleMesh
!Number of boundaries !Number of boundaries
INTEGER:: nBoundary = 0 INTEGER:: nBoundary = 0
!Array for boundaries !Array for boundaries
TYPE(boundaryCont), ALLOCATABLE, TARGET:: boundaries(:) TYPE(boundaryCont), ALLOCATABLE, TARGET:: boundariesParticle(:)
END MODULE moduleMesh END MODULE moduleMesh

View file

@ -1,29 +1,30 @@
!moduleMeshBoundary: Boundary functions for the mesh edges !moduleMeshBoundary: Boundary functions for the mesh edges
submodule(moduleMesh) boundary submodule(moduleMesh) boundary
CONTAINS CONTAINS
FUNCTION getBoundaryId(physicalSurface) RESULT(id) ! FUNCTION getBoundaryId(physicalSurface) RESULT(id)
IMPLICIT NONE ! IMPLICIT NONE
INTEGER:: physicalSurface ! INTEGER:: physicalSurface
INTEGER:: id ! INTEGER:: id
INTEGER:: i ! INTEGER:: i
id = 0 ! id = 0
DO i = 1, nBoundary ! DO i = 1, nBoundary
IF (physicalSurface == boundaries(i)%physicalSurface) id = boundaries(i)%n ! IF (physicalSurface == boundariesParticle(i)%obj%physicalSurface) id = boundariesParticle(i)%obj%n
END DO ! END DO
END FUNCTION getBoundaryId ! END FUNCTION getBoundaryId
module subroutine initBoundary(self, config, object, i) module subroutine initBoundary(self, config, object)
use json_module use json_module
use moduleRefParam, only: m_ref
use moduleConstParam, only: me
implicit none implicit none
class(boundaryGeneric), intent(out):: self class(boundaryGeneric), allocatable, intent(out):: self
type(json_file), intent(inout):: config type(json_file), intent(inout):: config
character(:), allocatable, intent(in):: object character(:), allocatable, intent(in):: object
integer, intent(in):: i
character(:), allocatable:: bType character(:), allocatable:: bType
logical:: found logical:: found
real(8):: Tw, cw !Wall temperature and specific heat real(8):: Tw, cw !Wall temperature and specific heat
@ -35,86 +36,73 @@ submodule(moduleMesh) boundary
integer:: speciesID, electronSecondaryID integer:: speciesID, electronSecondaryID
character(:), allocatable:: speciesName, crossSection, electronSecondary character(:), allocatable:: speciesName, crossSection, electronSecondary
self%n = i CALL config%get(object // '.name', self%name, found)
CALL config%get(object // '.name', self%name, found) CALL config%get(object // '.type', bType, found)
CALL config%get(object // '.physicalSurface', self%physicalSurface, found) SELECT CASE(bType)
CALL config%info(object // '.bTypes', found, n_children = nTypes) CASE('reflection')
IF (nTypes /= nSpecies) CALL criticalError('Not enough boundary types defined in ' // object, 'readBoundary') ALLOCATE(boundaryReflection:: self)
ALLOCATE(self%bTypes(1:nSpecies))
DO s = 1, nSpecies
WRITE(sString,'(i2)') s
object = 'boundary(' // TRIM(iString) // ').bTypes(' // TRIM(sString) // ')'
CALL config%get(object // '.type', bType, found)
associate(bound => self%bTypes(s)%obj)
SELECT CASE(bType)
CASE('reflection')
ALLOCATE(boundaryReflection:: bound)
CASE('absorption') CASE('absorption')
ALLOCATE(boundaryAbsorption:: bound) ALLOCATE(boundaryAbsorption:: self)
CASE('transparent') CASE('transparent')
ALLOCATE(boundaryTransparent:: bound) ALLOCATE(boundaryTransparent:: self)
CASE('axis') CASE('axis')
ALLOCATE(boundaryAxis:: bound) ALLOCATE(boundaryAxis:: self)
CASE('wallTemperature') CASE('wallTemperature')
CALL config%get(object // '.temperature', Tw, found) CALL config%get(object // '.temperature', Tw, found)
IF (.NOT. found) CALL criticalError("temperature not found for wallTemperature boundary type", 'readBoundary') IF (.NOT. found) CALL criticalError("temperature not found for wallTemperature boundary type", 'readBoundary')
CALL config%get(object // '.specificHeat', cw, found) CALL config%get(object // '.specificHeat', cw, found)
IF (.NOT. found) CALL criticalError("specificHeat not found for wallTemperature boundary type", 'readBoundary') IF (.NOT. found) CALL criticalError("specificHeat not found for wallTemperature boundary type", 'readBoundary')
CALL initWallTemperature(bound, Tw, cw) CALL initWallTemperature(self, Tw, cw)
CASE('ionization') CASE('ionization')
!Neutral parameters !Neutral parameters
CALL config%get(object // '.neutral.ion', speciesName, found) CALL config%get(object // '.neutral.ion', speciesName, found)
IF (.NOT. found) CALL criticalError("missing parameter 'ion' for neutrals in ionization", 'readBoundary') IF (.NOT. found) CALL criticalError("missing parameter 'ion' for neutrals in ionization", 'readBoundary')
speciesID = speciesName2Index(speciesName) speciesID = speciesName2Index(speciesName)
CALL config%get(object // '.neutral.mass', m0, found) CALL config%get(object // '.neutral.mass', m0, found)
IF (.NOT. found) THEN IF (.NOT. found) CALL criticalError("missing parameter 'mass' for neutrals in ionization", 'readBoundary')
m0 = species(s)%obj%m*m_ref CALL config%get(object // '.neutral.density', n0, found)
END IF IF (.NOT. found) CALL criticalError("missing parameter 'density' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.neutral.density', n0, found) CALL config%get(object // '.neutral.velocity', v0, found)
IF (.NOT. found) CALL criticalError("missing parameter 'density' for neutrals in ionization", 'readBoundary') IF (.NOT. found) CALL criticalError("missing parameter 'velocity' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.neutral.velocity', v0, found) CALL config%get(object // '.neutral.temperature', T0, found)
IF (.NOT. found) CALL criticalError("missing parameter 'velocity' for neutrals in ionization", 'readBoundary') IF (.NOT. found) CALL criticalError("missing parameter 'temperature' 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) CALL config%get(object // '.effectiveTime', effTime, found)
IF (.NOT. found) CALL criticalError("missing parameter 'effectiveTime' for ionization", 'readBoundary') IF (.NOT. found) CALL criticalError("missing parameter 'effectiveTime' for ionization", 'readBoundary')
CALL config%get(object // '.energyThreshold', eThreshold, found) CALL config%get(object // '.energyThreshold', eThreshold, found)
IF (.NOT. found) CALL criticalError("missing parameter 'eThreshold' in ionization", 'readBoundary') IF (.NOT. found) CALL criticalError("missing parameter 'eThreshold' in ionization", 'readBoundary')
CALL config%get(object // '.crossSection', crossSection, found) CALL config%get(object // '.crossSection', crossSection, found)
IF (.NOT. found) CALL criticalError("missing parameter 'crossSection' for neutrals in ionization", 'readBoundary') IF (.NOT. found) CALL criticalError("missing parameter 'crossSection' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.electronSecondary', electronSecondary, found) CALL config%get(object // '.electronSecondary', electronSecondary, found)
electronSecondaryID = speciesName2Index(electronSecondary) electronSecondaryID = speciesName2Index(electronSecondary)
IF (found) THEN IF (found) THEN
CALL initIonization(bound, species(s)%obj%m, m0, n0, v0, T0, & CALL initIonization(self, me/m_ref, m0, n0, v0, T0, &
speciesID, effTime, crossSection, eThreshold,electronSecondaryID) speciesID, effTime, crossSection, eThreshold,electronSecondaryID)
ELSE ELSE
CALL initIonization(bound, species(s)%obj%m, m0, n0, v0, T0, & CALL initIonization(self, me/m_ref, m0, n0, v0, T0, &
speciesID, effTime, crossSection, eThreshold) speciesID, effTime, crossSection, eThreshold)
END IF END IF
case('quasiNeutrality') case('quasiNeutrality')
call initQuasiNeutrality(bound) call initQuasiNeutrality(self)
CASE DEFAULT CASE DEFAULT
CALL criticalError('Boundary type ' // bType // ' undefined', 'readBoundary') CALL criticalError('Boundary type ' // bType // ' undefined', 'readBoundary')
END SELECT END SELECT
end associate
END DO
end subroutine initBoundary end subroutine initBoundary
SUBROUTINE initWallTemperature(boundary, T, c) SUBROUTINE initWallTemperature(boundary, T, c)
@ -130,7 +118,7 @@ submodule(moduleMesh) boundary
END SUBROUTINE initWallTemperature END SUBROUTINE initWallTemperature
SUBROUTINE initIonization(boundary, me, m0, n0, v0, T0, ion, effTime, crossSection, eThreshold, electronSecondary) SUBROUTINE initIonization(boundary, mImpact, m0, n0, v0, T0, ion, effTime, crossSection, eThreshold, electronSecondary)
USE moduleRefParam USE moduleRefParam
USE moduleSpecies USE moduleSpecies
USE moduleCaseParam USE moduleCaseParam
@ -139,7 +127,7 @@ submodule(moduleMesh) boundary
IMPLICIT NONE IMPLICIT NONE
CLASS(boundaryGeneric), ALLOCATABLE, INTENT(out):: boundary CLASS(boundaryGeneric), ALLOCATABLE, INTENT(out):: boundary
REAL(8), INTENT(in):: me !Electron mass real(8), intent(in):: mImpact
REAL(8), INTENT(in):: m0, n0, v0(1:3), T0 !Neutral properties REAL(8), INTENT(in):: m0, n0, v0(1:3), T0 !Neutral properties
INTEGER, INTENT(in):: ion INTEGER, INTENT(in):: ion
INTEGER, OPTIONAL, INTENT(in):: electronSecondary INTEGER, OPTIONAL, INTENT(in):: electronSecondary
@ -175,7 +163,7 @@ submodule(moduleMesh) boundary
CALL boundary%crossSection%init(crossSection) CALL boundary%crossSection%init(crossSection)
CALL boundary%crossSection%convert(eV2J/(m_ref*v_ref**2), 1.D0/L_ref**2) 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%eThreshold = eThreshold*eV2J/(m_ref*v_ref**2)
boundary%deltaV = DSQRT(boundary%eThreshold/me) boundary%deltaV = DSQRT(boundary%eThreshold/mImpact)
END SELECT END SELECT
@ -197,13 +185,14 @@ submodule(moduleMesh) boundary
end subroutine initQuasiNeutrality end subroutine initQuasiNeutrality
module SUBROUTINE reflection(edge, part) module SUBROUTINE reflection(edge, part, self)
USE moduleCaseParam USE moduleCaseParam
USE moduleSpecies USE moduleSpecies
IMPLICIT NONE IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part CLASS(particle), INTENT(inout):: part
class(boundaryGeneric), optional, intent(in):: self
!rp = intersection between particle and edge !rp = intersection between particle and edge
!rpp = final position of particle !rpp = final position of particle
!vpp = final velocity of particle !vpp = final velocity of particle
@ -223,13 +212,14 @@ submodule(moduleMesh) boundary
END SUBROUTINE reflection END SUBROUTINE reflection
!Absoption in a surface !Absoption in a surface
SUBROUTINE absorption(edge, part) SUBROUTINE absorption(edge, part, self)
USE moduleCaseParam USE moduleCaseParam
USE moduleSpecies USE moduleSpecies
IMPLICIT NONE IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part CLASS(particle), INTENT(inout):: part
class(boundaryGeneric), optional, intent(in):: self
REAL(8):: rpp(1:3) !Position of particle projected to the edge REAL(8):: rpp(1:3) !Position of particle projected to the edge
REAL(8):: d !Distance from particle to edge REAL(8):: d !Distance from particle to edge
@ -259,12 +249,13 @@ submodule(moduleMesh) boundary
END SUBROUTINE absorption END SUBROUTINE absorption
!Transparent boundary condition !Transparent boundary condition
SUBROUTINE transparent(edge, part) SUBROUTINE transparent(edge, part, self)
USE moduleSpecies USE moduleSpecies
IMPLICIT NONE IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part CLASS(particle), INTENT(inout):: part
class(boundaryGeneric), optional, intent(in):: self
!Removes particle from domain !Removes particle from domain
part%n_in = .FALSE. part%n_in = .FALSE.
@ -274,44 +265,46 @@ submodule(moduleMesh) boundary
!Symmetry axis. Reflects particles. !Symmetry axis. Reflects particles.
!Although this function should never be called, it is set as a reflective boundary !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. !to properly deal with possible particles reaching a corner and selecting this boundary.
SUBROUTINE symmetryAxis(edge, part) SUBROUTINE symmetryAxis(edge, part, self)
USE moduleSpecies USE moduleSpecies
IMPLICIT NONE IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part CLASS(particle), INTENT(inout):: part
class(boundaryGeneric), optional, intent(in):: self
CALL reflection(edge, part) CALL reflection(edge, part)
END SUBROUTINE symmetryAxis END SUBROUTINE symmetryAxis
!Wall with temperature !Wall with temperature
SUBROUTINE wallTemperature(edge, part) SUBROUTINE wallTemperature(edge, part, self)
USE moduleSpecies USE moduleSpecies
USE moduleRandom USE moduleRandom
IMPLICIT NONE IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part CLASS(particle), INTENT(inout):: part
class(boundaryGeneric), optional, intent(in):: self
INTEGER:: i INTEGER:: i
!Modifies particle velocity according to wall temperature select type(self)
SELECT TYPE(bound => edge%boundary%bTypes(part%species%n)%obj) type is(boundaryWallTemperature)
TYPE IS(boundaryWallTemperature) !Modifies particle velocity according to wall temperature
DO i = 1, 3 DO i = 1, 3
part%v(i) = part%v(i) + bound%vTh*randomMaxwellian() part%v(i) = part%v(i) + self%vTh*randomMaxwellian()
END DO END DO
END SELECT CALL reflection(edge, part)
CALL reflection(edge, part) end select
END SUBROUTINE wallTemperature END SUBROUTINE wallTemperature
!Ionization surface: an electron will pass through the surface !Ionization surface: an electron will pass through the surface
! and create an ion-electron pair based on a neutral background ! and create an ion-electron pair based on a neutral background
SUBROUTINE ionization(edge, part) SUBROUTINE ionization(edge, part, self)
USE moduleList USE moduleList
USE moduleSpecies USE moduleSpecies
USE moduleMesh USE moduleMesh
@ -320,8 +313,9 @@ submodule(moduleMesh) boundary
USE moduleMath USE moduleMath
IMPLICIT NONE IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part CLASS(particle), INTENT(inout):: part
class(boundaryGeneric), optional, intent(in):: self
REAL(8):: vRel, eRel, mRel !relative velocity, energy and mass REAL(8):: vRel, eRel, mRel !relative velocity, energy and mass
INTEGER:: nIonizations !Number of ionizations based on eRel INTEGER:: nIonizations !Number of ionizations based on eRel
REAL(8):: pIonization !Probability of ionization of each event REAL(8):: pIonization !Probability of ionization of each event
@ -330,40 +324,40 @@ submodule(moduleMesh) boundary
TYPE(particle), POINTER:: newElectron TYPE(particle), POINTER:: newElectron
TYPE(particle), POINTER:: newIon TYPE(particle), POINTER:: newIon
SELECT TYPE(bound => edge%boundary%bTypes(part%species%n)%obj) select type(self)
TYPE IS(boundaryIonization) type is(boundaryIonization)
mRel = reducedMass(bound%m0, part%species%m) mRel = reducedMass(self%m0, part%species%m)
vRel = SUM(DABS(part%v-bound%v0)) vRel = SUM(DABS(part%v-self%v0))
eRel = mRel*vRel**2*5.D-1 eRel = mRel*vRel**2*5.D-1
!Maximum number of possible ionizations based on relative energy !Maximum number of possible ionizations based on relative energy
nIonizations = FLOOR(eRel/bound%eThreshold) nIonizations = FLOOR(eRel/self%eThreshold)
DO p = 1, nIonizations DO p = 1, nIonizations
!Get probability of ionization !Get probability of ionization
pIonization = 1.D0 - DEXP(-bound%n0*bound%crossSection%get(eRel)*vRel*bound%effectiveTime/REAL(nIonizations)) 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 a random number is below the probability of ionization, create new pair of ion-electron
IF (random() < pIonization) THEN IF (random() < pIonization) THEN
!Assign random velocity to the neutral !Assign random velocity to the neutral
v0(1) = bound%v0(1) + bound%vTh*randomMaxwellian() v0(1) = self%v0(1) + self%vTh*randomMaxwellian()
v0(2) = bound%v0(2) + bound%vTh*randomMaxwellian() v0(2) = self%v0(2) + self%vTh*randomMaxwellian()
v0(3) = bound%v0(3) + bound%vTh*randomMaxwellian() v0(3) = self%v0(3) + self%vTh*randomMaxwellian()
!Allocates the new particles !Allocates the new particles
ALLOCATE(newElectron) ALLOCATE(newElectron)
ALLOCATE(newIon) ALLOCATE(newIon)
IF (ASSOCIATED(bound%electronSecondary)) THEN IF (ASSOCIATED(self%electronSecondary)) THEN
newElectron%species => bound%electronSecondary newElectron%species => self%electronSecondary
ELSE ELSE
newElectron%species => part%species newElectron%species => part%species
END IF END IF
newIon%species => bound%species newIon%species => self%species
newElectron%v = v0 + (1.D0 + bound%deltaV*v0/NORM2(v0)) newElectron%v = v0 + (1.D0 + self%deltaV*v0/NORM2(v0))
newIon%v = v0 newIon%v = v0
newElectron%r = edge%randPos() newElectron%r = edge%randPos()
@ -394,7 +388,7 @@ submodule(moduleMesh) boundary
CALL partSurfaces%unsetLock() CALL partSurfaces%unsetLock()
!Electron loses energy due to ionization !Electron loses energy due to ionization
eRel = eRel - bound%eThreshold eRel = eRel - self%eThreshold
vRel = 2.D0*DSQRT(eRel)/mRel vRel = 2.D0*DSQRT(eRel)/mRel
!Reduce number of possible ionizations !Reduce number of possible ionizations
@ -404,83 +398,79 @@ submodule(moduleMesh) boundary
END DO END DO
END SELECT !Removes ionizing electron regardless the number of pair created
part%n_in = .FALSE.
!Removes ionizing electron regardless the number of pair created end select
part%n_in = .FALSE.
END SUBROUTINE ionization END SUBROUTINE ionization
subroutine quasiNeutrality(edge, part) subroutine quasiNeutrality(edge, part, self)
use moduleRandom use moduleRandom
implicit none implicit none
class(meshEdge), intent(inout):: edge class(meshEdge), intent(inout):: edge
class(particle), intent(inout):: part class(particle), intent(inout):: part
class(boundaryGeneric), optional, intent(in):: self
real(8), allocatable:: density(:) real(8), allocatable:: density(:)
class(meshCell), pointer:: cell class(meshCell), pointer:: cell
real(8):: EF_dir real(8):: EF_dir
real(8):: alpha real(8):: alpha
select type(bound => edge%boundary%bTypes(part%species%n)%obj) if (associated(edge%e1)) then
type is(boundaryQuasiNeutrality) cell => edge%e1
if (associated(edge%e1)) then else
cell => edge%e1 cell => edge%e2
else end if
cell => edge%e2
end if if (random() <= alpha) then
call reflection(edge, part)
if (random() <= alpha) then else
call reflection(edge, part) call transparent(edge, part)
else end if
call transparent(edge, part)
end if
end select
end subroutine quasiNeutrality end subroutine quasiNeutrality
!Points the boundary function to specific type ! !Points the boundary function to specific type
module SUBROUTINE pointBoundaryFunction(edge, s) ! module SUBROUTINE pointBoundaryFunction(edge, s)
USE moduleErrors ! USE moduleErrors
IMPLICIT NONE ! IMPLICIT NONE
!
CLASS(meshEdge), INTENT(inout):: edge ! CLASS(meshEdge), INTENT(inout):: edge
INTEGER, INTENT(in):: s !Species index ! INTEGER, INTENT(in):: s !Species index
!
SELECT TYPE(obj => edge%boundary%bTypes(s)%obj) ! SELECT TYPE(obj => edge%boundary%bTypes(s)%obj)
TYPE IS(boundaryAbsorption) ! TYPE IS(boundaryAbsorption)
edge%fBoundary(s)%apply => absorption ! edge%fBoundary(s)%apply => absorption
!
TYPE IS(boundaryReflection) ! TYPE IS(boundaryReflection)
edge%fBoundary(s)%apply => reflection ! edge%fBoundary(s)%apply => reflection
!
TYPE IS(boundaryTransparent) ! TYPE IS(boundaryTransparent)
edge%fBoundary(s)%apply => transparent ! edge%fBoundary(s)%apply => transparent
!
TYPE IS(boundaryAxis) ! TYPE IS(boundaryAxis)
edge%fBoundary(s)%apply => symmetryAxis ! edge%fBoundary(s)%apply => symmetryAxis
!
TYPE IS(boundaryWallTemperature) ! TYPE IS(boundaryWallTemperature)
edge%fBoundary(s)%apply => wallTemperature ! edge%fBoundary(s)%apply => wallTemperature
!
TYPE IS(boundaryIonization) ! TYPE IS(boundaryIonization)
edge%fBoundary(s)%apply => ionization ! edge%fBoundary(s)%apply => ionization
!
type is(boundaryQuasiNeutrality) ! type is(boundaryQuasiNeutrality)
edge%fBoundary(s)%apply => quasiNeutrality ! edge%fBoundary(s)%apply => quasiNeutrality
!
CLASS DEFAULT ! CLASS DEFAULT
CALL criticalError("Boundary type not defined", 'pointBoundaryFunction') ! CALL criticalError("Boundary type not defined", 'pointBoundaryFunction')
!
END SELECT ! END SELECT
!
END SUBROUTINE pointBoundaryFunction ! END SUBROUTINE pointBoundaryFunction
end submodule boundary end submodule boundary

View file

@ -203,7 +203,7 @@ submodule(moduleMesh) elements
CLASS IS (meshEdge) CLASS IS (meshEdge)
!Particle encountered a surface, apply boundary !Particle encountered a surface, apply boundary
CALL neighbourElement%fBoundary(part%species%n)%apply(neighbourElement,part) CALL neighbourElement%boundariesParticle(part%species%n)%obj%apply(neighbourElement,part)
!If particle is still inside the domain, call findCell !If particle is still inside the domain, call findCell
IF (part%n_in) THEN IF (part%n_in) THEN