Merge branch 'feature/boundary' into 'development'
Testing of the ionization boundary and 3D geometry. See merge request JorgeGonz/fpakc!12
This commit is contained in:
commit
1f017bc5cc
8 changed files with 128 additions and 24 deletions
Binary file not shown.
|
|
@ -123,6 +123,10 @@
|
|||
Velocity and position are updated according to the old particle values and the external forces.
|
||||
All the push routines for the different geometries can be found in \lstinline|moduleSolver|.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{3D Cartesian pusher}
|
||||
Moving particles in a simple 3D Cartesian space.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{2D Cylindrical}
|
||||
When a 2D cylindrical geometry is used ($z$, $r$), a Boris solver\cite{boris1970relativistic} is used to move particles accounting for the effect of the symmetry axis.
|
||||
|
|
@ -151,7 +155,7 @@
|
|||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Variable Weighting Scheme\label{sec:weightingScheme}}
|
||||
One of the issues in particle simulations, specially for axisymmetrical cases, is that due to the disparate volume of cells, specially close to the axis, the statistics in some cells is usually poor.
|
||||
One of the issues in particle simulations, specially for axial-symmetrical cases, is that due to the disparate volume of cells, specially close to the axis, the statistics in some cells is usually poor.
|
||||
To try to fix that, the possibility to include a Variable Weighting Scheme in the simulations is available in \Gls{fpakc}.
|
||||
This schemes detect when a particle change cells and modify its weight accordingly.
|
||||
To avoid particles having a larger weight than the rest, particle can be split in multiple particles if weight become too large.
|
||||
|
|
@ -341,6 +345,8 @@ make
|
|||
Type of geometry.
|
||||
Current accepted vaules are
|
||||
\begin{itemize}
|
||||
\item \textbf{3DCart}: Three-dimensional grid ($x \hyphen y \hyphen z$) in Cartesian coordinates..
|
||||
For \Gls{gmsh} mesh format, the coordinates $x$, $y$ and $z$ correspond to $x$, $y$ and $z$ respectively.
|
||||
\item \textbf{2DCyl}: Two-dimensional grid ($z \hyphen r$) with symmetry axis at $r = 0$.
|
||||
For \Gls{gmsh} mesh format, the coordinates $x$ and $y$ correspond to $z$ and $r$ respectively.
|
||||
\item \textbf{2DCart}: Two-dimensional grid ($x \hyphen y$) in Cartesian coordinates..
|
||||
|
|
@ -401,8 +407,61 @@ make
|
|||
\item \textbf{absorption}: Particle is eliminated from the domain.
|
||||
The particle is first moved into the edge and its properties are scattered among the edge nodes.
|
||||
\item \textbf{transparent}: Particle abandon the numerical domain.
|
||||
\item \textbf{wallTemperature}: Reflective wall with cosntant temperature that exchange heat with particles.
|
||||
Required parameters are:
|
||||
\begin{itemize}
|
||||
\item \textbf{temperature}: Real.
|
||||
Units of $\unit{K}$.
|
||||
Temperature wall.
|
||||
\item \textbf{specificHeat}: Real.
|
||||
Units of $\unit{J kg^{-1} K^{-1}}$.
|
||||
Specific heat capacity of the material.
|
||||
\end{itemize}
|
||||
\item \textbf{ionization}: Per each particle crossing the surface with this type of boundary, a number of ionization events are calculated.
|
||||
A pair of ion-electron is generated for each ionization event taking as a reference a neutral background.
|
||||
Secondary electron is taken as same type as incident particle.
|
||||
The available input is:
|
||||
\begin{itemize}
|
||||
\item \textbf{neutral}: Object.
|
||||
Information about the neutral background.
|
||||
Required parameters are:
|
||||
\begin{itemize}
|
||||
\item \textbf{ion}: Character.
|
||||
Species name of the ion generated as defined in object \textbf{species}.
|
||||
Required parameter.
|
||||
\item \textbf{mass}: Real.
|
||||
Units in $\unit{kg}$.
|
||||
Mass of neutral species.
|
||||
If missing, the mass of the ion is ussed
|
||||
\item \textbf{density}: Real.
|
||||
Units in $\unit{m^{-3}}$.
|
||||
Density of neutral background.
|
||||
Required parameter.
|
||||
\item \textbf{velocity}: Real.
|
||||
Units in $\unit{m^{-3}}$.
|
||||
Array of dimension $3$.
|
||||
Mean velocity of neutral background.
|
||||
Required parameter.
|
||||
\item \textbf{temperature}: Real.
|
||||
Units in $\unit{K}$.
|
||||
Temperature of neutral background.
|
||||
Required parameter.
|
||||
|
||||
\end{itemize}
|
||||
\item \textbf{effectiveTime}: Real.
|
||||
Units in $\unit{s}$.
|
||||
As the particle is no longer simulated once it crossed the boundary, this time represent the effective time in which the particle produces ionization processes in the neutral background.
|
||||
Required parameter.
|
||||
\item \textbf{energyThreashold}: Real.
|
||||
Units in $\unit{eV}$.
|
||||
Ionization energy threshold for the simulated process.
|
||||
Required parameter.
|
||||
\item \textbf{crossSection}: Character.
|
||||
Complete path to the cross section data for the ionization process.
|
||||
|
||||
\end{itemize}
|
||||
\item \textbf{axis}: Identifies the symmetry axis for 2D cylindrical simulations.
|
||||
It has no actual function.
|
||||
If for some reason a particle interact with this axis, it is reflected.
|
||||
\end{itemize}
|
||||
\item \textbf{physicalSurface}: Integer.
|
||||
Identification of the edge in the mesh file.
|
||||
|
|
@ -499,6 +558,8 @@ make
|
|||
Array dimension 'number of species'.
|
||||
Indicates the type of pusher used for each species:
|
||||
\begin{itemize}
|
||||
\item \textbf{3DCartNeutral}: Pushes particles in a 3D Cartesian space ($x \hyphen y \hyphen z$) without any external force.
|
||||
\item \textbf{3DCartCharged}: Pushes particles in a 3D Cartesian space ($x \hyphen y \hyphen z$) including the effect of the electrostatic field.
|
||||
\item \textbf{2DCylNeutral}: Pushes particles in a 2D cylindrical space ($z \hyphen r$) without any external force.
|
||||
\item \textbf{2DCylCharged}: Pushes particles in a 2D cylindrical space ($z \hyphen r$) including the effect of the electrostatic field.
|
||||
\item \textbf{2DCartNeutral}: Pushes particles in a 2D Cartesian space ($x \hyphen y$) without any external force.
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ MODULE moduleMesh2DCyl
|
|||
r2 = self%n2%getCoordinates()
|
||||
self%z = (/r1(1), r2(1)/)
|
||||
self%r = (/r1(2), r2(2)/)
|
||||
self%weight = SUM(self%r)*5.D-1
|
||||
!Normal vector
|
||||
self%normal = (/ -(self%r(2)-self%r(1)), &
|
||||
self%z(2)-self%z(1) , &
|
||||
|
|
@ -247,14 +248,22 @@ MODULE moduleMesh2DCyl
|
|||
|
||||
CLASS(meshEdge2DCyl), INTENT(in):: self
|
||||
REAL(8):: rnd
|
||||
REAL(8):: dr, dz
|
||||
REAL(8):: r(1:3)
|
||||
REAL(8):: p1(1:2), p2(1:2)
|
||||
|
||||
rnd = random()
|
||||
dr = self%r(2) - self%r(1)
|
||||
dz = self%z(2) - self%z(1)
|
||||
IF (dr /= 0.D0) THEN
|
||||
r(2) = dr*DSQRT(rnd) + self%r(1)
|
||||
r(1) = dz * (r(2) - self%r(1))/dr + self%z(1)
|
||||
|
||||
ELSE
|
||||
r(2) = self%r(1)
|
||||
r(1) = dz * rnd + self%z(1)
|
||||
|
||||
END IF
|
||||
|
||||
p1 = (/self%z(1), self%r(1) /)
|
||||
p2 = (/self%z(2), self%r(2) /)
|
||||
r(1:2) = (1.D0 - rnd)*p1 + rnd*p2
|
||||
r(3) = 0.D0
|
||||
|
||||
END FUNCTION randPosEdge
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ MODULE moduleMesh
|
|||
CLASS(meshVol), POINTER:: e1 => NULL(), e2 => NULL()
|
||||
!Normal vector
|
||||
REAL(8):: normal(1:3)
|
||||
!Weight for random injection of particles
|
||||
REAL(8):: weight = 1.D0
|
||||
!Pointer to boundary element
|
||||
TYPE(boundaryCont), POINTER:: boundary
|
||||
!Array of functions for boundary conditions
|
||||
|
|
|
|||
|
|
@ -137,14 +137,15 @@ MODULE moduleMeshBoundary
|
|||
|
||||
!Create the new pair of particles
|
||||
DO p = 1, ionizationPair
|
||||
ALLOCATE(newElectron)
|
||||
ALLOCATE(newIon)
|
||||
|
||||
!Assign random velocity to the neutral
|
||||
v0(1) = bound%v0(1) + bound%vTh*randomMaxwellian()
|
||||
v0(2) = bound%v0(2) + bound%vTh*randomMaxwellian()
|
||||
v0(3) = bound%v0(3) + bound%vTh*randomMaxwellian()
|
||||
|
||||
!Allocates the new particles
|
||||
ALLOCATE(newElectron)
|
||||
ALLOCATE(newIon)
|
||||
|
||||
newElectron%sp = part%sp
|
||||
newIon%sp = bound%sp
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ MODULE moduleInject
|
|||
INTEGER:: sp !Species of injection
|
||||
INTEGER:: nEdges
|
||||
INTEGER, ALLOCATABLE:: edges(:) !Array with edges
|
||||
REAL(8), ALLOCATABLE:: cumWeight(:) !Array of cummulative probability
|
||||
REAL(8):: sumWeight
|
||||
TYPE(velDistCont):: v(1:3) !Velocity distribution function in each direction
|
||||
CONTAINS
|
||||
PROCEDURE, PASS:: init => initInject
|
||||
|
|
@ -127,6 +129,15 @@ MODULE moduleInject
|
|||
|
||||
END DO
|
||||
|
||||
!Calculates cumulative probability
|
||||
ALLOCATE(self%cumWeight(1:self%nEdges))
|
||||
self%cumWeight(1) = mesh%edges(self%edges(et))%obj%weight
|
||||
DO et = 2, self%nEdges
|
||||
self%cumWeight(et) = mesh%edges(self%edges(et))%obj%weight + self%cumWeight(et-1)
|
||||
|
||||
END DO
|
||||
self%sumWeight = self%cumWeight(self%nEdges)
|
||||
|
||||
nPartInj = nPartInj + self%nParticles
|
||||
|
||||
END SUBROUTINE initInject
|
||||
|
|
@ -229,7 +240,7 @@ MODULE moduleInject
|
|||
|
||||
!$OMP DO
|
||||
DO n = nMin, nMax
|
||||
randomX = random(1, self%nEdges)
|
||||
randomX = randomWeighted(self%cumWeight, self%sumWeight)
|
||||
|
||||
randomEdge => mesh%edges(self%edges(randomX))%obj
|
||||
!Random position in edge
|
||||
|
|
|
|||
|
|
@ -636,21 +636,27 @@ MODULE moduleInput
|
|||
ALLOCATE(boundaryTransparent:: boundary(i)%bTypes(s)%obj)
|
||||
|
||||
CASE('ionization')
|
||||
CALL config%get(object // '.neutral.name', speciesName, found)
|
||||
IF (.NOT. found) CALL criticalError("missing parameter 'name' for neutrals in ionization", 'readBoundary')
|
||||
!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')
|
||||
IF (.NOT. found) THEN
|
||||
m0 = species(s)%obj%m*m_ref
|
||||
END IF
|
||||
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 neutrals in ionization", 'readBoundary')
|
||||
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')
|
||||
|
||||
|
|
|
|||
|
|
@ -66,4 +66,18 @@ MODULE moduleRandom
|
|||
|
||||
END FUNCTION randomMaxwellian
|
||||
|
||||
!Returns a random number weighted with the cumWeight array
|
||||
FUNCTION randomWeighted(cumWeight, sumWeight) RESULT(rnd)
|
||||
IMPLICIT NONE
|
||||
|
||||
REAL(8), INTENT(in):: cumWeight(1:)
|
||||
REAL(8), INTENT(in):: sumWeight
|
||||
REAL(8):: rnd0b
|
||||
INTEGER:: rnd
|
||||
|
||||
rnd0b = random(0.D0, sumWeight)
|
||||
rnd = MINLOC(DABS(rnd0b - cumWeight), 1)
|
||||
|
||||
END FUNCTION randomWeighted
|
||||
|
||||
END MODULE moduleRandom
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue