Merge branch 'development' into feature/BoltzmannElectrons

This commit is contained in:
Jorge Gonzalez 2024-10-13 14:54:34 +02:00
commit 221de46734
26 changed files with 794 additions and 431 deletions

View file

@ -1,52 +1,200 @@
!Module to solve the electromagnetic field
MODULE moduleEM
USE moduleMesh
USE moduleTable
IMPLICIT NONE
TYPE:: boundaryEM
CHARACTER(:), ALLOCATABLE:: typeEM
INTEGER:: physicalSurface
! Generic type for electromagnetic boundary conditions
TYPE, PUBLIC, ABSTRACT:: boundaryEMGeneric
INTEGER:: nNodes
TYPE(meshNodePointer), ALLOCATABLE:: nodes(:)
CONTAINS
PROCEDURE(applyEM_interface), DEFERRED, PASS:: apply
!PROCEDURE, PASS:: update !only for time dependent boundary conditions or maybe change apply????? That might be better.
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
PROCEDURE, PASS:: apply
! boundaryEMGeneric DEFERRED PROCEDURES
PROCEDURE, PASS:: apply => applyDirichlet
END TYPE boundaryEM
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(boundaryEM), ALLOCATABLE:: boundEM(:)
TYPE(boundaryEMCont), ALLOCATABLE:: boundaryEM(:)
!Information of charge and reference parameters for rho vector
REAL(8), ALLOCATABLE:: qSpecies(:)
CONTAINS
!Apply boundary conditions to the K matrix for Poisson's equation
SUBROUTINE apply(self, edge)
SUBROUTINE findNodes(self, physicalSurface)
USE moduleMesh
IMPLICIT NONE
CLASS(boundaryEM), INTENT(in):: self
CLASS(meshEdge):: edge
INTEGER:: nNodes
INTEGER, ALLOCATABLE:: nodes(:)
INTEGER:: n
CLASS(boundaryEMGeneric), INTENT(inout):: self
INTEGER, INTENT(in):: physicalSurface
CLASS(meshEdge), POINTER:: edge
INTEGER, ALLOCATABLE:: nodes(:), nodesEdge(:)
INTEGER:: nNodes, nodesNew
INTEGER:: e, n
nNodes = edge%nNodes
nodes = edge%getNodes(nNodes)
!Temporal array to hold nodes
ALLOCATE(nodes(0))
DO n = 1, nNodes
SELECT CASE(self%typeEM)
CASE ("dirichlet")
mesh%K(nodes(n), :) = 0.D0
mesh%K(nodes(n), nodes(n)) = 1.D0
mesh%nodes(nodes(n))%obj%emData%type = self%typeEM
mesh%nodes(nodes(n))%obj%emData%phi = self%potential
! 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
END SELECT
ELSE
! If not, add element to array of nodes
nodes = [nodes, nodesEdge(n)]
END IF
END DO
END IF
END DO
END SUBROUTINE apply
! 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)
@ -60,7 +208,7 @@ MODULE moduleEM
REAL(8), ALLOCATABLE:: rho(:)
REAL(8), INTENT(in), OPTIONAL:: n_e(1:mesh%numNodes)
INTEGER:: nNodes
INTEGER:: e, i, ni
INTEGER:: e, i, ni, b
CLASS(meshNode), POINTER:: node
! !$OMP SINGLE