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

View file

@ -491,47 +491,46 @@ MODULE moduleSolver
END SUBROUTINE updateParticleCell
!Update the information about if a species needs to be moved this iteration
SUBROUTINE updatePushSpecies(self, t)
SUBROUTINE updatePushSpecies(self)
USE moduleSpecies
USE moduleCaseparam, ONLY: timeStep
IMPLICIT NONE
CLASS(solverGeneric), INTENT(inout):: self
INTEGER, INTENT(in):: t
INTEGER:: s
DO s=1, nSpecies
self%pusher(s)%pushSpecies = MOD(t, self%pusher(s)%every) == 0
self%pusher(s)%pushSpecies = MOD(timeStep, self%pusher(s)%every) == 0
END DO
END SUBROUTINE updatePushSpecies
!Output the different data and information
SUBROUTINE doOutput(t)
SUBROUTINE doOutput()
USE moduleMesh
USE moduleOutput
USE moduleSpecies
USE moduleCompTime
USE moduleProbe
USE moduleCaseParam, ONLY: timeStep
IMPLICIT NONE
INTEGER, INTENT(in):: t
CALL outputProbes(t)
CALL outputProbes()
counterOutput = counterOutput + 1
IF (counterOutput >= triggerOutput .OR. &
t == tFinal .OR. t == tInitial) THEN
timeStep == tFinal .OR. timeStep == tInitial) THEN
!Resets output counter
counterOutput=0
CALL mesh%printOutput(t)
IF (ASSOCIATED(meshForMCC)) CALL meshForMCC%printColl(t)
CALL mesh%printEM(t)
WRITE(*, "(5X,A21,I10,A1,I10)") "t/tFinal: ", t, "/", tFinal
CALL mesh%printOutput()
IF (ASSOCIATED(meshForMCC)) CALL meshForMCC%printColl()
CALL mesh%printEM()
WRITE(*, "(5X,A21,I10,A1,I10)") "t/tFinal: ", timeStep, "/", tFinal
WRITE(*, "(5X,A21,I10)") "Particles: ", nPartOld
IF (t == 0) THEN
IF (timeStep == 0) THEN
WRITE(*, "(5X,A21,F8.1,A2)") " init time: ", 1.D3*tStep, "ms"
ELSE
@ -549,34 +548,32 @@ MODULE moduleSolver
counterCPUTime = counterCPUTime + 1
IF (counterCPUTime >= triggerCPUTime .OR. &
t == tFinal .OR. t == tInitial) THEN
timeStep == tFinal .OR. timeStep == tInitial) THEN
!Reset CPU Time counter
counterCPUTime = 0
CALL printTime(t, t == 0)
CALL printTime(timeStep == 0)
END IF
!Output average values
IF (useAverage .AND. t == tFinal) THEN
IF (useAverage .AND. timeStep == tFinal) THEN
CALL mesh%printAverage()
END IF
END SUBROUTINE doOutput
SUBROUTINE doAverage(t)
SUBROUTINE doAverage()
USE moduleAverage
USE moduleMesh
IMPLICIT NONE
INTEGER, INTENT(in):: t
INTEGER:: tAverage, n
IF (useAverage) THEN
tAverage = t - tAverageStart
tAverage = timeStep - tAverageStart
IF (tAverage == 1) THEN
!First iteration in which average scheme is used