Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/amr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ set( SOURCES_INC
data/field/coarsening/field_coarsen_index_weight.hpp
data/field/coarsening/coarsen_weighter.hpp
data/field/coarsening/default_field_coarsener.hpp
data/field/coarsening/magnetic_field_coarsener.hpp
data/field/coarsening/electric_field_coarsener.hpp
data/field/field_data.hpp
data/field/field_data_factory.hpp
data/field/field_geometry.hpp
Expand All @@ -20,6 +20,7 @@ set( SOURCES_INC
data/field/refine/field_linear_refine.hpp
data/field/refine/field_refiner.hpp
data/field/refine/magnetic_field_refiner.hpp
data/field/refine/magnetic_field_regrider.hpp
data/field/refine/electric_field_refiner.hpp
data/field/refine/linear_weighter.hpp
data/field/refine/field_refine_operator.hpp
Expand Down
11 changes: 7 additions & 4 deletions src/amr/data/field/coarsening/default_field_coarsener.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@
#define PHARE_DEFAULT_FIELD_COARSENER_HPP


#include "core/def/phare_mpi.hpp"
#include "core/def/phare_mpi.hpp" // IWYU pragma: keep

#include "core/def.hpp"
#include "core/data/grid/gridlayoutdefs.hpp"
#include "core/utilities/constants.hpp"
#include "core/utilities/point/point.hpp"
#include "core/data/grid/gridlayoutdefs.hpp"

#include "amr/data/field/coarsening/field_coarsen_index_weight.hpp"
#include "amr/resources_manager/amr_utils.hpp"
#include "amr/data/field/coarsening/field_coarsen_index_weight.hpp"

#include <SAMRAI/hier/Box.h>

#include <cstddef>
#include <array>
#include <cstddef>




Expand Down Expand Up @@ -157,4 +158,6 @@ namespace amr
} // namespace PHARE




#endif
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#ifndef PHARE_MAGNETIC_FIELD_COARSENER
#define PHARE_MAGNETIC_FIELD_COARSENER


#include "core/def/phare_mpi.hpp"
#ifndef PHARE_ELECTRIC_FIELD_COARSENER
#define PHARE_ELECTRIC_FIELD_COARSENER

#include "amr/amr_constants.hpp"
#include "core/data/grid/gridlayoutdefs.hpp"
#include "core/hybrid/hybrid_quantities.hpp"
#include "core/utilities/constants.hpp"
#include "amr/resources_manager/amr_utils.hpp"


#include <SAMRAI/hier/Box.h>
#include <cstddef>
#include <stdexcept>

namespace PHARE::amr
Expand All @@ -32,13 +31,13 @@ using core::dirZ;
*
*/
template<std::size_t dimension>
class MagneticFieldCoarsener
class ElectricFieldCoarsener
{
public:
MagneticFieldCoarsener(std::array<core::QtyCentering, dimension> const centering,
ElectricFieldCoarsener(std::array<core::QtyCentering, dimension> const centering,
SAMRAI::hier::Box const& sourceBox,
SAMRAI::hier::Box const& destinationBox,
SAMRAI::hier::IntVector const& ratio)
SAMRAI::hier::IntVector const& /*ratio*/)
: centering_{centering}
, sourceBox_{sourceBox}
, destinationBox_{destinationBox}
Expand All @@ -55,86 +54,101 @@ class MagneticFieldCoarsener

core::Point<int, dimension> fineStartIndex;

fineStartIndex[dirX] = coarseIndex[dirX] * this->ratio_;

if constexpr (dimension > 1)
for (auto i = std::size_t{0}; i < dimension; ++i)
{
fineStartIndex[dirY] = coarseIndex[dirY] * this->ratio_;
if constexpr (dimension > 2)
{
fineStartIndex[dirZ] = coarseIndex[dirZ] * this->ratio_;
}
fineStartIndex[i] = coarseIndex[i] * refinementRatio;
}

fineStartIndex = AMRToLocal(fineStartIndex, sourceBox_);
coarseIndex = AMRToLocal(coarseIndex, destinationBox_);

// the following kinda assumes where B is, i.e. Yee layout centering
// as it only does faces pirmal-dual, dual-primal and dual-dual

if constexpr (dimension == 1)
{
// in 1D div(B) is automatically satisfied so using this coarsening
// opertor is probably not better than the default one, but we do that
// for a kind of consistency...
// coarse flux is equal to fine flux and we're 1D so there is flux partitioned
// only for By and Bz, Bx is equal to the fine value

if (centering_[dirX] == core::QtyCentering::primal) // bx
{
coarseField(coarseIndex[dirX]) = fineField(fineStartIndex[dirX]);
}
else if (centering_[dirX] == core::QtyCentering::dual) // by and bz
if (centering_[dirX] == core::QtyCentering::dual) // ex
{
coarseField(coarseIndex[dirX])
= 0.5 * (fineField(fineStartIndex[dirX] + 1) + fineField(fineStartIndex[dirX]));
}
else if (centering_[dirX] == core::QtyCentering::primal) // ey, ez
{
coarseField(coarseIndex[dirX]) = fineField(fineStartIndex[dirX]);
}
}
Comment on lines 65 to 76
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Coarsening assumes ratio==2 via 0.5 average; generalize to any refinement ratio along the dual axis.

Average over ratio_(X) fine edges for Ex in 1D; inject for primal. Current code is incorrect for ratios ≠ 2.

-            if (centering_[dirX] == core::QtyCentering::dual) // ex
-            {
-                coarseField(coarseIndex[dirX])
-                    = 0.5 * (fineField(fineStartIndex[dirX] + 1) + fineField(fineStartIndex[dirX]));
-            }
+            if (centering_[dirX] == core::QtyCentering::dual) // Ex
+            {
+                auto const rx = ratio_(dirX);
+                double acc    = 0.;
+                for (int sx = 0; sx < rx; ++sx)
+                    acc += fineField(fineStartIndex[dirX] + sx);
+                coarseField(coarseIndex[dirX]) = acc / rx;
+            }
             else if (centering_[dirX] == core::QtyCentering::primal) // ey, ez
             {
                 coarseField(coarseIndex[dirX]) = fineField(fineStartIndex[dirX]);
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if constexpr (dimension == 1)
{
// in 1D div(B) is automatically satisfied so using this coarsening
// opertor is probably not better than the default one, but we do that
// for a kind of consistency...
// coarse flux is equal to fine flux and we're 1D so there is flux partitioned
// only for By and Bz, Bx is equal to the fine value
if (centering_[dirX] == core::QtyCentering::primal) // bx
{
coarseField(coarseIndex[dirX]) = fineField(fineStartIndex[dirX]);
}
else if (centering_[dirX] == core::QtyCentering::dual) // by and bz
if (centering_[dirX] == core::QtyCentering::dual) // ex
{
coarseField(coarseIndex[dirX])
= 0.5 * (fineField(fineStartIndex[dirX] + 1) + fineField(fineStartIndex[dirX]));
}
else if (centering_[dirX] == core::QtyCentering::primal) // ey, ez
{
coarseField(coarseIndex[dirX]) = fineField(fineStartIndex[dirX]);
}
}
if constexpr (dimension == 1)
{
if (centering_[dirX] == core::QtyCentering::dual) // Ex
{
auto const rx = ratio_(dirX);
double acc = 0.;
for (int sx = 0; sx < rx; ++sx)
acc += fineField(fineStartIndex[dirX] + sx);
coarseField(coarseIndex[dirX]) = acc / rx;
}
else if (centering_[dirX] == core::QtyCentering::primal) // ey, ez
{
coarseField(coarseIndex[dirX]) = fineField(fineStartIndex[dirX]);
}
}


if constexpr (dimension == 2)
{
if (centering_[dirX] == core::QtyCentering::primal
and centering_[dirY] == core::QtyCentering::dual)
if (centering_[dirX] == core::QtyCentering::dual
and centering_[dirY] == core::QtyCentering::primal) // ex
{
coarseField(coarseIndex[dirX], coarseIndex[dirY])
= 0.5
* (fineField(fineStartIndex[dirX], fineStartIndex[dirY])
+ fineField(fineStartIndex[dirX], fineStartIndex[dirY] + 1));
+ fineField(fineStartIndex[dirX] + 1, fineStartIndex[dirY]));
}
Comment on lines +80 to 87
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

2D Ex: average across X over ratio_(X), not a hardcoded 0.5 of two points.

-            if (centering_[dirX] == core::QtyCentering::dual
-                and centering_[dirY] == core::QtyCentering::primal) // ex
+            if (centering_[dirX] == core::QtyCentering::dual
+                and centering_[dirY] == core::QtyCentering::primal) // Ex
             {
-                coarseField(coarseIndex[dirX], coarseIndex[dirY])
-                    = 0.5
-                      * (fineField(fineStartIndex[dirX], fineStartIndex[dirY])
-                         + fineField(fineStartIndex[dirX] + 1, fineStartIndex[dirY]));
+                auto const rx = ratio_(dirX);
+                double acc    = 0.;
+                for (int sx = 0; sx < rx; ++sx)
+                    acc += fineField(fineStartIndex[dirX] + sx, fineStartIndex[dirY]);
+                coarseField(coarseIndex[dirX], coarseIndex[dirY]) = acc / rx;
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (centering_[dirX] == core::QtyCentering::dual
and centering_[dirY] == core::QtyCentering::primal) // ex
{
coarseField(coarseIndex[dirX], coarseIndex[dirY])
= 0.5
* (fineField(fineStartIndex[dirX], fineStartIndex[dirY])
+ fineField(fineStartIndex[dirX], fineStartIndex[dirY] + 1));
+ fineField(fineStartIndex[dirX] + 1, fineStartIndex[dirY]));
}
if (centering_[dirX] == core::QtyCentering::dual
and centering_[dirY] == core::QtyCentering::primal) // Ex
{
auto const rx = ratio_(dirX);
double acc = 0.;
for (int sx = 0; sx < rx; ++sx)
acc += fineField(fineStartIndex[dirX] + sx, fineStartIndex[dirY]);
coarseField(coarseIndex[dirX], coarseIndex[dirY]) = acc / rx;
}
🤖 Prompt for AI Agents
In src/amr/data/field/coarsening/electric_field_coarsener.hpp around lines 80 to
87, the coarse-field assignment for the 2D Ex case currently uses a hardcoded
0.5 average of two points; replace that with a proper average across
ratio_[dirX] fine cells. Compute the sum of fineField over fineStartIndex[dirX]
.. fineStartIndex[dirX] + ratio_[dirX] - 1 (at the same fineStartIndex[dirY])
and divide by static_cast<double>(ratio_[dirX]) (or the appropriate scalar
type), or implement an explicit loop accumulating the values, then assign
coarseField = sum / ratio_[dirX]; ensure you reference ratio_[dirX] (not a
hardcoded 2) and preserve types/centering logic.

else if (centering_[dirX] == core::QtyCentering::dual
and centering_[dirY] == core::QtyCentering::primal)
else if (centering_[dirX] == core::QtyCentering::primal
and centering_[dirY] == core::QtyCentering::dual) // ey
{
coarseField(coarseIndex[dirX], coarseIndex[dirY])
= 0.5
* (fineField(fineStartIndex[dirX], fineStartIndex[dirY])
+ fineField(fineStartIndex[dirX] + 1, fineStartIndex[dirY]));
+ fineField(fineStartIndex[dirX], fineStartIndex[dirY] + 1));
}
Comment on lines +88 to 95
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

2D Ey: average across Y over ratio_(Y).

-            else if (centering_[dirX] == core::QtyCentering::primal
-                     and centering_[dirY] == core::QtyCentering::dual) // ey
+            else if (centering_[dirX] == core::QtyCentering::primal
+                     and centering_[dirY] == core::QtyCentering::dual) // Ey
             {
-                coarseField(coarseIndex[dirX], coarseIndex[dirY])
-                    = 0.5
-                      * (fineField(fineStartIndex[dirX], fineStartIndex[dirY])
-                         + fineField(fineStartIndex[dirX], fineStartIndex[dirY] + 1));
+                auto const ry = ratio_(dirY);
+                double acc    = 0.;
+                for (int sy = 0; sy < ry; ++sy)
+                    acc += fineField(fineStartIndex[dirX], fineStartIndex[dirY] + sy);
+                coarseField(coarseIndex[dirX], coarseIndex[dirY]) = acc / ry;
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
else if (centering_[dirX] == core::QtyCentering::primal
and centering_[dirY] == core::QtyCentering::dual) // ey
{
coarseField(coarseIndex[dirX], coarseIndex[dirY])
= 0.5
* (fineField(fineStartIndex[dirX], fineStartIndex[dirY])
+ fineField(fineStartIndex[dirX] + 1, fineStartIndex[dirY]));
+ fineField(fineStartIndex[dirX], fineStartIndex[dirY] + 1));
}
else if (centering_[dirX] == core::QtyCentering::primal
and centering_[dirY] == core::QtyCentering::dual) // Ey
{
auto const ry = ratio_(dirY);
double acc = 0.;
for (int sy = 0; sy < ry; ++sy)
acc += fineField(fineStartIndex[dirX], fineStartIndex[dirY] + sy);
coarseField(coarseIndex[dirX], coarseIndex[dirY]) = acc / ry;
}
🤖 Prompt for AI Agents
In src/amr/data/field/coarsening/electric_field_coarsener.hpp around lines
88-95, the 2D Ey case currently averages only two fine cells with a fixed factor
0.5 but must average across the full refinement ratio in Y (ratio_(Y)). Replace
the fixed two-point average with a sum over k=0..ratio_(Y)-1 of
fineField(fineStartIndex[dirX], fineStartIndex[dirY] + k) divided by
static_cast<Real>(ratio_(dirY)) (or 1.0/ratioY multiplied after the sum);
implement this with a small loop or std::accumulate to compute the sum and then
assign coarseField(coarseIndex[dirX], coarseIndex[dirY]) = sum * (1.0/ratioY).
Ensure you use the correct ratio variable for dirY and proper indexing types.

else if (centering_[dirX] == core::QtyCentering::dual
and centering_[dirY] == core::QtyCentering::dual)
else if (centering_[dirX] == core::QtyCentering::primal
and centering_[dirY] == core::QtyCentering::primal) // ez
{
coarseField(coarseIndex[dirX], coarseIndex[dirY])
= 0.25
* (fineField(fineStartIndex[dirX], fineStartIndex[dirY])
+ fineField(fineStartIndex[dirX] + 1, fineStartIndex[dirY])
+ fineField(fineStartIndex[dirX], fineStartIndex[dirY] + 1)
+ fineField(fineStartIndex[dirX] + 1, fineStartIndex[dirY] + 1));
= fineField(fineStartIndex[dirX], fineStartIndex[dirY]);
}
else
{
throw std::runtime_error("no magnetic field should end up here");
throw std::runtime_error("no electric field should end up here");
}
}
else if constexpr (dimension == 3)
{
throw std::runtime_error("Not Implemented yet");
if (centering_[dirX] == core::QtyCentering::dual
and centering_[dirY] == core::QtyCentering::primal
and centering_[dirZ] == core::QtyCentering::primal) // ex
{
coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ])
= 0.5
* (fineField(fineStartIndex[dirX], fineStartIndex[dirY], fineStartIndex[dirZ])
+ fineField(fineStartIndex[dirX] + 1, fineStartIndex[dirY],
fineStartIndex[dirZ]));
}
Comment on lines +109 to +118
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

3D Ex: average across X over ratio_(X).

-            if (centering_[dirX] == core::QtyCentering::dual
+            if (centering_[dirX] == core::QtyCentering::dual
                 and centering_[dirY] == core::QtyCentering::primal
                 and centering_[dirZ] == core::QtyCentering::primal) // ex
             {
-                coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ])
-                    = 0.5
-                      * (fineField(fineStartIndex[dirX], fineStartIndex[dirY], fineStartIndex[dirZ])
-                         + fineField(fineStartIndex[dirX] + 1, fineStartIndex[dirY],
-                                     fineStartIndex[dirZ]));
+                auto const rx = ratio_(dirX);
+                double acc    = 0.;
+                for (int sx = 0; sx < rx; ++sx)
+                    acc += fineField(fineStartIndex[dirX] + sx, fineStartIndex[dirY],
+                                     fineStartIndex[dirZ]);
+                coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ]) = acc / rx;
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (centering_[dirX] == core::QtyCentering::dual
and centering_[dirY] == core::QtyCentering::primal
and centering_[dirZ] == core::QtyCentering::primal) // ex
{
coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ])
= 0.5
* (fineField(fineStartIndex[dirX], fineStartIndex[dirY], fineStartIndex[dirZ])
+ fineField(fineStartIndex[dirX] + 1, fineStartIndex[dirY],
fineStartIndex[dirZ]));
}
if (centering_[dirX] == core::QtyCentering::dual
and centering_[dirY] == core::QtyCentering::primal
and centering_[dirZ] == core::QtyCentering::primal) // ex
{
auto const rx = ratio_(dirX);
double acc = 0.;
for (int sx = 0; sx < rx; ++sx)
acc += fineField(fineStartIndex[dirX] + sx, fineStartIndex[dirY],
fineStartIndex[dirZ]);
coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ]) = acc / rx;
}
🤖 Prompt for AI Agents
In src/amr/data/field/coarsening/electric_field_coarsener.hpp around lines
109-118 the code always averages exactly two fine cells in X using a hardcoded
0.5, but in 3D Ex coarsening you must average across ratio_[dirX] fine cells.
Replace the two-point average with a loop that accumulates
fineField(fineStartIndex[dirX] + i, fineStartIndex[dirY], fineStartIndex[dirZ])
for i = 0 .. ratio_[dirX]-1 and then assign coarseField = sum / ratio_[dirX];
ensure you use the integer ratio_ array (ratio_[dirX]) and appropriate numeric
type for the division to avoid integer truncation.

else if (centering_[dirX] == core::QtyCentering::primal
and centering_[dirY] == core::QtyCentering::dual
and centering_[dirZ] == core::QtyCentering::primal) // ey
{
coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ])
= 0.5
* (fineField(fineStartIndex[dirX], fineStartIndex[dirY], fineStartIndex[dirZ])
+ fineField(fineStartIndex[dirX], fineStartIndex[dirY] + 1,
fineStartIndex[dirZ]));
}
Comment on lines +119 to +128
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

3D Ey: average across Y over ratio_(Y).

-            else if (centering_[dirX] == core::QtyCentering::primal
+            else if (centering_[dirX] == core::QtyCentering::primal
                      and centering_[dirY] == core::QtyCentering::dual
                      and centering_[dirZ] == core::QtyCentering::primal) // ey
             {
-                coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ])
-                    = 0.5
-                      * (fineField(fineStartIndex[dirX], fineStartIndex[dirY], fineStartIndex[dirZ])
-                         + fineField(fineStartIndex[dirX], fineStartIndex[dirY] + 1,
-                                     fineStartIndex[dirZ]));
+                auto const ry = ratio_(dirY);
+                double acc    = 0.;
+                for (int sy = 0; sy < ry; ++sy)
+                    acc += fineField(fineStartIndex[dirX], fineStartIndex[dirY] + sy,
+                                     fineStartIndex[dirZ]);
+                coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ]) = acc / ry;
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
else if (centering_[dirX] == core::QtyCentering::primal
and centering_[dirY] == core::QtyCentering::dual
and centering_[dirZ] == core::QtyCentering::primal) // ey
{
coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ])
= 0.5
* (fineField(fineStartIndex[dirX], fineStartIndex[dirY], fineStartIndex[dirZ])
+ fineField(fineStartIndex[dirX], fineStartIndex[dirY] + 1,
fineStartIndex[dirZ]));
}
else if (centering_[dirX] == core::QtyCentering::primal
and centering_[dirY] == core::QtyCentering::dual
and centering_[dirZ] == core::QtyCentering::primal) // ey
{
auto const ry = ratio_(dirY);
double acc = 0.;
for (int sy = 0; sy < ry; ++sy)
acc += fineField(fineStartIndex[dirX], fineStartIndex[dirY] + sy,
fineStartIndex[dirZ]);
coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ]) = acc / ry;
}
🤖 Prompt for AI Agents
In src/amr/data/field/coarsening/electric_field_coarsener.hpp around lines 119
to 128, the Ey coarsening uses a hardcoded average of two fine cells (0.5 and
+1) which only works when ratio_[dirY]==2; change it to sum the fineField values
across the full refinement ratio in Y and divide by ratio_[dirY]. Implement a
small loop over ry from 0 to ratio_[dirY]-1, accumulate
fineField(fineStartIndex[dirX], fineStartIndex[dirY]+ry, fineStartIndex[dirZ])
into a local sum, then set coarseField(...) = sum /
static_cast<Real>(ratio_[dirY]) (keeping types consistent).

else if (centering_[dirX] == core::QtyCentering::primal
and centering_[dirY] == core::QtyCentering::primal
and centering_[dirZ] == core::QtyCentering::dual) // ez
{
coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ])
= 0.5
* (fineField(fineStartIndex[dirX], fineStartIndex[dirY], fineStartIndex[dirZ])
+ fineField(fineStartIndex[dirX], fineStartIndex[dirY],
fineStartIndex[dirZ] + 1));
}
Comment on lines +129 to +138
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

3D Ez: average across Z over ratio_(Z).

-            else if (centering_[dirX] == core::QtyCentering::primal
+            else if (centering_[dirX] == core::QtyCentering::primal
                      and centering_[dirY] == core::QtyCentering::primal
                      and centering_[dirZ] == core::QtyCentering::dual) // ez
             {
-                coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ])
-                    = 0.5
-                      * (fineField(fineStartIndex[dirX], fineStartIndex[dirY], fineStartIndex[dirZ])
-                         + fineField(fineStartIndex[dirX], fineStartIndex[dirY],
-                                     fineStartIndex[dirZ] + 1));
+                auto const rz = ratio_(dirZ);
+                double acc    = 0.;
+                for (int sz = 0; sz < rz; ++sz)
+                    acc += fineField(fineStartIndex[dirX], fineStartIndex[dirY],
+                                     fineStartIndex[dirZ] + sz);
+                coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ]) = acc / rz;
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
else if (centering_[dirX] == core::QtyCentering::primal
and centering_[dirY] == core::QtyCentering::primal
and centering_[dirZ] == core::QtyCentering::dual) // ez
{
coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ])
= 0.5
* (fineField(fineStartIndex[dirX], fineStartIndex[dirY], fineStartIndex[dirZ])
+ fineField(fineStartIndex[dirX], fineStartIndex[dirY],
fineStartIndex[dirZ] + 1));
}
else if (centering_[dirX] == core::QtyCentering::primal
and centering_[dirY] == core::QtyCentering::primal
and centering_[dirZ] == core::QtyCentering::dual) // ez
{
auto const rz = ratio_(dirZ);
double acc = 0.;
for (int sz = 0; sz < rz; ++sz)
acc += fineField(fineStartIndex[dirX], fineStartIndex[dirY],
fineStartIndex[dirZ] + sz);
coarseField(coarseIndex[dirX], coarseIndex[dirY], coarseIndex[dirZ]) = acc / rz;
}
🤖 Prompt for AI Agents
In src/amr/data/field/coarsening/electric_field_coarsener.hpp around lines 129
to 138, the 3D Ez coarsening currently averages only two fine-cell values
(fineStartIndex[dirZ] and fineStartIndex[dirZ]+1) but must average across the
full refinement ratio in Z; replace the fixed 2-point average with a loop or
accumulate over fineStartIndex[dirZ] .. fineStartIndex[dirZ] + ratio_[dirZ] - 1,
sum those fineField(...) values and divide by ratio_[dirZ] to compute
coarseField(...), keeping the existing indices for X and Y and using
ratio_[dirZ] as the divisor.

else
{
throw std::runtime_error("no electric field should end up here");
}
}
}

private:
std::array<core::QtyCentering, dimension> const centering_;
SAMRAI::hier::Box const sourceBox_;
SAMRAI::hier::Box const destinationBox_;
static int constexpr ratio_ = 2;
};

} // namespace PHARE::amr

#endif
5 changes: 1 addition & 4 deletions src/amr/data/field/coarsening/field_coarsen_index_weight.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@
#include "core/def/phare_mpi.hpp"

#include "core/def.hpp"
#include "coarsen_weighter.hpp"
#include "core/data/grid/gridlayoutdefs.hpp"
#include "core/hybrid/hybrid_quantities.hpp"
#include "core/data/field/field.hpp"
#include "core/utilities/constants.hpp"

#include "amr/resources_manager/amr_utils.hpp"

#include "coarsen_weighter.hpp"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential missing import of dirX/dirY/dirZ after include reordering.

This file uses dirX/dirY/dirZ unqualified, but no using core::dir*; nor core:: qualification is present. Since core/utilities/constants.hpp is no longer included here, this may fail if the symbols aren’t pulled transitively. Make usage explicit.

 namespace PHARE
 {
 namespace amr
 {
+    using core::dirX;
+    using core::dirY;
+    using core::dirZ;

Alternatively, qualify all occurrences (core::dirX, etc.).

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/amr/data/field/coarsening/field_coarsen_index_weight.hpp around line 12,
the reorder removed core/utilities/constants.hpp so unqualified symbols
dirX/dirY/dirZ may be undefined; update the file to either add an explicit
include for core/utilities/constants.hpp (or the specific header that defines
dirX/dirY/dirZ) or fully qualify all uses as core::dirX/core::dirY/core::dirZ so
the symbols are resolved without relying on transitive includes.


#include <SAMRAI/hier/Box.h>

Expand Down
Loading