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
|
|
@ -44,6 +44,9 @@ MODULE moduleInput
|
|||
CALL verboseError('Reading Geometry...')
|
||||
CALL readGeometry(config)
|
||||
|
||||
!Read boundary for EM field
|
||||
CALL readEMBoundary(config)
|
||||
|
||||
!Read injection of particles
|
||||
CALL verboseError('Reading Interactions between species...')
|
||||
CALL readInject(config)
|
||||
|
|
@ -63,7 +66,7 @@ MODULE moduleInput
|
|||
IMPLICIT NONE
|
||||
|
||||
TYPE(json_file), INTENT(inout):: config
|
||||
LOGICAL:: found
|
||||
LOGICAL:: found, found_r
|
||||
CHARACTER(:), ALLOCATABLE:: object
|
||||
|
||||
object = 'reference'
|
||||
|
|
@ -77,15 +80,25 @@ MODULE moduleInput
|
|||
CALL config%get(object // '.temperature', T_ref, found)
|
||||
IF (.NOT. found) CALL criticalError('Reference temperature not found','readReference')
|
||||
|
||||
CALL config%get(object // '.radius', r_ref, found)
|
||||
IF (.NOT. found) CALL criticalError('Reference radius not found','readReference')
|
||||
|
||||
CALL config%get(object // '.radius', r_ref, found_r)
|
||||
|
||||
!Derived parameters
|
||||
v_ref = DSQRT(kb*T_ref/m_ref) !reference velocity
|
||||
sigma_ref = PI*(r_ref+r_ref)**2 !reference cross section
|
||||
L_ref = 1.D0/(sigma_ref*n_ref) !mean free path
|
||||
!TODO: Make this solver dependent
|
||||
IF (found_r) THEN
|
||||
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
|
||||
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
|
||||
|
||||
|
|
@ -94,6 +107,7 @@ MODULE moduleInput
|
|||
USE moduleRefParam
|
||||
USE moduleErrors
|
||||
USE moduleCaseParam
|
||||
USE moduleSolver
|
||||
USE json_module
|
||||
IMPLICIT NONE
|
||||
|
||||
|
|
@ -101,6 +115,7 @@ MODULE moduleInput
|
|||
LOGICAL:: found
|
||||
CHARACTER(:), ALLOCATABLE:: object
|
||||
REAL(8):: time !simulation time in [t]
|
||||
CHARACTER(:), ALLOCATABLE:: solverType
|
||||
|
||||
object = 'case'
|
||||
!Time parameters
|
||||
|
|
@ -110,6 +125,21 @@ MODULE moduleInput
|
|||
CALL config%get(object // '.time', time, found)
|
||||
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
|
||||
tmax = INT(time/tau)
|
||||
|
||||
|
|
@ -149,6 +179,7 @@ MODULE moduleInput
|
|||
|
||||
CALL config%get(object // '.cpuTime', timeOutput, found)
|
||||
CALL config%get(object // '.numColl', collOutput, found)
|
||||
CALL config%get(object // '.EMField', emOutput, found)
|
||||
|
||||
END SUBROUTINE readOutput
|
||||
|
||||
|
|
@ -164,12 +195,12 @@ MODULE moduleInput
|
|||
CHARACTER(2):: iString
|
||||
CHARACTER(:), ALLOCATABLE:: object
|
||||
CHARACTER(:), ALLOCATABLE:: speciesType
|
||||
REAL(8):: mass
|
||||
REAL(8):: mass, charge
|
||||
LOGICAL:: found
|
||||
INTEGER:: i
|
||||
|
||||
!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
|
||||
IF (nSpecies == 0) CALL criticalError("No species found", "configRead")
|
||||
|
||||
|
|
@ -180,21 +211,28 @@ MODULE moduleInput
|
|||
WRITE(iString, '(I2)') i
|
||||
object = 'species(' // TRIM(iString) // ')'
|
||||
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)
|
||||
CASE ("neutral")
|
||||
ALLOCATE(species(i)%obj, source=speciesNeutral())
|
||||
!TODO: move to subroutine
|
||||
CALL config%get(object // '.name', species(i)%obj%name, found)
|
||||
CALL config%get(object // '.mass', mass, found)
|
||||
CALL config%get(object // '.weight', species(i)%obj%weight, found)
|
||||
species(i)%obj%pt = i
|
||||
species(i)%obj%m = mass/m_ref
|
||||
|
||||
CASE ("charged")
|
||||
CALL config%get(object // '.charge', charge, found)
|
||||
ALLOCATE(species(i)%obj, source=speciesCharged(q = charge, &
|
||||
qm = charge/mass))
|
||||
|
||||
CASE DEFAULT
|
||||
CALL warningError("Species " // speciesType // " not supported yet")
|
||||
|
||||
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
|
||||
|
||||
|
|
@ -217,29 +255,30 @@ MODULE moduleInput
|
|||
CHARACTER(:), ALLOCATABLE:: species_i, species_j
|
||||
CHARACTER(:), ALLOCATABLE:: crossSecFile
|
||||
CHARACTER(:), ALLOCATABLE:: crossSecFilePath
|
||||
LOGICAL:: found
|
||||
INTEGER:: nInteractions, nCollisions
|
||||
INTEGER:: i, k, ij
|
||||
INTEGER:: pt_i, pt_j
|
||||
|
||||
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
|
||||
WRITE(iString, '(I2)') i
|
||||
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)
|
||||
CALL config%get(object // '.species_j', species_j)
|
||||
CALL config%get(object // '.species_j', species_j, found)
|
||||
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)
|
||||
CALL interactionMatrix(ij)%init(nCollisions)
|
||||
|
||||
DO k = 1, nCollisions
|
||||
WRITE (kString, '(I2)') k
|
||||
CALL config%get(object // '.crossSections(' // TRIM(kString)// ')', crossSecFile)
|
||||
CALL config%get(object // '.crossSections(' // TRIM(kString)// ')', crossSecFile, found)
|
||||
crossSecFilePath = pathCollisions // crossSecFile
|
||||
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 SUBROUTINE readInteractions
|
||||
|
||||
!Reads boundary conditions for the mesh
|
||||
|
|
@ -263,7 +301,7 @@ MODULE moduleInput
|
|||
LOGICAL:: found
|
||||
INTEGER:: i
|
||||
|
||||
CALL config%info('boundary', n_children = nBoundary)
|
||||
CALL config%info('boundary', found, n_children = nBoundary)
|
||||
ALLOCATE(boundary(1:nBoundary))
|
||||
DO i = 1, nBoundary
|
||||
WRITE(istring, '(i2)') i
|
||||
|
|
@ -322,6 +360,85 @@ MODULE moduleInput
|
|||
|
||||
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
|
||||
SUBROUTINE readInject(config)
|
||||
USE moduleSpecies
|
||||
|
|
@ -340,10 +457,11 @@ MODULE moduleInput
|
|||
REAL(8):: v
|
||||
REAL(8), ALLOCATABLE:: T(:), normal(:)
|
||||
REAL(8):: flow
|
||||
CHARACTER(:), ALLOCATABLE:: units
|
||||
INTEGER:: physicalSurface
|
||||
INTEGER:: pt
|
||||
|
||||
CALL config%info('inject', n_children = nInject)
|
||||
CALL config%info('inject', found, n_children = nInject)
|
||||
ALLOCATE(inject(1:nInject))
|
||||
nPartInj = 0
|
||||
DO i = 1, nInject
|
||||
|
|
@ -359,11 +477,13 @@ MODULE moduleInput
|
|||
CALL config%get(object // '.T', T, found)
|
||||
CALL config%get(object // '.n', normal, found)
|
||||
CALL config%get(object // '.flow', flow, found)
|
||||
CALL config%get(object // '.units', units, 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
|
||||
PRINT *, inject(:)%nParticles
|
||||
|
||||
!Allocate array for injected particles
|
||||
IF (nPartInj > 0) THEN
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue