From abedb79b1651386d39e4e08c9de877a66a6d70e4 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Fri, 12 Jul 2024 11:02:26 +0200 Subject: [PATCH 1/8] Some comments Just some comments on how I am going to make the desired changes (have a Dirichlet boundary condition for the electric potential that changes with time). This might be a good opportunity to rework the boundary conditions in the electrostatic field and include other things like a Newmann boundary condition. We will see. --- src/modules/init/moduleInput.f90 | 6 ++++++ src/modules/solver/electromagnetic/moduleEM.f90 | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/modules/init/moduleInput.f90 b/src/modules/init/moduleInput.f90 index 6f1d5bb..4216c73 100644 --- a/src/modules/init/moduleInput.f90 +++ b/src/modules/init/moduleInput.f90 @@ -1173,6 +1173,12 @@ MODULE moduleInput IF (.NOT. found) & CALL criticalError('Required parameter "physicalSurface" for Dirichlet boundary condition not found', 'readEMBoundary') + CASE ("dirichletTime") + CALL config%get(object // '.potential', boundEM(i)%potential, found) + IF (.NOT. found) & + CALL criticalError('Required parameter "potential" for Dirichlet boundary condition not found', 'readEMBoundary') + boundEM(i)%potential = boundEM(i)%potential/Volt_ref + CASE DEFAULT CALL criticalError('Boundary type ' // boundEM(i)%typeEM // ' not yet supported', 'readEMBoundary') diff --git a/src/modules/solver/electromagnetic/moduleEM.f90 b/src/modules/solver/electromagnetic/moduleEM.f90 index d5d0793..f6c7112 100644 --- a/src/modules/solver/electromagnetic/moduleEM.f90 +++ b/src/modules/solver/electromagnetic/moduleEM.f90 @@ -2,6 +2,7 @@ MODULE moduleEM IMPLICIT NONE + ! TODO: Make this a derived type. TYPE:: boundaryEM CHARACTER(:), ALLOCATABLE:: typeEM INTEGER:: physicalSurface @@ -9,6 +10,7 @@ MODULE moduleEM CONTAINS PROCEDURE, PASS:: apply + !PROCEDURE, PASS:: update !only for time dependent boundary conditions or maybe change apply????? That might be better. END TYPE boundaryEM -- 2.49.1 From f0a27c05295e110829f91c23f1624b9596d1df32 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Fri, 12 Jul 2024 13:17:02 +0200 Subject: [PATCH 2/8] More comments So if the source vector is being updated every time step, it might be "easy" to implement these things. --- src/modules/solver/electromagnetic/moduleEM.f90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/solver/electromagnetic/moduleEM.f90 b/src/modules/solver/electromagnetic/moduleEM.f90 index f6c7112..ce33570 100644 --- a/src/modules/solver/electromagnetic/moduleEM.f90 +++ b/src/modules/solver/electromagnetic/moduleEM.f90 @@ -49,7 +49,7 @@ MODULE moduleEM END DO - END SUBROUTINE + END SUBROUTINE apply !Assemble the source vector based on the charge density to solve Poisson's equation SUBROUTINE assembleSourceVector(vectorF) @@ -130,6 +130,7 @@ MODULE moduleEM ALLOCATE(tempF(1:mesh%numNodes)) !$OMP END SINGLE + !TODO: Is this done every time step??? Then things are gonna be really simple. CALL assembleSourceVector(tempF) !$OMP SINGLE -- 2.49.1 From 49025a6965869b7a19975b8cad73a989cc0d6028 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Fri, 12 Jul 2024 19:21:00 +0200 Subject: [PATCH 3/8] Starting changes Planning the new way to do BC in the EM field solver. Probably I have to change how things are read, but I don't think this is going to affect the input file. --- src/modules/solver/electromagnetic/moduleEM.f90 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/modules/solver/electromagnetic/moduleEM.f90 b/src/modules/solver/electromagnetic/moduleEM.f90 index ce33570..a141eac 100644 --- a/src/modules/solver/electromagnetic/moduleEM.f90 +++ b/src/modules/solver/electromagnetic/moduleEM.f90 @@ -1,12 +1,23 @@ !Module to solve the electromagnetic field MODULE moduleEM + USE moduleMesh IMPLICIT NONE + ! Array of pointers to nodes. + !TODO: This is probably better in moduleMesh as multiple modules could use this. + TYPE:: meshNodePointer + CLASS(meshNode), POINTER:: obj + CONTAINS + + END TYPE meshNodePointer + + ! TODO: Make this a derived type. TYPE:: boundaryEM CHARACTER(:), ALLOCATABLE:: typeEM INTEGER:: physicalSurface REAL(8):: potential + TYPE(meshNodePointer), ALLOCATABLE:: nodes(:) CONTAINS PROCEDURE, PASS:: apply @@ -42,6 +53,7 @@ MODULE moduleEM 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 -- 2.49.1 From ac277259408bd6670ea17085527e3f91881fb04e Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Fri, 12 Jul 2024 23:08:19 +0200 Subject: [PATCH 4/8] 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) --- src/fpakc.f90 | 25 ++- src/modules/common/moduleCaseParam.f90 | 5 + src/modules/init/moduleInput.f90 | 134 +++++++------ .../mesh/inout/0D/moduleMeshOutput0D.f90 | 21 +- .../inout/gmsh2/moduleMeshOutputGmsh2.f90 | 38 ++-- .../mesh/inout/moduleMeshInoutCommon.f90 | 8 +- .../mesh/inout/vtu/moduleMeshInputVTU.f90 | 2 +- .../mesh/inout/vtu/moduleMeshOutputVTU.f90 | 35 ++-- src/modules/mesh/moduleMesh.f90 | 15 +- src/modules/moduleInject.f90 | 26 +-- src/modules/moduleProbe.f90 | 28 +-- src/modules/output/moduleOutput.f90 | 6 +- .../solver/electromagnetic/moduleEM.f90 | 180 +++++++++++++----- src/modules/solver/moduleSolver.f90 | 37 ++-- 14 files changed, 340 insertions(+), 220 deletions(-) diff --git a/src/fpakc.f90 b/src/fpakc.f90 index e90a5e0..ae6e7bb 100644 --- a/src/fpakc.f90 +++ b/src/fpakc.f90 @@ -11,12 +11,12 @@ PROGRAM fpakc USE OMP_LIB IMPLICIT NONE - ! t = time step - INTEGER:: t ! arg1 = Input argument 1 (input file) CHARACTER(200):: arg1 ! inputFile = path+name of input file CHARACTER(:), ALLOCATABLE:: inputFile + ! generic integer for time step + INTEGER:: t tStep = omp_get_wtime() !Gets the input file @@ -32,10 +32,13 @@ PROGRAM fpakc CALL initOutput(inputFile) !Do '0' iteration - t = tInitial + timeStep = tInitial !$OMP PARALLEL DEFAULT(SHARED) !$OMP SINGLE + ! Initial reset of probes + CALL resetProbes() + CALL verboseError("Initial scatter of particles...") !$OMP END SINGLE CALL doScatter() @@ -49,19 +52,21 @@ PROGRAM fpakc tStep = omp_get_wtime() - tStep !Output initial state - CALL doOutput(t) + CALL doOutput() CALL verboseError('Starting main loop...') !$OMP PARALLEL DEFAULT(SHARED) DO t = tInitial + 1, tFinal - !Insert new particles and push them !$OMP SINGLE tStep = omp_get_wtime() + ! Update global time step index + timeStep = t + !Checks if a species needs to me moved in this iteration - CALL solver%updatePushSpecies(t) + CALL solver%updatePushSpecies() !Checks if probes need to be calculated this iteration - CALL resetProbes(t) + CALL resetProbes() tPush = omp_get_wtime() !$OMP END SINGLE @@ -79,7 +84,7 @@ PROGRAM fpakc !$OMP END SINGLE IF (doMCCollisions) THEN - CALL meshForMCC%doCollisions(t) + CALL meshForMCC%doCollisions() END IF @@ -124,12 +129,12 @@ PROGRAM fpakc !$OMP SINGLE tEMField = omp_get_wtime() - tEMField - CALL doAverage(t) + CALL doAverage() tStep = omp_get_wtime() - tStep !Output data - CALL doOutput(t) + CALL doOutput() !$OMP END SINGLE END DO diff --git a/src/modules/common/moduleCaseParam.f90 b/src/modules/common/moduleCaseParam.f90 index 8df3210..551d867 100644 --- a/src/modules/common/moduleCaseParam.f90 +++ b/src/modules/common/moduleCaseParam.f90 @@ -2,8 +2,13 @@ MODULE moduleCaseParam !Final and initial iterations INTEGER:: tFinal, tInitial = 0 + ! Global index of current iteration + INTEGER:: timeStep + ! Time step for all species REAL(8), ALLOCATABLE:: tau(:) + ! Minimum time step REAL(8):: tauMin + ! Time step for Monte-Carlo Collisions REAL(8):: tauColl END MODULE moduleCaseParam diff --git a/src/modules/init/moduleInput.f90 b/src/modules/init/moduleInput.f90 index 4216c73..6800ac1 100644 --- a/src/modules/init/moduleInput.f90 +++ b/src/modules/init/moduleInput.f90 @@ -264,8 +264,8 @@ MODULE moduleInput CALL readEMBoundary(config) !Read constant magnetic field DO i = 1, 3 - WRITE(istring, '(i2)') i - CALL config%get(object // '.B(' // istring // ')', B(i), found) + WRITE(iString, '(i2)') i + CALL config%get(object // '.B(' // iString // ')', B(i), found) IF (.NOT. found) THEN CALL criticalError('Constant magnetic field not provided in direction ' // iString, 'readSolver') @@ -799,7 +799,7 @@ MODULE moduleInput TYPE(json_file), INTENT(inout):: config INTEGER:: i, s - CHARACTER(2):: istring, sString + CHARACTER(2):: iString, sString CHARACTER(:), ALLOCATABLE:: object, bType REAL(8):: Tw, cw !Wall temperature and specific heat !Neutral Properties @@ -815,8 +815,8 @@ MODULE moduleInput CALL config%info('boundary', found, n_children = nBoundary) ALLOCATE(boundary(1:nBoundary)) DO i = 1, nBoundary - WRITE(istring, '(i2)') i - object = 'boundary(' // TRIM(istring) // ')' + WRITE(iString, '(i2)') i + object = 'boundary(' // TRIM(iString) // ')' boundary(i)%n = i CALL config%get(object // '.name', boundary(i)%name, found) @@ -1100,13 +1100,13 @@ MODULE moduleInput TYPE(json_file), INTENT(inout):: config CHARACTER(:), ALLOCATABLE:: object LOGICAL:: found - CHARACTER(2):: istring + CHARACTER(2):: iString INTEGER:: i CHARACTER(:), ALLOCATABLE:: speciesName REAL(8), ALLOCATABLE, DIMENSION(:):: r REAL(8), ALLOCATABLE, DIMENSION(:):: v1, v2, v3 INTEGER, ALLOCATABLE, DIMENSION(:):: points - REAL(8):: timeStep + REAL(8):: everyTimeStep CALL config%info('output.probes', found, n_children = nProbes) @@ -1114,7 +1114,7 @@ MODULE moduleInput DO i = 1, nProbes WRITE(iString, '(I2)') i - object = 'output.probes(' // trim(istring) // ')' + object = 'output.probes(' // trim(iString) // ')' CALL config%get(object // '.species', speciesName, found) CALL config%get(object // '.position', r, found) @@ -1122,16 +1122,14 @@ MODULE moduleInput CALL config%get(object // '.velocity_2', v2, found) CALL config%get(object // '.velocity_3', v3, found) CALL config%get(object // '.points', points, found) - CALL config%get(object // '.timeStep', timeStep, found) + CALL config%get(object // '.timeStep', everyTimeStep, found) IF (ANY(points < 2)) CALL criticalError("Number of points in probe " // iString // " incorrect", 'readProbes') - CALL probe(i)%init(i, speciesName, r, v1, v2, v3, points, timeStep) + CALL probe(i)%init(i, speciesName, r, v1, v2, v3, points, everyTimeStep) END DO - CALL resetProbes(tInitial) - END SUBROUTINE readProbes SUBROUTINE readEMBoundary(config) @@ -1147,40 +1145,56 @@ MODULE moduleInput TYPE(json_file), INTENT(inout):: config CHARACTER(:), ALLOCATABLE:: object LOGICAL:: found - CHARACTER(2):: istring - INTEGER:: i, e, s + CHARACTER(:), ALLOCATABLE:: typeEM + REAL(8):: potential + INTEGER:: physicalSurface + CHARACTER(:), ALLOCATABLE:: timeProfile + INTEGER:: b, e, s, n, ni + CHARACTER(2):: bString INTEGER:: info EXTERNAL:: dgetrf CALL config%info('boundaryEM', found, n_children = nBoundaryEM) - IF (found) ALLOCATE(boundEM(1:nBoundaryEM)) + IF (found) ALLOCATE(boundaryEM(1:nBoundaryEM)) - DO i = 1, nBoundaryEM - WRITE(istring, '(I2)') i - object = 'boundaryEM(' // trim(istring) // ')' + DO b = 1, nBoundaryEM + WRITE(bString, '(I2)') b + object = 'boundaryEM(' // trim(bString) // ')' - CALL config%get(object // '.type', boundEM(i)%typeEM, found) + CALL config%get(object // '.type', typeEM, found) - SELECT CASE(boundEM(i)%typeEM) + SELECT CASE(typeEM) CASE ("dirichlet") - CALL config%get(object // '.potential', boundEM(i)%potential, found) - IF (.NOT. found) & + CALL config%get(object // '.potential', potential, found) + IF (.NOT. found) THEN CALL criticalError('Required parameter "potential" for Dirichlet boundary condition not found', 'readEMBoundary') - boundEM(i)%potential = boundEM(i)%potential/Volt_ref - CALL config%get(object // '.physicalSurface', boundEM(i)%physicalSurface, found) - IF (.NOT. found) & + END IF + + CALL config%get(object // '.physicalSurface', physicalSurface, found) + IF (.NOT. found) THEN CALL criticalError('Required parameter "physicalSurface" for Dirichlet boundary condition not found', 'readEMBoundary') + END IF + + CALL initDirichlet(boundaryEM(b)%obj, physicalSurface, potential) + CASE ("dirichletTime") - CALL config%get(object // '.potential', boundEM(i)%potential, found) - IF (.NOT. found) & + CALL config%get(object // '.potential', potential, found) + IF (.NOT. found) THEN CALL criticalError('Required parameter "potential" for Dirichlet boundary condition not found', 'readEMBoundary') - boundEM(i)%potential = boundEM(i)%potential/Volt_ref + + END IF + + CALL config%get(object // '.physicalSurface', physicalSurface, found) + IF (.NOT. found) THEN + CALL criticalError('Required parameter "physicalSurface" for Dirichlet boundary condition not found', 'readEMBoundary') + + END IF CASE DEFAULT - CALL criticalError('Boundary type ' // boundEM(i)%typeEM // ' not yet supported', 'readEMBoundary') + CALL criticalError('Boundary type ' // typeEM // ' not yet supported', 'readEMBoundary') END SELECT @@ -1199,18 +1213,28 @@ MODULE moduleInput END DO - IF (ALLOCATED(boundEM)) THEN - DO e = 1, mesh%numEdges - IF (ANY(mesh%edges(e)%obj%physicalSurface == boundEM(:)%physicalSurface)) THEN - DO i = 1, nBoundaryEM - IF (mesh%edges(e)%obj%physicalSurface == boundEM(i)%physicalSurface) THEN - CALL boundEM(i)%apply(mesh%edges(e)%obj) + ! Modify K matrix due to boundary conditions + DO b = 1, nBoundaryEM + SELECT TYPE(boundary => boundaryEM(b)%obj) + TYPE IS(boundaryEMDirichlet) + DO n = 1, boundary%nNodes + ni = boundary%nodes(n)%obj%n + mesh%K(ni, :) = 0.D0 + mesh%K(ni, ni) = 1.D0 - END IF - END DO - END IF - END DO - END IF + END DO + + TYPE IS(boundaryEMDirichletTime) + DO n = 1, boundary%nNodes + ni = boundary%nodes(n)%obj%n + mesh%K(ni, :) = 0.D0 + mesh%K(ni, ni) = 1.D0 + + END DO + + END SELECT + + END DO !Compute the PLU factorization of K once boundary conditions have been read CALL dgetrf(mesh%numNodes, mesh%numNodes, mesh%K, mesh%numNodes, mesh%IPIV, info) @@ -1231,13 +1255,13 @@ MODULE moduleInput TYPE(json_file), INTENT(inout):: config INTEGER:: i - CHARACTER(2):: istring + CHARACTER(2):: iString CHARACTER(:), ALLOCATABLE:: object LOGICAL:: found CHARACTER(:), ALLOCATABLE:: speciesName CHARACTER(:), ALLOCATABLE:: name REAL(8):: v - REAL(8), ALLOCATABLE:: T(:), normal(:) + REAL(8), ALLOCATABLE:: temperature(:), normal(:) REAL(8):: flow CHARACTER(:), ALLOCATABLE:: units INTEGER:: physicalSurface @@ -1248,8 +1272,8 @@ MODULE moduleInput ALLOCATE(inject(1:nInject)) nPartInj = 0 DO i = 1, nInject - WRITE(istring, '(i2)') i - object = 'inject(' // trim(istring) // ')' + WRITE(iString, '(i2)') i + object = 'inject(' // trim(iString) // ')' !Find species CALL config%get(object // '.species', speciesName, found) @@ -1257,7 +1281,7 @@ MODULE moduleInput CALL config%get(object // '.name', name, found) CALL config%get(object // '.v', v, found) - CALL config%get(object // '.T', T, found) + CALL config%get(object // '.T', temperature, found) CALL config%get(object // '.n', normal, found) IF (.NOT. found) THEN ALLOCATE(normal(1:3)) @@ -1269,7 +1293,7 @@ MODULE moduleInput particlesPerEdge = 0 CALL config%get(object // '.particlesPerEdge', particlesPerEdge, found) - CALL inject(i)%init(i, v, normal, T, flow, units, sp, physicalSurface, particlesPerEdge) + CALL inject(i)%init(i, v, normal, temperature, flow, units, sp, physicalSurface, particlesPerEdge) CALL readVelDistr(config, inject(i), object) @@ -1329,28 +1353,28 @@ MODULE moduleInput TYPE(injectGeneric), INTENT(inout):: inj CHARACTER(:), ALLOCATABLE, INTENT(in):: object INTEGER:: i - CHARACTER(2):: istring + CHARACTER(2):: iString CHARACTER(:), ALLOCATABLE:: fvType LOGICAL:: found - REAL(8):: v, T, m + REAL(8):: v, temperature, m !Reads species mass m = inj%species%m !Reads distribution functions for velocity DO i = 1, 3 - WRITE(istring, '(i2)') i - CALL config%get(object // '.velDist('// TRIM(istring) //')', fvType, found) - IF (.NOT. found) CALL criticalError("No velocity distribution in direction " // istring // & + WRITE(iString, '(i2)') i + CALL config%get(object // '.velDist('// TRIM(iString) //')', fvType, found) + IF (.NOT. found) CALL criticalError("No velocity distribution in direction " // iString // & " found for " // object, 'readVelDistr') SELECT CASE(fvType) CASE ("Maxwellian") - T = inj%T(i) - CALL initVelDistMaxwellian(inj%v(i)%obj, t, m) + temperature = inj%temperature(i) + CALL initVelDistMaxwellian(inj%v(i)%obj, temperature, m) CASE ("Half-Maxwellian") - T = inj%T(i) - CALL initVelDistHalfMaxwellian(inj%v(i)%obj, t, m) + temperature = inj%temperature(i) + CALL initVelDistHalfMaxwellian(inj%v(i)%obj, temperature, m) CASE ("Delta") v = inj%vMod*inj%n(i) diff --git a/src/modules/mesh/inout/0D/moduleMeshOutput0D.f90 b/src/modules/mesh/inout/0D/moduleMeshOutput0D.f90 index 97ec729..c0dcfbb 100644 --- a/src/modules/mesh/inout/0D/moduleMeshOutput0D.f90 +++ b/src/modules/mesh/inout/0D/moduleMeshOutput0D.f90 @@ -1,22 +1,22 @@ MODULE moduleMeshOutput0D CONTAINS - SUBROUTINE printOutput0D(self, t) + SUBROUTINE printOutput0D(self) USE moduleMesh USE moduleRefParam USE moduleSpecies USE moduleOutput + USE moduleCaseParam, ONLY: timeStep IMPLICIT NONE CLASS(meshParticles), INTENT(in):: self - INTEGER, INTENT(in):: t INTEGER:: i TYPE(outputFormat):: output CHARACTER(:), ALLOCATABLE:: fileName DO i = 1, nSpecies fileName='OUTPUT_' // species(i)%obj%name // '.dat' - IF (t == 0) THEN + IF (timeStep == 0) THEN OPEN(20, file = path // folder // '/' // fileName, action = 'write') WRITE(20, "(A1, 14X, A5, A20, 40X, A20, 2(A20))") "#","t (s)","density (m^-3)", "velocity (m/s)", & "pressure (Pa)", "temperature (K)" @@ -27,14 +27,17 @@ MODULE moduleMeshOutput0D OPEN(20, file = path // folder // '/' // fileName, position = 'append', action = 'write') CALL calculateOutput(self%nodes(1)%obj%output(i), output, self%nodes(1)%obj%v, species(i)%obj) - WRITE(20, "(7(ES20.6E3))") REAL(t)*tauMin*ti_ref, output%density, output%velocity, output%pressure, output%temperature + WRITE(20, "(7(ES20.6E3))") REAL(timeStep)*tauMin*ti_ref, output%density, & + output%velocity, & + output%pressure, & + output%temperature CLOSE(20) END DO END SUBROUTINE printOutput0D - SUBROUTINE printColl0D(self, t) + SUBROUTINE printColl0D(self) USE moduleMesh USE moduleRefParam USE moduleCaseParam @@ -43,12 +46,11 @@ MODULE moduleMeshOutput0D IMPLICIT NONE CLASS(meshGeneric), INTENT(in):: self - INTEGER, INTENT(in):: t CHARACTER(:), ALLOCATABLE:: fileName INTEGER:: k fileName='OUTPUT_Collisions.dat' - IF (t == tInitial) THEN + IF (timeStep == tInitial) THEN OPEN(20, file = path // folder // '/' // fileName, action = 'write') WRITE(20, "(A1, 14X, A5, A20)") "#","t (s)","collisions" WRITE(*, "(6X,A15,A)") "Creating file: ", fileName @@ -57,12 +59,12 @@ MODULE moduleMeshOutput0D END IF OPEN(20, file = path // folder // '/' // fileName, position = 'append', action = 'write') - WRITE(20, "(ES20.6E3, 10I20)") REAL(t)*tauMin*ti_ref, (self%cells(1)%obj%tallyColl(k)%tally, k=1,nCollPairs) + WRITE(20, "(ES20.6E3, 10I20)") REAL(timeStep)*tauMin*ti_ref, (self%cells(1)%obj%tallyColl(k)%tally, k=1,nCollPairs) CLOSE(20) END SUBROUTINE printColl0D - SUBROUTINE printEM0D(self, t) + SUBROUTINE printEM0D(self) USE moduleMesh USE moduleRefParam USE moduleCaseParam @@ -70,7 +72,6 @@ MODULE moduleMeshOutput0D IMPLICIT NONE CLASS(meshParticles), INTENT(in):: self - INTEGER, INTENT(in):: t END SUBROUTINE printEM0D diff --git a/src/modules/mesh/inout/gmsh2/moduleMeshOutputGmsh2.f90 b/src/modules/mesh/inout/gmsh2/moduleMeshOutputGmsh2.f90 index ccdcf3d..8176bb5 100644 --- a/src/modules/mesh/inout/gmsh2/moduleMeshOutputGmsh2.f90 +++ b/src/modules/mesh/inout/gmsh2/moduleMeshOutputGmsh2.f90 @@ -80,50 +80,50 @@ MODULE moduleMeshOutputGmsh2 END SUBROUTINE writeGmsh2FooterElementData !Prints the scattered properties of particles into the nodes - SUBROUTINE printOutputGmsh2(self, t) + SUBROUTINE printOutputGmsh2(self) USE moduleMesh USE moduleRefParam USE moduleSpecies USE moduleOutput USE moduleMeshInoutCommon + USE moduleCaseParam, ONLY: timeStep IMPLICIT NONE CLASS(meshParticles), INTENT(in):: self - INTEGER, INTENT(in):: t INTEGER:: n, i TYPE(outputFormat):: output(1:self%numNodes) REAL(8):: time CHARACTER(:), ALLOCATABLE:: fileName - time = DBLE(t)*tauMin*ti_ref + time = DBLE(timeStep)*tauMin*ti_ref DO i = 1, nSpecies - fileName = formatFileName(prefix, species(i)%obj%name, 'msh', t) + fileName = formatFileName(prefix, species(i)%obj%name, 'msh', timeStep) WRITE(*, "(6X,A15,A)") "Creating file: ", fileName OPEN (60, file = path // folder // '/' // fileName) CALL writeGmsh2HeaderMesh(60) - CALL writeGmsh2HeaderNodeData(60, species(i)%obj%name // ' density (m^-3)', t, time, 1, self%numNodes) + CALL writeGmsh2HeaderNodeData(60, species(i)%obj%name // ' density (m^-3)', timeStep, time, 1, self%numNodes) DO n=1, self%numNodes CALL calculateOutput(self%nodes(n)%obj%output(i), output(n), self%nodes(n)%obj%v, species(i)%obj) WRITE(60, "(I6,ES20.6E3)") n, output(n)%density END DO CALL writeGmsh2FooterNodeData(60) - CALL writeGmsh2HeaderNodeData(60, species(i)%obj%name // ' velocity (m s^-1)', t, time, 3, self%numNodes) + CALL writeGmsh2HeaderNodeData(60, species(i)%obj%name // ' velocity (m s^-1)', timeStep, time, 3, self%numNodes) DO n=1, self%numNodes WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%velocity END DO CALL writeGmsh2FooterNodeData(60) - CALL writeGmsh2HeaderNodeData(60, species(i)%obj%name // ' Pressure (Pa)', t, time, 1, self%numNodes) + CALL writeGmsh2HeaderNodeData(60, species(i)%obj%name // ' Pressure (Pa)', timeStep, time, 1, self%numNodes) DO n=1, self%numNodes WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%pressure END DO CALL writeGmsh2FooterNodeData(60) - CALL writeGmsh2HeaderNodeData(60, species(i)%obj%name // ' Temperature (K)', t, time, 1, self%numNodes) + CALL writeGmsh2HeaderNodeData(60, species(i)%obj%name // ' Temperature (K)', timeStep, time, 1, self%numNodes) DO n=1, self%numNodes WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%temperature END DO @@ -135,7 +135,7 @@ MODULE moduleMeshOutputGmsh2 END SUBROUTINE printOutputGmsh2 !Prints the number of collisions into the volumes - SUBROUTINE printCollGmsh2(self, t) + SUBROUTINE printCollGmsh2(self) USE moduleMesh USE moduleRefParam USE moduleCaseParam @@ -145,7 +145,6 @@ MODULE moduleMeshOutputGmsh2 IMPLICIT NONE CLASS(meshGeneric), INTENT(in):: self - INTEGER, INTENT(in):: t INTEGER:: numEdges INTEGER:: k, c INTEGER:: n @@ -167,9 +166,9 @@ MODULE moduleMeshOutputGmsh2 END SELECT IF (collOutput) THEN - time = DBLE(t)*tauMin*ti_ref + time = DBLE(timeStep)*tauMin*ti_ref - fileName = formatFileName(prefix, 'Collisions', 'msh', t) + fileName = formatFileName(prefix, 'Collisions', 'msh', timeStep) WRITE(*, "(6X,A15,A)") "Creating file: ", fileName OPEN (60, file = path // folder // '/' // fileName) @@ -179,7 +178,7 @@ MODULE moduleMeshOutputGmsh2 DO c = 1, interactionMatrix(k)%amount WRITE(cString, "(I2)") c title = '"Pair ' // interactionMatrix(k)%sp_i%name // '-' // interactionMatrix(k)%sp_j%name // ' collision ' // cString - CALL writeGmsh2HeaderElementData(60, title, t, time, 1, self%numCells) + CALL writeGmsh2HeaderElementData(60, title, timeStep, time, 1, self%numCells) DO n=1, self%numCells WRITE(60, "(I6,I10)") n + numEdges, self%cells(n)%obj%tallyColl(k)%tally(c) END DO @@ -196,7 +195,7 @@ MODULE moduleMeshOutputGmsh2 END SUBROUTINE printCollGmsh2 !Prints the electrostatic EM properties into the nodes and volumes - SUBROUTINE printEMGmsh2(self, t) + SUBROUTINE printEMGmsh2(self) USE moduleMesh USE moduleRefParam USE moduleCaseParam @@ -205,7 +204,6 @@ MODULE moduleMeshOutputGmsh2 IMPLICIT NONE CLASS(meshParticles), INTENT(in):: self - INTEGER, INTENT(in):: t INTEGER:: n, e REAL(8):: time CHARACTER(:), ALLOCATABLE:: fileName @@ -214,27 +212,27 @@ MODULE moduleMeshOutputGmsh2 Xi = (/ 0.D0, 0.D0, 0.D0 /) IF (emOutput) THEN - time = DBLE(t)*tauMin*ti_ref + time = DBLE(timeStep)*tauMin*ti_ref - fileName = formatFileName(prefix, 'EMField', 'msh', t) + fileName = formatFileName(prefix, 'EMField', 'msh', timeStep) WRITE(*, "(6X,A15,A)") "Creating file: ", fileName OPEN (20, file = path // folder // '/' // fileName) CALL writeGmsh2HeaderMesh(20) - CALL writeGmsh2HeaderNodeData(20, 'Potential (V)', t, time, 1, self%numNodes) + CALL writeGmsh2HeaderNodeData(20, 'Potential (V)', timeStep, time, 1, self%numNodes) DO n=1, self%numNodes WRITE(20, *) n, self%nodes(n)%obj%emData%phi*Volt_ref END DO CALL writeGmsh2FooterNodeData(20) - CALL writeGmsh2HeaderElementData(20, 'Electric Field (V m^-1)', t, time, 3, self%numCells) + CALL writeGmsh2HeaderElementData(20, 'Electric Field (V m^-1)', timeStep, time, 3, self%numCells) DO e=1, self%numCells WRITE(20, *) e+self%numEdges, self%cells(e)%obj%gatherElectricField(Xi)*EF_ref END DO CALL writeGmsh2FooterElementData(20) - CALL writeGmsh2HeaderNodeData(20, 'Magnetic Field (T)', t, time, 3, self%numNodes) + CALL writeGmsh2HeaderNodeData(20, 'Magnetic Field (T)', timeStep, time, 3, self%numNodes) DO n=1, self%numNodes WRITE(20, *) n, self%nodes(n)%obj%emData%B * B_ref END DO diff --git a/src/modules/mesh/inout/moduleMeshInoutCommon.f90 b/src/modules/mesh/inout/moduleMeshInoutCommon.f90 index e4a6c72..7dc2e84 100644 --- a/src/modules/mesh/inout/moduleMeshInoutCommon.f90 +++ b/src/modules/mesh/inout/moduleMeshInoutCommon.f90 @@ -3,17 +3,17 @@ MODULE moduleMeshInoutCommon CHARACTER(LEN=4):: prefix = 'Step' CONTAINS - PURE FUNCTION formatFileName(prefix, suffix, extension, t) RESULT(fileName) + PURE FUNCTION formatFileName(prefix, suffix, extension, timeStep) RESULT(fileName) USE moduleOutput IMPLICIT NONE CHARACTER(*), INTENT(in):: prefix, suffix, extension - INTEGER, INTENT(in), OPTIONAL:: t + INTEGER, INTENT(in), OPTIONAL:: timeStep CHARACTER (LEN=iterationDigits):: tString CHARACTER(:), ALLOCATABLE:: fileName - IF (PRESENT(t)) THEN - WRITE(tString, iterationFormat) t + IF (PRESENT(timeStep)) THEN + WRITE(tString, iterationFormat) timeStep fileName = prefix // '_' // tString // '_' // suffix // '.' // extension ELSE diff --git a/src/modules/mesh/inout/vtu/moduleMeshInputVTU.f90 b/src/modules/mesh/inout/vtu/moduleMeshInputVTU.f90 index 184d645..e07db01 100644 --- a/src/modules/mesh/inout/vtu/moduleMeshInputVTU.f90 +++ b/src/modules/mesh/inout/vtu/moduleMeshInputVTU.f90 @@ -167,7 +167,7 @@ MODULE moduleMeshInputVTU CLASS(meshGeneric), INTENT(inout):: self CHARACTER(:), ALLOCATABLE, INTENT(in):: filename REAL(8):: r(1:3) !3 generic coordinates - INTEGER:: fileID, error, found + INTEGER:: fileID CHARACTER(LEN=256):: line INTEGER:: numNodes, numElements, numEdges INTEGER, ALLOCATABLE, DIMENSION(:):: entitiesID, offsets, connectivity, types diff --git a/src/modules/mesh/inout/vtu/moduleMeshOutputVTU.f90 b/src/modules/mesh/inout/vtu/moduleMeshOutputVTU.f90 index da90b6b..81e4bbf 100644 --- a/src/modules/mesh/inout/vtu/moduleMeshOutputVTU.f90 +++ b/src/modules/mesh/inout/vtu/moduleMeshOutputVTU.f90 @@ -215,17 +215,16 @@ MODULE moduleMeshOutputVTU END SUBROUTINE writeEM - SUBROUTINE writeCollection(fileID, t, fileNameStep, fileNameCollection) + SUBROUTINE writeCollection(fileID, fileNameStep, fileNameCollection) USE moduleCaseParam USE moduleOutput USE moduleRefParam IMPLICIT NONE INTEGER:: fileID - INTEGER, INTENT(in):: t CHARACTER(*):: fileNameStep, fileNameCollection - IF (t == tInitial) THEN + IF (timeStep == tInitial) THEN !Create collection file WRITE(*, "(6X,A15,A)") "Creating file: ", fileNameCollection OPEN (fileID + 1, file = path // folder // '/' // fileNameCollection) @@ -237,10 +236,11 @@ MODULE moduleMeshOutputVTU !Write iteration file in collection OPEN (fileID + 1, file = path // folder // '/' // fileNameCollection, ACCESS='APPEND') - WRITE(fileID + 1, "(4X, A, ES20.6E3, A, A, A)") '' + WRITE(fileID + 1, "(4X, A, ES20.6E3, A, A, A)") & + '' !Close collection file - IF (t == tFinal) THEN + IF (timeStep == tFinal) THEN WRITE (fileID + 1, "(2X, A)") '' WRITE (fileID + 1, "(A)") '' @@ -307,21 +307,21 @@ MODULE moduleMeshOutputVTU END SUBROUTINE writeAverage - SUBROUTINE printOutputVTU(self,t) + SUBROUTINE printOutputVTU(self) USE moduleMesh USE moduleSpecies USE moduleMeshInoutCommon + USE moduleCaseParam, ONLY: timeStep IMPLICIT NONE CLASS(meshParticles), INTENT(in):: self - INTEGER, INTENT(in):: t INTEGER:: i, fileID CHARACTER(:), ALLOCATABLE:: fileName, fileNameCollection fileID = 60 DO i = 1, nSpecies - fileName = formatFileName(prefix, species(i)%obj%name, 'vtu', t) + fileName = formatFileName(prefix, species(i)%obj%name, 'vtu', timeStep) WRITE(*, "(6X,A15,A)") "Creating file: ", fileName OPEN (fileID, file = path // folder // '/' // fileName) @@ -337,28 +337,27 @@ MODULE moduleMeshOutputVTU !Write collection file for time plotting fileNameCollection = formatFileName('Collection', species(i)%obj%name, 'pvd') - CALL writeCollection(fileID, t, fileName, filenameCollection) + CALL writeCollection(fileID, fileName, filenameCollection) END DO END SUBROUTINE printOutputVTU - SUBROUTINE printCollVTU(self,t) + SUBROUTINE printCollVTU(self) USE moduleMesh USE moduleOutput USE moduleMeshInoutCommon + USE moduleCaseParam, ONLY: timeStep IMPLICIT NONE CLASS(meshGeneric), INTENT(in):: self - INTEGER, INTENT(in):: t INTEGER:: fileID CHARACTER(:), ALLOCATABLE:: fileName, fileNameCollection - CHARACTER (LEN=iterationDigits):: tstring fileID = 62 IF (collOutput) THEN - fileName = formatFileName(prefix, 'Collisions', 'vtu', t) + fileName = formatFileName(prefix, 'Collisions', 'vtu', timeStep) WRITE(*, "(6X,A15,A)") "Creating file: ", fileName OPEN (fileID, file = path // folder // '/' // fileName) @@ -374,26 +373,26 @@ MODULE moduleMeshOutputVTU !Write collection file for time plotting fileNameCollection = formatFileName('Collection', 'Collisions', 'pvd') - CALL writeCollection(fileID, t, fileName, filenameCollection) + CALL writeCollection(fileID, fileName, filenameCollection) END IF END SUBROUTINE printCollVTU - SUBROUTINE printEMVTU(self, t) + SUBROUTINE printEMVTU(self) USE moduleMesh USE moduleMeshInoutCommon + USE moduleCaseParam, ONLY: timeStep IMPLICIT NONE CLASS(meshParticles), INTENT(in):: self - INTEGER, INTENT(in):: t INTEGER:: fileID CHARACTER(:), ALLOCATABLE:: fileName, fileNameCollection fileID = 64 IF (emOutput) THEN - fileName = formatFileName(prefix, 'EMField', 'vtu', t) + fileName = formatFileName(prefix, 'EMField', 'vtu', timeStep) WRITE(*, "(6X,A15,A)") "Creating file: ", fileName OPEN (fileID, file = path // folder // '/' // fileName) @@ -409,7 +408,7 @@ MODULE moduleMeshOutputVTU !Write collection file for time plotting fileNameCollection = formatFileName('Collection', 'EMField', 'pvd') - CALL writeCollection(fileID, t, fileName, filenameCollection) + CALL writeCollection(fileID, fileName, filenameCollection) END IF diff --git a/src/modules/mesh/moduleMesh.f90 b/src/modules/mesh/moduleMesh.f90 index ae53aa0..f933dd1 100644 --- a/src/modules/mesh/moduleMesh.f90 +++ b/src/modules/mesh/moduleMesh.f90 @@ -372,10 +372,9 @@ MODULE moduleMesh END SUBROUTINE connectMesh_interface !Prints number of collisions in each cell - SUBROUTINE printColl_interface(self, t) + SUBROUTINE printColl_interface(self) IMPORT meshGeneric CLASS(meshGeneric), INTENT(in):: self - INTEGER, INTENT(in):: t END SUBROUTINE printColl_interface @@ -403,18 +402,16 @@ MODULE moduleMesh ABSTRACT INTERFACE !Prints Species data - SUBROUTINE printOutput_interface(self, t) + SUBROUTINE printOutput_interface(self) IMPORT meshParticles CLASS(meshParticles), INTENT(in):: self - INTEGER, INTENT(in):: t END SUBROUTINE printOutput_interface !Prints EM info - SUBROUTINE printEM_interface(self, t) + SUBROUTINE printEM_interface(self) IMPORT meshParticles CLASS(meshParticles), INTENT(in):: self - INTEGER, INTENT(in):: t END SUBROUTINE printEM_interface @@ -789,7 +786,7 @@ MODULE moduleMesh END FUNCTION findCellBrute !Computes collisions in element - SUBROUTINE doCollisions(self, t) + SUBROUTINE doCollisions(self) USE moduleCollisions USE moduleSpecies USE moduleList @@ -797,10 +794,10 @@ MODULE moduleMesh USE moduleRandom USE moduleOutput USE moduleMath + USE moduleCaseParam, ONLY: timeStep IMPLICIT NONE CLASS(meshGeneric), INTENT(inout), TARGET:: self - INTEGER, INTENT(in):: t INTEGER:: e CLASS(meshCell), POINTER:: cell INTEGER:: k, i, j @@ -816,7 +813,7 @@ MODULE moduleMesh REAL(8):: rnd_real !Random number for collision INTEGER:: rnd_int !Random number for collision - IF (MOD(t, everyColl) == 0) THEN + IF (MOD(timeStep, everyColl) == 0) THEN !Collisions need to be performed in this iteration !$OMP DO SCHEDULE(DYNAMIC) PRIVATE(part_i, part_j, partTemp_i, partTemp_j) DO e=1, self%numCells diff --git a/src/modules/moduleInject.f90 b/src/modules/moduleInject.f90 index 18c7fbb..5b96be2 100644 --- a/src/modules/moduleInject.f90 +++ b/src/modules/moduleInject.f90 @@ -54,7 +54,7 @@ MODULE moduleInject INTEGER:: id CHARACTER(:), ALLOCATABLE:: name REAL(8):: vMod !Velocity (module) - REAL(8):: T(1:3) !Temperature + REAL(8):: temperature(1:3) !Temperature REAL(8):: n(1:3) !Direction of injection LOGICAL:: fixDirection !The injection of particles has a fix direction defined by n INTEGER:: nParticles !Number of particles to introduce each time step @@ -76,7 +76,7 @@ MODULE moduleInject CONTAINS !Initialize an injection of particles - SUBROUTINE initInject(self, i, v, n, T, flow, units, sp, physicalSurface, particlesPerEdge) + SUBROUTINE initInject(self, i, v, n, temperature, flow, units, sp, physicalSurface, particlesPerEdge) USE moduleMesh USE moduleRefParam USE moduleConstParam @@ -87,7 +87,7 @@ MODULE moduleInject CLASS(injectGeneric), INTENT(inout):: self INTEGER, INTENT(in):: i - REAL(8), INTENT(in):: v, n(1:3), T(1:3) + REAL(8), INTENT(in):: v, n(1:3), temperature(1:3) INTEGER, INTENT(in):: sp, physicalSurface, particlesPerEdge REAL(8):: tauInject REAL(8), INTENT(in):: flow @@ -97,10 +97,10 @@ MODULE moduleInject INTEGER:: nVolColl REAL(8):: fluxPerStep = 0.D0 - self%id = i - self%vMod = v / v_ref - self%n = n / NORM2(n) - self%T = T / T_ref + self%id = i + self%vMod = v / v_ref + self%n = n / NORM2(n) + self%temperature = temperature / T_ref !Gets the edge elements from which particles are injected DO e = 1, mesh%numEdges phSurface(e) = mesh%edges(e)%obj%physicalSurface @@ -232,23 +232,23 @@ MODULE moduleInject END SUBROUTINE doInjects - SUBROUTINE initVelDistMaxwellian(velDist, T, m) + SUBROUTINE initVelDistMaxwellian(velDist, temperature, m) IMPLICIT NONE CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist - REAL(8), INTENT(in):: T, m + REAL(8), INTENT(in):: temperature, m - velDist = velDistMaxwellian(vTh = DSQRT(T/m)) + velDist = velDistMaxwellian(vTh = DSQRT(temperature/m)) END SUBROUTINE initVelDistMaxwellian - SUBROUTINE initVelDistHalfMaxwellian(velDist, T, m) + SUBROUTINE initVelDistHalfMaxwellian(velDist, temperature, m) IMPLICIT NONE CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist - REAL(8), INTENT(in):: T, m + REAL(8), INTENT(in):: temperature, m - velDist = velDistHalfMaxwellian(vTh = DSQRT(T/m)) + velDist = velDistHalfMaxwellian(vTh = DSQRT(temperature/m)) END SUBROUTINE initVelDistHalfMaxwellian diff --git a/src/modules/moduleProbe.f90 b/src/modules/moduleProbe.f90 index c29eeda..754d56a 100644 --- a/src/modules/moduleProbe.f90 +++ b/src/modules/moduleProbe.f90 @@ -27,7 +27,7 @@ MODULE moduleProbe CONTAINS !Functions for probeDistFunc type - SUBROUTINE init(self, id, speciesName, r, v1, v2, v3, points, timeStep) + SUBROUTINE init(self, id, speciesName, r, v1, v2, v3, points, everyTimeStep) USE moduleCaseParam USE moduleRefParam USE moduleSpecies @@ -41,7 +41,7 @@ MODULE moduleProbe REAL(8), INTENT(in):: r(1:3) REAL(8), INTENT(in):: v1(1:2), v2(1:2), v3(1:2) INTEGER, INTENT(in):: points(1:3) - REAL(8), INTENT(in):: timeStep + REAL(8), INTENT(in):: everyTimeStep INTEGER:: sp, i REAL(8):: dv(1:3) @@ -91,11 +91,11 @@ MODULE moduleProbe 1:self%nv(3))) !Number of iterations between output - IF (timeStep == 0.D0) THEN + IF (everyTimeStep == 0.D0) THEN self%every = 1 ELSE - self%every = NINT(timeStep/ tauMin / ti_ref) + self%every = NINT(everyTimeStep/ tauMin / ti_ref) END IF @@ -189,13 +189,13 @@ MODULE moduleProbe END SUBROUTINE calculate - SUBROUTINE output(self, t) + SUBROUTINE output(self) USE moduleOutput USE moduleRefParam + USE moduleCaseParam, ONLY: timeStep IMPLICIT NONE CLASS(probeDistFunc), INTENT(inout):: self - INTEGER, INTENT(in):: t CHARACTER (LEN=iterationDigits):: tstring CHARACTER (LEN=3):: pstring CHARACTER(:), ALLOCATABLE:: filename @@ -204,14 +204,14 @@ MODULE moduleProbe !Divide by the velocity cube volume self%f = self%f * self%dvInv - WRITE(tstring, iterationFormat) t + WRITE(tstring, iterationFormat) timeStep WRITE(pstring, "(I3.3)") self%id fileName='Probe_' // tstring// '_f_' // pstring // '.dat' WRITE(*, "(6X,A15,A)") "Creating file: ", fileName OPEN (10, file = path // folder // '/' // fileName) WRITE(10, "(A1, 1X, A)") "# ", self%species%name WRITE(10, "(A6, 3(ES15.6E3), A2)") "# r = ", self%r(:)*L_ref, " m" - WRITE(10, "(A6, ES15.6E3, A2)") "# t = ", REAL(t)*tauMin*ti_ref, " s" + WRITE(10, "(A6, ES15.6E3, A2)") "# t = ", REAL(timeStep)*tauMin*ti_ref, " s" WRITE(10, "(A1, A19, 3(A20))") "#", "v1 (m s^-1)", "v2 (m s^-1)", "v3 (m s^-1)", "f" DO i = 1, self%nv(1) DO j = 1, self%nv(2) @@ -252,15 +252,15 @@ MODULE moduleProbe END SUBROUTINE doProbes - SUBROUTINE outputProbes(t) + SUBROUTINE outputProbes() + USE moduleCaseParam, ONLY: timeStep IMPLICIT NONE - INTEGER, INTENT(in):: t INTEGER:: i DO i = 1, nProbes IF (probe(i)%update) THEN - CALL probe(i)%output(t) + CALL probe(i)%output() END IF @@ -268,15 +268,15 @@ MODULE moduleProbe END SUBROUTINE outputProbes - SUBROUTINE resetProbes(t) + SUBROUTINE resetProbes() + USE moduleCaseParam, ONLY: timeStep IMPLICIT NONE - INTEGER, INTENT(in):: t INTEGER:: i DO i = 1, nProbes probe(i)%f = 0.D0 - probe(i)%update = t == tFinal .OR. t == tInitial .OR. MOD(t, probe(i)%every) == 0 + probe(i)%update = timeStep == tFinal .OR. timeStep == tInitial .OR. MOD(timeStep, probe(i)%every) == 0 END DO diff --git a/src/modules/output/moduleOutput.f90 b/src/modules/output/moduleOutput.f90 index 18fbb7f..e6dc91f 100644 --- a/src/modules/output/moduleOutput.f90 +++ b/src/modules/output/moduleOutput.f90 @@ -160,12 +160,12 @@ MODULE moduleOutput END SUBROUTINE calculateOutput - SUBROUTINE printTime(t, first) + SUBROUTINE printTime(first) USE moduleSpecies USE moduleCompTime + USE moduleCaseParam, ONLY: timeStep IMPLICIT NONE - INTEGER, INTENT(in):: t LOGICAL, INTENT(in), OPTIONAL:: first CHARACTER(:), ALLOCATABLE:: fileName @@ -187,7 +187,7 @@ MODULE moduleOutput OPEN(20, file = path // folder // '/' // fileName, position = 'append', action = 'write') - WRITE (20, "(I10, I10, 7(ES20.6E3))") t, nPartOld, tStep, tPush, tReset, tColl, tCoul, tWeight, tEMField + WRITE (20, "(I10, I10, 7(ES20.6E3))") timeStep, nPartOld, tStep, tPush, tReset, tColl, tCoul, tWeight, tEMField CLOSE(20) diff --git a/src/modules/solver/electromagnetic/moduleEM.f90 b/src/modules/solver/electromagnetic/moduleEM.f90 index a141eac..30a23ad 100644 --- a/src/modules/solver/electromagnetic/moduleEM.f90 +++ b/src/modules/solver/electromagnetic/moduleEM.f90 @@ -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 diff --git a/src/modules/solver/moduleSolver.f90 b/src/modules/solver/moduleSolver.f90 index 0b2837f..5928508 100644 --- a/src/modules/solver/moduleSolver.f90 +++ b/src/modules/solver/moduleSolver.f90 @@ -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 -- 2.49.1 From 10dee05922e17d72258fbd432ed1c689f08571ba Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Fri, 12 Jul 2024 23:30:35 +0200 Subject: [PATCH 5/8] NOT WORKING: Compilation okay, but not Dirichlet BC The code compiles but the right BC is not being applied to the vectorF. I'll check this tomorrow. --- src/modules/init/moduleInput.f90 | 12 +- .../solver/electromagnetic/moduleEM.f90 | 126 ++++++++++++------ 2 files changed, 92 insertions(+), 46 deletions(-) diff --git a/src/modules/init/moduleInput.f90 b/src/modules/init/moduleInput.f90 index 6800ac1..eea1937 100644 --- a/src/modules/init/moduleInput.f90 +++ b/src/modules/init/moduleInput.f90 @@ -1148,8 +1148,8 @@ MODULE moduleInput CHARACTER(:), ALLOCATABLE:: typeEM REAL(8):: potential INTEGER:: physicalSurface - CHARACTER(:), ALLOCATABLE:: timeProfile - INTEGER:: b, e, s, n, ni + CHARACTER(:), ALLOCATABLE:: temporalProfile + INTEGER:: b, s, n, ni CHARACTER(2):: bString INTEGER:: info EXTERNAL:: dgetrf @@ -1187,12 +1187,20 @@ MODULE moduleInput END IF + CALL config%get(object // '.temporalProfile', temporalProfile, found) + IF (.NOT. found) THEN + CALL criticalError('Required parameter "potential" for Dirichlet boundary condition not found', 'readEMBoundary') + + END IF + CALL config%get(object // '.physicalSurface', physicalSurface, found) IF (.NOT. found) THEN CALL criticalError('Required parameter "physicalSurface" for Dirichlet boundary condition not found', 'readEMBoundary') END IF + CALL initDirichletTime(boundaryEM(b)%obj, physicalSurface, potential, temporalProfile) + CASE DEFAULT CALL criticalError('Boundary type ' // typeEM // ' not yet supported', 'readEMBoundary') diff --git a/src/modules/solver/electromagnetic/moduleEM.f90 b/src/modules/solver/electromagnetic/moduleEM.f90 index 30a23ad..b480330 100644 --- a/src/modules/solver/electromagnetic/moduleEM.f90 +++ b/src/modules/solver/electromagnetic/moduleEM.f90 @@ -66,20 +66,65 @@ MODULE moduleEM REAL(8), ALLOCATABLE:: qSpecies(:) CONTAINS - ! Initialize Dirichlet boundary condition - SUBROUTINE initDirichlet(self, physicalSurface, potential) + SUBROUTINE findNodes(self, physicalSurface) USE moduleMesh - USE moduleRefParam, ONLY: Volt_ref IMPLICIT NONE - CLASS(boundaryEMGeneric), ALLOCATABLE, INTENT(out):: self - INTEGER:: physicalSurface - REAL(8), INTENT(in):: potential + 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)) + 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) @@ -87,48 +132,39 @@ MODULE moduleEM 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 + 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 @@ -140,6 +176,7 @@ MODULE moduleEM 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 @@ -156,7 +193,8 @@ MODULE moduleEM INTEGER:: n, ni DO n = 1, self%nNodes - self%nodes(n)%obj%emData%phi = self%potential + self%nodes(n)%obj%emData%phi = self%potential !TODO: Correct for time + vectorF(self%nodes(n)%obj%n) = self%nodes(n)%obj%emData%phi END DO -- 2.49.1 From 2d4b405fb10f203b72a456871ac7bba26c328c1c Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Sat, 13 Jul 2024 12:06:41 +0200 Subject: [PATCH 6/8] Functionality added Now we have a new boundary condition that can change the value of the potential in a surface based on a file. --- src/modules/init/moduleInput.f90 | 25 ++++++++++++------- .../solver/electromagnetic/moduleEM.f90 | 7 ++++-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/modules/init/moduleInput.f90 b/src/modules/init/moduleInput.f90 index eea1937..b5f6881 100644 --- a/src/modules/init/moduleInput.f90 +++ b/src/modules/init/moduleInput.f90 @@ -1137,7 +1137,6 @@ MODULE moduleInput USE moduleOutput USE moduleErrors USE moduleEM - USE moduleRefParam USE moduleSpecies USE json_module IMPLICIT NONE @@ -1148,7 +1147,7 @@ MODULE moduleInput CHARACTER(:), ALLOCATABLE:: typeEM REAL(8):: potential INTEGER:: physicalSurface - CHARACTER(:), ALLOCATABLE:: temporalProfile + CHARACTER(:), ALLOCATABLE:: temporalProfile, temporalProfilePath INTEGER:: b, s, n, ni CHARACTER(2):: bString INTEGER:: info @@ -1156,11 +1155,14 @@ MODULE moduleInput CALL config%info('boundaryEM', found, n_children = nBoundaryEM) - IF (found) ALLOCATE(boundaryEM(1:nBoundaryEM)) + IF (found) THEN + ALLOCATE(boundaryEM(1:nBoundaryEM)) + + END IF DO b = 1, nBoundaryEM WRITE(bString, '(I2)') b - object = 'boundaryEM(' // trim(bString) // ')' + object = 'boundaryEM(' // TRIM(bString) // ')' CALL config%get(object // '.type', typeEM, found) @@ -1174,7 +1176,8 @@ MODULE moduleInput CALL config%get(object // '.physicalSurface', physicalSurface, found) IF (.NOT. found) THEN - CALL criticalError('Required parameter "physicalSurface" for Dirichlet boundary condition not found', 'readEMBoundary') + CALL criticalError('Required parameter "physicalSurface" for Dirichlet boundary condition not found', & + 'readEMBoundary') END IF @@ -1183,23 +1186,27 @@ MODULE moduleInput CASE ("dirichletTime") CALL config%get(object // '.potential', potential, found) IF (.NOT. found) THEN - CALL criticalError('Required parameter "potential" for Dirichlet boundary condition not found', 'readEMBoundary') + CALL criticalError('Required parameter "potential" for Dirichlet Time boundary condition not found', & + 'readEMBoundary') END IF CALL config%get(object // '.temporalProfile', temporalProfile, found) IF (.NOT. found) THEN - CALL criticalError('Required parameter "potential" for Dirichlet boundary condition not found', 'readEMBoundary') + CALL criticalError('Required parameter "temporalProfile" for Dirichlet Time boundary condition not found', & + 'readEMBoundary') END IF + temporalProfilePath = path // temporalProfile CALL config%get(object // '.physicalSurface', physicalSurface, found) IF (.NOT. found) THEN - CALL criticalError('Required parameter "physicalSurface" for Dirichlet boundary condition not found', 'readEMBoundary') + CALL criticalError('Required parameter "physicalSurface" for Dirichlet Time boundary condition not found', & + 'readEMBoundary') END IF - CALL initDirichletTime(boundaryEM(b)%obj, physicalSurface, potential, temporalProfile) + CALL initDirichletTime(boundaryEM(b)%obj, physicalSurface, potential, temporalProfilePath) CASE DEFAULT CALL criticalError('Boundary type ' // typeEM // ' not yet supported', 'readEMBoundary') diff --git a/src/modules/solver/electromagnetic/moduleEM.f90 b/src/modules/solver/electromagnetic/moduleEM.f90 index b480330..703b31c 100644 --- a/src/modules/solver/electromagnetic/moduleEM.f90 +++ b/src/modules/solver/electromagnetic/moduleEM.f90 @@ -109,6 +109,7 @@ MODULE moduleEM ! 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 @@ -190,10 +191,13 @@ MODULE moduleEM 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 !TODO: Correct for time + self%nodes(n)%obj%emData%phi = self%potential * timeFactor vectorF(self%nodes(n)%obj%n) = self%nodes(n)%obj%emData%phi END DO @@ -274,7 +278,6 @@ MODULE moduleEM ALLOCATE(tempF(1:mesh%numNodes)) !$OMP END SINGLE - !TODO: Is this done every time step??? Then things are gonna be really simple. CALL assembleSourceVector(tempF) !$OMP SINGLE -- 2.49.1 From e4dfba45f8c109748bed005549fd540183543a70 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Sat, 13 Jul 2024 12:13:39 +0200 Subject: [PATCH 7/8] Manual updated New dirichletTime condition is documented. --- doc/user-manual/fpakc_UserManual.pdf | Bin 186195 -> 187186 bytes doc/user-manual/fpakc_UserManual.tex | 18 +++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/doc/user-manual/fpakc_UserManual.pdf b/doc/user-manual/fpakc_UserManual.pdf index ef1494ac62b3a07c882225d34ac2998d565ae727..1666f42de4b56c9b9e049349df1126da6f6f973f 100644 GIT binary patch delta 23768 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 BX|MnQ delta 22743 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�ROsR%jeE-0^P7;y1mUrPre6LOZ?-mUxyFYN8H zsUGV|;X1<)WHfVcq_)Eg)FK1xf#H(CzaVg0Mgt!B-~T_^fcHiK0;u5{N%(U_dJn1`RkXfq?zV2hiY zgu}pC#=+5W2=?LsAs7J$V+lq;U|44nP!zTo;3zD?NXY-)2iX6QhCrCGynsL5^(6hz4{;jqa={naYBMHtpkHV5IB|)Bn*UMF~A2xVkwA(L$SPt zM4@!7!=>pdtSBj3H3(fR0EE4S@?G*oVOg%yxv%HAbf5UOXh*keUZ-o6jd;fC+jKb`ezzPXPVJZ!Sp}_wNZ(4aL9tj$b zc^eW1Mq-%(0UYwZbLnS0Iy96Kv0>U%{ z=o^^L91I2i!Q=x$pqM2C+y|5Rmka(A1b~RZZ2ACA0`>>vMV3Oarw!1JvCl%m*k^(1 zh2bqQ2nqwEv4lY3m~I6a5lC!4Bm|p=LSWHgAgu8Ufv;i(efMHmI5fCIs z@C4CVc_IPC5K~V8S70_OkObo5)0;nghy)S~F95?Gt0F-XNaSBS{Wm3m_6^7MI0*1K zRw6@yo{p(B1Ofjy%DGSq43a=$gdd;6VwX$^Q{15CDn)dlvoQ zlmO;CrWZgc@PCE}aQwfO3qTUAcp`xA@OO^=a~~8F|A8-{F@}O@fC%)0KQ#nH;6NY8 zpdp|j><){9VS-WMJ~(zr0051FD*!%V1aSQyApYArz=J^h!w?L>1bl4+sYOIEG-L z?ZVQi-{R2ngqy|GS zqJ0taf5jXE#ws}gQG)*CD!>VUy8wIvGcmdh;1&rGMjZltSaA8m1(0i69~ zp}YtJa3Kti6*wSnSb@73Lw{NaD2T*dhk*Nl4{847yP#pVMnFLXE+}nx7>^eHKRk*2 zA6`RZCm00Sy)b1#fkuo)1A>o119IuF9&+QKC;$@~3z2~V{DgTJ$p8N#7=}vgdWT1s zMm+==g@qr$P$X7^0%+L%3D|+L90*h^W`6?1z*wUIm}q~Ef`4rT01>No1F#ws%m76L z#Tt@8zrbt>z}y7=iTp3J2uPwol)lI<;Eeg21XFp z3IouvRv2KLf?#a}01>;2fdPw^Kk$qC1^)ZDf^ZNV6Z8O2b65}n$g;mf@(=Vw0cD3d zb%DtJFB(=A1Kz@VQUY|wf{0)MQvB&b0Q!O9a4hHt(6GBDfVHub3y!sh0C9(6jSMgx ziCI~|l!JpYp&tkiFk-tJfM6J|h5+S@(PjW=A+Qq@c42Ax8H~Cu#3M>J_@&W>@ z0Rw`uIzI>jEc%$90nEViAV32Q`Okp;r?CNO0rQmw@C<Il#Yfw^e|G+w^ z;I#vT4+I#DnJmDoCt%+H-S^+w2waG@L0-_X3ldoVG2#gzaKPCZ3PJ!Bjgid&g2C)8 z7qbz_Q%ptx(qp}Bfl+YmszU)^P{I%l20r${C~ZInHaZ1X1TZMA<^vuL8i8pLuoe7w zeEt2<0MM}N2m*rr_2m0ce+S-nv2+4xSoS~=e?KMuQv|?9CV}-f2}MG%XaE$%cwhqd zNg&5CdNeSvfe>Oi2mmO58V3{s7)TSWhf)A|V1*S9uwi-&Xi-?p5dsj6#RniQ%*X&U z34v7v7vC+zWR!paAO2xj0s+*<$)P#`H0@-VPGFyfH1(*Iu$6Eay@ cGItLPHxC~-8(T79lmPE6Wc>WfH&w{~A3jogl>h($ diff --git a/doc/user-manual/fpakc_UserManual.tex b/doc/user-manual/fpakc_UserManual.tex index 13be4cd..e572331 100644 --- a/doc/user-manual/fpakc_UserManual.tex +++ b/doc/user-manual/fpakc_UserManual.tex @@ -585,12 +585,20 @@ make Type of boundary. Accepted values are: \begin{itemize} - \item \textbf{dirichlet}: Elastic reflection of particles. + \item \textbf{dirichlet}: Constant value of electric potential on the surface. + \item \textbf{dirichletTime}: Constant value of the electric potential with a time variable profile. + The value of \textbf{boundaryEM.potential} will be multiplied for the corresponding value in the file \textbf{boundaryEM.temporalProfile}. \end{itemize} - \item \textbf{potential}: Real. - Fixed potential for Dirichlet boundary condition. + \item \textbf{potential}: Real. + Fixed potential for Dirichlet boundary condition. \item \textbf{physicalSurface}: Integer. Identification of the edge in the mesh file. + \item \textbf{temporalProfile}: Character. + Filename of the 2 column file containing the time variable profile. + File must be located in \textbf{output.path}. + The first column is the time in $\unit{s}$. + The second column is the factor that will multiply the value of the boundary. + \end{itemize} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -611,7 +619,7 @@ make \begin{itemize} \item \textbf{A}: Ampere. \item \textbf{Am2}: Ampere per square meter. - This value will be multiplied by the surface of injection. + This value will be multiplied by the area of injection. \item \textbf{sccm}: Standard cubic centimetre. \item \textbf{part/s}: Particles (real) per second. \end{itemize} @@ -717,7 +725,7 @@ make Output file from previous run used as an initial state for the species. The file format must be the same as in \textbf{geometry.meshType} Initial particles are assumed to have a Maxwellian distribution. - File must be located at \textbf{output.path}. + File must be located in \textbf{output.path}. \item \textbf{particlesPerCell}: Integer. Optional. Initial number of particles per cell. -- 2.49.1 From 6f185c418846a518a1afb338e71ab3204b869188 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Sat, 13 Jul 2024 12:35:42 +0200 Subject: [PATCH 8/8] Organizing things Move the array of pointers to the nodes to moduleMesh. --- src/modules/mesh/moduleMesh.f90 | 7 +++++++ src/modules/solver/electromagnetic/moduleEM.f90 | 8 -------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/modules/mesh/moduleMesh.f90 b/src/modules/mesh/moduleMesh.f90 index f933dd1..7ab3914 100644 --- a/src/modules/mesh/moduleMesh.f90 +++ b/src/modules/mesh/moduleMesh.f90 @@ -59,6 +59,13 @@ MODULE moduleMesh END TYPE meshNodeCont + ! Array of pointers to nodes. + TYPE:: meshNodePointer + CLASS(meshNode), POINTER:: obj + CONTAINS + + END TYPE meshNodePointer + !Type for array of boundary functions (one per species) TYPE, PUBLIC:: fBoundaryGeneric PROCEDURE(boundary_interface), POINTER, NOPASS:: apply => NULL() diff --git a/src/modules/solver/electromagnetic/moduleEM.f90 b/src/modules/solver/electromagnetic/moduleEM.f90 index 703b31c..126f9a6 100644 --- a/src/modules/solver/electromagnetic/moduleEM.f90 +++ b/src/modules/solver/electromagnetic/moduleEM.f90 @@ -4,14 +4,6 @@ MODULE moduleEM USE moduleTable IMPLICIT NONE - ! Array of pointers to nodes. - !TODO: This is probably better in moduleMesh as multiple modules could use this. - TYPE:: meshNodePointer - CLASS(meshNode), POINTER:: obj - CONTAINS - - END TYPE meshNodePointer - ! Generic type for electromagnetic boundary conditions TYPE, PUBLIC, ABSTRACT:: boundaryEMGeneric INTEGER:: nNodes -- 2.49.1