Skip to content

arbitrary mpirun N restarts#888

Open
PhilipDeegan wants to merge 1 commit intoPHAREHUB:masterfrom
PhilipDeegan:restartinator
Open

arbitrary mpirun N restarts#888
PhilipDeegan wants to merge 1 commit intoPHAREHUB:masterfrom
PhilipDeegan:restartinator

Conversation

@PhilipDeegan
Copy link
Member

@PhilipDeegan PhilipDeegan commented Sep 3, 2024

Summary by CodeRabbit

  • New Features

    • Introduced a new framework for initializing electromagnetic data structures, enhancing flexibility in initialization strategies.
    • Enhanced functionality for scanning groups in HDF5 files, providing better navigation and filtering options.
    • Added a utility function for converting vectors to fixed-size arrays, improving type safety and performance.
    • Introduced a new class for initializing particles from HDF5 data, streamlining particle management.
    • Improved the AMRToLocal function with new overloads for enhanced performance and flexibility.
    • Added new methods for calculating domain and ghost boxes, enhancing grid layout functionality.
    • Updated particle initialization logic to include population names, improving specificity.
  • Bug Fixes

    • Improved method signatures for const-correctness, enhancing clarity and usability.
    • Enhanced the robustness of data handling in particle initialization logic.
  • Chores

    • Updated namespace structures for better organization and clarity.
    • Modified CMake configurations to reflect updated library dependencies.

@PhilipDeegan PhilipDeegan marked this pull request as draft September 3, 2024 12:54
@coderabbitai
Copy link

coderabbitai bot commented Sep 3, 2024

📝 Walkthrough

Walkthrough

This change refactors the PHARE initialization system to support restart workflows from SAMRAI HDF5 files. It extracts the monolithic populateDict() function from the main __init__.py into modular initializers (general, user_fns, samrai_hdf5), moves particle and electromagnetics initializers to the AMR namespace with factory-based creation, and introduces HDF5 scanning utilities. The changes also update initialization dictionaries to use snake_case naming conventions and add support for loading particles and fields from HDF5 restart files.

Changes

Cohort / File(s) Summary
Python API refactoring
pyphare/pyphare/pharein/__init__.py, pyphare/pyphare/pharein/initialize/__init__.py
Removes legacy wrappers (getSimulation, _patch_data_ids, _serialized_simulation_string, py_fn_wrapper, fn_wrapper) and adds LoadBalancer to public exports. Delegates populateDict to modular initializers via initialize.general and conditional submodule population.
Modular Python initializers
pyphare/pyphare/pharein/initialize/general.py, pyphare/pyphare/pharein/initialize/user_fns.py, pyphare/pyphare/pharein/initialize/samrai_hdf5.py
New modules implementing populateDict and helper functions to build PHARE configuration dictionaries. general.py contains restart data helpers, I/O normalization wrappers (py_fn_wrapper, fn_wrapper), type-safe adders, and comprehensive dictionary population. user_fns.py handles user-function initialization for electromagnetics and particles. samrai_hdf5.py handles HDF5-based particle population initialization.
Python simulation validation
pyphare/pyphare/pharein/simulation.py
Adds check_init_options to validate init_options format and normalize directory paths. Integrates into the wrapper's validation flow.
Python test utilities
pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py, pyphare/pyphare/pharesee/hierarchy/patchdata.py
EqualityReport refactored to construct and return multi-line strings instead of printing; call now returns self for chaining. Adds imports to patchdata.py.
C++ electromagnetics initialization
src/amr/data/electromag/electromag_initializer.hpp
Introduces polymorphic electromagnetics initializer framework with ElectromagInitializer base class, ElectromagUserFuncInitializer, ElectromagSamraiH5Initializer, and factory for strategy selection.
C++ field HDF5 initializer
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
Adds SamraiHDF5FieldInitializer template for loading fields from HDF5, computing overlaps, and copying data elementwise.
C++ SAMRAI HDF5 interface
src/amr/data/initializers/samrai_hdf5_initializer.hpp
Introduces SamraiH5Interface singleton for collecting and querying patch data from SAMRAI restart files; provides box intersection queries and file scanning.
C++ particle initializers
src/amr/data/particles/initializers/particle_initializer_factory.hpp, src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
Moves ParticleInitializerFactory from core to amr namespace; adds samraih5 branch under PHARE_HAS_HIGHFIVE. Introduces SamraiHDF5ParticleInitializer for loading particles from HDF5.
C++ core particle initializer
src/core/data/ions/particle_initializers/particle_initializer.hpp, src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp
Updates ParticleInitializer and MaxwellianParticleInitializer signatures to accept popname parameter for population-aware initialization.
C++ HybridModel refactoring
src/amr/physical_models/hybrid_model.hpp
Adds nested _Initializers struct to encapsulate particle and electromagnetics initializers; updates ParticleInitializerFactory reference to amr namespace; delegates initialization to initializers_ members; releases initializers_ after restart registration.
C++ initialization support
src/amr/level_initializer/hybrid_level_initializer.hpp
Removes virtual keyword from initialize method.
C++ core data structures
src/core/data/electromag/electromag.hpp, src/core/data/vecfield/vecfield_initializer.hpp, src/core/data/grid/gridlayout.hpp, src/core/data/ndarray/ndarray_vector.hpp, src/core/utilities/box/box.hpp, src/core/utilities/types.hpp
Adds type aliases to Electromag; removes initialize method and Binit_ member. VecFieldInitializer::initialize now const. GridLayout adds levelNumber() accessor, domainBoxFor/ghostBoxFor methods, and updated AMRToLocal overloads. NdArrayViewer adds variadic idx and at methods with bounds checking. Adds box_iterator::operator== and to_array utility function.
C++ HDF5 utilities
src/hdf5/detail/h5/group_scanner.hpp, src/hdf5/detail/h5/h5_file.hpp
Adds GroupScanner for recursive HDF5 group traversal with filtering. Updates HighFiveFile with scan_for_groups method, auto file() accessors, and updated operator= signatures.
C++ core includes
src/core/data/ions/ions.hpp, src/core/CMakeLists.txt
Removes particle_initializer_factory.hpp include and from build sources.
C++ type system
src/phare_core.hpp, src/simulator/phare_types.hpp
Removes ParticleInitializerFactory_t from core types; updates simulator PHARE_Types to reference amr::ParticleInitializerFactory.
Build configuration
src/amr/CMakeLists.txt, tests/amr/data/particles/initializer/CMakeLists.txt, tests/core/numerics/ion_updater/CMakeLists.txt
Adds conditional HighFive linking to amr target. Updates particle initializer and ion updater test CMakeLists to link phare_amr instead of phare_core.
Test data structure
res/cmake/test.cmake
Moves particle_initializer from core data tests to amr data tests.
Test updates
tests/amr/data/particles/initializer/test_main.cpp, tests/amr/models/test_models.cpp, tests/amr/tagging/test_tagging.cpp, tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp, tests/core/numerics/ion_updater/test_updater.cpp
Updates particle initializer include path from core to amr; changes dict keys to snake_case and initializer names to lowercase; updates ParticleInitializerFactory namespace references; adds popname parameter to loadParticles calls; adds dict_ members and factory-based initialization paths.
New restart test
tests/simulator/test_init_from_restart.py
Adds RestartsParserTest to validate restart workflows, including simulation setup, data loading, hierarchy comparison.
Test suite configuration
tests/simulator/CMakeLists.txt
Adds new MPI test invocation for test_init_from_restart.py; normalizes whitespace.
Minor fixes
src/core/data/field/initializers/field_user_initializer.hpp
Corrects header guard macro name typo.

Sequence Diagram(s)

sequenceDiagram
    participant PyUser as Python User
    participant Pharein as pharein/__init__.py
    participant GenInit as initialize/general
    participant UserInit as initialize/user_fns
    participant H5Init as initialize/samrai_hdf5
    participant CPP as C++ (Factories/Initializers)

    PyUser->>Pharein: create Simulation, call populateDict
    Pharein->>GenInit: populateDict(sim)
    GenInit->>GenInit: build base config<br/>(metadata, AMR, grid, etc.)
    Note over GenInit: handles both user-defined<br/>and HDF5 modes
    alt User Functions Mode
        GenInit->>UserInit: populateDict(sim)
        UserInit->>UserInit: populate_electromag(sim)<br/>populate_particles(sim)
        UserInit-->>GenInit: done
    else SAMRAI HDF5 Mode
        GenInit->>H5Init: populateDict(sim)
        H5Init->>H5Init: configure particles<br/>from HDF5 paths
        H5Init-->>GenInit: done
    end
    GenInit-->>Pharein: complete dict
    Pharein-->>PyUser: return populated dict

    Note over CPP: Initialization at runtime
    PyUser->>CPP: HybridModel created with dict
    CPP->>CPP: _Initializers constructed<br/>ParticleInitializerFactory::create(dict)
    CPP->>CPP: ElectromagInitializerFactory::create(dict)
    Note over CPP: Factories detect initialization mode:<br/>user_fns vs samraih5
    CPP->>CPP: initializers_.particles(pop).loadParticles()
    CPP->>CPP: initializers_.electromag().init()
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • Python initialization refactoring: The delegation from monolithic populateDict() to modular initializers (general, user_fns, samrai_hdf5) requires careful verification that all configuration paths are correctly routed and that edge cases (restart vs. user-function modes) are properly handled.
  • Factory pattern and namespace changes: ParticleInitializerFactory moved from core to amr; verify all call sites updated and that the factory correctly dispatches between maxwellian and samraih5 branches based on configuration.
  • C++ initializer polymorphism: Review ElectromagInitializer/ElectromagInitializerFactory and SamraiHDF5ParticleInitializer for correct HDF5 integration, box intersection logic, and data copying semantics.
  • HybridModel initialization refactoring: The introduction of _Initializers and the replacement of direct initialization calls with factory-based accessors must maintain the original initialization order and error handling.
  • Grid coordinate transformations: Updates to GridLayout's AMRToLocal overloads and new domainBoxFor/ghostBoxFor methods should be verified for correctness across 1D/2D/3D cases.
  • Test data dictionary updates: Verify snake_case naming conventions are consistently applied across all test dictionaries and that the populated dicts match expected C++ side keys.

Possibly related PRs

  • Simulator template struct #1056: Refactors Simulator/PHARE_Types templates to use a single SimOpts parameter, affecting type aliases and initialization pathways.
  • origin made global #1093: Changes grid layout and AMR↔local coordinate APIs (AMRToLocal, fieldNodeCoordinates) with similar impacts on initialization.
  • Patchghostless #1019: Modifies AMR initialization and particle/ghost handling, including HybridModel/HybridLevelInitializer and SAMRAI HDF5 paths.

Suggested labels

refactoring, posterity

Suggested reviewers

  • nicolasaunai
  • UCaromel

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning No pull request description was provided by the author. The description field is empty, making it impossible to assess whether it relates to the changeset. Add a detailed description explaining the purpose of the changes, the problems they solve, and how the refactoring improves the restart initialization system.
Docstring Coverage ⚠️ Warning Docstring coverage is 4.59% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'arbitrary mpirun N restarts' is vague and uses generic terminology that doesn't clearly convey the main changes. It doesn't specifically describe what was added or changed in the codebase. Use a more descriptive title that clearly explains the primary change, such as 'Add SAMRAI HDF5 restart initialization support' or 'Refactor initialization system for restart compatibility'.
✨ 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

@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

Outside diff range, codebase verification and nitpick comments (2)
tests/simulator/test_samrai_restarts_parser.py (1)

69-93: Is there any redundant code that can be removed?

Based on the learnings from the previous PR, you mentioned that there might be some redundant code, such as sleep/wait/advances, that can be removed to streamline the code.

Please take a look at the test class and let me know if there is any redundant code that can be removed to further streamline it.

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

64-64: Consistent use of FileOp type alias in the constructor.

The constructor update to use FileOp flags is consistent with the introduction of the FileOp type alias and improves type safety and clarity.

Nitpick: Formatting change in the file() method.

The formatting change in the file() method, consolidating its definition into a single line, does not affect its functionality. Consider reverting this change to maintain consistency with the rest of the codebase.

Also applies to: 72-72

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 5933e40 and bf95f01.

Files selected for processing (8)
  • src/core/data/electromag/electromag.hpp (3 hunks)
  • src/core/data/electromag/electromag_initializer.hpp (1 hunks)
  • src/core/data/vecfield/vecfield_initializer.hpp (2 hunks)
  • src/diagnostic/detail/h5writer.hpp (5 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (3 hunks)
  • tests/diagnostic/test_diagnostics.hpp (3 hunks)
  • tests/simulator/test_diagnostics.py (1 hunks)
  • tests/simulator/test_samrai_restarts_parser.py (1 hunks)
Additional context used
Path-based instructions (6)
src/core/data/electromag/electromag_initializer.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/core/data/vecfield/vecfield_initializer.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

tests/diagnostic/test_diagnostics.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Learnings (1)
tests/simulator/test_samrai_restarts_parser.py (1)
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2023-11-25T19:21:40.002Z
Learning: The user has indicated that minimal changes were made to get the function working, but acknowledges that there may still be redundant code present, such as sleep/wait/advances. The user is open to further streamlining the code.
Ruff
tests/simulator/test_samrai_restarts_parser.py

1-1: copy imported but unused

Remove unused import: copy

(F401)


3-3: time imported but unused

Remove unused import: time

(F401)


5-5: datetime imported but unused

Remove unused import: datetime

(F401)


7-7: numpy imported but unused

Remove unused import: numpy

(F401)


8-8: pathlib.Path imported but unused

Remove unused import: pathlib.Path

(F401)


9-9: datetime.timedelta imported but unused

Remove unused import: datetime.timedelta

(F401)


11-11: ddt.data imported but unused

Remove unused import

(F401)


11-11: ddt.unpack imported but unused

Remove unused import

(F401)


18-18: pyphare.pharesee.run.Run imported but unused

Remove unused import: pyphare.pharesee.run.Run

(F401)


19-19: pyphare.simulator.simulator.Simulator imported but unused

Remove unused import: pyphare.simulator.simulator.Simulator

(F401)


22-22: tests.diagnostic.dump_all_diags imported but unused

Remove unused import: tests.diagnostic.dump_all_diags

(F401)


23-23: pyphare.pharesee.hierarchy.patchdata.ParticleData imported but unused

Remove unused import: pyphare.pharesee.hierarchy.patchdata.ParticleData

(F401)


24-24: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 imported but unused

Remove unused import: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5

(F401)

Additional comments not posted (25)
src/core/data/electromag/electromag_initializer.hpp (2)

12-17: LGTM!

The code changes are approved.


19-34: LGTM!

The code changes are approved.

src/core/data/vecfield/vecfield_initializer.hpp (2)

29-29: LGTM!

Adding the const qualifier to the initialize method is a good change that enhances the clarity of the method's intended use and potentially allows for optimizations by the compiler. The method does not modify the state of the class instance, so the const qualifier is appropriate.


42-42: LGTM!

Adding the const qualifier to the initializeComponent_ method is a good change that enhances the clarity of the method's intended use and potentially allows for optimizations by the compiler. The method does not modify the state of the class instance, so the const qualifier is appropriate.

src/core/data/electromag/electromag.hpp (5)

12-12: Verify the purpose and necessity of the new header file.

The new header file electromag_initializer.hpp is included. Ensure that the functionality provided by this header is necessary and used within the Electromag class.


21-21: LGTM!

The type alias This is a good addition to simplify referring to the class type within its own scope.


24-25: LGTM!

The changes to the member variables are good:

  • The additional whitespace in the vecfield_type alias improves readability.
  • The use of auto static constexpr for the dimension member improves type inference and clarity.

33-41: LGTM!

The new constructor and member variable are good additions:

  • The constructor allows for flexible initialization of the Electromag class using a dictionary.
  • The E and B fields are initialized consistently with the provided dictionary.
  • The dict_ member variable stores the magnetic initializer for later use in the initialize method.

49-50: LGTM!

The changes to the initialize method are good:

  • The use of the ElectromagInitializerFactory and the dict_ member allows for dynamic and flexible initialization.
  • The initialization logic is encapsulated within the created initializer, which improves modularity and maintainability.
tests/simulator/test_samrai_restarts_parser.py (3)

29-32: LGTM!

The code changes are approved.


46-57: LGTM!

The code changes are approved.


60-65: LGTM!

The code changes are approved.

tests/simulator/test_diagnostics.py (1)

209-210: LGTM!

The updated assertion is a reasonable change that accommodates semantic versioning conventions where the patch version can contain additional information like pre-release identifiers. It still ensures that the major and minor version components are numeric.

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

16-16: Improved type safety and code clarity.

The introduction of the FileOp type alias enhances code clarity and type safety by providing a more descriptive name for the file access mode type and replacing the use of unsigned for the flags parameter.


46-46: Consistent use of FileOp type alias.

The method signature update for createHighFiveFile to accept FileOp flags is consistent with the introduction of the FileOp type alias and improves type safety and clarity.

tests/diagnostic/test_diagnostics.hpp (4)

19-19: LGTM!

The change simplifies the file opening logic by using a single access mode, Overwrite, instead of a combination of flags. This improves code clarity and expressiveness.


50-50: LGTM!

The change enhances type safety and clarity by explicitly tying the flags parameter to the HiFile::AccessMode type. This improves code expressiveness and reduces the likelihood of type-related bugs.


94-94: LGTM!

The change improves const-correctness by indicating that the out_ member variable is not modified after initialization. This enhances code clarity and expressiveness.


95-95: LGTM!

The change reinforces type consistency throughout the structure by using HiFile::AccessMode const for the flags_ member variable. This improves code clarity, expressiveness, and const-correctness.

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

53-53: Improved clarity for file access mode.

The change from using a combination of flags to a structured enumeration enhances code clarity and maintainability.


59-59: Improved type safety for file access mode.

Using HiFile::AccessMode instead of unsigned for the _flags parameter improves type safety and makes the code more expressive.


71-72: Consistent use of HiFile::AccessMode for file access mode.

Using HiFile::AccessMode for the flags variable in make_unique is consistent with the updated constructor and improves type safety.


97-97: Improved type safety for makeFile method.

Using HiFile::AccessMode instead of unsigned for the file_flag parameter improves type safety and is consistent with the other updates.


171-171: Improved type safety for flags member variable.

Using HiFile::AccessMode instead of unsigned for the flags member variable improves type safety and is consistent with the other updates.


181-181: Improved type safety for file_flags map.

Using HiFile::AccessMode instead of unsigned for the values in the file_flags map improves type safety and is consistent with the other updates.

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

Outside diff range, codebase verification and nitpick comments (2)
src/core/data/electromag/electromag.hpp (1)

49-50: LGTM!

The modification of the initialize method to use the ElectromagInitializerFactory to create an initializer based on the dict_ member is approved. The change indicates a shift in how the class handles initialization, moving from a dedicated initializer object to a more flexible dictionary-based approach.

Remove the commented out line.

The commented out line that clears the dict member after initialization is not necessary, as the dict_ member is not used after initialization.

Apply this diff to remove the commented out line:

-            // dict = initializer::PHAREDict{}; // clear ?
tests/simulator/test_samrai_restarts_parser.py (1)

46-57: Improve the traverse_h5_for_groups_recursive function.

Consider the following improvements:

  1. Use os.path.join to construct the paths instead of string concatenation. This will make the code more readable and less error-prone.

  2. Use a single dictionary to store both the attributes and data. This will simplify the code and reduce the number of instance variables in the H5Content class.

Apply this diff to implement the suggested improvements:

+import os

-def traverse_h5_for_groups_recursive(h5content: "H5Content", group, path=""):
+def traverse_h5_for_groups_recursive(h5content: "H5Content", group, path="/"):
     if "level_0000" in path:
         for key in group.attrs:
-            h5content.attr[f"{path}/{key}"] = group.attrs[key]
+            h5content.content[os.path.join(path, key)] = group.attrs[key]
     if isinstance(group, h5py._hl.group.Group):
         for key in group:
-            kpath = f"{path}/{key}"
+            kpath = os.path.join(path, key)
             traverse_h5_for_groups_recursive(h5content, group[key], path=kpath)
     else:
         if "level_0000" not in path:
             return
-        h5content.data[path] = group
+        h5content.content[path] = group
 class H5Content:
     def __init__(self, path):
         self.file = h5py.File(path, "r")
-        self.data = {}
-        self.attr = {}
+        self.content = {}
         traverse_h5_for_groups_recursive(self, self.file)
Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between bf95f01 and b7147a9.

Files selected for processing (4)
  • src/core/data/electromag/electromag.hpp (3 hunks)
  • src/core/data/electromag/electromag_initializer.hpp (1 hunks)
  • src/core/data/vecfield/vecfield_initializer.hpp (2 hunks)
  • tests/simulator/test_samrai_restarts_parser.py (1 hunks)
Files skipped from review due to trivial changes (2)
  • src/core/data/electromag/electromag_initializer.hpp
  • src/core/data/vecfield/vecfield_initializer.hpp
Additional context used
Path-based instructions (1)
src/core/data/electromag/electromag.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Learnings (1)
tests/simulator/test_samrai_restarts_parser.py (1)
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2023-11-25T19:21:40.002Z
Learning: The user has indicated that minimal changes were made to get the function working, but acknowledges that there may still be redundant code present, such as sleep/wait/advances. The user is open to further streamlining the code.
Ruff
tests/simulator/test_samrai_restarts_parser.py

1-1: copy imported but unused

Remove unused import: copy

(F401)


3-3: time imported but unused

Remove unused import: time

(F401)


5-5: datetime imported but unused

Remove unused import: datetime

(F401)


7-7: numpy imported but unused

Remove unused import: numpy

(F401)


8-8: pathlib.Path imported but unused

Remove unused import: pathlib.Path

(F401)


9-9: datetime.timedelta imported but unused

Remove unused import: datetime.timedelta

(F401)


11-11: ddt.data imported but unused

Remove unused import

(F401)


11-11: ddt.unpack imported but unused

Remove unused import

(F401)


18-18: pyphare.pharesee.run.Run imported but unused

Remove unused import: pyphare.pharesee.run.Run

(F401)


19-19: pyphare.simulator.simulator.Simulator imported but unused

Remove unused import: pyphare.simulator.simulator.Simulator

(F401)


22-22: tests.diagnostic.dump_all_diags imported but unused

Remove unused import: tests.diagnostic.dump_all_diags

(F401)


23-23: pyphare.pharesee.hierarchy.patchdata.ParticleData imported but unused

Remove unused import: pyphare.pharesee.hierarchy.patchdata.ParticleData

(F401)


24-24: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 imported but unused

Remove unused import: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5

(F401)

Additional comments not posted (9)
src/core/data/electromag/electromag.hpp (7)

12-12: LGTM!

The inclusion of the new header file electromag_initializer.hpp is approved. The file name is expressive and follows the naming convention of the project.


21-21: LGTM!

The introduction of the type alias This is approved. The name is expressive and follows the naming convention of the project.


24-24: LGTM!

The alignment of the type alias vecfield_type is approved. The change improves the readability of the code.


25-25: LGTM!

The modification of the dimension member to use auto static constexpr is approved. The change enhances type inference and clarity.


33-33: LGTM!

The addition of the empty line is approved. The change improves the readability of the code by separating the member variables from the constructors.


34-41: LGTM!

The addition of the new constructor that takes an initializer::PHAREDict as an argument is approved. The constructor provides a more flexible way to initialize the Electromag class using a dictionary and follows the rule of three by initializing all the member variables.


84-84: LGTM!

The replacement of the Binit_ member variable with a new member variable dict_, which is initialized with an empty initializer::PHAREDict, is approved. The change is consistent with the modifications made to the constructor and the initialize method.

tests/simulator/test_samrai_restarts_parser.py (2)

1-24: Remove unused imports.

The following imports are unused and should be removed:

  • copy
  • time
  • datetime
  • numpy
  • pathlib.Path
  • datetime.timedelta
  • ddt.data
  • ddt.unpack
  • pyphare.pharesee.run.Run
  • pyphare.simulator.simulator.Simulator
  • tests.diagnostic.dump_all_diags
  • pyphare.pharesee.hierarchy.patchdata.ParticleData
  • pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5

Remove the unused imports to keep the code clean and maintainable.

The previous review comment flagging the unused imports is still valid and applicable.

Tools
Ruff

1-1: copy imported but unused

Remove unused import: copy

(F401)


3-3: time imported but unused

Remove unused import: time

(F401)


5-5: datetime imported but unused

Remove unused import: datetime

(F401)


7-7: numpy imported but unused

Remove unused import: numpy

(F401)


8-8: pathlib.Path imported but unused

Remove unused import: pathlib.Path

(F401)


9-9: datetime.timedelta imported but unused

Remove unused import: datetime.timedelta

(F401)


11-11: ddt.data imported but unused

Remove unused import

(F401)


11-11: ddt.unpack imported but unused

Remove unused import

(F401)


18-18: pyphare.pharesee.run.Run imported but unused

Remove unused import: pyphare.pharesee.run.Run

(F401)


19-19: pyphare.simulator.simulator.Simulator imported but unused

Remove unused import: pyphare.simulator.simulator.Simulator

(F401)


22-22: tests.diagnostic.dump_all_diags imported but unused

Remove unused import: tests.diagnostic.dump_all_diags

(F401)


23-23: pyphare.pharesee.hierarchy.patchdata.ParticleData imported but unused

Remove unused import: pyphare.pharesee.hierarchy.patchdata.ParticleData

(F401)


24-24: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 imported but unused

Remove unused import: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5

(F401)


81-92: Add assertions to the test method.

The test method test_restart_parser reads an HDF5 file and prints some data, but it doesn't have any assertions. To make it a proper test, please add assertions to verify the expected behavior.

The previous review comment suggesting to add assertions to the test method is still valid and applicable.

@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Sep 3, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Sep 3, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Sep 3, 2024
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: 5

Outside diff range, codebase verification and nitpick comments (13)
pyphare/pyphare/pharein/init.py (1)

9-10: The changes enhance error handling. Consider improving the error message.

The new conditional check improves the robustness of the code by ensuring that the function does not proceed with a potentially invalid module.

To provide more context in the error message, consider including the jobname that failed to import:

-    raise RuntimeError("failed to import job")
+    raise RuntimeError(f"Failed to import job module: {jobname}")
tests/core/numerics/ion_updater/CMakeLists.txt (1)

14-14: Issues Found: Dependency Change from phare_core to phare_amr is Problematic

The replacement of phare_core with phare_amr in tests/core/numerics/ion_updater/CMakeLists.txt is problematic for the following reasons:

  • phare_core is still used extensively across the codebase, indicating that it remains a necessary dependency.
  • phare_amr is not declared as a target in the codebase, suggesting it may not be a valid dependency.

Please review the necessity and validity of this change to avoid potential build issues.

Analysis chain

Verify the impact of the dependency change from phare_core to phare_amr.

Ensure that the replacement of phare_core with phare_amr does not introduce any breaking changes or compatibility issues in the project.

Run the following script to verify the impact of the dependency change:

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the impact of the dependency change from `phare_core` to `phare_amr`.

# Test 1: Search for the usage of `phare_core` in the codebase.
# Expect: No occurrences of `phare_core` usage, indicating that the replacement with `phare_amr` is complete.
echo "Searching for the usage of 'phare_core' in the codebase..."
if rg --type cmake $'phare_core'; then
  echo "FAIL: 'phare_core' is still used in the codebase. The replacement with 'phare_amr' may be incomplete."
else
  echo "PASS: 'phare_core' is not used in the codebase."
fi

# Test 2: Search for the declaration of the `phare_amr` target.
# Expect: The `phare_amr` target is declared in the codebase, indicating that it is a valid dependency.
echo "Searching for the declaration of the 'phare_amr' target..."
if rg --type cmake $'(add|declare)_library\(phare_amr'; then
  echo "PASS: The 'phare_amr' target is declared in the codebase."
else
  echo "FAIL: The 'phare_amr' target is not declared in the codebase. It may not be a valid dependency."
fi

Length of output: 2120

pyphare/pyphare/pharein/initialize/samrai_hdf5.py (2)

3-3: Remove the unused import.

The commented out import of pybindlibs.dictator is not used in the file and can be removed.

Apply this diff to remove the unused import:

-# import pybindlibs.dictator as pp

9-9: Rename the unused loop variable.

The loop variable pop is not used in the loop body.

Apply this diff to rename the unused loop variable:

-    for pop_index, pop in enumerate(init_model.populations):
+    for pop_index, _pop in enumerate(init_model.populations):
Tools
Ruff

9-9: Loop control variable pop not used within loop body

Rename unused pop to _pop

(B007)

res/cmake/test.cmake (1)

44-44: Issue Found: New Test Directory Not Referenced in CMake Files

The new test directory tests/amr/data/particles/initializer exists, but there are no references to it in any CMake files. This means the new tests might not be included in the build process, which could lead to them not being executed as part of the test suite. Please update the CMake configuration to ensure these tests are built and run.

  • Ensure that tests/amr/data/particles/initializer is referenced in the appropriate CMake files.
Analysis chain

Verify the impact of the test directory changes on the overall test suite.

The changes involve:

  • Removing the subdirectory tests/core/data/particle_initializer
  • Adding a new subdirectory tests/amr/data/particles/initializer

This indicates a restructuring of the test organization.

Please run the following script to verify the impact of the changes on the test suite:

This script checks:

  1. If the removed tests directory still exists and if any CMake files still reference it.
  2. If the new tests directory exists and is referenced in CMake files.
  3. Tries building and running the tests to ensure the new tests run successfully.

Please run this script and share the results so we can confirm the changes haven't broken the test suite.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: 
# - Verify that the removed tests from `tests/core/data/particle_initializer` are no longer being built and run.
# - Verify that the new tests from `tests/amr/data/particles/initializer` are being built and run successfully.

removed_tests_dir="tests/core/data/particle_initializer"
added_tests_dir="tests/amr/data/particles/initializer"

echo "Checking removed tests directory: $removed_tests_dir"
if [ -d "$removed_tests_dir" ]; then
    echo "Directory $removed_tests_dir still exists. Checking if tests are being built and run..."
    # Check if any CMake files in the removed directory are still being used
    if grep -q "$removed_tests_dir" "$(fd -e cmake)"; then
        echo "FAIL: Found references to $removed_tests_dir in CMake files. Removed tests might still be built."
    else
        echo "PASS: No references to $removed_tests_dir found in CMake files."
    fi
else
    echo "PASS: Directory $removed_tests_dir no longer exists."
fi

echo "Checking added tests directory: $added_tests_dir"
if [ -d "$added_tests_dir" ]; then
    echo "PASS: Directory $added_tests_dir exists."
    # Check if CMake files in the added directory are being used
    if grep -q "$added_tests_dir" "$(fd -e cmake)"; then
        echo "PASS: Found references to $added_tests_dir in CMake files. New tests should be built."
        # Try building and running the tests
        if cmake --build build --target test; then
            echo "PASS: New tests built and ran successfully."
        else
            echo "FAIL: Error building or running the new tests."
        fi
    else
        echo "FAIL: No references to $added_tests_dir found in CMake files. New tests might not be built."
    fi
else
    echo "FAIL: Directory $added_tests_dir does not exist."
fi

Length of output: 1765

src/core/CMakeLists.txt (1)

Re-add particle_initializer_factory.hpp to SOURCES_INC in CMakeLists.txt.

The file particle_initializer_factory.hpp is still being referenced and used in the codebase, as evidenced by its inclusion in several source files and the usage of the ParticleInitializerFactory class. Removing it from the CMakeLists.txt could lead to build errors or missing functionality. Please ensure this file is included in the build configuration.

  • tests/amr/data/particles/initializer/test_main.cpp
  • tests/core/numerics/ion_updater/test_updater.cpp
  • src/amr/physical_models/hybrid_model.hpp
  • src/simulator/phare_types.hpp
Analysis chain

Line range hint 1-53: Verify the impact of removing particle_initializer_factory.hpp on the codebase.

The removal of data/ions/particle_initializers/particle_initializer_factory.hpp from SOURCES_INC suggests a significant change in the particle initialization logic. It's crucial to ensure that this removal doesn't break the existing functionality or cause unintended consequences.

Please run the following script to verify the impact of this change:

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the impact of removing `particle_initializer_factory.hpp` on the codebase.

# Test 1: Search for references to the removed file. Expect: No results.
rg --type cpp $'particle_initializer_factory.hpp'

# Test 2: Search for occurrences of the `ParticleInitializerFactory` class. Expect: No results.
rg --type cpp $'ParticleInitializerFactory'

# Test 3: Verify if particle initializers are still being used in the codebase.
# Search for implementations of the `ParticleInitializer` interface. Expect: At least one result.
ast-grep --lang cpp --pattern $'class $_: public ParticleInitializer'

Length of output: 2173

src/phare_core.hpp (1)

Verify the impact of removing ParticleInitializerFactory on the codebase.

The ParticleInitializerFactory type alias has been removed from src/phare_core.hpp, but it is still used in several other files. This suggests that the removal might be incomplete or that the codebase is transitioning to a new particle initialization mechanism. It is important to verify that this change does not break existing functionality or tests.

  • Files still using ParticleInitializerFactory:
    • src/simulator/phare_types.hpp
    • tests/core/numerics/ion_updater/test_updater.cpp
    • src/amr/physical_models/hybrid_model.hpp
    • tests/amr/data/particles/initializer/test_main.cpp
    • src/amr/data/particles/initializers/particle_initializer_factory.hpp

Consider adding documentation or comments to clarify the new approach to particle initialization.

Analysis chain

Line range hint 46-46: Verify the impact of removing ParticleInitializerFactory on the codebase.

The removal of the ParticleInitializerFactory type alias from the PHARE_Types struct suggests a change in how particle initialization is handled. This could affect how other components interact with particle initialization.

Run the following script to verify the impact of the removal:

Additionally, consider adding a comment to explain the reason for the removal and provide guidance on the new particle initialization mechanism.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the impact of removing `ParticleInitializerFactory` on the codebase.

# Test 1: Search for the usage of `ParticleInitializerFactory`. Expect: No occurrences.
rg --type cpp $'ParticleInitializerFactory'

# Test 2: Search for particle initialization logic. Expect: Occurrences of alternative initialization mechanisms.
rg --type cpp -A 5 $'particle.*init'

Length of output: 49953

src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (3)

40-47: Consider making getRestartFileFullPath() a public static method.

The getRestartFileFullPath() method can be made public as it doesn't access any private members of the class.

Apply this diff to make the method public:

-    NO_DISCARD auto static getRestartFileFullPath(std::string path, int const& idx,
+public:
+    NO_DISCARD auto static getRestartFileFullPath(std::string path, int const& idx,

51-51: Add documentation for the box2dataset member.

The purpose of the box2dataset member is unclear from the provided code. Consider adding documentation to explain its purpose and how it's used.


76-76: Remove the unused dimension member.

The dimension member is not used in the provided code. Consider removing it to improve code clarity.

Apply this diff to remove the unused member:

-    static constexpr auto dimension = GridLayout::dimension;
src/amr/data/particles/initializers/particle_initializer_factory.hpp (2)

89-100: The new case for the "samraih5" initializer looks good!

The addition enhances the functionality of the factory by allowing it to instantiate a new type of particle initializer based on the provided configuration. The code follows the existing pattern of retrieving parameters from the dictionary and creating a unique pointer to the initializer.

One minor suggestion:

Consider extracting the common parameter retrieval logic (e.g., dir, index, mpi_size) into a separate function to improve readability and maintainability. This would also make it easier to add new initializers in the future that require similar parameters.


103-103: Improve the error message.

It is a good practice to handle unsupported or missing initializer names and provide a clear error message. However, the current error message could be improved to include the list of supported initializer names for better clarity.

Consider updating the error message to include the list of supported initializer names, like this:

throw std::runtime_error("No valid Particle Initializer chosen! Supported initializers: 'maxwellian', 'samraih5'.");

This would help users quickly identify the supported initializer names and fix any misconfigurations.

pyphare/pyphare/pharein/initialize/general.py (1)

89-301: Consider refactoring the function into smaller functions.

The populateDict function is quite long and complex. It could benefit from being broken down into smaller functions to improve readability and maintainability.

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between b7147a9 and 0ad9e31.

Files selected for processing (24)
  • pyphare/pyphare/pharein/init.py (5 hunks)
  • pyphare/pyphare/pharein/init.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/init.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/general.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/user_fns.py (1 hunks)
  • pyphare/pyphare/pharein/load_balancer.py (2 hunks)
  • pyphare/pyphare/pharein/simulation.py (3 hunks)
  • res/cmake/test.cmake (2 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/amr/physical_models/hybrid_model.hpp (2 hunks)
  • src/core/CMakeLists.txt (1 hunks)
  • src/core/data/electromag/electromag.hpp (3 hunks)
  • src/core/data/electromag/electromag_initializer.hpp (1 hunks)
  • src/core/data/ions/ions.hpp (1 hunks)
  • src/core/data/vecfield/vecfield_initializer.hpp (2 hunks)
  • src/phare_core.hpp (1 hunks)
  • src/simulator/phare_types.hpp (2 hunks)
  • tests/amr/data/particles/initializer/CMakeLists.txt (1 hunks)
  • tests/amr/data/particles/initializer/test_main.cpp (3 hunks)
  • tests/core/numerics/ion_updater/CMakeLists.txt (1 hunks)
  • tests/core/numerics/ion_updater/test_updater.cpp (4 hunks)
  • tests/simulator/test_samrai_restarts_parser.py (1 hunks)
Files skipped from review due to trivial changes (4)
  • pyphare/pyphare/pharein/initialize/init.py
  • pyphare/pyphare/pharein/load_balancer.py
  • src/core/data/electromag/electromag_initializer.hpp
  • src/core/data/ions/ions.hpp
Files skipped from review as they are similar to previous changes (1)
  • src/core/data/vecfield/vecfield_initializer.hpp
Additional context used
Path-based instructions (6)
src/simulator/phare_types.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/phare_core.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Learnings (1)
tests/simulator/test_samrai_restarts_parser.py (1)
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2023-11-25T19:21:40.002Z
Learning: The user has indicated that minimal changes were made to get the function working, but acknowledges that there may still be redundant code present, such as sleep/wait/advances. The user is open to further streamlining the code.
Ruff
pyphare/pyphare/pharein/initialize/samrai_hdf5.py

9-9: Loop control variable pop not used within loop body

Rename unused pop to _pop

(B007)

tests/simulator/test_samrai_restarts_parser.py

3-3: time imported but unused

Remove unused import: time

(F401)


5-5: datetime imported but unused

Remove unused import: datetime

(F401)


7-7: numpy imported but unused

Remove unused import: numpy

(F401)


8-8: pathlib.Path imported but unused

Remove unused import: pathlib.Path

(F401)


9-9: datetime.timedelta imported but unused

Remove unused import: datetime.timedelta

(F401)


11-11: ddt.data imported but unused

Remove unused import

(F401)


11-11: ddt.unpack imported but unused

Remove unused import

(F401)


18-18: pyphare.pharesee.run.Run imported but unused

Remove unused import: pyphare.pharesee.run.Run

(F401)


22-22: tests.diagnostic.dump_all_diags imported but unused

Remove unused import: tests.diagnostic.dump_all_diags

(F401)


23-23: pyphare.pharesee.hierarchy.patchdata.ParticleData imported but unused

Remove unused import: pyphare.pharesee.hierarchy.patchdata.ParticleData

(F401)


24-24: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 imported but unused

Remove unused import: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5

(F401)


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

Replace with None; initialize within function

(B006)


99-99: Local variable model is assigned to but never used

Remove assignment to unused variable model

(F841)

Additional comments not posted (34)
tests/amr/data/particles/initializer/CMakeLists.txt (1)

14-14: Verify the impact of changing the linked library from phare_core to phare_amr.

Ensure that the phare_amr library provides the necessary features and is compatible with the project's requirements. Verify that this change does not introduce any breaking changes or unintended side effects.

Run the following script to analyze the usage of the phare_core library in the codebase and assess the impact of the change:

If the tests pass, it suggests that the change from phare_core to phare_amr is likely safe and compatible. However, if any of the tests fail, further investigation and potential adjustments may be necessary to ensure a smooth transition.

tests/amr/data/particles/initializer/test_main.cpp (2)

10-10: LGTM: Refactoring enhances modularity.

The update to the header file inclusion path for ParticleInitializerFactory aligns with the refactoring effort to organize particle initializer functionality under the AMR (Adaptive Mesh Refinement) module. This change enhances the modularity of the codebase by separating concerns and improving code organization.


47-48: LGTM: Namespace update aligns with refactoring.

The update to the namespace for ParticleInitializerFactory from the core namespace to the PHARE::amr namespace is consistent with the refactoring effort to organize particle initializer functionality under the AMR module. This change ensures that the correct implementation of ParticleInitializerFactory is being used in the test case and maintains consistency with the updated header file inclusion path.

pyphare/pyphare/pharein/__init__.py (4)

15-15: LGTM!

The change is approved as it aligns with the goal of removing unnecessary complexity.


28-28: LGTM!

The change is approved as it improves the usability of the module by making LoadBalancer a public entity.


72-80: LGTM!

The changes are approved as they improve the modularity and clarity of the initialization process. Encapsulating the initialization logic within dedicated functions enhances the separation of concerns. The conditional logic based on sim.init_options allows for flexibility in the initialization path depending on the configuration.


Line range hint 1-14:

Also applies to: 16-27, 29-71

pyphare/pyphare/pharein/initialize/user_fns.py (3)

5-7: LGTM!

The code changes are approved.


10-16: LGTM!

The code changes are approved.


19-51: LGTM!

The code changes are approved.

src/simulator/phare_types.hpp (1)

33-34: LGTM!

The change to the ParticleInitializerFactory type alias is clean and expressive. It enhances the functionality and flexibility of the particle initialization process by using specific template parameters related to particle arrays and grid layouts.

The change should not have any performance impact.

src/core/data/electromag/electromag.hpp (5)

12-12: Verify the purpose and impact of including the new header file.

The new header file electromag_initializer.hpp is included, which suggests that it provides functionality related to initializing the Electromag class.

Please ensure that:

  • The header file is necessary and serves a clear purpose.
  • The inclusion of the header file does not introduce any unintended side effects or compilation issues.
  • The functionality provided by the header file aligns with the overall design and architecture of the codebase.

21-21: LGTM!

The type alias This improves code readability and maintainability by providing a shorter and more meaningful name for the class within its own scope. The naming convention is consistent with the codebase.


24-25: LGTM!

The changes improve code readability, consistency, and clarity:

  • Aligning the declaration of the vecfield_type type alias enhances readability and consistency.
  • Using auto static constexpr for the dimension member improves type inference and clarity.

33-50: Verify the initialization logic and consider removing the commented-out line.

The changes introduce a new constructor and modify the initialize method to use a dictionary-based approach for initialization, which can be more flexible and extensible.

Please ensure that:

  • The new constructor correctly initializes the E and B members using the values from the dictionary.
  • The initialize method properly creates an initializer using the ElectromagInitializerFactory based on the stored dictionary.
  • The initialization logic is consistent and aligns with the overall design and requirements of the codebase.

Additionally, consider removing the commented-out line dict = initializer::PHAREDict{}; if it is no longer needed.


84-84: LGTM!

Replacing the Binit_ member with dict_ aligns with the change in the initialization approach, moving from a dedicated initializer object to a dictionary-based approach. The dict_ member is properly initialized as an empty dictionary.

tests/simulator/test_samrai_restarts_parser.py (3)

29-32: LGTM!

The code changes are approved.


51-62: LGTM!

The code changes are approved.


1-104: Learnings considered during the review.

The provided learnings were taken into account while reviewing the code. However, no redundant code or opportunities for streamlining were identified in the current changes. The user's openness to improve the code is appreciated.

Tools
Ruff

3-3: time imported but unused

Remove unused import: time

(F401)


5-5: datetime imported but unused

Remove unused import: datetime

(F401)


7-7: numpy imported but unused

Remove unused import: numpy

(F401)


8-8: pathlib.Path imported but unused

Remove unused import: pathlib.Path

(F401)


9-9: datetime.timedelta imported but unused

Remove unused import: datetime.timedelta

(F401)


11-11: ddt.data imported but unused

Remove unused import

(F401)


11-11: ddt.unpack imported but unused

Remove unused import

(F401)


18-18: pyphare.pharesee.run.Run imported but unused

Remove unused import: pyphare.pharesee.run.Run

(F401)


22-22: tests.diagnostic.dump_all_diags imported but unused

Remove unused import: tests.diagnostic.dump_all_diags

(F401)


23-23: pyphare.pharesee.hierarchy.patchdata.ParticleData imported but unused

Remove unused import: pyphare.pharesee.hierarchy.patchdata.ParticleData

(F401)


24-24: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 imported but unused

Remove unused import: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5

(F401)


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

Replace with None; initialize within function

(B006)


99-99: Local variable model is assigned to but never used

Remove assignment to unused variable model

(F841)

src/amr/data/particles/initializers/particle_initializer_factory.hpp (2)

23-23: LGTM!

Fully qualifying the ParticleInitializer type with the core namespace is a good practice to avoid ambiguity and potential naming conflicts.


72-73: LGTM!

Fully qualifying the MaxwellianParticleInitializer type with the core namespace maintains consistency with the new namespace structure and ensures that the correct type is used. It is a good practice to avoid ambiguity and potential naming conflicts.

Also applies to: 83-84

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

6-7: LGTM!

The changes to the header file inclusions are valid and do not introduce any issues. The restructuring of dependencies helps streamline the code and resolve potential namespace conflicts.

Also applies to: 10-11, 13-14, 17-17


48-48: LGTM!

The update to the ParticleInitializerFactory type alias is valid and reflects a more modular approach to handling particle initialization. The change does not introduce any issues.

pyphare/pyphare/pharein/initialize/general.py (5)

4-13: LGTM!

The code changes are approved.


16-23: LGTM!

The code changes are approved.


26-29: LGTM!

The code changes are approved.


34-45: LGTM!

The code changes are approved.


50-59: LGTM!

The code changes are approved.

tests/core/numerics/ion_updater/test_updater.cpp (3)

6-6: LGTM!

The added include statement is necessary for using the ParticleInitializerFactory class.


207-214: LGTM!

The updated ParticleInitializerFactory type alias enhances the specificity by explicitly specifying the template parameters, aligning it more closely with the intended usage in the context of particle initialization.


357-358: LGTM!

The updated ParticleInitializerFactory type alias enhances the specificity by explicitly specifying the template parameters, aligning it more closely with the intended usage in the context of particle initialization.

pyphare/pyphare/pharein/simulation.py (3)

501-515: LGTM!

The new check_init_options function looks good. It correctly validates the format of the initialization options and checks the validity of the directory if provided.


636-636: LGTM!

The addition of init_options to the list of accepted keywords is correct and consistent with the new check_init_options function.


671-671: LGTM!

The call to check_init_options is correctly added to process the initialization options before setting up the simulation.

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: 2

Outside diff range, codebase verification and nitpick comments (4)
tests/core/numerics/ion_updater/CMakeLists.txt (1)

14-14: Issues with replacing phare_core with phare_amr

The phare_amr target is not declared or used elsewhere in the codebase, while phare_core is still widely used. This change could potentially break the build or tests. Please verify that phare_amr is a valid target and provides the necessary functionality before proceeding with this replacement.

  • phare_core is still used in multiple CMake files.
  • phare_amr is not declared as a target in the codebase.
  • phare_amr is not used in other CMake files.
Analysis chain

Verify the impact of replacing phare_core with phare_amr.

Ensure that phare_amr provides the same or a superset of the functionality provided by phare_core. If phare_amr has a different interface or lacks some functionality provided by phare_core, the change could potentially break the build or the tests.

Run the following script to verify the impact of the change:

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the impact of replacing `phare_core` with `phare_amr`.

# Test 1: Search for the usage of `phare_core` in the codebase.
# Expect: No occurrences of `phare_core` in the codebase.
echo "Searching for the usage of phare_core in the codebase..."
if rg --type cmake $'phare_core'; then
  echo "phare_core is still used in the codebase. Please verify that phare_amr provides the same functionality as phare_core."
else
  echo "phare_core is not used in the codebase."
fi

# Test 2: Search for the declaration of `phare_amr` target.
# Expect: The `phare_amr` target is declared in the codebase.
echo "Searching for the declaration of phare_amr target..."
if rg --type cmake $'add_library\(phare_amr'; then
  echo "phare_amr target is declared in the codebase."
else
  echo "phare_amr target is not declared in the codebase. Please verify that phare_amr is a valid target."
fi

# Test 3: Search for the usage of `phare_amr` in the codebase.
# Expect: `phare_amr` is used in other CMake files.
echo "Searching for the usage of phare_amr in the codebase..."
if rg --type cmake --files-without-match CMakeLists.txt $'phare_amr'; then
  echo "phare_amr is used in other CMake files."
else
  echo "phare_amr is not used in other CMake files. Please verify that phare_amr is a valid dependency for this project."
fi

Length of output: 2571

src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2)

65-66: Approve the addition of the popname parameter to enhance particle initialization flexibility.

The addition of the std::string const& popname parameter to the loadParticles method signature is a good design decision that enhances the flexibility of particle initialization by enabling the method to handle more specific scenarios based on the provided population name.

However, consider utilizing the popname parameter within the method body to handle specific particle initialization scenarios based on the provided population name. This will ensure that the parameter serves a meaningful purpose and is not just part of the interface without any practical usage.


140-140: Approve the inclusion of the popname parameter in the method definition.

The inclusion of the std::string const& popname parameter in the loadParticles method definition aligns with the updated method signature, ensuring consistency between the declaration and the definition.

As mentioned in the previous comment, consider utilizing the popname parameter within the method body to handle specific particle initialization scenarios based on the provided population name. This will ensure that the parameter serves a meaningful purpose and is not just part of the interface without any practical usage.

pyphare/pyphare/pharein/initialize/general.py (1)

89-301: Consider breaking down the populateDict function into smaller functions for better readability and maintainability.

The populateDict function is quite large and can be broken down into smaller functions for better readability and maintainability.

The rest of the code in the function looks good and is adding various simulation parameters, diagnostics, and restarts to the dictionary using the add_* functions.

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 0ad9e31 and 648c401.

Files selected for processing (26)
  • pyphare/pyphare/pharein/init.py (5 hunks)
  • pyphare/pyphare/pharein/init.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/init.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/general.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/user_fns.py (1 hunks)
  • pyphare/pyphare/pharein/load_balancer.py (2 hunks)
  • pyphare/pyphare/pharein/simulation.py (3 hunks)
  • res/cmake/test.cmake (2 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/amr/physical_models/hybrid_model.hpp (3 hunks)
  • src/core/CMakeLists.txt (1 hunks)
  • src/core/data/electromag/electromag_initializer.hpp (1 hunks)
  • src/core/data/ions/ions.hpp (1 hunks)
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2 hunks)
  • src/core/data/ions/particle_initializers/particle_initializer.hpp (1 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (4 hunks)
  • src/phare_core.hpp (1 hunks)
  • src/simulator/phare_types.hpp (2 hunks)
  • tests/amr/data/particles/initializer/CMakeLists.txt (1 hunks)
  • tests/amr/data/particles/initializer/test_main.cpp (3 hunks)
  • tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (2 hunks)
  • tests/core/numerics/ion_updater/CMakeLists.txt (1 hunks)
  • tests/core/numerics/ion_updater/test_updater.cpp (5 hunks)
  • tests/simulator/test_samrai_restarts_parser.py (1 hunks)
Files skipped from review due to trivial changes (4)
  • pyphare/pyphare/pharein/initialize/init.py
  • pyphare/pyphare/pharein/load_balancer.py
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
  • src/core/data/electromag/electromag_initializer.hpp
Files skipped from review as they are similar to previous changes (10)
  • pyphare/pyphare/pharein/init.py
  • pyphare/pyphare/pharein/initialize/user_fns.py
  • pyphare/pyphare/pharein/simulation.py
  • res/cmake/test.cmake
  • src/amr/physical_models/hybrid_model.hpp
  • src/core/CMakeLists.txt
  • src/core/data/ions/ions.hpp
  • src/hdf5/detail/h5/h5_file.hpp
  • src/phare_core.hpp
  • tests/core/numerics/ion_updater/test_updater.cpp
Additional context used
Path-based instructions (4)
src/core/data/ions/particle_initializers/particle_initializer.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/simulator/phare_types.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Learnings (1)
tests/simulator/test_samrai_restarts_parser.py (1)
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2023-11-25T19:21:40.002Z
Learning: The user has indicated that minimal changes were made to get the function working, but acknowledges that there may still be redundant code present, such as sleep/wait/advances. The user is open to further streamlining the code.
Ruff
pyphare/pyphare/pharein/initialize/samrai_hdf5.py

9-9: Loop control variable pop not used within loop body

Rename unused pop to _pop

(B007)

tests/simulator/test_samrai_restarts_parser.py

3-3: time imported but unused

Remove unused import: time

(F401)


5-5: datetime imported but unused

Remove unused import: datetime

(F401)


7-7: numpy imported but unused

Remove unused import: numpy

(F401)


8-8: pathlib.Path imported but unused

Remove unused import: pathlib.Path

(F401)


9-9: datetime.timedelta imported but unused

Remove unused import: datetime.timedelta

(F401)


11-11: ddt.data imported but unused

Remove unused import

(F401)


11-11: ddt.unpack imported but unused

Remove unused import

(F401)


18-18: pyphare.pharesee.run.Run imported but unused

Remove unused import: pyphare.pharesee.run.Run

(F401)


22-22: tests.diagnostic.dump_all_diags imported but unused

Remove unused import: tests.diagnostic.dump_all_diags

(F401)


23-23: pyphare.pharesee.hierarchy.patchdata.ParticleData imported but unused

Remove unused import: pyphare.pharesee.hierarchy.patchdata.ParticleData

(F401)


24-24: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 imported but unused

Remove unused import: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5

(F401)


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

Replace with None; initialize within function

(B006)


99-99: Local variable model is assigned to but never used

Remove assignment to unused variable model

(F841)

Additional comments not posted (20)
tests/amr/data/particles/initializer/CMakeLists.txt (1)

14-14: Verify the impact of the library change on the codebase.

The library phare_core has been replaced with phare_amr in the target_link_libraries directive. This change may have implications on the functionality and control flow of the project.

Please confirm the following:

  1. The phare_amr library provides the necessary features and behaviors required by the project.
  2. The change has been properly propagated to other parts of the codebase to ensure compatibility.
  3. The tests have been updated and are passing with the new library.

Run the following script to verify the usage of the phare_amr library in the codebase:

Verification successful

Integration of phare_amr confirmed across the codebase.

The phare_amr library is referenced in multiple CMakeLists.txt files and included in a C++ header file, indicating its active use and integration. Please ensure that all functionalities previously provided by phare_core are covered by phare_amr and verify that tests are passing with the new library.

  • CMakeLists.txt References:

    • src/restarts/CMakeLists.txt
    • src/simulator/CMakeLists.txt
    • src/diagnostic/CMakeLists.txt
    • Various test directories under tests/amr/
  • C++ Header Inclusion:

    • src/phare_solver.hpp
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of the `phare_amr` library in the codebase.

# Test: Search for the library usage in CMake files. Expect: Occurrences of `phare_amr`.
fd -e cmake -x rg phare_amr

# Test: Search for the library header usage. Expect: Occurrences of `#include <phare_amr/`.
rg -t cpp '#include <phare_amr/'

Length of output: 64


Script:

#!/bin/bash
# Description: Re-verify the usage of the `phare_amr` library in the codebase with broader search criteria.

# Test: Search for the library usage in all CMake files. Expect: Occurrences of `phare_amr`.
rg 'phare_amr' --glob '**/CMakeLists.txt' -A 2

# Test: Search for any mention of `phare_amr` in the entire codebase, including comments and documentation.
rg 'phare_amr' -A 2

# Test: Search for any potential alternative naming or usage patterns in C++ files.
rg 'phare_amr' -t cpp -A 2

Length of output: 6932

src/core/data/ions/particle_initializers/particle_initializer.hpp (1)

13-15: LGTM!

The addition of the popname parameter to the loadParticles method signature is a good enhancement. It allows the method to accept a population name as an argument, which can be used to specify or differentiate between various particle populations during the loading process.

The method remains a pure virtual function, ensuring that derived classes must implement this updated signature. The change is consistent with the class design and does not introduce any issues.

tests/amr/data/particles/initializer/test_main.cpp (2)

10-10: LGTM!

The change in the include path for particle_initializer_factory.hpp is approved. It enhances the modularity of the code and aligns the particle initialization logic with the AMR framework.


47-48: LGTM!

The change in the namespace for ParticleInitializerFactory is approved. It suggests that the factory's implementation has been moved to the AMR context, possibly to accommodate new features or optimizations related to particle initialization in an AMR framework.

pyphare/pyphare/pharein/__init__.py (3)

15-15: LGTM!

The changes to the import statements are approved. The unused imports have been removed while keeping the necessary Simulation import.


28-28: LGTM!

The changes to the __all__ list are approved. The LoadBalancer class has been correctly added to the list of public entities.


72-80: LGTM!

The changes to the populateDict function are approved. The refactoring improves code organization and modularity by:

  • Importing the sim variable from a separate module.
  • Splitting the initialization logic into separate functions in the initialize module.
  • Adding a conditional block to handle different initialization paths based on sim.init_options.
tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (2)

54-54: LGTM!

The code change is consistent with the updated loadParticles method signature.


63-63: LGTM!

The code change is consistent with the updated loadParticles method signature.

src/simulator/phare_types.hpp (1)

33-34: LGTM!

The change to the ParticleInitializerFactory type alias looks good:

  • It uses the amr namespace to make the type more specific.
  • It provides ParticleArray_t and GridLayout_t as template parameters, which are existing type aliases defined in the same struct. This promotes consistency and maintainability.
  • The change aligns well with the overall structure and naming conventions used in the file.
tests/simulator/test_samrai_restarts_parser.py (3)

1-24: Remove unused imports.

The following imports are unused and should be removed:

  • time (line 3)
  • datetime (line 5)
  • numpy (line 7)
  • pathlib.Path (line 8)
  • datetime.timedelta (line 9)
  • ddt.data (line 11)
  • ddt.unpack (line 11)
  • pyphare.pharesee.run.Run (line 18)
  • tests.diagnostic.dump_all_diags (line 22)
  • pyphare.pharesee.hierarchy.patchdata.ParticleData (line 23)
  • pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 (line 24)

Remove the unused imports to keep the code clean and maintainable.

Tools
Ruff

3-3: time imported but unused

Remove unused import: time

(F401)


5-5: datetime imported but unused

Remove unused import: datetime

(F401)


7-7: numpy imported but unused

Remove unused import: numpy

(F401)


8-8: pathlib.Path imported but unused

Remove unused import: pathlib.Path

(F401)


9-9: datetime.timedelta imported but unused

Remove unused import: datetime.timedelta

(F401)


11-11: ddt.data imported but unused

Remove unused import

(F401)


11-11: ddt.unpack imported but unused

Remove unused import

(F401)


18-18: pyphare.pharesee.run.Run imported but unused

Remove unused import: pyphare.pharesee.run.Run

(F401)


22-22: tests.diagnostic.dump_all_diags imported but unused

Remove unused import: tests.diagnostic.dump_all_diags

(F401)


23-23: pyphare.pharesee.hierarchy.patchdata.ParticleData imported but unused

Remove unused import: pyphare.pharesee.hierarchy.patchdata.ParticleData

(F401)


24-24: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 imported but unused

Remove unused import: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5

(F401)


46-48: Avoid using mutable default arguments.

It's generally a good practice to avoid using mutable default arguments as it can lead to unexpected behavior.

Consider using None as the default and initializing the dictionary within the function:

def dup(dic=None):
    if dic is None:
        dic = {}
    dic.update(copy.deepcopy(simArgs))
    return dic
Tools
Ruff

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

Replace with None; initialize within function

(B006)


99-99: Remove unused local variable.

The local variable model is assigned but never used.

Remove the assignment to the unused variable model:

-model = setup_model()
Tools
Ruff

99-99: Local variable model is assigned to but never used

Remove assignment to unused variable model

(F841)

src/amr/data/particles/initializers/particle_initializer_factory.hpp (4)

12-12: LGTM!

The new #include statement for samrai_hdf5_particle_initializer.hpp is necessary for the new case added to the create method and follows the existing naming convention.


23-23: LGTM!

The changes to the using directive for ParticleInitializerT and the std::make_unique calls for MaxwellianParticleInitializer maintain consistency with the new namespace structure and ensure that the correct types are used.

Also applies to: 72-73, 83-84


89-100: LGTM!

The new case added to the create method for handling the initializerName "samraih5" enhances the functionality of the factory and follows the existing structure and style. It properly retrieves the necessary parameters and initializes the SamraiHDF5ParticleInitializer.


18-18: Verify the impact of the namespace change on the rest of the codebase.

The namespace change from core to amr indicates a potential shift in the organizational structure of the codebase. Ensure that all references to the ParticleInitializerFactory class and its associated types are updated accordingly throughout the codebase.

Run the following script to verify the references:

Verification successful

Namespace change successfully propagated.

The namespace change from core to amr for ParticleInitializerFactory has been correctly applied across the codebase. All references have been updated accordingly, and there are no remaining references to the old namespace.

  • Verified in files:
    • src/simulator/phare_types.hpp
    • src/amr/physical_models/hybrid_model.hpp
    • tests/core/numerics/ion_updater/test_updater.cpp
    • tests/amr/data/particles/initializer/test_main.cpp
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify references to `ParticleInitializerFactory` and its associated types.

# Test 1: Search for references to `ParticleInitializerFactory` in the `core` namespace.
# Expect: No occurrences.
rg --type cpp $'core::ParticleInitializerFactory'

# Test 2: Search for references to `ParticleInitializerFactory` in the `amr` namespace. 
# Expect: Only occurrences in the reviewed file.
rg --type cpp $'amr::ParticleInitializerFactory' -g '!particle_initializer_factory.hpp'

Length of output: 757

pyphare/pyphare/pharein/initialize/general.py (3)

4-13: LGTM!

The imports are used in the code and look good.


34-45: LGTM!

The py_fn_wrapper class looks good and serves the purpose of converting scalars and lists to arrays.


50-59: LGTM!

The fn_wrapper class looks good and serves the purpose of wrapping calls to user init functions.

@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Sep 4, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Sep 4, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Sep 4, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Sep 4, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Sep 4, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Sep 4, 2024
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

Outside diff range, codebase verification and nitpick comments (2)
pyphare/pyphare/pharein/__init__.py (1)

72-80: LGTM!

The changes to the populateDict function look good. The modularization of the initialization logic improves clarity and separation of concerns.

Minor refactor suggestion:

Consider using an if-else statement instead of two separate if statements for a more concise implementation.

Apply this diff to refactor the code:

-    if sim.init_options is None:
-        initialize.user_fns.populateDict(sim)
-    else:
-        initialize.samrai_hdf5.populateDict(sim)
+    if sim.init_options is None:
+        initialize.user_fns.populateDict(sim)
+    else:
+        initialize.samrai_hdf5.populateDict(sim)
src/hdf5/detail/h5/h5_file.hpp (1)

250-253: Remove commented out code.

The commented out code for the scan_for_groups method should be removed to improve code cleanliness and maintainability.

Remove the following lines:

-// std::unordered_set<std::string> scan_for_groups(){}
-
-// std::unordered_set<std::string> scan_for_groups(std::string const& contains){}
Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 648c401 and 0d9fa53.

Files selected for processing (28)
  • pyphare/pyphare/pharein/init.py (5 hunks)
  • pyphare/pyphare/pharein/init.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/init.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/general.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/user_fns.py (1 hunks)
  • pyphare/pyphare/pharein/load_balancer.py (2 hunks)
  • pyphare/pyphare/pharein/simulation.py (3 hunks)
  • res/cmake/test.cmake (2 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/amr/physical_models/hybrid_model.hpp (3 hunks)
  • src/core/CMakeLists.txt (1 hunks)
  • src/core/data/electromag/electromag.hpp (3 hunks)
  • src/core/data/electromag/electromag_initializer.hpp (1 hunks)
  • src/core/data/ions/ions.hpp (1 hunks)
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2 hunks)
  • src/core/data/ions/particle_initializers/particle_initializer.hpp (1 hunks)
  • src/core/data/vecfield/vecfield_initializer.hpp (2 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (3 hunks)
  • src/phare_core.hpp (1 hunks)
  • src/simulator/phare_types.hpp (2 hunks)
  • tests/amr/data/particles/initializer/CMakeLists.txt (1 hunks)
  • tests/amr/data/particles/initializer/test_main.cpp (4 hunks)
  • tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (2 hunks)
  • tests/core/numerics/ion_updater/CMakeLists.txt (1 hunks)
  • tests/core/numerics/ion_updater/test_updater.cpp (5 hunks)
  • tests/simulator/test_samrai_restarts_parser.py (1 hunks)
Files skipped from review due to trivial changes (5)
  • pyphare/pyphare/pharein/initialize/init.py
  • pyphare/pyphare/pharein/load_balancer.py
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
  • src/core/data/electromag/electromag_initializer.hpp
  • src/core/data/ions/ions.hpp
Files skipped from review as they are similar to previous changes (13)
  • pyphare/pyphare/pharein/init.py
  • pyphare/pyphare/pharein/initialize/general.py
  • pyphare/pyphare/pharein/initialize/user_fns.py
  • pyphare/pyphare/pharein/simulation.py
  • res/cmake/test.cmake
  • src/core/CMakeLists.txt
  • src/core/data/electromag/electromag.hpp
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp
  • src/core/data/ions/particle_initializers/particle_initializer.hpp
  • src/core/data/vecfield/vecfield_initializer.hpp
  • src/phare_core.hpp
  • tests/amr/data/particles/initializer/CMakeLists.txt
  • tests/core/numerics/ion_updater/test_updater.cpp
Additional context used
Path-based instructions (4)
src/simulator/phare_types.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Learnings (1)
tests/simulator/test_samrai_restarts_parser.py (1)
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2023-11-25T19:21:40.002Z
Learning: The user has indicated that minimal changes were made to get the function working, but acknowledges that there may still be redundant code present, such as sleep/wait/advances. The user is open to further streamlining the code.
Ruff
pyphare/pyphare/pharein/initialize/samrai_hdf5.py

9-9: Loop control variable pop not used within loop body

Rename unused pop to _pop

(B007)

tests/simulator/test_samrai_restarts_parser.py

3-3: time imported but unused

Remove unused import: time

(F401)


5-5: datetime imported but unused

Remove unused import: datetime

(F401)


7-7: numpy imported but unused

Remove unused import: numpy

(F401)


8-8: pathlib.Path imported but unused

Remove unused import: pathlib.Path

(F401)


9-9: datetime.timedelta imported but unused

Remove unused import: datetime.timedelta

(F401)


11-11: ddt.data imported but unused

Remove unused import

(F401)


11-11: ddt.unpack imported but unused

Remove unused import

(F401)


18-18: pyphare.pharesee.run.Run imported but unused

Remove unused import: pyphare.pharesee.run.Run

(F401)


22-22: tests.diagnostic.dump_all_diags imported but unused

Remove unused import: tests.diagnostic.dump_all_diags

(F401)


23-23: pyphare.pharesee.hierarchy.patchdata.ParticleData imported but unused

Remove unused import: pyphare.pharesee.hierarchy.patchdata.ParticleData

(F401)


24-24: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 imported but unused

Remove unused import: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5

(F401)


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

Replace with None; initialize within function

(B006)


99-99: Local variable model is assigned to but never used

Remove assignment to unused variable model

(F841)

Additional comments not posted (21)
tests/core/numerics/ion_updater/CMakeLists.txt (1)

14-14: Verify the impact of the dependency change.

The change in the target_link_libraries directive from phare_core to phare_amr indicates a shift in dependencies. This could impact the functionality of the project if phare_amr provides different features or interfaces compared to phare_core.

Run the following script to verify the impact of the dependency change:

Please ensure that:

  1. The codebase has been updated to use phare_amr instead of phare_core.
  2. The phare_amr library provides the necessary features and interfaces required by the test-updater project.
  3. The test-updater project builds and runs successfully with the phare_amr dependency.
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)

9-9: Rename unused loop variable to silence Ruff warning.

The static analysis tool Ruff suggests renaming the unused loop variable pop to _pop.

Tools
Ruff

9-9: Loop control variable pop not used within loop body

Rename unused pop to _pop

(B007)

tests/amr/data/particles/initializer/test_main.cpp (2)

10-10: LGTM!

The change to the header file is approved as it aligns with the refactoring effort to organize particle initializer functionalities under the AMR module.


47-48: LGTM!

The namespace update for ParticleInitializerFactory is approved as it aligns with the refactoring effort to move the factory's implementation to the AMR context.

pyphare/pyphare/pharein/__init__.py (2)

15-15: LGTM!

The code changes are approved.


28-28: LGTM!

The code changes are approved.

tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (2)

54-54: LGTM!

The code changes are approved.


63-63: LGTM!

The code changes are approved.

src/simulator/phare_types.hpp (1)

33-34: LGTM!

The change to the ParticleInitializerFactory type alias is approved. The update to use amr::ParticleInitializerFactory with specific template parameters ParticleArray_t and GridLayout_t likely improves the functionality and adaptability of the particle initialization process within the simulation framework, while maintaining the overall structure of PHARE_Types.

tests/simulator/test_samrai_restarts_parser.py (3)

1-24: Remove unused imports.

The following imports are unused and should be removed:

  • time (line 3)
  • datetime (line 5)
  • numpy (line 7)
  • pathlib.Path (line 8)
  • datetime.timedelta (line 9)
  • ddt.data (line 11)
  • ddt.unpack (line 11)
  • pyphare.pharesee.run.Run (line 18)
  • tests.diagnostic.dump_all_diags (line 22)
  • pyphare.pharesee.hierarchy.patchdata.ParticleData (line 23)
  • pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 (line 24)

Remove the unused imports to keep the code clean and maintainable.

Tools
Ruff

3-3: time imported but unused

Remove unused import: time

(F401)


5-5: datetime imported but unused

Remove unused import: datetime

(F401)


7-7: numpy imported but unused

Remove unused import: numpy

(F401)


8-8: pathlib.Path imported but unused

Remove unused import: pathlib.Path

(F401)


9-9: datetime.timedelta imported but unused

Remove unused import: datetime.timedelta

(F401)


11-11: ddt.data imported but unused

Remove unused import

(F401)


11-11: ddt.unpack imported but unused

Remove unused import

(F401)


18-18: pyphare.pharesee.run.Run imported but unused

Remove unused import: pyphare.pharesee.run.Run

(F401)


22-22: tests.diagnostic.dump_all_diags imported but unused

Remove unused import: tests.diagnostic.dump_all_diags

(F401)


23-23: pyphare.pharesee.hierarchy.patchdata.ParticleData imported but unused

Remove unused import: pyphare.pharesee.hierarchy.patchdata.ParticleData

(F401)


24-24: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 imported but unused

Remove unused import: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5

(F401)


46-48: Avoid using mutable default arguments.

It's generally a good practice to avoid using mutable default arguments as it can lead to unexpected behavior.

Consider using None as the default and initializing the dictionary within the function:

def dup(dic=None):
    if dic is None:
        dic = {}
    dic.update(copy.deepcopy(simArgs))
    return dic
Tools
Ruff

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

Replace with None; initialize within function

(B006)


99-99: Remove unused local variable.

The local variable model is assigned but never used.

Remove the assignment to the unused variable model:

-model = setup_model()
Tools
Ruff

99-99: Local variable model is assigned to but never used

Remove assignment to unused variable model

(F841)

src/amr/data/particles/initializers/particle_initializer_factory.hpp (4)

23-23: LGTM!

The code change is approved. Fully qualifying the ParticleInitializer type improves code readability and maintainability.


72-73: LGTM!

The code change is approved. Fully qualifying the MaxwellianParticleInitializer type maintains consistency with the new namespace structure and improves code readability.


83-84: LGTM!

The code change is approved. Fully qualifying the MaxwellianParticleInitializer type maintains consistency with the new namespace structure and improves code readability.


89-100: LGTM!

The code change is approved. The new conditional block enhances the functionality of the factory by allowing it to instantiate a SamraiHDF5ParticleInitializer based on the provided configuration. It improves the flexibility and usability of the factory while following the existing code style and structure.

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

48-48: LGTM!

The change in the ParticleInitializerFactory type alias enhances the clarity and organization of the code by aligning the type definitions with the intended architecture.

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

13-14: LGTM!

The inclusion of the <unordered_set> header is necessary for using the std::unordered_set container in the code.


74-75: Improved flexibility and usability of the file() method.

The changes to the file() method signatures are beneficial:

  • Returning auto& allows the method to deduce the return type, providing flexibility.
  • The const overload allows const access to the file, improving usability.

254-293: Well-designed and modular GroupScanner struct.

The GroupScanner struct is a valuable addition to the HighFiveFile class:

  • It encapsulates the group scanning logic, promoting separation of concerns and modularity.
  • The recursive scan method efficiently traverses the groups in the HDF5 file.
  • The filtering functionality based on a vector of strings provides flexibility in selecting groups.

295-298: Useful scan_for_groups method utilizing the GroupScanner.

The scan_for_groups method is a valuable addition to the HighFiveFile class:

  • It provides a convenient way to retrieve a set of group paths based on specified criteria.
  • It leverages the GroupScanner struct to encapsulate the scanning logic, promoting code reuse and modularity.

@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Sep 4, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Sep 4, 2024
@PhilipDeegan PhilipDeegan force-pushed the restartinator branch 2 times, most recently from e721d2a to 14357eb Compare September 5, 2024 13:35
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.

Caution

Inline review comments failed to post

Actionable comments posted: 25

Outside diff range, codebase verification and nitpick comments (8)
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1)

4-24: Review the necessity of included headers.

Several headers are included, but it's unclear if all are necessary given the current functionality of the class. Reducing unnecessary includes can help decrease compilation times and reduce dependencies.

src/amr/data/electromag/electromag_initializer.hpp (1)

4-4: Consider removing commented-out include.

The commented-out include statement on line 4 might be unnecessary. If electromag.hpp is not needed, it's better to remove this line to keep the code clean.

src/amr/data/particles/initializers/particle_initializer_factory.hpp (2)

104-104: Exception handling for unhandled initializer names.

The exception thrown when no valid initializer is chosen is a good practice, as it prevents the factory from failing silently and helps in diagnosing configuration errors. However, the error message could be more descriptive to aid in debugging, especially in a production environment where more specific error messages can significantly reduce troubleshooting time.

Consider enhancing the error message to include the invalid initializerName value to aid in debugging:

-throw std::runtime_error("No Particle Initializer chosen!");
+throw std::runtime_error("No Particle Initializer chosen for name: " + initializerName);

90-101: Lack of Error Handling in populate_from Method

The populate_from method lacks explicit error handling mechanisms, such as try-catch blocks or error checks, for its file I/O operations. This could lead to unhandled exceptions or undefined behavior if file operations fail. It is recommended to implement robust error handling to manage potential issues like missing files or permission errors effectively.

  • Consider adding try-catch blocks around file operations.
  • Implement checks to verify file existence and accessibility before attempting to open them.
  • Log errors to provide insights into any issues encountered during execution.
Analysis chain

Addition of new case for samraih5 initializer.

The new conditional block for initializerName == "samraih5" is a significant addition. It handles the initialization from a specified directory and uses the SamraiHDF5ParticleInitializer. This block enhances the factory's capabilities by allowing it to instantiate a new type of particle initializer based on the provided configuration.

However, it's important to ensure that the populate_from method is robust and handles errors appropriately, especially since it interacts with file I/O operations which are prone to fail due to various reasons like missing files or permission issues.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify error handling in `populate_from` method.

# Test: Search for error handling in the `populate_from` method. Expect: Proper error handling mechanisms.
rg --type cpp -A 5 $'populate_from'

Length of output: 2600


Script:

#!/bin/bash
# Extract the full implementation of the `populate_from` method to verify error handling.
ast-grep --lang cpp --pattern $'void SamraiH5Interface<ParticleArray, GridLayout>::populate_from($_, $_, $_) {
  $$$
}'

Length of output: 120


Script:

#!/bin/bash
# Use rg to search for the `populate_from` method and include more lines of context to capture its full implementation.
rg --type cpp -A 20 'void SamraiH5Interface<ParticleArray, GridLayout>::populate_from'

Length of output: 2055

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

Line range hint 47-56: Enhance error handling and clarity in parallel file creation.

The method createHighFiveFile handles the creation of HDF5 files with parallel support. However, the error message "HDF5 NOT PARALLEL!" could be more descriptive, and the method could benefit from additional comments explaining the conditions under which errors are thrown.

Consider enhancing the error message and adding more descriptive comments:

-            std::cout << "WARNING: PARALLEL HDF5 not available" << std::endl;
-            if (core::mpi_size() > 1)
-            {
-                throw std::runtime_error("HDF5 NOT PARALLEL!");
-            }
+            std::cout << "WARNING: Parallel HDF5 support is not compiled into this build." << std::endl;
+            if (core::mpi_size() > 1) {
+                throw std::runtime_error("Parallel HDF5 is required but not available. Please check your HDF5 installation and compilation flags.");
+            }

Line range hint 180-213: Refactor: Simplify attribute writing method for better readability.

The write_attribute method is complex and handles multiple scenarios, including writing attributes to datasets or groups. The method could benefit from refactoring to separate concerns and improve readability.

Consider breaking down the method into smaller, more focused methods that handle specific parts of the attribute writing process. This would make the code easier to maintain and understand.

pyphare/pyphare/pharein/initialize/general.py (2)

16-23: Ensure proper documentation for function _patch_data_ids.

The function _patch_data_ids retrieves patch data IDs from a restart file directory. It is crucial to ensure that the documentation clearly explains the parameters and the return type to maintain code readability and usability.


26-29: Ensure proper documentation for function _serialized_simulation_string.

Similar to _patch_data_ids, the function _serialized_simulation_string lacks detailed documentation. Providing a clear description of its purpose, parameters, and return type would enhance code maintainability.

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 0d9fa53 and e721d2a.

Files selected for processing (33)
  • pyphare/pyphare/pharein/init.py (5 hunks)
  • pyphare/pyphare/pharein/init.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/init.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/general.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/user_fns.py (1 hunks)
  • pyphare/pyphare/pharein/load_balancer.py (2 hunks)
  • pyphare/pyphare/pharein/simulation.py (3 hunks)
  • res/cmake/test.cmake (2 hunks)
  • src/amr/data/electromag/electromag_initializer.hpp (1 hunks)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1 hunks)
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp (1 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/amr/physical_models/hybrid_model.hpp (7 hunks)
  • src/core/CMakeLists.txt (1 hunks)
  • src/core/data/electromag/electromag.hpp (3 hunks)
  • src/core/data/ions/ions.hpp (1 hunks)
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2 hunks)
  • src/core/data/ions/particle_initializers/particle_initializer.hpp (1 hunks)
  • src/core/data/vecfield/vecfield_initializer.hpp (2 hunks)
  • src/core/utilities/types.hpp (1 hunks)
  • src/hdf5/detail/h5/group_scanner.hpp (1 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (5 hunks)
  • src/phare_core.hpp (1 hunks)
  • src/simulator/phare_types.hpp (2 hunks)
  • tests/amr/data/particles/initializer/CMakeLists.txt (1 hunks)
  • tests/amr/data/particles/initializer/test_main.cpp (4 hunks)
  • tests/amr/tagging/test_tagging.cpp (2 hunks)
  • tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (2 hunks)
  • tests/core/numerics/ion_updater/CMakeLists.txt (1 hunks)
  • tests/core/numerics/ion_updater/test_updater.cpp (5 hunks)
  • tests/simulator/test_samrai_restarts_parser.py (1 hunks)
Files skipped from review due to trivial changes (4)
  • pyphare/pyphare/pharein/initialize/init.py
  • pyphare/pyphare/pharein/load_balancer.py
  • res/cmake/test.cmake
  • src/core/data/ions/ions.hpp
Files skipped from review as they are similar to previous changes (10)
  • pyphare/pyphare/pharein/init.py
  • pyphare/pyphare/pharein/initialize/user_fns.py
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
  • src/core/CMakeLists.txt
  • src/core/data/electromag/electromag.hpp
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp
  • src/core/data/ions/particle_initializers/particle_initializer.hpp
  • src/core/data/vecfield/vecfield_initializer.hpp
  • src/phare_core.hpp
  • tests/core/numerics/ion_updater/test_updater.cpp
Additional context used
Path-based instructions (9)
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/simulator/phare_types.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/amr/data/electromag/electromag_initializer.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Learnings (1)
tests/simulator/test_samrai_restarts_parser.py (1)
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2023-11-25T19:21:40.002Z
Learning: The user has indicated that minimal changes were made to get the function working, but acknowledges that there may still be redundant code present, such as sleep/wait/advances. The user is open to further streamlining the code.
Ruff
pyphare/pyphare/pharein/initialize/samrai_hdf5.py

9-9: Loop control variable pop not used within loop body

Rename unused pop to _pop

(B007)

tests/simulator/test_samrai_restarts_parser.py

3-3: time imported but unused

Remove unused import: time

(F401)


5-5: datetime imported but unused

Remove unused import: datetime

(F401)


7-7: numpy imported but unused

Remove unused import: numpy

(F401)


8-8: pathlib.Path imported but unused

Remove unused import: pathlib.Path

(F401)


9-9: datetime.timedelta imported but unused

Remove unused import: datetime.timedelta

(F401)


11-11: ddt.data imported but unused

Remove unused import

(F401)


11-11: ddt.unpack imported but unused

Remove unused import

(F401)


18-18: pyphare.pharesee.run.Run imported but unused

Remove unused import: pyphare.pharesee.run.Run

(F401)


22-22: tests.diagnostic.dump_all_diags imported but unused

Remove unused import: tests.diagnostic.dump_all_diags

(F401)


23-23: pyphare.pharesee.hierarchy.patchdata.ParticleData imported but unused

Remove unused import: pyphare.pharesee.hierarchy.patchdata.ParticleData

(F401)


24-24: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 imported but unused

Remove unused import: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5

(F401)


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

Replace with None; initialize within function

(B006)


99-99: Local variable model is assigned to but never used

Remove assignment to unused variable model

(F841)

pyphare/pyphare/pharein/initialize/general.py

165-165: Undefined name simulation

(F821)

Additional comments not posted (28)
tests/core/numerics/ion_updater/CMakeLists.txt (1)

14-14: Verify library replacement implications.

The change from phare_core to phare_amr in the target_link_libraries directive could have significant implications on the functionality and compatibility of the test executable. It is crucial to ensure that phare_amr provides all necessary functionalities and interfaces that were previously provided by phare_core.

Run the following script to verify the presence of required symbols in phare_amr:

tests/amr/data/particles/initializer/CMakeLists.txt (1)

14-14: Verify the functionality and dependencies of the new library phare_amr.

The change from phare_core to phare_amr in the target_link_libraries directive is significant. It's crucial to ensure that phare_amr provides all the functionalities expected by the project that were previously covered by phare_core. This change could potentially affect the build and runtime behavior of the project.

Run the following script to verify the functionality and dependencies:

pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)

3-3: Clarify or remove the commented import.

The commented import statement for pybindlibs.dictator may indicate an unused or future dependency. If it's not intended for future use, consider removing it to clean up the codebase.

src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1)

31-37: Class definition looks good; consider documenting potential future changes.

The class is currently well-defined. However, the comment about "no virtual classes needed (yet)" suggests there might be future changes. Documenting potential extensions or modifications could be helpful for future maintainers.

tests/amr/data/particles/initializer/test_main.cpp (3)

10-10: Header file inclusion updated.

The inclusion of the new header file amr/data/particles/initializers/particle_initializer_factory.hpp is consistent with the restructuring mentioned in the summary. This change suggests a more organized approach under the AMR module, which should be beneficial for maintaining the codebase.


Line range hint 32-45: Dictionary setup for particle initialization.

The dictionary is correctly configured with appropriate types and values for particle initialization parameters. This setup is crucial for ensuring that the particle initializer behaves as expected during tests.


47-48: Updated namespace and factory method usage.

The use of the PHARE::amr namespace for the ParticleInitializerFactory and the method call to create are correctly implemented. This aligns with the restructuring of the particle initialization functionalities under the AMR module, enhancing modularity and clarity.

pyphare/pyphare/pharein/__init__.py (2)

28-28: Approved: Addition of LoadBalancer to the __all__ list.

This change enhances the module's public API by explicitly exposing LoadBalancer, aligning with the PR's objectives of improving modularization.


72-80: Approved: Use of new initialization functions.

The introduction of initialize.general.populateDict(sim) and conditional calls to initialize.user_fns.populateDict(sim) or initialize.samrai_hdf5.populateDict(sim) enhances modularity and clarity. This approach allows for more flexible and maintainable code.

Please ensure that these new functions are well-integrated with the rest of the system and that all necessary conditions and configurations are handled correctly.

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

1-2: Header guards are correctly defined.

The header guards are well-defined and follow the naming convention, ensuring that the header file is included only once during compilation.

Also applies to: 72-72


16-69: Namespace declaration is appropriate.

The namespace PHARE::hdf5::h5 is appropriately used to encapsulate the GroupScanner functionality, aligning with the project's structure.

tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (2)

63-63: Clarify the purpose of the new parameter in test documentation.

The addition of the "protons" parameter to the loadParticles method is correctly implemented in this test case. Consider adding a comment in the test to explain why the "protons" parameter is necessary and how it affects the test logic.


54-54: Verify integration of the new parameter across the codebase.

The addition of the "protons" parameter to the loadParticles method is correctly implemented in this test case. Ensure that all other usages of this method in the codebase have been updated accordingly.

Run the following script to verify the method usage:

Verification successful

Successful integration of the new parameter across the codebase.

The loadParticles method has been updated to include the new parameter in all relevant files. The integration appears consistent and correct across the codebase. No further action is required.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all method calls to `loadParticles` match the new signature.

# Test: Search for the method usage. Expect: Only occurrences of the new signature.
rg --type cpp -A 5 $'loadParticles'

Length of output: 6714

src/simulator/phare_types.hpp (1)

33-34: Type Alias Update: Enhanced Specificity and Potential Impact

The update to the ParticleInitializerFactory type alias enhances its specificity by using template parameters ParticleArray_t and GridLayout_t. This change likely improves type safety and ensures that the initializer is used correctly within the simulation framework.

However, it's crucial to verify that this change does not negatively impact other parts of the system that might rely on the previous type alias. Ensure that all references to ParticleInitializerFactory have been updated accordingly.

Run the following script to verify the usage of ParticleInitializerFactory across the codebase:

Verification successful

Verification Successful: Type Alias Update Integrated Correctly

The update to the ParticleInitializerFactory type alias has been successfully integrated across the codebase. All references to ParticleInitializerFactory now use the new type alias with specific template parameters, ensuring consistency and correctness. No issues were found related to this change.

  • The new type alias is used consistently in both source and test files.
  • There are no occurrences of the old type alias, indicating a complete transition.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all references to `ParticleInitializerFactory` match the new type alias.

# Test: Search for the type alias usage. Expect: Only occurrences of the new type alias.
rg --type cpp -A 5 $'ParticleInitializerFactory'

Length of output: 5295

src/amr/data/electromag/electromag_initializer.hpp (2)

16-22: Review base class ElectromagInitializer.

The ElectromagInitializer class is designed as a base class with a virtual destructor and a virtual init method. This is a good practice for base classes intended for polymorphism, ensuring proper cleanup of derived class objects through base class pointers.


53-74: Review derived class ElectromagSamraiH5Initializer.

This class also inherits from ElectromagInitializer and specializes in initializing electromagnetic fields from HDF5 files using the SAMRAI framework. The use of a template for SamraiHDF5FieldInitializer to handle different field types is a robust design choice, allowing flexibility with field types. The loop in the init method efficiently handles each field in the electromagnetic vector field. Ensure that the SamraiHDF5FieldInitializer is well-tested, especially with regards to file I/O operations and error handling.

Verify the robustness and error handling of SamraiHDF5FieldInitializer in scenarios of missing files or corrupted data.

tests/simulator/test_samrai_restarts_parser.py (1)

73-103: Ensure proper cleanup and initialization in test class.

The RestartsParserTest class methods for setup and teardown are well-implemented, ensuring that the simulator is properly reset after each test. However, ensure that all resources are adequately released and that the simulator's state is fully reinitialized before each test to avoid state leakage between tests.

Tools
Ruff

99-99: Local variable model is assigned to but never used

Remove assignment to unused variable model

(F841)

src/amr/data/particles/initializers/particle_initializer_factory.hpp (2)

24-24: Namespace and type alias update.

The update to the ParticleInitializerT type alias to include the core:: namespace prefix improves clarity and ensures that the correct type is used. This change aligns with the restructuring mentioned in the summary and helps avoid potential namespace conflicts.


73-74: Consistency in namespace usage for MaxwellianParticleInitializer.

The changes to fully qualify MaxwellianParticleInitializer with the core:: namespace prefix are consistent and necessary due to the namespace restructuring. This ensures that the correct class is referenced, preventing any ambiguity that might arise from similar class names in different namespaces.

Also applies to: 84-85

src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)

49-78: Review of SamraiH5Interface class template.

The SamraiH5Interface class template is well-structured for handling HDF5 files specific to SAMRAI data structures. However, there are a few points to consider:

  • The use of static for the INSTANCE method is appropriate for the singleton pattern, but it's generally safer in multithreaded contexts to use a thread-safe initialization pattern or to document that the class is not thread-safe.
  • The method populate_from and getRestartFileFullPath are well-named and seem to follow good practices with clear parameter naming and usage.

Overall, the class design is clean, but consider adding thread safety documentation or enhancements if applicable.

tests/amr/tagging/test_tagging.cpp (3)

183-183: Approved: Addition of dict_ member variable.

The inclusion of the PHARE::initializer::PHAREDict dict_ in the TestTagger struct is a positive change, centralizing the initialization logic for the HybridState object.


186-190: Approved: New init method in SinglePatchHybridModel.

The addition of the init method, which takes Electromag and GridLayoutT references, is well-implemented. It encapsulates the initialization logic, enhancing the clarity and maintainability of the code.


202-212: Approved: Overall structure and logic of TestTagger.

The updates to the TestTagger struct, including the use of createDict<dim>() for initializing dict_ and the subsequent use of this dictionary to initialize the model, are well thought out and align with the PR's objectives of enhancing initialization processes.

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

97-97: Initialization of _Initializers in the constructor.

The addition of _Initializers in the constructor using std::make_unique is a good practice for managing dynamic resources. This ensures that the memory is properly managed and reduces the risk of memory leaks. However, ensure that the _Initializers class is fully defined and that its usage is safe and efficient in the context of this model.


147-148: Enhanced particle loading with additional context.

The modification to include pop.name() in the loadParticles method call is a positive change, providing more context to the particle loading process. This can help in debugging and logging by making the particle data operations more traceable.


54-55: Update to ParticleInitializerFactory type alias.

The change from core::ParticleInitializerFactory to amr::ParticleInitializerFactory reflects a shift in the namespace which could indicate a reorganization or modularization of the code. This should be checked for consistency across the project to ensure that all references to ParticleInitializerFactory are updated accordingly.

Verification successful

Namespace Update Verified for ParticleInitializerFactory.

The transition from core::ParticleInitializerFactory to amr::ParticleInitializerFactory has been successfully implemented across the codebase. All references have been updated to use the new namespace, ensuring consistency and alignment with the intended modularization or reorganization.

  • Confirmed usage in:
    • src/simulator/phare_types.hpp
    • src/amr/physical_models/hybrid_model.hpp
    • tests/core/numerics/ion_updater/test_updater.cpp
    • tests/amr/data/particles/initializer/test_main.cpp
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all references to `ParticleInitializerFactory` are updated.

# Test: Search for the old namespace usage. Expect: No occurrences of the old namespace.
rg --type cpp 'core::ParticleInitializerFactory'

Length of output: 48


Script:

#!/bin/bash
# Description: Verify the usage of the new namespace `amr::ParticleInitializerFactory`.

# Test: Search for occurrences of the new namespace usage.
rg --type cpp 'amr::ParticleInitializerFactory'

Length of output: 791

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

256-259: New Feature: Group scanning functionality.

The addition of the scan_for_groups method and the GroupScanner struct enhances the functionality of the HighFiveFile class by allowing for the scanning of groups within an HDF5 file based on specified criteria. This is a significant enhancement for users who need to filter and process large datasets efficiently.

pyphare/pyphare/pharein/simulation.py (1)

Line range hint 673-708: Verify the integration of init_options in the wrapper function.

The wrapper function has been updated to handle init_options. Ensure that:

  • The init_options are correctly processed and integrated into the kwargs dictionary.
  • The function maintains robustness and does not introduce any side effects by the addition of new keywords.

Consider adding unit tests to verify the correct processing and integration of init_options:

def test_wrapper_with_init_options():
    simulation_object = Simulation()
    kwargs = {'init_options': {'format': 'samraih5', 'options': {'dir': 'valid_dir'}}}
    simulation_object.wrapper(**kwargs)
    assert 'init_options' in kwargs and kwargs['init_options']['options']['dir'] == 'valid_dir'
Comments failed to post (25)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)

6-16: Optimize string operations and address unused loop variable.

  1. Unused Loop Variable: The variable pop is not used within the loop. If the details of pop are not needed, consider renaming it to _ to indicate it's intentionally unused.
  2. String Operations: The construction of partinit_path involves multiple concatenations which could be optimized using f-strings for better readability and performance.

Consider the following refactor:

-        partinit_path = pop_path + "{:d}/".format(pop_index) + partinit + "/"
+        partinit_path = f"{pop_path}{pop_index}/{partinit}/"
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.

def populateDict(sim):
    init_model = sim.model
    partinit = "particle_initializer"
    for pop_index, _ in enumerate(init_model.populations):
        pop_path = "simulation/ions/pop"
        partinit_path = f"{pop_path}{pop_index}/{partinit}/"

        add_string(partinit_path + "name", "samraih5")
        add_string(partinit_path + "filepath", sim.init_options["dir"])
        add_int(partinit_path + "mpi_size", sim.init_options.get("mpi_size", 1))
        add_int(partinit_path + "index", sim.init_options.get("index", 0))
Tools
Ruff

9-9: Loop control variable pop not used within loop body

Rename unused pop to _pop

(B007)

src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (2)

44-49: Clarify or implement the load method.

The load method currently only contains a logging statement and no functional code. If this is a placeholder, consider adding a comment to clarify that. Otherwise, implementation details should be added to match the class's intended functionality.


1-2: Correct the spelling in the header guards.

The header guards are misspelled as "INITIAZILIZERS" which should be "INITIALIZERS" to prevent issues with multiple inclusions.

Apply this diff to correct the spelling:

-#ifndef _PHARE_AMR_DATA_FIELD_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_FIELD_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef _PHARE_AMR_DATA_FIELD_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#define _PHARE_AMR_DATA_FIELD_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
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.

#ifndef _PHARE_AMR_DATA_FIELD_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
#define _PHARE_AMR_DATA_FIELD_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
src/hdf5/detail/h5/group_scanner.hpp (2)

4-13: Review of includes and namespace usage.

The includes are well-organized and relevant to the functionality of the GroupScanner. However, consider using forward declarations where possible to reduce compile-time dependencies.


19-66: Template structure GroupScanner review.

The GroupScanner is well-designed with clear responsibilities. However, there are several improvements and issues to address:

  1. Const-correctness: The constructor should mark contains_ as std::vector<std::string>&& to avoid unnecessary copies if the caller can move the vector.
  2. Performance: The recursive scan function can be optimized by passing std::string by reference to avoid copies.
  3. Logic issue: The logic in lines 47-53 seems inverted. It should continue if the path contains the string, not if it doesn't.

Consider the following changes:

- GroupScanner(HighFiveFile_t const& h5_, std::vector<std::string> const& contains_ = {})
+ GroupScanner(HighFiveFile_t const& h5_, std::vector<std::string>&& contains_ = {})

- void scan(HighFive::Group const& group, std::string const& path)
+ void scan(HighFive::Group const& group, std::string const& path) const

- if (fpath.find(c) == std::string::npos)
+ if (fpath.find(c) != std::string::npos)

Committable suggestion was skipped due to low confidence.

src/amr/data/electromag/electromag_initializer.hpp (2)

24-42: Review derived class ElectromagUserFuncInitializer.

This class inherits from ElectromagInitializer and overrides the init method. It uses a VecFieldInit object for initializing the magnetic field vector. The constructor initializes Binit_ directly from a dictionary, which is a clean way to handle configuration. However, error handling should be considered if the dictionary keys are not present or if the types do not match expectations.

Consider adding error handling or validation for the dictionary keys used in the constructor to prevent runtime errors.


78-90: Review factory class ElectromagInitializerFactory.

The factory class ElectromagInitializerFactory uses a dictionary to decide which initializer to create, which is a flexible design allowing runtime decisions. The use of std::make_unique ensures safe memory management. However, the condition in line 85 checks only for the presence of an "x_component" which might be too specific or error-prone if the dictionary structure changes.

Consider enhancing the robustness of the condition in the factory method to handle various configurations and potential changes in the dictionary structure more gracefully.

tests/simulator/test_samrai_restarts_parser.py (4)

3-3: Remove unused imports.

Several imports in the file are unused and should be removed to clean up the code and avoid confusion about dependencies. This includes imports for time, datetime, numpy, pathlib.Path, datetime.timedelta, ddt.data, ddt.unpack, pyphare.pharesee.run.Run, tests.diagnostic.dump_all_diags, pyphare.pharesee.hierarchy.patchdata.ParticleData, and pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5.

- import time
- import datetime
- import numpy
- from pathlib import Path
- from datetime import timedelta
- from ddt import data, unpack
- from pyphare.pharesee.run import Run
- from tests.diagnostic import dump_all_diags
- from pyphare.pharesee.hierarchy.patchdata import ParticleData
- from pyphare.pharesee.hierarchy.fromh5 get_all_available_quantities_from_h5

Also applies to: 5-5, 7-7, 8-8, 9-9, 11-11, 18-18, 22-22, 23-23, 24-24

Tools
Ruff

3-3: time imported but unused

Remove unused import: time

(F401)


51-63: Refactor recursive function for clarity and efficiency.

The function traverse_h5_for_groups_recursive is complex and hard to follow due to its recursive nature and mixed responsibilities. Consider refactoring it to separate concerns between handling attributes and data, and improve readability by using more descriptive variable names.

def traverse_h5_for_groups_recursive(h5content: "H5Content", group, path=""):
    if "level_0000" in path:
        h5content.attr.update({f"{path}/{key}": value for key, value in group.attrs.items()})
    if isinstance(group, h5py._hl.group.Group):
        for key in group:
            traverse_h5_for_groups_recursive(h5content, group[key], path=f"{path}/{key}")
    else:
        if "level_0000" not in path:
            return
        h5content.data[path] = group

99-99: Remove assignment to unused variable.

The local variable model is assigned but never used within the function or elsewhere in the code. This assignment can be removed to clean up the code.

- model = setup_model()
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.


Tools
Ruff

99-99: Local variable model is assigned to but never used

Remove assignment to unused variable model

(F841)


46-46: Avoid mutable default arguments.

Using mutable data structures like dictionaries as default arguments can lead to unexpected behavior because they are initialized only once. Use None as the default and initialize the dictionary inside the function.

-def dup(dic={}):
+def dup(dic=None):
+    if dic is None:
+        dic = {}
     dic.update(copy.deepcopy(simArgs))
     return dic
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.

def dup(dic=None):
    if dic is None:
        dic = {}
    dic.update(copy.deepcopy(simArgs))
    return dic
Tools
Ruff

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

Replace with None; initialize within function

(B006)

src/amr/data/initializers/samrai_hdf5_initializer.hpp (4)

61-70: Potential improvement in string concatenation.

The method getRestartFileFullPath uses manual string concatenation to build file paths. This is generally fine but can be error-prone and less efficient than using more robust methods like std::ostringstream or fmt::format (if available).

Consider using std::ostringstream for more robust and potentially more efficient string handling:

std::ostringstream pathBuilder;
pathBuilder << path
            << "/restore." << std::setw(6) << std::setfill('0') << idx
            << "/nodes." << SAMRAI::tbox::Utilities::nodeToString(mpi_size)
            << "/proc." << SAMRAI::tbox::Utilities::processorToString(rank);
return pathBuilder.str();

79-158: Review of nested SamraiHDF5File structure.

The nested SamraiHDF5File structure within SamraiH5Interface is a good use of C++ inheritance and encapsulation. The use of HighFive::CompoundType to define data types for HDF5 operations is appropriate and well-implemented. However, there are commented-out lines of code (e.g., lines 88-93) that should either be removed or clarified with comments if they are meant to be used in the future.

Additionally, the method getBoxFromPath is a clean implementation for retrieving data from HDF5 files, but ensure that the assertion on line 149 is appropriate as it assumes there will always be exactly one box data in the dataset.

Consider cleaning up or clarifying the purpose of commented-out code. Ensure the assertion in getBoxFromPath does not lead to unexpected crashes in cases where the dataset might not meet this expectation.


163-184: Review of populate_from method.

The populate_from method effectively demonstrates the use of the SamraiHDF5File structure for reading HDF5 files. The loop over MPI ranks and the logging are appropriate for the intended functionality. However, consider handling potential exceptions that might arise from HDF5 operations, especially given the direct file operations and data reads.

Add error handling for HDF5 operations to gracefully manage exceptions and provide more robust error reporting to the user.

Example:

try {
    // existing code
} catch (const HighFive::Exception& e) {
    PHARE_LOG_ERROR("Failed to populate from HDF5 file: " + std::string(e.what()));
    // handle error appropriately
}

1-2: Typographical error in include guard.

The include guard has a typographical error in its naming (INITIAZILIZERS should be INITIALIZERS). This could potentially lead to issues if the correct spelling is used elsewhere or in future code.

Suggested fix:

-#ifndef _PHARE_AMR_DATA_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#define _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
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.

#ifndef _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
#define _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
src/amr/physical_models/hybrid_model.hpp (1)

152-152: Concern about resource management with initializers_.release().

The call to initializers_.release() at the end of the initialize method is concerning. This operation detaches the managed object from the unique_ptr, potentially leading to a memory leak if not handled correctly elsewhere. It's crucial to ensure that the ownership and lifecycle of the object are managed appropriately after this call.

Consider managing the lifecycle of initializers_ more explicitly to prevent potential memory leaks. Here's a suggested change:

-    initializers_.release();
+    initializers_.reset();

This change ensures that the memory is properly freed when initializers_ is no longer needed.

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.

    initializers_.reset();
src/hdf5/detail/h5/h5_file.hpp (1)

78-79: Refactor: Use explicit type instead of auto for clarity.

The use of auto& in the file() method signatures (both const and non-const versions) could be less clear to readers unfamiliar with the underlying type. It's generally a good practice in C++ to use explicit types where it improves readability and maintainability, especially in public APIs.

Consider replacing auto& with the explicit type HiFile& to improve code clarity:

- NO_DISCARD auto& file() { return h5file_; }
- NO_DISCARD auto& file() const { return h5file_; }
+ NO_DISCARD HiFile& file() { return h5file_; }
+ NO_DISCARD HiFile& file() const { return h5file_; }
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.

    NO_DISCARD HiFile& file() { return h5file_; }
    NO_DISCARD HiFile& file() const { return h5file_; }
pyphare/pyphare/pharein/initialize/general.py (6)

32-45: Review and potentially refactor the py_fn_wrapper class.

The py_fn_wrapper class is designed to convert function arguments to numpy arrays and handle different return types. Consider the following improvements:

  • Documentation: There is no class or method documentation. Adding docstrings would improve understandability.
  • Error Handling: The class assumes that the input can always be converted to a numpy array. Consider adding error handling for cases where the conversion might fail.
  • Performance: Converting every argument to a numpy array might not be necessary and could impact performance. Evaluate if this conversion is required for all types of inputs.

48-59: Review the fn_wrapper class for potential improvements.

The fn_wrapper class extends py_fn_wrapper and adds functionality to convert numpy arrays to C++ SubSpan. Consider the following:

  • Documentation: Like its parent class, fn_wrapper lacks documentation. Adding detailed docstrings would clarify its role and usage.
  • Error Handling: The class does not handle potential exceptions from the cpp_etc_lib().makePyArrayWrapper call. Implementing error handling here would make the code more robust.
  • Design Consideration: The class tightly couples Python functionality with C++ operations. Ensure that this coupling is necessary and consider decoupling if possible to enhance modularity.

62-85: Simplify and document wrapper functions for type conversions.

The functions add_int, add_bool, add_double, and add_size_t are wrappers around library calls to add typed data to a path. Consider the following:

  • Documentation: None of these functions have docstrings. Adding them would clarify their purposes and usages.
  • Refactoring: These functions are very similar and could potentially be refactored into a single generic function that takes the type as a parameter.
  • Error Handling: The add_size_t function correctly handles negative inputs by raising an exception. Ensure similar robust error handling is present in other functions if applicable.

89-126: Review and potentially refactor the populateDict function.

The populateDict function is responsible for populating a dictionary with simulation parameters. It is a lengthy function with multiple responsibilities. Consider the following:

  • Refactoring: This function could be refactored to improve readability and maintainability. Breaking it down into smaller functions, each handling a specific part of the simulation configuration, would make the code cleaner and easier to manage.
  • Error Handling: The function assumes that all necessary attributes are present in the sim object. Adding checks and handling cases where attributes might be missing would prevent runtime errors.
  • Documentation: Adding a detailed docstring explaining the function's purpose, parameters, and expected behavior would enhance understandability.

257-309: Ensure robust error handling and validation in restart handling.

The restart handling logic in the populateDict function includes paths and file operations which could fail. Consider the following improvements:

  • Error Handling: The function should handle potential exceptions when file paths do not exist or data is not as expected. Use try-except blocks to catch and handle these exceptions gracefully.
  • Validation: Before using the restart file path, validate that it meets expected formats or contains expected data to prevent issues during runtime.
  • Documentation: Adding comments or docstrings explaining the logic and expectations around restart handling would make the code easier to understand and maintain.

165-166: Fix undefined variable issue in add_double call.

The variable simulation is not defined within the scope of the add_double function call. This will raise a NameError at runtime. It seems like it should be sim.tagging_threshold instead of simulation.tagging_threshold.

Proposed fix:

- add_double("simulation/AMR/refinement/tagging/threshold", simulation.tagging_threshold)
+ add_double("simulation/AMR/refinement/tagging/threshold", sim.tagging_threshold)
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.

            "simulation/AMR/refinement/tagging/threshold", sim.tagging_threshold
        )
Tools
Ruff

165-165: Undefined name simulation

(F821)

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

159-166: Add boundary checks to to_array function.

The function currently assumes that the input vector has at least To_Size elements. This could lead to undefined behavior if the vector is smaller than To_Size. Consider adding a check to ensure the vector's size is sufficient. If the vector is smaller, you could handle this case by either throwing an exception or filling the remaining elements of the array with default values.

Here's a suggested modification to include a size check:

+        if (from.size() < To_Size) {
+            throw std::length_error("Vector size is smaller than the specified array size.");
+        }
+        std::array<Type, To_Size> to{};
+        std::copy_n(from.begin(), To_Size, to.begin());
+        return to;

Committable suggestion was skipped due to low confidence.

pyphare/pyphare/pharein/simulation.py (1)

537-551: Improve error handling and clarity in error messages in check_init_options.

The function check_init_options correctly checks the format and directory but could improve by:

  • Providing more specific error messages related to the format and directory validation.
  • Adding exception handling for potential issues during directory checks.

Consider enhancing the function with more descriptive error messages and robust exception handling mechanisms:

    if init_options is not None and "format" in init_options:
        if init_options["format"] not in formats:
-            raise ValueError("Error - init_options format is invalid")
+            raise ValueError(f"Error - Unsupported init_options format: {init_options['format']}. Supported formats: {formats}")
        if "options" in init_options and "dir" in init_options["options"]:
            try:
                init_options["options"]["dir"] = check_directory(
                    init_options["options"]["dir"], "init_options"
                )
            except Exception as e:
+                raise ValueError(f"Error checking directory for init_options: {str(e)}")
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.

def check_init_options(**kwargs):
    """Advanced options to initialize from SAMRAI HDF5 files"""

    formats = ["samraih5"]
    init_options = kwargs.get("init_options", None)

    if init_options is not None and "format" in init_options:
        if init_options["format"] not in formats:
            raise ValueError(f"Error - Unsupported init_options format: {init_options['format']}. Supported formats: {formats}")
        if "options" in init_options and "dir" in init_options["options"]:
            try:
                init_options["options"]["dir"] = check_directory(
                    init_options["options"]["dir"], "init_options"
                )
            except Exception as e:
                raise ValueError(f"Error checking directory for init_options: {str(e)}")

    return init_options

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: 5

Outside diff range, codebase verification and nitpick comments (4)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)

29-43: Review of Class Structure and Method Signature

The class SamraiHDF5ParticleInitializer is well-structured for its purpose, using templates to handle different particle arrays and grid layouts. The inheritance from core::ParticleInitializer is correctly applied. However, the method loadParticles lacks implementation details, which might be intentional if this class serves as an interface or abstract class. If not, consider adding implementation details or documenting the expected behavior.

src/amr/data/particles/initializers/particle_initializer_factory.hpp (2)

73-74: Update references to MaxwellianParticleInitializer to use the fully qualified namespace.

The following files contain instances of MaxwellianParticleInitializer without the core:: prefix, which need to be updated to ensure consistency with the namespace restructuring:

  • tests/core/data/maxwellian_particle_initializer/test_init_funcs.hpp
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp

Please update these references to use core::MaxwellianParticleInitializer<ParticleArray, GridLayout>.

Analysis chain

Ensure consistency in namespace usage for MaxwellianParticleInitializer.

The MaxwellianParticleInitializer references have been updated to use the fully qualified namespace (core::MaxwellianParticleInitializer<ParticleArray, GridLayout>). This change aligns with the namespace restructuring and helps maintain consistency across the codebase. Ensure that all other references to MaxwellianParticleInitializer are similarly updated.

Also applies to: 84-85

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all references to `MaxwellianParticleInitializer` are updated.

# Test: Search for outdated references. Expect: No occurrences of unqualified `MaxwellianParticleInitializer`.
rg --type cpp 'MaxwellianParticleInitializer<ParticleArray, GridLayout>' -g '!src/amr/data/particles/initializers/particle_initializer_factory.hpp'

Length of output: 1204


24-24: Update references to ParticleInitializer to use fully qualified names.

The following files contain references to ParticleInitializer<ParticleArray, GridLayout> without the core:: namespace. To maintain consistency and avoid potential issues, these should be updated to core::ParticleInitializer<ParticleArray, GridLayout>.

  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp
  • tests/core/data/maxwellian_particle_initializer/test_init_funcs.hpp
Analysis chain

Clarify the usage of fully qualified names in type aliases.

The type alias ParticleInitializerT now uses a fully qualified name (core::ParticleInitializer<ParticleArray, GridLayout>). This change is consistent with the namespace restructuring mentioned in the summary. However, it's important to ensure that all references to ParticleInitializer in other parts of the codebase are updated to reflect this change.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify all references to `ParticleInitializer` are updated.

# Test: Search for outdated references. Expect: No occurrences of unqualified `ParticleInitializer`.
rg --type cpp 'ParticleInitializer<ParticleArray, GridLayout>' -g '!src/amr/data/particles/initializers/particle_initializer_factory.hpp'

Length of output: 1685

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

Line range hint 47-261: Review: Overall class HighFiveFile.

The class HighFiveFile is well-structured with clear separation of concerns, handling file operations, dataset and attribute management, and MPI communications effectively. The use of templates and conditionally compiled code enhances flexibility and adaptability to different environments.

However, consider the following improvements:

  • Error Handling: The method createHighFiveFile prints a warning and throws an exception if parallel HDF5 is not available. This is good, but ensure that all possible error states are handled similarly to prevent runtime issues.
  • Documentation: The class and methods could benefit from more detailed comments explaining the parameters and the behavior, especially for complex operations like write_attributes_per_mpi.
  • Const Correctness: The new file() method overload for const access is a good addition for const correctness.
Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between e721d2a and 85724ca.

Files selected for processing (15)
  • pyphare/pyphare/pharein/initialize/general.py (1 hunks)
  • src/amr/data/electromag/electromag_initializer.hpp (1 hunks)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1 hunks)
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp (1 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/amr/physical_models/hybrid_model.hpp (7 hunks)
  • src/core/data/electromag/electromag.hpp (3 hunks)
  • src/core/utilities/types.hpp (1 hunks)
  • src/hdf5/detail/h5/group_scanner.hpp (1 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (5 hunks)
  • tests/amr/models/test_models.cpp (3 hunks)
  • tests/amr/tagging/test_tagging.cpp (2 hunks)
  • tests/core/numerics/ion_updater/test_updater.cpp (5 hunks)
  • tests/simulator/test_samrai_restarts_parser.py (1 hunks)
Files skipped from review due to trivial changes (2)
  • src/amr/data/electromag/electromag_initializer.hpp
  • tests/amr/models/test_models.cpp
Files skipped from review as they are similar to previous changes (9)
  • pyphare/pyphare/pharein/initialize/general.py
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp
  • src/amr/physical_models/hybrid_model.hpp
  • src/core/data/electromag/electromag.hpp
  • src/core/utilities/types.hpp
  • src/hdf5/detail/h5/group_scanner.hpp
  • tests/amr/tagging/test_tagging.cpp
  • tests/core/numerics/ion_updater/test_updater.cpp
Additional context used
Path-based instructions (3)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

Pattern **/*.hpp: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

Learnings (1)
tests/simulator/test_samrai_restarts_parser.py (1)
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#784
File: tests/simulator/test_restarts.py:333-339
Timestamp: 2023-11-25T19:21:40.002Z
Learning: The user has indicated that minimal changes were made to get the function working, but acknowledges that there may still be redundant code present, such as sleep/wait/advances. The user is open to further streamlining the code.
Ruff
tests/simulator/test_samrai_restarts_parser.py

3-3: time imported but unused

Remove unused import: time

(F401)


5-5: datetime imported but unused

Remove unused import: datetime

(F401)


7-7: numpy imported but unused

Remove unused import: numpy

(F401)


8-8: pathlib.Path imported but unused

Remove unused import: pathlib.Path

(F401)


9-9: datetime.timedelta imported but unused

Remove unused import: datetime.timedelta

(F401)


11-11: ddt.data imported but unused

Remove unused import

(F401)


11-11: ddt.unpack imported but unused

Remove unused import

(F401)


18-18: pyphare.pharesee.run.Run imported but unused

Remove unused import: pyphare.pharesee.run.Run

(F401)


19-19: pyphare.simulator.simulator.Simulator imported but unused

Remove unused import: pyphare.simulator.simulator.Simulator

(F401)


22-22: tests.diagnostic.dump_all_diags imported but unused

Remove unused import: tests.diagnostic.dump_all_diags

(F401)


23-23: pyphare.pharesee.hierarchy.patchdata.ParticleData imported but unused

Remove unused import: pyphare.pharesee.hierarchy.patchdata.ParticleData

(F401)


24-24: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5 imported but unused

Remove unused import: pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5

(F401)


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

Replace with None; initialize within function

(B006)

Additional comments not posted (3)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)

47-52: Enhance Logging and Verify Method Implementation

The loadParticles method in SamraiHDF5ParticleInitializer class includes a basic logging statement. Consider enhancing this logging to include more context such as popname or details about the particles and layout. Additionally, if this method is intended to have more logic, ensure that the implementation is completed or well-documented if it serves as an interface.

src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

90-101: Review the new initializer case for samraih5.

A new case has been added for initializerName == "samraih5", which involves creating a SamraiHDF5ParticleInitializer. This addition enhances the factory's capabilities by supporting a new type of particle initializer. The implementation retrieves parameters from the dictionary and uses them to populate data from a specified directory. Ensure that the SamraiH5Interface and SamraiHDF5ParticleInitializer are properly implemented and tested, as this is a critical functionality addition.

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

256-259: New Feature: scan_for_groups method.

The addition of the scan_for_groups method enhances the HighFiveFile class by enabling the scanning of groups within an HDF5 file based on specified criteria. This method leverages the GroupScanner struct to perform the scanning, which is a good use of encapsulation and modularity.

However, ensure that the GroupScanner is thoroughly tested, especially since it involves recursive traversal which can be prone to errors if not handled carefully.

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 (4)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (4)

27-27: Inconsistent namespace in type alias

The type alias ParticleInitializerT still uses core::ParticleInitializer despite the namespace change to amr. This creates inconsistency in the codebase.


76-88: Consider updating namespace for consistency

The code continues to use core::MaxwellianParticleInitializer and core::Basis enums. For consistency with the namespace migration to amr, consider updating these references if the corresponding classes have been moved.


92-105: Add validation for required dictionary keys and error handling

The samraih5 initializer assumes required keys exist in the dictionary without validation, and the external call to populate_from lacks error handling.


107-107: Improve exception message informativeness

The exception message could be more helpful by including the unrecognized initializer name from the initializerName variable.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b9b5ce and e66b0df.

📒 Files selected for processing (4)
  • src/amr/CMakeLists.txt (1 hunks)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.hpp`: Review the C++ code, point out issues relative to principles of clean code, expressiveness, and performance.

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

⚙️ Source: CodeRabbit Configuration File

List of files the instruction was applied to:

  • src/amr/data/particles/initializers/particle_initializer_factory.hpp
🧠 Learnings (2)
📓 Common learnings
Learnt from: rochSmets
PR: PHAREHUB/PHARE#921
File: src/core/data/ions/ions.hpp:138-142
Timestamp: 2025-02-06T10:52:56.461Z
Learning: In PHARE's physics simulations, handling of zero density cells in velocity calculations must be based on physical requirements rather than simple numerical fixes. The solution must account for population-specific behavior in the bulk velocity computation.
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#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
PR: PHAREHUB/PHARE#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
PR: PHAREHUB/PHARE#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.
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#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
PR: PHAREHUB/PHARE#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.
src/amr/CMakeLists.txt (2)
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#943
File: res/cmake/dep/highfive.cmake:7-7
Timestamp: 2025-01-16T10:45:48.912Z
Learning: The HighFive library development has moved from BlueBrain/HighFive to highfive-devs/highfive as of December 2024 due to the conclusion of the Blue Brain Project.
Learnt from: nicolasaunai
PR: PHAREHUB/PHARE#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.
⏰ 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, gcc)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (macos-13)
  • GitHub Check: Analyze (cpp)
🔇 Additional comments (3)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (3)

8-16: LGTM: Clean conditional compilation for HIGHFIVE support

The conditional compilation block properly isolates the HIGHFIVE-dependent includes, maintaining clean separation of optional dependencies.


22-22: LGTM: Namespace updated to reflect code reorganization

The namespace change from core to amr aligns with the broader code reorganization mentioned in the AI summary.


111-111: LGTM: Namespace closing comment updated

The namespace closing comment properly reflects the updated namespace.

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: 2

♻️ Duplicate comments (24)
src/core/data/ndarray/ndarray_vector.hpp (6)

49-58: 2D index: fix integer promotion/overflow and add bounds checks

Current math may overflow in 32-bit intermediates; add casts to size_t and validate i,j within shape.

         {
-            auto i = std::get<0>(params);
-            auto j = std::get<1>(params);
+            auto const i0 = static_cast<std::size_t>(std::get<0>(params));
+            auto const j0 = static_cast<std::size_t>(std::get<1>(params));
+            auto const dim0 = static_cast<std::size_t>(nCells[0]);
+            auto const dim1 = static_cast<std::size_t>(nCells[1]);
+            if (i0 >= dim0 || j0 >= dim1)
+                throw std::out_of_range("NdArrayViewer::idx: 2D index out of bounds");
 
             if constexpr (c_ordering)
-                return j + i * nCells[1];
+                return j0 + i0 * dim1;
             else
-                return i + j * nCells[0];
+                return i0 + j0 * dim0;
         }

60-70: 3D index: fix integer promotion/overflow and add bounds checks

Same overflow risk and missing validation in 3D path.

         {
-            auto i = std::get<0>(params);
-            auto j = std::get<1>(params);
-            auto k = std::get<2>(params);
+            auto const i0 = static_cast<std::size_t>(std::get<0>(params));
+            auto const j0 = static_cast<std::size_t>(std::get<1>(params));
+            auto const k0 = static_cast<std::size_t>(std::get<2>(params));
+            auto const dim0 = static_cast<std::size_t>(nCells[0]);
+            auto const dim1 = static_cast<std::size_t>(nCells[1]);
+            auto const dim2 = static_cast<std::size_t>(nCells[2]);
+            if (i0 >= dim0 || j0 >= dim1 || k0 >= dim2)
+                throw std::out_of_range("NdArrayViewer::idx: 3D index out of bounds");
 
             if constexpr (c_ordering)
-                return k + j * nCells[2] + i * nCells[1] * nCells[2];
+                return k0 + j0 * dim2 + i0 * dim1 * dim2;
             else
-                return i + j * nCells[0] + k * nCells[1] * nCells[0];
+                return i0 + j0 * dim0 + k0 * dim1 * dim0;
         }

24-36: Add runtime bounds checks for container-based idx()

Without checks, invalid indexes can produce OOB access. Add explicit bounds validation (release-safe).

 NO_DISCARD static std::size_t idx(NCells const& nCells, Indexes<Index, dim> const& indexes)
 {
+    // runtime bounds checks per dimension
+    if constexpr (dim >= 1)
+        if (static_cast<std::size_t>(indexes[0]) >= static_cast<std::size_t>(nCells[0]))
+            throw std::out_of_range("NdArrayViewer::idx: index 0 out of bounds");
+    if constexpr (dim >= 2)
+        if (static_cast<std::size_t>(indexes[1]) >= static_cast<std::size_t>(nCells[1]))
+            throw std::out_of_range("NdArrayViewer::idx: index 1 out of bounds");
+    if constexpr (dim >= 3)
+        if (static_cast<std::size_t>(indexes[2]) >= static_cast<std::size_t>(nCells[2]))
+            throw std::out_of_range("NdArrayViewer::idx: index 2 out of bounds");
 
     if constexpr (dim == 1)
         return idx(nCells, indexes[0]);
 
     else if constexpr (dim == 2)
         return idx(nCells, indexes[0], indexes[1]);
 
     else if constexpr (dim == 3)
         return idx(nCells, indexes[0], indexes[1], indexes[2]);
 }

86-89: Promote debug-only assert to release-safe check in at(container idx)

Keep the assert, but also throw on OOB in release builds.

         auto const i = idx(nCells, indexes);
-        assert(i < product(nCells, std::size_t{1})); // debug bounds check
-        return data[i];
+        assert(i < product(nCells, std::size_t{1})); // debug bounds check
+        if (i >= product(nCells, std::size_t{1})) {
+            throw std::out_of_range("Index out of bounds in NdArrayViewer::at");
+        }
+        return data[i];

75-79: Add release-safe bounds check in at(..., Indexes&&...)

This overload lacks any check; introduce assert + exception for OOB.

-        return data[idx(nCells, indexes...)];
+        auto const i = idx(nCells, indexes...);
+        assert(i < product(nCells, std::size_t{1}));
+        if (i >= product(nCells, std::size_t{1})) {
+            throw std::out_of_range("Index out of bounds in NdArrayViewer::at");
+        }
+        return data[i];

44-47: Guard 1D index against negative-to-size_t wrap and add bounds check

Returning std::get<0>(params) directly can wrap if negative; also lacks bounds validation.

-            return std::get<0>(params);
+            {
+                auto const i0 = static_cast<std::size_t>(std::get<0>(params));
+                if (i0 >= static_cast<std::size_t>(nCells[0]))
+                    throw std::out_of_range("NdArrayViewer::idx: 1D index out of bounds");
+                return i0;
+            }
pyphare/pyphare/pharein/simulation.py (1)

541-542: Drop redundant default in kwargs.get.

Use the default None implicitly.

-    init_options = kwargs.get("init_options", None)
+    init_options = kwargs.get("init_options")
tests/simulator/test_init_from_restart.py (2)

1-16: Trim unused imports.

-import sys
@@
-from pyphare.pharesee.hierarchy.patchdata import FieldData, ParticleData
+# (remove unused FieldData, ParticleData)
@@
-from tests.simulator import SimulatorTest, test_restarts
+from tests.simulator import SimulatorTest

61-66: Assign Simulator to self for robust teardown.

Ensures reset runs even if the test fails mid‑run.

-        setup_model(sim)
-        Simulator(sim).run().reset()
+        setup_model()
+        self.simulator = Simulator(sim)
+        self.simulator.run().reset()
src/core/data/electromag/electromag.hpp (1)

24-24: Fix specifier order for static constexpr.

Prefer “static constexpr auto” for readability and consistency.

-        auto static constexpr dimension = VecFieldT::dimension;
+        static constexpr auto dimension = VecFieldT::dimension;
src/amr/data/initializers/samrai_hdf5_initializer.hpp (5)

53-60: Signature and specifier cleanup for getRestartFileFullPath.

Pass string by const&, ints by value; put ‘static’ before return type; place NO_DISCARD before type.

-    NO_DISCARD auto static getRestartFileFullPath(std::string path, int const& idx,
-                                                  int const& mpi_size, int const& rank)
+    NO_DISCARD static auto getRestartFileFullPath(const std::string& path, int idx,
+                                                  int mpi_size, int rank)

88-92: Optional: robust HDF5 open error handling.

Wrap file open to surface meaningful errors.

-    SamraiHDF5File(std::string const& filepath)
-        : Super{filepath, HighFive::File::ReadOnly, /*para=*/false}
+    SamraiHDF5File(std::string const& filepath)
+        : Super{/*para=*/false}
         , filepath_{filepath}
     {
+        try {
+            this->openFile(filepath, HighFive::File::ReadOnly);
+        } catch (const HighFive::Exception& e) {
+            throw std::runtime_error("Failed to open HDF5 file: " + filepath + " (" + e.what() + ")");
+        }
     }

1-2: Include guard typo (“INITIAZILIZERS”).

Correct to “INITIALIZERS”.

-#ifndef _PHARE_AMR_DATA_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#define _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_

102-106: Handle empty box vectors from SAMRAI HDFDatabase.

Avoid out-of-bounds access on boxes[0].

-        auto const boxes = db.getDatabaseBoxVector(path);
-        return Box_t{_to_std_array(boxes[0].d_data.d_lo), _to_std_array(boxes[0].d_data.d_hi)};
+        auto const boxes = db.getDatabaseBoxVector(path);
+        if (boxes.empty())
+            throw std::runtime_error("No boxes at path: " + path);
+        return Box_t{_to_std_array(boxes[0].d_data.d_lo), _to_std_array(boxes[0].d_data.d_hi)};

96-101: Undefined behavior: reinterpret_cast to std::array.

Do not assume SAMRAI internals layout. Copy explicitly.

-        std::size_t constexpr samrai_dim = 3; // always 3!
-        auto constexpr _to_std_array     = [](auto& i) {
-            return core::sized_array<GridLayout::dimension>(
-                *reinterpret_cast<std::array<int, samrai_dim> const*>(&i));
-        };
+        std::size_t constexpr samrai_dim = 3; // always 3!
+        auto constexpr _to_std_array     = [](auto const& i) {
+            std::array<int, samrai_dim> tmp{};
+            // assume i exposes operator[] or .d_data.{d_lo,d_hi}[k] via caller
+            for (std::size_t k = 0; k < samrai_dim; ++k)
+                tmp[k] = i[k];
+            return core::sized_array<GridLayout::dimension>(tmp);
+        };

If SAMRAI types don’t support operator[], build tmp using their documented accessors and then call sized_array.

src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)

1-2: Include guard typo (“INITIAZILIZERS”).

Correct to “INITIALIZERS” to avoid ODR/include issues.

-#ifndef _PHARE_AMR_DATA_PARTICLE_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_PARTICLE_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#define _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
src/amr/physical_models/hybrid_model.hpp (2)

32-33: Avoid using reserved identifiers for _Initializers

The name _Initializers starts with an underscore followed by a capital letter, which is reserved in C++ for compiler and standard library implementations. This could lead to undefined behavior or naming conflicts.


153-153: Memory leak from manual release of initializers_

Calling initializers_.release(); transfers ownership without deleting the object, causing a memory leak. The std::unique_ptr should automatically handle the object's lifetime. Additionally, releasing it could cause null pointer dereferences if initializers_ is accessed after this point.

pyphare/pyphare/pharein/initialize/general.py (6)

21-23: Move imports to the top-level scope

Importing modules inside functions can lead to decreased performance due to repeated imports and may affect readability. Unless there's a specific reason to import within the function (e.g., to avoid circular dependencies), it's recommended to place imports at the module level.


75-79: Use ValueError instead of RuntimeError in add_size_t

ValueError is more appropriate when the input argument has an invalid value, providing clearer semantics about the nature of the error.

 def add_size_t(path, val):
     casted = int(val)
     if casted < 0:
-        raise RuntimeError("pyphare.__init__::add_size_t received negative value")
+        raise ValueError(f"add_size_t: path '{path}' received negative value: {val}")
     pp.add_size_t(path, casted)

82-84: Add type checking in add_vector_int to handle non-iterable inputs

The function assumes that val is iterable. If a non-iterable is passed, it will raise a TypeError. Adding explicit type checking can provide a clearer error message.


198-199: Use ValueError instead of RuntimeError for negative populations

ValueError provides a clearer indication that the input value is invalid.


314-318: Add type handling for electron attributes in sim.electrons.dict_path()

The code assumes that electron attributes are either strings or numeric values. If an attribute is of a different type, it could cause unexpected errors.


204-208: Include population index in pop_path to prevent data overwriting

The pop_path variable construction doesn't properly incorporate the population index into the path string, which could lead to data overwriting for multiple populations.

     for pop_index, pop in enumerate(init_model.populations):
-        pop_path = "simulation/ions/pop"
-        add_string(pop_path + "{:d}/name".format(pop_index), pop)
+        pop_path = "simulation/ions/pop{:d}/".format(pop_index)
+        add_string(pop_path + "name", pop)
         d = modelDict[pop]
-        add_double(pop_path + "{:d}/mass".format(pop_index), d["mass"])
+        add_double(pop_path + "mass", d["mass"])
🧹 Nitpick comments (23)
src/core/data/ndarray/ndarray_vector.hpp (1)

5-5: Remove unused include to avoid compile-time overhead

core/logger.hpp isn’t used in this header. Drop it to reduce transitive includes.

-#include "core/logger.hpp"
tools/test_data_gen.py (3)

3-5: Remove unused imports.

-import unittest
-import numpy as np
+# (removed unused unittest, numpy)

31-38: Tighten subprocess handling and fix typo.

Avoid unused variable, capture text output for debugging, and correct “initalizing”.

-def launch(fn, n=5):
-    """Launch secondary process to run first simulation to avoid initalizing MPI now"""
+def launch(fn, n=5):
+    """Launch secondary process to run first simulation to avoid initializing MPI now"""
     cmd = f"mpirun -n {n} python3 -O {__file__} {fn}"
     print(cmd)
     try:
-        p = subprocess.run(cmd.split(" "), check=True, capture_output=True)
+        result = subprocess.run(cmd.split(" "), check=True, capture_output=True, text=True)
+        if result.stdout:
+            print(result.stdout)
+        if result.stderr:
+            print(result.stderr)
     except subprocess.CalledProcessError as e:
         print("CalledProcessError", e)
+        if e.stdout:
+            print(e.stdout)
+        if e.stderr:
+            print(e.stderr)
+        raise

Ruff flags S603 for subprocess use. Given fn comes from our code paths, risk is low; confirm it isn’t user-supplied at runtime.


11-23: Consider using pathlib for paths.

This script builds paths with string concatenation; pathlib improves portability.

-from tests.simulator import test_restarts
-from tests.diagnostic import dump_all_diags
-
-output_dir = "phare_data_gen/"
+from tests.simulator import test_restarts
+from tests.diagnostic import dump_all_diags
+from pathlib import Path
+output_dir = Path("phare_data_gen")
@@
-    out = output_dir + "/tests/simulator/test_init_from_restart"
+    out = output_dir / "tests/simulator" / "test_init_from_restart"
tests/simulator/test_init_from_restart.py (2)

28-36: Nit: remove redundant alias and make init format explicit.

Z duplicates restart_idx; also consider declaring init_options.format.

-restart_idx = Z = 2
+restart_idx = 2
@@
-    init_options=dict(dir=f"{first_out}/00000.00{Z}00", mpi_size=first_mpi_size),
+    init_options=dict(format="samraih5",
+                      dir=f"{first_out}/00000.00{restart_idx}00",
+                      mpi_size=first_mpi_size),

39-47: Remove unused parameter and fix alpha charge.

sim isn’t used; alpha charge should be +2 unless intentionally modeled otherwise.

-def setup_model(sim):
+def setup_model():
@@
-        alpha={"mass": 4, "charge": 1, "nbr_part_per_cell": ppc},
+        alpha={"mass": 4, "charge": 2, "nbr_part_per_cell": ppc},

Also update call sites accordingly (see Line 64).

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

1267-1276: Size directions array to dimension.

Minor safety/readability: constrain the directions array to the compile‑time dimension.

-            constexpr auto directions = std::array{Direction::X, Direction::Y, Direction::Z};
+            constexpr std::array<Direction, dimension> directions = [] {
+                if constexpr (dimension == 1) return std::array{Direction::X};
+                if constexpr (dimension == 2) return std::array{Direction::X, Direction::Y};
+                return std::array{Direction::X, Direction::Y, Direction::Z};
+            }();
pyphare/pyphare/pharein/initialize/__init__.py (1)

5-9: Optional: sort all for consistency.

 __all__ = [
-    "general",
-    "user_fns",
-    "samrai_hdf5",
+    "general",
+    "samrai_hdf5",
+    "user_fns",
 ]
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)

9-16: Rename unused loop variable and guard dir access.

-    for pop_index, pop in enumerate(init_model.populations):
+    for pop_index, _pop in enumerate(init_model.populations):
@@
-        add_string(partinit_path + "filepath", sim.init_options["dir"])
+        if "dir" not in sim.init_options:
+            raise ValueError("Error - init_options.dir is required for samraih5 initialization")
+        add_string(partinit_path + "filepath", sim.init_options["dir"])

Note: alternatively, validate this earlier in check_init_options (preferred).

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

20-23: Make This alias public (or remove if unused).

Declared before the public section, so it’s private. Move it below ‘public:’ if it’s part of the API.

-    class Electromag
-    {
-        using This = Electromag<VecFieldT>;
-    
-    public:
+    class Electromag
+    {
+    public:
+        using This = Electromag<VecFieldT>;
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (2)

12-14: #error without a clear message.

Provide a literal message for portability.

-#if !PHARE_HAS_HIGHFIVE
-#error // HIGHFIVE REQUIRED!
-#endif // PHARE_HAS_HIGHFIVE
+#if !PHARE_HAS_HIGHFIVE
+#error HIGHFIVE REQUIRED!
+#endif // PHARE_HAS_HIGHFIVE

54-63: No error handling around HDF5 dataset reads.

Gracefully handle missing datasets or read failures to prevent hard crashes.

-            core::apply(soa.as_tuple(), [&](auto& arg) {
-                auto const datapath = poppath + Packer::keys()[part_idx++];
-                h5File.file().getDataSet(datapath).read(arg);
-            });
+            core::apply(soa.as_tuple(), [&](auto& arg) {
+                auto const datapath = poppath + Packer::keys()[part_idx++];
+                try {
+                    auto ds = h5File.file().getDataSet(datapath);
+                    ds.read(arg);
+                } catch (const std::exception& e) {
+                    throw std::runtime_error(std::string("Failed to read dataset: ")
+                                             + datapath + " (" + e.what() + ")");
+                }
+            });
pyphare/pyphare/pharein/initialize/user_fns.py (4)

25-27: Use ValueError for invalid counts.

ValueError better fits invalid argument value.

-    if init_model.nbr_populations() < 0:
-        raise RuntimeError("Number of populations cannot be negative")
+    if init_model.nbr_populations() < 0:
+        raise ValueError("Number of populations cannot be negative")

10-16: Guard against missing electromag keys.

Avoid KeyError by validating required keys.

 def populate_electromag(sim):
     addInitFunction = getattr(pp, "addInitFunction{:d}".format(sim.ndim) + "D")
     modelDict = sim.model.model_dict
+    for k in ("bx", "by", "bz"):
+        if k not in modelDict:
+            raise KeyError(f"model_dict missing '{k}' for magnetic initializer")
     maginit_path = "simulation/electromag/magnetic/initializer/"

20-21: Minor duplication and configurability.

  • addInitFunction retrieval duplicated; factor per-file helper if desired.
  • “maxwellian” hardcoded; consider making it configurable if multiple distributions are planned.

Also applies to: 35-35


33-45: Validate population dict keys before use.

Prevent KeyError for required fields like density, vx, …, nbrParticlesPerCell, density_cut_off.

-        d = modelDict[pop]
+        d = modelDict[pop]
+        required = ("density","vx","vy","vz","vthx","vthy","vthz","charge",
+                    "nbrParticlesPerCell","density_cut_off")
+        missing = [k for k in required if k not in d]
+        if missing:
+            raise KeyError(f"population '{pop}' missing keys: {missing}")

Also applies to: 50-51

src/amr/data/initializers/samrai_hdf5_initializer.hpp (2)

4-11: Missing standard includes; make header self-contained.

Requires , , , <unordered_map>.

 #include <memory>
 #include <cassert>
+#include <vector>
+#include <tuple>
+#include <string>
+#include <unordered_map>

78-79: Remove unused member.

box2dataset is declared but never used.

-    std::unordered_map<std::string, std::string> box2dataset;
+    // removed unused box2dataset
src/amr/physical_models/hybrid_model.hpp (2)

231-239: Consider error handling for missing particle initializers

The constructor creates particle initializers for each population but doesn't validate that creation succeeded. If ParticleInitializerFactory::create returns nullptr for an invalid configuration, the map would store a null pointer leading to crashes when dereferenced in particles().

Consider adding validation:

     for (auto& pop : state.ions)
-        particle_pop_init.emplace(
-            pop.name(), ParticleInitializerFactory::create(pop.particleInitializerInfo()));
+    {
+        auto initializer = ParticleInitializerFactory::create(pop.particleInitializerInfo());
+        if (!initializer)
+            throw std::runtime_error("Failed to create particle initializer for population: " + pop.name());
+        particle_pop_init.emplace(pop.name(), std::move(initializer));
+    }

243-243: Add bounds checking for particle population access

The particles() method directly accesses the map without checking if the population exists, which could throw std::out_of_range if called with an invalid population name.

Consider adding bounds checking:

-    auto& particles(typename Ions::value_type& pop) { return *particle_pop_init[pop.name()]; }
+    auto& particles(typename Ions::value_type& pop) { 
+        auto it = particle_pop_init.find(pop.name());
+        if (it == particle_pop_init.end())
+            throw std::runtime_error("Particle initializer not found for population: " + pop.name());
+        return *it->second;
+    }
pyphare/pyphare/pharein/initialize/general.py (3)

135-135: Remove unnecessary int() cast

The value len(boxes) already returns an integer, making the explicit cast redundant.

-            add_int(level_path + "nbr_boxes/", int(len(boxes)))
+            add_int(level_path + "nbr_boxes/", len(boxes))

89-319: Consider breaking down populateDict into smaller functions

This function is quite lengthy (230+ lines) and handles many different aspects of simulation configuration. Breaking it down into smaller, focused functions would improve maintainability and readability.

Consider refactoring into focused helper functions:

def _populate_grid_settings(sim):
    """Populate grid-related settings."""
    add_string("simulation/grid/layout_type", sim.layout)
    add_int("simulation/grid/nbr_cells/x", sim.cells[0])
    # ... rest of grid settings

def _populate_amr_settings(sim):
    """Populate AMR-related settings."""
    if sim.smallest_patch_size is not None:
        add_vector_int("simulation/AMR/smallest_patch_size", sim.smallest_patch_size)
    # ... rest of AMR settings

def _populate_diagnostic_settings(sim, serialized_sim):
    """Populate diagnostic settings."""
    diag_path = "simulation/diagnostics/"
    for diag in list(sim.diagnostics.values()):
        # ... diagnostic settings

def populateDict(sim):
    import pybindlibs.dictator as pp
    
    add_string("simulation/name", "simulation_test")
    add_int("simulation/dimension", sim.ndim)
    
    _populate_grid_settings(sim)
    _populate_amr_settings(sim)
    # ... call other helper functions

273-275: Improve error message formatting

The error message spans multiple lines in the source code. Consider using a more concise format or using string formatting for better readability.

-                raise ValueError(
-                    f"PHARE restart file not found for time {restart_time}"
-                )
+                raise ValueError(f"PHARE restart file not found for time {restart_time}")
📜 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 e66b0df and 6009bd3.

📒 Files selected for processing (41)
  • pyphare/pyphare/pharein/__init__.py (3 hunks)
  • pyphare/pyphare/pharein/initialize/__init__.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/general.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/user_fns.py (1 hunks)
  • pyphare/pyphare/pharein/simulation.py (3 hunks)
  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (3 hunks)
  • pyphare/pyphare/pharesee/hierarchy/patchdata.py (1 hunks)
  • res/cmake/test.cmake (1 hunks)
  • src/amr/CMakeLists.txt (1 hunks)
  • src/amr/data/electromag/electromag_initializer.hpp (1 hunks)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1 hunks)
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp (1 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/amr/level_initializer/hybrid_level_initializer.hpp (2 hunks)
  • src/amr/physical_models/hybrid_model.hpp (7 hunks)
  • src/core/CMakeLists.txt (0 hunks)
  • src/core/data/electromag/electromag.hpp (3 hunks)
  • src/core/data/grid/gridlayout.hpp (3 hunks)
  • src/core/data/ions/ions.hpp (1 hunks)
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2 hunks)
  • src/core/data/ions/particle_initializers/particle_initializer.hpp (1 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (4 hunks)
  • src/core/data/vecfield/vecfield_initializer.hpp (1 hunks)
  • src/core/utilities/box/box.hpp (1 hunks)
  • src/core/utilities/types.hpp (1 hunks)
  • src/hdf5/detail/h5/group_scanner.hpp (1 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (4 hunks)
  • src/phare_core.hpp (0 hunks)
  • src/simulator/phare_types.hpp (1 hunks)
  • tests/amr/data/particles/initializer/CMakeLists.txt (1 hunks)
  • tests/amr/data/particles/initializer/test_main.cpp (3 hunks)
  • tests/amr/models/test_models.cpp (3 hunks)
  • tests/amr/tagging/test_tagging.cpp (2 hunks)
  • tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (2 hunks)
  • tests/core/numerics/ion_updater/CMakeLists.txt (1 hunks)
  • tests/core/numerics/ion_updater/test_updater.cpp (4 hunks)
  • tests/simulator/CMakeLists.txt (2 hunks)
  • tests/simulator/test_init_from_restart.py (1 hunks)
  • tools/test_data_gen.py (1 hunks)
💤 Files with no reviewable changes (2)
  • src/core/CMakeLists.txt
  • src/phare_core.hpp
🚧 Files skipped from review as they are similar to previous changes (23)
  • tests/amr/data/particles/initializer/CMakeLists.txt
  • src/core/utilities/box/box.hpp
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp
  • src/core/utilities/types.hpp
  • res/cmake/test.cmake
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
  • src/core/data/ions/particle_initializers/particle_initializer.hpp
  • tests/amr/models/test_models.cpp
  • pyphare/pyphare/pharesee/hierarchy/patchdata.py
  • src/amr/CMakeLists.txt
  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py
  • tests/amr/data/particles/initializer/test_main.cpp
  • tests/core/numerics/ion_updater/test_updater.cpp
  • src/simulator/phare_types.hpp
  • src/amr/level_initializer/hybrid_level_initializer.hpp
  • src/core/data/vecfield/vecfield_initializer.hpp
  • tests/simulator/CMakeLists.txt
  • src/hdf5/detail/h5/group_scanner.hpp
  • tests/amr/tagging/test_tagging.cpp
  • src/amr/data/electromag/electromag_initializer.hpp
  • tests/core/numerics/ion_updater/CMakeLists.txt
  • src/hdf5/detail/h5/h5_file.hpp
  • src/amr/data/particles/initializers/particle_initializer_factory.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/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
  • src/core/data/ions/ions.hpp
  • src/core/data/electromag/electromag.hpp
  • src/amr/physical_models/hybrid_model.hpp
  • src/core/data/grid/gridlayout.hpp
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
🧬 Code graph analysis (13)
tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (3)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)
  • particles (34-35)
src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (1)
  • particles (65-66)
src/core/data/ions/particle_initializers/particle_initializer.hpp (1)
  • particles (13-14)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (2)
pyphare/pyphare/pharein/initialize/general.py (2)
  • add_int (63-64)
  • populateDict (89-318)
pyphare/pyphare/pharein/__init__.py (1)
  • populateDict (71-80)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (4)
src/core/data/ions/particle_initializers/particle_initializer.hpp (1)
  • particles (13-14)
src/core/utilities/types.hpp (2)
  • apply (97-100)
  • apply (97-97)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • i (44-48)
src/core/utilities/box/box.hpp (5)
  • isIn (218-245)
  • isIn (218-218)
  • isIn (248-252)
  • isIn (248-249)
  • isIn (258-258)
src/core/data/electromag/electromag.hpp (2)
src/diagnostic/diagnostic_model_view.hpp (1)
  • dimension (30-60)
tests/core/data/electromag/test_electromag_fixtures.hpp (1)
  • E (19-23)
pyphare/pyphare/pharein/__init__.py (5)
pyphare/pyphare/pharein/simulation.py (1)
  • Simulation (764-1099)
pyphare/pyphare/pharesee/hierarchy/hierarchy.py (1)
  • sim (117-136)
pyphare/pyphare/pharein/initialize/general.py (1)
  • populateDict (89-318)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)
  • populateDict (6-16)
pyphare/pyphare/pharein/initialize/user_fns.py (1)
  • populateDict (5-7)
src/amr/physical_models/hybrid_model.hpp (1)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
src/core/data/grid/gridlayout.hpp (3)
pyphare/pyphare/core/gridlayout.py (2)
  • physicalStartIndex (262-264)
  • AMRToLocal (343-347)
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/amr/resources_manager/amr_utils.hpp (5)
  • AMRToLocal (47-48)
  • AMRToLocal (55-56)
  • AMRToLocal (64-64)
  • AMRToLocal (79-92)
  • AMRToLocal (79-80)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (2)
src/core/utilities/types.hpp (2)
  • sized_array (133-147)
  • sized_array (133-134)
src/hdf5/detail/h5/group_scanner.hpp (2)
  • group (35-61)
  • group (35-35)
src/core/data/ndarray/ndarray_vector.hpp (1)
src/core/utilities/types.hpp (2)
  • product (256-259)
  • product (256-256)
pyphare/pyphare/pharein/initialize/general.py (4)
pyphare/pyphare/core/phare_utilities.py (1)
  • is_scalar (54-55)
pyphare/pyphare/pharein/load_balancer.py (1)
  • LoadBalancer (9-57)
pyphare/pyphare/pharein/simulation.py (3)
  • serialize (1105-1114)
  • deserialize (1117-1121)
  • is_restartable_compared_to (1060-1068)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_etc_lib (12-15)
pyphare/pyphare/pharein/initialize/user_fns.py (3)
pyphare/pyphare/pharein/initialize/general.py (5)
  • add_double (71-72)
  • add_int (63-64)
  • add_size_t (75-79)
  • fn_wrapper (50-59)
  • populateDict (89-318)
pyphare/pyphare/pharein/__init__.py (1)
  • populateDict (71-80)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)
  • populateDict (6-16)
tests/simulator/test_init_from_restart.py (6)
pyphare/pyphare/pharesee/hierarchy/patchdata.py (2)
  • FieldData (32-194)
  • ParticleData (197-240)
pyphare/pyphare/pharesee/hierarchy/fromh5.py (1)
  • get_all_available_quantities_from_h5 (27-33)
pyphare/pyphare/pharesee/hierarchy/hierarchy.py (1)
  • format_timestamp (13-16)
pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (2)
  • single_patch_for_LO (662-705)
  • hierarchy_compare (618-659)
tests/simulator/__init__.py (2)
  • SimulatorTest (200-266)
  • register_diag_dir_for_cleanup (233-234)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-61)
tools/test_data_gen.py (3)
tests/simulator/test_restarts.py (1)
  • test_restarts (230-289)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-61)
tests/simulator/test_init_from_restart.py (1)
  • setup_model (39-46)
🪛 Ruff (0.12.2)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py

9-9: Loop control variable pop not used within loop body

Rename unused pop to _pop

(B007)

pyphare/pyphare/pharein/initialize/__init__.py

5-9: __all__ is not sorted

Apply an isort-style sorting to __all__

(RUF022)

pyphare/pyphare/pharein/initialize/general.py

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

(TRY003)


135-135: Value being cast to int is already an integer

Remove unnecessary int call

(RUF046)


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

(TRY003)


273-275: Avoid specifying long messages outside the exception class

(TRY003)


281-283: Avoid specifying long messages outside the exception class

(TRY003)


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

(TRY003)

pyphare/pyphare/pharein/initialize/user_fns.py

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

(TRY003)

pyphare/pyphare/pharein/simulation.py

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

(TRY003)

tests/simulator/test_init_from_restart.py

39-39: Unused function argument: sim

(ARG001)

tools/test_data_gen.py

35-35: Local variable p is assigned to but never used

Remove assignment to unused variable p

(F841)


35-35: subprocess call: check for execution of untrusted input

(S603)

⏰ 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-latest)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (macos-13)
  • GitHub Check: Analyze (cpp)
  • GitHub Check: Analyze (python)
🔇 Additional comments (9)
src/core/data/ions/ions.hpp (1)

18-19: Decoupling from ParticleInitializerFactory looks good.

Removing the factory include from this header reduces coupling and rebuilds; no usage remains here.

Please confirm all call sites now include the moved AMR factory header where needed (tests already seem updated).

pyphare/pyphare/pharein/simulation.py (2)

678-679: Accept new keyword.

Adding "init_options" to accepted keywords aligns the API surface.


713-714: Wiring validation is correct.

Propagating the (possibly normalized) init_options back into kwargs is consistent with the existing pattern.

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

804-820: AMRToLocal(Point, localbox): OK; pre‑cast assert is good.

Logic matches the inverse of localToAMR and keeps the assert before uint cast (per prior guidance).

Confirm physicalStartIndex(QtyCentering::dual, Direction::X) is identical across directions for all supported layouts, as assumed here.


834-846: AMRToLocal(Box, localbox) and convenience overloads: LGTM.

Box mapping composes the point mapping correctly and the overloads preserve the prior API.


1212-1226: New domainBoxFor/ghostBoxFor helpers improve clarity.

Nice wrappers around _BoxFor; no issues spotted.

tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (1)

54-55: Test updates for popname parameter are correct.

Passing "protons" matches the new loadParticles signature.

Also applies to: 63-64

pyphare/pyphare/pharein/__init__.py (1)

72-81: LGTM — modular initializer delegation is clear.

Delegation to general/user_fns/samrai_hdf5 based on init_options is straightforward.

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

148-149: Verified — no change required: loadParticles already accepts pop name

ParticleInitializer::loadParticles(ParticleArray&, GridLayout const&, std::string const& popname) is declared and concrete initializers implement that signature (e.g. src/core/data/ions/particle_initializers/particle_initializer.hpp:13, src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp:139, src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp:34).

@PhilipDeegan PhilipDeegan force-pushed the restartinator branch 2 times, most recently from e64ba6c to 7d40b01 Compare October 7, 2025 18: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: 4

♻️ Duplicate comments (36)
src/core/data/ndarray/ndarray_vector.hpp (3)

38-71: Fix integer overflow risk and add bounds validation.

The multiplication operations in the 2D and 3D index calculations can overflow when array dimensions are large, as the operands are likely uint32_t (from nCells_ in the classes using this viewer) but the result is size_t. Additionally, there is no validation that the input indexes are within the valid range defined by nCells.

Apply this diff to fix overflow and add bounds checking:

 template<typename NCells, typename... Indexes>
 NO_DISCARD static std::size_t idx(NCells const& nCells, Indexes const&... indexes)
 {
     auto params = std::forward_as_tuple(indexes...);
     static_assert(sizeof...(Indexes) == dim);

     if constexpr (dim == 1)
     {
-        return std::get<0>(params);
+        auto i = std::get<0>(params);
+        if (i >= nCells[0]) {
+            throw std::out_of_range("Index out of bounds in NdArrayViewer::idx");
+        }
+        return i;
     }

     if constexpr (dim == 2)
     {
         auto i = std::get<0>(params);
         auto j = std::get<1>(params);
+        if (i >= nCells[0] || j >= nCells[1]) {
+            throw std::out_of_range("Index out of bounds in NdArrayViewer::idx");
+        }

         if constexpr (c_ordering)
-            return j + i * nCells[1];
+            return j + static_cast<std::size_t>(i) * static_cast<std::size_t>(nCells[1]);
         else
-            return i + j * nCells[0];
+            return i + static_cast<std::size_t>(j) * static_cast<std::size_t>(nCells[0]);
     }

     if constexpr (dim == 3)
     {
         auto i = std::get<0>(params);
         auto j = std::get<1>(params);
         auto k = std::get<2>(params);
+        if (i >= nCells[0] || j >= nCells[1] || k >= nCells[2]) {
+            throw std::out_of_range("Index out of bounds in NdArrayViewer::idx");
+        }

         if constexpr (c_ordering)
-            return k + j * nCells[2] + i * nCells[1] * nCells[2];
+        {
+            auto const dim2 = static_cast<std::size_t>(nCells[2]);
+            auto const dim1 = static_cast<std::size_t>(nCells[1]);
+            return k + static_cast<std::size_t>(j) * dim2 + 
+                   static_cast<std::size_t>(i) * dim1 * dim2;
+        }
         else
-            return i + j * nCells[0] + k * nCells[1] * nCells[0];
+        {
+            auto const dim0 = static_cast<std::size_t>(nCells[0]);
+            auto const dim1 = static_cast<std::size_t>(nCells[1]);
+            return i + static_cast<std::size_t>(j) * dim0 + 
+                   static_cast<std::size_t>(k) * dim1 * dim0;
+        }
     }
 }

Based on past review comments and security scanner findings.


24-36: Missing bounds validation in idx delegation.

This overload delegates to dimension-specific idx implementations without validating that the input indexes are within bounds. While the actual index calculation happens in lines 38-71, bounds validation should occur before delegation to catch out-of-bounds access early.

Add bounds checking before delegation:

 template<typename NCells, template<typename, std::size_t> typename Indexes, typename Index>
 NO_DISCARD static std::size_t idx(NCells const& nCells, Indexes<Index, dim> const& indexes)
 {
+    for (std::size_t i = 0; i < dim; ++i) {
+        if (indexes[i] >= nCells[i]) {
+            throw std::out_of_range("Index out of bounds in NdArrayViewer::idx");
+        }
+    }
+
     if constexpr (dim == 1)
         return idx(nCells, indexes[0]);

Based on past review comments.


86-88: Replace debug-only assert with runtime bounds checking.

The assert on Line 87 is only active in debug builds and is disabled in release builds. This means out-of-bounds access can occur silently in production, potentially leading to undefined behavior or security vulnerabilities.

Apply this diff to add runtime bounds checking:

 auto const i = idx(nCells, indexes);
-assert(i < product(nCells, std::size_t{1})); // debug bounds check
+if (i >= product(nCells, std::size_t{1})) {
+    throw std::out_of_range("Index out of bounds in NdArrayViewer::at");
+}
 return data[i];

Based on past review comments.

src/amr/CMakeLists.txt (1)

103-105: Link HighFive with PUBLIC scope so the target can include it

Using INTERFACE here means ${PROJECT_NAME} itself won’t inherit HighFive’s include directories or any other usage requirements. Because the library’s sources include HighFive headers, the build breaks once this condition is hit. Switch the scope to PUBLIC (or at least PRIVATE) so the target can compile successfully.

-if (HighFive)
-  target_link_libraries(${PROJECT_NAME} INTERFACE HighFive)
+if (HighFive)
+  target_link_libraries(${PROJECT_NAME} PUBLIC HighFive)
 endif()

Based on learnings

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

78-79: Consider explicit return types for clarity.

The auto& return type reduces clarity about what is being returned. Consider using explicit types (HiFile& and HiFile const&) for better code readability, especially for developers unfamiliar with the implementation.


256-259: Add const qualifier to scan_for_groups method.

The method does not modify any member variables and should be marked const to improve const-correctness and allow it to be called on const instances of HighFiveFile.

Apply this diff:

-    std::unordered_set<std::string> scan_for_groups(std::vector<std::string> const& contains)
+    std::unordered_set<std::string> scan_for_groups(std::vector<std::string> const& contains) const
src/hdf5/detail/h5/group_scanner.hpp (2)

29-34: Specify explicit return type.

The scan method returns auto&, which reduces clarity. Consider using an explicit return type std::unordered_set<std::string>& or, preferably, returning by value to match the usage pattern in h5_file.hpp and avoid confusion with temporary objects.

Apply this diff to return by value:

-    auto& scan(std::string const& from = "/")
+    std::unordered_set<std::string> scan(std::string const& from = "/")

46-58: Simplify filtering logic for clarity.

The current filtering logic is correct but uses a confusing variable name (cont) and a manual loop. Consider using std::all_of to make the intent clearer: include paths that contain all specified strings.

Apply this diff:

-                else
-                {
-                    bool cont = false;
-                    for (auto const& c : contains)
-                        if (fpath.find(c) == std::string::npos)
-                        {
-                            cont = true;
-                            break;
-                        }
-                    if (cont) // next node in listObjectNames
-                        continue;
-                    groups.insert(fpath);
-                }
+                else if (std::all_of(contains.begin(), contains.end(),
+                                     [&](auto const& c) { return fpath.find(c) != std::string::npos; }))
+                {
+                    groups.insert(fpath);
+                }
tools/test_data_gen.py (2)

1-11: Remove unused imports.

The unittest and numpy imports are not used in this file.

Apply this diff to remove unused imports:

 import sys
 import copy
-import unittest
 import subprocess
-import numpy as np
 import pyphare.pharein as ph

30-38: Fix unused variable and improve error reporting.

The variable p is assigned but never used. Additionally, error handling could be more informative.

Apply this diff:

 def launch(fn, n=5):
     """Launch secondary process to run first simulation to avoid initalizing MPI now"""
     cmd = f"mpirun -n {n} python3 -O {__file__} {fn}"
     print(cmd)
     try:
-        p = subprocess.run(cmd.split(" "), check=True, capture_output=True)
+        subprocess.run(cmd.split(" "), check=True, capture_output=True, text=True)
     except subprocess.CalledProcessError as e:
-        print("CalledProcessError", e)
+        print(f"Error running {fn}: {e}")
+        if e.stdout:
+            print(f"stdout: {e.stdout}")
+        if e.stderr:
+            print(f"stderr: {e.stderr}")
+        raise
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)

6-16: Rename unused loop variable.

The loop variable pop is not used within the loop body and should be renamed to _pop to indicate it's intentionally unused.

Apply this diff:

-    for pop_index, pop in enumerate(init_model.populations):
+    for pop_index, _pop in enumerate(init_model.populations):
pyphare/pyphare/pharein/simulation.py (1)

541-541: Omit explicit None in dict.get

Use kwargs.get("init_options") instead of kwargs.get("init_options", None).

-    init_options = kwargs.get("init_options", None)
+    init_options = kwargs.get("init_options")
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (3)

30-33: Default the empty constructor

Cleaner and conveys intent.

-    SamraiHDF5FieldInitializer() {}
+    SamraiHDF5FieldInitializer() = default;

43-47: Assert pointers before deref

Guard h5FilePtr and pdataptr to avoid null deref.

-    for (auto const& [overlap_box, h5FilePtr, pdataptr] : overlaps)
+    for (auto const& [overlap_box, h5FilePtr, pdataptr] : overlaps)
     {
+        assert(h5FilePtr && "null HDF5 file pointer");
+        assert(pdataptr && "null pdata pointer");
         auto& h5File       = *h5FilePtr;
         auto& pdata        = *pdataptr;

1-2: Fix typo in include guard macro

Use INITIALIZERS (not INITIAZILIZERS).

-#ifndef _PHARE_AMR_DATA_FIELD_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_FIELD_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef _PHARE_AMR_DATA_FIELD_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#define _PHARE_AMR_DATA_FIELD_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (3)

57-62: Add error handling for HDF5 reads

Check dataset existence or catch read exceptions to improve diagnostics when files/paths are missing.


1-2: Fix typo in include guard macro

Use INITIALIZERS.

-#ifndef _PHARE_AMR_DATA_PARTICLE_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_PARTICLE_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#define _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_

5-11: Include SamraiH5Interface header (self‑contained)

Avoid relying on transitive includes.

 #include "core/utilities/types.hpp"
 #include "core/utilities/box/box.hpp"
 #include "core/utilities/point/point.hpp"
 #include "core/data/ions/particle_initializers/particle_initializer.hpp"
 
 #include "core/data/particles/particle_packer.hpp"
+#include "amr/data/initializers/samrai_hdf5_initializer.hpp"
pyphare/pyphare/pharein/initialize/user_fns.py (4)

25-27: Use ValueError for invalid population count

More appropriate for bad values.

-    if init_model.nbr_populations() < 0:
-        raise RuntimeError("Number of populations cannot be negative")
+    if init_model.nbr_populations() < 0:
+        raise ValueError("Number of populations cannot be negative")

35-46: Hardcoded names: consider parameterizing or deriving from model dict

If multiple distributions/bases are needed, read from d (with defaults) instead of constants.


10-16: Add minimal key checks for bx/by/bz to avoid KeyError

Validate presence or provide defaults before registration.


11-11: Deduplicate addInitFunction retrieval

Extract helper to reduce repetition.

Also applies to: 20-20

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

24-24: Unconventional specifier order.

The specifier order auto static constexpr is non-standard. C++ convention places storage-class specifiers before type specifiers.

Apply this diff to follow conventional ordering:

-auto static constexpr dimension = VecFieldT::dimension;
+static constexpr auto dimension = VecFieldT::dimension;
tests/simulator/test_init_from_restart.py (2)

1-1: Remove unused imports.

Multiple imports are flagged as unused by static analysis:

  • sys (line 1)
  • subprocess (line 4)
  • numpy (line 5)
  • FieldData, ParticleData (line 10)
  • test_restarts (line 15)

Apply this diff to remove unused imports:

-import sys
 import copy
 import unittest
-import subprocess
-import numpy as np
 import pyphare.pharein as ph
 from pathlib import Path

 from pyphare.simulator.simulator import Simulator
-from pyphare.pharesee.hierarchy.patchdata import FieldData, ParticleData
 from pyphare.pharesee.hierarchy.fromh5 import get_all_available_quantities_from_h5
 from pyphare.pharesee.hierarchy.hierarchy import format_timestamp
 from pyphare.pharesee.hierarchy.hierarchy_utils import single_patch_for_LO
 from pyphare.pharesee.hierarchy.hierarchy_utils import hierarchy_compare
-from tests.simulator import SimulatorTest, test_restarts
+from tests.simulator import SimulatorTest
 from tests.diagnostic import dump_all_diags

Also applies to: 4-4, 5-5, 10-10, 15-15


42-42: Verify alpha particle charge value.

Alpha particles typically have a charge of +2. The code sets it to 1, which may not reflect the correct physical properties unless this is intentional for testing purposes.

src/amr/data/particles/initializers/particle_initializer_factory.hpp (4)

50-51: Pass small built-in types by value.

The int parameters are passed by const reference (int const&), which is less efficient than passing by value for small built-in types. This applies to both declarations in the provided context (though the second one is in a different file).

Apply this diff:

-void populate_from(std::string const& dir, int const& idx, int const& mpi_size,
+void populate_from(std::string const& dir, int idx, int mpi_size,
                    std::string const& field_name = "field_EM_B_x");

-NO_DISCARD auto static getRestartFileFullPath(std::string path, int const& idx,
-                                              int const& mpi_size, int const& rank)
+NO_DISCARD static auto getRestartFileFullPath(std::string const& path, int idx,
+                                              int mpi_size, int rank)

Also applies to: 53-55


101-101: Add error handling for external call.

The call to populate_from lacks error handling. If this function fails or throws an exception, it may cause unexpected application behavior. Wrap it in a try-catch block.

Apply this diff:

-                // scan restart files for later use
-                SamraiH5Interface<GridLayout>::INSTANCE().populate_from(dir, index, mpi_size);
+                try
+                {
+                    // scan restart files for later use
+                    SamraiH5Interface<GridLayout>::INSTANCE().populate_from(dir, index, mpi_size);
+                }
+                catch (const std::exception& e)
+                {
+                    throw std::runtime_error(std::string("Failed to populate from SAMRAI H5: ") + e.what());
+                }

107-107: Improve exception message specificity.

The exception message is generic. Including the unrecognized initializer name would help with debugging.

Apply this diff:

-            throw std::runtime_error("No Particle Initializer chosen!");
+            throw std::runtime_error("Unknown Particle Initializer: '" + initializerName + "'");

94-105: Add validation for required dictionary keys.

The samraih5 initializer assumes that dict contains filepath, index, and mpi_size. Missing keys will cause runtime errors. Add validation before accessing these keys.

Apply this diff:

 #if PHARE_HAS_HIGHFIVE
             if (initializerName == "samraih5")
             {
+                if (!dict.contains("filepath") || !dict.contains("index") || !dict.contains("mpi_size"))
+                    throw std::runtime_error("Missing required parameters for 'samraih5' initializer.");
+
                 auto const dir     = dict["filepath"].template to<std::string>();
                 int const index    = dict["index"].template to<int>();
                 int const mpi_size = dict["mpi_size"].template to<int>();
src/amr/data/initializers/samrai_hdf5_initializer.hpp (3)

1-2: Typo in include guard macro.

The include guard contains a typo: "INITIAZILIZERS" should be "INITIALIZERS".

Apply this diff:

-#ifndef _PHARE_AMR_DATA_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#define _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_

97-100: Avoid reinterpret_cast for type conversion.

Using reinterpret_cast assumes that the memory layout of the SAMRAI type is compatible with std::array<int, samrai_dim>, which may lead to undefined behavior and portability issues. Use explicit element-wise copying instead.

Apply this diff:

-        auto constexpr _to_std_array     = [](auto& i) {
-            return core::sized_array<GridLayout::dimension>(
-                *reinterpret_cast<std::array<int, samrai_dim> const*>(&i));
-        };
+        auto constexpr _to_std_array = [](auto& i) {
+            std::array<int, samrai_dim> temp{};
+            std::copy_n(reinterpret_cast<int*>(&i), samrai_dim, temp.begin());
+            return core::sized_array<GridLayout::dimension>(temp);
+        };

104-105: Add validation for empty box vector.

The code assumes boxes contains at least one element. If boxes is empty, accessing boxes[0] will result in undefined behavior.

Apply this diff:

 SAMRAI::tbox::HDFDatabase db{"db"};
 db.open(filepath_);
 auto const boxes = db.getDatabaseBoxVector(path);
+if (boxes.empty())
+    throw std::runtime_error("No boxes found at the specified path: " + path);
 return Box_t{_to_std_array(boxes[0].d_data.d_lo), _to_std_array(boxes[0].d_data.d_hi)};
src/amr/data/electromag/electromag_initializer.hpp (2)

71-71: Remove unused member variable dict_.

The dict_ member is initialized in the constructor but never used in the class. Removing it improves code clarity.

Apply this diff:

 ElectromagSamraiH5Initializer(initializer::PHAREDict const& dict)
-    : dict_{dict}
 {
 }

-    initializer::PHAREDict const dict_;

43-48: Remove commented-out code.

The commented-out HDF5 path structure should be removed to keep the codebase clean. If these paths are needed for documentation, consider adding them to a separate documentation file or inline comments without code fragments.

Apply this diff:

-/*
-/PHARE_hierarchy/level_0000/level_0000-patch_0000000-block_0000000/EM_B_y##default/d_box
-/PHARE_hierarchy/level_0000/level_0000-patch_0000000-block_0000000/EM_B_x##default/field_EM_B_x
-/PHARE_hierarchy/level_0000/level_0000-patch_0000000-block_0000000/EM_B_y##default/field_EM_B_y
-/PHARE_hierarchy/level_0000/level_0000-patch_0000000-block_0000000/EM_B_z##default/field_EM_B_z
-*/
src/amr/physical_models/hybrid_model.hpp (2)

32-32: Avoid reserved identifier _Initializers.

Names beginning with an underscore followed by a capital letter are reserved for compiler and standard library implementations in C++. This could lead to undefined behavior or naming conflicts.

Apply this diff to rename:

-    struct _Initializers;
+    struct Initializers;

Also update all references:

  • Line 98: initializers_{std::make_unique<Initializers>(dict, state)}
  • Line 122: std::unique_ptr<Initializers> initializers_;
  • Line 223: struct HybridModel<...>::Initializers

153-153: Remove manual release that causes memory leak.

Calling initializers_.release() transfers ownership without deleting the object, causing a memory leak. Since initializers_ is a std::unique_ptr, it will automatically manage the object's lifetime when it goes out of scope. If the intent is to prevent further use after initialization, consider setting it to nullptr instead, or simply remove the line and let the destructor handle cleanup.

Apply this diff:

     resourcesManager->registerForRestarts(*this);
-    initializers_.release();

Alternatively, if you want to explicitly clear it:

-    initializers_.release();
+    initializers_.reset();
🧹 Nitpick comments (15)
src/core/data/ndarray/ndarray_vector.hpp (1)

5-5: Remove unused include.

The core/logger.hpp include is not used anywhere in this file.

Apply this diff to remove the unused include:

-#include "core/logger.hpp"
src/hdf5/detail/h5/group_scanner.hpp (1)

44-44: Prefer .empty() over .size() == 0.

Use contains.empty() for better readability and intent expression.

Apply this diff:

-                if (contains.size() == 0)
+                if (contains.empty())
tools/test_data_gen.py (1)

40-45: Add error handling for invalid function names.

The main block should handle cases where an invalid function name is provided via command line.

Apply this diff:

 if __name__ == "__main__":
     if len(sys.argv) > 1:
+        fn_name = sys.argv[1]
+        if fn_name not in globals() or not callable(globals()[fn_name]):
+            print(f"Error: Function '{fn_name}' not found")
+            sys.exit(1)
         globals()[sys.argv[1]]()
     else:
         for k in [k for k in list(globals().keys()) if k.startswith("run_")]:
             launch(k)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)

3-3: Remove commented-out import.

The commented-out import should either be removed if not needed or uncommented with documentation if it will be used later.

Apply this diff:

 from .general import add_string, add_int
 
-# import pybindlibs.dictator as pp
-
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1)

48-49: Optional: check dataset existence or handle read errors

Consider verifying the dataset path exists or catching exceptions from read_data_set_flat to surface clearer errors.

src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)

30-31: Default the empty constructor

Small style cleanup.

-    SamraiHDF5ParticleInitializer() {}
+    SamraiHDF5ParticleInitializer() = default;
pyphare/pyphare/pharein/initialize/user_fns.py (1)

50-50: Support both key styles and use size_t for particle count

Be compatible with d["nbr_part_per_cell"] and d["nbrParticlesPerCell"], and prefer add_size_t.

-        add_int(partinit_path + "nbr_part_per_cell", d["nbrParticlesPerCell"])
+        npc = d.get("nbr_part_per_cell", d.get("nbrParticlesPerCell"))
+        if npc is None:
+            raise KeyError("Missing nbr_part_per_cell/nbrParticlesPerCell in population dict")
+        add_size_t(partinit_path + "nbr_part_per_cell", npc)
src/core/data/electromag/electromag.hpp (1)

20-20: Private type alias placement may reduce discoverability.

The type alias This is placed before the public: section, making it effectively private. If this alias is intended for internal use only, the placement is correct. However, if it's meant to facilitate external generic code (as suggested by the PR context introducing generic initializers), consider moving it to the public section for better discoverability.

tests/simulator/test_init_from_restart.py (1)

39-39: Unused parameter can be removed or documented.

The sim parameter is unused in setup_model. If it's intentionally kept for future use or API consistency, consider adding a comment explaining its purpose. Otherwise, remove it.

Based on learnings

src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)

119-120: Document idempotency guard more clearly.

The early return ensures idempotency (called once per population but only needs to execute once). Consider clarifying this with a more explicit comment or assertion to make the intent clearer to future maintainers.

Apply this diff:

-    if (restart_files.size()) // executed per pop, but we only need to run this once
+    // Idempotency guard: this method may be called once per population,
+    // but we only need to scan restart files once for all populations.
+    if (!restart_files.empty())
         return;
pyphare/pyphare/pharein/initialize/general.py (3)

135-135: Remove unnecessary int() cast.

The value len(boxes) is already an integer, so the explicit int() cast is redundant and adds no value.

Apply this diff:

-            add_int(level_path + "nbr_boxes/", int(len(boxes)))
+            add_int(level_path + "nbr_boxes/", len(boxes))

78-78: Use ValueError for invalid input value.

When validating input, ValueError is more semantically appropriate than RuntimeError for indicating that the value is invalid.

Apply this diff:

-        raise RuntimeError("pyphare.__init__::add_size_t received negative value")
+        raise ValueError("pyphare.__init__::add_size_t received negative value")

198-199: Use ValueError for negative population count.

Consistent with best practices, use ValueError instead of RuntimeError when the input value is semantically invalid.

Apply this diff:

-        raise RuntimeError("Number of populations cannot be negative")
+        raise ValueError("Number of populations cannot be negative")
src/amr/data/electromag/electromag_initializer.hpp (2)

32-32: Use = default for empty destructor and add override.

The virtual destructor can be defaulted for clarity and explicitly marked with override to indicate it overrides the base class destructor.

Apply this diff:

-    virtual ~ElectromagUserFuncInitializer() {}
+    ~ElectromagUserFuncInitializer() override = default;

63-63: Use = default for empty destructor and add override.

Similar to the other derived class, the destructor can be defaulted and marked with override.

Apply this diff:

-    virtual ~ElectromagSamraiH5Initializer() {}
+    ~ElectromagSamraiH5Initializer() override = default;
📜 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 6009bd3 and 7d40b01.

📒 Files selected for processing (40)
  • pyphare/pyphare/pharein/__init__.py (3 hunks)
  • pyphare/pyphare/pharein/initialize/__init__.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/general.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/user_fns.py (1 hunks)
  • pyphare/pyphare/pharein/simulation.py (3 hunks)
  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (3 hunks)
  • pyphare/pyphare/pharesee/hierarchy/patchdata.py (1 hunks)
  • res/cmake/test.cmake (1 hunks)
  • src/amr/CMakeLists.txt (1 hunks)
  • src/amr/data/electromag/electromag_initializer.hpp (1 hunks)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1 hunks)
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp (1 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/amr/level_initializer/hybrid_level_initializer.hpp (2 hunks)
  • src/amr/physical_models/hybrid_model.hpp (7 hunks)
  • src/core/CMakeLists.txt (0 hunks)
  • src/core/data/electromag/electromag.hpp (3 hunks)
  • src/core/data/grid/gridlayout.hpp (3 hunks)
  • src/core/data/ions/ions.hpp (1 hunks)
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2 hunks)
  • src/core/data/ions/particle_initializers/particle_initializer.hpp (1 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (4 hunks)
  • src/core/data/vecfield/vecfield_initializer.hpp (1 hunks)
  • src/core/utilities/box/box.hpp (1 hunks)
  • src/core/utilities/types.hpp (1 hunks)
  • src/hdf5/detail/h5/group_scanner.hpp (1 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (4 hunks)
  • src/phare_core.hpp (0 hunks)
  • tests/amr/data/particles/initializer/CMakeLists.txt (1 hunks)
  • tests/amr/data/particles/initializer/test_main.cpp (3 hunks)
  • tests/amr/models/test_models.cpp (3 hunks)
  • tests/amr/tagging/test_tagging.cpp (2 hunks)
  • tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (2 hunks)
  • tests/core/numerics/ion_updater/CMakeLists.txt (1 hunks)
  • tests/core/numerics/ion_updater/test_updater.cpp (7 hunks)
  • tests/simulator/CMakeLists.txt (2 hunks)
  • tests/simulator/test_init_from_restart.py (1 hunks)
  • tools/test_data_gen.py (1 hunks)
💤 Files with no reviewable changes (2)
  • src/phare_core.hpp
  • src/core/CMakeLists.txt
🚧 Files skipped from review as they are similar to previous changes (9)
  • tests/amr/data/particles/initializer/CMakeLists.txt
  • src/core/utilities/box/box.hpp
  • src/core/utilities/types.hpp
  • pyphare/pyphare/pharesee/hierarchy/patchdata.py
  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py
  • tests/simulator/CMakeLists.txt
  • tests/amr/tagging/test_tagging.cpp
  • tests/amr/models/test_models.cpp
  • res/cmake/test.cmake
🧰 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/ions/particle_initializers/maxwellian_particle_initializer.hpp
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
  • src/core/data/vecfield/vecfield_initializer.hpp
  • src/amr/physical_models/hybrid_model.hpp
  • src/core/data/ions/particle_initializers/particle_initializer.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
  • src/amr/level_initializer/hybrid_level_initializer.hpp
  • src/hdf5/detail/h5/h5_file.hpp
  • src/core/data/electromag/electromag.hpp
  • src/amr/data/electromag/electromag_initializer.hpp
  • src/core/data/grid/gridlayout.hpp
  • src/core/data/ions/ions.hpp
  • src/hdf5/detail/h5/group_scanner.hpp
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp
🧠 Learnings (5)
📓 Common learnings
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#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
PR: PHAREHUB/PHARE#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.
📚 Learning: 2025-07-09T17:18:05.771Z
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#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/amr/CMakeLists.txt
📚 Learning: 2024-10-22T10:05:54.014Z
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#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/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#888
File: src/amr/level_initializer/hybrid_level_initializer.hpp:44-49
Timestamp: 2024-10-09T08:32:15.667Z
Learning: In this codebase, when a derived class method overrides a virtual function using `override`, and there are no further subclasses, the `virtual` keyword is not required in the subclass.

Applied to files:

  • src/amr/level_initializer/hybrid_level_initializer.hpp
📚 Learning: 2024-09-17T13:33:47.475Z
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#888
File: src/core/data/grid/gridlayout.hpp:805-821
Timestamp: 2024-09-17T13:33:47.475Z
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 (22)
src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)
  • particles (34-35)
src/core/data/ions/particle_initializers/particle_initializer.hpp (1)
  • particles (13-14)
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (6)
src/core/data/grid/gridlayout.hpp (4)
  • centering (891-895)
  • centering (891-892)
  • centering (902-906)
  • centering (902-903)
src/hdf5/detail/h5/h5_file.hpp (1)
  • data (85-85)
src/core/utilities/types.hpp (6)
  • ConstArray (168-174)
  • ConstArray (168-168)
  • for_N (434-465)
  • for_N (434-434)
  • for_N (468-471)
  • for_N (468-468)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • i (44-48)
src/core/data/ndarray/ndarray_vector.hpp (4)
  • make_array_view (232-235)
  • make_array_view (232-232)
  • make_array_view (238-241)
  • make_array_view (238-238)
src/core/utilities/box/box.hpp (4)
  • grow (88-93)
  • grow (88-88)
  • grow (277-282)
  • grow (277-277)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (4)
src/core/data/ions/particle_initializers/particle_initializer.hpp (1)
  • particles (13-14)
src/core/utilities/types.hpp (2)
  • apply (97-100)
  • apply (97-97)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • i (44-48)
src/core/utilities/box/box.hpp (5)
  • isIn (218-245)
  • isIn (218-218)
  • isIn (248-252)
  • isIn (248-249)
  • isIn (258-258)
src/amr/physical_models/hybrid_model.hpp (1)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
tests/amr/data/particles/initializer/test_main.cpp (1)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
src/core/data/ions/particle_initializers/particle_initializer.hpp (2)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)
  • particles (34-35)
src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (1)
  • particles (65-66)
src/core/data/ndarray/ndarray_vector.hpp (1)
src/core/utilities/types.hpp (2)
  • product (256-259)
  • product (256-256)
pyphare/pyphare/pharein/initialize/user_fns.py (4)
pyphare/pyphare/pharein/initialize/general.py (5)
  • add_double (71-72)
  • add_int (63-64)
  • add_size_t (75-79)
  • fn_wrapper (50-59)
  • populateDict (89-318)
pyphare/pyphare/pharein/__init__.py (1)
  • populateDict (71-80)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)
  • populateDict (6-16)
pyphare/pyphare/core/gridlayout.py (1)
  • ndim (221-222)
src/amr/level_initializer/hybrid_level_initializer.hpp (2)
src/amr/multiphysics_integrator.hpp (10)
  • hierarchy (301-376)
  • hierarchy (301-306)
  • hierarchy (380-409)
  • hierarchy (381-382)
  • hierarchy (413-427)
  • hierarchy (413-416)
  • hierarchy (556-578)
  • hierarchy (557-560)
  • model (688-707)
  • model (688-689)
src/amr/messengers/hybrid_messenger.hpp (2)
  • model (136-140)
  • model (136-137)
tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (3)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)
  • particles (34-35)
src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (1)
  • particles (65-66)
src/core/data/ions/particle_initializers/particle_initializer.hpp (1)
  • particles (13-14)
pyphare/pyphare/pharein/initialize/general.py (4)
pyphare/pyphare/core/phare_utilities.py (1)
  • is_scalar (54-55)
pyphare/pyphare/pharein/load_balancer.py (1)
  • LoadBalancer (9-57)
pyphare/pyphare/pharein/simulation.py (3)
  • serialize (1105-1114)
  • deserialize (1117-1121)
  • is_restartable_compared_to (1060-1068)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_etc_lib (12-15)
src/core/data/electromag/electromag.hpp (2)
src/diagnostic/diagnostic_model_view.hpp (1)
  • dimension (30-60)
tests/core/data/electromag/test_electromag_fixtures.hpp (1)
  • E (19-23)
tests/simulator/test_init_from_restart.py (7)
pyphare/pyphare/pharesee/hierarchy/patchdata.py (2)
  • FieldData (32-194)
  • ParticleData (197-240)
pyphare/pyphare/pharesee/hierarchy/fromh5.py (1)
  • get_all_available_quantities_from_h5 (27-33)
pyphare/pyphare/pharesee/hierarchy/hierarchy.py (1)
  • format_timestamp (13-16)
pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (2)
  • single_patch_for_LO (662-705)
  • hierarchy_compare (618-659)
tests/simulator/__init__.py (2)
  • SimulatorTest (200-266)
  • register_diag_dir_for_cleanup (233-234)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-61)
pyphare/pyphare/simulator/simulator.py (1)
  • reset (254-265)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (3)
pyphare/pyphare/pharein/initialize/general.py (2)
  • add_int (63-64)
  • populateDict (89-318)
pyphare/pyphare/pharein/__init__.py (1)
  • populateDict (71-80)
pyphare/pyphare/pharein/initialize/user_fns.py (1)
  • populateDict (5-7)
src/amr/data/electromag/electromag_initializer.hpp (1)
tests/amr/tagging/test_tagging.cpp (2)
  • em (189-193)
  • em (189-189)
tools/test_data_gen.py (4)
tests/simulator/test_restarts.py (1)
  • test_restarts (230-289)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-61)
pyphare/pyphare/pharein/simulation.py (1)
  • Simulation (764-1099)
tests/simulator/test_init_from_restart.py (1)
  • setup_model (39-46)
tests/core/numerics/ion_updater/test_updater.cpp (1)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
src/core/data/grid/gridlayout.hpp (3)
pyphare/pyphare/core/gridlayout.py (2)
  • physicalStartIndex (262-264)
  • AMRToLocal (343-347)
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/amr/resources_manager/amr_utils.hpp (5)
  • AMRToLocal (47-48)
  • AMRToLocal (55-56)
  • AMRToLocal (64-64)
  • AMRToLocal (79-92)
  • AMRToLocal (79-80)
src/hdf5/detail/h5/group_scanner.hpp (1)
src/hdf5/detail/h5/h5_file.hpp (6)
  • path (274-280)
  • path (274-274)
  • path (282-287)
  • path (282-282)
  • contains (256-259)
  • contains (256-256)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • dir (50-51)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (3)
src/hdf5/detail/h5/h5_file.hpp (4)
  • path (274-280)
  • path (274-274)
  • path (282-287)
  • path (282-282)
src/core/utilities/types.hpp (2)
  • sized_array (133-147)
  • sized_array (133-134)
src/hdf5/detail/h5/group_scanner.hpp (2)
  • group (35-61)
  • group (35-35)
pyphare/pyphare/pharein/__init__.py (4)
pyphare/pyphare/pharein/simulation.py (1)
  • Simulation (764-1099)
pyphare/pyphare/pharein/initialize/general.py (1)
  • populateDict (89-318)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)
  • populateDict (6-16)
pyphare/pyphare/pharein/initialize/user_fns.py (1)
  • populateDict (5-7)
🪛 Ruff (0.13.3)
pyphare/pyphare/pharein/initialize/user_fns.py

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

(TRY003)

pyphare/pyphare/pharein/initialize/general.py

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

(TRY003)


135-135: Value being cast to int is already an integer

Remove unnecessary int call

(RUF046)


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

(TRY003)


273-275: Avoid specifying long messages outside the exception class

(TRY003)


281-283: Avoid specifying long messages outside the exception class

(TRY003)


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

(TRY003)

tests/simulator/test_init_from_restart.py

39-39: Unused function argument: sim

(ARG001)

pyphare/pyphare/pharein/initialize/samrai_hdf5.py

9-9: Loop control variable pop not used within loop body

Rename unused pop to _pop

(B007)

tools/test_data_gen.py

35-35: Local variable p is assigned to but never used

Remove assignment to unused variable p

(F841)


35-35: subprocess call: check for execution of untrusted input

(S603)

pyphare/pyphare/pharein/simulation.py

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

(TRY003)

pyphare/pyphare/pharein/initialize/__init__.py

5-9: __all__ is not sorted

Apply an isort-style sorting to __all__

(RUF022)

⏰ 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 (macos-13)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: Analyze (cpp)
🔇 Additional comments (26)
src/hdf5/detail/h5/h5_file.hpp (1)

13-15: LGTM!

The new includes are necessary for the scan_for_groups functionality and are properly placed.

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

1-18: LGTM!

Header guards, includes, and namespace declaration are well-structured and appropriate.


19-26: LGTM!

The constructor is well-designed with appropriate parameter types and initialization.

pyphare/pyphare/pharein/initialize/__init__.py (1)

1-9: LGTM!

The module structure is clean and properly exposes the initialization submodules.

tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (2)

54-54: LGTM!

The test correctly passes the population name parameter to match the updated loadParticles signature.


63-63: LGTM!

The test correctly passes the population name parameter to match the updated loadParticles signature.

src/core/data/vecfield/vecfield_initializer.hpp (1)

30-30: LGTM!

Adding the const qualifier to the initialize method improves const-correctness without changing functionality.

src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2)

65-66: LGTM!

The signature update to include popname maintains API consistency across particle initializers. The parameter is currently unused but reserved for future implementation.


140-140: LGTM!

The popname parameter is correctly marked as unused in the implementation while maintaining the updated API signature.

src/core/data/ions/particle_initializers/particle_initializer.hpp (1)

13-15: LGTM!

The interface update to include the popname parameter is correct and aligns with the broader API refactor for population-specific initialization.

src/amr/level_initializer/hybrid_level_initializer.hpp (2)

44-49: LGTM!

The removal of the virtual keyword is correct. The override specifier is sufficient here since this is a final implementation with no further subclasses. Based on learnings.


178-179: LGTM!

The added blank lines improve code readability without affecting functionality.

pyphare/pyphare/pharein/simulation.py (2)

678-679: Keyword added: init_options

Good addition to accepted_keywords.


713-714: Init options validated early

Calling check_init_options here is correct.

tests/amr/data/particles/initializer/test_main.cpp (1)

32-32: Key/name updates and amr factory usage look good

  • "maxwellian", "nbr_part_per_cell", "cartesian" keys align with new conventions.
  • Using PHARE::amr::ParticleInitializerFactory is correct.

Also applies to: 43-49

pyphare/pyphare/pharein/__init__.py (1)

71-80: LGTM! Clean delegation to modular initialization.

The refactoring of populateDict() to delegate to initialize.general, initialize.user_fns, or initialize.samrai_hdf5 based on sim.init_options improves code organization and separation of concerns. This aligns well with the PR's goal of supporting arbitrary MPI restart configurations.

pyphare/pyphare/pharein/initialize/general.py (1)

89-318: LGTM on the overall structure.

The populateDict function is comprehensive and handles the complex simulation configuration well. While the function is lengthy, it logically organizes the configuration steps (grid, AMR, load balancer, populations, diagnostics, restarts, electrons), making it reasonably maintainable for this domain. Based on learnings, the preference is for minimal and efficient code, which this achieves.

src/amr/data/electromag/electromag_initializer.hpp (1)

14-20: LGTM on the base class design.

The ElectromagInitializer base class provides a clean interface with a virtual init method and proper virtual destructor. The default no-op implementation is appropriate for the factory pattern.

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

804-820: LGTM on the parameterized AMRToLocal implementation.

The two-argument AMRToLocal method correctly validates that local indices are non-negative before converting to uint32_t, as indicated by the learning. The assertion at line 816 ensures safe conversion.

Based on learnings


822-846: LGTM on the convenience overloads.

The one-argument overloads properly delegate to the two-argument versions, using AMRBox_ as the default local box. This provides a clean API for common use cases while maintaining the flexibility of the parameterized version.


1212-1226: LGTM on the new domain and ghost box helpers.

The domainBoxFor and ghostBoxFor methods provide a clean abstraction for retrieving field-specific boxes. The implementation correctly delegates to _BoxFor with appropriate start-to-end functions.


1264-1276: LGTM on the dimension-agnostic _BoxFor implementation.

The refactored _BoxFor method uses a compile-time loop with a direction array, making it more maintainable and dimension-agnostic. The implementation correctly iterates only up to dimension, avoiding out-of-bounds access.

tests/core/numerics/ion_updater/test_updater.cpp (3)

6-7: LGTM on the new includes.

The includes for electromag_initializer.hpp and particle_initializer_factory.hpp properly support the factory-based initialization pattern introduced in this PR.


418-419: LGTM on factory-based electromag initialization.

The code correctly uses ElectromagInitializerFactory_t::create to instantiate the appropriate initializer and calls init to initialize the electromagnetic fields. This aligns with the new factory pattern.


424-424: LGTM on updated loadParticles signature.

The addition of pop.name() as a parameter to loadParticles provides necessary context for population-specific initialization, consistent with the updated API.

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

221-248: LGTM on the _Initializers struct design (naming aside).

The _Initializers struct effectively encapsulates initialization logic for electromagnetics and particles, promoting modularity and separation of concerns. The use of factory methods and a map for population-specific initializers is a clean design choice. Once the reserved identifier naming issue is addressed, this implementation will be solid.

Comment on lines +543 to +551
if init_options is not None and "format" in init_options:
if init_options["format"] not in formats:
raise ValueError("Error - init_options format is invalid")
if "options" in init_options and "dir" in init_options["options"]:
init_options["options"]["dir"] = check_directory(
init_options["options"]["dir"], "init_options"
)

return init_options
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Init options: require format, validate top-level dir, and don’t create input dirs

  • Enforce presence/validity of "format".
  • Support top-level init_options["dir"] (used by initialize.samrai_hdf5).
  • Validate existing directory (read/execute), don’t create it.
-    if init_options is not None and "format" in init_options:
-        if init_options["format"] not in formats:
-            raise ValueError("Error - init_options format is invalid")
-        if "options" in init_options and "dir" in init_options["options"]:
-            init_options["options"]["dir"] = check_directory(
-                init_options["options"]["dir"], "init_options"
-            )
+    if init_options is not None:
+        if "format" not in init_options or init_options["format"] not in formats:
+            raise ValueError("Error - init_options format is invalid (expected one of: "
+                             + str(formats) + ")")
+        # Accept and validate the commonly used top-level dir for input
+        if "dir" in init_options:
+            init_options["dir"] = check_existing_directory(init_options["dir"], "init_options")
+        # If nested options.dir is provided, validate it too (do not create)
+        if "options" in init_options and "dir" in init_options["options"]:
+            init_options["options"]["dir"] = check_existing_directory(
+                init_options["options"]["dir"], "init_options"
+            )

Add this helper near check_directory():

def check_existing_directory(directory, key):
    directory = directory.rstrip(os.path.sep)
    if not os.path.exists(directory) or not os.path.isdir(directory):
        raise ValueError(f"Error: Simulation {key} dir does not exist or is not a directory.")
    if not os.access(directory, os.R_OK | os.X_OK):
        raise ValueError(f"Directory ({directory}) for {key} lacks read/execute permissions")
    return directory

To confirm usage patterns:

Based on learnings


🏁 Script executed:

#!/bin/bash
# Find code that expects top-level vs nested init_options dir
rg -n -C2 --type py 'init_options\["dir"\]|init_options\["options"\]\["dir"\]'

Length of output: 1089


Enforce required format and validate both top‐level and nested dirs

  • Always require "format" in init_options and error if not in formats (include supported values).
  • Support and validate a top‐level "dir" key (used by initialize.samrai_hdf5) and nested init_options["options"]["dir"] via a new check_existing_directory helper that ensures the directory exists, is a directory, and has read/execute permissions (do not create directories).
🧰 Tools
🪛 Ruff (0.13.3)

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

(TRY003)

🤖 Prompt for AI Agents
In pyphare/pyphare/pharein/simulation.py around lines 543-551, the code
currently only optionally checks "format" and only validates a nested
options["dir"]; update it to require init_options to contain "format" and raise
a ValueError listing the supported formats if missing or not in formats, and add
support for validating a top-level "dir" key as well as
init_options["options"]["dir"] by calling a new check_existing_directory helper
(which must verify the path exists, is a directory, and has read+execute
permissions without creating anything); replace the current check_directory
usage with check_existing_directory for the nested dir, and ensure error
messages clearly identify which key ("format", top-level "dir", or options.dir)
failed validation.

Comment on lines +5 to +10
#include "core/data/grid/gridlayoutdefs.hpp"
#include "core/data/ndarray/ndarray_vector.hpp"

#include "core/utilities/types.hpp"
#include "core/utilities/point/point.hpp"

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Make header self‑contained (include Box/grow)

Add box.hpp to define core::Box and grow used below.

 #include "core/data/grid/gridlayoutdefs.hpp"
 #include "core/data/ndarray/ndarray_vector.hpp"
 
 #include "core/utilities/types.hpp"
 #include "core/utilities/point/point.hpp"
+#include "core/utilities/box/box.hpp"

As per coding guidelines

📝 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 "core/data/grid/gridlayoutdefs.hpp"
#include "core/data/ndarray/ndarray_vector.hpp"
#include "core/utilities/types.hpp"
#include "core/utilities/point/point.hpp"
#include "core/data/grid/gridlayoutdefs.hpp"
#include "core/data/ndarray/ndarray_vector.hpp"
#include "core/utilities/types.hpp"
#include "core/utilities/point/point.hpp"
#include "core/utilities/box/box.hpp"
🤖 Prompt for AI Agents
In src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp around
lines 5 to 10, the header uses core::Box and the grow utility but does not
include the Box definition; add the appropriate include (e.g. #include
"core/utilities/box.hpp") to make the header self-contained and ensure any use
of grow/Box is resolved so the header compiles on its own.

#include "core/data/vecfield/vecfield_component.hpp"
#include "initializer/data_provider.hpp"
#include "particle_initializers/particle_initializer_factory.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

Verify that removing this include doesn't break downstream compilation.

The removal of the particle_initializer_factory.hpp include appears correct, as no symbols from it are directly used in this file. However, verify that files including ions.hpp don't rely on this transitive include.

Run the following script to check for potential transitive dependencies:


🏁 Script executed:

#!/bin/bash
# Description: Check if any files include ions.hpp and use particle_initializer_factory symbols

# Find files that include ions.hpp
echo "=== Files including ions.hpp ==="
rg -l '#include.*ions\.hpp'

echo -e "\n=== Checking if particle_initializer_factory.hpp still exists ==="
fd -t f particle_initializer_factory.hpp

echo -e "\n=== Files that include both ions.hpp and reference particle_initializer ==="
rg -l '#include.*ions\.hpp' | xargs -I {} sh -c 'if rg -q "particle_initializer" {}; then echo {}; fi'

Length of output: 1164


Restore the include for particle_initializer_factory.hpp or add it directly in all dependent files.

Removing this header from ions.hpp breaks compilation in consumers that reference particle_initializer symbols transitively. Either re-include particle_initializer_factory.hpp in src/core/data/ions/ions.hpp or ensure each file using those symbols includes it explicitly.

🤖 Prompt for AI Agents
In src/core/data/ions/ions.hpp around line 18, the header remove caused
particle_initializer symbols to be unavailable transitively; restore the include
for particle_initializer_factory.hpp at the top of ions.hpp (or alternatively
add that include to every translation unit that directly uses
particle_initializer types) so consumers compile. Re-add #include
"src/core/data/particles/particle_initializer_factory.hpp" to ions.hpp (or
ensure each dependent file explicitly includes that header) and run a rebuild to
verify no missing-symbol compile errors remain.

Comment on lines +74 to +79
template<typename NCells, typename... Indexes>
NO_DISCARD static DataType const& at(DataType const* data, NCells const& nCells,
Indexes const&... indexes)
{
return data[idx(nCells, indexes...)];
}
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 bounds checking for robust error handling.

This new at overload directly indexes into the data array without any bounds validation, relying entirely on the idx function. If idx does not validate bounds (as currently implemented), out-of-bounds access can occur silently in release builds.

The bounds checking should be added to the idx function as suggested in the previous comment. Once that is in place, this overload will be safe.

@PhilipDeegan PhilipDeegan force-pushed the restartinator branch 2 times, most recently from 15cb5bb to d2be573 Compare October 7, 2025 18:41
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 (6)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (2)

107-107: Improve exception message with initializer name.

Including the unrecognized initializer name in the error message would aid debugging. This suggestion from a previous review remains unaddressed.

Apply this diff:

-throw std::runtime_error("No Particle Initializer chosen!");
+throw std::runtime_error("Unknown Particle Initializer: '" + initializerName + "'");

94-106: Add validation and error handling for samraih5 initialization.

The code directly accesses dictionary keys (Lines 96-98) without verifying they exist, and calls populate_from (Line 101) without error handling. These issues were previously flagged and remain unaddressed.

Consider applying these improvements:

 if (initializerName == "samraih5")
 {
+    if (!dict.contains("filepath") || !dict.contains("index") || !dict.contains("mpi_size")) {
+        throw std::runtime_error("Missing required parameters for 'samraih5' initializer.");
+    }
     auto const dir     = dict["filepath"].template to<std::string>();
     int const index    = dict["index"].template to<int>();
     int const mpi_size = dict["mpi_size"].template to<int>();

     // scan restart files for later use
-    SamraiH5Interface<GridLayout>::INSTANCE().populate_from(dir, index, mpi_size);
+    try
+    {
+        SamraiH5Interface<GridLayout>::INSTANCE().populate_from(dir, index, mpi_size);
+    }
+    catch (const std::exception& e)
+    {
+        throw std::runtime_error(std::string("Failed to populate from SAMRAI H5: ") + e.what());
+    }

     return std::make_unique<SamraiHDF5ParticleInitializer<ParticleArray, GridLayout>>();
 }
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (4)

30-31: Default the empty constructor.

The default constructor is empty and can be defaulted for clarity.


1-2: Correct the typo in the include guard macro.

The include guard uses INITIAZILIZERS but should be INITIALIZERS.


5-10: Include box.hpp to make the header self-contained.

The code uses core::Box and grow without including their definition. Add #include "core/utilities/box/box.hpp" to ensure the header compiles independently.


43-46: Validate pointers before dereferencing.

The loop dereferences h5FilePtr and pdataptr without null checks, which could cause undefined behavior.

🧹 Nitpick comments (2)
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (2)

11-13: Provide a meaningful error message for the HIGHFIVE check.

The #error directive lacks a descriptive message. This makes it harder for developers to understand why compilation failed.

Apply this diff:

-#if !PHARE_HAS_HIGHFIVE
-#error // HIGHFIVE REQUIRED!
-#endif // PHARE_HAS_HIGHFIVE
+#if !PHARE_HAS_HIGHFIVE
+#error "HIGHFIVE library is required for SamraiHDF5FieldInitializer"
+#endif

50-57: Consider improving readability of the box calculation.

The nested lambda and template metaprogramming constructs computing lcl_src_gbox are dense. Adding intermediate variables or brief comments explaining the calculation (e.g., "compute shape as source range + 2×ghosts + primal offset") would aid maintainability.

📜 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 7d40b01 and 15cb5bb.

📒 Files selected for processing (6)
  • src/amr/CMakeLists.txt (1 hunks)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/phare_core.hpp (0 hunks)
  • tests/core/numerics/ion_updater/test_updater.cpp (7 hunks)
💤 Files with no reviewable changes (1)
  • src/phare_core.hpp
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
  • src/amr/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/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp
🧠 Learnings (2)
📓 Common learnings
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#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
PR: PHAREHUB/PHARE#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.
📚 Learning: 2024-10-22T10:05:54.014Z
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#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/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
🧬 Code graph analysis (3)
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (5)
src/core/data/grid/gridlayout.hpp (4)
  • centering (891-895)
  • centering (891-892)
  • centering (902-906)
  • centering (902-903)
src/core/utilities/types.hpp (6)
  • ConstArray (168-174)
  • ConstArray (168-168)
  • for_N (434-465)
  • for_N (434-434)
  • for_N (468-471)
  • for_N (468-468)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • i (44-48)
src/core/data/ndarray/ndarray_vector.hpp (4)
  • make_array_view (232-235)
  • make_array_view (232-232)
  • make_array_view (238-241)
  • make_array_view (238-238)
src/core/utilities/box/box.hpp (4)
  • grow (88-93)
  • grow (88-88)
  • grow (277-282)
  • grow (277-277)
tests/core/numerics/ion_updater/test_updater.cpp (1)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • dir (50-51)
⏰ 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-14)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-13)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: Analyze (cpp)
  • GitHub Check: Analyze (python)
🔇 Additional comments (7)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (3)

9-11: Include paths are correct for cross-namespace usage.

The past review comment suggesting these includes are inconsistent is incorrect. The factory is in the amr namespace but correctly uses types from the core namespace (ParticleInitializer, MaxwellianParticleInitializer). Including from core/data/ions/particle_initializers/ is appropriate.


27-27: Type alias correctly references core namespace.

The past review comment suggesting to change this to amr::ParticleInitializer is incorrect. The ParticleInitializer type is defined in the core namespace, and the factory in amr correctly uses it via the core:: qualifier.


76-77: Namespace usage is correct for core types.

The past review comments suggesting to change core::MaxwellianParticleInitializer to amr::MaxwellianParticleInitializer are incorrect. These types are defined in the core namespace, and the factory correctly instantiates them with the core:: qualifier.

Also applies to: 87-88

tests/core/numerics/ion_updater/test_updater.cpp (3)

6-7: LGTM! Includes support factory-based initialization.

The added includes for electromag_initializer and particle_initializer_factory are necessary for the factory-based initialization pattern implemented later in the test.


370-378: LGTM! Type aliases correctly structured for factory pattern.

The updated type aliases properly support the factory-based initialization pattern. The explicit GridLayout definition and new factory aliases (ParticleInitializerFactory, ElectromagInitializerFactory_t) are appropriate.


418-424: LGTM! Factory-based initialization implemented correctly.

The electromagnetic and particle initialization now uses the factory pattern appropriately:

  • ElectromagInitializerFactory_t::create() returns a unique_ptr that's immediately used to initialize fields
  • loadParticles signature updated to include pop.name() as required by the new API
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1)

62-66: Assertion for matching sizes is unnecessary: AMRToLocal is a pure translation that preserves box extents, so lcl_src_box and lcl_dst_box always have identical iteration counts.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

82-89: Bug: magnetic_basis uses x-component for all axes

All three components are read from "magnetic_x". Use y/z keys for the other axes.

Apply:

-                    magneticField[0] = dict["magnetic_x"].template to<FunctionType>();
-                    magneticField[1] = dict["magnetic_x"].template to<FunctionType>();
-                    magneticField[2] = dict["magnetic_x"].template to<FunctionType>();
+                    magneticField[0] = dict["magnetic_x"].template to<FunctionType>();
+                    magneticField[1] = dict["magnetic_y"].template to<FunctionType>();
+                    magneticField[2] = dict["magnetic_z"].template to<FunctionType>();
♻️ Duplicate comments (4)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (3)

58-63: Add error handling around HDF5 dataset reads

Reading without checks risks exceptions on missing/corrupt datasets. Wrap reads and surface context.

Apply:

-            core::apply(soa.as_tuple(), [&](auto& arg) {
-                auto const datapath = poppath + Packer::keys()[part_idx++];
-                h5File.file().getDataSet(datapath).read(arg);
-            });
+            try
+            {
+                core::apply(soa.as_tuple(), [&](auto& arg) {
+                    auto const datapath = poppath + Packer::keys()[part_idx++];
+                    h5File.file().getDataSet(datapath).read(arg);
+                });
+            }
+            catch (std::exception const& e)
+            {
+                throw std::runtime_error(std::string{"HDF5 read failed for population '"}
+                                         + popname + "' at index " + std::to_string(part_idx - 1)
+                                         + ": " + e.what());
+            }

1-2: Fix include guard typo (INITIALIZERS)

Current macro spells INITIAZILIZERS, breaking the guard.

Apply:

-#ifndef _PHARE_AMR_DATA_PARTICLE_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_PARTICLE_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#define _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_

5-11: Header not self-contained: missing SamraiH5Interface include

This file uses SamraiH5Interface but doesn’t include it. Include the defining header.

Apply:

 #include "core/data/ions/particle_initializers/particle_initializer.hpp"
 
 #include "core/data/particles/particle_packer.hpp"
+// for SamraiH5Interface
+#include "amr/data/initializers/samrai_hdf5_initializer.hpp"
src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

93-105: HDF5 initializer: validate dict inputs and guard populate_from

Check required keys and wrap the external call to provide a clearer error path.

Apply:

 #if PHARE_HAS_HIGHFIVE
             if (initializerName == "samraih5")
             {
-                auto const dir     = dict["filepath"].template to<std::string>();
-                int const index    = dict["index"].template to<int>();
-                int const mpi_size = dict["mpi_size"].template to<int>();
+                if (!dict.contains("filepath") || !dict.contains("index") || !dict.contains("mpi_size"))
+                    throw std::runtime_error("Missing required parameters for 'samraih5' initializer "
+                                             "(need: filepath, index, mpi_size).");
+                auto const dir     = dict["filepath"].template to<std::string>();
+                int const index    = dict["index"].template to<int>();
+                int const mpi_size = dict["mpi_size"].template to<int>();
 
                 // scan restart files for later use
-                SamraiH5Interface<GridLayout>::INSTANCE().populate_from(dir, index, mpi_size);
+                try
+                {
+                    SamraiH5Interface<GridLayout>::INSTANCE().populate_from(dir, index, mpi_size);
+                }
+                catch (std::exception const& e)
+                {
+                    throw std::runtime_error(std::string{"Failed to populate from SAMRAI H5: "} + e.what());
+                }
 
                 return std::make_unique<SamraiHDF5ParticleInitializer<ParticleArray, GridLayout>>();
             }
 #endif // PHARE_HAS_HIGHFIVE
🧹 Nitpick comments (4)
src/simulator/phare_types.hpp (1)

28-30: Make header self-contained: include the amr factory header

The alias depends on amr::ParticleInitializerFactory; add its header to avoid relying on transitive includes. As per coding guidelines.

Apply:

 #include "phare_solver.hpp"
+// for amr::ParticleInitializerFactory
+#include "amr/data/particles/initializers/particle_initializer_factory.hpp"
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (2)

30-31: Default the trivial ctor

Prefer = default for clarity.

Apply:

-    SamraiHDF5ParticleInitializer() {}
+    SamraiHDF5ParticleInitializer() = default;

Based on learnings.


65-67: Optional: pre-reserve to reduce reallocations

Reserve for a rough upper bound to avoid repeated growth.

Apply:

-        for (std::size_t i = 0; i < soa.size(); ++i)
+        particles.reserve(particles.size() + soa.size());
+        for (std::size_t i = 0; i < soa.size(); ++i)
             if (auto const p = soa.copy(i); core::isIn(core::Point{p.iCell}, dest_box))
                 particles.push_back(p);

Based on learnings.

src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

107-107: Improve exception message

Include the unrecognized initializer name.

Apply:

-            throw std::runtime_error("No Particle Initializer chosen!");
+            throw std::runtime_error("Unknown Particle Initializer: '" + initializerName + "'");
📜 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 15cb5bb and d2be573.

📒 Files selected for processing (7)
  • src/amr/CMakeLists.txt (1 hunks)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/phare_core.hpp (0 hunks)
  • src/simulator/phare_types.hpp (1 hunks)
  • tests/core/numerics/ion_updater/test_updater.cpp (7 hunks)
💤 Files with no reviewable changes (1)
  • src/phare_core.hpp
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
  • src/amr/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/amr/data/particles/initializers/particle_initializer_factory.hpp
  • src/simulator/phare_types.hpp
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
🧠 Learnings (1)
📓 Common learnings
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#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
PR: PHAREHUB/PHARE#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.
🧬 Code graph analysis (3)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • dir (50-51)
tests/core/numerics/ion_updater/test_updater.cpp (1)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (3)
src/core/utilities/types.hpp (2)
  • apply (97-100)
  • apply (97-97)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • i (44-48)
src/core/utilities/box/box.hpp (5)
  • isIn (218-245)
  • isIn (218-218)
  • isIn (248-252)
  • isIn (248-249)
  • isIn (258-258)
⏰ 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 (macos-14)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-13)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (ubuntu-latest, gcc)
  • GitHub Check: Analyze (cpp)
🔇 Additional comments (4)
tests/core/numerics/ion_updater/test_updater.cpp (4)

6-8: Includes: LGTM

Brings in the new electromag and particle initializer factories appropriately.


170-178: Alias cleanup: LGTM

Switching to PHARETypes aliases (Grid, GridLayout, Electromag, Ions, ParticleArray) improves readability and consistency.

Also applies to: 210-216


370-379: Factory-based initialization and API updates: LGTM

  • New ParticleInitializerFactory alias and usage.
  • Electromag initializer factory usage.
  • loadParticles updated to pass pop.name().

All consistent with the refactor.

Also applies to: 392-394, 418-425


536-536: Interpolator alias change: LGTM

Using IonUpdater::Interpolator reduces template verbosity.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/core/data/grid/gridlayout.hpp (1)

1160-1166: Remove duplicate ghostBoxFor definition.

The method ghostBoxFor(Field const& field) is defined twice: once at lines 1160-1166 and again at lines 1220-1226. This will cause a compilation error due to duplicate definitions.

Apply this diff to remove the duplicate:

-    template<typename Field>
-    auto ghostBoxFor(Field const& field) const
-    {
-        return _BoxFor(field, [&](auto const& centering, auto const direction) {
-            return this->ghostStartToEnd(centering, direction);
-        });
-    }
-
-
-

The first definition at lines 1160-1166 should be kept, and the duplicate at lines 1220-1226 should be removed.

Also applies to: 1220-1226

tests/core/numerics/ion_updater/test_updater.cpp (1)

783-787: Fix alpha ghost expectations: compare to the correct buffers

These two assertions compare old/new ghosts to alphaLevelGhost instead of alphaLevelGhostOld/alphaLevelGhostNew. This weakens the test.

-    checkIsUnTouched(populations[1].levelGhostParticlesOld(), ionsBufferCpy.alphaLevelGhost);
-    checkIsUnTouched(populations[1].levelGhostParticlesNew(), ionsBufferCpy.alphaLevelGhost);
+    checkIsUnTouched(populations[1].levelGhostParticlesOld(), ionsBufferCpy.alphaLevelGhostOld);
+    checkIsUnTouched(populations[1].levelGhostParticlesNew(), ionsBufferCpy.alphaLevelGhostNew);
♻️ Duplicate comments (14)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (2)

1-2: Fix typo in include guard.

The include guard macro contains a spelling error: INITIAZILIZERS should be INITIALIZERS.

-#ifndef _PHARE_AMR_DATA_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#define _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_

94-106: Add bounds checking before accessing boxes vector.

Line 105 accesses boxes[0] without verifying the vector is non-empty. If the HDF5 path is invalid or contains no boxes, this will cause undefined behavior.

 SAMRAI::tbox::HDFDatabase db{"db"};
 db.open(filepath_);
 auto const boxes = db.getDatabaseBoxVector(path);
+if (boxes.empty())
+{
+    throw std::runtime_error("No boxes found at HDF5 path: " + path);
+}
 return Box_t{_to_std_array(boxes[0].d_data.d_lo), _to_std_array(boxes[0].d_data.d_hi)};
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1)

1-2: Fix typo in include guard.

The include guard macro contains a spelling error: INITIAZILIZERS should be INITIALIZERS.

-#ifndef _PHARE_AMR_DATA_FIELD_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_FIELD_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef _PHARE_AMR_DATA_FIELD_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#define _PHARE_AMR_DATA_FIELD_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)

9-9: Rename unused loop variable to indicate it's intentionally unused.

The loop variable pop is not used within the loop body. Rename it to _pop to indicate it's intentionally unused.

Apply this diff:

-for pop_index, pop in enumerate(init_model.populations):
+for pop_index, _pop in enumerate(init_model.populations):
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)

1-2: Fix typo in include guard macro name.

The include guard contains a typo: "INITIAZILIZERS" should be "INITIALIZERS". This could cause issues with include guards if the correct spelling is used elsewhere.

Apply this diff:

-#ifndef _PHARE_AMR_DATA_PARTICLE_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_PARTICLE_INITIAZILIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#define _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
src/hdf5/detail/h5/h5_file.hpp (1)

256-259: Make scan_for_groups const for const-correctness.

The scan_for_groups method doesn't modify any member variables and should be marked const to enable calling it on const instances.

Apply this diff:

-    std::unordered_set<std::string> scan_for_groups(std::vector<std::string> const& contains)
+    std::unordered_set<std::string> scan_for_groups(std::vector<std::string> const& contains) const
pyphare/pyphare/pharein/simulation.py (1)

537-551: Validate top-level init_options["dir"] key used by samrai_hdf5.

The samrai_hdf5.py module (line 14) accesses sim.init_options["dir"] directly, but check_init_options only validates the nested path at init_options["options"]["dir"]. Add validation for the top-level "dir" key to prevent runtime KeyError.

Apply this diff:

 def check_init_options(**kwargs):
     """Advanced options to initialize from SAMRAI HDF5 files"""
 
     formats = ["samraih5"]
     init_options = kwargs.get("init_options", None)
 
     if init_options is not None and "format" in init_options:
         if init_options["format"] not in formats:
             raise ValueError("Error - init_options format is invalid")
+        # Validate top-level dir used by samrai_hdf5.py
+        if "dir" in init_options:
+            init_options["dir"] = check_directory(init_options["dir"], "init_options")
         if "options" in init_options and "dir" in init_options["options"]:
             init_options["options"]["dir"] = check_directory(
                 init_options["options"]["dir"], "init_options"
             )
 
     return init_options
src/core/data/electromag/electromag.hpp (1)

24-24: Correct the specifier order.

The declaration auto static constexpr dimension = VecFieldT::dimension; uses an unconventional specifier order. The standard C++ convention places storage-class and cv-qualifiers before the type specifier.

Apply this diff:

-        auto static constexpr dimension = VecFieldT::dimension;
+        static constexpr auto dimension = VecFieldT::dimension;
tests/amr/tagging/test_tagging.cpp (1)

189-193: Add validation for required dictionary key.

The init method accesses dict_["electromag"] without verifying the key exists. If missing, this will cause undefined behavior or a runtime exception.

Add a check before accessing the key:

         void init(Electromag& em, GridLayoutT const& layout)
         {
+            if (!dict_.contains("electromag"))
+                throw std::runtime_error("Key 'electromag' not found in dictionary");
+
             ElectromagUserFuncInitializer<Electromag, GridLayoutT>{dict_["electromag"]}.init(
                 em, layout);
         }
src/amr/data/electromag/electromag_initializer.hpp (2)

32-32: Simplify destructor declaration.

The virtual keyword is redundant in derived class destructors when the base class destructor is already virtual. Use override and = default for clarity.

Apply this diff:

-    virtual ~ElectromagUserFuncInitializer() {}
+    ~ElectromagUserFuncInitializer() override = default;

63-63: Simplify destructor declaration.

The virtual keyword is redundant here. Use override and = default.

Apply this diff:

-    virtual ~ElectromagSamraiH5Initializer() {}
+    ~ElectromagSamraiH5Initializer() override = default;
src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

94-106: Add validation for required dictionary keys.

The samraih5 initializer assumes dict contains filepath, index, and mpi_size. Missing keys will cause runtime errors when accessing them.

Add checks before accessing these keys:

 #if PHARE_HAS_HIGHFIVE
             if (initializerName == "samraih5")
             {
+                if (!dict.contains("filepath") || !dict.contains("index") || !dict.contains("mpi_size"))
+                {
+                    throw std::runtime_error("Missing required parameters ('filepath', 'index', 'mpi_size') for 'samraih5' initializer");
+                }
+
                 auto const dir     = dict["filepath"].template to<std::string>();
                 int const index    = dict["index"].template to<int>();
                 int const mpi_size = dict["mpi_size"].template to<int>();
src/amr/physical_models/hybrid_model.hpp (2)

32-33: Rename reserved identifier _Initializers to a non-reserved name

Leading underscore + capital is reserved in C++. Rename to Initializers and update uses.

-    struct _Initializers;
+    struct Initializers;
...
-        , initializers_{std::make_unique<_Initializers>(dict, state)}
+        , initializers_{std::make_unique<Initializers>(dict, state)}
...
-    std::unique_ptr<_Initializers> initializers_;
+    std::unique_ptr<Initializers> initializers_;
...
-struct HybridModel<GridLayoutT, Electromag, Ions, Electrons, AMR_Types, Grid_t>::_Initializers
+struct HybridModel<GridLayoutT, Electromag, Ions, Electrons, AMR_Types, Grid_t>::Initializers
 {
-    _Initializers(initializer::PHAREDict const& dict, HybridState_t const& state)
+    Initializers(initializer::PHAREDict const& dict, HybridState_t const& state)

Also applies to: 221-224, 231-239


152-154: Fix leak and prevent UB: replace release() with reset(), and avoid returning a dangling reference

  • initializers_.release(); leaks. Use reset() for early destruction.
  • After reset, auto& initializers() can be called and deref null → UB. Return a pointer (or remove/privatize the accessor).
-    initializers_.release();
+    initializers_.reset();

Option A (safer API):

-    auto& initializers() { return *initializers_; }
+    NO_DISCARD Initializers* initializers() noexcept { return initializers_.get(); }

Option B (preferable): move the accessor to private or remove it if only used internally.

Also applies to: 124-125

🧹 Nitpick comments (16)
tools/test_data_gen.py (2)

1-10: Remove unused imports.

The unittest (line 3) and numpy (line 5) imports are not used in this module.

 import sys
 import copy
-import unittest
 import subprocess
-import numpy as np
 import pyphare.pharein as ph

30-37: Remove unused variable assignment.

The variable p assigned at line 35 is never used.

     try:
-        p = subprocess.run(cmd.split(" "), check=True, capture_output=True)
+        subprocess.run(cmd.split(" "), check=True, capture_output=True)
     except subprocess.CalledProcessError as e:
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1)

30-30: Consider defaulting the empty constructor.

The default constructor has an empty body and could be explicitly defaulted for clarity.

-    SamraiHDF5FieldInitializer() {}
+    SamraiHDF5FieldInitializer() = default;
tests/simulator/test_init_from_restart.py (2)

1-16: Remove unused imports.

Several imports are not used in this test module: sys, subprocess, numpy, FieldData, ParticleData, and test_restarts.

-import sys
 import copy
 import unittest
-import subprocess
-import numpy as np
 import pyphare.pharein as ph
 from pathlib import Path
 
 from pyphare.simulator.simulator import Simulator
-from pyphare.pharesee.hierarchy.patchdata import FieldData, ParticleData
 from pyphare.pharesee.hierarchy.fromh5 import get_all_available_quantities_from_h5
 from pyphare.pharesee.hierarchy.hierarchy import format_timestamp
 from pyphare.pharesee.hierarchy.hierarchy_utils import single_patch_for_LO
 from pyphare.pharesee.hierarchy.hierarchy_utils import hierarchy_compare
-from tests.simulator import SimulatorTest, test_restarts
+from tests.simulator import SimulatorTest
 from tests.diagnostic import dump_all_diags

39-46: Remove unused function parameter.

The sim parameter in setup_model is not used in the function body.

-def setup_model(sim):
+def setup_model():
     model = ph.MaxwellianFluidModel(

Also update the call site at line 64:

-        setup_model(sim)
+        setup_model()
pyphare/pyphare/pharein/initialize/__init__.py (1)

1-9: LGTM: Clean modularization of initialization logic.

The new initialize package cleanly exposes three submodules (general, user_fns, samrai_hdf5) for modular initialization, aligning with the broader refactoring described in the PR.

Optionally, consider sorting the __all__ list alphabetically for consistency:

 __all__ = [
     "general",
-    "user_fns",
     "samrai_hdf5",
+    "user_fns",
 ]
src/hdf5/detail/h5/h5_file.hpp (1)

78-79: Consider explicit return types for clarity.

Changing file() to return auto& instead of HiFile& reduces type clarity for developers unfamiliar with the codebase. Consider using explicit types for better readability and maintainability.

-    NO_DISCARD auto& file() { return h5file_; }
-    NO_DISCARD auto& file() const { return h5file_; }
+    NO_DISCARD HiFile& file() { return h5file_; }
+    NO_DISCARD HiFile const& file() const { return h5file_; }
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)

61-64: Add error handling for HDF5 dataset reads.

Consider adding error handling around the HDF5 getDataSet and read operations to handle potential failures if the dataset path is incorrect or a read error occurs. This improves robustness.

For example, check if the dataset exists before reading:

core::apply(soa.as_tuple(), [&](auto& arg) {
    auto const datapath = poppath + Packer::keys()[part_idx++];
    if (!h5File.file().exist(datapath))
        throw std::runtime_error("Dataset not found: " + datapath);
    h5File.file().getDataSet(datapath).read(arg);
});
src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

107-107: Improve error message specificity.

Include the unrecognized initializer name in the exception message to aid debugging.

Apply this diff:

-            throw std::runtime_error("No Particle Initializer chosen!");
+            throw std::runtime_error("Unknown particle initializer: '" + initializerName + "'");
src/hdf5/detail/h5/group_scanner.hpp (2)

29-34: Consider explicit return type for clarity.

The method returns auto&, which refers to groups. Explicitly specifying std::unordered_set<std::string>& improves code readability and self-documentation.

Apply this diff:

-    auto& scan(std::string const& from = "/")
+    std::unordered_set<std::string>& scan(std::string const& from = "/")
     {
         // prevent double / at start of full path
         scan(h5.file().getGroup(from), from == "/" ? "" : from);
         return groups;
     }

47-58: Refactor filtering logic for clarity.

The current filtering logic using cont is not immediately clear. The intent is to include paths that contain all strings in the contains vector. Using std::all_of makes this intent explicit and improves readability.

Apply this diff:

                 else
                 {
-                    bool cont = false;
-                    for (auto const& c : contains)
-                        if (fpath.find(c) == std::string::npos)
-                        {
-                            cont = true;
-                            break;
-                        }
-                    if (cont) // next node in listObjectNames
+                    // Include path only if it contains all required strings
+                    bool has_all = std::all_of(contains.begin(), contains.end(),
+                        [&fpath](auto const& c) { return fpath.find(c) != std::string::npos; });
+                    if (!has_all)
                         continue;
                     groups.insert(fpath);
                 }

This makes the logic clearer: insert the path only if all required substrings are present.

pyphare/pyphare/pharein/initialize/general.py (1)

135-135: Remove unnecessary type cast.

The value len(boxes) already returns an integer, so the int() cast is redundant.

Apply this diff:

-            add_int(level_path + "nbr_boxes/", int(len(boxes)))
+            add_int(level_path + "nbr_boxes/", len(boxes))

Based on learnings

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

227-229: Remove duplicate alias shadowing the outer ParticleInitializerFactory

This inner alias duplicates the class-scope alias and adds noise. Use the outer alias directly.

-    using ParticleInitializerFactory
-        = amr::ParticleInitializerFactory<particle_array_type, gridlayout_type>;
+    // use the outer ParticleInitializerFactory alias from HybridModel

245-247: Drop unused dict_ member to reduce footprint

dict_ isn’t used after constructing electromag_init. Remove the member and its initialization.

-    initializer::PHAREDict dict_;
-    std::unique_ptr<ElectromagInitializer_t> electromag_init;
+    std::unique_ptr<ElectromagInitializer_t> electromag_init;

And in the ctor:

-    Initializers(initializer::PHAREDict const& dict, HybridState_t const& state)
-        : dict_{dict}
-        , electromag_init{amr::ElectromagInitializerFactory::create<Electromag, GridLayoutT>(
-              dict["electromag"])}
+    Initializers(initializer::PHAREDict const& dict, HybridState_t const& state)
+        : electromag_init{amr::ElectromagInitializerFactory::create<Electromag, GridLayoutT>(
+              dict["electromag"])}

103-103: Prefer defaulted destructor

Use = default for clarity and consistency.

-    virtual ~HybridModel() override {}
+    ~HybridModel() override = default;
tests/core/numerics/ion_updater/test_updater.cpp (1)

372-376: Unify GridLayout alias style for clarity

Elsewhere in this file you use PHARETypes::GridLayout_t. Consider using it here too to keep aliases consistent. Minimal change below.

-    using GridLayout    = PHARE::core::GridLayout<GridLayoutImplYee<dim, interp_order>>;
+    using GridLayout    = PHARETypes::GridLayout_t;
📜 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 3a690c9 and 24d906c.

📒 Files selected for processing (41)
  • pyphare/pyphare/pharein/__init__.py (3 hunks)
  • pyphare/pyphare/pharein/initialize/__init__.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/general.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/user_fns.py (1 hunks)
  • pyphare/pyphare/pharein/simulation.py (3 hunks)
  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (3 hunks)
  • pyphare/pyphare/pharesee/hierarchy/patchdata.py (1 hunks)
  • res/cmake/test.cmake (1 hunks)
  • src/amr/CMakeLists.txt (1 hunks)
  • src/amr/data/electromag/electromag_initializer.hpp (1 hunks)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1 hunks)
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp (1 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/amr/level_initializer/hybrid_level_initializer.hpp (2 hunks)
  • src/amr/physical_models/hybrid_model.hpp (7 hunks)
  • src/core/CMakeLists.txt (0 hunks)
  • src/core/data/electromag/electromag.hpp (3 hunks)
  • src/core/data/grid/gridlayout.hpp (3 hunks)
  • src/core/data/ions/ions.hpp (1 hunks)
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2 hunks)
  • src/core/data/ions/particle_initializers/particle_initializer.hpp (2 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (4 hunks)
  • src/core/data/vecfield/vecfield_initializer.hpp (1 hunks)
  • src/core/utilities/box/box.hpp (1 hunks)
  • src/core/utilities/types.hpp (1 hunks)
  • src/hdf5/detail/h5/group_scanner.hpp (1 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (4 hunks)
  • src/phare_core.hpp (0 hunks)
  • src/simulator/phare_types.hpp (1 hunks)
  • tests/amr/data/particles/initializer/CMakeLists.txt (1 hunks)
  • tests/amr/data/particles/initializer/test_main.cpp (3 hunks)
  • tests/amr/models/test_models.cpp (3 hunks)
  • tests/amr/tagging/test_tagging.cpp (2 hunks)
  • tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (2 hunks)
  • tests/core/numerics/ion_updater/CMakeLists.txt (1 hunks)
  • tests/core/numerics/ion_updater/test_updater.cpp (7 hunks)
  • tests/simulator/CMakeLists.txt (2 hunks)
  • tests/simulator/test_init_from_restart.py (1 hunks)
  • tools/test_data_gen.py (1 hunks)
💤 Files with no reviewable changes (2)
  • src/core/CMakeLists.txt
  • src/phare_core.hpp
🚧 Files skipped from review as they are similar to previous changes (13)
  • src/core/data/ions/ions.hpp
  • tests/core/numerics/ion_updater/CMakeLists.txt
  • src/core/data/vecfield/vecfield_initializer.hpp
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp
  • tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp
  • src/core/utilities/box/box.hpp
  • tests/amr/models/test_models.cpp
  • src/core/utilities/types.hpp
  • tests/simulator/CMakeLists.txt
  • res/cmake/test.cmake
  • src/amr/CMakeLists.txt
  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py
  • pyphare/pyphare/pharesee/hierarchy/patchdata.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/amr/data/particles/initializers/particle_initializer_factory.hpp
  • src/hdf5/detail/h5/group_scanner.hpp
  • src/core/data/electromag/electromag.hpp
  • src/amr/level_initializer/hybrid_level_initializer.hpp
  • src/hdf5/detail/h5/h5_file.hpp
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp
  • src/core/data/ions/particle_initializers/particle_initializer.hpp
  • src/simulator/phare_types.hpp
  • src/amr/data/electromag/electromag_initializer.hpp
  • src/core/data/grid/gridlayout.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
  • src/amr/physical_models/hybrid_model.hpp
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
🧠 Learnings (4)
📓 Common learnings
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#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
PR: PHAREHUB/PHARE#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.
📚 Learning: 2024-09-17T13:36:04.487Z
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#888
File: src/amr/level_initializer/hybrid_level_initializer.hpp:44-49
Timestamp: 2024-09-17T13:36:04.487Z
Learning: In this codebase, when a derived class method overrides a virtual function using `override`, and there are no further subclasses, the `virtual` keyword is not required in the subclass.

Applied to files:

  • src/amr/level_initializer/hybrid_level_initializer.hpp
📚 Learning: 2024-09-17T13:33:47.475Z
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#888
File: src/core/data/grid/gridlayout.hpp:805-821
Timestamp: 2024-09-17T13:33:47.475Z
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-07-26T22:04:34.160Z
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#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/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
🧬 Code graph analysis (20)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • dir (50-51)
src/hdf5/detail/h5/group_scanner.hpp (1)
src/hdf5/detail/h5/h5_file.hpp (6)
  • path (274-280)
  • path (274-274)
  • path (282-287)
  • path (282-282)
  • contains (256-259)
  • contains (256-256)
src/core/data/electromag/electromag.hpp (1)
src/diagnostic/diagnostic_model_view.hpp (1)
  • dimension (30-60)
pyphare/pyphare/pharein/__init__.py (4)
pyphare/pyphare/pharein/simulation.py (1)
  • Simulation (764-1099)
pyphare/pyphare/pharein/initialize/general.py (1)
  • populateDict (89-318)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)
  • populateDict (6-16)
pyphare/pyphare/pharein/initialize/user_fns.py (1)
  • populateDict (5-7)
src/amr/level_initializer/hybrid_level_initializer.hpp (2)
src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp (16)
  • hierarchy (215-264)
  • hierarchy (215-216)
  • hierarchy (272-328)
  • hierarchy (272-275)
  • hierarchy (858-1049)
  • hierarchy (858-861)
  • model (349-377)
  • model (349-350)
  • model (599-622)
  • model (599-599)
  • model (637-661)
  • model (637-638)
  • model (666-689)
  • model (666-667)
  • model (714-734)
  • model (714-715)
src/amr/multiphysics_integrator.hpp (10)
  • hierarchy (301-376)
  • hierarchy (301-306)
  • hierarchy (380-409)
  • hierarchy (381-382)
  • hierarchy (413-427)
  • hierarchy (413-416)
  • hierarchy (556-578)
  • hierarchy (557-560)
  • model (688-707)
  • model (688-689)
tests/simulator/test_init_from_restart.py (7)
pyphare/pyphare/pharesee/hierarchy/patchdata.py (2)
  • FieldData (32-194)
  • ParticleData (197-240)
pyphare/pyphare/pharesee/hierarchy/fromh5.py (1)
  • get_all_available_quantities_from_h5 (27-33)
pyphare/pyphare/pharesee/hierarchy/hierarchy.py (1)
  • format_timestamp (13-16)
pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (2)
  • single_patch_for_LO (662-705)
  • hierarchy_compare (618-659)
tests/simulator/__init__.py (2)
  • SimulatorTest (200-266)
  • register_diag_dir_for_cleanup (233-234)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-61)
pyphare/pyphare/simulator/simulator.py (1)
  • reset (254-265)
pyphare/pyphare/pharein/initialize/user_fns.py (3)
pyphare/pyphare/pharein/initialize/general.py (5)
  • add_double (71-72)
  • add_int (63-64)
  • add_size_t (75-79)
  • fn_wrapper (50-59)
  • populateDict (89-318)
pyphare/pyphare/pharein/__init__.py (1)
  • populateDict (71-80)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)
  • populateDict (6-16)
pyphare/pyphare/pharein/initialize/general.py (4)
pyphare/pyphare/core/phare_utilities.py (1)
  • is_scalar (54-55)
pyphare/pyphare/pharein/load_balancer.py (1)
  • LoadBalancer (9-57)
pyphare/pyphare/pharein/simulation.py (4)
  • serialize (1105-1114)
  • deserialize (1117-1121)
  • restart_file_path (1010-1012)
  • is_restartable_compared_to (1060-1068)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_etc_lib (12-15)
tests/core/numerics/ion_updater/test_updater.cpp (1)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (4)
src/core/data/ions/particle_initializers/particle_initializer.hpp (1)
  • particles (14-15)
src/core/utilities/types.hpp (2)
  • apply (97-100)
  • apply (97-97)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • i (44-48)
src/core/utilities/box/box.hpp (5)
  • isIn (218-245)
  • isIn (218-218)
  • isIn (248-252)
  • isIn (248-249)
  • isIn (258-258)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (2)
src/core/utilities/types.hpp (2)
  • sized_array (133-147)
  • sized_array (133-134)
src/hdf5/detail/h5/group_scanner.hpp (2)
  • group (35-61)
  • group (35-35)
src/core/data/ions/particle_initializers/particle_initializer.hpp (2)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)
  • particles (36-37)
src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (1)
  • particles (65-66)
tests/amr/tagging/test_tagging.cpp (2)
src/amr/data/electromag/electromag_initializer.hpp (4)
  • em (34-37)
  • em (34-34)
  • em (65-69)
  • em (65-65)
tests/amr/models/test_models.cpp (2)
  • createDict (58-132)
  • createDict (58-58)
src/amr/data/electromag/electromag_initializer.hpp (1)
tests/amr/tagging/test_tagging.cpp (2)
  • em (189-193)
  • em (189-189)
src/core/data/grid/gridlayout.hpp (2)
pyphare/pyphare/core/gridlayout.py (2)
  • physicalStartIndex (262-264)
  • AMRToLocal (343-347)
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 (256-259)
  • product (256-256)
tools/test_data_gen.py (3)
tests/simulator/test_restarts.py (1)
  • test_restarts (230-289)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-61)
tests/simulator/test_init_from_restart.py (1)
  • setup_model (39-46)
src/amr/physical_models/hybrid_model.hpp (1)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (5)
src/core/data/grid/gridlayout.hpp (4)
  • centering (891-895)
  • centering (891-892)
  • centering (902-906)
  • centering (902-903)
src/core/utilities/types.hpp (6)
  • ConstArray (168-174)
  • ConstArray (168-168)
  • for_N (434-465)
  • for_N (434-434)
  • for_N (468-471)
  • for_N (468-468)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • i (44-48)
src/core/data/ndarray/ndarray_vector.hpp (4)
  • make_array_view (232-235)
  • make_array_view (232-232)
  • make_array_view (238-241)
  • make_array_view (238-238)
src/core/utilities/box/box.hpp (4)
  • grow (88-93)
  • grow (88-88)
  • grow (277-282)
  • grow (277-277)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (3)
pyphare/pyphare/pharein/initialize/general.py (2)
  • add_int (63-64)
  • populateDict (89-318)
pyphare/pyphare/pharein/__init__.py (1)
  • populateDict (71-80)
pyphare/pyphare/pharein/initialize/user_fns.py (1)
  • populateDict (5-7)
🪛 Ruff (0.14.0)
pyphare/pyphare/pharein/simulation.py

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

(TRY003)

tests/simulator/test_init_from_restart.py

39-39: Unused function argument: sim

(ARG001)

pyphare/pyphare/pharein/initialize/user_fns.py

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

(TRY003)

pyphare/pyphare/pharein/initialize/general.py

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

(TRY003)


135-135: Value being cast to int is already an integer

Remove unnecessary int call

(RUF046)


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

(TRY003)


273-275: Avoid specifying long messages outside the exception class

(TRY003)


281-283: Avoid specifying long messages outside the exception class

(TRY003)


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

(TRY003)

tools/test_data_gen.py

35-35: Local variable p is assigned to but never used

Remove assignment to unused variable p

(F841)


35-35: subprocess call: check for execution of untrusted input

(S603)

pyphare/pyphare/pharein/initialize/__init__.py

5-9: __all__ is not sorted

Apply an isort-style sorting to __all__

(RUF022)

pyphare/pyphare/pharein/initialize/samrai_hdf5.py

9-9: Loop control variable pop not used within loop body

Rename unused pop to _pop

(B007)

⏰ 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: build (macos-14)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-13)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (ubuntu-latest, gcc)
🔇 Additional comments (35)
src/core/data/ions/particle_initializers/particle_initializer.hpp (2)

4-4: LGTM!

The #include <string> is correctly added to support the new std::string const& popname parameter.


14-16: LGTM!

The addition of the popname parameter enables population-aware particle initialization, aligning with the PR's objectives. The signature change is consistent with updates in derived classes.

tools/test_data_gen.py (2)

14-27: LGTM!

The function correctly generates restart test data by configuring simulation parameters and running the simulation.


40-45: LGTM!

The main guard correctly handles both single-function execution and batch execution modes.

src/amr/level_initializer/hybrid_level_initializer.hpp (1)

44-49: LGTM!

The formatting changes improve readability. The method correctly uses override without virtual, which is acceptable for this final override.

pyphare/pyphare/pharein/initialize/user_fns.py (2)

5-16: LGTM!

The electromagnetic field initialization correctly registers magnetic field components using dimension-specific initialization functions.


19-51: LGTM!

The particle initialization correctly configures per-population initializers with density and velocity functions. The implementation aligns with the new population-aware initialization workflow.

src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1)

36-67: LGTM!

The HDF5 field loading implementation correctly:

  • Retrieves overlapping patches from the SAMRAI interface
  • Reads dataset from HDF5
  • Computes local coordinate transformations
  • Copies data element-wise from source to destination fields
tests/simulator/test_init_from_restart.py (2)

49-59: LGTM!

The test class correctly manages simulator lifecycle with proper tearDown cleanup.


61-77: LGTM!

The restart test correctly:

  • Initializes simulation from HDF5 restart data
  • Loads and compares hierarchies from different restart sources
  • Filters ghost patches and validates data consistency
src/core/data/ndarray/ndarray_vector.hpp (4)

24-36: LGTM!

The compile-time dimension dispatch for index calculation is clean and efficient.


38-71: LGTM with note on potential overflow.

The index calculation is efficient and correct. Note that for very large arrays (dimensions > 65535), integer overflow could occur at lines 55 and 67. Consider if grid size validation exists elsewhere in the codebase.


74-89: LGTM!

The data access methods correctly use index calculation with debug-time bounds checking. The assertion provides safety during development while maintaining release-build performance.


254-261: Excellent use of concepts!

The requires clause ensuring integral node types is a clean way to enforce type safety at compile time.

src/amr/data/initializers/samrai_hdf5_initializer.hpp (4)

18-32: LGTM!

The patch data info structure is clean and uses const members appropriately to ensure immutability.


44-72: LGTM!

The singleton interface and box intersection logic are correctly implemented. The API provides clean access to restart data loading and patch queries.


88-92: LGTM!

The constructor correctly initializes the HDF5 file in read-only mode. HighFive exceptions will propagate appropriately if the file cannot be opened.


114-133: LGTM!

The population logic correctly:

  • Ensures single execution via early return
  • Scans all MPI rank restart files
  • Extracts patch metadata and bounding boxes
  • Builds the internal patch registry for intersection queries
src/core/data/grid/gridlayout.hpp (4)

804-820: LGTM: AMRToLocal 2-argument overload is well-designed.

The new parameterized form allows callers to specify an explicit local box for coordinate transformation, increasing flexibility. The assertion before the uint32_t cast ensures validity, consistent with past review guidance.

Based on learnings


822-826: LGTM: Delegation to 2-argument overloads maintains backward compatibility.

The 1-argument overloads cleanly delegate to the new 2-argument versions using AMRBox_ as the default local box, preserving the existing API without code duplication.

Also applies to: 842-846


1209-1209: LGTM: Simple accessor for level number.

The levelNumber() accessor cleanly exposes the internal level number state.


1264-1276: LGTM: _BoxFor correctly handles variable dimensions.

The directions array contains all three directions, but the loop at line 1269 only iterates i < dimension, ensuring only the relevant direction elements are accessed. This is safe and correct for 1D, 2D, and 3D cases.

tests/amr/data/particles/initializer/CMakeLists.txt (1)

14-14: LGTM: Library linkage updated to match namespace migration.

The change from phare_core to phare_amr correctly reflects the migration of ParticleInitializerFactory from the core to the amr namespace, as described in the PR summary.

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

13-15: LGTM: Includes added for new scan_for_groups functionality.

The new includes (<unordered_set> and "group_scanner.hpp") support the scan_for_groups method added below.

src/simulator/phare_types.hpp (1)

28-30: LGTM: ParticleInitializerFactory alias updated to reference amr namespace.

The change from core_types::ParticleInitializerFactory_t to the explicitly templated amr::ParticleInitializerFactory<ParticleArray_t, GridLayout_t> correctly reflects the namespace migration and improves clarity by making the template parameters explicit.

pyphare/pyphare/pharein/simulation.py (1)

678-678: LGTM: init_options integrated into validation flow.

The addition of "init_options" to the accepted keywords (line 678) and the call to check_init_options (line 713) properly integrates the new initialization options validation into the existing flow.

Also applies to: 713-713

src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)

46-71: LGTM: Particle loading logic is sound.

The implementation correctly:

  • Obtains overlapping regions via SamraiH5Interface
  • Constructs dataset paths using popname and ParticlePacker keys
  • Reads particles into a temporary ContiguousParticles container
  • Filters particles by cell position within the destination box
  • Appends qualifying particles to the output array

The logic aligns well with the broader restart/initialization refactoring.

tests/amr/data/particles/initializer/test_main.cpp (1)

10-10: LGTM! Namespace refactor and key normalization.

The changes correctly reflect the namespace migration from core to amr and the normalization of dictionary keys to snake_case (maxwellian, nbr_part_per_cell, cartesian). This improves consistency across the codebase.

Also applies to: 32-32, 43-48

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

20-20: LGTM! Type aliases improve code clarity.

The addition of This and vecfield_type type aliases enhances code readability and provides convenient shorthands for template types. This aligns well with the broader refactor toward external initialization.

Also applies to: 23-23

src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

76-90: LGTM! Correct use of core namespace.

The usage of core::MaxwellianParticleInitializer and core::Basis is appropriate, as these classes remain in the core namespace. The factory correctly resides in the amr namespace while utilizing core components.

tests/amr/tagging/test_tagging.cpp (1)

185-187: LGTM! Dictionary-driven initialization pattern.

The addition of dict_ and the use of state{dict_} correctly implements the new factory-based initialization pattern. The test properly delegates electromagnetics initialization to the new init method.

Also applies to: 196-196, 205-210, 215-215

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

22-26: LGTM! Clean scanning implementation.

The recursive scanning logic correctly traverses HDF5 groups and builds full paths. The constructor and member variables are well-structured for the scanning task.

Also applies to: 35-46, 64-67

pyphare/pyphare/pharein/__init__.py (1)

72-80: LGTM! Clean delegation to modular initializers.

The refactored populateDict() cleanly delegates to modular initialization submodules (initialize.general, initialize.user_fns, initialize.samrai_hdf5) based on sim.init_options. This improves maintainability and separation of concerns.

pyphare/pyphare/pharein/initialize/general.py (1)

89-318: LGTM! Comprehensive configuration builder.

The populateDict function systematically builds the hierarchical configuration dictionary covering simulation parameters, AMR settings, diagnostics, restarts, and electron populations. While lengthy, the function is logically structured and handles the necessary complexity of the initialization system.

src/amr/data/electromag/electromag_initializer.hpp (1)

76-88: LGTM! Clean factory pattern implementation.

The factory correctly selects between user-function and HDF5-based initialization based on dictionary contents. The logic is clear and the pattern promotes modularity.

Comment on lines +59 to +61
ElectromagSamraiH5Initializer(initializer::PHAREDict const& dict)
: dict_{dict}
{
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove unused member variable.

The dict_ member is initialized in the constructor but never used in the init method or elsewhere. This adds unnecessary memory overhead and may confuse future maintainers.

Apply this diff:

     ElectromagSamraiH5Initializer(initializer::PHAREDict const& dict)
-        : dict_{dict}
     {
     }
     
     ...
     
-    initializer::PHAREDict const dict_;

Based on learnings

Also applies to: 71-71

🤖 Prompt for AI Agents
In src/amr/data/electromag/electromag_initializer.hpp around lines 59-61 (and
also line 71), remove the unused member variable dict_ and its initialization in
the constructor initializer list; update the constructor signature to either
drop the initializer::PHAREDict const& dict parameter if it's not required by
callers, or keep the parameter but stop storing it (remove dict_ declaration and
the ": dict_{dict}" initializer). Also remove any forward declaration or
includes only needed for dict_ if they become unused, and rebuild to ensure no
remaining references to dict_ remain.

Comment on lines +243 to +244
auto& particles(typename Ions::value_type& pop) { return *particle_pop_init[pop.name()]; }

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

Don’t use operator[] for lookup; use at() or find() to avoid default insertion

particle_pop_init[pop.name()] may insert a null unique_ptr and then be dereferenced.

-    auto& particles(typename Ions::value_type& pop) { return *particle_pop_init[pop.name()]; }
+    auto& particles(typename Ions::value_type& pop) { return *particle_pop_init.at(pop.name()); }

If you prefer explicit checks:

-    auto& particles(typename Ions::value_type& pop) { return *particle_pop_init[pop.name()]; }
+    auto& particles(typename Ions::value_type& pop) {
+        auto it = particle_pop_init.find(pop.name());
+        PHARE_ASSERT(it != particle_pop_init.end());
+        return *it->second;
+    }
🤖 Prompt for AI Agents
In src/amr/physical_models/hybrid_model.hpp around lines 243-244, the expression
particle_pop_init[pop.name()] uses operator[] which can default-insert a null
unique_ptr and then be dereferenced; change the lookup to use at() or find()
instead, check the lookup result (or catch std::out_of_range from at()) and
ensure the pointer is non-null before dereferencing, and provide a clear error
(throw or return) if the entry is missing or null to avoid undefined behavior.

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: 2

♻️ Duplicate comments (13)
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (4)

30-30: Default the empty constructor.

The default constructor has an empty body and can be explicitly defaulted for clarity.


1-2: Typo in include guard macro.

The include guard contains a spelling error: INITIAZILIZERS should be INITIALIZERS.


5-10: Header is not self-contained (missing Box/grow includes).

The header uses core::Box and the grow utility but doesn't directly include their definitions.


43-49: Add null pointer checks and HDF5 error handling.

h5FilePtr and pdataptr are dereferenced without validation. Additionally, the HDF5 read_data_set_flat call has no error handling if the dataset is missing or corrupted.

Consider adding:

 for (auto const& [overlap_box, h5FilePtr, pdataptr] : overlaps)
 {
+    assert(h5FilePtr && pdataptr && "Overlap pointers must be valid");
     auto& h5File       = *h5FilePtr;
     auto& pdata        = *pdataptr;
     auto const src_box = pdata.box;
-    auto const data    = h5File.template read_data_set_flat<double>(
-        pdata.base_path + "/" + field.name() + "##default/field_" + field.name());
+    auto const dataset_path = pdata.base_path + "/" + field.name() + "##default/field_" + field.name();
+    auto const data = h5File.template read_data_set_flat<double>(dataset_path);
+    // Validate data size matches expected volume
src/amr/data/initializers/samrai_hdf5_initializer.hpp (7)

50-51: Pass small built-in types by value.

Parameters idx and mpi_size are passed by const reference, but int is a small type that should be passed by value for efficiency.


53-55: Pass small built-in types by value and string by const reference.

Pass int parameters by value and consider passing the path parameter by const reference to avoid unnecessary copying.


125-125: Simplify unique_ptr insertion and dereferencing.

The combined emplace_back and dereference on one line reduces readability.


1-2: Typo in include guard macro.

The include guard contains a spelling error: INITIAZILIZERS should be INITIALIZERS.


88-92: Add error handling for HDF5 file opening failures.

The base class constructor opens the HDF5 file, but if the file doesn't exist or lacks read permissions, the exception propagation may not provide sufficient context.


96-100: Unsafe reinterpret_cast violates type safety and may cause undefined behavior.

The reinterpret_cast assumes the internal layout of SAMRAI's integer box structure matches std::array<int, 3>, which is not guaranteed and violates strict aliasing rules. This is a portability and correctness risk.


104-105: Guard against empty box vector to prevent out-of-bounds access.

Accessing boxes[0] without checking if the vector is non-empty will cause undefined behavior if no boxes are found at the specified path.

src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (2)

1-2: Typo in include guard macro.

The include guard contains a spelling error: INITIAZILIZERS should be INITIALIZERS.


51-64: Add null pointer checks and validate HDF5 read operations.

h5FilePtr and pdataptr are dereferenced without validation. Additionally, the HDF5 getDataSet().read() operations lack error handling if datasets are missing or have mismatched sizes.

Consider:

 for (auto const& [overlap_box, h5FilePtr, pdataptr] : overlaps)
 {
+    assert(h5FilePtr && pdataptr && "Overlap pointers must be valid");
     auto& h5File = *h5FilePtr;
     auto& pdata  = *pdataptr;

     std::string const poppath = pdata.base_path + "/" + popname + "##default/domainParticles_";
     core::ContiguousParticles<ParticleArray::dimension> soa{0};

     {
         std::size_t part_idx = 0;
         core::apply(soa.as_tuple(), [&](auto& arg) {
             auto const datapath = poppath + Packer::keys()[part_idx++];
+            if (!h5File.file().exist(datapath))
+                throw std::runtime_error("Missing dataset: " + datapath);
             h5File.file().getDataSet(datapath).read(arg);
         });
+        // Validate all SOA arrays have consistent size
     }
🧹 Nitpick comments (6)
src/core/data/grid/gridlayout.hpp (2)

1209-1218: Add documentation for new public API methods.

The new public methods levelNumber() and domainBoxFor() lack documentation comments. Consider adding doxygen-style comments to explain their purpose, parameters, and return values, consistent with other well-documented methods in this class (e.g., physicalStartIndex at lines 301-310).

Example:

/**
 * @brief returns the AMR level number of this grid layout
 */
auto levelNumber() const { return levelNumber_; }

/**
 * @brief domainBoxFor returns the physical domain box for a given field
 * @param field the field for which to compute the domain box
 * @return Box containing the start and end indices of the physical domain
 */
template<typename Field>
auto domainBoxFor(Field const& field) const
{
    return _BoxFor(field, [&](auto const& centering, auto const direction) {
        return this->physicalStartToEnd(centering, direction);
    });
}

1258-1265: Consider sizing the directions array to match dimension (optional).

While the current implementation is safe because the loop bound at line 1260 prevents out-of-bounds access, the directions array always allocates 3 elements regardless of the actual dimension. For clarity and to avoid confusion, you could size it to match dimension:

constexpr auto directions = []() {
    if constexpr (dimension == 1) {
        return std::array{Direction::X};
    } else if constexpr (dimension == 2) {
        return std::array{Direction::X, Direction::Y};
    } else {
        return std::array{Direction::X, Direction::Y, Direction::Z};
    }
}();

However, the current approach is simpler and the performance difference is negligible for a small constexpr array.

Based on learnings

src/core/data/field/initializers/field_user_initializer.hpp (3)

1-2: Header guard spelling fix looks good; drop leading underscore to avoid reserved identifiers.

Names beginning with an underscore followed by an uppercase letter are reserved. Recommend using a non‑reserved guard and syncing the closing comment.

Apply:

-#ifndef _PHARE_CORE_DATA_FIELD_INITIALIZERS_FIELD_USER_INITIALIZER_HPP_
-#define _PHARE_CORE_DATA_FIELD_INITIALIZERS_FIELD_USER_INITIALIZER_HPP_
+#ifndef PHARE_CORE_DATA_FIELD_INITIALIZERS_FIELD_USER_INITIALIZER_HPP_
+#define PHARE_CORE_DATA_FIELD_INITIALIZERS_FIELD_USER_INITIALIZER_HPP_
@@
-#endif /*_PHARE_CORE_DATA_FIELD_INITIALIZERS_FIELD_USER_INITIALIZER_HPP_*/
+#endif /* PHARE_CORE_DATA_FIELD_INITIALIZERS_FIELD_USER_INITIALIZER_HPP_ */

As per coding guidelines.

Also applies to: 36-36


25-31: Add debug checks to prevent null deref and OOB writes.

init(...) may return nullptr or a grid with a size different from indices.size(); both lead to UB here. Cheap debug asserts catch this without runtime cost in release.

Apply:

@@
-        std::shared_ptr<Span<double>> gridPtr // keep grid data alive
-            = std::apply([&](auto&... args) { return init(args...); }, coords);
-        Span<double>& grid = *gridPtr;
+        auto gridPtr // keep grid data alive
+            = std::apply([&](auto&... args) { return init(args...); }, coords);
+        assert(gridPtr && "Init function returned null grid");
+        Span<double> const& grid = *gridPtr;
+        assert(grid.size() == indices.size()
+               && "Init grid size must equal number of target indices");
@@
         for (std::size_t cell_idx = 0; cell_idx < indices.size(); cell_idx++)
             std::apply([&](auto&... args) { field(args...) = grid[cell_idx]; }, indices[cell_idx]);

And add the header:

@@
 #include <tuple>
 #include <memory>
+#include <cassert>

Based on learnings.


27-27: Const‑correctness for grid view.

grid is read‑only; take it as const reference.

Apply:

-        Span<double>& grid = *gridPtr;
+        Span<double> const& grid = *gridPtr;
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)

32-32: Default the empty constructor.

The default constructor has an empty body and can be explicitly defaulted.

-SamraiHDF5ParticleInitializer() {}
+SamraiHDF5ParticleInitializer() = default;
📜 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 24d906c and 222a021.

📒 Files selected for processing (5)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1 hunks)
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp (1 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/core/data/field/initializers/field_user_initializer.hpp (2 hunks)
  • src/core/data/grid/gridlayout.hpp (3 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/data/field/initializers/field_user_initializer.hpp
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
  • src/core/data/grid/gridlayout.hpp
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp
🧠 Learnings (3)
📓 Common learnings
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#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
PR: PHAREHUB/PHARE#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.
📚 Learning: 2024-07-26T22:04:34.160Z
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#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/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
📚 Learning: 2024-09-17T13:33:47.475Z
Learnt from: PhilipDeegan
PR: PHAREHUB/PHARE#888
File: src/core/data/grid/gridlayout.hpp:805-821
Timestamp: 2024-09-17T13:33:47.475Z
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 (4)
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (5)
src/core/data/grid/gridlayout.hpp (4)
  • centering (891-895)
  • centering (891-892)
  • centering (902-906)
  • centering (902-903)
src/core/utilities/types.hpp (6)
  • ConstArray (168-174)
  • ConstArray (168-168)
  • for_N (434-465)
  • for_N (434-434)
  • for_N (468-471)
  • for_N (468-468)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • i (44-48)
src/core/data/ndarray/ndarray_vector.hpp (4)
  • make_array_view (232-235)
  • make_array_view (232-232)
  • make_array_view (238-241)
  • make_array_view (238-238)
src/core/utilities/box/box.hpp (4)
  • grow (88-93)
  • grow (88-88)
  • grow (277-282)
  • grow (277-277)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (3)
src/core/utilities/types.hpp (2)
  • apply (97-100)
  • apply (97-97)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • i (44-48)
src/core/utilities/box/box.hpp (5)
  • isIn (218-245)
  • isIn (218-218)
  • isIn (248-252)
  • isIn (248-249)
  • isIn (258-258)
src/core/data/grid/gridlayout.hpp (3)
pyphare/pyphare/core/gridlayout.py (2)
  • physicalStartIndex (262-264)
  • AMRToLocal (343-347)
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/amr/resources_manager/amr_utils.hpp (5)
  • AMRToLocal (47-48)
  • AMRToLocal (55-56)
  • AMRToLocal (64-64)
  • AMRToLocal (79-92)
  • AMRToLocal (79-80)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (2)
src/core/utilities/types.hpp (2)
  • sized_array (133-147)
  • sized_array (133-134)
src/hdf5/detail/h5/group_scanner.hpp (2)
  • group (35-61)
  • group (35-35)
🔇 Additional comments (5)
src/core/data/grid/gridlayout.hpp (3)

804-820: LGTM!

The parameterization of AMRToLocal with the localbox argument is well-implemented. The assertion on line 816 correctly validates that local >= 0 before the cast to uint32_t, as previously discussed.


822-826: LGTM!

The 1-argument overload provides clean backward compatibility through delegation to the 2-argument version. This is a good pattern.


834-846: LGTM!

The Box overloads mirror the Point overloads appropriately. The transformation logic correctly applies AMRToLocal to both lower and upper bounds.

src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1)

62-65: Verify that source and destination boxes have equal element counts.

The parallel iteration assumes lcl_src_box and lcl_dst_box have the same number of elements. If they differ due to a logic error in box computation, the loop could advance iterators beyond valid ranges.

While the box intersection logic should guarantee matching sizes, consider adding a debug assertion:

     auto src_it            = lcl_src_box.begin();
     auto dst_it            = lcl_dst_box.begin();
+    assert(lcl_src_box.size() == lcl_dst_box.size() && "Source and destination boxes must match");
     for (; src_it != lcl_src_box.end(); ++src_it, ++dst_it)
         field(*dst_it) = data_view(*src_it);
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)

119-132: Consider thread safety for the singleton pattern.

The singleton INSTANCE() and populate_from() method use a size check (line 119) to avoid re-population, but this is not thread-safe if multiple threads call populate_from() concurrently. In an MPI context this may not be an issue, but document the assumption or add synchronization.

If concurrent access is possible, consider:

  • Adding a mutex around the early-return check and file population
  • Documenting that populate_from() must be called from a single thread
  • Using std::call_once for initialization

Comment on lines +50 to +66
core::Box<std::uint32_t, GridLayout::dimension> const lcl_src_gbox{
core::Point{core::ConstArray<std::uint32_t, GridLayout::dimension>()},
core::Point{
core::for_N<GridLayout::dimension, core::for_N_R_mode::make_array>([&](auto i) {
return static_cast<std::uint32_t>(
src_box.upper[i] - src_box.lower[i] + (GridLayout::nbrGhosts() * 2)
+ (centering[i] == core::QtyCentering::primal ? 1 : 0));
})}};
auto const data_view = core::make_array_view(data.data(), *lcl_src_gbox.shape());
auto const overlap_gb = grow(overlap_box, GridLayout::nbrGhosts());
auto const lcl_src_box = layout.AMRToLocal(overlap_gb, src_box);
auto const lcl_dst_box = layout.AMRToLocal(overlap_gb, dest_box);
auto src_it = lcl_src_box.begin();
auto dst_it = lcl_dst_box.begin();
for (; src_it != lcl_src_box.end(); ++src_it, ++dst_it)
field(*dst_it) = data_view(*src_it);
}
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

Validate that source data size matches the expected ghosted box volume.

The code constructs lcl_src_gbox and creates a view over data but doesn't verify that data.size() equals the volume of lcl_src_gbox. If the HDF5 dataset has the wrong size, the view could access out-of-bounds memory.

Apply this check after reading the dataset:

     auto const data    = h5File.template read_data_set_flat<double>(
         pdata.base_path + "/" + field.name() + "##default/field_" + field.name());
     core::Box<std::uint32_t, GridLayout::dimension> const lcl_src_gbox{
         core::Point{core::ConstArray<std::uint32_t, GridLayout::dimension>()},
         core::Point{
             core::for_N<GridLayout::dimension, core::for_N_R_mode::make_array>([&](auto i) {
                 return static_cast<std::uint32_t>(
                     src_box.upper[i] - src_box.lower[i] + (GridLayout::nbrGhosts() * 2)
                     + (centering[i] == core::QtyCentering::primal ? 1 : 0));
             })}};
+    auto const expected_size = lcl_src_gbox.size();
+    if (data.size() != expected_size)
+        throw std::runtime_error("HDF5 dataset size mismatch: expected " 
+                                 + std::to_string(expected_size) + ", got " 
+                                 + std::to_string(data.size()));
     auto const data_view   = core::make_array_view(data.data(), *lcl_src_gbox.shape());
📝 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
core::Box<std::uint32_t, GridLayout::dimension> const lcl_src_gbox{
core::Point{core::ConstArray<std::uint32_t, GridLayout::dimension>()},
core::Point{
core::for_N<GridLayout::dimension, core::for_N_R_mode::make_array>([&](auto i) {
return static_cast<std::uint32_t>(
src_box.upper[i] - src_box.lower[i] + (GridLayout::nbrGhosts() * 2)
+ (centering[i] == core::QtyCentering::primal ? 1 : 0));
})}};
auto const data_view = core::make_array_view(data.data(), *lcl_src_gbox.shape());
auto const overlap_gb = grow(overlap_box, GridLayout::nbrGhosts());
auto const lcl_src_box = layout.AMRToLocal(overlap_gb, src_box);
auto const lcl_dst_box = layout.AMRToLocal(overlap_gb, dest_box);
auto src_it = lcl_src_box.begin();
auto dst_it = lcl_dst_box.begin();
for (; src_it != lcl_src_box.end(); ++src_it, ++dst_it)
field(*dst_it) = data_view(*src_it);
}
core::Box<std::uint32_t, GridLayout::dimension> const lcl_src_gbox{
core::Point{core::ConstArray<std::uint32_t, GridLayout::dimension>()},
core::Point{
core::for_N<GridLayout::dimension, core::for_N_R_mode::make_array>([&](auto i) {
return static_cast<std::uint32_t>(
src_box.upper[i] - src_box.lower[i] + (GridLayout::nbrGhosts() * 2)
(centering[i] == core::QtyCentering::primal ? 1 : 0));
})}};
auto const expected_size = lcl_src_gbox.size();
if (data.size() != expected_size)
throw std::runtime_error("HDF5 dataset size mismatch: expected "
std::to_string(expected_size) + ", got "
std::to_string(data.size()));
auto const data_view = core::make_array_view(data.data(), *lcl_src_gbox.shape());
auto const overlap_gb = grow(overlap_box, GridLayout::nbrGhosts());
auto const lcl_src_box = layout.AMRToLocal(overlap_gb, src_box);
auto const lcl_dst_box = layout.AMRToLocal(overlap_gb, dest_box);
auto src_it = lcl_src_box.begin();
auto dst_it = lcl_dst_box.begin();
for (; src_it != lcl_src_box.end(); ++src_it, ++dst_it)
field(*dst_it) = data_view(*src_it);
}
🤖 Prompt for AI Agents
In src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp around
lines 50 to 66, after constructing lcl_src_gbox and before creating data_view,
validate that data.size() equals the expected volume of lcl_src_gbox (product of
its shape extents); if it does not, produce a clear error (throw
std::runtime_error or return an error) that includes the expected and actual
sizes to avoid out-of-bounds access when making the view and copying values.
Calculate the expected volume from *lcl_src_gbox.shape(), compare to
data.size(), and bail out with a descriptive error message if they differ.

Comment on lines +61 to +64
core::apply(soa.as_tuple(), [&](auto& arg) {
auto const datapath = poppath + Packer::keys()[part_idx++];
h5File.file().getDataSet(datapath).read(arg);
});
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

Validate that all particle SOA arrays have consistent sizes after reading.

After reading multiple datasets into the SOA structure, the code doesn't verify that all arrays (iCell, delta, weight, charge, v) have the same size. Mismatched sizes would lead to incorrect particle reconstruction at line 68.

Add validation after the read loop:

     {
         std::size_t part_idx = 0;
         core::apply(soa.as_tuple(), [&](auto& arg) {
             auto const datapath = poppath + Packer::keys()[part_idx++];
             h5File.file().getDataSet(datapath).read(arg);
         });
+        // Verify all SOA components have the same size
+        if (!soa.validate_sizes())
+            throw std::runtime_error("Particle SOA size mismatch in dataset: " + poppath);
     }

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

🤖 Prompt for AI Agents
In src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
around lines 61-64, after the core::apply read loop add a validation step that
inspects the sizes of each SOA array (iCell, delta, weight, charge, v) and
ensures they are all equal; if any size differs, throw or log a clear
runtime_error including the expected size and each array's actual size and the
dataset path so the caller can diagnose the bad HDF5 input. Implement this by
extracting size() from each tuple element (or by iterating the tuple to collect
sizes), compare them to the first element's size, and fail fast with a
descriptive message when a mismatch is detected.

@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 8, 2025
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 8, 2025
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 8, 2025
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 8, 2025
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 8, 2025
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 8, 2025
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Nov 8, 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: 17

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

82-89: Fix magnetic basis field component lookups.

magnetic_y and magnetic_z get ignored because all three entries reuse "magnetic_x". That zeros-out the transverse field in magnetic-basis runs. Please load each component from its proper key.

-                    magneticField[0] = dict["magnetic_x"].template to<FunctionType>();
-                    magneticField[1] = dict["magnetic_x"].template to<FunctionType>();
-                    magneticField[2] = dict["magnetic_x"].template to<FunctionType>();
+                    magneticField[0] = dict["magnetic_x"].template to<FunctionType>();
+                    magneticField[1] = dict["magnetic_y"].template to<FunctionType>();
+                    magneticField[2] = dict["magnetic_z"].template to<FunctionType>();
♻️ Duplicate comments (24)
tests/core/numerics/ion_updater/CMakeLists.txt (1)

13-16: Dependency change already addressed in prior review.

This change was previously flagged in the codebase verification review and has been addressed. The shift from phare_core to phare_amr is part of the consistent refactoring across all test modules.

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

149-156: Critical: Add bounds checking to prevent undefined behavior.

Line 154 accesses from[i] without verifying that i < from.size(). If To_Size exceeds the vector size, this causes undefined behavior.

Apply this diff to add safety checks and use std::copy_n:

 template<std::size_t To_Size, typename Type>
 NO_DISCARD std::array<Type, To_Size> to_array(std::vector<Type> const& from)
 {
+    if (from.size() < To_Size)
+        throw std::invalid_argument("Input vector size is smaller than the requested array size");
     std::array<Type, To_Size> to{};
-    for (std::size_t i = 0; i < to.size(); i++)
-        to[i] = from[i];
+    std::copy_n(from.begin(), To_Size, to.begin());
     return to;
 }
pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (1)

592-602: Fix IndexError when accessing empty failed list.

Line 601 accesses self.failed[0][0] without verifying that failed is non-empty, which will raise an IndexError if no failures are recorded. This issue was flagged in previous review comments but remains unresolved.

Additionally, performing assertions within __repr__ (lines 596-600) is unexpected behavior for a string representation method.

Apply this diff to prevent the IndexError and simplify the implementation:

 def __repr__(self):
+    if not self.failed:
+        return "EqualityReport(success)"
     strs = []
     for msg, ref, cmp in self:
         strs.append(msg)
         try:
             if type(ref) is FieldData:
                 phut.assert_fp_any_all_close(ref[:], cmp[:], atol=1e-16)
         except AssertionError as e:
-            strs.append(e)
-    strs.append(self.failed[0][0])
+            strs.append(str(e))
+    strs.append(self.failed[0][0])
     return os.linesep.join(strs)
src/core/data/ndarray/ndarray_vector.hpp (1)

55-55: Fix potential integer overflow in index calculations.

The multiplication of array dimensions can overflow when operands are uint32_t before being converted to size_t. This was flagged by the security scanner and could lead to incorrect memory access.

Apply this diff to cast operands before multiplication:

             if constexpr (c_ordering)
-                return j + i * nCells[1];
+                return j + static_cast<std::size_t>(i) * static_cast<std::size_t>(nCells[1]);
             else
-                return i + j * nCells[0];
+                return i + static_cast<std::size_t>(j) * static_cast<std::size_t>(nCells[0]);

And for the 3D case:

             if constexpr (c_ordering)
-                return k + j * nCells[2] + i * nCells[1] * nCells[2];
+            {
+                auto const dim2 = static_cast<std::size_t>(nCells[2]);
+                auto const dim1 = static_cast<std::size_t>(nCells[1]);
+                return static_cast<std::size_t>(k) + static_cast<std::size_t>(j) * dim2 
+                       + static_cast<std::size_t>(i) * dim1 * dim2;
+            }
             else
-                return i + j * nCells[0] + k * nCells[1] * nCells[0];
+            {
+                auto const dim0 = static_cast<std::size_t>(nCells[0]);
+                auto const dim1 = static_cast<std::size_t>(nCells[1]);
+                return static_cast<std::size_t>(i) + static_cast<std::size_t>(j) * dim0 
+                       + static_cast<std::size_t>(k) * dim1 * dim0;
+            }

Also applies to: 67-67

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

78-79: Consider explicit return types for clarity.

The return type auto& was previously flagged for reducing code clarity. Using the explicit type HiFile& (and HiFile const& for the const overload) would improve readability and maintainability.


260-263: Add const qualifier to scan_for_groups method.

The method does not modify any member variables and should be marked const to improve const-correctness and allow it to be called on const instances of HighFiveFile.

Apply this diff:

-    std::unordered_set<std::string> scan_for_groups(std::vector<std::string> const& contains)
+    std::unordered_set<std::string> scan_for_groups(std::vector<std::string> const& contains) const
src/hdf5/detail/h5/group_scanner.hpp (1)

48-57: Improve filtering logic clarity.

The variable cont is unclear and the nested loop could be replaced with standard algorithms like std::all_of for better expressiveness. This was previously suggested but remains unaddressed.

Consider refactoring:

if (std::all_of(contains.begin(), contains.end(),
                [&](const std::string& c) { return fpath.find(c) != std::string::npos; }))
    groups.insert(fpath);
pyphare/pyphare/pharein/simulation.py (1)

533-543: Simplify kwargs.get and improve validation logic.

The implementation has several areas for improvement:

  1. Line 533: kwargs.get("init_options", None) can be simplified to kwargs.get("init_options") since None is the default.
  2. Lines 535-537: The format validation should be mandatory when init_options is provided, and the error message should list valid formats.
  3. The function should validate both top-level dir and nested options["dir"] keys.

Apply this diff:

 def check_init_options(**kwargs):
     """Advanced options to initialize from SAMRAI HDF5 files"""
 
     formats = ["samraih5"]
-    init_options = kwargs.get("init_options", None)
+    init_options = kwargs.get("init_options")
 
-    if init_options is not None and "format" in init_options:
-        if init_options["format"] not in formats:
-            raise ValueError("Error - init_options format is invalid")
+    if init_options is not None:
+        if "format" not in init_options or init_options["format"] not in formats:
+            raise ValueError(f"Error - init_options format is invalid or missing, expected one of: {formats}")
+        if "dir" in init_options:
+            init_options["dir"] = check_directory(init_options["dir"], "init_options")
         if "options" in init_options and "dir" in init_options["options"]:
             init_options["options"]["dir"] = check_directory(
                 init_options["options"]["dir"], "init_options"
             )
 
     return init_options
src/core/data/electromag/electromag.hpp (1)

24-24: Reorder specifiers for consistency.

The specifier order auto static constexpr is unconventional. The standard order places storage-class specifiers before type specifiers.

Apply this diff to reorder the specifiers:

-        auto static constexpr dimension = VecFieldT::dimension;
+        static constexpr auto dimension = VecFieldT::dimension;
tests/simulator/test_init_from_restart.py (5)

1-1: Remove unused import.

Apply this diff:

-import sys

4-4: Remove unused import.

Apply this diff:

-import subprocess

5-5: Remove unused import.

Apply this diff:

-import numpy as np

10-10: Remove unused imports.

Apply this diff:

-from pyphare.pharesee.hierarchy.patchdata import FieldData, ParticleData

15-15: Remove unused import.

Apply this diff:

-from tests.simulator import SimulatorTest, test_restarts
+from tests.simulator import SimulatorTest
pyphare/pyphare/pharein/initialize/general.py (1)

198-200: Use ValueError for invalid population count.

Apply this diff:

     if init_model.nbr_populations() < 0:
-        raise RuntimeError("Number of populations cannot be negative")
+        raise ValueError("Number of populations cannot be negative")
     add_size_t("simulation/ions/nbrPopulations", init_model.nbr_populations())
pyphare/pyphare/pharein/initialize/user_fns.py (2)

25-27: Use ValueError for invalid population count.

Apply this diff:

     if init_model.nbr_populations() < 0:
-        raise RuntimeError("Number of populations cannot be negative")
+        raise ValueError("Number of populations cannot be negative")
     add_size_t("simulation/ions/nbrPopulations", init_model.nbr_populations())

11-11: Consider extracting duplicate addInitFunction retrieval.

The retrieval of addInitFunction is duplicated in both populate_electromag and populate_particles.

Consider refactoring:

def _get_add_init_function(sim):
    return getattr(pp, f"addInitFunction{sim.ndim}D")

def populate_electromag(sim):
    addInitFunction = _get_add_init_function(sim)
    # ... rest of function

def populate_particles(sim):
    addInitFunction = _get_add_init_function(sim)
    # ... rest of function
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)

94-106: Remove UB reinterpret_cast and guard empty SAMRAI boxes.

The old reinterpret_cast assumes SAMRAI’s box layout matches std::array<int,3>—that’s undefined behaviour and already raised earlier. We still also dereference boxes[0] without checking for an empty vector. Please copy component-wise and fail fast when no boxes are found.

-        std::size_t constexpr samrai_dim = 3; // always 3!
-        auto constexpr _to_std_array     = [](auto& i) {
-            return core::sized_array<GridLayout::dimension>(
-                *reinterpret_cast<std::array<int, samrai_dim> const*>(&i));
-        };
-
-        SAMRAI::tbox::HDFDatabase db{"db"};
-        db.open(filepath_);
-        auto const boxes = db.getDatabaseBoxVector(path);
-        return Box_t{_to_std_array(boxes[0].d_data.d_lo), _to_std_array(boxes[0].d_data.d_hi)};
+        constexpr std::size_t samrai_dim = 3; // always 3!
+        auto constexpr to_std_array       = [](auto const& vec) {
+            std::array<int, samrai_dim> full{};
+            for (std::size_t d = 0; d < samrai_dim; ++d)
+                full[d] = vec[static_cast<int>(d)];
+            return core::sized_array<GridLayout::dimension>(full);
+        };
+
+        SAMRAI::tbox::HDFDatabase db{"db"};
+        db.open(filepath_);
+        auto const boxes = db.getDatabaseBoxVector(path);
+        if (boxes.empty())
+            throw std::runtime_error("No SAMRAI boxes found at path: " + path);
+        auto const& lower = boxes[0].d_data.d_lo;
+        auto const& upper = boxes[0].d_data.d_hi;
+        return Box_t{to_std_array(lower), to_std_array(upper)};
src/amr/data/electromag/electromag_initializer.hpp (3)

32-32: Simplify the destructor.

The virtual keyword is redundant because the base class destructor is already virtual. Consider using override and = default.

Apply this diff:

-    virtual ~ElectromagUserFuncInitializer() {}
+    ~ElectromagUserFuncInitializer() override = default;

59-61: Remove unused member variable dict_.

The dict_ member is initialized but never used in the init method. This adds unnecessary memory overhead.

[Based on learnings]

Apply this diff:

     ElectromagSamraiH5Initializer(initializer::PHAREDict const& dict)
-        : dict_{dict}
     {
     }
     
     ...
     
-    initializer::PHAREDict const dict_;

Also applies to: 71-71


63-63: Simplify the destructor.

The virtual keyword is redundant because the base class destructor is already virtual. Consider using override and = default.

Apply this diff:

-    virtual ~ElectromagSamraiH5Initializer() {}
+    ~ElectromagSamraiH5Initializer() override = default;
src/amr/physical_models/hybrid_model.hpp (3)

151-152: Verify intentional memory management strategy.

Calling initializers_.release() transfers ownership without deletion, which typically causes a memory leak. If the intent is to free memory after initialization, use initializers_.reset() instead. If the initializers are needed later (e.g., for restarts), keep the unique_ptr.

Apply this diff if the intent is to free memory:

     resourcesManager->registerForRestarts(*this);
-    initializers_.release();
+    initializers_.reset();

Or remove the line entirely if initializers should remain available:

     resourcesManager->registerForRestarts(*this);
-    initializers_.release();

32-33: Rename _Initializers to avoid reserved identifier.

Names starting with an underscore followed by a capital letter are reserved in C++ and could lead to undefined behavior or conflicts. Consider renaming to Initializers or InitializerState.

Apply this diff to rename throughout the file:

-    struct _Initializers;
+    struct Initializers;
...
-    std::unique_ptr<_Initializers> initializers_;
+    std::unique_ptr<Initializers> initializers_;
...
-        , initializers_{std::make_unique<_Initializers>(dict, state)}
+        , initializers_{std::make_unique<Initializers>(dict, state)}
...
-struct HybridModel<GridLayoutT, Electromag, Ions, Electrons, AMR_Types, Grid_t>::_Initializers
+struct HybridModel<GridLayoutT, Electromag, Ions, Electrons, AMR_Types, Grid_t>::Initializers

241-241: Use .at() instead of operator[] to prevent undefined behavior.

operator[] can default-insert a null unique_ptr if the key doesn't exist, then dereferencing it causes undefined behavior. Use .at() which throws std::out_of_range on missing keys, or use .find() with an explicit check.

Apply this diff:

-    auto& particles(typename Ions::value_type& pop) { return *particle_pop_init[pop.name()]; }
+    auto& particles(typename Ions::value_type& pop) { return *particle_pop_init.at(pop.name()); }
🧹 Nitpick comments (20)
res/__tc/gcc/3_test_mpi.sh (1)

6-6: Remove duplicate MODULEPATH entry.

The MODULEPATH contains a duplicate /etc/scl/modulefiles entry, which can be simplified for clarity.

Apply this diff to deduplicate the path:

-export MODULEPATH=/etc/scl/modulefiles:/etc/scl/modulefiles:/usr/share/Modules/modulefiles:/etc/modulefiles:/usr/share/modulefiles
+export MODULEPATH=/etc/scl/modulefiles:/usr/share/Modules/modulefiles:/etc/modulefiles:/usr/share/modulefiles
res/__tc/nightly/2_test.sh (2)

6-6: Remove duplicate path in MODULEPATH.

The path /etc/scl/modulefiles appears twice in the MODULEPATH variable, which is redundant.

Apply this diff:

-export MODULEPATH=/etc/scl/modulefiles:/etc/scl/modulefiles:/usr/share/Modules/modulefiles:/etc/modulefiles:/usr/share/modulefiles
+export MODULEPATH=/etc/scl/modulefiles:/usr/share/Modules/modulefiles:/etc/modulefiles:/usr/share/modulefiles

18-18: Quote variable reference for safety.

While $N_CORES is validated as numeric, quoting the variable reference follows shell best practices and prevents potential word-splitting issues.

Apply this diff:

-  ctest -j$N_CORES --output-on-failure
+  ctest -j"$N_CORES" --output-on-failure
res/__tc/gcc/1_build.sh (1)

14-15: Move the SAMRAI subproject check before cmake to fail fast.

The comment indicates that the subproject presence is a critical precondition ("NO SUBPROJECT SAMRAI EXPECTED!"), but the check occurs after cmake has already run. If an unwanted subproject exists, cmake will have already consumed resources and time. Move this check earlier for fail-fast behavior.

Apply this diff to reorder the checks:

   mkdir build && cd build
+  # NO SUBPROJECT SAMRAI EXPECTED!
+  [ -d ../subprojects/samrai ] && exit 1
   cmake .. -G Ninja -Dasan=ON  \
           -DdevMode=ON -Dcppcheck=ON \
           -DCMAKE_BUILD_TYPE=Debug \
           -Dphare_configurator=ON -DSAMRAI_ROOT=/usr/local \
           -DCMAKE_CXX_FLAGS="-g3 -O3 -march=native -mtune=native -DPHARE_DIAG_DOUBLES=1"
-
-
-  # NO SUBPROJECT SAMRAI EXPECTED!
-  [ -d ../subprojects/samrai ] && exit 1
   ninja -j$N_CORES -v
res/__tc/nightly/0_config.sh (1)

1-6: Consider adding a comment header explaining the script's purpose.

The script collects diagnostic information (working directory, resource limits, compiler/linker versions), but its purpose within the nightly CI pipeline is not immediately clear. A brief comment explaining why this information is being gathered would improve maintainability for future developers.

Example header comment to add after the shebang:

 #!/bin/bash
+
+# Print diagnostic information about the build environment (cwd, limits, tool versions)
+# Used in nightly CI to troubleshoot and log system state at test startup.
+
 pwd
 set -ex
 ulimit -a
res/__tc/clang_samraisub/0_config.sh (1)

1-6: Add a shebang to make the script directly executable.

Shell scripts should include a shebang directive to specify the interpreter and enable direct execution via ./0_config.sh rather than requiring bash 0_config.sh.

Apply this change:

+#!/bin/bash
+
 pwd
 set -ex
 ulimit -a
res/__tc/clang_samraisub/1_build.sh (2)

1-15: Add a shebang to make the script directly executable.

Shell scripts should include a shebang directive to specify the interpreter and enable direct execution via ./1_build.sh rather than requiring bash 1_build.sh.

Apply this change:

+#!/bin/bash
+
 set -ex

13-13: The samrai subproject guard exits silently; consider adding a diagnostic message.

Line 13 exits with status 1 if ../subprojects/samrai exists, but provides no error message. This makes it difficult for users to diagnose the failure. If this constraint is intentional, add context.

Apply this change to clarify the error:

-  [ -d ../subprojects/samrai ] && exit 1
+  [ -d ../subprojects/samrai ] && echo "ERROR: samrai subproject directory should not exist" && exit 1
res/__tc/clang_samraisub/2_test.sh (1)

1-19: Add a shebang to make the script directly executable.

Shell scripts should include a shebang directive to specify the interpreter and enable direct execution via ./2_test.sh rather than requiring bash 2_test.sh.

Apply this change:

+#!/bin/bash
+
 set -ex
res/__tc/gcc_samraisub/2_test.sh (1)

5-7: Remove duplicate path in MODULEPATH.

The MODULEPATH on line 6 contains /etc/scl/modulefiles twice, which is redundant.

Apply this diff to clean up the redundancy:

-export MODULEPATH=/etc/scl/modulefiles:/etc/scl/modulefiles:/usr/share/Modules/modulefiles:/etc/modulefiles:/usr/share/modulefiles
+export MODULEPATH=/etc/scl/modulefiles:/usr/share/Modules/modulefiles:/etc/modulefiles:/usr/share/modulefiles

Based on learnings: PhilipDeegan prefers minimal and efficient code.

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

5-5: Remove unused include core/logger.hpp.

The logger include at line 5 has no usages in this file. Removing it will reduce compilation dependencies.

res/__tc/clang/2_test.sh (1)

21-22: Remove unused GCC_ASAN_PRELOAD variable.

The GCC_ASAN_PRELOAD variable is computed but never used. Only CLANG_ASAN_PRELOAD is referenced on line 26.

Apply this diff:

-GCC_ASAN_PRELOAD=$(gcc -print-file-name=libasan.so)
 CLANG_ASAN_PRELOAD=$(clang -print-file-name=libclang_rt.asan.so)
res/__tc/clang/3_test_mpi.sh (1)

21-22: Remove unused GCC_ASAN_PRELOAD variable.

The GCC_ASAN_PRELOAD variable is computed but never used. Only CLANG_ASAN_PRELOAD is referenced on line 30.

Apply this diff:

-GCC_ASAN_PRELOAD=$(gcc -print-file-name=libasan.so)
 CLANG_ASAN_PRELOAD=$(clang -print-file-name=libclang_rt.asan.so)
tests/simulator/test_init_from_restart.py (1)

39-46: Remove unused sim parameter.

The sim parameter is not used in the function body.

Apply this diff:

-def setup_model(sim):
+def setup_model():

Then update the call site on line 64:

-        setup_model(sim)
+        setup_model()
pyphare/pyphare/pharein/initialize/general.py (2)

75-79: Use ValueError for invalid input.

When validating input arguments, ValueError is more appropriate than RuntimeError for signaling invalid values.

Apply this diff:

     casted = int(val)
     if casted < 0:
-        raise RuntimeError("pyphare.__init__::add_size_t received negative value")
+        raise ValueError("pyphare.__init__::add_size_t received negative value")
     pp.add_size_t(path, casted)

135-135: Remove redundant int() cast.

The len() function already returns an integer, so the cast is unnecessary.

Apply this diff:

-            add_int("simulation/AMR/refinement/boxes/nbr_levels/", int(len(rb.keys())))
+            add_int("simulation/AMR/refinement/boxes/nbr_levels/", len(rb.keys()))
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)

9-9: Rename unused loop variable.

The loop variable pop is not used within the loop body.

Apply this diff:

-    for pop_index, pop in enumerate(init_model.populations):
+    for pop_index, _pop in enumerate(init_model.populations):
src/amr/data/electromag/electromag_initializer.hpp (3)

1-2: Adjust header guard to follow project conventions.

The header guard uses a reserved identifier pattern (leading underscore followed by capital letter). Based on learnings, the preferred pattern is PHARE_[PATH_WITH_UNDERSCORES]_HPP without leading or trailing underscores.

[Based on learnings]

Apply this diff:

-#ifndef _PHARE_AMR_DATA_ELECTROMAG_ELECTROMAG_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_ELECTROMAG_ELECTROMAG_INITIALIZER_HPP_
+#ifndef PHARE_AMR_DATA_ELECTROMAG_ELECTROMAG_INITIALIZER_HPP
+#define PHARE_AMR_DATA_ELECTROMAG_ELECTROMAG_INITIALIZER_HPP

And at the end:

-#endif // _PHARE_AMR_DATA_ELECTROMAG_ELECTROMAG_INITIALIZER_HPP_
+#endif // PHARE_AMR_DATA_ELECTROMAG_ELECTROMAG_INITIALIZER_HPP

43-48: Clarify whether this is documentation or dead code.

The commented-out section appears to document the HDF5 path structure. If this is intended as documentation, consider moving it to a proper comment block or documentation file. If it's dead code, remove it.


79-87: Consider explicit mode selection instead of heuristic.

The factory uses a heuristic (presence of "x_component") to distinguish between user functions and HDF5 restart. This works but may be fragile if configuration formats change. Consider adding an explicit mode key like dict["magnetic"]["initializer"]["type"] to make the selection clearer and more maintainable.

For example:

if (dict["magnetic"]["initializer"].contains("type") 
    && dict["magnetic"]["initializer"]["type"] == "hdf5")
    return std::make_unique<ElectromagSamraiH5Initializer<Electromag_t, GridLayout>>(dict);
else if (dict["magnetic"]["initializer"].contains("x_component"))
    return std::make_unique<ElectromagUserFuncInitializer<Electromag_t, GridLayout>>(dict);
else
    throw std::runtime_error("Unknown electromag initializer type");
📜 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 222a021 and 2a5f606.

📒 Files selected for processing (59)
  • pyphare/pyphare/pharein/__init__.py (3 hunks)
  • pyphare/pyphare/pharein/initialize/__init__.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/general.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/user_fns.py (1 hunks)
  • pyphare/pyphare/pharein/simulation.py (3 hunks)
  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (3 hunks)
  • pyphare/pyphare/pharesee/hierarchy/patchdata.py (1 hunks)
  • res/__tc/clang/0_config.sh (1 hunks)
  • res/__tc/clang/1_build.sh (1 hunks)
  • res/__tc/clang/2_test.sh (1 hunks)
  • res/__tc/clang/3_test_mpi.sh (1 hunks)
  • res/__tc/clang_samraisub/0_config.sh (1 hunks)
  • res/__tc/clang_samraisub/1_build.sh (1 hunks)
  • res/__tc/clang_samraisub/2_test.sh (1 hunks)
  • res/__tc/gcc/0_config.sh (1 hunks)
  • res/__tc/gcc/1_build.sh (1 hunks)
  • res/__tc/gcc/2_test.sh (1 hunks)
  • res/__tc/gcc/3_test_mpi.sh (1 hunks)
  • res/__tc/gcc_samraisub/0_config.sh (1 hunks)
  • res/__tc/gcc_samraisub/1_build.sh (1 hunks)
  • res/__tc/gcc_samraisub/2_test.sh (1 hunks)
  • res/__tc/nightly/0_config.sh (1 hunks)
  • res/__tc/nightly/1_build.sh (1 hunks)
  • res/__tc/nightly/2_test.sh (1 hunks)
  • res/__tc/nightly/3_test_mpi.sh (1 hunks)
  • res/cmake/test.cmake (1 hunks)
  • src/amr/CMakeLists.txt (1 hunks)
  • src/amr/data/electromag/electromag_initializer.hpp (1 hunks)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1 hunks)
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp (1 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/amr/level_initializer/hybrid_level_initializer.hpp (2 hunks)
  • src/amr/physical_models/hybrid_model.hpp (7 hunks)
  • src/core/CMakeLists.txt (0 hunks)
  • src/core/data/electromag/electromag.hpp (3 hunks)
  • src/core/data/field/initializers/field_user_initializer.hpp (2 hunks)
  • src/core/data/grid/gridlayout.hpp (3 hunks)
  • src/core/data/ions/ions.hpp (1 hunks)
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2 hunks)
  • src/core/data/ions/particle_initializers/particle_initializer.hpp (2 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (4 hunks)
  • src/core/data/vecfield/vecfield_initializer.hpp (1 hunks)
  • src/core/utilities/box/box.hpp (1 hunks)
  • src/core/utilities/types.hpp (1 hunks)
  • src/hdf5/detail/h5/group_scanner.hpp (1 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (4 hunks)
  • src/phare_core.hpp (0 hunks)
  • src/simulator/phare_types.hpp (1 hunks)
  • tests/amr/data/particles/initializer/CMakeLists.txt (1 hunks)
  • tests/amr/data/particles/initializer/test_main.cpp (3 hunks)
  • tests/amr/models/test_models.cpp (3 hunks)
  • tests/amr/tagging/test_tagging.cpp (2 hunks)
  • tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (2 hunks)
  • tests/core/numerics/ion_updater/CMakeLists.txt (1 hunks)
  • tests/core/numerics/ion_updater/test_updater.cpp (7 hunks)
  • tests/simulator/CMakeLists.txt (2 hunks)
  • tests/simulator/test_init_from_restart.py (1 hunks)
💤 Files with no reviewable changes (2)
  • src/core/CMakeLists.txt
  • src/phare_core.hpp
✅ Files skipped from review due to trivial changes (1)
  • src/core/data/field/initializers/field_user_initializer.hpp
🚧 Files skipped from review as they are similar to previous changes (11)
  • src/core/utilities/box/box.hpp
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
  • src/core/data/ions/ions.hpp
  • tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp
  • src/amr/CMakeLists.txt
  • src/simulator/phare_types.hpp
  • src/amr/level_initializer/hybrid_level_initializer.hpp
  • src/core/data/ions/particle_initializers/particle_initializer.hpp
  • tests/amr/models/test_models.cpp
  • res/cmake/test.cmake
  • pyphare/pyphare/pharesee/hierarchy/patchdata.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/core/data/vecfield/vecfield_initializer.hpp
  • src/core/utilities/types.hpp
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp
  • src/hdf5/detail/h5/group_scanner.hpp
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp
  • src/hdf5/detail/h5/h5_file.hpp
  • src/amr/physical_models/hybrid_model.hpp
  • src/amr/data/electromag/electromag_initializer.hpp
  • src/core/data/electromag/electromag.hpp
  • src/core/data/grid/gridlayout.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
🧠 Learnings (13)
📓 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-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:

  • res/__tc/gcc_samraisub/1_build.sh
  • res/__tc/gcc/1_build.sh
  • tests/simulator/CMakeLists.txt
  • res/__tc/nightly/1_build.sh
  • tests/amr/data/particles/initializer/CMakeLists.txt
  • tests/core/numerics/ion_updater/CMakeLists.txt
  • res/__tc/clang_samraisub/1_build.sh
📚 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:

  • res/__tc/nightly/3_test_mpi.sh
  • tests/simulator/CMakeLists.txt
  • res/__tc/nightly/1_build.sh
  • tests/amr/data/particles/initializer/CMakeLists.txt
  • tests/core/numerics/ion_updater/CMakeLists.txt
  • res/__tc/gcc/3_test_mpi.sh
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 892
File: tools/data/generate.sh:1-8
Timestamp: 2024-10-09T08:32:15.667Z
Learning: In `tools/data/generate.sh`, the script sets `$CWD` to `tools/data` and changes directory to `$CWD`, so scripts are run relative to that directory.

Applied to files:

  • res/__tc/gcc_samraisub/0_config.sh
  • res/__tc/clang_samraisub/0_config.sh
  • res/__tc/clang/0_config.sh
  • res/__tc/nightly/0_config.sh
📚 Learning: 2024-07-23T09:51:46.761Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 859
File: pyphare/pyphare/pharesee/hierarchy/fromh5.py:27-34
Timestamp: 2024-07-23T09:51:46.761Z
Learning: Mutable default arguments like lists or dictionaries can lead to unexpected behavior because the same instance of the mutable object is shared across all calls to the function. It is a good practice to use `None` as the default value and initialize the mutable object inside the function.

Applied to files:

  • pyphare/pyphare/pharein/simulation.py
📚 Learning: 2024-10-18T13:23:32.074Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 910
File: pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py:7-7
Timestamp: 2024-10-18T13:23:32.074Z
Learning: In the `pyphare.pharesee.hierarchy` module, importing `PatchHierarchy` and `format_timestamp` from `hierarchy.py` into `hierarchy_utils.py` is acceptable as long as `hierarchy.py` does not import `hierarchy_utils.py`, thereby avoiding a cyclic import.

Applied to files:

  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py
  • tests/simulator/test_init_from_restart.py
  • pyphare/pyphare/pharein/initialize/__init__.py
📚 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:

  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp
  • src/hdf5/detail/h5/h5_file.hpp
📚 Learning: 2024-09-04T13:45:43.884Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: tests/simulator/test_samrai_restarts_parser.py:86-97
Timestamp: 2024-09-04T13:45:43.884Z
Learning: Do not comment on pull requests that are in draft status.

Applied to files:

  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py
📚 Learning: 2024-09-05T17:02:58.784Z
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.

Applied to files:

  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py
📚 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/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp
  • tests/core/numerics/ion_updater/test_updater.cpp
📚 Learning: 2024-10-09T08:32:15.667Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/amr/level_initializer/hybrid_level_initializer.hpp:44-49
Timestamp: 2024-10-09T08:32:15.667Z
Learning: In this codebase, when a derived class method overrides a virtual function using `override`, and there are no further subclasses, the `virtual` keyword is not required in the subclass.

Applied to files:

  • src/amr/data/electromag/electromag_initializer.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/data/electromag/electromag.hpp
📚 Learning: 2024-09-17T13:33:47.475Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/core/data/grid/gridlayout.hpp:805-821
Timestamp: 2024-09-17T13:33:47.475Z
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 (19)
tests/amr/tagging/test_tagging.cpp (2)
src/amr/data/electromag/electromag_initializer.hpp (4)
  • em (34-37)
  • em (34-34)
  • em (65-69)
  • em (65-65)
tests/amr/models/test_models.cpp (2)
  • createDict (58-132)
  • createDict (58-58)
src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)
  • particles (36-37)
src/core/data/ions/particle_initializers/particle_initializer.hpp (1)
  • particles (14-15)
pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (2)
pyphare/pyphare/pharesee/hierarchy/patchdata.py (1)
  • FieldData (32-194)
pyphare/pyphare/core/phare_utilities.py (1)
  • assert_fp_any_all_close (141-142)
pyphare/pyphare/pharein/__init__.py (4)
pyphare/pyphare/pharein/simulation.py (1)
  • Simulation (754-1088)
pyphare/pyphare/pharein/initialize/general.py (1)
  • populateDict (89-318)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)
  • populateDict (6-16)
pyphare/pyphare/pharein/initialize/user_fns.py (1)
  • populateDict (5-7)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • dir (50-51)
pyphare/pyphare/pharein/initialize/general.py (5)
pyphare/pyphare/core/phare_utilities.py (1)
  • is_scalar (54-55)
pyphare/pyphare/pharein/load_balancer.py (1)
  • LoadBalancer (9-57)
pyphare/pyphare/pharein/simulation.py (4)
  • serialize (1094-1103)
  • deserialize (1106-1110)
  • restart_file_path (999-1001)
  • is_restartable_compared_to (1049-1057)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_etc_lib (12-15)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)
  • populateDict (6-16)
src/hdf5/detail/h5/group_scanner.hpp (1)
src/hdf5/detail/h5/h5_file.hpp (6)
  • path (274-280)
  • path (274-274)
  • path (282-287)
  • path (282-282)
  • contains (260-263)
  • contains (260-260)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (4)
src/core/data/ions/particle_initializers/particle_initializer.hpp (1)
  • particles (14-15)
src/core/utilities/types.hpp (2)
  • apply (97-100)
  • apply (97-97)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • i (44-48)
src/core/utilities/box/box.hpp (5)
  • isIn (218-245)
  • isIn (218-218)
  • isIn (248-252)
  • isIn (248-249)
  • isIn (258-258)
tests/simulator/test_init_from_restart.py (7)
pyphare/pyphare/pharesee/hierarchy/patchdata.py (2)
  • FieldData (32-194)
  • ParticleData (197-240)
pyphare/pyphare/pharesee/hierarchy/fromh5.py (1)
  • get_all_available_quantities_from_h5 (27-33)
pyphare/pyphare/pharesee/hierarchy/hierarchy.py (1)
  • format_timestamp (13-16)
pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (2)
  • single_patch_for_LO (662-705)
  • hierarchy_compare (618-659)
tests/simulator/__init__.py (2)
  • SimulatorTest (200-266)
  • register_diag_dir_for_cleanup (233-234)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-62)
pyphare/pyphare/simulator/simulator.py (1)
  • reset (258-269)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (2)
src/core/utilities/types.hpp (2)
  • sized_array (133-147)
  • sized_array (133-134)
src/hdf5/detail/h5/group_scanner.hpp (2)
  • group (35-61)
  • group (35-35)
tests/amr/data/particles/initializer/test_main.cpp (1)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
tests/core/numerics/ion_updater/test_updater.cpp (2)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
src/amr/physical_models/hybrid_model.hpp (2)
  • pop (241-241)
  • pop (241-241)
src/amr/physical_models/hybrid_model.hpp (1)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
src/amr/data/electromag/electromag_initializer.hpp (1)
tests/amr/tagging/test_tagging.cpp (2)
  • em (189-193)
  • em (189-189)
src/core/data/electromag/electromag.hpp (2)
src/diagnostic/diagnostic_model_view.hpp (1)
  • dimension (30-60)
tests/core/data/electromag/test_electromag_fixtures.hpp (1)
  • E (19-23)
src/core/data/grid/gridlayout.hpp (3)
pyphare/pyphare/core/gridlayout.py (2)
  • physicalStartIndex (262-264)
  • AMRToLocal (330-334)
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 (256-259)
  • product (256-256)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (3)
pyphare/pyphare/pharein/initialize/general.py (2)
  • add_int (63-64)
  • populateDict (89-318)
pyphare/pyphare/pharein/__init__.py (1)
  • populateDict (71-81)
pyphare/pyphare/pharein/initialize/user_fns.py (1)
  • populateDict (5-7)
pyphare/pyphare/pharein/initialize/user_fns.py (4)
pyphare/pyphare/pharein/initialize/general.py (5)
  • add_double (71-72)
  • add_int (63-64)
  • add_size_t (75-79)
  • fn_wrapper (50-59)
  • populateDict (89-318)
pyphare/pyphare/pharein/__init__.py (1)
  • populateDict (71-81)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)
  • populateDict (6-16)
pyphare/pyphare/core/gridlayout.py (1)
  • ndim (221-222)
🪛 Ruff (0.14.3)
pyphare/pyphare/pharein/simulation.py

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

(TRY003)

pyphare/pyphare/pharein/initialize/general.py

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

(TRY003)


135-135: Value being cast to int is already an integer

Remove unnecessary int call

(RUF046)


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

(TRY003)


273-275: Avoid specifying long messages outside the exception class

(TRY003)


281-283: Avoid specifying long messages outside the exception class

(TRY003)


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

(TRY003)

tests/simulator/test_init_from_restart.py

39-39: Unused function argument: sim

(ARG001)

pyphare/pyphare/pharein/initialize/__init__.py

5-9: __all__ is not sorted

Apply an isort-style sorting to __all__

(RUF022)

pyphare/pyphare/pharein/initialize/samrai_hdf5.py

9-9: Loop control variable pop not used within loop body

Rename unused pop to _pop

(B007)

pyphare/pyphare/pharein/initialize/user_fns.py

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

(TRY003)

🪛 Shellcheck (0.11.0)
res/__tc/gcc_samraisub/1_build.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/gcc_samraisub/2_test.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/nightly/3_test_mpi.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/gcc/1_build.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/gcc_samraisub/0_config.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/clang/2_test.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)


[warning] 21-21: GCC_ASAN_PRELOAD appears unused. Verify use (or export if used externally).

(SC2034)

res/__tc/clang_samraisub/0_config.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/clang/1_build.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/nightly/1_build.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/clang_samraisub/2_test.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/gcc/3_test_mpi.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/gcc/2_test.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/gcc/0_config.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/clang/0_config.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/clang/3_test_mpi.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)


[warning] 21-21: GCC_ASAN_PRELOAD appears unused. Verify use (or export if used externally).

(SC2034)

res/__tc/clang_samraisub/1_build.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/nightly/2_test.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

res/__tc/nightly/0_config.sh

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

⏰ 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 (ubuntu-latest, gcc)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (macos-latest)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (macos-13)
  • GitHub Check: Analyze (cpp)
  • GitHub Check: Analyze (python)

Comment on lines 1 to 6
pwd
set -ex
ulimit -a
clang -v
ldd --version
ld -v
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add shebang to specify shell interpreter.

Shell scripts should begin with a shebang line to ensure they execute with the correct interpreter.

Apply this diff:

+#!/usr/bin/env bash
 pwd
 set -ex
 ulimit -a
📝 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
pwd
set -ex
ulimit -a
clang -v
ldd --version
ld -v
#!/usr/bin/env bash
pwd
set -ex
ulimit -a
clang -v
ldd --version
ld -v
🧰 Tools
🪛 Shellcheck (0.11.0)

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

🤖 Prompt for AI Agents
In res/__tc/clang/0_config.sh around lines 1 to 6, the script lacks a shebang so
the interpreter is not guaranteed; add a shebang as the very first line (for
portability use /usr/bin/env bash or /bin/bash) so the script runs with the
intended shell, then keep the existing lines (pwd, set -ex, ulimit -a, clang -v,
ldd --version, ld -v) unchanged.

Comment on lines 1 to 3
set -ex

[ -z "$N_CORES" ] && echo "N_CORES not set: error" && exit 1
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add shebang to specify shell interpreter.

Shell scripts should begin with a shebang line to ensure they execute with the correct interpreter.

Apply this diff:

+#!/usr/bin/env bash
 set -ex
 
📝 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
set -ex
[ -z "$N_CORES" ] && echo "N_CORES not set: error" && exit 1
#!/usr/bin/env bash
set -ex
[ -z "$N_CORES" ] && echo "N_CORES not set: error" && exit 1
🧰 Tools
🪛 Shellcheck (0.11.0)

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

🤖 Prompt for AI Agents
In res/__tc/clang/1_build.sh around lines 1 to 3, the script is missing a
shebang so the interpreter is ambiguous; add a shebang as the very first line
(for example "#!/usr/bin/env bash") so the script runs with the intended shell,
leaving the existing set -ex and N_CORES check unchanged.

Comment on lines 1 to 3
set -ex
pwd
ulimit -a
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add shebang to specify shell interpreter.

Shell scripts should begin with a shebang line to ensure they execute with the correct interpreter.

Apply this diff:

+#!/usr/bin/env bash
 set -ex
 pwd
📝 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
set -ex
pwd
ulimit -a
#!/usr/bin/env bash
set -ex
pwd
ulimit -a
🧰 Tools
🪛 Shellcheck (0.11.0)

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

🤖 Prompt for AI Agents
In res/__tc/clang/2_test.sh around lines 1 to 3, the script lacks a shebang;
insert a shebang as the very first line (for example "#!/usr/bin/env bash") and
ensure the existing lines (set -ex, pwd, ulimit -a) follow unchanged so the
script runs with the intended shell interpreter.

Comment on lines 1 to 3
set -ex
pwd
ulimit -a
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add shebang to specify shell interpreter.

Shell scripts should begin with a shebang line to ensure they execute with the correct interpreter.

Apply this diff:

+#!/usr/bin/env bash
 set -ex
 pwd
📝 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
set -ex
pwd
ulimit -a
#!/usr/bin/env bash
set -ex
pwd
ulimit -a
🧰 Tools
🪛 Shellcheck (0.11.0)

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

🤖 Prompt for AI Agents
In res/__tc/clang/3_test_mpi.sh around lines 1 to 3, the script lacks a shebang
so its interpreter is not guaranteed; add an appropriate shebang as the first
line (for example #!/bin/bash or #!/usr/bin/env bash) so the script runs with
the intended shell, keeping the rest of the file unchanged.

@@ -0,0 +1,6 @@
pwd
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

Add a shebang to enable direct execution.

The script is missing a shebang (#!/bin/bash or #!/bin/sh). Without it, the script cannot be directly executed; it must be explicitly sourced or invoked with an interpreter. This prevents the script from being executable and discoverable as a shell script.

Add a shebang at the beginning of the file:

+#!/bin/bash
 pwd
 set -ex
 ulimit -a
📝 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
pwd
#!/bin/bash
pwd
set -ex
ulimit -a
🧰 Tools
🪛 Shellcheck (0.11.0)

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

🤖 Prompt for AI Agents
In res/__tc/nightly/0_config.sh at line 1, the file lacks a shebang so it cannot
be executed directly; add a POSIX-compatible shebang as the very first line (for
example #!/bin/sh or #!/bin/bash depending on needed features) and save the
current "pwd" line after it, then make the file executable (chmod +x) so it can
be run directly.

@@ -0,0 +1,14 @@
set -ex
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

Add shebang to specify target shell.

The script lacks a shebang, making the target shell ambiguous. This directly causes the Shellcheck warning SC2148 and can lead to inconsistent behavior across different environments.

Apply this diff to add the shebang:

+#!/bin/bash
 set -ex
📝 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
set -ex
#!/bin/bash
set -ex
🧰 Tools
🪛 Shellcheck (0.11.0)

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

🤖 Prompt for AI Agents
In res/__tc/nightly/1_build.sh at line 1, the script is missing a shebang which
makes the target shell ambiguous and triggers ShellCheck SC2148; add a proper
shebang as the first line (for example "#!/usr/bin/env bash") so the script
always runs under bash, keep the existing "set -ex" on the next line, and ensure
the file remains executable.

[ -z "$N_CORES" ] && echo "N_CORES not set: error" && exit 1

(
mkdir build && cd build
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

Handle pre-existing build directory.

The mkdir build command will fail if the build directory already exists from a previous run. Although set -e will catch and exit on the error, this creates a friction point for re-running the script locally.

Consider using mkdir -p to allow re-runs, or explicitly clean the directory first:

- mkdir build && cd build
+ rm -rf build && mkdir build && cd build

Alternatively, if build directory persistence is intentional for the nightly workflow, add a comment clarifying this.

📝 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
mkdir build && cd build
rm -rf build && mkdir build && cd build
🤖 Prompt for AI Agents
In res/__tc/nightly/1_build.sh around line 6, the script uses "mkdir build && cd
build" which will fail if the build directory already exists; update the command
to create the directory idempotently (e.g., use mkdir -p build before cd build)
or, if you intend to recreate the directory each run, explicitly remove/clean it
first (e.g., rm -rf build && mkdir build) and add a brief comment explaining the
chosen behavior so re-runs behave predictably.

@@ -0,0 +1,19 @@
set -ex
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

Add shebang declaration to specify bash interpreter.

The script uses bash-specific features (set -ex, variable expansion) but lacks a shebang. This is required to explicitly specify the interpreter and is flagged by Shellcheck (SC2148).

Apply this diff:

+#!/bin/bash
 set -ex
📝 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
set -ex
#!/bin/bash
set -ex
🧰 Tools
🪛 Shellcheck (0.11.0)

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

🤖 Prompt for AI Agents
In res/__tc/nightly/2_test.sh around line 1, the script lacks a shebang so the
bash-specific "set -ex" may be executed by the wrong shell; add a bash shebang
as the first line (e.g. #!/usr/bin/env bash) so the file is explicitly run with
bash (place it above the existing set -ex line).

@@ -0,0 +1,24 @@
set -ex
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

Add shebang directive.

The script uses bash-specific constructs (e.g., set -ex, subshell syntax) but lacks a shebang. This can cause execution issues in CI/CD systems and violates standard shell script conventions.

Apply this diff:

+#!/bin/bash
+
 set -ex
📝 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
set -ex
#!/bin/bash
set -ex
🧰 Tools
🪛 Shellcheck (0.11.0)

[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.

(SC2148)

🤖 Prompt for AI Agents
In res/__tc/nightly/3_test_mpi.sh at line 1, the script lacks a shebang even
though it uses bash-specific constructs; add a bash shebang as the very first
line (e.g. #!/usr/bin/env bash) so the script is executed with bash in CI/CD and
local runs, ensuring no blank lines precede it and commit the change.

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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)

82-89: Correct magnetic basis component lookup.

Line 83–84 assign the Y and Z components of magneticField from "magnetic_x", so magnetic initializers in the magnetic basis ignore the user-provided Y/Z functions and reuse X instead. That yields the wrong field orientation at runtime. Pull the proper "magnetic_y" and "magnetic_z" entries instead.

Use this fix:

-                    magneticField[1] = dict["magnetic_x"].template to<FunctionType>();
-                    magneticField[2] = dict["magnetic_x"].template to<FunctionType>();
+                    magneticField[1] = dict["magnetic_y"].template to<FunctionType>();
+                    magneticField[2] = dict["magnetic_z"].template to<FunctionType>();
♻️ Duplicate comments (12)
src/core/data/ndarray/ndarray_vector.hpp (4)

38-71: Fix potential integer overflow in index calculations.

The multiplication of nCells elements (which are uint32_t) can overflow before conversion to size_t. This security issue was previously flagged by the code scanner and past reviews.

Apply this diff to cast operands before multiplication:

         if constexpr (dim == 2)
         {
             auto i = std::get<0>(params);
             auto j = std::get<1>(params);
 
             if constexpr (c_ordering)
-                return j + i * nCells[1];
+                return j + static_cast<std::size_t>(i) * static_cast<std::size_t>(nCells[1]);
             else
-                return i + j * nCells[0];
+                return i + static_cast<std::size_t>(j) * static_cast<std::size_t>(nCells[0]);
         }
 
         if constexpr (dim == 3)
         {
             auto i = std::get<0>(params);
             auto j = std::get<1>(params);
             auto k = std::get<2>(params);
 
             if constexpr (c_ordering)
-                return k + j * nCells[2] + i * nCells[1] * nCells[2];
+            {
+                auto const dim1 = static_cast<std::size_t>(nCells[1]);
+                auto const dim2 = static_cast<std::size_t>(nCells[2]);
+                return k + static_cast<std::size_t>(j) * dim2 + 
+                       static_cast<std::size_t>(i) * dim1 * dim2;
+            }
             else
-                return i + j * nCells[0] + k * nCells[1] * nCells[0];
+            {
+                auto const dim0 = static_cast<std::size_t>(nCells[0]);
+                auto const dim1 = static_cast<std::size_t>(nCells[1]);
+                return i + static_cast<std::size_t>(j) * dim0 + 
+                       static_cast<std::size_t>(k) * dim1 * dim0;
+            }
         }

24-36: Add input bounds validation.

The idx function lacks validation that the input indexes are within the valid range [0, nCells[i]) for each dimension. Invalid indexes will silently compute an out-of-bounds offset, leading to undefined behavior when accessing the data array.

Apply this diff to add bounds checking:

 NO_DISCARD static std::size_t idx(NCells const& nCells, Indexes<Index, dim> const& indexes)
 {
+    for (std::size_t i = 0; i < dim; ++i) {
+        if (indexes[i] >= nCells[i]) {
+            throw std::out_of_range("Index out of bounds in NdArrayViewer::idx");
+        }
+    }
+
     if constexpr (dim == 1)
         return idx(nCells, indexes[0]);

74-79: Add bounds checking to prevent out-of-bounds access.

This new at overload directly indexes into the data array without any bounds validation, relying entirely on the idx function. Since idx does not validate bounds (as flagged above), out-of-bounds access can occur silently in release builds.

Once bounds checking is added to the idx function, this overload will be safe. Alternatively, add an assert here as well:

 template<typename NCells, typename... Indexes>
 NO_DISCARD static DataType const& at(DataType const* data, NCells const& nCells,
                                      Indexes const&... indexes)
 {
-    return data[idx(nCells, indexes...)];
+    auto const i = idx(nCells, indexes...);
+    assert(i < product(nCells, std::size_t{1}));
+    return data[i];
 }

86-88: Consider runtime bounds checking for production safety.

The assert on line 87 only provides bounds checking in debug builds and is disabled in release builds. Out-of-bounds access in production would result in undefined behavior.

If you prefer to keep the assert for performance reasons in release builds, consider adding a comment explaining this trade-off. Otherwise, replace the assert with runtime checking:

     auto const i = idx(nCells, indexes);
-    assert(i < product(nCells, std::size_t{1})); // debug bounds check
+    if (i >= product(nCells, std::size_t{1})) {
+        throw std::out_of_range("Index out of bounds in NdArrayViewer::at");
+    }
     return data[i];
tests/simulator/test_init_from_restart.py (3)

42-42: Verify alpha particle charge value.

Alpha particles typically have a charge of +2, but the code sets charge: 1. Please confirm this is intentional for the test scenario.


1-1: Remove unused imports.

Several imports are unused and should be removed to keep the code clean:

  • Line 1: sys
  • Line 4: subprocess
  • Line 15: test_restarts

Apply this diff:

-import sys
 import copy
 import unittest
-import subprocess
 import numpy as np
 import pyphare.pharein as ph
 from pathlib import Path

 from pyphare.simulator.simulator import Simulator
 from pyphare.pharesee.hierarchy.patchdata import FieldData, ParticleData
 from pyphare.pharesee.hierarchy.fromh5 import get_all_available_quantities_from_h5
 from pyphare.pharesee.hierarchy.hierarchy import format_timestamp
 from pyphare.pharesee.hierarchy.hierarchy_utils import single_patch_for_LO
 from pyphare.pharesee.hierarchy.hierarchy_utils import hierarchy_compare
-from tests.simulator import SimulatorTest, test_restarts
+from tests.simulator import SimulatorTest
 from tests.diagnostic import dump_all_diags

Also applies to: 4-4, 15-15


10-10: Remove unused imports from patchdata.

FieldData and ParticleData are imported but never used in this test file.

Apply this diff:

-from pyphare.pharesee.hierarchy.patchdata import FieldData, ParticleData
 from pyphare.pharesee.hierarchy.fromh5 import get_all_available_quantities_from_h5
pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (1)

592-602: Guard against IndexError when failed list is empty.

Line 601 accesses self.failed[0][0] without checking if the list is empty, which will raise an IndexError.

Apply this diff to add a guard:

 def __repr__(self):
     strs = []
     for msg, ref, cmp in self:
         strs.append(msg)
         try:
             if type(ref) is FieldData:
                 phut.assert_fp_any_all_close(ref[:], cmp[:], atol=1e-16)
         except AssertionError as e:
             strs.append(e)
-    strs.append(self.failed[0][0])
+    if self.failed:
+        strs.append(self.failed[0][0])
     return os.linesep.join(strs)
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1)

48-65: Validate HDF5 payload size before exposing the view

We derive a ghosted box shape and immediately build a view over the raw vector. If the dataset is truncated or mismatched, the view happily indexes past data and we hit UB while copying. Please compute the expected volume and fail fast when it diverges so restart corruption doesn’t crash the process.

Apply this diff inside load:

-        auto const data_view   = core::make_array_view(data.data(), *lcl_src_gbox.shape());
+        auto const shape = *lcl_src_gbox.shape();
+        std::size_t expected_size = 1;
+        for (auto extent : shape)
+            expected_size *= extent;
+        if (data.size() != expected_size)
+        {
+            throw std::runtime_error(
+                "HDF5 dataset size mismatch for " + field.name() + ": expected "
+                + std::to_string(expected_size) + " values, got "
+                + std::to_string(data.size()));
+        }
+
+        auto const data_view = core::make_array_view(data.data(), shape);
pyphare/pyphare/pharein/simulation.py (1)

533-543: Do not auto-create SAMRAI init directories

check_init_options calls check_directory, which silently creates missing paths. For read-only SAMRAI/HDF5 restarts, a typo should raise immediately; auto-creating the directory leaves an empty tree and the real failure surfaces much later when we try to open the datasets. We also never verify the top-level init_options["dir"], so invalid paths slip through. Please require a recognised format and ensure both the top-level and nested directories already exist with read/execute access.

Apply these diffs to add a read-only helper and tighten validation:

 def check_directory(directory, key):
     directory = directory.rstrip(os.path.sep)  # trim trailing slashes
@@
     except FileExistsError:
         raise ValueError("Creation of the directory %s failed" % directory)

     return directory
+
+
+def check_existing_directory(directory, key):
+    directory = directory.rstrip(os.path.sep)
+    if not os.path.exists(directory) or not os.path.isdir(directory):
+        raise ValueError(f"Error: Simulation {key} dir does not exist or is not a directory.")
+    if not os.access(directory, os.R_OK | os.X_OK):
+        raise ValueError(
+            f"Directory ({directory}) for {key} lacks read/execute permissions"
+        )
+    return directory
 def check_init_options(**kwargs):
     """Advanced options to initialize from SAMRAI HDF5 files"""

-    formats = ["samraih5"]
-    init_options = kwargs.get("init_options", None)
-
-    if init_options is not None and "format" in init_options:
-        if init_options["format"] not in formats:
-            raise ValueError("Error - init_options format is invalid")
-        if "options" in init_options and "dir" in init_options["options"]:
-            init_options["options"]["dir"] = check_directory(
-                init_options["options"]["dir"], "init_options"
-            )
-
-    return init_options
+    formats = ["samraih5"]
+    init_options = kwargs.get("init_options")
+
+    if init_options is None:
+        return None
+
+    if init_options.get("format") not in formats:
+        raise ValueError(
+            f"Error - init_options format is invalid (expected one of: {formats})"
+        )
+
+    if "dir" in init_options:
+        init_options["dir"] = check_existing_directory(
+            init_options["dir"], "init_options"
+        )
+
+    if "options" in init_options and "dir" in init_options["options"]:
+        init_options["options"]["dir"] = check_existing_directory(
+            init_options["options"]["dir"], "init_options"
+        )
+
+    return init_options
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)

102-106: Handle missing box metadata before indexing

SAMRAI::tbox::HDFDatabase::getDatabaseBoxVector can legitimately return an empty collection. Line 104 then does boxes[0], which is undefined behaviour and will crash. Guard the empty case and fail fast with a clear error (don’t forget to include <stdexcept> for the throw).

         SAMRAI::tbox::HDFDatabase db{"db"};
         db.open(filepath_);
         auto const boxes = db.getDatabaseBoxVector(path);
+        if (boxes.empty())
+        {
+            throw std::runtime_error("Missing SAMRAI box metadata at \"" + path + "\" in " + filepath_);
+        }
         return Box_t{_to_std_array(boxes[0].d_data.d_lo), _to_std_array(boxes[0].d_data.d_hi)};
src/amr/physical_models/hybrid_model.hpp (1)

146-152: Do not release() the _Initializers helper.

Line 151 calls initializers_.release(), which both leaks the _Initializers instance and leaves initializers_ null. The very next initialize() invocation (or any use of initializers()) will dereference that null pointer and crash. Please drop the release() (or otherwise keep the object alive) so the cached initializers remain valid across calls.

-    initializers_.release();
+    // keep the helper alive for subsequent initialize() calls
🧹 Nitpick comments (5)
src/core/utilities/box/box.hpp (1)

191-194: LGTM! Consider adding NO_DISCARD for consistency.

The equality operator implementation is correct and consistent with the existing operator!=. Both properly compare the box pointer and index.

For consistency with the Box::operator== at line 51, consider adding the NO_DISCARD attribute:

-    bool operator==(box_iterator const& other) const
+    NO_DISCARD bool operator==(box_iterator const& other) const
     {
         return box_ == other.box_ and index_ == other.index_;
     }
src/core/data/grid/gridlayout.hpp (1)

1259-1271: Effective dimension-agnostic refactoring.

The refactored _BoxFor eliminates code duplication by using an array-based approach. The loop correctly accesses only the first dimension elements of the directions array, making it safe for all dimensionalities.

Optionally, consider making the directions array static constexpr for clarity:

-            constexpr auto directions = std::array{Direction::X, Direction::Y, Direction::Z};
+            static constexpr auto directions = std::array{Direction::X, Direction::Y, Direction::Z};

This emphasizes that it's a compile-time constant shared across invocations, though the compiler will likely optimize this either way.

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

5-5: Remove unused include.

The core/logger.hpp header is included but not used in this file.

Apply this diff:

-#include "core/logger.hpp"
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)

9-9: Rename unused loop variable.

The loop variable pop is not used within the loop body. Only pop_index is needed.

Apply this diff:

-    for pop_index, pop in enumerate(init_model.populations):
+    for pop_index, _pop in enumerate(init_model.populations):
pyphare/pyphare/pharein/initialize/__init__.py (1)

5-9: Consider alphabetically sorting __all__.

The __all__ list could be sorted alphabetically for consistency with Python conventions.

Apply this diff:

 __all__ = [
     "general",
-    "user_fns",
     "samrai_hdf5",
+    "user_fns",
 ]
📜 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 2a5f606 and 4fb2794.

📒 Files selected for processing (41)
  • pyphare/pyphare/pharein/__init__.py (3 hunks)
  • pyphare/pyphare/pharein/initialize/__init__.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/general.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1 hunks)
  • pyphare/pyphare/pharein/initialize/user_fns.py (1 hunks)
  • pyphare/pyphare/pharein/simulation.py (3 hunks)
  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (3 hunks)
  • pyphare/pyphare/pharesee/hierarchy/patchdata.py (1 hunks)
  • res/cmake/test.cmake (1 hunks)
  • src/amr/CMakeLists.txt (1 hunks)
  • src/amr/data/electromag/electromag_initializer.hpp (1 hunks)
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (1 hunks)
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp (1 hunks)
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp (3 hunks)
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1 hunks)
  • src/amr/level_initializer/hybrid_level_initializer.hpp (2 hunks)
  • src/amr/physical_models/hybrid_model.hpp (7 hunks)
  • src/core/CMakeLists.txt (0 hunks)
  • src/core/data/electromag/electromag.hpp (3 hunks)
  • src/core/data/field/initializers/field_user_initializer.hpp (2 hunks)
  • src/core/data/grid/gridlayout.hpp (3 hunks)
  • src/core/data/ions/ions.hpp (1 hunks)
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2 hunks)
  • src/core/data/ions/particle_initializers/particle_initializer.hpp (2 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (4 hunks)
  • src/core/data/vecfield/vecfield_initializer.hpp (1 hunks)
  • src/core/utilities/box/box.hpp (1 hunks)
  • src/core/utilities/types.hpp (1 hunks)
  • src/hdf5/detail/h5/group_scanner.hpp (1 hunks)
  • src/hdf5/detail/h5/h5_file.hpp (4 hunks)
  • src/phare_core.hpp (0 hunks)
  • src/simulator/phare_types.hpp (1 hunks)
  • tests/amr/data/particles/initializer/CMakeLists.txt (1 hunks)
  • tests/amr/data/particles/initializer/test_main.cpp (3 hunks)
  • tests/amr/models/test_models.cpp (3 hunks)
  • tests/amr/tagging/test_tagging.cpp (2 hunks)
  • tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (2 hunks)
  • tests/core/numerics/ion_updater/CMakeLists.txt (1 hunks)
  • tests/core/numerics/ion_updater/test_updater.cpp (7 hunks)
  • tests/simulator/CMakeLists.txt (2 hunks)
  • tests/simulator/test_init_from_restart.py (1 hunks)
💤 Files with no reviewable changes (2)
  • src/core/CMakeLists.txt
  • src/phare_core.hpp
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/core/data/field/initializers/field_user_initializer.hpp
  • tests/amr/models/test_models.cpp
  • src/amr/data/electromag/electromag_initializer.hpp
  • tests/simulator/CMakeLists.txt
  • src/core/data/ions/ions.hpp
  • src/core/utilities/types.hpp
  • tests/amr/data/particles/initializer/CMakeLists.txt
  • tests/amr/tagging/test_tagging.cpp
  • tests/amr/data/particles/initializer/test_main.cpp
🧰 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/simulator/phare_types.hpp
  • src/core/data/ions/particle_initializers/particle_initializer.hpp
  • src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp
  • src/core/data/vecfield/vecfield_initializer.hpp
  • src/core/data/electromag/electromag.hpp
  • src/hdf5/detail/h5/group_scanner.hpp
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
  • src/amr/level_initializer/hybrid_level_initializer.hpp
  • src/amr/data/particles/initializers/particle_initializer_factory.hpp
  • src/core/data/grid/gridlayout.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
  • src/hdf5/detail/h5/h5_file.hpp
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp
  • src/core/utilities/box/box.hpp
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
  • src/amr/physical_models/hybrid_model.hpp
🧠 Learnings (15)
📓 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-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/amr/CMakeLists.txt
  • tests/core/numerics/ion_updater/CMakeLists.txt
📚 Learning: 2025-01-16T10:45:48.912Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 943
File: res/cmake/dep/highfive.cmake:7-7
Timestamp: 2025-01-16T10:45:48.912Z
Learning: The HighFive library development has moved from BlueBrain/HighFive to highfive-devs/highfive as of December 2024 due to the conclusion of the Blue Brain Project.

Applied to files:

  • src/amr/CMakeLists.txt
📚 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:

  • src/amr/CMakeLists.txt
  • tests/core/numerics/ion_updater/CMakeLists.txt
📚 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/amr/CMakeLists.txt
  • src/hdf5/detail/h5/h5_file.hpp
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py
📚 Learning: 2024-09-05T17:02:58.784Z
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.

Applied to files:

  • src/amr/CMakeLists.txt
  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py
📚 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/simulator/phare_types.hpp
  • src/core/data/electromag/electromag.hpp
  • src/hdf5/detail/h5/group_scanner.hpp
📚 Learning: 2024-10-18T13:23:32.074Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 910
File: pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py:7-7
Timestamp: 2024-10-18T13:23:32.074Z
Learning: In the `pyphare.pharesee.hierarchy` module, importing `PatchHierarchy` and `format_timestamp` from `hierarchy.py` into `hierarchy_utils.py` is acceptable as long as `hierarchy.py` does not import `hierarchy_utils.py`, thereby avoiding a cyclic import.

Applied to files:

  • pyphare/pyphare/pharesee/hierarchy/patchdata.py
  • pyphare/pyphare/pharein/initialize/__init__.py
  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py
  • tests/simulator/test_init_from_restart.py
📚 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 `__eq__` method in `ParticleData` uses `self.dataset == that.dataset` for dataset comparison, which might not be sufficient for numpy arrays as it returns an array of booleans. The use of `np.array_equal` is suggested for a more robust comparison.

Applied to files:

  • pyphare/pyphare/pharesee/hierarchy/patchdata.py
📚 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/hdf5/detail/h5/group_scanner.hpp
  • src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
  • src/amr/data/initializers/samrai_hdf5_initializer.hpp
  • tests/core/numerics/ion_updater/test_updater.cpp
  • src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
📚 Learning: 2024-09-17T13:36:04.487Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/amr/level_initializer/hybrid_level_initializer.hpp:44-49
Timestamp: 2024-09-17T13:36:04.487Z
Learning: In this codebase, when a derived class method overrides a virtual function using `override`, and there are no further subclasses, the `virtual` keyword is not required in the subclass.

Applied to files:

  • src/amr/level_initializer/hybrid_level_initializer.hpp
📚 Learning: 2024-07-23T09:51:46.761Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 859
File: pyphare/pyphare/pharesee/hierarchy/fromh5.py:27-34
Timestamp: 2024-07-23T09:51:46.761Z
Learning: Mutable default arguments like lists or dictionaries can lead to unexpected behavior because the same instance of the mutable object is shared across all calls to the function. It is a good practice to use `None` as the default value and initialize the mutable object inside the function.

Applied to files:

  • pyphare/pyphare/pharein/simulation.py
📚 Learning: 2024-09-17T13:33:47.475Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: src/core/data/grid/gridlayout.hpp:805-821
Timestamp: 2024-09-17T13:33:47.475Z
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/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp
📚 Learning: 2024-09-04T13:45:43.884Z
Learnt from: PhilipDeegan
Repo: PHAREHUB/PHARE PR: 888
File: tests/simulator/test_samrai_restarts_parser.py:86-97
Timestamp: 2024-09-04T13:45:43.884Z
Learning: Do not comment on pull requests that are in draft status.

Applied to files:

  • pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py
🧬 Code graph analysis (20)
tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (3)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)
  • particles (36-37)
src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (1)
  • particles (65-66)
src/core/data/ions/particle_initializers/particle_initializer.hpp (1)
  • particles (14-15)
src/core/data/ions/particle_initializers/particle_initializer.hpp (2)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)
  • particles (36-37)
src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (1)
  • particles (65-66)
src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (1)
  • particles (36-37)
src/core/data/ions/particle_initializers/particle_initializer.hpp (1)
  • particles (14-15)
src/core/data/electromag/electromag.hpp (3)
src/diagnostic/diagnostic_model_view.hpp (1)
  • dimension (30-60)
src/amr/messengers/hybrid_messenger.hpp (8)
  • E (283-287)
  • E (283-284)
  • E (345-345)
  • E (345-345)
  • B (269-273)
  • B (269-270)
  • B (344-344)
  • B (344-344)
tests/core/data/electromag/test_electromag_fixtures.hpp (1)
  • E (19-23)
src/hdf5/detail/h5/group_scanner.hpp (1)
src/hdf5/detail/h5/h5_file.hpp (6)
  • path (274-280)
  • path (274-274)
  • path (282-287)
  • path (282-282)
  • contains (260-263)
  • contains (260-260)
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp (3)
src/core/utilities/types.hpp (2)
  • apply (97-100)
  • apply (97-97)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • i (44-48)
src/core/utilities/box/box.hpp (5)
  • isIn (218-245)
  • isIn (218-218)
  • isIn (248-252)
  • isIn (248-249)
  • isIn (258-258)
src/amr/level_initializer/hybrid_level_initializer.hpp (2)
src/amr/messengers/hybrid_hybrid_messenger_strategy.hpp (16)
  • hierarchy (219-273)
  • hierarchy (219-220)
  • hierarchy (281-317)
  • hierarchy (281-283)
  • hierarchy (908-917)
  • hierarchy (908-911)
  • model (338-364)
  • model (338-338)
  • model (601-624)
  • model (601-601)
  • model (640-663)
  • model (640-640)
  • model (668-692)
  • model (668-669)
  • model (722-735)
  • model (722-722)
src/amr/multiphysics_integrator.hpp (10)
  • hierarchy (301-376)
  • hierarchy (301-306)
  • hierarchy (380-409)
  • hierarchy (381-382)
  • hierarchy (413-427)
  • hierarchy (413-416)
  • hierarchy (566-595)
  • hierarchy (567-570)
  • model (705-724)
  • model (705-706)
pyphare/pyphare/pharein/__init__.py (4)
pyphare/pyphare/pharein/simulation.py (1)
  • Simulation (754-1088)
pyphare/pyphare/pharein/initialize/general.py (1)
  • populateDict (89-315)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)
  • populateDict (6-16)
pyphare/pyphare/pharein/initialize/user_fns.py (1)
  • populateDict (5-7)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (1)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • dir (50-51)
src/core/data/grid/gridlayout.hpp (3)
pyphare/pyphare/core/gridlayout.py (2)
  • physicalStartIndex (262-264)
  • AMRToLocal (330-334)
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)
pyphare/pyphare/pharein/initialize/user_fns.py (4)
pyphare/pyphare/pharein/initialize/general.py (5)
  • add_double (71-72)
  • add_int (63-64)
  • add_size_t (75-79)
  • fn_wrapper (50-59)
  • populateDict (89-315)
pyphare/pyphare/pharein/__init__.py (1)
  • populateDict (71-81)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)
  • populateDict (6-16)
pyphare/pyphare/core/gridlayout.py (1)
  • ndim (221-222)
src/core/data/ndarray/ndarray_vector.hpp (1)
src/core/utilities/types.hpp (2)
  • product (256-259)
  • product (256-256)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (2)
src/core/utilities/types.hpp (2)
  • sized_array (133-147)
  • sized_array (133-134)
src/hdf5/detail/h5/group_scanner.hpp (2)
  • group (35-61)
  • group (35-35)
tests/core/numerics/ion_updater/test_updater.cpp (1)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (5)
src/core/data/grid/gridlayout.hpp (7)
  • centering (873-877)
  • centering (873-874)
  • centering (884-888)
  • centering (884-885)
  • centering (891-896)
  • centering (891-892)
  • centering (899-900)
src/core/utilities/types.hpp (6)
  • ConstArray (168-174)
  • ConstArray (168-168)
  • for_N (454-485)
  • for_N (454-454)
  • for_N (488-491)
  • for_N (488-488)
src/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
  • i (44-48)
src/core/data/ndarray/ndarray_vector.hpp (4)
  • make_array_view (232-235)
  • make_array_view (232-232)
  • make_array_view (238-241)
  • make_array_view (238-238)
src/core/utilities/box/box.hpp (4)
  • grow (89-94)
  • grow (89-89)
  • grow (277-282)
  • grow (277-277)
pyphare/pyphare/pharein/initialize/general.py (5)
pyphare/pyphare/core/phare_utilities.py (1)
  • is_scalar (54-55)
pyphare/pyphare/pharein/load_balancer.py (1)
  • LoadBalancer (9-57)
pyphare/pyphare/pharein/simulation.py (4)
  • serialize (1094-1103)
  • deserialize (1106-1110)
  • restart_file_path (999-1001)
  • is_restartable_compared_to (1049-1057)
pyphare/pyphare/cpp/__init__.py (1)
  • cpp_etc_lib (12-15)
pyphare/pyphare/pharein/__init__.py (1)
  • populateDict (71-81)
src/amr/physical_models/hybrid_model.hpp (1)
src/amr/data/electromag/electromag_initializer.hpp (2)
  • create (80-87)
  • create (80-81)
pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (2)
pyphare/pyphare/pharesee/hierarchy/patchdata.py (1)
  • FieldData (32-194)
pyphare/pyphare/core/phare_utilities.py (1)
  • assert_fp_any_all_close (141-142)
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (3)
pyphare/pyphare/pharein/initialize/general.py (2)
  • add_int (63-64)
  • populateDict (89-315)
pyphare/pyphare/pharein/__init__.py (1)
  • populateDict (71-81)
pyphare/pyphare/pharein/initialize/user_fns.py (1)
  • populateDict (5-7)
tests/simulator/test_init_from_restart.py (6)
pyphare/pyphare/pharesee/hierarchy/patchdata.py (2)
  • FieldData (32-194)
  • ParticleData (197-240)
pyphare/pyphare/pharesee/hierarchy/fromh5.py (1)
  • get_all_available_quantities_from_h5 (27-33)
pyphare/pyphare/pharesee/hierarchy/hierarchy.py (1)
  • format_timestamp (13-16)
pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (2)
  • single_patch_for_LO (662-705)
  • hierarchy_compare (618-659)
tests/simulator/__init__.py (2)
  • SimulatorTest (200-266)
  • register_diag_dir_for_cleanup (233-234)
tests/diagnostic/__init__.py (1)
  • dump_all_diags (15-62)
🪛 Ruff (0.14.3)
pyphare/pyphare/pharein/simulation.py

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

(TRY003)

pyphare/pyphare/pharein/initialize/user_fns.py

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

(TRY003)

pyphare/pyphare/pharein/initialize/__init__.py

5-9: __all__ is not sorted

Apply an isort-style sorting to __all__

(RUF022)

pyphare/pyphare/pharein/initialize/general.py

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

(TRY003)


132-132: Value being cast to int is already an integer

Remove unnecessary int call

(RUF046)


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

(TRY003)


270-272: Avoid specifying long messages outside the exception class

(TRY003)


278-280: Avoid specifying long messages outside the exception class

(TRY003)


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

(TRY003)

pyphare/pyphare/pharein/initialize/samrai_hdf5.py

9-9: Loop control variable pop not used within loop body

Rename unused pop to _pop

(B007)

tests/simulator/test_init_from_restart.py

39-39: Unused function argument: sim

(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). (7)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (macos-13)
  • GitHub Check: build (macos-latest)
  • GitHub Check: Analyze (cpp)
  • GitHub Check: Analyze (python)
  • GitHub Check: build (ubuntu-latest, clang)
  • GitHub Check: build (ubuntu-latest, gcc)
🔇 Additional comments (17)
tests/core/numerics/ion_updater/CMakeLists.txt (1)

14-14: Dependency replacement aligns with broader AMR refactoring.

The change from phare_core to phare_amr is consistent with the PR's modularization of initialization logic into the AMR namespace and has been verified across the codebase per the earlier comprehensive review.

src/amr/CMakeLists.txt (1)

104-106: Manually verify HighFive linkage scope is appropriate for target usage.

The INTERFACE scope provided to HighFive means phare_amr will not receive HighFive's include directories during its own compilation, only its consumers will. This is correct if phare_amr does not directly include HighFive headers in its sources.

Verify one of the following:

  • If phare_amr sources include HighFive headers directly (e.g., #include <highfive/...>): change INTERFACE to PUBLIC
  • If HighFive is only used by consumers of phare_amr: INTERFACE scope is acceptable and the code is correct
src/core/data/grid/gridlayout.hpp (6)

786-802: Well-designed coordinate transformation.

The addition of the localbox parameter to AMRToLocal provides flexibility for coordinate transformations relative to different reference boxes. The assertion at line 798 correctly validates non-negative values before the unsigned conversion.


804-808: Clean backward-compatible API.

The overload delegation pattern maintains backward compatibility while enabling the new localbox-based functionality.


816-822: Consistent Box transformation.

The Box variant correctly applies the localbox-based transformation to both corners, maintaining consistency with the Point variant.


824-828: LGTM!

The Box overload follows the same delegation pattern as the Point variant, providing a consistent backward-compatible API.


1213-1213: LGTM!

Clean accessor for the level number.


1216-1222: Well-structured domain Box construction.

The domainBoxFor method follows the same pattern as ghostBoxFor, correctly using physicalStartToEnd to define domain boundaries.

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

264-270: LGTM!

The requires clause correctly constrains the variadic constructor to integral types, enabling construction from individual dimension arguments while maintaining type safety.

res/cmake/test.cmake (1)

44-44: Change verified and correct. Directory and CMakeLists.txt both exist.

The particle initializer test subdirectory has been properly added to the AMR namespace under tests/amr/data/particles/initializer (line 44), with its own CMakeLists.txt. Placement is logical within the existing particles test structure and follows the established pattern of organizing test subdirectories.

Note: The core tests/core/data/maxwellian_particle_initializer (line 18) still exists, which appears to be a separate, specialized initializer module.

pyphare/pyphare/pharesee/hierarchy/patchdata.py (1)

3-6: LGTM: Clean import additions.

The new imports for phare_utilities and box are properly formatted and used throughout the file.

pyphare/pyphare/pharesee/hierarchy/hierarchy_utils.py (2)

1-4: LGTM: Import additions support EqualityReport enhancements.

The new imports for os and dataclasses are used in the updated EqualityReport implementation.


604-606: LGTM: Method chaining enabled.

Returning self from __call__ allows for fluent API usage.

src/simulator/phare_types.hpp (1)

28-30: LGTM: Factory alias updated to AMR namespace.

The ParticleInitializerFactory alias now correctly references the AMR namespace implementation, aligning with the broader refactoring in this PR.

tests/core/data/maxwellian_particle_initializer/test_maxwellian_particle_initializer.cpp (1)

54-54: LGTM: Test updated for new loadParticles signature.

The calls to loadParticles correctly include the new popname parameter, matching the updated interface.

Also applies to: 63-63

src/core/data/ions/particle_initializers/particle_initializer.hpp (1)

4-4: LGTM: Interface extended for population-aware loading.

The addition of the popname parameter enables population-specific particle initialization. The <string> include is properly added, and the change is consistently applied across derived classes and call sites.

Also applies to: 14-16

pyphare/pyphare/pharein/initialize/general.py (1)

128-134: Fix incorrect use of add_vector_int.

Line 129 calls add_vector_int(..., len(rb.keys())), but add_vector_int immediately executes list(val), so handing it an int raises a TypeError as soon as refinement boxes are present. Switch this to add_int (or another scalar helper) so the refinement metadata can be populated without crashing.

Apply this correction:

-        add_int("simulation/AMR/refinement/boxes/nbr_levels/", len(rb.keys()))
+        add_int("simulation/AMR/refinement/boxes/nbr_levels/", len(rb))

Likely an incorrect or invalid review comment.

Comment on lines +1 to +2
#ifndef _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
#define _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_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 | 🟠 Major

Rename header guard to non-reserved form

Line 1’s _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_ is a reserved identifier. Please rename it to PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP to keep us standards-compliant and consistent with the established pattern. Based on learnings.

-#ifndef _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP
+#define PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP
@@
-#endif /*_PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_*/
+#endif /* PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP */

Also applies to: 140-140

🤖 Prompt for AI Agents
In src/amr/data/initializers/samrai_hdf5_initializer.hpp around lines 1-2 and
line 140, the header guard uses a reserved identifier
(_PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_); change it to a
non-reserved form PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP across
the file by updating the #ifndef and #define at the top and the corresponding
#endif (and any trailing comment) at line 140 to match the new name.

Comment on lines +126 to +131
for (auto const& group : h5File.scan_for_groups({"level_0000", field_name}))
{
auto const field_path = group.substr(0, group.rfind("/"));
auto const& field_box = h5File.getBoxFromPath(field_path + "/d_box");
h5File.patches.emplace_back(field_box, field_path.substr(0, field_path.rfind("/")));
}
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

Do not hardcode level_0000 when discovering datasets

By requiring "level_0000" at Line 126, we only ever pick up base-level patches. Any restart containing finer levels (level_0001, level_0002, …) will be ignored, so particle data above level 0 vanishes during initialization. Please broaden the scan so every level is considered (for example, filter on field_name alone and check the level prefix inside the loop).

-        for (auto const& group : h5File.scan_for_groups({"level_0000", field_name}))
+        for (auto const& group : h5File.scan_for_groups({field_name}))
         {
             auto const field_path = group.substr(0, group.rfind("/"));
             auto const& field_box = h5File.getBoxFromPath(field_path + "/d_box");
             h5File.patches.emplace_back(field_box, field_path.substr(0, field_path.rfind("/")));
         }
📝 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
for (auto const& group : h5File.scan_for_groups({"level_0000", field_name}))
{
auto const field_path = group.substr(0, group.rfind("/"));
auto const& field_box = h5File.getBoxFromPath(field_path + "/d_box");
h5File.patches.emplace_back(field_box, field_path.substr(0, field_path.rfind("/")));
}
for (auto const& group : h5File.scan_for_groups({field_name}))
{
auto const field_path = group.substr(0, group.rfind("/"));
auto const& field_box = h5File.getBoxFromPath(field_path + "/d_box");
h5File.patches.emplace_back(field_box, field_path.substr(0, field_path.rfind("/")));
}

Comment on lines +1 to +2
#ifndef _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
#define _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_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 | 🟠 Major

Align header guard with project convention

Line 1 introduces _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_, which begins with a reserved identifier. Rename it to the canonical PHARE_AMR_DATA_PARTICLES_INITIALIZERS_SAMRAI_HDF5_PARTICLE_INITIALIZER_HPP form so we stay standards-compliant and consistent with the documented preference. Based on learnings.

-#ifndef _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
-#define _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_
+#ifndef PHARE_AMR_DATA_PARTICLES_INITIALIZERS_SAMRAI_HDF5_PARTICLE_INITIALIZER_HPP
+#define PHARE_AMR_DATA_PARTICLES_INITIALIZERS_SAMRAI_HDF5_PARTICLE_INITIALIZER_HPP
@@
-#endif /*_PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_*/
+#endif /* PHARE_AMR_DATA_PARTICLES_INITIALIZERS_SAMRAI_HDF5_PARTICLE_INITIALIZER_HPP */

Also applies to: 77-77

🤖 Prompt for AI Agents
In src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
lines 1-2 and line 77, the header guard macro uses a reserved identifier
`_PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_`; rename it
to the canonical, project-consistent
PHARE_AMR_DATA_PARTICLES_INITIALIZERS_SAMRAI_HDF5_PARTICLE_INITIALIZER_HPP
everywhere the guard appears (both the #ifndef/#define at the top and the
matching #endif comment at line 77) so the macro no longer begins with an
underscore and matches the documented naming convention.

Comment on lines +1 to +2
#ifndef _PHARE_HDF5_DETAIL_H5_GROUP_SCANNER_HPP_
#define _PHARE_HDF5_DETAIL_H5_GROUP_SCANNER_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 | 🟠 Major

Fix reserved header guard identifier

Line 1 defines _PHARE_HDF5_DETAIL_H5_GROUP_SCANNER_HPP_, which starts with an underscore followed by a capital letter, making it reserved and formally undefined behaviour in user code. Please switch to the project’s PHARE_… guard convention to stay within the standard and match prior guidance. Based on learnings.

-#ifndef _PHARE_HDF5_DETAIL_H5_GROUP_SCANNER_HPP_
-#define _PHARE_HDF5_DETAIL_H5_GROUP_SCANNER_HPP_
+#ifndef PHARE_HDF5_DETAIL_H5_GROUP_SCANNER_HPP
+#define PHARE_HDF5_DETAIL_H5_GROUP_SCANNER_HPP
@@
-#endif /* _PHARE_HDF5_DETAIL_H5_GROUP_SCANNER_HPP_ */
+#endif /* PHARE_HDF5_DETAIL_H5_GROUP_SCANNER_HPP */

Also applies to: 73-73

🤖 Prompt for AI Agents
In src/hdf5/detail/h5/group_scanner.hpp around lines 1-2 and line 73, the
include guard uses a reserved identifier starting with an underscore and capital
letter; replace the guard with the project convention (e.g.,
PHARE_HDF5_DETAIL_H5_GROUP_SCANNER_HPP) and update the matching #endif comment
to use the same new macro so the header guard is non-reserved and consistent.

Comment on lines 534 to 538
void fillIonsMomentsGhosts()
{
using Interpolator = typename IonUpdater::Interpolator;
using Interpolator = IonUpdater::Interpolator;
Interpolator interpolate;

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

Restore typename for dependent nested type.

Line 536 defines using Interpolator = IonUpdater::Interpolator;, but IonUpdater depends on the fixture template parameters, so the nested type lookup requires the typename keyword. Without it the test no longer compiles.

Apply:

-        using Interpolator = IonUpdater::Interpolator;
+        using Interpolator = typename IonUpdater::Interpolator;
📝 Committable suggestion

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

Suggested change
void fillIonsMomentsGhosts()
{
using Interpolator = typename IonUpdater::Interpolator;
using Interpolator = IonUpdater::Interpolator;
Interpolator interpolate;
void fillIonsMomentsGhosts()
{
using Interpolator = typename IonUpdater::Interpolator;
Interpolator interpolate;
🤖 Prompt for AI Agents
In tests/core/numerics/ion_updater/test_updater.cpp around lines 534 to 538, the
alias declaration "using Interpolator = IonUpdater::Interpolator;" omits the
required typename for a dependent nested type; change it to use the typename
keyword (i.e., use "using Interpolator = typename IonUpdater::Interpolator;") so
the compiler recognizes the nested type of the template-dependent IonUpdater.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant