Big one...

I should've commited before, but I wanted to make things compile.

The big change is that I've added a global time step so the parameter
does not need to be passed in each function. This is useful as we are
moving towards using time profiles for boundary conditions and injection
of particles (not in this branch, but in the future and the procedure
will be quite similar)
This commit is contained in:
Jorge Gonzalez 2024-07-12 23:08:19 +02:00
commit ac27725940
14 changed files with 340 additions and 220 deletions

View file

@ -1,6 +1,7 @@
!Module to solve the electromagnetic field
MODULE moduleEM
USE moduleMesh
USE moduleTable
IMPLICIT NONE
! Array of pointers to nodes.
@ -11,57 +12,155 @@ MODULE moduleEM
END TYPE meshNodePointer
! TODO: Make this a derived type.
TYPE:: boundaryEM
CHARACTER(:), ALLOCATABLE:: typeEM
INTEGER:: physicalSurface
REAL(8):: potential
! Generic type for electromagnetic boundary conditions
TYPE, PUBLIC, ABSTRACT:: boundaryEMGeneric
INTEGER:: nNodes
TYPE(meshNodePointer), ALLOCATABLE:: nodes(:)
CONTAINS
PROCEDURE, PASS:: apply
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 boundaryEM
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(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)
! Initialize Dirichlet boundary condition
SUBROUTINE initDirichlet(self, physicalSurface, potential)
USE moduleMesh
USE moduleRefParam, ONLY: Volt_ref
IMPLICIT NONE
CLASS(boundaryEMGeneric), ALLOCATABLE, INTENT(out):: self
INTEGER:: physicalSurface
REAL(8), INTENT(in):: potential
CLASS(meshEdge), POINTER:: edge
INTEGER, ALLOCATABLE:: nodes(:), nodesEdge(:)
INTEGER:: nNodes, nodesNew
INTEGER:: e, n
! Allocate boundary edge
ALLOCATE(boundaryEMDirichlet:: self)
SELECT TYPE(self)
TYPE IS(boundaryEMDirichlet)
self%potential = potential / Volt_ref
!TODO: This is going into a function
!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))
DO n = 1, nNodes
self%nodes(n)%obj => mesh%nodes(nodes(n))%obj
END DO
END SELECT
END SUBROUTINE initDirichlet
!Apply Dirichlet boundary condition to the poisson equation
SUBROUTINE applyDirichlet(self, vectorF)
USE moduleMesh
IMPLICIT NONE
CLASS(boundaryEM), INTENT(in):: self
CLASS(meshEdge):: edge
INTEGER:: nNodes
INTEGER, ALLOCATABLE:: nodes(:)
INTEGER:: n
CLASS(boundaryEMDirichlet), INTENT(in):: self
REAL(8), INTENT(inout):: vectorF(:)
INTEGER:: n, ni
nNodes = 1
nNodes = edge%nNodes
nodes = edge%getNodes(nNodes)
DO n = 1, nNodes
SELECT CASE(self%typeEM)
CASE ("dirichlet")
mesh%K(nodes(n), :) = 0.D0
mesh%K(nodes(n), nodes(n)) = 1.D0
! TODO: Change this to pointer
mesh%nodes(nodes(n))%obj%emData%type = self%typeEM
mesh%nodes(nodes(n))%obj%emData%phi = self%potential
END SELECT
DO n = 1, self%nNodes
self%nodes(n)%obj%emData%phi = self%potential
END DO
END SUBROUTINE apply
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(:)
INTEGER:: n, ni
DO n = 1, self%nNodes
self%nodes(n)%obj%emData%phi = self%potential
END DO
END SUBROUTINE applyDirichletTime
!Assemble the source vector based on the charge density to solve Poisson's equation
SUBROUTINE assembleSourceVector(vectorF)
@ -74,13 +173,14 @@ MODULE moduleEM
INTEGER, ALLOCATABLE:: nodes(:)
REAL(8), ALLOCATABLE:: rho(:)
INTEGER:: nNodes
INTEGER:: e, i, ni
INTEGER:: e, i, ni, b
CLASS(meshNode), POINTER:: node
!$OMP SINGLE
vectorF = 0.D0
!$OMP END SINGLE
! Calculate charge density in each node
!$OMP DO REDUCTION(+:vectorF)
DO e = 1, mesh%numCells
nNodes = mesh%cells(e)%obj%nNodes
@ -112,18 +212,12 @@ MODULE moduleEM
!$OMP END DO
!Apply boundary conditions
!$OMP DO
DO i = 1, mesh%numNodes
node => mesh%nodes(i)%obj
SELECT CASE(node%emData%type)
CASE ("dirichlet")
vectorF(i) = node%emData%phi
END SELECT
!$OMP SINGLE
DO b = 1, nBoundaryEM
CALL boundaryEM(b)%obj%apply(vectorF)
END DO
!$OMP END DO
!$OMP END SINGLE
END SUBROUTINE assembleSourceVector