1080 lines
32 KiB
Fortran
1080 lines
32 KiB
Fortran
!moduleMesh: General module for Finite Element mesh
|
|
MODULE moduleMesh
|
|
USE moduleList
|
|
USE moduleOutput
|
|
USE moduleCollisions
|
|
use moduleSpecies, only: nSpecies
|
|
|
|
! MESH ELEMENTS
|
|
!Generic mesh element
|
|
TYPE, PUBLIC, ABSTRACT:: meshElement
|
|
!Index
|
|
INTEGER:: n = 0
|
|
|
|
END TYPE meshElement
|
|
|
|
!Generic Node element
|
|
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshElement):: meshNode
|
|
!Node volume
|
|
REAL(8):: v = 0.D0
|
|
!Output values
|
|
TYPE(outputNode), ALLOCATABLE:: output(:)
|
|
TYPE(emNode):: emData
|
|
!Lock indicator for scattering
|
|
INTEGER(KIND=OMP_LOCK_KIND):: lock
|
|
CONTAINS
|
|
!DEFERED PROCEDURES
|
|
PROCEDURE(initNode_interface), DEFERRED, PASS:: init
|
|
PROCEDURE(getCoord_interface), DEFERRED, PASS:: getCoordinates
|
|
!GENERIC PROCEDURES
|
|
PROCEDURE, PASS:: resetOutput
|
|
|
|
END TYPE meshNode
|
|
|
|
interface
|
|
pure module subroutine resetOutput(self)
|
|
class(meshNode), intent(inout):: self
|
|
|
|
end subroutine resetOutput
|
|
|
|
end interface
|
|
|
|
ABSTRACT INTERFACE
|
|
!Interface of init a node (3D generic coordinates)
|
|
SUBROUTINE initNode_interface(self, n, r)
|
|
IMPORT:: meshNode
|
|
CLASS(meshNode), INTENT(out):: self
|
|
INTEGER, INTENT(in):: n
|
|
REAL(8), INTENT(in):: r(1:3)
|
|
|
|
END SUBROUTINE initNode_interface
|
|
|
|
!Interface to get coordinates from node
|
|
PURE FUNCTION getCoord_interface(self) RESULT(r)
|
|
IMPORT:: meshNode
|
|
CLASS(meshNode), INTENT(in):: self
|
|
REAL(8):: r(1:3)
|
|
|
|
END FUNCTION getCoord_interface
|
|
|
|
END INTERFACE
|
|
|
|
!Containers for nodes in the mesh
|
|
TYPE:: meshNodeCont
|
|
CLASS(meshNode), ALLOCATABLE:: obj
|
|
|
|
END TYPE meshNodeCont
|
|
|
|
! Array of pointers to nodes.
|
|
TYPE:: meshNodePointer
|
|
CLASS(meshNode), POINTER:: obj
|
|
contains
|
|
procedure, pass:: meshNodePointer_equal_type_type
|
|
procedure, pass:: meshNodePointer_equal_type_int
|
|
generic:: operator(==) => meshNodePointer_equal_type_type, meshNodePointer_equal_type_int
|
|
|
|
END TYPE meshNodePointer
|
|
|
|
interface
|
|
module subroutine meshNodePointer_add(self, node)
|
|
class(meshNodePointer), allocatable, intent(inout):: self(:)
|
|
integer, intent(in):: node
|
|
|
|
end subroutine meshNodePointer_add
|
|
|
|
module function meshNodePointer_equal_type_type(self, other) result(isEqual)
|
|
class(meshNodePointer), intent(in):: self, other
|
|
logical:: isEqual
|
|
|
|
end function meshNodePointer_equal_type_type
|
|
|
|
module function meshNodePointer_equal_type_int(self, other) result(isEqual)
|
|
class(meshNodePointer), intent(in):: self
|
|
integer, intent(in):: other
|
|
logical:: isEqual
|
|
|
|
end function meshNodePointer_equal_type_int
|
|
|
|
end interface
|
|
|
|
!Parent of Edge element
|
|
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshElement):: meshEdge
|
|
!Nomber of nodes in the edge
|
|
INTEGER:: nNodes
|
|
!Connectivity to cells
|
|
CLASS(meshCell), POINTER:: e1 => NULL(), e2 => NULL()
|
|
!Connectivity to cells in meshColl
|
|
CLASS(meshCell), POINTER:: eColl => NULL()
|
|
!Normal vector
|
|
REAL(8):: normal(1:3)
|
|
! Surface of edge
|
|
REAL(8):: surface = 0.D0
|
|
!Pointer to boundary per species
|
|
TYPE(boundaryParticlePointer), allocatable:: boundariesParticle(:)
|
|
!Physical surface for the edge
|
|
CONTAINS
|
|
!DEFERED PROCEDURES
|
|
PROCEDURE(initEdge_interface), DEFERRED, PASS:: init
|
|
PROCEDURE(getNodesEdge_interface), DEFERRED, PASS:: getNodes
|
|
PROCEDURE(intersectionEdge_interface), DEFERRED, PASS:: intersection
|
|
PROCEDURE(randPosEdge_interface), DEFERRED, PASS:: randPos
|
|
procedure(centerEdge_interface), deferred, pass:: center
|
|
procedure(centerXiEdge_interface), deferred, nopass:: centerXi
|
|
PROCEDURE(fPsi_interface), DEFERRED, NOPASS:: fPsi
|
|
!Gather value and spatial derivative on the nodes at position Xi
|
|
PROCEDURE, PASS, PRIVATE:: gatherF_edge_scalar
|
|
GENERIC:: gatherF => gatherF_edge_scalar
|
|
|
|
END TYPE meshEdge
|
|
|
|
interface
|
|
pure module function gatherF_edge_scalar(self, Xi, nNodes, valNodes) result(f)
|
|
class(meshEdge), intent(in):: self
|
|
real(8), intent(in):: Xi(1:3)
|
|
integer, intent(in):: nNodes
|
|
real(8), intent(in):: valNodes(1:nNodes)
|
|
real(8):: f
|
|
|
|
end function gatherF_edge_scalar
|
|
|
|
end interface
|
|
|
|
ABSTRACT INTERFACE
|
|
!Inits the edge parameters
|
|
subroutine initEdge_interface(self, n, p, ps)
|
|
use moduleSpecies, only:nSpecies
|
|
import:: meshEdge
|
|
|
|
class(meshEdge), intent(out):: self
|
|
integer, intent(in):: n
|
|
integer, intent(in):: p(:)
|
|
integer, intent(in):: ps
|
|
|
|
end subroutine initEdge_interface
|
|
|
|
!Get nodes index from node
|
|
PURE FUNCTION getNodesEdge_interface(self, nNodes) RESULT(n)
|
|
IMPORT:: meshEdge
|
|
CLASS(meshEdge), INTENT(in):: self
|
|
INTEGER, INTENT(in):: nNodes
|
|
INTEGER:: n(1:nNodes)
|
|
|
|
END FUNCTION getNodesEdge_interface
|
|
|
|
!Returns the intersecction between an edge and a line defined by point r0
|
|
PURE FUNCTION intersectionEdge_interface(self, r0) RESULT(r)
|
|
IMPORT:: meshEdge
|
|
CLASS(meshEdge), INTENT(in):: self
|
|
REAL(8), INTENT(in), DIMENSION(1:3):: r0
|
|
REAL(8):: r(1:3)
|
|
|
|
END FUNCTION intersectionEdge_interface
|
|
|
|
!Returns a random position in the edge
|
|
FUNCTION randPosEdge_interface(self) RESULT(r)
|
|
IMPORT:: meshEdge
|
|
CLASS(meshEdge), INTENT(in):: self
|
|
REAL(8):: r(1:3)
|
|
|
|
END FUNCTION randPosEdge_interface
|
|
|
|
! Returns the center point of an edge
|
|
FUNCTION centerEdge_interface(self) RESULT(r)
|
|
IMPORT:: meshEdge
|
|
CLASS(meshEdge), INTENT(in):: self
|
|
REAL(8):: r(1:3)
|
|
|
|
END FUNCTION centerEdge_interface
|
|
|
|
! Returns the center point of an edge in natural coordinates
|
|
FUNCTION centerXiEdge_interface() RESULT(Xi)
|
|
REAL(8):: Xi(1:3)
|
|
|
|
END FUNCTION centerXiEdge_interface
|
|
|
|
END INTERFACE
|
|
|
|
!Containers for edges in the mesh
|
|
TYPE:: meshEdgeCont
|
|
CLASS(meshEdge), ALLOCATABLE:: obj
|
|
|
|
END TYPE meshEdgeCont
|
|
|
|
! Array of pointers to edges.
|
|
type:: meshEdgePointer
|
|
class(meshEdge), pointer:: obj
|
|
contains
|
|
procedure, pass:: meshEdgePointer_equal_type_type
|
|
procedure, pass:: meshEdgePointer_equal_type_int
|
|
generic:: operator(==) => meshEdgePointer_equal_type_type, meshEdgePointer_equal_type_int
|
|
|
|
end type meshEdgePointer
|
|
|
|
interface
|
|
module subroutine meshEdgePointer_add(self, edge)
|
|
class(meshEdgePointer), allocatable, intent(inout):: self(:)
|
|
integer, intent(in):: edge
|
|
|
|
end subroutine meshEdgePointer_add
|
|
|
|
module function meshEdgePointer_equal_type_type(self, other) result(isEqual)
|
|
class(meshEdgePointer), intent(in):: self, other
|
|
logical:: isEqual
|
|
|
|
end function meshEdgePointer_equal_type_type
|
|
|
|
module function meshEdgePointer_equal_type_int(self, other) result(isEqual)
|
|
class(meshEdgePointer), intent(in):: self
|
|
integer, intent(in):: other
|
|
logical:: isEqual
|
|
|
|
end function meshEdgePointer_equal_type_int
|
|
|
|
end interface
|
|
|
|
!Parent of cell element
|
|
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshElement):: meshCell
|
|
!Number of nodes in the cell
|
|
INTEGER:: nNodes
|
|
!Maximum collision rate
|
|
REAL(8), ALLOCATABLE:: sigmaVrelMax(:)
|
|
!Arrays for counting number of collisions
|
|
TYPE(tallyCollisions), ALLOCATABLE:: tallyColl(:)
|
|
!Volume
|
|
REAL(8):: volume = 0.D0
|
|
!List of particles inside the volume
|
|
TYPE(listNode), ALLOCATABLE:: listPart_in(:)
|
|
!Lock indicator for listPart_in
|
|
INTEGER(KIND=OMP_LOCK_KIND):: lock
|
|
!Total weight of particles inside cell
|
|
REAL(8), ALLOCATABLE:: totalWeight(:)
|
|
CONTAINS
|
|
!DEFERRED PROCEDURES
|
|
!Init the cell
|
|
PROCEDURE(initCell_interface), DEFERRED, PASS:: init
|
|
!Get the index of the nodes
|
|
PROCEDURE(getNodesCell_interface), DEFERRED, PASS:: getNodes
|
|
!Calculate random position on the cell
|
|
PROCEDURE(randPosCell_interface), DEFERRED, PASS:: randPos
|
|
!Obtain functions and values of cell natural functions
|
|
PROCEDURE(fPsi_interface), DEFERRED, NOPASS:: fPsi
|
|
PROCEDURE(dPsi_interface), DEFERRED, NOPASS:: dPsi
|
|
PROCEDURE(partialDer_interface), DEFERRED, PASS:: partialDer
|
|
PROCEDURE(detJac_interface), DEFERRED, NOPASS:: detJac
|
|
PROCEDURE(invJac_interface), DEFERRED, NOPASS:: invJac
|
|
!Procedures to get specific values in the node
|
|
PROCEDURE(gatherCellArray_interface), DEFERRED, PASS:: gatherElectricField
|
|
PROCEDURE(gatherCellArray_interface), DEFERRED, PASS:: gatherMagneticField
|
|
!Compute K and F to solve PDE on the mesh
|
|
PROCEDURE(elemK_interface), DEFERRED, PASS:: elemK
|
|
PROCEDURE(elemF_interface), DEFERRED, PASS:: elemF
|
|
!Check if particle is inside the cell
|
|
PROCEDURE(inside_interface), DEFERRED, NOPASS:: inside
|
|
!Convert physical coordinates (r) into logical coordinates (Xi)
|
|
PROCEDURE(phy2log_interface), DEFERRED, PASS:: phy2log
|
|
!Returns the neighbour element based on particle position outside the cell
|
|
PROCEDURE(neighbourElement_interface), DEFERRED, PASS:: neighbourElement
|
|
!Scatter properties of particles on cell nodes
|
|
PROCEDURE, PASS:: scatter
|
|
!Subroutine to find in which cell a particle is located
|
|
PROCEDURE, PASS:: findCell
|
|
!Gather value and spatial derivative on the nodes at position Xi
|
|
procedure, pass, private:: gatherF_cell_scalar
|
|
procedure, pass, private:: gatherF_cell_array
|
|
procedure, pass, private:: gatherDF_cell_scalar
|
|
generic:: gatherF => gatherF_cell_scalar, gatherF_cell_array
|
|
generic:: gatherDF => gatherDF_cell_scalar
|
|
|
|
END TYPE meshCell
|
|
|
|
interface
|
|
recursive module subroutine findCell(self, part, oldCell)
|
|
use moduleSpecies, only: particle
|
|
|
|
class(meshCell), intent(inout):: self
|
|
class(particle), intent(inout), target:: part
|
|
class(meshCell), optional, intent(in):: oldCell
|
|
|
|
end subroutine findCell
|
|
|
|
module subroutine scatter(self, nNodes, part)
|
|
use moduleSpecies, only: particle
|
|
|
|
class(meshCell), intent(inout):: self
|
|
integer, intent(in):: nNodes
|
|
class(particle), intent(in):: part
|
|
|
|
end subroutine scatter
|
|
|
|
pure module function gatherF_cell_scalar(self, Xi, nNodes, valNodes) result(f)
|
|
class(meshCell), intent(in):: self
|
|
real(8), intent(in):: Xi(1:3)
|
|
integer, intent(in):: nNodes
|
|
real(8), intent(in):: valNodes(1:nNodes)
|
|
real(8):: f
|
|
|
|
end function gatherF_cell_scalar
|
|
|
|
pure module function gatherF_cell_array(self, Xi, nNodes, valNodes) result(f)
|
|
class(meshCell), intent(in):: self
|
|
real(8), intent(in):: Xi(1:3)
|
|
integer, intent(in):: nNodes
|
|
real(8), intent(in):: valNodes(1:nNodes, 1:3)
|
|
real(8):: f(1:3)
|
|
|
|
end function gatherF_cell_array
|
|
|
|
pure module function gatherDF_cell_scalar(self, Xi, nNodes, valNodes) RESULT(df)
|
|
|
|
class(meshCell), intent(in):: self
|
|
real(8), intent(in):: Xi(1:3)
|
|
integer, intent(in):: nNodes
|
|
real(8), intent(in):: valNodes(1:nNodes)
|
|
real(8):: df(1:3)
|
|
|
|
end function gatherDF_cell_scalar
|
|
|
|
end interface
|
|
|
|
ABSTRACT INTERFACE
|
|
SUBROUTINE initCell_interface(self, n, p, nodes)
|
|
IMPORT:: meshCell, meshNodeCont
|
|
CLASS(meshCell), INTENT(out):: self
|
|
INTEGER, INTENT(in):: n
|
|
INTEGER, INTENT(in):: p(:)
|
|
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
|
|
|
|
END SUBROUTINE initCell_interface
|
|
|
|
PURE FUNCTION getNodesCell_interface(self, nNodes) RESULT(n)
|
|
IMPORT:: meshCell
|
|
CLASS(meshCell), INTENT(in):: self
|
|
INTEGER, INTENT(in):: nNodes
|
|
INTEGER:: n(1:nNodes)
|
|
|
|
END FUNCTION getNodesCell_interface
|
|
|
|
FUNCTION randPosCell_interface(self) RESULT(r)
|
|
IMPORT:: meshCell
|
|
CLASS(meshCell), INTENT(in):: self
|
|
REAL(8):: r(1:3)
|
|
|
|
END FUNCTION randPosCell_interface
|
|
|
|
PURE FUNCTION fPsi_interface(Xi, nNodes) RESULT(fPsi)
|
|
REAL(8), INTENT(in):: Xi(1:3)
|
|
INTEGER, INTENT(in):: nNodes
|
|
REAL(8):: fPsi(1:nNodes)
|
|
|
|
END FUNCTION fPsi_interface
|
|
|
|
PURE FUNCTION dPsi_interface(Xi, nNodes) RESULT(dPsi)
|
|
REAL(8), INTENT(in):: Xi(1:3)
|
|
INTEGER, INTENT(in):: nNodes
|
|
REAL(8):: dPsi(1:3, 1:nNodes)
|
|
|
|
END FUNCTION dPsi_interface
|
|
|
|
PURE FUNCTION partialDer_interface(self, nNodes, dPsi) RESULT(pDer)
|
|
IMPORT:: meshCell
|
|
CLASS(meshCell), INTENT(in):: self
|
|
INTEGER, INTENT(in):: nNodes
|
|
REAL(8), INTENT(in):: dPsi(1:3, 1:nNodes)
|
|
REAL(8):: pDer(1:3, 1:3)
|
|
|
|
END FUNCTION partialDer_interface
|
|
|
|
PURE FUNCTION detJac_interface(pDer) RESULT(dJ)
|
|
REAL(8), INTENT(in):: pDer(1:3,1:3)
|
|
REAL(8):: dJ
|
|
|
|
END FUNCTION detJac_interface
|
|
|
|
PURE FUNCTION invJac_interface(pDer) RESULT(invJ)
|
|
REAL(8), INTENT(in):: pDer(1:3,1:3)
|
|
REAL(8):: invJ(1:3,1:3)
|
|
|
|
END FUNCTION invJac_interface
|
|
|
|
PURE FUNCTION gatherCellArray_interface(self, Xi) RESULT(array)
|
|
IMPORT:: meshCell
|
|
CLASS(meshCell), INTENT(in):: self
|
|
REAL(8), INTENT(in):: Xi(1:3)
|
|
REAL(8):: array(1:3)
|
|
|
|
END FUNCTION gatherCellArray_interface
|
|
|
|
PURE FUNCTION elemK_interface(self, nNodes) RESULT(localK)
|
|
IMPORT:: meshCell
|
|
CLASS(meshCell), INTENT(in):: self
|
|
INTEGER, INTENT(in):: nNodes
|
|
REAL(8):: localK(1:nNodes,1:nNodes)
|
|
|
|
END FUNCTION elemK_interface
|
|
|
|
PURE FUNCTION elemF_interface(self, nNodes, source) RESULT(localF)
|
|
IMPORT:: meshCell
|
|
CLASS(meshCell), INTENT(in):: self
|
|
INTEGER, INTENT(in):: nNodes
|
|
REAL(8), INTENT(in):: source(1:nNodes)
|
|
REAL(8):: localF(1:nNodes)
|
|
|
|
END FUNCTION elemF_interface
|
|
|
|
PURE FUNCTION inside_interface(Xi) RESULT(ins)
|
|
IMPORT:: meshCell
|
|
REAL(8), INTENT(in):: Xi(1:3)
|
|
LOGICAL:: ins
|
|
|
|
END FUNCTION inside_interface
|
|
|
|
PURE FUNCTION phy2log_interface(self,r) RESULT(Xi)
|
|
IMPORT:: meshCell
|
|
CLASS(meshCell), INTENT(in):: self
|
|
REAL(8), INTENT(in):: r(1:3)
|
|
REAL(8):: Xi(1:3)
|
|
|
|
END FUNCTION phy2log_interface
|
|
|
|
SUBROUTINE neighbourElement_interface(self, Xi, neighbourElement)
|
|
IMPORT:: meshCell, meshElement
|
|
CLASS(meshCell), INTENT(in):: self
|
|
REAL(8), INTENT(in):: Xi(1:3)
|
|
CLASS(meshElement), POINTER, INTENT(out):: neighbourElement
|
|
|
|
END SUBROUTINE neighbourElement_interface
|
|
|
|
END INTERFACE
|
|
|
|
!Containers for cells in the mesh
|
|
TYPE:: meshCellCont
|
|
CLASS(meshCell), ALLOCATABLE:: obj
|
|
|
|
END TYPE meshCellCont
|
|
|
|
!Generic mesh type
|
|
TYPE, ABSTRACT:: meshGeneric
|
|
!Dimension of the mesh
|
|
INTEGER:: dimen
|
|
!Geometry of the mesh
|
|
CHARACTER(:), ALLOCATABLE:: geometry
|
|
!Number of elements
|
|
INTEGER:: numNodes, numCells
|
|
!Array of nodes
|
|
TYPE(meshNodeCont), ALLOCATABLE:: nodes(:)
|
|
!Array of cell elements
|
|
TYPE(meshCellCont), ALLOCATABLE:: cells(:)
|
|
!PROCEDURES SPECIFIC OF FILE TYPE
|
|
PROCEDURE(readMesh_interface), POINTER, PASS:: readMesh => NULL()
|
|
PROCEDURE(readInitial_interface), POINTER, NOPASS:: readInitial => NULL()
|
|
PROCEDURE(connectMesh_interface), POINTER, PASS:: connectMesh => NULL()
|
|
PROCEDURE(printColl_interface), POINTER, PASS:: printColl => NULL()
|
|
CONTAINS
|
|
!GENERIC PROCEDURES
|
|
PROCEDURE, PASS:: doCollisions
|
|
|
|
END TYPE meshGeneric
|
|
|
|
interface
|
|
module subroutine doCollisions(self)
|
|
class(meshGeneric), intent(inout), target:: self
|
|
|
|
end subroutine doCollisions
|
|
|
|
module function findCellBrute(self, r) result(nVol)
|
|
class(meshGeneric), intent(in):: self
|
|
real(8), dimension(1:3), intent(in):: r
|
|
integer:: nVol
|
|
|
|
end function findCellBrute
|
|
|
|
end interface
|
|
|
|
ABSTRACT INTERFACE
|
|
!Reads the mesh from a file
|
|
SUBROUTINE readMesh_interface(self, filename)
|
|
IMPORT meshGeneric
|
|
CLASS(meshGeneric), INTENT(inout):: self
|
|
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
|
|
|
|
END SUBROUTINE readMesh_interface
|
|
|
|
SUBROUTINE readInitial_interface(filename, density, velocity, temperature)
|
|
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
|
|
REAL(8), ALLOCATABLE, INTENT(out), DIMENSION(:):: density
|
|
REAL(8), ALLOCATABLE, INTENT(out), DIMENSION(:,:):: velocity
|
|
REAL(8), ALLOCATABLE, INTENT(out), DIMENSION(:):: temperature
|
|
|
|
END SUBROUTINE readInitial_interface
|
|
|
|
!Connects cell and edges to the mesh
|
|
SUBROUTINE connectMesh_interface(self)
|
|
IMPORT meshGeneric
|
|
CLASS(meshGeneric), INTENT(inout):: self
|
|
|
|
END SUBROUTINE connectMesh_interface
|
|
|
|
!Prints number of collisions in each cell
|
|
SUBROUTINE printColl_interface(self)
|
|
IMPORT meshGeneric
|
|
CLASS(meshGeneric), INTENT(in):: self
|
|
|
|
END SUBROUTINE printColl_interface
|
|
|
|
END INTERFACE
|
|
|
|
!Particle mesh
|
|
TYPE, EXTENDS(meshGeneric), PUBLIC:: meshParticles
|
|
INTEGER:: numEdges
|
|
!Array of boundary elements
|
|
TYPE(meshEdgeCont), ALLOCATABLE:: edges(:)
|
|
!Global stiffness matrix
|
|
REAL(8), ALLOCATABLE, DIMENSION(:,:):: K
|
|
!Permutation matrix for P L U factorization
|
|
INTEGER, ALLOCATABLE, DIMENSION(:,:):: IPIV
|
|
!PROCEDURES SPECIFIC OF FILE TYPE
|
|
PROCEDURE(printOutput_interface), POINTER, PASS:: printOutput => NULL()
|
|
PROCEDURE(printEM_interface), POINTER, PASS:: printEM => NULL()
|
|
PROCEDURE(printAverage_interface), POINTER, PASS:: printAverage => NULL()
|
|
CONTAINS
|
|
!GENERIC PROCEDURES
|
|
PROCEDURE, PASS:: constructGlobalK
|
|
PROCEDURE, PASS:: doCoulomb
|
|
|
|
END TYPE meshParticles
|
|
|
|
interface
|
|
module subroutine constructGlobalK(self)
|
|
class(meshParticles), intent(inout):: self
|
|
|
|
end subroutine constructGlobalK
|
|
|
|
module subroutine doCoulomb(self)
|
|
class(meshParticles), intent(in), target:: self
|
|
|
|
end subroutine doCoulomb
|
|
|
|
end interface
|
|
|
|
ABSTRACT INTERFACE
|
|
!Prints Species data
|
|
SUBROUTINE printOutput_interface(self)
|
|
IMPORT meshParticles
|
|
CLASS(meshParticles), INTENT(in):: self
|
|
|
|
END SUBROUTINE printOutput_interface
|
|
|
|
!Prints EM info
|
|
SUBROUTINE printEM_interface(self)
|
|
IMPORT meshParticles
|
|
CLASS(meshParticles), INTENT(in):: self
|
|
|
|
END SUBROUTINE printEM_interface
|
|
|
|
!Perform Coulomb Scattering
|
|
!Prints average values
|
|
SUBROUTINE printAverage_interface(self)
|
|
IMPORT meshParticles
|
|
CLASS(meshParticles), INTENT(in):: self
|
|
|
|
END SUBROUTINE printAverage_interface
|
|
|
|
END INTERFACE
|
|
|
|
TYPE(meshParticles), TARGET:: mesh
|
|
|
|
!Collision (MCC) mesh
|
|
TYPE, EXTENDS(meshGeneric):: meshCollisions
|
|
|
|
END TYPE meshCollisions
|
|
|
|
TYPE(meshCollisions), TARGET:: meshColl
|
|
|
|
ABSTRACT INTERFACE
|
|
SUBROUTINE readMeshColl_interface(self, filename)
|
|
IMPORT meshCollisions
|
|
CLASS(meshCollisions), INTENT(inout):: self
|
|
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
|
|
|
|
END SUBROUTINE readMeshColl_interface
|
|
|
|
SUBROUTINE connectMeshColl_interface(self)
|
|
IMPORT meshParticles
|
|
|
|
CLASS(meshParticles), INTENT(inout):: self
|
|
|
|
END SUBROUTINE connectMeshColl_interface
|
|
|
|
END INTERFACE
|
|
|
|
!Pointer to mesh used for MC collisions
|
|
CLASS(meshGeneric), POINTER:: meshForMCC => NULL()
|
|
|
|
!Procedure to find a cell for a particle in meshColl
|
|
PROCEDURE(findCellColl_interface), POINTER:: findCellColl => NULL()
|
|
|
|
interface
|
|
module subroutine findCellCollMesh(part)
|
|
use moduleSpecies
|
|
implicit none
|
|
|
|
type(particle), intent(inout):: part
|
|
|
|
end subroutine findCellCollMesh
|
|
|
|
module subroutine findCellSameMesh(part)
|
|
use moduleSpecies
|
|
|
|
type(particle), intent(inout):: part
|
|
|
|
end subroutine findCellSameMesh
|
|
end interface
|
|
|
|
ABSTRACT INTERFACE
|
|
SUBROUTINE findCellColl_interface(part)
|
|
USE moduleSpecies
|
|
|
|
TYPE(particle), INTENT(inout):: part
|
|
|
|
END SUBROUTINE findCellColl_interface
|
|
|
|
END INTERFACE
|
|
|
|
!Logical to indicate if an specific mesh for MC Collisions is used
|
|
LOGICAL:: doubleMesh = .false.
|
|
!Logical to indicate if MCC collisions are performed
|
|
LOGICAL:: doMCCollisions = .FALSE.
|
|
!Logical to indicate if Coulomb scattering is performed
|
|
LOGICAL:: doCoulombScattering = .FALSE.
|
|
!Logica to indicate if particles have to be listed in list inside the cells
|
|
LOGICAL:: listInCells = .FALSE.
|
|
!Complete path for the two meshes
|
|
CHARACTER(:), ALLOCATABLE:: pathMeshColl, pathMeshParticle
|
|
|
|
! BOUNDARY PARTICLE DEFINITIONS
|
|
!Generic type for boundaries
|
|
type, abstract, public:: boundaryParticleGeneric
|
|
integer:: n
|
|
character(:), allocatable:: name
|
|
procedure(updateParticle_interface), pointer, pass:: update => null()
|
|
procedure(printParticle_interface), pointer, pass:: print => null()
|
|
contains
|
|
procedure(applyParticle_interface), deferred, pass:: apply
|
|
|
|
end type boundaryParticleGeneric
|
|
|
|
interface
|
|
! Init interfaces
|
|
! wallTemeprature
|
|
module subroutine wallTemperature_init(boundary, T, c)
|
|
CLASS(boundaryParticleGeneric), ALLOCATABLE, INTENT(inout):: boundary
|
|
REAL(8), INTENT(in):: T, c !Wall temperature and specific heat
|
|
|
|
end subroutine wallTemperature_init
|
|
|
|
module subroutine ionization_init(boundary, mImpact, m0, n0, v0, T0, ion, effTime, crossSection, eThreshold, electronSecondary)
|
|
class(boundaryParticleGeneric), allocatable, intent(inout):: boundary
|
|
real(8), intent(in):: mImpact
|
|
real(8), intent(in):: m0, n0, v0(1:3), T0 !Neutral properties
|
|
integer, intent(in):: ion
|
|
real(8), intent(in):: effTime
|
|
character(:), allocatable, intent(in):: crossSection
|
|
real(8), intent(in):: eThreshold
|
|
integer, optional, intent(in):: electronSecondary
|
|
|
|
end subroutine ionization_init
|
|
|
|
! quasiNeutrality
|
|
module subroutine quasiNeutrality_init(boundary, s_incident)
|
|
class(boundaryParticleGeneric), allocatable, intent(inout):: boundary
|
|
integer, intent(in):: s_incident
|
|
|
|
end subroutine quasiNeutrality_init
|
|
|
|
! outflowAdaptive
|
|
module subroutine outflowAdaptive_init(boundary, s_incident)
|
|
class(boundaryParticleGeneric), allocatable, intent(inout):: boundary
|
|
integer, intent(in):: s_incident
|
|
|
|
end subroutine outflowAdaptive_init
|
|
|
|
! Get the index of the species from its name
|
|
module function boundaryParticleName_to_Index(boundaryName) result(bp)
|
|
character(:), allocatable:: boundaryName
|
|
integer:: bp
|
|
|
|
end function boundaryParticleName_to_Index
|
|
|
|
end interface
|
|
|
|
abstract interface
|
|
! Apply the effects of the boundary to the particle
|
|
subroutine applyParticle_interface(self, edge, part)
|
|
use moduleSpecies
|
|
import boundaryParticleGeneric, meshEdge
|
|
|
|
class(boundaryParticleGeneric), intent(inout):: self
|
|
class(meshEdge), intent(inout):: edge
|
|
class(particle), intent(inout):: part
|
|
|
|
end subroutine
|
|
|
|
! Update the values of the particle boundary model
|
|
subroutine updateParticle_interface(self)
|
|
import boundaryParticleGeneric
|
|
|
|
class(boundaryParticleGeneric), intent(inout):: self
|
|
|
|
end subroutine updateParticle_interface
|
|
|
|
! Write the values of the particle boundary model
|
|
subroutine printParticle_interface(self, fileID)
|
|
import boundaryParticleGeneric
|
|
|
|
class(boundaryParticleGeneric), intent(inout):: self
|
|
integer, intent(in):: fileID
|
|
|
|
end subroutine printParticle_interface
|
|
|
|
end interface
|
|
|
|
!Reflecting boundary
|
|
TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryReflection
|
|
CONTAINS
|
|
procedure, pass:: apply => reflection_apply
|
|
|
|
END TYPE boundaryReflection
|
|
|
|
!Absorption boundary
|
|
TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryAbsorption
|
|
CONTAINS
|
|
procedure, pass:: apply => absorption_apply
|
|
|
|
END TYPE boundaryAbsorption
|
|
|
|
!Transparent boundary
|
|
TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryTransparent
|
|
CONTAINS
|
|
procedure, pass:: apply => transparent_apply
|
|
|
|
END TYPE boundaryTransparent
|
|
|
|
!Symmetry axis
|
|
TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryAxis
|
|
CONTAINS
|
|
procedure, pass:: apply => symmetryAxis_apply
|
|
|
|
END TYPE boundaryAxis
|
|
|
|
!Wall Temperature boundary
|
|
TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryWallTemperature
|
|
!Thermal velocity of the wall: square root(Wall temperature X specific heat)
|
|
REAL(8):: vTh
|
|
CONTAINS
|
|
procedure, pass:: apply => wallTemperature_apply
|
|
|
|
END TYPE boundaryWallTemperature
|
|
|
|
!Ionization boundary
|
|
TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryIonization
|
|
REAL(8):: m0, n0, v0(1:3), vTh !Properties of background neutrals.
|
|
CLASS(speciesGeneric), POINTER:: species !Ion species
|
|
CLASS(speciesCharged), POINTER:: electronSecondary !Pointer to species considerer as secondary electron
|
|
TYPE(table1D):: crossSection
|
|
REAL(8):: effectiveTime
|
|
REAL(8):: eThreshold
|
|
REAL(8):: deltaV
|
|
integer:: tally
|
|
integer(KIND=OMP_LOCK_KIND):: tally_lock
|
|
CONTAINS
|
|
procedure, pass:: apply => ionization_apply
|
|
|
|
END TYPE boundaryIonization
|
|
|
|
! Ensures quasi-neutrality by changing the reflection coefficient
|
|
type, public, extends(boundaryParticleGeneric):: boundaryQuasiNeutrality
|
|
real(8), allocatable:: alpha(:) ! Reflection parameter
|
|
integer:: s_incident ! species index of the incident species
|
|
type(meshEdgePointer), allocatable:: edges(:) !Array with edges
|
|
contains
|
|
procedure, pass:: apply => quasiNeutrality_apply
|
|
|
|
end type boundaryQuasiNeutrality
|
|
|
|
!Boundary for quasi-neutral outflow adjusting reflection coefficient
|
|
type, public, extends(boundaryParticleGeneric):: boundaryOutflowAdaptive
|
|
real(8), allocatable:: velocity_shift(:)
|
|
integer:: s_incident ! species index of the incident species
|
|
type(meshEdgePointer), allocatable:: edges(:) !Array with edges
|
|
contains
|
|
procedure, pass:: apply => outflowAdaptive_apply
|
|
|
|
end type boundaryOutflowAdaptive
|
|
|
|
interface
|
|
module subroutine reflection_apply(self, edge, part)
|
|
use moduleSpecies
|
|
|
|
class(boundaryReflection), intent(inout):: self
|
|
class(meshEdge), intent(inout):: edge
|
|
class(particle), intent(inout):: part
|
|
|
|
end subroutine reflection_apply
|
|
|
|
module subroutine absorption_apply(self, edge, part)
|
|
use moduleSpecies
|
|
|
|
class(boundaryAbsorption), intent(inout):: self
|
|
class(meshEdge), intent(inout):: edge
|
|
class(particle), intent(inout):: part
|
|
|
|
end subroutine absorption_apply
|
|
|
|
module subroutine transparent_apply(self, edge, part)
|
|
use moduleSpecies
|
|
|
|
class(boundaryTransparent), intent(inout):: self
|
|
class(meshEdge), intent(inout):: edge
|
|
class(particle), intent(inout):: part
|
|
|
|
end subroutine transparent_apply
|
|
|
|
module subroutine symmetryAxis_apply(self, edge, part)
|
|
use moduleSpecies
|
|
|
|
class(boundaryAxis), intent(inout):: self
|
|
class(meshEdge), intent(inout):: edge
|
|
class(particle), intent(inout):: part
|
|
|
|
end subroutine symmetryAxis_apply
|
|
|
|
module subroutine wallTemperature_apply(self, edge, part)
|
|
use moduleSpecies
|
|
|
|
class(boundaryWallTemperature), intent(inout):: self
|
|
class(meshEdge), intent(inout):: edge
|
|
class(particle), intent(inout):: part
|
|
|
|
end subroutine wallTemperature_apply
|
|
|
|
module subroutine ionization_apply(self, edge, part)
|
|
use moduleSpecies
|
|
|
|
class(boundaryIonization), intent(inout):: self
|
|
class(meshEdge), intent(inout):: edge
|
|
class(particle), intent(inout):: part
|
|
|
|
end subroutine ionization_apply
|
|
|
|
module subroutine quasiNeutrality_apply(self, edge, part)
|
|
use moduleSpecies
|
|
|
|
class(boundaryQuasiNeutrality), intent(inout):: self
|
|
class(meshEdge), intent(inout):: edge
|
|
class(particle), intent(inout):: part
|
|
|
|
end subroutine quasiNeutrality_apply
|
|
|
|
module subroutine outflowAdaptive_apply(self, edge, part)
|
|
use moduleSpecies
|
|
|
|
class(boundaryOutflowAdaptive), intent(inout):: self
|
|
class(meshEdge), intent(inout):: edge
|
|
class(particle), intent(inout):: part
|
|
|
|
end subroutine outflowAdaptive_apply
|
|
|
|
! Generic basic boundary conditions to use internally in the code
|
|
module subroutine genericReflection(edge, part)
|
|
use moduleSpecies
|
|
|
|
class(meshEdge), intent(inout):: edge
|
|
class(particle), intent(inout):: part
|
|
|
|
end subroutine genericReflection
|
|
|
|
module subroutine genericAbsorption(edge, part)
|
|
use moduleSpecies
|
|
|
|
class(meshEdge), intent(inout):: edge
|
|
class(particle), intent(inout):: part
|
|
|
|
end subroutine genericAbsorption
|
|
|
|
module subroutine genericTransparent(edge, part)
|
|
use moduleSpecies
|
|
|
|
class(meshEdge), intent(inout):: edge
|
|
class(particle), intent(inout):: part
|
|
|
|
end subroutine genericTransparent
|
|
|
|
end interface
|
|
|
|
TYPE:: boundaryParticleCont
|
|
CLASS(boundaryParticleGeneric), ALLOCATABLE:: obj
|
|
|
|
END TYPE boundaryParticleCont
|
|
|
|
type:: boundaryParticlePointer
|
|
class(boundaryParticleGeneric), pointer:: obj
|
|
|
|
end type boundaryParticlePointer
|
|
|
|
!Number of boundaries
|
|
INTEGER:: nBoundariesParticle = 0
|
|
!Array for boundaries
|
|
type(boundaryParticleCont), allocatable, target:: boundariesParticle(:)
|
|
|
|
interface
|
|
! Update the particle boundary models
|
|
module subroutine boundariesParticle_update()
|
|
|
|
end subroutine boundariesParticle_update
|
|
|
|
! Write data about particle boundaries
|
|
module subroutine boundariesParticle_write()
|
|
|
|
end subroutine boundariesParticle_write
|
|
end interface
|
|
|
|
! BOUNDARY ELECTROMAGNETIC DEFINITIONS
|
|
! Generic type for electromagnetic boundary conditions
|
|
type, public, abstract:: boundaryEMGeneric
|
|
integer:: n
|
|
character(:), allocatable:: name
|
|
integer:: nNodes
|
|
type(meshNodePointer), allocatable:: nodes(:)
|
|
|
|
procedure(updateEM_interface), pointer, pass:: update => null()
|
|
contains
|
|
procedure(applyEM_interface), deferred, pass:: apply
|
|
|
|
end type boundaryEMGeneric
|
|
|
|
interface
|
|
module subroutine initDirichlet(self, config, object)
|
|
use json_module
|
|
|
|
class(boundaryEMGeneric), allocatable, intent(inout):: self
|
|
type(json_file), intent(inout):: config
|
|
character(:), allocatable, intent(in):: object
|
|
|
|
end subroutine initDirichlet
|
|
|
|
module subroutine initDirichletTime(self, config, object)
|
|
use json_module
|
|
|
|
class(boundaryEMGeneric), allocatable, intent(inout):: self
|
|
type(json_file), intent(inout):: config
|
|
character(:), allocatable, intent(in):: object
|
|
|
|
end subroutine initDirichletTime
|
|
|
|
module function boundaryEMName_to_Index(boundaryName) result(bp)
|
|
character(:), allocatable:: boundaryName
|
|
integer:: bp
|
|
|
|
end function boundaryEMName_to_Index
|
|
|
|
end interface
|
|
|
|
abstract interface
|
|
! Apply boundary condition to the load vector for the Poission equation
|
|
subroutine applyEM_interface(self, vectorF)
|
|
import boundaryEMGeneric
|
|
|
|
class(boundaryEMGeneric), intent(in):: self
|
|
real(8), intent(inout):: vectorF(:)
|
|
|
|
end subroutine applyEM_interface
|
|
|
|
! Update the values of the EM boundary model
|
|
subroutine updateEM_interface(self)
|
|
import boundaryEMGeneric
|
|
|
|
class(boundaryEMGeneric), intent(inout):: self
|
|
|
|
end subroutine updateEM_interface
|
|
|
|
end interface
|
|
|
|
! Extended types
|
|
TYPE, EXTENDS(boundaryEMGeneric):: boundaryEMDirichlet
|
|
REAL(8):: potential
|
|
CONTAINS
|
|
! boundaryEMGeneric DEFERRED PROCEDURES
|
|
PROCEDURE, PASS:: apply => applyDirichlet
|
|
|
|
END TYPE boundaryEMDirichlet
|
|
|
|
TYPE, EXTENDS(boundaryEMGeneric):: boundaryEMDirichletTime
|
|
real(8):: potential
|
|
real(8):: timeFactor
|
|
type(table1D):: temporalProfile
|
|
contains
|
|
! boundaryEMGeneric DEFERRED PROCEDURES
|
|
procedure, pass:: apply => applyDirichletTime
|
|
|
|
END TYPE boundaryEMDirichletTime
|
|
|
|
interface
|
|
module subroutine applyDirichlet(self, vectorF)
|
|
class(boundaryEMDirichlet), intent(in):: self
|
|
real(8), intent(inout):: vectorF(:)
|
|
|
|
end subroutine applyDirichlet
|
|
|
|
module subroutine applyDirichletTime(self, vectorF)
|
|
class(boundaryEMDirichletTime), intent(in):: self
|
|
real(8), intent(inout):: vectorF(:)
|
|
|
|
end subroutine applyDirichletTime
|
|
|
|
end interface
|
|
|
|
! Container for boundary conditions
|
|
TYPE:: boundaryEMCont
|
|
CLASS(boundaryEMGeneric), ALLOCATABLE:: obj
|
|
|
|
END TYPE boundaryEMCont
|
|
|
|
INTEGER:: nBoundariesEM
|
|
TYPE(boundaryEMCont), ALLOCATABLE, target:: boundariesEM(:)
|
|
|
|
!Information of charge and reference parameters for rho vector
|
|
REAL(8), ALLOCATABLE:: qSpecies(:)
|
|
|
|
! Update the EM boundary models
|
|
interface
|
|
module subroutine boundariesEM_update()
|
|
|
|
end subroutine boundariesEM_update
|
|
|
|
end interface
|
|
|
|
! PHYSICAL SURFACES LINKING TO MESH ELEMENTS
|
|
! Link physical surface to edges
|
|
type:: physicalSurface
|
|
integer:: index
|
|
class(meshNodePointer), allocatable:: nodes(:)
|
|
class(meshEdgePointer), allocatable:: edges(:)
|
|
class(boundaryParticlePointer), allocatable:: particles(:)
|
|
class(boundaryEMGeneric), pointer:: EM => null()
|
|
|
|
end type
|
|
|
|
integer:: nPhysicalSurfaces
|
|
type(physicalSurface), allocatable:: physicalSurfaces(:)
|
|
|
|
! Get ID from array based on physical surface
|
|
interface
|
|
module function physicalSurface_to_index(ps) result(index)
|
|
integer:: ps
|
|
integer:: index
|
|
|
|
end function physicalSurface_to_index
|
|
|
|
end interface
|
|
|
|
END MODULE moduleMesh
|