Impliementation of a collision mesh which is independent for the mesh

used to scatter particles and compute the EM field.
This commit is contained in:
Jorge Gonzalez 2021-04-03 09:20:46 +02:00
commit a2631f6b78
19 changed files with 636 additions and 368 deletions

View file

@ -3,7 +3,7 @@
"path": "./runs/Argon_Expansion/", "path": "./runs/Argon_Expansion/",
"triggerOutput": 10, "triggerOutput": 10,
"cpuTime": false, "cpuTime": false,
"numColl": false, "numColl": true,
"folder": "CX_case" "folder": "CX_case"
}, },
"geometry": { "geometry": {

View file

@ -3,7 +3,7 @@
"path": "./runs/cylFlow/", "path": "./runs/cylFlow/",
"triggerOutput": 10, "triggerOutput": 10,
"cpuTime": true, "cpuTime": true,
"numColl": false "numColl": true
}, },
"geometry": { "geometry": {
"type": "2DCyl", "type": "2DCyl",

View file

@ -4,6 +4,7 @@ PROGRAM fpakc
USE moduleErrors USE moduleErrors
USE moduleInject USE moduleInject
USE moduleSolver USE moduleSolver
USE moduleMesh
USE moduleCompTime USE moduleCompTime
USE moduleCaseParam USE moduleCaseParam
USE OMP_LIB USE OMP_LIB
@ -67,11 +68,20 @@ PROGRAM fpakc
tColl = omp_get_wtime() tColl = omp_get_wtime()
!$OMP END SINGLE !$OMP END SINGLE
CALL doCollisions() IF (ASSOCIATED(meshForMCC)) CALL meshForMCC%doCollisions()
!$OMP SINGLE !$OMP SINGLE
tColl = omp_get_wtime() - tColl tColl = omp_get_wtime() - tColl
!Coulomb scattering
tCoul = omp_get_wTime()
!$OMP END SINGLE
IF (ASSOCIATED(mesh%doCoulomb)) CALL mesh%doCoulomb()
!$OMP SINGLE
tCoul = omp_get_wTime() - tCoul
!Reset particles !Reset particles
tReset = omp_get_wtime() tReset = omp_get_wtime()
!$OMP END SINGLE !$OMP END SINGLE

View file

@ -198,18 +198,19 @@ MODULE moduleMesh1DCart
!VOLUME FUNCTIONS !VOLUME FUNCTIONS
!SEGMENT FUNCTIONS !SEGMENT FUNCTIONS
!Init segment element !Init segment element
SUBROUTINE initVol1DCartSegm(self, n, p) SUBROUTINE initVol1DCartSegm(self, n, p, nodes)
USE moduleRefParam USE moduleRefParam
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVol1DCartSegm), INTENT(out):: self CLASS(meshVol1DCartSegm), INTENT(out):: self
INTEGER, INTENT(in):: n INTEGER, INTENT(in):: n
INTEGER, INTENT(in):: p(:) INTEGER, INTENT(in):: p(:)
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
REAL(8), DIMENSION(1:3):: r1, r2 REAL(8), DIMENSION(1:3):: r1, r2
self%n = n self%n = n
self%n1 => mesh%nodes(p(1))%obj self%n1 => nodes(p(1))%obj
self%n2 => mesh%nodes(p(2))%obj self%n2 => nodes(p(2))%obj
!Get element coordinates !Get element coordinates
r1 = self%n1%getCoordinates() r1 = self%n1%getCoordinates()
r2 = self%n2%getCoordinates() r2 = self%n2%getCoordinates()
@ -525,7 +526,7 @@ MODULE moduleMesh1DCart
SUBROUTINE connectMesh1DCart(self) SUBROUTINE connectMesh1DCart(self)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshParticle), INTENT(inout):: self CLASS(meshGeneric), INTENT(inout):: self
INTEGER:: e, et INTEGER:: e, et
DO e = 1, self%numVols DO e = 1, self%numVols
@ -538,11 +539,15 @@ MODULE moduleMesh1DCart
END DO END DO
!Connect Vol-Edge SELECT TYPE(self)
DO et = 1, self%numEdges TYPE IS(meshParticles)
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj) !Connect Vol-Edge
DO et = 1, self%numEdges
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj)
END DO END DO
END SELECT
END DO END DO

View file

@ -200,18 +200,19 @@ MODULE moduleMesh1DRad
!VOLUME FUNCTIONS !VOLUME FUNCTIONS
!SEGMENT FUNCTIONS !SEGMENT FUNCTIONS
!Init segment element !Init segment element
SUBROUTINE initVol1DRadSegm(self, n, p) SUBROUTINE initVol1DRadSegm(self, n, p, nodes)
USE moduleRefParam USE moduleRefParam
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVol1DRadSegm), INTENT(out):: self CLASS(meshVol1DRadSegm), INTENT(out):: self
INTEGER, INTENT(in):: n INTEGER, INTENT(in):: n
INTEGER, INTENT(in):: p(:) INTEGER, INTENT(in):: p(:)
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
REAL(8), DIMENSION(1:3):: r1, r2 REAL(8), DIMENSION(1:3):: r1, r2
self%n = n self%n = n
self%n1 => mesh%nodes(p(1))%obj self%n1 => nodes(p(1))%obj
self%n2 => mesh%nodes(p(2))%obj self%n2 => nodes(p(2))%obj
!Get element coordinates !Get element coordinates
r1 = self%n1%getCoordinates() r1 = self%n1%getCoordinates()
r2 = self%n2%getCoordinates() r2 = self%n2%getCoordinates()
@ -536,7 +537,7 @@ MODULE moduleMesh1DRad
SUBROUTINE connectMesh1DRad(self) SUBROUTINE connectMesh1DRad(self)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshParticle), INTENT(inout):: self CLASS(meshGeneric), INTENT(inout):: self
INTEGER:: e, et INTEGER:: e, et
DO e = 1, self%numVols DO e = 1, self%numVols
@ -549,11 +550,15 @@ MODULE moduleMesh1DRad
END DO END DO
!Connect Vol-Edge SELECT TYPE(self)
DO et = 1, self%numEdges TYPE IS(meshParticles)
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj) !Connect Vol-Edge
DO et = 1, self%numEdges
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj)
END DO END DO
END SELECT
END DO END DO

View file

@ -283,20 +283,21 @@ MODULE moduleMesh2DCart
!VOLUME FUNCTIONS !VOLUME FUNCTIONS
!QUAD FUNCTIONS !QUAD FUNCTIONS
!Inits quadrilateral element !Inits quadrilateral element
SUBROUTINE initVolQuad2DCart(self, n, p) SUBROUTINE initVolQuad2DCart(self, n, p, nodes)
USE moduleRefParam USE moduleRefParam
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVol2DCartQuad), INTENT(out):: self CLASS(meshVol2DCartQuad), INTENT(out):: self
INTEGER, INTENT(in):: n INTEGER, INTENT(in):: n
INTEGER, INTENT(in):: p(:) INTEGER, INTENT(in):: p(:)
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
REAL(8), DIMENSION(1:3):: r1, r2, r3, r4 REAL(8), DIMENSION(1:3):: r1, r2, r3, r4
self%n = n self%n = n
self%n1 => mesh%nodes(p(1))%obj self%n1 => nodes(p(1))%obj
self%n2 => mesh%nodes(p(2))%obj self%n2 => nodes(p(2))%obj
self%n3 => mesh%nodes(p(3))%obj self%n3 => nodes(p(3))%obj
self%n4 => mesh%nodes(p(4))%obj self%n4 => nodes(p(4))%obj
!Get element coordinates !Get element coordinates
r1 = self%n1%getCoordinates() r1 = self%n1%getCoordinates()
r2 = self%n2%getCoordinates() r2 = self%n2%getCoordinates()
@ -631,22 +632,23 @@ MODULE moduleMesh2DCart
!TRIA ELEMENT !TRIA ELEMENT
!Init tria element !Init tria element
SUBROUTINE initVolTria2DCart(self, n, p) SUBROUTINE initVolTria2DCart(self, n, p, nodes)
USE moduleRefParam USE moduleRefParam
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVol2DCartTria), INTENT(out):: self CLASS(meshVol2DCartTria), INTENT(out):: self
INTEGER, INTENT(in):: n INTEGER, INTENT(in):: n
INTEGER, INTENT(in):: p(:) INTEGER, INTENT(in):: p(:)
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
REAL(8), DIMENSION(1:3):: r1, r2, r3 REAL(8), DIMENSION(1:3):: r1, r2, r3
!Assign node index !Assign node index
self%n = n self%n = n
!Assign nodes to element !Assign nodes to element
self%n1 => mesh%nodes(p(1))%obj self%n1 => nodes(p(1))%obj
self%n2 => mesh%nodes(p(2))%obj self%n2 => nodes(p(2))%obj
self%n3 => mesh%nodes(p(3))%obj self%n3 => nodes(p(3))%obj
!Get element coordinates !Get element coordinates
r1 = self%n1%getCoordinates() r1 = self%n1%getCoordinates()
r2 = self%n2%getCoordinates() r2 = self%n2%getCoordinates()
@ -1022,7 +1024,7 @@ MODULE moduleMesh2DCart
SUBROUTINE connectMesh2DCart(self) SUBROUTINE connectMesh2DCart(self)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshParticle), INTENT(inout):: self CLASS(meshGeneric), INTENT(inout):: self
INTEGER:: e, et INTEGER:: e, et
DO e = 1, self%numVols DO e = 1, self%numVols
@ -1035,11 +1037,15 @@ MODULE moduleMesh2DCart
END DO END DO
!Connect Vol-Edge SELECT TYPE(self)
DO et = 1, self%numEdges TYPE IS(meshParticles)
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj) !Connect Vol-Edge
DO et = 1, self%numEdges
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj)
END DO END DO
END SELECT
END DO END DO

View file

@ -271,20 +271,21 @@ MODULE moduleMesh2DCyl
!VOLUME FUNCTIONS !VOLUME FUNCTIONS
!QUAD FUNCTIONS !QUAD FUNCTIONS
!Inits quadrilateral element !Inits quadrilateral element
SUBROUTINE initVolQuad2DCyl(self, n, p) SUBROUTINE initVolQuad2DCyl(self, n, p, nodes)
USE moduleRefParam USE moduleRefParam
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVol2DCylQuad), INTENT(out):: self CLASS(meshVol2DCylQuad), INTENT(out):: self
INTEGER, INTENT(in):: n INTEGER, INTENT(in):: n
INTEGER, INTENT(in):: p(:) INTEGER, INTENT(in):: p(:)
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
REAL(8), DIMENSION(1:3):: r1, r2, r3, r4 REAL(8), DIMENSION(1:3):: r1, r2, r3, r4
self%n = n self%n = n
self%n1 => mesh%nodes(p(1))%obj self%n1 => nodes(p(1))%obj
self%n2 => mesh%nodes(p(2))%obj self%n2 => nodes(p(2))%obj
self%n3 => mesh%nodes(p(3))%obj self%n3 => nodes(p(3))%obj
self%n4 => mesh%nodes(p(4))%obj self%n4 => nodes(p(4))%obj
!Get element coordinates !Get element coordinates
r1 = self%n1%getCoordinates() r1 = self%n1%getCoordinates()
r2 = self%n2%getCoordinates() r2 = self%n2%getCoordinates()
@ -652,22 +653,23 @@ MODULE moduleMesh2DCyl
!TRIA ELEMENT !TRIA ELEMENT
!Init tria element !Init tria element
SUBROUTINE initVolTria2DCyl(self, n, p) SUBROUTINE initVolTria2DCyl(self, n, p, nodes)
USE moduleRefParam USE moduleRefParam
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVol2DCylTria), INTENT(out):: self CLASS(meshVol2DCylTria), INTENT(out):: self
INTEGER, INTENT(in):: n INTEGER, INTENT(in):: n
INTEGER, INTENT(in):: p(:) INTEGER, INTENT(in):: p(:)
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
REAL(8), DIMENSION(1:3):: r1, r2, r3 REAL(8), DIMENSION(1:3):: r1, r2, r3
!Assign node index !Assign node index
self%n = n self%n = n
!Assign nodes to element !Assign nodes to element
self%n1 => mesh%nodes(p(1))%obj self%n1 => nodes(p(1))%obj
self%n2 => mesh%nodes(p(2))%obj self%n2 => nodes(p(2))%obj
self%n3 => mesh%nodes(p(3))%obj self%n3 => nodes(p(3))%obj
!Get element coordinates !Get element coordinates
r1 = self%n1%getCoordinates() r1 = self%n1%getCoordinates()
r2 = self%n2%getCoordinates() r2 = self%n2%getCoordinates()
@ -1052,7 +1054,7 @@ MODULE moduleMesh2DCyl
SUBROUTINE connectMesh2DCyl(self) SUBROUTINE connectMesh2DCyl(self)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshParticle), INTENT(inout):: self CLASS(meshGeneric), INTENT(inout):: self
INTEGER:: e, et INTEGER:: e, et
DO e = 1, self%numVols DO e = 1, self%numVols
@ -1065,11 +1067,15 @@ MODULE moduleMesh2DCyl
END DO END DO
!Connect Vol-Edge SELECT TYPE(self)
DO et = 1, self%numEdges TYPE IS(meshParticles)
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj) !Connect Vol-Edge
DO et = 1, self%numEdges
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj)
END DO END DO
END SELECT
END DO END DO

View file

@ -248,21 +248,22 @@ MODULE moduleMesh3DCart
!VOLUME FUNCTIONS !VOLUME FUNCTIONS
!TETRA FUNCTIONS !TETRA FUNCTIONS
!Inits tetrahedron element !Inits tetrahedron element
SUBROUTINE initVolTetra3DCart(self, n, p) SUBROUTINE initVolTetra3DCart(self, n, p, nodes)
USE moduleRefParam USE moduleRefParam
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVol3DCartTetra), INTENT(out):: self CLASS(meshVol3DCartTetra), INTENT(out):: self
INTEGER, INTENT(in):: n INTEGER, INTENT(in):: n
INTEGER, INTENT(in):: p(:) INTEGER, INTENT(in):: p(:)
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
REAL(8), DIMENSION(1:3):: r1, r2, r3, r4 !Positions of each node REAL(8), DIMENSION(1:3):: r1, r2, r3, r4 !Positions of each node
REAL(8):: volNodes(1:4) !Volume of each node REAL(8):: volNodes(1:4) !Volume of each node
self%n = n self%n = n
self%n1 => mesh%nodes(p(1))%obj self%n1 => nodes(p(1))%obj
self%n2 => mesh%nodes(p(2))%obj self%n2 => nodes(p(2))%obj
self%n3 => mesh%nodes(p(3))%obj self%n3 => nodes(p(3))%obj
self%n4 => mesh%nodes(p(4))%obj self%n4 => nodes(p(4))%obj
!Get element coordinates !Get element coordinates
r1 = self%n1%getCoordinates() r1 = self%n1%getCoordinates()
r2 = self%n2%getCoordinates() r2 = self%n2%getCoordinates()
@ -707,7 +708,7 @@ MODULE moduleMesh3DCart
SUBROUTINE connectMesh3DCart(self) SUBROUTINE connectMesh3DCart(self)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshParticle), INTENT(inout):: self CLASS(meshGeneric), INTENT(inout):: self
INTEGER:: e, et INTEGER:: e, et
DO e = 1, self%numVols DO e = 1, self%numVols
@ -720,11 +721,15 @@ MODULE moduleMesh3DCart
END DO END DO
!Connect Vol-Edge SELECT TYPE(self)
DO et = 1, self%numEdges TYPE IS(meshParticles)
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj) !Connect Vol-Edge
DO et = 1, self%numEdges
CALL connectVolEdge(self%vols(e)%obj, self%edges(et)%obj)
END DO END DO
END SELECT
END DO END DO

View file

@ -7,11 +7,15 @@ MODULE moduleMeshInputGmsh2
USE moduleMeshOutputGmsh2 USE moduleMeshOutputGmsh2
IMPLICIT NONE IMPLICIT NONE
TYPE(meshParticle), INTENT(inout):: self CLASS(meshGeneric), INTENT(inout), TARGET:: self
self%printOutput => printOutputGmsh2 IF (ASSOCIATED(meshForMCC, self)) self%printColl => printCollGmsh2
self%printColl => printCollGmsh2 SELECT TYPE(self)
self%printEM => printEMGmsh2 TYPE IS(meshParticles)
self%printOutput => printOutputGmsh2
self%printEM => printEMGmsh2
END SELECT
self%readMesh => readGmsh2 self%readMesh => readGmsh2
END SUBROUTINE initGmsh2 END SUBROUTINE initGmsh2
@ -26,12 +30,13 @@ MODULE moduleMeshInputGmsh2
USE moduleBoundary USE moduleBoundary
IMPLICIT NONE IMPLICIT NONE
CLASS(meshParticle), INTENT(inout):: self CLASS(meshGeneric), INTENT(inout):: self
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
REAL(8):: x1, x2, x3 !3 generic coordinates REAL(8):: r(1:3) !3 generic coordinates
INTEGER, ALLOCATABLE:: p(:) !Array for nodes INTEGER, ALLOCATABLE:: p(:) !Array for nodes
INTEGER:: e = 0, n = 0, eTemp = 0, elemType = 0, bt = 0 INTEGER:: e = 0, n = 0, eTemp = 0, elemType = 0, bt = 0
INTEGER:: totalNumElem INTEGER:: totalNumElem
INTEGER:: numEdges
INTEGER:: boundaryType INTEGER:: boundaryType
!Read mesh !Read mesh
@ -48,39 +53,44 @@ MODULE moduleMeshInputGmsh2
!Allocate required matrices and vectors !Allocate required matrices and vectors
ALLOCATE(self%nodes(1:self%numNodes)) ALLOCATE(self%nodes(1:self%numNodes))
ALLOCATE(self%K(1:self%numNodes, 1:self%numNodes)) SELECT TYPE(self)
ALLOCATE(self%IPIV(1:self%numNodes, 1:self%numNodes)) TYPE IS(meshParticles)
self%K = 0.D0 ALLOCATE(self%K(1:self%numNodes, 1:self%numNodes))
self%IPIV = 0 ALLOCATE(self%IPIV(1:self%numNodes, 1:self%numNodes))
self%K = 0.D0
self%IPIV = 0
END SELECT
!Read the nodes information !Read the nodes information
DO e = 1, self%numNodes DO e = 1, self%numNodes
READ(10, *) n, x1, x2, x3 READ(10, *) n, r(1), r(2), r(3)
SELECT CASE(self%geometry) SELECT CASE(self%geometry)
CASE("3DCart") CASE("3DCart")
ALLOCATE(meshNode3Dcart::self%nodes(n)%obj) ALLOCATE(meshNode3Dcart::self%nodes(n)%obj)
CALL self%nodes(n)%obj%init(n, (/x1, x2, x3 /))
CASE("2DCyl") CASE("2DCyl")
ALLOCATE(meshNode2DCyl:: self%nodes(n)%obj) ALLOCATE(meshNode2DCyl:: self%nodes(n)%obj)
CALL self%nodes(n)%obj%init(n, (/x1, x2, 0.D0 /)) r(3) = 0.D0
CASE("2DCart") CASE("2DCart")
ALLOCATE(meshNode2DCart:: self%nodes(n)%obj) ALLOCATE(meshNode2DCart:: self%nodes(n)%obj)
CALL self%nodes(n)%obj%init(n, (/x1, x2, 0.D0 /)) r(3) = 0.D0
CASE("1DRad") CASE("1DRad")
ALLOCATE(meshNode1DRad:: self%nodes(n)%obj) ALLOCATE(meshNode1DRad:: self%nodes(n)%obj)
CALL self%nodes(n)%obj%init(n, (/x1, 0.D0, 0.D0 /)) r(2:3) = 0.D0
CASE("1DCart") CASE("1DCart")
ALLOCATE(meshNode1DCart:: self%nodes(n)%obj) ALLOCATE(meshNode1DCart:: self%nodes(n)%obj)
CALL self%nodes(n)%obj%init(n, (/x1, 0.D0, 0.D0 /)) r(2:3) = 0.D0
END SELECT END SELECT
CALL self%nodes(n)%obj%init(n, r)
END DO END DO
!Skip comments !Skip comments
READ(10, *) READ(10, *)
READ(10, *) READ(10, *)
@ -89,118 +99,116 @@ MODULE moduleMeshInputGmsh2
READ(10, *) totalNumElem READ(10, *) totalNumElem
!conts edges and volume elements !conts edges and volume elements
self%numEdges = 0 SELECT TYPE(self)
DO e = 1, totalNumElem TYPE IS(meshParticles)
READ(10, *) eTemp, elemType self%numEdges = 0
SELECT CASE(self%geometry) DO e = 1, totalNumElem
CASE("3DCart") READ(10, *) eTemp, elemType
!Element type 2 is triangle in gmsh SELECT CASE(self%geometry)
IF (elemType == 2) self%numEdges = e CASE("3DCart")
!Element type 2 is triangle in gmsh
IF (elemType == 2) self%numEdges = e
CASE("2DCyl","2DCart") CASE("2DCyl","2DCart")
!Element type 1 is segment in Gmsh !Element type 1 is segment in Gmsh
IF (elemType == 1) self%numEdges = e IF (elemType == 1) self%numEdges = e
CASE("1DRad","1DCart") CASE("1DRad","1DCart")
!Element type 15 is physical point in Gmsh !Element type 15 is physical point in Gmsh
IF (elemType == 15) self%numEdges = e IF (elemType == 15) self%numEdges = e
END SELECT
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
!Reads the edge according to the geometry
SELECT CASE(self%geometry)
CASE("3DCart")
READ(10, *) n, elemType, eTemp, boundaryType
BACKSPACE(10)
!Associate boundary condition procedure.
bt = getBoundaryID(boundaryType)
SELECT CASE(elemType)
CASE(2)
!Triangular surface
ALLOCATE(p(1:3))
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1:3)
ALLOCATE(meshEdge3DCartTria:: self%edges(e)%obj)
CALL self%edges(e)%obj%init(n, p(1:3), bt, boundaryType)
DEALLOCATE(p)
END SELECT END SELECT
CASE("2DCyl") END DO
ALLOCATE(p(1:2))
READ(10,*) n, elemType, eTemp, boundaryType, eTemp, p(1:2) !Substract the number of edges to the total number of elements
!Associate boundary condition procedure. !to obtain the number of volume elements
bt = getBoundaryId(boundaryType) self%numVols = TotalnumElem - self%numEdges
ALLOCATE(self%edges(1:self%numEdges))
numEdges = self%numEdges
ALLOCATE(meshEdge2DCyl:: self%edges(e)%obj) !Go back to the beggining to read elements
DO e=1, totalNumElem
BACKSPACE(10)
END DO
CALL self%edges(e)%obj%init(n, p(1:2), bt, boundaryType) TYPE IS(meshCollisions)
self%numVols = TotalnumElem
numEdges = 0
END SELECT
!Allocates arrays
ALLOCATE(self%vols(1:self%numVols))
SELECT TYPE(self)
TYPE IS(meshParticles)
!Reads edges
DO e=1, self%numEdges
!Reads the edge according to the geometry
SELECT CASE(self%geometry)
CASE("3DCart")
READ(10, *) n, elemType, eTemp, boundaryType
BACKSPACE(10)
!Associate boundary condition procedure.
bt = getBoundaryID(boundaryType)
SELECT CASE(elemType)
CASE(2)
!Triangular surface
ALLOCATE(p(1:3))
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1:3)
ALLOCATE(meshEdge3DCartTria:: self%edges(e)%obj)
END SELECT
CASE("2DCyl")
ALLOCATE(p(1:2))
READ(10,*) n, elemType, eTemp, boundaryType, eTemp, p(1:2)
!Associate boundary condition procedure.
bt = getBoundaryId(boundaryType)
ALLOCATE(meshEdge2DCyl:: self%edges(e)%obj)
CASE("2DCart")
ALLOCATE(p(1:2))
READ(10,*) n, elemType, eTemp, boundaryType, eTemp, p(1:2)
!Associate boundary condition procedure.
bt = getBoundaryId(boundaryType)
ALLOCATE(meshEdge2DCart:: self%edges(e)%obj)
CASE("1DRad")
ALLOCATE(p(1:1))
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1)
!Associate boundary condition
bt = getBoundaryId(boundaryType)
ALLOCATE(meshEdge1DRad:: self%edges(e)%obj)
CASE("1DCart")
ALLOCATE(p(1:1))
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1)
!Associate boundary condition
bt = getBoundaryId(boundaryType)
ALLOCATE(meshEdge1DCart:: self%edges(e)%obj)
END SELECT
CALL self%edges(e)%obj%init(n, p, bt, boundaryType)
DEALLOCATE(p) DEALLOCATE(p)
CASE("2DCart") END DO
ALLOCATE(p(1:2))
READ(10,*) n, elemType, eTemp, boundaryType, eTemp, p(1:2) END SELECT
!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)
DEALLOCATE(p)
CASE("1DRad")
ALLOCATE(p(1:1))
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1)
!Associate boundary condition
bt = getBoundaryId(boundaryType)
ALLOCATE(meshEdge1DRad:: self%edges(e)%obj)
CALL self%edges(e)%obj%init(n, p(1:1), bt, boundaryType)
DEALLOCATE(p)
CASE("1DCart")
ALLOCATE(p(1:1))
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1)
!Associate boundary condition
bt = getBoundaryId(boundaryType)
ALLOCATE(meshEdge1DCart:: self%edges(e)%obj)
CALL self%edges(e)%obj%init(n, p(1:1), bt, boundaryType)
DEALLOCATE(p)
END SELECT
END DO
!Read and initialize volumes !Read and initialize volumes
DO e = 1, self%numVols DO e = 1, self%numVols
@ -216,12 +224,9 @@ MODULE moduleMeshInputGmsh2
ALLOCATE(p(1:4)) ALLOCATE(p(1:4))
READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:4) READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:4)
ALLOCATE(meshVol3DCartTetra:: self%vols(e)%obj) ALLOCATE(meshVol3DCartTetra:: self%vols(e)%obj)
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:4))
END SELECT END SELECT
DEALLOCATE(p)
CASE("2DCyl") CASE("2DCyl")
READ(10,*) n, elemType READ(10,*) n, elemType
BACKSPACE(10) BACKSPACE(10)
@ -232,19 +237,15 @@ MODULE moduleMeshInputGmsh2
ALLOCATE(p(1:3)) ALLOCATE(p(1:3))
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:3) READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:3)
ALLOCATE(meshVol2DCylTria:: self%vols(e)%obj) ALLOCATE(meshVol2DCylTria:: self%vols(e)%obj)
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:3))
CASE (3) CASE (3)
!Quadrilateral element !Quadrilateral element
ALLOCATE(p(1:4)) ALLOCATE(p(1:4))
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:4) READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:4)
ALLOCATE(meshVol2DCylQuad:: self%vols(e)%obj) ALLOCATE(meshVol2DCylQuad:: self%vols(e)%obj)
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:4))
END SELECT END SELECT
DEALLOCATE(p)
CASE("2DCart") CASE("2DCart")
READ(10,*) n, elemType READ(10,*) n, elemType
BACKSPACE(10) BACKSPACE(10)
@ -255,41 +256,36 @@ MODULE moduleMeshInputGmsh2
ALLOCATE(p(1:3)) ALLOCATE(p(1:3))
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:3) READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:3)
ALLOCATE(meshVol2DCartTria:: self%vols(e)%obj) ALLOCATE(meshVol2DCartTria:: self%vols(e)%obj)
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:3))
CASE (3) CASE (3)
!Quadrilateral element !Quadrilateral element
ALLOCATE(p(1:4)) ALLOCATE(p(1:4))
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:4) READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:4)
ALLOCATE(meshVol2DCartQuad:: self%vols(e)%obj) ALLOCATE(meshVol2DCartQuad:: self%vols(e)%obj)
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:4))
END SELECT END SELECT
DEALLOCATE(p)
CASE("1DRad") CASE("1DRad")
ALLOCATE(p(1:2)) ALLOCATE(p(1:2))
READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:2) READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:2)
ALLOCATE(meshVol1DRadSegm:: self%vols(e)%obj) ALLOCATE(meshVol1DRadSegm:: self%vols(e)%obj)
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:2))
DEALLOCATE(p)
CASE("1DCart") CASE("1DCart")
ALLOCATE(p(1:2)) ALLOCATE(p(1:2))
READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:2) READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:2)
ALLOCATE(meshVol1DCartSegm:: self%vols(e)%obj) ALLOCATE(meshVol1DCartSegm:: self%vols(e)%obj)
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:2))
DEALLOCATE(p)
END SELECT END SELECT
CALL self%vols(e)%obj%init(n - numEdges, p, self%nodes)
DEALLOCATE(p)
END DO END DO
CLOSE(10)
END SUBROUTINE readGmsh2 END SUBROUTINE readGmsh2
END MODULE moduleMeshInputGmsh2 END MODULE moduleMeshInputGmsh2

View file

@ -9,7 +9,7 @@ MODULE moduleMeshOutputGmsh2
USE moduleOutput USE moduleOutput
IMPLICIT NONE IMPLICIT NONE
CLASS(meshParticle), INTENT(in):: self CLASS(meshParticles), INTENT(in):: self
INTEGER, INTENT(in):: t INTEGER, INTENT(in):: t
INTEGER:: n, i INTEGER:: n, i
TYPE(outputFormat):: output(1:self%numNodes) TYPE(outputFormat):: output(1:self%numNodes)
@ -95,13 +95,25 @@ MODULE moduleMeshOutputGmsh2
USE moduleOutput USE moduleOutput
IMPLICIT NONE IMPLICIT NONE
CLASS(meshParticle), INTENT(in):: self CLASS(meshGeneric), INTENT(in):: self
INTEGER:: numEdges
INTEGER, INTENT(in):: t INTEGER, INTENT(in):: t
INTEGER:: n INTEGER:: n
REAL(8):: time REAL(8):: time
CHARACTER(:), ALLOCATABLE:: fileName CHARACTER(:), ALLOCATABLE:: fileName
CHARACTER (LEN=iterationDigits):: tstring CHARACTER (LEN=iterationDigits):: tstring
SELECT TYPE(self)
TYPE IS(meshParticles)
numEdges = self%numEdges
TYPE IS(meshCollisions)
numEdges = 0
CLASS DEFAULT
numEdges = 0
END SELECT
IF (collOutput) THEN IF (collOutput) THEN
time = DBLE(t)*tauMin*ti_ref time = DBLE(t)*tauMin*ti_ref
@ -123,7 +135,7 @@ MODULE moduleMeshOutputGmsh2
WRITE(60, *) 1 WRITE(60, *) 1
WRITE(60, *) self%numVols WRITE(60, *) self%numVols
DO n=1, self%numVols DO n=1, self%numVols
WRITE(60, "(I6,I10)") n + self%numEdges, self%vols(n)%obj%nColl WRITE(60, "(I6,I10)") n + numEdges, self%vols(n)%obj%nColl
END DO END DO
WRITE(60, "(A)") '$EndElementData' WRITE(60, "(A)") '$EndElementData'
@ -141,7 +153,7 @@ MODULE moduleMeshOutputGmsh2
USE moduleOutput USE moduleOutput
IMPLICIT NONE IMPLICIT NONE
CLASS(meshParticle), INTENT(in):: self CLASS(meshParticles), INTENT(in):: self
INTEGER, INTENT(in):: t INTEGER, INTENT(in):: t
INTEGER:: n, e INTEGER:: n, e
REAL(8):: time REAL(8):: time

View file

@ -65,6 +65,8 @@ MODULE moduleMesh
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshElement):: meshEdge TYPE, PUBLIC, ABSTRACT, EXTENDS(meshElement):: meshEdge
!Connectivity to vols !Connectivity to vols
CLASS(meshVol), POINTER:: e1 => NULL(), e2 => NULL() CLASS(meshVol), POINTER:: e1 => NULL(), e2 => NULL()
!Connectivity to vols in meshColl
CLASS(meshVol), POINTER:: eColl => NULL()
!Normal vector !Normal vector
REAL(8):: normal(1:3) REAL(8):: normal(1:3)
!Weight for random injection of particles !Weight for random injection of particles
@ -153,8 +155,6 @@ MODULE moduleMesh
INTEGER(KIND=OMP_LOCK_KIND):: lock INTEGER(KIND=OMP_LOCK_KIND):: lock
!Number of collisions per volume !Number of collisions per volume
INTEGER:: nColl = 0 INTEGER:: nColl = 0
!Collisional fraction
REAL(8):: collFrac = 0.D0
!Total weight of particles inside cell !Total weight of particles inside cell
REAL(8):: totalWeight = 0.D0 REAL(8):: totalWeight = 0.D0
CONTAINS CONTAINS
@ -169,16 +169,17 @@ MODULE moduleMesh
PROCEDURE(phy2log_interface), DEFERRED, PASS:: phy2log PROCEDURE(phy2log_interface), DEFERRED, PASS:: phy2log
PROCEDURE(inside_interface), DEFERRED, NOPASS:: inside PROCEDURE(inside_interface), DEFERRED, NOPASS:: inside
PROCEDURE(nextElement_interface), DEFERRED, PASS:: nextElement PROCEDURE(nextElement_interface), DEFERRED, PASS:: nextElement
PROCEDURE, PASS:: collision
END TYPE meshVol END TYPE meshVol
ABSTRACT INTERFACE ABSTRACT INTERFACE
SUBROUTINE initVol_interface(self, n, p) SUBROUTINE initVol_interface(self, n, p, nodes)
IMPORT:: meshVol IMPORT:: meshVol
IMPORT meshNodeCont
CLASS(meshVol), INTENT(out):: self CLASS(meshVol), INTENT(out):: self
INTEGER, INTENT(in):: n INTEGER, INTENT(in):: n
INTEGER, INTENT(in):: p(:) INTEGER, INTENT(in):: p(:)
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
END SUBROUTINE initVol_interface END SUBROUTINE initVol_interface
@ -260,80 +261,143 @@ MODULE moduleMesh
END TYPE meshVolCont END TYPE meshVolCont
!Particle mesh !Generic mesh type
TYPE, PUBLIC:: meshParticle TYPE, ABSTRACT:: meshGeneric
INTEGER:: numEdges, numNodes, numVols
!Array of nodes
TYPE(meshNodeCont), ALLOCATABLE:: nodes(:)
!Array of boundary elements
TYPE(meshEdgeCont), ALLOCATABLE:: edges(:)
!Array of volume elements
TYPE(meshVolCont), ALLOCATABLE:: vols(:)
!Geometry of the mesh !Geometry of the mesh
CHARACTER(:), ALLOCATABLE:: geometry CHARACTER(:), ALLOCATABLE:: geometry
!Number of elements
INTEGER:: numNodes, numVols
!Array of nodes
TYPE(meshNodeCont), ALLOCATABLE:: nodes(:)
!Array of volume elements
TYPE(meshVolCont), ALLOCATABLE:: vols(:)
PROCEDURE(readMesh_interface), POINTER, PASS:: readMesh => NULL()
PROCEDURE(connectMesh_interface), POINTER, PASS:: connectMesh => NULL()
PROCEDURE(printColl_interface), POINTER, PASS:: printColl => NULL()
CONTAINS
PROCEDURE, PASS:: doCollisions
END TYPE
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
!Connects volume 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 volume
SUBROUTINE printColl_interface(self, t)
IMPORT meshGeneric
CLASS(meshGeneric), INTENT(in):: self
INTEGER, INTENT(in):: t
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 !Global stiffness matrix
REAL(8), ALLOCATABLE, DIMENSION(:,:):: K REAL(8), ALLOCATABLE, DIMENSION(:,:):: K
!Permutation matrix for P L U factorization !Permutation matrix for P L U factorization
INTEGER, ALLOCATABLE, DIMENSION(:,:):: IPIV INTEGER, ALLOCATABLE, DIMENSION(:,:):: IPIV
PROCEDURE(printOutput_interface), POINTER, PASS:: printOutput => NULL() PROCEDURE(printOutput_interface), POINTER, PASS:: printOutput => NULL()
PROCEDURE(printColl_interface), POINTER, PASS:: printColl => NULL()
PROCEDURE(printEM_interface), POINTER, PASS:: printEM => NULL() PROCEDURE(printEM_interface), POINTER, PASS:: printEM => NULL()
PROCEDURE(readMesh_interface), POINTER, PASS:: readMesh => NULL() PROCEDURE(doCoulomb_interface), POINTER, PASS:: doCoulomb => NULL()
PROCEDURE(connectMesh_interface), POINTER, PASS:: connectMesh => NULL()
CONTAINS CONTAINS
PROCEDURE, PASS:: constructGlobalK PROCEDURE, PASS:: constructGlobalK
END TYPE meshParticle END TYPE meshParticles
ABSTRACT INTERFACE ABSTRACT INTERFACE
!Perform Coulomb Scattering
SUBROUTINE doCoulomb_interface(self)
IMPORT meshParticles
CLASS(meshParticles), INTENT(inout):: self
END SUBROUTINE doCoulomb_interface
!Prints Species data !Prints Species data
SUBROUTINE printOutput_interface(self, t) SUBROUTINE printOutput_interface(self, t)
IMPORT meshParticle IMPORT meshParticles
CLASS(meshParticle), INTENT(in):: self CLASS(meshParticles), INTENT(in):: self
INTEGER, INTENT(in):: t INTEGER, INTENT(in):: t
END SUBROUTINE printOutput_interface END SUBROUTINE printOutput_interface
!Prints number of collisions
SUBROUTINE printColl_interface(self, t)
IMPORT meshParticle
CLASS(meshParticle), INTENT(in):: self
INTEGER, INTENT(in):: t
END SUBROUTINE printColl_interface
!Prints EM info !Prints EM info
SUBROUTINE printEM_interface(self, t) SUBROUTINE printEM_interface(self, t)
IMPORT meshParticle IMPORT meshParticles
CLASS(meshParticle), INTENT(in):: self CLASS(meshParticles), INTENT(in):: self
INTEGER, INTENT(in):: t INTEGER, INTENT(in):: t
END SUBROUTINE printEM_interface END SUBROUTINE printEM_interface
!Reads the mesh from a file
SUBROUTINE readMesh_interface(self, filename)
IMPORT meshParticle
CLASS(meshParticle), INTENT(inout):: self
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
END SUBROUTINE readMesh_interface
SUBROUTINE connectMesh_interface(self)
IMPORT meshParticle
CLASS(meshParticle), INTENT(inout):: self
END SUBROUTINE connectMesh_interface
END INTERFACE END INTERFACE
!Particle mesh TYPE(meshParticles), TARGET:: mesh
TYPE(meshParticle), TARGET:: mesh
!Collision (MCC) mesh
TYPE, EXTENDS(meshGeneric):: meshCollisions
CONTAINS
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 volume for a particle in meshColl
PROCEDURE(findCellColl_interface), POINTER:: findCellColl => NULL()
ABSTRACT INTERFACE
SUBROUTINE findCellColl_interface(part)
USE moduleSpecies
TYPE(particle), INTENT(inout):: part
END SUBROUTINE findCellColl_interface
END INTERFACE
CONTAINS CONTAINS
!Reset the output of node !Reset the output of node
@ -362,8 +426,8 @@ MODULE moduleMesh
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVol), INTENT(inout):: self CLASS(meshVol), INTENT(inout):: self
CLASS(meshVol), OPTIONAL, INTENT(in):: oldCell
CLASS(particle), INTENT(inout), TARGET:: part CLASS(particle), INTENT(inout), TARGET:: part
CLASS(meshVol), OPTIONAL, INTENT(in):: oldCell
REAL(8):: xi(1:3) REAL(8):: xi(1:3)
CLASS(meshElement), POINTER:: nextElement CLASS(meshElement), POINTER:: nextElement
@ -408,12 +472,96 @@ MODULE moduleMesh
CALL criticalError("No connectivity found for element", "findCell") CALL criticalError("No connectivity found for element", "findCell")
END SELECT END SELECT
END IF END IF
END SUBROUTINE findCell END SUBROUTINE findCell
!If Coll and Particle are the same, simply copy the part%vol into part%volColl
SUBROUTINE findCellSameMesh(part)
USE moduleSpecies
IMPLICIT NONE
TYPE(particle), INTENT(inout):: part
part%volColl = part%vol
END SUBROUTINE findCellSameMesh
!TODO: try to combine this with the findCell for a regular mesh
!Find the volume in which particle reside in the mesh for collisions
SUBROUTINE findCellCollMesh(part)
USE moduleSpecies
IMPLICIT NONE
TYPE(particle), INTENT(inout):: part
LOGICAL:: found
CLASS(meshVol), POINTER:: vol
REAL(8), DIMENSION(1:3):: xii
CLASS(meshElement), POINTER:: nextElement
found = .FALSE.
vol => meshColl%vols(part%volColl)%obj
DO WHILE(.NOT. found)
xii = vol%phy2log(part%r)
IF (vol%inside(xii)) THEN
part%volColl = vol%n
CALL OMP_SET_LOCK(vol%lock)
CALL vol%listPart_in%add(part)
vol%totalWeight = vol%totalWeight + part%weight
CALL OMP_UNSET_LOCK(vol%lock)
found = .TRUE.
ELSE
CALL vol%nextElement(xii, nextElement)
SELECT TYPE(nextElement)
CLASS IS(meshVol)
!Try next element
vol => nextElement
CLASS DEFAULT
!Should never happend, but just in case, stops loops
found = .TRUE.
END SELECT
END IF
END DO
END SUBROUTINE findCellCollMesh
!Returns index of volume associated to a position (if any)
!If no voulme is found, returns 0
!WARNING: This function is slow and should only be used in initialization phase
FUNCTION findCellBrute(self, r) RESULT(nVol)
USE moduleSpecies
IMPLICIT NONE
CLASS(meshGeneric), INTENT(in):: self
REAL(8), DIMENSION(1:3), INTENT(in):: r
INTEGER:: nVol
INTEGER:: e
REAL(8), DIMENSION(1:3):: xii
!Inits RESULT
nVol = 0
DO e = 1, self%numVols
xii = self%vols(e)%obj%phy2log(r)
IF(self%vols(e)%obj%inside(xii)) THEN
nVol = self%vols(e)%obj%n
EXIT
END IF
END DO
END FUNCTION findCellBrute
!Computes collisions in element !Computes collisions in element
SUBROUTINE collision(self) SUBROUTINE doCollisions(self)
USE moduleCollisions USE moduleCollisions
USE moduleSpecies USE moduleSpecies
USE moduleList USE moduleList
@ -421,7 +569,9 @@ MODULE moduleMesh
USE moduleRandom USE moduleRandom
IMPLICIT NONE IMPLICIT NONE
CLASS(meshVol), INTENT(inout):: self CLASS(meshGeneric), INTENT(inout), TARGET:: self
INTEGER:: e
CLASS(meshVol), POINTER:: vol
INTEGER:: nPart !Number of particles inside the cell INTEGER:: nPart !Number of particles inside the cell
REAL(8):: pMax !Maximum probability of collision REAL(8):: pMax !Maximum probability of collision
INTEGER:: rnd !random index INTEGER:: rnd !random index
@ -431,57 +581,57 @@ MODULE moduleMesh
REAL(8):: sigmaVrelMaxNew REAL(8):: sigmaVrelMaxNew
TYPE(pointerArray), ALLOCATABLE:: partTemp(:) TYPE(pointerArray), ALLOCATABLE:: partTemp(:)
nPart = self%listPart_in%amount !$OMP DO SCHEDULE(DYNAMIC)
!Computes iterations if there is more than one particle in the cell DO e=1, self%numVols
IF (nPart > 1) THEN vol => self%vols(e)%obj
!Probability of collision nPart = vol%listPart_in%amount
pMax = self%totalWeight*self%sigmaVrelMax*tauMin/self%volume !Computes iterations if there is more than one particle in the cell
IF (nPart > 1) THEN
!Probability of collision
pMax = vol%totalWeight*vol%sigmaVrelMax*tauMin/vol%volume
!Increases the collisional fraction of the cell !Number of collisions in the cell
self%collFrac = self%collFrac + REAL(nPart)*pMax*0.5D0 vol%nColl = NINT(REAL(nPart)*pMax*0.5D0)
!Number of collisions in the cell IF (vol%nColl > 0) THEN
self%nColl = FLOOR(self%collFrac) !Converts the list of particles to an array for easy access
partTemp = vol%listPart_in%convert2Array()
IF (self%nColl > 0) THEN
!Converts the list of particles to an array for easy access
partTemp = self%listPart_in%convert2Array()
END IF
DO n = 1, self%nColl
!Select random numbers
rnd = random(1, nPart)
part_i => partTemp(rnd)%part
rnd = random(1, nPart)
part_j => partTemp(rnd)%part
ij = interactionIndex(part_i%species%n, part_j%species%n)
sigmaVrelMaxNew = 0.D0
DO k = 1, interactionMatrix(ij)%amount
CALL interactionMatrix(ij)%collisions(k)%obj%collide(self%sigmaVrelMax, sigmaVrelMaxNew, part_i, part_j)
END DO
!Update maximum cross section*v_rel per each collision
IF (sigmaVrelMaxNew > self%sigmaVrelMax) THEN
self%sigmaVrelMax = sigmaVrelMaxNew
END IF END IF
!Removes one collision from the collisional fraction DO n = 1, vol%nColl
self%collFrac = self%collFrac - 1.D0 !Select random numbers
rnd = random(1, nPart)
part_i => partTemp(rnd)%part
rnd = random(1, nPart)
part_j => partTemp(rnd)%part
ij = interactionIndex(part_i%species%n, part_j%species%n)
sigmaVrelMaxNew = 0.D0
DO k = 1, interactionMatrix(ij)%amount
CALL interactionMatrix(ij)%collisions(k)%obj%collide(vol%sigmaVrelMax, sigmaVrelMaxNew, part_i, part_j)
END DO END DO
END IF !Update maximum cross section*v_rel per each collision
IF (sigmaVrelMaxNew > vol%sigmaVrelMax) THEN
vol%sigmaVrelMax = sigmaVrelMaxNew
END SUBROUTINE collision END IF
END DO
END IF
END DO
!$OMP END DO
END SUBROUTINE doCollisions
!Constructs the global K matrix !Constructs the global K matrix
SUBROUTINE constructGlobalK(self) SUBROUTINE constructGlobalK(self)
IMPLICIT NONE IMPLICIT NONE
CLASS(meshParticle), INTENT(inout):: self CLASS(meshParticles), INTENT(inout):: self
INTEGER:: e INTEGER:: e
INTEGER, ALLOCATABLE:: n(:) INTEGER, ALLOCATABLE:: n(:)
REAL(8), ALLOCATABLE:: localK(:,:) REAL(8), ALLOCATABLE:: localK(:,:)

View file

@ -320,6 +320,7 @@ MODULE moduleCollisions
newElectron%xi = neutral%xi newElectron%xi = neutral%xi
newElectron%n_in = .TRUE. newElectron%n_in = .TRUE.
newElectron%vol = neutral%vol newElectron%vol = neutral%vol
newElectron%volColl = neutral%volColl
newElectron%weight = neutral%weight newElectron%weight = neutral%weight
newElectron%qm = electron%qm newElectron%qm = electron%qm

View file

@ -1,11 +1,12 @@
!Information to calculate computation time !Information to calculate computation time
MODULE moduleCompTime MODULE moduleCompTime
REAL(8):: tStep=0.D0 REAL(8):: tStep = 0.D0
REAL(8):: tPush=0.D0 REAL(8):: tPush = 0.D0
REAL(8):: tReset=0.D0 REAL(8):: tReset = 0.D0
REAL(8):: tColl=0.D0 REAL(8):: tColl = 0.D0
REAL(8):: tWeight=0.D0 REAL(8):: tCoul = 0.D0
REAL(8):: tEMField=0.D0 REAL(8):: tWeight = 0.D0
REAL(8):: tEMField = 0.D0
END MODULE moduleCompTime END MODULE moduleCompTime

View file

@ -86,6 +86,7 @@ MODULE moduleInject
CHARACTER(:), ALLOCATABLE, INTENT(in):: units CHARACTER(:), ALLOCATABLE, INTENT(in):: units
INTEGER:: e, et INTEGER:: e, et
INTEGER:: phSurface(1:mesh%numEdges) INTEGER:: phSurface(1:mesh%numEdges)
INTEGER:: nVolColl
self%id = i self%id = i
self%vMod = v/v_ref self%vMod = v/v_ref
@ -125,6 +126,27 @@ MODULE moduleInject
IF (mesh%edges(e)%obj%physicalSurface == physicalSurface) THEN IF (mesh%edges(e)%obj%physicalSurface == physicalSurface) THEN
et = et + 1 et = et + 1
self%edges(et) = mesh%edges(e)%obj%n self%edges(et) = mesh%edges(e)%obj%n
!Assign connectivity between injection edge and meshColl volume
IF (ASSOCIATED(meshForMCC, meshColl)) THEN
nVolColl = findCellBrute(meshColl, mesh%edges(e)%obj%randPos())
IF (nVolColl > 0) THEN
mesh%edges(e)%obj%eColl => meshColl%vols(nVolColl)%obj
ELSE
CALL criticalError("No connection between edge and meshColl", "initInject")
END IF
ELSE
IF (ASSOCIATED(mesh%edges(e)%obj%e1)) THEN
mesh%edges(e)%obj%eColl => mesh%edges(e)%obj%e1
ELSE
mesh%edges(e)%obj%eColl => mesh%edges(e)%obj%e2
END IF
END IF
END IF END IF
@ -255,6 +277,7 @@ MODULE moduleInject
CALL criticalError("No Volume associated to edge", 'addParticles') CALL criticalError("No Volume associated to edge", 'addParticles')
END IF END IF
partInj(n)%volColl = randomEdge%eColl%n
!Assign particle type !Assign particle type
partInj(n)%species => self%species partInj(n)%species => self%species

View file

@ -59,7 +59,7 @@ MODULE moduleInput
CALL checkStatus(config, "readCase") CALL checkStatus(config, "readCase")
!Read injection of particles !Read injection of particles
CALL verboseError('Reading Interactions between species...') CALL verboseError('Reading injection of particles from boundaries...')
CALL readInject(config) CALL readInject(config)
CALL checkStatus(config, "readInject") CALL checkStatus(config, "readInject")
@ -483,7 +483,6 @@ MODULE moduleInput
END DO END DO
!Set number of particles to 0 for init state !Set number of particles to 0 for init state
!TODO: In a future, this should include the particles from init states
nPartOld = 0 nPartOld = 0
!Initialize the lock for the non-analogue (NA) list of particles !Initialize the lock for the non-analogue (NA) list of particles
@ -497,6 +496,7 @@ MODULE moduleInput
USE moduleList USE moduleList
USE moduleCollisions USE moduleCollisions
USE moduleErrors USE moduleErrors
USE moduleMesh
USE OMP_LIB USE OMP_LIB
USE json_module USE json_module
IMPLICIT NONE IMPLICIT NONE
@ -515,74 +515,98 @@ MODULE moduleInput
REAL(8):: energyThreshold, energyBinding REAL(8):: energyThreshold, energyBinding
CHARACTER(:), ALLOCATABLE:: electron CHARACTER(:), ALLOCATABLE:: electron
CALL initInteractionMatrix(interactionMatrix) !Firstly, checks if the object 'interactions' exists
CALL config%info('interactions', found)
IF (found) THEN
!Checks if MC collisions have been defined
CALL config%info('interactions.collisions', found)
IF (found) THEN
!Checks if a mesh for collisions has been defined
!The mesh will be initialized and reader in readGeometry
CALL config%info('interactions.meshCollisions', found)
IF (found) THEN
!Points meshForMCC to the specific mesh defined
meshForMCC => meshColl
!Path for collision cross-section data files ELSE
CALL config%get('interactions.folderCollisions', pathCollisions, found) !Points the meshForMCC pointer to the Particles Mesh
meshForMCC => mesh
!Inits lock for list of particles END IF
CALL OMP_INIT_LOCK(lockCollisions)
CALL config%info('interactions.collisions', found, n_children = nInteractions) !Inits the MCC matrix
DO i = 1, nInteractions CALL initInteractionMatrix(interactionMatrix)
WRITE(iString, '(I2)') i
object = 'interactions.collisions(' // TRIM(iString) // ')'
CALL config%get(object // '.species_i', species_i, found)
pt_i = speciesName2Index(species_i)
CALL config%get(object // '.species_j', species_j, found)
pt_j = speciesName2Index(species_j)
CALL config%info(object // '.cTypes', found, n_children = nCollisions)
ij = interactionIndex(pt_i,pt_j)
!Allocates the required number of collisions per each pair of species ij
CALL interactionMatrix(ij)%init(nCollisions)
DO k = 1, nCollisions !Path for collision cross-section data files
WRITE (kString, '(I2)') k CALL config%get('interactions.folderCollisions', pathCollisions, found)
object = 'interactions.collisions(' // TRIM(iString) // ').cTypes(' // TRIM(kString) // ')'
!Reads the cross section file
CALL config%get(object // '.crossSection', crossSecFile, found)
crossSecFilePath = pathCollisions // crossSecFile
IF (.NOT. found) CALL criticalError('crossSection not found for ' // object, 'readInteractions')
!Reads the type of collision
CALL config%get(object // '.type', cType, found)
!Initialize collision type and reads required additional data
SELECT CASE(cType)
CASE ('elastic')
!Elastic collision
CALL initBinaryElastic(interactionMatrix(ij)%collisions(k)%obj, &
crossSecFilePath, species(pt_i)%obj%m, species(pt_j)%obj%m)
CASE ('chargeExchange') !Inits lock for list of particles
!Resonant charge exchange CALL OMP_INIT_LOCK(lockCollisions)
CALL initBinaryChargeExchange(interactionMatrix(ij)%collisions(k)%obj, &
crossSecFilePath, species(pt_i)%obj%m, species(pt_j)%obj%m)
CASE ('ionization') CALL config%info('interactions.collisions', found, n_children = nInteractions)
!Electorn impact ionization DO i = 1, nInteractions
CALL config%get(object // '.energyThreshold', energyThreshold, found) WRITE(iString, '(I2)') i
IF (.NOT. found) CALL criticalError('energyThreshold not found for collision' // object, 'readInteractions') object = 'interactions.collisions(' // TRIM(iString) // ')'
CALL config%get(object // '.electron', electron, found) CALL config%get(object // '.species_i', species_i, found)
IF (.NOT. found) CALL criticalError('electron not found for collision' // object, 'readInteractions') pt_i = speciesName2Index(species_i)
CALL initBinaryIonization(interactionMatrix(ij)%collisions(k)%obj, & CALL config%get(object // '.species_j', species_j, found)
crossSecFilePath, energyThreshold, species(pt_i)%obj%m, species(pt_j)%obj%m, electron) pt_j = speciesName2Index(species_j)
CALL config%info(object // '.cTypes', found, n_children = nCollisions)
ij = interactionIndex(pt_i,pt_j)
!Allocates the required number of collisions per each pair of species ij
CALL interactionMatrix(ij)%init(nCollisions)
CASE ('recombination') DO k = 1, nCollisions
!Electorn impact ionization WRITE (kString, '(I2)') k
CALL config%get(object // '.energyBinding', energyBinding, found) object = 'interactions.collisions(' // TRIM(iString) // ').cTypes(' // TRIM(kString) // ')'
IF (.NOT. found) CALL criticalError('energyThreshold not found for collision' // object, 'readInteractions') !Reads the cross section file
CALL config%get(object // '.electron', electron, found) CALL config%get(object // '.crossSection', crossSecFile, found)
IF (.NOT. found) CALL criticalError('electron not found for collision' // object, 'readInteractions') crossSecFilePath = pathCollisions // crossSecFile
CALL initBinaryRecombination(interactionMatrix(ij)%collisions(k)%obj, & IF (.NOT. found) CALL criticalError('crossSection not found for ' // object, 'readInteractions')
crossSecFilePath, energyBinding, species(pt_i)%obj%m, species(pt_j)%obj%m, electron) !Reads the type of collision
CALL config%get(object // '.type', cType, found)
!Initialize collision type and reads required additional data
SELECT CASE(cType)
CASE ('elastic')
!Elastic collision
CALL initBinaryElastic(interactionMatrix(ij)%collisions(k)%obj, &
crossSecFilePath, species(pt_i)%obj%m, species(pt_j)%obj%m)
CASE DEFAULT CASE ('chargeExchange')
CALL criticalError('Collision type' // cType // 'not defined yet', 'readInteractions') !Resonant charge exchange
CALL initBinaryChargeExchange(interactionMatrix(ij)%collisions(k)%obj, &
crossSecFilePath, species(pt_i)%obj%m, species(pt_j)%obj%m)
END SELECT CASE ('ionization')
!Electorn impact ionization
CALL config%get(object // '.energyThreshold', energyThreshold, found)
IF (.NOT. found) CALL criticalError('energyThreshold not found for collision' // object, 'readInteractions')
CALL config%get(object // '.electron', electron, found)
IF (.NOT. found) CALL criticalError('electron not found for collision' // object, 'readInteractions')
CALL initBinaryIonization(interactionMatrix(ij)%collisions(k)%obj, &
crossSecFilePath, energyThreshold, species(pt_i)%obj%m, species(pt_j)%obj%m, electron)
END DO CASE ('recombination')
!Electorn impact ionization
CALL config%get(object // '.energyBinding', energyBinding, found)
IF (.NOT. found) CALL criticalError('energyThreshold not found for collision' // object, 'readInteractions')
CALL config%get(object // '.electron', electron, found)
IF (.NOT. found) CALL criticalError('electron not found for collision' // object, 'readInteractions')
CALL initBinaryRecombination(interactionMatrix(ij)%collisions(k)%obj, &
crossSecFilePath, energyBinding, species(pt_i)%obj%m, species(pt_j)%obj%m, electron)
END DO CASE DEFAULT
CALL criticalError('Collision type' // cType // 'not defined yet', 'readInteractions')
END SELECT
END DO
END DO
END IF
END IF
END SUBROUTINE readInteractions END SUBROUTINE readInteractions
@ -702,17 +726,23 @@ MODULE moduleInput
TYPE(json_file), INTENT(inout):: config TYPE(json_file), INTENT(inout):: config
LOGICAL:: found LOGICAL:: found
LOGICAL:: doubleMesh
CHARACTER(:), ALLOCATABLE:: meshFormat, meshFile CHARACTER(:), ALLOCATABLE:: meshFormat, meshFile
CHARACTER(:), ALLOCATABLE:: fullPath CHARACTER(:), ALLOCATABLE:: fullPath
!Firstly, indicates if a specific mesh for MC collisions is being use
doubleMesh = ASSOCIATED(meshForMCC, meshColl)
!Selects the type of geometry. !Selects the type of geometry.
CALL config%get('geometry.type', mesh%geometry, found) CALL config%get('geometry.type', mesh%geometry, found)
IF (doubleMesh) meshColl%geometry = mesh%geometry
!Gets the type of mesh !Gets the type of mesh
CALL config%get('geometry.meshType', meshFormat, found) CALL config%get('geometry.meshType', meshFormat, found)
SELECT CASE(meshFormat) SELECT CASE(meshFormat)
CASE ("gmsh2") CASE ("gmsh2")
CALL initGmsh2(mesh) CALL initGmsh2(mesh)
IF (doubleMesh) CALL initGmsh2(meshColl)
CASE DEFAULT CASE DEFAULT
CALL criticalError("Mesh format " // meshFormat // " not recogniced", "readGeometry") CALL criticalError("Mesh format " // meshFormat // " not recogniced", "readGeometry")
@ -723,6 +753,14 @@ MODULE moduleInput
CALL config%get('geometry.meshFile', meshFile, found) CALL config%get('geometry.meshFile', meshFile, found)
fullpath = path // meshFile fullpath = path // meshFile
CALL mesh%readMesh(fullPath) CALL mesh%readMesh(fullPath)
DEALLOCATE(fullPath, meshFile)
IF (doubleMesh) THEN
!Reads the mesh file for collisions
CALL config%get('interactions.meshCollisions', meshFile, found)
fullpath = path // meshFile
CALL meshColl%readMesh(fullPath)
END IF
!Creates the connectivity between elements !Creates the connectivity between elements
SELECT CASE(mesh%geometry) SELECT CASE(mesh%geometry)
@ -744,9 +782,24 @@ MODULE moduleInput
END SELECT END SELECT
CALL mesh%connectMesh CALL mesh%connectMesh
!Builds the K matrix IF (doubleMesh) THEN
meshColl%connectMesh => mesh%connectMesh
CALL meshColl%connectMesh
END IF
!Builds the K matrix for the Particles mesh
CALL mesh%constructGlobalK() CALL mesh%constructGlobalK()
!Assign the procedure to find a volume for meshColl
IF (doubleMesh) THEN
findCellColl => findCellCollMesh
ELSE
findCellColl => findCellSameMesh
END IF
END SUBROUTINE readGeometry END SUBROUTINE readGeometry
SUBROUTINE readEMBoundary(config) SUBROUTINE readEMBoundary(config)

View file

@ -10,7 +10,7 @@ MODULE moduleList
END TYPE lNode END TYPE lNode
TYPE listNode TYPE listNode
INTEGER:: amount = 0!TODO: Make private INTEGER:: amount = 0
TYPE(lNode),POINTER:: head => NULL() TYPE(lNode),POINTER:: head => NULL()
TYPE(lNode),POINTER:: tail => NULL() TYPE(lNode),POINTER:: tail => NULL()
CONTAINS CONTAINS

View file

@ -109,7 +109,7 @@ MODULE moduleOutput
END IF END IF
WRITE (20, "(I10, I10, 6(ES20.6E3))") t, nPartOld, tStep, tPush, tReset, tColl, tWeight, tEMField WRITE (20, "(I10, I10, 7(ES20.6E3))") t, nPartOld, tStep, tPush, tReset, tColl, tCoul, tWeight, tEMField
CLOSE(20) CLOSE(20)

View file

@ -483,21 +483,6 @@ MODULE moduleSolver
END SUBROUTINE push1DRadCharged END SUBROUTINE push1DRadCharged
!Do the collisions in all the cells
SUBROUTINE doCollisions()
USE moduleMesh
IMPLICIT NONE
INTEGER:: e
!$OMP DO SCHEDULE(DYNAMIC)
DO e=1, mesh%numVols
CALL mesh%vols(e)%obj%collision()
END DO
!$OMP END DO
END SUBROUTINE doCollisions
SUBROUTINE doReset() SUBROUTINE doReset()
USE moduleSpecies USE moduleSpecies
USE moduleMesh USE moduleMesh
@ -623,6 +608,14 @@ MODULE moduleSolver
END DO END DO
!$OMP SECTION
!Erase the list of particles inside the cell in coll mesh
DO e = 1, meshColl%numVols
meshColl%vols(e)%obj%totalWeight = 0.D0
CALL meshColl%vols(e)%obj%listPart_in%erase()
END DO
!$OMP END SECTIONS !$OMP END SECTIONS
!$OMP SINGLE !$OMP SINGLE
@ -788,6 +781,7 @@ MODULE moduleSolver
volOld => mesh%vols(part%vol)%obj volOld => mesh%vols(part%vol)%obj
CALL volOld%findCell(part) CALL volOld%findCell(part)
CALL findCellColl(part)
volNew => mesh%vols(part%vol)%obj volNew => mesh%vols(part%vol)%obj
!Call the NA shcme !Call the NA shcme
IF (ASSOCIATED(self%weightingScheme)) THEN IF (ASSOCIATED(self%weightingScheme)) THEN
@ -831,7 +825,7 @@ MODULE moduleSolver
counterOutput=0 counterOutput=0
CALL mesh%printOutput(t) CALL mesh%printOutput(t)
CALL mesh%printColl(t) IF (ASSOCIATED(meshForMCC)) CALL meshForMCC%printColl(t)
CALL mesh%printEM(t) CALL mesh%printEM(t)
WRITE(*, "(5X,A21,I10,A1,I10)") "t/tmax: ", t, "/", tmax WRITE(*, "(5X,A21,I10,A1,I10)") "t/tmax: ", t, "/", tmax
WRITE(*, "(5X,A21,I10)") "Particles: ", nPartOld WRITE(*, "(5X,A21,I10)") "Particles: ", nPartOld

View file

@ -39,6 +39,7 @@ MODULE moduleSpecies
REAL(8):: v(1:3) !Velocity REAL(8):: v(1:3) !Velocity
CLASS(speciesGeneric), POINTER:: species !Pointer to species associated with this particle CLASS(speciesGeneric), POINTER:: species !Pointer to species associated with this particle
INTEGER:: vol !Index of element in which the particle is located INTEGER:: vol !Index of element in which the particle is located
INTEGER:: volColl !Index of element in which the particle is located in the Collision Mesh
REAL(8):: xi(1:3) !Logical coordinates of particle in element e_p. REAL(8):: xi(1:3) !Logical coordinates of particle in element e_p.
LOGICAL:: n_in !Flag that indicates if a particle is in the domain LOGICAL:: n_in !Flag that indicates if a particle is in the domain
REAL(8):: weight=0.D0 !weight of particle REAL(8):: weight=0.D0 !weight of particle