First version with possibility for charged particles to be included.
Now, the solver needs to be an input parameter of the case, to select if it is for charged or neutral particles. Resolution of Poisson equation with Dirichlet boundary conditions is possible. The source vector is the charge density. This resolution is done in two steps to save computational time: 1. When reading the mesh, the PLU factorization of the K matrix is computed. 2. In each iteration, the system K*u = f is solved, in which f is the source vector (charge density) and u is the solution (potential) in each node. No case has been added to the repository. This will be done in next commit. The 'non-analog' scheme has been commented. It still needs to split the particle to avoid 'overweight' particles.
This commit is contained in:
parent
73fc9f69c1
commit
c82279f5c5
20 changed files with 859 additions and 227 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,4 +1,4 @@
|
||||||
DSMC_Neutrals
|
PPartiC
|
||||||
mod/
|
mod/
|
||||||
obj/
|
obj/
|
||||||
doc/user_manual/
|
doc/user_manual/
|
||||||
|
|
|
||||||
10
makefile
10
makefile
|
|
@ -12,20 +12,24 @@ JSONINC := $(JSONDIR)/include
|
||||||
INCDIR :=
|
INCDIR :=
|
||||||
INCDIR += $(JSONINC)
|
INCDIR += $(JSONINC)
|
||||||
|
|
||||||
|
VAR := ""
|
||||||
|
|
||||||
# compile flags
|
# compile flags
|
||||||
FCFLAGS := -fopenmp -Ofast -J $(MODDIR) -I $(INCDIR) -Wall -fno-stack-arrays -g
|
FCFLAGS := -fopenmp -Ofast -J $(MODDIR) -I $(INCDIR) -Wall -g
|
||||||
|
|
||||||
#Output file
|
#Output file
|
||||||
OUTPUT = DSMC_Neutrals
|
OUTPUT = PPartiC
|
||||||
|
|
||||||
export
|
export
|
||||||
|
|
||||||
|
all: $(OUTPUT)
|
||||||
|
|
||||||
$(OUTPUT): src.o
|
$(OUTPUT): src.o
|
||||||
|
|
||||||
src.o:
|
src.o:
|
||||||
@mkdir -p $(MODDIR)
|
@mkdir -p $(MODDIR)
|
||||||
@mkdir -p $(OBJDIR)
|
@mkdir -p $(OBJDIR)
|
||||||
$(MAKE) -C src all
|
$(MAKE) -C src $(OUTPUT)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OUTPUT)
|
rm -f $(OUTPUT)
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,9 @@
|
||||||
"radius": 1.88e-10
|
"radius": 1.88e-10
|
||||||
},
|
},
|
||||||
"case": {
|
"case": {
|
||||||
"tau": 6.e-7,
|
"tau": 6.0e-7,
|
||||||
"time": 3.e-3
|
"time": 3.0e-3,
|
||||||
|
"solver": "2DCylNeutral"
|
||||||
},
|
},
|
||||||
"interactions": {
|
"interactions": {
|
||||||
"folderCollisions": "./data/collisions/",
|
"folderCollisions": "./data/collisions/",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
! PPartiC neutral DSMC main program.
|
! PPartiC neutral PIC main program.
|
||||||
PROGRAM DSMC_Neutrals
|
PROGRAM PPartiC
|
||||||
USE moduleInput
|
USE moduleInput
|
||||||
USE moduleErrors
|
USE moduleErrors
|
||||||
USE OMP_LIB
|
USE OMP_LIB
|
||||||
|
|
@ -10,28 +10,32 @@ PROGRAM DSMC_Neutrals
|
||||||
USE moduleMesh
|
USE moduleMesh
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
! t = time step; n = number of particle; e = number of element; i = number of inject
|
! t = time step
|
||||||
INTEGER:: t = 0
|
INTEGER:: t = 0
|
||||||
|
! arg1 = Input argument 1 (input file)
|
||||||
CHARACTER(200):: arg1
|
CHARACTER(200):: arg1
|
||||||
|
! inputFile = path+name of input file
|
||||||
CHARACTER(:), ALLOCATABLE:: inputFile
|
CHARACTER(:), ALLOCATABLE:: inputFile
|
||||||
|
|
||||||
|
|
||||||
tStep = omp_get_wtime()
|
tStep = omp_get_wtime()
|
||||||
!Gets the input file
|
!Gets the input file
|
||||||
CALL getarg(1, arg1)
|
CALL getarg(1, arg1)
|
||||||
inputFile = TRIM(arg1)
|
inputFile = TRIM(arg1)
|
||||||
!If no input file is declared, a critical error is called
|
!If no input file is declared, a critical error is called
|
||||||
IF (inputFile == "") CALL criticalError("No input file provided", "DSMC_Neutrals")
|
IF (inputFile == "") CALL criticalError("No input file provided", "PPartiC")
|
||||||
|
|
||||||
!Reads the json configuration file
|
!Reads the json configuration file
|
||||||
CALL readConfig(inputFile)
|
CALL readConfig(inputFile)
|
||||||
|
|
||||||
|
CALL verboseError("Calculating initial EM field...")
|
||||||
|
CALL doEMField()
|
||||||
|
|
||||||
tStep = omp_get_wtime() - tStep
|
tStep = omp_get_wtime() - tStep
|
||||||
|
|
||||||
!Output initial state
|
!Output initial state
|
||||||
CALL doOutput(t)
|
CALL doOutput(t)
|
||||||
CALL verboseError('Starting main loop...')
|
CALL verboseError('Starting main loop...')
|
||||||
!$OMP PARALLEL PRIVATE(t) DEFAULT(SHARED)
|
!$OMP PARALLEL DEFAULT(SHARED)
|
||||||
DO t = 1, tmax
|
DO t = 1, tmax
|
||||||
!Insert new particles and push them
|
!Insert new particles and push them
|
||||||
!$OMP SINGLE
|
!$OMP SINGLE
|
||||||
|
|
@ -46,18 +50,18 @@ PROGRAM DSMC_Neutrals
|
||||||
|
|
||||||
!$OMP SINGLE
|
!$OMP SINGLE
|
||||||
tPush = omp_get_wtime() - tPush
|
tPush = omp_get_wtime() - tPush
|
||||||
|
!Collisions
|
||||||
tColl = omp_get_wtime()
|
tColl = omp_get_wtime()
|
||||||
!$OMP END SINGLE
|
!$OMP END SINGLE
|
||||||
|
|
||||||
!Collisions
|
|
||||||
CALL doCollisions()
|
CALL doCollisions()
|
||||||
|
|
||||||
!$OMP SINGLE
|
!$OMP SINGLE
|
||||||
tColl = omp_get_wtime() - tColl
|
tColl = omp_get_wtime() - tColl
|
||||||
|
!Reset particles
|
||||||
tReset = omp_get_wtime()
|
tReset = omp_get_wtime()
|
||||||
!$OMP END SINGLE
|
!$OMP END SINGLE
|
||||||
|
|
||||||
!Reset particles
|
|
||||||
CALL doReset()
|
CALL doReset()
|
||||||
|
|
||||||
!$OMP SINGLE
|
!$OMP SINGLE
|
||||||
|
|
@ -71,6 +75,13 @@ PROGRAM DSMC_Neutrals
|
||||||
|
|
||||||
!$OMP SINGLE
|
!$OMP SINGLE
|
||||||
tWeight = omp_get_wtime() - tWeight
|
tWeight = omp_get_wtime() - tWeight
|
||||||
|
tEMField = omp_get_wtime()
|
||||||
|
!$OMP END SINGLE
|
||||||
|
|
||||||
|
CALL doEMField()
|
||||||
|
|
||||||
|
!$OMP SINGLE
|
||||||
|
tEMField = omp_get_wtime() - tEMField
|
||||||
tStep = omp_get_wtime() - tStep
|
tStep = omp_get_wtime() - tStep
|
||||||
!Output data
|
!Output data
|
||||||
CALL doOutput(t)
|
CALL doOutput(t)
|
||||||
|
|
@ -79,5 +90,5 @@ PROGRAM DSMC_Neutrals
|
||||||
END DO
|
END DO
|
||||||
!$OMP END PARALLEL
|
!$OMP END PARALLEL
|
||||||
|
|
||||||
END PROGRAM DSMC_Neutrals
|
END PROGRAM PPartiC
|
||||||
|
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
OBJECTS = $(OBJDIR)/$(OUTPUT).o \
|
OBJECTS = $(OBJDIR)/moduleMesh.o $(OBJDIR)/moduleCompTime.o $(OBJDIR)/moduleSolver.o \
|
||||||
$(OBJDIR)/moduleMesh.o $(OBJDIR)/moduleCompTime.o $(OBJDIR)/moduleSolver.o \
|
|
||||||
$(OBJDIR)/moduleSpecies.o $(OBJDIR)/moduleInject.o $(OBJDIR)/moduleInput.o \
|
$(OBJDIR)/moduleSpecies.o $(OBJDIR)/moduleInject.o $(OBJDIR)/moduleInput.o \
|
||||||
$(OBJDIR)/moduleErrors.o $(OBJDIR)/moduleList.o $(OBJDIR)/moduleOutput.o \
|
$(OBJDIR)/moduleErrors.o $(OBJDIR)/moduleList.o $(OBJDIR)/moduleOutput.o \
|
||||||
$(OBJDIR)/moduleMeshCyl.o $(OBJDIR)/moduleMeshCylRead.o $(OBJDIR)/moduleMeshCylBoundary.o \
|
$(OBJDIR)/moduleMeshCyl.o $(OBJDIR)/moduleMeshCylRead.o $(OBJDIR)/moduleMeshCylBoundary.o \
|
||||||
$(OBJDIR)/moduleBoundary.o $(OBJDIR)/moduleCaseParam.o $(OBJDIR)/moduleRefParam.o \
|
$(OBJDIR)/moduleBoundary.o $(OBJDIR)/moduleCaseParam.o $(OBJDIR)/moduleRefParam.o \
|
||||||
$(OBJDIR)/moduleCollisions.o $(OBJDIR)/moduleTable.o $(OBJDIR)/moduleParallel.o
|
$(OBJDIR)/moduleCollisions.o $(OBJDIR)/moduleTable.o $(OBJDIR)/moduleParallel.o \
|
||||||
|
$(OBJDIR)/moduleEM.o
|
||||||
|
|
||||||
all: $(OUTPUT)
|
all: $(OUTPUT)
|
||||||
$(FC) $(FCFLAGS) -o $(TOPDIR)/$(OUTPUT) $(OBJECTS) $(JSONLIB)
|
|
||||||
|
|
||||||
$(OUTPUT): modules.o $(OUTPUT).f95
|
$(OUTPUT): modules.o $(OUTPUT).f95
|
||||||
$(FC) $(FCFLAGS) -o $(OBJDIR)/$(OUTPUT).o -c $(OUTPUT).f95
|
$(FC) $(FCFLAGS) -o $(OBJDIR)/$(OUTPUT).o -c $(OUTPUT).f95
|
||||||
|
$(FC) $(FCFLAGS) -o $(TOPDIR)/$(OUTPUT) $(OBJECTS) $(OBJDIR)/$(OUTPUT).o $(JSONLIB) -L/usr/local/lib -llapack -lopenblas
|
||||||
|
|
||||||
modules.o:
|
modules.o:
|
||||||
$(MAKE) -C modules all
|
$(MAKE) -C modules all
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ OBJS = moduleCaseParam.o moduleCompTime.o moduleList.o\
|
||||||
moduleMesh.o moduleMeshCyl.o moduleMeshCylBoundary.o\
|
moduleMesh.o moduleMeshCyl.o moduleMeshCylBoundary.o\
|
||||||
moduleMeshCylRead.o moduleOutput.o moduleInput.o \
|
moduleMeshCylRead.o moduleOutput.o moduleInput.o \
|
||||||
moduleSolver.o moduleCollisions.o moduleTable.o \
|
moduleSolver.o moduleCollisions.o moduleTable.o \
|
||||||
moduleParallel.o
|
moduleParallel.o moduleEM.o
|
||||||
|
|
||||||
all: $(OBJS)
|
all: $(OBJS)
|
||||||
|
|
||||||
|
|
@ -40,11 +40,14 @@ moduleRefParam.o: moduleConstParam.o moduleRefParam.f95
|
||||||
moduleSpecies.o: moduleCaseParam.o moduleSpecies.f95
|
moduleSpecies.o: moduleCaseParam.o moduleSpecies.f95
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||||
|
|
||||||
moduleSolver.o: moduleSpecies.o moduleRefParam.o moduleMesh.o moduleOutput.o moduleSolver.f95
|
moduleSolver.o: moduleEM.o moduleSpecies.o moduleRefParam.o moduleMesh.o moduleOutput.o moduleSolver.f95
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||||
|
|
||||||
moduleTable.o: moduleErrors.o moduleTable.f95
|
moduleTable.o: moduleErrors.o moduleTable.f95
|
||||||
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||||
|
|
||||||
|
moduleEM.o: moduleSpecies.o moduleMesh.o moduleEM.f95
|
||||||
|
$(FC) $(FCFLAGS) -c $(subst .o,.f95,$@) -o $(OBJDIR)/$@
|
||||||
|
|
||||||
%.o: %.f95
|
%.o: %.f95
|
||||||
$(FC) $(FCFLAGS) -c $< -o $(OBJDIR)/$@
|
$(FC) $(FCFLAGS) -c $< -o $(OBJDIR)/$@
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ MODULE moduleCompTime
|
||||||
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):: tWeight=0.D0
|
||||||
|
REAL(8):: tEMField=0.D0
|
||||||
|
|
||||||
END MODULE moduleCompTime
|
END MODULE moduleCompTime
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,10 @@ MODULE moduleConstParam
|
||||||
|
|
||||||
REAL(8), PARAMETER:: PI = 4.D0*DATAN(1.D0) !number pi
|
REAL(8), PARAMETER:: PI = 4.D0*DATAN(1.D0) !number pi
|
||||||
REAL(8), PARAMETER:: sccm2atomPerS = 4.5D17 !sccm to atom s^-1
|
REAL(8), PARAMETER:: sccm2atomPerS = 4.5D17 !sccm to atom s^-1
|
||||||
REAL(8), PARAMETER:: eV2J = 1.60217662D-19 !Electron volt to Joule (elementary charge)
|
REAL(8), PARAMETER:: qe = 1.60217662D-19 !Elementary charge
|
||||||
REAL(8), PARAMETER:: kb = 1.38064852D-23 !Boltzmann constants SI
|
REAL(8), PARAMETER:: kb = 1.38064852D-23 !Boltzmann constants SI
|
||||||
! REAL(8), PARAMETER:: eps_0 = 8.8542D-12 !Epsilon_0 (Not used in Neutrals)
|
REAL(8), PARAMETER:: eV2J = qe !Electron volt to Joule conversion
|
||||||
|
REAL(8), PARAMETER:: eps_0 = 8.8542D-12 !Epsilon_0
|
||||||
|
|
||||||
END MODULE moduleConstParam
|
END MODULE moduleConstParam
|
||||||
|
|
||||||
|
|
|
||||||
133
src/modules/moduleEM.f95
Normal file
133
src/modules/moduleEM.f95
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
!Module to solve the electromagnetic field
|
||||||
|
MODULE moduleEM
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
TYPE:: boundaryEM
|
||||||
|
CHARACTER(:), ALLOCATABLE:: typeEM
|
||||||
|
INTEGER:: physicalSurface
|
||||||
|
REAL(8):: potential
|
||||||
|
|
||||||
|
CONTAINS
|
||||||
|
PROCEDURE, PASS:: apply
|
||||||
|
|
||||||
|
END TYPE boundaryEM
|
||||||
|
|
||||||
|
INTEGER:: nBoundaryEM
|
||||||
|
TYPE(boundaryEM), ALLOCATABLE:: boundEM(:)
|
||||||
|
|
||||||
|
!Information of charge and reference parameters for rho vector
|
||||||
|
REAL(8), ALLOCATABLE:: qSpecies(:)
|
||||||
|
|
||||||
|
CONTAINS
|
||||||
|
SUBROUTINE apply(self, edge)
|
||||||
|
USE moduleMesh
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(boundaryEM), INTENT(in):: self
|
||||||
|
CLASS(meshEdge):: edge
|
||||||
|
INTEGER, ALLOCATABLE:: nodes(:)
|
||||||
|
INTEGER:: n
|
||||||
|
|
||||||
|
nodes = edge%getNodes()
|
||||||
|
|
||||||
|
DO n = 1, SIZE(nodes)
|
||||||
|
SELECT CASE(self%typeEM)
|
||||||
|
CASE ("dirichlet")
|
||||||
|
mesh%K(nodes(n), :) = 0.D0
|
||||||
|
mesh%K(nodes(n), nodes(n)) = 1.D0
|
||||||
|
|
||||||
|
mesh%nodes(nodes(n))%obj%emData%type = self%typeEM
|
||||||
|
mesh%nodes(nodes(n))%obj%emData%phi = self%potential
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SUBROUTINE
|
||||||
|
|
||||||
|
PURE FUNCTION gatherElecField(part) RESULT(elField)
|
||||||
|
USE moduleSpecies
|
||||||
|
USE moduleMesh
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
TYPE(particle), INTENT(in):: part
|
||||||
|
REAl(8):: xi(1:3) !Logical coordinates of particle in element
|
||||||
|
REAL(8):: elField(1:3)
|
||||||
|
|
||||||
|
elField = 0.D0
|
||||||
|
|
||||||
|
xi = part%xLog
|
||||||
|
|
||||||
|
elField = mesh%vols(part%e_p)%obj%gatherEF(xi)
|
||||||
|
|
||||||
|
END FUNCTION gatherElecField
|
||||||
|
|
||||||
|
SUBROUTINE assembleSourceVector(vectorF)
|
||||||
|
USE moduleMesh
|
||||||
|
USE moduleRefParam
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
REAL(8), INTENT(out):: vectorF(1:mesh%numNodes)
|
||||||
|
REAL(8), ALLOCATABLE:: localF(:)
|
||||||
|
INTEGER, ALLOCATABLE:: nodes(:)
|
||||||
|
REAL(8), ALLOCATABLE:: rho(:)
|
||||||
|
INTEGER:: nNodes
|
||||||
|
INTEGER:: e, i, ni
|
||||||
|
CLASS(meshNode), POINTER:: node
|
||||||
|
|
||||||
|
!$OMP SINGLE
|
||||||
|
vectorF = 0.D0
|
||||||
|
!$OMP END SINGLE
|
||||||
|
|
||||||
|
!$OMP SINGLE
|
||||||
|
DO e = 1, mesh%numVols
|
||||||
|
nodes = mesh%vols(e)%obj%getNodes()
|
||||||
|
nNodes = SIZE(nodes)
|
||||||
|
!Calculates charge density (rho) in element nodes
|
||||||
|
ALLOCATE(rho(1:nNodes))
|
||||||
|
rho = 0.D0
|
||||||
|
DO i = 1, nNodes
|
||||||
|
ni = nodes(i)
|
||||||
|
node => mesh%nodes(ni)%obj
|
||||||
|
rho(i) = DOT_PRODUCT(qSpecies(:), node%output(:)%den/(vol_ref*node%v*n_ref))
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
!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
|
||||||
|
|
||||||
|
DEALLOCATE(nodes, rho)
|
||||||
|
|
||||||
|
END DO
|
||||||
|
!$OMP END SINGLE
|
||||||
|
|
||||||
|
!Apply boundary conditions
|
||||||
|
!$OMP DO
|
||||||
|
DO i = 1, mesh%numNodes
|
||||||
|
node => mesh%nodes(i)%obj
|
||||||
|
|
||||||
|
SELECT CASE(node%emData%type)
|
||||||
|
CASE ("dirichlet")
|
||||||
|
vectorF(i) = node%emData%phi
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END DO
|
||||||
|
!$OMP END DO
|
||||||
|
|
||||||
|
END SUBROUTINE assembleSourceVector
|
||||||
|
|
||||||
|
END MODULE moduleEM
|
||||||
|
|
@ -37,7 +37,6 @@ MODULE moduleErrors
|
||||||
errorMsg = msg
|
errorMsg = msg
|
||||||
|
|
||||||
WRITE (*, '(A)') errorMsg
|
WRITE (*, '(A)') errorMsg
|
||||||
WRITE (*, *)
|
|
||||||
|
|
||||||
END SUBROUTINE verboseError
|
END SUBROUTINE verboseError
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,24 +25,14 @@ MODULE moduleInject
|
||||||
TYPE(injectGeneric), ALLOCATABLE:: inject(:)
|
TYPE(injectGeneric), ALLOCATABLE:: inject(:)
|
||||||
|
|
||||||
CONTAINS
|
CONTAINS
|
||||||
!Injection of particles
|
!Initialize an injection of particles
|
||||||
SUBROUTINE doInjects()
|
SUBROUTINE initInject(self, i, v, n, T, flow, units, pt, physicalSurface)
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
INTEGER:: i
|
|
||||||
|
|
||||||
DO i=1, nInject
|
|
||||||
CALL inject(i)%addParticles()
|
|
||||||
END DO
|
|
||||||
|
|
||||||
END SUBROUTINE doInjects
|
|
||||||
|
|
||||||
SUBROUTINE initInject(self, i, v, n, T, flow, pt, physicalSurface)
|
|
||||||
USE moduleMesh
|
USE moduleMesh
|
||||||
USE moduleMeshCyl
|
USE moduleMeshCyl
|
||||||
USE moduleRefParam
|
USE moduleRefParam
|
||||||
USE moduleConstParam
|
USE moduleConstParam
|
||||||
USE moduleSpecies
|
USE moduleSpecies
|
||||||
|
USE moduleErrors
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(injectGeneric), INTENT(inout):: self
|
CLASS(injectGeneric), INTENT(inout):: self
|
||||||
|
|
@ -50,6 +40,7 @@ MODULE moduleInject
|
||||||
REAL(8), INTENT(in):: v, n(1:3), T(1:3)
|
REAL(8), INTENT(in):: v, n(1:3), T(1:3)
|
||||||
INTEGER, INTENT(in):: pt, physicalSurface
|
INTEGER, INTENT(in):: pt, physicalSurface
|
||||||
REAL(8), INTENT(in):: flow
|
REAL(8), INTENT(in):: flow
|
||||||
|
CHARACTER(:), ALLOCATABLE, INTENT(in):: units
|
||||||
INTEGER:: e, et
|
INTEGER:: e, et
|
||||||
INTEGER:: phSurface(1:mesh%numEdges)
|
INTEGER:: phSurface(1:mesh%numEdges)
|
||||||
|
|
||||||
|
|
@ -57,7 +48,20 @@ MODULE moduleInject
|
||||||
self%vMod = v/v_ref
|
self%vMod = v/v_ref
|
||||||
self%n = n
|
self%n = n
|
||||||
self%T = T/T_ref
|
self%T = T/T_ref
|
||||||
|
SELECT CASE(units)
|
||||||
|
CASE ("sccm")
|
||||||
|
!Standard cubic centimeter per minute
|
||||||
self%nParticles = INT(flow*sccm2atomPerS*tau*ti_ref/species(pt)%obj%weight)
|
self%nParticles = INT(flow*sccm2atomPerS*tau*ti_ref/species(pt)%obj%weight)
|
||||||
|
|
||||||
|
CASE ("A")
|
||||||
|
!Input current in Ampers
|
||||||
|
self%nParticles = INT(flow*tau*ti_ref/(qe*species(pt)%obj%weight))
|
||||||
|
|
||||||
|
CASE DEFAULT
|
||||||
|
CALL criticalError("No support for units: " // units, 'initInject')
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
IF (self%nParticles == 0) CALL criticalError("The number of particles for inject is 0.", 'initInject')
|
||||||
self%pt = pt
|
self%pt = pt
|
||||||
|
|
||||||
self%v = self%v * self%n
|
self%v = self%v * self%n
|
||||||
|
|
@ -92,6 +96,19 @@ MODULE moduleInject
|
||||||
|
|
||||||
END SUBROUTINE
|
END SUBROUTINE
|
||||||
|
|
||||||
|
!Injection of particles
|
||||||
|
SUBROUTINE doInjects()
|
||||||
|
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
INTEGER:: i
|
||||||
|
|
||||||
|
DO i=1, nInject
|
||||||
|
CALL inject(i)%addParticles()
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SUBROUTINE doInjects
|
||||||
|
|
||||||
!Random velocity from maxwellian distribution
|
!Random velocity from maxwellian distribution
|
||||||
REAL(8) FUNCTION vBC(u, vth)
|
REAL(8) FUNCTION vBC(u, vth)
|
||||||
USE moduleConstParam, ONLY: PI
|
USE moduleConstParam, ONLY: PI
|
||||||
|
|
@ -119,18 +136,28 @@ MODULE moduleInject
|
||||||
CLASS(injectGeneric), INTENT(in):: self
|
CLASS(injectGeneric), INTENT(in):: self
|
||||||
REAL(8):: randomX
|
REAL(8):: randomX
|
||||||
INTEGER:: j
|
INTEGER:: j
|
||||||
REAL(8):: randomPos
|
INTEGER, SAVE:: nMin, nMax !Min and Max index in partInj array
|
||||||
INTEGER:: nMin, nMax !Min and Max index in partInj array
|
|
||||||
INTEGER:: n
|
INTEGER:: n
|
||||||
CLASS(meshEdge), POINTER:: randomEdge
|
CLASS(meshEdge), POINTER:: randomEdge
|
||||||
|
|
||||||
!Insert particles
|
!Insert particles
|
||||||
|
!$OMP SINGLE
|
||||||
nMin = SUM(inject(1:(self%id-1))%nParticles) + 1
|
nMin = SUM(inject(1:(self%id-1))%nParticles) + 1
|
||||||
nMax = nMin + self%nParticles
|
nMax = nMin + self%nParticles - 1
|
||||||
!Assign particle type
|
!Assign particle type
|
||||||
partInj(nMin:nMax)%pt = self%pt
|
partInj(nMin:nMax)%pt = self%pt
|
||||||
!Assign weight to particle.
|
!Assign weight to particle.
|
||||||
partInj(nMin:nMax)%weight = species(self%pt)%obj%weight
|
partInj(nMin:nMax)%weight = species(self%pt)%obj%weight
|
||||||
|
!Particle is considered to be outside the domain
|
||||||
|
partInj(nMin:nMax)%n_in = .FALSE.
|
||||||
|
!Assign charge/mass to charged particle.
|
||||||
|
SELECT TYPE(sp => species(self%pt)%obj)
|
||||||
|
TYPE IS(speciesCharged)
|
||||||
|
partInj(nMin:nMax)%qm = sp%qm
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
!$OMP END SINGLE
|
||||||
|
|
||||||
!$OMP DO
|
!$OMP DO
|
||||||
DO n = nMin, nMax
|
DO n = nMin, nMax
|
||||||
!Select edge randomly from which inject particle
|
!Select edge randomly from which inject particle
|
||||||
|
|
@ -143,8 +170,7 @@ MODULE moduleInject
|
||||||
|
|
||||||
randomEdge => mesh%edges(self%edges(j))%obj
|
randomEdge => mesh%edges(self%edges(j))%obj
|
||||||
!Random position in edge
|
!Random position in edge
|
||||||
randomPos = RAND()
|
partInj(n)%r = randomEdge%randPos()
|
||||||
partInj(n)%r = randomEdge%randPos(randomPos)
|
|
||||||
!Volume associated to the edge:
|
!Volume associated to the edge:
|
||||||
IF (DOT_PRODUCT(self%n, randomEdge%normal) >= 0.D0) THEN
|
IF (DOT_PRODUCT(self%n, randomEdge%normal) >= 0.D0) THEN
|
||||||
partInj(n)%e_p = randomEdge%e1%n
|
partInj(n)%e_p = randomEdge%e1%n
|
||||||
|
|
@ -159,7 +185,7 @@ MODULE moduleInject
|
||||||
vBC(self%v(3), self%vTh(3)) /)
|
vBC(self%v(3), self%vTh(3)) /)
|
||||||
|
|
||||||
!Push new particle
|
!Push new particle
|
||||||
CALL push(partInj(n))
|
CALL solver%push(partInj(n))
|
||||||
!Assign cell to new particle
|
!Assign cell to new particle
|
||||||
CALL mesh%vols(partInj(n)%e_p)%obj%findCell(partInj(n))
|
CALL mesh%vols(partInj(n)%e_p)%obj%findCell(partInj(n))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,9 @@ MODULE moduleInput
|
||||||
CALL verboseError('Reading Geometry...')
|
CALL verboseError('Reading Geometry...')
|
||||||
CALL readGeometry(config)
|
CALL readGeometry(config)
|
||||||
|
|
||||||
|
!Read boundary for EM field
|
||||||
|
CALL readEMBoundary(config)
|
||||||
|
|
||||||
!Read injection of particles
|
!Read injection of particles
|
||||||
CALL verboseError('Reading Interactions between species...')
|
CALL verboseError('Reading Interactions between species...')
|
||||||
CALL readInject(config)
|
CALL readInject(config)
|
||||||
|
|
@ -63,7 +66,7 @@ MODULE moduleInput
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
TYPE(json_file), INTENT(inout):: config
|
TYPE(json_file), INTENT(inout):: config
|
||||||
LOGICAL:: found
|
LOGICAL:: found, found_r
|
||||||
CHARACTER(:), ALLOCATABLE:: object
|
CHARACTER(:), ALLOCATABLE:: object
|
||||||
|
|
||||||
object = 'reference'
|
object = 'reference'
|
||||||
|
|
@ -77,15 +80,25 @@ MODULE moduleInput
|
||||||
CALL config%get(object // '.temperature', T_ref, found)
|
CALL config%get(object // '.temperature', T_ref, found)
|
||||||
IF (.NOT. found) CALL criticalError('Reference temperature not found','readReference')
|
IF (.NOT. found) CALL criticalError('Reference temperature not found','readReference')
|
||||||
|
|
||||||
CALL config%get(object // '.radius', r_ref, found)
|
CALL config%get(object // '.radius', r_ref, found_r)
|
||||||
IF (.NOT. found) CALL criticalError('Reference radius not found','readReference')
|
|
||||||
|
|
||||||
!Derived parameters
|
!Derived parameters
|
||||||
v_ref = DSQRT(kb*T_ref/m_ref) !reference velocity
|
v_ref = DSQRT(kb*T_ref/m_ref) !reference velocity
|
||||||
sigma_ref = PI*(r_ref+r_ref)**2 !reference cross section
|
!TODO: Make this solver dependent
|
||||||
|
IF (found_r) THEN
|
||||||
L_ref = 1.D0/(sigma_ref*n_ref) !mean free path
|
L_ref = 1.D0/(sigma_ref*n_ref) !mean free path
|
||||||
|
sigma_ref = PI*(r_ref+r_ref)**2 !reference cross section
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
L_ref = DSQRT(kb*T_ref*eps_0/n_ref)/qe !Debye length
|
||||||
|
!TODO: Obtain right sigma_ref for PIC case
|
||||||
|
sigma_ref = PI*(4.D-10)**2 !reference cross section
|
||||||
|
|
||||||
|
END IF
|
||||||
ti_ref = L_ref/v_ref !reference time
|
ti_ref = L_ref/v_ref !reference time
|
||||||
Vol_ref = L_ref**3 !reference volume
|
Vol_ref = L_ref**3 !reference volume
|
||||||
|
EF_ref = qe*n_ref*L_ref/eps_0 !reference electric field
|
||||||
|
Volt_ref = EF_ref*L_ref !reference voltage
|
||||||
|
|
||||||
END SUBROUTINE readReference
|
END SUBROUTINE readReference
|
||||||
|
|
||||||
|
|
@ -94,6 +107,7 @@ MODULE moduleInput
|
||||||
USE moduleRefParam
|
USE moduleRefParam
|
||||||
USE moduleErrors
|
USE moduleErrors
|
||||||
USE moduleCaseParam
|
USE moduleCaseParam
|
||||||
|
USE moduleSolver
|
||||||
USE json_module
|
USE json_module
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
|
@ -101,6 +115,7 @@ MODULE moduleInput
|
||||||
LOGICAL:: found
|
LOGICAL:: found
|
||||||
CHARACTER(:), ALLOCATABLE:: object
|
CHARACTER(:), ALLOCATABLE:: object
|
||||||
REAL(8):: time !simulation time in [t]
|
REAL(8):: time !simulation time in [t]
|
||||||
|
CHARACTER(:), ALLOCATABLE:: solverType
|
||||||
|
|
||||||
object = 'case'
|
object = 'case'
|
||||||
!Time parameters
|
!Time parameters
|
||||||
|
|
@ -110,6 +125,21 @@ MODULE moduleInput
|
||||||
CALL config%get(object // '.time', time, found)
|
CALL config%get(object // '.time', time, found)
|
||||||
IF (.NOT. found) CALL criticalError('Required parameter time not found','readCase')
|
IF (.NOT. found) CALL criticalError('Required parameter time not found','readCase')
|
||||||
|
|
||||||
|
CALL config%get(object // '.solver', solverType, found)
|
||||||
|
IF (.NOT. found) CALL criticalError('Required parameter solver not found','readCase')
|
||||||
|
|
||||||
|
!Allocate the type of solver
|
||||||
|
SELECT CASE(solverType)
|
||||||
|
CASE('2DCylNeutral')
|
||||||
|
!Allocate the solver for neutral pusher 2D Cylindrical
|
||||||
|
ALLOCATE(solver, source=solverCylNeutral())
|
||||||
|
|
||||||
|
CASE('2DCylCharged')
|
||||||
|
!Allocate the solver for charged pusher 2D Cylindrical
|
||||||
|
ALLOCATE(solver, source=solverCylCharged())
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
!Convert simulation time to number of iterations
|
!Convert simulation time to number of iterations
|
||||||
tmax = INT(time/tau)
|
tmax = INT(time/tau)
|
||||||
|
|
||||||
|
|
@ -149,6 +179,7 @@ MODULE moduleInput
|
||||||
|
|
||||||
CALL config%get(object // '.cpuTime', timeOutput, found)
|
CALL config%get(object // '.cpuTime', timeOutput, found)
|
||||||
CALL config%get(object // '.numColl', collOutput, found)
|
CALL config%get(object // '.numColl', collOutput, found)
|
||||||
|
CALL config%get(object // '.EMField', emOutput, found)
|
||||||
|
|
||||||
END SUBROUTINE readOutput
|
END SUBROUTINE readOutput
|
||||||
|
|
||||||
|
|
@ -164,12 +195,12 @@ MODULE moduleInput
|
||||||
CHARACTER(2):: iString
|
CHARACTER(2):: iString
|
||||||
CHARACTER(:), ALLOCATABLE:: object
|
CHARACTER(:), ALLOCATABLE:: object
|
||||||
CHARACTER(:), ALLOCATABLE:: speciesType
|
CHARACTER(:), ALLOCATABLE:: speciesType
|
||||||
REAL(8):: mass
|
REAL(8):: mass, charge
|
||||||
LOGICAL:: found
|
LOGICAL:: found
|
||||||
INTEGER:: i
|
INTEGER:: i
|
||||||
|
|
||||||
!Gets the number of species
|
!Gets the number of species
|
||||||
CALL config%info('species', n_children = nSpecies)
|
CALL config%info('species', found, n_children = nSpecies)
|
||||||
!Zero species means critical error
|
!Zero species means critical error
|
||||||
IF (nSpecies == 0) CALL criticalError("No species found", "configRead")
|
IF (nSpecies == 0) CALL criticalError("No species found", "configRead")
|
||||||
|
|
||||||
|
|
@ -180,21 +211,28 @@ MODULE moduleInput
|
||||||
WRITE(iString, '(I2)') i
|
WRITE(iString, '(I2)') i
|
||||||
object = 'species(' // TRIM(iString) // ')'
|
object = 'species(' // TRIM(iString) // ')'
|
||||||
CALL config%get(object // '.type', speciesType, found)
|
CALL config%get(object // '.type', speciesType, found)
|
||||||
|
CALL config%get(object // '.mass', mass, found)
|
||||||
|
mass = mass/m_ref
|
||||||
|
|
||||||
|
!Allocate species depending on type and assign specific parameters
|
||||||
SELECT CASE(speciesType)
|
SELECT CASE(speciesType)
|
||||||
CASE ("neutral")
|
CASE ("neutral")
|
||||||
ALLOCATE(species(i)%obj, source=speciesNeutral())
|
ALLOCATE(species(i)%obj, source=speciesNeutral())
|
||||||
!TODO: move to subroutine
|
|
||||||
CALL config%get(object // '.name', species(i)%obj%name, found)
|
CASE ("charged")
|
||||||
CALL config%get(object // '.mass', mass, found)
|
CALL config%get(object // '.charge', charge, found)
|
||||||
CALL config%get(object // '.weight', species(i)%obj%weight, found)
|
ALLOCATE(species(i)%obj, source=speciesCharged(q = charge, &
|
||||||
species(i)%obj%pt = i
|
qm = charge/mass))
|
||||||
species(i)%obj%m = mass/m_ref
|
|
||||||
|
|
||||||
CASE DEFAULT
|
CASE DEFAULT
|
||||||
CALL warningError("Species " // speciesType // " not supported yet")
|
CALL warningError("Species " // speciesType // " not supported yet")
|
||||||
|
|
||||||
END SELECT
|
END SELECT
|
||||||
|
!Assign shared parameters for all species
|
||||||
|
CALL config%get(object // '.name', species(i)%obj%name, found)
|
||||||
|
CALL config%get(object // '.weight', species(i)%obj%weight, found)
|
||||||
|
species(i)%obj%pt = i
|
||||||
|
species(i)%obj%m = mass
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
||||||
|
|
@ -217,29 +255,30 @@ MODULE moduleInput
|
||||||
CHARACTER(:), ALLOCATABLE:: species_i, species_j
|
CHARACTER(:), ALLOCATABLE:: species_i, species_j
|
||||||
CHARACTER(:), ALLOCATABLE:: crossSecFile
|
CHARACTER(:), ALLOCATABLE:: crossSecFile
|
||||||
CHARACTER(:), ALLOCATABLE:: crossSecFilePath
|
CHARACTER(:), ALLOCATABLE:: crossSecFilePath
|
||||||
|
LOGICAL:: found
|
||||||
INTEGER:: nInteractions, nCollisions
|
INTEGER:: nInteractions, nCollisions
|
||||||
INTEGER:: i, k, ij
|
INTEGER:: i, k, ij
|
||||||
INTEGER:: pt_i, pt_j
|
INTEGER:: pt_i, pt_j
|
||||||
|
|
||||||
CALL initInteractionMatrix(interactionMatrix)
|
CALL initInteractionMatrix(interactionMatrix)
|
||||||
|
|
||||||
CALL config%get('interactions.folderCollisions', pathCollisions)
|
CALL config%get('interactions.folderCollisions', pathCollisions, found)
|
||||||
|
|
||||||
CALL config%info('interactions.collisions', n_children = nInteractions)
|
CALL config%info('interactions.collisions', found, n_children = nInteractions)
|
||||||
DO i = 1, nInteractions
|
DO i = 1, nInteractions
|
||||||
WRITE(iString, '(I2)') i
|
WRITE(iString, '(I2)') i
|
||||||
object = 'interactions.collisions(' // TRIM(iString) // ')'
|
object = 'interactions.collisions(' // TRIM(iString) // ')'
|
||||||
CALL config%get(object // '.species_i', species_i)
|
CALL config%get(object // '.species_i', species_i, found)
|
||||||
pt_i = speciesName2Index(species_i)
|
pt_i = speciesName2Index(species_i)
|
||||||
CALL config%get(object // '.species_j', species_j)
|
CALL config%get(object // '.species_j', species_j, found)
|
||||||
pt_j = speciesName2Index(species_j)
|
pt_j = speciesName2Index(species_j)
|
||||||
CALL config%info(object // '.crossSections', n_children = nCollisions)
|
CALL config%info(object // '.crossSections', found, n_children = nCollisions)
|
||||||
ij = interactionIndex(pt_i,pt_j)
|
ij = interactionIndex(pt_i,pt_j)
|
||||||
CALL interactionMatrix(ij)%init(nCollisions)
|
CALL interactionMatrix(ij)%init(nCollisions)
|
||||||
|
|
||||||
DO k = 1, nCollisions
|
DO k = 1, nCollisions
|
||||||
WRITE (kString, '(I2)') k
|
WRITE (kString, '(I2)') k
|
||||||
CALL config%get(object // '.crossSections(' // TRIM(kString)// ')', crossSecFile)
|
CALL config%get(object // '.crossSections(' // TRIM(kString)// ')', crossSecFile, found)
|
||||||
crossSecFilePath = pathCollisions // crossSecFile
|
crossSecFilePath = pathCollisions // crossSecFile
|
||||||
CALL interactionMatrix(ij)%collisions(k)%obj%init(crossSecFilePath, species(pt_i)%obj%m, species(pt_j)%obj%m)
|
CALL interactionMatrix(ij)%collisions(k)%obj%init(crossSecFilePath, species(pt_i)%obj%m, species(pt_j)%obj%m)
|
||||||
|
|
||||||
|
|
@ -247,7 +286,6 @@ MODULE moduleInput
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
||||||
|
|
||||||
END SUBROUTINE readInteractions
|
END SUBROUTINE readInteractions
|
||||||
|
|
||||||
!Reads boundary conditions for the mesh
|
!Reads boundary conditions for the mesh
|
||||||
|
|
@ -263,7 +301,7 @@ MODULE moduleInput
|
||||||
LOGICAL:: found
|
LOGICAL:: found
|
||||||
INTEGER:: i
|
INTEGER:: i
|
||||||
|
|
||||||
CALL config%info('boundary', n_children = nBoundary)
|
CALL config%info('boundary', found, n_children = nBoundary)
|
||||||
ALLOCATE(boundary(1:nBoundary))
|
ALLOCATE(boundary(1:nBoundary))
|
||||||
DO i = 1, nBoundary
|
DO i = 1, nBoundary
|
||||||
WRITE(istring, '(i2)') i
|
WRITE(istring, '(i2)') i
|
||||||
|
|
@ -322,6 +360,85 @@ MODULE moduleInput
|
||||||
|
|
||||||
END SUBROUTINE readGeometry
|
END SUBROUTINE readGeometry
|
||||||
|
|
||||||
|
SUBROUTINE readEMBoundary(config)
|
||||||
|
USE moduleMesh
|
||||||
|
USE moduleOutput
|
||||||
|
USE moduleErrors
|
||||||
|
USE moduleEM
|
||||||
|
USE moduleRefParam
|
||||||
|
USE moduleSpecies
|
||||||
|
USE json_module
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
TYPE(json_file), INTENT(inout):: config
|
||||||
|
CHARACTER(:), ALLOCATABLE:: object
|
||||||
|
LOGICAL:: found
|
||||||
|
CHARACTER(2):: istring
|
||||||
|
INTEGER:: i, e, s
|
||||||
|
INTEGER:: info
|
||||||
|
EXTERNAL:: dgetrf
|
||||||
|
|
||||||
|
CALL config%info('boundaryEM', found, n_children = nBoundaryEM)
|
||||||
|
|
||||||
|
IF (found) ALLOCATE(boundEM(1:nBoundaryEM))
|
||||||
|
|
||||||
|
DO i = 1, nBoundaryEM
|
||||||
|
WRITE(istring, '(i2)') i
|
||||||
|
object = 'boundaryEM(' // trim(istring) // ')'
|
||||||
|
|
||||||
|
CALL config%get(object // '.type', boundEM(i)%typeEM, found)
|
||||||
|
|
||||||
|
SELECT CASE(boundEM(i)%typeEM)
|
||||||
|
CASE ("dirichlet")
|
||||||
|
CALL config%get(object // '.potential', boundEM(i)%potential, found)
|
||||||
|
IF (.NOT. found) &
|
||||||
|
CALL criticalError('Required parameter "potential" for Dirichlet boundary condition not found', 'readEMBoundary')
|
||||||
|
boundEM(i)%potential = boundEM(i)%potential/Volt_ref
|
||||||
|
|
||||||
|
CALL config%get(object // '.physicalSurface', boundEM(i)%physicalSurface, found)
|
||||||
|
IF (.NOT. found) &
|
||||||
|
CALL criticalError('Required parameter "physicalSurface" for Dirichlet boundary condition not found', 'readEMBoundary')
|
||||||
|
|
||||||
|
CASE DEFAULT
|
||||||
|
CALL criticalError('Boundary type ' // boundEM(i)%typeEM // ' not yet supported', 'readEMBoundary')
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
ALLOCATE(qSpecies(1:nSpecies))
|
||||||
|
DO s = 1, nSpecies
|
||||||
|
SELECT TYPE(sp => species(s)%obj)
|
||||||
|
TYPE IS (speciesCharged)
|
||||||
|
qSpecies(s) = sp%q
|
||||||
|
|
||||||
|
CLASS DEFAULT
|
||||||
|
qSpecies(s) = 0.D0
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
END DO
|
||||||
|
|
||||||
|
!TODO: Improve this
|
||||||
|
IF (ALLOCATED(boundEM)) THEN
|
||||||
|
DO e = 1, mesh%numEdges
|
||||||
|
IF (ANY(mesh%edges(e)%obj%physicalSurface == boundEM(:)%physicalSurface)) THEN
|
||||||
|
DO i = 1, nBoundaryEM
|
||||||
|
IF (mesh%edges(e)%obj%physicalSurface == boundEM(i)%physicalSurface) THEN
|
||||||
|
CALL boundEM(i)%apply(mesh%edges(e)%obj)
|
||||||
|
|
||||||
|
END IF
|
||||||
|
END DO
|
||||||
|
END IF
|
||||||
|
END DO
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!Compute the PLU factorization of K once boundary conditions have been read
|
||||||
|
CALL dgetrf(mesh%numNodes, mesh%numNodes, mesh%K, mesh%numNodes, mesh%IPIV, info)
|
||||||
|
IF (info /= 0) CALL criticalError('Factorization of K matrix failed', 'readEMBoundary')
|
||||||
|
|
||||||
|
END SUBROUTINE readEMBoundary
|
||||||
|
|
||||||
!Reads the injection of particles from the boundaries
|
!Reads the injection of particles from the boundaries
|
||||||
SUBROUTINE readInject(config)
|
SUBROUTINE readInject(config)
|
||||||
USE moduleSpecies
|
USE moduleSpecies
|
||||||
|
|
@ -340,10 +457,11 @@ MODULE moduleInput
|
||||||
REAL(8):: v
|
REAL(8):: v
|
||||||
REAL(8), ALLOCATABLE:: T(:), normal(:)
|
REAL(8), ALLOCATABLE:: T(:), normal(:)
|
||||||
REAL(8):: flow
|
REAL(8):: flow
|
||||||
|
CHARACTER(:), ALLOCATABLE:: units
|
||||||
INTEGER:: physicalSurface
|
INTEGER:: physicalSurface
|
||||||
INTEGER:: pt
|
INTEGER:: pt
|
||||||
|
|
||||||
CALL config%info('inject', n_children = nInject)
|
CALL config%info('inject', found, n_children = nInject)
|
||||||
ALLOCATE(inject(1:nInject))
|
ALLOCATE(inject(1:nInject))
|
||||||
nPartInj = 0
|
nPartInj = 0
|
||||||
DO i = 1, nInject
|
DO i = 1, nInject
|
||||||
|
|
@ -359,11 +477,13 @@ MODULE moduleInput
|
||||||
CALL config%get(object // '.T', T, found)
|
CALL config%get(object // '.T', T, found)
|
||||||
CALL config%get(object // '.n', normal, found)
|
CALL config%get(object // '.n', normal, found)
|
||||||
CALL config%get(object // '.flow', flow, found)
|
CALL config%get(object // '.flow', flow, found)
|
||||||
|
CALL config%get(object // '.units', units, found)
|
||||||
CALL config%get(object // '.physicalSurface', physicalSurface, found)
|
CALL config%get(object // '.physicalSurface', physicalSurface, found)
|
||||||
|
|
||||||
CALL inject(i)%init(i, v, normal, T, flow, pt, physicalSurface)
|
CALL inject(i)%init(i, v, normal, T, flow, units, pt, physicalSurface)
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
PRINT *, inject(:)%nParticles
|
||||||
|
|
||||||
!Allocate array for injected particles
|
!Allocate array for injected particles
|
||||||
IF (nPartInj > 0) THEN
|
IF (nPartInj > 0) THEN
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
MODULE moduleMesh
|
MODULE moduleMesh
|
||||||
USE moduleList
|
USE moduleList
|
||||||
USE moduleOutput
|
USE moduleOutput
|
||||||
USE OMP_LIB
|
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
!Parent of Node element
|
!Parent of Node element
|
||||||
|
|
@ -13,6 +12,7 @@ MODULE moduleMesh
|
||||||
REAL(8):: v = 0.D0
|
REAL(8):: v = 0.D0
|
||||||
!Output values
|
!Output values
|
||||||
TYPE(outputNode), ALLOCATABLE:: output(:)
|
TYPE(outputNode), ALLOCATABLE:: output(:)
|
||||||
|
TYPE(emNode):: emData
|
||||||
CONTAINS
|
CONTAINS
|
||||||
PROCEDURE(initNode_interface), DEFERRED, PASS:: init
|
PROCEDURE(initNode_interface), DEFERRED, PASS:: init
|
||||||
PROCEDURE(getCoord_interface), DEFERRED, PASS:: getCoordinates
|
PROCEDURE(getCoord_interface), DEFERRED, PASS:: getCoordinates
|
||||||
|
|
@ -60,6 +60,7 @@ MODULE moduleMesh
|
||||||
CONTAINS
|
CONTAINS
|
||||||
PROCEDURE(initEdge_interface), DEFERRED, PASS:: init
|
PROCEDURE(initEdge_interface), DEFERRED, PASS:: init
|
||||||
PROCEDURE(boundary_interface), DEFERRED, PASS:: fBoundary
|
PROCEDURE(boundary_interface), DEFERRED, PASS:: fBoundary
|
||||||
|
PROCEDURE(getNodesEdge_interface), DEFERRED, PASS:: getNodes
|
||||||
PROCEDURE(randPos_interface), DEFERRED, PASS:: randPos
|
PROCEDURE(randPos_interface), DEFERRED, PASS:: randPos
|
||||||
|
|
||||||
END TYPE meshEdge
|
END TYPE meshEdge
|
||||||
|
|
@ -67,6 +68,7 @@ MODULE moduleMesh
|
||||||
ABSTRACT INTERFACE
|
ABSTRACT INTERFACE
|
||||||
SUBROUTINE initEdge_interface(self, n, p, bt, physicalSurface)
|
SUBROUTINE initEdge_interface(self, n, p, bt, physicalSurface)
|
||||||
IMPORT:: meshEdge
|
IMPORT:: meshEdge
|
||||||
|
|
||||||
CLASS(meshEdge), INTENT(out):: self
|
CLASS(meshEdge), INTENT(out):: self
|
||||||
INTEGER, INTENT(in):: n
|
INTEGER, INTENT(in):: n
|
||||||
INTEGER, INTENT(in):: p(:)
|
INTEGER, INTENT(in):: p(:)
|
||||||
|
|
@ -84,10 +86,16 @@ MODULE moduleMesh
|
||||||
|
|
||||||
END SUBROUTINE
|
END SUBROUTINE
|
||||||
|
|
||||||
PURE FUNCTION randPos_interface(self, rnd) RESULT(r)
|
PURE FUNCTION getNodesEdge_interface(self) RESULT(n)
|
||||||
|
IMPORT:: meshEdge
|
||||||
|
CLASS(meshEdge), INTENT(in):: self
|
||||||
|
INTEGER, ALLOCATABLE:: n(:)
|
||||||
|
|
||||||
|
END FUNCTION
|
||||||
|
|
||||||
|
FUNCTION randPos_interface(self) RESULT(r)
|
||||||
IMPORT:: meshEdge
|
IMPORT:: meshEdge
|
||||||
CLASS(meshEdge), INTENT(in):: self
|
CLASS(meshEdge), INTENT(in):: self
|
||||||
REAL(8), INTENT(in):: rnd
|
|
||||||
REAL(8):: r(1:3)
|
REAL(8):: r(1:3)
|
||||||
|
|
||||||
END FUNCTION randPos_interface
|
END FUNCTION randPos_interface
|
||||||
|
|
@ -119,6 +127,9 @@ MODULE moduleMesh
|
||||||
CONTAINS
|
CONTAINS
|
||||||
PROCEDURE(initVol_interface), DEFERRED, PASS:: init
|
PROCEDURE(initVol_interface), DEFERRED, PASS:: init
|
||||||
PROCEDURE(scatter_interface), DEFERRED, PASS:: scatter
|
PROCEDURE(scatter_interface), DEFERRED, PASS:: scatter
|
||||||
|
PROCEDURE(gatherEF_interface), DEFERRED, PASS:: gatherEF
|
||||||
|
PROCEDURE(getNodesVol_interface), DEFERRED, PASS:: getNodes
|
||||||
|
PROCEDURE(elemF_interface), DEFERRED, PASS:: elemF
|
||||||
PROCEDURE(collision_interface), DEFERRED, PASS:: collision
|
PROCEDURE(collision_interface), DEFERRED, PASS:: collision
|
||||||
PROCEDURE(findCell_interface), DEFERRED, PASS:: findCell
|
PROCEDURE(findCell_interface), DEFERRED, PASS:: findCell
|
||||||
PROCEDURE(resetOutput_interface), DEFERRED, PASS:: resetOutput
|
PROCEDURE(resetOutput_interface), DEFERRED, PASS:: resetOutput
|
||||||
|
|
@ -143,6 +154,32 @@ MODULE moduleMesh
|
||||||
|
|
||||||
END SUBROUTINE scatter_interface
|
END SUBROUTINE scatter_interface
|
||||||
|
|
||||||
|
PURE FUNCTION gatherEF_interface(self, xi) RESULT(EF)
|
||||||
|
|
||||||
|
IMPORT:: meshVol
|
||||||
|
CLASS(meshVol), INTENT(in):: self
|
||||||
|
REAL(8), INTENT(in):: xi(1:3)
|
||||||
|
REAL(8):: EF(1:3)
|
||||||
|
|
||||||
|
END FUNCTION gatherEF_interface
|
||||||
|
|
||||||
|
PURE FUNCTION getNodesVol_interface(self) RESULT(n)
|
||||||
|
|
||||||
|
IMPORT:: meshVol
|
||||||
|
CLASS(meshVol), INTENT(in):: self
|
||||||
|
INTEGER, ALLOCATABLE:: n(:)
|
||||||
|
|
||||||
|
END FUNCTION getNodesVol_interface
|
||||||
|
|
||||||
|
PURE FUNCTION elemF_interface(self, source) RESULT(localF)
|
||||||
|
|
||||||
|
IMPORT:: meshVol
|
||||||
|
CLASS(meshVol), INTENT(in):: self
|
||||||
|
REAL(8), INTENT(in):: source(1:)
|
||||||
|
REAL(8), ALLOCATABLE:: localF(:)
|
||||||
|
|
||||||
|
END FUNCTION elemF_interface
|
||||||
|
|
||||||
SUBROUTINE collision_interface(self)
|
SUBROUTINE collision_interface(self)
|
||||||
IMPORT:: meshVol
|
IMPORT:: meshVol
|
||||||
CLASS(meshVol), INTENT(inout):: self
|
CLASS(meshVol), INTENT(inout):: self
|
||||||
|
|
@ -184,13 +221,14 @@ MODULE moduleMesh
|
||||||
TYPE(meshVolCont), ALLOCATABLE:: vols(:)
|
TYPE(meshVolCont), ALLOCATABLE:: vols(:)
|
||||||
!Global stiffness matrix
|
!Global stiffness matrix
|
||||||
REAL(8), ALLOCATABLE, DIMENSION(:,:):: K
|
REAL(8), ALLOCATABLE, DIMENSION(:,:):: K
|
||||||
!Global load vector
|
!Permutation matrix for P L U factorization
|
||||||
REAL(8), ALLOCATABLE, DIMENSION(:):: F
|
INTEGER, ALLOCATABLE, DIMENSION(:,:):: IPIV
|
||||||
|
|
||||||
CONTAINS
|
CONTAINS
|
||||||
PROCEDURE(readMesh_interface), PASS, DEFERRED:: readMesh
|
PROCEDURE(readMesh_interface), PASS, DEFERRED:: readMesh
|
||||||
PROCEDURE(printOutput_interface), PASS, DEFERRED:: printOutput
|
PROCEDURE(printOutput_interface), PASS, DEFERRED:: printOutput
|
||||||
PROCEDURE(printColl_interface), PASS, DEFERRED:: printColl
|
PROCEDURE(printColl_interface), PASS, DEFERRED:: printColl
|
||||||
|
PROCEDURE(printEM_interface), PASS, DEFERRED:: printEM
|
||||||
|
|
||||||
END TYPE meshGeneric
|
END TYPE meshGeneric
|
||||||
|
|
||||||
|
|
@ -213,7 +251,7 @@ MODULE moduleMesh
|
||||||
|
|
||||||
END SUBROUTINE printOutput_interface
|
END SUBROUTINE printOutput_interface
|
||||||
|
|
||||||
!Prints unmber of collisions
|
!Prints number of collisions
|
||||||
SUBROUTINE printColl_interface(self, t)
|
SUBROUTINE printColl_interface(self, t)
|
||||||
IMPORT meshGeneric
|
IMPORT meshGeneric
|
||||||
|
|
||||||
|
|
@ -222,6 +260,14 @@ MODULE moduleMesh
|
||||||
|
|
||||||
END SUBROUTINE printColl_interface
|
END SUBROUTINE printColl_interface
|
||||||
|
|
||||||
|
!Prints EM info
|
||||||
|
SUBROUTINE printEM_interface(self, t)
|
||||||
|
IMPORT meshGeneric
|
||||||
|
|
||||||
|
CLASS(meshGeneric), INTENT(in):: self
|
||||||
|
INTEGER, INTENT(in):: t
|
||||||
|
|
||||||
|
END SUBROUTINE printEM_interface
|
||||||
END INTERFACE
|
END INTERFACE
|
||||||
|
|
||||||
!Generic mesh
|
!Generic mesh
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ MODULE moduleMeshCyl
|
||||||
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL()
|
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL()
|
||||||
CONTAINS
|
CONTAINS
|
||||||
PROCEDURE, PASS:: init => initEdgeCyl
|
PROCEDURE, PASS:: init => initEdgeCyl
|
||||||
|
PROCEDURE, PASS:: getNodes => getNodesCyl
|
||||||
PROCEDURE, PASS:: randPos => randPosCyl
|
PROCEDURE, PASS:: randPos => randPosCyl
|
||||||
|
|
||||||
END TYPE meshEdgeCyl
|
END TYPE meshEdgeCyl
|
||||||
|
|
@ -43,22 +44,20 @@ MODULE moduleMeshCyl
|
||||||
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL(), n3 => NULL(), n4 => NULL()
|
CLASS(meshNode), POINTER:: n1 => NULL(), n2 => NULL(), n3 => NULL(), n4 => NULL()
|
||||||
!Connectivity to adjacent elements
|
!Connectivity to adjacent elements
|
||||||
CLASS(*), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL(), e4 => NULL()
|
CLASS(*), POINTER:: e1 => NULL(), e2 => NULL(), e3 => NULL(), e4 => NULL()
|
||||||
!Maximum collision rate
|
|
||||||
!TODO: Move to other more appropiate section
|
|
||||||
REAL(8):: phi(1:4) = 0.D0
|
|
||||||
REAL(8):: Ke(1:4,1:4) = 0.D0
|
|
||||||
REAL(8):: arNodes(1:4) = 0.D0
|
REAL(8):: arNodes(1:4) = 0.D0
|
||||||
|
|
||||||
CONTAINS
|
CONTAINS
|
||||||
PROCEDURE, PASS:: init => initVolQuadCyl
|
PROCEDURE, PASS:: init => initVolQuadCyl
|
||||||
PROCEDURE, PASS:: locKe => localKeQuad
|
PROCEDURE, PASS:: elemK => elemKQuad
|
||||||
|
PROCEDURE, PASS:: elemF => elemFQuad
|
||||||
PROCEDURE, PASS:: detJac => detJQuad
|
PROCEDURE, PASS:: detJac => detJQuad
|
||||||
PROCEDURE, PASS:: invJ => invJQuad
|
PROCEDURE, PASS:: invJ => invJQuad
|
||||||
PROCEDURE, PASS:: area => areaQuad
|
PROCEDURE, PASS:: area => areaQuad
|
||||||
PROCEDURE, NOPASS:: weight => weightQuad
|
PROCEDURE, NOPASS:: weight => weightQuad
|
||||||
PROCEDURE, NOPASS:: inside => insideQuad
|
PROCEDURE, NOPASS:: inside => insideQuad
|
||||||
PROCEDURE, PASS:: dVal => dValQuad
|
|
||||||
PROCEDURE, PASS:: scatter => scatterQuad
|
PROCEDURE, PASS:: scatter => scatterQuad
|
||||||
|
PROCEDURE, PASS:: gatherEF => gatherEFQuad
|
||||||
|
PROCEDURE, PASS:: getNodes => getNodesQuad
|
||||||
PROCEDURE, PASS:: phy2log => phy2logQuad
|
PROCEDURE, PASS:: phy2log => phy2logQuad
|
||||||
PROCEDURE, PASS:: findCell => findCellCylQuad
|
PROCEDURE, PASS:: findCell => findCellCylQuad
|
||||||
PROCEDURE, PASS:: resetOutput => resetOutputQuad
|
PROCEDURE, PASS:: resetOutput => resetOutputQuad
|
||||||
|
|
@ -78,8 +77,8 @@ MODULE moduleMeshCyl
|
||||||
REAL(8), INTENT(in):: r(1:3)
|
REAL(8), INTENT(in):: r(1:3)
|
||||||
|
|
||||||
self%n = n
|
self%n = n
|
||||||
self%r = r(1)/L_ref
|
|
||||||
self%z = r(2)/L_ref
|
self%z = r(2)/L_ref
|
||||||
|
self%r = r(1)/L_ref
|
||||||
!Node volume, to be determined in mesh
|
!Node volume, to be determined in mesh
|
||||||
self%v = 0.D0
|
self%v = 0.D0
|
||||||
|
|
||||||
|
|
@ -128,13 +127,25 @@ MODULE moduleMeshCyl
|
||||||
|
|
||||||
END SUBROUTINE initEdgeCyl
|
END SUBROUTINE initEdgeCyl
|
||||||
|
|
||||||
|
PURE FUNCTION getNodesCyl(self) RESULT(n)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
PURE FUNCTION randPosCyl(self, rnd) RESULT(r)
|
|
||||||
CLASS(meshEdgeCyl), INTENT(in):: self
|
CLASS(meshEdgeCyl), INTENT(in):: self
|
||||||
REAL(8), INTENT(in):: rnd
|
INTEGER, ALLOCATABLE:: n(:)
|
||||||
|
|
||||||
|
ALLOCATE(n(1:2))
|
||||||
|
n = (/self%n1%n, self%n2%n /)
|
||||||
|
|
||||||
|
END FUNCTION getNodesCyl
|
||||||
|
|
||||||
|
FUNCTION randPosCyl(self) RESULT(r)
|
||||||
|
CLASS(meshEdgeCyl), INTENT(in):: self
|
||||||
|
REAL(8):: rnd
|
||||||
REAL(8):: r(1:3)
|
REAL(8):: r(1:3)
|
||||||
REAL(8):: p1(1:2), p2(1:2)
|
REAL(8):: p1(1:2), p2(1:2)
|
||||||
|
|
||||||
|
rnd = RAND()
|
||||||
|
|
||||||
p1 = (/self%z(1), self%r(1) /)
|
p1 = (/self%z(1), self%r(1) /)
|
||||||
p2 = (/self%z(2), self%r(2) /)
|
p2 = (/self%z(2), self%r(2) /)
|
||||||
r(1:2) = (1.D0 - rnd)*p1 + rnd*p2
|
r(1:2) = (1.D0 - rnd)*p1 + rnd*p2
|
||||||
|
|
@ -173,15 +184,14 @@ MODULE moduleMeshCyl
|
||||||
self%n3%v = self%n3%v + self%arNodes(3)
|
self%n3%v = self%n3%v + self%arNodes(3)
|
||||||
self%n4%v = self%n4%v + self%arNodes(4)
|
self%n4%v = self%n4%v + self%arNodes(4)
|
||||||
|
|
||||||
CALL self%locKe()
|
|
||||||
|
|
||||||
self%sigmaVrelMax = sigma_ref/L_ref**2
|
self%sigmaVrelMax = sigma_ref/L_ref**2
|
||||||
|
|
||||||
CALL OMP_INIT_LOCK(self%lock)
|
CALL OMP_INIT_LOCK(self%lock)
|
||||||
|
|
||||||
END SUBROUTINE initVolQuadCyl
|
END SUBROUTINE initVolQuadCyl
|
||||||
|
|
||||||
FUNCTION fpsi(xi1,xi2) RESULT(psi)
|
!TODO: MAKE ELEMENT DEPENDENT
|
||||||
|
PURE FUNCTION fpsi(xi1,xi2) RESULT(psi)
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
REAL(8),INTENT(in):: xi1,xi2
|
REAL(8),INTENT(in):: xi1,xi2
|
||||||
|
|
@ -195,7 +205,8 @@ MODULE moduleMeshCyl
|
||||||
END FUNCTION fpsi
|
END FUNCTION fpsi
|
||||||
|
|
||||||
!Derivative element function (xi1)
|
!Derivative element function (xi1)
|
||||||
FUNCTION dpsiXi1(xi2) RESULT(psiXi1)
|
!TODO: MAKE ELEMENT DEPENDENT
|
||||||
|
PURE FUNCTION dpsiXi1(xi2) RESULT(psiXi1)
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
REAL(8),INTENT(in):: xi2
|
REAL(8),INTENT(in):: xi2
|
||||||
|
|
@ -209,7 +220,8 @@ MODULE moduleMeshCyl
|
||||||
END FUNCTION dpsiXi1
|
END FUNCTION dpsiXi1
|
||||||
|
|
||||||
!Derivative element function (xi2)
|
!Derivative element function (xi2)
|
||||||
FUNCTION dpsiXi2(xi1) RESULT(psiXi2)
|
!TODO: MAKE ELEMENT DEPENDENT
|
||||||
|
PURE FUNCTION dpsiXi2(xi1) RESULT(psiXi2)
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
REAL(8),INTENT(in):: xi1
|
REAL(8),INTENT(in):: xi1
|
||||||
|
|
@ -223,12 +235,13 @@ MODULE moduleMeshCyl
|
||||||
END FUNCTION dpsiXi2
|
END FUNCTION dpsiXi2
|
||||||
|
|
||||||
!Transforms physical coordinates to element coordinates
|
!Transforms physical coordinates to element coordinates
|
||||||
FUNCTION phy2logQuad(this,r) RESULT(xN)
|
PURE FUNCTION phy2logQuad(self,r) RESULT(xN)
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVolCylQuad):: this
|
CLASS(meshVolCylQuad), INTENT(in):: self
|
||||||
REAL(8):: r(1:2)
|
REAL(8), INTENT(in):: r(1:3)
|
||||||
REAL(8):: xN(1:2), xO(1:2), dPsi(1:2,1:4), detJ, j(1:2,1:2), psi(1:4), f(1:2)
|
REAL(8):: xN(1:3)
|
||||||
|
REAL(8):: xO(1:3), dPsi(1:2,1:4), detJ, j(1:2,1:2), psi(1:4), f(1:2)
|
||||||
REAL(8):: conv
|
REAL(8):: conv
|
||||||
|
|
||||||
!Iterative newton method to transform coordinates
|
!Iterative newton method to transform coordinates
|
||||||
|
|
@ -238,12 +251,12 @@ MODULE moduleMeshCyl
|
||||||
DO WHILE(conv>1.D-4)
|
DO WHILE(conv>1.D-4)
|
||||||
dPsi(1,:) = dpsiXi1(xO(2))
|
dPsi(1,:) = dpsiXi1(xO(2))
|
||||||
dPsi(2,:) = dpsiXi2(xO(1))
|
dPsi(2,:) = dpsiXi2(xO(1))
|
||||||
j = this%invJ(xO(1),xO(2),dPsi)
|
j = self%invJ(xO, dPsi)
|
||||||
psi = fpsi(xO(1), xO(2))
|
psi = fpsi(xO(1), xO(2))
|
||||||
f(1) = DOT_PRODUCT(psi,this%z)-r(1)
|
f(1) = DOT_PRODUCT(psi,self%z)-r(1)
|
||||||
f(2) = DOT_PRODUCT(psi,this%r)-r(2)
|
f(2) = DOT_PRODUCT(psi,self%r)-r(2)
|
||||||
detJ = this%detJac(xO(1),xO(2),dPsi)
|
detJ = self%detJac(xO,dPsi)
|
||||||
xN=xO - MATMUL(j, f)/detJ
|
xN(1:2)=xO(1:2) - MATMUL(j, f)/detJ
|
||||||
conv=MAXVAL(DABS(xN-xO),1)
|
conv=MAXVAL(DABS(xN-xO),1)
|
||||||
xO=xN
|
xO=xN
|
||||||
|
|
||||||
|
|
@ -252,106 +265,139 @@ MODULE moduleMeshCyl
|
||||||
END FUNCTION phy2logQuad
|
END FUNCTION phy2logQuad
|
||||||
|
|
||||||
!Computes element local stiffness matrix
|
!Computes element local stiffness matrix
|
||||||
SUBROUTINE localKeQuad(this)
|
PURE FUNCTION elemKQuad(self) RESULT(ke)
|
||||||
USE moduleConstParam
|
USE moduleConstParam
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVolCylQuad):: this
|
CLASS(meshVolCylQuad), INTENT(in):: self
|
||||||
REAL(8):: r, xi1, xi2, dPsi(1:2,1:4)
|
REAL(8):: r, xi(1:3), dPsi(1:2,1:4)
|
||||||
|
REAL(8):: ke(1:4,1:4)
|
||||||
REAL(8):: j(1:2,1:2), detJ
|
REAL(8):: j(1:2,1:2), detJ
|
||||||
INTEGER:: l, m
|
INTEGER:: l, m
|
||||||
|
|
||||||
this%Ke=0.D0
|
ke=0.D0
|
||||||
!Start 2D Gauss Quad Integral
|
!Start 2D Gauss Quad Integral
|
||||||
DO l=1, 3
|
DO l=1, 3
|
||||||
|
xi(1) = cor(l)
|
||||||
|
dPsi(2,:) = dpsiXi2(xi(1))
|
||||||
DO m = 1, 3
|
DO m = 1, 3
|
||||||
xi1 = cor(l)
|
xi(2) = cor(m)
|
||||||
xi2 = cor(m)
|
dPsi(1,:) = dpsiXi1(xi(2))
|
||||||
dPsi(1,:) = dpsiXi1(xi2)
|
detJ = self%detJac(xi,dPsi)
|
||||||
dPsi(2,:) = dpsiXi2(xi1)
|
j = self%invJ(xi,dPsi)
|
||||||
detJ = this%detJac(xi1,xi2,dPsi)
|
r = DOT_PRODUCT(fpsi(xi(1),xi(2)),self%r)
|
||||||
j = this%invJ(xi1,xi2,dPsi)
|
ke = ke + MATMUL(TRANSPOSE(MATMUL(j,dPsi)),MATMUL(j,dPsi))*r*w(l)*w(m)/detJ
|
||||||
r = DOT_PRODUCT(fpsi(xi1,xi2),this%r)
|
|
||||||
this%Ke = this%Ke + MATMUL(TRANSPOSE(MATMUL(j,dPsi)),MATMUL(j,dPsi))*r*w(l)*w(m)/detJ
|
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
END DO
|
END DO
|
||||||
this%Ke = this%Ke*2.D0*PI
|
ke = ke*2.D0*PI
|
||||||
|
|
||||||
END SUBROUTINE localKeQuad
|
END FUNCTION elemKQuad
|
||||||
|
|
||||||
!Computes element Jacobian determinant
|
!Computes the local source vector for a force f
|
||||||
FUNCTION detJQuad(this,xi1,xi2,dPsi_in) RESULT(dJ)
|
PURE FUNCTION elemFQuad(self, source) RESULT(localF)
|
||||||
|
USE moduleConstParam
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
REAL(8),OPTIONAL:: dPsi_in(1:2,1:4)
|
CLASS(meshVolCylQuad), INTENT(in):: self
|
||||||
|
REAL(8), INTENT(in):: source(1:)
|
||||||
|
REAL(8), ALLOCATABLE:: localF(:)
|
||||||
|
REAL(8):: r, xi(1:3), psi(1:4)
|
||||||
|
REAL(8):: detJ, f
|
||||||
|
INTEGER:: l, m
|
||||||
|
|
||||||
|
ALLOCATE(localF(1:4))
|
||||||
|
localF = 0.D0
|
||||||
|
xi = 0.D0
|
||||||
|
DO l=1, 3
|
||||||
|
DO m = 1, 3
|
||||||
|
xi(1) = cor(l)
|
||||||
|
xi(2) = cor(m)
|
||||||
|
detJ = self%detJac(xi)
|
||||||
|
psi = fpsi(xi(1),xi(2))
|
||||||
|
r = DOT_PRODUCT(psi,self%r)
|
||||||
|
f = DOT_PRODUCT(psi,source)
|
||||||
|
localF = localF + r*f*psi*w(l)*w(m)*detJ
|
||||||
|
|
||||||
|
END DO
|
||||||
|
END DO
|
||||||
|
localF = localF*2.D0*PI
|
||||||
|
|
||||||
|
END FUNCTION elemFQuad
|
||||||
|
|
||||||
|
!Computes element Jacobian determinant
|
||||||
|
PURE FUNCTION detJQuad(self,xi,dPsi_in) RESULT(dJ)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVolCylQuad), INTENT(in):: self
|
||||||
|
REAL(8), INTENT(in):: xi(1:3)
|
||||||
|
REAL(8), INTENT(in), OPTIONAL:: dPsi_in(1:2,1:4)
|
||||||
|
REAL(8):: dJ
|
||||||
REAL(8):: dPsi(1:2,1:4)
|
REAL(8):: dPsi(1:2,1:4)
|
||||||
REAL(8):: dz(1:2), dr(1:2)
|
REAL(8):: dz(1:2), dr(1:2)
|
||||||
REAL(8):: xi1,xi2, dJ
|
|
||||||
CLASS(meshVolCylQuad):: this
|
|
||||||
|
|
||||||
IF(PRESENT(dPsi_in)) THEN
|
IF(PRESENT(dPsi_in)) THEN
|
||||||
dPsi=dPsi_in
|
dPsi=dPsi_in
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
dPsi(1,:) = dpsiXi1(xi2)
|
dPsi(1,:) = dpsiXi1(xi(2))
|
||||||
dPsi(2,:) = dpsiXi2(xi1)
|
dPsi(2,:) = dpsiXi2(xi(1))
|
||||||
|
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
dz(1) = DOT_PRODUCT(dPsi(1,:),this%z)
|
dz(1) = DOT_PRODUCT(dPsi(1,:),self%z)
|
||||||
dz(2) = DOT_PRODUCT(dPsi(2,:),this%z)
|
dz(2) = DOT_PRODUCT(dPsi(2,:),self%z)
|
||||||
dr(1) = DOT_PRODUCT(dPsi(1,:),this%r)
|
dr(1) = DOT_PRODUCT(dPsi(1,:),self%r)
|
||||||
dr(2) = DOT_PRODUCT(dPsi(2,:),this%r)
|
dr(2) = DOT_PRODUCT(dPsi(2,:),self%r)
|
||||||
dJ = dz(1)*dr(2)-dz(2)*dr(1)
|
dJ = dz(1)*dr(2)-dz(2)*dr(1)
|
||||||
|
|
||||||
END FUNCTION detJQuad
|
END FUNCTION detJQuad
|
||||||
|
|
||||||
FUNCTION invJQuad(this,xi1,xi2,dPsi_in) RESULT(j) !Computes element Jacobian inverse matrix (without determinant)
|
PURE FUNCTION invJQuad(self,xi,dPsi_in) RESULT(j) !Computes element Jacobian inverse matrix (without determinant)
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
REAL(8),OPTIONAL:: dpsi_in(1:2,1:4)
|
CLASS(meshVolCylQuad), INTENT(in):: self
|
||||||
|
REAL(8), INTENT(in):: xi(1:3)
|
||||||
|
REAL(8), INTENT(in), OPTIONAL:: dpsi_in(1:2,1:4)
|
||||||
REAL(8):: dPsi(1:2,1:4)
|
REAL(8):: dPsi(1:2,1:4)
|
||||||
REAL(8):: dz(1:2), dr(1:2)
|
REAL(8):: dz(1:2), dr(1:2)
|
||||||
REAL(8):: xi1,xi2, j(1:2,1:2)
|
REAL(8):: j(1:2,1:2)
|
||||||
CLASS(meshVolCylQuad):: this
|
|
||||||
|
|
||||||
IF(PRESENT(dPsi_in)) THEN
|
IF(PRESENT(dPsi_in)) THEN
|
||||||
dPsi=dPsi_in
|
dPsi=dPsi_in
|
||||||
|
|
||||||
ELSE
|
ELSE
|
||||||
dPsi(1,:) = dpsiXi1(xi2)
|
dPsi(1,:) = dpsiXi1(xi(2))
|
||||||
dPsi(2,:) = dpsiXi2(xi1)
|
dPsi(2,:) = dpsiXi2(xi(1))
|
||||||
|
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
dz(1) = DOT_PRODUCT(dPsi(1,:),this%z)
|
dz(1) = DOT_PRODUCT(dPsi(1,:),self%z)
|
||||||
dz(2) = DOT_PRODUCT(dPsi(2,:),this%z)
|
dz(2) = DOT_PRODUCT(dPsi(2,:),self%z)
|
||||||
dr(1) = DOT_PRODUCT(dPsi(1,:),this%r)
|
dr(1) = DOT_PRODUCT(dPsi(1,:),self%r)
|
||||||
dr(2) = DOT_PRODUCT(dPsi(2,:),this%r)
|
dr(2) = DOT_PRODUCT(dPsi(2,:),self%r)
|
||||||
j(1,:) = (/ dr(2), -dz(2) /)
|
j(1,:) = (/ dr(2), -dz(2) /)
|
||||||
j(2,:) = (/ -dr(1), dz(1) /)
|
j(2,:) = (/ -dr(1), dz(1) /)
|
||||||
|
|
||||||
END FUNCTION invJQuad
|
END FUNCTION invJQuad
|
||||||
|
|
||||||
SUBROUTINE areaQuad(this)!Computes element area
|
SUBROUTINE areaQuad(self)!Computes element area
|
||||||
USE moduleConstParam
|
USE moduleConstParam
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVolCylQuad):: this
|
CLASS(meshVolCylQuad):: self
|
||||||
REAL(8):: r, xi1, xi2
|
REAL(8):: r, xi(1:3)
|
||||||
REAL(8):: detJ, fpsi0(1:4)
|
REAL(8):: detJ, fpsi0(1:4)
|
||||||
|
|
||||||
this%volume = 0.D0
|
self%volume = 0.D0
|
||||||
this%arNodes = 0.D0
|
self%arNodes = 0.D0
|
||||||
!2D 1 point Gauss Quad Integral
|
!2D 1 point Gauss Quad Integral
|
||||||
xi1 = 0.D0
|
xi = 0.D0
|
||||||
xi2 = 0.D0
|
detJ = self%detJac(xi)*8.D0*PI !4*2*pi
|
||||||
detJ = this%detJac(xi1,xi2)*8.D0*PI !4*2*pi
|
fpsi0 = fpsi(xi(1),xi(2))
|
||||||
fpsi0 = fpsi(xi1,xi2)
|
r = DOT_PRODUCT(fpsi0,self%r)
|
||||||
r = DOT_PRODUCT(fpsi0,this%r)
|
self%volume = r*detJ
|
||||||
this%volume = r*detJ
|
self%arNodes = fpsi0*r*detJ
|
||||||
this%arNodes = fpsi0*r*detJ
|
|
||||||
|
|
||||||
END SUBROUTINE areaQuad
|
END SUBROUTINE areaQuad
|
||||||
|
|
||||||
|
|
@ -376,24 +422,6 @@ MODULE moduleMeshCyl
|
||||||
|
|
||||||
END FUNCTION insideQuad
|
END FUNCTION insideQuad
|
||||||
|
|
||||||
FUNCTION dValQuad(this,xi1,xi2) RESULT(EF)!Computes electric field in xi1,xi2
|
|
||||||
IMPLICIT NONE
|
|
||||||
|
|
||||||
CLASS(meshVolCylQuad):: this
|
|
||||||
REAL(8):: xi1, xi2, dPsi(1:2,1:4)
|
|
||||||
REAL(8):: j(1:2,1:2), detJ
|
|
||||||
REAL(8):: EF(1:3)
|
|
||||||
|
|
||||||
dPsi(1,:) = dpsiXi1(xi2)
|
|
||||||
dPsi(2,:) = dpsiXi2(xi1)
|
|
||||||
detJ = this%detJac(xi1,xi2,dPsi)
|
|
||||||
j = this%invJ(xi1,xi2,dPsi)
|
|
||||||
EF(1) = -DOT_PRODUCT(dPsi(1,:), this%phi)*j(2,2)/detJ
|
|
||||||
EF(2) = -DOT_PRODUCT(dPsi(2,:), this%phi)*j(1,1)/detJ
|
|
||||||
EF(3) = 0.D0
|
|
||||||
|
|
||||||
END FUNCTION dValQuad
|
|
||||||
|
|
||||||
SUBROUTINE scatterQuad(self, part)
|
SUBROUTINE scatterQuad(self, part)
|
||||||
USE moduleOutput
|
USE moduleOutput
|
||||||
USE moduleSpecies
|
USE moduleSpecies
|
||||||
|
|
@ -428,29 +456,65 @@ MODULE moduleMeshCyl
|
||||||
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(4)*part%v(:)
|
vertex%mom(:) = vertex%mom(:) + part%weight*w_p(4)*part%v(:)
|
||||||
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(4)*tensorS
|
vertex%tensorS(:,:) = vertex%tensorS(:,:) + part%weight*w_p(4)*tensorS
|
||||||
|
|
||||||
|
|
||||||
END SUBROUTINE scatterQuad
|
END SUBROUTINE scatterQuad
|
||||||
|
|
||||||
|
PURE FUNCTION gatherEFQuad(self,xi) RESULT(EF)!Computes electric field inside element
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVolCylQuad), INTENT(in):: self
|
||||||
|
REAL(8), INTENT(in):: xi(1:3)
|
||||||
|
REAL(8):: dPsi(1:2,1:4)
|
||||||
|
REAL(8):: j(1:2,1:2), detJ
|
||||||
|
REAL(8):: phi(1:4)
|
||||||
|
REAL(8):: EF(1:3)
|
||||||
|
|
||||||
|
phi = (/self%n1%emData%phi, &
|
||||||
|
self%n2%emData%phi, &
|
||||||
|
self%n3%emData%phi, &
|
||||||
|
self%n4%emData%phi /)
|
||||||
|
|
||||||
|
dPsi(1,:) = dpsiXi1(xi(2))
|
||||||
|
dPsi(2,:) = dpsiXi2(xi(1))
|
||||||
|
detJ = self%detJac(xi,dPsi)
|
||||||
|
j = self%invJ(xi,dPsi)
|
||||||
|
EF(1) = -DOT_PRODUCT(dPsi(1,:), phi)*j(2,2)/detJ
|
||||||
|
EF(2) = -DOT_PRODUCT(dPsi(2,:), phi)*j(1,1)/detJ
|
||||||
|
EF(3) = 0.D0
|
||||||
|
|
||||||
|
END FUNCTION gatherEFQuad
|
||||||
|
|
||||||
|
PURE FUNCTION getNodesQuad(self) RESULT(n)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CLASS(meshVolCylQuad), INTENT(in):: self
|
||||||
|
INTEGER, ALLOCATABLE:: n(:)
|
||||||
|
|
||||||
|
ALLOCATE(n(1:4))
|
||||||
|
n = (/self%n1%n, self%n2%n, self%n3%n, self%n4%n /)
|
||||||
|
|
||||||
|
END FUNCTION getNodesQuad
|
||||||
|
|
||||||
RECURSIVE SUBROUTINE findCellCylQuad(self, part, oldCell)
|
RECURSIVE SUBROUTINE findCellCylQuad(self, part, oldCell)
|
||||||
USE moduleSpecies
|
USE moduleSpecies
|
||||||
|
USE OMP_LIB
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
CLASS(meshVolCylQuad), INTENT(inout):: self
|
CLASS(meshVolCylQuad), INTENT(inout):: self
|
||||||
CLASS(meshVol), OPTIONAL, INTENT(in):: oldCell
|
CLASS(meshVol), OPTIONAL, INTENT(in):: oldCell
|
||||||
CLASS(particle), INTENT(inout), TARGET:: part
|
CLASS(particle), INTENT(inout), TARGET:: part
|
||||||
REAL(8):: xLog(1:2)
|
REAL(8):: xLog(1:3)
|
||||||
REAL(8):: xLogArray(1:4)
|
REAL(8):: xLogArray(1:4)
|
||||||
CLASS(*), POINTER:: nextElement
|
CLASS(*), POINTER:: nextElement
|
||||||
INTEGER:: nextInt
|
INTEGER:: nextInt
|
||||||
|
|
||||||
xLog = self%phy2log(part%r(1:2))
|
xLog = self%phy2log(part%r)
|
||||||
IF (self%inside(xLog(1), xLog(2))) THEN
|
|
||||||
!Checks if particle is inside of current cell
|
!Checks if particle is inside of current cell
|
||||||
IF (PRESENT(oldCell)) THEN
|
IF (self%inside(xLog(1), xLog(2))) THEN
|
||||||
!If oldCell, recalculate particle weight, as particle has entered a new cell.
|
! IF (PRESENT(oldCell)) THEN
|
||||||
part%weight = part%weight*oldCell%volume/self%volume
|
! !If oldCell, recalculate particle weight, as particle has entered a new cell.
|
||||||
|
! part%weight = part%weight*oldCell%volume/self%volume
|
||||||
END IF
|
!
|
||||||
|
! END IF
|
||||||
part%e_p = self%n
|
part%e_p = self%n
|
||||||
part%xLog = xLog
|
part%xLog = xLog
|
||||||
part%n_in = .TRUE.
|
part%n_in = .TRUE.
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,6 @@ MODULE moduleMeshCylBoundary
|
||||||
CLASS(meshEdgeCylAxis), INTENT(inout):: self
|
CLASS(meshEdgeCylAxis), INTENT(inout):: self
|
||||||
CLASS(particle), INTENT(inout):: part
|
CLASS(particle), INTENT(inout):: part
|
||||||
|
|
||||||
!Do to the 2D Cyl pusher, this function should never be called.
|
|
||||||
|
|
||||||
END SUBROUTINE symmetryAxis
|
END SUBROUTINE symmetryAxis
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ MODULE moduleMeshCylRead
|
||||||
PROCEDURE, PASS:: readMesh => readMeshCyl
|
PROCEDURE, PASS:: readMesh => readMeshCyl
|
||||||
PROCEDURE, PASS:: printOutput => printOutputCyl
|
PROCEDURE, PASS:: printOutput => printOutputCyl
|
||||||
PROCEDURE, PASS:: printColl => printCollisionsCyl
|
PROCEDURE, PASS:: printColl => printCollisionsCyl
|
||||||
|
PROCEDURE, PASS:: printEM => printEMCyl
|
||||||
|
|
||||||
END TYPE
|
END TYPE
|
||||||
|
|
||||||
|
|
@ -41,8 +42,10 @@ MODULE moduleMeshCylRead
|
||||||
READ(10, *) self%numNodes
|
READ(10, *) self%numNodes
|
||||||
!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:numNodes,1:numNodes))
|
ALLOCATE(self%K(1:self%numNodes,1:self%numNodes))
|
||||||
! ALLOCATE(self%F(1:numNodes))
|
ALLOCATE(self%IPIV(1:self%numNodes,1:self%numNodes))
|
||||||
|
self%K = 0.D0
|
||||||
|
self%IPIV = 0
|
||||||
!Read nodes cartesian coordinates (x=z, y=r, z=null)
|
!Read nodes cartesian coordinates (x=z, y=r, z=null)
|
||||||
DO e=1, self%numNodes
|
DO e=1, self%numNodes
|
||||||
READ(10, *) n, z, r
|
READ(10, *) n, z, r
|
||||||
|
|
@ -123,24 +126,10 @@ MODULE moduleMeshCylRead
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
||||||
END DO
|
!Constructs the global K matrix
|
||||||
|
CALL constructGlobalK(self%K, self%vols(e)%obj)
|
||||||
|
|
||||||
! !Compute global stiffness matrix
|
END DO
|
||||||
! GlobalK=0.D0
|
|
||||||
! DO e=1, numElem
|
|
||||||
! DO i=1, 4
|
|
||||||
! DO j=1, 4
|
|
||||||
! GlobalK(elems(e)%p(i),elems(e)%p(j)) = GlobalK(elems(e)%p(i),elems(e)%p(j)) + elems(e)%Ke(i,j)
|
|
||||||
! END DO
|
|
||||||
! END DO
|
|
||||||
! END DO
|
|
||||||
! ! Apply Dirichlet boundary conditions to GlobalK
|
|
||||||
! DO n=1, numNodes
|
|
||||||
! IF (nodes(n)%bound == 1) THEN
|
|
||||||
! GlobalK(n,:)=0.D0
|
|
||||||
! GlobalK(n,n)=1.D0
|
|
||||||
! END IF
|
|
||||||
! END DO
|
|
||||||
|
|
||||||
END SUBROUTINE
|
END SUBROUTINE
|
||||||
|
|
||||||
|
|
@ -298,6 +287,41 @@ MODULE moduleMeshCylRead
|
||||||
|
|
||||||
END SUBROUTINE connectedQuadEdge
|
END SUBROUTINE connectedQuadEdge
|
||||||
|
|
||||||
|
SUBROUTINE constructGlobalK(K, elem)
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
REAL(8), INTENT(inout):: K(1:,1:)
|
||||||
|
CLASS(meshVol), INTENT(in):: elem
|
||||||
|
REAL(8), ALLOCATABLE:: localK(:,:)
|
||||||
|
INTEGER:: nNodes, i, j
|
||||||
|
INTEGER, ALLOCATABLE:: n(:)
|
||||||
|
|
||||||
|
SELECT TYPE(elem)
|
||||||
|
TYPE IS(meshVolCylQuad)
|
||||||
|
nNodes = 4
|
||||||
|
ALLOCATE(localK(1:nNodes,1:nNodes))
|
||||||
|
localK = elem%elemK()
|
||||||
|
ALLOCATE(n(1:nNodes))
|
||||||
|
n = (/ elem%n1%n, elem%n2%n, &
|
||||||
|
elem%n3%n, elem%n4%n /)
|
||||||
|
|
||||||
|
CLASS DEFAULT
|
||||||
|
nNodes = 0
|
||||||
|
ALLOCATE(localK(1:1, 1:1))
|
||||||
|
localK = 0.D0
|
||||||
|
ALLOCATE(n(1:1))
|
||||||
|
n = 0
|
||||||
|
|
||||||
|
END SELECT
|
||||||
|
|
||||||
|
DO i = 1, nNodes
|
||||||
|
DO j = 1, nNodes
|
||||||
|
K(n(i), n(j)) = K(n(i), n(j)) + localK(i, j)
|
||||||
|
END DO
|
||||||
|
END DO
|
||||||
|
|
||||||
|
END SUBROUTINE constructGlobalK
|
||||||
|
|
||||||
SUBROUTINE printOutputCyl(self, t)
|
SUBROUTINE printOutputCyl(self, t)
|
||||||
USE moduleRefParam
|
USE moduleRefParam
|
||||||
USE moduleSpecies
|
USE moduleSpecies
|
||||||
|
|
@ -425,4 +449,60 @@ MODULE moduleMeshCylRead
|
||||||
|
|
||||||
END SUBROUTINE printCollisionsCyl
|
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
|
||||||
|
|
||||||
|
IF (emOutput) THEN
|
||||||
|
time = DBLE(t)*tau*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((/0.D0, 0.D0, 0.D0/))*EF_ref
|
||||||
|
END DO
|
||||||
|
WRITE(20, "(A)") '$EndElementData'
|
||||||
|
CLOSE(20)
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
END SUBROUTINE printEMCyl
|
||||||
|
|
||||||
END MODULE moduleMeshCylRead
|
END MODULE moduleMeshCylRead
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,13 @@ MODULE moduleOutput
|
||||||
|
|
||||||
END TYPE
|
END TYPE
|
||||||
|
|
||||||
|
!Type for EM data in node
|
||||||
|
TYPE emNode
|
||||||
|
CHARACTER(:), ALLOCATABLE:: type
|
||||||
|
REAL(8):: phi
|
||||||
|
|
||||||
|
END TYPE emNode
|
||||||
|
|
||||||
!Output in dimensional units to print
|
!Output in dimensional units to print
|
||||||
TYPE outputFormat
|
TYPE outputFormat
|
||||||
REAL(8):: density, velocity(1:3), pressure, temperature
|
REAL(8):: density, velocity(1:3), pressure, temperature
|
||||||
|
|
@ -18,6 +25,7 @@ MODULE moduleOutput
|
||||||
INTEGER:: triggerOutput, counterOutput
|
INTEGER:: triggerOutput, counterOutput
|
||||||
LOGICAL:: timeOutput = .FALSE.
|
LOGICAL:: timeOutput = .FALSE.
|
||||||
LOGICAL:: collOutput = .FALSE.
|
LOGICAL:: collOutput = .FALSE.
|
||||||
|
LOGICAL:: emOutput = .FALSE.
|
||||||
|
|
||||||
CONTAINS
|
CONTAINS
|
||||||
FUNCTION outerProduct(a,b) RESULT(s)
|
FUNCTION outerProduct(a,b) RESULT(s)
|
||||||
|
|
@ -42,6 +50,7 @@ MODULE moduleOutput
|
||||||
END FUNCTION tensorTrace
|
END FUNCTION tensorTrace
|
||||||
|
|
||||||
SUBROUTINE calculateOutput(rawValues, formatValues, nodeVol, speciesIn)
|
SUBROUTINE calculateOutput(rawValues, formatValues, nodeVol, speciesIn)
|
||||||
|
USE moduleConstParam
|
||||||
USE moduleRefParam
|
USE moduleRefParam
|
||||||
USE moduleSpecies
|
USE moduleSpecies
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
!Reference parameters
|
!Reference parameters
|
||||||
MODULE moduleRefParam
|
MODULE moduleRefParam
|
||||||
USE moduleConstParam
|
|
||||||
!Parameters that define the problem (inputs)
|
!Parameters that define the problem (inputs)
|
||||||
REAL(8):: n_ref, m_ref, T_ref, r_ref, sigma_ref!, q_ref=1.6022D-19
|
REAL(8):: n_ref, m_ref, T_ref, r_ref, debye_ref, sigma_ref
|
||||||
!Reference parameters for non-dimensional problem
|
!Reference parameters for non-dimensional problem
|
||||||
REAL(8):: L_ref, v_ref, ti_ref, Vol_ref
|
REAL(8):: L_ref, v_ref, ti_ref, Vol_ref, EF_ref, Volt_ref
|
||||||
|
|
||||||
END MODULE moduleRefParam
|
END MODULE moduleRefParam
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,44 @@
|
||||||
MODULE moduleSolver
|
MODULE moduleSolver
|
||||||
|
|
||||||
|
TYPE, PUBLIC, ABSTRACT:: solverGeneric
|
||||||
|
CONTAINS
|
||||||
|
PROCEDURE(push_interafece), DEFERRED, NOPASS:: push
|
||||||
|
PROCEDURE(solveEM_interface), DEFERRED, NOPASS:: solveEMField
|
||||||
|
|
||||||
|
END TYPE solverGeneric
|
||||||
|
|
||||||
|
ABSTRACT INTERFACE
|
||||||
|
!Push a particle
|
||||||
|
PURE SUBROUTINE push_interafece(part)
|
||||||
|
USE moduleSpecies
|
||||||
|
|
||||||
|
TYPE(particle), INTENT(inout):: part
|
||||||
|
|
||||||
|
END SUBROUTINE push_interafece
|
||||||
|
|
||||||
|
!Solve the electromagnetic field
|
||||||
|
SUBROUTINE solveEM_interface()
|
||||||
|
|
||||||
|
END SUBROUTINE solveEM_interface
|
||||||
|
|
||||||
|
END INTERFACE
|
||||||
|
|
||||||
|
TYPE, PUBLIC, EXTENDS(solverGeneric):: solverCylNeutral
|
||||||
|
CONTAINS
|
||||||
|
PROCEDURE, NOPASS:: push => pushCylNeutral
|
||||||
|
PROCEDURE, NOPASS:: solveEMField => noEMField
|
||||||
|
|
||||||
|
END TYPE solverCylNeutral
|
||||||
|
|
||||||
|
TYPE, PUBLIC, EXTENDS(solverGeneric):: solverCylCharged
|
||||||
|
CONTAINS
|
||||||
|
PROCEDURE, NOPASS:: push => pushCylCharged
|
||||||
|
PROCEDURE, NOPASS:: solveEMField => solveElecField
|
||||||
|
|
||||||
|
END TYPE solverCylCharged
|
||||||
|
|
||||||
|
CLASS(solverGeneric), ALLOCATABLE:: solver
|
||||||
|
|
||||||
CONTAINS
|
CONTAINS
|
||||||
SUBROUTINE doPushes()
|
SUBROUTINE doPushes()
|
||||||
USE moduleSpecies
|
USE moduleSpecies
|
||||||
|
|
@ -10,7 +49,9 @@ MODULE moduleSolver
|
||||||
|
|
||||||
!$OMP DO
|
!$OMP DO
|
||||||
DO n=1, nPartOld
|
DO n=1, nPartOld
|
||||||
CALL push(partOld(n))
|
!Push particle
|
||||||
|
CALL solver%push(partOld(n))
|
||||||
|
!Find cell in wich particle reside
|
||||||
CALL mesh%vols(partOld(n)%e_p)%obj%findCell(partOld(n))
|
CALL mesh%vols(partOld(n)%e_p)%obj%findCell(partOld(n))
|
||||||
|
|
||||||
END DO
|
END DO
|
||||||
|
|
@ -18,16 +59,15 @@ MODULE moduleSolver
|
||||||
|
|
||||||
END SUBROUTINE doPushes
|
END SUBROUTINE doPushes
|
||||||
|
|
||||||
!Push one particle. Boris pusher for 2D Cyl
|
!Push one particle. Boris pusher for 2D Cyl Neutral particle
|
||||||
!TODO: make general for any pusher
|
PURE SUBROUTINE pushCylNeutral(part)
|
||||||
PURE SUBROUTINE push(part)
|
|
||||||
USE moduleSpecies
|
USE moduleSpecies
|
||||||
USE moduleMesh
|
|
||||||
IMPLICIT NONE
|
IMPLICIT NONE
|
||||||
|
|
||||||
TYPE(particle), INTENT(inout):: part
|
TYPE(particle), INTENT(inout):: part
|
||||||
REAL(8):: v_p_oh_star(2:3)
|
REAL(8):: v_p_oh_star(2:3)
|
||||||
TYPE(particle):: part_temp
|
TYPE(particle):: part_temp
|
||||||
REAL(8):: x_new, y_new, r, sin_alpha, cos_alpha, alpha
|
REAL(8):: x_new, y_new, r, sin_alpha, cos_alpha
|
||||||
|
|
||||||
part_temp = part
|
part_temp = part
|
||||||
!z
|
!z
|
||||||
|
|
@ -40,8 +80,6 @@ MODULE moduleSolver
|
||||||
y_new = v_p_oh_star(3)*tau
|
y_new = v_p_oh_star(3)*tau
|
||||||
r = DSQRT(x_new**2+y_new**2)
|
r = DSQRT(x_new**2+y_new**2)
|
||||||
part_temp%r(2) = r
|
part_temp%r(2) = r
|
||||||
alpha = 0.D0!ATAN2(y_new,x_new) !0 in 2D problem
|
|
||||||
part_temp%r(3) = part%r(3) + alpha
|
|
||||||
IF (r > 0.D0) THEN
|
IF (r > 0.D0) THEN
|
||||||
sin_alpha = y_new/r
|
sin_alpha = y_new/r
|
||||||
cos_alpha = x_new/r
|
cos_alpha = x_new/r
|
||||||
|
|
@ -57,7 +95,47 @@ MODULE moduleSolver
|
||||||
!Copy temporal particle to particle
|
!Copy temporal particle to particle
|
||||||
part=part_temp
|
part=part_temp
|
||||||
|
|
||||||
END SUBROUTINE push
|
END SUBROUTINE pushCylNeutral
|
||||||
|
|
||||||
|
!Push one particle. Boris pusher for 2D Cyl Charged particle
|
||||||
|
PURE SUBROUTINE pushCylCharged(part)
|
||||||
|
USE moduleSpecies
|
||||||
|
USE moduleEM
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
TYPE(particle), INTENT(inout):: part
|
||||||
|
REAL(8):: v_p_oh_star(2:3)
|
||||||
|
TYPE(particle):: part_temp
|
||||||
|
REAL(8):: x_new, y_new, r, sin_alpha, cos_alpha
|
||||||
|
REAL(8):: qmEFt(1:3)!charge*tau*EF/mass
|
||||||
|
|
||||||
|
part_temp = part
|
||||||
|
!Get electric field at particle position
|
||||||
|
qmEFt = part_temp%qm*gatherElecField(part_temp)*tau
|
||||||
|
!z
|
||||||
|
part_temp%v(1) = part%v(1) + qmEFt(1)
|
||||||
|
part_temp%r(1) = part%r(1) + part_temp%v(1)*tau
|
||||||
|
!r,theta
|
||||||
|
v_p_oh_star(2) = part%v(2) + qmEFt(2)
|
||||||
|
x_new = part%r(2) + v_p_oh_star(2)*tau
|
||||||
|
v_p_oh_star(3) = part%v(3) + qmEFt(3)
|
||||||
|
y_new = v_p_oh_star(3)*tau
|
||||||
|
r = DSQRT(x_new**2+y_new**2)
|
||||||
|
part_temp%r(2) = r
|
||||||
|
IF (r > 0.D0) THEN
|
||||||
|
sin_alpha = y_new/r
|
||||||
|
cos_alpha = x_new/r
|
||||||
|
ELSE
|
||||||
|
sin_alpha = 0.D0
|
||||||
|
cos_alpha = 1.D0
|
||||||
|
END IF
|
||||||
|
part_temp%v(2) = cos_alpha*v_p_oh_star(2)+sin_alpha*v_p_oh_star(3)
|
||||||
|
part_temp%v(3) = -sin_alpha*v_p_oh_star(2)+cos_alpha*v_p_oh_star(3)
|
||||||
|
part_temp%n_in = .FALSE. !Assume particle is outside until cell is found
|
||||||
|
!Copy temporal particle to particle
|
||||||
|
part=part_temp
|
||||||
|
|
||||||
|
END SUBROUTINE pushCylCharged
|
||||||
|
|
||||||
!Do the collisions in all the cells
|
!Do the collisions in all the cells
|
||||||
SUBROUTINE doCollisions()
|
SUBROUTINE doCollisions()
|
||||||
|
|
@ -153,6 +231,64 @@ MODULE moduleSolver
|
||||||
|
|
||||||
END SUBROUTINE doScatter
|
END SUBROUTINE doScatter
|
||||||
|
|
||||||
|
SUBROUTINE doEMField()
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
CALL solver%solveEMField()
|
||||||
|
|
||||||
|
END SUBROUTINE doEMField
|
||||||
|
|
||||||
|
!Solving the Poisson equation for electrostatic potential
|
||||||
|
SUBROUTINE solveElecField()
|
||||||
|
USE moduleEM
|
||||||
|
USE moduleMesh
|
||||||
|
USE moduleErrors
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
INTEGER, SAVE:: INFO
|
||||||
|
INTEGER:: n
|
||||||
|
REAL(8), ALLOCATABLE, SAVE:: tempF(:)
|
||||||
|
EXTERNAL:: dgetrs
|
||||||
|
|
||||||
|
!$OMP SINGLE
|
||||||
|
ALLOCATE(tempF(1:mesh%numNodes))
|
||||||
|
!$OMP END SINGLE
|
||||||
|
|
||||||
|
CALL assembleSourceVector(tempF)
|
||||||
|
|
||||||
|
!$OMP SINGLE
|
||||||
|
CALL dgetrs('N', mesh%numNodes, 1, mesh%K, mesh%numNodes, &
|
||||||
|
mesh%IPIV, tempF, mesh%numNodes, info)
|
||||||
|
!$OMP END SINGLE
|
||||||
|
|
||||||
|
IF (info == 0) THEN
|
||||||
|
!Suscessful resolution of Poission equation
|
||||||
|
!$OMP DO
|
||||||
|
DO n = 1, mesh%numNodes
|
||||||
|
mesh%nodes(n)%obj%emData%phi = tempF(n)
|
||||||
|
|
||||||
|
END DO
|
||||||
|
!$OMP END DO
|
||||||
|
|
||||||
|
ELSE
|
||||||
|
!$OMP SINGLE
|
||||||
|
CALL criticalError('Poisson equation failed', 'solveElecField')
|
||||||
|
!$OMP END SINGLE
|
||||||
|
|
||||||
|
END IF
|
||||||
|
|
||||||
|
!$OMP SINGLE
|
||||||
|
DEALLOCATE(tempF)
|
||||||
|
!$OMP END SINGLE
|
||||||
|
|
||||||
|
END SUBROUTINE solveElecField
|
||||||
|
|
||||||
|
!Empty module that does no computation of EM field for neutral cases
|
||||||
|
SUBROUTINE noEMField()
|
||||||
|
IMPLICIT NONE
|
||||||
|
|
||||||
|
END SUBROUTINE noEMField
|
||||||
|
|
||||||
SUBROUTINE doOutput(t)
|
SUBROUTINE doOutput(t)
|
||||||
USE moduleMesh
|
USE moduleMesh
|
||||||
USE moduleOutput
|
USE moduleOutput
|
||||||
|
|
@ -172,7 +308,8 @@ MODULE moduleSolver
|
||||||
CALL mesh%printOutput(t)
|
CALL mesh%printOutput(t)
|
||||||
CALL printTime(t, t == 0)
|
CALL printTime(t, t == 0)
|
||||||
CALL mesh%printColl(t)
|
CALL mesh%printColl(t)
|
||||||
WRITE(*, "(5X,A21,I10,A1,I8)") "t/tmax: ", t, "/", tmax
|
CALL mesh%printEM(t)
|
||||||
|
WRITE(*, "(5X,A21,I10,A1,I10)") "t/tmax: ", t, "/", tmax
|
||||||
WRITE(*, "(5X,A21,I10)") "Particles: ", nPartOld
|
WRITE(*, "(5X,A21,I10)") "Particles: ", nPartOld
|
||||||
IF (t == 0) THEN
|
IF (t == 0) THEN
|
||||||
WRITE(*, "(5X,A21,F8.1,A2)") " init time: ", 1.D3*tStep, "ms"
|
WRITE(*, "(5X,A21,F8.1,A2)") " init time: ", 1.D3*tStep, "ms"
|
||||||
|
|
@ -183,7 +320,7 @@ MODULE moduleSolver
|
||||||
END IF
|
END IF
|
||||||
|
|
||||||
IF (nPartOld > 0) THEN
|
IF (nPartOld > 0) THEN
|
||||||
WRITE(*, "(5X,A21,F8.1,A2)") "avg t/particle: ", 1.D9*(tPush+tReset+tColl+tWeight)/DBLE(nPartOld), "ns"
|
WRITE(*, "(5X,A21,F8.1,A2)") "avg t/particle: ", 1.D9*tStep/DBLE(nPartOld), "ns"
|
||||||
|
|
||||||
END IF
|
END IF
|
||||||
WRITE(*,*)
|
WRITE(*,*)
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,10 @@ MODULE moduleSpecies
|
||||||
REAL(8):: v(1:3) !Velocity
|
REAL(8):: v(1:3) !Velocity
|
||||||
INTEGER:: pt !Particle species id
|
INTEGER:: pt !Particle species id
|
||||||
INTEGER:: e_p !Index of element in which the particle is located
|
INTEGER:: e_p !Index of element in which the particle is located
|
||||||
REAL(8):: xLog(1:2) !Logical coordinates of particle in element e_p.
|
REAL(8):: xLog(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
|
REAL(8):: weight=0.D0 !weight of particle
|
||||||
|
REAL(8):: qm = 0.D0 !charge over mass
|
||||||
|
|
||||||
END TYPE particle
|
END TYPE particle
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue