From 1b864d6bedb071cb82b2041f16c60222a332da50 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Mon, 6 Apr 2026 18:01:48 +0200 Subject: [PATCH 01/10] Skeleton of functions --- src/modules/mesh/moduleMesh.f90 | 29 ++++ src/modules/mesh/moduleMesh@boundaryEM.f90 | 153 +++++++++++++++------ 2 files changed, 137 insertions(+), 45 deletions(-) diff --git a/src/modules/mesh/moduleMesh.f90 b/src/modules/mesh/moduleMesh.f90 index 6cc48ee..d27c1db 100644 --- a/src/modules/mesh/moduleMesh.f90 +++ b/src/modules/mesh/moduleMesh.f90 @@ -990,6 +990,7 @@ MODULE moduleMesh end interface ! Extended types + ! Dirichlet: Constant potential value TYPE, EXTENDS(boundaryEMGeneric):: boundaryEMDirichlet REAL(8):: potential CONTAINS @@ -1016,6 +1017,7 @@ MODULE moduleMesh end interface + ! Dirichlet time: time-dependent potential value TYPE, EXTENDS(boundaryEMGeneric):: boundaryEMDirichletTime real(8):: potential real(8):: timeFactor @@ -1044,6 +1046,33 @@ MODULE moduleMesh end interface + ! Floating: Floating surface, ie, zero net current + type, extends(boundaryEMGeneric):: boundaryEMFloating + real(8):: potential + contains + ! boundaryEMGeneric DEFERRED PROCEDURES + procedure, pass:: apply => applyFloating + + end type boundaryEMFloating + + interface + module subroutine initFloating(self, config, object) + use json_module + + class(boundaryEMGeneric), allocatable, intent(inout):: self + type(json_file), intent(inout):: config + character(:), allocatable, intent(in):: object + + end subroutine initFloating + + module subroutine applyFloating(self, vectorF) + class(boundaryEMFloating), intent(in):: self + real(8), intent(inout):: vectorF(:) + + end subroutine applyFloating + + end interface + ! Container for boundary conditions TYPE:: boundaryEMCont CLASS(boundaryEMGeneric), ALLOCATABLE:: obj diff --git a/src/modules/mesh/moduleMesh@boundaryEM.f90 b/src/modules/mesh/moduleMesh@boundaryEM.f90 index 8640d24..5e30627 100644 --- a/src/modules/mesh/moduleMesh@boundaryEM.f90 +++ b/src/modules/mesh/moduleMesh@boundaryEM.f90 @@ -1,30 +1,7 @@ submodule(moduleMesh) boundaryEM CONTAINS - module function boundaryEMName_to_Index(boundaryName) result(bp) - use moduleErrors - implicit none - - character(:), allocatable:: boundaryName - integer:: bp - integer:: b - - bp = 0 - do b = 1, nBoundariesEM - if (boundaryName == boundariesEM(b)%obj%name) then - bp = boundariesEM(b)%obj%n - - end if - - end do - - if (bp == 0) then - call criticalError('Boundary ' // boundaryName // ' not found', 'boundaryEMName_to_Index') - - end if - - end function boundaryEMName_to_Index - - ! Initialize Dirichlet boundary condition + ! Dirichlet boundary condition + ! Init module SUBROUTINE initDirichlet(self, config, object) use json_module USE moduleRefParam, ONLY: Volt_ref @@ -51,7 +28,25 @@ submodule(moduleMesh) boundaryEM end subroutine initDirichlet - ! Initialize Dirichlet boundary condition + ! Apply + module SUBROUTINE applyDirichlet(self, vectorF) + USE moduleMesh + IMPLICIT NONE + + CLASS(boundaryEMDirichlet), INTENT(in):: self + REAL(8), INTENT(inout):: vectorF(:) + integer:: n + + 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 + + ! Dirichlet time-dependent boundary condition + ! Init module subroutine initDirichletTime(self, config, object) use json_module use moduleRefParam, ONLY: Volt_ref, ti_ref @@ -96,24 +91,7 @@ submodule(moduleMesh) boundaryEM END SUBROUTINE initDirichletTime - !Apply Dirichlet boundary condition to the poisson equation - module SUBROUTINE applyDirichlet(self, vectorF) - USE moduleMesh - IMPLICIT NONE - - CLASS(boundaryEMDirichlet), INTENT(in):: self - REAL(8), INTENT(inout):: vectorF(:) - integer:: n - - 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 + ! Apply module SUBROUTINE applyDirichletTime(self, vectorF) USE moduleMesh USE moduleCaseParam, ONLY: timeStep, tauMin @@ -131,7 +109,8 @@ submodule(moduleMesh) boundaryEM END SUBROUTINE applyDirichletTime - module subroutine updateDirichletTime(self) + ! Update + subroutine updateDirichletTime(self) implicit none class(boundaryEMGeneric), intent(inout):: self @@ -144,6 +123,90 @@ submodule(moduleMesh) boundaryEM end subroutine updateDirichletTime + ! Floating surface + ! Init + module subroutine initFloating(self, config, object) + use json_module + use moduleRefParam, only: Volt_ref + use moduleErrors + implicit none + + class(boundaryEMGeneric), allocatable, intent(inout):: self + type(json_file), intent(inout):: config + character(:), allocatable, intent(in):: object + real(8):: potential + logical:: found + + select type(self) + type is(boundaryEMFloating) + call config%get(object // '.potential', potential, found) + if (.not. found) then + call criticalError('Required parameter "potential" for Floating boundary condition not found', & + 'readBoundaryEM') + + end if + + self%potential = potential / Volt_ref + + self%update => updateFloating + + end select + + end subroutine initFloating + + ! Apply + module subroutine applyFloating(self, vectorF) + use moduleMesh + implicit none + + class(boundaryEMFloating), intent(in):: self + real(8), intent(inout):: vectorF(:) + integer:: n + + 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 applyFloating + + ! Update + subroutine updateFloating(self) + class(boundaryEMGeneric), intent(inout):: self + select type(self) + type is(boundaryEMFloating) + + end select + + end subroutine updateFloating + + ! Get the index of the boundary based on the name + module function boundaryEMName_to_Index(boundaryName) result(bp) + use moduleErrors + implicit none + + character(:), allocatable:: boundaryName + integer:: bp + integer:: b + + bp = 0 + do b = 1, nBoundariesEM + if (boundaryName == boundariesEM(b)%obj%name) then + bp = boundariesEM(b)%obj%n + + end if + + end do + + if (bp == 0) then + call criticalError('Boundary ' // boundaryName // ' not found', 'boundaryEMName_to_Index') + + end if + + end function boundaryEMName_to_Index + + ! Update all EM boundaries module subroutine boundariesEM_update() implicit none From 2291236efb54b15e7251f9bf345fa82dc89c3457 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Tue, 7 Apr 2026 09:37:10 +0200 Subject: [PATCH 02/10] Input for floating boundary --- src/modules/init/moduleInput.f90 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/modules/init/moduleInput.f90 b/src/modules/init/moduleInput.f90 index eb8bde5..93bb51f 100644 --- a/src/modules/init/moduleInput.f90 +++ b/src/modules/init/moduleInput.f90 @@ -969,17 +969,20 @@ MODULE moduleInput select case(bType) case ("dirichlet") - ! Allocate boundary edge allocate(boundaryEMDirichlet:: self) CALL initDirichlet(self, config, object) case ("dirichlettime") - ! Allocate boundary edge allocate(boundaryEMDirichletTime:: self) call initDirichletTime(self, config, object) + case ("floating") + allocate(boundaryEMFloating:: self) + + call initFloating(self, config, object) + case default call criticalError('Boundary type ' // bType // ' not supported', 'readBoundaryEM') From 40163a0056ed0c89cf7dd2fbccb5517280d6504c Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Tue, 7 Apr 2026 12:28:29 +0200 Subject: [PATCH 03/10] Calculating current in node. Maybe it should be on edge. Need to check. --- src/modules/init/moduleInput.f90 | 10 ++++++++ src/modules/mesh/moduleMesh@boundaryEM.f90 | 27 ++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/modules/init/moduleInput.f90 b/src/modules/init/moduleInput.f90 index 93bb51f..be92b31 100644 --- a/src/modules/init/moduleInput.f90 +++ b/src/modules/init/moduleInput.f90 @@ -1361,6 +1361,16 @@ MODULE moduleInput end do + type is(boundaryEMFloating) + ! Loop over all physical surfaces + do ps = 1, nPhysicalSurfaces + ! If the boundary for the species is linked to the one analysing, add the edges + if (associated(physicalSurfaces(ps)%EM, bound)) then + bound%nodes = [bound%nodes, physicalSurfaces(ps)%nodes] + end if + + end do + end select bound%nNodes = size(bound%nodes) diff --git a/src/modules/mesh/moduleMesh@boundaryEM.f90 b/src/modules/mesh/moduleMesh@boundaryEM.f90 index 5e30627..3b52c78 100644 --- a/src/modules/mesh/moduleMesh@boundaryEM.f90 +++ b/src/modules/mesh/moduleMesh@boundaryEM.f90 @@ -173,9 +173,36 @@ submodule(moduleMesh) boundaryEM ! Update subroutine updateFloating(self) + use moduleMesh, only: qSpecies, meshNode + implicit none + class(boundaryEMGeneric), intent(inout):: self + integer:: n, s + integer, allocatable:: nodes(:) + class(meshNode), pointer:: node + real(8):: momNode, momNodeTotal, totalCurrent + + totalCurrent = 0.0d0 select type(self) type is(boundaryEMFloating) + do n = 1, self%nNodes + momNodeTotal = 0.0d0 + + node => self%nodes(n)%obj + + do s = 1, nSpecies + print *, s, node%output(s)%mom + momNode = norm2(node%output(s)%mom) + + momNodeTotal = momNodeTotal + qSpecies(s) * momNode + + end do + + totalCurrent = totalCurrent + momNodeTotal + + end do + + print *, totalCurrent end select From eb10ae92a621b4562b7e903256d4aa85387bb3f1 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 8 Apr 2026 15:17:30 +0200 Subject: [PATCH 04/10] It seems to work, but I don't think this is quite useful for the manuscript --- src/modules/init/moduleInput.f90 | 2 + src/modules/mesh/moduleMesh.f90 | 16 ++++++ src/modules/mesh/moduleMesh@boundaryEM.f90 | 57 +++++++++++++++++----- src/modules/mesh/moduleMesh@elements.f90 | 8 +++ 4 files changed, 71 insertions(+), 12 deletions(-) diff --git a/src/modules/init/moduleInput.f90 b/src/modules/init/moduleInput.f90 index be92b31..575b372 100644 --- a/src/modules/init/moduleInput.f90 +++ b/src/modules/init/moduleInput.f90 @@ -1367,6 +1367,8 @@ MODULE moduleInput ! If the boundary for the species is linked to the one analysing, add the edges if (associated(physicalSurfaces(ps)%EM, bound)) then bound%nodes = [bound%nodes, physicalSurfaces(ps)%nodes] + + bound%edges = [bound%edges, physicalSurfaces(ps)%edges] end if end do diff --git a/src/modules/mesh/moduleMesh.f90 b/src/modules/mesh/moduleMesh.f90 index d27c1db..aa20a2b 100644 --- a/src/modules/mesh/moduleMesh.f90 +++ b/src/modules/mesh/moduleMesh.f90 @@ -964,6 +964,7 @@ MODULE moduleMesh type(meshNodePointer), allocatable:: nodes(:) procedure(updateEM_interface), pointer, pass:: update => null() + procedure(printEM_interface), pointer, pass:: print => null() contains procedure(applyEM_interface), deferred, pass:: apply @@ -987,6 +988,15 @@ MODULE moduleMesh end subroutine updateEM_interface + ! Write the values of the particle boundary model + subroutine printEM_interface(self, fileID) + import boundaryEMGeneric + + class(boundaryEMGeneric), intent(inout):: self + integer, intent(in):: fileID + + end subroutine printEM_interface + end interface ! Extended types @@ -1049,6 +1059,8 @@ MODULE moduleMesh ! Floating: Floating surface, ie, zero net current type, extends(boundaryEMGeneric):: boundaryEMFloating real(8):: potential + real(8):: invC ! Inverse of the capacitance of the surface + type(meshEdgePointer), allocatable:: edges(:) !Array with edges contains ! boundaryEMGeneric DEFERRED PROCEDURES procedure, pass:: apply => applyFloating @@ -1097,6 +1109,10 @@ MODULE moduleMesh end subroutine boundariesEM_update + module subroutine boundariesEM_write() + + end subroutine boundariesEM_write + end interface ! PHYSICAL SURFACES LINKING TO MESH ELEMENTS diff --git a/src/modules/mesh/moduleMesh@boundaryEM.f90 b/src/modules/mesh/moduleMesh@boundaryEM.f90 index 3b52c78..e45f996 100644 --- a/src/modules/mesh/moduleMesh@boundaryEM.f90 +++ b/src/modules/mesh/moduleMesh@boundaryEM.f90 @@ -127,14 +127,15 @@ submodule(moduleMesh) boundaryEM ! Init module subroutine initFloating(self, config, object) use json_module - use moduleRefParam, only: Volt_ref + use moduleRefParam, only: Volt_ref, L_ref + use moduleConstParam, only: eps_0 use moduleErrors implicit none class(boundaryEMGeneric), allocatable, intent(inout):: self type(json_file), intent(inout):: config character(:), allocatable, intent(in):: object - real(8):: potential + real(8):: potential, capacitance logical:: found select type(self) @@ -148,8 +149,20 @@ submodule(moduleMesh) boundaryEM self%potential = potential / Volt_ref + call config%get(object // '.capacitance', capacitance, found) + if (.not. found) then + call warningError('Parameter "capacitance" for floating boundary condition not found. Using the default value of 1 nF.') + capacitance = 1.0d-9 + + end if + + ! Inverse of non-dimensional capacitance + self%invC = 1.0d0 / (capacitance / (eps_0 * L_ref)) + self%update => updateFloating + allocate(self%edges(0)) + end select end subroutine initFloating @@ -174,40 +187,60 @@ submodule(moduleMesh) boundaryEM ! Update subroutine updateFloating(self) use moduleMesh, only: qSpecies, meshNode + use moduleCaseParam, only: tauMin implicit none class(boundaryEMGeneric), intent(inout):: self - integer:: n, s + integer:: e, n, s integer, allocatable:: nodes(:) + class(meshEdge), pointer:: edge + real(8), allocatable:: mom_nodes(:) class(meshNode), pointer:: node - real(8):: momNode, momNodeTotal, totalCurrent + real(8):: mom_center, edgeDensityCurrent, totalCurrent totalCurrent = 0.0d0 select type(self) type is(boundaryEMFloating) - do n = 1, self%nNodes - momNodeTotal = 0.0d0 + do e = 1, size(self%edges) + edge => self%edges(e)%obj - node => self%nodes(n)%obj + edgeDensityCurrent = 0.0d0 + nodes = edge%getNodes(edge%nNodes) + allocate(mom_nodes(1:edge%nNodes)) do s = 1, nSpecies - print *, s, node%output(s)%mom - momNode = norm2(node%output(s)%mom) + mom_center = 0.0d0 + do n = 1, self%nNodes + node => mesh%nodes(nodes(n))%obj - momNodeTotal = momNodeTotal + qSpecies(s) * momNode + ! Minus sign to get the flux exiting the edge + mom_nodes(n) = - dot_product(node%output(s)%mom, edge%normal) + + end do + + mom_center = edge%gatherF(edge%centerXi(), edge%nNodes, mom_nodes) + + edgeDensityCurrent = edgeDensityCurrent + qSpecies(s) * mom_center end do - totalCurrent = totalCurrent + momNodeTotal + totalCurrent = totalCurrent + edgeDensityCurrent * edge%surface end do - print *, totalCurrent + self%potential = self%potential + self%invC * totalCurrent * tauMin + + ! print *, totalCurrent, self%potential end select end subroutine updateFloating + ! Write + subroutine writeFloating() + + end subroutine writeFloating + ! Get the index of the boundary based on the name module function boundaryEMName_to_Index(boundaryName) result(bp) use moduleErrors diff --git a/src/modules/mesh/moduleMesh@elements.f90 b/src/modules/mesh/moduleMesh@elements.f90 index 5eadf28..b947278 100644 --- a/src/modules/mesh/moduleMesh@elements.f90 +++ b/src/modules/mesh/moduleMesh@elements.f90 @@ -176,6 +176,14 @@ submodule(moduleMesh) elements END DO + TYPE IS(boundaryEMFloating) + DO n = 1, boundary%nNodes + ni = boundary%nodes(n)%obj%n + self%K(ni, :) = 0.D0 + self%K(ni, ni) = 1.D0 + + END DO + END SELECT END DO From 12b427eaa03e7018182d82cb22d25f8fc47e1e0d Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 8 Apr 2026 15:22:23 +0200 Subject: [PATCH 05/10] Missing alignment --- src/modules/output/moduleOutput.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/output/moduleOutput.f90 b/src/modules/output/moduleOutput.f90 index 3011396..d9fb91f 100644 --- a/src/modules/output/moduleOutput.f90 +++ b/src/modules/output/moduleOutput.f90 @@ -34,7 +34,7 @@ MODULE moduleOutput integer, parameter:: fileID_output = 20 ! Base id for species/collisions/EM output integer, parameter:: fileID_boundaryParticle = 30 ! Particle boundaries integer, parameter:: fileID_boundaryEM = 31 ! EM boundaries - integer, parameter:: fileID_inject = 32 ! Injects + integer, parameter:: fileID_inject = 32 ! Injects integer, parameter:: fileID_reference = 40 ! Reference values integer, parameter:: fileID_time =50 ! Computation time From 9f7b73054b3ddb615f719ddc6cbdebe6f8bda5cf Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 8 Apr 2026 15:44:16 +0200 Subject: [PATCH 06/10] Double import --- src/fpakc.f90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fpakc.f90 b/src/fpakc.f90 index cb68754..7726329 100644 --- a/src/fpakc.f90 +++ b/src/fpakc.f90 @@ -25,7 +25,6 @@ PROGRAM fpakc doAverage, & doInjects use moduleMesh, only: boundariesEM_update, & - boundariesEM_update, & boundariesParticle_update, & mesh, & meshForMCC, & From 73f585ed8b130072361478b6059f763992171523 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 8 Apr 2026 15:47:36 +0200 Subject: [PATCH 07/10] Inout working --- src/modules/init/moduleInput.f90 | 1 + src/modules/mesh/moduleMesh.f90 | 9 +-- src/modules/mesh/moduleMesh@boundaryEM.f90 | 66 +++++++++++++++++++--- src/modules/output/moduleOutput.f90 | 1 + src/modules/solver/moduleSolver.f90 | 1 + 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/modules/init/moduleInput.f90 b/src/modules/init/moduleInput.f90 index 575b372..19a4369 100644 --- a/src/modules/init/moduleInput.f90 +++ b/src/modules/init/moduleInput.f90 @@ -493,6 +493,7 @@ MODULE moduleInput CALL config%get(object // '.numColl', collOutput, found) CALL config%get(object // '.EMField', emOutput, found) call config%get(object // '.boundariesParticle', boundaryParticleOutput, found) + call config%get(object // '.boundariesEM', boundaryEMOutput, found) call config%get(object // '.injects', injectOutput, found) CALL config%get(object // '.triggerCPUTime', triggerCPUTime, found) diff --git a/src/modules/mesh/moduleMesh.f90 b/src/modules/mesh/moduleMesh.f90 index aa20a2b..e257cf2 100644 --- a/src/modules/mesh/moduleMesh.f90 +++ b/src/modules/mesh/moduleMesh.f90 @@ -963,8 +963,8 @@ MODULE moduleMesh integer:: nNodes type(meshNodePointer), allocatable:: nodes(:) - procedure(updateEM_interface), pointer, pass:: update => null() - procedure(printEM_interface), pointer, pass:: print => null() + procedure(updateEM_interface), pointer, pass:: update => null() + procedure(printEMboundary_interface), pointer, pass:: print => null() contains procedure(applyEM_interface), deferred, pass:: apply @@ -989,13 +989,13 @@ MODULE moduleMesh end subroutine updateEM_interface ! Write the values of the particle boundary model - subroutine printEM_interface(self, fileID) + subroutine printEMboundary_interface(self, fileID) import boundaryEMGeneric class(boundaryEMGeneric), intent(inout):: self integer, intent(in):: fileID - end subroutine printEM_interface + end subroutine printEMboundary_interface end interface @@ -1060,6 +1060,7 @@ MODULE moduleMesh type, extends(boundaryEMGeneric):: boundaryEMFloating real(8):: potential real(8):: invC ! Inverse of the capacitance of the surface + real(8):: charge ! Charge accumulated on surface type(meshEdgePointer), allocatable:: edges(:) !Array with edges contains ! boundaryEMGeneric DEFERRED PROCEDURES diff --git a/src/modules/mesh/moduleMesh@boundaryEM.f90 b/src/modules/mesh/moduleMesh@boundaryEM.f90 index e45f996..43202b4 100644 --- a/src/modules/mesh/moduleMesh@boundaryEM.f90 +++ b/src/modules/mesh/moduleMesh@boundaryEM.f90 @@ -159,8 +159,12 @@ submodule(moduleMesh) boundaryEM ! Inverse of non-dimensional capacitance self%invC = 1.0d0 / (capacitance / (eps_0 * L_ref)) + self%charge = 0.0d0 + self%update => updateFloating + self%print => writeFloating + allocate(self%edges(0)) end select @@ -196,9 +200,8 @@ submodule(moduleMesh) boundaryEM class(meshEdge), pointer:: edge real(8), allocatable:: mom_nodes(:) class(meshNode), pointer:: node - real(8):: mom_center, edgeDensityCurrent, totalCurrent + real(8):: mom_center, edgeDensityCurrent - totalCurrent = 0.0d0 select type(self) type is(boundaryEMFloating) do e = 1, size(self%edges) @@ -224,20 +227,34 @@ submodule(moduleMesh) boundaryEM end do - totalCurrent = totalCurrent + edgeDensityCurrent * edge%surface + ! Accumulate charge of speceis on surface + self%charge = self%charge + edgeDensityCurrent * edge%surface * tauMin end do - self%potential = self%potential + self%invC * totalCurrent * tauMin - - ! print *, totalCurrent, self%potential + self%potential = self%charge * self%invC end select end subroutine updateFloating ! Write - subroutine writeFloating() + subroutine writeFloating(self, fileID) + use moduleOutput, only: fmtColReal + use moduleConstParam, only: qe + use moduleRefParam, only: Volt_ref + implicit none + + class(boundaryEMGeneric), intent(inout):: self + integer, intent(in):: fileID + + write(fileID, '(A)') self%name + select type(self) + type is(boundaryEMFloating) + write(fileID, '(A,",",A)') 'Total charge', 'Potential (V)' + write(fileID, '('//fmtColReal//','//fmtColReal//')') self%charge * qe, self%potential * Volt_ref + + end select end subroutine writeFloating @@ -274,7 +291,7 @@ submodule(moduleMesh) boundaryEM do b = 1, nBoundariesEM if (associated(boundariesEM(b)%obj%update)) then - call boundariesEM(b)%obj%update + call boundariesEM(b)%obj%update() end if @@ -282,4 +299,37 @@ submodule(moduleMesh) boundaryEM end subroutine boundariesEM_update + ! Write all EM boundaries + module subroutine boundariesEM_write() + use moduleCaseparam, only: timeStep + use moduleOutput, only: fileID_boundaryEM, & + formatFileName, & + informFileCreation,& + boundaryEMOutput,& + generateFilePath, & + prefix + implicit none + + integer:: b + character(:), allocatable:: fileName + + if (boundaryEMOutput) then + fileName = formatFileName(prefix, 'boundariesEM', 'csv', timeStep) + call informFileCreation(fileName) + open(fileID_boundaryEM, file = generateFilePath(fileName)) + + do b = 1, nBoundariesEM + if (associated(boundariesEM(b)%obj%update)) then + call boundariesEM(b)%obj%print(fileID_boundaryEM) + + end if + + end do + + close(fileID_boundaryEM) + + end if + + end subroutine boundariesEM_write + end submodule boundaryEM diff --git a/src/modules/output/moduleOutput.f90 b/src/modules/output/moduleOutput.f90 index d9fb91f..bf75c27 100644 --- a/src/modules/output/moduleOutput.f90 +++ b/src/modules/output/moduleOutput.f90 @@ -14,6 +14,7 @@ MODULE moduleOutput LOGICAL:: collOutput = .FALSE. LOGICAL:: emOutput = .FALSE. logical:: boundaryParticleOutput = .false. + logical:: boundaryEMOutput = .false. logical:: injectOutput = .false. ! Prefix for iteration files diff --git a/src/modules/solver/moduleSolver.f90 b/src/modules/solver/moduleSolver.f90 index 635c9eb..33e3408 100644 --- a/src/modules/solver/moduleSolver.f90 +++ b/src/modules/solver/moduleSolver.f90 @@ -548,6 +548,7 @@ MODULE moduleSolver ! Output of boundaries call boundariesParticle_write() + call boundariesEM_write() ! Output of inejcts call writeInjects() From f35d6138087d80a0d627e2519f874e5671f08e28 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 8 Apr 2026 18:36:57 +0200 Subject: [PATCH 08/10] txs auto checkin --- doc/user-manual/fpakc_UserManual.tex | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/user-manual/fpakc_UserManual.tex b/doc/user-manual/fpakc_UserManual.tex index 75f0106..5368d1c 100644 --- a/doc/user-manual/fpakc_UserManual.tex +++ b/doc/user-manual/fpakc_UserManual.tex @@ -626,6 +626,14 @@ make 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 set in \textbf{potential}. + + \item \textbf{floating}: The potential is adjusted over time to maintain a zero current on the surface, \textit{i. e.}, the surface is \textit{floating}. + \textbf{potential}: Real. + Potential for Dirichlet boundary condition. + + \textbf{capacitance}: Real. + Capacitance of the surface in Farads. + If none is provided, a default value of $1$ nF is used. \end{itemize} From f81c42a6da3b1da7ae4106ad5921b3b8e6a89fec Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 8 Apr 2026 20:07:57 +0200 Subject: [PATCH 09/10] txs auto checkin --- doc/user-manual/fpakc_UserManual.tex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/user-manual/fpakc_UserManual.tex b/doc/user-manual/fpakc_UserManual.tex index 5368d1c..c43fb65 100644 --- a/doc/user-manual/fpakc_UserManual.tex +++ b/doc/user-manual/fpakc_UserManual.tex @@ -629,7 +629,8 @@ make \item \textbf{floating}: The potential is adjusted over time to maintain a zero current on the surface, \textit{i. e.}, the surface is \textit{floating}. \textbf{potential}: Real. - Potential for Dirichlet boundary condition. + Initial potential of the surface. + The initial charge value for the simulation will be calculated by the potential times the capacitance. \textbf{capacitance}: Real. Capacitance of the surface in Farads. From a1f94c1e4d8ae8d39aef9bec308d3d4f785415a4 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 8 Apr 2026 20:17:49 +0200 Subject: [PATCH 10/10] Adjusted initial condition, dimensions of output, and output file header --- src/modules/mesh/moduleMesh@boundaryEM.f90 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/modules/mesh/moduleMesh@boundaryEM.f90 b/src/modules/mesh/moduleMesh@boundaryEM.f90 index 43202b4..c43dd8e 100644 --- a/src/modules/mesh/moduleMesh@boundaryEM.f90 +++ b/src/modules/mesh/moduleMesh@boundaryEM.f90 @@ -159,7 +159,7 @@ submodule(moduleMesh) boundaryEM ! Inverse of non-dimensional capacitance self%invC = 1.0d0 / (capacitance / (eps_0 * L_ref)) - self%charge = 0.0d0 + self%charge = self%potential / self%invC self%update => updateFloating @@ -222,6 +222,9 @@ submodule(moduleMesh) boundaryEM end do mom_center = edge%gatherF(edge%centerXi(), edge%nNodes, mom_nodes) + + ! Only account for charge exiting the surface + mom_center = max(mom_center, 0.0d0) edgeDensityCurrent = edgeDensityCurrent + qSpecies(s) * mom_center @@ -242,7 +245,7 @@ submodule(moduleMesh) boundaryEM subroutine writeFloating(self, fileID) use moduleOutput, only: fmtColReal use moduleConstParam, only: qe - use moduleRefParam, only: Volt_ref + use moduleRefParam, only: Volt_ref, v_ref, n_ref, L_ref, ti_ref implicit none class(boundaryEMGeneric), intent(inout):: self @@ -251,8 +254,8 @@ submodule(moduleMesh) boundaryEM write(fileID, '(A)') self%name select type(self) type is(boundaryEMFloating) - write(fileID, '(A,",",A)') 'Total charge', 'Potential (V)' - write(fileID, '('//fmtColReal//','//fmtColReal//')') self%charge * qe, self%potential * Volt_ref + write(fileID, '(A,",",A)') 'Total charge (C)', 'Potential (V)' + write(fileID, '(*('//fmtColReal//'))') self%charge*qe*v_ref*n_ref*L_ref**2*ti_ref, self%potential * Volt_ref end select