The program reads the case but stops while doind the simulation

This commit is contained in:
Jorge Gonzalez 2026-02-26 14:25:47 +01:00
commit 31f0b510bc
5 changed files with 224 additions and 215 deletions

View file

@ -287,9 +287,6 @@ MODULE moduleInput
END DO END DO
CASE DEFAULT
CALL criticalError('EM Solver ' // EMType // ' not found', 'readSolver')
END SELECT END SELECT
END IF END IF
@ -794,26 +791,117 @@ MODULE moduleInput
SUBROUTINE readBoundaryParticle(config) SUBROUTINE readBoundaryParticle(config)
use moduleMesh use moduleMesh
USE moduleErrors USE moduleErrors
use moduleSpecies, only: nSpecies
USE moduleList, ONLY: partSurfaces USE moduleList, ONLY: partSurfaces
use moduleRefParam, only: m_ref
use moduleConstParam, only: me
USE json_module USE json_module
IMPLICIT NONE IMPLICIT NONE
TYPE(json_file), INTENT(inout):: config TYPE(json_file), INTENT(inout):: config
integer:: b integer:: b
character(2):: iString character(2):: bString
character(:), allocatable:: object character(:), allocatable:: object
character(len=100), allocatable:: speciesNames(:)
LOGICAL:: found LOGICAL:: found
character(:), allocatable:: bType
real(8):: Tw, cw !Wall temperature and specific heat
!neutral Properties
real(8):: m0, n0, T0
real(8), dimension(:), allocatable:: v0
real(8):: effTime
real(8):: eThreshold !Energy threshold
integer:: speciesID, electronSecondaryID
character(:), allocatable:: speciesName, crossSection, electronSecondary
! Read models of particles ! Read models of particles
CALL config%info('boundaries.particles.models', found, n_children = nBoundariesParticle) object = 'boundaries.particles'
ALLOCATE(boundariesParticle(1:nBoundariesParticle)) CALL config%info(object, found, n_children = nBoundariesParticle)
allocate(boundariesParticle(1:nBoundariesParticle))
DO b = 1, nBoundariesParticle DO b = 1, nBoundariesParticle
WRITE(iString, '(i2)') b WRITE(bString, '(i2)') b
object = 'boundary.particles.models(' // TRIM(iString) // ')' object = 'boundaries.particles(' // trim(bString) // ')'
call boundariesParticle(b)%obj%init(config, object, b) CALL config%get(object // '.type', bType, found)
if (.not. found) then
call criticalError('Required parameter "type" for particle boundary condition not found', &
'initBoundaryParticle')
end if
associate(self => boundariesParticle(b)%obj)
SELECT CASE(bType)
CASE('reflection')
ALLOCATE(boundaryReflection:: self)
CASE('absorption')
ALLOCATE(boundaryAbsorption:: self)
CASE('transparent')
ALLOCATE(boundaryTransparent:: self)
CASE('axis')
ALLOCATE(boundaryAxis:: self)
CASE('wallTemperature')
CALL config%get(object // '.temperature', Tw, found)
IF (.NOT. found) CALL criticalError("temperature not found for wallTemperature boundary type", 'readBoundary')
CALL config%get(object // '.specificHeat', cw, found)
IF (.NOT. found) CALL criticalError("specificHeat not found for wallTemperature boundary type", 'readBoundary')
CALL initWallTemperature(self, Tw, cw)
CASE('ionization')
!Neutral parameters
CALL config%get(object // '.neutral.ion', speciesName, found)
IF (.NOT. found) CALL criticalError("missing parameter 'ion' for neutrals in ionization", 'readBoundary')
speciesID = speciesName2Index(speciesName)
CALL config%get(object // '.neutral.mass', m0, found)
IF (.NOT. found) CALL criticalError("missing parameter 'mass' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.neutral.density', n0, found)
IF (.NOT. found) CALL criticalError("missing parameter 'density' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.neutral.velocity', v0, found)
IF (.NOT. found) CALL criticalError("missing parameter 'velocity' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.neutral.temperature', T0, found)
IF (.NOT. found) CALL criticalError("missing parameter 'temperature' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.effectiveTime', effTime, found)
IF (.NOT. found) CALL criticalError("missing parameter 'effectiveTime' for ionization", 'readBoundary')
CALL config%get(object // '.energyThreshold', eThreshold, found)
IF (.NOT. found) CALL criticalError("missing parameter 'eThreshold' in ionization", 'readBoundary')
CALL config%get(object // '.crossSection', crossSection, found)
IF (.NOT. found) CALL criticalError("missing parameter 'crossSection' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.electronSecondary', electronSecondary, found)
electronSecondaryID = speciesName2Index(electronSecondary)
IF (found) THEN
CALL initIonization(self, me/m_ref, m0, n0, v0, T0, &
speciesID, effTime, crossSection, eThreshold,electronSecondaryID)
ELSE
CALL initIonization(self, me/m_ref, m0, n0, v0, T0, &
speciesID, effTime, crossSection, eThreshold)
END IF
case('quasiNeutrality')
call initQuasiNeutrality(self)
CASE DEFAULT
CALL criticalError('Boundary type ' // bType // ' undefined', 'readBoundary')
END SELECT
self%n = b
CALL config%get(object // '.name', self%name, found)
if (.not. found) then
call criticalError('Required parameter "name" for particle boundary condition not found', &
'initBoundaryParticle')
end if
end associate
END DO END DO
@ -827,7 +915,6 @@ MODULE moduleInput
USE moduleOutput USE moduleOutput
USE moduleErrors USE moduleErrors
USE moduleEM USE moduleEM
USE moduleSpecies, only: nSpecies
USE json_module USE json_module
IMPLICIT NONE IMPLICIT NONE
@ -836,9 +923,9 @@ MODULE moduleInput
LOGICAL:: found LOGICAL:: found
INTEGER:: b, s INTEGER:: b, s
CHARACTER(2):: bString CHARACTER(2):: bString
character(len=100), allocatable:: modelName(:) character(:), allocatable:: bType
CALL config%info('boundaries.EM.models', found, n_children = nBoundariesEM) CALL config%info('boundaries.EM', found, n_children = nBoundariesEM)
IF (found) THEN IF (found) THEN
ALLOCATE(boundariesEM(1:nBoundariesEM)) ALLOCATE(boundariesEM(1:nBoundariesEM))
@ -847,9 +934,45 @@ MODULE moduleInput
do b = 1, nBoundariesEM do b = 1, nBoundariesEM
write(bString, '(I2)') b write(bString, '(I2)') b
object = 'boundaries.EM.models(' // TRIM(bString) // ')' object = 'boundaries.EM(' // TRIM(bString) // ')'
call boundariesEM(b)%obj%init(config, object, b) associate(self => boundariesEM(b)%obj)
call config%get(object // '.type', bType, found)
if (.not. found) then
call criticalError('Required parameter "type" for EM boundary condition not found', &
'initBoundaryEM')
end if
select case(bType)
case ("dirichlet")
! Allocate boundary edge
allocate(boundaryEMDirichlet:: self)
CALL initDirichlet(self, config, object)
case ("dirichlettime")
! Allocate boundary edge
allocate(boundaryEMDirichletTime:: self)
call initDirichletTime(self, config, object)
case default
call criticalError('Boundary type ' // bType // ' not supported', 'readBoundaryEM')
end select
self%n = b
allocate(self%nodes(0))
call config%get(object // '.name', self%name, found)
if (.not. found) then
call criticalError('Required parameter "name" for EM boundary condition not found', &
'initBoundaryEM')
end if
end associate
end do end do
@ -1130,9 +1253,6 @@ MODULE moduleInput
END SELECT END SELECT
!Builds the K matrix for the Particles mesh
CALL mesh%constructGlobalK()
!Assign the procedure to find a cell for meshColl !Assign the procedure to find a cell for meshColl
IF (doubleMesh) THEN IF (doubleMesh) THEN
findCellColl => findCellCollMesh findCellColl => findCellCollMesh
@ -1189,21 +1309,39 @@ MODULE moduleInput
! EM Boundaries ! EM Boundaries
do b = 1, nBoundariesEM do b = 1, nBoundariesEM
select type(bound => boundariesEM(b)%obj) associate(bound => boundariesEM(b)%obj)
type is(boundaryEMDirichlet) select type(bound)
! Loop over all physical surfaces type is(boundaryEMDirichlet)
do ps = 1, nPhysicalSurfaces ! Loop over all physical surfaces
! If the boundary for the species is linked to the one analysing, add the edges do ps = 1, nPhysicalSurfaces
if (associated(physicalSurfaces(ps)%EM, bound)) then ! If the boundary for the species is linked to the one analysing, add the edges
bound%nodes = [bound%nodes, physicalSurfaces(ps)%nodes] if (associated(physicalSurfaces(ps)%EM, bound)) then
end if bound%nodes = [bound%nodes, physicalSurfaces(ps)%nodes]
end if
end do end do
end select type is(boundaryEMDirichletTime)
! Loop over all physical surfaces
do ps = 1, nPhysicalSurfaces
! If the boundary for the species is linked to the one analysing, add the edges
if (associated(physicalSurfaces(ps)%EM, bound)) then
bound%nodes = [bound%nodes, physicalSurfaces(ps)%nodes]
end if
end do
end select
bound%nNodes = size(bound%nodes)
end associate
end do end do
! Builds the K matrix for the Particles mesh
call mesh%constructGlobalK()
END SUBROUTINE readGeometry END SUBROUTINE readGeometry
SUBROUTINE readProbes(config) SUBROUTINE readProbes(config)

View file

@ -642,21 +642,33 @@ MODULE moduleMesh
integer:: n integer:: n
character(:), allocatable:: name character(:), allocatable:: name
contains contains
procedure, pass:: init => initBoundaryParticle
procedure(applyParticle_interface), deferred, pass:: apply procedure(applyParticle_interface), deferred, pass:: apply
end type boundaryParticleGeneric end type boundaryParticleGeneric
interface interface
module subroutine initBoundaryParticle(self, config, object, b) module subroutine initWallTemperature(boundary, T, c)
use json_module CLASS(boundaryParticleGeneric), ALLOCATABLE, INTENT(inout):: boundary
REAL(8), INTENT(in):: T, c !Wall temperature and specific heat
class(boundaryParticleGeneric), intent(out):: self end subroutine initWallTemperature
type(json_file), intent(inout):: config
character(:), allocatable, intent(in):: object
integer, intent(in):: b
end subroutine initBoundaryParticle module subroutine initIonization(boundary, mImpact, m0, n0, v0, T0, ion, effTime, crossSection, eThreshold, electronSecondary)
class(boundaryParticleGeneric), allocatable, intent(inout):: boundary
real(8), intent(in):: mImpact
real(8), intent(in):: m0, n0, v0(1:3), T0 !Neutral properties
integer, intent(in):: ion
real(8), intent(in):: effTime
character(:), allocatable, intent(in):: crossSection
real(8), intent(in):: eThreshold
integer, optional, intent(in):: electronSecondary
end subroutine initIonization
module subroutine initQuasiNeutrality(boundary)
class(boundaryParticleGeneric), allocatable, intent(inout):: boundary
end subroutine initQuasiNeutrality
module function boundaryParticleName_to_Index(boundaryName) result(bp) module function boundaryParticleName_to_Index(boundaryName) result(bp)
character(:), allocatable:: boundaryName character(:), allocatable:: boundaryName
@ -844,7 +856,7 @@ MODULE moduleMesh
!Number of boundaries !Number of boundaries
INTEGER:: nBoundariesParticle = 0 INTEGER:: nBoundariesParticle = 0
!Array for boundaries !Array for boundaries
TYPE(boundaryParticleCont), ALLOCATABLE, TARGET:: boundariesParticle(:) type(boundaryParticleCont), allocatable, target:: boundariesParticle(:)
! BOUNDARY ELECTROMAGNETIC DEFINITIONS ! BOUNDARY ELECTROMAGNETIC DEFINITIONS
! Generic type for electromagnetic boundary conditions ! Generic type for electromagnetic boundary conditions
@ -856,21 +868,28 @@ MODULE moduleMesh
procedure(updateEM_interface), pointer, pass:: update => null() procedure(updateEM_interface), pointer, pass:: update => null()
contains contains
procedure, pass:: init => initBoundaryEM
procedure(applyEM_interface), deferred, pass:: apply procedure(applyEM_interface), deferred, pass:: apply
end type boundaryEMGeneric end type boundaryEMGeneric
interface interface
module subroutine initBoundaryEM(self, config, object, b) module subroutine initDirichlet(self, config, object)
use json_module use json_module
class(boundaryEMGeneric), intent(out):: self class(boundaryEMGeneric), allocatable, intent(inout):: self
type(json_file), intent(inout):: config type(json_file), intent(inout):: config
character(:), allocatable, intent(in):: object character(:), allocatable, intent(in):: object
integer, intent(in):: b
end subroutine initBoundaryEM end subroutine initDirichlet
module subroutine initDirichletTime(self, config, object)
use json_module
class(boundaryEMGeneric), allocatable, intent(inout):: self
type(json_file), intent(inout):: config
character(:), allocatable, intent(in):: object
end subroutine initDirichletTime
module function boundaryEMName_to_Index(boundaryName) result(bp) module function boundaryEMName_to_Index(boundaryName) result(bp)
character(:), allocatable:: boundaryName character(:), allocatable:: boundaryName

View file

@ -24,54 +24,6 @@ submodule(moduleMesh) boundaryEM
end function boundaryEMName_to_Index end function boundaryEMName_to_Index
module subroutine initBoundaryEM(self, config, object, b)
use json_module
use moduleErrors
implicit none
class(boundaryEMGeneric), allocatable, intent(out):: self
type(json_file), intent(inout):: config
character(:), allocatable, intent(in):: object
integer, intent(in):: b
character(:), allocatable:: bType
logical:: found
self%n = b
allocate(self%nodes(0))
call config%get(object // '.name', self%name, found)
if (.not. found) then
call criticalError('Required parameter "name" for EM boundary condition not found', &
'initBoundaryEM')
end if
call config%get(object // '.type', bType, found)
if (.not. found) then
call criticalError('Required parameter "type" for EM boundary condition not found', &
'initBoundaryEM')
end if
select case(bType)
case ("dirichlet")
! Allocate boundary edge
ALLOCATE(boundaryEMDirichlet:: self)
CALL initDirichlet(self, config, object)
case ("dirichlettime")
! Allocate boundary edge
ALLOCATE(boundaryEMDirichletTime:: self)
call initDirichletTime(self, config, object)
case default
call criticalError('Boundary type ' // bType // ' not supported', 'readBoundaryEM')
end select
end subroutine initBoundaryEM
! Initialize Dirichlet boundary condition ! Initialize Dirichlet boundary condition
module SUBROUTINE initDirichlet(self, config, object) module SUBROUTINE initDirichlet(self, config, object)
use json_module use json_module
@ -79,7 +31,7 @@ submodule(moduleMesh) boundaryEM
use moduleErrors use moduleErrors
IMPLICIT NONE IMPLICIT NONE
CLASS(boundaryEMGeneric), ALLOCATABLE, INTENT(out):: self CLASS(boundaryEMGeneric), ALLOCATABLE, INTENT(inout):: self
type(json_file), intent(inout):: config type(json_file), intent(inout):: config
character(:), allocatable, intent(in):: object character(:), allocatable, intent(in):: object
REAL(8):: potential REAL(8):: potential
@ -106,7 +58,7 @@ submodule(moduleMesh) boundaryEM
use moduleErrors use moduleErrors
implicit none implicit none
class(boundaryEMGeneric), allocatable, intent(out):: self class(boundaryEMGeneric), allocatable, intent(inout):: self
type(json_file), intent(inout):: config type(json_file), intent(inout):: config
character(:), allocatable, intent(in):: object character(:), allocatable, intent(in):: object
real(8):: potential real(8):: potential

View file

@ -25,115 +25,11 @@ submodule(moduleMesh) boundaryParticle
end function boundaryParticleName_to_Index end function boundaryParticleName_to_Index
module subroutine initBoundaryParticle(self, config, object, b) module SUBROUTINE initWallTemperature(boundary, T, c)
use json_module
use moduleRefParam, only: m_ref
use moduleConstParam, only: me
use moduleErrors, only: criticalError
implicit none
class(boundaryParticleGeneric), allocatable, intent(out):: self
type(json_file), intent(inout):: config
character(:), allocatable, intent(in):: object
integer, intent(in):: b
character(:), allocatable:: bType
logical:: found
real(8):: Tw, cw !Wall temperature and specific heat
!neutral Properties
real(8):: m0, n0, T0
real(8), dimension(:), allocatable:: v0
real(8):: effTime
real(8):: eThreshold !Energy threshold
integer:: speciesID, electronSecondaryID
character(:), allocatable:: speciesName, crossSection, electronSecondary
self%n = b
CALL config%get(object // '.name', self%name, found)
if (.not. found) then
call criticalError('Required parameter "name" for EM boundary condition not found', &
'initBoundaryParticle')
end if
CALL config%get(object // '.type', bType, found)
if (.not. found) then
call criticalError('Required parameter "type" for EM boundary condition not found', &
'initBoundaryParticle')
end if
SELECT CASE(bType)
CASE('reflection')
ALLOCATE(boundaryReflection:: self)
CASE('absorption')
ALLOCATE(boundaryAbsorption:: self)
CASE('transparent')
ALLOCATE(boundaryTransparent:: self)
CASE('axis')
ALLOCATE(boundaryAxis:: self)
CASE('wallTemperature')
CALL config%get(object // '.temperature', Tw, found)
IF (.NOT. found) CALL criticalError("temperature not found for wallTemperature boundary type", 'readBoundary')
CALL config%get(object // '.specificHeat', cw, found)
IF (.NOT. found) CALL criticalError("specificHeat not found for wallTemperature boundary type", 'readBoundary')
CALL initWallTemperature(self, Tw, cw)
CASE('ionization')
!Neutral parameters
CALL config%get(object // '.neutral.ion', speciesName, found)
IF (.NOT. found) CALL criticalError("missing parameter 'ion' for neutrals in ionization", 'readBoundary')
speciesID = speciesName2Index(speciesName)
CALL config%get(object // '.neutral.mass', m0, found)
IF (.NOT. found) CALL criticalError("missing parameter 'mass' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.neutral.density', n0, found)
IF (.NOT. found) CALL criticalError("missing parameter 'density' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.neutral.velocity', v0, found)
IF (.NOT. found) CALL criticalError("missing parameter 'velocity' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.neutral.temperature', T0, found)
IF (.NOT. found) CALL criticalError("missing parameter 'temperature' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.effectiveTime', effTime, found)
IF (.NOT. found) CALL criticalError("missing parameter 'effectiveTime' for ionization", 'readBoundary')
CALL config%get(object // '.energyThreshold', eThreshold, found)
IF (.NOT. found) CALL criticalError("missing parameter 'eThreshold' in ionization", 'readBoundary')
CALL config%get(object // '.crossSection', crossSection, found)
IF (.NOT. found) CALL criticalError("missing parameter 'crossSection' for neutrals in ionization", 'readBoundary')
CALL config%get(object // '.electronSecondary', electronSecondary, found)
electronSecondaryID = speciesName2Index(electronSecondary)
IF (found) THEN
CALL initIonization(self, me/m_ref, m0, n0, v0, T0, &
speciesID, effTime, crossSection, eThreshold,electronSecondaryID)
ELSE
CALL initIonization(self, me/m_ref, m0, n0, v0, T0, &
speciesID, effTime, crossSection, eThreshold)
END IF
case('quasiNeutrality')
call initQuasiNeutrality(self)
CASE DEFAULT
CALL criticalError('Boundary type ' // bType // ' undefined', 'readBoundary')
END SELECT
end subroutine initBoundaryParticle
SUBROUTINE initWallTemperature(boundary, T, c)
USE moduleRefParam USE moduleRefParam
IMPLICIT NONE IMPLICIT NONE
CLASS(boundaryParticleGeneric), ALLOCATABLE, INTENT(out):: boundary CLASS(boundaryParticleGeneric), ALLOCATABLE, INTENT(inout):: boundary
REAL(8), INTENT(in):: T, c !Wall temperature and specific heat REAL(8), INTENT(in):: T, c !Wall temperature and specific heat
REAL(8):: vTh REAL(8):: vTh
@ -148,22 +44,22 @@ submodule(moduleMesh) boundaryParticle
END SUBROUTINE initWallTemperature END SUBROUTINE initWallTemperature
SUBROUTINE initIonization(boundary, mImpact, m0, n0, v0, T0, ion, effTime, crossSection, eThreshold, electronSecondary) module SUBROUTINE initIonization(boundary, mImpact, m0, n0, v0, T0, ion, effTime, crossSection, eThreshold, electronSecondary)
USE moduleRefParam use moduleRefParam
USE moduleSpecies use moduleSpecies
USE moduleCaseParam use moduleCaseParam
USE moduleConstParam use moduleConstParam
USE moduleErrors, only: criticalError use moduleErrors, only: criticalError
IMPLICIT NONE implicit none
CLASS(boundaryParticleGeneric), ALLOCATABLE, INTENT(out):: boundary class(boundaryParticleGeneric), allocatable, intent(inout):: boundary
real(8), intent(in):: mImpact real(8), intent(in):: mImpact
REAL(8), INTENT(in):: m0, n0, v0(1:3), T0 !Neutral properties real(8), intent(in):: m0, n0, v0(1:3), T0 !Neutral properties
INTEGER, INTENT(in):: ion integer, intent(in):: ion
INTEGER, OPTIONAL, INTENT(in):: electronSecondary real(8), intent(in):: effTime
REAL(8):: effTime character(:), allocatable, intent(in):: crossSection
CHARACTER(:), ALLOCATABLE, INTENT(in):: crossSection real(8), intent(in):: eThreshold
REAL(8), INTENT(in):: eThreshold integer, optional, intent(in):: electronSecondary
ALLOCATE(boundaryIonization:: boundary) ALLOCATE(boundaryIonization:: boundary)
@ -199,10 +95,10 @@ submodule(moduleMesh) boundaryParticle
END SUBROUTINE initIonization END SUBROUTINE initIonization
subroutine initQuasiNeutrality(boundary) module subroutine initQuasiNeutrality(boundary)
implicit none implicit none
class(boundaryParticleGeneric), allocatable, intent(out):: boundary class(boundaryParticleGeneric), allocatable, intent(inout):: boundary
integer:: e, et integer:: e, et
allocate(boundaryQuasiNeutrality:: boundary) allocate(boundaryQuasiNeutrality:: boundary)

View file

@ -129,6 +129,7 @@ MODULE moduleSolver
SUBROUTINE initEM(self, EMType) SUBROUTINE initEM(self, EMType)
USE moduleEM USE moduleEM
USE moduleErrors, only: criticalError
IMPLICIT NONE IMPLICIT NONE
CLASS(solverGeneric), INTENT(inout):: self CLASS(solverGeneric), INTENT(inout):: self
@ -141,6 +142,9 @@ MODULE moduleSolver
CASE('ElectrostaticBoltzmann') CASE('ElectrostaticBoltzmann')
self%solveEM => solveElecFieldBoltzmann self%solveEM => solveElecFieldBoltzmann
CASE DEFAULT
CALL criticalError('EM Solver ' // EMType // ' not found', 'readSolver')
END SELECT END SELECT
END SUBROUTINE initEM END SUBROUTINE initEM