Added the possibility to have different boundary conditions per species.

A boundary condition for each species must be indicated in the case
file.
This opens the door to use boundary conditions with different parameters
(for example, a wall temperature, coefficients for reflection or
 absorption...)

The examples included with the code have been updated accordently.
This commit is contained in:
Jorge Gonzalez 2020-12-17 18:21:27 +01:00
commit 2c3e25b40e
18 changed files with 19389 additions and 1174 deletions

View file

@ -15,7 +15,7 @@ MODULE moduleMesh1DCart
END TYPE meshNode1DCart
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshEdge):: meshEdge1DCart
TYPE, PUBLIC, EXTENDS(meshEdge):: meshEdge1DCart
!Element coordinates
REAL(8):: x = 0.D0
!Connectivity to nodes
@ -27,6 +27,28 @@ MODULE moduleMesh1DCart
END TYPE meshEdge1DCart
!Boundary functions defined in the submodule Boundary
INTERFACE
MODULE SUBROUTINE reflection(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
END SUBROUTINE reflection
MODULE SUBROUTINE absorption(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
END SUBROUTINE absorption
END INTERFACE
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshVol):: meshVol1DCart
CONTAINS
PROCEDURE, PASS:: detJac => detJ1DCart
@ -122,6 +144,9 @@ MODULE moduleMesh1DCart
!EDGE FUNCTIONS
!Inits edge element
SUBROUTINE initEdge1DCart(self, n, p, bt, physicalSurface)
USE moduleSpecies
USE moduleBoundary
USE moduleErrors
IMPLICIT NONE
CLASS(meshEdge1DCart), INTENT(out):: self
@ -130,6 +155,7 @@ MODULE moduleMesh1DCart
INTEGER, INTENT(in):: bt
INTEGER, INTENT(in):: physicalSurface
REAL(8), DIMENSION(1:3):: r1
INTEGER:: s
self%n = n
self%n1 => mesh%nodes(p(1))%obj
@ -141,7 +167,24 @@ MODULE moduleMesh1DCart
self%normal = (/ 1.D0, 0.D0, 0.D0 /)
!Boundary index
self%bt = bt
self%boundary => boundary(bt)
ALLOCATE(self%fboundary(1:nSpecies))
!Assign functions to boundary
DO s = 1, nSpecies
SELECT TYPE(obj => self%boundary%bTypes(s)%obj)
TYPE IS(boundaryAbsorption)
self%fBoundary(s)%apply => absorption
TYPE IS(boundaryReflection)
self%fBoundary(s)%apply => reflection
CLASS DEFAULT
CALL criticalError("Boundary type not defined in this geometry", 'initEdge1DCart')
END SELECT
END DO
!Physical Surface
self%physicalSurface = physicalSurface

View file

@ -1,40 +1,32 @@
MODULE moduleMesh1DCartBoundary
SUBMODULE (moduleMesh1DCart) moduleMesh1DCartBoundary
USE moduleMesh1DCart
TYPE, PUBLIC, EXTENDS(meshEdge1DCart):: meshEdge1DCartRef
CONTAINS
PROCEDURE, PASS:: fBoundary => reflection
END TYPE meshEdge1DCartRef
TYPE, PUBLIC, EXTENDS(meshEdge1DCart):: meshEdge1DCartAbs
CONTAINS
PROCEDURE, PASS:: fBoundary => absorption
END TYPE meshEdge1DCartAbs
CONTAINS
SUBROUTINE reflection(self, part)
SUBROUTINE reflection(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge1DCartRef), INTENT(inout):: self
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
part%v(1) = -part%v(1)
part%r(1) = 2.D0*self%x - part%r(1)
SELECT TYPE(edge)
TYPE IS(meshEdge1DCart)
part%v(1) = -part%v(1)
part%r(1) = 2.D0*edge%x - part%r(1)
END SELECT
END SUBROUTINE reflection
SUBROUTINE absorption(self, part)
SUBROUTINE absorption(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge1DCartAbs), INTENT(inout):: self
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
part%n_in = .FALSE.
END SUBROUTINE absorption
END MODULE moduleMesh1DCartBoundary
END SUBMODULE moduleMesh1DCartBoundary

View file

@ -1,7 +1,6 @@
MODULE moduleMesh1DCartRead
USE moduleMesh
USE moduleMesh1DCart
USE moduleMesh1DCartBoundary
!TODO: make this abstract to allow different mesh formats
TYPE, EXTENDS(meshGeneric):: mesh1DCartGeneric
@ -107,14 +106,8 @@ MODULE moduleMesh1DCartRead
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1)
!Associate boundary condition
bt = getBoundaryId(boundaryType)
SELECT CASE(boundary(bt)%obj%boundaryType)
CASE ('reflection')
ALLOCATE(meshEdge1DCartRef:: self%edges(e)%obj)
CASE ('absorption')
ALLOCATE(meshEdge1DCartAbs:: self%edges(e)%obj)
END SELECT
ALLOCATE(meshEdge1DCart:: self%edges(e)%obj)
CALL self%edges(e)%obj%init(n, p(1:1), bt, boundaryType)

View file

@ -15,7 +15,7 @@ MODULE moduleMesh1DRad
END TYPE meshNode1DRad
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshEdge):: meshEdge1DRad
TYPE, PUBLIC, EXTENDS(meshEdge):: meshEdge1DRad
!Element coordinates
REAL(8):: r = 0.D0
!Connectivity to nodes
@ -27,6 +27,28 @@ MODULE moduleMesh1DRad
END TYPE meshEdge1DRad
!Boundary functions defined in the submodule Boundary
INTERFACE
MODULE SUBROUTINE reflection(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
END SUBROUTINE reflection
MODULE SUBROUTINE absorption(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
END SUBROUTINE absorption
END INTERFACE
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshVol):: meshVol1DRad
CONTAINS
PROCEDURE, PASS:: detJac => detJ1DRad
@ -123,6 +145,9 @@ MODULE moduleMesh1DRad
!EDGE FUNCTIONS
!Inits edge element
SUBROUTINE initEdge1DRad(self, n, p, bt, physicalSurface)
USE moduleSpecies
USE moduleBoundary
USE moduleErrors
IMPLICIT NONE
CLASS(meshEdge1DRad), INTENT(out):: self
@ -131,6 +156,7 @@ MODULE moduleMesh1DRad
INTEGER, INTENT(in):: bt
INTEGER, INTENT(in):: physicalSurface
REAL(8), DIMENSION(1:3):: r1
INTEGER:: s
self%n = n
self%n1 => mesh%nodes(p(1))%obj
@ -142,7 +168,24 @@ MODULE moduleMesh1DRad
self%normal = (/ 1.D0, 0.D0, 0.D0 /)
!Boundary index
self%bt = bt
self%boundary => boundary(bt)
ALLOCATE(self%fboundary(1:nSpecies))
!Assign functions to boundary
DO s = 1, nSpecies
SELECT TYPE(obj => self%boundary%bTypes(s)%obj)
TYPE IS(boundaryAbsorption)
self%fBoundary(s)%apply => absorption
TYPE IS(boundaryReflection)
self%fBoundary(s)%apply => reflection
CLASS DEFAULT
CALL criticalError("Boundary type not defined in this geometry", 'initEdge1DRad')
END SELECT
END DO
!Physical Surface
self%physicalSurface = physicalSurface

View file

@ -1,40 +1,32 @@
MODULE moduleMesh1DRadBoundary
SUBMODULE (moduleMesh1DRad) moduleMesh1DRadBoundary
USE moduleMesh1DRad
TYPE, PUBLIC, EXTENDS(meshEdge1DRad):: meshEdge1DRadRef
CONTAINS
PROCEDURE, PASS:: fBoundary => reflection
END TYPE meshEdge1DRadRef
TYPE, PUBLIC, EXTENDS(meshEdge1DRad):: meshEdge1DRadAbs
CONTAINS
PROCEDURE, PASS:: fBoundary => absorption
END TYPE meshEdge1DRadAbs
CONTAINS
SUBROUTINE reflection(self, part)
SUBROUTINE reflection(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge1DRadRef), INTENT(inout):: self
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
part%v(1) = -part%v(1)
part%r(1) = 2.D0*self%r - part%r(1)
SELECT TYPE(edge)
TYPE IS(meshEdge1DRad)
part%v(1) = -part%v(1)
part%r(1) = 2.D0*edge%r - part%r(1)
END SELECT
END SUBROUTINE reflection
SUBROUTINE absorption(self, part)
SUBROUTINE absorption(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge1DRadAbs), INTENT(inout):: self
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
part%n_in = .FALSE.
END SUBROUTINE absorption
END MODULE moduleMesh1DRadBoundary
END SUBMODULE moduleMesh1DRadBoundary

View file

@ -1,7 +1,6 @@
MODULE moduleMesh1DRadRead
USE moduleMesh
USE moduleMesh1DRad
USE moduleMesh1DRadBoundary
!TODO: make this abstract to allow different mesh formats
TYPE, EXTENDS(meshGeneric):: mesh1DRadGeneric
@ -107,14 +106,8 @@ MODULE moduleMesh1DRadRead
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1)
!Associate boundary condition
bt = getBoundaryId(boundaryType)
SELECT CASE(boundary(bt)%obj%boundaryType)
CASE ('reflection')
ALLOCATE(meshEdge1DRadRef:: self%edges(e)%obj)
CASE ('absorption')
ALLOCATE(meshEdge1DRadAbs:: self%edges(e)%obj)
END SELECT
ALLOCATE(meshEdge1DRad:: self%edges(e)%obj)
CALL self%edges(e)%obj%init(n, p(1:1), bt, boundaryType)

View file

@ -23,7 +23,7 @@ MODULE moduleMeshCyl
END TYPE meshNodeCyl
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshEdge):: meshEdgeCyl
TYPE, PUBLIC, EXTENDS(meshEdge):: meshEdgeCyl
!Element coordinates
REAL(8):: r(1:2) = 0.D0, z(1:2) = 0.D0
!Connectivity to nodes
@ -35,6 +35,37 @@ MODULE moduleMeshCyl
END TYPE meshEdgeCyl
!Boundary functions defined in the submodule Boundary
INTERFACE
MODULE SUBROUTINE reflection(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
END SUBROUTINE reflection
MODULE SUBROUTINE absorption(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
END SUBROUTINE absorption
MODULE SUBROUTINE symmetryAxis(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
END SUBROUTINE symmetryAxis
END INTERFACE
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshVol):: meshVolCyl
CONTAINS
PROCEDURE, PASS:: detJac => detJCyl
@ -68,6 +99,7 @@ MODULE moduleMeshCyl
END INTERFACE
!Quadrilateral volume element
TYPE, PUBLIC, EXTENDS(meshVolCyl):: meshVolCylQuad
!Element coordinates
REAL(8):: r(1:4) = 0.D0, z(1:4) = 0.D0
@ -98,6 +130,7 @@ MODULE moduleMeshCyl
END TYPE meshVolCylQuad
!Triangular volume element
TYPE, PUBLIC, EXTENDS(meshVolCyl):: meshVolCylTria
!Element coordinates
REAL(8):: r(1:3) = 0.D0, z(1:3) = 0.D0
@ -131,7 +164,6 @@ MODULE moduleMeshCyl
END TYPE meshVolCylTria
CONTAINS
!NODE FUNCTIONS
!Inits node element
SUBROUTINE initNodeCyl(self, n, r)
@ -154,6 +186,7 @@ MODULE moduleMeshCyl
END SUBROUTINE initNodeCyl
!Get coordinates from node
PURE FUNCTION getCoordCyl(self) RESULT(r)
IMPLICIT NONE
@ -167,6 +200,9 @@ MODULE moduleMeshCyl
!EDGE FUNCTIONS
!Inits edge element
SUBROUTINE initEdgeCyl(self, n, p, bt, physicalSurface)
USE moduleSpecies
USE moduleBoundary
USE moduleErrors
IMPLICIT NONE
CLASS(meshEdgeCyl), INTENT(out):: self
@ -175,6 +211,7 @@ MODULE moduleMeshCyl
INTEGER, INTENT(in):: bt
INTEGER, INTENT(in):: physicalSurface
REAL(8), DIMENSION(1:3):: r1, r2
INTEGER:: s
self%n = n
self%n1 => mesh%nodes(p(1))%obj
@ -189,8 +226,28 @@ MODULE moduleMeshCyl
self%z(2)-self%z(1), &
0.D0 /)
!Boundary index
self%bt = bt
!Phyiscal Surface
self%boundary => boundary(bt)
ALLOCATE(self%fboundary(1:nSpecies))
!Assign functions to boundary
DO s = 1, nSpecies
SELECT TYPE(obj => self%boundary%bTypes(s)%obj)
TYPE IS(boundaryAbsorption)
self%fBoundary(s)%apply => absorption
TYPE IS(boundaryReflection)
self%fBoundary(s)%apply => reflection
TYPE IS(boundaryAxis)
self%fBoundary(s)%apply => symmetryAxis
CLASS DEFAULT
CALL criticalError("Boundary type not defined in this geometry", 'initEdgeCyl')
END SELECT
END DO
!Physical surface
self%physicalSurface = physicalSurface
END SUBROUTINE initEdgeCyl

View file

@ -1,64 +1,51 @@
!moduleMeshCylBoundary: Edge elements for Cylindrical mesh.
MODULE moduleMeshCylBoundary
!moduleMeshCylBoundary: Boundary functions for cylindrical coordinates
SUBMODULE (moduleMeshCyl) moduleMeshCylBoundary
USE moduleMeshCyl
TYPE, PUBLIC, EXTENDS(meshEdgeCyl):: meshEdgeCylRef
CONTAINS
PROCEDURE, PASS:: fBoundary => reflection
END TYPE meshEdgeCylRef
TYPE, PUBLIC, EXTENDS(meshEdgeCyl):: meshEdgeCylAbs
CONTAINS
PROCEDURE, PASS:: fBoundary => absorption
END TYPE meshEdgeCylAbs
TYPE, PUBLIC, EXTENDS(meshEdgeCyl):: meshEdgeCylAxis
CONTAINS
PROCEDURE, PASS:: fBoundary => symmetryAxis
END TYPE meshEdgeCylAxis
CONTAINS
SUBROUTINE reflection(self, part)
SUBROUTINE reflection(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdgeCylRef), INTENT(inout):: self
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
REAL(8):: edgeNorm, cosT, sinT, rp(1:2), rpp(1:2), vpp(1:2)
edgeNorm = DSQRT((self%r(2)-self%r(1))**2 + (self%z(2)-self%z(1))**2)
cosT = (self%z(2)-self%z(1))/edgeNorm
sinT = DSQRT(1-cosT**2)
!TODO: Try to do this without select
SELECT TYPE(edge)
TYPE IS(meshEdgeCyl)
edgeNorm = DSQRT((edge%r(2)-edge%r(1))**2 + (edge%z(2)-edge%z(1))**2)
cosT = (edge%z(2)-edge%z(1))/edgeNorm
sinT = DSQRT(1-cosT**2)
rp(1) = part%r(1) - self%z(1);
rp(2) = part%r(2) - self%r(1);
rp(1) = part%r(1) - edge%z(1);
rp(2) = part%r(2) - edge%r(1);
rpp(1) = cosT*rp(1) - sinT*rp(2)
rpp(2) = sinT*rp(1) + cosT*rp(2)
rpp(2) = -rpp(2)
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)
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) + self%z(1);
part%r(2) = -sinT*rpp(1) + cosT*rpp(2) + self%r(1);
part%v(1) = cosT*vpp(1) + sinT*vpp(2)
part%v(2) = -sinT*vpp(1) + cosT*vpp(2)
part%r(1) = cosT*rpp(1) + sinT*rpp(2) + edge%z(1);
part%r(2) = -sinT*rpp(1) + cosT*rpp(2) + edge%r(1);
part%v(1) = cosT*vpp(1) + sinT*vpp(2)
part%v(2) = -sinT*vpp(1) + cosT*vpp(2)
part%n_in = .TRUE.
part%n_in = .TRUE.
END SELECT
END SUBROUTINE reflection
!Absoption in a surface
SUBROUTINE absorption(self, part)
SUBROUTINE absorption(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdgeCylAbs), INTENT(inout):: self
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
@ -67,14 +54,13 @@ MODULE moduleMeshCylBoundary
END SUBROUTINE absorption
SUBROUTINE symmetryAxis(self, part)
SUBROUTINE symmetryAxis(edge, part)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshEdgeCylAxis), INTENT(inout):: self
CLASS(meshEdge), INTENT(inout):: edge
CLASS(particle), INTENT(inout):: part
END SUBROUTINE symmetryAxis
END MODULE moduleMeshCylBoundary
END SUBMODULE moduleMeshCylBoundary

View file

@ -1,9 +1,7 @@
MODULE moduleMeshCylRead
USE moduleMesh
USE moduleMeshCyl
USE moduleMeshCylBoundary
!TODO: make this abstract to allow different mesh formats
TYPE, EXTENDS(meshGeneric):: meshCylGeneric
CONTAINS
PROCEDURE, PASS:: init => initCylMesh
@ -104,17 +102,8 @@ MODULE moduleMeshCylRead
READ(10,*) n, elemType, eTemp, boundaryType, eTemp, p(1:2)
!Associate boundary condition procedure.
bt = getBoundaryId(boundaryType)
SELECT CASE(boundary(bt)%obj%boundaryType)
CASE ('reflection')
ALLOCATE(meshEdgeCylRef:: self%edges(e)%obj)
CASE ('absorption')
ALLOCATE(meshEdgeCylAbs:: self%edges(e)%obj)
CASE ('axis')
ALLOCATE(meshEdgeCylAxis:: self%edges(e)%obj)
END SELECT
ALLOCATE(meshEdgeCyl:: self%edges(e)%obj)
CALL self%edges(e)%obj%init(n, p(1:2), bt, boundaryType)

View file

@ -2,6 +2,7 @@
MODULE moduleMesh
USE moduleList
USE moduleOutput
USE moduleBoundary
IMPLICIT NONE
!Parent of Node element
@ -45,6 +46,12 @@ MODULE moduleMesh
END TYPE meshNodeCont
!Type for array of boundary functions (one per species)
TYPE, PUBLIC:: fBoundaryGeneric
PROCEDURE(boundary_interface), POINTER, NOPASS:: apply => NULL()
END TYPE
!Parent of Edge element
TYPE, PUBLIC, ABSTRACT:: meshEdge
!Element index
@ -53,13 +60,14 @@ MODULE moduleMesh
CLASS(meshVol), POINTER:: e1 => NULL(), e2 => NULL()
!Normal vector
REAL(8):: normal(1:3)
!Physical surface in mesh
!Pointer to boundary element
TYPE(boundaryCont), POINTER:: boundary
!Array of functions for boundary conditions
TYPE(fBoundaryGeneric), ALLOCATABLE:: fBoundary(:)
!Physical surface for the edge
INTEGER:: physicalSurface
!id for boundary condition
INTEGER:: bt = 0
CONTAINS
PROCEDURE(initEdge_interface), DEFERRED, PASS:: init
PROCEDURE(boundary_interface), DEFERRED, PASS:: fBoundary
PROCEDURE(getNodesEdge_interface), DEFERRED, PASS:: getNodes
PROCEDURE(randPos_interface), DEFERRED, PASS:: randPos
@ -77,15 +85,6 @@ MODULE moduleMesh
END SUBROUTINE initEdge_interface
SUBROUTINE boundary_interface(self, part)
USE moduleSpecies
IMPORT:: meshEdge
CLASS (meshEdge), INTENT(inout):: self
CLASS (particle), INTENT(inout):: part
END SUBROUTINE
PURE FUNCTION getNodesEdge_interface(self) RESULT(n)
IMPORT:: meshEdge
CLASS(meshEdge), INTENT(in):: self
@ -102,6 +101,18 @@ MODULE moduleMesh
END INTERFACE
INTERFACE
SUBROUTINE boundary_interface(edge, part)
USE moduleSpecies
IMPORT:: meshEdge
CLASS (meshEdge), INTENT(inout):: edge
CLASS (particle), INTENT(inout):: part
END SUBROUTINE
END INTERFACE
!Containers for edges in the mesh
TYPE:: meshEdgeCont
CLASS(meshEdge), ALLOCATABLE:: obj
@ -332,8 +343,8 @@ MODULE moduleMesh
CALL nextElement%findCell(part, self)
CLASS IS (meshEdge)
!Particle encountered an edge, execute boundary
CALL nextElement%fBoundary(part)
!Particle encountered an edge, apply boundary
CALL nextElement%fBoundary(part%sp)%apply(nextElement,part)
!If particle is still inside the domain, call findCell
IF (part%n_in) THEN
IF(PRESENT(oldCell)) THEN