Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 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
11 changes: 11 additions & 0 deletions src/amr/debugod.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "debugod.hpp"


namespace PHARE::amr
{
DEBUGOD& DEBUGOD::INSTANCE()
{
static DEBUGOD instance;
return instance;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix template instantiation for compilation.

The DEBUGOD class is a template but this implementation doesn't specify the template parameter, which will cause compilation errors.

Since this is a template class, either move the implementation to the header file or provide explicit template instantiations. Here's the fix to move it to the header:

-namespace PHARE::amr
-{
-DEBUGOD& DEBUGOD::INSTANCE()
-{
-    static DEBUGOD instance;
-    return instance;
-}
-}; // namespace PHARE::amr

And add this implementation in debugod.hpp after the class definition:

template<std::size_t dim>
DEBUGOD<dim>& DEBUGOD<dim>::INSTANCE()
{
    static DEBUGOD<dim> instance;
    return instance;
}
🤖 Prompt for AI Agents
In src/amr/debugod.cpp around lines 6 to 10, the implementation of the template
class DEBUGOD's INSTANCE method lacks the template parameter, causing
compilation errors. To fix this, move the implementation of the INSTANCE method
to the header file debugod.hpp after the class definition, and specify the
template parameter explicitly as template<std::size_t dim>. Implement INSTANCE
as a template method returning a static instance of DEBUGOD<dim>.

}; // namespace PHARE::amr
189 changes: 189 additions & 0 deletions src/amr/debugod.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#ifndef PHARE_DEBUGOD_HPP
#define PHARE_DEBUGOD_HPP

#include "core/def.hpp"
#include "core/utilities/point/point.hpp"
#include "core/utilities/mpi_utils.hpp"
#include "amr/wrappers/hierarchy.hpp"
#include "core/utilities/box/box.hpp"

#include <SAMRAI/hier/PatchHierarchy.h>

#include <memory>
#include <string>
#include <vector>
#include <unordered_map>
#include <cstdint>

namespace PHARE::amr
{


template<std::size_t dim>
class DEBUGOD
{
public:
using Point_t = PHARE::core::Point<double, dim>;

struct GodValue
{
Point_t coords;
std::array<int, dim> loc_index;
std::array<int, dim> amr_index;
double value;
int rank;
int patchID;

// Add other necessary fields and methods as needed
};
using GodExtract = std::unordered_map<std::uint32_t, std::vector<GodValue>>;

NO_DISCARD static DEBUGOD& INSTANCE();

void init() { god_ = std::make_unique<DEBUGOD>(); }

void setHierarchy(std::shared_ptr<SAMRAI::hier::PatchHierarchy> const& hier)
{
hierarchy_ = hier;
}

NO_DISCARD auto inspect(std::string name, Point_t& lower, Point_t& upper) const
{
GodExtract god_values;
for (auto ilvl = 0u; ilvl < hierarchy_->getNumberOfLevels(); ++ilvl)
{
auto level = hierarchy_->getPatchLevel(ilvl);
god_values[ilvl] = std::vector<GodValue>{};

for (auto& patch : *level)
{
if (!is_local(patch))
continue;

auto extract_box = PHARE::core::Box<double, dim>{lower, upper};
auto patch_ghost_box
= phare_box_from<dim, double>(getPatchData(patch, name)->getGhostBox());

auto intersected_box = *extract_box;

if (intersected_box.isEmpty())
continue;

auto& field = getField(patch, name);
auto layout = getLayoutFromPatch(patch, field->physicalQuantity());

// loop on nodes
// given the mesh_size_ on root level
// it is easy to get the level mesh size
// and given the lower/upper bounds of the coordinates
// it's easy to iterate over all nodes
// these if constexpr may be removable
// with the FieldBox object maybe....

GodValue gval;

if constexpr (dim == 1)
{
//
}

else if constexpr (dim == 2)
{
auto& dl = layout.meshSize();
auto ixStart = intersected_box.lower(0) / dl[0] - layout.origin()[0];
auto ixEnd = intersected_box.upper(0) / dl[0] - layout.origin()[0];

auto iyStart = intersected_box.lower(1) / dl[1] - layout.origin()[1];
auto iyEnd = intersected_box.upper(1) / dl[1] - layout.origin()[1];

for (auto ix = ixStart; ix <= ixEnd; ++ix)
{
for (auto iy = iyStart; iy <= iyEnd; ++iy)
{
gval.coords
= layout.fieldNodeCoordinates(field, layout.origin(), ix, iy);
gval.value = field(ix, iy);
}
}
}
else if constexpr (dim == 3)
{
// for (auto& node : intersected_box)
// {
// }
}
god_values[ilvl].push_back(gval);
}
}

return god_values;
}


NO_DISCARD auto inspect(std::string name, Point_t& coord)
{
return inspect(name, coord, coord);
}



void print(GodExtract const& god_values)
{
for (auto& [ilvl, values] : god_values)
{
std::cout << "Level " << ilvl << ":\n";
for (auto& v : values)
{
auto& coords = v.coords;
auto& loc_idx = v.loc_index;
auto& amr_idx = v.loc_index;
auto& rank = v.rank;
auto& patchID = v.patchID;

std::cout << "\n";
}
}
}
Comment on lines +163 to +179
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Complete the print implementation

The print method extracts variables but doesn't output them. Consider implementing proper output formatting.

 void print(GodExtract const& god_values)
 {
     for (auto& [ilvl, values] : god_values)
     {
         std::cout << "Level " << ilvl << ":\n";
         for (auto& v : values)
         {
             auto& coords  = v.coords;
             auto& loc_idx = v.loc_index;
-            auto& amr_idx = v.loc_index;
+            auto& amr_idx = v.amr_index;
             auto& rank    = v.rank;
             auto& patchID = v.patchID;
+            auto& value   = v.value;

-            std::cout << "\n";
+            std::cout << "  Patch " << patchID << " (rank " << rank << "):\n";
+            std::cout << "    Coords: (";
+            for (std::size_t d = 0; d < dimension; ++d) {
+                if (d > 0) std::cout << ", ";
+                std::cout << coords[d];
+            }
+            std::cout << ")\n";
+            std::cout << "    Value: " << value << "\n";
+            std::cout << "    Local index: (";
+            for (std::size_t d = 0; d < dimension; ++d) {
+                if (d > 0) std::cout << ", ";
+                std::cout << loc_idx[d];
+            }
+            std::cout << ")\n";
         }
     }
 }
📝 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
void print(GodExtract const& god_values)
{
for (auto& [ilvl, values] : god_values)
{
std::cout << "Level " << ilvl << ":\n";
for (auto& v : values)
{
auto& coords = v.coords;
auto& loc_idx = v.loc_index;
auto& amr_idx = v.loc_index;
auto& rank = v.rank;
auto& patchID = v.patchID;
std::cout << "\n";
}
}
}
void print(GodExtract const& god_values)
{
for (auto& [ilvl, values] : god_values)
{
std::cout << "Level " << ilvl << ":\n";
for (auto& v : values)
{
auto& coords = v.coords;
auto& loc_idx = v.loc_index;
auto& amr_idx = v.amr_index;
auto& rank = v.rank;
auto& patchID = v.patchID;
auto& value = v.value;
std::cout << " Patch " << patchID << " (rank " << rank << "):\n";
std::cout << " Coords: (";
for (std::size_t d = 0; d < dimension; ++d) {
if (d > 0) std::cout << ", ";
std::cout << coords[d];
}
std::cout << ")\n";
std::cout << " Value: " << value << "\n";
std::cout << " Local index: (";
for (std::size_t d = 0; d < dimension; ++d) {
if (d > 0) std::cout << ", ";
std::cout << loc_idx[d];
}
std::cout << ")\n";
}
}
}
🤖 Prompt for AI Agents
In src/amr/debugod.hpp between lines 160 and 176, the print method extracts
variables from god_values but does not output their contents. Complete the
implementation by adding std::cout statements to print the values of coords,
loc_index, amr_idx (correct the duplicate reference), rank, and patchID with
clear labels and formatting for readability.



// void stop() { god_.release(); }

// NO_DISCARD auto& god()
// {
// if (!god_)
// init();
// return *god_;
// }

private:
bool is_local(SAMRAI::hier::Patch const& patch) const
{
return patch.getBox().getBoxId().getOwnerRank() == PHARE::core::mpi::rank();
}

auto& getPatchData(SAMRAI::hier::Patch const& patch, std::string const& name)
{
auto db = SAMRAI::hier::VariableDatabase::getDatabase();
auto var_id = db->getVariable(name);
auto context = db->getContext("default");
return patch.getPatchData(var_id, context);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for potential null returns.

The method should handle cases where the variable or context might not exist in the database.

Apply this diff to add error handling:

 auto& getPatchData(SAMRAI::hier::Patch const& patch, std::string const& name)
 {
     auto db      = SAMRAI::hier::VariableDatabase::getDatabase();
     auto var_id  = db->getVariable(name);
+    if (!var_id) {
+        throw std::runtime_error("Variable '" + name + "' not found in database");
+    }
     auto context = db->getContext("default");
-    return patch.getPatchData(var_id, context);
+    auto data = patch.getPatchData(var_id, context);
+    if (!data) {
+        throw std::runtime_error("Patch data not found for variable '" + name + "'");
+    }
+    return *data;
 }
📝 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
auto& getPatchData(SAMRAI::hier::Patch const& patch, std::string const& name)
{
auto db = SAMRAI::hier::VariableDatabase::getDatabase();
auto var_id = db->getVariable(name);
auto context = db->getContext("default");
return patch.getPatchData(var_id, context);
}
auto& getPatchData(SAMRAI::hier::Patch const& patch, std::string const& name)
{
auto db = SAMRAI::hier::VariableDatabase::getDatabase();
auto var_id = db->getVariable(name);
if (!var_id) {
throw std::runtime_error("Variable '" + name + "' not found in database");
}
auto context = db->getContext("default");
auto data = patch.getPatchData(var_id, context);
if (!data) {
throw std::runtime_error("Patch data not found for variable '" + name + "'");
}
return *data;
}
🤖 Prompt for AI Agents
In src/amr/debugod.hpp around lines 127 to 133, the getPatchData function does
not handle cases where getVariable or getContext might return null pointers. Add
checks after retrieving var_id and context to verify they are not null. If
either is null, handle the error appropriately, such as throwing an exception or
returning an error indicator, to prevent undefined behavior when calling
patch.getPatchData.


auto& getField(SAMRAI::hier::Patch const& patch, std::string const& name)
{
auto db = SAMRAI::hier::VariableDatabase::getDatabase();
auto var_id = db->getVariable(name);
// auto context = db->getContext("default");
// auto patchdata = patch.getPatchData(var_id, context);
return FieldData::getPatchData(patch, var_id);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Complete the getField implementation and add missing include.

The method references FieldData which is not included or defined. Also, the return type is not specified.

Add the necessary include at the top of the file:

#include "amr/data/field/field_data.hpp" // or the appropriate header

And complete the implementation:

-auto& getField(SAMRAI::hier::Patch const& patch, std::string const& name)
+auto& getField(SAMRAI::hier::Patch const& patch, std::string const& name) const
 {
     auto db     = SAMRAI::hier::VariableDatabase::getDatabase();
     auto var_id = db->getVariable(name);
-    // auto context   = db->getContext("default");
-    // auto patchdata = patch.getPatchData(var_id, context);
+    if (!var_id) {
+        throw std::runtime_error("Variable '" + name + "' not found in database");
+    }
     return FieldData::getPatchData(patch, var_id);
 }
🤖 Prompt for AI Agents
In src/amr/debugod.hpp around lines 135 to 142, the getField method lacks a
specified return type and references FieldData without including its definition.
Add the include directive for "amr/data/field/field_data.hpp" at the top of the
file to provide FieldData's declaration. Then, specify the correct return type
for getField, likely a reference to the FieldData type returned by getPatchData,
and ensure the method implementation correctly returns that type.




DEBUGOD() {}
std::unique_ptr<DEBUGOD> god_;
std::shared_ptr<SAMRAI::hier::PatchHierarchy> hierarchy_;
};
}; // namespace PHARE::amr

#endif
8 changes: 8 additions & 0 deletions src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,14 @@ namespace amr
magSharedNodeRefineSchedules[levelNumber]->fillData(time);
elecSharedNodesRefiners_.fill(hybridModel.state.electromag.E, levelNumber, time);

auto& god = DEBUGOD::INSTANCE();
if (god.time_is("EM_B_x", 0.225))
{
auto bx_dbg = god.inpect("EM_B_x", {12.2, 13.5});
god.print(bx_dbg);
auto bx_dbg_rge = god.inpect("EM_B_x", {12.2, 8.0}, {12.6, 9.});
}

// we fill magnetic field ghosts only on patch ghost nodes and not on level
// ghosts the reason is that 1/ filling ghosts is necessary to prevent mismatch
// between ghost and overlaped neighboring patch domain nodes resulting from
Expand Down
2 changes: 2 additions & 0 deletions src/simulator/simulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "amr/load_balancing/load_balancer_details.hpp"
#include "amr/load_balancing/load_balancer_manager.hpp"
#include "amr/load_balancing/load_balancer_estimator_hybrid.hpp"
#include "amr/debugod.hpp"

namespace PHARE
{
Expand Down Expand Up @@ -339,6 +340,7 @@ Simulator<_dimension, _interp_order, _nbRefinedPart>::Simulator(
, functors_{functors_setup(dict)}
, multiphysInteg_{std::make_shared<MultiPhysicsIntegrator>(dict["simulation"], functors_)}
{
PHARE::amr::DEBUGOD<_dimension>::INSTANCE().setHierarchy(hierarchy_);
if (find_model("HybridModel"))
hybrid_init(dict);
else
Expand Down
Loading