!Implementation for 1D solver for charged particles. Added a 1D case for
testing. Still, no formal test has been performed so issues may appear.
This commit is contained in:
parent
7859a73274
commit
d69b59143d
14 changed files with 3229 additions and 403 deletions
|
|
@ -4,7 +4,8 @@ OBJECTS = $(OBJDIR)/moduleMesh.o $(OBJDIR)/moduleCompTime.o $(OBJDIR)/moduleSolv
|
|||
$(OBJDIR)/moduleMeshCyl.o $(OBJDIR)/moduleMeshCylRead.o $(OBJDIR)/moduleMeshCylBoundary.o \
|
||||
$(OBJDIR)/moduleBoundary.o $(OBJDIR)/moduleCaseParam.o $(OBJDIR)/moduleRefParam.o \
|
||||
$(OBJDIR)/moduleCollisions.o $(OBJDIR)/moduleTable.o $(OBJDIR)/moduleParallel.o \
|
||||
$(OBJDIR)/moduleEM.o
|
||||
$(OBJDIR)/moduleEM.o $(OBJDIR)/moduleMesh1D.o $(OBJDIR)/moduleMesh1DRead.o \
|
||||
$(OBJDIR)/moduleMesh1DBoundary.o
|
||||
|
||||
all: $(OUTPUT)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,15 @@ OBJS = moduleCaseParam.o moduleCompTime.o moduleList.o\
|
|||
moduleMesh.o moduleMeshCyl.o moduleMeshCylBoundary.o\
|
||||
moduleMeshCylRead.o moduleOutput.o moduleInput.o \
|
||||
moduleSolver.o moduleCollisions.o moduleTable.o \
|
||||
moduleParallel.o moduleEM.o
|
||||
moduleParallel.o moduleEM.o moduleMesh1D.o \
|
||||
moduleMesh1DBoundary.o moduleMesh1DRead.o
|
||||
|
||||
all: $(OBJS)
|
||||
|
||||
moduleCollisions.o: moduleTable.o moduleSpecies.o moduleRefParam.o moduleConstParam.o moduleMeshCyl.f95
|
||||
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||
|
||||
moduleInput.o: moduleParallel.o moduleRefParam.o moduleCaseParam.o moduleSolver.o moduleInject.o moduleBoundary.o moduleMesh.o moduleMeshCylRead.o moduleErrors.o moduleSpecies.o moduleInput.f95
|
||||
moduleInput.o: moduleParallel.o moduleRefParam.o moduleCaseParam.o moduleSolver.o moduleInject.o moduleBoundary.o moduleMesh.o moduleMeshCylRead.o moduleMesh1DRead.o moduleErrors.o moduleSpecies.o moduleInput.f95
|
||||
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||
|
||||
moduleInject.o: moduleSpecies.o moduleSolver.o moduleMesh.o moduleMeshCyl.o moduleInject.f95
|
||||
|
|
@ -19,7 +20,7 @@ moduleInject.o: moduleSpecies.o moduleSolver.o moduleMesh.o moduleMeshCyl.o modu
|
|||
moduleList.o: moduleSpecies.o moduleErrors.o moduleList.f95
|
||||
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||
|
||||
moduleMesh.o: moduleOutput.o moduleList.o moduleSpecies.o moduleMesh.f95
|
||||
moduleMesh.o: moduleCollisions.o moduleOutput.o moduleList.o moduleSpecies.o moduleMesh.f95
|
||||
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||
|
||||
moduleMeshCyl.o: moduleRefParam.o moduleCollisions.o moduleOutput.o moduleMesh.o moduleMeshCyl.f95
|
||||
|
|
@ -31,6 +32,15 @@ moduleMeshCylBoundary.o: moduleMeshCyl.o moduleMeshCylBoundary.f95
|
|||
moduleMeshCylRead.o: moduleBoundary.o moduleMeshCyl.o moduleMeshCylBoundary.o moduleMeshCylRead.f95
|
||||
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||
|
||||
moduleMesh1D.o: moduleRefParam.o moduleCollisions.o moduleOutput.o moduleMesh.o moduleMesh1D.f95
|
||||
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||
|
||||
moduleMesh1DBoundary.o: moduleMesh1D.o moduleMesh1DBoundary.f95
|
||||
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||
|
||||
moduleMesh1DRead.o: moduleBoundary.o moduleMesh1D.o moduleMesh1DBoundary.o moduleMesh1DRead.f95
|
||||
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||
|
||||
moduleOutput.o: moduleSpecies.o moduleRefParam.o moduleOutput.f95
|
||||
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||
|
||||
|
|
|
|||
|
|
@ -93,22 +93,17 @@ MODULE moduleEM
|
|||
|
||||
END DO
|
||||
|
||||
!If there is charge in the nodes, compute the local F vector
|
||||
IF (ANY(rho > 0.D0)) THEN
|
||||
!Calculates local F vector
|
||||
localF = mesh%vols(e)%obj%elemF(rho)
|
||||
!Calculates local F vector
|
||||
localF = mesh%vols(e)%obj%elemF(rho)
|
||||
|
||||
!Assign local F to global F
|
||||
DO i = 1, nNodes
|
||||
ni = nodes(i)
|
||||
vectorF(ni) = vectorF(ni) + localF(i)
|
||||
!Assign local F to global F
|
||||
DO i = 1, nNodes
|
||||
ni = nodes(i)
|
||||
vectorF(ni) = vectorF(ni) + localF(i)
|
||||
|
||||
END DO
|
||||
|
||||
DEALLOCATE(localF)
|
||||
|
||||
END IF
|
||||
END DO
|
||||
|
||||
DEALLOCATE(localF)
|
||||
DEALLOCATE(nodes, rho)
|
||||
|
||||
END DO
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ MODULE moduleInject
|
|||
!Initialize an injection of particles
|
||||
SUBROUTINE initInject(self, i, v, n, T, flow, units, sp, physicalSurface)
|
||||
USE moduleMesh
|
||||
USE moduleMeshCyl
|
||||
USE moduleRefParam
|
||||
USE moduleConstParam
|
||||
USE moduleSpecies
|
||||
|
|
@ -67,7 +66,7 @@ MODULE moduleInject
|
|||
self%nParticles = self%nParticles * solver%pusher(sp)%every
|
||||
self%sp = sp
|
||||
|
||||
self%v = self%v * self%n
|
||||
self%v = self%vMod * self%n
|
||||
self%vTh = DSQRT(self%T/species(self%sp)%obj%m)
|
||||
|
||||
!Gets the edge elements from which particles are injected
|
||||
|
|
@ -85,11 +84,6 @@ MODULE moduleInject
|
|||
IF (mesh%edges(e)%obj%physicalSurface == physicalSurface) THEN
|
||||
et = et + 1
|
||||
self%edges(et) = mesh%edges(e)%obj%n
|
||||
! SELECT TYPE(edge => mesh%edges(e)%obj)
|
||||
! CLASS IS (meshEdgeCyl)
|
||||
! self%weight(et) = (edge%r(1)+edge%r(2))/2.D0
|
||||
!
|
||||
! END SELECT
|
||||
|
||||
END IF
|
||||
|
||||
|
|
@ -143,7 +137,6 @@ MODULE moduleInject
|
|||
USE moduleSpecies
|
||||
USE moduleSolver
|
||||
USE moduleMesh
|
||||
USE moduleMeshCyl
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(injectGeneric), INTENT(in):: self
|
||||
|
|
@ -178,13 +171,6 @@ MODULE moduleInject
|
|||
|
||||
!$OMP DO
|
||||
DO n = nMin, nMax
|
||||
!Select edge randomly from which inject particle
|
||||
! randomX = RAND()*self%sumWeight
|
||||
! DO j = 1, self%nEdges
|
||||
! IF (randomX < self%weight(j)) EXIT
|
||||
! randomX = randomX - self%weight(j)
|
||||
!
|
||||
! END DO
|
||||
randomX = INT(DBLE(self%nEdges-1)*RAND()) + 1
|
||||
|
||||
randomEdge => mesh%edges(self%edges(randomX))%obj
|
||||
|
|
@ -203,11 +189,8 @@ MODULE moduleInject
|
|||
vBC(self%v(2), self%vTh(2)), &
|
||||
vBC(self%v(3), self%vTh(3)) /)
|
||||
|
||||
IF (solver%pusher(self%sp)%pushSpecies) THEN
|
||||
!Push new particle
|
||||
CALL solver%pusher(self%sp)%pushParticle(partInj(n))
|
||||
|
||||
END IF
|
||||
!Push new particle
|
||||
CALL solver%pusher(self%sp)%pushParticle(partInj(n))
|
||||
!Assign cell to new particle
|
||||
CALL solver%updateParticleCell(partInj(n))
|
||||
|
||||
|
|
|
|||
|
|
@ -45,9 +45,6 @@ MODULE moduleInput
|
|||
CALL verboseError('Reading Case Parameters...')
|
||||
CALL readCase(config)
|
||||
|
||||
!Read boundary for EM field
|
||||
CALL readEMBoundary(config)
|
||||
|
||||
!Read injection of particles
|
||||
CALL verboseError('Reading Interactions between species...')
|
||||
CALL readInject(config)
|
||||
|
|
@ -164,6 +161,11 @@ MODULE moduleInput
|
|||
!Gets the solver for the electromagnetic field
|
||||
CALL config%get(object // '.EMSolver', EMType, found)
|
||||
CALL solver%initEM(EMType)
|
||||
SELECT CASE(EMType)
|
||||
CASE("Electrostatic")
|
||||
CALL readEMBoundary(config)
|
||||
|
||||
END SELECT
|
||||
|
||||
!Gest the non-analogue scheme
|
||||
CALL config%get(object // '.NAScheme', NAType, found)
|
||||
|
|
@ -351,7 +353,8 @@ MODULE moduleInput
|
|||
!Read the geometry (mesh) for the case
|
||||
SUBROUTINE readGeometry(config)
|
||||
USE moduleMesh
|
||||
USE moduleMeshCylRead
|
||||
USE moduleMeshCylRead, ONLY: meshCylGeneric
|
||||
USE moduleMesh1DRead, ONLY: mesh1DGeneric
|
||||
USE moduleErrors
|
||||
USE moduleOutput
|
||||
USE json_module
|
||||
|
|
@ -369,26 +372,31 @@ MODULE moduleInput
|
|||
!Creates a 2D cylindrical mesh
|
||||
ALLOCATE(meshCylGeneric:: mesh)
|
||||
|
||||
!Gets the type of mesh
|
||||
CALL config%get('geometry.meshType', meshType, found)
|
||||
SELECT CASE(meshType)
|
||||
CASE ("gmsh")
|
||||
!Gets the gmsh file
|
||||
CALL config%get('geometry.meshFile', meshFile, found)
|
||||
|
||||
CASE DEFAULT
|
||||
CALL criticalError("Mesh type " // meshType // " not supported.", "readGeometry")
|
||||
|
||||
END SELECT
|
||||
!Reads the mesh
|
||||
fullpath = path // meshFile
|
||||
CALL mesh%readMesh(fullPath)
|
||||
CASE ("1DCart")
|
||||
!Creates a 1D cartesian mesh
|
||||
ALLOCATE(mesh1DGeneric:: mesh)
|
||||
|
||||
CASE DEFAULT
|
||||
CALL criticalError("Geometry type " // geometryType // " not supported.", "readGeometry")
|
||||
|
||||
END SELECT
|
||||
|
||||
!Gets the type of mesh
|
||||
CALL config%get('geometry.meshType', meshType, found)
|
||||
SELECT CASE(meshType)
|
||||
CASE ("gmsh")
|
||||
!Gets the gmsh file
|
||||
CALL config%get('geometry.meshFile', meshFile, found)
|
||||
|
||||
CASE DEFAULT
|
||||
CALL criticalError("Mesh type " // meshType // " not supported.", "readGeometry")
|
||||
|
||||
END SELECT
|
||||
|
||||
!Reads the mesh
|
||||
fullpath = path // meshFile
|
||||
CALL mesh%readMesh(fullPath)
|
||||
|
||||
END SUBROUTINE readGeometry
|
||||
|
||||
SUBROUTINE readEMBoundary(config)
|
||||
|
|
|
|||
|
|
@ -130,11 +130,11 @@ MODULE moduleMesh
|
|||
PROCEDURE(gatherEF_interface), DEFERRED, PASS:: gatherEF
|
||||
PROCEDURE(getNodesVol_interface), DEFERRED, PASS:: getNodes
|
||||
PROCEDURE(elemF_interface), DEFERRED, PASS:: elemF
|
||||
PROCEDURE(findCell_interface), DEFERRED, PASS:: findCell
|
||||
PROCEDURE, PASS:: findCell
|
||||
PROCEDURE(phy2log_interface), DEFERRED, PASS:: phy2log
|
||||
PROCEDURE(inside_interface), DEFERRED, NOPASS:: inside
|
||||
PROCEDURE(nextElement_interface), DEFERRED, PASS:: nextElement
|
||||
PROCEDURE(collision_interface), DEFERRED, PASS:: collision
|
||||
PROCEDURE, PASS:: collision
|
||||
PROCEDURE(resetOutput_interface), DEFERRED, PASS:: resetOutput
|
||||
|
||||
END TYPE meshVol
|
||||
|
|
@ -189,16 +189,6 @@ MODULE moduleMesh
|
|||
|
||||
END SUBROUTINE nextElement_interface
|
||||
|
||||
SUBROUTINE findCell_interface(self, part, oldCell)
|
||||
USE moduleSpecies
|
||||
|
||||
IMPORT:: meshVol
|
||||
CLASS(meshVol), INTENT(inout):: self
|
||||
CLASS(meshVol), OPTIONAL, INTENT(in):: oldCell
|
||||
CLASS(particle), INTENT(inout), TARGET:: part
|
||||
|
||||
END SUBROUTINE findCell_interface
|
||||
|
||||
PURE FUNCTION phy2log_interface(self,r) RESULT(xN)
|
||||
IMPORT:: meshVol
|
||||
CLASS(meshVol), INTENT(in):: self
|
||||
|
|
@ -249,10 +239,10 @@ MODULE moduleMesh
|
|||
INTEGER, ALLOCATABLE, DIMENSION(:,:):: IPIV
|
||||
|
||||
CONTAINS
|
||||
PROCEDURE(readMesh_interface), PASS, DEFERRED:: readMesh
|
||||
PROCEDURE(printOutput_interface), PASS, DEFERRED:: printOutput
|
||||
PROCEDURE(printColl_interface), PASS, DEFERRED:: printColl
|
||||
PROCEDURE(printEM_interface), PASS, DEFERRED:: printEM
|
||||
PROCEDURE(readMesh_interface), DEFERRED, PASS:: readMesh
|
||||
PROCEDURE, PASS:: printOutput
|
||||
PROCEDURE, PASS:: printColl
|
||||
PROCEDURE, PASS:: printEM
|
||||
|
||||
END TYPE meshGeneric
|
||||
|
||||
|
|
@ -266,15 +256,6 @@ MODULE moduleMesh
|
|||
|
||||
END SUBROUTINE readMesh_interface
|
||||
|
||||
!Prints output variables
|
||||
SUBROUTINE printOutput_interface(self, t)
|
||||
IMPORT meshGeneric
|
||||
|
||||
CLASS(meshGeneric), INTENT(in):: self
|
||||
INTEGER, INTENT(in):: t
|
||||
|
||||
END SUBROUTINE printOutput_interface
|
||||
|
||||
!Prints number of collisions
|
||||
SUBROUTINE printColl_interface(self, t)
|
||||
IMPORT meshGeneric
|
||||
|
|
@ -297,4 +278,309 @@ MODULE moduleMesh
|
|||
!Generic mesh
|
||||
CLASS(meshGeneric), ALLOCATABLE, TARGET:: mesh
|
||||
|
||||
CONTAINS
|
||||
!Find next cell for particle
|
||||
RECURSIVE SUBROUTINE findCell(self, part, oldCell)
|
||||
USE moduleSpecies
|
||||
USE OMP_LIB
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol), INTENT(inout):: self
|
||||
CLASS(meshVol), OPTIONAL, INTENT(in):: oldCell
|
||||
CLASS(particle), INTENT(inout), TARGET:: part
|
||||
REAL(8):: xi(1:3)
|
||||
CLASS(*), POINTER:: nextElement
|
||||
|
||||
xi = self%phy2log(part%r)
|
||||
!Checks if particle is inside 'self' cell
|
||||
IF (self%inside(xi)) THEN
|
||||
part%vol = self%n
|
||||
part%xi = xi
|
||||
part%n_in = .TRUE.
|
||||
!Assign particle to listPart_in
|
||||
CALL OMP_SET_LOCK(self%lock)
|
||||
CALL self%listPart_in%add(part)
|
||||
self%totalWeight = self%totalWeight + part%weight
|
||||
CALL OMP_UNSET_LOCK(self%lock)
|
||||
|
||||
ELSE
|
||||
!If not, searches for a neighbour and repeats the process.
|
||||
CALL self%nextElement(xi, nextElement)
|
||||
!Defines the next step
|
||||
SELECT TYPE(nextElement)
|
||||
CLASS IS(meshVol)
|
||||
!Particle moved to new cell, repeat find procedure
|
||||
CALL nextElement%findCell(part, self)
|
||||
|
||||
CLASS IS (meshEdge)
|
||||
!Particle encountered an edge, execute boundary
|
||||
CALL nextElement%fBoundary(part)
|
||||
!If particle is still inside the domain, call findCell
|
||||
IF (part%n_in) THEN
|
||||
IF(PRESENT(oldCell)) THEN
|
||||
CALL self%findCell(part, oldCell)
|
||||
|
||||
ELSE
|
||||
CALL self%findCell(part)
|
||||
|
||||
END IF
|
||||
END IF
|
||||
|
||||
CLASS DEFAULT
|
||||
WRITE(*,*) "ERROR, CHECK findCell"
|
||||
|
||||
END SELECT
|
||||
END IF
|
||||
|
||||
END SUBROUTINE findCell
|
||||
|
||||
!Computes collisions in element
|
||||
SUBROUTINE collision(self)
|
||||
USE moduleCollisions
|
||||
USE moduleSpecies
|
||||
USE moduleList
|
||||
use moduleRefParam
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol), INTENT(inout):: self
|
||||
INTEGER:: nPart !Number of particles inside the cell
|
||||
REAL(8):: pMax !Maximum probability of collision
|
||||
INTEGER:: rnd !random index
|
||||
TYPE(particle), POINTER:: part_i, part_j
|
||||
INTEGER:: n !collision
|
||||
INTEGER:: ij, k
|
||||
REAL(8):: sigmaVrelMaxNew
|
||||
TYPE(pointerArray), ALLOCATABLE:: partTemp(:)
|
||||
|
||||
self%nColl = 0
|
||||
nPart = self%listPart_in%amount
|
||||
IF (nPart > 1) THEN
|
||||
pMax = self%totalWeight*self%sigmaVrelMax*tauMin/self%volume
|
||||
self%nColl = INT(REAL(nPart)*pMax*0.5D0)
|
||||
|
||||
!Converts the list of particles to an array for easy access
|
||||
IF (self%nColl > 0) THEN
|
||||
partTemp = self%listPart_in%convert2Array()
|
||||
|
||||
END IF
|
||||
|
||||
DO n = 1, self%nColl
|
||||
!Select random numbers
|
||||
rnd = 1 + FLOOR(nPart*RAND())
|
||||
part_i => partTemp(rnd)%part
|
||||
rnd = 1 + FLOOR(nPart*RAND())
|
||||
part_j => partTemp(rnd)%part
|
||||
ij = interactionIndex(part_i%sp, part_j%sp)
|
||||
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 DO
|
||||
|
||||
END IF
|
||||
|
||||
self%totalWeight = 0.D0
|
||||
|
||||
!Reset output in nodes
|
||||
CALL self%resetOutput()
|
||||
|
||||
!Erase the list of particles inside the cell
|
||||
CALL self%listPart_in%erase()
|
||||
|
||||
END SUBROUTINE collision
|
||||
|
||||
SUBROUTINE printOutput(self, t)
|
||||
USE moduleRefParam
|
||||
USE moduleSpecies
|
||||
USE moduleOutput
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshGeneric), INTENT(in):: self
|
||||
INTEGER, INTENT(in):: t
|
||||
INTEGER:: n, i
|
||||
TYPE(outputFormat):: output(1:self%numNodes)
|
||||
REAL(8):: time
|
||||
CHARACTER(:), ALLOCATABLE:: fileName
|
||||
CHARACTER (LEN=6):: tstring !TODO: Review to allow any number of iterations
|
||||
|
||||
time = DBLE(t)*tauMin*ti_ref
|
||||
|
||||
DO i = 1, nSpecies
|
||||
WRITE(tstring, '(I6.6)') t
|
||||
fileName='OUTPUT_' // tstring// '_' // species(i)%obj%name // '.msh'
|
||||
WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
|
||||
OPEN (60, file = path // folder // '/' // fileName)
|
||||
WRITE(60, "(A)") '$MeshFormat'
|
||||
WRITE(60, "(A)") '2.2 0 8'
|
||||
WRITE(60, "(A)") '$EndMeshFormat'
|
||||
WRITE(60, "(A)") '$NodeData'
|
||||
WRITE(60, "(A)") '1'
|
||||
WRITE(60, "(A)") '"Density (m^-3)"'
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) time
|
||||
WRITE(60, *) 3
|
||||
WRITE(60, *) t
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) self%numNodes
|
||||
DO n=1, self%numNodes
|
||||
CALL calculateOutput(self%nodes(n)%obj%output(i), output(n), self%nodes(n)%obj%v, species(i)%obj)
|
||||
WRITE(60, "(I6,ES20.6E3)") n, output(n)%density
|
||||
END DO
|
||||
WRITE(60, "(A)") '$EndNodeData'
|
||||
WRITE(60, "(A)") '$NodeData'
|
||||
WRITE(60, "(A)") '1'
|
||||
WRITE(60, "(A)") '"Velocity (m/s)"'
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) time
|
||||
WRITE(60, *) 3
|
||||
WRITE(60, *) t
|
||||
WRITE(60, *) 3
|
||||
WRITE(60, *) self%numNodes
|
||||
DO n=1, self%numNodes
|
||||
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%velocity
|
||||
END DO
|
||||
WRITE(60, "(A)") '$EndNodeData'
|
||||
WRITE(60, "(A)") '$NodeData'
|
||||
WRITE(60, "(A)") '1'
|
||||
WRITE(60, "(A)") '"Pressure (Pa)"'
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) time
|
||||
WRITE(60, *) 3
|
||||
WRITE(60, *) t
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) self%numNodes
|
||||
DO n=1, self%numNodes
|
||||
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%pressure
|
||||
END DO
|
||||
WRITE(60, "(A)") '$EndNodeData'
|
||||
WRITE(60, "(A)") '$NodeData'
|
||||
WRITE(60, "(A)") '1'
|
||||
WRITE(60, "(A)") '"Temperature (K)"'
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) time
|
||||
WRITE(60, *) 3
|
||||
WRITE(60, *) t
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) self%numNodes
|
||||
DO n=1, self%numNodes
|
||||
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%temperature
|
||||
END DO
|
||||
WRITE(60, "(A)") '$EndNodeData'
|
||||
CLOSE (60)
|
||||
|
||||
END DO
|
||||
|
||||
END SUBROUTINE printOutput
|
||||
|
||||
SUBROUTINE printColl(self, t)
|
||||
USE moduleRefParam
|
||||
USE moduleCaseParam
|
||||
USE moduleOutput
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshGeneric), INTENT(in):: self
|
||||
INTEGER, INTENT(in):: t
|
||||
INTEGER:: n
|
||||
REAL(8):: time
|
||||
CHARACTER(:), ALLOCATABLE:: fileName
|
||||
CHARACTER (LEN=6):: tstring !TODO: Review to allow any number of iterations
|
||||
|
||||
|
||||
IF (collOutput) THEN
|
||||
time = DBLE(t)*tauMin*ti_ref
|
||||
WRITE(tstring, '(I6.6)') t
|
||||
|
||||
fileName='OUTPUT_' // tstring// '_Collisions.msh'
|
||||
WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
|
||||
OPEN (60, file = path // folder // '/' // fileName)
|
||||
WRITE(60, "(A)") '$MeshFormat'
|
||||
WRITE(60, "(A)") '2.2 0 8'
|
||||
WRITE(60, "(A)") '$EndMeshFormat'
|
||||
WRITE(60, "(A)") '$ElementData'
|
||||
WRITE(60, "(A)") '1'
|
||||
WRITE(60, "(A)") '"Collisions"'
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) time
|
||||
WRITE(60, *) 3
|
||||
WRITE(60, *) t
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) self%numVols
|
||||
DO n=1, self%numVols
|
||||
WRITE(60, "(I6,I10)") n + self%numEdges, self%vols(n)%obj%nColl
|
||||
END DO
|
||||
WRITE(60, "(A)") '$EndElementData'
|
||||
|
||||
CLOSE(60)
|
||||
|
||||
END IF
|
||||
|
||||
END SUBROUTINE printColl
|
||||
|
||||
SUBROUTINE printEM(self, t)
|
||||
USE moduleRefParam
|
||||
USE moduleCaseParam
|
||||
USE moduleOutput
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshGeneric), INTENT(in):: self
|
||||
INTEGER, INTENT(in):: t
|
||||
INTEGER:: n, e
|
||||
REAL(8):: time
|
||||
CHARACTER(:), ALLOCATABLE:: fileName
|
||||
CHARACTER (LEN=6):: tstring !TODO: Review to allow any number of iterations
|
||||
REAL(8):: xi(1:3)
|
||||
|
||||
xi = (/ 0.D0, 0.D0, 0.D0 /)
|
||||
|
||||
IF (emOutput) THEN
|
||||
time = DBLE(t)*tauMin*ti_ref
|
||||
WRITE(tstring, '(I6.6)') t
|
||||
|
||||
fileName='OUTPUT_' // tstring// '_EMField.msh'
|
||||
WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
|
||||
OPEN (20, file = path // folder // '/' // fileName)
|
||||
WRITE(20, "(A)") '$MeshFormat'
|
||||
WRITE(20, "(A)") '2.2 0 8'
|
||||
WRITE(20, "(A)") '$EndMeshFormat'
|
||||
WRITE(20, "(A)") '$NodeData'
|
||||
WRITE(20, "(A)") '1'
|
||||
WRITE(20, "(A)") '"Potential (V)"'
|
||||
WRITE(20, *) 1
|
||||
WRITE(20, *) time
|
||||
WRITE(20, *) 3
|
||||
WRITE(20, *) t
|
||||
WRITE(20, *) 1
|
||||
WRITE(20, *) self%numNodes
|
||||
DO n=1, self%numNodes
|
||||
WRITE(20, *) n, self%nodes(n)%obj%emData%phi*Volt_ref
|
||||
END DO
|
||||
WRITE(20, "(A)") '$EndNodeData'
|
||||
|
||||
WRITE(20, "(A)") '$ElementData'
|
||||
WRITE(20, "(A)") '1'
|
||||
WRITE(20, "(A)") '"Electric Field (V/m)"'
|
||||
WRITE(20, *) 1
|
||||
WRITE(20, *) time
|
||||
WRITE(20, *) 3
|
||||
WRITE(20, *) t
|
||||
WRITE(20, *) 3
|
||||
WRITE(20, *) self%numVols
|
||||
DO e=1, self%numVols
|
||||
WRITE(20, *) e+self%numEdges, self%vols(e)%obj%gatherEF(xi)*EF_ref
|
||||
END DO
|
||||
WRITE(20, "(A)") '$EndElementData'
|
||||
CLOSE(20)
|
||||
|
||||
END IF
|
||||
|
||||
END SUBROUTINE printEM
|
||||
|
||||
END MODULE moduleMesh
|
||||
|
|
|
|||
489
src/modules/moduleMesh1D.f95
Normal file
489
src/modules/moduleMesh1D.f95
Normal file
|
|
@ -0,0 +1,489 @@
|
|||
!moduleMesh1D: 1D cartesian module
|
||||
! x == x
|
||||
! y == unused
|
||||
! z == unused
|
||||
MODULE moduleMesh1D
|
||||
USE moduleMesh
|
||||
IMPLICIT NONE
|
||||
|
||||
TYPE, PUBLIC, EXTENDS(meshNode):: meshNode1D
|
||||
!Element coordinates
|
||||
REAL(8):: x = 0.D0
|
||||
CONTAINS
|
||||
PROCEDURE, PASS:: init => initNode1D
|
||||
PROCEDURE, PASS:: getCoordinates => getCoord1D
|
||||
|
||||
END TYPE meshNode1D
|
||||
|
||||
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshEdge):: meshEdge1D
|
||||
!Element coordinates
|
||||
REAL(8):: x = 0.D0
|
||||
!Connectivity to nodes
|
||||
CLASS(meshNode), POINTER:: n1 => NULL()
|
||||
CONTAINS
|
||||
PROCEDURE, PASS:: init => initEdge1D
|
||||
PROCEDURE, PASS:: getNodes => getNodes1D
|
||||
PROCEDURE, PASS:: randPos => randPos1D
|
||||
|
||||
END TYPE meshEdge1D
|
||||
|
||||
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshVol):: meshVol1D
|
||||
CONTAINS
|
||||
PROCEDURE, PASS:: detJac => detJ1D
|
||||
PROCEDURE, PASS:: invJac => invJ1D
|
||||
PROCEDURE(fPsi_interface), DEFERRED, NOPASS:: fPsi
|
||||
PROCEDURE(dPsi_interface), DEFERRED, NOPASS:: dPsi
|
||||
PROCEDURE(partialDer_interface), DEFERRED, PASS:: partialDer
|
||||
|
||||
END TYPE meshVol1D
|
||||
|
||||
ABSTRACT INTERFACE
|
||||
PURE FUNCTION fPsi_interface(xi) RESULT(fPsi)
|
||||
REAL(8), INTENT(in):: xi(1:3)
|
||||
REAL(8), ALLOCATABLE:: fPsi(:)
|
||||
|
||||
END FUNCTION fPsi_interface
|
||||
|
||||
PURE FUNCTION dPsi_interface(xi) RESULT(dPsi)
|
||||
REAL(8), INTENT(in):: xi(1:3)
|
||||
REAL(8), ALLOCATABLE:: dPsi(:,:)
|
||||
|
||||
END FUNCTION dPsi_interface
|
||||
|
||||
PURE SUBROUTINE partialDer_interface(self, dPsi, dx)
|
||||
IMPORT meshVol1D
|
||||
CLASS(meshVol1D), INTENT(in):: self
|
||||
REAL(8), INTENT(in):: dPsi(1:,1:)
|
||||
REAL(8), INTENT(out), DIMENSION(1):: dx
|
||||
|
||||
END SUBROUTINE partialDer_interface
|
||||
|
||||
END INTERFACE
|
||||
|
||||
TYPE, PUBLIC, EXTENDS(meshVol1D):: meshVol1DSegm
|
||||
!Element coordinates
|
||||
REAL(8):: x(1:2)
|
||||
!Connectivity to nodes
|
||||
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL()
|
||||
!Connectivity to adjacent elements
|
||||
CLASS(*), POINTER:: e1 => NULL(), e2 => NULL()
|
||||
REAL(8):: arNodes(1:2)
|
||||
CONTAINS
|
||||
PROCEDURE, PASS:: init => initVol1DSegm
|
||||
PROCEDURE, PASS:: area => areaSegm
|
||||
PROCEDURE, NOPASS:: fPsi => fPsiSegm
|
||||
PROCEDURE, NOPASS:: dPsi => dPsiSegm
|
||||
PROCEDURE, PASS:: partialDer => partialDerSegm
|
||||
PROCEDURE, PASS:: elemK => elemKSegm
|
||||
PROCEDURE, PASS:: elemF => elemFSegm
|
||||
PROCEDURE, NOPASS:: weight => weightSegm
|
||||
PROCEDURE, NOPASS:: inside => insideSegm
|
||||
PROCEDURE, PASS:: scatter => scatterSegm
|
||||
PROCEDURE, PASS:: gatherEF => gatherEFSegm
|
||||
PROCEDURE, PASS:: getNodes => getNodesSegm
|
||||
PROCEDURE, PASS:: phy2log => phy2logSegm
|
||||
PROCEDURE, PASS:: nextElement => nextElementSegm
|
||||
PROCEDURE, PASS:: resetOutput => resetOutputSegm
|
||||
|
||||
END TYPE meshVol1DSegm
|
||||
|
||||
CONTAINS
|
||||
!NODE FUNCTIONS
|
||||
!Init node element
|
||||
SUBROUTINE initNode1D(self, n, r)
|
||||
USE moduleSpecies
|
||||
USE moduleRefParam
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshNode1D), INTENT(out):: self
|
||||
INTEGER, INTENT(in):: n
|
||||
REAL(8), INTENT(in):: r(1:3)
|
||||
|
||||
self%n = n
|
||||
self%x = r(1)/L_ref
|
||||
!Node volume, to be determined in mesh
|
||||
self%v = 0.D0
|
||||
|
||||
!Allocates output
|
||||
ALLOCATE(self%output(1:nSpecies))
|
||||
|
||||
END SUBROUTINE initNode1D
|
||||
|
||||
FUNCTION getCoord1D(self) RESULT(r)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshNode1D):: self
|
||||
REAL(8):: r(1:3)
|
||||
|
||||
r = (/ self%x, 0.D0, 0.D0 /)
|
||||
|
||||
END FUNCTION getCoord1D
|
||||
|
||||
!EDGE FUNCTIONS
|
||||
!Inits edge element
|
||||
SUBROUTINE initEdge1D(self, n, p, bt, physicalSurface)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshEdge1D), INTENT(out):: self
|
||||
INTEGER, INTENT(in):: n
|
||||
INTEGER, INTENT(in):: p(:)
|
||||
INTEGER, INTENT(in):: bt
|
||||
INTEGER, INTENT(in):: physicalSurface
|
||||
REAL(8), DIMENSION(1:3):: r1
|
||||
|
||||
self%n = n
|
||||
self%n1 => mesh%nodes(p(1))%obj
|
||||
!Get element coordinates
|
||||
r1 = self%n1%getCoordinates()
|
||||
|
||||
self%x = r1(1)
|
||||
|
||||
self%normal = (/ 1.D0, 0.D0, 0.D0 /)
|
||||
|
||||
!Boundary index
|
||||
self%bt = bt
|
||||
!Physical Surface
|
||||
self%physicalSurface = physicalSurface
|
||||
|
||||
END SUBROUTINE initEdge1D
|
||||
|
||||
!Get nodes from edge
|
||||
PURE FUNCTION getNodes1D(self) RESULT(n)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshEdge1D), INTENT(in):: self
|
||||
INTEGER, ALLOCATABLE:: n(:)
|
||||
|
||||
ALLOCATE(n(1))
|
||||
n = (/ self%n1%n /)
|
||||
|
||||
END FUNCTION getNodes1D
|
||||
|
||||
!Calculates a 'random' position in edge
|
||||
FUNCTION randPos1D(self) RESULT(r)
|
||||
CLASS(meshEdge1D), INTENT(in):: self
|
||||
REAL(8):: r(1:3)
|
||||
|
||||
r = (/ self%x, 0.D0, 0.D0 /)
|
||||
|
||||
END FUNCTION randPos1D
|
||||
|
||||
!VOLUME FUNCTIONS
|
||||
!SEGMENT FUNCTIONS
|
||||
!Init segment element
|
||||
SUBROUTINE initVol1DSegm(self, n, p)
|
||||
USE moduleRefParam
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(out):: self
|
||||
INTEGER, INTENT(in):: n
|
||||
INTEGER, INTENT(in):: p(:)
|
||||
REAL(8), DIMENSION(1:3):: r1, r2
|
||||
|
||||
self%n = n
|
||||
self%n1 => mesh%nodes(p(1))%obj
|
||||
self%n2 => mesh%nodes(p(2))%obj
|
||||
!Get element coordinates
|
||||
r1 = self%n1%getCoordinates()
|
||||
r2 = self%n2%getCoordinates()
|
||||
self%x = (/ r1(1), r2(1) /)
|
||||
|
||||
!Assign node volume
|
||||
CALL self%area()
|
||||
self%n1%v = self%n1%v + self%arNodes(1)
|
||||
self%n2%v = self%n2%v + self%arNodes(2)
|
||||
|
||||
self%sigmaVrelMax = sigma_ref/L_ref**2
|
||||
|
||||
CALL OMP_INIT_LOCK(self%lock)
|
||||
|
||||
END SUBROUTINE initVol1DSegm
|
||||
|
||||
!Computes element area
|
||||
PURE SUBROUTINE areaSegm(self)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(inout):: self
|
||||
REAL(8):: l !element length
|
||||
REAL(8):: fPsi(1:2)
|
||||
REAL(8):: detJ
|
||||
REAL(8):: Xii(1:3)
|
||||
|
||||
self%volume = 0.D0
|
||||
self%arNodes = 0.D0
|
||||
!1 point Gauss integral
|
||||
Xii = 0.D0
|
||||
fPsi = self%fPsi(Xii)
|
||||
detJ = self%detJac(Xii)
|
||||
l = 2.D0*detJ
|
||||
self%volume = l
|
||||
self%arNodes = fPsi*l
|
||||
|
||||
END SUBROUTINE areaSegm
|
||||
|
||||
!Computes element functions at point xii
|
||||
PURE FUNCTION fPsiSegm(xi) RESULT(fPsi)
|
||||
IMPLICIT NONE
|
||||
|
||||
REAL(8), INTENT(in):: xi(1:3)
|
||||
REAL(8), ALLOCATABLE:: fPsi(:)
|
||||
|
||||
ALLOCATE(fPsi(1:2))
|
||||
|
||||
fPsi(1) = 1.D0 - xi(1)
|
||||
fPsi(2) = 1.D0 + xi(1)
|
||||
fPsi = fPsi * 5.D-1
|
||||
|
||||
END FUNCTION fPsiSegm
|
||||
|
||||
!Computes element derivative shape function at Xii
|
||||
PURE FUNCTION dPsiSegm(xi) RESULT(dPsi)
|
||||
IMPLICIT NONE
|
||||
|
||||
REAL(8), INTENT(in):: xi(1:3)
|
||||
REAL(8), ALLOCATABLE:: dPsi(:,:)
|
||||
|
||||
ALLOCATE(dPsi(1:1, 1:2))
|
||||
|
||||
dPsi(1, 1) = -5.D-1
|
||||
dPsi(1, 2) = 5.D-1
|
||||
|
||||
END FUNCTION dPsiSegm
|
||||
|
||||
!Computes partial derivatives of coordinates
|
||||
PURE SUBROUTINE partialDerSegm(self, dPsi, dx)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(in):: self
|
||||
REAL(8), INTENT(in):: dPsi(1:,1:)
|
||||
REAL(8), INTENT(out), DIMENSION(1):: dx
|
||||
|
||||
dx(1) = DOT_PRODUCT(dPsi(1,:), self%x)
|
||||
|
||||
END SUBROUTINE partialDerSegm
|
||||
|
||||
!Computes local stiffness matrix
|
||||
PURE FUNCTION elemKSegm(self) RESULT(ke)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(in):: self
|
||||
REAL(8):: ke(1:2,1:2)
|
||||
REAL(8):: Xii(1:3)
|
||||
REAL(8):: dPsi(1:1, 1:2)
|
||||
REAL(8):: invJ
|
||||
|
||||
ke = 0.D0
|
||||
Xii = (/ 0.D0, 0.D0, 0.D0 /)
|
||||
dPsi = self%dPsi(Xii)
|
||||
invJ = self%invJac(Xii, dPsi)
|
||||
ke(1,:) = (/ dPsi(1,1)*dPsi(1,1), dPsi(1,1)*dPsi(1,2) /)
|
||||
ke(2,:) = (/ dPsi(1,2)*dPsi(1,1), dPsi(1,2)*dPsi(1,2) /)
|
||||
ke = 2.D0*ke*invJ
|
||||
|
||||
END FUNCTION elemKSegm
|
||||
|
||||
PURE FUNCTION elemFSegm(self, source) RESULT(localF)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(in):: self
|
||||
REAL(8), INTENT(in):: source(1:)
|
||||
REAL(8), ALLOCATABLE:: localF(:)
|
||||
REAL(8):: fPsi(1:2)
|
||||
REAL(8):: detJ
|
||||
REAL(8):: Xii(1:3)
|
||||
|
||||
Xii = 0.D0
|
||||
fPsi = self%fPsi(Xii)
|
||||
detJ = self%detJac(Xii)
|
||||
ALLOCATE(localF(1:2))
|
||||
localF = 2.D0*DOT_PRODUCT(fPsi, source)*detJ
|
||||
|
||||
END FUNCTION elemFSegm
|
||||
|
||||
PURE FUNCTION weightSegm(xi) RESULT(w)
|
||||
IMPLICIT NONE
|
||||
|
||||
REAL(8), INTENT(in):: xi(1:3)
|
||||
REAL(8):: w(1:3)
|
||||
|
||||
w = fPsiSegm(xi)
|
||||
|
||||
END FUNCTION weightSegm
|
||||
|
||||
PURE FUNCTION insideSegm(xi) RESULT(ins)
|
||||
IMPLICIT NONE
|
||||
|
||||
REAL(8), INTENT(in):: xi(1:3)
|
||||
LOGICAL:: ins
|
||||
|
||||
ins = xi(1) >=-1.D0 .AND. &
|
||||
xi(1) <= 1.D0
|
||||
|
||||
END FUNCTION insideSegm
|
||||
|
||||
SUBROUTINE scatterSegm(self, part)
|
||||
USE moduleOutput
|
||||
USE moduleSpecies
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(in):: self
|
||||
CLASS(particle), INTENT(in):: part
|
||||
TYPE(outputNode), POINTER:: vertex
|
||||
REAL(8):: w_p(1:2)
|
||||
REAL(8):: tensorS(1:3,1:3)
|
||||
|
||||
w_p = self%weight(part%xi)
|
||||
tensorS = outerProduct(part%v, part%v)
|
||||
|
||||
vertex => self%n1%output(part%sp)
|
||||
vertex%den = vertex%den + part%weight*w_p(1)
|
||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(1)*part%v(:)
|
||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(1)*tensorS
|
||||
|
||||
vertex => self%n2%output(part%sp)
|
||||
vertex%den = vertex%den + part%weight*w_p(2)
|
||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(2)*part%v(:)
|
||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(2)*tensorS
|
||||
|
||||
END SUBROUTINE scatterSegm
|
||||
|
||||
!Gathers EF at position Xii
|
||||
PURE FUNCTION gatherEFSegm(self, xi) RESULT(EF)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(in):: self
|
||||
REAL(8), INTENT(in):: xi(1:3)
|
||||
REAL(8):: dPsi(1, 1:2)
|
||||
REAL(8):: phi(1:2)
|
||||
REAL(8):: EF(1:3)
|
||||
REAL(8):: invJ
|
||||
|
||||
phi = (/ self%n1%emData%phi, &
|
||||
self%n2%emData%phi /)
|
||||
|
||||
dPsi = self%dPsi(xi)
|
||||
invJ = self%invJac(xi, dPsi)
|
||||
EF(1) = -DOT_PRODUCT(dPsi(1, :), phi)*invJ
|
||||
EF(2) = 0.D0
|
||||
EF(3) = 0.D0
|
||||
|
||||
END FUNCTION gatherEFSegm
|
||||
|
||||
!Get nodes from segment
|
||||
PURE FUNCTION getNodesSegm(self) RESULT(n)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(in):: self
|
||||
INTEGER, ALLOCATABLE:: n(:)
|
||||
|
||||
ALLOCATE(n(1:2))
|
||||
n = (/ self%n1%n, self%n2%n /)
|
||||
|
||||
END FUNCTION getNodesSegm
|
||||
|
||||
PURE FUNCTION phy2logSegm(self, r) RESULT(xN)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(in):: self
|
||||
REAL(8), INTENT(in):: r(1:3)
|
||||
REAL(8):: xN(1:3)
|
||||
|
||||
xN = 0.D0
|
||||
xN(1) = 2.D0*(r(1) - self%x(1))/(self%x(2) - self%x(1)) - 1.D0
|
||||
|
||||
END FUNCTION phy2logSegm
|
||||
|
||||
!Get next element for a logical position xi
|
||||
SUBROUTINE nextElementSegm(self, xi, nextElement)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(in):: self
|
||||
REAL(8), INTENT(in):: xi(1:3)
|
||||
CLASS(*), POINTER, INTENT(out):: nextElement
|
||||
|
||||
NULLIFY(nextElement)
|
||||
IF (xi(1) < -1.D0) THEN
|
||||
nextElement => self%e2
|
||||
|
||||
ELSEIF (xi(1) > 1.D0) THEN
|
||||
nextElement => self%e1
|
||||
|
||||
END IF
|
||||
|
||||
END SUBROUTINE nextElementSegm
|
||||
|
||||
!Reset the output of nodes in element
|
||||
PURE SUBROUTINE resetOutputSegm(self)
|
||||
USE moduleSpecies
|
||||
USE moduleOutput
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(inout):: self
|
||||
INTEGER:: k
|
||||
|
||||
DO k = 1, nSpecies
|
||||
self%n1%output(k)%den = 0.D0
|
||||
self%n1%output(k)%mom = 0.D0
|
||||
self%n1%output(k)%tensorS = 0.D0
|
||||
|
||||
self%n2%output(k)%den = 0.D0
|
||||
self%n2%output(k)%mom = 0.D0
|
||||
self%n2%output(k)%tensorS = 0.D0
|
||||
|
||||
END DO
|
||||
|
||||
END SUBROUTINE resetOutputSegm
|
||||
|
||||
|
||||
!COMMON FUNCTIONS FOR 1D VOLUME ELEMENTS
|
||||
!Computes the element Jacobian determinant
|
||||
PURE FUNCTION detJ1D(self, xi, dPsi_in) RESULT(dJ)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1D), INTENT(in):: self
|
||||
REAL(8), INTENT(in):: xi(1:3)
|
||||
REAL(8), INTENT(in), OPTIONAL:: dPsi_in(1:,1:)
|
||||
REAL(8), ALLOCATABLE:: dPsi(:,:)
|
||||
REAL(8):: dJ
|
||||
REAL(8):: dx(1)
|
||||
|
||||
IF (PRESENT(dPsi_in)) THEN
|
||||
dPsi = dPsi_in
|
||||
|
||||
ELSE
|
||||
dPsi = self%dPsi(xi)
|
||||
|
||||
END IF
|
||||
|
||||
CALL self%partialDer(dPsi, dx)
|
||||
dJ = dx(1)
|
||||
|
||||
END FUNCTION detJ1D
|
||||
|
||||
!Computes the invers Jacobian
|
||||
PURE FUNCTION invJ1D(self, xi, dPsi_in) RESULT(invJ)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1D), INTENT(in):: self
|
||||
REAL(8), INTENT(in):: xi(1:3)
|
||||
REAL(8), INTENT(in), OPTIONAL:: dPsi_in(1:,1:)
|
||||
REAL(8), ALLOCATABLE:: dPsi(:,:)
|
||||
REAL(8):: dx(1)
|
||||
REAL(8):: invJ
|
||||
|
||||
IF (PRESENT(dPsi_in)) THEN
|
||||
dPsi = dPsi_in
|
||||
|
||||
ELSE
|
||||
dPsi = self%dPsi(xi)
|
||||
|
||||
END IF
|
||||
|
||||
CALL self%partialDer(dPsi, dx)
|
||||
invJ = 1.D0/dx(1)
|
||||
|
||||
END FUNCTION invJ1D
|
||||
|
||||
|
||||
END MODULE moduleMesh1D
|
||||
|
||||
40
src/modules/moduleMesh1DBoundary.f95
Normal file
40
src/modules/moduleMesh1DBoundary.f95
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
MODULE moduleMesh1DBoundary
|
||||
USE moduleMesh1D
|
||||
|
||||
TYPE, PUBLIC, EXTENDS(meshEdge1D):: meshEdge1DRef
|
||||
CONTAINS
|
||||
PROCEDURE, PASS:: fBoundary => reflection
|
||||
|
||||
END TYPE meshEdge1DRef
|
||||
|
||||
TYPE, PUBLIC, EXTENDS(meshEdge1D):: meshEdge1DAbs
|
||||
CONTAINS
|
||||
PROCEDURE, PASS:: fBoundary => absorption
|
||||
|
||||
END TYPE meshEdge1DAbs
|
||||
|
||||
CONTAINS
|
||||
SUBROUTINE reflection(self, part)
|
||||
USE moduleSpecies
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshEdge1DRef), INTENT(inout):: self
|
||||
CLASS(particle), INTENT(inout):: part
|
||||
|
||||
part%v(1) = -part%v(1)
|
||||
part%r(1) = 2.D0*self%x - part%r(1)
|
||||
|
||||
END SUBROUTINE reflection
|
||||
|
||||
SUBROUTINE absorption(self, part)
|
||||
USE moduleSpecies
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshEdge1DAbs), INTENT(inout):: self
|
||||
CLASS(particle), INTENT(inout):: part
|
||||
|
||||
part%n_in = .FALSE.
|
||||
|
||||
END SUBROUTINE absorption
|
||||
|
||||
END MODULE moduleMesh1DBoundary
|
||||
243
src/modules/moduleMesh1DRead.f95
Normal file
243
src/modules/moduleMesh1DRead.f95
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
MODULE moduleMesh1DRead
|
||||
USE moduleMesh
|
||||
USE moduleMesh1D
|
||||
USE moduleMesh1DBoundary
|
||||
|
||||
TYPE, EXTENDS(meshGeneric):: mesh1DGeneric
|
||||
CONTAINS
|
||||
PROCEDURE, PASS:: readMesh => readMesh1D
|
||||
|
||||
END TYPE
|
||||
|
||||
INTERFACE connected
|
||||
MODULE PROCEDURE connectedVolVol, connectedVolEdge
|
||||
|
||||
END INTERFACE connected
|
||||
|
||||
CONTAINS
|
||||
SUBROUTINE readMesh1D(self, filename)
|
||||
USE moduleBoundary
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(mesh1DGeneric), INTENT(out):: self
|
||||
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
|
||||
REAL(8):: x
|
||||
INTEGER:: p(1:2)
|
||||
INTEGER:: e, et, n, eTemp, elemType, bt
|
||||
INTEGER:: totalNumElem
|
||||
INTEGER:: boundaryType
|
||||
|
||||
!Open file mesh
|
||||
OPEN(10, FILE=TRIM(filename))
|
||||
!Skip header
|
||||
READ(10, *)
|
||||
READ(10, *)
|
||||
READ(10, *)
|
||||
READ(10, *)
|
||||
!Read number of nodes
|
||||
READ(10, *) self%numNodes
|
||||
!Allocate required matrices and vectors
|
||||
ALLOCATE(self%nodes(1:self%numNodes))
|
||||
ALLOCATE(self%K(1:self%numNodes, 1:self%numNodes))
|
||||
ALLOCATE(self%IPIV(1:self%numNodes, 1:self%numNodes))
|
||||
self%K = 0.D0
|
||||
self%IPIV = 0
|
||||
!Read nodes coordinates. Only relevant for x
|
||||
DO e = 1, self%numNodes
|
||||
READ(10, *) n, x
|
||||
ALLOCATE(meshNode1D:: self%nodes(n)%obj)
|
||||
CALL self%nodes(n)%obj%init(n, (/ x, 0.D0, 0.D0 /))
|
||||
|
||||
END DO
|
||||
!Skips comments
|
||||
READ(10, *)
|
||||
READ(10, *)
|
||||
!Reads the total number of elements (edges+vol)
|
||||
READ(10, *) totalNumElem
|
||||
self%numEdges = 0
|
||||
DO e = 1, totalNumElem
|
||||
READ(10, *) eTemp, elemType
|
||||
IF (elemType == 15) THEN !15 is physical node in GMSH
|
||||
self%numEdges = e
|
||||
|
||||
END IF
|
||||
|
||||
END DO
|
||||
|
||||
!Substract the number of edges to the total number of elements
|
||||
!to obtain the number of volume elements
|
||||
self%numVols = totalNumelem - self%numEdges
|
||||
!Allocates arrays
|
||||
ALLOCATE(self%edges(1:self%numEdges))
|
||||
ALLOCATE(self%vols(1:self%numVols))
|
||||
|
||||
!Go back to the beginning of reading elements
|
||||
DO e = 1, totalNumelem
|
||||
BACKSPACE(10)
|
||||
|
||||
END DO
|
||||
|
||||
!Reads edges
|
||||
DO e = 1, self%numEdges
|
||||
READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1)
|
||||
!Associate boundary condition
|
||||
bt = getBoundaryId(boundaryType)
|
||||
SELECT CASE(boundary(bt)%obj%boundaryType)
|
||||
CASE ('reflection')
|
||||
ALLOCATE(meshEdge1DRef:: self%edges(e)%obj)
|
||||
|
||||
CASE ('absorption')
|
||||
ALLOCATE(meshEdge1DAbs:: self%edges(e)%obj)
|
||||
|
||||
END SELECT
|
||||
|
||||
CALL self%edges(e)%obj%init(n, p(1:1), bt, boundaryType)
|
||||
|
||||
END DO
|
||||
|
||||
!Read and initialize volumes
|
||||
DO e = 1, self%numVols
|
||||
READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:2)
|
||||
ALLOCATE(meshVol1DSegm:: self%vols(e)%obj)
|
||||
CALL self%vols(e)%obj%init(n - self%numEdges, p(1:2))
|
||||
|
||||
END DO
|
||||
|
||||
CLOSE(10)
|
||||
|
||||
!Build connectivity between elements
|
||||
DO e = 1, self%numVols
|
||||
!Connectivity between volumes
|
||||
DO et = 1, self%numVols
|
||||
IF (e /= et) THEN
|
||||
CALL connected(self%vols(e)%obj, self%vols(et)%obj)
|
||||
|
||||
END IF
|
||||
|
||||
END DO
|
||||
|
||||
!Connectivity betwen vols and edges
|
||||
DO et = 1, self%numEdges
|
||||
CALL connected(self%vols(e)%obj, self%edges(et)%obj)
|
||||
|
||||
END DO
|
||||
|
||||
!Constructs the global K matrix
|
||||
CALL constructGlobalK(self%K, self%vols(e)%obj)
|
||||
|
||||
END DO
|
||||
|
||||
END SUBROUTINE readMesh1D
|
||||
|
||||
SUBROUTINE connectedVolVol(elemA, elemB)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol), INTENT(inout):: elemA
|
||||
CLASS(meshVol), INTENT(inout):: elemB
|
||||
|
||||
SELECT TYPE(elemA)
|
||||
TYPE IS(meshVol1DSegm)
|
||||
SELECT TYPE(elemB)
|
||||
TYPE IS(meshVol1DSegm)
|
||||
CALL connectedSegmSegm(elemA, elemB)
|
||||
|
||||
END SELECT
|
||||
|
||||
END SELECT
|
||||
|
||||
END SUBROUTINE connectedVolVol
|
||||
|
||||
SUBROUTINE connectedSegmSegm(elemA, elemB)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(inout), TARGET:: elemA
|
||||
CLASS(meshVol1DSegm), INTENT(inout), TARGET:: elemB
|
||||
|
||||
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
||||
elemA%n2%n == elemB%n1%n) THEN
|
||||
elemA%e1 => elemB
|
||||
elemB%e2 => elemA
|
||||
|
||||
END IF
|
||||
|
||||
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
||||
elemA%n1%n == elemB%n2%n) THEN
|
||||
|
||||
elemA%e2 => elemB
|
||||
elemB%e1 => elemA
|
||||
|
||||
END IF
|
||||
|
||||
END SUBROUTINE connectedSegmSegm
|
||||
|
||||
SUBROUTINE connectedVolEdge(elemA, elemB)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol), INTENT(inout):: elemA
|
||||
CLASS(meshEdge), INTENT(inout):: elemB
|
||||
|
||||
SELECT TYPE(elemA)
|
||||
TYPE IS (meshVol1DSegm)
|
||||
SELECT TYPE(elemB)
|
||||
CLASS IS(meshEdge1D)
|
||||
CALL connectedSegmEdge(elemA, elemB)
|
||||
|
||||
END SELECT
|
||||
|
||||
END SELECT
|
||||
|
||||
END SUBROUTINE connectedVolEdge
|
||||
|
||||
SUBROUTINE connectedSegmEdge(elemA, elemB)
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVol1DSegm), INTENT(inout), TARGET:: elemA
|
||||
CLASS(meshEdge1D), INTENT(inout), TARGET:: elemB
|
||||
|
||||
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
||||
elemA%n2%n == elemB%n1%n) THEN
|
||||
|
||||
elemA%e1 => elemB
|
||||
elemB%e2 => elemA
|
||||
|
||||
END IF
|
||||
|
||||
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
||||
elemA%n1%n == elemB%n1%n) THEN
|
||||
|
||||
elemA%e2 => elemB
|
||||
elemB%e1 => elemA
|
||||
|
||||
END IF
|
||||
|
||||
END SUBROUTINE connectedSegmEdge
|
||||
|
||||
SUBROUTINE constructGlobalK(K, elem)
|
||||
IMPLICIT NONE
|
||||
|
||||
REAL(8), INTENT(inout):: K(1:,1:)
|
||||
CLASS(meshVol), INTENT(in):: elem
|
||||
REAL(8):: localK(1:2,1:2)
|
||||
INTEGER:: i, j
|
||||
INTEGER:: n(1:2)
|
||||
|
||||
SELECT TYPE(elem)
|
||||
TYPE IS(meshVol1DSegm)
|
||||
localK = elem%elemK()
|
||||
n = (/ elem%n1%n, elem%n2%n /)
|
||||
|
||||
CLASS DEFAULT
|
||||
n = 0
|
||||
localK = 0.D0
|
||||
|
||||
END SELECT
|
||||
|
||||
DO i = 1, 2
|
||||
DO j = 1, 2
|
||||
K(n(i), n(j)) = K(n(i), n(j)) + localK(i, j)
|
||||
END DO
|
||||
END DO
|
||||
|
||||
END SUBROUTINE constructGlobalK
|
||||
|
||||
END MODULE moduleMesh1DRead
|
||||
|
|
@ -37,8 +37,6 @@ MODULE moduleMeshCyl
|
|||
|
||||
TYPE, PUBLIC, ABSTRACT, EXTENDS(meshVol):: meshVolCyl
|
||||
CONTAINS
|
||||
PROCEDURE, PASS:: collision => collision2DCyl
|
||||
PROCEDURE, PASS:: findCell => findCellCyl
|
||||
PROCEDURE, PASS:: detJac => detJCyl
|
||||
PROCEDURE, PASS:: invJac => invJCyl
|
||||
PROCEDURE(fPsi_interface), DEFERRED, NOPASS:: fPsi
|
||||
|
|
@ -176,7 +174,7 @@ MODULE moduleMeshCyl
|
|||
INTEGER, INTENT(in):: p(:)
|
||||
INTEGER, INTENT(in):: bt
|
||||
INTEGER, INTENT(in):: physicalSurface
|
||||
REAL(8):: r1(1:3), r2(1:3)
|
||||
REAL(8), DIMENSION(1:3):: r1, r2
|
||||
|
||||
self%n = n
|
||||
self%n1 => mesh%nodes(p(1))%obj
|
||||
|
|
@ -581,7 +579,7 @@ MODULE moduleMeshCyl
|
|||
|
||||
END SUBROUTINE nextElementQuad
|
||||
|
||||
!Reset the output of nodes in tria element
|
||||
!Reset the output of nodes in quad element
|
||||
PURE SUBROUTINE resetOutputQuad(self)
|
||||
USE moduleSpecies
|
||||
USE moduleOutput
|
||||
|
|
@ -1021,122 +1019,4 @@ MODULE moduleMeshCyl
|
|||
|
||||
END FUNCTION invJCyl
|
||||
|
||||
!Find next cell for particle
|
||||
RECURSIVE SUBROUTINE findCellCyl(self, part, oldCell)
|
||||
USE moduleSpecies
|
||||
USE OMP_LIB
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVolCyl), INTENT(inout):: self
|
||||
CLASS(meshVol), OPTIONAL, INTENT(in):: oldCell
|
||||
CLASS(particle), INTENT(inout), TARGET:: part
|
||||
REAL(8):: xi(1:3)
|
||||
CLASS(*), POINTER:: nextElement
|
||||
|
||||
xi = self%phy2log(part%r)
|
||||
!Checks if particle is inside 'self' cell
|
||||
IF (self%inside(xi)) THEN
|
||||
part%vol = self%n
|
||||
part%xi = xi
|
||||
part%n_in = .TRUE.
|
||||
!Assign particle to listPart_in
|
||||
CALL OMP_SET_LOCK(self%lock)
|
||||
CALL self%listPart_in%add(part)
|
||||
self%totalWeight = self%totalWeight + part%weight
|
||||
CALL OMP_UNSET_LOCK(self%lock)
|
||||
|
||||
ELSE
|
||||
!If not, searches for a neighbour and repeats the process.
|
||||
CALL self%nextElement(xi, nextElement)
|
||||
!Defines the next step
|
||||
SELECT TYPE(nextElement)
|
||||
CLASS IS(meshVolCyl)
|
||||
!Particle moved to new cell, repeat find procedure
|
||||
CALL nextElement%findCell(part, self)
|
||||
|
||||
CLASS IS (meshEdgeCyl)
|
||||
!Particle encountered an edge, execute boundary
|
||||
CALL nextElement%fBoundary(part)
|
||||
!If particle is still inside the domain, call findCell
|
||||
IF (part%n_in) THEN
|
||||
IF(PRESENT(oldCell)) THEN
|
||||
CALL self%findCell(part, oldCell)
|
||||
|
||||
ELSE
|
||||
CALL self%findCell(part)
|
||||
|
||||
END IF
|
||||
END IF
|
||||
|
||||
CLASS DEFAULT
|
||||
WRITE(*,*) "ERROR, CHECK findCellCylQuad"
|
||||
|
||||
END SELECT
|
||||
END IF
|
||||
|
||||
END SUBROUTINE findCellCyl
|
||||
|
||||
!Computes collisions in element
|
||||
SUBROUTINE collision2DCyl(self)
|
||||
USE moduleCollisions
|
||||
USE moduleSpecies
|
||||
USE moduleList
|
||||
use moduleRefParam
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshVolCyl), INTENT(inout):: self
|
||||
INTEGER:: nPart !Number of particles inside the cell
|
||||
REAL(8):: pMax !Maximum probability of collision
|
||||
INTEGER:: rnd !random index
|
||||
TYPE(particle), POINTER:: part_i, part_j
|
||||
INTEGER:: n !collision
|
||||
INTEGER:: ij, k
|
||||
REAL(8):: sigmaVrelMaxNew
|
||||
TYPE(pointerArray), ALLOCATABLE:: partTemp(:)
|
||||
|
||||
self%nColl = 0
|
||||
nPart = self%listPart_in%amount
|
||||
IF (nPart > 1) THEN
|
||||
pMax = self%totalWeight*self%sigmaVrelMax*tauMin/self%volume
|
||||
self%nColl = INT(REAL(nPart)*pMax*0.5D0)
|
||||
|
||||
!Converts the list of particles to an array for easy access
|
||||
IF (self%nColl > 0) THEN
|
||||
partTemp = self%listPart_in%convert2Array()
|
||||
|
||||
END IF
|
||||
|
||||
DO n = 1, self%nColl
|
||||
!Select random numbers
|
||||
rnd = 1 + FLOOR(nPart*RAND())
|
||||
part_i => partTemp(rnd)%part
|
||||
rnd = 1 + FLOOR(nPart*RAND())
|
||||
part_j => partTemp(rnd)%part
|
||||
ij = interactionIndex(part_i%sp, part_j%sp)
|
||||
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 DO
|
||||
|
||||
END IF
|
||||
|
||||
self%totalWeight = 0.D0
|
||||
|
||||
!Reset output in nodes
|
||||
CALL self%resetOutput()
|
||||
|
||||
!Erase the list of particles inside the cell
|
||||
CALL self%listPart_in%erase()
|
||||
|
||||
END SUBROUTINE collision2DCyl
|
||||
|
||||
END MODULE moduleMeshCyl
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ MODULE moduleMeshCylRead
|
|||
|
||||
TYPE, EXTENDS(meshGeneric):: meshCylGeneric
|
||||
CONTAINS
|
||||
PROCEDURE, PASS:: readMesh => readMeshCyl
|
||||
PROCEDURE, PASS:: printOutput => printOutputCyl
|
||||
PROCEDURE, PASS:: printColl => printCollisionsCyl
|
||||
PROCEDURE, PASS:: printEM => printEMCyl
|
||||
PROCEDURE, PASS:: readMesh => readMeshCyl
|
||||
|
||||
END TYPE
|
||||
|
||||
|
|
@ -19,7 +16,6 @@ MODULE moduleMeshCylRead
|
|||
|
||||
CONTAINS
|
||||
SUBROUTINE readMeshCyl(self, filename)
|
||||
USE moduleRefParam
|
||||
USE moduleBoundary
|
||||
IMPLICIT NONE
|
||||
|
||||
|
|
@ -82,7 +78,6 @@ MODULE moduleMeshCylRead
|
|||
DO e=1, self%numEdges
|
||||
READ(10,*) n, elemType, eTemp, boundaryType, eTemp, p(1:2)
|
||||
!Associate boundary condition procedure.
|
||||
!TODO: move to subroutine
|
||||
bt = getBoundaryId(boundaryType)
|
||||
SELECT CASE(boundary(bt)%obj%boundaryType)
|
||||
CASE ('reflection')
|
||||
|
|
@ -120,7 +115,6 @@ MODULE moduleMeshCylRead
|
|||
|
||||
END SELECT
|
||||
|
||||
|
||||
END DO
|
||||
|
||||
CLOSE(10)
|
||||
|
|
@ -128,12 +122,12 @@ MODULE moduleMeshCylRead
|
|||
!Build connectivity between elements
|
||||
DO e = 1, self%numVols
|
||||
!Connectivity between volumes
|
||||
IF (e /= et) THEN
|
||||
DO et = 1, self%numVols
|
||||
DO et = 1, self%numVols
|
||||
IF (e /= et) THEN
|
||||
CALL connected(self%vols(e)%obj, self%vols(et)%obj)
|
||||
|
||||
END DO
|
||||
END IF
|
||||
END IF
|
||||
END DO
|
||||
|
||||
!Connectivity between vols and edges
|
||||
DO et = 1, self%numEdges
|
||||
|
|
@ -588,194 +582,4 @@ MODULE moduleMeshCylRead
|
|||
|
||||
END SUBROUTINE constructGlobalK
|
||||
|
||||
SUBROUTINE printOutputCyl(self, t)
|
||||
USE moduleRefParam
|
||||
USE moduleSpecies
|
||||
USE moduleOutput
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshCylGeneric), INTENT(in):: self
|
||||
INTEGER, INTENT(in):: t
|
||||
INTEGER:: n, i
|
||||
TYPE(outputFormat):: output(1:self%numNodes)
|
||||
REAL(8):: time
|
||||
CHARACTER(:), ALLOCATABLE:: fileName
|
||||
CHARACTER (LEN=6):: tstring !TODO: Review to allow any number of iterations
|
||||
|
||||
time = DBLE(t)*tauMin*ti_ref
|
||||
|
||||
DO i = 1, nSpecies
|
||||
WRITE(tstring, '(I6.6)') t
|
||||
fileName='OUTPUT_' // tstring// '_' // species(i)%obj%name // '.msh'
|
||||
WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
|
||||
OPEN (60, file = path // folder // '/' // fileName)
|
||||
WRITE(60, "(A)") '$MeshFormat'
|
||||
WRITE(60, "(A)") '2.2 0 8'
|
||||
WRITE(60, "(A)") '$EndMeshFormat'
|
||||
WRITE(60, "(A)") '$NodeData'
|
||||
WRITE(60, "(A)") '1'
|
||||
WRITE(60, "(A)") '"Density (m^-3)"'
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) time
|
||||
WRITE(60, *) 3
|
||||
WRITE(60, *) t
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) self%numNodes
|
||||
DO n=1, self%numNodes
|
||||
CALL calculateOutput(self%nodes(n)%obj%output(i), output(n), self%nodes(n)%obj%v, species(i)%obj)
|
||||
WRITE(60, "(I6,ES20.6E3)") n, output(n)%density
|
||||
END DO
|
||||
WRITE(60, "(A)") '$EndNodeData'
|
||||
WRITE(60, "(A)") '$NodeData'
|
||||
WRITE(60, "(A)") '1'
|
||||
WRITE(60, "(A)") '"Velocity (m/s)"'
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) time
|
||||
WRITE(60, *) 3
|
||||
WRITE(60, *) t
|
||||
WRITE(60, *) 3
|
||||
WRITE(60, *) self%numNodes
|
||||
DO n=1, self%numNodes
|
||||
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%velocity
|
||||
END DO
|
||||
WRITE(60, "(A)") '$EndNodeData'
|
||||
WRITE(60, "(A)") '$NodeData'
|
||||
WRITE(60, "(A)") '1'
|
||||
WRITE(60, "(A)") '"Pressure (Pa)"'
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) time
|
||||
WRITE(60, *) 3
|
||||
WRITE(60, *) t
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) self%numNodes
|
||||
DO n=1, self%numNodes
|
||||
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%pressure
|
||||
END DO
|
||||
WRITE(60, "(A)") '$EndNodeData'
|
||||
WRITE(60, "(A)") '$NodeData'
|
||||
WRITE(60, "(A)") '1'
|
||||
WRITE(60, "(A)") '"Temperature (K)"'
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) time
|
||||
WRITE(60, *) 3
|
||||
WRITE(60, *) t
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) self%numNodes
|
||||
DO n=1, self%numNodes
|
||||
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%temperature
|
||||
END DO
|
||||
WRITE(60, "(A)") '$EndNodeData'
|
||||
CLOSE (60)
|
||||
|
||||
END DO
|
||||
|
||||
END SUBROUTINE printOutputCyl
|
||||
|
||||
SUBROUTINE printCollisionsCyl(self, t)
|
||||
USE moduleRefParam
|
||||
USE moduleCaseParam
|
||||
USE moduleOutput
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshCylGeneric), INTENT(in):: self
|
||||
INTEGER, INTENT(in):: t
|
||||
INTEGER:: n
|
||||
REAL(8):: time
|
||||
CHARACTER(:), ALLOCATABLE:: fileName
|
||||
CHARACTER (LEN=6):: tstring !TODO: Review to allow any number of iterations
|
||||
|
||||
|
||||
IF (collOutput) THEN
|
||||
time = DBLE(t)*tauMin*ti_ref
|
||||
WRITE(tstring, '(I6.6)') t
|
||||
|
||||
fileName='OUTPUT_' // tstring// '_Collisions.msh'
|
||||
WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
|
||||
OPEN (60, file = path // folder // '/' // fileName)
|
||||
WRITE(60, "(A)") '$MeshFormat'
|
||||
WRITE(60, "(A)") '2.2 0 8'
|
||||
WRITE(60, "(A)") '$EndMeshFormat'
|
||||
WRITE(60, "(A)") '$ElementData'
|
||||
WRITE(60, "(A)") '1'
|
||||
WRITE(60, "(A)") '"Collisions"'
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) time
|
||||
WRITE(60, *) 3
|
||||
WRITE(60, *) t
|
||||
WRITE(60, *) 1
|
||||
WRITE(60, *) self%numVols
|
||||
DO n=1, self%numVols
|
||||
WRITE(60, "(I6,I10)") n + self%numEdges, self%vols(n)%obj%nColl
|
||||
END DO
|
||||
WRITE(60, "(A)") '$EndElementData'
|
||||
|
||||
CLOSE(60)
|
||||
|
||||
END IF
|
||||
|
||||
END SUBROUTINE printCollisionsCyl
|
||||
|
||||
SUBROUTINE printEMCyl(self, t)
|
||||
USE moduleRefParam
|
||||
USE moduleCaseParam
|
||||
USE moduleOutput
|
||||
IMPLICIT NONE
|
||||
|
||||
CLASS(meshCylGeneric), INTENT(in):: self
|
||||
INTEGER, INTENT(in):: t
|
||||
INTEGER:: n, e
|
||||
REAL(8):: time
|
||||
CHARACTER(:), ALLOCATABLE:: fileName
|
||||
CHARACTER (LEN=6):: tstring !TODO: Review to allow any number of iterations
|
||||
REAL(8):: xi(1:3)
|
||||
|
||||
IF (emOutput) THEN
|
||||
time = DBLE(t)*tauMin*ti_ref
|
||||
WRITE(tstring, '(I6.6)') t
|
||||
|
||||
fileName='OUTPUT_' // tstring// '_EMField.msh'
|
||||
WRITE(*, "(6X,A15,A)") "Creating file: ", fileName
|
||||
OPEN (20, file = path // folder // '/' // fileName)
|
||||
WRITE(20, "(A)") '$MeshFormat'
|
||||
WRITE(20, "(A)") '2.2 0 8'
|
||||
WRITE(20, "(A)") '$EndMeshFormat'
|
||||
WRITE(20, "(A)") '$NodeData'
|
||||
WRITE(20, "(A)") '1'
|
||||
WRITE(20, "(A)") '"Potential (V)"'
|
||||
WRITE(20, *) 1
|
||||
WRITE(20, *) time
|
||||
WRITE(20, *) 3
|
||||
WRITE(20, *) t
|
||||
WRITE(20, *) 1
|
||||
WRITE(20, *) self%numNodes
|
||||
DO n=1, self%numNodes
|
||||
WRITE(20, *) n, self%nodes(n)%obj%emData%phi*Volt_ref
|
||||
END DO
|
||||
WRITE(20, "(A)") '$EndNodeData'
|
||||
|
||||
WRITE(20, "(A)") '$ElementData'
|
||||
WRITE(20, "(A)") '1'
|
||||
WRITE(20, "(A)") '"Electric Field (V/m)"'
|
||||
WRITE(20, *) 1
|
||||
WRITE(20, *) time
|
||||
WRITE(20, *) 3
|
||||
WRITE(20, *) t
|
||||
WRITE(20, *) 3
|
||||
WRITE(20, *) self%numVols
|
||||
DO e=1, self%numVols
|
||||
SELECT TYPE(elem=>self%vols(e)%obj)
|
||||
TYPE IS(meshVolCylQuad)
|
||||
xi = (/ 0.D0, 0.D0, 0.D0 /)
|
||||
TYPE IS(meshVolCylTria)
|
||||
xi = (/ 1.D0/3.D0, 1.D0/3.D0, 0.D0 /)
|
||||
END SELECT
|
||||
WRITE(20, *) e+self%numEdges, self%vols(e)%obj%gatherEF(xi)*EF_ref
|
||||
END DO
|
||||
WRITE(20, "(A)") '$EndElementData'
|
||||
CLOSE(20)
|
||||
|
||||
END IF
|
||||
|
||||
END SUBROUTINE printEMCyl
|
||||
|
||||
END MODULE moduleMeshCylRead
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ MODULE moduleSolver
|
|||
CASE('2DCylCharged')
|
||||
self%pushParticle => pushCylCharged
|
||||
|
||||
CASE('1DCartCharged')
|
||||
self%pushParticle => push1DCharged
|
||||
|
||||
CASE DEFAULT
|
||||
CALL criticalError('Solver ' // pusherType // ' not found','readCase')
|
||||
|
||||
|
|
@ -227,6 +230,33 @@ MODULE moduleSolver
|
|||
|
||||
END SUBROUTINE pushCylCharged
|
||||
|
||||
!Push charged particles in 1D cartesian coordinates
|
||||
PURE SUBROUTINE push1DCharged(part)
|
||||
USE moduleSPecies
|
||||
USE moduleEM
|
||||
IMPLICIT NONE
|
||||
|
||||
TYPE(particle), INTENT(inout):: part
|
||||
TYPE(particle):: part_temp
|
||||
REAL(8):: tauSp
|
||||
REAL(8):: qmEFt(1:3)
|
||||
|
||||
part_temp = part
|
||||
!Time step for particle species
|
||||
tauSp = tau(part_temp%sp)
|
||||
!Get the electric field at particle position
|
||||
qmEFt = part_temp%qm*gatherElecField(part_temp)*tauSp
|
||||
|
||||
!x
|
||||
part_temp%v(1) = part%v(1) + qmEFt(1)
|
||||
part_temp%r(1) = part%r(1) + part_temp%v(1)*tauSp
|
||||
|
||||
part_temp%n_in = .FALSE.
|
||||
|
||||
part = part_temp
|
||||
|
||||
END SUBROUTINE push1DCharged
|
||||
|
||||
!Do the collisions in all the cells
|
||||
SUBROUTINE doCollisions()
|
||||
USE moduleMesh
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue