1010#include " core/utilities/index/index.hpp"
1111#include " refiner_pool.hpp"
1212#include " synchronizer_pool.hpp"
13+ #include " amr/data/field/coarsening/field_coarsen_operator.hpp"
1314#include " amr/data/field/coarsening/default_field_coarsener.hpp"
1415#include " amr/data/field/coarsening/magnetic_field_coarsener.hpp"
16+ #include " amr/data/field/coarsening/flux_sum_coarsener.hpp"
1517#include " amr/data/field/refine/field_refiner.hpp"
1618#include " amr/data/field/refine/magnetic_field_refiner.hpp"
1719#include " amr/data/field/refine/electric_field_refiner.hpp"
1820#include " amr/data/field/time_interpolate/field_linear_time_interpolate.hpp"
1921#include " amr/data/field/refine/field_refine_operator.hpp"
20- #include " amr/data/field/coarsening/field_coarsen_operator.hpp"
2122#include " amr/messengers/messenger_info.hpp"
2223#include " amr/messengers/hybrid_messenger_info.hpp"
2324#include " amr/messengers/hybrid_messenger_strategy.hpp"
3536
3637#include " SAMRAI/xfer/RefineAlgorithm.h"
3738#include " SAMRAI/xfer/RefineSchedule.h"
39+ #include " SAMRAI/xfer/CoarsenAlgorithm.h"
40+ #include " SAMRAI/xfer/CoarsenSchedule.h"
3841#include " SAMRAI/xfer/BoxGeometryVariableFillPattern.h"
3942
4043
@@ -99,6 +102,7 @@ namespace amr
99102 using BaseCoarsenOp = FieldCoarsenOperator<GridLayoutT, GridT, Policy>;
100103 using MagneticCoarsenOp = BaseCoarsenOp<MagneticFieldCoarsener<dimension>>;
101104 using DefaultCoarsenOp = BaseCoarsenOp<DefaultFieldCoarsener<dimension>>;
105+ using FluxSumCoarsenOp = BaseCoarsenOp<FluxSumCoarsener<dimension>>;
102106
103107 public:
104108 static inline std::string const stratName = " HybridModel-HybridModel" ;
@@ -185,6 +189,42 @@ namespace amr
185189 BalgoNode.registerRefine (*bz_id, *bz_id, *bz_id, BfieldNodeRefineOp_,
186190 zVariableFillPattern);
187191
192+ // refluxing
193+ // we first want to coarsen the flux sum onto the coarser level
194+ auto ex_reflux_id = resourcesManager_->getID (hybridInfo->refluxElectric .xName );
195+ auto ey_reflux_id = resourcesManager_->getID (hybridInfo->refluxElectric .yName );
196+ auto ez_reflux_id = resourcesManager_->getID (hybridInfo->refluxElectric .zName );
197+
198+ auto ex_fluxsum_id = resourcesManager_->getID (hybridInfo->fluxSumElectric .xName );
199+ auto ey_fluxsum_id = resourcesManager_->getID (hybridInfo->fluxSumElectric .yName );
200+ auto ez_fluxsum_id = resourcesManager_->getID (hybridInfo->fluxSumElectric .zName );
201+
202+ if (!ex_reflux_id or !ey_reflux_id or !ez_reflux_id or !ex_fluxsum_id or !ey_fluxsum_id
203+ or !ez_fluxsum_id)
204+ {
205+ throw std::runtime_error (
206+ " HybridHybridMessengerStrategy: missing electric field variable IDs" );
207+ }
208+
209+ RefluxAlgo.registerCoarsen (*ex_reflux_id, *ex_fluxsum_id, fluxSumCoarseningOp_,
210+ xVariableFillPattern);
211+ RefluxAlgo.registerCoarsen (*ey_reflux_id, *ey_fluxsum_id, fluxSumCoarseningOp_,
212+ yVariableFillPattern);
213+ RefluxAlgo.registerCoarsen (*ez_reflux_id, *ez_fluxsum_id, fluxSumCoarseningOp_,
214+ zVariableFillPattern);
215+
216+ // we then need to refill the ghosts so that they agree with the newly refluxed cells
217+
218+ GhostRefluxedAlgo.registerRefine (*ex_reflux_id, *ex_reflux_id, *ex_reflux_id,
219+ EfieldRefineOp_, xVariableFillPattern);
220+
221+ GhostRefluxedAlgo.registerRefine (*ey_reflux_id, *ey_reflux_id, *ey_reflux_id,
222+ EfieldRefineOp_, yVariableFillPattern);
223+
224+ GhostRefluxedAlgo.registerRefine (*ez_reflux_id, *ez_reflux_id, *ez_reflux_id,
225+ EfieldRefineOp_, zVariableFillPattern);
226+
227+
188228 registerGhostComms_ (hybridInfo);
189229 registerInitComms (hybridInfo);
190230 registerSyncComms (hybridInfo);
@@ -210,6 +250,9 @@ namespace amr
210250 magGhostsRefineSchedules[levelNumber] = Balgo.createSchedule (
211251 level, levelNumber - 1 , hierarchy, &magneticRefinePatchStrategy_);
212252
253+ // technically not needed for finest
254+ ghostRefluxedSchedules[levelNumber] = GhostRefluxedAlgo.createSchedule (level);
255+
213256 elecSharedNodesRefiners_.registerLevel (hierarchy, level);
214257 currentSharedNodesRefiners_.registerLevel (hierarchy, level);
215258
@@ -227,9 +270,14 @@ namespace amr
227270 // TODO this 'if' may not be OK if L0 is regrided
228271 if (levelNumber != rootLevelNumber)
229272 {
273+ // refluxing
274+ auto const & coarseLevel = hierarchy->getPatchLevel (levelNumber - 1 );
275+ refluxSchedules[levelNumber] = RefluxAlgo.createSchedule (coarseLevel, level);
276+
230277 // those are for refinement
231278 magInitRefineSchedules[levelNumber] = Balgo.createSchedule (
232279 level, nullptr , levelNumber - 1 , hierarchy, &magneticRefinePatchStrategy_);
280+
233281 electricInitRefiners_.registerLevel (hierarchy, level);
234282 domainParticlesRefiners_.registerLevel (hierarchy, level);
235283 lvlGhostPartOldRefiners_.registerLevel (hierarchy, level);
@@ -544,6 +592,7 @@ namespace amr
544592
545593
546594
595+
547596 /* *
548597 * @brief prepareStep is the concrete implementation of the
549598 * HybridMessengerStrategy::prepareStep method For hybrid-Hybrid communications.
@@ -564,8 +613,7 @@ namespace amr
564613 for (auto & patch : level)
565614 {
566615 auto dataOnPatch = resourcesManager_->setOnPatch (
567- *patch, hybridModel.state .electromag , hybridModel.state .J ,
568- hybridModel.state .ions , Jold_, NiOld_, ViOld_);
616+ *patch, hybridModel.state .J , hybridModel.state .ions , Jold_, NiOld_, ViOld_);
569617
570618 resourcesManager_->setTime (Jold_, *patch, currentTime);
571619 resourcesManager_->setTime (NiOld_, *patch, currentTime);
@@ -623,12 +671,20 @@ namespace amr
623671 PHARE_LOG_LINE_STR (" synchronizing level " + std::to_string (levelNumber));
624672
625673 // call coarsning schedules...
626- magnetoSynchronizers_.sync (levelNumber);
674+ // magnetoSynchronizers_.sync(levelNumber);
627675 electroSynchronizers_.sync (levelNumber);
628676 densitySynchronizers_.sync (levelNumber);
629677 ionBulkVelSynchronizers_.sync (levelNumber);
630678 }
631679
680+
681+ void reflux (int const coarserLevelNumber, int const fineLevelNumber,
682+ double const syncTime) override
683+ {
684+ refluxSchedules[fineLevelNumber]->coarsenData ();
685+ ghostRefluxedSchedules[coarserLevelNumber]->fillData (syncTime);
686+ }
687+
632688 // after coarsening, domain nodes have been updated and therefore patch ghost nodes
633689 // will probably stop having the exact same value as their overlapped neighbor
634690 // domain node we thus fill ghost nodes. note that we first fill shared border nodes
@@ -654,7 +710,7 @@ namespace amr
654710 // level border with next coarser model B would invalidate divB on the first
655711 // fine domain cell since its border face only received a fraction of the
656712 // induction that has occured on the shared coarse face.
657- magPatchGhostsRefineSchedules[levelNumber]->fillData (time);
713+ // magPatchGhostsRefineSchedules[levelNumber]->fillData(time);
658714 elecGhostsRefiners_.fill (hybridModel.state .electromag .E , levelNumber, time);
659715 rhoGhostsRefiners_.fill (levelNumber, time);
660716 velGhostsRefiners_.fill (hybridModel.state .ions .velocity (), levelNumber, time);
@@ -973,7 +1029,6 @@ namespace amr
9731029
9741030
9751031
976-
9771032 VecFieldT Jold_{stratName + " _Jold" , core::HybridQuantity::Vector::J};
9781033 VecFieldT ViOld_{stratName + " _VBulkOld" , core::HybridQuantity::Vector::V};
9791034 FieldT NiOld_{stratName + " _NiOld" , core::HybridQuantity::Scalar::rho};
@@ -1011,6 +1066,10 @@ namespace amr
10111066 std::map<int , std::shared_ptr<SAMRAI::xfer::RefineSchedule>> magPatchGhostsRefineSchedules;
10121067 std::map<int , std::shared_ptr<SAMRAI::xfer::RefineSchedule>> magSharedNodeRefineSchedules;
10131068
1069+ SAMRAI::xfer::CoarsenAlgorithm RefluxAlgo{SAMRAI::tbox::Dimension{dimension}};
1070+ SAMRAI::xfer::RefineAlgorithm GhostRefluxedAlgo;
1071+ std::map<int , std::shared_ptr<SAMRAI::xfer::CoarsenSchedule>> refluxSchedules;
1072+ std::map<int , std::shared_ptr<SAMRAI::xfer::RefineSchedule>> ghostRefluxedSchedules;
10141073
10151074 // ! store refiners for electric fields that need ghosts to be filled
10161075 SharedNodeRefinerPool elecSharedNodesRefiners_{resourcesManager_};
@@ -1069,6 +1128,7 @@ namespace amr
10691128 using CoarsenOperator_ptr = std::shared_ptr<SAMRAI::hier::CoarsenOperator>;
10701129 CoarsenOperator_ptr fieldCoarseningOp_{std::make_shared<DefaultCoarsenOp>()};
10711130 CoarsenOperator_ptr magneticCoarseningOp_{std::make_shared<MagneticCoarsenOp>()};
1131+ CoarsenOperator_ptr fluxSumCoarseningOp_{std::make_shared<FluxSumCoarsenOp>()};
10721132
10731133 MagneticRefinePatchStrategy<ResourcesManagerT, FieldDataT> magneticRefinePatchStrategy_{
10741134 *resourcesManager_};
0 commit comments