First implementation of 2D Cartesian space.

Files and types with 'Cyl' have been changed to '2DCyl' to better
differentiate between the two types of 2D geometry.

Solvers for charged and neutral particles in 2D Cartesian space.

Added solveds for 1D neutral particles (this branch is not the place to
    do it, but it was a minor change).

User Manual updated with the new accepted options.
This commit is contained in:
Jorge Gonzalez 2021-01-21 12:03:10 +01:00
commit 2ae4a6c785
14 changed files with 2110 additions and 162 deletions

Binary file not shown.

View file

@ -128,15 +128,18 @@
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. 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.
This pusher removes the issue with particles going to infinite velocity when $r \rightarrow 0$ by pushing the particles in Cartesian space and then converting it to $r-z$ geometry. This pusher removes the issue with particles going to infinite velocity when $r \rightarrow 0$ by pushing the particles in Cartesian space and then converting it to $r-z$ geometry.
Velocity in the $\theta$ direction is updated for collision processes, although the dynamic in the angular direction is assumed as symmetric. Velocity in the $\theta$ direction is updated for collision processes, although the dynamic in the angular direction is assumed as symmetric.
Cross-sections are read from files.
These files contains two columns: one for the relative energy (in $\unit{eV}$) and another one for the cross-section (in $\unit{m^{-2}}$).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{1D Cartesian pusher} \subsection{2D Cartesian pusher}
Moving particles in a simple 2D Cartesian space.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{1D Radial pusher} \subsection{1D Radial pusher}
Same implementation as 2D cylindrical pusher but direction $z$ is ignored.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{1D Cartesian pusher}
Moving particles in a simple 1D Cartesian space. Same implementation as in 2D Cartesian but $y$ direction is ignored.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Find new cell} \section{Find new cell}
@ -338,12 +341,14 @@ make
Type of geometry. Type of geometry.
Current accepted vaules are Current accepted vaules are
\begin{itemize} \begin{itemize}
\item \textbf{2DCyl}: Two-dimensional grid (z-r) with symmetry axis at $r = 0$. \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. For \Gls{gmsh} mesh format, the coordinates $x$ and $y$ correspond to $z$ and $r$ respectively.
\item \textbf{1DCart}: One-dimensional grid (x) in Cartesian coordinates \item \textbf{2DCart}: Two-dimensional grid ($x \hyphen y$) in Cartesian coordinates..
For \Gls{gmsh} mesh format, the coordinates $x$ corresponds to $x$. For \Gls{gmsh} mesh format, the coordinates $x$ and $y$ correspond to $x$ and $y$ respectively.
\item \textbf{1DRad}: One-dimensional grid (r) in radial coordinates \item \textbf{1DRad}: One-dimensional grid ($r$) in radial coordinates
For \Gls{gmsh} mesh format, the coordinates $x$ corresponds to $r$. For \Gls{gmsh} mesh format, the coordinates $x$ corresponds to $r$.
\item \textbf{1DCart}: One-dimensional grid ($x$) in Cartesian coordinates
For \Gls{gmsh} mesh format, the coordinates $x$ corresponds to $x$.
\end{itemize} \end{itemize}
\item \textbf{meshType}: Character. \item \textbf{meshType}: Character.
Format of mesh file. Format of mesh file.
@ -494,10 +499,14 @@ make
Array dimension 'number of species'. Array dimension 'number of species'.
Indicates the type of pusher used for each species: Indicates the type of pusher used for each species:
\begin{itemize} \begin{itemize}
\item \textbf{2DCylNeutral}: Pushes particles in a 2D z-r space without any external force. \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 z-r space including the effect of the electrostatic field. \item \textbf{2DCylCharged}: Pushes particles in a 2D cylindrical space ($z \hyphen r$) including the effect of the electrostatic field.
\item \textbf{1DCartCharged}: Pushes particles in a 1D Cartesian space accounting the the electrostatic field. \item \textbf{2DCartNeutral}: Pushes particles in a 2D Cartesian space ($x \hyphen y$) without any external force.
\item \textbf{1DRadCharged}: Pushes particles in a 1D cylindrical space (r) accounting the the electrostatic field. \item \textbf{2DCartCharged}: Pushes particles in a 2D Cartesian space ($x \hyphen y$) including the effect of the electrostatic field.
\item \textbf{1DRadNeutral}: Pushes particles in a 1D cylindrical space ($r$) without any external force.
\item \textbf{1DRadCharged}: Pushes particles in a 1D cylindrical space ($r$) accounting the the electrostatic field.
\item \textbf{1DCartNeutral}: Pushes particles in a 1D Cartesian space ($x$) without any external force.
\item \textbf{1DCartCharged}: Pushes particles in a 1D Cartesian space ($x$) accounting the the electrostatic field.
\end{itemize} \end{itemize}
\item \textbf{WeightingScheme}: Character. \item \textbf{WeightingScheme}: Character.
Indicates the variable weighting scheme to be used in the simulation. Indicates the variable weighting scheme to be used in the simulation.

View file

@ -4,7 +4,8 @@ OBJECTS = $(OBJDIR)/moduleMesh.o $(OBJDIR)/moduleCompTime.o $(OBJDIR)/moduleSolv
$(OBJDIR)/moduleBoundary.o $(OBJDIR)/moduleCaseParam.o $(OBJDIR)/moduleRefParam.o \ $(OBJDIR)/moduleBoundary.o $(OBJDIR)/moduleCaseParam.o $(OBJDIR)/moduleRefParam.o \
$(OBJDIR)/moduleCollisions.o $(OBJDIR)/moduleTable.o $(OBJDIR)/moduleParallel.o \ $(OBJDIR)/moduleCollisions.o $(OBJDIR)/moduleTable.o $(OBJDIR)/moduleParallel.o \
$(OBJDIR)/moduleEM.o $(OBJDIR)/moduleRandom.o \ $(OBJDIR)/moduleEM.o $(OBJDIR)/moduleRandom.o \
$(OBJDIR)/moduleMeshCyl.o $(OBJDIR)/moduleMeshCylRead.o $(OBJDIR)/moduleMeshCylBoundary.o \ $(OBJDIR)/moduleMesh2DCyl.o $(OBJDIR)/moduleMesh2DCylRead.o $(OBJDIR)/moduleMesh2DCylBoundary.o \
$(OBJDIR)/moduleMesh2DCart.o $(OBJDIR)/moduleMesh2DCartRead.o $(OBJDIR)/moduleMesh2DCartBoundary.o \
$(OBJDIR)/moduleMesh1DCart.o $(OBJDIR)/moduleMesh1DCartRead.o $(OBJDIR)/moduleMesh1DCartBoundary.o \ $(OBJDIR)/moduleMesh1DCart.o $(OBJDIR)/moduleMesh1DCartRead.o $(OBJDIR)/moduleMesh1DCartBoundary.o \
$(OBJDIR)/moduleMesh1DRad.o $(OBJDIR)/moduleMesh1DRadRead.o $(OBJDIR)/moduleMesh1DRadBoundary.o $(OBJDIR)/moduleMesh1DRad.o $(OBJDIR)/moduleMesh1DRadRead.o $(OBJDIR)/moduleMesh1DRadBoundary.o

View file

@ -0,0 +1,11 @@
all : moduleMesh2DCart.o moduleMesh2DCartBoundary.o moduleMesh2DCartRead.o
moduleMesh2DCart.o: moduleMesh2DCart.f90
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
moduleMesh2DCartBoundary.o: moduleMesh2DCart.o moduleMesh2DCartBoundary.f90
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
moduleMesh2DCartRead.o: moduleMesh2DCart.o moduleMesh2DCartBoundary.o moduleMesh2DCartRead.f90
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,154 @@
!moduleMesh2DCartBoundary: Boundary functions for cylindrical coordinates
SUBMODULE (moduleMesh2DCart) moduleMesh2DCartBoundary
USE moduleMesh2DCart
CONTAINS
SUBROUTINE reflection(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
REAL(8):: edgeNorm, cosT, sinT, rp(1:2), rpp(1:2), vpp(1:2)
!TODO: Try to do this without select
SELECT TYPE(edge)
TYPE IS(meshEdge2DCart)
edgeNorm = DSQRT((edge%y(2)-edge%y(1))**2 + (edge%x(2)-edge%x(1))**2)
cosT = (edge%x(2)-edge%x(1))/edgeNorm
sinT = DSQRT(1-cosT**2)
rp(1) = part%r(1) - edge%x(1);
rp(2) = part%r(2) - edge%y(1);
rpp(1) = cosT*rp(1) - sinT*rp(2)
rpp(2) = sinT*rp(1) + cosT*rp(2)
rpp(2) = -rpp(2)
vpp(1) = cosT*part%v(1) - sinT*part%v(2)
vpp(2) = sinT*part%v(1) + cosT*part%v(2)
vpp(2) = -vpp(2)
part%r(1) = cosT*rpp(1) + sinT*rpp(2) + edge%x(1);
part%r(2) = -sinT*rpp(1) + cosT*rpp(2) + edge%y(1);
part%v(1) = cosT*vpp(1) + sinT*vpp(2)
part%v(2) = -sinT*vpp(1) + cosT*vpp(2)
END SELECT
part%n_in = .TRUE.
END SUBROUTINE reflection
!Absoption in a surface
SUBROUTINE absorption(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
REAL(8):: rEdge(1:2) !Position of particle projected to the edge
REAL(8):: a, b, c
REAL(8):: a2b2
REAL(8):: d !Distance from particle to edge
SELECT TYPE(edge)
TYPE IS(meshEdge2DCart)
a = (edge%x(1) - edge%x(2))
b = (edge%y(1) - edge%y(2))
c = edge%x(1)*edge%y(2) - edge%x(2)*edge%y(1)
a2b2 = a**2 + b**2
rEdge(1) = (b*( b*part%r(1) - a*part%r(2)) - a*c)/a2b2
rEdge(2) = (a*(-b*part%r(1) + a*part%r(2)) - b*c)/a2b2
d = NORM2(rEdge - part%r(1:2))
!Reduce weight of particle by the distance to the edge and move it to the edge
IF (d > 0.D0) THEN
part%weight = part%weight / d
part%r(1:2) = rEdge
END IF
!Scatter particle in associated volume
IF (ASSOCIATED(edge%e1)) THEN
CALL edge%e1%scatter(part)
ELSE
CALL edge%e2%scatter(part)
END IF
END SELECT
!Remove particle from the domain
part%n_in = .FALSE.
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
REAL(8):: edgeNorm, cosT, sinT, rp(1:2), rpp(1:2), vpp(1:2)
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
!Reflects particle in the edge
SELECT TYPE(edge)
TYPE IS(meshEdge2DCart)
edgeNorm = DSQRT((edge%y(2)-edge%y(1))**2 + (edge%x(2)-edge%x(1))**2)
cosT = (edge%x(2)-edge%x(1))/edgeNorm
sinT = DSQRT(1-cosT**2)
rp(1) = part%r(1) - edge%x(1);
rp(2) = part%r(2) - edge%y(1);
rpp(1) = cosT*rp(1) - sinT*rp(2)
rpp(2) = sinT*rp(1) + cosT*rp(2)
rpp(2) = -rpp(2)
vpp(1) = cosT*part%v(1) - sinT*part%v(2)
vpp(2) = sinT*part%v(1) + cosT*part%v(2)
vpp(2) = -vpp(2)
part%r(1) = cosT*rpp(1) + sinT*rpp(2) + edge%x(1);
part%r(2) = -sinT*rpp(1) + cosT*rpp(2) + edge%y(1);
part%v(1) = cosT*vpp(1) + sinT*vpp(2)
part%v(2) = -sinT*vpp(1) + cosT*vpp(2)
END SELECT
part%n_in = .TRUE.
END SUBROUTINE wallTemperature
END SUBMODULE moduleMesh2DCartBoundary

View file

@ -0,0 +1,599 @@
MODULE moduleMesh2DCartRead
USE moduleMesh
USE moduleMesh2DCart
TYPE, EXTENDS(meshGeneric):: mesh2DCartGeneric
CONTAINS
PROCEDURE, PASS:: init => init2DCartMesh
PROCEDURE, PASS:: readMesh => readMesh2DCartGmsh
END TYPE
INTERFACE connected
MODULE PROCEDURE connectedVolVol, connectedVolEdge
END INTERFACE connected
CONTAINS
!Init mesh
SUBROUTINE init2DCartMesh(self, meshFormat)
USE moduleMesh
USE moduleErrors
IMPLICIT NONE
CLASS(mesh2DCartGeneric), INTENT(out):: self
CHARACTER(:), ALLOCATABLE, INTENT(in):: meshFormat
SELECT CASE(meshFormat)
CASE ("gmsh")
self%printOutput => printOutputGmsh
self%printColl => printCollGmsh
self%printEM => printEMGmsh
CASE DEFAULT
CALL criticalError("Mesh type " // meshFormat // " not supported.", "init2DCartMesh")
END SELECT
END SUBROUTINE init2DCartMesh
!Read mesh from gmsh file
SUBROUTINE readMesh2DCartGmsh(self, filename)
USE moduleBoundary
IMPLICIT NONE
CLASS(mesh2DCartGeneric), INTENT(inout):: self
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
REAL(8):: x, y
INTEGER:: p(1:4)
INTEGER:: e=0, et=0, n=0, eTemp=0, elemType=0, bt = 0
INTEGER:: totalNumElem
INTEGER:: boundaryType
!Read msh
OPEN(10, FILE=TRIM(filename))
!Skip header
READ(10, *)
READ(10, *)
READ(10, *)
READ(10, *)
!Read number of nodes
READ(10, *) self%numNodes
!Allocate required matrices and vectors
ALLOCATE(self%nodes(1:self%numNodes))
ALLOCATE(self%K(1:self%numNodes,1:self%numNodes))
ALLOCATE(self%IPIV(1:self%numNodes,1:self%numNodes))
self%K = 0.D0
self%IPIV = 0
!Read nodes cartesian coordinates (x=x, y=y, z=null)
DO e=1, self%numNodes
READ(10, *) n, x, y
ALLOCATE(meshNode2DCart:: self%nodes(n)%obj)
CALL self%nodes(n)%obj%init(n, (/x, y, 0.D0 /))
END DO
!Skips comments
READ(10, *)
READ(10, *)
!Reads Totalnumber of elements
READ(10, *) TotalnumElem
!counts edges and volume elements
self%numEdges = 0
DO e=1, TotalnumElem
READ(10,*) eTemp, elemType
IF (elemType==1) THEN
self%numEdges=e
END IF
END DO
!Substract the number of edges to the total number of elements
!to obtain the number of volume elements
self%numVols = TotalnumElem - self%numEdges
!Allocates arrays
ALLOCATE(self%edges(1:self%numEdges))
ALLOCATE(self%vols(1:self%numVols))
!Go back to the beggining to read elements
DO e=1, totalNumElem
BACKSPACE(10)
END DO
!Reads edges
DO e=1, self%numEdges
READ(10,*) n, elemType, eTemp, boundaryType, eTemp, p(1:2)
!Associate boundary condition procedure.
bt = getBoundaryId(boundaryType)
ALLOCATE(meshEdge2DCart:: self%edges(e)%obj)
CALL self%edges(e)%obj%init(n, p(1:2), bt, boundaryType)
END DO
!Read and initialize volumes
DO e=1, self%numVols
READ(10,*) n, elemType
BACKSPACE(10)
SELECT CASE(elemType)
CASE (2)
!Triangular element
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:3)
ALLOCATE(meshVol2DCartTria:: self%vols(e)%obj)
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:3))
CASE (3)
!Quadrilateral element
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:4)
ALLOCATE(meshVol2DCartQuad:: self%vols(e)%obj)
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:4))
END SELECT
END DO
CLOSE(10)
!Build connectivity between elements
DO e = 1, self%numVols
!Connectivity between volumes
DO et = 1, self%numVols
IF (e /= et) THEN
CALL connected(self%vols(e)%obj, self%vols(et)%obj)
END IF
END DO
!Connectivity between vols and edges
DO et = 1, self%numEdges
CALL connected(self%vols(e)%obj, self%edges(et)%obj)
END DO
!Constructs the global K matrix
CALL constructGlobalK(self%K, self%vols(e)%obj)
END DO
END SUBROUTINE readMesh2DCartGmsh
!Selects type of elements to build connection
SUBROUTINE connectedVolVol(elemA, elemB)
IMPLICIT NONE
CLASS(meshVol), INTENT(inout):: elemA
CLASS(meshVol), INTENT(inout):: elemB
SELECT TYPE(elemA)
TYPE IS(meshVol2DCartQuad)
!Element A is a quadrilateral
SELECT TYPE(elemB)
TYPE IS(meshVol2DCartQuad)
!Element B is a quadrilateral
CALL connectedQuadQuad(elemA, elemB)
TYPE IS(meshVol2DCartTria)
!Element B is a triangle
CALL connectedQuadTria(elemA, elemB)
END SELECT
TYPE IS(meshVol2DCartTria)
!Element A is a Triangle
SELECT TYPE(elemB)
TYPE IS(meshVol2DCartQuad)
!Element B is a quadrilateral
CALL connectedQuadTria(elemB, elemA)
TYPE IS(meshVol2DCartTria)
!Element B is a triangle
CALL connectedTriaTria(elemA, elemB)
END SELECT
END SELECT
END SUBROUTINE connectedVolVol
SUBROUTINE connectedVolEdge(elemA, elemB)
IMPLICIT NONE
CLASS(meshVol), INTENT(inout):: elemA
CLASS(meshEdge), INTENT(inout):: elemB
SELECT TYPE(elemB)
CLASS IS(meshEdge2DCart)
SELECT TYPE(elemA)
TYPE IS(meshVol2DCartQuad)
!Element A is a quadrilateral
CALL connectedQuadEdge(elemA, elemB)
TYPE IS(meshVol2DCartTria)
!Element A is a triangle
CALL connectedTriaEdge(elemA, elemB)
END SELECT
END SELECT
END SUBROUTINE connectedVolEdge
SUBROUTINE connectedQuadQuad(elemA, elemB)
IMPLICIT NONE
CLASS(meshVol2DCartQuad), INTENT(inout), TARGET:: elemA
CLASS(meshVol2DCartQuad), INTENT(inout), TARGET:: elemB
!Check direction 1
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
elemA%n1%n == elemB%n4%n .AND. &
elemA%n2%n == elemB%n3%n) THEN
elemA%e1 => elemB
elemB%e3 => elemA
END IF
!Check direction 2
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
elemA%n2%n == elemB%n1%n .AND. &
elemA%n3%n == elemB%n4%n) THEN
elemA%e2 => elemB
elemB%e4 => elemA
END IF
!Check direction 3
IF (.NOT. ASSOCIATED(elemA%e3) .AND. &
elemA%n3%n == elemB%n2%n .AND. &
elemA%n4%n == elemB%n1%n) THEN
elemA%e3 => elemB
elemB%e1 => elemA
END IF
!Check direction 4
IF (.NOT. ASSOCIATED(elemA%e4) .AND. &
elemA%n4%n == elemB%n3%n .AND. &
elemA%n1%n == elemB%n2%n) THEN
elemA%e4 => elemB
elemB%e2 => elemA
END IF
END SUBROUTINE connectedQuadQuad
SUBROUTINE connectedQuadTria(elemA, elemB)
IMPLICIT NONE
CLASS(meshVol2DCartQuad), INTENT(inout), TARGET:: elemA
CLASS(meshVol2DCartTria), INTENT(inout), TARGET:: elemB
!Check direction 1
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
IF (elemA%n1%n == elemB%n1%n .AND. &
elemA%n2%n == elemB%n3%n) THEN
elemA%e1 => elemB
elemB%e3 => elemA
ELSEIF (elemA%n1%n == elemB%n3%n .AND. &
elemA%n2%n == elemB%n2%n) THEN
elemA%e1 => elemB
elemB%e2 => elemA
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
elemA%n2%n == elemB%n1%n) THEN
elemA%e1 => elemB
elemB%e1 => elemA
END IF
END IF
!Check direction 2
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
IF (elemA%n2%n == elemB%n1%n .AND. &
elemA%n3%n == elemB%n3%n) THEN
elemA%e2 => elemB
elemB%e3 => elemA
ELSEIF (elemA%n2%n == elemB%n3%n .AND. &
elemA%n3%n == elemB%n2%n) THEN
elemA%e2 => elemB
elemB%e2 => elemA
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
elemA%n3%n == elemB%n1%n) THEN
elemA%e2 => elemB
elemB%e1 => elemA
END IF
END IF
!Check direction 3
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
IF (elemA%n3%n == elemB%n1%n .AND. &
elemA%n4%n == elemB%n3%n) THEN
elemA%e3 => elemB
elemB%e3 => elemA
ELSEIF (elemA%n3%n == elemB%n3%n .AND. &
elemA%n4%n == elemB%n2%n) THEN
elemA%e3 => elemB
elemB%e2 => elemA
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
elemA%n4%n == elemB%n1%n) THEN
elemA%e3 => elemB
elemB%e1 => elemA
END IF
END IF
!Check direction 4
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
IF (elemA%n4%n == elemB%n1%n .AND. &
elemA%n1%n == elemB%n3%n) THEN
elemA%e4 => elemB
elemB%e3 => elemA
ELSEIF (elemA%n4%n == elemB%n3%n .AND. &
elemA%n1%n == elemB%n2%n) THEN
elemA%e4 => elemB
elemB%e2 => elemA
ELSEIF (elemA%n4%n == elemB%n2%n .AND. &
elemA%n1%n == elemB%n1%n) THEN
elemA%e4 => elemB
elemB%e1 => elemA
END IF
END IF
END SUBROUTINE connectedQuadTria
SUBROUTINE connectedTriaTria(elemA, elemB)
IMPLICIT NONE
CLASS(meshVol2DCartTria), INTENT(inout), TARGET:: elemA
CLASS(meshVol2DCartTria), INTENT(inout), TARGET:: elemB
!Check direction 1
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
IF (elemA%n1%n == elemB%n1%n .AND. &
elemA%n2%n == elemB%n3%n) THEN
elemA%e1 => elemB
elemB%e3 => elemA
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
elemA%n2%n == elemB%n1%n) THEN
elemA%e1 => elemB
elemB%e1 => elemA
ELSEIF (elemA%n1%n == elemB%n3%n .AND. &
elemA%n2%n == elemB%n2%n) THEN
elemA%e1 => elemB
elemB%e2 => elemA
END IF
END IF
!Check direction 2
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
IF (elemA%n2%n == elemB%n1%n .AND. &
elemA%n3%n == elemB%n3%n) THEN
elemA%e2 => elemB
elemB%e3 => elemA
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
elemA%n3%n == elemB%n1%n) THEN
elemA%e2 => elemB
elemB%e1 => elemA
ELSEIF (elemA%n2%n == elemB%n3%n .AND. &
elemA%n3%n == elemB%n2%n) THEN
elemA%e2 => elemB
elemB%e2 => elemA
END IF
END IF
!Check direction 3
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
IF (elemA%n3%n == elemB%n1%n .AND. &
elemA%n1%n == elemB%n3%n) THEN
elemA%e3 => elemB
elemB%e3 => elemA
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
elemA%n1%n == elemB%n1%n) THEN
elemA%e3 => elemB
elemB%e1 => elemA
ELSEIF (elemA%n3%n == elemB%n3%n .AND. &
elemA%n1%n == elemB%n2%n) THEN
elemA%e3 => elemB
elemB%e2 => elemA
END IF
END IF
END SUBROUTINE connectedTriaTria
SUBROUTINE connectedQuadEdge(elemA, elemB)
IMPLICIT NONE
CLASS(meshVol2DCartQuad), INTENT(inout), TARGET:: elemA
CLASS(meshEdge2DCart), INTENT(inout), TARGET:: elemB
!Check direction 1
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
IF (elemA%n1%n == elemB%n1%n .AND. &
elemA%n2%n == elemB%n2%n) THEN
elemA%e1 => elemB
elemB%e2 => elemA
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
elemA%n2%n == elemB%n1%n) THEN
elemA%e1 => elemB
elemB%e1 => elemA
END IF
END IF
!Check direction 2
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
IF (elemA%n2%n == elemB%n1%n .AND. &
elemA%n3%n == elemB%n2%n) THEN
elemA%e2 => elemB
elemB%e2 => elemA
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
elemA%n3%n == elemB%n1%n) THEN
elemA%e2 => elemB
elemB%e1 => elemA
END IF
END IF
!Check direction 3
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
IF (elemA%n3%n == elemB%n1%n .AND. &
elemA%n4%n == elemB%n2%n) THEN
elemA%e3 => elemB
elemB%e2 => elemA
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
elemA%n4%n == elemB%n1%n) THEN
elemA%e3 => elemB
elemB%e1 => elemA
END IF
END IF
!Check direction 4
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
IF (elemA%n4%n == elemB%n1%n .AND. &
elemA%n1%n == elemB%n2%n) THEN
elemA%e4 => elemB
elemB%e2 => elemA
ELSEIF (elemA%n4%n == elemB%n2%n .AND. &
elemA%n1%n == elemB%n1%n) THEN
elemA%e4 => elemB
elemB%e1 => elemA
END IF
END IF
END SUBROUTINE connectedQuadEdge
SUBROUTINE connectedTriaEdge(elemA, elemB)
IMPLICIT NONE
CLASS(meshVol2DCartTria), INTENT(inout), TARGET:: elemA
CLASS(meshEdge2DCart), INTENT(inout), TARGET:: elemB
!Check direction 1
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
IF (elemA%n1%n == elemB%n1%n .AND. &
elemA%n2%n == elemB%n2%n) THEN
elemA%e1 => elemB
elemB%e2 => elemA
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
elemA%n2%n == elemB%n1%n) THEN
elemA%e1 => elemB
elemB%e1 => elemA
END IF
END IF
!Check direction 2
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
IF (elemA%n2%n == elemB%n1%n .AND. &
elemA%n3%n == elemB%n2%n) THEN
elemA%e2 => elemB
elemB%e2 => elemA
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
elemA%n3%n == elemB%n1%n) THEN
elemA%e2 => elemB
elemB%e1 => elemA
END IF
END IF
!Check direction 3
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
IF (elemA%n3%n == elemB%n1%n .AND. &
elemA%n1%n == elemB%n2%n) THEN
elemA%e3 => elemB
elemB%e2 => elemA
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
elemA%n1%n == elemB%n1%n) THEN
elemA%e3 => elemB
elemB%e1 => elemA
END IF
END IF
END SUBROUTINE connectedTriaEdge
SUBROUTINE constructGlobalK(K, elem)
IMPLICIT NONE
REAL(8), INTENT(inout):: K(1:,1:)
CLASS(meshVol), INTENT(in):: elem
REAL(8), ALLOCATABLE:: localK(:,:)
INTEGER:: nNodes, i, j
INTEGER, ALLOCATABLE:: n(:)
SELECT TYPE(elem)
TYPE IS(meshVol2DCartQuad)
nNodes = 4
ALLOCATE(localK(1:nNodes,1:nNodes))
localK = elem%elemK()
ALLOCATE(n(1:nNodes))
n = (/ elem%n1%n, elem%n2%n, &
elem%n3%n, elem%n4%n /)
TYPE IS(meshVol2DCartTria)
nNodes = 3
ALLOCATE(localK(1:nNodes,1:nNodes))
localK = elem%elemK()
ALLOCATE(n(1:nNodes))
n = (/ elem%n1%n, elem%n2%n, elem%n3%n /)
CLASS DEFAULT
nNodes = 0
ALLOCATE(localK(1:1, 1:1))
localK = 0.D0
ALLOCATE(n(1:1))
n = 0
END SELECT
DO i = 1, nNodes
DO j = 1, nNodes
K(n(i), n(j)) = K(n(i), n(j)) + localK(i, j)
END DO
END DO
END SUBROUTINE constructGlobalK
END MODULE moduleMesh2DCartRead

View file

@ -1,11 +1,11 @@
all : moduleMeshCyl.o moduleMeshCylBoundary.o moduleMeshCylRead.o all : moduleMesh2DCyl.o moduleMesh2DCylBoundary.o moduleMesh2DCylRead.o
moduleMeshCyl.o: moduleMeshCyl.f90 moduleMesh2DCyl.o: moduleMesh2DCyl.f90
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@ $(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
moduleMeshCylBoundary.o: moduleMeshCyl.o moduleMeshCylBoundary.f90 moduleMesh2DCylBoundary.o: moduleMesh2DCyl.o moduleMesh2DCylBoundary.f90
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@ $(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
moduleMeshCylRead.o: moduleMeshCyl.o moduleMeshCylBoundary.o moduleMeshCylRead.f90 moduleMesh2DCylRead.o: moduleMesh2DCyl.o moduleMesh2DCylBoundary.o moduleMesh2DCylRead.f90
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@ $(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@

View file

@ -1,8 +1,8 @@
!moduleMeshCyl: 2D axial symmetric extension of generic mesh from GMSH format. !moduleMesh2DCyl: 2D axial symmetric extension of generic mesh from GMSH format.
! x == z ! x == z
! y == r ! y == r
! z == theta (unused) ! z == theta (unused)
MODULE moduleMeshCyl MODULE moduleMesh2DCyl
USE moduleMesh USE moduleMesh
IMPLICIT NONE IMPLICIT NONE
@ -14,26 +14,26 @@ MODULE moduleMeshCyl
REAL(8), PARAMETER:: xi2Tria(1:4) = (/ 1.D0/3.D0, 1.D0/5.D0, 1.D0/5.D0, 3.D0/5.D0 /) REAL(8), PARAMETER:: xi2Tria(1:4) = (/ 1.D0/3.D0, 1.D0/5.D0, 1.D0/5.D0, 3.D0/5.D0 /)
REAL(8), PARAMETER:: wTria(1:4) = (/ -27.D0/96.D0, 25.D0/96.D0, 25.D0/96.D0, 25.D0/96.D0 /) REAL(8), PARAMETER:: wTria(1:4) = (/ -27.D0/96.D0, 25.D0/96.D0, 25.D0/96.D0, 25.D0/96.D0 /)
TYPE, PUBLIC, EXTENDS(meshNode):: meshNodeCyl TYPE, PUBLIC, EXTENDS(meshNode):: meshNode2DCyl
!Element coordinates !Element coordinates
REAL(8):: r = 0.D0, z = 0.D0 REAL(8):: r = 0.D0, z = 0.D0
CONTAINS CONTAINS
PROCEDURE, PASS:: init => initNodeCyl PROCEDURE, PASS:: init => initNode2DCyl
PROCEDURE, PASS:: getCoordinates => getCoordCyl PROCEDURE, PASS:: getCoordinates => getCoord2DCyl
END TYPE meshNodeCyl END TYPE meshNode2DCyl
TYPE, PUBLIC, EXTENDS(meshEdge):: meshEdgeCyl TYPE, PUBLIC, EXTENDS(meshEdge):: meshEdge2DCyl
!Element coordinates !Element coordinates
REAL(8):: r(1:2) = 0.D0, z(1:2) = 0.D0 REAL(8):: r(1:2) = 0.D0, z(1:2) = 0.D0
!Connectivity to nodes !Connectivity to nodes
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL() CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL()
CONTAINS CONTAINS
PROCEDURE, PASS:: init => initEdgeCyl PROCEDURE, PASS:: init => initEdge2DCyl
PROCEDURE, PASS:: getNodes => getNodesCyl PROCEDURE, PASS:: getNodes => getNodes2DCyl
PROCEDURE, PASS:: randPos => randPosEdge PROCEDURE, PASS:: randPos => randPosEdge
END TYPE meshEdgeCyl END TYPE meshEdge2DCyl
!Boundary functions defined in the submodule Boundary !Boundary functions defined in the submodule Boundary
INTERFACE INTERFACE
@ -84,15 +84,15 @@ MODULE moduleMeshCyl
END INTERFACE END INTERFACE
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshVol):: meshVolCyl TYPE, PUBLIC, ABSTRACT, EXTENDS(meshVol):: meshVol2DCyl
CONTAINS CONTAINS
PROCEDURE, PASS:: detJac => detJCyl PROCEDURE, PASS:: detJac => detJ2DCyl
PROCEDURE, PASS:: invJac => invJCyl PROCEDURE, PASS:: invJac => invJ2DCyl
PROCEDURE(fPsi_interface), DEFERRED, NOPASS:: fPsi PROCEDURE(fPsi_interface), DEFERRED, NOPASS:: fPsi
PROCEDURE(dPsi_interface), DEFERRED, NOPASS:: dPsi PROCEDURE(dPsi_interface), DEFERRED, NOPASS:: dPsi
PROCEDURE(partialDer_interface), DEFERRED, PASS:: partialDer PROCEDURE(partialDer_interface), DEFERRED, PASS:: partialDer
END TYPE meshVolCyl END TYPE meshVol2DCyl
ABSTRACT INTERFACE ABSTRACT INTERFACE
PURE FUNCTION fPsi_interface(xi) RESULT(fPsi) PURE FUNCTION fPsi_interface(xi) RESULT(fPsi)
@ -108,8 +108,8 @@ MODULE moduleMeshCyl
END FUNCTION dPsi_interface END FUNCTION dPsi_interface
PURE SUBROUTINE partialDer_interface(self, dPsi, dz, dr) PURE SUBROUTINE partialDer_interface(self, dPsi, dz, dr)
IMPORT meshVolCyl IMPORT meshVol2DCyl
CLASS(meshVolCyl), INTENT(in):: self CLASS(meshVol2DCyl), INTENT(in):: self
REAL(8), INTENT(in):: dPsi(1:,1:) REAL(8), INTENT(in):: dPsi(1:,1:)
REAL(8), INTENT(out), DIMENSION(1:2):: dz, dr REAL(8), INTENT(out), DIMENSION(1:2):: dz, dr
@ -118,7 +118,7 @@ MODULE moduleMeshCyl
END INTERFACE END INTERFACE
!Quadrilateral volume element !Quadrilateral volume element
TYPE, PUBLIC, EXTENDS(meshVolCyl):: meshVolCylQuad TYPE, PUBLIC, EXTENDS(meshVol2DCyl):: meshVol2DCylQuad
!Element coordinates !Element coordinates
REAL(8):: r(1:4) = 0.D0, z(1:4) = 0.D0 REAL(8):: r(1:4) = 0.D0, z(1:4) = 0.D0
!Connectivity to nodes !Connectivity to nodes
@ -128,7 +128,7 @@ MODULE moduleMeshCyl
REAL(8):: arNodes(1:4) = 0.D0 REAL(8):: arNodes(1:4) = 0.D0
CONTAINS CONTAINS
PROCEDURE, PASS:: init => initVolQuadCyl PROCEDURE, PASS:: init => initVolQuad2DCyl
PROCEDURE, PASS:: randPos => randPosVolQuad PROCEDURE, PASS:: randPos => randPosVolQuad
PROCEDURE, PASS:: area => areaQuad PROCEDURE, PASS:: area => areaQuad
PROCEDURE, NOPASS:: fPsi => fPsiQuad PROCEDURE, NOPASS:: fPsi => fPsiQuad
@ -146,10 +146,10 @@ MODULE moduleMeshCyl
PROCEDURE, PASS:: phy2log => phy2logQuad PROCEDURE, PASS:: phy2log => phy2logQuad
PROCEDURE, PASS:: nextElement => nextElementQuad PROCEDURE, PASS:: nextElement => nextElementQuad
END TYPE meshVolCylQuad END TYPE meshVol2DCylQuad
!Triangular volume element !Triangular volume element
TYPE, PUBLIC, EXTENDS(meshVolCyl):: meshVolCylTria TYPE, PUBLIC, EXTENDS(meshVol2DCyl):: meshVol2DCylTria
!Element coordinates !Element coordinates
REAL(8):: r(1:3) = 0.D0, z(1:3) = 0.D0 REAL(8):: r(1:3) = 0.D0, z(1:3) = 0.D0
!Connectivity to nodes !Connectivity to nodes
@ -157,11 +157,9 @@ MODULE moduleMeshCyl
!Connectivity to adjacent elements !Connectivity to adjacent elements
CLASS(*), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL() CLASS(*), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL()
REAL(8):: arNodes(1:3) = 0.D0 REAL(8):: arNodes(1:3) = 0.D0
!Derivatives in z,r real space
REAL(8), DIMENSION(1:3):: dPsiZ, dPsiR
CONTAINS CONTAINS
PROCEDURE, PASS:: init => initVolTriaCyl PROCEDURE, PASS:: init => initVolTria2DCyl
PROCEDURE, PASS:: randPos => randPosVolTria PROCEDURE, PASS:: randPos => randPosVolTria
PROCEDURE, PASS:: area => areaTria PROCEDURE, PASS:: area => areaTria
PROCEDURE, NOPASS:: fPsi => fPsiTria PROCEDURE, NOPASS:: fPsi => fPsiTria
@ -179,51 +177,51 @@ MODULE moduleMeshCyl
PROCEDURE, PASS:: phy2log => phy2logTria PROCEDURE, PASS:: phy2log => phy2logTria
PROCEDURE, PASS:: nextElement => nextElementTria PROCEDURE, PASS:: nextElement => nextElementTria
END TYPE meshVolCylTria END TYPE meshVol2DCylTria
CONTAINS CONTAINS
!NODE FUNCTIONS !NODE FUNCTIONS
!Inits node element !Inits node element
SUBROUTINE initNodeCyl(self, n, r) SUBROUTINE initNode2DCyl(self, n, r)
USE moduleSpecies USE moduleSpecies
USE moduleRefParam USE moduleRefParam
IMPLICIT NONE IMPLICIT NONE
CLASS(meshNodeCyl), INTENT(out):: self CLASS(meshNode2DCyl), INTENT(out):: self
INTEGER, INTENT(in):: n INTEGER, INTENT(in):: n
REAL(8), INTENT(in):: r(1:3) REAL(8), INTENT(in):: r(1:3)
self%n = n self%n = n
self%z = r(2)/L_ref self%z = r(1)/L_ref
self%r = r(1)/L_ref self%r = r(2)/L_ref
!Node volume, to be determined in mesh !Node volume, to be determined in mesh
self%v = 0.D0 self%v = 0.D0
!Allocates output: !Allocates output:
ALLOCATE(self%output(1:nSpecies)) ALLOCATE(self%output(1:nSpecies))
END SUBROUTINE initNodeCyl END SUBROUTINE initNode2DCyl
!Get coordinates from node !Get coordinates from node
PURE FUNCTION getCoordCyl(self) RESULT(r) PURE FUNCTION getCoord2DCyl(self) RESULT(r)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshNodeCyl), INTENT(in):: self CLASS(meshNode2DCyl), INTENT(in):: self
REAL(8):: r(1:3) REAL(8):: r(1:3)
r = (/self%z, self%r, 0.D0/) r = (/self%z, self%r, 0.D0/)
END FUNCTION getCoordCyl END FUNCTION getCoord2DCyl
!EDGE FUNCTIONS !EDGE FUNCTIONS
!Inits edge element !Inits edge element
SUBROUTINE initEdgeCyl(self, n, p, bt, physicalSurface) SUBROUTINE initEdge2DCyl(self, n, p, bt, physicalSurface)
USE moduleSpecies USE moduleSpecies
USE moduleBoundary USE moduleBoundary
USE moduleErrors USE moduleErrors
IMPLICIT NONE IMPLICIT NONE
CLASS(meshEdgeCyl), INTENT(out):: self CLASS(meshEdge2DCyl), INTENT(out):: self
INTEGER, INTENT(in):: n INTEGER, INTENT(in):: n
INTEGER, INTENT(in):: p(:) INTEGER, INTENT(in):: p(:)
INTEGER, INTENT(in):: bt INTEGER, INTENT(in):: bt
@ -265,7 +263,7 @@ MODULE moduleMeshCyl
self%fBoundary(s)%apply => symmetryAxis self%fBoundary(s)%apply => symmetryAxis
CLASS DEFAULT CLASS DEFAULT
CALL criticalError("Boundary type not defined in this geometry", 'initEdgeCyl') CALL criticalError("Boundary type not defined in this geometry", 'initEdge2DCyl')
END SELECT END SELECT
@ -274,14 +272,14 @@ MODULE moduleMeshCyl
!Physical surface !Physical surface
self%physicalSurface = physicalSurface self%physicalSurface = physicalSurface
END SUBROUTINE initEdgeCyl END SUBROUTINE initEdge2DCyl
!Random position in quadrilateral volume !Random position in quadrilateral volume
FUNCTION randPosVolQuad(self) RESULT(r) FUNCTION randPosVolQuad(self) RESULT(r)
USE moduleRandom USE moduleRandom
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(in):: self CLASS(meshVol2DCylQuad), INTENT(in):: self
REAL(8):: r(1:3) REAL(8):: r(1:3)
REAL(8):: xii(1:3) REAL(8):: xii(1:3)
REAL(8), ALLOCATABLE:: fPsi(:) REAL(8), ALLOCATABLE:: fPsi(:)
@ -299,23 +297,23 @@ MODULE moduleMeshCyl
END FUNCTION randposVolQuad END FUNCTION randposVolQuad
!Get nodes from edge !Get nodes from edge
PURE FUNCTION getNodesCyl(self) RESULT(n) PURE FUNCTION getNodes2DCyl(self) RESULT(n)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshEdgeCyl), INTENT(in):: self CLASS(meshEdge2DCyl), INTENT(in):: self
INTEGER, ALLOCATABLE:: n(:) INTEGER, ALLOCATABLE:: n(:)
ALLOCATE(n(1:2)) ALLOCATE(n(1:2))
n = (/self%n1%n, self%n2%n /) n = (/self%n1%n, self%n2%n /)
END FUNCTION getNodesCyl END FUNCTION getNodes2DCyl
!Calculates a random position in edge !Calculates a random position in edge
FUNCTION randPosEdge(self) RESULT(r) FUNCTION randPosEdge(self) RESULT(r)
USE moduleRandom USE moduleRandom
IMPLICIT NONE IMPLICIT NONE
CLASS(meshEdgeCyl), INTENT(in):: self CLASS(meshEdge2DCyl), INTENT(in):: self
REAL(8):: rnd REAL(8):: rnd
REAL(8):: r(1:3) REAL(8):: r(1:3)
REAL(8):: p1(1:2), p2(1:2) REAL(8):: p1(1:2), p2(1:2)
@ -332,11 +330,11 @@ MODULE moduleMeshCyl
!VOLUME FUNCTIONS !VOLUME FUNCTIONS
!QUAD FUNCTIONS !QUAD FUNCTIONS
!Inits quadrilateral element !Inits quadrilateral element
SUBROUTINE initVolQuadCyl(self, n, p) SUBROUTINE initVolQuad2DCyl(self, n, p)
USE moduleRefParam USE moduleRefParam
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(out):: self CLASS(meshVol2DCylQuad), INTENT(out):: self
INTEGER, INTENT(in):: n INTEGER, INTENT(in):: n
INTEGER, INTENT(in):: p(:) INTEGER, INTENT(in):: p(:)
REAL(8), DIMENSION(1:3):: r1, r2, r3, r4 REAL(8), DIMENSION(1:3):: r1, r2, r3, r4
@ -365,14 +363,14 @@ MODULE moduleMeshCyl
CALL OMP_INIT_LOCK(self%lock) CALL OMP_INIT_LOCK(self%lock)
END SUBROUTINE initVolQuadCyl END SUBROUTINE initVolQuad2DCyl
!Computes element area !Computes element area
PURE SUBROUTINE areaQuad(self) PURE SUBROUTINE areaQuad(self)
USE moduleConstParam, ONLY: PI8 USE moduleConstParam, ONLY: PI8
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(inout):: self CLASS(meshVol2DCylQuad), INTENT(inout):: self
REAL(8):: r, xi(1:3) REAL(8):: r, xi(1:3)
REAL(8):: detJ REAL(8):: detJ
REAL(8):: fPsi(1:4) REAL(8):: fPsi(1:4)
@ -453,7 +451,7 @@ MODULE moduleMeshCyl
PURE SUBROUTINE partialDerQuad(self, dPsi, dz, dr) PURE SUBROUTINE partialDerQuad(self, dPsi, dz, dr)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(in):: self CLASS(meshVol2DCylQuad), INTENT(in):: self
REAL(8), INTENT(in):: dPsi(1:,1:) REAL(8), INTENT(in):: dPsi(1:,1:)
REAL(8), INTENT(out), DIMENSION(1:2):: dz, dr REAL(8), INTENT(out), DIMENSION(1:2):: dz, dr
@ -469,7 +467,7 @@ MODULE moduleMeshCyl
USE moduleConstParam, ONLY: PI2 USE moduleConstParam, ONLY: PI2
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(in):: self CLASS(meshVol2DCylQuad), INTENT(in):: self
REAL(8):: r, xi(1:3) REAL(8):: r, xi(1:3)
REAL(8):: fPsi(1:4), dPsi(1:2,1:4) REAL(8):: fPsi(1:4), dPsi(1:2,1:4)
REAL(8):: ke(1:4,1:4) REAL(8):: ke(1:4,1:4)
@ -502,7 +500,7 @@ MODULE moduleMeshCyl
USE moduleConstParam, ONLY: PI2 USE moduleConstParam, ONLY: PI2
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(in):: self CLASS(meshVol2DCylQuad), INTENT(in):: self
REAL(8), INTENT(in):: source(1:) REAL(8), INTENT(in):: source(1:)
REAL(8), ALLOCATABLE:: localF(:) REAL(8), ALLOCATABLE:: localF(:)
REAL(8):: r, xi(1:3) REAL(8):: r, xi(1:3)
@ -558,7 +556,7 @@ MODULE moduleMeshCyl
USE moduleSpecies USE moduleSpecies
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(in):: self CLASS(meshVol2DCylQuad), INTENT(in):: self
CLASS(particle), INTENT(in):: part CLASS(particle), INTENT(in):: part
TYPE(outputNode), POINTER:: vertex TYPE(outputNode), POINTER:: vertex
REAL(8):: w_p(1:4) REAL(8):: w_p(1:4)
@ -593,7 +591,7 @@ MODULE moduleMeshCyl
PURE FUNCTION gatherEFQuad(self,xi) RESULT(EF) PURE FUNCTION gatherEFQuad(self,xi) RESULT(EF)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(in):: self CLASS(meshVol2DCylQuad), INTENT(in):: self
REAL(8), INTENT(in):: xi(1:3) REAL(8), INTENT(in):: xi(1:3)
REAL(8):: dPsi(1:2,1:4) REAL(8):: dPsi(1:2,1:4)
REAL(8):: dPsiR(1:2,1:4)!Derivative of shpae functions in global coordinates REAL(8):: dPsiR(1:2,1:4)!Derivative of shpae functions in global coordinates
@ -620,7 +618,7 @@ MODULE moduleMeshCyl
PURE FUNCTION getNodesQuad(self) RESULT(n) PURE FUNCTION getNodesQuad(self) RESULT(n)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(in):: self CLASS(meshVol2DCylQuad), INTENT(in):: self
INTEGER, ALLOCATABLE:: n(:) INTEGER, ALLOCATABLE:: n(:)
ALLOCATE(n(1:4)) ALLOCATE(n(1:4))
@ -632,7 +630,7 @@ MODULE moduleMeshCyl
PURE FUNCTION phy2logQuad(self,r) RESULT(xN) PURE FUNCTION phy2logQuad(self,r) RESULT(xN)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(in):: self CLASS(meshVol2DCylQuad), INTENT(in):: self
REAL(8), INTENT(in):: r(1:3) REAL(8), INTENT(in):: r(1:3)
REAL(8):: xN(1:3) REAL(8):: xN(1:3)
REAL(8):: xO(1:3), detJ, invJ(1:2,1:2), f(1:2) REAL(8):: xO(1:3), detJ, invJ(1:2,1:2), f(1:2)
@ -662,7 +660,7 @@ MODULE moduleMeshCyl
SUBROUTINE nextElementQuad(self, xi, nextElement) SUBROUTINE nextElementQuad(self, xi, nextElement)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(in):: self CLASS(meshVol2DCylQuad), INTENT(in):: self
REAL(8), INTENT(in):: xi(1:3) REAL(8), INTENT(in):: xi(1:3)
CLASS(*), POINTER, INTENT(out):: nextElement CLASS(*), POINTER, INTENT(out):: nextElement
REAL(8):: xiArray(1:4) REAL(8):: xiArray(1:4)
@ -687,15 +685,14 @@ MODULE moduleMeshCyl
!TRIA ELEMENT !TRIA ELEMENT
!Init tria element !Init tria element
SUBROUTINE initVolTriaCyl(self, n, p) SUBROUTINE initVolTria2DCyl(self, n, p)
USE moduleRefParam USE moduleRefParam
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(out):: self CLASS(meshVol2DCylTria), INTENT(out):: self
INTEGER, INTENT(in):: n INTEGER, INTENT(in):: n
INTEGER, INTENT(in):: p(:) INTEGER, INTENT(in):: p(:)
REAL(8), DIMENSION(1:3):: r1, r2, r3 REAL(8), DIMENSION(1:3):: r1, r2, r3
REAL(8):: A
!Assign node index !Assign node index
self%n = n self%n = n
@ -716,31 +713,18 @@ MODULE moduleMeshCyl
self%n2%v = self%n2%v + self%arNodes(2) self%n2%v = self%n2%v + self%arNodes(2)
self%n3%v = self%n3%v + self%arNodes(3) self%n3%v = self%n3%v + self%arNodes(3)
!Derivatives in z/r for shape functions (node independent)
A = self%z(2)*self%r(3) - self%z(3)*self%r(2) + &
self%z(3)*self%r(1) - self%z(1)*self%r(3) + &
self%z(1)*self%r(2) - self%z(2)*self%r(1)
self%dPsiZ = (/ self%r(2)-self%r(3), &
self%r(3)-self%r(1), &
self%r(1)-self%r(2) /)/A
self%dPsiR = (/ self%z(3)-self%z(2), &
self%z(1)-self%z(3), &
self%z(2)-self%z(1) /)/A
self%sigmaVrelMax = sigma_ref/L_ref**2 self%sigmaVrelMax = sigma_ref/L_ref**2
CALL OMP_INIT_LOCK(self%lock) CALL OMP_INIT_LOCK(self%lock)
END SUBROUTINE initVolTriaCyl END SUBROUTINE initVolTria2DCyl
!Random position in quadrilateral volume !Random position in quadrilateral volume
FUNCTION randPosVolTria(self) RESULT(r) FUNCTION randPosVolTria(self) RESULT(r)
USE moduleRandom USE moduleRandom
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(in):: self CLASS(meshVol2DCylTria), INTENT(in):: self
REAL(8):: r(1:3) REAL(8):: r(1:3)
REAL(8):: xii(1:3) REAL(8):: xii(1:3)
REAL(8), ALLOCATABLE:: fPsi(:) REAL(8), ALLOCATABLE:: fPsi(:)
@ -762,7 +746,7 @@ MODULE moduleMeshCyl
USE moduleConstParam, ONLY: PI USE moduleConstParam, ONLY: PI
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(inout):: self CLASS(meshVol2DCylTria), INTENT(inout):: self
REAL(8):: r, xi(1:3) REAL(8):: r, xi(1:3)
REAL(8):: detJ REAL(8):: detJ
REAL(8):: fPsi(1:3) REAL(8):: fPsi(1:3)
@ -837,7 +821,7 @@ MODULE moduleMeshCyl
PURE SUBROUTINE partialDerTria(self, dPsi, dz, dr) PURE SUBROUTINE partialDerTria(self, dPsi, dz, dr)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(in):: self CLASS(meshVol2DCylTria), INTENT(in):: self
REAL(8), INTENT(in):: dPsi(1:,1:) REAL(8), INTENT(in):: dPsi(1:,1:)
REAL(8), INTENT(out), DIMENSION(1:2):: dz, dr REAL(8), INTENT(out), DIMENSION(1:2):: dz, dr
@ -853,7 +837,7 @@ MODULE moduleMeshCyl
USE moduleConstParam, ONLY: PI2 USE moduleConstParam, ONLY: PI2
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(in):: self CLASS(meshVol2DCylTria), INTENT(in):: self
REAL(8):: r, xi(1:3) REAL(8):: r, xi(1:3)
REAL(8):: fPsi(1:3), dPsi(1:2,1:3) REAL(8):: fPsi(1:3), dPsi(1:2,1:3)
REAL(8):: ke(1:3,1:3) REAL(8):: ke(1:3,1:3)
@ -883,7 +867,7 @@ MODULE moduleMeshCyl
USE moduleConstParam, ONLY: PI2 USE moduleConstParam, ONLY: PI2
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(in):: self CLASS(meshVol2DCylTria), INTENT(in):: self
REAL(8), INTENT(in):: source(1:) REAL(8), INTENT(in):: source(1:)
REAL(8), ALLOCATABLE:: localF(:) REAL(8), ALLOCATABLE:: localF(:)
REAL(8):: fPsi(1:3) REAL(8):: fPsi(1:3)
@ -938,7 +922,7 @@ MODULE moduleMeshCyl
USE moduleSpecies USE moduleSpecies
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(in):: self CLASS(meshVol2DCylTria), INTENT(in):: self
CLASS(particle), INTENT(in):: part CLASS(particle), INTENT(in):: part
TYPE(outputNode), POINTER:: vertex TYPE(outputNode), POINTER:: vertex
REAL(8):: w_p(1:3) REAL(8):: w_p(1:3)
@ -968,7 +952,7 @@ MODULE moduleMeshCyl
PURE FUNCTION gatherEFTria(self,xi) RESULT(EF) PURE FUNCTION gatherEFTria(self,xi) RESULT(EF)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(in):: self CLASS(meshVol2DCylTria), INTENT(in):: self
REAL(8), INTENT(in):: xi(1:3) REAL(8), INTENT(in):: xi(1:3)
REAL(8):: dPsi(1:2,1:3) REAL(8):: dPsi(1:2,1:3)
REAL(8):: dPsiR(1:2,1:3)!Derivative of shpae functions in global coordinates REAL(8):: dPsiR(1:2,1:3)!Derivative of shpae functions in global coordinates
@ -995,7 +979,7 @@ MODULE moduleMeshCyl
PURE FUNCTION getNodesTria(self) RESULT(n) PURE FUNCTION getNodesTria(self) RESULT(n)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(in):: self CLASS(meshVol2DCylTria), INTENT(in):: self
INTEGER, ALLOCATABLE:: n(:) INTEGER, ALLOCATABLE:: n(:)
ALLOCATE(n(1:3)) ALLOCATE(n(1:3))
@ -1007,7 +991,7 @@ MODULE moduleMeshCyl
PURE FUNCTION phy2logTria(self,r) RESULT(xi) PURE FUNCTION phy2logTria(self,r) RESULT(xi)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(in):: self CLASS(meshVol2DCylTria), INTENT(in):: self
REAL(8), INTENT(in):: r(1:3) REAL(8), INTENT(in):: r(1:3)
REAL(8):: xi(1:3) REAL(8):: xi(1:3)
REAL(8):: invJ(1:2,1:2), detJ REAL(8):: invJ(1:2,1:2), detJ
@ -1027,7 +1011,7 @@ MODULE moduleMeshCyl
SUBROUTINE nextElementTria(self, xi, nextElement) SUBROUTINE nextElementTria(self, xi, nextElement)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(in):: self CLASS(meshVol2DCylTria), INTENT(in):: self
REAL(8), INTENT(in):: xi(1:3) REAL(8), INTENT(in):: xi(1:3)
CLASS(*), POINTER, INTENT(out):: nextElement CLASS(*), POINTER, INTENT(out):: nextElement
REAL(8):: xiArray(1:3) REAL(8):: xiArray(1:3)
@ -1049,10 +1033,10 @@ MODULE moduleMeshCyl
!COMMON FUNCTIONS FOR CYLINDRICAL VOLUME ELEMENTS !COMMON FUNCTIONS FOR CYLINDRICAL VOLUME ELEMENTS
!Computes element Jacobian determinant !Computes element Jacobian determinant
PURE FUNCTION detJCyl(self, xi, dPsi_in) RESULT(dJ) PURE FUNCTION detJ2DCyl(self, xi, dPsi_in) RESULT(dJ)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCyl), INTENT(in):: self CLASS(meshVol2DCyl), INTENT(in):: self
REAL(8), INTENT(in):: xi(1:3) REAL(8), INTENT(in):: xi(1:3)
REAL(8), INTENT(in), OPTIONAL:: dPsi_in(1:,1:) REAL(8), INTENT(in), OPTIONAL:: dPsi_in(1:,1:)
REAL(8), ALLOCATABLE:: dPsi(:,:) REAL(8), ALLOCATABLE:: dPsi(:,:)
@ -1070,13 +1054,13 @@ MODULE moduleMeshCyl
CALL self%partialDer(dPsi, dz, dr) CALL self%partialDer(dPsi, dz, dr)
dJ = dz(1)*dr(2)-dz(2)*dr(1) dJ = dz(1)*dr(2)-dz(2)*dr(1)
END FUNCTION detJCyl END FUNCTION detJ2DCyl
!Computes element Jacobian inverse matrix (without determinant) !Computes element Jacobian inverse matrix (without determinant)
PURE FUNCTION invJCyl(self,xi,dPsi_in) RESULT(invJ) PURE FUNCTION invJ2DCyl(self,xi,dPsi_in) RESULT(invJ)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCyl), INTENT(in):: self CLASS(meshVol2DCyl), INTENT(in):: self
REAL(8), INTENT(in):: xi(1:3) REAL(8), INTENT(in):: xi(1:3)
REAL(8), INTENT(in), OPTIONAL:: dPsi_in(1:,1:) REAL(8), INTENT(in), OPTIONAL:: dPsi_in(1:,1:)
REAL(8), ALLOCATABLE:: dPsi(:,:) REAL(8), ALLOCATABLE:: dPsi(:,:)
@ -1095,6 +1079,6 @@ MODULE moduleMeshCyl
invJ(1,:) = (/ dr(2), -dz(2) /) invJ(1,:) = (/ dr(2), -dz(2) /)
invJ(2,:) = (/ -dr(1), dz(1) /) invJ(2,:) = (/ -dr(1), dz(1) /)
END FUNCTION invJCyl END FUNCTION invJ2DCyl
END MODULE moduleMeshCyl END MODULE moduleMesh2DCyl

View file

@ -1,6 +1,6 @@
!moduleMeshCylBoundary: Boundary functions for cylindrical coordinates !moduleMesh2DCylBoundary: Boundary functions for cylindrical coordinates
SUBMODULE (moduleMeshCyl) moduleMeshCylBoundary SUBMODULE (moduleMesh2DCyl) moduleMesh2DCylBoundary
USE moduleMeshCyl USE moduleMesh2DCyl
CONTAINS CONTAINS
SUBROUTINE reflection(edge, part) SUBROUTINE reflection(edge, part)
@ -13,7 +13,7 @@ SUBMODULE (moduleMeshCyl) moduleMeshCylBoundary
!TODO: Try to do this without select !TODO: Try to do this without select
SELECT TYPE(edge) SELECT TYPE(edge)
TYPE IS(meshEdgeCyl) TYPE IS(meshEdge2DCyl)
edgeNorm = DSQRT((edge%r(2)-edge%r(1))**2 + (edge%z(2)-edge%z(1))**2) edgeNorm = DSQRT((edge%r(2)-edge%r(1))**2 + (edge%z(2)-edge%z(1))**2)
cosT = (edge%z(2)-edge%z(1))/edgeNorm cosT = (edge%z(2)-edge%z(1))/edgeNorm
sinT = DSQRT(1-cosT**2) sinT = DSQRT(1-cosT**2)
@ -53,7 +53,7 @@ SUBMODULE (moduleMeshCyl) moduleMeshCylBoundary
REAL(8):: d !Distance from particle to edge REAL(8):: d !Distance from particle to edge
SELECT TYPE(edge) SELECT TYPE(edge)
TYPE IS(meshEdgeCyl) TYPE IS(meshEdge2DCyl)
a = (edge%z(1) - edge%z(2)) a = (edge%z(1) - edge%z(2))
b = (edge%r(1) - edge%r(2)) b = (edge%r(1) - edge%r(2))
c = edge%z(1)*edge%r(2) - edge%z(2)*edge%r(1) c = edge%z(1)*edge%r(2) - edge%z(2)*edge%r(1)
@ -124,7 +124,7 @@ SUBMODULE (moduleMeshCyl) moduleMeshCylBoundary
!Reflects particle in the edge !Reflects particle in the edge
SELECT TYPE(edge) SELECT TYPE(edge)
TYPE IS(meshEdgeCyl) TYPE IS(meshEdge2DCyl)
edgeNorm = DSQRT((edge%r(2)-edge%r(1))**2 + (edge%z(2)-edge%z(1))**2) edgeNorm = DSQRT((edge%r(2)-edge%r(1))**2 + (edge%z(2)-edge%z(1))**2)
cosT = (edge%z(2)-edge%z(1))/edgeNorm cosT = (edge%z(2)-edge%z(1))/edgeNorm
sinT = DSQRT(1-cosT**2) sinT = DSQRT(1-cosT**2)
@ -161,4 +161,4 @@ SUBMODULE (moduleMeshCyl) moduleMeshCylBoundary
END SUBROUTINE symmetryAxis END SUBROUTINE symmetryAxis
END SUBMODULE moduleMeshCylBoundary END SUBMODULE moduleMesh2DCylBoundary

View file

@ -1,11 +1,11 @@
MODULE moduleMeshCylRead MODULE moduleMesh2DCylRead
USE moduleMesh USE moduleMesh
USE moduleMeshCyl USE moduleMesh2DCyl
TYPE, EXTENDS(meshGeneric):: meshCylGeneric TYPE, EXTENDS(meshGeneric):: mesh2DCylGeneric
CONTAINS CONTAINS
PROCEDURE, PASS:: init => initCylMesh PROCEDURE, PASS:: init => init2DCylMesh
PROCEDURE, PASS:: readMesh => readMeshCylGmsh PROCEDURE, PASS:: readMesh => readMesh2DCylGmsh
END TYPE END TYPE
@ -16,12 +16,12 @@ MODULE moduleMeshCylRead
CONTAINS CONTAINS
!Init mesh !Init mesh
SUBROUTINE initCylMesh(self, meshFormat) SUBROUTINE init2DCylMesh(self, meshFormat)
USE moduleMesh USE moduleMesh
USE moduleErrors USE moduleErrors
IMPLICIT NONE IMPLICIT NONE
CLASS(meshCylGeneric), INTENT(out):: self CLASS(mesh2DCylGeneric), INTENT(out):: self
CHARACTER(:), ALLOCATABLE, INTENT(in):: meshFormat CHARACTER(:), ALLOCATABLE, INTENT(in):: meshFormat
SELECT CASE(meshFormat) SELECT CASE(meshFormat)
@ -31,18 +31,18 @@ MODULE moduleMeshCylRead
self%printEM => printEMGmsh self%printEM => printEMGmsh
CASE DEFAULT CASE DEFAULT
CALL criticalError("Mesh type " // meshFormat // " not supported.", "initCylMesh") CALL criticalError("Mesh type " // meshFormat // " not supported.", "init2DCylMesh")
END SELECT END SELECT
END SUBROUTINE initCylMesh END SUBROUTINE init2DCylMesh
!Read mesh from gmsh file !Read mesh from gmsh file
SUBROUTINE readMeshCylGmsh(self, filename) SUBROUTINE readMesh2DCylGmsh(self, filename)
USE moduleBoundary USE moduleBoundary
IMPLICIT NONE IMPLICIT NONE
CLASS(meshCylGeneric), INTENT(inout):: self CLASS(mesh2DCylGeneric), INTENT(inout):: self
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
REAL(8):: r, z REAL(8):: r, z
INTEGER:: p(1:4) INTEGER:: p(1:4)
@ -68,8 +68,8 @@ MODULE moduleMeshCylRead
!Read nodes cartesian coordinates (x=z, y=r, z=null) !Read nodes cartesian coordinates (x=z, y=r, z=null)
DO e=1, self%numNodes DO e=1, self%numNodes
READ(10, *) n, z, r READ(10, *) n, z, r
ALLOCATE(meshNodeCyl:: self%nodes(n)%obj) ALLOCATE(meshNode2DCyl:: self%nodes(n)%obj)
CALL self%nodes(n)%obj%init(n, (/r, z, 0.D0 /)) CALL self%nodes(n)%obj%init(n, (/z, r, 0.D0 /))
END DO END DO
!Skips comments !Skips comments
@ -103,7 +103,7 @@ MODULE moduleMeshCylRead
!Associate boundary condition procedure. !Associate boundary condition procedure.
bt = getBoundaryId(boundaryType) bt = getBoundaryId(boundaryType)
ALLOCATE(meshEdgeCyl:: self%edges(e)%obj) ALLOCATE(meshEdge2DCyl:: self%edges(e)%obj)
CALL self%edges(e)%obj%init(n, p(1:2), bt, boundaryType) CALL self%edges(e)%obj%init(n, p(1:2), bt, boundaryType)
@ -118,13 +118,13 @@ MODULE moduleMeshCylRead
CASE (2) CASE (2)
!Triangular element !Triangular element
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:3) READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:3)
ALLOCATE(meshVolCylTria:: self%vols(e)%obj) ALLOCATE(meshVol2DCylTria:: self%vols(e)%obj)
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:3)) CALL self%vols(e)%obj%init(n - self%numEdges, p(1:3))
CASE (3) CASE (3)
!Quadrilateral element !Quadrilateral element
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:4) READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:4)
ALLOCATE(meshVolCylQuad:: self%vols(e)%obj) ALLOCATE(meshVol2DCylQuad:: self%vols(e)%obj)
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:4)) CALL self%vols(e)%obj%init(n - self%numEdges, p(1:4))
END SELECT END SELECT
@ -154,7 +154,7 @@ MODULE moduleMeshCylRead
END DO END DO
END SUBROUTINE readMeshCylGmsh END SUBROUTINE readMesh2DCylGmsh
!Selects type of elements to build connection !Selects type of elements to build connection
SUBROUTINE connectedVolVol(elemA, elemB) SUBROUTINE connectedVolVol(elemA, elemB)
@ -164,27 +164,27 @@ MODULE moduleMeshCylRead
CLASS(meshVol), INTENT(inout):: elemB CLASS(meshVol), INTENT(inout):: elemB
SELECT TYPE(elemA) SELECT TYPE(elemA)
TYPE IS(meshVolCylQuad) TYPE IS(meshVol2DCylQuad)
!Element A is a quadrilateral !Element A is a quadrilateral
SELECT TYPE(elemB) SELECT TYPE(elemB)
TYPE IS(meshVolCylQuad) TYPE IS(meshVol2DCylQuad)
!Element B is a quadrilateral !Element B is a quadrilateral
CALL connectedQuadQuad(elemA, elemB) CALL connectedQuadQuad(elemA, elemB)
TYPE IS(meshVolCylTria) TYPE IS(meshVol2DCylTria)
!Element B is a triangle !Element B is a triangle
CALL connectedQuadTria(elemA, elemB) CALL connectedQuadTria(elemA, elemB)
END SELECT END SELECT
TYPE IS(meshVolCylTria) TYPE IS(meshVol2DCylTria)
!Element A is a Triangle !Element A is a Triangle
SELECT TYPE(elemB) SELECT TYPE(elemB)
TYPE IS(meshVolCylQuad) TYPE IS(meshVol2DCylQuad)
!Element B is a quadrilateral !Element B is a quadrilateral
CALL connectedQuadTria(elemB, elemA) CALL connectedQuadTria(elemB, elemA)
TYPE IS(meshVolCylTria) TYPE IS(meshVol2DCylTria)
!Element B is a triangle !Element B is a triangle
CALL connectedTriaTria(elemA, elemB) CALL connectedTriaTria(elemA, elemB)
@ -201,13 +201,13 @@ MODULE moduleMeshCylRead
CLASS(meshEdge), INTENT(inout):: elemB CLASS(meshEdge), INTENT(inout):: elemB
SELECT TYPE(elemB) SELECT TYPE(elemB)
CLASS IS(meshEdgeCyl) CLASS IS(meshEdge2DCyl)
SELECT TYPE(elemA) SELECT TYPE(elemA)
TYPE IS(meshVolCylQuad) TYPE IS(meshVol2DCylQuad)
!Element A is a quadrilateral !Element A is a quadrilateral
CALL connectedQuadEdge(elemA, elemB) CALL connectedQuadEdge(elemA, elemB)
TYPE IS(meshVolCylTria) TYPE IS(meshVol2DCylTria)
!Element A is a triangle !Element A is a triangle
CALL connectedTriaEdge(elemA, elemB) CALL connectedTriaEdge(elemA, elemB)
@ -220,8 +220,8 @@ MODULE moduleMeshCylRead
SUBROUTINE connectedQuadQuad(elemA, elemB) SUBROUTINE connectedQuadQuad(elemA, elemB)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(inout), TARGET:: elemA CLASS(meshVol2DCylQuad), INTENT(inout), TARGET:: elemA
CLASS(meshVolCylQuad), INTENT(inout), TARGET:: elemB CLASS(meshVol2DCylQuad), INTENT(inout), TARGET:: elemB
!Check direction 1 !Check direction 1
IF (.NOT. ASSOCIATED(elemA%e1) .AND. & IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
@ -264,8 +264,8 @@ MODULE moduleMeshCylRead
SUBROUTINE connectedQuadTria(elemA, elemB) SUBROUTINE connectedQuadTria(elemA, elemB)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(inout), TARGET:: elemA CLASS(meshVol2DCylQuad), INTENT(inout), TARGET:: elemA
CLASS(meshVolCylTria), INTENT(inout), TARGET:: elemB CLASS(meshVol2DCylTria), INTENT(inout), TARGET:: elemB
!Check direction 1 !Check direction 1
IF (.NOT. ASSOCIATED(elemA%e1)) THEN IF (.NOT. ASSOCIATED(elemA%e1)) THEN
@ -356,8 +356,8 @@ MODULE moduleMeshCylRead
SUBROUTINE connectedTriaTria(elemA, elemB) SUBROUTINE connectedTriaTria(elemA, elemB)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(inout), TARGET:: elemA CLASS(meshVol2DCylTria), INTENT(inout), TARGET:: elemA
CLASS(meshVolCylTria), INTENT(inout), TARGET:: elemB CLASS(meshVol2DCylTria), INTENT(inout), TARGET:: elemB
!Check direction 1 !Check direction 1
IF (.NOT. ASSOCIATED(elemA%e1)) THEN IF (.NOT. ASSOCIATED(elemA%e1)) THEN
@ -429,8 +429,8 @@ MODULE moduleMeshCylRead
SUBROUTINE connectedQuadEdge(elemA, elemB) SUBROUTINE connectedQuadEdge(elemA, elemB)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylQuad), INTENT(inout), TARGET:: elemA CLASS(meshVol2DCylQuad), INTENT(inout), TARGET:: elemA
CLASS(meshEdgeCyl), INTENT(inout), TARGET:: elemB CLASS(meshEdge2DCyl), INTENT(inout), TARGET:: elemB
!Check direction 1 !Check direction 1
IF (.NOT. ASSOCIATED(elemA%e1)) THEN IF (.NOT. ASSOCIATED(elemA%e1)) THEN
@ -501,8 +501,8 @@ MODULE moduleMeshCylRead
SUBROUTINE connectedTriaEdge(elemA, elemB) SUBROUTINE connectedTriaEdge(elemA, elemB)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVolCylTria), INTENT(inout), TARGET:: elemA CLASS(meshVol2DCylTria), INTENT(inout), TARGET:: elemA
CLASS(meshEdgeCyl), INTENT(inout), TARGET:: elemB CLASS(meshEdge2DCyl), INTENT(inout), TARGET:: elemB
!Check direction 1 !Check direction 1
IF (.NOT. ASSOCIATED(elemA%e1)) THEN IF (.NOT. ASSOCIATED(elemA%e1)) THEN
@ -564,7 +564,7 @@ MODULE moduleMeshCylRead
INTEGER, ALLOCATABLE:: n(:) INTEGER, ALLOCATABLE:: n(:)
SELECT TYPE(elem) SELECT TYPE(elem)
TYPE IS(meshVolCylQuad) TYPE IS(meshVol2DCylQuad)
nNodes = 4 nNodes = 4
ALLOCATE(localK(1:nNodes,1:nNodes)) ALLOCATE(localK(1:nNodes,1:nNodes))
localK = elem%elemK() localK = elem%elemK()
@ -572,7 +572,7 @@ MODULE moduleMeshCylRead
n = (/ elem%n1%n, elem%n2%n, & n = (/ elem%n1%n, elem%n2%n, &
elem%n3%n, elem%n4%n /) elem%n3%n, elem%n4%n /)
TYPE IS(meshVolCylTria) TYPE IS(meshVol2DCylTria)
nNodes = 3 nNodes = 3
ALLOCATE(localK(1:nNodes,1:nNodes)) ALLOCATE(localK(1:nNodes,1:nNodes))
localK = elem%elemK() localK = elem%elemK()
@ -596,4 +596,4 @@ MODULE moduleMeshCylRead
END SUBROUTINE constructGlobalK END SUBROUTINE constructGlobalK
END MODULE moduleMeshCylRead END MODULE moduleMesh2DCylRead

View file

@ -1,8 +1,11 @@
all: moduleMesh.o 2DCyl.o 1DRad.o 1DCart.o all: moduleMesh.o 2DCyl.o 2DCart.o 1DRad.o 1DCart.o
2DCyl.o: 2DCyl.o:
$(MAKE) -C 2DCyl all $(MAKE) -C 2DCyl all
2DCart.o:
$(MAKE) -C 2DCart all
1DCart.o: 1DCart.o:
$(MAKE) -C 1DCart all $(MAKE) -C 1DCart all

View file

@ -365,7 +365,6 @@ MODULE moduleInput
!Gets the basename of the folder !Gets the basename of the folder
CALL config%get(object // '.folder', baseName, found) CALL config%get(object // '.folder', baseName, found)
PRINT *, baseName
IF (found) THEN IF (found) THEN
folder = baseName folder = baseName
@ -654,7 +653,8 @@ MODULE moduleInput
!Read the geometry (mesh) for the case !Read the geometry (mesh) for the case
SUBROUTINE readGeometry(config) SUBROUTINE readGeometry(config)
USE moduleMesh USE moduleMesh
USE moduleMeshCylRead, ONLY: meshCylGeneric USE moduleMesh2DCylRead, ONLY: mesh2DCylGeneric
USE moduleMesh2DCartRead, ONLY: mesh2DCartGeneric
USE moduleMesh1DCartRead, ONLY: mesh1DCartGeneric USE moduleMesh1DCartRead, ONLY: mesh1DCartGeneric
USE moduleMesh1DRadRead, ONLY: mesh1DRadGeneric USE moduleMesh1DRadRead, ONLY: mesh1DRadGeneric
USE moduleErrors USE moduleErrors
@ -672,7 +672,11 @@ MODULE moduleInput
SELECT CASE(geometryType) SELECT CASE(geometryType)
CASE ("2DCyl") CASE ("2DCyl")
!Creates a 2D cylindrical mesh !Creates a 2D cylindrical mesh
ALLOCATE(meshCylGeneric:: mesh) ALLOCATE(mesh2DCylGeneric:: mesh)
CASE ("2DCart")
!Creates a 2D cylindrical mesh
ALLOCATE(mesh2DCartGeneric:: mesh)
CASE ("1DCart") CASE ("1DCart")
!Creates a 1D cartesian mesh !Creates a 1D cartesian mesh

View file

@ -67,15 +67,31 @@ MODULE moduleSolver
REAL(8):: tau, tauSp REAL(8):: tau, tauSp
SELECT CASE(pusherType) SELECT CASE(pusherType)
!2D Cylindrical
CASE('2DCylNeutral') CASE('2DCylNeutral')
self%pushParticle => pushCylNeutral self%pushParticle => push2DCylNeutral
CASE('2DCylCharged') CASE('2DCylCharged')
self%pushParticle => pushCylCharged self%pushParticle => push2DCylCharged
!2D Cartesian
CASE('2DCartNeutral')
self%pushParticle => push2DCartNeutral
CASE('2DCartCharged')
self%pushParticle => push2DCartCharged
!1D Cartesian
CASE('1DCartNeutral')
self%pushParticle => push1DCartNeutral
CASE('1DCartCharged') CASE('1DCartCharged')
self%pushParticle => push1DCartCharged self%pushParticle => push1DCartCharged
!1D Radial
CASE('1DRadNeutral')
self%pushParticle => push1DRadNeutral
CASE('1DRadCharged') CASE('1DRadCharged')
self%pushParticle => push1DRadCharged self%pushParticle => push1DRadCharged
@ -147,7 +163,7 @@ MODULE moduleSolver
END SUBROUTINE doPushes END SUBROUTINE doPushes
!Push one particle. Boris pusher for 2D Cyl Neutral particle !Push one particle. Boris pusher for 2D Cyl Neutral particle
PURE SUBROUTINE pushCylNeutral(part, tauIn) PURE SUBROUTINE push2DCylNeutral(part, tauIn)
USE moduleSpecies USE moduleSpecies
IMPLICIT NONE IMPLICIT NONE
@ -181,10 +197,10 @@ MODULE moduleSolver
!Copy temporal particle to particle !Copy temporal particle to particle
part=part_temp part=part_temp
END SUBROUTINE pushCylNeutral END SUBROUTINE push2DCylNeutral
!Push one particle. Boris pusher for 2D Cyl Charged particle !Push one particle. Boris pusher for 2D Cyl Charged particle
PURE SUBROUTINE pushCylCharged(part, tauIn) PURE SUBROUTINE push2DCylCharged(part, tauIn)
USE moduleSpecies USE moduleSpecies
USE moduleEM USE moduleEM
IMPLICIT NONE IMPLICIT NONE
@ -222,7 +238,83 @@ MODULE moduleSolver
!Copy temporal particle to particle !Copy temporal particle to particle
part=part_temp part=part_temp
END SUBROUTINE pushCylCharged END SUBROUTINE push2DCylCharged
!Push neutral particles in 2D cartesian coordinates
PURE SUBROUTINE push2DCartNeutral(part, tauIn)
USE moduleSPecies
IMPLICIT NONE
TYPE(particle), INTENT(inout):: part
REAL(8), INTENT(in):: tauIn
TYPE(particle):: part_temp
part_temp = part
!x
part_temp%v(1) = part%v(1)
part_temp%r(1) = part%r(1) + part_temp%v(1)*tauIn
!y
part_temp%v(2) = part%v(2)
part_temp%r(2) = part%r(2) + part_temp%v(2)*tauIn
part_temp%n_in = .FALSE.
part = part_temp
END SUBROUTINE push2DCartNeutral
!Push charged particles in 2D cartesian coordinates
PURE SUBROUTINE push2DCartCharged(part, tauIn)
USE moduleSPecies
USE moduleEM
IMPLICIT NONE
TYPE(particle), INTENT(inout):: part
REAL(8), INTENT(in):: tauIn
TYPE(particle):: part_temp
REAL(8):: qmEFt(1:3)
part_temp = part
!Get the electric field at particle position
qmEFt = part_temp%qm*gatherElecField(part_temp)*tauIn
!x
part_temp%v(1) = part%v(1) + qmEFt(1)
part_temp%r(1) = part%r(1) + part_temp%v(1)*tauIn
!y
part_temp%v(2) = part%v(2) + qmEFt(2)
part_temp%r(2) = part%r(2) + part_temp%v(2)*tauIn
part_temp%n_in = .FALSE.
part = part_temp
END SUBROUTINE push2DCartCharged
!Push neutral particles in 1D cartesian coordinates
PURE SUBROUTINE push1DCartNeutral(part, tauIn)
USE moduleSPecies
USE moduleEM
IMPLICIT NONE
TYPE(particle), INTENT(inout):: part
REAL(8), INTENT(in):: tauIn
TYPE(particle):: part_temp
part_temp = part
!x
part_temp%v(1) = part%v(1)
part_temp%r(1) = part%r(1) + part_temp%v(1)*tauIn
part_temp%n_in = .FALSE.
part = part_temp
END SUBROUTINE push1DCartNeutral
!Push charged particles in 1D cartesian coordinates !Push charged particles in 1D cartesian coordinates
PURE SUBROUTINE push1DCartCharged(part, tauIn) PURE SUBROUTINE push1DCartCharged(part, tauIn)
@ -249,6 +341,41 @@ MODULE moduleSolver
END SUBROUTINE push1DCartCharged END SUBROUTINE push1DCartCharged
!Push one particle. Boris pusher for 1D Radial Neutral particle
PURE SUBROUTINE push1DRadNeutral(part, tauIn)
USE moduleSpecies
USE moduleEM
IMPLICIT NONE
TYPE(particle), INTENT(inout):: part
REAL(8), INTENT(in):: tauIn
REAL(8):: v_p_oh_star(1:2)
TYPE(particle):: part_temp
REAL(8):: x_new, y_new, r, sin_alpha, cos_alpha
part_temp = part
!r,theta
v_p_oh_star(1) = part%v(1)
x_new = part%r(1) + v_p_oh_star(1)*tauIn
v_p_oh_star(2) = part%v(2)
y_new = v_p_oh_star(2)*tauIn
r = DSQRT(x_new**2+y_new**2)
part_temp%r(1) = r
IF (r > 0.D0) THEN
sin_alpha = y_new/r
cos_alpha = x_new/r
ELSE
sin_alpha = 0.D0
cos_alpha = 1.D0
END IF
part_temp%v(1) = cos_alpha*v_p_oh_star(1)+sin_alpha*v_p_oh_star(2)
part_temp%v(2) = -sin_alpha*v_p_oh_star(1)+cos_alpha*v_p_oh_star(2)
part_temp%n_in = .FALSE. !Assume particle is outside until cell is found
!Copy temporal particle to particle
part=part_temp
END SUBROUTINE push1DRadNeutral
!Push one particle. Boris pusher for 1D Radial Charged particle !Push one particle. Boris pusher for 1D Radial Charged particle
PURE SUBROUTINE push1DRadCharged(part, tauIn) PURE SUBROUTINE push1DRadCharged(part, tauIn)
USE moduleSpecies USE moduleSpecies
@ -263,7 +390,6 @@ MODULE moduleSolver
REAL(8):: qmEFt(1:3)!charge*tauIn*EF/mass REAL(8):: qmEFt(1:3)!charge*tauIn*EF/mass
part_temp = part part_temp = part
!Time step for the species
!Get electric field at particle position !Get electric field at particle position
qmEFt = part_temp%qm*gatherElecField(part_temp)*tauMin qmEFt = part_temp%qm*gatherElecField(part_temp)*tauMin
!r,theta !r,theta