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

@ -65,6 +65,8 @@ MODULE moduleMesh
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshElement):: meshEdge
!Connectivity to vols
CLASS(meshVol), POINTER:: e1 => NULL(), e2 => NULL()
!Connectivity to vols in meshColl
CLASS(meshVol), POINTER:: eColl => NULL()
!Normal vector
REAL(8):: normal(1:3)
!Weight for random injection of particles
@ -153,8 +155,6 @@ MODULE moduleMesh
INTEGER(KIND=OMP_LOCK_KIND):: lock
!Number of collisions per volume
INTEGER:: nColl = 0
!Collisional fraction
REAL(8):: collFrac = 0.D0
!Total weight of particles inside cell
REAL(8):: totalWeight = 0.D0
CONTAINS
@ -169,16 +169,17 @@ MODULE moduleMesh
PROCEDURE(phy2log_interface), DEFERRED, PASS:: phy2log
PROCEDURE(inside_interface), DEFERRED, NOPASS:: inside
PROCEDURE(nextElement_interface), DEFERRED, PASS:: nextElement
PROCEDURE, PASS:: collision
END TYPE meshVol
ABSTRACT INTERFACE
SUBROUTINE initVol_interface(self, n, p)
SUBROUTINE initVol_interface(self, n, p, nodes)
IMPORT:: meshVol
IMPORT meshNodeCont
CLASS(meshVol), INTENT(out):: self
INTEGER, INTENT(in):: n
INTEGER, INTENT(in):: p(:)
TYPE(meshNodeCont), INTENT(in), TARGET:: nodes(:)
END SUBROUTINE initVol_interface
@ -260,80 +261,143 @@ MODULE moduleMesh
END TYPE meshVolCont
!Particle mesh
TYPE, PUBLIC:: meshParticle
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(:)
!Generic mesh type
TYPE, ABSTRACT:: meshGeneric
!Geometry of the mesh
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
REAL(8), ALLOCATABLE, DIMENSION(:,:):: K
!Permutation matrix for P L U factorization
INTEGER, ALLOCATABLE, DIMENSION(:,:):: IPIV
PROCEDURE(printOutput_interface), POINTER, PASS:: printOutput => NULL()
PROCEDURE(printColl_interface), POINTER, PASS:: printColl => NULL()
PROCEDURE(printEM_interface), POINTER, PASS:: printEM => NULL()
PROCEDURE(readMesh_interface), POINTER, PASS:: readMesh => NULL()
PROCEDURE(connectMesh_interface), POINTER, PASS:: connectMesh => NULL()
PROCEDURE(doCoulomb_interface), POINTER, PASS:: doCoulomb => NULL()
CONTAINS
PROCEDURE, PASS:: constructGlobalK
END TYPE meshParticle
END TYPE meshParticles
ABSTRACT INTERFACE
!Perform Coulomb Scattering
SUBROUTINE doCoulomb_interface(self)
IMPORT meshParticles
CLASS(meshParticles), INTENT(inout):: self
END SUBROUTINE doCoulomb_interface
!Prints Species data
SUBROUTINE printOutput_interface(self, t)
IMPORT meshParticle
IMPORT meshParticles
CLASS(meshParticle), INTENT(in):: self
CLASS(meshParticles), INTENT(in):: self
INTEGER, INTENT(in):: t
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
SUBROUTINE printEM_interface(self, t)
IMPORT meshParticle
IMPORT meshParticles
CLASS(meshParticle), INTENT(in):: self
CLASS(meshParticles), INTENT(in):: self
INTEGER, INTENT(in):: t
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
!Particle mesh
TYPE(meshParticle), TARGET:: mesh
TYPE(meshParticles), 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
!Reset the output of node
@ -362,8 +426,8 @@ MODULE moduleMesh
IMPLICIT NONE
CLASS(meshVol), INTENT(inout):: self
CLASS(meshVol), OPTIONAL, INTENT(in):: oldCell
CLASS(particle), INTENT(inout), TARGET:: part
CLASS(meshVol), OPTIONAL, INTENT(in):: oldCell
REAL(8):: xi(1:3)
CLASS(meshElement), POINTER:: nextElement
@ -408,12 +472,96 @@ MODULE moduleMesh
CALL criticalError("No connectivity found for element", "findCell")
END SELECT
END IF
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
SUBROUTINE collision(self)
SUBROUTINE doCollisions(self)
USE moduleCollisions
USE moduleSpecies
USE moduleList
@ -421,7 +569,9 @@ MODULE moduleMesh
USE moduleRandom
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
REAL(8):: pMax !Maximum probability of collision
INTEGER:: rnd !random index
@ -431,57 +581,57 @@ MODULE moduleMesh
REAL(8):: sigmaVrelMaxNew
TYPE(pointerArray), ALLOCATABLE:: partTemp(:)
nPart = self%listPart_in%amount
!Computes iterations if there is more than one particle in the cell
IF (nPart > 1) THEN
!Probability of collision
pMax = self%totalWeight*self%sigmaVrelMax*tauMin/self%volume
!$OMP DO SCHEDULE(DYNAMIC)
DO e=1, self%numVols
vol => self%vols(e)%obj
nPart = vol%listPart_in%amount
!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
self%collFrac = self%collFrac + REAL(nPart)*pMax*0.5D0
!Number of collisions in the cell
self%nColl = FLOOR(self%collFrac)
!Number of collisions in the cell
vol%nColl = NINT(REAL(nPart)*pMax*0.5D0)
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
IF (vol%nColl > 0) THEN
!Converts the list of particles to an array for easy access
partTemp = vol%listPart_in%convert2Array()
END IF
!Removes one collision from the collisional fraction
self%collFrac = self%collFrac - 1.D0
END DO
DO n = 1, vol%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(vol%sigmaVrelMax, sigmaVrelMaxNew, part_i, part_j)
END IF
END DO
END SUBROUTINE collision
!Update maximum cross section*v_rel per each collision
IF (sigmaVrelMaxNew > vol%sigmaVrelMax) THEN
vol%sigmaVrelMax = sigmaVrelMaxNew
END IF
END DO
END IF
END DO
!$OMP END DO
END SUBROUTINE doCollisions
!Constructs the global K matrix
SUBROUTINE constructGlobalK(self)
IMPLICIT NONE
CLASS(meshParticle), INTENT(inout):: self
CLASS(meshParticles), INTENT(inout):: self
INTEGER:: e
INTEGER, ALLOCATABLE:: n(:)
REAL(8), ALLOCATABLE:: localK(:,:)