assigning the normal vector in 2D and 3D. 3D Cartesian geometry is working properly, although it needs testing. Still issue with ionization boundary.
230 lines
6.1 KiB
Fortran
230 lines
6.1 KiB
Fortran
!moduleMeshBoundary: Boundary functions
|
|
MODULE moduleMeshBoundary
|
|
USE moduleMesh
|
|
|
|
CONTAINS
|
|
SUBROUTINE reflection(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
|
|
REAL(8):: tI
|
|
REAL(8):: taup !time step for reflecting process
|
|
|
|
!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(edge, part)
|
|
USE moduleCaseParam
|
|
USE moduleSpecies
|
|
IMPLICIT NONE
|
|
|
|
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(part)
|
|
|
|
ELSE
|
|
CALL edge%e2%scatter(part)
|
|
|
|
END IF
|
|
|
|
END SUBROUTINE absorption
|
|
|
|
!Transparent boundary condition
|
|
SUBROUTINE transparent(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 transparent
|
|
|
|
!Wall with temperature
|
|
SUBROUTINE wallTemperature(edge, part)
|
|
USE moduleSpecies
|
|
USE moduleBoundary
|
|
USE moduleRandom
|
|
IMPLICIT NONE
|
|
|
|
CLASS(meshEdge), INTENT(inout):: edge
|
|
CLASS(particle), INTENT(inout):: part
|
|
INTEGER:: i
|
|
|
|
!Modifies particle velocity according to wall temperature
|
|
SELECT TYPE(bound => edge%boundary%bTypes(part%sp)%obj)
|
|
TYPE IS(boundaryWallTemperature)
|
|
DO i = 1, 3
|
|
part%v(i) = part%v(i) + bound%vTh*randomMaxwellian()
|
|
|
|
END DO
|
|
|
|
END SELECT
|
|
|
|
CALL reflection(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(edge, part)
|
|
USE moduleList
|
|
USE moduleSpecies
|
|
USE moduleMesh
|
|
USE moduleRefParam
|
|
IMPLICIT NONE
|
|
|
|
CLASS(meshEdge), INTENT(inout):: edge
|
|
CLASS(particle), INTENT(inout):: part
|
|
REAL(8):: vRel, eRel, mRel !relative velocity, energy and mass
|
|
REAL(8):: ionizationRate
|
|
INTEGER:: ionizationPair, p
|
|
TYPE(particle), POINTER:: newElectron
|
|
TYPE(particle), POINTER:: newIon
|
|
|
|
SELECT TYPE(bound => edge%boundary%bTypes(part%sp)%obj)
|
|
TYPE IS(boundaryIonization)
|
|
mRel = (bound%m0*species(part%sp)%obj%m)*(bound%m0+species(part%sp)%obj%m)
|
|
vRel = SUM(DABS(part%v-bound%v0))
|
|
eRel = mRel*vRel**2*5.D-1
|
|
|
|
IF (eRel > bound%eThreshold) THEN
|
|
!TODO: Check units
|
|
ionizationRate = bound%n0*bound%crossSection%get(eRel)
|
|
|
|
ionizationPair = INT(ionizationRate*tauMin*ti_ref/species(bound%sp)%obj%weight)
|
|
|
|
!Create the new pair of particles
|
|
DO p = 1, ionizationPair
|
|
ALLOCATE(newElectron)
|
|
ALLOCATE(newIon)
|
|
|
|
newElectron%sp = part%sp
|
|
newIon%sp = bound%sp
|
|
|
|
newElectron%v = 10.D0*bound%v0 + (1.D0 + bound%deltaV/NORM2(bound%v0))
|
|
newIon%v = bound%v0
|
|
|
|
newElectron%r = edge%randPos()
|
|
newIon%r = newElectron%r
|
|
|
|
newElectron%vol = part%vol
|
|
newIon%vol = part%vol
|
|
|
|
newElectron%xi = mesh%vols(part%vol)%obj%phy2log(newElectron%r)
|
|
newIon%xi = newElectron%xi
|
|
|
|
newElectron%qm = part%qm
|
|
SELECT TYPE(spe => species(bound%sp)%obj)
|
|
TYPE IS(speciesCharged)
|
|
newIon%qm = spe%qm
|
|
|
|
END SELECT
|
|
|
|
newElectron%weight = species(bound%sp)%obj%weight
|
|
newIon%weight = newElectron%weight
|
|
|
|
newElectron%n_in = .TRUE.
|
|
newIon%n_in = .TRUE.
|
|
|
|
!Add particles to list
|
|
CALL OMP_SET_LOCK(lockSurfaces)
|
|
CALL partSurfaces%add(newElectron)
|
|
CALL partSurfaces%add(newIon)
|
|
CALL OMP_UNSET_LOCK(lockSurfaces)
|
|
|
|
END DO
|
|
|
|
!Removes ionizing electron
|
|
part%n_in = .FALSE.
|
|
|
|
END IF
|
|
|
|
END SELECT
|
|
|
|
END SUBROUTINE ionization
|
|
|
|
!Symmetry axis. Dummy function
|
|
SUBROUTINE symmetryAxis(edge, part)
|
|
USE moduleSpecies
|
|
IMPLICIT NONE
|
|
|
|
CLASS(meshEdge), INTENT(inout):: edge
|
|
CLASS(particle), INTENT(inout):: part
|
|
|
|
END SUBROUTINE symmetryAxis
|
|
|
|
!Points the boundary function to specific type
|
|
SUBROUTINE pointBoundaryFunction(edge, s)
|
|
USE moduleErrors
|
|
IMPLICIT NONE
|
|
|
|
CLASS(meshEdge), INTENT(inout):: edge
|
|
INTEGER, INTENT(in):: s !Species index
|
|
|
|
SELECT TYPE(obj => edge%boundary%bTypes(s)%obj)
|
|
TYPE IS(boundaryAbsorption)
|
|
edge%fBoundary(s)%apply => absorption
|
|
|
|
TYPE IS(boundaryReflection)
|
|
edge%fBoundary(s)%apply => reflection
|
|
|
|
TYPE IS(boundaryTransparent)
|
|
edge%fBoundary(s)%apply => transparent
|
|
|
|
TYPE IS(boundaryWallTemperature)
|
|
edge%fBoundary(s)%apply => wallTemperature
|
|
|
|
TYPE IS(boundaryIonization)
|
|
edge%fBoundary(s)%apply => ionization
|
|
|
|
TYPE IS(boundaryAxis)
|
|
edge%fBoundary(s)%apply => symmetryAxis
|
|
|
|
CLASS DEFAULT
|
|
CALL criticalError("Boundary type not defined in this geometry", 'pointBoundaryFunction')
|
|
|
|
END SELECT
|
|
|
|
END SUBROUTINE pointBoundaryFunction
|
|
|
|
END MODULE moduleMeshBoundary
|