diff --git a/src/modules/mesh/makefile b/src/modules/mesh/makefile index 83fd7fc..7481690 100644 --- a/src/modules/mesh/makefile +++ b/src/modules/mesh/makefile @@ -21,8 +21,7 @@ all: moduleMesh.o inout.o 3DCart.o 2DCyl.o 2DCart.o 1DRad.o 1DCart.o 0D.o 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)/$@ + $(FC) $(FCFLAGS) -c moduleMesh@boundary.f90 -o $(OBJDIR)/$@ inout.o: 3DCart.o 2DCyl.o 2DCart.o 1DRad.o 1DCart.o 0D.o $(MAKE) -C inout all diff --git a/src/modules/mesh/moduleMesh.f90 b/src/modules/mesh/moduleMesh.f90 index 190c50c..b53fc93 100644 --- a/src/modules/mesh/moduleMesh.f90 +++ b/src/modules/mesh/moduleMesh.f90 @@ -6,7 +6,7 @@ MODULE moduleMesh use moduleSpecies, only: nSpecies IMPLICIT NONE - ! MESH ELEMENTS + ! Declarations for elements !Generic mesh element TYPE, PUBLIC, ABSTRACT:: meshElement !Index @@ -88,8 +88,7 @@ MODULE moduleMesh ! Surface of edge REAL(8):: surface = 0.D0 !Pointer to boundary per species - TYPE(boundaryParticlePointer), allocatable:: boundariesParticle(:) - class(boundaryEMGeneric), pointer:: boundaryEM => null() + TYPE(boundaryPointer), allocatable:: boundariesParticle(:) !Physical surface for the edge CONTAINS !DEFERED PROCEDURES @@ -585,36 +584,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:: boundaryParticleGeneric + TYPE, abstract, PUBLIC:: boundaryGeneric integer:: n character(:), allocatable:: name contains - procedure, pass:: init => initBoundaryParticle - procedure(applyParticle_interface), deferred, pass:: apply + procedure, pass:: init => initBoundary + procedure(boundary_interface), deferred, pass:: apply - end type boundaryParticleGeneric + END TYPE boundaryGeneric interface - module subroutine initBoundaryParticle(self, config, object, b) + module subroutine initBoundary(self, config, object, b) use json_module - class(boundaryParticleGeneric), intent(out):: self + class(boundaryGeneric), intent(out):: self type(json_file), intent(inout):: config character(:), allocatable, intent(in):: object integer, intent(in):: b - end subroutine initBoundaryParticle + end subroutine initBoundary end interface abstract interface - subroutine applyParticle_interface(self, edge, part) + subroutine boundary_interface(self, edge, part) use moduleSpecies - import boundaryParticleGeneric, meshEdge + import boundaryGeneric, meshEdge - class(boundaryParticleGeneric), intent(in):: self + class(boundaryGeneric), intent(in):: self class(meshEdge), intent(inout):: edge class(particle), intent(inout):: part @@ -623,35 +622,35 @@ MODULE moduleMesh end interface !Reflecting boundary - TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryReflection + TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryReflection CONTAINS procedure, pass:: apply => reflection END TYPE boundaryReflection !Absorption boundary - TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryAbsorption + TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAbsorption CONTAINS procedure, pass:: apply => absorption END TYPE boundaryAbsorption !Transparent boundary - TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryTransparent + TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryTransparent CONTAINS procedure, pass:: apply => transparent END TYPE boundaryTransparent !Symmetry axis - TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryAxis + TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryAxis CONTAINS procedure, pass:: apply => axis END TYPE boundaryAxis !Wall Temperature boundary - TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryWallTemperature + TYPE, PUBLIC, EXTENDS(boundaryGeneric):: boundaryWallTemperature !Thermal velocity of the wall: square root(Wall temperature X specific heat) REAL(8):: vTh CONTAINS @@ -660,7 +659,7 @@ MODULE moduleMesh END TYPE boundaryWallTemperature !Ionization boundary - TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryIonization + TYPE, PUBLIC, EXTENDS(boundaryGeneric):: 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 @@ -674,7 +673,7 @@ MODULE moduleMesh END TYPE boundaryIonization ! Ensures quasi-neutrality by changing the reflection coefficient - type, public, extends(boundaryParticleGeneric):: boundaryQuasiNeutrality + type, public, extends(boundaryGeneric):: boundaryQuasiNeutrality real(8):: alpha ! Reflection parameter integer, allocatable:: edges(:) !Array with edges contains @@ -774,17 +773,17 @@ MODULE moduleMesh end interface - TYPE:: boundaryParticleCont - CLASS(boundaryParticleGeneric), ALLOCATABLE:: obj + TYPE:: boundaryCont + CLASS(boundaryGeneric), ALLOCATABLE:: obj CONTAINS - END TYPE boundaryParticleCont + END TYPE boundaryCont - type:: boundaryParticlePointer - class(boundaryParticleGeneric), pointer:: obj + type:: boundaryPointer + class(boundaryGeneric), pointer:: obj contains - end type boundaryParticlePointer + end type boundaryPointer type boundaryParticleLinking integer:: physicalSurface @@ -795,7 +794,7 @@ MODULE moduleMesh !Number of boundaries INTEGER:: nBoundaries = 0, nPhysicalSurfaces = 0 !Array for boundaries - TYPE(boundaryParticleCont), ALLOCATABLE, TARGET:: boundariesParticle(:) + TYPE(boundaryCont), ALLOCATABLE, TARGET:: boundariesParticle(:) !Array for linking boundaries type(boundaryParticleLinking), allocatable, dimension(:):: boundariesParticleLinking @@ -808,96 +807,4 @@ 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 diff --git a/src/modules/mesh/moduleMesh@boundaryEM.f90 b/src/modules/mesh/moduleMesh@boundaryEM.f90 deleted file mode 100644 index 3878532..0000000 --- a/src/modules/mesh/moduleMesh@boundaryEM.f90 +++ /dev/null @@ -1,141 +0,0 @@ -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 diff --git a/src/modules/mesh/moduleMesh@boundaryParticle.f90 b/src/modules/mesh/moduleMesh@boundaryParticle.f90 index b3225b3..a6ce1b1 100644 --- a/src/modules/mesh/moduleMesh@boundaryParticle.f90 +++ b/src/modules/mesh/moduleMesh@boundaryParticle.f90 @@ -25,13 +25,13 @@ submodule(moduleMesh) boundaryParticle end function boundaryParticleName_to_Index - module subroutine initBoundaryParticle(self, config, object, b) + module subroutine initBoundary(self, config, object, b) use json_module use moduleRefParam, only: m_ref use moduleConstParam, only: me implicit none - class(boundaryParticleGeneric), allocatable, intent(out):: self + class(boundaryGeneric), 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 initBoundaryParticle + end subroutine initBoundary SUBROUTINE initWallTemperature(boundary, T, c) USE moduleRefParam IMPLICIT NONE - CLASS(boundaryParticleGeneric), ALLOCATABLE, INTENT(out):: boundary + CLASS(boundaryGeneric), 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(boundaryParticleGeneric), ALLOCATABLE, INTENT(out):: boundary + CLASS(boundaryGeneric), 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(boundaryParticleGeneric), allocatable, intent(out):: boundary + class(boundaryGeneric), allocatable, intent(out):: boundary integer:: e, et allocate(boundaryQuasiNeutrality:: boundary) diff --git a/src/modules/solver/electromagnetic/moduleEM.f90 b/src/modules/solver/electromagnetic/moduleEM.f90 index 656c5bd..7f6891c 100644 --- a/src/modules/solver/electromagnetic/moduleEM.f90 +++ b/src/modules/solver/electromagnetic/moduleEM.f90 @@ -4,7 +4,197 @@ MODULE moduleEM USE moduleTable IMPLICIT NONE - contains + ! 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 + !Assemble the source vector based on the charge density to solve Poisson's equation SUBROUTINE assembleSourceVector(vectorF, n_e) USE moduleMesh