From 555ebd6771c8f7111b6f5a6a9289b1c1a24fb272 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Tue, 31 Mar 2026 18:37:23 +0200 Subject: [PATCH 01/21] Obtain quasi-neutrality by changing the injection flow From d3f1f0808e3cdffc1b9b365239c70fbb23da2bac Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Tue, 31 Mar 2026 19:21:03 +0200 Subject: [PATCH 02/21] Skeleton for new injection type --- src/fpakc.f90 | 3 +++ src/modules/init/moduleInput.f90 | 8 +++++++- src/modules/moduleInject.f90 | 28 +++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/fpakc.f90 b/src/fpakc.f90 index 921d4ac..48c3657 100644 --- a/src/fpakc.f90 +++ b/src/fpakc.f90 @@ -71,6 +71,9 @@ PROGRAM fpakc ! Update EM boundary models call boundariesEM_update() + ! Update injects + call updateInjects + !Checks if a species needs to me moved in this iteration CALL solver%updatePushSpecies() diff --git a/src/modules/init/moduleInput.f90 b/src/modules/init/moduleInput.f90 index 8b7aaff..4f4abae 100644 --- a/src/modules/init/moduleInput.f90 +++ b/src/modules/init/moduleInput.f90 @@ -1432,6 +1432,7 @@ MODULE moduleInput REAL(8), ALLOCATABLE:: temperature(:), normal(:) REAL(8):: flow CHARACTER(:), ALLOCATABLE:: units + character(:), allocatable:: type INTEGER:: physicalSurface INTEGER:: particlesPerEdge INTEGER:: sp @@ -1457,11 +1458,16 @@ MODULE moduleInput END IF CALL config%get(object // '.flow', flow, found) CALL config%get(object // '.units', units, found) + CALL config%get(object // '.type', type, found) + if (.not. found) then + ! If no type is found, assume constant injection of particles + type = 'constant' + end if CALL config%get(object // '.physicalSurface', physicalSurface, found) particlesPerEdge = 0 CALL config%get(object // '.particlesPerEdge', particlesPerEdge, found) - CALL inject(i)%init(i, v, normal, temperature, flow, units, sp, physicalSurface, particlesPerEdge) + CALL inject(i)%init(i, v, normal, temperature, flow, units, type, sp, physicalSurface, particlesPerEdge) CALL readVelDistr(config, inject(i), object) diff --git a/src/modules/moduleInject.f90 b/src/modules/moduleInject.f90 index d22258a..1b64e67 100644 --- a/src/modules/moduleInject.f90 +++ b/src/modules/moduleInject.f90 @@ -14,6 +14,7 @@ MODULE moduleInject LOGICAL:: fixDirection !The injection of particles has a fix direction defined by n INTEGER:: nParticles !Number of particles to introduce each time step CLASS(speciesGeneric), POINTER:: species !Species of injection + character(:), allocatable:: type INTEGER:: nEdges type(meshEdgePointer), allocatable:: edges(:) INTEGER, ALLOCATABLE:: particlesPerEdge(:) ! Particles per edge @@ -31,7 +32,7 @@ MODULE moduleInject CONTAINS !Initialize an injection of particles - SUBROUTINE initInject(self, i, v, n, temperature, flow, units, sp, ps, particlesPerEdge) + SUBROUTINE initInject(self, i, v, n, temperature, flow, units, type, sp, ps, particlesPerEdge) USE moduleMesh USE moduleRefParam USE moduleConstParam @@ -48,6 +49,7 @@ MODULE moduleInject REAL(8):: tauInject REAL(8), INTENT(in):: flow CHARACTER(:), ALLOCATABLE, INTENT(in):: units + character(:), allocatable, intent(in):: type INTEGER:: e REAL(8):: fluxPerStep = 0.D0 @@ -143,6 +145,14 @@ MODULE moduleInject !Scale particles for different species steps IF (self%nParticles == 0) CALL criticalError("The number of particles for inject is 0.", 'initInject') + ! Assign type to inject + select case(type) + case ('constant', 'quasiNeutral') + self%type = type + case default + call criticalError('No injection type ' // type // ' defined', 'initInject') + end select + END SUBROUTINE initInject !Injection of particles @@ -176,6 +186,22 @@ MODULE moduleInject END SUBROUTINE doInjects + ! Update the value of injects + subroutine updateInjects() + implicit none + + integer:: i + + do i = 1, nInject + select case(inject(i)%type) + case ('quasiNeutral') + print*, "Calculating quasi-neutrality" + + end select + end do + + end subroutine updateInjects + SUBROUTINE initVelDistMaxwellian(velDist, temperature, m) IMPLICIT NONE From 891da162cc73e99c8d05fc8d95b5c34ded18919f Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Tue, 31 Mar 2026 19:44:15 +0200 Subject: [PATCH 03/21] Working, but I think I need to redo the injection module to make it more flexible --- src/modules/moduleInject.f90 | 59 ++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/src/modules/moduleInject.f90 b/src/modules/moduleInject.f90 index 1b64e67..427b3ce 100644 --- a/src/modules/moduleInject.f90 +++ b/src/modules/moduleInject.f90 @@ -28,7 +28,7 @@ MODULE moduleInject END TYPE injectGeneric INTEGER:: nInject - TYPE(injectGeneric), ALLOCATABLE:: inject(:) + TYPE(injectGeneric), ALLOCATABLE, target:: inject(:) CONTAINS !Initialize an injection of particles @@ -188,14 +188,67 @@ MODULE moduleInject ! Update the value of injects subroutine updateInjects() + use moduleMesh, only: meshEdge, meshNode, mesh, qSpecies implicit none - integer:: i + integer:: i, e, s, n + class(injectGeneric), pointer:: self + integer, allocatable:: nodes(:) + class(meshEdge), pointer:: edge + real(8), allocatable:: density_nodes(:) + class(meshNode), pointer:: node + real(8):: den_center + real(8):: density_incident, density_rest + real(8):: alpha do i = 1, nInject + self => inject(i) select case(inject(i)%type) case ('quasiNeutral') - print*, "Calculating quasi-neutrality" + do e = 1, self%nEdges + edge => self%edges(e)%obj + + density_incident = 0.d0 + density_rest = 0.d0 + + nodes = edge%getNodes(edge%nNodes) + allocate(density_nodes(1:edge%nNodes)) + do s = 1, nSpecies + do n = 1, edge%nNodes + node => mesh%nodes(nodes(n))%obj + + density_nodes(n) = node%output(s)%den + + end do + + ! Gather the density at the edge center and multiply by the species charge + den_center = qSpecies(s)*edge%gatherF(edge%centerXi(), edge%nNodes, density_nodes) + + if (s == self%species%n) then + density_incident = den_center + + else + density_rest = density_rest + den_center + + end if + + end do + + ! Correction for this time step + if (density_rest > 1.0d-10) then + ! If there is a rest population, correct + alpha = 1.d0 + density_incident/density_rest + + else + ! If not, alpha is assumed unchaged + alpha = 0.d0 + + end if + + ! Adjust the weight of particles to match the new current + self%weightPerEdge(e) = self%weightPerEdge(e) + 1.0d-2 * alpha + + end do end select end do From d680112764b61676868b578fb493751ae4fb14ae Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Tue, 31 Mar 2026 19:58:00 +0200 Subject: [PATCH 04/21] Reorganization of boundaries Particles --- src/modules/mesh/moduleMesh.f90 | 229 +++++++++++++++++--------------- 1 file changed, 123 insertions(+), 106 deletions(-) diff --git a/src/modules/mesh/moduleMesh.f90 b/src/modules/mesh/moduleMesh.f90 index 7ce7565..76e2367 100644 --- a/src/modules/mesh/moduleMesh.f90 +++ b/src/modules/mesh/moduleMesh.f90 @@ -663,50 +663,6 @@ MODULE moduleMesh end type boundaryParticleGeneric - interface - ! Init interfaces - ! wallTemeprature - module subroutine wallTemperature_init(boundary, T, c) - CLASS(boundaryParticleGeneric), ALLOCATABLE, INTENT(inout):: boundary - REAL(8), INTENT(in):: T, c !Wall temperature and specific heat - - end subroutine wallTemperature_init - - module subroutine ionization_init(boundary, mImpact, m0, n0, v0, T0, ion, effTime, crossSection, eThreshold, electronSecondary) - class(boundaryParticleGeneric), allocatable, intent(inout):: boundary - real(8), intent(in):: mImpact - real(8), intent(in):: m0, n0, v0(1:3), T0 !Neutral properties - integer, intent(in):: ion - real(8), intent(in):: effTime - character(:), allocatable, intent(in):: crossSection - real(8), intent(in):: eThreshold - integer, optional, intent(in):: electronSecondary - - end subroutine ionization_init - - ! quasiNeutrality - module subroutine quasiNeutrality_init(boundary, s_incident) - class(boundaryParticleGeneric), allocatable, intent(inout):: boundary - integer, intent(in):: s_incident - - end subroutine quasiNeutrality_init - - ! outflowAdaptive - module subroutine outflowAdaptive_init(boundary, s_incident) - class(boundaryParticleGeneric), allocatable, intent(inout):: boundary - integer, intent(in):: s_incident - - end subroutine outflowAdaptive_init - - ! Get the index of the species from its name - module function boundaryParticleName_to_Index(boundaryName) result(bp) - character(:), allocatable:: boundaryName - integer:: bp - - end function boundaryParticleName_to_Index - - end interface - abstract interface ! Apply the effects of the boundary to the particle subroutine applyParticle_interface(self, edge, part) @@ -745,6 +701,18 @@ MODULE moduleMesh END TYPE boundaryReflection + interface + module subroutine reflection_apply(self, edge, part) + use moduleSpecies + + class(boundaryReflection), intent(inout):: self + class(meshEdge), intent(inout):: edge + class(particle), intent(inout):: part + + end subroutine reflection_apply + + end interface + !Absorption boundary TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryAbsorption CONTAINS @@ -752,6 +720,18 @@ MODULE moduleMesh END TYPE boundaryAbsorption + interface + module subroutine absorption_apply(self, edge, part) + use moduleSpecies + + class(boundaryAbsorption), intent(inout):: self + class(meshEdge), intent(inout):: edge + class(particle), intent(inout):: part + + end subroutine absorption_apply + + end interface + !Transparent boundary TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryTransparent CONTAINS @@ -759,6 +739,18 @@ MODULE moduleMesh END TYPE boundaryTransparent + interface + module subroutine transparent_apply(self, edge, part) + use moduleSpecies + + class(boundaryTransparent), intent(inout):: self + class(meshEdge), intent(inout):: edge + class(particle), intent(inout):: part + + end subroutine transparent_apply + + end interface + !Symmetry axis TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryAxis CONTAINS @@ -766,6 +758,18 @@ MODULE moduleMesh END TYPE boundaryAxis + interface + module subroutine symmetryAxis_apply(self, edge, part) + use moduleSpecies + + class(boundaryAxis), intent(inout):: self + class(meshEdge), intent(inout):: edge + class(particle), intent(inout):: part + + end subroutine symmetryAxis_apply + + end interface + !Wall Temperature boundary TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryWallTemperature !Thermal velocity of the wall: square root(Wall temperature X specific heat) @@ -775,6 +779,24 @@ MODULE moduleMesh END TYPE boundaryWallTemperature + interface + module subroutine wallTemperature_init(boundary, T, c) + CLASS(boundaryParticleGeneric), ALLOCATABLE, INTENT(inout):: boundary + REAL(8), INTENT(in):: T, c !Wall temperature and specific heat + + end subroutine wallTemperature_init + + module subroutine wallTemperature_apply(self, edge, part) + use moduleSpecies + + class(boundaryWallTemperature), intent(inout):: self + class(meshEdge), intent(inout):: edge + class(particle), intent(inout):: part + + end subroutine wallTemperature_apply + + end interface + !Ionization boundary TYPE, PUBLIC, EXTENDS(boundaryParticleGeneric):: boundaryIonization REAL(8):: m0, n0, v0(1:3), vTh !Properties of background neutrals. @@ -791,6 +813,30 @@ MODULE moduleMesh END TYPE boundaryIonization + interface + module subroutine ionization_init(boundary, mImpact, m0, n0, v0, T0, ion, effTime, crossSection, eThreshold, electronSecondary) + class(boundaryParticleGeneric), allocatable, intent(inout):: boundary + real(8), intent(in):: mImpact + real(8), intent(in):: m0, n0, v0(1:3), T0 !Neutral properties + integer, intent(in):: ion + real(8), intent(in):: effTime + character(:), allocatable, intent(in):: crossSection + real(8), intent(in):: eThreshold + integer, optional, intent(in):: electronSecondary + + end subroutine ionization_init + + module subroutine ionization_apply(self, edge, part) + use moduleSpecies + + class(boundaryIonization), intent(inout):: self + class(meshEdge), intent(inout):: edge + class(particle), intent(inout):: part + + end subroutine ionization_apply + + end interface + ! Ensures quasi-neutrality by changing the reflection coefficient type, public, extends(boundaryParticleGeneric):: boundaryQuasiNeutrality real(8), allocatable:: alpha(:) ! Reflection parameter @@ -801,6 +847,24 @@ MODULE moduleMesh end type boundaryQuasiNeutrality + interface + module subroutine quasiNeutrality_init(boundary, s_incident) + class(boundaryParticleGeneric), allocatable, intent(inout):: boundary + integer, intent(in):: s_incident + + end subroutine quasiNeutrality_init + + module subroutine quasiNeutrality_apply(self, edge, part) + use moduleSpecies + + class(boundaryQuasiNeutrality), intent(inout):: self + class(meshEdge), intent(inout):: edge + class(particle), intent(inout):: part + + end subroutine quasiNeutrality_apply + + end interface + !Boundary for quasi-neutral outflow adjusting reflection coefficient type, public, extends(boundaryParticleGeneric):: boundaryOutflowAdaptive real(8), allocatable:: velocity_shift(:) @@ -812,68 +876,11 @@ MODULE moduleMesh end type boundaryOutflowAdaptive interface - module subroutine reflection_apply(self, edge, part) - use moduleSpecies + module subroutine outflowAdaptive_init(boundary, s_incident) + class(boundaryParticleGeneric), allocatable, intent(inout):: boundary + integer, intent(in):: s_incident - class(boundaryReflection), intent(inout):: self - class(meshEdge), intent(inout):: edge - class(particle), intent(inout):: part - - end subroutine reflection_apply - - module subroutine absorption_apply(self, edge, part) - use moduleSpecies - - class(boundaryAbsorption), intent(inout):: self - class(meshEdge), intent(inout):: edge - class(particle), intent(inout):: part - - end subroutine absorption_apply - - module subroutine transparent_apply(self, edge, part) - use moduleSpecies - - class(boundaryTransparent), intent(inout):: self - class(meshEdge), intent(inout):: edge - class(particle), intent(inout):: part - - end subroutine transparent_apply - - module subroutine symmetryAxis_apply(self, edge, part) - use moduleSpecies - - class(boundaryAxis), intent(inout):: self - class(meshEdge), intent(inout):: edge - class(particle), intent(inout):: part - - end subroutine symmetryAxis_apply - - module subroutine wallTemperature_apply(self, edge, part) - use moduleSpecies - - class(boundaryWallTemperature), intent(inout):: self - class(meshEdge), intent(inout):: edge - class(particle), intent(inout):: part - - end subroutine wallTemperature_apply - - module subroutine ionization_apply(self, edge, part) - use moduleSpecies - - class(boundaryIonization), intent(inout):: self - class(meshEdge), intent(inout):: edge - class(particle), intent(inout):: part - - end subroutine ionization_apply - - module subroutine quasiNeutrality_apply(self, edge, part) - use moduleSpecies - - class(boundaryQuasiNeutrality), intent(inout):: self - class(meshEdge), intent(inout):: edge - class(particle), intent(inout):: part - - end subroutine quasiNeutrality_apply + end subroutine outflowAdaptive_init module subroutine outflowAdaptive_apply(self, edge, part) use moduleSpecies @@ -884,7 +891,10 @@ MODULE moduleMesh end subroutine outflowAdaptive_apply - ! Generic basic boundary conditions to use internally in the code + end interface + + ! Generic basic boundary conditions to use internally in the code + interface module subroutine genericReflection(edge, part) use moduleSpecies @@ -927,6 +937,13 @@ MODULE moduleMesh type(boundaryParticleCont), allocatable, target:: boundariesParticle(:) interface + ! Get the index of the species from its name + module function boundaryParticleName_to_Index(boundaryName) result(bp) + character(:), allocatable:: boundaryName + integer:: bp + + end function boundaryParticleName_to_Index + ! Update the particle boundary models module subroutine boundariesParticle_update() From f400bd46eb85d925e8f2b4c0f95a5ec204348913 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Tue, 31 Mar 2026 20:00:20 +0200 Subject: [PATCH 05/21] Reorganization of boundaries EM --- src/modules/mesh/moduleMesh.f90 | 62 ++++++++++++++++----------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/modules/mesh/moduleMesh.f90 b/src/modules/mesh/moduleMesh.f90 index 76e2367..b14b4f8 100644 --- a/src/modules/mesh/moduleMesh.f90 +++ b/src/modules/mesh/moduleMesh.f90 @@ -969,33 +969,6 @@ MODULE moduleMesh end type boundaryEMGeneric - interface - module subroutine initDirichlet(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 initDirichlet - - module subroutine initDirichletTime(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 initDirichletTime - - module function boundaryEMName_to_Index(boundaryName) result(bp) - character(:), allocatable:: boundaryName - integer:: bp - - end function boundaryEMName_to_Index - - end interface - abstract interface ! Apply boundary condition to the load vector for the Poission equation subroutine applyEM_interface(self, vectorF) @@ -1025,6 +998,24 @@ MODULE moduleMesh END TYPE boundaryEMDirichlet + interface + module subroutine initDirichlet(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 initDirichlet + + module subroutine applyDirichlet(self, vectorF) + class(boundaryEMDirichlet), intent(in):: self + real(8), intent(inout):: vectorF(:) + + end subroutine applyDirichlet + + end interface + TYPE, EXTENDS(boundaryEMGeneric):: boundaryEMDirichletTime real(8):: potential real(8):: timeFactor @@ -1036,11 +1027,14 @@ MODULE moduleMesh END TYPE boundaryEMDirichletTime interface - module subroutine applyDirichlet(self, vectorF) - class(boundaryEMDirichlet), intent(in):: self - real(8), intent(inout):: vectorF(:) + module subroutine initDirichletTime(self, config, object) + use json_module - end subroutine applyDirichlet + class(boundaryEMGeneric), allocatable, intent(inout):: self + type(json_file), intent(inout):: config + character(:), allocatable, intent(in):: object + + end subroutine initDirichletTime module subroutine applyDirichletTime(self, vectorF) class(boundaryEMDirichletTime), intent(in):: self @@ -1064,6 +1058,12 @@ MODULE moduleMesh ! Update the EM boundary models interface + module function boundaryEMName_to_Index(boundaryName) result(bp) + character(:), allocatable:: boundaryName + integer:: bp + + end function boundaryEMName_to_Index + module subroutine boundariesEM_update() end subroutine boundariesEM_update From 04cd9dffc669713addd4343b7ff76a75e7bc31b6 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 1 Apr 2026 16:19:16 +0200 Subject: [PATCH 06/21] Implementing output for injects. Cleaning code --- src/fpakc.f90 | 2 +- src/modules/common/moduleRandom.f90 | 2 +- src/modules/init/moduleInput.f90 | 42 +- .../mesh/inout/text/moduleMeshOutputText.f90 | 11 +- .../mesh/inout/vtu/moduleMeshOutputVTU.f90 | 7 +- src/modules/mesh/moduleMesh.f90 | 2 +- src/modules/mesh/moduleMesh@boundaryEM.f90 | 1 + .../mesh/moduleMesh@boundaryParticle.f90 | 12 +- src/modules/moduleInject.f90 | 371 ++++++++++++------ src/modules/output/moduleOutput.f90 | 2 + 10 files changed, 283 insertions(+), 169 deletions(-) diff --git a/src/fpakc.f90 b/src/fpakc.f90 index 48c3657..feee89a 100644 --- a/src/fpakc.f90 +++ b/src/fpakc.f90 @@ -72,7 +72,7 @@ PROGRAM fpakc call boundariesEM_update() ! Update injects - call updateInjects + call updateInjects() !Checks if a species needs to me moved in this iteration CALL solver%updatePushSpecies() diff --git a/src/modules/common/moduleRandom.f90 b/src/modules/common/moduleRandom.f90 index 1b8ec67..f4dcc46 100644 --- a/src/modules/common/moduleRandom.f90 +++ b/src/modules/common/moduleRandom.f90 @@ -53,7 +53,7 @@ MODULE moduleRandom implicit none real(8):: rnd - real(8):: v1, v2, Rsquare + real(8):: v1, v2 v1 = 0.d0 do while (v1 <= 0.d0) diff --git a/src/modules/init/moduleInput.f90 b/src/modules/init/moduleInput.f90 index 4f4abae..1b4ff21 100644 --- a/src/modules/init/moduleInput.f90 +++ b/src/modules/init/moduleInput.f90 @@ -628,6 +628,7 @@ MODULE moduleInput USE moduleMesh USE moduleCaseParam USE moduleRefParam + use moduleOutput, only: collOutput USE OMP_LIB USE json_module IMPLICIT NONE @@ -1426,50 +1427,17 @@ MODULE moduleInput CHARACTER(2):: iString CHARACTER(:), ALLOCATABLE:: object LOGICAL:: found - CHARACTER(:), ALLOCATABLE:: speciesName - CHARACTER(:), ALLOCATABLE:: name - REAL(8):: v - REAL(8), ALLOCATABLE:: temperature(:), normal(:) - REAL(8):: flow - CHARACTER(:), ALLOCATABLE:: units - character(:), allocatable:: type - INTEGER:: physicalSurface - INTEGER:: particlesPerEdge - INTEGER:: sp CALL config%info('inject', found, n_children = nInject) - ALLOCATE(inject(1:nInject)) + ALLOCATE(injects(1:nInject)) nPartInj = 0 DO i = 1, nInject WRITE(iString, '(i2)') i object = 'inject(' // trim(iString) // ')' - !Find species - CALL config%get(object // '.species', speciesName, found) - sp = speciesName2Index(speciesName) + CALL initInject(injects(i)%obj, i, object, config) - CALL config%get(object // '.name', name, found) - CALL config%get(object // '.v', v, found) - CALL config%get(object // '.T', temperature, found) - CALL config%get(object // '.n', normal, found) - IF (.NOT. found) THEN - ALLOCATE(normal(1:3)) - normal = 0.D0 - END IF - CALL config%get(object // '.flow', flow, found) - CALL config%get(object // '.units', units, found) - CALL config%get(object // '.type', type, found) - if (.not. found) then - ! If no type is found, assume constant injection of particles - type = 'constant' - end if - CALL config%get(object // '.physicalSurface', physicalSurface, found) - particlesPerEdge = 0 - CALL config%get(object // '.particlesPerEdge', particlesPerEdge, found) - - CALL inject(i)%init(i, v, normal, temperature, flow, units, type, sp, physicalSurface, particlesPerEdge) - - CALL readVelDistr(config, inject(i), object) + CALL readVelDistr(config, injects(i)%obj, object) END DO @@ -1528,7 +1496,7 @@ MODULE moduleInput IMPLICIT NONE TYPE(json_file), INTENT(inout):: config - TYPE(injectGeneric), INTENT(inout):: inj + class(injectGeneric), INTENT(inout):: inj CHARACTER(:), ALLOCATABLE, INTENT(in):: object INTEGER:: i CHARACTER(2):: iString diff --git a/src/modules/mesh/inout/text/moduleMeshOutputText.f90 b/src/modules/mesh/inout/text/moduleMeshOutputText.f90 index 7f95788..168f519 100644 --- a/src/modules/mesh/inout/text/moduleMeshOutputText.f90 +++ b/src/modules/mesh/inout/text/moduleMeshOutputText.f90 @@ -1,9 +1,14 @@ module moduleMeshOutputText + use moduleOutput, only: prefix, & + informFileCreation, & + formatFileName, & + generateFilePath + contains subroutine writeSpeciesOutput(self, fileID, speciesIndex) use moduleMesh - use moduleOutput + use moduleOutput, only: calculateOutput, outputFormat use moduleRefParam, only: L_ref implicit none @@ -88,7 +93,6 @@ module moduleMeshOutputText speciesIndex) use moduleMesh - use moduleOutput use moduleAverage use moduleRefParam, only: L_ref implicit none @@ -151,8 +155,8 @@ module moduleMeshOutputText subroutine printCollText(self) use moduleMesh - use moduleOutput use moduleCaseParam, only: timeStep + use moduleOutput, only: collOutput implicit none class(meshGeneric), intent(in):: self @@ -190,6 +194,7 @@ module moduleMeshOutputText subroutine printEMText(self) use moduleMesh use moduleCaseParam, only: timeStep + use moduleOutput, only: emOutput implicit none class(meshParticles), intent(in):: self diff --git a/src/modules/mesh/inout/vtu/moduleMeshOutputVTU.f90 b/src/modules/mesh/inout/vtu/moduleMeshOutputVTU.f90 index 3462940..8058896 100644 --- a/src/modules/mesh/inout/vtu/moduleMeshOutputVTU.f90 +++ b/src/modules/mesh/inout/vtu/moduleMeshOutputVTU.f90 @@ -1,9 +1,11 @@ MODULE moduleMeshOutputVTU + use moduleOutput, only: prefix, informFileCreation, formatFileName, generateFilePath CONTAINS SUBROUTINE writeHeader(nNodes, nCells, fileID) USE moduleMesh + use moduleOutput, only: fmtInt IMPLICIT NONE INTEGER, INTENT(in):: nNodes, nCells @@ -77,6 +79,7 @@ MODULE moduleMeshOutputVTU SUBROUTINE writeMesh(self, fileID) USE moduleMesh USE moduleRefParam + use moduleOutput, only: fmtReal, fmtInt IMPLICIT NONE CLASS(meshGeneric), INTENT(in):: self @@ -159,6 +162,7 @@ MODULE moduleMeshOutputVTU SUBROUTINE writeCollOutput(self,fileID) USE moduleMesh USE moduleCollisions + use moduleOutput, only: fmtInt IMPLICIT NONE CLASS(meshGeneric), INTENT(in):: self @@ -185,6 +189,7 @@ MODULE moduleMeshOutputVTU SUBROUTINE writeEM(self, fileID) USE moduleMesh USE moduleRefParam + use moduleOutput, only: fmtReal IMPLICIT NONE CLASS(meshParticles), INTENT(in):: self @@ -381,6 +386,7 @@ MODULE moduleMeshOutputVTU SUBROUTINE printEMVTU(self) USE moduleMesh USE moduleCaseParam, ONLY: timeStep + use moduleOutput, only: emOutput IMPLICIT NONE CLASS(meshParticles), INTENT(in):: self @@ -414,7 +420,6 @@ MODULE moduleMeshOutputVTU SUBROUTINE printAverageVTU(self) USE moduleMesh - use moduleOutput USE moduleSpecies IMPLICIT NONE diff --git a/src/modules/mesh/moduleMesh.f90 b/src/modules/mesh/moduleMesh.f90 index b14b4f8..6cc48ee 100644 --- a/src/modules/mesh/moduleMesh.f90 +++ b/src/modules/mesh/moduleMesh.f90 @@ -1,7 +1,7 @@ !moduleMesh: General module for Finite Element mesh MODULE moduleMesh USE moduleList - USE moduleOutput + USE moduleOutput, only: outputNode, emNode USE moduleCollisions use moduleSpecies, only: nSpecies diff --git a/src/modules/mesh/moduleMesh@boundaryEM.f90 b/src/modules/mesh/moduleMesh@boundaryEM.f90 index 14fd0ee..8640d24 100644 --- a/src/modules/mesh/moduleMesh@boundaryEM.f90 +++ b/src/modules/mesh/moduleMesh@boundaryEM.f90 @@ -56,6 +56,7 @@ submodule(moduleMesh) boundaryEM use json_module use moduleRefParam, ONLY: Volt_ref, ti_ref use moduleErrors + use moduleOutput, only: path implicit none class(boundaryEMGeneric), allocatable, intent(inout):: self diff --git a/src/modules/mesh/moduleMesh@boundaryParticle.f90 b/src/modules/mesh/moduleMesh@boundaryParticle.f90 index 2e2acfa..04116be 100644 --- a/src/modules/mesh/moduleMesh@boundaryParticle.f90 +++ b/src/modules/mesh/moduleMesh@boundaryParticle.f90 @@ -342,6 +342,7 @@ submodule(moduleMesh) boundaryParticle ! Print subroutine ionization_print(self, fileID) + use moduleOutput, only: fmtInt implicit none class(boundaryParticleGeneric), intent(inout):: self @@ -473,6 +474,7 @@ submodule(moduleMesh) boundaryParticle ! Print output subroutine quasiNeutrality_print(self, fileID) + use moduleOutput, only: fmtColInt, fmtColReal implicit none class(boundaryParticleGeneric), intent(inout):: self @@ -613,6 +615,7 @@ submodule(moduleMesh) boundaryParticle ! Print subroutine outflowAdaptive_print(self, fileID) + use moduleOutput, only: fmtColInt, fmtColReal implicit none class(boundaryParticleGeneric), intent(inout):: self @@ -691,7 +694,12 @@ submodule(moduleMesh) boundaryParticle ! Writes the output into the Step_XXXXX_boundaryParticles file when the %print procedure is associated module subroutine boundariesParticle_write() use moduleCaseparam, only: timeStep - use moduleOutput, only:fileID_boundaryParticle, formatFileName, informFileCreation + use moduleOutput, only: fileID_boundaryParticle, & + formatFileName, & + informFileCreation,& + boundaryParticleOutput,& + generateFilePath, & + prefix implicit none integer:: b @@ -700,7 +708,7 @@ submodule(moduleMesh) boundaryParticle if (boundaryParticleOutput) then fileName = formatFileName(prefix, 'boundariesParticle', 'csv', timeStep) call informFileCreation(fileName) - open(fileID_boundaryParticle, file = path // folder // '/' // fileName) + open(fileID_boundaryParticle, file = generateFilePath(fileName)) do b = 1, nBoundariesParticle if (associated(boundariesParticle(b)%obj%print)) then diff --git a/src/modules/moduleInject.f90 b/src/modules/moduleInject.f90 index 427b3ce..003fd73 100644 --- a/src/modules/moduleInject.f90 +++ b/src/modules/moduleInject.f90 @@ -5,7 +5,7 @@ MODULE moduleInject use moduleMesh, only: meshEdgePointer !Generic injection of particles - TYPE:: injectGeneric + TYPE, abstract:: injectGeneric INTEGER:: id CHARACTER(:), ALLOCATABLE:: name REAL(8):: vMod !Velocity (module) @@ -14,46 +14,130 @@ MODULE moduleInject LOGICAL:: fixDirection !The injection of particles has a fix direction defined by n INTEGER:: nParticles !Number of particles to introduce each time step CLASS(speciesGeneric), POINTER:: species !Species of injection - character(:), allocatable:: type INTEGER:: nEdges type(meshEdgePointer), allocatable:: edges(:) INTEGER, ALLOCATABLE:: particlesPerEdge(:) ! Particles per edge REAL(8), ALLOCATABLE:: weightPerEdge(:) ! Weight per edge REAL(8):: surface ! Total surface of injection TYPE(velDistCont):: v(1:3) !Velocity distribution function in each direction + procedure(updateInject_interface), pointer, pass:: update => null() + procedure(printInject_interface), pointer, pass:: print => null() CONTAINS - PROCEDURE, PASS:: init => initInject PROCEDURE, PASS:: addParticles END TYPE injectGeneric + abstract interface + ! Update the values of the particle boundary model + subroutine updateInject_interface(self) + import injectGeneric + + class(injectGeneric), intent(inout):: self + + end subroutine updateInject_interface + + ! Write the values of the particle boundary model + subroutine printInject_interface(self, fileID) + import injectGeneric + + class(injectGeneric), intent(inout):: self + integer, intent(in):: fileID + + end subroutine printInject_interface + + end interface + + ! Default type, constant inject of particles + type, extends(injectGeneric):: injectConstant + + end type injectconstant + + type, extends(injectGeneric):: injectQuasiNeutral + + end type injectQuasiNeutral + + ! Wrapper for injects + type:: injectWrapper + class(injectGeneric), allocatable:: obj + + end type injectWrapper + INTEGER:: nInject - TYPE(injectGeneric), ALLOCATABLE, target:: inject(:) + TYPE(injectWrapper), ALLOCATABLE, target:: injects(:) CONTAINS !Initialize an injection of particles - SUBROUTINE initInject(self, i, v, n, temperature, flow, units, type, sp, ps, particlesPerEdge) + SUBROUTINE initInject(self, i, object, config) USE moduleMesh USE moduleRefParam USE moduleConstParam USE moduleSpecies USE moduleSolver USE moduleErrors + use json_module IMPLICIT NONE - CLASS(injectGeneric), INTENT(inout):: self + CLASS(injectGeneric), allocatable, INTENT(inout):: self INTEGER, INTENT(in):: i - REAL(8), INTENT(in):: v, n(1:3), temperature(1:3) - INTEGER, INTENT(in):: sp, ps, particlesPerEdge + character(:), allocatable, intent(in):: object + type(json_file), intent(inout):: config + character(:), allocatable:: type + logical:: found + REAL(8):: v + real(8), allocatable:: n(:), temperature(:) + INTEGER:: sp, ps, particlesPerEdge + character(:), allocatable:: speciesName integer:: ps_index REAL(8):: tauInject - REAL(8), INTENT(in):: flow - CHARACTER(:), ALLOCATABLE, INTENT(in):: units - character(:), allocatable, intent(in):: type + REAL(8):: flow + CHARACTER(:), ALLOCATABLE:: units INTEGER:: e REAL(8):: fluxPerStep = 0.D0 - self%id = i + !Type of injection + call config%get(object // '.type', type, found) + if (.not. found) then + ! If no type is found, assume constant injection of particles + type = 'constant' + end if + + ! Assign type to inject and allocates it + select case(type) + case ('constant') + allocate(injectConstant:: self) + + case ('quasiNeutral') + allocate(injectQuasiNeutral:: self) + + self%update => updateQuasiNeutral + + case default + call criticalError('No injection type ' // type // ' defined', 'initInject') + end select + + self%id = i + call config%get(object // '.name', self%name, found) + + !Find species + CALL config%get(object // '.species', speciesName, found) + sp = speciesName2Index(speciesName) + + ! Velocity and direction of injection + call config%get(object // '.v', v, found) + call config%get(object // '.n', n, found) + if (.not. found) then + allocate(n(1:3)) + n = 0.D0 + end if + ! Temperature of injection + call config%get(object // '.T', temperature, found) + ! Flow + call config%get(object // '.flow', flow, found) + call config%get(object // '.units', units, found) + CALL config%get(object // '.physicalSurface', ps, found) + particlesPerEdge = 0 + CALL config%get(object // '.particlesPerEdge', particlesPerEdge, found) + self%vMod = v / v_ref self%n = n / NORM2(n) self%temperature = temperature / T_ref @@ -145,15 +229,91 @@ MODULE moduleInject !Scale particles for different species steps IF (self%nParticles == 0) CALL criticalError("The number of particles for inject is 0.", 'initInject') - ! Assign type to inject - select case(type) - case ('constant', 'quasiNeutral') - self%type = type - case default - call criticalError('No injection type ' // type // ' defined', 'initInject') + END SUBROUTINE initInject + + ! Update the value of injects + subroutine updateInjects() + implicit none + + integer:: i + + do i = 1, nInject + if (associated(injects(i)%obj%update)) then + call injects(i)%obj%update() + + end if + + end do + + end subroutine updateInjects + + ! Updates the flow in the injection to maintain quasineutrality + subroutine updateQuasiNeutral(self) + use moduleMesh, only: meshEdge, meshNode, mesh, qSpecies + implicit none + + class(injectGeneric), intent(inout):: self + integer:: e, s, n + integer, allocatable:: nodes(:) + class(meshEdge), pointer:: edge + real(8), allocatable:: density_nodes(:) + class(meshNode), pointer:: node + real(8):: den_center + real(8):: density_incident, density_rest + real(8):: alpha + + select type(self) + type is (injectQuasiNeutral) + do e = 1, self%nEdges + edge => self%edges(e)%obj + + density_incident = 0.d0 + density_rest = 0.d0 + + nodes = edge%getNodes(edge%nNodes) + allocate(density_nodes(1:edge%nNodes)) + do s = 1, nSpecies + do n = 1, edge%nNodes + node => mesh%nodes(nodes(n))%obj + + density_nodes(n) = node%output(s)%den + + end do + + ! Gather the density at the edge center and multiply by the species charge + den_center = qSpecies(s)*edge%gatherF(edge%centerXi(), edge%nNodes, density_nodes) + + if (s == self%species%n) then + density_incident = den_center + + else + density_rest = density_rest + den_center + + end if + + end do + + ! Correction for this time step + if (density_rest > 1.0d-10) then + ! If there is a rest population, correct + alpha = 1.d0 + density_incident/density_rest + + else + ! If not, alpha is assumed unchaged + alpha = 0.d0 + + end if + + print *, e, alpha + + ! Adjust the weight of particles to match the new current + self%weightPerEdge(e) = self%weightPerEdge(e) + 1.0d-1 * alpha + + end do + end select - END SUBROUTINE initInject + end subroutine updateQuasiNeutral !Injection of particles SUBROUTINE doInjects() @@ -166,8 +326,8 @@ MODULE moduleInject !$OMP SINGLE nPartInj = 0 DO i = 1, nInject - IF (solver%pusher(inject(i)%species%n)%pushSpecies) THEN - nPartInj = nPartInj + inject(i)%nParticles + IF (solver%pusher(injects(i)%obj%species%n)%pushSpecies) THEN + nPartInj = nPartInj + injects(i)%obj%nParticles END IF @@ -178,112 +338,14 @@ MODULE moduleInject !$OMP END SINGLE DO i=1, nInject - IF (solver%pusher(inject(i)%species%n)%pushSpecies) THEN - CALL inject(i)%addParticles() + IF (solver%pusher(injects(i)%obj%species%n)%pushSpecies) THEN + CALL injects(i)%obj%addParticles() END IF END DO END SUBROUTINE doInjects - ! Update the value of injects - subroutine updateInjects() - use moduleMesh, only: meshEdge, meshNode, mesh, qSpecies - implicit none - - integer:: i, e, s, n - class(injectGeneric), pointer:: self - integer, allocatable:: nodes(:) - class(meshEdge), pointer:: edge - real(8), allocatable:: density_nodes(:) - class(meshNode), pointer:: node - real(8):: den_center - real(8):: density_incident, density_rest - real(8):: alpha - - do i = 1, nInject - self => inject(i) - select case(inject(i)%type) - case ('quasiNeutral') - do e = 1, self%nEdges - edge => self%edges(e)%obj - - density_incident = 0.d0 - density_rest = 0.d0 - - nodes = edge%getNodes(edge%nNodes) - allocate(density_nodes(1:edge%nNodes)) - do s = 1, nSpecies - do n = 1, edge%nNodes - node => mesh%nodes(nodes(n))%obj - - density_nodes(n) = node%output(s)%den - - end do - - ! Gather the density at the edge center and multiply by the species charge - den_center = qSpecies(s)*edge%gatherF(edge%centerXi(), edge%nNodes, density_nodes) - - if (s == self%species%n) then - density_incident = den_center - - else - density_rest = density_rest + den_center - - end if - - end do - - ! Correction for this time step - if (density_rest > 1.0d-10) then - ! If there is a rest population, correct - alpha = 1.d0 + density_incident/density_rest - - else - ! If not, alpha is assumed unchaged - alpha = 0.d0 - - end if - - ! Adjust the weight of particles to match the new current - self%weightPerEdge(e) = self%weightPerEdge(e) + 1.0d-2 * alpha - - end do - - end select - end do - - end subroutine updateInjects - - SUBROUTINE initVelDistMaxwellian(velDist, temperature, m) - IMPLICIT NONE - - CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist - REAL(8), INTENT(in):: temperature, m - - velDist = velDistMaxwellian(vTh = DSQRT(2.d0*temperature/m)) - - END SUBROUTINE initVelDistMaxwellian - - SUBROUTINE initVelDistHalfMaxwellian(velDist, temperature, m) - IMPLICIT NONE - - CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist - REAL(8), INTENT(in):: temperature, m - - velDist = velDistHalfMaxwellian(vTh = DSQRT(2.d0*temperature/m)) - - END SUBROUTINE initVelDistHalfMaxwellian - - SUBROUTINE initVelDistDelta(velDist) - IMPLICIT NONE - - CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist - - velDist = velDistDelta() - - END SUBROUTINE initVelDistDelta - !Add particles for the injection SUBROUTINE addParticles(self) USE moduleSpecies @@ -304,8 +366,8 @@ MODULE moduleInject !$OMP SINGLE nMin = 0 DO i = 1, self%id -1 - IF (solver%pusher(inject(i)%species%n)%pushSpecies) THEN - nMin = nMin + inject(i)%nParticles + IF (solver%pusher(injects(i)%obj%species%n)%pushSpecies) THEN + nMin = nMin + injects(i)%obj%nParticles END IF @@ -381,4 +443,67 @@ MODULE moduleInject END SUBROUTINE addParticles + ! Writes the value of injects + subroutine writeInjects() + use moduleCaseparam, only: timeStep + use moduleOutput, only: fileID_inject, & + formatFileName, & + informFileCreation,& + injectOutput,& + generateFilePath, & + prefix + implicit none + + integer:: i + character(:), allocatable:: fileName + + if (injectOutput) then + fileName = formatFileName(prefix, 'injects', 'csv', timeStep) + call informFileCreation(fileName) + open(fileID_inject, file = generateFilePath(fileName)) + + do i = 1, nInject + if (associated(injects(i)%obj%print)) then + call injects(i)%obj%print(fileID_inject) + + end if + + end do + + close(fileID_inject) + + end if + + end subroutine writeInjects + + ! Inits for different velocity distribution functions + SUBROUTINE initVelDistMaxwellian(velDist, temperature, m) + IMPLICIT NONE + + CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist + REAL(8), INTENT(in):: temperature, m + + velDist = velDistMaxwellian(vTh = DSQRT(2.d0*temperature/m)) + + END SUBROUTINE initVelDistMaxwellian + + SUBROUTINE initVelDistHalfMaxwellian(velDist, temperature, m) + IMPLICIT NONE + + CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist + REAL(8), INTENT(in):: temperature, m + + velDist = velDistHalfMaxwellian(vTh = DSQRT(2.d0*temperature/m)) + + END SUBROUTINE initVelDistHalfMaxwellian + + SUBROUTINE initVelDistDelta(velDist) + IMPLICIT NONE + + CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist + + velDist = velDistDelta() + + END SUBROUTINE initVelDistDelta + END MODULE moduleInject diff --git a/src/modules/output/moduleOutput.f90 b/src/modules/output/moduleOutput.f90 index ab2d341..3011396 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:: injectOutput = .false. ! Prefix for iteration files character(len=*), parameter:: prefix = 'Step' @@ -33,6 +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_reference = 40 ! Reference values integer, parameter:: fileID_time =50 ! Computation time From fdbe6c683b6eba955fd063dc6e42202f7fbe4e02 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 1 Apr 2026 16:23:53 +0200 Subject: [PATCH 07/21] Bit more of cleaning --- .../mesh/inout/gmsh2/moduleMeshOutputGmsh2.f90 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/mesh/inout/gmsh2/moduleMeshOutputGmsh2.f90 b/src/modules/mesh/inout/gmsh2/moduleMeshOutputGmsh2.f90 index 0ca61ad..acd4189 100644 --- a/src/modules/mesh/inout/gmsh2/moduleMeshOutputGmsh2.f90 +++ b/src/modules/mesh/inout/gmsh2/moduleMeshOutputGmsh2.f90 @@ -1,4 +1,5 @@ MODULE moduleMeshOutputGmsh2 + use moduleOutput, only: prefix, informFileCreation, formatFileName, generateFilePath CONTAINS !Header for mesh format @@ -16,7 +17,7 @@ MODULE moduleMeshOutputGmsh2 !Node data subroutines !Header SUBROUTINE writeGmsh2HeaderNodeData(fileID, title, iteration, time, dimensions, nNodes) - use moduleOutput + use moduleOutput, only: fmtInt, fmtReal IMPLICIT NONE INTEGER, INTENT(in):: fileID @@ -50,7 +51,7 @@ MODULE moduleMeshOutputGmsh2 !Element data subroutines !Header SUBROUTINE writeGmsh2HeaderElementData(fileID, title, iteration, time, dimensions, nVols) - use moduleOutput + use moduleOutput, only: fmtInt, fmtReal IMPLICIT NONE INTEGER, INTENT(in):: fileID @@ -86,7 +87,7 @@ MODULE moduleMeshOutputGmsh2 USE moduleMesh USE moduleRefParam USE moduleSpecies - USE moduleOutput + use moduleOutput, only: outputFormat, calculateOutput, fmtReal USE moduleCaseParam, ONLY: timeStep IMPLICIT NONE @@ -141,7 +142,7 @@ MODULE moduleMeshOutputGmsh2 USE moduleRefParam USE moduleCaseParam USE moduleCollisions - USE moduleOutput + use moduleOutput, only: collOutput, fmtInt IMPLICIT NONE CLASS(meshGeneric), INTENT(in):: self @@ -199,7 +200,7 @@ MODULE moduleMeshOutputGmsh2 USE moduleMesh USE moduleRefParam USE moduleCaseParam - USE moduleOutput + use moduleOutput, only: emOutput IMPLICIT NONE CLASS(meshParticles), INTENT(in):: self @@ -248,7 +249,6 @@ MODULE moduleMeshOutputGmsh2 USE moduleMesh USE moduleRefParam USE moduleSpecies - USE moduleOutput USE moduleAverage IMPLICIT NONE From 4049bbca314e07bcb0d0f3b151bd1543b929fac9 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 1 Apr 2026 16:45:39 +0200 Subject: [PATCH 08/21] Implemented. Now the doc --- src/modules/init/moduleInput.f90 | 1 + src/modules/moduleInject.f90 | 21 +++++++++++++++++++-- src/modules/solver/moduleSolver.f90 | 4 ++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/modules/init/moduleInput.f90 b/src/modules/init/moduleInput.f90 index 1b4ff21..bcf4dcc 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 // '.injects', injectOutput, found) CALL config%get(object // '.triggerCPUTime', triggerCPUTime, found) IF (.NOT. found) THEN diff --git a/src/modules/moduleInject.f90 b/src/modules/moduleInject.f90 index 003fd73..39de1ad 100644 --- a/src/modules/moduleInject.f90 +++ b/src/modules/moduleInject.f90 @@ -110,6 +110,7 @@ MODULE moduleInject allocate(injectQuasiNeutral:: self) self%update => updateQuasiNeutral + self%print => printQuasiNeutral case default call criticalError('No injection type ' // type // ' defined', 'initInject') @@ -304,8 +305,6 @@ MODULE moduleInject end if - print *, e, alpha - ! Adjust the weight of particles to match the new current self%weightPerEdge(e) = self%weightPerEdge(e) + 1.0d-1 * alpha @@ -476,6 +475,24 @@ MODULE moduleInject end subroutine writeInjects + ! Write information about quasiNeutral inject + subroutine printQuasiNeutral(self, fileID) + use moduleOutput, only: fmtColInt, fmtColReal + implicit none + + class(injectGeneric), intent(inout):: self + integer, intent(in):: fileID + integer:: e + + write(fileID, '(A)') self%name + write(fileID, '(A,",",A)') '"Edge id"', '"weight of particles"' + do e = 1, self%nEdges + write(fileID, '('//fmtColInt//','//fmtColReal//')') self%edges(e)%obj%n, self%weightPerEdge(e) + + end do + + end subroutine printQuasiNeutral + ! Inits for different velocity distribution functions SUBROUTINE initVelDistMaxwellian(velDist, temperature, m) IMPLICIT NONE diff --git a/src/modules/solver/moduleSolver.f90 b/src/modules/solver/moduleSolver.f90 index ed566e9..f951839 100644 --- a/src/modules/solver/moduleSolver.f90 +++ b/src/modules/solver/moduleSolver.f90 @@ -520,6 +520,7 @@ MODULE moduleSolver USE moduleSpecies USE moduleCompTime USE moduleProbe + use moduleInject, only: writeInjects USE moduleCaseParam, ONLY: timeStep IMPLICIT NONE @@ -539,6 +540,9 @@ MODULE moduleSolver ! Output of boundaries call boundariesParticle_write() + ! Output of inejcts + call writeInjects() + WRITE(*, "(5X,A21,I10,A1,I10)") "t/tFinal: ", timeStep, "/", tFinal WRITE(*, "(5X,A21,I10)") "Particles: ", nPartOld IF (timeStep == 0) THEN From 0c2e8dd502e376b450dc8cee73852d108fa0cf05 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 1 Apr 2026 19:35:42 +0200 Subject: [PATCH 09/21] txs auto checkin --- doc/user-manual/fpakc_UserManual.tex | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/user-manual/fpakc_UserManual.tex b/doc/user-manual/fpakc_UserManual.tex index 1b4e258..16a3436 100644 --- a/doc/user-manual/fpakc_UserManual.tex +++ b/doc/user-manual/fpakc_UserManual.tex @@ -401,6 +401,9 @@ make \item \textbf{bounraiesParticle}: Logical. Determines if the properties of the boundaries are written. \textit{Warning}: Not all particle models produce this output, only those whose properties change during the simulation. + \item \textbf{injects}: Logical. + Determines if the properties of the injection of particles are written. + \textit{Warning}: Not all particle models produce this output, only those whose properties change during the simulation. \item \textbf{probes}: Array of objects. Defines the probes employed for obtaining the distribution function at specific positions. See Sec.~\ref{sec:probing} for more information. From 79e5c05e4a8a82ce6c935f55a17ef14eb11fa1d6 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 1 Apr 2026 19:35:52 +0200 Subject: [PATCH 10/21] txs auto checkin --- doc/user-manual/fpakc_UserManual.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user-manual/fpakc_UserManual.tex b/doc/user-manual/fpakc_UserManual.tex index 16a3436..293c1f8 100644 --- a/doc/user-manual/fpakc_UserManual.tex +++ b/doc/user-manual/fpakc_UserManual.tex @@ -403,7 +403,7 @@ make \textit{Warning}: Not all particle models produce this output, only those whose properties change during the simulation. \item \textbf{injects}: Logical. Determines if the properties of the injection of particles are written. - \textit{Warning}: Not all particle models produce this output, only those whose properties change during the simulation. + \textit{Warning}: Not all injection types produce this output, only those whose properties change during the simulation. \item \textbf{probes}: Array of objects. Defines the probes employed for obtaining the distribution function at specific positions. See Sec.~\ref{sec:probing} for more information. From c070ec6033828dde78254a25ff9e2e142cb1310d Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 1 Apr 2026 19:42:19 +0200 Subject: [PATCH 11/21] txs auto checkin --- doc/user-manual/fpakc_UserManual.tex | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/user-manual/fpakc_UserManual.tex b/doc/user-manual/fpakc_UserManual.tex index 293c1f8..ecb719b 100644 --- a/doc/user-manual/fpakc_UserManual.tex +++ b/doc/user-manual/fpakc_UserManual.tex @@ -691,6 +691,15 @@ make Units of $\unit{K}$ Array dimension $3$. Temperature in each direction. + \item \textbf{type}: Character. + Type of injection. + The default value is \textbf{constant}. + Available values are: + \begin{itemize} + \item \textbf{constant}: The flow does not change. + \item \textbf{quasiNeutral}: The flow of the species is changed over time to keep the charge density close to zero at the injection surface. + The weight of the injected particles is changed. + \end{itemize} \item \textbf{physicalSurface}: Integer. Identification of the edge in the mesh file. \item \textbf{particlesPerEdge}: Integer. From 0f2d6dd94f82b7ec9b50ef3860a63eacbb451977 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 1 Apr 2026 19:43:05 +0200 Subject: [PATCH 12/21] txs auto checkin --- doc/user-manual/fpakc_UserManual.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user-manual/fpakc_UserManual.tex b/doc/user-manual/fpakc_UserManual.tex index ecb719b..f9f9ae8 100644 --- a/doc/user-manual/fpakc_UserManual.tex +++ b/doc/user-manual/fpakc_UserManual.tex @@ -693,10 +693,10 @@ make Temperature in each direction. \item \textbf{type}: Character. Type of injection. - The default value is \textbf{constant}. Available values are: \begin{itemize} \item \textbf{constant}: The flow does not change. + This is the default value if none is provided. \item \textbf{quasiNeutral}: The flow of the species is changed over time to keep the charge density close to zero at the injection surface. The weight of the injected particles is changed. \end{itemize} From 45a4c3fe3d41cd9f697c5f29fcbb702e2f49f0a4 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Wed, 1 Apr 2026 19:55:33 +0200 Subject: [PATCH 13/21] Updated manual --- doc/user-manual/fpakc_UserManual.pdf | Bin 273870 -> 274312 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/user-manual/fpakc_UserManual.pdf b/doc/user-manual/fpakc_UserManual.pdf index c3b66ab10a8d7a8824228bd822725698016e0746..f8ab920f00798906cb7c06b940a91748e7f59e3a 100644 GIT binary patch delta 37587 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 ZUkK|{rP_!B9+HX6Ns{sMLUh&1{tLwb=g$BD From 20f15fb23975dbb9459fd56608cb19bd95cb8246 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Thu, 2 Apr 2026 16:07:20 +0200 Subject: [PATCH 14/21] Typo with headers in mean/deviation files --- src/modules/mesh/inout/text/moduleMeshOutputText.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/mesh/inout/text/moduleMeshOutputText.f90 b/src/modules/mesh/inout/text/moduleMeshOutputText.f90 index 168f519..74ac0ea 100644 --- a/src/modules/mesh/inout/text/moduleMeshOutputText.f90 +++ b/src/modules/mesh/inout/text/moduleMeshOutputText.f90 @@ -241,7 +241,7 @@ module moduleMeshOutputText write(fileIDMean, '(5(A,","),A)') '"Position (m)"', & '"Density, mean (m^-3)"', & - '"Velocity, mean (m s^-1):0"', '"Velocity (m s^-1):1"', '"Velocity (m s^-1):2"', & + '"Velocity, mean (m s^-1):0"', '"Velocity, mean (m s^-1):1"', '"Velocity, mean (m s^-1):2"', & '"Temperature, mean (K)"' fileNameDeviation = formatFileName('Average_deviation', species(s)%obj%name, 'csv') @@ -250,7 +250,7 @@ module moduleMeshOutputText write(fileIDDeviation, '(5(A,","),A)') '"Position (m)"', & '"Density, deviation (m^-3)"', & - '"Velocity, deviation (m s^-1):0"', 'Velocity (m s^-1):1"', 'Velocity (m s^-1):2"', & + '"Velocity, deviation (m s^-1):0"', 'Velocity, deviation (m s^-1):1"', 'Velocity, deviation (m s^-1):2"', & '"Temperature, deviation (K)"' call writeAverage(self, fileIDMean, fileIDDeviation, s) From cf4488976ae76b3d5a083c39e1f3114f2898f299 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Sat, 4 Apr 2026 20:03:20 +0200 Subject: [PATCH 15/21] Finally, the right values for velocity distributions --- src/modules/common/moduleRandom.f90 | 17 +-- src/modules/common/velocityDistribution.f90 | 3 +- src/modules/moduleInject.f90 | 114 ++++++-------------- 3 files changed, 44 insertions(+), 90 deletions(-) diff --git a/src/modules/common/moduleRandom.f90 b/src/modules/common/moduleRandom.f90 index f4dcc46..a1bc3fc 100644 --- a/src/modules/common/moduleRandom.f90 +++ b/src/modules/common/moduleRandom.f90 @@ -67,19 +67,20 @@ MODULE moduleRandom end function randomMaxwellian !Returns a random number in a Maxwellian distribution of mean 0 and width 1 - FUNCTION randomHalfMaxwellian() RESULT(rnd) + function randomHalfMaxwellian() result(rnd) IMPLICIT NONE - REAL(8):: rnd - REAL(8):: x + real(8):: rnd + real(8):: v1 rnd = 0.D0 - x = 0.D0 - DO WHILE (x == 0.D0) - CALL RANDOM_NUMBER(x) - END DO + v1 = 0.D0 + do while (v1 == 0.D0) + v1 = random() + + end do - rnd = DSQRT(-DLOG(x)) + rnd = sqrt(-2.d0*log(v1)) END FUNCTION randomHalfMaxwellian diff --git a/src/modules/common/velocityDistribution.f90 b/src/modules/common/velocityDistribution.f90 index 5b6c342..359eebd 100644 --- a/src/modules/common/velocityDistribution.f90 +++ b/src/modules/common/velocityDistribution.f90 @@ -53,12 +53,11 @@ module velocityDistribution function randomVelMaxwellian(self) result (v) use moduleRandom implicit none - class(velDistMaxwellian), intent(in):: self real(8):: v v = 0.D0 - v = self%vTh*randomMaxwellian()/sqrt(2.d0) + v = self%vTh*randomMaxwellian() end function randomVelMaxwellian diff --git a/src/modules/moduleInject.f90 b/src/modules/moduleInject.f90 index 39de1ad..7a1c5d6 100644 --- a/src/modules/moduleInject.f90 +++ b/src/modules/moduleInject.f90 @@ -12,7 +12,7 @@ MODULE moduleInject 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 + INTEGER:: nParticles !Number of particles to inject each time step CLASS(speciesGeneric), POINTER:: species !Species of injection INTEGER:: nEdges type(meshEdgePointer), allocatable:: edges(:) @@ -72,7 +72,6 @@ MODULE moduleInject USE moduleRefParam USE moduleConstParam USE moduleSpecies - USE moduleSolver USE moduleErrors use json_module IMPLICIT NONE @@ -211,8 +210,6 @@ MODULE moduleInject END DO - self%nParticles = SUM(self%particlesPerEdge) - ELSE ! No particles assigned per edge, use the species weight self%weightPerEdge = self%species%weight @@ -220,13 +217,14 @@ MODULE moduleInject self%particlesPerEdge(e) = max(1,FLOOR(fluxPerStep*self%edges(e)%obj%surface / self%species%weight)) END DO - self%nParticles = SUM(self%particlesPerEdge) - !Rescale weight to match flux self%weightPerEdge = fluxPerStep * self%surface / (real(self%nParticles)) END IF + ! Total number of particles to inject + self%nParticles = SUM(self%particlesPerEdge) + !Scale particles for different species steps IF (self%nParticles == 0) CALL criticalError("The number of particles for inject is 0.", 'initInject') @@ -314,126 +312,82 @@ MODULE moduleInject end subroutine updateQuasiNeutral - !Injection of particles - SUBROUTINE doInjects() - USE moduleSpecies - USE moduleSolver - IMPLICIT NONE - - INTEGER:: i - - !$OMP SINGLE - nPartInj = 0 - DO i = 1, nInject - IF (solver%pusher(injects(i)%obj%species%n)%pushSpecies) THEN - nPartInj = nPartInj + injects(i)%obj%nParticles - - END IF - - END DO - - IF (ALLOCATED(partInj)) DEALLOCATE(partInj) - ALLOCATE(partInj(1:nPartInj)) - !$OMP END SINGLE - - DO i=1, nInject - IF (solver%pusher(injects(i)%obj%species%n)%pushSpecies) THEN - CALL injects(i)%obj%addParticles() - - END IF - END DO - - END SUBROUTINE doInjects - !Add particles for the injection - SUBROUTINE addParticles(self) + SUBROUTINE addParticles(self, partArray) USE moduleSpecies - USE moduleSolver USE moduleMesh USE moduleRandom USE moduleErrors IMPLICIT NONE CLASS(injectGeneric), INTENT(in):: self - INTEGER, SAVE:: nMin + type(particle), allocatable, intent(inout):: partArray(:) INTEGER:: i, e INTEGER:: n, sp - CLASS(meshEdge), POINTER:: randomEdge + CLASS(meshEdge), POINTER:: edge REAL(8):: direction(1:3) + !$omp single + n = 0 + !$omp end single + !Insert particles - !$OMP SINGLE - nMin = 0 - DO i = 1, self%id -1 - IF (solver%pusher(injects(i)%obj%species%n)%pushSpecies) THEN - nMin = nMin + injects(i)%obj%nParticles - - END IF - - END DO - nMin = nMin + 1 - !$OMP END SINGLE - !$OMP DO DO e = 1, self%nEdges ! Select edge for injection - randomEdge => self%edges(e)%obj + edge => self%edges(e)%obj ! Inject particles in edge DO i = 1, self%particlesPerEdge(e) - ! Index in the global partInj array - n = nMin - 1 + SUM(self%particlesPerEdge(1:e-1)) + i - !Particle is considered to be outside the domain - partInj(n)%n_in = .FALSE. + ! Index in the partInj array + n = n + 1 + !Particle is considered to be outside the domain for now + partArray(n)%n_in = .FALSE. !Random position in edge - partInj(n)%r = randomEdge%randPos() + partArray(n)%r = edge%randPos() !Assign weight to particle. - partInj(n)%weight = self%weightPerEdge(e) + partArray(n)%weight = self%weightPerEdge(e) !Volume associated to the edge: - IF (ASSOCIATED(randomEdge%e1)) THEN - partInj(n)%cell = randomEdge%e1%n + IF (ASSOCIATED(edge%e1)) THEN + partArray(n)%cell = edge%e1%n - ELSEIF (ASSOCIATED(randomEdge%e2)) THEN - partInj(n)%cell = randomEdge%e2%n + ELSEIF (ASSOCIATED(edge%e2)) THEN + partArray(n)%cell = edge%e2%n ELSE CALL criticalError("No Volume associated to edge", 'addParticles') END IF - partInj(n)%cellColl = randomEdge%eColl%n + partArray(n)%cellColl = edge%eColl%n sp = self%species%n !Assign particle type - partInj(n)%species => self%species + partArray(n)%species => self%species if (all(self%n == 0.D0)) then - direction = randomEdge%normal + direction = edge%normal else direction = self%n end if - partInj(n)%v = 0.D0 + partArray(n)%v = 0.D0 - do while(dot_product(partInj(n)%v, direction) <= 0.d0) - partInj(n)%v = self%vMod*direction + (/ self%v(1)%obj%randomVel(), & + ! do while(dot_product(partInj(n)%v, direction) <= 0.d0) + partArray(n)%v = self%vMod*direction + (/ self%v(1)%obj%randomVel(), & self%v(2)%obj%randomVel(), & self%v(3)%obj%randomVel() /) !If injecting a no-drift distribution and velocity is negative, reflect if ((self%vMod == 0.D0) .and. & - (dot_product(partInj(n)%v, direction) <= 0.D0)) then - partInj(n)%v = - partInj(n)%v + (dot_product(partArray(n)%v, direction) <= 0.D0)) then + partArray(n)%v = - partArray(n)%v end if - end do + ! end do !Obtain natural coordinates of particle in cell - partInj(n)%Xi = mesh%cells(partInj(n)%cell)%obj%phy2log(partInj(n)%r) - !Push new particle with the minimum time step - CALL solver%pusher(sp)%pushParticle(partInj(n), tau(sp)) - !Assign cell to new particle - CALL solver%updateParticleCell(partInj(n)) + partArray(n)%Xi = mesh%cells(partArray(n)%cell)%obj%phy2log(partArray(n)%r) END DO @@ -500,7 +454,7 @@ MODULE moduleInject CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist REAL(8), INTENT(in):: temperature, m - velDist = velDistMaxwellian(vTh = DSQRT(2.d0*temperature/m)) + velDist = velDistMaxwellian(vTh = DSQRT(temperature/m)) END SUBROUTINE initVelDistMaxwellian @@ -510,7 +464,7 @@ MODULE moduleInject CLASS(velDistGeneric), ALLOCATABLE, INTENT(out):: velDist REAL(8), INTENT(in):: temperature, m - velDist = velDistHalfMaxwellian(vTh = DSQRT(2.d0*temperature/m)) + velDist = velDistHalfMaxwellian(vTh = DSQRT(temperature/m)) END SUBROUTINE initVelDistHalfMaxwellian From ed79eb018e695902ffadb84e3b0642b3dc684a85 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Sat, 4 Apr 2026 20:24:16 +0200 Subject: [PATCH 16/21] Import only what you need --- src/fpakc.f90 | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/fpakc.f90 b/src/fpakc.f90 index feee89a..cb68754 100644 --- a/src/fpakc.f90 +++ b/src/fpakc.f90 @@ -1,15 +1,39 @@ ! FPAKC main program PROGRAM fpakc - USE moduleCompTime - USE moduleCaseParam - USE moduleInput - USE moduleInject - USE moduleSolver - USE moduleMesh - USE moduleProbe - USE moduleErrors - USE OMP_LIB - IMPLICIT NONE + use moduleCompTime, only: tStep, & + tEMField, & + tCoul, & + tColl, & + tPush, & + tReset, & + tWeight + use omp_lib, only: omp_get_wtime + use moduleErrors, only: criticalError, & + verboseError + use moduleInput, only: readCOnfig, & + initOutput + use moduleCaseParam, only: timeStep, & + tInitial, & + tFinal + use moduleProbe, only: resetProbes + use moduleSolver, only: doScatter, & + doEMField, & + doOutput, & + solver, & + doPushes, & + doReset, & + doAverage, & + doInjects + use moduleMesh, only: boundariesEM_update, & + boundariesEM_update, & + boundariesParticle_update, & + mesh, & + meshForMCC, & + doMCCollisions, & + doCollisions, & + doCoulombScattering + use moduleInject, only: updateInjects + implicit none ! arg1 = Input argument 1 (input file) CHARACTER(200):: arg1 From 6b72dbb108bdb8c01c9c250dbc433036d75bbbc0 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Sat, 4 Apr 2026 22:49:14 +0200 Subject: [PATCH 17/21] Organized injection --- src/modules/init/moduleInput.f90 | 7 ---- src/modules/makefile | 2 +- src/modules/moduleInject.f90 | 45 ++++++++++---------- src/modules/moduleList.f90 | 1 + src/modules/moduleSpecies.f90 | 3 -- src/modules/solver/moduleSolver.f90 | 65 ++++++++++++++++------------- 6 files changed, 63 insertions(+), 60 deletions(-) diff --git a/src/modules/init/moduleInput.f90 b/src/modules/init/moduleInput.f90 index bcf4dcc..eb8bde5 100644 --- a/src/modules/init/moduleInput.f90 +++ b/src/modules/init/moduleInput.f90 @@ -1431,7 +1431,6 @@ MODULE moduleInput CALL config%info('inject', found, n_children = nInject) ALLOCATE(injects(1:nInject)) - nPartInj = 0 DO i = 1, nInject WRITE(iString, '(i2)') i object = 'inject(' // trim(iString) // ')' @@ -1442,12 +1441,6 @@ MODULE moduleInput END DO - !Allocate array for injected particles - IF (nPartInj > 0) THEN - ALLOCATE(partInj(1:nPartInj)) - - END IF - END SUBROUTINE readInject SUBROUTINE readAverage(config) diff --git a/src/modules/makefile b/src/modules/makefile index 9f62c85..5789276 100644 --- a/src/modules/makefile +++ b/src/modules/makefile @@ -14,7 +14,7 @@ output.o: moduleSpecies.o common.o mesh.o: moduleList.o moduleSpecies.o moduleCollisions.o moduleCoulomb.o output.o common.o $(MAKE) -C mesh all -solver.o: moduleSpecies.o moduleProbe.o common.o output.o mesh.o +solver.o: moduleInject.o moduleSpecies.o moduleProbe.o common.o output.o mesh.o $(MAKE) -C solver all init.o: common.o solver.o moduleInject.o diff --git a/src/modules/moduleInject.f90 b/src/modules/moduleInject.f90 index 7a1c5d6..942189c 100644 --- a/src/modules/moduleInject.f90 +++ b/src/modules/moduleInject.f90 @@ -313,23 +313,21 @@ MODULE moduleInject end subroutine updateQuasiNeutral !Add particles for the injection - SUBROUTINE addParticles(self, partArray) + SUBROUTINE addParticles(self) USE moduleSpecies USE moduleMesh USE moduleRandom USE moduleErrors + use moduleList, only: partInj IMPLICIT NONE CLASS(injectGeneric), INTENT(in):: self - type(particle), allocatable, intent(inout):: partArray(:) + type(particle), pointer:: part INTEGER:: i, e - INTEGER:: n, sp + INTEGER:: sp CLASS(meshEdge), POINTER:: edge - REAL(8):: direction(1:3) - !$omp single - n = 0 - !$omp end single + REAL(8):: direction(1:3) !Insert particles !$OMP DO @@ -338,30 +336,30 @@ MODULE moduleInject edge => self%edges(e)%obj ! Inject particles in edge DO i = 1, self%particlesPerEdge(e) + allocate(part) ! Index in the partInj array - n = n + 1 - !Particle is considered to be outside the domain for now - partArray(n)%n_in = .FALSE. + !Particle is considered to be inside the domain + part%n_in = .true. !Random position in edge - partArray(n)%r = edge%randPos() + part%r = edge%randPos() !Assign weight to particle. - partArray(n)%weight = self%weightPerEdge(e) + part%weight = self%weightPerEdge(e) !Volume associated to the edge: IF (ASSOCIATED(edge%e1)) THEN - partArray(n)%cell = edge%e1%n + part%cell = edge%e1%n ELSEIF (ASSOCIATED(edge%e2)) THEN - partArray(n)%cell = edge%e2%n + part%cell = edge%e2%n ELSE CALL criticalError("No Volume associated to edge", 'addParticles') END IF - partArray(n)%cellColl = edge%eColl%n + part%cellColl = edge%eColl%n sp = self%species%n !Assign particle type - partArray(n)%species => self%species + part%species => self%species if (all(self%n == 0.D0)) then direction = edge%normal @@ -371,23 +369,28 @@ MODULE moduleInject end if - partArray(n)%v = 0.D0 + part%v = 0.D0 ! do while(dot_product(partInj(n)%v, direction) <= 0.d0) - partArray(n)%v = self%vMod*direction + (/ self%v(1)%obj%randomVel(), & + part%v = self%vMod*direction + (/ self%v(1)%obj%randomVel(), & self%v(2)%obj%randomVel(), & self%v(3)%obj%randomVel() /) !If injecting a no-drift distribution and velocity is negative, reflect if ((self%vMod == 0.D0) .and. & - (dot_product(partArray(n)%v, direction) <= 0.D0)) then - partArray(n)%v = - partArray(n)%v + (dot_product(part%v, direction) <= 0.D0)) then + part%v = - part%v end if ! end do !Obtain natural coordinates of particle in cell - partArray(n)%Xi = mesh%cells(partArray(n)%cell)%obj%phy2log(partArray(n)%r) + part%Xi = mesh%cells(part%cell)%obj%phy2log(part%r) + + ! Add particle to global list + call partInj%setLock() + call partInj%add(part) + call partInj%unsetLock() END DO diff --git a/src/modules/moduleList.f90 b/src/modules/moduleList.f90 index b1dafdc..44524c6 100644 --- a/src/modules/moduleList.f90 +++ b/src/modules/moduleList.f90 @@ -23,6 +23,7 @@ MODULE moduleList END TYPE listNode + TYPE(listNode):: partInj !Particles comming from injections TYPE(listNode):: partWScheme !Particles comming from the nonAnalogue scheme TYPE(listNode):: partCollisions !Particles created in collisional process TYPE(listNode):: partSurfaces !Particles created in surface interactions diff --git a/src/modules/moduleSpecies.f90 b/src/modules/moduleSpecies.f90 index ab08f08..8c575da 100644 --- a/src/modules/moduleSpecies.f90 +++ b/src/modules/moduleSpecies.f90 @@ -48,11 +48,8 @@ MODULE moduleSpecies !Number of old particles INTEGER:: nPartOld - !Number of injected particles - INTEGER:: nPartInj !Arrays that contain the particles TYPE(particle), ALLOCATABLE, DIMENSION(:), TARGET:: partOld !array of particles from previous iteration - TYPE(particle), ALLOCATABLE, DIMENSION(:), TARGET:: partInj !array of inject particles CONTAINS FUNCTION speciesName2Index(speciesName) RESULT(sp) diff --git a/src/modules/solver/moduleSolver.f90 b/src/modules/solver/moduleSolver.f90 index f951839..e0ca06c 100644 --- a/src/modules/solver/moduleSolver.f90 +++ b/src/modules/solver/moduleSolver.f90 @@ -235,23 +235,21 @@ MODULE moduleSolver INTEGER:: nn, n, e INTEGER, SAVE:: nPartNew - INTEGER, SAVE:: nInjIn, nOldIn, nWScheme, nCollisions, nSurfaces + INTEGER, SAVE:: nOldIn, nInj, nWScheme, nCollisions, nSurfaces TYPE(particle), ALLOCATABLE, SAVE:: partTemp(:) INTEGER:: s !$OMP SECTIONS !$OMP SECTION - nInjIn = 0 - IF (ALLOCATED(partInj)) THEN - nInjIn = COUNT(partInj%n_in) - - END IF - !$OMP SECTION nOldIn = 0 IF (ALLOCATED(partOld)) THEN nOldIn = COUNT(partOld%n_in) END IF + + !$OMP SECTION + nInj = partInj%amount + !$OMP SECTION nWScheme = partWScheme%amount @@ -267,30 +265,14 @@ MODULE moduleSolver !$OMP SINGLE CALL MOVE_ALLOC(partOld, partTemp) - nPartNew = nInjIn + nOldIn + nWScheme + nCollisions + nSurfaces + nPartNew = nInj + nOldIn + nWScheme + nCollisions + nSurfaces ALLOCATE(partOld(1:nPartNew)) !$OMP END SINGLE !$OMP SECTIONS - !$OMP SECTION - !Reset particles from injection - nn = 0 - DO n = 1, nPartInj - IF (partInj(n)%n_in) THEN - nn = nn + 1 - partOld(nn) = partInj(n) - IF (nProbes > 0) THEN - CALL doProbes(partOld(nn)) - - END IF - - END IF - - END DO - !$OMP SECTION !Reset particles from previous iteration - nn = nInjIn + nn = 0 DO n = 1, nPartOld IF (partTemp(n)%n_in) THEN nn = nn + 1 @@ -304,19 +286,24 @@ MODULE moduleSolver END DO + !$OMP SECTION + !Reset particles from injection + nn = nOldIn + call resetList(partInj, partOld, nn) + !$OMP SECTION !Reset particles from weighting scheme - nn = nInjIn + nOldIn + nn = nOldIn + nInj CALL resetList(partWScheme, partOld, nn) !$OMP SECTION !Reset particles from collisional process - nn = nInjIn + nOldIn + nWScheme + nn = nOldIn + nInj + nWScheme CALL resetList(partCollisions, partOld, nn) !$OMP SECTION !Reset particles from surface process - nn = nInjIn + nOldIn + nWScheme + nCollisions + nn = nOldIn + nInj + nWScheme + nCollisions CALL resetList(partSurfaces, partOld, nn) !$OMP SECTION @@ -473,6 +460,28 @@ MODULE moduleSolver END SUBROUTINE splitParticle + !Injection of particles + SUBROUTINE doInjects() + USE moduleSpecies + use moduleInject + IMPLICIT NONE + + INTEGER:: i, n, sp + + DO i=1, nInject + associate(inject => injects(i)%obj) + sp = inject%species%n + IF (solver%pusher(sp)%pushSpecies) THEN + + CALL inject%addParticles() + + END IF + end associate + + END DO + + END SUBROUTINE doInjects + SUBROUTINE updateParticleCell(self, part) USE moduleSpecies USE moduleMesh From 70deaf08fa2f4a69a7d831bdc89d4994acb7a3ca Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Sun, 5 Apr 2026 15:27:50 +0200 Subject: [PATCH 18/21] Remove unused variables --- src/modules/solver/moduleSolver.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/solver/moduleSolver.f90 b/src/modules/solver/moduleSolver.f90 index e0ca06c..635c9eb 100644 --- a/src/modules/solver/moduleSolver.f90 +++ b/src/modules/solver/moduleSolver.f90 @@ -466,7 +466,7 @@ MODULE moduleSolver use moduleInject IMPLICIT NONE - INTEGER:: i, n, sp + INTEGER:: i, sp DO i=1, nInject associate(inject => injects(i)%obj) From 813edbb6a343507ece13d38a1d0520bdc28217f3 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Sun, 5 Apr 2026 15:28:29 +0200 Subject: [PATCH 19/21] Changed the injection quasiNuetral type to keep a 0 electric field at the edge --- src/modules/moduleInject.f90 | 62 ++++++++++++++---------------------- 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/src/modules/moduleInject.f90 b/src/modules/moduleInject.f90 index 942189c..2b23ac6 100644 --- a/src/modules/moduleInject.f90 +++ b/src/modules/moduleInject.f90 @@ -53,6 +53,7 @@ MODULE moduleInject end type injectconstant type, extends(injectGeneric):: injectQuasiNeutral + real(8):: qSign_incident end type injectQuasiNeutral @@ -228,6 +229,14 @@ MODULE moduleInject !Scale particles for different species steps IF (self%nParticles == 0) CALL criticalError("The number of particles for inject is 0.", 'initInject') + ! Specific parameters per type + select type(self) + type is(injectQuasiNeutral) + ! Get the sign of the charged species + self%qSign_incident = sign(1.d0, self%species%qm) + + end select + END SUBROUTINE initInject ! Update the value of injects @@ -248,17 +257,15 @@ MODULE moduleInject ! Updates the flow in the injection to maintain quasineutrality subroutine updateQuasiNeutral(self) - use moduleMesh, only: meshEdge, meshNode, mesh, qSpecies + use moduleMesh, only: meshEdge, meshCell implicit none class(injectGeneric), intent(inout):: self - integer:: e, s, n - integer, allocatable:: nodes(:) + integer:: e class(meshEdge), pointer:: edge - real(8), allocatable:: density_nodes(:) - class(meshNode), pointer:: node - real(8):: den_center - real(8):: density_incident, density_rest + class(meshCell), pointer:: cell + real(8):: Xi(1:3) + real(8):: EF_normal real(8):: alpha select type(self) @@ -266,43 +273,22 @@ MODULE moduleInject do e = 1, self%nEdges edge => self%edges(e)%obj - density_incident = 0.d0 - density_rest = 0.d0 + Xi = edge%centerXi() - nodes = edge%getNodes(edge%nNodes) - allocate(density_nodes(1:edge%nNodes)) - do s = 1, nSpecies - do n = 1, edge%nNodes - node => mesh%nodes(nodes(n))%obj - - density_nodes(n) = node%output(s)%den - - end do - - ! Gather the density at the edge center and multiply by the species charge - den_center = qSpecies(s)*edge%gatherF(edge%centerXi(), edge%nNodes, density_nodes) - - if (s == self%species%n) then - density_incident = den_center - - else - density_rest = density_rest + den_center - - end if - - end do - - ! Correction for this time step - if (density_rest > 1.0d-10) then - ! If there is a rest population, correct - alpha = 1.d0 + density_incident/density_rest + if (associated(edge%e1)) then + cell => edge%e1 else - ! If not, alpha is assumed unchaged - alpha = 0.d0 + cell => edge%e2 end if + ! Projection of EF on the edge normal vector + EF_normal = dot_product(cell%gatherElectricField(Xi), edge%normal) + + ! Correction for this time step + alpha = self%qSign_incident * EF_normal + ! Adjust the weight of particles to match the new current self%weightPerEdge(e) = self%weightPerEdge(e) + 1.0d-1 * alpha From 8ce86663a771b1f6847f7cefdaec672fda294fac Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Sun, 5 Apr 2026 15:29:46 +0200 Subject: [PATCH 20/21] txs auto checkin --- doc/user-manual/fpakc_UserManual.tex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/user-manual/fpakc_UserManual.tex b/doc/user-manual/fpakc_UserManual.tex index f9f9ae8..75f0106 100644 --- a/doc/user-manual/fpakc_UserManual.tex +++ b/doc/user-manual/fpakc_UserManual.tex @@ -697,8 +697,7 @@ make \begin{itemize} \item \textbf{constant}: The flow does not change. This is the default value if none is provided. - \item \textbf{quasiNeutral}: The flow of the species is changed over time to keep the charge density close to zero at the injection surface. - The weight of the injected particles is changed. + \item \textbf{quasiNeutral}: The weight of the injected species' particles is changed over time to keep a zero electric field at the boundary. \end{itemize} \item \textbf{physicalSurface}: Integer. Identification of the edge in the mesh file. From 2c49e477126748581892f4d1b13b74119cc53b80 Mon Sep 17 00:00:00 2001 From: JGonzalez Date: Mon, 6 Apr 2026 12:02:34 +0200 Subject: [PATCH 21/21] Avoid very low macroparticle weight --- src/modules/moduleInject.f90 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/moduleInject.f90 b/src/modules/moduleInject.f90 index 2b23ac6..52e26d3 100644 --- a/src/modules/moduleInject.f90 +++ b/src/modules/moduleInject.f90 @@ -292,6 +292,9 @@ MODULE moduleInject ! Adjust the weight of particles to match the new current self%weightPerEdge(e) = self%weightPerEdge(e) + 1.0d-1 * alpha + ! Limit the weight of a macroparticle to 1.0 + self%weightPerEdge(e) = max(self%weightPerEdge(e), 1.d0) + end do end select