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:
parent
49025a6965
commit
ac27725940
14 changed files with 340 additions and 220 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue