issue/edgesVolume #59

Merged
JGonzalez merged 4 commits from issue/edgesVolume into development 2026-02-26 19:21:53 +01:00
5 changed files with 126 additions and 92 deletions
Showing only changes of commit 7208b2e0da - Show all commits

Merge remote-tracking branch 'origin/issue/Maxwellian' into issue/edgesVolume

Jorge Gonzalez 2026-02-04 19:59:59 +01:00

View file

@ -48,24 +48,23 @@ MODULE moduleRandom
END FUNCTION randomIntAB END FUNCTION randomIntAB
!Returns a random number in a Maxwellian distribution of mean 0 and width 1 with the Box-Muller Method !Returns a random number in a Maxwellian distribution of mean 0 and width 1 with the Box-Muller Method
FUNCTION randomMaxwellian() RESULT(rnd) function randomMaxwellian() result(rnd)
USE moduleConstParam, ONLY: PI USE moduleConstParam, only: pi
IMPLICIT NONE implicit none
REAL(8):: rnd real(8):: rnd
REAL(8):: v1, v2, Rsquare real(8):: v1, v2, Rsquare
Rsquare = 1.D0 v1 = 0.d0
do while (Rsquare >= 1.D0 .and. Rsquare > 0.D0) do while (v1 <= 0.d0)
v1 = 2.D0 * random() - 1.D0 v1 = random()
v2 = 2.D0 * random() - 1.D0
Rsquare = v1**2 + v2**2
end do end do
v2 = random()
rnd = v2 * sqrt(-2.D0 * log(Rsquare) / Rsquare) rnd = sqrt(-2.d0*log(v1))*cos(2*pi*v2)
END FUNCTION randomMaxwellian end function randomMaxwellian
!Returns a random number in a Maxwellian distribution of mean 0 and width 1 !Returns a random number in a Maxwellian distribution of mean 0 and width 1
FUNCTION randomHalfMaxwellian() RESULT(rnd) FUNCTION randomHalfMaxwellian() RESULT(rnd)

View file

@ -829,18 +829,30 @@ MODULE moduleInput
IF (nTypes /= nSpecies) CALL criticalError('Not enough boundary types defined in ' // object, 'readBoundary') IF (nTypes /= nSpecies) CALL criticalError('Not enough boundary types defined in ' // object, 'readBoundary')
ALLOCATE(boundary(i)%bTypes(1:nSpecies)) ALLOCATE(boundary(i)%bTypes(1:nSpecies))
DO s = 1, nSpecies DO s = 1, nSpecies
associate(bound => boundary(i)%bTypes(s)%obj)
WRITE(sString,'(i2)') s WRITE(sString,'(i2)') s
object = 'boundary(' // TRIM(iString) // ').bTypes(' // TRIM(sString) // ')' object = 'boundary(' // TRIM(iString) // ').bTypes(' // TRIM(sString) // ')'
CALL config%get(object // '.type', bType, found) CALL config%get(object // '.type', bType, found)
SELECT CASE(bType) SELECT CASE(bType)
CASE('reflection') CASE('reflection')
ALLOCATE(boundaryReflection:: boundary(i)%bTypes(s)%obj) ALLOCATE(boundaryReflection:: bound)
CASE('absorption') CASE('absorption')
ALLOCATE(boundaryAbsorption:: boundary(i)%bTypes(s)%obj) ALLOCATE(boundaryAbsorption:: bound)
CASE('transparent') CASE('transparent')
ALLOCATE(boundaryTransparent:: boundary(i)%bTypes(s)%obj) ALLOCATE(boundaryTransparent:: bound)
CASE('axis')
ALLOCATE(boundaryAxis:: bound)
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(bound, Tw, cw)
CASE('ionization') CASE('ionization')
!Neutral parameters !Neutral parameters
@ -870,31 +882,25 @@ MODULE moduleInput
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(boundary(i)%bTypes(s)%obj, species(s)%obj%m, m0, n0, v0, T0, & CALL initIonization(bound, species(s)%obj%m, m0, n0, v0, T0, &
speciesID, effTime, crossSection, eThreshold,electronSecondaryID) speciesID, effTime, crossSection, eThreshold,electronSecondaryID)
ELSE ELSE
CALL initIonization(boundary(i)%bTypes(s)%obj, species(s)%obj%m, m0, n0, v0, T0, & CALL initIonization(bound, species(s)%obj%m, m0, n0, v0, T0, &
speciesID, effTime, crossSection, eThreshold) speciesID, effTime, crossSection, eThreshold)
END IF END IF
CASE('wallTemperature') case('outflowAdaptive')
CALL config%get(object // '.temperature', Tw, found) allocate(boundaryOutflowAdaptive:: bound)
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(boundary(i)%bTypes(s)%obj, Tw, cw)
CASE('axis')
ALLOCATE(boundaryAxis:: boundary(i)%bTypes(s)%obj)
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 DO
END DO END DO

View file

@ -77,6 +77,20 @@ MODULE moduleMeshBoundary
END SUBROUTINE transparent 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(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
CALL reflection(edge, part)
END SUBROUTINE symmetryAxis
!Wall with temperature !Wall with temperature
SUBROUTINE wallTemperature(edge, part) SUBROUTINE wallTemperature(edge, part)
USE moduleSpecies USE moduleSpecies
@ -204,19 +218,27 @@ MODULE moduleMeshBoundary
END SUBROUTINE ionization END SUBROUTINE ionization
!Symmetry axis. Reflects particles. subroutine outflowAdaptive(edge, part)
!Although this function should never be called, it is set as a reflective boundary use moduleRandom
!to properly deal with possible particles reaching a corner and selecting this boundary. implicit none
SUBROUTINE symmetryAxis(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge class(meshEdge), intent(inout):: edge
CLASS(particle), INTENT(inout):: part class(particle), intent(inout):: part
CALL reflection(edge, part) select type(bound => edge%boundary%bTypes(part%species%n)%obj)
type is(boundaryOutflowAdaptive)
END SUBROUTINE symmetryAxis if (random() < 0.844d0) then
call reflection(edge, part)
else
call transparent(edge, part)
end if
end select
end subroutine outflowAdaptive
!Points the boundary function to specific type !Points the boundary function to specific type
SUBROUTINE pointBoundaryFunction(edge, s) SUBROUTINE pointBoundaryFunction(edge, s)
@ -236,14 +258,17 @@ MODULE moduleMeshBoundary
TYPE IS(boundaryTransparent) TYPE IS(boundaryTransparent)
edge%fBoundary(s)%apply => transparent edge%fBoundary(s)%apply => transparent
TYPE IS(boundaryAxis)
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(boundaryAxis) type is(boundaryOutflowAdaptive)
edge%fBoundary(s)%apply => symmetryAxis edge%fBoundary(s)%apply => outflowAdaptive
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

@ -26,6 +26,12 @@ MODULE moduleBoundary
END TYPE boundaryTransparent END TYPE boundaryTransparent
!Symmetry axis
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAxis
CONTAINS
END TYPE boundaryAxis
!Wall Temperature boundary !Wall Temperature boundary
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryWallTemperature TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryWallTemperature
!Thermal velocity of the wall: square root(Wall temperature X specific heat) !Thermal velocity of the wall: square root(Wall temperature X specific heat)
@ -47,11 +53,13 @@ MODULE moduleBoundary
END TYPE boundaryIonization END TYPE boundaryIonization
!Symmetry axis !Boundary for quasi-neutral outflow adjusting reflection coefficient
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAxis type, public, extends(boundaryGeneric):: boundaryOutflowAdaptive
CONTAINS real(8):: outflowCurrent
real(8):: reflectionFraction
contains
END TYPE boundaryAxis end type boundaryOutflowAdaptive
!Wrapper for boundary types (one per species) !Wrapper for boundary types (one per species)
TYPE:: bTypesCont TYPE:: bTypesCont

View file

@ -257,7 +257,7 @@ MODULE moduleInject
CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist
REAL(8), INTENT(in):: temperature, m REAL(8), INTENT(in):: temperature, m
velDist = velDistMaxwellian(vTh = DSQRT(temperature/m)) velDist = velDistMaxwellian(vTh = DSQRT(2.d0*temperature/m))
END SUBROUTINE initVelDistMaxwellian END SUBROUTINE initVelDistMaxwellian
@ -267,7 +267,7 @@ MODULE moduleInject
CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist
REAL(8), INTENT(in):: temperature, m REAL(8), INTENT(in):: temperature, m
velDist = velDistHalfMaxwellian(vTh = DSQRT(temperature/m)) velDist = velDistHalfMaxwellian(vTh = DSQRT(2.d0*temperature/m))
END SUBROUTINE initVelDistHalfMaxwellian END SUBROUTINE initVelDistHalfMaxwellian
@ -289,7 +289,7 @@ MODULE moduleInject
REAL(8):: v REAL(8):: v
v = 0.D0 v = 0.D0
v = sqrt(2.0)*self%vTh*randomMaxwellian() v = self%vTh*randomMaxwellian()/sqrt(2.d0)
END FUNCTION randomVelMaxwellian END FUNCTION randomVelMaxwellian
@ -302,7 +302,7 @@ MODULE moduleInject
REAL(8):: v REAL(8):: v
v = 0.D0 v = 0.D0
v = sqrt(2.0)*self%vTh*randomHalfMaxwellian() v = self%vTh*randomHalfMaxwellian()/sqrt(2.d0)
END FUNCTION randomVelHalfMaxwellian END FUNCTION randomVelHalfMaxwellian
@ -387,16 +387,12 @@ MODULE moduleInject
partInj(n)%v = 0.D0 partInj(n)%v = 0.D0
do while(dot_product(partInj(n)%v, direction) <= 0.d0)
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() /)
end do
!If injecting a no-drift distribution and velocity is negative, reflect
if ((self%vMod == 0.D0) .and. &
(dot_product(direction, partInj(n)%v) < 0.D0)) then
partInj(n)%v = - partInj(n)%v
end if
!Obtain natural coordinates of particle in cell !Obtain natural coordinates of particle in cell
partInj(n)%Xi = mesh%cells(partInj(n)%cell)%obj%phy2log(partInj(n)%r) partInj(n)%Xi = mesh%cells(partInj(n)%cell)%obj%phy2log(partInj(n)%r)