First commit of code.

New functionality:
- DSMC module:
  - 2D cyl geometry
    - GMSH file format
    - Elastic cross-section for Argon-Argon collisions.
    - Basic boundary conditions: reflection, absorption and axis
      symmetry.

Bugs fixed:

Other comments:
- Still searching for name.
This commit is contained in:
Jorge Gonzalez 2020-10-09 08:45:07 +02:00
commit bd7e8b040b
29 changed files with 4069 additions and 0 deletions

366
src/modules/moduleInput.f95 Normal file
View file

@ -0,0 +1,366 @@
! moduleInput: Reads JSON configuration file
MODULE moduleInput
USE json_module
IMPLICIT NONE
CONTAINS
!Main routine to read the input JSON file
SUBROUTINE readConfig(inputFile)
USE json_module
USE moduleErrors
USE moduleBoundary
USE moduleInject
IMPLICIT NONE
CHARACTER(:), ALLOCATABLE, INTENT(in):: inputFile
TYPE(json_file):: config
!Initialize the json file variable
CALL config%initialize()
!Loads the config file
CALL config%load(filename = inputFile)
!Reads reference parameters
CALL readReference(config)
!Reads case parameters
CALL readCase(config)
!Reads output parameters
CALL readOutput(config)
!Read species
CALL readSpecies(config)
!Read interactions between species
CALL readInteractions(config)
!Read boundaries
CALL readBoundary(config)
!Read Geometry
CALL readGeometry(config)
!Read injection of particles
CALL readInject(config)
END SUBROUTINE readConfig
!Reads the reference parameters
SUBROUTINE readReference(config)
USE moduleRefParam
USE moduleConstParam
USE moduleErrors
USE json_module
IMPLICIT NONE
TYPE(json_file), INTENT(inout):: config
LOGICAL:: found
CHARACTER(:), ALLOCATABLE:: object
object = 'reference'
!Mandatory parameters that define the case and computes derived parameters
CALL config%get(object // '.density', n_ref, found)
IF (.NOT. found) CALL criticalError('Reference density not found','readReference')
CALL config%get(object // '.mass', m_ref, found)
IF (.NOT. found) CALL criticalError('Reference mass not found','readReference')
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')
!Derived parameters
sigma_ref = PI*(r_ref+r_ref)**2 !reference cross section
L_ref = 1.D0/(sigma_ref*n_ref) !mean free path
ti_ref = L_ref/v_ref !reference time
Vol_ref = L_ref**3 !reference volume
v_ref = DSQRT(kb*T_ref/m_ref) !reference velocity
END SUBROUTINE readReference
!Reads the specific case parameters
SUBROUTINE readCase(config)
USE moduleRefParam
USE moduleErrors
USE moduleCaseParam
USE json_module
IMPLICIT NONE
TYPE(json_file), INTENT(inout):: config
LOGICAL:: found
CHARACTER(:), ALLOCATABLE:: object
REAL(8):: time !simulation time in [t]
object = 'case'
!Time parameters
CALL config%get(object // '.tau', tau, found)
IF (.NOT. found) CALL criticalError('Required parameter tau not found','readCase')
CALL config%get(object // '.time', time, found)
IF (.NOT. found) CALL criticalError('Required parameter time not found','readCase')
!Convert simulation time to number of iterations
tmax = INT(time/(ti_ref*tau))
END SUBROUTINE readCase
!Reads configuration for the output files
SUBROUTINE readOutput(config)
USE moduleErrors
USE moduleOutput
USE json_module
IMPLICIT NONE
TYPE(json_file), INTENT(inout):: config
LOGICAL:: found
CHARACTER(:), ALLOCATABLE:: object
CHARACTER(8) :: date_now=''
CHARACTER(10) :: time_now=''
object = 'output'
CALL config%get(object // '.path', path, found)
CALL config%get(object // '.trigger', triggerOutput, found)
IF (.NOT. found) THEN
triggerOutput = 100
CALL warningError('Using default trigger for output file of 100 iterations')
END IF
!Creates output folder
!TODO: Add option for custon name output_folder
CALL DATE_AND_TIME(date_now, time_now)
folder = date_now(1:4) // '-' // date_now(5:6) // '-' // date_now(7:8) // '_' &
// time_now(1:2) // '.' // time_now(3:4) // '.' // time_now(5:6)
CALL SYSTEM('mkdir ' // path // folder )
CALL config%get(object // '.cpuTime', timeOutput, found)
CALL config%get(object // '.numColl', collOutput, found)
END SUBROUTINE readOutput
!Reads information about the case species
SUBROUTINE readSpecies(config)
USE moduleSpecies
USE moduleErrors
USE moduleRefParam
USE json_module
IMPLICIT NONE
TYPE(json_file), INTENT(inout):: config
CHARACTER(2):: iString
CHARACTER(:), ALLOCATABLE:: object
CHARACTER(:), ALLOCATABLE:: speciesType
REAL(8):: mass
LOGICAL:: found
INTEGER:: i
!Gets the number of species
CALL config%info('species', n_children = nSpecies)
!Zero species means critical error
IF (nSpecies == 0) CALL criticalError("No species found", "configRead")
ALLOCATE(species(1:nSpecies))
!Reads information of individual species
DO i = 1, nSpecies
WRITE(iString, '(I2)') i
object = 'species(' // TRIM(iString) // ')'
CALL config%get(object // '.type', speciesType, found)
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 DEFAULT
CALL warningError("Species " // speciesType // " not supported yet")
END SELECT
END DO
!Set number of particles to 0 for init state
!TODO: In a future, this should include the particles from init states
n_part_old = 0
END SUBROUTINE readSpecies
!Reads information about interactions between species
SUBROUTINE readInteractions(config)
USE moduleSpecies
USE moduleCollisions
USE json_module
IMPLICIT NONE
TYPE(json_file), INTENT(inout):: config
CHARACTER(2):: iString, kString
CHARACTER(:), ALLOCATABLE:: object
CHARACTER(:), ALLOCATABLE:: species_i, species_j
CHARACTER(:), ALLOCATABLE:: crossSecFile
CHARACTER(:), ALLOCATABLE:: crossSecFilePath
INTEGER:: nInteractions, nCollisions
INTEGER:: i, k, ij
INTEGER:: pt_i, pt_j
CALL initInteractionMatrix(interactionMatrix)
CALL config%get('interactions.folderCollisions', pathCollisions)
CALL config%info('interactions.collisions', n_children = nInteractions)
DO i = 1, nInteractions
WRITE(iString, '(I2)') i
object = 'interactions.collisions(' // TRIM(iString) // ')'
CALL config%get(object // '.species_i', species_i)
pt_i = speciesName2Index(species_i)
CALL config%get(object // '.species_j', species_j)
pt_j = speciesName2Index(species_j)
CALL config%info(object // '.crossSections', 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)
crossSecFilePath = pathCollisions // crossSecFile
CALL interactionMatrix(ij)%collisions(k)%obj%init(crossSecFilePath)
END DO
END DO
END SUBROUTINE readInteractions
!Reads boundary conditions for the mesh
SUBROUTINE readBoundary(config)
USE moduleBoundary
USE moduleErrors
USE json_module
IMPLICIT NONE
TYPE(json_file), INTENT(inout):: config
CHARACTER(2):: istring
CHARACTER(:), ALLOCATABLE:: object
LOGICAL:: found
INTEGER:: i
CALL config%info('boundary', n_children = nBoundary)
ALLOCATE(boundary(1:nBoundary))
DO i = 1, nBoundary
WRITE(istring, '(i2)') i
object = 'boundary(' // trim(istring) // ')'
ALLOCATE(boundaryGeneric:: boundary(i)%obj)
CALL config%get(object // '.type', boundary(i)%obj%boundaryType, found)
CALL config%get(object // '.physicalSurface', boundary(i)%obj%physicalSurface, found)
boundary(i)%obj%id = i
END DO
END SUBROUTINE readBoundary
!Read the geometry (mesh) for the case
SUBROUTINE readGeometry(config)
USE moduleMesh
USE moduleMeshCylRead
USE moduleErrors
USE moduleOutput
USE json_module
IMPLICIT NONE
TYPE(json_file), INTENT(inout):: config
LOGICAL:: found
CHARACTER(:), ALLOCATABLE:: geometryType, meshType, meshFile
CHARACTER(:), ALLOCATABLE:: fullPath
!Selects the type of geometry.
CALL config%get('geometry.type', geometryType, found)
SELECT CASE(geometryType)
CASE ("2DCyl")
!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 DEFAULT
CALL criticalError("Geometry type " // geometryType // " not supported.", "readGeometry")
END SELECT
END SUBROUTINE readGeometry
!Reads the injection of particles from the boundaries
SUBROUTINE readInject(config)
USE moduleSpecies
USE moduleErrors
USE moduleInject
USE json_module
IMPLICIT NONE
TYPE(json_file), INTENT(inout):: config
INTEGER:: i
character(2):: istring
character(:), allocatable:: object
logical:: found
CHARACTER(:), ALLOCATABLE:: speciesName
CHARACTER(:), ALLOCATABLE:: name
REAL(8):: v
REAL(8), ALLOCATABLE:: T(:), normal(:)
REAL(8):: flow
INTEGER:: physicalSurface
INTEGER:: pt
CALL config%info('inject', n_children = nInject)
ALLOCATE(inject(1:nInject))
nPartInj = 0
DO i = 1, nInject
WRITE(istring, '(i2)') i
object = 'inject(' // trim(istring) // ')'
!Find species
CALL config%get(object // '.species', speciesName, found)
pt = speciesName2Index(speciesName)
CALL config%get(object // '.name', name, found)
CALL config%get(object // '.v', v, found)
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 // '.physicalSurface', physicalSurface, found)
CALL inject(i)%init(i, v, normal, T, flow, pt, physicalSurface)
END DO
!Allocate array for injected particles
IF (nPartInj > 0) THEN
ALLOCATE(part_inj(1:nPartInj))
END IF
END SUBROUTINE readInject
END MODULE moduleInput