Skeleton of boundaries for EM with new structure for mesh

This commit is contained in:
Jorge Gonzalez 2026-02-17 14:54:22 +01:00
commit 6a7c92f62f
5 changed files with 269 additions and 224 deletions

View file

@ -22,6 +22,7 @@ moduleMesh.o: moduleMeshCommon.o moduleMesh.f90
$(FC) $(FCFLAGS) -c $(subst .o,.f90,$@) -o $(OBJDIR)/$@
$(FC) $(FCFLAGS) -c moduleMesh@elements.f90 -o $(OBJDIR)/$@
$(FC) $(FCFLAGS) -c moduleMesh@boundaryParticle.f90 -o $(OBJDIR)/$@
$(FC) $(FCFLAGS) -c moduleMesh@boundaryEM.f90 -o $(OBJDIR)/$@
inout.o: 3DCart.o 2DCyl.o 2DCart.o 1DRad.o 1DCart.o 0D.o
$(MAKE) -C inout all

View file

@ -6,7 +6,7 @@ MODULE moduleMesh
use moduleSpecies, only: nSpecies
IMPLICIT NONE
! Declarations for elements
! MESH ELEMENTS
!Generic mesh element
TYPE, PUBLIC, ABSTRACT:: meshElement
!Index
@ -88,7 +88,8 @@ MODULE moduleMesh
! Surface of edge
REAL(8):: surface = 0.D0
!Pointer to boundary per species
TYPE(boundaryPointer), allocatable:: boundariesParticle(:)
TYPE(boundaryParticlePointer), allocatable:: boundariesParticle(:)
class(boundaryEMGeneric), pointer:: boundaryEM => null()
!Physical surface for the edge
CONTAINS
!DEFERED PROCEDURES
@ -584,36 +585,36 @@ MODULE moduleMesh
!Complete path for the two meshes
CHARACTER(:), ALLOCATABLE:: pathMeshColl, pathMeshParticle
! Boundary Particle Definitions
! BOUNDARY PARTICLE DEFINITIONS
!Generic type for boundaries
TYPE, abstract, PUBLIC:: boundaryGeneric
type, abstract, public:: boundaryParticleGeneric
integer:: n
character(:), allocatable:: name
contains
procedure, pass:: init => initBoundary
procedure(boundary_interface), deferred, pass:: apply
procedure, pass:: init => initBoundaryParticle
procedure(applyParticle_interface), deferred, pass:: apply
END TYPE boundaryGeneric
end type boundaryParticleGeneric
interface
module subroutine initBoundary(self, config, object, b)
module subroutine initBoundaryParticle(self, config, object, b)
use json_module
class(boundaryGeneric), intent(out):: self
class(boundaryParticleGeneric), intent(out):: self
type(json_file), intent(inout):: config
character(:), allocatable, intent(in):: object
integer, intent(in):: b
end subroutine initBoundary
end subroutine initBoundaryParticle
end interface
abstract interface
subroutine boundary_interface(self, edge, part)
subroutine applyParticle_interface(self, edge, part)
use moduleSpecies
import boundaryGeneric, meshEdge
import boundaryParticleGeneric, meshEdge
class(boundaryGeneric), intent(in):: self
class(boundaryParticleGeneric), intent(in):: self
class(meshEdge), intent(inout):: edge
class(particle), intent(inout):: part
@ -622,35 +623,35 @@ MODULE moduleMesh
end interface
!Reflecting boundary
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryReflection
TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryReflection
CONTAINS
procedure, pass:: apply => reflection
END TYPE boundaryReflection
!Absorption boundary
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAbsorption
TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryAbsorption
CONTAINS
procedure, pass:: apply => absorption
END TYPE boundaryAbsorption
!Transparent boundary
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryTransparent
TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryTransparent
CONTAINS
procedure, pass:: apply => transparent
END TYPE boundaryTransparent
!Symmetry axis
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAxis
TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryAxis
CONTAINS
procedure, pass:: apply => axis
END TYPE boundaryAxis
!Wall Temperature boundary
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryWallTemperature
TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryWallTemperature
!Thermal velocity of the wall: square root(Wall temperature X specific heat)
REAL(8):: vTh
CONTAINS
@ -659,7 +660,7 @@ MODULE moduleMesh
END TYPE boundaryWallTemperature
!Ionization boundary
TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryIonization
TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryIonization
REAL(8):: m0, n0, v0(1:3), vTh !Properties of background neutrals.
CLASS(speciesGeneric), POINTER:: species !Ion species
CLASS(speciesCharged), POINTER:: electronSecondary !Pointer to species considerer as secondary electron
@ -673,7 +674,7 @@ MODULE moduleMesh
END TYPE boundaryIonization
! Ensures quasi-neutrality by changing the reflection coefficient
type, public, extends(boundaryGeneric):: boundaryQuasiNeutrality
type, public, extends(boundaryParticleGeneric):: boundaryQuasiNeutrality
real(8):: alpha ! Reflection parameter
integer, allocatable:: edges(:) !Array with edges
contains
@ -773,17 +774,17 @@ MODULE moduleMesh
end interface
TYPE:: boundaryCont
CLASS(boundaryGeneric), ALLOCATABLE:: obj
TYPE:: boundaryParticleCont
CLASS(boundaryParticleGeneric), ALLOCATABLE:: obj
CONTAINS
END TYPE boundaryCont
END TYPE boundaryParticleCont
type:: boundaryPointer
class(boundaryGeneric), pointer:: obj
type:: boundaryParticlePointer
class(boundaryParticleGeneric), pointer:: obj
contains
end type boundaryPointer
end type boundaryParticlePointer
type boundaryParticleLinking
integer:: physicalSurface
@ -794,7 +795,7 @@ MODULE moduleMesh
!Number of boundaries
INTEGER:: nBoundaries = 0, nPhysicalSurfaces = 0
!Array for boundaries
TYPE(boundaryCont), ALLOCATABLE, TARGET:: boundariesParticle(:)
TYPE(boundaryParticleCont), ALLOCATABLE, TARGET:: boundariesParticle(:)
!Array for linking boundaries
type(boundaryParticleLinking), allocatable, dimension(:):: boundariesParticleLinking
@ -807,4 +808,96 @@ MODULE moduleMesh
end interface
! BOUNDARY ELECTROMAGNETIC DEFINITIONS
! Generic type for electromagnetic boundary conditions
type, public, abstract:: boundaryEMGeneric
integer:: nNodes
type(meshNodePointer), allocatable:: nodes(:)
procedure(updateEM_interface), pointer, pass:: update => null()
contains
procedure, pass:: init => initBoundaryEM
procedure(applyEM_interface), deferred, pass:: apply
end type boundaryEMGeneric
interface
module subroutine initBoundaryEM(self, config, object, b)
use json_module
class(boundaryEMGeneric), intent(out):: self
type(json_file), intent(inout):: config
character(:), allocatable, intent(in):: object
integer, intent(in):: b
end subroutine initBoundaryEM
end interface
abstract interface
! Apply boundary condition to the load vector for the Poission equation
subroutine applyEM_interface(self, vectorF)
import boundaryEMGeneric
class(boundaryEMGeneric), intent(in):: self
real(8), intent(inout):: vectorF(:)
end subroutine applyEM_interface
! Update the values of the boundary condition
subroutine updateEM_interface(self)
import boundaryEMGeneric
class(boundaryEMGeneric), intent(in):: self
end subroutine updateEM_interface
end interface
TYPE, EXTENDS(boundaryEMGeneric):: boundaryEMDirichlet
REAL(8):: potential
CONTAINS
! boundaryEMGeneric DEFERRED PROCEDURES
PROCEDURE, PASS:: apply => applyDirichlet
END TYPE boundaryEMDirichlet
TYPE, EXTENDS(boundaryEMGeneric):: boundaryEMDirichletTime
real(8):: potential
type(table1D):: temporalProfile
contains
! boundaryEMGeneric DEFERRED PROCEDURES
procedure, pass:: apply => applyDirichletTime
END TYPE boundaryEMDirichletTime
interface
module subroutine applyDirichlet(self, vectorF)
class(boundaryEMDirichlet), intent(in):: self
real(8), intent(inout):: vectorF(:)
end subroutine applyDirichlet
module subroutine applyDirichletTime(self, vectorF)
class(boundaryEMDirichletTime), intent(in):: self
real(8), intent(inout):: vectorF(:)
end subroutine applyDirichletTime
end interface
! Container for boundary conditions
TYPE:: boundaryEMCont
CLASS(boundaryEMGeneric), ALLOCATABLE:: obj
END TYPE boundaryEMCont
INTEGER:: nBoundaryEM
TYPE(boundaryEMCont), ALLOCATABLE:: boundaryEM(:)
!Information of charge and reference parameters for rho vector
REAL(8), ALLOCATABLE:: qSpecies(:)
END MODULE moduleMesh

View file

@ -0,0 +1,141 @@
submodule(moduleMesh) boundaryEM
CONTAINS
SUBROUTINE findNodes(self, physicalSurface)
USE moduleMesh
IMPLICIT NONE
CLASS(boundaryEMGeneric), INTENT(inout):: self
INTEGER, INTENT(in):: physicalSurface
CLASS(meshEdge), POINTER:: edge
INTEGER, ALLOCATABLE:: nodes(:), nodesEdge(:)
INTEGER:: nNodes, nodesNew
INTEGER:: e, n
!Temporal array to hold nodes
ALLOCATE(nodes(0))
! Loop thorugh the edges and identify those that are part of the boundary
DO e = 1, mesh%numEdges
edge => mesh%edges(e)%obj
IF (edge%physicalSurface == physicalSurface) THEN
! Edge is of the right boundary index
! Get nodes in the edge
nNodes = edge%nNodes
nodesEdge = edge%getNodes(nNodes)
! Collect all nodes that are not already in the temporal array
DO n = 1, nNodes
IF (ANY(nodes == nodesEdge(n))) THEN
! Node already in array, skip
CYCLE
ELSE
! If not, add element to array of nodes
nodes = [nodes, nodesEdge(n)]
END IF
END DO
END IF
END DO
! Point boundary to nodes
nNodes = SIZE(nodes)
ALLOCATE(self%nodes(nNodes))
self%nNodes = nNodes
DO n = 1, nNodes
self%nodes(n)%obj => mesh%nodes(nodes(n))%obj
END DO
END SUBROUTINE findNodes
! Initialize Dirichlet boundary condition
SUBROUTINE initDirichlet(self, physicalSurface, potential)
USE moduleRefParam, ONLY: Volt_ref
IMPLICIT NONE
CLASS(boundaryEMGeneric), ALLOCATABLE, INTENT(out):: self
INTEGER, INTENT(in):: physicalSurface
REAL(8), INTENT(in):: potential
! Allocate boundary edge
ALLOCATE(boundaryEMDirichlet:: self)
SELECT TYPE(self)
TYPE IS(boundaryEMDirichlet)
self%potential = potential / Volt_ref
CALL findNodes(self, physicalSurface)
END SELECT
END SUBROUTINE initDirichlet
! Initialize Dirichlet boundary condition
SUBROUTINE initDirichletTime(self, physicalSurface, potential, temporalProfile)
USE moduleRefParam, ONLY: Volt_ref, ti_ref
IMPLICIT NONE
CLASS(boundaryEMGeneric), ALLOCATABLE, INTENT(out):: self
INTEGER, INTENT(in):: physicalSurface
REAL(8), INTENT(in):: potential
CHARACTER(:), ALLOCATABLE, INTENT(in):: temporalProfile
! Allocate boundary edge
ALLOCATE(boundaryEMDirichletTime:: self)
SELECT TYPE(self)
TYPE IS(boundaryEMDirichletTime)
self%potential = potential / Volt_ref
CALL findNodes(self, physicalSurface)
CALL self%temporalProfile%init(temporalProfile)
CALL self%temporalProfile%convert(1.D0/ti_ref, 1.D0)
END SELECT
END SUBROUTINE initDirichletTime
!Apply Dirichlet boundary condition to the poisson equation
SUBROUTINE applyDirichlet(self, vectorF)
USE moduleMesh
IMPLICIT NONE
CLASS(boundaryEMDirichlet), INTENT(in):: self
REAL(8), INTENT(inout):: vectorF(:)
INTEGER:: n, ni
DO n = 1, self%nNodes
self%nodes(n)%obj%emData%phi = self%potential
vectorF(self%nodes(n)%obj%n) = self%nodes(n)%obj%emData%phi
END DO
END SUBROUTINE applyDirichlet
!Apply Dirichlet boundary condition with time temporal profile
SUBROUTINE applyDirichletTime(self, vectorF)
USE moduleMesh
USE moduleCaseParam, ONLY: timeStep, tauMin
IMPLICIT NONE
CLASS(boundaryEMDirichletTime), INTENT(in):: self
REAL(8), INTENT(inout):: vectorF(:)
REAL(8):: timeFactor
INTEGER:: n, ni
timeFactor = self%temporalProfile%get(DBLE(timeStep)*tauMin)
DO n = 1, self%nNodes
self%nodes(n)%obj%emData%phi = self%potential * timeFactor
vectorF(self%nodes(n)%obj%n) = self%nodes(n)%obj%emData%phi
END DO
END SUBROUTINE applyDirichletTime
end submodule boundaryEM

View file

@ -25,13 +25,13 @@ submodule(moduleMesh) boundaryParticle
end function boundaryParticleName_to_Index
module subroutine initBoundary(self, config, object, b)
module subroutine initBoundaryParticle(self, config, object, b)
use json_module
use moduleRefParam, only: m_ref
use moduleConstParam, only: me
implicit none
class(boundaryGeneric), allocatable, intent(out):: self
class(boundaryParticleGeneric), allocatable, intent(out):: self
type(json_file), intent(inout):: config
character(:), allocatable, intent(in):: object
integer, intent(in):: b
@ -114,13 +114,13 @@ submodule(moduleMesh) boundaryParticle
END SELECT
end subroutine initBoundary
end subroutine initBoundaryParticle
SUBROUTINE initWallTemperature(boundary, T, c)
USE moduleRefParam
IMPLICIT NONE
CLASS(boundaryGeneric), ALLOCATABLE, INTENT(out):: boundary
CLASS(boundaryParticleGeneric), ALLOCATABLE, INTENT(out):: boundary
REAL(8), INTENT(in):: T, c !Wall temperature and specific heat
REAL(8):: vTh
@ -143,7 +143,7 @@ submodule(moduleMesh) boundaryParticle
USE moduleErrors
IMPLICIT NONE
CLASS(boundaryGeneric), ALLOCATABLE, INTENT(out):: boundary
CLASS(boundaryParticleGeneric), ALLOCATABLE, INTENT(out):: boundary
real(8), intent(in):: mImpact
REAL(8), INTENT(in):: m0, n0, v0(1:3), T0 !Neutral properties
INTEGER, INTENT(in):: ion
@ -189,7 +189,7 @@ submodule(moduleMesh) boundaryParticle
subroutine initQuasiNeutrality(boundary)
implicit none
class(boundaryGeneric), allocatable, intent(out):: boundary
class(boundaryParticleGeneric), allocatable, intent(out):: boundary
integer:: e, et
allocate(boundaryQuasiNeutrality:: boundary)

View file

@ -4,197 +4,7 @@ MODULE moduleEM
USE moduleTable
IMPLICIT NONE
! Generic type for electromagnetic boundary conditions
TYPE, PUBLIC, ABSTRACT:: boundaryEMGeneric
INTEGER:: nNodes
TYPE(meshNodePointer), ALLOCATABLE:: nodes(:)
CONTAINS
PROCEDURE(applyEM_interface), DEFERRED, PASS:: apply
END TYPE boundaryEMGeneric
ABSTRACT INTERFACE
! Apply boundary condition to the load vector for the Poission equation
SUBROUTINE applyEM_interface(self, vectorF)
IMPORT boundaryEMGeneric
CLASS(boundaryEMGeneric), INTENT(in):: self
REAL(8), INTENT(inout):: vectorF(:)
END SUBROUTINE applyEM_interface
END INTERFACE
TYPE, EXTENDS(boundaryEMGeneric):: boundaryEMDirichlet
REAL(8):: potential
CONTAINS
! boundaryEMGeneric DEFERRED PROCEDURES
PROCEDURE, PASS:: apply => applyDirichlet
END TYPE boundaryEMDirichlet
TYPE, EXTENDS(boundaryEMGeneric):: boundaryEMDirichletTime
REAL(8):: potential
TYPE(table1D):: temporalProfile
CONTAINS
! boundaryEMGeneric DEFERRED PROCEDURES
PROCEDURE, PASS:: apply => applyDirichletTime
END TYPE boundaryEMDirichletTime
! Container for boundary conditions
TYPE:: boundaryEMCont
CLASS(boundaryEMGeneric), ALLOCATABLE:: obj
END TYPE boundaryEMCont
INTEGER:: nBoundaryEM
TYPE(boundaryEMCont), ALLOCATABLE:: boundaryEM(:)
!Information of charge and reference parameters for rho vector
REAL(8), ALLOCATABLE:: qSpecies(:)
CONTAINS
SUBROUTINE findNodes(self, physicalSurface)
USE moduleMesh
IMPLICIT NONE
CLASS(boundaryEMGeneric), INTENT(inout):: self
INTEGER, INTENT(in):: physicalSurface
CLASS(meshEdge), POINTER:: edge
INTEGER, ALLOCATABLE:: nodes(:), nodesEdge(:)
INTEGER:: nNodes, nodesNew
INTEGER:: e, n
!Temporal array to hold nodes
ALLOCATE(nodes(0))
! Loop thorugh the edges and identify those that are part of the boundary
DO e = 1, mesh%numEdges
edge => mesh%edges(e)%obj
IF (edge%physicalSurface == physicalSurface) THEN
! Edge is of the right boundary index
! Get nodes in the edge
nNodes = edge%nNodes
nodesEdge = edge%getNodes(nNodes)
! Collect all nodes that are not already in the temporal array
DO n = 1, nNodes
IF (ANY(nodes == nodesEdge(n))) THEN
! Node already in array, skip
CYCLE
ELSE
! If not, add element to array of nodes
nodes = [nodes, nodesEdge(n)]
END IF
END DO
END IF
END DO
! Point boundary to nodes
nNodes = SIZE(nodes)
ALLOCATE(self%nodes(nNodes))
self%nNodes = nNodes
DO n = 1, nNodes
self%nodes(n)%obj => mesh%nodes(nodes(n))%obj
END DO
END SUBROUTINE findNodes
! Initialize Dirichlet boundary condition
SUBROUTINE initDirichlet(self, physicalSurface, potential)
USE moduleRefParam, ONLY: Volt_ref
IMPLICIT NONE
CLASS(boundaryEMGeneric), ALLOCATABLE, INTENT(out):: self
INTEGER, INTENT(in):: physicalSurface
REAL(8), INTENT(in):: potential
! Allocate boundary edge
ALLOCATE(boundaryEMDirichlet:: self)
SELECT TYPE(self)
TYPE IS(boundaryEMDirichlet)
self%potential = potential / Volt_ref
CALL findNodes(self, physicalSurface)
END SELECT
END SUBROUTINE initDirichlet
! Initialize Dirichlet boundary condition
SUBROUTINE initDirichletTime(self, physicalSurface, potential, temporalProfile)
USE moduleRefParam, ONLY: Volt_ref, ti_ref
IMPLICIT NONE
CLASS(boundaryEMGeneric), ALLOCATABLE, INTENT(out):: self
INTEGER, INTENT(in):: physicalSurface
REAL(8), INTENT(in):: potential
CHARACTER(:), ALLOCATABLE, INTENT(in):: temporalProfile
! Allocate boundary edge
ALLOCATE(boundaryEMDirichletTime:: self)
SELECT TYPE(self)
TYPE IS(boundaryEMDirichletTime)
self%potential = potential / Volt_ref
CALL findNodes(self, physicalSurface)
CALL self%temporalProfile%init(temporalProfile)
CALL self%temporalProfile%convert(1.D0/ti_ref, 1.D0)
END SELECT
END SUBROUTINE initDirichletTime
!Apply Dirichlet boundary condition to the poisson equation
SUBROUTINE applyDirichlet(self, vectorF)
USE moduleMesh
IMPLICIT NONE
CLASS(boundaryEMDirichlet), INTENT(in):: self
REAL(8), INTENT(inout):: vectorF(:)
INTEGER:: n, ni
DO n = 1, self%nNodes
self%nodes(n)%obj%emData%phi = self%potential
vectorF(self%nodes(n)%obj%n) = self%nodes(n)%obj%emData%phi
END DO
END SUBROUTINE applyDirichlet
!Apply Dirichlet boundary condition with time temporal profile
SUBROUTINE applyDirichletTime(self, vectorF)
USE moduleMesh
USE moduleCaseParam, ONLY: timeStep, tauMin
IMPLICIT NONE
CLASS(boundaryEMDirichletTime), INTENT(in):: self
REAL(8), INTENT(inout):: vectorF(:)
REAL(8):: timeFactor
INTEGER:: n, ni
timeFactor = self%temporalProfile%get(DBLE(timeStep)*tauMin)
DO n = 1, self%nNodes
self%nodes(n)%obj%emData%phi = self%potential * timeFactor
vectorF(self%nodes(n)%obj%n) = self%nodes(n)%obj%emData%phi
END DO
END SUBROUTINE applyDirichletTime
contains
!Assemble the source vector based on the charge density to solve Poisson's equation
SUBROUTINE assembleSourceVector(vectorF, n_e)
USE moduleMesh