Skip to content

Conversation

@PhilipDeegan
Copy link
Member

@PhilipDeegan PhilipDeegan commented Oct 8, 2025

Write diagnostics in VTKHDF file format

  • converting to all primal and fortran ordering

tested via manual inspection in paraview
We should probably use the vtk module in a test and generate some artifacts

@coderabbitai
Copy link

coderabbitai bot commented Oct 8, 2025

📝 Walkthrough

Walkthrough

Adds a VTK/HDF5 diagnostic backend ("pharevtkhdf") and writers, extends Python diagnostic format handling, refactors grid and ndarray indexing APIs, introduces new HDF5 helpers and VTK-type writer infrastructure, updates diagnostics dispatch, and adds tests for VTK diagnostics.

Changes

Cohort / File(s) Summary
Python diagnostic format support
pyphare/pyphare/pharein/__init__.py, pyphare/pyphare/pharein/simulation.py
Write diag format option when present and accept "pharevtkhdf" as a valid diagnostic format.
VTK‑HDF diagnostic writers & dispatcher
src/diagnostic/detail/vtkh5_writer.hpp, src/diagnostic/detail/vtkh5_type_writer.hpp, src/diagnostic/detail/vtk_types/electromag.hpp, src/diagnostic/detail/vtk_types/fluid.hpp, src/diagnostic/diagnostics.hpp
New MPI-aware VTK‑HDF writer types (H5Writer, H5TypeWriter) and per-type writers; diagnostics resolver now selects backend by format (phareh5 or pharevtkhdf).
HDF5 file utilities
src/hdf5/detail/h5/h5_file.hpp, src/diagnostic/detail/h5writer.hpp
Added chunk/resizable dataset helpers and exist/getDataSet APIs; adjusted move/copy semantics and includes; replaced some operator& deletions with operator= deletions and reorganized includes.
Grid layout & moment helpers
src/core/data/grid/gridlayout.hpp, src/core/data/grid/gridlayoutimplyee.hpp, src/core/data/grid/gridlayoutdefs.hpp
Added Bx/By/Bz moment accessors, renamed/swapped AMRBoxFor ↔ AMRGhostBoxFor, added amr_lcl_idx/domain/ghost helpers, replaced array init patterns with CTAD, and reordered includes.
NdArray indexing refactor
src/core/data/ndarray/ndarray_vector.hpp
Removed DataType template parameter from NdArrayViewer; added Id/Idx aliases and unified idx-based indexing; updated call sites.
Diagnostic model/view updates
src/diagnostic/diagnostic_model_view.hpp, src/diagnostic/diagnostic_manager.hpp, src/diagnostic/diagnostic_writer.hpp
Replaced sumTensor_ with tmpField/tmpVec/tmpTensor storage, added tmp accessors and localLevelBoxes, adjusted visitHierarchy forwarding; removed cppdict include.
Utilities & core tweaks
src/core/utilities/algorithm.hpp, src/core/utilities/types.hpp, src/core/utilities/box/box.hpp, src/core/data/tensorfield/tensorfield.hpp, src/core/data/grid/gridlayout.hpp, src/amr/resources_manager/amr_utils.hpp, src/amr/physical_models/hybrid_model.hpp
Added conversion helpers (convert_to_primal/fortran), from_string/get_env_as/for_N_all, boxes_iterator/grow, minor qualifier/order fixes, corrected forwarding in variadic template forwarding, and removed redundant typename qualifiers.
Build/test & examples
src/phare/CMakeLists.txt, src/phare/phare_init.py, src/phare/phare_init_small.py, tests/simulator/CMakeLists.txt, tests/simulator/__init__.py, tests/simulator/refinement/test_2d_10_core.py, tests/simulator/test_vtk_diagnostics.py
Removed two example init scripts and configure_file step; added/activated VTK diagnostics tests and timestamp test; added Box import and reorganized test initializations; new test test_vtk_diagnostics.py.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant DiagnosticsManagerResolver
    participant PhareDict
    participant DiagnosticsManager
    participant H5Writer_h5
    participant H5Writer_vtkh5

    Caller->>DiagnosticsManagerResolver: make_unique(hier, model, dict)
    DiagnosticsManagerResolver->>PhareDict: read "format" (default "phareh5")
    PhareDict-->>DiagnosticsManagerResolver: "phareh5" / "pharevtkhdf" / other

    alt "phareh5"
        DiagnosticsManagerResolver->>H5Writer_h5: construct H5Writer<ModelView>
        H5Writer_h5-->>DiagnosticsManagerResolver: h5_writer
        DiagnosticsManagerResolver->>DiagnosticsManager: make with h5_writer
    else "pharevtkhdf"
        DiagnosticsManagerResolver->>H5Writer_vtkh5: construct vtkh5::H5Writer<ModelView>
        H5Writer_vtkh5-->>DiagnosticsManagerResolver: vtkh5_writer
        DiagnosticsManagerResolver->>DiagnosticsManager: make with vtkh5_writer
    else unknown
        DiagnosticsManagerResolver-->>Caller: throw runtime_error
    end
Loading
sequenceDiagram
    participant VTKh5Writer
    participant H5TypeWriter
    participant VTKFileWriter
    participant ElectromagWriter
    participant HighFiveFile
    VTKh5Writer->>H5TypeWriter: getOrCreateH5File(diagnostic)
    H5TypeWriter->>HighFiveFile: open/create per-quantity file
    VTKh5Writer->>ElectromagWriter: write(diagnostic)
    ElectromagWriter->>VTKFileWriter: initFileLevel / initFieldFileLevel
    ElectromagWriter->>VTKFileWriter: visitHierarchy(write_quantity)
    VTKFileWriter->>HighFiveFile: write datasets (per-level / per-box / data)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • src/diagnostic/detail/vtkh5_type_writer.hpp and src/diagnostic/detail/vtkh5_writer.hpp — new complex writer infrastructure, HDF5 layout and MPI semantics.
  • src/core/data/grid/gridlayout.hpp & gridlayoutimplyee.hpp — API renames (AMRBoxFor/AMRGhostBoxFor) and new index helpers; verify all call sites.
  • src/core/data/ndarray/ndarray_vector.hpp — signature change to NdArrayViewer; audit instantiations.
  • src/diagnostic/diagnostic_model_view.hpp — storage and visitHierarchy forwarding changes affecting algorithms and multithreading.
  • Tests: tests/simulator/test_vtk_diagnostics.py — ensure CI environment has required HDF5/HighFive and MPI.

Possibly related PRs

Suggested reviewers

  • UCaromel
  • nicolasaunai

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.63% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Vtk hdf' is very vague and does not clearly convey the main change; it uses non-descriptive abbreviations without context. Consider revising to a more descriptive title such as 'Add VTK-HDF5 diagnostic output support' to clearly communicate the primary change.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description is related to the changeset, explaining the addition of VTKHDF diagnostic format with data conversion to primal and Fortran ordering, though it is brief.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@github-advanced-security github-advanced-security bot left a comment

Choose a reason for hiding this comment

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

CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

@PhilipDeegan PhilipDeegan force-pushed the vtk branch 2 times, most recently from 39d7491 to 0c9462d Compare October 24, 2025 14:50
@PhilipDeegan PhilipDeegan changed the title WIP Vtk hdf Vtk hdf Oct 31, 2025
@PhilipDeegan PhilipDeegan marked this pull request as ready for review October 31, 2025 12:47
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

🧹 Nitpick comments (3)
src/python3/patch_data.hpp (1)

35-36: Consider passing string parameters by const reference.

The patchID and origin parameters in setPatchData, setPatchDataFromGrid, and setPatchDataFromField are passed by value, creating unnecessary copies. Since these functions don't require ownership, passing them as std::string const& would be more efficient.

Apply this pattern to avoid copies:

-void setPatchData(PatchData& data, std::string const patchID, std::string const origin,
+void setPatchData(PatchData& data, std::string const& patchID, std::string const& origin,
                   Container lower, Container upper)
-void setPatchDataFromGrid(PatchData& pdata, GridLayout& grid, std::string patchID)
+void setPatchDataFromGrid(PatchData& pdata, GridLayout& grid, std::string const& patchID)
-void setPatchDataFromField(PatchData& pdata, Field const& field, GridLayout& grid,
-                           std::string patchID)
+void setPatchDataFromField(PatchData& pdata, Field const& field, GridLayout& grid,
+                           std::string const& patchID)

Also applies to: 46-46, 54-55

src/core/data/ndarray/ndarray_vector.hpp (1)

38-38: Simplify unused parameter.

The inline comment /*nCells*/ for the unused parameter is non-standard. Modern C++ convention is to simply omit the parameter name.

Apply this diff:

-    static inline std::uint32_t idx(auto const /*nCells*/, Idx i) { return i; }
+    static inline std::uint32_t idx(auto const, Idx i) { return i; }
src/amr/resources_manager/amr_utils.hpp (1)

247-247: Preserve perfect forwarding into resman.setOnPatch

Now that visitHierarchy forwards args, we should propagate the perfect forwarding down into setOnPatch; otherwise rvalues (e.g., move-only helpers) devolve to lvalues when named inside visitLevel, preventing those call-sites from compiling or forcing extra copies. Applying std::forward here keeps the chain intact.

-            auto guard        = resman.setOnPatch(*patch, args...);
+            auto guard        = resman.setOnPatch(*patch, std::forward<Args>(args)...);
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 238185f and 3e87615.

📒 Files selected for processing (34)
  • pyphare/pyphare/pharein/__init__.py (1 hunks)
  • pyphare/pyphare/pharein/simulation.py (1 hunks)
  • pyphare/pyphare/pharesee/__init__.py (1 hunks)
  • pyphare/pyphare/pharesee/tovtk.py (1 hunks)
  • src/amr/physical_models/hybrid_model.hpp (1 hunks)
  • src/amr/resources_manager/amr_utils.hpp (1 hunks)
  • src/core/data/grid/gridlayout.hpp (3 hunks)
  • src/core/data/grid/gridlayoutimplyee.hpp (1 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (5 hunks)
  • src/core/data/tensorfield/tensorfield.hpp (1 hunks)
  • src/core/utilities/algorithm.hpp (2 hunks)
  • src/core/utilities/box/box.hpp (2 hunks)
  • src/core/utilities/mpi_utils.hpp (1 hunks)
  • src/core/utilities/types.hpp (3 hunks)
  • src/diagnostic/detail/h5writer.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/electromag.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/fluid.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/info.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/meta.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/particle.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_type_writer.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_writer.hpp (1 hunks)
  • src/diagnostic/diagnostic_manager.hpp (1 hunks)
  • src/diagnostic/diagnostic_model_view.hpp (6 hunks)
  • src/diagnostic/diagnostics.hpp (2 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (2 hunks)
  • src/phare/CMakeLists.txt (0 hunks)
  • src/phare/phare_init.py (0 hunks)
  • src/phare/phare_init_small.py (0 hunks)
  • src/python3/patch_data.hpp (1 hunks)
  • tests/simulator/CMakeLists.txt (1 hunks)
  • tests/simulator/__init__.py (1 hunks)
  • tests/simulator/refinement/test_2d_10_core.py (1 hunks)
  • tests/simulator/test_vtk_diagnostics.py (1 hunks)
💤 Files with no reviewable changes (3)
  • src/phare/CMakeLists.txt
  • src/phare/phare_init_small.py
  • src/phare/phare_init.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.hpp

⚙️ CodeRabbit configuration file

Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Files:

  • src/diagnostic/diagnostics.hpp
  • src/python3/patch_data.hpp
  • src/amr/physical_models/hybrid_model.hpp
  • src/amr/resources_manager/amr_utils.hpp
  • src/diagnostic/detail/vtk_types/particle.hpp
  • src/diagnostic/detail/vtk_types/fluid.hpp
  • src/core/utilities/box/box.hpp
  • src/core/utilities/mpi_utils.hpp
  • src/diagnostic/detail/h5writer.hpp
  • src/diagnostic/detail/vtk_types/info.hpp
  • src/core/data/grid/gridlayout.hpp
  • src/diagnostic/diagnostic_manager.hpp
  • src/core/data/grid/gridlayoutimplyee.hpp
  • src/core/utilities/types.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
  • src/hdf5/detail/h5/h5_file.hpp
  • src/diagnostic/detail/vtk_types/meta.hpp
  • src/core/utilities/algorithm.hpp
  • src/diagnostic/diagnostic_model_view.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/core/data/tensorfield/tensorfield.hpp
  • src/diagnostic/detail/vtk_types/electromag.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
🧠 Learnings (7)
📓 Common learnings
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-10-09T08:32:15.667Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-07-26T22:04:34.160Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-09-05T17:02:58.784Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
📚 Learning: 2025-02-07T14:35:14.630Z
Learnt from: nicolasaunai
Repo: PHAREHUB/PHARE PR: 591
File: res/cmake/options.cmake:73-75
Timestamp: 2025-02-07T14:35:14.630Z
Learning: In CMake configuration for PHARE, `lowResourceTests` and `highResourceTests` options must be mutually exclusive and cannot be enabled simultaneously.

Applied to files:

  • tests/simulator/CMakeLists.txt
📚 Learning: 2025-07-09T17:18:05.771Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/amr/CMakeLists.txt:103-105
Timestamp: 2025-07-09T17:18:05.771Z
Learning: In the PHARE project, `HighFive` is a CMake option defined in `res/cmake/options.cmake` as `option(HighFive "Build with highfive usage" ON)`, not a target that would be created by find_package(). The condition `if (HighFive)` correctly checks this option.

Applied to files:

  • src/diagnostic/detail/h5writer.hpp
📚 Learning: 2024-07-26T22:04:34.160Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 0
File: :0-0
Timestamp: 2024-07-26T22:04:34.160Z
Learning: The variable `c_ordering` in `ConcreteLoadBalancerHybridStrategyNPPC<PHARE_T>::compute` is used to create an array view `lb_view` for handling load balancing data.

Applied to files:

  • src/core/utilities/algorithm.hpp
📚 Learning: 2025-09-17T13:35:11.533Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.

Applied to files:

  • src/core/utilities/algorithm.hpp
📚 Learning: 2024-09-09T13:57:02.285Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py:566-568
Timestamp: 2024-09-09T13:57:02.285Z
Learning: Avoid commenting on draft PRs for PhilipDeegan unless explicitly requested.

Applied to files:

  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
📚 Learning: 2025-09-17T13:50:16.038Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/tensorfield/tensor_field_data_factory.hpp:112-112
Timestamp: 2025-09-17T13:50:16.038Z
Learning: PhilipDeegan indicated that getSizeOfMemory returning a placeholder value of 1 in TensorFieldDataFactory is acceptable for their use case, suggesting it may not be critical for PHARE's memory management needs.

Applied to files:

  • src/core/data/tensorfield/tensorfield.hpp
🧬 Code graph analysis (20)
src/diagnostic/diagnostics.hpp (3)
src/diagnostic/diagnostic_manager.hpp (5)
  • dict (83-83)
  • dict (86-86)
  • dict (86-86)
  • make_unique (74-80)
  • make_unique (74-75)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • make_unique (67-74)
  • make_unique (67-67)
src/diagnostic/detail/h5writer.hpp (2)
  • make_unique (61-68)
  • make_unique (61-61)
src/amr/resources_manager/amr_utils.hpp (1)
src/core/data/field/field.hpp (4)
  • args (75-81)
  • args (75-75)
  • args (83-86)
  • args (83-83)
src/diagnostic/detail/vtk_types/particle.hpp (4)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
  • write (30-55)
  • write (30-30)
src/diagnostic/detail/vtkh5_type_writer.hpp (4)
  • diagnostic (87-92)
  • diagnostic (87-87)
  • ilvl (385-414)
  • ilvl (385-385)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
src/diagnostic/detail/h5writer.hpp (4)
  • diagnostic (94-98)
  • diagnostic (94-94)
  • iLevel (210-214)
  • iLevel (210-210)
src/diagnostic/detail/vtk_types/fluid.hpp (3)
src/diagnostic/detail/vtkh5_type_writer.hpp (6)
  • diagnostic (87-92)
  • diagnostic (87-87)
  • ilvl (385-414)
  • ilvl (385-385)
  • boxes (57-71)
  • boxes (57-57)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
  • write (30-55)
  • write (30-30)
src/core/utilities/box/box.hpp (1)
src/core/utilities/types.hpp (2)
  • product (265-268)
  • product (265-265)
tests/simulator/refinement/test_2d_10_core.py (2)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_lib (6-9)
tests/simulator/test_advance.py (1)
  • AdvanceTestBase (33-788)
src/diagnostic/detail/vtk_types/info.hpp (7)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
  • write (30-55)
  • write (30-30)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
  • write (38-71)
  • write (38-38)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtk_types/meta.hpp (2)
  • write (29-31)
  • write (29-29)
src/diagnostic/detail/vtk_types/particle.hpp (2)
  • write (31-54)
  • write (31-31)
src/diagnostic/detail/vtkh5_type_writer.hpp (2)
  • diagnostic (87-92)
  • diagnostic (87-87)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
src/diagnostic/detail/h5writer.hpp (2)
  • diagnostic (94-98)
  • diagnostic (94-94)
src/core/data/grid/gridlayout.hpp (2)
src/core/utilities/types.hpp (5)
  • auto (151-156)
  • auto (491-494)
  • auto (497-500)
  • for_N_make_array (484-487)
  • for_N_make_array (484-484)
src/core/utilities/box/box.hpp (6)
  • grow (88-93)
  • grow (88-88)
  • grow (323-328)
  • grow (323-323)
  • i (96-96)
  • i (96-96)
tests/simulator/test_vtk_diagnostics.py (7)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_lib (6-9)
pyphare/pyphare/simulator/simulator.py (2)
  • startMPI (40-44)
  • reset (254-265)
tests/simulator/__init__.py (4)
  • SimulatorTest (201-267)
  • tearDown (204-205)
  • unique_diag_dir_for_test_case (250-254)
  • run (246-248)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-61)
pyphare/pyphare/pharein/simulation.py (2)
  • simulation_domain (978-979)
  • Simulation (745-1080)
pyphare/pyphare/pharein/maxwellian_fluid_model.py (1)
  • MaxwellianFluidModel (8-303)
pyphare/pyphare/pharesee/tovtk.py (1)
  • convert (269-416)
tests/simulator/__init__.py (1)
pyphare/pyphare/core/box.py (1)
  • Box (5-69)
src/core/data/grid/gridlayoutimplyee.hpp (1)
tests/core/data/gridlayout/test_linear_combinaisons_yee.py (1)
  • dualToPrimal (27-35)
src/core/utilities/types.hpp (1)
src/core/data/tensorfield/tensorfield.hpp (2)
  • for_N (83-87)
  • for_N (88-92)
src/core/data/ndarray/ndarray_vector.hpp (1)
src/core/utilities/types.hpp (2)
  • product (265-268)
  • product (265-265)
src/diagnostic/detail/vtk_types/meta.hpp (5)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
  • write (30-55)
  • write (30-30)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
  • write (38-71)
  • write (38-38)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtk_types/info.hpp (2)
  • write (31-33)
  • write (31-31)
src/diagnostic/detail/vtkh5_type_writer.hpp (2)
  • diagnostic (87-92)
  • diagnostic (87-87)
src/diagnostic/detail/types/meta.hpp (1)
  • PHARE (7-143)
pyphare/pyphare/pharesee/tovtk.py (1)
src/diagnostic/detail/vtkh5_type_writer.hpp (8)
  • shape (114-121)
  • shape (114-114)
  • shape (123-131)
  • shape (123-123)
  • ilvl (385-414)
  • ilvl (385-385)
  • resize (417-423)
  • resize (417-417)
src/core/utilities/algorithm.hpp (2)
src/core/utilities/types.hpp (2)
  • all (355-358)
  • all (355-355)
src/core/data/ndarray/ndarray_vector.hpp (4)
  • make_array_view (214-217)
  • make_array_view (214-214)
  • make_array_view (220-223)
  • make_array_view (220-220)
src/diagnostic/diagnostic_model_view.hpp (5)
src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp (12)
  • patch (137-145)
  • patch (137-137)
  • ions (410-420)
  • ions (410-411)
  • ions (424-450)
  • ions (424-425)
  • ions (452-486)
  • ions (452-453)
  • ions (498-537)
  • ions (498-499)
  • ions (545-551)
  • ions (545-546)
src/amr/resources_manager/amr_utils.hpp (2)
  • visitHierarchy (257-266)
  • visitHierarchy (257-258)
src/core/data/electrons/electrons.hpp (16)
  • layout (107-133)
  • layout (107-107)
  • layout (285-285)
  • layout (285-285)
  • layout (286-286)
  • layout (286-286)
  • layout (309-319)
  • layout (309-309)
  • forward_as_tuple (47-50)
  • forward_as_tuple (52-55)
  • forward_as_tuple (181-184)
  • forward_as_tuple (186-186)
  • forward_as_tuple (254-257)
  • forward_as_tuple (259-262)
  • forward_as_tuple (330-333)
  • forward_as_tuple (335-338)
src/core/data/ions/ion_population/ion_population.hpp (1)
  • forward_as_tuple (109-113)
src/core/data/ions/ions.hpp (1)
  • forward_as_tuple (225-229)
src/diagnostic/detail/vtkh5_writer.hpp (4)
src/diagnostic/diagnostic_model_view.hpp (1)
  • dimension (30-61)
src/diagnostic/detail/h5writer.hpp (15)
  • H5Writer (51-56)
  • H5Writer (58-58)
  • H5Writer (194-194)
  • H5Writer (195-195)
  • make_unique (61-68)
  • make_unique (61-61)
  • level (72-73)
  • timestamp (101-104)
  • timestamp (101-101)
  • diagnostic (94-98)
  • diagnostic (94-94)
  • modelView_ (160-160)
  • timestamp_ (161-161)
  • dump (224-250)
  • dump (224-225)
src/diagnostic/diagnostics.hpp (2)
  • make_unique (50-65)
  • make_unique (50-51)
src/diagnostic/detail/vtkh5_type_writer.hpp (6)
  • level (309-331)
  • level (309-309)
  • level (333-337)
  • level (333-333)
  • diagnostic (87-92)
  • diagnostic (87-87)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
  • write (38-71)
  • write (38-38)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtkh5_type_writer.hpp (6)
  • diagnostic (87-92)
  • diagnostic (87-87)
  • ilvl (385-414)
  • ilvl (385-385)
  • boxes (57-71)
  • boxes (57-57)
src/diagnostic/detail/vtkh5_type_writer.hpp (7)
src/core/utilities/types.hpp (5)
  • get_env_as (249-249)
  • sum_from (277-285)
  • sum_from (277-277)
  • sum (271-274)
  • sum (271-271)
src/hdf5/detail/h5/h5_file.hpp (9)
  • data (66-66)
  • s (248-248)
  • s (248-248)
  • s (249-253)
  • s (249-249)
  • path (267-273)
  • path (267-267)
  • path (275-280)
  • path (275-275)
src/core/utilities/box/box.hpp (11)
  • box (50-50)
  • i (96-96)
  • i (96-96)
  • grow (88-93)
  • grow (88-88)
  • grow (323-328)
  • grow (323-323)
  • s (209-234)
  • s (209-209)
  • s (235-240)
  • s (235-235)
src/core/data/tensorfield/tensorfield.hpp (6)
  • i (178-178)
  • i (178-178)
  • i (179-179)
  • i (179-179)
  • tensor_field_dim_from_rank (18-24)
  • tensor_field_dim_from_rank (18-18)
src/core/utilities/mpi_utils.hpp (4)
  • rank (25-25)
  • collect (17-17)
  • collect (214-229)
  • collect (214-214)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
src/core/utilities/algorithm.hpp (2)
  • convert_to_fortran_primal (137-140)
  • convert_to_fortran_primal (137-137)
🪛 GitHub Check: CodeQL
pyphare/pyphare/pharesee/tovtk.py

[notice] 163-163: Unused local variable
Variable cellData_g is not used.


[notice] 165-165: Unused local variable
Variable fieldData_g is not used.


[notice] 166-166: Unused local variable
Variable cellDataOffset_g is not used.


[notice] 167-167: Explicit returns mixed with implicit (fall through) returns
Mixing implicit and explicit returns may indicate an error, as implicit returns always return None.


[notice] 168-168: Unused local variable
Variable FieldDataOffset_g is not used.


[failure] 361-361: Wrong number of arguments in a call
Call to function primalScalarToFlatPrimal with too many arguments; should be no more than 5.


[failure] 387-387: Wrong number of arguments in a call
Call to function BtoFlatPrimal with too few arguments; should be no fewer than 6.
Call to function EtoFlatPrimal with too few arguments; should be no fewer than 6.
Call to function primalVectorToFlatPrimal with too few arguments; should be no fewer than 6.

src/core/utilities/algorithm.hpp

[notice] 105-105: Unused local variable
Variable c_ordering is not used.

src/diagnostic/detail/vtkh5_type_writer.hpp

[notice] 41-41: Commented-out code
This comment appears to contain commented-out code.

🪛 Ruff (0.14.2)
tests/simulator/test_vtk_diagnostics.py

1-1: Shebang is present but file is not executable

(EXE001)


27-27: Unused function argument: xyz

(ARG001)


34-34: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


41-41: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


44-44: Unused function argument: xyz

(ARG001)


47-47: Unused function argument: xyz

(ARG001)


54-54: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


61-61: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


64-64: Unused function argument: xyz

(ARG001)


67-67: Unused function argument: xyz

(ARG001)


70-70: Unused function argument: xyz

(ARG001)


121-121: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)

pyphare/pyphare/pharesee/tovtk.py

1-1: Shebang is present but file is not executable

(EXE001)


17-19: Avoid specifying long messages outside the exception class

(TRY003)


204-204: Avoid specifying long messages outside the exception class

(TRY003)


232-232: Avoid specifying long messages outside the exception class

(TRY003)


263-263: Consider [*root_spacing, 0, 0] instead of concatenation

Replace with [*root_spacing, 0, 0]

(RUF005)


265-265: Consider [*root_spacing, 0] instead of concatenation

Replace with [*root_spacing, 0]

(RUF005)


321-321: Local variable cellData_g is assigned to but never used

Remove assignment to unused variable cellData_g

(F841)


323-323: Local variable fieldData_g is assigned to but never used

Remove assignment to unused variable fieldData_g

(F841)


324-324: Local variable cellDataOffset_g is assigned to but never used

Remove assignment to unused variable cellDataOffset_g

(F841)


326-326: Local variable FieldDataOffset_g is assigned to but never used

Remove assignment to unused variable FieldDataOffset_g

(F841)


384-384: Prefer next(iter(patch.keys())) over single element slice

Replace with next(iter(patch.keys()))

(RUF015)

🔇 Additional comments (8)
src/python3/patch_data.hpp (1)

26-30: Critical fix: Correct variadic template forwarding.

The change from std::forward<Args...>(args...) to std::forward<Args>(args)... fixes invalid syntax. The ellipsis must appear outside the std::forward call to properly expand each argument in the parameter pack individually, ensuring correct perfect forwarding semantics.

src/hdf5/detail/h5/h5_file.hpp (1)

98-99: LGTM!

The defensive existence check prevents duplicate dataset creation and returns the existing dataset if found.

src/core/utilities/types.hpp (2)

248-254: Verify error handling for invalid environment variable values.

This function depends on from_string<T>, which silently returns a default-initialized value on conversion failure. If an environment variable exists but contains an invalid value for type T, this function will return an unexpected result without any indication of failure.

Ensure that upstream callers can handle or validate the returned values, especially for critical configuration parameters.


483-487: LGTM!

This is a clean convenience wrapper around for_N with the make_array mode. The implementation properly forwards the function parameter and maintains constexpr correctness.

src/core/utilities/mpi_utils.hpp (1)

5-7: LGTM!

The added includes are necessary and properly support the file's dependencies:

  • phare_mpi.hpp for MPI definitions used throughout
  • span.hpp for SpanSet template (lines 169, 174, 204)
  • types.hpp for type traits like is_std_vector_v, is_std_array_v, and displacementFrom (lines 77, 154, 221)
src/core/data/ndarray/ndarray_vector.hpp (3)

55-70: LGTM!

The unified index computation via idx(...) followed by bounds-checked access through data[i] provides a clean, consistent access pattern across all dimensionalities.


101-101: LGTM! Consistent template parameter updates.

All usage sites have been correctly updated to use NdArrayViewer without the DataType template parameter, maintaining consistency with the simplified template signature.

Also applies to: 138-138, 271-271, 283-283


22-23: Reconsider index type constraint—no evidence of practical limitation.

The std::uint16_t index type appears to be an intentional design constraint for this physics simulation codebase. Shape values are stored as std::uint32_t arrays (lines 124, 209, 307), but indices are constrained to uint16_t—a deliberate trade-off likely for memory efficiency or simulation requirements. No codebase search found array dimensions exceeding 65K in any single dimension, and type promotion in index calculations prevents overflow. This design aligns with typical physics grid constraints for plasma simulations.

@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 7, 2025
@PhilipDeegan PhilipDeegan force-pushed the vtk branch 4 times, most recently from 9371cab to da3b967 Compare November 7, 2025 17:16
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (7)
src/hdf5/detail/h5/h5_file.hpp (3)

105-114: Missing parent group creation will cause runtime failure.

Unlike create_data_set (line 100), this function doesn't call createGroupsToDataSet(path) before creating the dataset. If parent groups don't exist, h5file_.createDataSet will fail at runtime.

Apply this diff to add parent group creation:

 template<typename Type>
 auto create_chunked_data_set(auto const& path, auto const chunk, auto const& dataspace)
 {
     if (exist(path))
         return h5file_.getDataSet(path);
 
+    createGroupsToDataSet(path);
     HighFive::DataSetCreateProps props;
     props.add(HighFive::Chunking{chunk});
     return h5file_.createDataSet(path, dataspace, HighFive::create_datatype<Type>(), props);
 }

249-253: Replace assertion with exception for production safety.

The assert(exist(s)) is compiled out in release builds (when NDEBUG is defined), leading to undefined behavior if a non-existent dataset is accessed. This could cause crashes or silent data corruption in production.

Apply this diff:

 auto getDataSet(std::string const& s)
 {
-    assert(exist(s));
+    if (!exist(s))
+        throw std::runtime_error("Dataset does not exist: " + s);
     return h5file_.getDataSet(s);
 }

255-258: Fix incorrect special member function signatures.

Two critical issues:

  1. Line 256: Move constructor declared with const&& defeats move semantics since you cannot transfer ownership from a const object.
  2. Line 257: Copy assignment operator missing const qualifier on parameter, which is non-standard and could allow accidental modification of the source object.

Apply this diff to correct both signatures:

 HighFiveFile(HighFiveFile const&)       = delete;
-HighFiveFile(HighFiveFile const&&)      = delete;
-HighFiveFile& operator=(HighFiveFile&)  = delete;
+HighFiveFile(HighFiveFile&&)            = delete;
+HighFiveFile& operator=(HighFiveFile const&) = delete;
 HighFiveFile& operator=(HighFiveFile&&) = delete;
src/core/utilities/types.hpp (1)

224-231: Missing include and error handling already flagged.

The issues with missing <sstream> include and silent failure on conversion errors have already been identified in a previous review.

pyphare/pyphare/pharesee/tovtk.py (1)

80-91: Correct 3D By primalization averaging.

The 3D branch reuses ph_bz and averages along the Y axis, so By mixes the wrong component and skips the X-direction dual pair. The exported magnetic field is therefore incorrect.

Replace the averaging with this fix:

-        by[:, :, :] = 0.5 * (
-            0.5
-            * (
-                ph_by[domain, domainP1, domain][:, 1:, :]
-                + ph_by[domain, domainP1, domain][:, :-1, :]
-            )
-            + 0.5
-            * (
-                ph_bz[domain, domain, domainP1][:, :, 1:]
-                + ph_bz[domain, domain, domainP1][:, :, :-1]
-            )
-        )
+        by[:, :, :] = 0.5 * (
+            0.5
+            * (
+                ph_by[domainP1, domain, domain][1:, :, :]
+                + ph_by[domainP1, domain, domain][:-1, :, :]
+            )
+            + 0.5
+            * (
+                ph_by[domain, domain, domainP1][:, :, 1:]
+                + ph_by[domain, domain, domainP1][:, :, :-1]
+            )
+        )
src/diagnostic/detail/vtk_types/particle.hpp (1)

37-54: Particle VTK writer is still a no-op

write_quantity never writes anything, so visitHierarchy produces empty particle datasets and every particle diagnostic is silently lost. This is the same blocker that was raised earlier—please port the actual write logic (e.g., iterate populations/layouts and feed the initializer just like the existing H5 ParticlesDiagnosticWriter does) before landing this format.

src/diagnostic/detail/vtkh5_writer.hpp (1)

177-183: Restore post-write flag downgrade to prevent data loss.

Line 179 sets file_flags[diagnostic->type + diagnostic->quantity] = this->flags, which in overwrite mode includes HiFile::Truncate. This flag persists across subsequent dump() calls, causing each dump to reopen the file in truncate mode and erase earlier time steps.

Apply this diff to reset flags after writing:

     for (auto* diagnostic : diagnostics)
         typeWriters_.at(diagnostic->type)->write(*diagnostic);
+
+    for (auto* diagnostic : diagnostics)
+        file_flags[diagnostic->type + diagnostic->quantity] = READ_WRITE;
🧹 Nitpick comments (6)
src/amr/resources_manager/amr_utils.hpp (1)

229-239: Consider forwarding args for consistency with visitHierarchy.

While visitHierarchy now properly forwards the variadic arguments (line 251), visitLevel receives forwarding references but passes them to setOnPatch without forwarding (line 234). For consistency and to preserve move semantics, consider applying the same forwarding pattern.

Apply this diff to forward the arguments:

 template<typename GridLayout, typename ResMan, typename Action, typename... Args>
 void visitLevel(SAMRAI_Types::level_t& level, ResMan& resman, Action&& action, Args&&... args)
 {
     for (auto& patch : level)
     {
-        auto guard        = resman.setOnPatch(*patch, args...);
+        auto guard        = resman.setOnPatch(*patch, std::forward<Args>(args)...);
         GridLayout layout = layoutFromPatch<GridLayout>(*patch);
         action(layout, to_string(patch->getGlobalId()),
                static_cast<std::size_t>(level.getLevelNumber()));
     }
 }
tests/simulator/refinement/test_2d_10_core.py (1)

17-24: Consider refactoring for test isolation.

Module-level initialization of cpp, test, L0_diags, and L0L1_diags creates global mutable state that persists across imports. While this works for single-use test scripts, it could impact test isolation if this module is later integrated into a larger test suite.

Consider lazy initialization or moving these to main() to improve test isolation and initialization order control.

Example refactor moving initialization to main():

-cpp = cpp_lib()
-test = AdvanceTestBase(rethrow=True)  # change to False for debugging images
-L0_diags = "phare_outputs/test_x_homo_0"
-L0L1_diags = "phare_outputs/test_x_homo_1"
-
 ph.NO_GUI()
 
+# Module-level variables to be initialized in main()
+cpp = None
+test = None
+L0_diags = "phare_outputs/test_x_homo_0"
+L0L1_diags = "phare_outputs/test_x_homo_1"
 
 def config(diag_outputs, model_init={}, refinement_boxes=None):

Then initialize in main():

 def main():
+    global cpp, test
     import random
 
     startMPI()
+    cpp = cpp_lib()
+    test = AdvanceTestBase(rethrow=True)
     rando = random.randint(0, int(1e10))
tests/simulator/test_vtk_diagnostics.py (2)

34-34: Consider replacing lambda assignments with def statements.

PEP 8 recommends using def statements instead of assigning lambdas to variables for better traceability and debugging.

Example refactor for one occurrence:

-        _ = lambda i: 0.1 * np.sin(2 * np.pi * xyz[i] / L[i])
+        def component_value(i):
+            return 0.1 * np.sin(2 * np.pi * xyz[i] / L[i])

Also applies to: 41-41, 54-54, 61-61


169-169: Clarify the status of EM_B conversion.

The commented-out line suggests tovtk conversion fails for EM_B.h5.

Should this be tracked as a TODO/FIXME, or is this a known limitation that's acceptable for this PR? If it's a bug, consider opening an issue to track it.

Do you want me to help create an issue for tracking the EM_B conversion problem?

src/diagnostic/detail/vtkh5_writer.hpp (1)

130-130: Hard-coded maxLevel limit.

The hard-coded maxLevel = 10 may be insufficient for simulations requiring deeper AMR hierarchies.

Consider making this configurable via the PHAREDict in make_unique, e.g.:

auto maxLevel = cppdict::get_value(dict, "max_level", std::size_t{10});
src/diagnostic/detail/vtkh5_type_writer.hpp (1)

361-361: Document the X_TIMES multiplier logic.

The dimension-dependent multiplier X_TIMES (4 for 1D, 2 for 2D, 1 for 3D) implements an important conversion factor but lacks explanation.

Add a comment explaining why the multiplier is needed:

// VTK stores data per cube face: 2D data requires 2 faces, 1D requires 4 faces, 3D is 1:1
constexpr static auto X_TIMES = std::array{4, 2, /* 3d noop */ 1}[dimension - 1];
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3e87615 and 4078b83.

📒 Files selected for processing (33)
  • pyphare/pyphare/pharein/__init__.py (1 hunks)
  • pyphare/pyphare/pharein/simulation.py (1 hunks)
  • pyphare/pyphare/pharesee/__init__.py (1 hunks)
  • pyphare/pyphare/pharesee/tovtk.py (1 hunks)
  • src/amr/physical_models/hybrid_model.hpp (1 hunks)
  • src/amr/resources_manager/amr_utils.hpp (1 hunks)
  • src/core/data/grid/gridlayout.hpp (3 hunks)
  • src/core/data/grid/gridlayoutdefs.hpp (1 hunks)
  • src/core/data/grid/gridlayoutimplyee.hpp (27 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (5 hunks)
  • src/core/data/tensorfield/tensorfield.hpp (1 hunks)
  • src/core/utilities/algorithm.hpp (2 hunks)
  • src/core/utilities/box/box.hpp (2 hunks)
  • src/core/utilities/types.hpp (3 hunks)
  • src/diagnostic/detail/h5writer.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/electromag.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/fluid.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/info.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/meta.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/particle.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_type_writer.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_writer.hpp (1 hunks)
  • src/diagnostic/diagnostic_manager.hpp (1 hunks)
  • src/diagnostic/diagnostic_model_view.hpp (7 hunks)
  • src/diagnostic/diagnostics.hpp (2 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (2 hunks)
  • src/phare/CMakeLists.txt (0 hunks)
  • src/phare/phare_init.py (0 hunks)
  • src/phare/phare_init_small.py (0 hunks)
  • tests/simulator/CMakeLists.txt (2 hunks)
  • tests/simulator/__init__.py (1 hunks)
  • tests/simulator/refinement/test_2d_10_core.py (1 hunks)
  • tests/simulator/test_vtk_diagnostics.py (1 hunks)
💤 Files with no reviewable changes (3)
  • src/phare/CMakeLists.txt
  • src/phare/phare_init_small.py
  • src/phare/phare_init.py
🚧 Files skipped from review as they are similar to previous changes (12)
  • src/diagnostic/diagnostic_manager.hpp
  • pyphare/pyphare/pharein/simulation.py
  • tests/simulator/init.py
  • pyphare/pyphare/pharein/init.py
  • src/core/data/grid/gridlayout.hpp
  • pyphare/pyphare/pharesee/init.py
  • src/diagnostic/detail/vtk_types/meta.hpp
  • src/diagnostic/detail/h5writer.hpp
  • src/amr/physical_models/hybrid_model.hpp
  • src/core/utilities/algorithm.hpp
  • tests/simulator/CMakeLists.txt
  • src/core/utilities/box/box.hpp
🧰 Additional context used
📓 Path-based instructions (1)
**/*.hpp

⚙️ CodeRabbit configuration file

Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Files:

  • src/core/data/grid/gridlayoutdefs.hpp
  • src/core/data/tensorfield/tensorfield.hpp
  • src/amr/resources_manager/amr_utils.hpp
  • src/diagnostic/detail/vtk_types/electromag.hpp
  • src/diagnostic/detail/vtk_types/particle.hpp
  • src/diagnostic/detail/vtk_types/fluid.hpp
  • src/diagnostic/diagnostics.hpp
  • src/core/utilities/types.hpp
  • src/hdf5/detail/h5/h5_file.hpp
  • src/core/data/grid/gridlayoutimplyee.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/detail/vtk_types/info.hpp
  • src/diagnostic/diagnostic_model_view.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
🧠 Learnings (2)
📓 Common learnings
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-10-09T08:32:15.667Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-07-26T22:04:34.160Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-09-05T17:02:58.784Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
📚 Learning: 2024-09-09T13:57:02.285Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py:566-568
Timestamp: 2024-09-09T13:57:02.285Z
Learning: Avoid commenting on draft PRs for PhilipDeegan unless explicitly requested.

Applied to files:

  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
🧬 Code graph analysis (13)
src/amr/resources_manager/amr_utils.hpp (1)
src/core/data/field/field.hpp (4)
  • args (75-81)
  • args (75-75)
  • args (83-86)
  • args (83-83)
src/diagnostic/detail/vtk_types/electromag.hpp (3)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
  • write (38-71)
  • write (38-38)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtkh5_type_writer.hpp (8)
  • diagnostic (87-92)
  • diagnostic (87-87)
  • lvl (267-272)
  • lvl (267-267)
  • ilvl (388-417)
  • ilvl (388-388)
  • boxes (57-71)
  • boxes (57-57)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
tests/simulator/test_vtk_diagnostics.py (5)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_lib (6-9)
pyphare/pyphare/simulator/simulator.py (2)
  • startMPI (41-45)
  • reset (258-269)
tests/simulator/__init__.py (3)
  • SimulatorTest (201-267)
  • tearDown (204-205)
  • unique_diag_dir_for_test_case (250-254)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-62)
pyphare/pyphare/pharesee/tovtk.py (1)
  • convert (269-416)
src/diagnostic/detail/vtk_types/particle.hpp (3)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
  • write (30-55)
  • write (30-30)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
  • write (38-71)
  • write (38-38)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtkh5_type_writer.hpp (6)
  • diagnostic (87-92)
  • diagnostic (87-87)
  • lvl (267-272)
  • lvl (267-267)
  • ilvl (388-417)
  • ilvl (388-388)
src/diagnostic/detail/vtk_types/fluid.hpp (2)
src/diagnostic/detail/vtkh5_type_writer.hpp (8)
  • diagnostic (87-92)
  • diagnostic (87-87)
  • lvl (267-272)
  • lvl (267-267)
  • ilvl (388-417)
  • ilvl (388-388)
  • boxes (57-71)
  • boxes (57-57)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
  • write (30-55)
  • write (30-30)
src/diagnostic/diagnostics.hpp (3)
src/diagnostic/diagnostic_manager.hpp (5)
  • dict (83-83)
  • dict (86-86)
  • dict (86-86)
  • make_unique (74-80)
  • make_unique (74-75)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • make_unique (67-74)
  • make_unique (67-67)
src/diagnostic/detail/h5writer.hpp (2)
  • make_unique (61-68)
  • make_unique (61-61)
src/core/data/ndarray/ndarray_vector.hpp (1)
src/core/utilities/types.hpp (2)
  • product (265-268)
  • product (265-265)
tests/simulator/refinement/test_2d_10_core.py (2)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_lib (6-9)
tests/simulator/test_advance.py (1)
  • AdvanceTestBase (33-869)
src/diagnostic/detail/vtkh5_writer.hpp (4)
src/diagnostic/diagnostic_model_view.hpp (1)
  • dimension (30-60)
src/diagnostic/diagnostics.hpp (2)
  • make_unique (50-65)
  • make_unique (50-51)
src/diagnostic/detail/vtkh5_type_writer.hpp (6)
  • level (298-334)
  • level (298-298)
  • level (336-340)
  • level (336-336)
  • diagnostic (87-92)
  • diagnostic (87-87)
src/hdf5/detail/h5/h5_file.hpp (4)
  • path (267-273)
  • path (267-267)
  • path (275-280)
  • path (275-275)
src/diagnostic/detail/vtk_types/info.hpp (5)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
  • write (30-55)
  • write (30-30)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
  • write (38-71)
  • write (38-38)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtk_types/meta.hpp (2)
  • write (29-31)
  • write (29-29)
src/diagnostic/detail/vtk_types/particle.hpp (2)
  • write (31-54)
  • write (31-31)
src/diagnostic/detail/vtkh5_type_writer.hpp (2)
  • diagnostic (87-92)
  • diagnostic (87-87)
src/diagnostic/diagnostic_model_view.hpp (4)
src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp (10)
  • patch (146-154)
  • patch (146-146)
  • ions (407-416)
  • ions (407-407)
  • ions (420-445)
  • ions (420-420)
  • ions (447-480)
  • ions (447-447)
  • ions (492-531)
  • ions (492-493)
src/amr/resources_manager/amr_utils.hpp (2)
  • visitHierarchy (244-253)
  • visitHierarchy (244-245)
src/core/data/ions/ion_population/ion_population.hpp (1)
  • forward_as_tuple (109-113)
src/core/data/ions/ions.hpp (1)
  • forward_as_tuple (225-229)
src/diagnostic/detail/vtkh5_type_writer.hpp (5)
src/core/utilities/types.hpp (7)
  • get_env_as (249-249)
  • for_N_make_array (504-507)
  • for_N_make_array (504-504)
  • sum_from (277-285)
  • sum_from (277-277)
  • sum (271-274)
  • sum (271-271)
src/core/utilities/box/box.hpp (7)
  • box (51-51)
  • i (97-97)
  • i (97-97)
  • grow (89-94)
  • grow (89-89)
  • grow (275-280)
  • grow (275-275)
src/core/data/tensorfield/tensorfield.hpp (6)
  • i (181-181)
  • i (181-181)
  • i (182-182)
  • i (182-182)
  • tensor_field_dim_from_rank (17-24)
  • tensor_field_dim_from_rank (17-17)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
src/core/utilities/algorithm.hpp (2)
  • convert_to_fortran_primal (137-140)
  • convert_to_fortran_primal (137-137)
pyphare/pyphare/pharesee/tovtk.py (2)
pyphare/pyphare/core/box.py (1)
  • shape (32-34)
src/diagnostic/detail/vtkh5_type_writer.hpp (6)
  • ilvl (388-417)
  • ilvl (388-388)
  • lvl (267-272)
  • lvl (267-267)
  • resize (420-426)
  • resize (420-420)
🪛 GitHub Check: CodeQL
pyphare/pyphare/pharesee/tovtk.py

[failure] 361-361: Wrong number of arguments in a call
Call to function primalScalarToFlatPrimal with too many arguments; should be no more than 5.


[failure] 387-387: Wrong number of arguments in a call
Call to function BtoFlatPrimal with too few arguments; should be no fewer than 6.
Call to function EtoFlatPrimal with too few arguments; should be no fewer than 6.
Call to function primalVectorToFlatPrimal with too few arguments; should be no fewer than 6.


[notice] 163-163: Unused local variable
Variable cellData_g is not used.


[notice] 165-165: Unused local variable
Variable fieldData_g is not used.


[notice] 166-166: Unused local variable
Variable cellDataOffset_g is not used.


[notice] 167-167: Explicit returns mixed with implicit (fall through) returns
Mixing implicit and explicit returns may indicate an error, as implicit returns always return None.


[notice] 168-168: Unused local variable
Variable FieldDataOffset_g is not used.

🪛 Ruff (0.14.3)
tests/simulator/test_vtk_diagnostics.py

1-1: Shebang is present but file is not executable

(EXE001)


27-27: Unused function argument: xyz

(ARG001)


34-34: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


41-41: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


44-44: Unused function argument: xyz

(ARG001)


47-47: Unused function argument: xyz

(ARG001)


54-54: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


61-61: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


64-64: Unused function argument: xyz

(ARG001)


67-67: Unused function argument: xyz

(ARG001)


70-70: Unused function argument: xyz

(ARG001)


121-121: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)

pyphare/pyphare/pharesee/tovtk.py

1-1: Shebang is present but file is not executable

(EXE001)


17-19: Avoid specifying long messages outside the exception class

(TRY003)


204-204: Avoid specifying long messages outside the exception class

(TRY003)


232-232: Avoid specifying long messages outside the exception class

(TRY003)


263-263: Consider [*root_spacing, 0, 0] instead of concatenation

Replace with [*root_spacing, 0, 0]

(RUF005)


265-265: Consider [*root_spacing, 0] instead of concatenation

Replace with [*root_spacing, 0]

(RUF005)


321-321: Local variable cellData_g is assigned to but never used

Remove assignment to unused variable cellData_g

(F841)


323-323: Local variable fieldData_g is assigned to but never used

Remove assignment to unused variable fieldData_g

(F841)


324-324: Local variable cellDataOffset_g is assigned to but never used

Remove assignment to unused variable cellDataOffset_g

(F841)


326-326: Local variable FieldDataOffset_g is assigned to but never used

Remove assignment to unused variable FieldDataOffset_g

(F841)


384-384: Prefer next(iter(patch.keys())) over single element slice

Replace with next(iter(patch.keys()))

(RUF015)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: build (macos-13)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-14)
  • GitHub Check: Analyze (cpp)
  • GitHub Check: Analyze (python)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (ubuntu-latest, gcc)
🔇 Additional comments (4)
src/hdf5/detail/h5/h5_file.hpp (1)

98-99: LGTM! Good defensive check.

The existence check makes dataset creation idempotent, allowing safe repeated calls.

src/amr/resources_manager/amr_utils.hpp (1)

251-251: LGTM! Critical correctness fix for perfect forwarding.

The corrected forwarding syntax std::forward<Args>(args)... properly expands the parameter pack, forwarding each argument individually with its original value category. This matches the pattern shown in the relevant code snippets from field.hpp.

tests/simulator/refinement/test_2d_10_core.py (1)

20-23: Initialization order with MPI startup is a valid concern—verify actual runtime behavior.

cpp_lib() is imported at module load time (line 20), but MPI initialization via SamraiLifeCycle() doesn't occur until startMPI() is called in main() (line 188) or via SimulatorTest.setUp(). The C++ bindings module (pybindlibs.cpp) may require MPI context to be initialized at import time. Additionally, instantiating test = AdvanceTestBase(rethrow=True) at module level (line 21) before MPI is set up could cause issues if the class initialization has MPI dependencies, though setUp() is only called by the test framework before test methods run.

Consider moving module-level initialization inside main() after startMPI() is called, or implement lazy initialization (defer cpp_lib() and AdvanceTestBase instantiation until after MPI setup). This is especially important for MPI-based tests that initialize at module scope.

src/diagnostic/detail/vtkh5_type_writer.hpp (1)

138-139: Verify duplicate write() calls in 2D writers.

Both VTKFileFieldWriter::write2D and VTKFileTensorFieldWriter::write2D call write() twice consecutively without any intervening state change. This pattern is unusual and may indicate either:

  • An intentional handling of 2D data peculiarities
  • A copy-paste error

Please confirm whether the duplicate write() calls are intentional. If intentional, add a comment explaining why 2D data requires two identical write passes.

If this is an error, remove the duplicate call:

         };
         write();
-        write();
     }

Also applies to: 187-188

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
tests/simulator/test_vtk_diagnostics.py (2)

19-19: Remove unused module-level variable.

The cpp variable is instantiated but never referenced in this file.

Apply this diff:

-cpp = cpp_lib()
-
 ndims = [2]  # 3d todo / 1d not supported
 interp_orders = [1]  # , 2, 3

29-61: Eliminate code duplication in field and velocity functions.

The by/bz functions are identical, and the vy/vz functions are identical. This duplication can be eliminated with a shared helper.

Consider refactoring to use a shared periodic function generator:

def make_periodic_sin(*xyz):
    from pyphare.pharein.global_vars import sim
    L = sim.simulation_domain()
    _ = lambda i: 0.1 * np.sin(2 * np.pi * xyz[i] / L[i])
    return np.asarray([_(i) for i in range(len(xyz))]).prod(axis=0)

def make_periodic_cos(*xyz):
    from pyphare.pharein.global_vars import sim
    L = sim.simulation_domain()
    _ = lambda i: 0.1 * np.cos(2 * np.pi * xyz[i] / L[i])
    return np.asarray([_(i) for i in range(len(xyz))]).prod(axis=0)

def by(*xyz):
    return make_periodic_sin(*xyz)

def bz(*xyz):
    return make_periodic_sin(*xyz)

def vy(*xyz):
    return make_periodic_cos(*xyz)

def vz(*xyz):
    return make_periodic_cos(*xyz)
src/core/utilities/types.hpp (1)

226-235: Consider verifying full string consumption.

The function correctly implements exception-based error handling. However, it may silently ignore trailing characters (e.g., "123abc" parses as 123).

Apply this diff to ensure the entire string is consumed:

 template<typename T>
 NO_DISCARD T from_string(std::string const& s)
 {
     T t;
     std::stringstream ss(s);
     ss >> t;
-    if (ss.fail())
+    if (ss.fail() || (!ss.eof() && ss.peek() != std::stringstream::traits_type::eof()))
         throw std::runtime_error("Cannot Parse T from: " + s);
     return t;
 }

Optionally, consider adding a specialization for std::string if environment variables may contain whitespace:

template<>
NO_DISCARD inline std::string from_string<std::string>(std::string const& s)
{
    return s;
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6ebc3b9 and 927ef0b.

📒 Files selected for processing (4)
  • src/core/utilities/algorithm.hpp (2 hunks)
  • src/core/utilities/types.hpp (5 hunks)
  • src/diagnostic/detail/vtkh5_type_writer.hpp (1 hunks)
  • tests/simulator/test_vtk_diagnostics.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/core/utilities/algorithm.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
🧰 Additional context used
📓 Path-based instructions (1)
**/*.hpp

⚙️ CodeRabbit configuration file

Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Files:

  • src/core/utilities/types.hpp
🧠 Learnings (4)
📓 Common learnings
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-07-26T22:04:34.160Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-10-09T08:32:15.667Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-09-05T17:02:58.784Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
📚 Learning: 2025-09-01T09:41:40.618Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1056
File: tests/core/numerics/interpolator/test_main.cpp:314-318
Timestamp: 2025-09-01T09:41:40.618Z
Learning: The PHARE project uses C++20, which makes the typename keyword optional for dependent types in obvious contexts. The project prefers minimal code without unnecessary keywords, so typename suggestions for dependent types should be avoided when the code compiles successfully in C++20.

Applied to files:

  • src/core/utilities/types.hpp
📚 Learning: 2025-09-17T13:35:11.533Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.

Applied to files:

  • src/core/utilities/types.hpp
📚 Learning: 2025-04-17T14:41:53.643Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 998
File: src/core/utilities/point/point.hpp:195-210
Timestamp: 2025-04-17T14:41:53.643Z
Learning: In `src/core/utilities/point/point.hpp`, the `as_signed()` and `as_unsigned()` methods are intentionally designed to cause compilation errors for unsupported types (only 4-byte types are supported). This forces developers to implement proper conversions themselves when extending the functionality to new types. The comment "else no return cause not yet handled" indicates this is a deliberate design choice.

Applied to files:

  • src/core/utilities/types.hpp
🧬 Code graph analysis (1)
tests/simulator/test_vtk_diagnostics.py (5)
pyphare/pyphare/simulator/simulator.py (2)
  • startMPI (41-45)
  • reset (258-269)
tests/simulator/__init__.py (3)
  • SimulatorTest (201-267)
  • tearDown (204-205)
  • unique_diag_dir_for_test_case (250-254)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-62)
pyphare/pyphare/pharein/simulation.py (2)
  • simulation_domain (967-968)
  • Simulation (735-1069)
pyphare/pyphare/pharein/maxwellian_fluid_model.py (1)
  • MaxwellianFluidModel (8-303)
🪛 Ruff (0.14.4)
tests/simulator/test_vtk_diagnostics.py

26-26: Unused function argument: xyz

(ARG001)


33-33: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


40-40: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


43-43: Unused function argument: xyz

(ARG001)


46-46: Unused function argument: xyz

(ARG001)


53-53: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


60-60: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


63-63: Unused function argument: xyz

(ARG001)


66-66: Unused function argument: xyz

(ARG001)


69-69: Unused function argument: xyz

(ARG001)

🔇 Additional comments (5)
tests/simulator/test_vtk_diagnostics.py (1)

161-162: Verify the purpose of the render_data call.

The test calls phc.vtkhdf.render_data but doesn't assert anything about the output. The comment suggests adding verification logic using the vtk module.

Is this call intentional for manual inspection only, or should it include assertions to verify the generated VTK/HDF artifacts? If verification is needed, consider:

# Example verification approach
import os
self.assertTrue(os.path.exists(f"{local_out}/EM_E.vtkhdf"))
# Add vtk module-based validation of file structure/contents
src/core/utilities/types.hpp (4)

1-2: LGTM: Header guard follows project convention.

The header guard naming correctly follows the project's full-path structure pattern.

Also applies to: 566-566


7-21: LGTM: All necessary includes present.

The include additions properly support the new functionality, including <sstream> and <stdexcept> for the from_string implementation.


252-258: LGTM: Clean environment variable parsing utility.

The function correctly integrates get_env with from_string to provide type-safe environment variable access with defaults.


514-518: LGTM: Clean constexpr utility.

The function correctly composes for_N and all to provide a compile-time evaluable check across N invocations.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/diagnostic/detail/vtkh5_type_writer.hpp (1)

128-140: Add explanatory comment for duplicate write() calls.

The write() lambda is invoked twice (lines 138-139) in the 2D case to write data for both faces of the cube (per the X_TIMES = 2 multiplier at line 361). A brief comment explaining this per-face data structure would improve code clarity.

Apply this diff to add the explanatory comment:

         };
+        // 2D data is written per face of cube, requiring 2 passes (X_TIMES = 2)
         write();
         write();
     }
🧹 Nitpick comments (2)
src/diagnostic/detail/vtkh5_type_writer.hpp (2)

176-189: Add explanatory comment for duplicate write() calls.

Similar to the scalar field writer, the tensor field write() lambda is invoked twice (lines 187-188) for 2D per-face data. Add a comment for consistency and clarity.

Apply this diff:

         };
+        // 2D data is written per face of cube, requiring 2 passes (X_TIMES = 2)
         write();
         write();
     }

102-121: Consider clarifying the primal_qty sentinel usage.

The primal_qty is hardcoded to rho at line 104 and used to query the primal grid layout. While this works (all primal quantities share the same centering), the intent—using rho as a representative primal quantity—could be clearer with a brief comment.

Consider adding a comment:

-    auto static constexpr primal_qty = physical_quantity_type::rho;
+    // Use rho as representative primal quantity (all primal quantities share same centering)
+    auto static constexpr primal_qty = physical_quantity_type::rho;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 927ef0b and 614be65.

📒 Files selected for processing (3)
  • src/core/utilities/algorithm.hpp (2 hunks)
  • src/core/utilities/types.hpp (5 hunks)
  • src/diagnostic/detail/vtkh5_type_writer.hpp (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.hpp

⚙️ CodeRabbit configuration file

Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Files:

  • src/core/utilities/algorithm.hpp
  • src/core/utilities/types.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
🧠 Learnings (7)
📓 Common learnings
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-07-26T22:04:34.160Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-10-09T08:32:15.667Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-09-05T17:02:58.784Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
📚 Learning: 2024-10-22T10:05:54.014Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 0
File: :0-0
Timestamp: 2024-10-22T10:05:54.014Z
Learning: The variable `c_ordering` in `ConcreteLoadBalancerHybridStrategyNPPC<PHARE_T>::compute` is used to create an array view `lb_view` for handling load balancing data.

Applied to files:

  • src/core/utilities/algorithm.hpp
📚 Learning: 2025-11-10T09:37:57.021Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1084
File: src/diagnostic/diagnostic_model_view.hpp:219-221
Timestamp: 2025-11-10T09:37:57.021Z
Learning: In PHARE, temporary fields like tmpField_, tmpVec_, and tmpTensor_ in src/diagnostic/diagnostic_model_view.hpp use a name-based resource allocation pattern. Fields with names "PHARE_sumField", "PHARE_sumVec", and "PHARE_sumTensor" are allocated globally elsewhere in the resources manager (e.g., in src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp), and components reference the same storage through identically-named field objects. These do not require local allocation via rm.enumerate().

Applied to files:

  • src/core/utilities/algorithm.hpp
📚 Learning: 2025-09-17T13:35:11.533Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.

Applied to files:

  • src/core/utilities/algorithm.hpp
📚 Learning: 2025-09-01T09:41:40.618Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1056
File: tests/core/numerics/interpolator/test_main.cpp:314-318
Timestamp: 2025-09-01T09:41:40.618Z
Learning: The PHARE project uses C++20, which makes the typename keyword optional for dependent types in obvious contexts. The project prefers minimal code without unnecessary keywords, so typename suggestions for dependent types should be avoided when the code compiles successfully in C++20.

Applied to files:

  • src/core/utilities/algorithm.hpp
  • src/core/utilities/types.hpp
📚 Learning: 2025-04-17T14:41:53.643Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 998
File: src/core/utilities/point/point.hpp:195-210
Timestamp: 2025-04-17T14:41:53.643Z
Learning: In `src/core/utilities/point/point.hpp`, the `as_signed()` and `as_unsigned()` methods are intentionally designed to cause compilation errors for unsupported types (only 4-byte types are supported). This forces developers to implement proper conversions themselves when extending the functionality to new types. The comment "else no return cause not yet handled" indicates this is a deliberate design choice.

Applied to files:

  • src/core/utilities/types.hpp
📚 Learning: 2024-09-09T13:57:02.285Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py:566-568
Timestamp: 2024-09-09T13:57:02.285Z
Learning: Avoid commenting on draft PRs for PhilipDeegan unless explicitly requested.

Applied to files:

  • src/diagnostic/detail/vtkh5_type_writer.hpp
🧬 Code graph analysis (1)
src/core/utilities/algorithm.hpp (3)
src/core/data/electrons/electrons.hpp (8)
  • layout (107-133)
  • layout (107-107)
  • layout (285-285)
  • layout (285-285)
  • layout (286-286)
  • layout (286-286)
  • layout (309-319)
  • layout (309-309)
src/core/utilities/types.hpp (4)
  • all (365-369)
  • all (365-366)
  • all (376-379)
  • all (376-376)
src/core/data/ndarray/ndarray_vector.hpp (4)
  • make_array_view (214-217)
  • make_array_view (214-214)
  • make_array_view (220-223)
  • make_array_view (220-220)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (cpp)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (macos-13)
🔇 Additional comments (8)
src/core/utilities/types.hpp (3)

226-235: LGTM! Error handling properly implemented.

The from_string function now includes proper error handling by throwing std::runtime_error on parse failure, addressing the concern raised in the previous review. The approach aligns with the author's preference for explicit error signaling.


252-258: LGTM! Clean environment variable utility.

The get_env_as function provides a clean, type-safe interface for reading environment variables with defaults, properly leveraging the from_string utility.


514-518: LGTM! Consistent with existing patterns.

The for_N_all function cleanly integrates with the existing for_N infrastructure, providing a convenient compile-time predicate evaluation utility.

src/core/utilities/algorithm.hpp (3)

98-123: LGTM! Variable usage is correct.

The c_ordering variable at line 105 is correctly used as a template parameter in make_array_view<c_ordering> at line 109. The static analysis warning about it being unused is a false positive—the variable is used in a constant expression context to specify Fortran (row-major) ordering for the array view.

The conversion logic properly handles both all-primal and mixed-centering cases with an appropriate optimization path.

Based on learnings: Variable c_ordering is used to create an array view for handling Fortran-ordered data layout.


125-140: LGTM! Clean recursive implementation.

The TensorField specialization correctly applies field-level primal conversion to each tensor component, and the wrapper provides a clean public interface.


71-96: <!-- [scratchpad_start]
[task review_file_2/3 review_segment_1/3]
Verify limited PhysicalQuantity support - FINAL CONCLUSION

[observations]

  • Physical quantities exist: Bx, By, Bz, Ex, Ey, Ez, Jx, Jy, Jz, rho, Vx, Vy, Vz, P, Mxx, Mxy, Mxz, Myy, Myz, Mzz (from gridlayoutimplyee.hpp:111-112)
  • HybridQuantity::Scalar defines rho, Vx, Vy, Vz and more
  • VTK-HDF5 diagnostics output: charge_density (rho), mass_density (rho), bulkVelocity (V tensor)
  • Fluid quantities flow through: writeTensorField/writeField → convert_to_fortran_primal → convert_to_primal
  • convert_to_primal throws runtime_error for ANY quantity outside {Bx, By, Bz, Ex, Ey, Ez}
  • Vx, Vy, Vz shown with all-primal centering in gridlayoutimplyee.hpp lines 87-92
  • BUT: gridlayoutimplyee.hpp has full centering array for all 20 quantities, suggesting they CAN have different centerings

[analysis]

  • Review concern is VALID: function only handles EM fields but may receive fluid quantities
  • Evidence suggests Vx/Vy/Vz are typically primal, but centering system is flexible
  • If ANY fluid quantity can be dual-centered and flows to diagnostic output, runtime error occurs
  • Code structure suggests this is either: (a) incomplete bug, (b) untested edge case, or (c) guaranteed safe by external constraints not visible here

[pending]
Verification needed: Can rho, Vx, Vy, Vz ever have dual centering? If yes, is there test coverage?

[decision]
Review comment is LEGITIMATE but cannot be definitively proven as bug without runtime/behavioral analysis.
Tag:

I have gathered sufficient information to evaluate the review comment. The verification reveals that:

  1. The convert_to_primal function handles only electromagnetic field components (Bx, By, Bz, Ex, Ey, Ez)
  2. The codebase defines many additional physical quantities: rho, Vx, Vy, Vz, P, Jx, Jy, Jz, and tensor components (Mxx, Mxy, etc.)
  3. The VTK-HDF5 diagnostic writer outputs fluid quantities (charge density, mass density, bulk velocity) alongside electromagnetic fields
  4. Both fluid and electromagnetic fields flow through the same convert_to_fortran_primalconvert_to_primal conversion path
  5. The function throws std::runtime_error for any unsupported quantity

While evidence suggests velocity components (Vx, Vy, Vz) are typically primal-centered, the grid layout system supports configurable centering for all quantities, and the code provides no guarantee that fluid quantities cannot be dual-centered in certain configurations.

The review comment identifies a legitimate concern: the function is incomplete for the full set of physical quantities it may receive at runtime. Whether this manifests as an actual bug depends on whether dual-centered fluid fields can occur in practice, which cannot be determined from static analysis alone.

src/diagnostic/detail/vtkh5_type_writer.hpp (2)

355-385: LGTM! MPI coordination logic is correct.

The resize_data function properly coordinates parallel HDF5 writes using MPI collective operations. Each rank computes its write offset by summing the data sizes of all preceding ranks, ensuring non-overlapping writes to the shared dataset.


388-417: LGTM! Consistent MPI coordination pattern.

The resize_boxes function follows the same correct MPI coordination pattern as resize_data, ensuring each rank writes its box metadata to non-overlapping regions of the shared HDF5 dataset.

Comment on lines +219 to +221
Field tmpField_{"PHARE_sumField", core::HybridQuantity::Scalar::rho};
VecField tmpVec_{"PHARE_sumVec", core::HybridQuantity::Vector::V};
TensorFieldT tmpTensor_{"PHARE_sumTensor", core::HybridQuantity::Tensor::M};
Copy link
Member Author

Choose a reason for hiding this comment

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

during PGL these were only doing a sum, but perhaps they should be renamed generally, to PHARE_tmpX or similar

@PhilipDeegan
Copy link
Member Author

PhilipDeegan commented Nov 16, 2025

wheel available for python3.14. see https://gitlab.kitware.com/vtk/vtk/-/issues/19845#note_1729163

I had to rename it to vtk-9.5.20251115.dev0-cp314-cp314t-manylinux_2_17_x86_64.whl

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
src/core/data/grid/gridlayout.hpp (1)

5-14: Use a signed ghost width in AMRGhostBoxFor to avoid signed/unsigned underflow.

AMRGhostBoxFor currently does:

auto AMRGhostBoxFor(auto const& field) const
{
    auto const centerings = centering(field);
    return grow(AMRBoxFor(field),
                for_N_make_array<dimension>([&](auto i) { return nbrGhosts(centerings[i]); }));
}

nbrGhosts returns std::uint32_t, while Box<int, dimension>::grow subtracts this value from lower. That mixes signed and unsigned arithmetic; for small AMRBox_.lower[i] (e.g., 0), lower -= size can underflow in the unsigned domain and then be converted back to int, which is undefined behavior.

Casting the ghost count to a signed type when building the array keeps all arithmetic in the signed domain:

-        auto AMRGhostBoxFor(auto const& field) const
-        {
-            auto const centerings = centering(field);
-            return grow(AMRBoxFor(field), for_N_make_array<dimension>(
-                                              [&](auto i) { return nbrGhosts(centerings[i]); }));
-        }
+        auto AMRGhostBoxFor(auto const& field) const
+        {
+            auto const centerings = centering(field);
+            return grow(
+                AMRBoxFor(field),
+                for_N_make_array<dimension>([&](auto i) {
+                    return static_cast<int>(nbrGhosts(centerings[i]));
+                }));
+        }

This preserves the intended semantics (grow the field box by the ghost width on all sides) while avoiding undefined behavior from signed/unsigned underflow. The new amr_lcl_idx helpers built on these boxes then remain safe.

Also applies to: 1027-1046, 1180-1194, 1220-1226

src/diagnostic/detail/vtkh5_type_writer.hpp (1)

128-139: Add inline comment for duplicate write() in 2D.

The duplicate write() call at lines 137-138 is intentional (per X_TIMES multiplier logic at line 358) but lacks inline documentation. Add a brief comment explaining that 2D data is written per face of a cube and requires two passes.

Based on past review comments.

🧹 Nitpick comments (14)
src/core/utilities/types.hpp (1)

1-2: New utility helpers are consistent and well-scoped

  • The expanded includes and updated guard match the new usages (std::stringstream, std::optional, algorithms, exceptions).
  • from_string and get_env_as are straightforward and make the env/config handling clearer; throwing on parse failure is a reasonable, explicit policy.
  • for_N_all / for_N_any correctly reuse the existing for_N + container all/any helpers, keeping the implementation minimal.

If you expect from_string to be used only for a narrow set of types (e.g., arithmetic), you could later add a static_assert to document that constraint, but it’s not required now.

Also applies to: 12-21, 226-235, 252-258, 514-519, 566-566

src/core/data/ndarray/ndarray_vector.hpp (1)

19-24: Reworked NdArrayViewer indexing fixes the 16‑bit issue and centralizes layout logic

  • Using Id = std::uint32_t and routing all access through the new idx helpers addresses the previous 16‑bit overflow risk and keeps C/Fortran ordering logic in one place.
  • The at(...) helpers with the product(nCells, std::uint32_t{1}) assertion give a clear bound check and are used consistently by MaskedView, NdArrayView, and NdArrayVector.

If you ever need arrays with more than ~4e9 elements, consider switching Id and the product accumulator to std::size_t to avoid 32‑bit overflow; for current realistic grid sizes this is fine.

Also applies to: 25-37, 38-53, 55-63, 65-70, 101-102, 130-139, 288-292, 300-304

src/diagnostic/diagnostics.hpp (1)

27-29: Format‑driven writer selection is clear and backward‑compatible

The resolver cleanly adds a "format" switch:

  • Defaults to "phareh5" to preserve existing behavior.
  • Selects the new vtkh5::H5Writer when "pharevtkhdf" is requested.
  • Throws with a clear message on unknown formats.

You might later want a slightly more descriptive log (e.g., prefixing "diagnostics format=") instead of logging the raw string, but the current behavior is acceptable.

Also applies to: 53-62

src/diagnostic/detail/vtk_types/electromag.hpp (1)

12-55: Electromag VTKHDF writer follows the existing fluid writer pattern

The new ElectromagDiagnosticWriter:

  • Uses VTKFileWriter and modelView.onLevels in the same way as the fluid writer, initializing per‑level datasets and then writing via visitHierarchy.
  • Filters electromag fields by matching diagnostic.quantity to "/" + vecField->name(), which keeps the selection logic straightforward.

Minor nits, purely optional:

  • You already bind auto& modelView at the top; write_quantity could reuse it instead of re‑calling this->h5Writer_.modelView().
  • The header‑guard end comment still says PHARE_DIAGNOSTIC_DETAIL_TYPES_ELECTROMAG_H; consider updating it to match the actual guard macro for consistency.

Also applies to: 60-62

src/diagnostic/detail/vtk_types/info.hpp (1)

11-33: InfoDiagnosticWriter is currently a no‑op stub

InfoDiagnosticWriter is wired into the vtkh5 infrastructure but both write and compute are empty. That’s safe if info diagnostics aren’t yet meant to produce VTKHDF output, but it may be surprising to users who configure such diagnostics and see no data.

Consider either:

  • Adding a TODO/comment to make the stub status explicit, or
  • Implementing a minimal write that populates basic run metadata once you know the desired content.

You could also mark the diagnostic parameter [[maybe_unused]] in the stub to silence unused‑parameter warnings, and update the #endif comment to match the guard macro.

Also applies to: 38-38

tests/simulator/test_vtk_diagnostics.py (1)

105-129: Avoid reusing the same simInput dict across parameter combinations.

permute mutates a single dic and then passes that same dict object as simInput for every (ndim, interp_order) pair. With only one combination today this is harmless, but as soon as you uncomment more interp_orders or ndims, later tests will see the mutated state from earlier ones.

Consider building a fresh config per case:

-def permute(dic):
-    dic.update(simArgs.copy())
-    return [
-        dict(
-            ndim=ndim,
-            interp=interp_order,
-            simInput=dic,
-        )
-        for ndim, interp_order in itertools.product(ndims, interp_orders)
-    ]
+def permute(overrides):
+    base = simArgs.copy()
+    base.update(overrides)
+    return [
+        dict(
+            ndim=ndim,
+            interp=interp_order,
+            simInput=base.copy(),
+        )
+        for ndim, interp_order in itertools.product(ndims, interp_orders)
+    ]

The rest of the test (model setup, tearDown, and diagnostic run) looks sound; Ruff’s ARG001/E731 hints in setup_model are stylistic and can be addressed later if you want a clean lint run.

Also applies to: 144-159

src/diagnostic/detail/vtk_types/fluid.hpp (1)

13-97: Fluid VTK/HDF writer wiring matches the existing Electromag patterns.

The isActiveDiag checks, per-level initialization, and per-population handling (density, charge_density, flux) are consistent with the H5/VTK writer design and should correctly gate which fields are emitted for a given DiagnosticProperties. Only a tiny nit: the #endif comment uses ...FLUID_H while the guard macro is ...FLUID_HPP; you may want to align those for clarity.

Also applies to: 100-104

src/diagnostic/diagnostic_model_view.hpp (1)

33-39: Model view tmp-field plumbing and hierarchy helpers are coherent.

The switch to tmpTensor_ (with rm.enumerate-based allocation), the updated visitHierarchy call, and the new utilities (localLevelBoxes, tmpField/tmpVecField/tmpTensorField, getCompileTimeResourcesViewList) all line up with the existing name-based resource pattern (PHARE_sumField/Vec/Tensor) and the vtkh5 writers’ needs. Behavior should remain unchanged while making the temporary storage more explicit. Renaming the tmp resources away from "*sum*" is purely cosmetic and can be deferred if you want to preserve resource-manager conventions.
Based on learnings

Also applies to: 62-81, 93-99, 145-172, 179-195, 218-221

src/diagnostic/detail/vtkh5_writer.hpp (1)

130-130: Document or parametrize the hardcoded level bounds.

The TODO indicates minLevel and maxLevel are hardcoded. Consider documenting why these specific values (0 and 10) were chosen, or add a constructor parameter or dict entry to allow configuration.

src/diagnostic/detail/vtkh5_type_writer.hpp (5)

38-38: Document the FloatType override rationale.

FloatType is hardcoded to float, ignoring Writer::FloatType. Based on past comments, this is due to ParaView VTK reader limitations with doubles. Consider adding a more detailed comment explaining this constraint and referencing the ParaView limitation.


164-164: Clarify ownership comment.

The comment "NOT OWNED HERE" could be more explicit. Consider: "References parent VTKFileWriter's data_offset member" for clarity.


211-211: Clarify ownership comment.

The comment "NOT OWNED HERE" could be more explicit. Consider: "References parent VTKFileWriter's data_offset member" for clarity.


352-359: Expand documentation for X_TIMES dimension mapping.

The X_TIMES calculation is clever but cryptic. The comment mentions "per face of a cube" but doesn't explain why 2D is ×2 or 1D is ×4. Consider expanding the comment to clarify that this accounts for converting lower-dimensional data into 3D cube faces for VTK compatibility.


417-419: Document in-place modification of boxes parameter.

Line 418 modifies boxes.upper += 1 in place to convert to primal indexing. Since boxes is passed by non-const reference, this side effect may not be obvious to callers. Add a comment documenting this intentional mutation or consider returning a copy if the modification isn't required by the caller.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 614be65 and e4192e8.

📒 Files selected for processing (31)
  • pyphare/pyphare/pharein/__init__.py (1 hunks)
  • pyphare/pyphare/pharein/simulation.py (1 hunks)
  • src/amr/physical_models/hybrid_model.hpp (1 hunks)
  • src/amr/resources_manager/amr_utils.hpp (1 hunks)
  • src/core/data/grid/gridlayout.hpp (4 hunks)
  • src/core/data/grid/gridlayoutdefs.hpp (1 hunks)
  • src/core/data/grid/gridlayoutimplyee.hpp (27 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (5 hunks)
  • src/core/data/tensorfield/tensorfield.hpp (1 hunks)
  • src/core/utilities/algorithm.hpp (2 hunks)
  • src/core/utilities/box/box.hpp (6 hunks)
  • src/core/utilities/types.hpp (5 hunks)
  • src/diagnostic/detail/h5writer.hpp (2 hunks)
  • src/diagnostic/detail/vtk_types/electromag.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/fluid.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/info.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/meta.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/particle.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_type_writer.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_writer.hpp (1 hunks)
  • src/diagnostic/diagnostic_manager.hpp (1 hunks)
  • src/diagnostic/diagnostic_model_view.hpp (7 hunks)
  • src/diagnostic/diagnostics.hpp (2 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (2 hunks)
  • src/phare/CMakeLists.txt (0 hunks)
  • src/phare/phare_init.py (0 hunks)
  • src/phare/phare_init_small.py (0 hunks)
  • tests/simulator/CMakeLists.txt (2 hunks)
  • tests/simulator/__init__.py (1 hunks)
  • tests/simulator/refinement/test_2d_10_core.py (1 hunks)
  • tests/simulator/test_vtk_diagnostics.py (1 hunks)
💤 Files with no reviewable changes (3)
  • src/phare/CMakeLists.txt
  • src/phare/phare_init.py
  • src/phare/phare_init_small.py
🚧 Files skipped from review as they are similar to previous changes (10)
  • pyphare/pyphare/pharein/simulation.py
  • src/core/data/grid/gridlayoutdefs.hpp
  • src/core/data/tensorfield/tensorfield.hpp
  • src/diagnostic/detail/vtk_types/particle.hpp
  • src/amr/physical_models/hybrid_model.hpp
  • pyphare/pyphare/pharein/init.py
  • tests/simulator/refinement/test_2d_10_core.py
  • src/diagnostic/detail/vtk_types/meta.hpp
  • tests/simulator/init.py
  • tests/simulator/CMakeLists.txt
🧰 Additional context used
📓 Path-based instructions (1)
**/*.hpp

⚙️ CodeRabbit configuration file

Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Files:

  • src/diagnostic/detail/vtk_types/electromag.hpp
  • src/diagnostic/diagnostic_manager.hpp
  • src/core/utilities/algorithm.hpp
  • src/diagnostic/detail/vtk_types/fluid.hpp
  • src/diagnostic/diagnostics.hpp
  • src/core/data/grid/gridlayoutimplyee.hpp
  • src/amr/resources_manager/amr_utils.hpp
  • src/diagnostic/detail/vtk_types/info.hpp
  • src/core/data/grid/gridlayout.hpp
  • src/diagnostic/detail/h5writer.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
  • src/diagnostic/diagnostic_model_view.hpp
  • src/core/utilities/types.hpp
  • src/hdf5/detail/h5/h5_file.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
  • src/core/utilities/box/box.hpp
🧠 Learnings (11)
📓 Common learnings
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-07-26T22:04:34.160Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-10-09T08:32:15.667Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-09-05T17:02:58.784Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
📚 Learning: 2024-10-22T10:05:54.014Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 0
File: :0-0
Timestamp: 2024-10-22T10:05:54.014Z
Learning: The variable `c_ordering` in `ConcreteLoadBalancerHybridStrategyNPPC<PHARE_T>::compute` is used to create an array view `lb_view` for handling load balancing data.

Applied to files:

  • src/core/utilities/algorithm.hpp
📚 Learning: 2025-09-17T13:35:11.533Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.

Applied to files:

  • src/core/utilities/algorithm.hpp
  • src/diagnostic/diagnostic_model_view.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
📚 Learning: 2025-11-10T09:37:57.021Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1084
File: src/diagnostic/diagnostic_model_view.hpp:219-221
Timestamp: 2025-11-10T09:37:57.021Z
Learning: In PHARE, temporary fields like tmpField_, tmpVec_, and tmpTensor_ in src/diagnostic/diagnostic_model_view.hpp use a name-based resource allocation pattern. Fields with names "PHARE_sumField", "PHARE_sumVec", and "PHARE_sumTensor" are allocated globally elsewhere in the resources manager (e.g., in src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp), and components reference the same storage through identically-named field objects. These do not require local allocation via rm.enumerate().

Applied to files:

  • src/core/utilities/algorithm.hpp
  • src/diagnostic/detail/h5writer.hpp
  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2025-09-01T09:41:40.618Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1056
File: tests/core/numerics/interpolator/test_main.cpp:314-318
Timestamp: 2025-09-01T09:41:40.618Z
Learning: The PHARE project uses C++20, which makes the typename keyword optional for dependent types in obvious contexts. The project prefers minimal code without unnecessary keywords, so typename suggestions for dependent types should be avoided when the code compiles successfully in C++20.

Applied to files:

  • src/core/utilities/algorithm.hpp
  • src/core/utilities/types.hpp
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/core/data/grid/gridlayout.hpp:805-821
Timestamp: 2024-10-09T08:32:15.667Z
Learning: In the `AMRToLocal` function, before converting to `uint32_t`, assert that `local >= 0` to ensure values are valid.

Applied to files:

  • src/core/data/grid/gridlayout.hpp
📚 Learning: 2025-07-09T17:18:05.771Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/amr/CMakeLists.txt:103-105
Timestamp: 2025-07-09T17:18:05.771Z
Learning: In the PHARE project, `HighFive` is a CMake option defined in `res/cmake/options.cmake` as `option(HighFive "Build with highfive usage" ON)`, not a target that would be created by find_package(). The condition `if (HighFive)` correctly checks this option.

Applied to files:

  • src/diagnostic/detail/h5writer.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
📚 Learning: 2025-09-17T13:50:16.038Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/tensorfield/tensor_field_data_factory.hpp:112-112
Timestamp: 2025-09-17T13:50:16.038Z
Learning: PhilipDeegan indicated that getSizeOfMemory returning a placeholder value of 1 in TensorFieldDataFactory is acceptable for their use case, suggesting it may not be critical for PHARE's memory management needs.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2024-09-09T13:57:02.285Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py:566-568
Timestamp: 2024-09-09T13:57:02.285Z
Learning: Avoid commenting on draft PRs for PhilipDeegan unless explicitly requested.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2025-04-17T14:41:53.643Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 998
File: src/core/utilities/point/point.hpp:195-210
Timestamp: 2025-04-17T14:41:53.643Z
Learning: In `src/core/utilities/point/point.hpp`, the `as_signed()` and `as_unsigned()` methods are intentionally designed to cause compilation errors for unsupported types (only 4-byte types are supported). This forces developers to implement proper conversions themselves when extending the functionality to new types. The comment "else no return cause not yet handled" indicates this is a deliberate design choice.

Applied to files:

  • src/core/utilities/types.hpp
  • src/core/utilities/box/box.hpp
🧬 Code graph analysis (14)
src/diagnostic/detail/vtk_types/electromag.hpp (3)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
  • write (38-97)
  • write (38-38)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtkh5_type_writer.hpp (8)
  • diagnostic (87-92)
  • diagnostic (87-87)
  • lvl (261-266)
  • lvl (261-261)
  • ilvl (382-411)
  • ilvl (382-382)
  • boxes (57-71)
  • boxes (57-57)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
src/diagnostic/diagnostic_manager.hpp (1)
src/amr/resources_manager/amr_utils.hpp (2)
  • to_string (222-227)
  • to_string (222-222)
src/core/utilities/algorithm.hpp (3)
src/core/utilities/types.hpp (4)
  • all (365-369)
  • all (365-366)
  • all (376-379)
  • all (376-376)
src/core/data/ndarray/ndarray_vector.hpp (4)
  • make_array_view (214-217)
  • make_array_view (214-214)
  • make_array_view (220-223)
  • make_array_view (220-220)
src/amr/data/field/field_geometry.hpp (4)
  • box (136-179)
  • box (136-137)
  • box (198-207)
  • box (198-198)
tests/simulator/test_vtk_diagnostics.py (7)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_lib (6-9)
pyphare/pyphare/simulator/simulator.py (2)
  • startMPI (41-45)
  • reset (258-269)
tests/simulator/__init__.py (4)
  • SimulatorTest (201-267)
  • tearDown (204-205)
  • unique_diag_dir_for_test_case (250-254)
  • run (246-248)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-62)
pyphare/pyphare/pharein/simulation.py (2)
  • simulation_domain (967-968)
  • Simulation (735-1069)
pyphare/pyphare/pharein/maxwellian_fluid_model.py (1)
  • MaxwellianFluidModel (8-303)
pyphare/pyphare/pharein/electron_model.py (1)
  • ElectronModel (22-35)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
src/diagnostic/detail/vtkh5_type_writer.hpp (8)
  • diagnostic (87-92)
  • diagnostic (87-87)
  • lvl (261-266)
  • lvl (261-261)
  • ilvl (382-411)
  • ilvl (382-382)
  • boxes (57-71)
  • boxes (57-57)
src/diagnostic/detail/h5writer.hpp (4)
  • diagnostic (94-98)
  • diagnostic (94-94)
  • iLevel (210-214)
  • iLevel (210-210)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
  • write (30-55)
  • write (30-30)
src/diagnostic/diagnostics.hpp (3)
src/diagnostic/diagnostic_manager.hpp (5)
  • dict (83-83)
  • dict (86-86)
  • dict (86-86)
  • make_unique (74-80)
  • make_unique (74-75)
src/diagnostic/detail/h5writer.hpp (2)
  • make_unique (61-68)
  • make_unique (61-61)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • make_unique (67-74)
  • make_unique (67-67)
src/amr/resources_manager/amr_utils.hpp (1)
src/core/data/field/field.hpp (4)
  • args (75-81)
  • args (75-75)
  • args (83-86)
  • args (83-83)
src/diagnostic/detail/vtk_types/info.hpp (7)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
  • write (38-97)
  • write (38-38)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
  • write (30-55)
  • write (30-30)
src/diagnostic/detail/vtk_types/meta.hpp (2)
  • write (29-31)
  • write (29-29)
src/diagnostic/detail/vtk_types/particle.hpp (2)
  • write (31-33)
  • write (31-31)
src/diagnostic/detail/vtkh5_type_writer.hpp (2)
  • diagnostic (87-92)
  • diagnostic (87-87)
src/diagnostic/detail/h5writer.hpp (2)
  • diagnostic (94-98)
  • diagnostic (94-94)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
src/core/data/grid/gridlayout.hpp (4)
src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp (4)
  • field (929-956)
  • field (929-930)
  • field (958-964)
  • field (958-958)
src/core/utilities/types.hpp (2)
  • for_N_make_array (508-511)
  • for_N_make_array (508-508)
src/amr/resources_manager/amr_utils.hpp (5)
  • AMRToLocal (45-46)
  • AMRToLocal (53-54)
  • AMRToLocal (62-62)
  • AMRToLocal (77-90)
  • AMRToLocal (77-78)
src/amr/resources_manager/amr_utils.cpp (6)
  • AMRToLocal (34-40)
  • AMRToLocal (34-35)
  • AMRToLocal (47-54)
  • AMRToLocal (47-48)
  • AMRToLocal (62-66)
  • AMRToLocal (62-62)
src/core/data/ndarray/ndarray_vector.hpp (1)
src/core/utilities/types.hpp (2)
  • product (269-272)
  • product (269-269)
src/diagnostic/diagnostic_model_view.hpp (5)
src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp (10)
  • patch (146-154)
  • patch (146-146)
  • ions (407-416)
  • ions (407-407)
  • ions (420-445)
  • ions (420-420)
  • ions (447-480)
  • ions (447-447)
  • ions (492-531)
  • ions (492-493)
src/amr/messengers/refiner.hpp (8)
  • rm (276-281)
  • rm (276-276)
  • rm (284-290)
  • rm (284-285)
  • rm (293-299)
  • rm (293-293)
  • rm (302-312)
  • rm (302-303)
src/amr/resources_manager/amr_utils.hpp (2)
  • visitHierarchy (244-253)
  • visitHierarchy (244-245)
src/core/data/ions/ions.hpp (1)
  • forward_as_tuple (225-229)
src/core/data/ions/ion_population/ion_population.hpp (1)
  • forward_as_tuple (109-113)
src/diagnostic/detail/vtkh5_writer.hpp (5)
src/diagnostic/diagnostic_model_view.hpp (1)
  • dimension (30-60)
src/diagnostic/detail/vtkh5_type_writer.hpp (6)
  • level (292-328)
  • level (292-292)
  • level (330-337)
  • level (330-330)
  • diagnostic (87-92)
  • diagnostic (87-87)
src/amr/resources_manager/amr_utils.hpp (2)
  • to_string (222-227)
  • to_string (222-222)
src/hdf5/detail/h5/h5_file.hpp (4)
  • path (270-276)
  • path (270-270)
  • path (278-283)
  • path (278-278)
src/core/data/tensorfield/tensorfield.hpp (2)
  • size (208-208)
  • size (208-208)
src/diagnostic/detail/vtkh5_type_writer.hpp (5)
src/core/utilities/types.hpp (7)
  • get_env_as (253-253)
  • for_N_make_array (508-511)
  • for_N_make_array (508-508)
  • sum_from (281-289)
  • sum_from (281-281)
  • sum (275-278)
  • sum (275-275)
src/hdf5/detail/h5/h5_file.hpp (5)
  • data (66-66)
  • path (270-276)
  • path (270-270)
  • path (278-283)
  • path (278-278)
src/core/utilities/box/box.hpp (9)
  • box (53-53)
  • i (99-99)
  • i (99-99)
  • grow (91-96)
  • grow (91-91)
  • grow (328-333)
  • grow (328-328)
  • size (78-88)
  • size (78-78)
src/core/data/tensorfield/tensorfield.hpp (8)
  • i (181-181)
  • i (181-181)
  • i (182-182)
  • i (182-182)
  • size (208-208)
  • size (208-208)
  • tensor_field_dim_from_rank (17-24)
  • tensor_field_dim_from_rank (17-17)
src/core/utilities/algorithm.hpp (2)
  • convert_to_fortran_primal (149-152)
  • convert_to_fortran_primal (149-149)
src/core/utilities/box/box.hpp (2)
src/core/utilities/point/point.hpp (4)
  • i (68-68)
  • i (68-68)
  • i (69-69)
  • i (69-69)
src/core/utilities/types.hpp (7)
  • product (269-272)
  • product (269-269)
  • for_N (467-498)
  • for_N (467-467)
  • for_N (501-504)
  • for_N (501-501)
  • for_N_any (521-521)
🪛 Ruff (0.14.5)
tests/simulator/test_vtk_diagnostics.py

25-25: Unused function argument: xyz

(ARG001)


32-32: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


39-39: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


42-42: Unused function argument: xyz

(ARG001)


45-45: Unused function argument: xyz

(ARG001)


52-52: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


59-59: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


62-62: Unused function argument: xyz

(ARG001)


65-65: Unused function argument: xyz

(ARG001)


68-68: Unused function argument: xyz

(ARG001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: Analyze (cpp)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-14)
🔇 Additional comments (6)
src/amr/resources_manager/amr_utils.hpp (1)

244-252: Corrected forwarding in visitHierarchy

Switching to std::forward<Action>(action), std::forward<Args>(args)... is the right fix for propagating value categories into visitLevel; this aligns with the rest of the templated call sites. No further changes needed here.

src/diagnostic/detail/h5writer.hpp (1)

6-8: Header wiring and non-assignable H5Writer look good

The new diagnostic-type includes correctly match the typeWriters_ instantiations, and the header ordering remains sane.

Replacing the bogus deleted operator& with deleted copy/move assignment operators is the right way to make H5Writer non-assignable while keeping intent clear.

Also applies to: 12-17, 176-198

src/diagnostic/diagnostic_manager.hpp (1)

23-37: Cosmetic diagName declaration change only

Switching to std::string const diagName is a style-only change with no behavioral impact; the registration loop remains unchanged.

src/core/data/grid/gridlayoutimplyee.hpp (1)

413-537: Bx/By/Bz-to-moments stencils and updated moments↔field helpers look correct.

The new BxToMoments/ByToMoments/BzToMoments implementations cover all required dual combinations in 2D and 3D with properly normalized weights, and the updated momentsToE* / *ToMoments helpers using std::array{...} via CTAD preserve the existing stencils with cleaner syntax. The patterns are consistent with the existing Yee layout projections and previous fixes to the B→moment offsets.

Also applies to: 575-603

src/hdf5/detail/h5/h5_file.hpp (1)

95-117: HDF5 dataset helpers now handle existence and chunking robustly.

Reusing existing datasets in create_data_set/create_chunked_data_set, adding exist/checked getDataSet, and fixing the special-member declarations all look correct and improve safety without adding complexity.

Also applies to: 250-261

src/core/utilities/box/box.hpp (1)

29-31: Box iterator alias, shape/size helpers, and boxes_iterator look solid.

The added iterator alias, shape/size helpers, boxes_iterator zipper, and free grow all integrate cleanly with existing Box semantics and support the new AMR and Fortran-ordering utilities without adding complexity.

Also applies to: 99-102, 160-203, 209-259, 327-333

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/core/utilities/algorithm.hpp (1)

102-135: Fix invalid dereference of Box::shape() return value.

Line 117 dereferences lcl_box.shape() when constructing dst_view. If Box::shape() returns a value (not a pointer), this dereference is ill-formed and will cause compilation errors or undefined behavior. The make_array_view function expects a std::array<std::uint32_t, dim>-like shape.

Build an explicit shape array from the box extents:

     auto const lcl_box = layout.AMRToLocal(layout.AMRBoxFor(dst));
-    auto dst_view      = make_array_view<c_ordering>(dst.data(), *lcl_box.shape());
+
+    std::array<std::uint32_t, dim> shape{};
+    for (std::size_t d = 0; d < dim; ++d)
+        shape[d] = static_cast<std::uint32_t>(lcl_box.shape(d));
+
+    auto dst_view = make_array_view<c_ordering>(dst.data(), shape);

This same fix should also be applied if shape() is dereferenced elsewhere in the conversion functions.

🧹 Nitpick comments (2)
src/diagnostic/diagnostics.hpp (1)

28-29: Format-based writer selection cleanly introduces VTK/HDF diagnostics.

  • Reading format from the dict (defaulting to "phareh5") keeps the old HDF5 path as the default while allowing "pharevtkhdf" to select the new VTK writer.
  • The explicit runtime error for unknown formats plus the log line make configuration issues easy to diagnose and keep the resolver logic simple to extend later.

Also applies to: 53-62

src/diagnostic/detail/vtk_types/electromag.hpp (1)

12-55: Electromagnetic VTK/HDF writer integrates correctly with the existing type-writer pattern.

  • ElectromagDiagnosticWriter mirrors the other type writers: per‑diagnostic filtering on quantity, initFileLevel and initTensorFieldFileLevel<1> per level, then visitHierarchy driving writeTensorField<1> for matching electromag fields.
  • Using a no‑op compute is appropriate when the fields are already available from the model view and no extra preprocessing is required.

One tiny nit: the #endif comment guard name doesn’t match the #ifndef macro, but it’s purely cosmetic.

Also applies to: 60-62

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e4192e8 and 460ebf0.

📒 Files selected for processing (31)
  • pyphare/pyphare/pharein/__init__.py (1 hunks)
  • pyphare/pyphare/pharein/simulation.py (1 hunks)
  • src/amr/physical_models/hybrid_model.hpp (1 hunks)
  • src/amr/resources_manager/amr_utils.hpp (1 hunks)
  • src/core/data/grid/gridlayout.hpp (4 hunks)
  • src/core/data/grid/gridlayoutdefs.hpp (1 hunks)
  • src/core/data/grid/gridlayoutimplyee.hpp (27 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (5 hunks)
  • src/core/data/tensorfield/tensorfield.hpp (1 hunks)
  • src/core/utilities/algorithm.hpp (2 hunks)
  • src/core/utilities/box/box.hpp (6 hunks)
  • src/core/utilities/types.hpp (5 hunks)
  • src/diagnostic/detail/h5writer.hpp (2 hunks)
  • src/diagnostic/detail/vtk_types/electromag.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/fluid.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/info.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/meta.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/particle.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_type_writer.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_writer.hpp (1 hunks)
  • src/diagnostic/diagnostic_manager.hpp (1 hunks)
  • src/diagnostic/diagnostic_model_view.hpp (7 hunks)
  • src/diagnostic/diagnostics.hpp (2 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (2 hunks)
  • src/phare/CMakeLists.txt (0 hunks)
  • src/phare/phare_init.py (0 hunks)
  • src/phare/phare_init_small.py (0 hunks)
  • tests/simulator/CMakeLists.txt (2 hunks)
  • tests/simulator/__init__.py (1 hunks)
  • tests/simulator/refinement/test_2d_10_core.py (1 hunks)
  • tests/simulator/test_vtk_diagnostics.py (1 hunks)
💤 Files with no reviewable changes (3)
  • src/phare/CMakeLists.txt
  • src/phare/phare_init_small.py
  • src/phare/phare_init.py
🚧 Files skipped from review as they are similar to previous changes (11)
  • tests/simulator/CMakeLists.txt
  • tests/simulator/test_vtk_diagnostics.py
  • src/core/data/grid/gridlayoutdefs.hpp
  • pyphare/pyphare/pharein/init.py
  • src/diagnostic/detail/vtk_types/particle.hpp
  • src/diagnostic/detail/vtk_types/meta.hpp
  • src/diagnostic/detail/vtk_types/fluid.hpp
  • pyphare/pyphare/pharein/simulation.py
  • tests/simulator/refinement/test_2d_10_core.py
  • src/amr/physical_models/hybrid_model.hpp
  • src/diagnostic/detail/vtk_types/info.hpp
🧰 Additional context used
📓 Path-based instructions (1)
**/*.hpp

⚙️ CodeRabbit configuration file

Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Files:

  • src/amr/resources_manager/amr_utils.hpp
  • src/diagnostic/detail/vtk_types/electromag.hpp
  • src/core/data/tensorfield/tensorfield.hpp
  • src/core/data/grid/gridlayoutimplyee.hpp
  • src/diagnostic/diagnostic_manager.hpp
  • src/diagnostic/diagnostics.hpp
  • src/diagnostic/detail/h5writer.hpp
  • src/core/utilities/box/box.hpp
  • src/core/utilities/types.hpp
  • src/hdf5/detail/h5/h5_file.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
  • src/core/utilities/algorithm.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
  • src/core/data/grid/gridlayout.hpp
  • src/diagnostic/diagnostic_model_view.hpp
🧠 Learnings (11)
📓 Common learnings
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-07-26T22:04:34.160Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-10-09T08:32:15.667Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-09-05T17:02:58.784Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
📚 Learning: 2025-07-09T17:18:05.771Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/amr/CMakeLists.txt:103-105
Timestamp: 2025-07-09T17:18:05.771Z
Learning: In the PHARE project, `HighFive` is a CMake option defined in `res/cmake/options.cmake` as `option(HighFive "Build with highfive usage" ON)`, not a target that would be created by find_package(). The condition `if (HighFive)` correctly checks this option.

Applied to files:

  • src/diagnostic/detail/h5writer.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
📚 Learning: 2025-11-10T09:37:57.021Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1084
File: src/diagnostic/diagnostic_model_view.hpp:219-221
Timestamp: 2025-11-10T09:37:57.021Z
Learning: In PHARE, temporary fields like tmpField_, tmpVec_, and tmpTensor_ in src/diagnostic/diagnostic_model_view.hpp use a name-based resource allocation pattern. Fields with names "PHARE_sumField", "PHARE_sumVec", and "PHARE_sumTensor" are allocated globally elsewhere in the resources manager (e.g., in src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp), and components reference the same storage through identically-named field objects. These do not require local allocation via rm.enumerate().

Applied to files:

  • src/diagnostic/detail/h5writer.hpp
  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2025-04-17T14:41:53.643Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 998
File: src/core/utilities/point/point.hpp:195-210
Timestamp: 2025-04-17T14:41:53.643Z
Learning: In `src/core/utilities/point/point.hpp`, the `as_signed()` and `as_unsigned()` methods are intentionally designed to cause compilation errors for unsupported types (only 4-byte types are supported). This forces developers to implement proper conversions themselves when extending the functionality to new types. The comment "else no return cause not yet handled" indicates this is a deliberate design choice.

Applied to files:

  • src/core/utilities/box/box.hpp
  • src/core/utilities/types.hpp
📚 Learning: 2025-09-01T09:41:40.618Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1056
File: tests/core/numerics/interpolator/test_main.cpp:314-318
Timestamp: 2025-09-01T09:41:40.618Z
Learning: The PHARE project uses C++20, which makes the typename keyword optional for dependent types in obvious contexts. The project prefers minimal code without unnecessary keywords, so typename suggestions for dependent types should be avoided when the code compiles successfully in C++20.

Applied to files:

  • src/core/utilities/types.hpp
  • src/core/utilities/algorithm.hpp
📚 Learning: 2025-09-17T13:35:11.533Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.

Applied to files:

  • src/core/utilities/algorithm.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2024-10-22T10:05:54.014Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 0
File: :0-0
Timestamp: 2024-10-22T10:05:54.014Z
Learning: The variable `c_ordering` in `ConcreteLoadBalancerHybridStrategyNPPC<PHARE_T>::compute` is used to create an array view `lb_view` for handling load balancing data.

Applied to files:

  • src/core/utilities/algorithm.hpp
📚 Learning: 2024-09-09T13:57:02.285Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py:566-568
Timestamp: 2024-09-09T13:57:02.285Z
Learning: Avoid commenting on draft PRs for PhilipDeegan unless explicitly requested.

Applied to files:

  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/core/data/grid/gridlayout.hpp:805-821
Timestamp: 2024-10-09T08:32:15.667Z
Learning: In the `AMRToLocal` function, before converting to `uint32_t`, assert that `local >= 0` to ensure values are valid.

Applied to files:

  • src/core/data/grid/gridlayout.hpp
📚 Learning: 2025-09-17T13:50:16.038Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/tensorfield/tensor_field_data_factory.hpp:112-112
Timestamp: 2025-09-17T13:50:16.038Z
Learning: PhilipDeegan indicated that getSizeOfMemory returning a placeholder value of 1 in TensorFieldDataFactory is acceptable for their use case, suggesting it may not be critical for PHARE's memory management needs.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
🔇 Additional comments (15)
src/amr/resources_manager/amr_utils.hpp (1)

243-252: Corrected perfect-forwarding of variadic arguments

Using std::forward<Args>(args)... here is the correct pattern for forwarding a parameter pack into visitLevel; the previous std::forward<Args...>(args...) form would be ill-formed and break perfect forwarding. No further changes needed around this call site.

src/core/data/grid/gridlayoutimplyee.hpp (1)

413-603: Yee B↔moment stencils and CTAD refactor look consistent.

  • The new BxToMoments/ByToMoments/BzToMoments implementations correctly cover all dual directions: 2 points in 1D, 2 points for single-dual 2D cases, and 4-point averages for 3D where two directions are dual, with weights summing to 1 in each stencil and offsets aligned with the centering comments.
  • The switch from std::array<WeightPoint<dimension>, N>{...} to std::array{...} is a pure CTAD cleanup and keeps the existing interpolation behavior unchanged across momentsTo*, *ToMoments, and the various B↔E mappings.

Also applies to: 784-924

src/hdf5/detail/h5/h5_file.hpp (2)

95-117: Chunked dataset helper and parent-group handling are sound.

create_data_set and create_chunked_data_set now both:

  • Reuse an existing dataset when exist(path) is true, and
  • Call createGroupsToDataSet(path) before creation, ensuring parent groups exist.

This aligns the chunked path with the non‑chunked API and avoids group-creation failures while keeping the interface compact.


250-261: Existence wrapper and stricter ownership semantics are appropriate.

  • exist(std::string const&) const and getDataSet(std::string const&) add a clear, checked access path; throwing on missing datasets avoids the previous release‑build assert hole.
  • Deleting copy and move operations for HighFiveFile is a good safeguard around the underlying HDF5 handle and simplifies lifetime reasoning.
src/core/utilities/box/box.hpp (2)

29-32: Box iterator alias and shape/size helpers are clear and idiomatic.

  • Exposing using iterator = box_iterator<Type, dim>; aligns Box with standard container conventions and enables the new higher‑level iterators.
  • shape(i), shape(), and size() make the “inclusive upper bound” convention explicit and keep size() readable via core::product(shape(), std::size_t{1}).
  • The free grow(Box, size) thin wrapper is a useful utility without adding complexity.

Also applies to: 99-102, 327-333


160-203: box_iterator and boxes_iterator semantics look correct for multi-box traversal.

  • box_iterator::operator!= now checks both box_ and index_, which matches the sentinel construction in Box::end() and gives expected STL-style loop semantics.
  • boxes_iterator<Boxes...>:
    • Stores the boxes by value in a tuple and uses Boxes::iterator to derive the iterator tuple type.
    • iterator::operator++ advances all underlying iterators, and operator!= uses for_N_any so iteration stops when any component reaches its own end().
    • operator* aggregates *it per box via for_N, which is a compact way to yield per-box indices in lockstep.

Assuming for_N/for_N_any behave as in the rest of the codebase (tuple/any-style reducers), this design is consistent and efficient.

Also applies to: 209-259

src/diagnostic/diagnostic_manager.hpp (1)

31-37: Const placement change for diagName is harmless.

Using std::string const diagName is equivalent to the previous declaration and keeps the loop logic unchanged.

src/core/data/tensorfield/tensorfield.hpp (1)

206-209: Qualifier reordering on size() has no behavioral effect.

Swapping constexpr static to static constexpr is purely cosmetic; the function remains a constexpr static size helper returning N.

src/diagnostic/detail/h5writer.hpp (1)

6-7: LGTM! Include reorganization and operator deletion fix are correct.

The include reordering and additions support the new VTK-HDF5 writer architecture, and fixing the operator deletions from operator& (address-of) to operator= (assignment) is the correct approach for a non-copyable, non-movable class.

Also applies to: 12-17, 196-197

src/core/utilities/types.hpp (1)

226-235: LGTM! New utility functions are well-designed.

The new functions provide clean interfaces:

  • from_string<T> throws on parse failure, avoiding silent errors
  • get_env_as<T> provides type-safe environment variable access with defaults
  • for_N_all and for_N_any are convenient wrappers over the existing for_N infrastructure

Also applies to: 252-258, 514-524

src/core/data/grid/gridlayout.hpp (1)

1027-1045: LGTM! Grid layout extensions support primal projections.

The new BxToMoments, ByToMoments, and BzToMoments accessors, along with the updated AMRBoxFor/AMRGhostBoxFor methods and amr_lcl_idx helpers, provide the necessary infrastructure for the VTK-HDF5 primal conversions introduced elsewhere in the PR.

Also applies to: 1180-1194, 1220-1226

src/diagnostic/diagnostic_model_view.hpp (1)

37-37: LGTM! Temporary storage and helper accessors support VTK-HDF5 diagnostics.

The new Field alias, updated visitHierarchy signature, and temporary storage accessors (tmpField(), tmpVecField(), tmpTensorField()) provide the necessary infrastructure for primal conversion and VTK-HDF5 output. The temporary fields use name-based resource allocation patterns that are managed globally.

Based on learnings

Also applies to: 96-98, 145-172, 219-221

src/core/data/ndarray/ndarray_vector.hpp (1)

19-70: LGTM! NdArrayViewer refactoring and index type fix are correct.

The template signature simplification (removing the DataType parameter) and the fix to use std::uint32_t for indices (instead of the previous 16-bit type) correctly addresses the wraparound concern for large grids.

src/diagnostic/detail/vtkh5_writer.hpp (1)

52-74: LGTM! VTK-HDF5 writer implementation is well-structured.

The new H5Writer<ModelView> class correctly implements:

  • Non-copyable/non-movable semantics via deleted assignment operators
  • Per-diagnostic file management with proper flag handling (including reset to READ_WRITE after the first dump to prevent truncation)
  • Level-based dump control via dump_level
  • Type-writer registry for per-diagnostic-type output

Also applies to: 77-186

src/diagnostic/detail/vtkh5_type_writer.hpp (1)

1-348: LGTM! VTK-HDF5 type writer base provides comprehensive infrastructure.

The H5TypeWriter<Writer> base class and its nested helper structures (VTKFileFieldInfo, VTKFileWriter, etc.) provide well-organized support for:

  • Per-level dataset initialization and resizing
  • Field and tensor field writing with primal conversion
  • AMR box and offset management
  • Configurable chunk sizes via environment variable

The X_TIMES multiplier logic for lower-dimensional data replication in 3D views is clearly documented.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
src/core/utilities/algorithm.hpp (1)

102-135: Fix the shape construction for make_array_view calls.

Line 117 dereferences lcl_box.shape(), but Box::shape() now returns a value (not a pointer), so *lcl_box.shape() is ill-formed. Additionally, make_array_view expects a std::array<std::uint32_t, dim>.

Build an explicit shape array from the box instead:

 auto const lcl_box = layout.AMRToLocal(layout.AMRBoxFor(dst));
-auto dst_view      = make_array_view<c_ordering>(dst.data(), *lcl_box.shape());
+
+std::array<std::uint32_t, dim> shape{};
+for (std::size_t d = 0; d < dim; ++d)
+    shape[d] = static_cast<std::uint32_t>(lcl_box.shape()[d]);
+
+auto dst_view = make_array_view<c_ordering>(dst.data(), shape);
src/diagnostic/detail/vtk_types/particle.hpp (1)

12-26: Particle VTK diagnostics never write anything (empty write)

ParticlesDiagnosticWriter::write is empty, so selecting this backend for particle diagnostics will silently generate VTKHDF files with no particle data. That’s a functional break compared to the existing HDF writer.

Either implement the actual write path (mirroring ParticlesDiagnosticWriter in src/diagnostic/detail/types/particle.hpp) or explicitly disable/register particle diagnostics as unsupported for pharevtkhdf so this can’t be selected by configuration.

Also applies to: 30-33

🧹 Nitpick comments (5)
src/diagnostic/detail/vtk_types/fluid.hpp (1)

1-2: Align #endif comment with header guard name

The guard macro is PHARE_DIAGNOSTIC_DETAIL_VTK_TYPES_FLUID_HPP but the trailing #endif comment uses ...FLUID_H. For consistency and grep-ability, consider updating the comment to match the macro name.

Also applies to: 100-104

src/diagnostic/detail/vtkh5_type_writer.hpp (1)

162-174: Avoid copying the Fortran-primal buffers returned by convert_to_fortran_primal

convert_to_fortran_primal returns a reference to the temporary workspace, but here it’s bound by value:

auto const frimal = core::convert_to_fortran_primal(...);

This copies the entire field/tensor before every write. You can keep the same semantics and avoid the copy by binding a const reference instead:

-        auto const frimal = core::convert_to_fortran_primal(
+        auto const& frimal = core::convert_to_fortran_primal(
             typewriter->h5Writer_.modelView().tmpField(), field, layout);
...
-        auto const frimal = core::convert_to_fortran_primal(
+        auto const& frimal = core::convert_to_fortran_primal(
             typewriter->h5Writer_.modelView().template tmpTensorField<rank>(), tf, layout);

This should reduce memory traffic noticeably on large grids without changing behavior.

Also applies to: 176-192

src/diagnostic/detail/vtk_types/particle.hpp (1)

7-7: Tidy up comment and header-guard comment for particles header

  • The comment // not sure this makes sense is vague and likely stale; consider either removing it or replacing with a concrete TODO if there’s a known limitation.
  • The guard macro is PHARE_DIAGNOSTIC_DETAIL_VTK_TYPES_PARTICLE_HPP but the #endif comment uses PHARE_DIAGNOSTIC_DETAIL_TYPES_PARTICLE_H. Aligning the comment with the macro name keeps headers easier to navigate and grep. Based on learnings

Also applies to: 1-2, 37-39

src/diagnostic/detail/vtk_types/electromag.hpp (1)

1-2: Normalize header-guard comment for electromag header

Similar to the other vtk type headers, the guard macro (PHARE_DIAGNOSTIC_DETAIL_VTK_TYPES_ELECTROMAG_HPP) and the trailing #endif comment (...TYPES_ELECTROMAG_H) don’t match. Consider updating the comment to mirror the macro for consistency across headers. Based on learnings

Also applies to: 60-62

tests/simulator/test_vtk_diagnostics.py (1)

119-128: Avoid sharing a single mutable simInput across parameterized tests

permute updates a single dic with simArgs.copy() and then reuses that same dict as simInput for all (ndim, interp) combinations. This is harmless with the current single (2, 1) combo, but if you uncomment more dimensions/orders, later tests will see state mutated by earlier tests (e.g., cells becoming nested lists).

Consider returning an independent simInput per case, e.g.:

-def permute(dic):
-    dic.update(simArgs.copy())
-    return [
-        dict(
-            ndim=ndim,
-            interp=interp_order,
-            simInput=dic,
-        )
-        for ndim, interp_order in itertools.product(ndims, interp_orders)
-    ]
+def permute(overrides):
+    return [
+        dict(
+            ndim=ndim,
+            interp=interp_order,
+            simInput={**simArgs, **overrides},
+        )
+        for ndim, interp_order in itertools.product(ndims, interp_orders)
+    ]

This keeps each test case isolated and makes it safe to expand ndims/interp_orders.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 460ebf0 and 4fb69ed.

📒 Files selected for processing (31)
  • pyphare/pyphare/pharein/__init__.py (1 hunks)
  • pyphare/pyphare/pharein/simulation.py (1 hunks)
  • src/amr/physical_models/hybrid_model.hpp (1 hunks)
  • src/amr/resources_manager/amr_utils.hpp (1 hunks)
  • src/core/data/grid/gridlayout.hpp (4 hunks)
  • src/core/data/grid/gridlayoutdefs.hpp (1 hunks)
  • src/core/data/grid/gridlayoutimplyee.hpp (27 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (5 hunks)
  • src/core/data/tensorfield/tensorfield.hpp (1 hunks)
  • src/core/utilities/algorithm.hpp (2 hunks)
  • src/core/utilities/box/box.hpp (6 hunks)
  • src/core/utilities/types.hpp (5 hunks)
  • src/diagnostic/detail/h5writer.hpp (2 hunks)
  • src/diagnostic/detail/vtk_types/electromag.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/fluid.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/info.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/meta.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/particle.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_type_writer.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_writer.hpp (1 hunks)
  • src/diagnostic/diagnostic_manager.hpp (1 hunks)
  • src/diagnostic/diagnostic_model_view.hpp (7 hunks)
  • src/diagnostic/diagnostics.hpp (2 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (3 hunks)
  • src/phare/CMakeLists.txt (0 hunks)
  • src/phare/phare_init.py (0 hunks)
  • src/phare/phare_init_small.py (0 hunks)
  • tests/simulator/CMakeLists.txt (2 hunks)
  • tests/simulator/__init__.py (1 hunks)
  • tests/simulator/refinement/test_2d_10_core.py (1 hunks)
  • tests/simulator/test_vtk_diagnostics.py (1 hunks)
💤 Files with no reviewable changes (3)
  • src/phare/CMakeLists.txt
  • src/phare/phare_init_small.py
  • src/phare/phare_init.py
🚧 Files skipped from review as they are similar to previous changes (12)
  • pyphare/pyphare/pharein/simulation.py
  • src/diagnostic/diagnostic_manager.hpp
  • src/diagnostic/detail/vtk_types/info.hpp
  • tests/simulator/init.py
  • pyphare/pyphare/pharein/init.py
  • src/amr/physical_models/hybrid_model.hpp
  • src/diagnostic/detail/vtk_types/meta.hpp
  • tests/simulator/refinement/test_2d_10_core.py
  • src/core/utilities/box/box.hpp
  • src/hdf5/detail/h5/h5_file.hpp
  • src/core/data/grid/gridlayoutdefs.hpp
  • src/amr/resources_manager/amr_utils.hpp
🧰 Additional context used
📓 Path-based instructions (1)
**/*.hpp

⚙️ CodeRabbit configuration file

Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Files:

  • src/core/data/tensorfield/tensorfield.hpp
  • src/core/data/grid/gridlayoutimplyee.hpp
  • src/diagnostic/detail/vtk_types/electromag.hpp
  • src/diagnostic/diagnostics.hpp
  • src/core/utilities/types.hpp
  • src/diagnostic/detail/vtk_types/particle.hpp
  • src/diagnostic/detail/h5writer.hpp
  • src/diagnostic/detail/vtk_types/fluid.hpp
  • src/diagnostic/diagnostic_model_view.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
  • src/core/data/grid/gridlayout.hpp
  • src/core/utilities/algorithm.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
🧠 Learnings (12)
📓 Common learnings
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-07-26T22:04:34.160Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-10-09T08:32:15.667Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-09-05T17:02:58.784Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
📚 Learning: 2025-02-07T14:35:14.630Z
Learnt from: nicolasaunai
Repo: PHAREHUB/PHARE PR: 591
File: res/cmake/options.cmake:73-75
Timestamp: 2025-02-07T14:35:14.630Z
Learning: In CMake configuration for PHARE, `lowResourceTests` and `highResourceTests` options must be mutually exclusive and cannot be enabled simultaneously.

Applied to files:

  • tests/simulator/CMakeLists.txt
📚 Learning: 2025-07-09T17:18:05.771Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/amr/CMakeLists.txt:103-105
Timestamp: 2025-07-09T17:18:05.771Z
Learning: In the PHARE project, `HighFive` is a CMake option defined in `res/cmake/options.cmake` as `option(HighFive "Build with highfive usage" ON)`, not a target that would be created by find_package(). The condition `if (HighFive)` correctly checks this option.

Applied to files:

  • tests/simulator/CMakeLists.txt
  • src/diagnostic/detail/h5writer.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
📚 Learning: 2025-09-01T09:41:40.618Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1056
File: tests/core/numerics/interpolator/test_main.cpp:314-318
Timestamp: 2025-09-01T09:41:40.618Z
Learning: The PHARE project uses C++20, which makes the typename keyword optional for dependent types in obvious contexts. The project prefers minimal code without unnecessary keywords, so typename suggestions for dependent types should be avoided when the code compiles successfully in C++20.

Applied to files:

  • src/core/utilities/types.hpp
  • src/core/utilities/algorithm.hpp
📚 Learning: 2025-09-17T13:35:11.533Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.

Applied to files:

  • src/core/utilities/types.hpp
  • src/diagnostic/diagnostic_model_view.hpp
  • src/core/utilities/algorithm.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
📚 Learning: 2025-04-17T14:41:53.643Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 998
File: src/core/utilities/point/point.hpp:195-210
Timestamp: 2025-04-17T14:41:53.643Z
Learning: In `src/core/utilities/point/point.hpp`, the `as_signed()` and `as_unsigned()` methods are intentionally designed to cause compilation errors for unsupported types (only 4-byte types are supported). This forces developers to implement proper conversions themselves when extending the functionality to new types. The comment "else no return cause not yet handled" indicates this is a deliberate design choice.

Applied to files:

  • src/core/utilities/types.hpp
📚 Learning: 2025-11-10T09:37:57.021Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1084
File: src/diagnostic/diagnostic_model_view.hpp:219-221
Timestamp: 2025-11-10T09:37:57.021Z
Learning: In PHARE, temporary fields like tmpField_, tmpVec_, and tmpTensor_ in src/diagnostic/diagnostic_model_view.hpp use a name-based resource allocation pattern. Fields with names "PHARE_sumField", "PHARE_sumVec", and "PHARE_sumTensor" are allocated globally elsewhere in the resources manager (e.g., in src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp), and components reference the same storage through identically-named field objects. These do not require local allocation via rm.enumerate().

Applied to files:

  • src/diagnostic/detail/h5writer.hpp
  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2025-09-17T13:50:16.038Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/tensorfield/tensor_field_data_factory.hpp:112-112
Timestamp: 2025-09-17T13:50:16.038Z
Learning: PhilipDeegan indicated that getSizeOfMemory returning a placeholder value of 1 in TensorFieldDataFactory is acceptable for their use case, suggesting it may not be critical for PHARE's memory management needs.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2024-09-09T13:57:02.285Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py:566-568
Timestamp: 2024-09-09T13:57:02.285Z
Learning: Avoid commenting on draft PRs for PhilipDeegan unless explicitly requested.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/core/data/grid/gridlayout.hpp:805-821
Timestamp: 2024-10-09T08:32:15.667Z
Learning: In the `AMRToLocal` function, before converting to `uint32_t`, assert that `local >= 0` to ensure values are valid.

Applied to files:

  • src/core/data/grid/gridlayout.hpp
📚 Learning: 2024-10-22T10:05:54.014Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 0
File: :0-0
Timestamp: 2024-10-22T10:05:54.014Z
Learning: The variable `c_ordering` in `ConcreteLoadBalancerHybridStrategyNPPC<PHARE_T>::compute` is used to create an array view `lb_view` for handling load balancing data.

Applied to files:

  • src/core/utilities/algorithm.hpp
🧬 Code graph analysis (11)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
  • write (38-97)
  • write (38-38)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtkh5_type_writer.hpp (8)
  • diagnostic (74-79)
  • diagnostic (74-74)
  • lvl (155-160)
  • lvl (155-155)
  • ilvl (262-291)
  • ilvl (262-262)
  • boxes (51-65)
  • boxes (51-51)
src/diagnostic/diagnostics.hpp (3)
src/diagnostic/diagnostic_manager.hpp (5)
  • dict (83-83)
  • dict (86-86)
  • dict (86-86)
  • make_unique (74-80)
  • make_unique (74-75)
src/diagnostic/detail/h5writer.hpp (2)
  • make_unique (61-68)
  • make_unique (61-61)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • make_unique (67-74)
  • make_unique (67-67)
src/diagnostic/detail/vtk_types/particle.hpp (7)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
  • write (30-55)
  • write (30-30)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
  • write (38-97)
  • write (38-38)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtk_types/info.hpp (2)
  • write (31-33)
  • write (31-31)
src/diagnostic/detail/vtk_types/meta.hpp (2)
  • write (29-31)
  • write (29-29)
src/diagnostic/detail/h5writer.hpp (2)
  • diagnostic (94-98)
  • diagnostic (94-94)
src/diagnostic/detail/vtkh5_type_writer.hpp (2)
  • diagnostic (74-79)
  • diagnostic (74-74)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
src/diagnostic/detail/vtk_types/fluid.hpp (3)
src/diagnostic/detail/vtkh5_type_writer.hpp (8)
  • diagnostic (74-79)
  • diagnostic (74-74)
  • lvl (155-160)
  • lvl (155-155)
  • ilvl (262-291)
  • ilvl (262-262)
  • boxes (51-65)
  • boxes (51-51)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
  • write (30-55)
  • write (30-30)
tests/simulator/test_vtk_diagnostics.py (6)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_lib (6-9)
pyphare/pyphare/simulator/simulator.py (2)
  • startMPI (41-45)
  • reset (258-269)
tests/simulator/__init__.py (3)
  • SimulatorTest (201-267)
  • tearDown (204-205)
  • unique_diag_dir_for_test_case (250-254)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-62)
pyphare/pyphare/pharein/simulation.py (2)
  • simulation_domain (967-968)
  • Simulation (735-1069)
pyphare/pyphare/pharein/maxwellian_fluid_model.py (1)
  • MaxwellianFluidModel (8-303)
src/diagnostic/diagnostic_model_view.hpp (4)
src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp (10)
  • patch (146-154)
  • patch (146-146)
  • ions (407-416)
  • ions (407-407)
  • ions (420-445)
  • ions (420-420)
  • ions (447-480)
  • ions (447-447)
  • ions (492-531)
  • ions (492-493)
src/amr/resources_manager/amr_utils.hpp (2)
  • visitHierarchy (244-253)
  • visitHierarchy (244-245)
src/core/data/ions/ion_population/ion_population.hpp (1)
  • forward_as_tuple (109-113)
src/core/data/ions/ions.hpp (1)
  • forward_as_tuple (225-229)
src/core/data/ndarray/ndarray_vector.hpp (1)
src/core/utilities/types.hpp (2)
  • product (269-272)
  • product (269-269)
src/core/data/grid/gridlayout.hpp (3)
src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp (4)
  • field (929-956)
  • field (929-930)
  • field (958-964)
  • field (958-958)
src/core/utilities/types.hpp (2)
  • for_N_make_array (508-511)
  • for_N_make_array (508-508)
src/amr/resources_manager/amr_utils.cpp (6)
  • AMRToLocal (34-40)
  • AMRToLocal (34-35)
  • AMRToLocal (47-54)
  • AMRToLocal (47-48)
  • AMRToLocal (62-66)
  • AMRToLocal (62-62)
src/core/utilities/algorithm.hpp (3)
src/core/utilities/box/box.hpp (4)
  • dim (109-125)
  • dim (127-142)
  • box (53-53)
  • boxes_iterator (214-217)
src/core/utilities/types.hpp (4)
  • all (365-369)
  • all (365-366)
  • all (376-379)
  • all (376-376)
src/core/data/ndarray/ndarray_vector.hpp (4)
  • make_array_view (214-217)
  • make_array_view (214-214)
  • make_array_view (220-223)
  • make_array_view (220-220)
src/diagnostic/detail/vtkh5_writer.hpp (6)
src/diagnostic/diagnostic_model_view.hpp (1)
  • dimension (30-60)
src/diagnostic/detail/h5writer.hpp (14)
  • H5Writer (51-56)
  • H5Writer (58-58)
  • H5Writer (194-194)
  • H5Writer (195-195)
  • make_unique (61-68)
  • make_unique (61-61)
  • timestamp (101-104)
  • timestamp (101-101)
  • diagnostic (94-98)
  • diagnostic (94-94)
  • modelView_ (160-160)
  • timestamp_ (161-161)
  • dump (224-250)
  • dump (224-225)
src/diagnostic/diagnostic_manager.hpp (7)
  • dict (83-83)
  • dict (86-86)
  • dict (86-86)
  • make_unique (74-80)
  • make_unique (74-75)
  • dump (172-202)
  • dump (172-172)
src/diagnostic/diagnostics.hpp (2)
  • make_unique (50-65)
  • make_unique (50-51)
src/diagnostic/detail/vtkh5_type_writer.hpp (2)
  • diagnostic (74-79)
  • diagnostic (74-74)
src/hdf5/detail/h5/h5_file.hpp (4)
  • path (295-301)
  • path (295-295)
  • path (303-308)
  • path (303-303)
src/diagnostic/detail/vtkh5_type_writer.hpp (4)
src/core/utilities/box/box.hpp (9)
  • box (53-53)
  • i (99-99)
  • i (99-99)
  • grow (91-96)
  • grow (91-91)
  • grow (328-333)
  • grow (328-328)
  • size (78-88)
  • size (78-78)
src/core/data/tensorfield/tensorfield.hpp (8)
  • i (181-181)
  • i (181-181)
  • i (182-182)
  • i (182-182)
  • size (208-208)
  • size (208-208)
  • tensor_field_dim_from_rank (17-24)
  • tensor_field_dim_from_rank (17-17)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
src/core/utilities/algorithm.hpp (4)
  • convert_to_fortran_primal (103-135)
  • convert_to_fortran_primal (103-107)
  • convert_to_fortran_primal (138-147)
  • convert_to_fortran_primal (138-142)
🪛 Ruff (0.14.5)
tests/simulator/test_vtk_diagnostics.py

25-25: Unused function argument: xyz

(ARG001)


32-32: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


39-39: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


42-42: Unused function argument: xyz

(ARG001)


45-45: Unused function argument: xyz

(ARG001)


52-52: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


59-59: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


62-62: Unused function argument: xyz

(ARG001)


65-65: Unused function argument: xyz

(ARG001)


68-68: Unused function argument: xyz

(ARG001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-14)
  • GitHub Check: Analyze (cpp)
🔇 Additional comments (22)
src/core/data/tensorfield/tensorfield.hpp (1)

208-208: LGTM!

The reordering of static constexpr follows the conventional C++ style where storage class specifiers precede type specifiers. No functional change.

src/core/utilities/types.hpp (3)

1-2: LGTM!

The header guard rename follows the preferred pattern for this project.

Based on learnings


226-258: LGTM!

The utility functions are well-designed:

  • from_string provides proper error handling by throwing on parse failure
  • get_env_as safely wraps environment variable parsing with a default fallback

These complement the existing get_env functions nicely.


514-518: LGTM!

The for_N_all helper correctly composes for_N with the all() predicate to provide a clean API for all/any evaluations over generated sequences.

src/core/data/ndarray/ndarray_vector.hpp (1)

19-70: LGTM!

The refactoring to remove the DataType template parameter and use auto makes NdArrayViewer more flexible and generic. The index type (std::uint32_t) is correctly sized to handle large grids without overflow. The C-ordering and Fortran-ordering index calculations are correct.

src/core/utilities/algorithm.hpp (2)

75-100: LGTM!

The convert_to_primal function correctly handles the projection of magnetic and electric field components to primal locations using the layout's projection methods.


137-147: LGTM!

The TensorField overload correctly applies the Field conversion to each component.

src/core/data/grid/gridlayoutimplyee.hpp (1)

511-604: LGTM!

The three new B-to-moments projection functions are correctly implemented:

  • Each properly handles the dual→primal conversion for their respective components
  • 3D implementations correctly use all four dual combinations with equal 0.25 weights
  • The dimension-specific implementations are appropriate for 1D/2D/3D
src/core/data/grid/gridlayout.hpp (3)

1027-1045: LGTM!

The three new accessor functions correctly delegate to the corresponding GridLayoutImpl methods for B-to-moments projections.


1180-1194: LGTM!

The naming clarification is helpful:

  • AMRBoxFor returns the AMR box for the field (without ghosts)
  • AMRGhostBoxFor returns the ghost box by growing the AMR box

The logic correctly grows the box by nbrGhosts to create the ghost box (no unsigned wraparound issue since we're adding, not subtracting).


1220-1226: LGTM!

The new iterator helpers provide clean APIs for common iteration patterns over AMR/local index pairs. The boxes_iterator usage correctly pairs AMR indices with their corresponding local indices.

src/diagnostic/detail/vtk_types/fluid.hpp (1)

37-97: Fluid VTK writer wiring looks consistent with existing H5 logic

Per-quantity matching, per-level init, and hierarchy traversal all line up with the existing fluid diagnostics; ions and per-pop paths look correct and you only allocate datasets for the active quantity. I don’t see correctness issues here.

tests/simulator/CMakeLists.txt (1)

16-21: VTK diagnostics and timestamp tests are wired appropriately

Adding vtk_diagnostics and re-enabling test_diagnostic_timestamps under the HighFive guard matches how other diagnostic tests are handled and keeps the config coherent. No issues from a CMake/test orchestration standpoint.

Also applies to: 33-33

src/diagnostic/detail/vtk_types/electromag.hpp (1)

29-55: Electromag writer wiring and level handling look correct

The electromag writer follows the same pattern as the fluid writer: you only init datasets and write when diagnostic.quantity matches a registered electromag field, and you correctly use initTensorFieldFileLevel<1> with writeTensorField<1>. I don’t see correctness or performance issues here.

src/diagnostic/diagnostics.hpp (1)

55-61: Format-based diagnostics backend selection is clear and safe

Using cppdict::get_value with default "phareh5" and explicit branches for "phareh5" vs "pharevtkhdf" (with a runtime error on unknown formats) cleanly wires the new backend without changing the public factory API. This looks good.

src/diagnostic/detail/h5writer.hpp (1)

6-17: H5 writer dependency wiring and ownership semantics look solid

Bringing in mpi_utils and the per-type writer headers aligns with the actual usage (MPI reductions and typeWriters_), and switching to deleted copy/move assignment operators is the right way to make H5Writer non-assignable while keeping construction via make_unique. The typeWriters_ map initialization with shared_ptr-backed writers is consistent with the existing H5TypeWriter pattern.

Also applies to: 176-182, 194-197

tests/simulator/test_vtk_diagnostics.py (2)

24-103: Model setup is compatible with MaxwellianFluidModel expectations

The setup_model helpers use *xyz signatures and density/velocity/thermal closures in a way that matches the MaxwellianFluidModel defaulter pattern and should exercise both field and population diagnostics meaningfully.


131-159: Test lifecycle integration with Simulator looks consistent

VTKDiagnosticsTest correctly resets the Simulator and PHARE global state in tearDown while still calling super().tearDown(), and test_dump_diags uses unique_diag_dir_for_test_case plus dump_all_diags to exercise the new "pharevtkhdf" format end-to-end. This wiring matches the existing simulator test harness.

src/diagnostic/diagnostic_model_view.hpp (2)

62-81: Momentum tensor staging via tmpTensor_ is symmetric and safe

The updated fillPopMomTensor correctly mirrors the messenger pattern: enumerate patches with the shared "PHARE_sumTensor" buffer, copy momentumTensor into tmpTensor_, run the MT schedule, then copy back. This keeps the temporary storage localized while reusing the global buffer via the known name-based allocation pattern.


145-172: New local box helper and tmp-field accessors fit existing resource patterns

localLevelBoxes offers a concise way to gather AMRBoxes using visitHierarchy, and the tmp accessors plus getCompileTimeResourcesViewList expose tmpField_, tmpVec_, and tmpTensor_ consistently with other components’ getCompileTimeResourcesViewList APIs. Using the "PHARE_sumField", "PHARE_sumVec", and "PHARE_sumTensor" names matches the global resource-manager allocation pattern noted earlier and avoids duplicate allocation.
Based on learnings

Also applies to: 219-221

src/diagnostic/detail/vtkh5_writer.hpp (2)

171-186: VTK-HDF dump lifecycle matches the intended file-flag behavior

The dump implementation correctly initializes per-diagnostic file_flags from this->flags, delegates to type-specific writers, and then downgrades flags to READ_WRITE to avoid truncating on subsequent dumps. This mirrors the fixed behavior in the existing HDF writer.


40-47: Add typename for dependent nested types in template aliases

In H5Writer, ModelView is a template parameter, so its nested types are dependent and require typename:

-    using ModelView  = _ModelView;
-    using This       = H5Writer<ModelView>;
-    using GridLayout = ModelView::GridLayout;
-    using Attributes = ModelView::PatchProperties;
+    using ModelView  = _ModelView;
+    using This       = H5Writer<ModelView>;
+    using GridLayout = typename ModelView::GridLayout;
+    using Attributes = typename ModelView::PatchProperties;

Without typename, this is ill-formed in standard C++ and will typically fail to compile once this writer is instantiated.

⛔ Skipped due to learnings
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1056
File: tests/core/numerics/interpolator/test_main.cpp:314-318
Timestamp: 2025-09-01T09:41:40.618Z
Learning: The PHARE project uses C++20, which makes the typename keyword optional for dependent types in obvious contexts. The project prefers minimal code without unnecessary keywords, so typename suggestions for dependent types should be avoided when the code compiles successfully in C++20.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/core/utilities/algorithm.hpp (1)

102-135: Fix incorrect dereference of Box::shape().

Line 117 dereferences lcl_box.shape() with *, but Box::shape() returns a value (Point), not a pointer. The past review comment has already flagged this critical issue and provided a detailed fix.

🧹 Nitpick comments (5)
src/diagnostic/detail/vtk_types/electromag.hpp (1)

1-2: Align header guard closing comment with macro name (cosmetic)

The header guard macro is PHARE_DIAGNOSTIC_DETAIL_VTK_TYPES_ELECTROMAG_HPP, but the closing comment uses a different name. Consider updating the #endif comment to match the macro for consistency with your usual guard style.
Based on learnings

Also applies to: 60-62

tests/simulator/test_vtk_diagnostics.py (1)

144-159: Register VTK diagnostic output dirs for cleanup

test_dump_diags writes diagnostics under local_out but never calls self.register_diag_dir_for_cleanup(local_out), so those directories will persist between runs even though SimulatorTest.tearDown() is wired to clean registered paths.

Consider registering local_out after it’s computed:

         local_out = self.unique_diag_dir_for_test_case(f"{out}/test_vtk", ndim, interp)
         simInput["diag_options"]["options"]["dir"] = local_out
         simInput["diag_options"]["format"] = "pharevtkhdf"
+        self.register_diag_dir_for_cleanup(local_out)

This keeps the filesystem clean while preserving the existing SimulatorTest cleanup behaviour.

src/hdf5/detail/h5/h5_file.hpp (2)

19-21: Chunked/resizable dataset helpers are well-factored; consider guarding CHUNK_SIZE

Using detail::CHUNK_SIZE plus create_resizable_{1d,2d}_data_set cleanly encapsulates the common “0‑length, UNLIMITED, chunked” HDF5 pattern and keeps call sites simple.

You might optionally add a small guard to ensure PHARE_H5_CHUNK_SIZE doesn’t resolve to 0 (or some obviously invalid value) before using it in the chunk vector, e.g. clamp to at least 1 or throw early; otherwise a misconfigured env var could fail at dataset creation time.

Also applies to: 127-141


116-125: Consider avoiding C++20 abbreviated template parameters in create_chunked_data_set

create_chunked_data_set currently uses auto function parameters, which rely on C++20 abbreviated function templates. If the project still targets C++17, this will not compile on stricter toolchains.

You can keep the flexibility while staying explicit:

-    template<typename Type>
-    auto create_chunked_data_set(auto const& path, auto const chunk, auto const& dataspace)
+    template<typename Type>
+    auto create_chunked_data_set(std::string const& path,
+                                 std::vector<hsize_t> const& chunk,
+                                 HighFive::DataSpace const& dataspace)

(adapt the types if call sites use slightly different but compatible containers).

This also makes the intended usage clearer at the interface.

src/diagnostic/detail/vtkh5_type_writer.hpp (1)

49-49: Document X_TIMES multiplier rationale.

The X_TIMES constant duplicates data in lower dimensions (2D: ×2, 1D: ×4) to fit a 3D view, but the comment at lines 46-48 is brief. Consider adding a reference to the VTK-HDF5 spec or ParaView requirements explaining why this duplication is necessary for correct rendering.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4fb69ed and 7395d74.

📒 Files selected for processing (31)
  • pyphare/pyphare/pharein/__init__.py (1 hunks)
  • pyphare/pyphare/pharein/simulation.py (1 hunks)
  • src/amr/physical_models/hybrid_model.hpp (1 hunks)
  • src/amr/resources_manager/amr_utils.hpp (1 hunks)
  • src/core/data/grid/gridlayout.hpp (4 hunks)
  • src/core/data/grid/gridlayoutdefs.hpp (1 hunks)
  • src/core/data/grid/gridlayoutimplyee.hpp (27 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (5 hunks)
  • src/core/data/tensorfield/tensorfield.hpp (1 hunks)
  • src/core/utilities/algorithm.hpp (2 hunks)
  • src/core/utilities/box/box.hpp (6 hunks)
  • src/core/utilities/types.hpp (5 hunks)
  • src/diagnostic/detail/h5writer.hpp (2 hunks)
  • src/diagnostic/detail/vtk_types/electromag.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/fluid.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/info.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/meta.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/particle.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_type_writer.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_writer.hpp (1 hunks)
  • src/diagnostic/diagnostic_manager.hpp (1 hunks)
  • src/diagnostic/diagnostic_model_view.hpp (7 hunks)
  • src/diagnostic/diagnostics.hpp (2 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (3 hunks)
  • src/phare/CMakeLists.txt (0 hunks)
  • src/phare/phare_init.py (0 hunks)
  • src/phare/phare_init_small.py (0 hunks)
  • tests/simulator/CMakeLists.txt (2 hunks)
  • tests/simulator/__init__.py (1 hunks)
  • tests/simulator/refinement/test_2d_10_core.py (1 hunks)
  • tests/simulator/test_vtk_diagnostics.py (1 hunks)
💤 Files with no reviewable changes (3)
  • src/phare/CMakeLists.txt
  • src/phare/phare_init_small.py
  • src/phare/phare_init.py
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/diagnostic/diagnostic_manager.hpp
  • src/amr/physical_models/hybrid_model.hpp
  • src/diagnostic/detail/vtk_types/info.hpp
  • pyphare/pyphare/pharein/init.py
  • pyphare/pyphare/pharein/simulation.py
  • tests/simulator/init.py
  • src/diagnostic/detail/vtk_types/particle.hpp
  • src/diagnostic/detail/vtk_types/meta.hpp
  • src/diagnostic/detail/vtk_types/fluid.hpp
🧰 Additional context used
📓 Path-based instructions (1)
**/*.hpp

⚙️ CodeRabbit configuration file

Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Files:

  • src/diagnostic/diagnostics.hpp
  • src/diagnostic/detail/vtk_types/electromag.hpp
  • src/core/utilities/types.hpp
  • src/core/utilities/algorithm.hpp
  • src/core/utilities/box/box.hpp
  • src/core/data/grid/gridlayoutimplyee.hpp
  • src/diagnostic/diagnostic_model_view.hpp
  • src/amr/resources_manager/amr_utils.hpp
  • src/diagnostic/detail/h5writer.hpp
  • src/core/data/grid/gridlayout.hpp
  • src/hdf5/detail/h5/h5_file.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/core/data/tensorfield/tensorfield.hpp
  • src/core/data/grid/gridlayoutdefs.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
🧠 Learnings (12)
📓 Common learnings
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-07-26T22:04:34.160Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-10-09T08:32:15.667Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-09-05T17:02:58.784Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
📚 Learning: 2025-02-07T14:35:14.630Z
Learnt from: nicolasaunai
Repo: PHAREHUB/PHARE PR: 591
File: res/cmake/options.cmake:73-75
Timestamp: 2025-02-07T14:35:14.630Z
Learning: In CMake configuration for PHARE, `lowResourceTests` and `highResourceTests` options must be mutually exclusive and cannot be enabled simultaneously.

Applied to files:

  • tests/simulator/CMakeLists.txt
📚 Learning: 2025-07-09T17:18:05.771Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/amr/CMakeLists.txt:103-105
Timestamp: 2025-07-09T17:18:05.771Z
Learning: In the PHARE project, `HighFive` is a CMake option defined in `res/cmake/options.cmake` as `option(HighFive "Build with highfive usage" ON)`, not a target that would be created by find_package(). The condition `if (HighFive)` correctly checks this option.

Applied to files:

  • tests/simulator/CMakeLists.txt
  • src/diagnostic/detail/h5writer.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
📚 Learning: 2025-09-01T09:41:40.618Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1056
File: tests/core/numerics/interpolator/test_main.cpp:314-318
Timestamp: 2025-09-01T09:41:40.618Z
Learning: The PHARE project uses C++20, which makes the typename keyword optional for dependent types in obvious contexts. The project prefers minimal code without unnecessary keywords, so typename suggestions for dependent types should be avoided when the code compiles successfully in C++20.

Applied to files:

  • src/core/utilities/types.hpp
  • src/core/utilities/algorithm.hpp
📚 Learning: 2025-04-17T14:41:53.643Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 998
File: src/core/utilities/point/point.hpp:195-210
Timestamp: 2025-04-17T14:41:53.643Z
Learning: In `src/core/utilities/point/point.hpp`, the `as_signed()` and `as_unsigned()` methods are intentionally designed to cause compilation errors for unsupported types (only 4-byte types are supported). This forces developers to implement proper conversions themselves when extending the functionality to new types. The comment "else no return cause not yet handled" indicates this is a deliberate design choice.

Applied to files:

  • src/core/utilities/types.hpp
  • src/core/utilities/box/box.hpp
📚 Learning: 2025-09-17T13:35:11.533Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.

Applied to files:

  • src/core/utilities/algorithm.hpp
  • src/diagnostic/diagnostic_model_view.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
📚 Learning: 2024-10-22T10:05:54.014Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 0
File: :0-0
Timestamp: 2024-10-22T10:05:54.014Z
Learning: The variable `c_ordering` in `ConcreteLoadBalancerHybridStrategyNPPC<PHARE_T>::compute` is used to create an array view `lb_view` for handling load balancing data.

Applied to files:

  • src/core/utilities/algorithm.hpp
📚 Learning: 2025-11-10T09:37:57.021Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1084
File: src/diagnostic/diagnostic_model_view.hpp:219-221
Timestamp: 2025-11-10T09:37:57.021Z
Learning: In PHARE, temporary fields like tmpField_, tmpVec_, and tmpTensor_ in src/diagnostic/diagnostic_model_view.hpp use a name-based resource allocation pattern. Fields with names "PHARE_sumField", "PHARE_sumVec", and "PHARE_sumTensor" are allocated globally elsewhere in the resources manager (e.g., in src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp), and components reference the same storage through identically-named field objects. These do not require local allocation via rm.enumerate().

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
  • src/diagnostic/detail/h5writer.hpp
📚 Learning: 2025-09-17T13:50:16.038Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/tensorfield/tensor_field_data_factory.hpp:112-112
Timestamp: 2025-09-17T13:50:16.038Z
Learning: PhilipDeegan indicated that getSizeOfMemory returning a placeholder value of 1 in TensorFieldDataFactory is acceptable for their use case, suggesting it may not be critical for PHARE's memory management needs.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
  • src/core/data/tensorfield/tensorfield.hpp
📚 Learning: 2024-09-09T13:57:02.285Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py:566-568
Timestamp: 2024-09-09T13:57:02.285Z
Learning: Avoid commenting on draft PRs for PhilipDeegan unless explicitly requested.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/core/data/grid/gridlayout.hpp:805-821
Timestamp: 2024-10-09T08:32:15.667Z
Learning: In the `AMRToLocal` function, before converting to `uint32_t`, assert that `local >= 0` to ensure values are valid.

Applied to files:

  • src/core/data/grid/gridlayout.hpp
🧬 Code graph analysis (13)
src/diagnostic/diagnostics.hpp (3)
src/diagnostic/diagnostic_manager.hpp (5)
  • dict (83-83)
  • dict (86-86)
  • dict (86-86)
  • make_unique (74-80)
  • make_unique (74-75)
src/diagnostic/detail/h5writer.hpp (2)
  • make_unique (61-68)
  • make_unique (61-61)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • make_unique (67-74)
  • make_unique (67-67)
tests/simulator/test_vtk_diagnostics.py (5)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_lib (6-9)
pyphare/pyphare/simulator/simulator.py (2)
  • startMPI (41-45)
  • reset (258-269)
tests/simulator/__init__.py (4)
  • SimulatorTest (201-267)
  • tearDown (204-205)
  • unique_diag_dir_for_test_case (250-254)
  • run (246-248)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-62)
pyphare/pyphare/pharein/simulation.py (2)
  • simulation_domain (967-968)
  • Simulation (735-1069)
src/diagnostic/detail/vtk_types/electromag.hpp (2)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
  • write (38-97)
  • write (38-38)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtkh5_type_writer.hpp (8)
  • diagnostic (74-79)
  • diagnostic (74-74)
  • lvl (155-160)
  • lvl (155-155)
  • ilvl (266-295)
  • ilvl (266-266)
  • boxes (51-65)
  • boxes (51-51)
src/core/utilities/algorithm.hpp (4)
src/core/data/electrons/electrons.hpp (8)
  • layout (107-133)
  • layout (107-107)
  • layout (285-285)
  • layout (285-285)
  • layout (286-286)
  • layout (286-286)
  • layout (309-319)
  • layout (309-309)
src/core/utilities/box/box.hpp (4)
  • dim (109-125)
  • dim (127-142)
  • box (53-53)
  • boxes_iterator (214-217)
src/core/utilities/types.hpp (4)
  • all (365-369)
  • all (365-366)
  • all (376-379)
  • all (376-376)
src/core/data/ndarray/ndarray_vector.hpp (4)
  • make_array_view (214-217)
  • make_array_view (214-214)
  • make_array_view (220-223)
  • make_array_view (220-220)
src/core/utilities/box/box.hpp (2)
src/core/utilities/point/point.hpp (4)
  • i (68-68)
  • i (68-68)
  • i (69-69)
  • i (69-69)
src/core/utilities/types.hpp (7)
  • product (269-272)
  • product (269-269)
  • for_N (467-498)
  • for_N (467-467)
  • for_N (501-504)
  • for_N (501-501)
  • for_N_any (521-521)
src/diagnostic/diagnostic_model_view.hpp (4)
src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp (10)
  • patch (146-154)
  • patch (146-146)
  • ions (407-416)
  • ions (407-407)
  • ions (420-445)
  • ions (420-420)
  • ions (447-480)
  • ions (447-447)
  • ions (492-531)
  • ions (492-493)
src/amr/resources_manager/amr_utils.hpp (2)
  • visitHierarchy (244-253)
  • visitHierarchy (244-245)
src/core/data/ions/ions.hpp (1)
  • forward_as_tuple (225-229)
src/core/data/ions/ion_population/ion_population.hpp (1)
  • forward_as_tuple (109-113)
src/amr/resources_manager/amr_utils.hpp (1)
src/core/data/field/field.hpp (4)
  • args (75-81)
  • args (75-75)
  • args (83-86)
  • args (83-83)
src/core/data/grid/gridlayout.hpp (5)
src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp (4)
  • field (929-956)
  • field (929-930)
  • field (958-964)
  • field (958-958)
src/amr/data/field/field_geometry.hpp (4)
  • box (136-179)
  • box (136-137)
  • box (198-207)
  • box (198-198)
src/core/utilities/types.hpp (2)
  • for_N_make_array (508-511)
  • for_N_make_array (508-508)
src/amr/resources_manager/amr_utils.hpp (5)
  • AMRToLocal (45-46)
  • AMRToLocal (53-54)
  • AMRToLocal (62-62)
  • AMRToLocal (77-90)
  • AMRToLocal (77-78)
src/amr/resources_manager/amr_utils.cpp (6)
  • AMRToLocal (34-40)
  • AMRToLocal (34-35)
  • AMRToLocal (47-54)
  • AMRToLocal (47-48)
  • AMRToLocal (62-66)
  • AMRToLocal (62-62)
tests/simulator/refinement/test_2d_10_core.py (2)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_lib (6-9)
tests/simulator/test_advance.py (1)
  • AdvanceTestBase (33-869)
src/hdf5/detail/h5/h5_file.hpp (1)
src/core/utilities/types.hpp (1)
  • get_env_as (253-253)
src/diagnostic/detail/vtkh5_writer.hpp (4)
src/diagnostic/diagnostic_model_view.hpp (1)
  • dimension (30-60)
src/diagnostic/detail/vtkh5_type_writer.hpp (6)
  • level (196-218)
  • level (196-196)
  • level (231-231)
  • level (231-231)
  • diagnostic (74-79)
  • diagnostic (74-74)
src/amr/resources_manager/amr_utils.hpp (2)
  • to_string (222-227)
  • to_string (222-222)
src/hdf5/detail/h5/h5_file.hpp (4)
  • path (295-301)
  • path (295-295)
  • path (303-308)
  • path (303-303)
src/core/data/ndarray/ndarray_vector.hpp (1)
src/core/utilities/types.hpp (2)
  • product (269-272)
  • product (269-269)
src/diagnostic/detail/vtkh5_type_writer.hpp (5)
src/core/utilities/box/box.hpp (9)
  • box (53-53)
  • i (99-99)
  • i (99-99)
  • grow (91-96)
  • grow (91-91)
  • grow (328-333)
  • grow (328-328)
  • size (78-88)
  • size (78-78)
src/core/data/tensorfield/tensorfield.hpp (8)
  • i (181-181)
  • i (181-181)
  • i (182-182)
  • i (182-182)
  • size (208-208)
  • size (208-208)
  • tensor_field_dim_from_rank (17-24)
  • tensor_field_dim_from_rank (17-17)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (97-101)
  • diagnostic (97-97)
src/core/utilities/types.hpp (6)
  • for_N_make_array (508-511)
  • for_N_make_array (508-508)
  • sum_from (281-289)
  • sum_from (281-281)
  • sum (275-278)
  • sum (275-275)
src/core/utilities/algorithm.hpp (4)
  • convert_to_fortran_primal (103-135)
  • convert_to_fortran_primal (103-107)
  • convert_to_fortran_primal (138-147)
  • convert_to_fortran_primal (138-142)
🪛 Ruff (0.14.5)
tests/simulator/test_vtk_diagnostics.py

25-25: Unused function argument: xyz

(ARG001)


32-32: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


39-39: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


42-42: Unused function argument: xyz

(ARG001)


45-45: Unused function argument: xyz

(ARG001)


52-52: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


59-59: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


62-62: Unused function argument: xyz

(ARG001)


65-65: Unused function argument: xyz

(ARG001)


68-68: Unused function argument: xyz

(ARG001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: Analyze (cpp)
  • GitHub Check: Analyze (python)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-14)
🔇 Additional comments (33)
src/amr/resources_manager/amr_utils.hpp (1)

251-251: Correct variadic forwarding syntax applied.

The change from std::forward<Args...>(args...) to std::forward<Args>(args)... fixes incorrect template parameter pack expansion. The corrected syntax properly forwards each argument in the pack to visitLevel.

src/diagnostic/diagnostic_model_view.hpp (1)

37-37: LGTM! Well-structured refactoring for VTK HDF diagnostic support.

The changes effectively refactor temporary storage and provide clean accessor APIs:

  • Field alias (line 37): Useful public type for external code
  • Temporary storage refactoring (lines 219-221): Expands single sumTensor_ to tmpField_, tmpVec_, tmpTensor_ with appropriate name-based resource allocation
  • New accessor methods (lines 145-172): localLevelBoxes(), tmpField(), tmpVecField(), tmpTensorField<rank>(), and getCompileTimeResourcesViewList() provide efficient, type-safe access following established patterns
  • Efficient implementation: Proper use of if constexpr, move semantics, std::forward_as_tuple, and compile-time enforcement via static_assert
  • Consistent updates: fillPopMomTensor(), dst_name(), and template parameters updated consistently

The code is expressive, follows clean code principles, and aligns with patterns established elsewhere in the codebase (e.g., ions.hpp, ion_population.hpp).

Also applies to: 70-80, 96-98, 145-172, 183-183, 194-194, 219-221

tests/simulator/refinement/test_2d_10_core.py (2)

22-24: LGTM!

The diagnostic path constants are clearly defined and used consistently throughout the test.


17-21: The review comment is based on incorrect assumptions about the codebase pattern.

The module-level initialization of cpp = cpp_lib() and test = AdvanceTestBase(rethrow=True) is not only safe but is the established pattern in this codebase. Test file tests/simulator/refinement/test_2d_2_core.py uses the identical initialization pattern at lines 150-151. Additionally, startMPI() itself calls cpp_lib() internally (simulator.py:45), demonstrating that cpp_lib() functions independently of MPI initialization state. No MPI dependencies exist in cpp_lib() or AdvanceTestBase. Since these are direct-run scripts executed with mpirun (not pytest test modules), module-level initialization is appropriate and standard in this codebase.

Likely an incorrect or invalid review comment.

src/core/data/tensorfield/tensorfield.hpp (1)

208-208: LGTM: Improved qualifier ordering.

The reordering of qualifiers (static constexpr instead of constexpr static) follows a more conventional style where storage-class specifiers precede cv-qualifiers. No functional change.

src/core/utilities/algorithm.hpp (2)

75-100: LGTM: Well-structured projection logic.

The quantity-specific branching and error handling for unsupported quantities are appropriate.


137-147: LGTM: Correct recursive application.

The TensorField variant properly delegates to the Field conversion for each component.

src/core/utilities/types.hpp (2)

226-235: LGTM: Clear error handling.

The function uses exceptions for parse failures with an informative error message, which aligns with the project's preferences based on past feedback.


252-258: LGTM: Clean environment variable parsing.

The function appropriately delegates to from_string and provides a sensible default fallback.

src/core/utilities/box/box.hpp (4)

30-30: LGTM: Standard iterator typedef.


99-101: LGTM: Clean shape and size accessors.

The per-dimension shape(i) accessor and the updated size() using core::product are well-designed.


209-259: LGTM: Well-designed composite iterator.

The boxes_iterator implements a parallel iteration pattern that advances multiple box iterators simultaneously. The use of compile-time for_N helpers and tuple handling is appropriate.


327-333: LGTM: Simple non-mutating wrapper.

src/diagnostic/detail/h5writer.hpp (1)

196-197: LGTM: Critical fix for deleted assignment operators.

Correcting operator& to operator= properly deletes the copy and move assignment operators. The previous code inadvertently deleted the bitwise AND operator instead.

src/core/data/ndarray/ndarray_vector.hpp (4)

19-23: LGTM: Improved generic design.

Removing DataType from the template parameters and using uint32_t for indices (correcting the previous narrowing issue) makes NdArrayViewer more flexible and safe for large grids.


25-53: LGTM: Correct index computation.

The idx methods correctly compute flat indices for both C-ordering (row-major) and Fortran-ordering (column-major) across 1D, 2D, and 3D cases.


55-70: LGTM: Generic accessor with bounds checking.

The refactored at methods use auto for generic type handling and include appropriate bounds assertions.


101-101: LGTM: Consistent usage updates.

All call sites have been updated consistently to use the refactored NdArrayViewer interface without the DataType template parameter.

Also applies to: 138-138, 161-162, 167-167, 291-291, 303-303

tests/simulator/CMakeLists.txt (2)

21-21: LGTM: VTK diagnostics test added.

The new test for VTK diagnostics is appropriately placed within the HighFive conditional block and follows the existing test pattern.


33-33: LGTM: Diagnostic timestamps test enabled.

Re-enabling this test ensures timestamp functionality is properly validated.

src/core/data/grid/gridlayoutdefs.hpp (1)

6-8: LGTM: Include reordering for dependencies.

The include reordering ensures proper dependency resolution without affecting the public API.

src/diagnostic/diagnostics.hpp (1)

28-61: Format-based diagnostics writer selection is clear and robust

The new format dispatch (defaulting to "phareh5" and adding "pharevtkhdf") is straightforward, preserves the existing API, and fails fast on unknown formats with a descriptive error message. No issues from this change.

src/diagnostic/detail/vtk_types/electromag.hpp (2)

29-55: Electromagnetic VTK writer implementation matches existing patterns

The write implementation follows the same structure as the fluid VTK writer (per-level init, per-field init, then visitHierarchy with a quantity filter) and correctly restricts initialization and writes to the active diagnostic.quantity. This is consistent and easy to maintain.


13-17: Remove incorrect typename suggestion; code is valid C++20 as-is

In C++20, typename is optional for dependent types in type alias declarations. The context makes the type intent unambiguous, and the pattern using VTKFileWriter = Super::VTKFileWriter; is valid and widely used throughout the PHARE codebase (particle.hpp, fluid.hpp, and electromag.hpp all use this form). The code compiles correctly without the keyword and aligns with the project's preference for minimal syntax in C++20.

Likely an incorrect or invalid review comment.

src/core/data/grid/gridlayoutimplyee.hpp (2)

423-441: Use of std::array CTAD in interpolation stencils looks good

Switching these interpolation helpers to return std::array{...}; keeps the code shorter and clearer while preserving the existing stencils and weights across dimensions. No behavioural issues spotted in these changes.

Also applies to: 446-473, 487-506, 617-634, 641-664, 671-693, 706-723, 736-752, 768-781


511-603: New Bx/By/Bz→Moments stencils are consistent with Yee centering in 1D/2D/3D

The new BxToMoments, ByToMoments, and BzToMoments helpers correctly:

  • Treat 1D cases as identity for primal components (Bx) and 2‑point averages for dual ones (By, Bz).
  • In 2D, average over the single dual direction (2‑point stencils for Bx and By, 4‑point stencil for Bz which is dual in both X and Y).
  • In 3D, average over all 2² dual combinations in the shifted directions for each component, with weights that sum to 1.

This matches the Yee centering defined earlier and addresses the previous 3D under‑sampling concerns around B→moment interpolation.

tests/simulator/test_vtk_diagnostics.py (1)

24-103: Model setup for VTK diagnostics is straightforward and appropriate

The Maxwellian fluid model (constant density, sinusoidal/cosinusoidal B/V profiles, small thermal speeds, plus isothermal electrons) is a good, lightweight choice for exercising the electromag and fluid VTK/HDF diagnostics without overcomplicating the test. The use of sim.simulation_domain() keeps fields properly periodic with the configured domain.

src/hdf5/detail/h5/h5_file.hpp (1)

275-287: Existence-checked getDataSet and deleted copy/move clarify ownership

Wrapping h5file_.exist in exist() and adding a getDataSet that throws on missing datasets is a safer alternative to the old assert‑based pattern, and deleting copy/move operations for HighFiveFile makes its ownership/lifetime semantics explicit. These changes improve robustness without altering existing call sites that use the raw h5file_.

src/core/data/grid/gridlayout.hpp (3)

1027-1046: LGTM: Consistent projection helpers added.

The new BxToMoments, ByToMoments, and BzToMoments methods follow the existing pattern for field projection helpers and correctly delegate to the GridLayoutImpl counterparts.


1180-1194: LGTM: Box accessors refactored correctly.

The AMRBoxFor and AMRGhostBoxFor methods now correctly compute the physical and ghost boxes respectively. AMRGhostBoxFor uses positive nbrGhosts() values with grow(), which properly expands the box—avoiding the unsigned wraparound issue flagged in earlier reviews.


1220-1226: LGTM: Iterator helpers added.

The new indexer methods (amr_lcl_idx, domain_amr_lcl_idx, ghost_amr_lcl_idx) provide convenient access to AMR/local box iterators for different use cases.

src/diagnostic/detail/vtkh5_writer.hpp (1)

1-209: LGTM: Well-structured HDF5 writer.

The H5Writer class provides a clean, templated interface for VTK-HDF5 diagnostic output:

  • Proper RAII semantics and deleted copy/move operations
  • Lazy per-quantity file creation via makeFile()
  • Correct flag management in dump() to prevent truncation on subsequent writes
  • Factory method make_unique() with optional overwrite mode

Past issues (operator deletion, header guard comment, flag reset) have been addressed.

src/diagnostic/detail/vtkh5_type_writer.hpp (1)

162-305: LGTM: VTK-HDF5 dataset management.

The VTKFileWriter methods correctly handle:

  • Field and tensor-field conversion to Fortran-ordered primal data
  • Per-level dataset initialization with appropriate metadata (spacing, offsets)
  • MPI-aware offset and size accumulation in resize_data and resize_boxes
  • Primal box adjustment (line 303) aligns with the convert_to_fortran_primal calls

@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 19, 2025
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 19, 2025
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 19, 2025
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 19, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (9)
src/diagnostic/diagnostic_manager.hpp (1)

31-37: Avoid recomputing diagName inside the loop (optional micro‑cleanup).

The change to std::string const diagName is fine and behavior‑preserving. Right now, though, diagType + std::to_string(diagBlockID) is built once in the while condition and again for diagName. If you want to trim a tiny bit of duplication and work, you could compute diagName once per iteration and reuse it for both the contains check and the dictionary access, e.g.:

-    std::size_t diagBlockID = 0;
-    while (diagsParams.contains(diagType)
-           && diagsParams[diagType].contains(diagType + std::to_string(diagBlockID)))
-    {
-        std::string const diagName = diagType + std::to_string(diagBlockID);
+    std::size_t diagBlockID = 0;
+    while (diagsParams.contains(diagType))
+    {
+        std::string const diagName = diagType + std::to_string(diagBlockID);
+        if (!diagsParams[diagType].contains(diagName))
+            break;
         dMan.addDiagDict(diagsParams[diagType][diagName]);
         ++diagBlockID;
     }

Not required, but it slightly simplifies the logic and avoids repeated string concatenation, in line with the minimal/efficient style used elsewhere.

src/amr/resources_manager/amr_utils.hpp (1)

229-239: Consider forwarding args in visitLevel for consistency.

While not part of the current change, for consistency with the perfect forwarding pattern now established in visitHierarchy, consider forwarding the args parameter pack when passing to resman.setOnPatch at line 234.

Apply this diff:

 template<typename GridLayout, typename ResMan, typename Action, typename... Args>
 void visitLevel(SAMRAI_Types::level_t& level, ResMan& resman, Action&& action, Args&&... args)
 {
     for (auto& patch : level)
     {
-        auto guard        = resman.setOnPatch(*patch, args...);
+        auto guard        = resman.setOnPatch(*patch, std::forward<Args>(args)...);
         GridLayout layout = layoutFromPatch<GridLayout>(*patch);
         action(layout, to_string(patch->getGlobalId()),
                static_cast<std::size_t>(level.getLevelNumber()));
     }
 }
src/diagnostic/detail/h5writer.hpp (1)

1-2: Consider aligning the header guard name and comment with the file path convention

The guard macro (PHARE_DETAIL_DIAGNOSTIC_HIGHFIVE_HPP) and the closing comment (PHARE_DETAIL_DIAGNOSTIC_HIGHFIVE_H) don’t match each other or the file name h5writer.hpp. When convenient, consider renaming the guard to follow the project-wide PHARE_[PATH_WITH_UNDERSCORES]_HPP pattern and updating the closing comment accordingly.

Based on learnings

Also applies to: 347-347

src/core/utilities/box/box.hpp (1)

209-259: Add documentation and const overloads for boxes_iterator.

The boxes_iterator is a powerful parallel-iteration utility, but its usage pattern isn't immediately obvious. Consider adding class-level documentation explaining that it simultaneously iterates over multiple boxes, yielding tuples of points.

Additionally, begin() and end() (lines 249-256) should provide const overloads since they don't modify the boxes and Box itself supports const iteration:

auto begin() const
{
    return iterator{for_N<N>([&](auto i) { return std::get<i>(boxes).begin(); })};
}
auto end() const
{
    return iterator{for_N<N>([&](auto i) { return std::get<i>(boxes).end(); })};
}

Minor note: line 215 uses std::forward_as_tuple (tuple of references), but the member at line 258 is std::tuple<Boxes...> (stores by value). This causes boxes to be copied during construction, which is safe but might be surprising. For small Box objects this is fine, but consider documenting or using std::tuple<Boxes const&...> if copies are unintended.

src/core/utilities/algorithm.hpp (2)

75-100: convert_to_primal mapping looks correct; consider future‑proofing unsupported quantities

The mapping from PhysicalQuantity (Bx/By/Bz/Ex/Ey/Ez) to the corresponding layout.*ToMoments() projector is clear and keeps the hot path simple. The fallback std::runtime_error will surface misuse at runtime.

If there are quantities for which calling this is a programming error (rather than a recoverable runtime condition), you may eventually want to enforce that via static constraints or a debug assert before throwing, but the current implementation is fine for now.


102-135: Field convert_to_fortran_primal implementation is sound; consider tightening preconditions

The implementation looks good:

  • Asserts that dst is fully primal.
  • Detects whether src is all‑primal once, then uses two separate loops to avoid an extra branch in the inner loop.
  • Uses boxes_iterator with a zero‑shifted local box to write into a Fortran‑ordered NdArrayView, with c_ordering clearly set to false locally.

Given the comment // DOES NOT WORK ON GHOST BOX!, you might eventually want to turn that into an assert once there is an accessor on layout/box to detect ghost regions; until then, the comment at least documents the precondition.

src/core/utilities/types.hpp (1)

226-235: from_string / get_env_as look good, with one parsing nuance

The new from_string + get_env_as helpers are clear and minimal, and throwing on failed extraction is a reasonable choice here. One behavioral detail to be aware of: formatted extraction will accept prefixes like "42xyz" as 42 without setting failbit. If you ever need stricter validation (rejecting trailing junk), you’d need an extra check (e.g., consume std::ws then verify eof()), but what you have is fine if partial parses are acceptable.

Also applies to: 252-258

src/diagnostic/detail/vtk_types/electromag.hpp (1)

12-55: Electromag VTK/HDF writer logic matches existing pattern; consider small cleanups

The new ElectromagDiagnosticWriter follows the same pattern as the fluid writer: level loop, per-level initFileLevel + initTensorFieldFileLevel, then visitHierarchy with a lambda that writes the selected electromag vector field. The matching on diagnostic.quantity == "/" + vecField->name() keeps selection simple and localized.

Two optional refinements you might consider later:

  • If diagnostic.quantity doesn’t correspond to any electromag field, you could early-return before calling onLevels to avoid creating empty files.
  • The matching loop over getElectromagFields() is duplicated in write_quantity and the level init lambda; caching a has_match flag or a pointer to the matched field would remove that duplication and a bit of repeated string work.

Both are non-essential; the current implementation is sound and consistent with the rest of the vtkh5 writers.

tests/simulator/test_vtk_diagnostics.py (1)

119-128: Avoid mutating and reusing the same simInput dict across permutations.

permute(dic) updates the passed-in dict in place and reuses that single instance for all (ndim, interp) combinations. With more than one combo this would couple test cases via shared simInput state.

A small refactor keeps behavior while isolating cases:

-def permute(dic):
-    dic.update(simArgs.copy())
-    return [
-        dict(
-            ndim=ndim,
-            interp=interp_order,
-            simInput=dic,
-        )
-        for ndim, interp_order in itertools.product(ndims, interp_orders)
-    ]
+def permute(overrides):
+    base = simArgs.copy()
+    base.update(overrides)
+    return [
+        dict(
+            ndim=ndim,
+            interp=interp_order,
+            simInput=base.copy(),
+        )
+        for ndim, interp_order in itertools.product(ndims, interp_orders)
+    ]
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7395d74 and caa898e.

📒 Files selected for processing (29)
  • pyphare/pyphare/pharein/__init__.py (1 hunks)
  • pyphare/pyphare/pharein/simulation.py (1 hunks)
  • src/amr/physical_models/hybrid_model.hpp (1 hunks)
  • src/amr/resources_manager/amr_utils.hpp (1 hunks)
  • src/core/data/grid/gridlayout.hpp (4 hunks)
  • src/core/data/grid/gridlayoutdefs.hpp (1 hunks)
  • src/core/data/grid/gridlayoutimplyee.hpp (27 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (5 hunks)
  • src/core/data/tensorfield/tensorfield.hpp (1 hunks)
  • src/core/utilities/algorithm.hpp (2 hunks)
  • src/core/utilities/box/box.hpp (6 hunks)
  • src/core/utilities/types.hpp (5 hunks)
  • src/diagnostic/detail/h5writer.hpp (2 hunks)
  • src/diagnostic/detail/vtk_types/electromag.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/fluid.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_type_writer.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_writer.hpp (1 hunks)
  • src/diagnostic/diagnostic_manager.hpp (1 hunks)
  • src/diagnostic/diagnostic_model_view.hpp (7 hunks)
  • src/diagnostic/diagnostic_writer.hpp (1 hunks)
  • src/diagnostic/diagnostics.hpp (2 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (3 hunks)
  • src/phare/CMakeLists.txt (0 hunks)
  • src/phare/phare_init.py (0 hunks)
  • src/phare/phare_init_small.py (0 hunks)
  • tests/simulator/CMakeLists.txt (2 hunks)
  • tests/simulator/__init__.py (1 hunks)
  • tests/simulator/refinement/test_2d_10_core.py (1 hunks)
  • tests/simulator/test_vtk_diagnostics.py (1 hunks)
💤 Files with no reviewable changes (3)
  • src/phare/CMakeLists.txt
  • src/phare/phare_init_small.py
  • src/phare/phare_init.py
🚧 Files skipped from review as they are similar to previous changes (7)
  • tests/simulator/CMakeLists.txt
  • src/diagnostic/detail/vtk_types/fluid.hpp
  • pyphare/pyphare/pharein/init.py
  • pyphare/pyphare/pharein/simulation.py
  • src/diagnostic/diagnostics.hpp
  • tests/simulator/init.py
  • tests/simulator/refinement/test_2d_10_core.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.hpp

⚙️ CodeRabbit configuration file

Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Files:

  • src/diagnostic/diagnostic_writer.hpp
  • src/core/utilities/algorithm.hpp
  • src/core/data/grid/gridlayoutdefs.hpp
  • src/core/utilities/types.hpp
  • src/core/data/tensorfield/tensorfield.hpp
  • src/core/data/grid/gridlayoutimplyee.hpp
  • src/diagnostic/detail/h5writer.hpp
  • src/amr/physical_models/hybrid_model.hpp
  • src/diagnostic/diagnostic_model_view.hpp
  • src/core/utilities/box/box.hpp
  • src/diagnostic/detail/vtk_types/electromag.hpp
  • src/hdf5/detail/h5/h5_file.hpp
  • src/core/data/grid/gridlayout.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
  • src/amr/resources_manager/amr_utils.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/diagnostic_manager.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
🧠 Learnings (11)
📓 Common learnings
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-07-26T22:04:34.160Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-10-09T08:32:15.667Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-09-05T17:02:58.784Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
📚 Learning: 2025-11-10T09:37:57.021Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1084
File: src/diagnostic/diagnostic_model_view.hpp:219-221
Timestamp: 2025-11-10T09:37:57.021Z
Learning: In PHARE, temporary fields like tmpField_, tmpVec_, and tmpTensor_ in src/diagnostic/diagnostic_model_view.hpp use a name-based resource allocation pattern. Fields with names "PHARE_sumField", "PHARE_sumVec", and "PHARE_sumTensor" are allocated globally elsewhere in the resources manager (e.g., in src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp), and components reference the same storage through identically-named field objects. These do not require local allocation via rm.enumerate().

Applied to files:

  • src/diagnostic/diagnostic_writer.hpp
  • src/diagnostic/detail/h5writer.hpp
  • src/amr/physical_models/hybrid_model.hpp
  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2025-09-17T13:35:11.533Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.

Applied to files:

  • src/core/utilities/algorithm.hpp
  • src/diagnostic/diagnostic_model_view.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
📚 Learning: 2024-10-22T10:05:54.014Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 0
File: :0-0
Timestamp: 2024-10-22T10:05:54.014Z
Learning: The variable `c_ordering` in `ConcreteLoadBalancerHybridStrategyNPPC<PHARE_T>::compute` is used to create an array view `lb_view` for handling load balancing data.

Applied to files:

  • src/core/utilities/algorithm.hpp
📚 Learning: 2025-09-01T09:41:40.618Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1056
File: tests/core/numerics/interpolator/test_main.cpp:314-318
Timestamp: 2025-09-01T09:41:40.618Z
Learning: The PHARE project uses C++20, which makes the typename keyword optional for dependent types in obvious contexts. The project prefers minimal code without unnecessary keywords, so typename suggestions for dependent types should be avoided when the code compiles successfully in C++20.

Applied to files:

  • src/core/utilities/algorithm.hpp
  • src/core/utilities/types.hpp
📚 Learning: 2025-04-17T14:41:53.643Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 998
File: src/core/utilities/point/point.hpp:195-210
Timestamp: 2025-04-17T14:41:53.643Z
Learning: In `src/core/utilities/point/point.hpp`, the `as_signed()` and `as_unsigned()` methods are intentionally designed to cause compilation errors for unsupported types (only 4-byte types are supported). This forces developers to implement proper conversions themselves when extending the functionality to new types. The comment "else no return cause not yet handled" indicates this is a deliberate design choice.

Applied to files:

  • src/core/utilities/types.hpp
  • src/core/utilities/box/box.hpp
📚 Learning: 2025-09-17T13:50:16.038Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/tensorfield/tensor_field_data_factory.hpp:112-112
Timestamp: 2025-09-17T13:50:16.038Z
Learning: PhilipDeegan indicated that getSizeOfMemory returning a placeholder value of 1 in TensorFieldDataFactory is acceptable for their use case, suggesting it may not be critical for PHARE's memory management needs.

Applied to files:

  • src/core/data/tensorfield/tensorfield.hpp
  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2025-07-09T17:18:05.771Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/amr/CMakeLists.txt:103-105
Timestamp: 2025-07-09T17:18:05.771Z
Learning: In the PHARE project, `HighFive` is a CMake option defined in `res/cmake/options.cmake` as `option(HighFive "Build with highfive usage" ON)`, not a target that would be created by find_package(). The condition `if (HighFive)` correctly checks this option.

Applied to files:

  • src/diagnostic/detail/h5writer.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
📚 Learning: 2024-09-09T13:57:02.285Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py:566-568
Timestamp: 2024-09-09T13:57:02.285Z
Learning: Avoid commenting on draft PRs for PhilipDeegan unless explicitly requested.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
  • src/diagnostic/detail/vtkh5_writer.hpp
  • src/diagnostic/detail/vtkh5_type_writer.hpp
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.

Applied to files:

  • src/diagnostic/diagnostic_model_view.hpp
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/core/data/grid/gridlayout.hpp:805-821
Timestamp: 2024-10-09T08:32:15.667Z
Learning: In the `AMRToLocal` function, before converting to `uint32_t`, assert that `local >= 0` to ensure values are valid.

Applied to files:

  • src/core/data/grid/gridlayout.hpp
🧬 Code graph analysis (11)
src/core/utilities/algorithm.hpp (3)
src/core/utilities/box/box.hpp (4)
  • dim (109-125)
  • dim (127-142)
  • box (53-53)
  • boxes_iterator (214-217)
src/core/utilities/types.hpp (4)
  • all (365-369)
  • all (365-366)
  • all (376-379)
  • all (376-376)
src/core/data/ndarray/ndarray_vector.hpp (4)
  • make_array_view (214-217)
  • make_array_view (214-214)
  • make_array_view (220-223)
  • make_array_view (220-220)
tests/simulator/test_vtk_diagnostics.py (5)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_lib (6-9)
pyphare/pyphare/simulator/simulator.py (2)
  • startMPI (41-45)
  • reset (258-269)
tests/simulator/__init__.py (4)
  • SimulatorTest (201-267)
  • tearDown (204-205)
  • unique_diag_dir_for_test_case (250-254)
  • run (246-248)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-62)
pyphare/pyphare/pharein/maxwellian_fluid_model.py (1)
  • MaxwellianFluidModel (8-303)
src/diagnostic/diagnostic_model_view.hpp (3)
src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp (10)
  • patch (146-154)
  • patch (146-146)
  • ions (407-416)
  • ions (407-407)
  • ions (420-445)
  • ions (420-420)
  • ions (447-480)
  • ions (447-447)
  • ions (492-531)
  • ions (492-493)
src/amr/resources_manager/amr_utils.hpp (2)
  • visitHierarchy (244-253)
  • visitHierarchy (244-245)
src/core/data/ions/ions.hpp (1)
  • forward_as_tuple (225-229)
src/core/utilities/box/box.hpp (2)
src/core/utilities/point/point.hpp (4)
  • i (68-68)
  • i (68-68)
  • i (69-69)
  • i (69-69)
src/core/utilities/types.hpp (7)
  • product (269-272)
  • product (269-269)
  • for_N (467-498)
  • for_N (467-467)
  • for_N (501-504)
  • for_N (501-501)
  • for_N_any (521-521)
src/diagnostic/detail/vtk_types/electromag.hpp (3)
src/diagnostic/detail/vtk_types/fluid.hpp (4)
  • write (38-97)
  • write (38-38)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtkh5_type_writer.hpp (14)
  • diagnostic (71-76)
  • diagnostic (71-71)
  • diagnostic (78-81)
  • diagnostic (78-78)
  • layout (124-127)
  • layout (124-124)
  • lvl (117-122)
  • lvl (117-117)
  • ilvl (106-106)
  • ilvl (108-108)
  • ilvl (108-108)
  • ilvl (140-140)
  • boxes (51-65)
  • boxes (51-51)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (103-107)
  • diagnostic (103-103)
src/hdf5/detail/h5/h5_file.hpp (1)
src/core/utilities/types.hpp (1)
  • get_env_as (253-253)
src/core/data/grid/gridlayout.hpp (3)
src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp (4)
  • field (929-956)
  • field (929-930)
  • field (958-964)
  • field (958-958)
src/amr/data/field/field_geometry.hpp (4)
  • box (136-179)
  • box (136-137)
  • box (198-207)
  • box (198-198)
src/amr/resources_manager/amr_utils.cpp (6)
  • AMRToLocal (34-40)
  • AMRToLocal (34-35)
  • AMRToLocal (47-54)
  • AMRToLocal (47-48)
  • AMRToLocal (62-66)
  • AMRToLocal (62-62)
src/core/data/ndarray/ndarray_vector.hpp (1)
src/core/utilities/types.hpp (2)
  • product (269-272)
  • product (269-269)
src/amr/resources_manager/amr_utils.hpp (1)
src/core/data/field/field.hpp (4)
  • args (75-81)
  • args (75-75)
  • args (83-86)
  • args (83-83)
src/diagnostic/detail/vtkh5_writer.hpp (5)
src/diagnostic/diagnostic_model_view.hpp (1)
  • dimension (30-60)
src/diagnostic/detail/h5writer.hpp (16)
  • H5Writer (51-56)
  • H5Writer (58-58)
  • H5Writer (194-194)
  • H5Writer (195-195)
  • make_unique (61-68)
  • make_unique (61-61)
  • timestamp (101-104)
  • timestamp (101-101)
  • diagnostic (94-98)
  • diagnostic (94-94)
  • modelView_ (160-160)
  • timestamp_ (161-161)
  • fileStr (81-87)
  • fileStr (81-81)
  • dump (224-250)
  • dump (224-225)
src/diagnostic/diagnostics.hpp (2)
  • make_unique (50-65)
  • make_unique (50-51)
src/diagnostic/detail/vtk_types/fluid.hpp (2)
  • diagnostic (29-33)
  • diagnostic (29-30)
src/diagnostic/detail/vtkh5_type_writer.hpp (4)
  • diagnostic (71-76)
  • diagnostic (71-71)
  • diagnostic (78-81)
  • diagnostic (78-78)
src/diagnostic/detail/vtkh5_type_writer.hpp (4)
src/core/data/tensorfield/tensorfield.hpp (8)
  • i (181-181)
  • i (181-181)
  • i (182-182)
  • i (182-182)
  • size (208-208)
  • size (208-208)
  • tensor_field_dim_from_rank (17-24)
  • tensor_field_dim_from_rank (17-17)
src/diagnostic/detail/vtkh5_writer.hpp (2)
  • diagnostic (103-107)
  • diagnostic (103-103)
src/core/utilities/types.hpp (2)
  • for_N_make_array (508-511)
  • for_N_make_array (508-508)
src/core/utilities/algorithm.hpp (4)
  • convert_to_fortran_primal (103-135)
  • convert_to_fortran_primal (103-107)
  • convert_to_fortran_primal (138-147)
  • convert_to_fortran_primal (138-142)
🪛 Ruff (0.14.5)
tests/simulator/test_vtk_diagnostics.py

25-25: Unused function argument: xyz

(ARG001)


32-32: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


39-39: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


42-42: Unused function argument: xyz

(ARG001)


45-45: Unused function argument: xyz

(ARG001)


52-52: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


59-59: Do not assign a lambda expression, use a def

Rewrite _ as a def

(E731)


62-62: Unused function argument: xyz

(ARG001)


65-65: Unused function argument: xyz

(ARG001)


68-68: Unused function argument: xyz

(ARG001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Analyze (cpp)
  • GitHub Check: Analyze (python)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (macos-latest)
🔇 Additional comments (22)
src/amr/resources_manager/amr_utils.hpp (1)

251-251: LGTM! Perfect forwarding syntax corrected.

The change from std::forward<Args...>(args...) to std::forward<Args>(args)... is the correct C++ syntax for perfect forwarding of parameter packs. The ellipsis must expand outside the std::forward call, not within the template parameter list.

src/diagnostic/detail/h5writer.hpp (4)

6-7: Explicit includes for MPI and Components look correct

These additions match direct uses of core::mpi::max and core::Components::componentMap later in the file and help keep the header self-contained.


12-17: Including diagnostic writer type headers is appropriate for inline typeWriters_ initialization

Pulling in the concrete writer type headers here ensures full definitions are available where typeWriters_ is initialized and the writers are constructed, avoiding reliance on fragile forward declarations or transitive includes.


176-182: typeWriters_ map initialization is coherent with diagnostic type strings

The static mapping from diagnostic type strings ("info", "meta", "fluid", "electromag", "particle") to their corresponding writer instances is clear and keeps writer construction centralized and lazy-per-H5Writer.


196-197: Deleting copy/move assignment operators instead of operator& is the correct non-copyable pattern

Switching from deleted operator& overloads to deleted copy/move assignment operators aligns with standard C++ idioms for making a type non-assignable, and is consistent with the already-deleted copy/move constructors.

src/core/utilities/box/box.hpp (4)

5-5: LGTM! Includes support new functionality.

The added includes are appropriate: core/def.hpp for common definitions, <tuple> for the new boxes_iterator, and <algorithm> for std::min/std::max operations.

Also applies to: 10-10, 14-14


30-30: LGTM! Standard container interface.

Adding the iterator type alias follows C++ standard library conventions and makes Box compatible with generic algorithms that expect this member type.


327-333: LGTM! Clean functional-style utility.

The non-member grow() function provides a functional alternative to the mutating member method, returning a grown copy without modifying the original. The implementation is clean and the template parameter OType provides appropriate flexibility.


99-101: Point class provides iterator support; iterator concern is unfounded.

The Point class (line 40) has value_type typedef and provides begin() and end() methods (lines 212–215 in point.hpp), which delegate to the internal r member. The call to core::product(shape(), std::size_t{1}) at line 101 is therefore valid and will compile.

The new shape(std::size_t const i) overload (line 99) could benefit from a bounds check assertion (assert(i < dim)) to catch misuse in debug builds, but this is optional for robustness.

src/core/utilities/algorithm.hpp (2)

1-2: Header guard rename matches project convention

The new guard PHARE_CORE_UTILITIES_ALGORITHM_HPP and the updated #endif comment correctly reflect the full path and are consistent with the PHARE header‑guard pattern.
Based on learnings

Also applies to: 153-153


137-147: TensorField overload correctly delegates to Field version

The tensor overload simply iterates components and reuses the Field convert_to_fortran_primal, which is straightforward and avoids duplication. Assuming dst and src are shape‑compatible, this looks correct and efficient.

src/core/data/tensorfield/tensorfield.hpp (1)

208-208: Static size() qualifier reorder is fine

Swapping constexpr static to static constexpr is semantically neutral; the API and behavior stay identical.

src/amr/physical_models/hybrid_model.hpp (1)

31-32: Alias cleanup matches project’s C++20 style

Removing typename from these dependent aliases doesn’t change semantics and aligns with the existing minimal C++20 style in this codebase.

Based on learnings

Also applies to: 35-36, 39-39

src/core/utilities/types.hpp (1)

513-524: for_N_all / for_N_any implementations are consistent with existing helpers

Reusing for_N with make_array and then all/any keeps the API compact and expressive. The semantics (bool-returning functor over N compile-time indices) are clear and match the naming.

src/core/data/ndarray/ndarray_vector.hpp (1)

19-71: NdArrayViewer-based indexing refactor looks correct and fixes prior width issue

Centralizing the 1D/2D/3D flattening logic in NdArrayViewer with Id = std::uint32_t plus the product(nCells, std::uint32_t{1}) bound assert gives consistent, wider indexing across MaskedView, NdArrayView, and NdArrayVector. The C-order / non‑C-order formulas look correct, and delegating all operator() paths through viewer::at removes duplication without changing semantics.

Also applies to: 98-107, 139-139, 288-304

src/diagnostic/diagnostic_writer.hpp (1)

6-6: Removing unused cppdict include is a good cleanup

This header only depends on DiagnosticProperties, so dropping the extra include reduces coupling without affecting the interface.

src/core/data/grid/gridlayoutdefs.hpp (1)

5-8: Explicit HybridQuantity and <cstddef> includes are appropriate

Bringing in core/hybrid/hybrid_quantities.hpp where HybridQuantity is used, and <cstddef> for size types, makes this header more self-contained and avoids relying on transitive includes.

src/core/data/grid/gridlayoutimplyee.hpp (1)

413-441: Yee moment/mapping helpers and new Bx/By/Bz→moments stencils look consistent.

The switch to CTAD std::array{...} and the new BxToMoments/ByToMoments/BzToMoments implementations give normalized weights and complete stencils in 2D/3D, aligned with the declared centerings. No issues spotted here.

Also applies to: 446-507, 511-537, 541-569, 574-603, 609-723, 784-1165

src/hdf5/detail/h5/h5_file.hpp (1)

16-23: Chunked/resizable dataset helpers and existence checks look good.

Configurable CHUNK_SIZE, create_chunked_data_set, and the resizable 1D/2D helpers integrate cleanly with exist()/getDataSet(), and the parent-group creation mirrors prior patterns. The checked getDataSet improves safety in production builds.

Also applies to: 105-141, 275-287

src/diagnostic/diagnostic_model_view.hpp (1)

37-38: Tmp field/tensor plumbing and hierarchy helpers integrate cleanly.

Using named tmp resources (PHARE_sumField/Vec/Tensor) as shared scratch, wrapping the momentum‑tensor refine via fillPopMomTensor, and exposing localLevelBoxes plus tmp*/getCompileTimeResourcesViewList() all align with the existing resource‑manager and AMR patterns. No issues spotted.

Based on learnings

Also applies to: 62-81, 93-99, 145-172, 183-195, 218-221

src/core/data/grid/gridlayout.hpp (1)

5-14: New Bx/By/Bz→moments and AMR indexing helpers are consistent with existing grid logic.

The Bx/By/BzToMoments accessors cleanly forward to the impl, and the AMRBoxFor/AMRGhostBoxFor + amr_lcl_idx* helpers match the AMR/local box usage in convert_to_fortran_primal and the VTKHDF writers. No correctness or performance issues noticed in the new pieces.

Also applies to: 101-103, 821-845, 1027-1046, 1180-1195, 1220-1226

src/diagnostic/detail/vtkh5_writer.hpp (1)

31-77: VTK H5Writer lifecycle and file‑flag handling look correct.

Construction, make_unique, and the dump/dump_level logic (especially resetting file_flags to READ_WRITE after the first write) align with the existing HDF5 writer semantics and avoid repeated truncation. No issues found.

Also applies to: 79-88, 90-107, 118-125, 126-155, 159-174, 177-191

Comment on lines +7 to +13
#include "core/utilities/span.hpp"
#include "core/utilities/types.hpp"
#include "core/data/field/field.hpp"
#include "core/utilities/box/box.hpp"
#include "core/data/grid/gridlayoutdefs.hpp"
#include "core/data/ndarray/ndarray_vector.hpp"
#include "core/data/tensorfield/tensorfield.hpp"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Add <stdexcept> for std::runtime_error instead of relying on transitive includes

This header throws std::runtime_error in convert_to_primal, but <stdexcept> is not explicitly included here. To avoid depending on transitive includes (and potential ODR/compile issues if upstream headers change), it’s better for this header to include <stdexcept> itself.

Suggested diff:

-#include <string>
-#include <algorithm>
+#include <string>
+#include <algorithm>
+#include <stdexcept>

Please confirm this compiles cleanly across your TU set after adding the include.

Also applies to: 16-18


I'll help you verify this review comment. Let me examine the file and confirm the issues.


---

🏁 Script executed:

```shell
#!/bin/bash
# First, let's view the full algorithm.hpp file to see all includes and context
cat src/core/utilities/algorithm.hpp

Length of output: 4090


🏁 Script executed:

#!/bin/bash
# Search for convert_to_primal function and std::runtime_error usage
rg -n "convert_to_primal|std::runtime_error" src/core/utilities/algorithm.hpp -A5 -B2

Length of output: 846


🏁 Script executed:

#!/bin/bash
# Check if stdexcept is already included anywhere in the file
rg -n "stdexcept" src/core/utilities/algorithm.hpp

Length of output: 0


Add <stdexcept> header to resolve missing include for std::runtime_error

The verification confirms the issue. Line 99 of src/core/utilities/algorithm.hpp throws std::runtime_error, but <stdexcept> is not explicitly included. The file currently relies on transitive includes from upstream headers (lines 7–13 show only project-specific includes; lines 16–17 show <string> and <algorithm>).

Add #include <stdexcept> after the existing standard library includes to satisfy the direct dependency:

#include <string>
#include <algorithm>
+#include <stdexcept>

This ensures the header is self-contained and does not break if upstream dependencies change.

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

🤖 Prompt for AI Agents
In src/core/utilities/algorithm.hpp around lines 7 to 13, the header throws
std::runtime_error on line 99 but does not include <stdexcept>, relying on
transitive includes; add a direct include for <stdexcept> (place it alongside
the other standard library includes, e.g., after the existing <string> and
<algorithm> includes) so the header is self-contained and no longer depends on
upstream headers for std::runtime_error.

Comment on lines 9 to 22
#include <array>
#include <iomanip>
#include <optional>
#include <string>
#include <algorithm>
#include <cinttypes>
#include <cmath>
#include <numeric>
#include <tuple>
#include <string>
#include <vector>
#include <cassert>
#include <cstdint>
#include <iomanip>
#include <numeric>
#include <sstream>
#include <optional>
#include <algorithm>
#include <stdexcept>

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add <cstdlib> for std::getenv

get_env calls std::getenv, which is declared in <cstdlib>. It’s safer/standard-compliant to include it explicitly rather than relying on transitive includes.

 #include <array>
 #include <cmath>
 #include <tuple>
 #include <string>
 #include <vector>
 #include <cassert>
 #include <cstdint>
 #include <iomanip>
 #include <numeric>
 #include <sstream>
 #include <optional>
 #include <algorithm>
 #include <stdexcept>
+ #include <cstdlib>
📝 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
#include <array>
#include <iomanip>
#include <optional>
#include <string>
#include <algorithm>
#include <cinttypes>
#include <cmath>
#include <numeric>
#include <tuple>
#include <string>
#include <vector>
#include <cassert>
#include <cstdint>
#include <iomanip>
#include <numeric>
#include <sstream>
#include <optional>
#include <algorithm>
#include <stdexcept>
#include <array>
#include <cmath>
#include <tuple>
#include <string>
#include <vector>
#include <cassert>
#include <cstdint>
#include <iomanip>
#include <numeric>
#include <sstream>
#include <optional>
#include <algorithm>
#include <stdexcept>
#include <cstdlib>
🤖 Prompt for AI Agents
In src/core/utilities/types.hpp around lines 9 to 22, the header list is missing
the <cstdlib> include required for std::getenv; add #include <cstdlib> to the
include block so get_env uses the standard-declared getenv symbol (place it with
the other C++ standard headers near <cstdint> or similar).

@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 19, 2025
@PhilipDeegan
Copy link
Member Author

PhilipDeegan commented Nov 19, 2025

in conjunction with #1100

we have the following renders

image image image image

and I can see some variation across timesteps, not much as it's only 3 timesteps worth of diags

dump_all_diags(setup_model().populations)
self.simulator = Simulator(simulation).run().reset()

# maybe use vtk python module to generate artifacts here
Copy link
Member

Choose a reason for hiding this comment

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

maybe we can have an issue on that

dump_all_diags(setup_model().populations)
self.simulator = Simulator(simulation).run().reset()

# maybe use vtk python module to generate artifacts here
Copy link
Member

Choose a reason for hiding this comment

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

we could have an issue on that

return dst;
}

template<typename Field_t, typename PQ, std::size_t rank>
Copy link
Member

Choose a reason for hiding this comment

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

if we have Field_t can't we use Field_t::physical_quantity_type for PQ?

PhysicalQuantity const qty //
)
{
using PQ = PhysicalQuantity;
Copy link
Member

Choose a reason for hiding this comment

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

🚽

for (std::uint8_t i = 0; i < dimension; ++i)
ghostBox.upper[i] += (centerings[i] == QtyCentering::primal) ? 1 : 0;
return ghostBox;
box.upper[i] += (centerings[i] == QtyCentering::primal) ? 1 : 0;
Copy link
Member

Choose a reason for hiding this comment

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

we also have this +1 code in toFieldBox() that takes a gridlayout, maybe this could be a toPrimal layout static method that the toFieldBox and this method use?

Copy link
Member Author

Choose a reason for hiding this comment

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

I would argue it should be here, and update the toFieldBox to use this?

Copy link
Member

Choose a reason for hiding this comment

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

if by "here" you mean a function in the layout I agree

static_assert(sizeof...(Indexes) == dim);
// static_assert((... && std::is_unsigned_v<decltype(indexes)>)); TODO : manage later if
// this test should be included
using Id = std::uint32_t;
Copy link
Member

Choose a reason for hiding this comment

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

is that used?

Copy link
Member Author

@PhilipDeegan PhilipDeegan Nov 19, 2025

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

I don't know why I did not see the usage of Idx before now it's obvious...
I don't know if I like "hiding" the const like that... on the other hand having function(Idx i) or function(Id const i) you still have to find out what the type means...

auto ds = h5file.getDataSet(level_data_path(layout.levelNumber()));
for (std::uint16_t i = 0; i < X_TIMES; ++i)
{
ds.select({data_offset, 0}, {size, 1}).write_raw(frimal.data());
Copy link
Member

Choose a reason for hiding this comment

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

unless you know exactly the highfive API, this is a bit obscure to understand
what {data_offset, 0}, {size, 1} are for instance ? maybe naming them would help ?
or what select does maybe a comment ?

Copy link
Member Author

Choose a reason for hiding this comment

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

select is the location, and order/direction for the data to be written

https://github.com/highfive-devs/highfive/blob/main/src/examples/create_extensible_dataset.cpp#L38

Copy link
Member

Choose a reason for hiding this comment

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

ok but it's still a bit hard to read if you do not know highfive.
a little comment explaining why the first and second arguments are what they are would be nice. In particular the 0 and 1.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (9)
src/diagnostic/detail/vtkh5_type_writer.hpp (9)

24-24: Avoid using namespace in a header to limit symbol pollution

using namespace hdf5::h5; inside a header pulls all HighFive symbols into PHARE::diagnostic::vtkh5, which can make ADL/call-site resolution harder and increase risk of collisions for any includer that also opens PHARE::diagnostic::vtkh5. A narrower alias such as:

using HighFiveFile = hdf5::h5::HighFiveFile;

(or just fully qualifying the few used types) keeps dependencies explicit and local while staying minimal.


29-35: Tighten base usage to avoid // in HDF5 paths

With base = "/VTKHDF/", expressions like base + "/Steps/Values" and base + "/Steps" generate paths containing a double slash (e.g. "/VTKHDF//Steps/Values"). HDF5 typically tolerates this, but it’s visually confusing and brittle if any path parsing code assumes normalized names.

You can avoid this by either dropping the trailing slash in base or concatenating without a leading slash in the suffix:

std::string static inline const base = "/VTKHDF";
// ...
h5file.create_resizable_1d_data_set<FloatType>(base + "/Steps/Values");

or

std::string static inline const base = "/VTKHDF/";
// ...
h5file.create_resizable_1d_data_set<FloatType>(base + "Steps/Values");

Also applies to: 176-183


29-30: Document why diagnostics are stored as float

You consistently downcast to FloatType = float for datasets and attributes (steps, spacing, origin, tensor fields). Given your earlier note about ParaView’s VTKHDF reader not handling doubles, this is clearly intentional but non-obvious to someone skimming the file later, who might be tempted to “fix” it back to double.

A one‑line comment near using FloatType = float; (e.g. “VTKHDF/ParaView reader currently expects single precision”) would make this constraint explicit without adding code complexity.

Also applies to: 95-98, 176-183, 237-239


46-52: Clarify 1D/2D AMRBox layout vs 3D boxValsIn3D width

AMRBox is always created with width boxValsIn3D = 6, but for lower dimensions you only write dimension * 2 columns via:

auto const vtk_boxes = flatten_boxes(boxes);          // 2 * dimension entries
amrbox_ds.select({box_offset, 0}, {boxes.size(), dimension * 2}).write(vtk_boxes);

leaving the remaining coordinates to whatever fill value the dataset uses (likely zero).

If this relies on the VTKHDF reader interpreting missing trailing dimensions as collapsed (e.g. z=[0,0] in 2D/1D), it would be helpful to either:

  • Explicitly write the remaining columns as zeros for all dims, or
  • Add a brief comment stating that the unused coordinates are intentionally left to the dataset fill value and are interpreted as collapsed dimensions.

This makes the 1D/2D → 3D mapping more obvious and avoids surprises if default fill behavior ever changes.

Also applies to: 96-97, 259-263, 326-342


95-98: Check Spacing attribute size for lower dimensions

Spacing is written as:

auto const mesh_size = typewriter->h5Writer_.modelView().cellWidth();
return core::for_N_make_array<dimension>(
    [&](auto i) { return static_cast<float>(mesh_size[i] / std::pow(2, lvl)); });
...
level_group.template createAttribute<std::array<float, dimension>>("Spacing",
                                                                   level_spacing(ilvl));

So in 1D/2D runs the attribute has 1 or 2 components, while other attributes (Origin) are always 3‑component arrays.

VTK’s OverlappingAMR examples typically use 3‑component spacing vectors. If the VTKHDF reader expects exactly 3 entries, we may want to always emit 3 components and pad the unused ones with 1.0 (or equivalent) for lower dimensions. If it already accepts dimension‑sized spacing arrays, then a short comment indicating that behavior would prevent future “normalization” attempts that could break compatibility.

Also applies to: 118-123, 265-269


118-123: Reuse modelView member instead of re-querying it

VTKFileWriter already stores a reference to ModelView:

ModelView& modelView = typewriter->h5Writer_.modelView();

but level_spacing calls back through typewriter->h5Writer_.modelView() again. For both clarity and to keep dependencies minimal, you could just use the existing member:

auto const mesh_size = modelView.cellWidth();

This keeps the data flow obvious and avoids re-traversing the stack of owners.

Also applies to: 154-160


125-128: Make the rho-based local_box assumption explicit

local_box() uses:

auto static constexpr primal_qty = physical_quantity_type::rho;

auto local_box(auto const& layout) const
{
    return layout.AMRToLocal(layout.AMRBoxFor(primal_qty));
}

and its size() is then used to size writes for all scalar and tensor fields, regardless of the actual quantity being written.

This implies:

  • All point-data diagnostics share the same AMR box as rho once converted to primal centering, and
  • convert_to_fortran_primal fills exactly that local region.

If that invariant ever stops holding (e.g. diagnostics with different staggering or layouts), offsets and dataset extents will silently mismatch. I’d suggest either:

  • Adding a brief comment documenting that all fields are assumed to share rho’s AMR topology after conversion, or
  • Deriving the box from the specific layout/field being written if that’s straightforward.

That keeps this coupling visible to future refactors.

Also applies to: 220-222, 237-241


282-306: Document MPI collect + prefix-sum assumption for offsets

Both resize_data and resize_boxes use the pattern:

auto const rank_data_size = core::mpi::collect(...); // or collect(boxes.size())
auto const new_size = data_offset + core::sum(rank_data_size);
point_data_ds.resize({new_size, N});
for (int i = 0; i < core::mpi::rank(); ++i)
    data_offset += rank_data_size[i];

and similarly for box_offset. This relies on core::mpi::collect returning, on every rank, a container indexed by global rank (i.e. an allgather), so that each rank can compute its own prefix sum to get a unique offset.

If collect were ever changed to behave differently (e.g. gather to rank 0 only, or use a subcommunicator), this would break offsets in a non-obvious way. A short comment like “collect is assumed to be an allgather over MPI_COMM_WORLD; we then prefix-sum to get per-rank offsets” (or factoring this into a small helper) would make the assumption explicit and protect against future refactors of the MPI layer.

Also applies to: 310-342


216-229: Double-check consistency between local_box size and convert_to_fortran_primal

Both scalar and tensor writes compute:

auto const size = local_box(layout).size();
...
ds.select({data_offset, 0 or c}, {size, 1}).write_raw(frimal[?].data());

where frimal is produced via convert_to_fortran_primal(...) into a modelView-owned temporary. This assumes that:

  • The temporary holds exactly size primal interior values (no ghosts), laid out contiguously in Fortran order, and
  • local_box(layout) refers to that same interior region.

Given the comment in convert_to_fortran_primal about not working on ghost boxes, this is probably correct, but any future change to the temporary’s extent or to local_box would silently desynchronize the HDF5 write. A brief comment stating that size is the number of interior primal points in the converted buffer would help lock in this invariant.

Also applies to: 232-248

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between caa898e and 0cc4fd2.

📒 Files selected for processing (4)
  • src/diagnostic/detail/vtk_types/electromag.hpp (1 hunks)
  • src/diagnostic/detail/vtk_types/fluid.hpp (1 hunks)
  • src/diagnostic/detail/vtkh5_type_writer.hpp (1 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/diagnostic/detail/vtk_types/electromag.hpp
  • src/diagnostic/detail/vtk_types/fluid.hpp
  • src/hdf5/detail/h5/h5_file.hpp
🧰 Additional context used
📓 Path-based instructions (1)
**/*.hpp

⚙️ CodeRabbit configuration file

Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Files:

  • src/diagnostic/detail/vtkh5_type_writer.hpp
🧠 Learnings (2)
📓 Common learnings
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-07-26T22:04:34.160Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2024-10-09T08:32:15.667Z
Learning: PhilipDeegan has indicated a preference for minimal and efficient code, even after making changes to get a function working. There may be opportunities to remove or optimize parts of the code such as sleep/wait/advances.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 1068
File: src/amr/data/field/coarsening/electric_field_coarsener.hpp:1-2
Timestamp: 2025-09-17T13:35:11.533Z
Learning: PhilipDeegan prefers header guard names that include the full directory path structure, following the pattern PHARE_[PATH_WITH_UNDERSCORES]_HPP. For example, a file at src/amr/data/field/coarsening/electric_field_coarsener.hpp should use PHARE_AMR_DATA_FIELD_COARSENING_ELECTRIC_FIELD_COARSENER_HPP as the header guard.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-10-09T08:32:15.667Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/hdf5/detail/h5/h5_file.hpp:78-79
Timestamp: 2024-09-05T17:02:58.784Z
Learning: Avoid commenting on draft PRs for the user PhilipDeegan.
📚 Learning: 2024-09-09T13:57:02.285Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py:566-568
Timestamp: 2024-09-09T13:57:02.285Z
Learning: Avoid commenting on draft PRs for PhilipDeegan unless explicitly requested.

Applied to files:

  • src/diagnostic/detail/vtkh5_type_writer.hpp
🧬 Code graph analysis (1)
src/diagnostic/detail/vtkh5_type_writer.hpp (5)
src/diagnostic/diagnostic_model_view.hpp (1)
  • dimension (30-60)
src/core/utilities/box/box.hpp (5)
  • box (53-53)
  • i (99-99)
  • i (99-99)
  • size (78-88)
  • size (78-78)
src/core/data/tensorfield/tensorfield.hpp (8)
  • i (181-181)
  • i (181-181)
  • i (182-182)
  • i (182-182)
  • size (208-208)
  • size (208-208)
  • tensor_field_dim_from_rank (17-24)
  • tensor_field_dim_from_rank (17-17)
src/core/utilities/types.hpp (2)
  • for_N_make_array (508-511)
  • for_N_make_array (508-508)
src/core/utilities/algorithm.hpp (4)
  • convert_to_fortran_primal (103-135)
  • convert_to_fortran_primal (103-107)
  • convert_to_fortran_primal (138-147)
  • convert_to_fortran_primal (138-142)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: Analyze (cpp)
  • GitHub Check: build (ubuntu-latest, clang)
🔇 Additional comments (1)
src/diagnostic/detail/vtkh5_type_writer.hpp (1)

165-193: Confirm Steps/Values/NSteps updates are safe under MPI

The constructor always does:

h5file.create_resizable_1d_data_set<FloatType>(base + "/Steps/Values");
auto steps_group = h5file.file().getGroup(base + "/Steps");
if (!steps_group.hasAttribute("NSteps")) { /* create & init 0 */ }
auto steps_attr = steps_group.getAttribute("NSteps");
steps_attr.write(steps_attr.template read<int>() + 1);
// ...
auto ds = h5file.getDataSet(base + "/Steps/Values");
auto const old_size = ds.getDimensions()[0];
ds.resize({old_size + 1});
ds.select({old_size}, {1}).write(timestamp);

If VTKFileWriter is constructed on every MPI rank, this will:

  • Increment NSteps once per rank, not once per logical timestep, and
  • Potentially resize and append to Steps/Values concurrently from multiple ranks.

If only rank 0 ever constructs VTKFileWriter, this is fine; otherwise, these operations probably need to be root‑only or explicitly collective (depending on how HighFiveFile is configured for parallel HDF5). It would be good to double‑check the calling pattern and, if appropriate, assert or comment that only a single writer instance per file/timestep exists.


auto static flatten_boxes(auto const& boxes)
{
std::vector<std::array<int, dimension * 2>> data(boxes.size());
Copy link
Member

Choose a reason for hiding this comment

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

*2?

Copy link
Member Author

Choose a reason for hiding this comment

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

lower / upper

using FileOp = HighFive::File::AccessMode;

// https://support.hdfgroup.org/documentation/hdf5/latest/hdf5_chunking.html
static inline auto const CHUNK_SIZE = core::get_env_as("PHARE_H5_CHUNK_SIZE", std::size_t{1024});
Copy link
Member

Choose a reason for hiding this comment

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

I feel the comment should also say something about the default 1024 ?
is there a chance this will even fail in some cases, like 1D simulations with lots of small patches you will end up having chunks larger than datasets

Copy link
Member Author

Choose a reason for hiding this comment

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

with lots of small patches

It's the aggregate of all patch datas, so I don't see how that's relevant

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet