I need to ensure quasi-neutrality at the inlet with a new kind of BC

This commit is contained in:
Jorge Gonzalez 2026-02-04 22:43:59 +01:00
commit 13dde3b1f9
3 changed files with 66 additions and 31 deletions

View file

@ -77,10 +77,23 @@ MODULE moduleMeshBoundary
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
SUBROUTINE wallTemperature(edge, part)
USE moduleSpecies
USE moduleBoundary
USE moduleRandom
IMPLICIT NONE
@ -204,19 +217,28 @@ MODULE moduleMeshBoundary
END SUBROUTINE ionization
!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
subroutine quasiNeutrality(edge, part)
use moduleRandom
implicit none
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
class(meshEdge), intent(inout):: edge
class(particle), intent(inout):: part
CALL reflection(edge, part)
select type(bound => edge%boundary%bTypes(part%species%n)%obj)
type is(boundaryQuasiNeutrality)
bound%alpha = 1.0d-1
END SUBROUTINE symmetryAxis
if (random() < bound%alpha) then
call reflection(edge, part)
else
call transparent(edge, part)
end if
end select
end subroutine quasiNeutrality
!Points the boundary function to specific type
SUBROUTINE pointBoundaryFunction(edge, s)
@ -236,17 +258,20 @@ MODULE moduleMeshBoundary
TYPE IS(boundaryTransparent)
edge%fBoundary(s)%apply => transparent
TYPE IS(boundaryAxis)
edge%fBoundary(s)%apply => symmetryAxis
TYPE IS(boundaryWallTemperature)
edge%fBoundary(s)%apply => wallTemperature
TYPE IS(boundaryIonization)
edge%fBoundary(s)%apply => ionization
TYPE IS(boundaryAxis)
edge%fBoundary(s)%apply => symmetryAxis
type is(boundaryQuasiNeutrality)
edge%fBoundary(s)%apply => quasiNeutrality
CLASS DEFAULT
CALL criticalError("Boundary type not defined in this geometry", 'pointBoundaryFunction')
CALL criticalError("Boundary type not defined", 'pointBoundaryFunction')
END SELECT

View file

@ -26,6 +26,12 @@ MODULE moduleBoundary
END TYPE boundaryTransparent
!Symmetry axis
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAxis
CONTAINS
END TYPE boundaryAxis
!Wall Temperature boundary
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryWallTemperature
!Thermal velocity of the wall: square root(Wall temperature X specific heat)
@ -47,12 +53,11 @@ MODULE moduleBoundary
END TYPE boundaryIonization
!Symmetry axis
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAxis
CONTAINS
END TYPE boundaryAxis
! Ensures quasi-neutrality by changing the reflection coefficient
type, public, extends(boundaryGeneric):: boundaryQuasiNeutrality
real(8):: alpha ! Reflection parameter
end type boundaryQuasiNeutrality
!Wrapper for boundary types (one per species)
TYPE:: bTypesCont
CLASS(boundaryGeneric), ALLOCATABLE:: obj

View file

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