Conversation
📝 WalkthroughWalkthroughThis change refactors the PHARE initialization system to support restart workflows from SAMRAI HDF5 files. It extracts the monolithic Changes
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()
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Areas requiring extra attention:
Possibly related PRs
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (2 warnings, 1 inconclusive)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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 ofFileOptype alias in the constructor.The constructor update to use
FileOp flagsis consistent with the introduction of theFileOptype 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
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:
copyimported but unusedRemove unused import:
copy(F401)
3-3:
timeimported but unusedRemove unused import:
time(F401)
5-5:
datetimeimported but unusedRemove unused import:
datetime(F401)
7-7:
numpyimported but unusedRemove unused import:
numpy(F401)
8-8:
pathlib.Pathimported but unusedRemove unused import:
pathlib.Path(F401)
9-9:
datetime.timedeltaimported but unusedRemove unused import:
datetime.timedelta(F401)
11-11:
ddt.dataimported but unusedRemove unused import
(F401)
11-11:
ddt.unpackimported but unusedRemove unused import
(F401)
18-18:
pyphare.pharesee.run.Runimported but unusedRemove unused import:
pyphare.pharesee.run.Run(F401)
19-19:
pyphare.simulator.simulator.Simulatorimported but unusedRemove unused import:
pyphare.simulator.simulator.Simulator(F401)
22-22:
tests.diagnostic.dump_all_diagsimported but unusedRemove unused import:
tests.diagnostic.dump_all_diags(F401)
23-23:
pyphare.pharesee.hierarchy.patchdata.ParticleDataimported but unusedRemove unused import:
pyphare.pharesee.hierarchy.patchdata.ParticleData(F401)
24-24:
pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5imported but unusedRemove 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
constqualifier to theinitializemethod 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 theconstqualifier is appropriate.
42-42: LGTM!Adding the
constqualifier to theinitializeComponent_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 theconstqualifier 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.hppis included. Ensure that the functionality provided by this header is necessary and used within theElectromagclass.
21-21: LGTM!The type alias
Thisis 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_typealias improves readability.- The use of
auto static constexprfor thedimensionmember 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
Electromagclass using a dictionary.- The
EandBfields are initialized consistently with the provided dictionary.- The
dict_member variable stores the magnetic initializer for later use in theinitializemethod.
49-50: LGTM!The changes to the
initializemethod are good:
- The use of the
ElectromagInitializerFactoryand thedict_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
FileOptype alias enhances code clarity and type safety by providing a more descriptive name for the file access mode type and replacing the use ofunsignedfor theflagsparameter.
46-46: Consistent use ofFileOptype alias.The method signature update for
createHighFiveFileto acceptFileOp flagsis consistent with the introduction of theFileOptype 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
flagsparameter to theHiFile::AccessModetype. 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 constfor theflags_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::AccessModeinstead ofunsignedfor the_flagsparameter improves type safety and makes the code more expressive.
71-72: Consistent use ofHiFile::AccessModefor file access mode.Using
HiFile::AccessModefor theflagsvariable inmake_uniqueis consistent with the updated constructor and improves type safety.
97-97: Improved type safety formakeFilemethod.Using
HiFile::AccessModeinstead ofunsignedfor thefile_flagparameter improves type safety and is consistent with the other updates.
171-171: Improved type safety forflagsmember variable.Using
HiFile::AccessModeinstead ofunsignedfor theflagsmember variable improves type safety and is consistent with the other updates.
181-181: Improved type safety forfile_flagsmap.Using
HiFile::AccessModeinstead ofunsignedfor the values in thefile_flagsmap improves type safety and is consistent with the other updates.
bf95f01 to
b7147a9
Compare
There was a problem hiding this comment.
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
initializemethod to use theElectromagInitializerFactoryto create an initializer based on thedict_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
dictmember after initialization is not necessary, as thedict_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 thetraverse_h5_for_groups_recursivefunction.Consider the following improvements:
Use
os.path.jointo construct the paths instead of string concatenation. This will make the code more readable and less error-prone.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
H5Contentclass.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] = groupclass 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
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:
copyimported but unusedRemove unused import:
copy(F401)
3-3:
timeimported but unusedRemove unused import:
time(F401)
5-5:
datetimeimported but unusedRemove unused import:
datetime(F401)
7-7:
numpyimported but unusedRemove unused import:
numpy(F401)
8-8:
pathlib.Pathimported but unusedRemove unused import:
pathlib.Path(F401)
9-9:
datetime.timedeltaimported but unusedRemove unused import:
datetime.timedelta(F401)
11-11:
ddt.dataimported but unusedRemove unused import
(F401)
11-11:
ddt.unpackimported but unusedRemove unused import
(F401)
18-18:
pyphare.pharesee.run.Runimported but unusedRemove unused import:
pyphare.pharesee.run.Run(F401)
19-19:
pyphare.simulator.simulator.Simulatorimported but unusedRemove unused import:
pyphare.simulator.simulator.Simulator(F401)
22-22:
tests.diagnostic.dump_all_diagsimported but unusedRemove unused import:
tests.diagnostic.dump_all_diags(F401)
23-23:
pyphare.pharesee.hierarchy.patchdata.ParticleDataimported but unusedRemove unused import:
pyphare.pharesee.hierarchy.patchdata.ParticleData(F401)
24-24:
pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5imported but unusedRemove 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.hppis approved. The file name is expressive and follows the naming convention of the project.
21-21: LGTM!The introduction of the type alias
Thisis approved. The name is expressive and follows the naming convention of the project.
24-24: LGTM!The alignment of the type alias
vecfield_typeis approved. The change improves the readability of the code.
25-25: LGTM!The modification of the
dimensionmember to useauto static constexpris 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::PHAREDictas an argument is approved. The constructor provides a more flexible way to initialize theElectromagclass 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 variabledict_, which is initialized with an emptyinitializer::PHAREDict, is approved. The change is consistent with the modifications made to the constructor and theinitializemethod.tests/simulator/test_samrai_restarts_parser.py (2)
1-24: Remove unused imports.The following imports are unused and should be removed:
copytimedatetimenumpypathlib.Pathdatetime.timedeltaddt.dataddt.unpackpyphare.pharesee.run.Runpyphare.simulator.simulator.Simulatortests.diagnostic.dump_all_diagspyphare.pharesee.hierarchy.patchdata.ParticleDatapyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5Remove 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:
copyimported but unusedRemove unused import:
copy(F401)
3-3:
timeimported but unusedRemove unused import:
time(F401)
5-5:
datetimeimported but unusedRemove unused import:
datetime(F401)
7-7:
numpyimported but unusedRemove unused import:
numpy(F401)
8-8:
pathlib.Pathimported but unusedRemove unused import:
pathlib.Path(F401)
9-9:
datetime.timedeltaimported but unusedRemove unused import:
datetime.timedelta(F401)
11-11:
ddt.dataimported but unusedRemove unused import
(F401)
11-11:
ddt.unpackimported but unusedRemove unused import
(F401)
18-18:
pyphare.pharesee.run.Runimported but unusedRemove unused import:
pyphare.pharesee.run.Run(F401)
19-19:
pyphare.simulator.simulator.Simulatorimported but unusedRemove unused import:
pyphare.simulator.simulator.Simulator(F401)
22-22:
tests.diagnostic.dump_all_diagsimported but unusedRemove unused import:
tests.diagnostic.dump_all_diags(F401)
23-23:
pyphare.pharesee.hierarchy.patchdata.ParticleDataimported but unusedRemove unused import:
pyphare.pharesee.hierarchy.patchdata.ParticleData(F401)
24-24:
pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5imported but unusedRemove 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_parserreads 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.
b7147a9 to
3a16ee3
Compare
There was a problem hiding this comment.
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
jobnamethat 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 fromphare_coretophare_amris ProblematicThe replacement of
phare_corewithphare_amrintests/core/numerics/ion_updater/CMakeLists.txtis problematic for the following reasons:
phare_coreis still used extensively across the codebase, indicating that it remains a necessary dependency.phare_amris 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_coretophare_amr.Ensure that the replacement of
phare_corewithphare_amrdoes 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." fiLength of output: 2120
pyphare/pyphare/pharein/initialize/samrai_hdf5.py (2)
3-3: Remove the unused import.The commented out import of
pybindlibs.dictatoris 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
popis 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
popnot used within loop bodyRename unused
popto_pop(B007)
res/cmake/test.cmake (1)
44-44: Issue Found: New Test Directory Not Referenced in CMake FilesThe new test directory
tests/amr/data/particles/initializerexists, 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/initializeris 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/initializerThis 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:
- If the removed tests directory still exists and if any CMake files still reference it.
- If the new tests directory exists and is referenced in CMake files.
- 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." fiLength of output: 1765
src/core/CMakeLists.txt (1)
Re-add
particle_initializer_factory.hpptoSOURCES_INCinCMakeLists.txt.The file
particle_initializer_factory.hppis still being referenced and used in the codebase, as evidenced by its inclusion in several source files and the usage of theParticleInitializerFactoryclass. Removing it from theCMakeLists.txtcould lead to build errors or missing functionality. Please ensure this file is included in the build configuration.
tests/amr/data/particles/initializer/test_main.cpptests/core/numerics/ion_updater/test_updater.cppsrc/amr/physical_models/hybrid_model.hppsrc/simulator/phare_types.hppAnalysis chain
Line range hint
1-53: Verify the impact of removingparticle_initializer_factory.hppon the codebase.The removal of
data/ions/particle_initializers/particle_initializer_factory.hppfromSOURCES_INCsuggests 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
ParticleInitializerFactoryon the codebase.The
ParticleInitializerFactorytype alias has been removed fromsrc/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.hpptests/core/numerics/ion_updater/test_updater.cppsrc/amr/physical_models/hybrid_model.hpptests/amr/data/particles/initializer/test_main.cppsrc/amr/data/particles/initializers/particle_initializer_factory.hppConsider adding documentation or comments to clarify the new approach to particle initialization.
Analysis chain
Line range hint
46-46: Verify the impact of removingParticleInitializerFactoryon the codebase.The removal of the
ParticleInitializerFactorytype alias from thePHARE_Typesstruct 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 makinggetRestartFileFullPath()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 thebox2datasetmember.The purpose of the
box2datasetmember is unclear from the provided code. Consider adding documentation to explain its purpose and how it's used.
76-76: Remove the unuseddimensionmember.The
dimensionmember 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
populateDictfunction 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
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
popnot used within loop bodyRename unused
popto_pop(B007)
tests/simulator/test_samrai_restarts_parser.py
3-3:
timeimported but unusedRemove unused import:
time(F401)
5-5:
datetimeimported but unusedRemove unused import:
datetime(F401)
7-7:
numpyimported but unusedRemove unused import:
numpy(F401)
8-8:
pathlib.Pathimported but unusedRemove unused import:
pathlib.Path(F401)
9-9:
datetime.timedeltaimported but unusedRemove unused import:
datetime.timedelta(F401)
11-11:
ddt.dataimported but unusedRemove unused import
(F401)
11-11:
ddt.unpackimported but unusedRemove unused import
(F401)
18-18:
pyphare.pharesee.run.Runimported but unusedRemove unused import:
pyphare.pharesee.run.Run(F401)
22-22:
tests.diagnostic.dump_all_diagsimported but unusedRemove unused import:
tests.diagnostic.dump_all_diags(F401)
23-23:
pyphare.pharesee.hierarchy.patchdata.ParticleDataimported but unusedRemove unused import:
pyphare.pharesee.hierarchy.patchdata.ParticleData(F401)
24-24:
pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5imported but unusedRemove 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
modelis assigned to but never usedRemove 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 fromphare_coretophare_amr.Ensure that the
phare_amrlibrary 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_corelibrary in the codebase and assess the impact of the change:If the tests pass, it suggests that the change from
phare_coretophare_amris 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
ParticleInitializerFactoryaligns 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
ParticleInitializerFactoryfrom the core namespace to thePHARE::amrnamespace is consistent with the refactoring effort to organize particle initializer functionality under the AMR module. This change ensures that the correct implementation ofParticleInitializerFactoryis 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
LoadBalancera 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_optionsallows 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
ParticleInitializerFactorytype 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.hppis included, which suggests that it provides functionality related to initializing theElectromagclass.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
Thisimproves 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_typetype alias enhances readability and consistency.- Using
auto static constexprfor thedimensionmember 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
initializemethod to use a dictionary-based approach for initialization, which can be more flexible and extensible.Please ensure that:
- The new constructor correctly initializes the
EandBmembers using the values from the dictionary.- The
initializemethod properly creates an initializer using theElectromagInitializerFactorybased 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 withdict_aligns with the change in the initialization approach, moving from a dedicated initializer object to a dictionary-based approach. Thedict_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:
timeimported but unusedRemove unused import:
time(F401)
5-5:
datetimeimported but unusedRemove unused import:
datetime(F401)
7-7:
numpyimported but unusedRemove unused import:
numpy(F401)
8-8:
pathlib.Pathimported but unusedRemove unused import:
pathlib.Path(F401)
9-9:
datetime.timedeltaimported but unusedRemove unused import:
datetime.timedelta(F401)
11-11:
ddt.dataimported but unusedRemove unused import
(F401)
11-11:
ddt.unpackimported but unusedRemove unused import
(F401)
18-18:
pyphare.pharesee.run.Runimported but unusedRemove unused import:
pyphare.pharesee.run.Run(F401)
22-22:
tests.diagnostic.dump_all_diagsimported but unusedRemove unused import:
tests.diagnostic.dump_all_diags(F401)
23-23:
pyphare.pharesee.hierarchy.patchdata.ParticleDataimported but unusedRemove unused import:
pyphare.pharesee.hierarchy.patchdata.ParticleData(F401)
24-24:
pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5imported but unusedRemove 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
modelis assigned to but never usedRemove assignment to unused variable
model(F841)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (2)
23-23: LGTM!Fully qualifying the
ParticleInitializertype with thecorenamespace is a good practice to avoid ambiguity and potential naming conflicts.
72-73: LGTM!Fully qualifying the
MaxwellianParticleInitializertype with thecorenamespace 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
ParticleInitializerFactorytype 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
ParticleInitializerFactoryclass.
207-214: LGTM!The updated
ParticleInitializerFactorytype 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
ParticleInitializerFactorytype 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_optionsfunction 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_optionsto the list of accepted keywords is correct and consistent with the newcheck_init_optionsfunction.
671-671: LGTM!The call to
check_init_optionsis correctly added to process the initialization options before setting up the simulation.
0ad9e31 to
648c401
Compare
There was a problem hiding this comment.
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 replacingphare_corewithphare_amrThe
phare_amrtarget is not declared or used elsewhere in the codebase, whilephare_coreis still widely used. This change could potentially break the build or tests. Please verify thatphare_amris a valid target and provides the necessary functionality before proceeding with this replacement.
phare_coreis still used in multiple CMake files.phare_amris not declared as a target in the codebase.phare_amris not used in other CMake files.Analysis chain
Verify the impact of replacing
phare_corewithphare_amr.Ensure that
phare_amrprovides the same or a superset of the functionality provided byphare_core. Ifphare_amrhas a different interface or lacks some functionality provided byphare_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." fiLength of output: 2571
src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpp (2)
65-66: Approve the addition of thepopnameparameter to enhance particle initialization flexibility.The addition of the
std::string const& popnameparameter to theloadParticlesmethod 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
popnameparameter 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 thepopnameparameter in the method definition.The inclusion of the
std::string const& popnameparameter in theloadParticlesmethod definition aligns with the updated method signature, ensuring consistency between the declaration and the definition.As mentioned in the previous comment, consider utilizing the
popnameparameter 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 thepopulateDictfunction into smaller functions for better readability and maintainability.The
populateDictfunction 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
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
popnot used within loop bodyRename unused
popto_pop(B007)
tests/simulator/test_samrai_restarts_parser.py
3-3:
timeimported but unusedRemove unused import:
time(F401)
5-5:
datetimeimported but unusedRemove unused import:
datetime(F401)
7-7:
numpyimported but unusedRemove unused import:
numpy(F401)
8-8:
pathlib.Pathimported but unusedRemove unused import:
pathlib.Path(F401)
9-9:
datetime.timedeltaimported but unusedRemove unused import:
datetime.timedelta(F401)
11-11:
ddt.dataimported but unusedRemove unused import
(F401)
11-11:
ddt.unpackimported but unusedRemove unused import
(F401)
18-18:
pyphare.pharesee.run.Runimported but unusedRemove unused import:
pyphare.pharesee.run.Run(F401)
22-22:
tests.diagnostic.dump_all_diagsimported but unusedRemove unused import:
tests.diagnostic.dump_all_diags(F401)
23-23:
pyphare.pharesee.hierarchy.patchdata.ParticleDataimported but unusedRemove unused import:
pyphare.pharesee.hierarchy.patchdata.ParticleData(F401)
24-24:
pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5imported but unusedRemove 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
modelis assigned to but never usedRemove 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_corehas been replaced withphare_amrin thetarget_link_librariesdirective. This change may have implications on the functionality and control flow of the project.Please confirm the following:
- The
phare_amrlibrary provides the necessary features and behaviors required by the project.- The change has been properly propagated to other parts of the codebase to ensure compatibility.
- The tests have been updated and are passing with the new library.
Run the following script to verify the usage of the
phare_amrlibrary in the codebase:Verification successful
Integration of
phare_amrconfirmed across the codebase.The
phare_amrlibrary 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 byphare_coreare covered byphare_amrand verify that tests are passing with the new library.
CMakeLists.txt References:
src/restarts/CMakeLists.txtsrc/simulator/CMakeLists.txtsrc/diagnostic/CMakeLists.txt- Various test directories under
tests/amr/C++ Header Inclusion:
src/phare_solver.hppScripts 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 2Length of output: 6932
src/core/data/ions/particle_initializers/particle_initializer.hpp (1)
13-15: LGTM!The addition of the
popnameparameter to theloadParticlesmethod 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.hppis 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
ParticleInitializerFactoryis 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
Simulationimport.
28-28: LGTM!The changes to the
__all__list are approved. TheLoadBalancerclass has been correctly added to the list of public entities.
72-80: LGTM!The changes to the
populateDictfunction are approved. The refactoring improves code organization and modularity by:
- Importing the
simvariable from a separate module.- Splitting the initialization logic into separate functions in the
initializemodule.- 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
loadParticlesmethod signature.
63-63: LGTM!The code change is consistent with the updated
loadParticlesmethod signature.src/simulator/phare_types.hpp (1)
33-34: LGTM!The change to the
ParticleInitializerFactorytype alias looks good:
- It uses the
amrnamespace to make the type more specific.- It provides
ParticleArray_tandGridLayout_tas 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:
timeimported but unusedRemove unused import:
time(F401)
5-5:
datetimeimported but unusedRemove unused import:
datetime(F401)
7-7:
numpyimported but unusedRemove unused import:
numpy(F401)
8-8:
pathlib.Pathimported but unusedRemove unused import:
pathlib.Path(F401)
9-9:
datetime.timedeltaimported but unusedRemove unused import:
datetime.timedelta(F401)
11-11:
ddt.dataimported but unusedRemove unused import
(F401)
11-11:
ddt.unpackimported but unusedRemove unused import
(F401)
18-18:
pyphare.pharesee.run.Runimported but unusedRemove unused import:
pyphare.pharesee.run.Run(F401)
22-22:
tests.diagnostic.dump_all_diagsimported but unusedRemove unused import:
tests.diagnostic.dump_all_diags(F401)
23-23:
pyphare.pharesee.hierarchy.patchdata.ParticleDataimported but unusedRemove unused import:
pyphare.pharesee.hierarchy.patchdata.ParticleData(F401)
24-24:
pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5imported but unusedRemove 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
Noneas the default and initializing the dictionary within the function:def dup(dic=None): if dic is None: dic = {} dic.update(copy.deepcopy(simArgs)) return dicTools
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
modelis assigned but never used.Remove the assignment to the unused variable
model:-model = setup_model()Tools
Ruff
99-99: Local variable
modelis assigned to but never usedRemove assignment to unused variable
model(F841)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (4)
12-12: LGTM!The new
#includestatement forsamrai_hdf5_particle_initializer.hppis necessary for the new case added to thecreatemethod and follows the existing naming convention.
23-23: LGTM!The changes to the
usingdirective forParticleInitializerTand thestd::make_uniquecalls forMaxwellianParticleInitializermaintain 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
createmethod for handling theinitializerName"samraih5" enhances the functionality of the factory and follows the existing structure and style. It properly retrieves the necessary parameters and initializes theSamraiHDF5ParticleInitializer.
18-18: Verify the impact of the namespace change on the rest of the codebase.The namespace change from
coretoamrindicates a potential shift in the organizational structure of the codebase. Ensure that all references to theParticleInitializerFactoryclass 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
coretoamrforParticleInitializerFactoryhas 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.hppsrc/amr/physical_models/hybrid_model.hpptests/core/numerics/ion_updater/test_updater.cpptests/amr/data/particles/initializer/test_main.cppScripts 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_wrapperclass looks good and serves the purpose of converting scalars and lists to arrays.
50-59: LGTM!The
fn_wrapperclass looks good and serves the purpose of wrapping calls to user init functions.
e9bc35a to
0d9fa53
Compare
There was a problem hiding this comment.
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
populateDictfunction 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_groupsmethod 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
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
popnot used within loop bodyRename unused
popto_pop(B007)
tests/simulator/test_samrai_restarts_parser.py
3-3:
timeimported but unusedRemove unused import:
time(F401)
5-5:
datetimeimported but unusedRemove unused import:
datetime(F401)
7-7:
numpyimported but unusedRemove unused import:
numpy(F401)
8-8:
pathlib.Pathimported but unusedRemove unused import:
pathlib.Path(F401)
9-9:
datetime.timedeltaimported but unusedRemove unused import:
datetime.timedelta(F401)
11-11:
ddt.dataimported but unusedRemove unused import
(F401)
11-11:
ddt.unpackimported but unusedRemove unused import
(F401)
18-18:
pyphare.pharesee.run.Runimported but unusedRemove unused import:
pyphare.pharesee.run.Run(F401)
22-22:
tests.diagnostic.dump_all_diagsimported but unusedRemove unused import:
tests.diagnostic.dump_all_diags(F401)
23-23:
pyphare.pharesee.hierarchy.patchdata.ParticleDataimported but unusedRemove unused import:
pyphare.pharesee.hierarchy.patchdata.ParticleData(F401)
24-24:
pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5imported but unusedRemove 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
modelis assigned to but never usedRemove 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_librariesdirective fromphare_coretophare_amrindicates a shift in dependencies. This could impact the functionality of the project ifphare_amrprovides different features or interfaces compared tophare_core.Run the following script to verify the impact of the dependency change:
Please ensure that:
- The codebase has been updated to use
phare_amrinstead ofphare_core.- The
phare_amrlibrary provides the necessary features and interfaces required by thetest-updaterproject.- The
test-updaterproject builds and runs successfully with thephare_amrdependency.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
popto_pop.Tools
Ruff
9-9: Loop control variable
popnot used within loop bodyRename unused
popto_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
ParticleInitializerFactoryis 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
ParticleInitializerFactorytype alias is approved. The update to useamr::ParticleInitializerFactorywith specific template parametersParticleArray_tandGridLayout_tlikely improves the functionality and adaptability of the particle initialization process within the simulation framework, while maintaining the overall structure ofPHARE_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:
timeimported but unusedRemove unused import:
time(F401)
5-5:
datetimeimported but unusedRemove unused import:
datetime(F401)
7-7:
numpyimported but unusedRemove unused import:
numpy(F401)
8-8:
pathlib.Pathimported but unusedRemove unused import:
pathlib.Path(F401)
9-9:
datetime.timedeltaimported but unusedRemove unused import:
datetime.timedelta(F401)
11-11:
ddt.dataimported but unusedRemove unused import
(F401)
11-11:
ddt.unpackimported but unusedRemove unused import
(F401)
18-18:
pyphare.pharesee.run.Runimported but unusedRemove unused import:
pyphare.pharesee.run.Run(F401)
22-22:
tests.diagnostic.dump_all_diagsimported but unusedRemove unused import:
tests.diagnostic.dump_all_diags(F401)
23-23:
pyphare.pharesee.hierarchy.patchdata.ParticleDataimported but unusedRemove unused import:
pyphare.pharesee.hierarchy.patchdata.ParticleData(F401)
24-24:
pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5imported but unusedRemove 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
Noneas the default and initializing the dictionary within the function:def dup(dic=None): if dic is None: dic = {} dic.update(copy.deepcopy(simArgs)) return dicTools
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
modelis assigned but never used.Remove the assignment to the unused variable
model:-model = setup_model()Tools
Ruff
99-99: Local variable
modelis assigned to but never usedRemove 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
ParticleInitializertype improves code readability and maintainability.
72-73: LGTM!The code change is approved. Fully qualifying the
MaxwellianParticleInitializertype maintains consistency with the new namespace structure and improves code readability.
83-84: LGTM!The code change is approved. Fully qualifying the
MaxwellianParticleInitializertype 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
SamraiHDF5ParticleInitializerbased 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
ParticleInitializerFactorytype 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 thestd::unordered_setcontainer in the code.
74-75: Improved flexibility and usability of thefile()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 modularGroupScannerstruct.The
GroupScannerstruct is a valuable addition to theHighFiveFileclass:
- It encapsulates the group scanning logic, promoting separation of concerns and modularity.
- The recursive
scanmethod efficiently traverses the groups in the HDF5 file.- The filtering functionality based on a vector of strings provides flexibility in selecting groups.
295-298: Usefulscan_for_groupsmethod utilizing theGroupScanner.The
scan_for_groupsmethod is a valuable addition to theHighFiveFileclass:
- It provides a convenient way to retrieve a set of group paths based on specified criteria.
- It leverages the
GroupScannerstruct to encapsulate the scanning logic, promoting code reuse and modularity.
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
Fixed
Show fixed
Hide fixed
e721d2a to
14357eb
Compare
There was a problem hiding this comment.
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.hppis 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
initializerNamevalue 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 inpopulate_fromMethodThe
populate_frommethod 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
samraih5initializer.The new conditional block for
initializerName == "samraih5"is a significant addition. It handles the initialization from a specified directory and uses theSamraiHDF5ParticleInitializer. 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_frommethod 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
createHighFiveFilehandles 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_attributemethod 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_idsretrieves 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_stringlacks 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
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
popnot used within loop bodyRename unused
popto_pop(B007)
tests/simulator/test_samrai_restarts_parser.py
3-3:
timeimported but unusedRemove unused import:
time(F401)
5-5:
datetimeimported but unusedRemove unused import:
datetime(F401)
7-7:
numpyimported but unusedRemove unused import:
numpy(F401)
8-8:
pathlib.Pathimported but unusedRemove unused import:
pathlib.Path(F401)
9-9:
datetime.timedeltaimported but unusedRemove unused import:
datetime.timedelta(F401)
11-11:
ddt.dataimported but unusedRemove unused import
(F401)
11-11:
ddt.unpackimported but unusedRemove unused import
(F401)
18-18:
pyphare.pharesee.run.Runimported but unusedRemove unused import:
pyphare.pharesee.run.Run(F401)
22-22:
tests.diagnostic.dump_all_diagsimported but unusedRemove unused import:
tests.diagnostic.dump_all_diags(F401)
23-23:
pyphare.pharesee.hierarchy.patchdata.ParticleDataimported but unusedRemove unused import:
pyphare.pharesee.hierarchy.patchdata.ParticleData(F401)
24-24:
pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5imported but unusedRemove 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
modelis assigned to but never usedRemove 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_coretophare_amrin thetarget_link_librariesdirective could have significant implications on the functionality and compatibility of the test executable. It is crucial to ensure thatphare_amrprovides all necessary functionalities and interfaces that were previously provided byphare_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 libraryphare_amr.The change from
phare_coretophare_amrin thetarget_link_librariesdirective is significant. It's crucial to ensure thatphare_amrprovides all the functionalities expected by the project that were previously covered byphare_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.dictatormay 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.hppis 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::amrnamespace for theParticleInitializerFactoryand the method call tocreateare 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 ofLoadBalancerto 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 toinitialize.user_fns.populateDict(sim)orinitialize.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::h5is appropriately used to encapsulate theGroupScannerfunctionality, 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 theloadParticlesmethod 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 theloadParticlesmethod 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
loadParticlesmethod 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 ImpactThe update to the
ParticleInitializerFactorytype alias enhances its specificity by using template parametersParticleArray_tandGridLayout_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
ParticleInitializerFactoryhave been updated accordingly.Run the following script to verify the usage of
ParticleInitializerFactoryacross the codebase:Verification successful
Verification Successful: Type Alias Update Integrated Correctly
The update to the
ParticleInitializerFactorytype alias has been successfully integrated across the codebase. All references toParticleInitializerFactorynow 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 classElectromagInitializer.The
ElectromagInitializerclass is designed as a base class with a virtual destructor and a virtualinitmethod. 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 classElectromagSamraiH5Initializer.This class also inherits from
ElectromagInitializerand specializes in initializing electromagnetic fields from HDF5 files using the SAMRAI framework. The use of a template forSamraiHDF5FieldInitializerto handle different field types is a robust design choice, allowing flexibility with field types. The loop in theinitmethod efficiently handles each field in the electromagnetic vector field. Ensure that theSamraiHDF5FieldInitializeris well-tested, especially with regards to file I/O operations and error handling.Verify the robustness and error handling of
SamraiHDF5FieldInitializerin 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
RestartsParserTestclass 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
modelis assigned to but never usedRemove 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
ParticleInitializerTtype alias to include thecore::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 forMaxwellianParticleInitializer.The changes to fully qualify
MaxwellianParticleInitializerwith thecore::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 ofSamraiH5Interfaceclass template.The
SamraiH5Interfaceclass template is well-structured for handling HDF5 files specific to SAMRAI data structures. However, there are a few points to consider:
- The use of
staticfor theINSTANCEmethod 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_fromandgetRestartFileFullPathare 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 ofdict_member variable.The inclusion of the
PHARE::initializer::PHAREDict dict_in theTestTaggerstruct is a positive change, centralizing the initialization logic for theHybridStateobject.
186-190: Approved: Newinitmethod inSinglePatchHybridModel.The addition of the
initmethod, which takesElectromagandGridLayoutTreferences, is well-implemented. It encapsulates the initialization logic, enhancing the clarity and maintainability of the code.
202-212: Approved: Overall structure and logic ofTestTagger.The updates to the
TestTaggerstruct, including the use ofcreateDict<dim>()for initializingdict_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_Initializersin the constructor.The addition of
_Initializersin the constructor usingstd::make_uniqueis 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_Initializersclass 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 theloadParticlesmethod 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 toParticleInitializerFactorytype alias.The change from
core::ParticleInitializerFactorytoamr::ParticleInitializerFactoryreflects 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 toParticleInitializerFactoryare updated accordingly.Verification successful
Namespace Update Verified for
ParticleInitializerFactory.The transition from
core::ParticleInitializerFactorytoamr::ParticleInitializerFactoryhas 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.hppsrc/amr/physical_models/hybrid_model.hpptests/core/numerics/ion_updater/test_updater.cpptests/amr/data/particles/initializer/test_main.cppScripts 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_groupsmethod and theGroupScannerstruct enhances the functionality of theHighFiveFileclass 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 ofinit_optionsin thewrapperfunction.The
wrapperfunction has been updated to handleinit_options. Ensure that:
- The
init_optionsare correctly processed and integrated into thekwargsdictionary.- 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.
- Unused Loop Variable: The variable
popis not used within the loop. If the details ofpopare not needed, consider renaming it to_to indicate it's intentionally unused.- String Operations: The construction of
partinit_pathinvolves 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
popnot used within loop bodyRename unused
popto_pop(B007)
src/amr/data/field/initializers/samrai_hdf5_field_initializer.hpp (2)
44-49: Clarify or implement the
loadmethod.The
loadmethod 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
GroupScannerreview.The
GroupScanneris well-designed with clear responsibilities. However, there are several improvements and issues to address:
- Const-correctness: The constructor should mark
contains_asstd::vector<std::string>&&to avoid unnecessary copies if the caller can move the vector.- Performance: The recursive
scanfunction can be optimized by passingstd::stringby reference to avoid copies.- 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
ElectromagInitializerand overrides theinitmethod. It uses aVecFieldInitobject for initializing the magnetic field vector. The constructor initializesBinit_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
ElectromagInitializerFactoryuses a dictionary to decide which initializer to create, which is a flexible design allowing runtime decisions. The use ofstd::make_uniqueensures 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, andpyphare.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_h5Also applies to: 5-5, 7-7, 8-8, 9-9, 11-11, 18-18, 22-22, 23-23, 24-24
Tools
Ruff
3-3:
timeimported but unusedRemove unused import:
time(F401)
51-63: Refactor recursive function for clarity and efficiency.
The function
traverse_h5_for_groups_recursiveis 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
modelis 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
modelis assigned to but never usedRemove 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
Noneas 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 dicCommittable 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 dicTools
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
getRestartFileFullPathuses manual string concatenation to build file paths. This is generally fine but can be error-prone and less efficient than using more robust methods likestd::ostringstreamorfmt::format(if available).Consider using
std::ostringstreamfor 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
SamraiHDF5Filestructure.The nested
SamraiHDF5Filestructure withinSamraiH5Interfaceis a good use of C++ inheritance and encapsulation. The use ofHighFive::CompoundTypeto 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
getBoxFromPathis 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
getBoxFromPathdoes not lead to unexpected crashes in cases where the dataset might not meet this expectation.
163-184: Review of
populate_frommethod.The
populate_frommethod effectively demonstrates the use of theSamraiHDF5Filestructure 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 (
INITIAZILIZERSshould beINITIALIZERS). 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 theinitializemethod is concerning. This operation detaches the managed object from theunique_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 thefile()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 typeHiFile&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_wrapperclass.The
py_fn_wrapperclass 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_wrapperclass for potential improvements.The
fn_wrapperclass extendspy_fn_wrapperand adds functionality to convert numpy arrays to C++SubSpan. Consider the following:
- Documentation: Like its parent class,
fn_wrapperlacks documentation. Adding detailed docstrings would clarify its role and usage.- Error Handling: The class does not handle potential exceptions from the
cpp_etc_lib().makePyArrayWrappercall. 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, andadd_size_tare 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_tfunction 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
populateDictfunction.The
populateDictfunction 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
simobject. 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
populateDictfunction 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_doublecall.The variable
simulationis not defined within the scope of theadd_doublefunction call. This will raise aNameErrorat runtime. It seems like it should besim.tagging_thresholdinstead ofsimulation.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_arrayfunction.The function currently assumes that the input vector has at least
To_Sizeelements. This could lead to undefined behavior if the vector is smaller thanTo_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_optionscorrectly 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
There was a problem hiding this comment.
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 SignatureThe class
SamraiHDF5ParticleInitializeris well-structured for its purpose, using templates to handle different particle arrays and grid layouts. The inheritance fromcore::ParticleInitializeris correctly applied. However, the methodloadParticleslacks 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 toMaxwellianParticleInitializerto use the fully qualified namespace.The following files contain instances of
MaxwellianParticleInitializerwithout thecore::prefix, which need to be updated to ensure consistency with the namespace restructuring:
tests/core/data/maxwellian_particle_initializer/test_init_funcs.hppsrc/core/data/ions/particle_initializers/maxwellian_particle_initializer.hppPlease update these references to use
core::MaxwellianParticleInitializer<ParticleArray, GridLayout>.Analysis chain
Ensure consistency in namespace usage for
MaxwellianParticleInitializer.The
MaxwellianParticleInitializerreferences 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 toMaxwellianParticleInitializerare 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 toParticleInitializerto use fully qualified names.The following files contain references to
ParticleInitializer<ParticleArray, GridLayout>without thecore::namespace. To maintain consistency and avoid potential issues, these should be updated tocore::ParticleInitializer<ParticleArray, GridLayout>.
src/core/data/ions/particle_initializers/maxwellian_particle_initializer.hpptests/core/data/maxwellian_particle_initializer/test_init_funcs.hppAnalysis chain
Clarify the usage of fully qualified names in type aliases.
The type alias
ParticleInitializerTnow 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 toParticleInitializerin 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 classHighFiveFile.The class
HighFiveFileis 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
createHighFiveFileprints 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
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:
timeimported but unusedRemove unused import:
time(F401)
5-5:
datetimeimported but unusedRemove unused import:
datetime(F401)
7-7:
numpyimported but unusedRemove unused import:
numpy(F401)
8-8:
pathlib.Pathimported but unusedRemove unused import:
pathlib.Path(F401)
9-9:
datetime.timedeltaimported but unusedRemove unused import:
datetime.timedelta(F401)
11-11:
ddt.dataimported but unusedRemove unused import
(F401)
11-11:
ddt.unpackimported but unusedRemove unused import
(F401)
18-18:
pyphare.pharesee.run.Runimported but unusedRemove unused import:
pyphare.pharesee.run.Run(F401)
19-19:
pyphare.simulator.simulator.Simulatorimported but unusedRemove unused import:
pyphare.simulator.simulator.Simulator(F401)
22-22:
tests.diagnostic.dump_all_diagsimported but unusedRemove unused import:
tests.diagnostic.dump_all_diags(F401)
23-23:
pyphare.pharesee.hierarchy.patchdata.ParticleDataimported but unusedRemove unused import:
pyphare.pharesee.hierarchy.patchdata.ParticleData(F401)
24-24:
pyphare.pharesee.hierarchy.fromh5.get_all_available_quantities_from_h5imported but unusedRemove 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 ImplementationThe
loadParticlesmethod inSamraiHDF5ParticleInitializerclass includes a basic logging statement. Consider enhancing this logging to include more context such aspopnameor details about theparticlesandlayout. 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 forsamraih5.A new case has been added for
initializerName == "samraih5", which involves creating aSamraiHDF5ParticleInitializer. 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 theSamraiH5InterfaceandSamraiHDF5ParticleInitializerare 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_groupsmethod.The addition of the
scan_for_groupsmethod enhances theHighFiveFileclass by enabling the scanning of groups within an HDF5 file based on specified criteria. This method leverages theGroupScannerstruct to perform the scanning, which is a good use of encapsulation and modularity.However, ensure that the
GroupScanneris thoroughly tested, especially since it involves recursive traversal which can be prone to errors if not handled carefully.
85724ca to
bdf8576
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (4)
src/amr/data/particles/initializers/particle_initializer_factory.hpp (4)
27-27: Inconsistent namespace in type aliasThe type alias
ParticleInitializerTstill usescore::ParticleInitializerdespite the namespace change toamr. This creates inconsistency in the codebase.
76-88: Consider updating namespace for consistencyThe code continues to use
core::MaxwellianParticleInitializerandcore::Basisenums. For consistency with the namespace migration toamr, consider updating these references if the corresponding classes have been moved.
92-105: Add validation for required dictionary keys and error handlingThe samraih5 initializer assumes required keys exist in the dictionary without validation, and the external call to
populate_fromlacks error handling.
107-107: Improve exception message informativenessThe exception message could be more helpful by including the unrecognized initializer name from the
initializerNamevariable.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 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 supportThe conditional compilation block properly isolates the HIGHFIVE-dependent includes, maintaining clean separation of optional dependencies.
22-22: LGTM: Namespace updated to reflect code reorganizationThe namespace change from
coretoamraligns with the broader code reorganization mentioned in the AI summary.
111-111: LGTM: Namespace closing comment updatedThe namespace closing comment properly reflects the updated namespace.
e66b0df to
6009bd3
Compare
There was a problem hiding this comment.
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 checksCurrent math may overflow in 32-bit intermediates; add casts to size_t and validate
i,jwithin 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 checksSame 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 checkReturning
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_InitializersThe name
_Initializersstarts 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 ofinitializers_Calling
initializers_.release();transfers ownership without deleting the object, causing a memory leak. Thestd::unique_ptrshould automatically handle the object's lifetime. Additionally, releasing it could cause null pointer dereferences ifinitializers_is accessed after this point.pyphare/pyphare/pharein/initialize/general.py (6)
21-23: Move imports to the top-level scopeImporting 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: UseValueErrorinstead ofRuntimeErrorinadd_size_t
ValueErroris 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 inadd_vector_intto handle non-iterable inputsThe function assumes that
valis iterable. If a non-iterable is passed, it will raise aTypeError. Adding explicit type checking can provide a clearer error message.
198-199: UseValueErrorinstead ofRuntimeErrorfor negative populations
ValueErrorprovides a clearer indication that the input value is invalid.
314-318: Add type handling for electron attributes insim.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 inpop_pathto prevent data overwritingThe
pop_pathvariable 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.hppisn’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) + raiseRuff 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 box2datasetsrc/amr/physical_models/hybrid_model.hpp (2)
231-239: Consider error handling for missing particle initializersThe constructor creates particle initializers for each population but doesn't validate that creation succeeded. If
ParticleInitializerFactory::createreturns nullptr for an invalid configuration, the map would store a null pointer leading to crashes when dereferenced inparticles().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 accessThe
particles()method directly accesses the map without checking if the population exists, which could throwstd::out_of_rangeif 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 unnecessaryint()castThe 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 downpopulateDictinto smaller functionsThis 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 formattingThe 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
📒 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.hppsrc/core/data/ions/ions.hppsrc/core/data/electromag/electromag.hppsrc/amr/physical_models/hybrid_model.hppsrc/core/data/grid/gridlayout.hppsrc/amr/data/initializers/samrai_hdf5_initializer.hppsrc/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 nameParticleInitializer::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).
src/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hpp
Show resolved
Hide resolved
e64ba6c to
7d40b01
Compare
There was a problem hiding this comment.
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(fromnCells_in the classes using this viewer) but the result issize_t. Additionally, there is no validation that the input indexes are within the valid range defined bynCells.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
asserton 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 itUsing
INTERFACEhere 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 toPUBLIC(or at leastPRIVATE) 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&andHiFile const&) for better code readability, especially for developers unfamiliar with the implementation.
256-259: Add const qualifier toscan_for_groupsmethod.The method does not modify any member variables and should be marked
constto improve const-correctness and allow it to be called on const instances ofHighFiveFile.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) constsrc/hdf5/detail/h5/group_scanner.hpp (2)
29-34: Specify explicit return type.The
scanmethod returnsauto&, which reduces clarity. Consider using an explicit return typestd::unordered_set<std::string>&or, preferably, returning by value to match the usage pattern inh5_file.hppand 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 usingstd::all_ofto 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
unittestandnumpyimports 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
pis 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}") + raisepyphare/pyphare/pharein/initialize/samrai_hdf5.py (1)
6-16: Rename unused loop variable.The loop variable
popis not used within the loop body and should be renamed to_popto 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.getUse 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 constructorCleaner and conveys intent.
- SamraiHDF5FieldInitializer() {} + SamraiHDF5FieldInitializer() = default;
43-47: Assert pointers before derefGuard 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 macroUse 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 readsCheck dataset existence or catch read exceptions to improve diagnostics when files/paths are missing.
1-2: Fix typo in include guard macroUse 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 countMore 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 dictIf 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 KeyErrorValidate presence or provide defaults before registration.
11-11: Deduplicate addInitFunction retrievalExtract 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 constexpris 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_diagsAlso 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
intparameters 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_fromlacks 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
samraih5initializer assumes thatdictcontainsfilepath,index, andmpi_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: Avoidreinterpret_castfor type conversion.Using
reinterpret_castassumes that the memory layout of the SAMRAI type is compatible withstd::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
boxescontains at least one element. Ifboxesis empty, accessingboxes[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 variabledict_.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. Sinceinitializers_is astd::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 tonullptrinstead, 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.hppinclude 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 errorsConsider 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 constructorSmall 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 countBe 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
Thisis placed before thepublic: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
simparameter is unused insetup_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 unnecessaryint()cast.The value
len(boxes)is already an integer, so the explicitint()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: UseValueErrorfor invalid input value.When validating input,
ValueErroris more semantically appropriate thanRuntimeErrorfor 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: UseValueErrorfor negative population count.Consistent with best practices, use
ValueErrorinstead ofRuntimeErrorwhen 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= defaultfor empty destructor and addoverride.The virtual destructor can be defaulted for clarity and explicitly marked with
overrideto indicate it overrides the base class destructor.Apply this diff:
- virtual ~ElectromagUserFuncInitializer() {} + ~ElectromagUserFuncInitializer() override = default;
63-63: Use= defaultfor empty destructor and addoverride.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
📒 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.hppsrc/amr/data/field/initializers/samrai_hdf5_field_initializer.hppsrc/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hppsrc/core/data/vecfield/vecfield_initializer.hppsrc/amr/physical_models/hybrid_model.hppsrc/core/data/ions/particle_initializers/particle_initializer.hppsrc/core/data/ndarray/ndarray_vector.hppsrc/amr/level_initializer/hybrid_level_initializer.hppsrc/hdf5/detail/h5/h5_file.hppsrc/core/data/electromag/electromag.hppsrc/amr/data/electromag/electromag_initializer.hppsrc/core/data/grid/gridlayout.hppsrc/core/data/ions/ions.hppsrc/hdf5/detail/h5/group_scanner.hppsrc/amr/data/particles/initializers/particle_initializer_factory.hppsrc/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_groupsfunctionality 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
loadParticlessignature.
63-63: LGTM!The test correctly passes the population name parameter to match the updated
loadParticlessignature.src/core/data/vecfield/vecfield_initializer.hpp (1)
30-30: LGTM!Adding the
constqualifier to theinitializemethod 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
popnamemaintains API consistency across particle initializers. The parameter is currently unused but reserved for future implementation.
140-140: LGTM!The
popnameparameter 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
popnameparameter 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
virtualkeyword is correct. Theoverridespecifier 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_optionsGood addition to accepted_keywords.
713-714: Init options validated earlyCalling 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 toinitialize.general,initialize.user_fns, orinitialize.samrai_hdf5based onsim.init_optionsimproves 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
populateDictfunction 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
ElectromagInitializerbase class provides a clean interface with a virtualinitmethod 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 parameterizedAMRToLocalimplementation.The two-argument
AMRToLocalmethod correctly validates that local indices are non-negative before converting touint32_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
domainBoxForandghostBoxFormethods provide a clean abstraction for retrieving field-specific boxes. The implementation correctly delegates to_BoxForwith appropriate start-to-end functions.
1264-1276: LGTM on the dimension-agnostic_BoxForimplementation.The refactored
_BoxFormethod uses a compile-time loop with a direction array, making it more maintainable and dimension-agnostic. The implementation correctly iterates only up todimension, 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.hppandparticle_initializer_factory.hppproperly support the factory-based initialization pattern introduced in this PR.
418-419: LGTM on factory-based electromag initialization.The code correctly uses
ElectromagInitializerFactory_t::createto instantiate the appropriate initializer and callsinitto initialize the electromagnetic fields. This aligns with the new factory pattern.
424-424: LGTM on updatedloadParticlessignature.The addition of
pop.name()as a parameter toloadParticlesprovides necessary context for population-specific initialization, consistent with the updated API.src/amr/physical_models/hybrid_model.hpp (1)
221-248: LGTM on the_Initializersstruct design (naming aside).The
_Initializersstruct 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.
| 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 |
There was a problem hiding this comment.
🛠️ 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 directoryTo 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"ininit_optionsand error if not informats(include supported values). - Support and validate a top‐level
"dir"key (used byinitialize.samrai_hdf5) and nestedinit_options["options"]["dir"]via a newcheck_existing_directoryhelper 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.
| #include "core/data/grid/gridlayoutdefs.hpp" | ||
| #include "core/data/ndarray/ndarray_vector.hpp" | ||
|
|
||
| #include "core/utilities/types.hpp" | ||
| #include "core/utilities/point/point.hpp" | ||
|
|
There was a problem hiding this comment.
🛠️ 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.
| #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" | ||
|
|
There was a problem hiding this comment.
🧩 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.
| 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...)]; | ||
| } |
There was a problem hiding this comment.
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.
15cb5bb to
d2be573
Compare
There was a problem hiding this comment.
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
INITIAZILIZERSbut should beINITIALIZERS.
5-10: Include box.hpp to make the header self-contained.The code uses
core::Boxandgrowwithout 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
h5FilePtrandpdataptrwithout 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
#errordirective 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_gboxare 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
📒 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.hppsrc/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
amrnamespace but correctly uses types from thecorenamespace (ParticleInitializer,MaxwellianParticleInitializer). Including fromcore/data/ions/particle_initializers/is appropriate.
27-27: Type alias correctly references core namespace.The past review comment suggesting to change this to
amr::ParticleInitializeris incorrect. TheParticleInitializertype is defined in thecorenamespace, and the factory inamrcorrectly uses it via thecore::qualifier.
76-77: Namespace usage is correct for core types.The past review comments suggesting to change
core::MaxwellianParticleInitializertoamr::MaxwellianParticleInitializerare incorrect. These types are defined in thecorenamespace, and the factory correctly instantiates them with thecore::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_initializerandparticle_initializer_factoryare 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
GridLayoutdefinition 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 aunique_ptrthat's immediately used to initialize fieldsloadParticlessignature updated to includepop.name()as required by the new APIsrc/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.
There was a problem hiding this comment.
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 axesAll 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 readsReading 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 includeThis 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_fromCheck 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 headerThe 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 ctorPrefer = default for clarity.
Apply:
- SamraiHDF5ParticleInitializer() {} + SamraiHDF5ParticleInitializer() = default;Based on learnings.
65-67: Optional: pre-reserve to reduce reallocationsReserve 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 messageInclude 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
📒 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.hppsrc/simulator/phare_types.hppsrc/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: LGTMBrings in the new electromag and particle initializer factories appropriately.
170-178: Alias cleanup: LGTMSwitching 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: LGTMUsing IonUpdater::Interpolator reduces template verbosity.
3a690c9 to
24d906c
Compare
There was a problem hiding this comment.
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 duplicateghostBoxFordefinition.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 buffersThese two assertions compare old/new ghosts to
alphaLevelGhostinstead ofalphaLevelGhostOld/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:
INITIAZILIZERSshould beINITIALIZERS.-#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:
INITIAZILIZERSshould beINITIALIZERS.-#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
popis not used within the loop body. Rename it to_popto 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_groupsmethod doesn't modify any member variables and should be markedconstto 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) constpyphare/pyphare/pharein/simulation.py (1)
537-551: Validate top-level init_options["dir"] key used by samrai_hdf5.The
samrai_hdf5.pymodule (line 14) accessessim.init_options["dir"]directly, butcheck_init_optionsonly validates the nested path atinit_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_optionssrc/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
initmethod accessesdict_["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
virtualkeyword is redundant in derived class destructors when the base class destructor is already virtual. Useoverrideand= defaultfor clarity.Apply this diff:
- virtual ~ElectromagUserFuncInitializer() {} + ~ElectromagUserFuncInitializer() override = default;
63-63: Simplify destructor declaration.The
virtualkeyword is redundant here. Useoverrideand= 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
samraih5initializer assumesdictcontainsfilepath,index, andmpi_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_Initializersto a non-reserved nameLeading underscore + capital is reserved in C++. Rename to
Initializersand 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: replacerelease()withreset(), and avoid returning a dangling reference
initializers_.release();leaks. Usereset()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) andnumpy(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
passigned 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, andtest_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
simparameter insetup_modelis 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
initializepackage 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 returnauto&instead ofHiFile&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
getDataSetandreadoperations 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 togroups. Explicitly specifyingstd::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
contis not immediately clear. The intent is to include paths that contain all strings in thecontainsvector. Usingstd::all_ofmakes 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 theint()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 outerParticleInitializerFactoryThis 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 unuseddict_member to reduce footprint
dict_isn’t used after constructingelectromag_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 destructorUse
= defaultfor clarity and consistency.- virtual ~HybridModel() override {} + ~HybridModel() override = default;tests/core/numerics/ion_updater/test_updater.cpp (1)
372-376: UnifyGridLayoutalias style for clarityElsewhere 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
📒 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.hppsrc/hdf5/detail/h5/group_scanner.hppsrc/core/data/electromag/electromag.hppsrc/amr/level_initializer/hybrid_level_initializer.hppsrc/hdf5/detail/h5/h5_file.hppsrc/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hppsrc/amr/data/initializers/samrai_hdf5_initializer.hppsrc/core/data/ions/particle_initializers/particle_initializer.hppsrc/simulator/phare_types.hppsrc/amr/data/electromag/electromag_initializer.hppsrc/core/data/grid/gridlayout.hppsrc/core/data/ndarray/ndarray_vector.hppsrc/amr/physical_models/hybrid_model.hppsrc/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 newstd::string const& popnameparameter.
14-16: LGTM!The addition of the
popnameparameter 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
overridewithoutvirtual, 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
requiresclause 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_tcast 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
directionsarray contains all three directions, but the loop at line 1269 only iteratesi < 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_coretophare_amrcorrectly reflects the migration ofParticleInitializerFactoryfrom 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 thescan_for_groupsmethod added below.src/simulator/phare_types.hpp (1)
28-30: LGTM: ParticleInitializerFactory alias updated to reference amr namespace.The change from
core_types::ParticleInitializerFactory_tto the explicitly templatedamr::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 tocheck_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
popnameandParticlePackerkeys- Reads particles into a temporary
ContiguousParticlescontainer- 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
coretoamrand 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
Thisandvecfield_typetype 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::MaxwellianParticleInitializerandcore::Basisis appropriate, as these classes remain in thecorenamespace. The factory correctly resides in theamrnamespace 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 ofstate{dict_}correctly implements the new factory-based initialization pattern. The test properly delegates electromagnetics initialization to the newinitmethod.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 onsim.init_options. This improves maintainability and separation of concerns.pyphare/pyphare/pharein/initialize/general.py (1)
89-318: LGTM! Comprehensive configuration builder.The
populateDictfunction 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.
| ElectromagSamraiH5Initializer(initializer::PHAREDict const& dict) | ||
| : dict_{dict} | ||
| { |
There was a problem hiding this comment.
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.
| auto& particles(typename Ions::value_type& pop) { return *particle_pop_init[pop.name()]; } | ||
|
|
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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:
INITIAZILIZERSshould beINITIALIZERS.
5-10: Header is not self-contained (missing Box/grow includes).The header uses
core::Boxand thegrowutility but doesn't directly include their definitions.
43-49: Add null pointer checks and HDF5 error handling.
h5FilePtrandpdataptrare dereferenced without validation. Additionally, the HDF5read_data_set_flatcall 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 volumesrc/amr/data/initializers/samrai_hdf5_initializer.hpp (7)
50-51: Pass small built-in types by value.Parameters
idxandmpi_sizeare passed by const reference, butintis 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
intparameters by value and consider passing thepathparameter 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:
INITIAZILIZERSshould beINITIALIZERS.
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: Unsafereinterpret_castviolates type safety and may cause undefined behavior.The
reinterpret_castassumes the internal layout of SAMRAI's integer box structure matchesstd::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:
INITIAZILIZERSshould beINITIALIZERS.
51-64: Add null pointer checks and validate HDF5 read operations.
h5FilePtrandpdataptrare dereferenced without validation. Additionally, the HDF5getDataSet().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()anddomainBoxFor()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.,physicalStartIndexat 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
directionsarray always allocates 3 elements regardless of the actualdimension. For clarity and to avoid confusion, you could size it to matchdimension: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
📒 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.hppsrc/amr/data/field/initializers/samrai_hdf5_field_initializer.hppsrc/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hppsrc/core/data/grid/gridlayout.hppsrc/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
AMRToLocalwith thelocalboxargument is well-implemented. The assertion on line 816 correctly validates thatlocal >= 0before the cast touint32_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
AMRToLocalto bothlowerandupperbounds.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_boxandlcl_dst_boxhave 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()andpopulate_from()method use a size check (line 119) to avoid re-population, but this is not thread-safe if multiple threads callpopulate_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_oncefor initialization
| 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); | ||
| } |
There was a problem hiding this comment.
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.
| 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.
| core::apply(soa.as_tuple(), [&](auto& arg) { | ||
| auto const datapath = poppath + Packer::keys()[part_idx++]; | ||
| h5File.file().getDataSet(datapath).read(arg); | ||
| }); |
There was a problem hiding this comment.
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.
222a021 to
2a5f606
Compare
There was a problem hiding this comment.
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_yandmagnetic_zget 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_coretophare_amris 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 thati < from.size(). IfTo_Sizeexceeds 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 emptyfailedlist.Line 601 accesses
self.failed[0][0]without verifying thatfailedis non-empty, which will raise anIndexErrorif 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_tbefore being converted tosize_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 typeHiFile&(andHiFile const&for the const overload) would improve readability and maintainability.
260-263: Addconstqualifier toscan_for_groupsmethod.The method does not modify any member variables and should be marked
constto improve const-correctness and allow it to be called on const instances ofHighFiveFile.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) constsrc/hdf5/detail/h5/group_scanner.hpp (1)
48-57: Improve filtering logic clarity.The variable
contis unclear and the nested loop could be replaced with standard algorithms likestd::all_offor 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:
- Line 533:
kwargs.get("init_options", None)can be simplified tokwargs.get("init_options")sinceNoneis the default.- Lines 535-537: The format validation should be mandatory when
init_optionsis provided, and the error message should list valid formats.- The function should validate both top-level
dirand nestedoptions["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_optionssrc/core/data/electromag/electromag.hpp (1)
24-24: Reorder specifiers for consistency.The specifier order
auto static constexpris 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 SimulatorTestpyphare/pyphare/pharein/initialize/general.py (1)
198-200: UseValueErrorfor 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: UseValueErrorfor 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 duplicateaddInitFunctionretrieval.The retrieval of
addInitFunctionis duplicated in bothpopulate_electromagandpopulate_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 functionsrc/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
94-106: Remove UB reinterpret_cast and guard empty SAMRAI boxes.The old
reinterpret_castassumes SAMRAI’s box layout matchesstd::array<int,3>—that’s undefined behaviour and already raised earlier. We still also dereferenceboxes[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
virtualkeyword is redundant because the base class destructor is already virtual. Consider usingoverrideand= default.Apply this diff:
- virtual ~ElectromagUserFuncInitializer() {} + ~ElectromagUserFuncInitializer() override = default;
59-61: Remove unused member variabledict_.The
dict_member is initialized but never used in theinitmethod. 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
virtualkeyword is redundant because the base class destructor is already virtual. Consider usingoverrideand= 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, useinitializers_.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_Initializersto 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
InitializersorInitializerState.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 ofoperator[]to prevent undefined behavior.
operator[]can default-insert a nullunique_ptrif the key doesn't exist, then dereferencing it causes undefined behavior. Use.at()which throwsstd::out_of_rangeon 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/modulefilesentry, 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/modulefilesres/__tc/nightly/2_test.sh (2)
6-6: Remove duplicate path in MODULEPATH.The path
/etc/scl/modulefilesappears 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_CORESis 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-failureres/__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 -vres/__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 -ares/__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.shrather than requiringbash 0_config.sh.Apply this change:
+#!/bin/bash + pwd set -ex ulimit -ares/__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.shrather than requiringbash 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/samraiexists, 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 1res/__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.shrather than requiringbash 2_test.sh.Apply this change:
+#!/bin/bash + set -exres/__tc/gcc_samraisub/2_test.sh (1)
5-7: Remove duplicate path in MODULEPATH.The MODULEPATH on line 6 contains
/etc/scl/modulefilestwice, 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/modulefilesBased on learnings: PhilipDeegan prefers minimal and efficient code.
src/core/data/ndarray/ndarray_vector.hpp (1)
5-5: Remove unused includecore/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_PRELOADvariable is computed but never used. OnlyCLANG_ASAN_PRELOADis 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_PRELOADvariable is computed but never used. OnlyCLANG_ASAN_PRELOADis 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 unusedsimparameter.The
simparameter 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: UseValueErrorfor invalid input.When validating input arguments,
ValueErroris more appropriate thanRuntimeErrorfor 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 redundantint()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
popis 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]_HPPwithout 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_HPPAnd 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
📒 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.hppsrc/core/utilities/types.hppsrc/core/data/ions/particle_initializers/maxwellian_particle_initializer.hppsrc/amr/data/particles/initializers/particle_initializer_factory.hppsrc/hdf5/detail/h5/group_scanner.hppsrc/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hppsrc/amr/data/initializers/samrai_hdf5_initializer.hppsrc/hdf5/detail/h5/h5_file.hppsrc/amr/physical_models/hybrid_model.hppsrc/amr/data/electromag/electromag_initializer.hppsrc/core/data/electromag/electromag.hppsrc/core/data/grid/gridlayout.hppsrc/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.shres/__tc/gcc/1_build.shtests/simulator/CMakeLists.txtres/__tc/nightly/1_build.shtests/amr/data/particles/initializer/CMakeLists.txttests/core/numerics/ion_updater/CMakeLists.txtres/__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.shtests/simulator/CMakeLists.txtres/__tc/nightly/1_build.shtests/amr/data/particles/initializer/CMakeLists.txttests/core/numerics/ion_updater/CMakeLists.txtres/__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.shres/__tc/clang_samraisub/0_config.shres/__tc/clang/0_config.shres/__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.pytests/simulator/test_init_from_restart.pypyphare/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.pysrc/amr/data/initializers/samrai_hdf5_initializer.hppsrc/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.hppsrc/amr/data/initializers/samrai_hdf5_initializer.hpptests/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)
res/__tc/clang/0_config.sh
Outdated
| pwd | ||
| set -ex | ||
| ulimit -a | ||
| clang -v | ||
| ldd --version | ||
| ld -v |
There was a problem hiding this comment.
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.
| 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.
res/__tc/clang/1_build.sh
Outdated
| set -ex | ||
|
|
||
| [ -z "$N_CORES" ] && echo "N_CORES not set: error" && exit 1 |
There was a problem hiding this comment.
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.
| 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.
res/__tc/clang/2_test.sh
Outdated
| set -ex | ||
| pwd | ||
| ulimit -a |
There was a problem hiding this comment.
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.
| 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.
res/__tc/clang/3_test_mpi.sh
Outdated
| set -ex | ||
| pwd | ||
| ulimit -a |
There was a problem hiding this comment.
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.
| 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.
res/__tc/nightly/0_config.sh
Outdated
| @@ -0,0 +1,6 @@ | |||
| pwd | |||
There was a problem hiding this comment.
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.
| 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.
res/__tc/nightly/1_build.sh
Outdated
| @@ -0,0 +1,14 @@ | |||
| set -ex | |||
There was a problem hiding this comment.
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.
| 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.
res/__tc/nightly/1_build.sh
Outdated
| [ -z "$N_CORES" ] && echo "N_CORES not set: error" && exit 1 | ||
|
|
||
| ( | ||
| mkdir build && cd build |
There was a problem hiding this comment.
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 buildAlternatively, 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.
| 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.
res/__tc/nightly/2_test.sh
Outdated
| @@ -0,0 +1,19 @@ | |||
| set -ex | |||
There was a problem hiding this comment.
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.
| 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).
res/__tc/nightly/3_test_mpi.sh
Outdated
| @@ -0,0 +1,24 @@ | |||
| set -ex | |||
There was a problem hiding this comment.
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.
| 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.
2a5f606 to
4fb2794
Compare
There was a problem hiding this comment.
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
magneticFieldfrom"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
nCellselements (which areuint32_t) can overflow before conversion tosize_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
idxfunction 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
atoverload directly indexes into the data array without any bounds validation, relying entirely on theidxfunction. Sinceidxdoes not validate bounds (as flagged above), out-of-bounds access can occur silently in release builds.Once bounds checking is added to the
idxfunction, 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
asserton 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_restartsApply 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_diagsAlso applies to: 4-4, 15-15
10-10: Remove unused imports from patchdata.
FieldDataandParticleDataare 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_h5pyphare/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 anIndexError.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 viewWe 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
dataand 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_optionscallscheck_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-levelinit_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 directorydef 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_optionssrc/amr/data/initializers/samrai_hdf5_initializer.hpp (1)
102-106: Handle missing box metadata before indexing
SAMRAI::tbox::HDFDatabase::getDatabaseBoxVectorcan legitimately return an empty collection. Line 104 then doesboxes[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 notrelease()the_Initializershelper.Line 151 calls
initializers_.release(), which both leaks the_Initializersinstance and leavesinitializers_null. The very nextinitialize()invocation (or any use ofinitializers()) will dereference that null pointer and crash. Please drop therelease()(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 theNO_DISCARDattribute:- 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
_BoxForeliminates code duplication by using an array-based approach. The loop correctly accesses only the firstdimensionelements of thedirectionsarray, making it safe for all dimensionalities.Optionally, consider making the
directionsarraystatic constexprfor 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.hppheader 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
popis not used within the loop body. Onlypop_indexis 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
📒 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.hppsrc/core/data/ions/particle_initializers/particle_initializer.hppsrc/core/data/ions/particle_initializers/maxwellian_particle_initializer.hppsrc/core/data/vecfield/vecfield_initializer.hppsrc/core/data/electromag/electromag.hppsrc/hdf5/detail/h5/group_scanner.hppsrc/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hppsrc/amr/level_initializer/hybrid_level_initializer.hppsrc/amr/data/particles/initializers/particle_initializer_factory.hppsrc/core/data/grid/gridlayout.hppsrc/core/data/ndarray/ndarray_vector.hppsrc/hdf5/detail/h5/h5_file.hppsrc/amr/data/initializers/samrai_hdf5_initializer.hppsrc/core/utilities/box/box.hppsrc/amr/data/field/initializers/samrai_hdf5_field_initializer.hppsrc/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.txttests/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.txttests/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.txtsrc/hdf5/detail/h5/h5_file.hppsrc/amr/data/initializers/samrai_hdf5_initializer.hppsrc/amr/data/field/initializers/samrai_hdf5_field_initializer.hpppyphare/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.txtpyphare/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.hppsrc/core/data/electromag/electromag.hppsrc/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.pypyphare/pyphare/pharein/initialize/__init__.pypyphare/pyphare/pharesee/hierarchy/hierarchy_utils.pytests/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.hppsrc/amr/data/particles/initializers/samrai_hdf5_particle_initializer.hppsrc/amr/data/initializers/samrai_hdf5_initializer.hpptests/core/numerics/ion_updater/test_updater.cppsrc/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_coretophare_amris 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_amrwill not receive HighFive's include directories during its own compilation, only its consumers will. This is correct ifphare_amrdoes not directly include HighFive headers in its sources.Verify one of the following:
- If
phare_amrsources include HighFive headers directly (e.g.,#include <highfive/...>): changeINTERFACEtoPUBLIC- If HighFive is only used by consumers of
phare_amr:INTERFACEscope is acceptable and the code is correctsrc/core/data/grid/gridlayout.hpp (6)
786-802: Well-designed coordinate transformation.The addition of the
localboxparameter toAMRToLocalprovides 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
domainBoxFormethod follows the same pattern asghostBoxFor, correctly usingphysicalStartToEndto define domain boundaries.src/core/data/ndarray/ndarray_vector.hpp (1)
264-270: LGTM!The
requiresclause 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_utilitiesandboxare 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
osanddataclassesare used in the updatedEqualityReportimplementation.
604-606: LGTM: Method chaining enabled.Returning
selffrom__call__allows for fluent API usage.src/simulator/phare_types.hpp (1)
28-30: LGTM: Factory alias updated to AMR namespace.The
ParticleInitializerFactoryalias 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
loadParticlescorrectly include the newpopnameparameter, 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
popnameparameter 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 ofadd_vector_int.Line 129 calls
add_vector_int(..., len(rb.keys())), butadd_vector_intimmediately executeslist(val), so handing it anintraises aTypeErroras soon as refinement boxes are present. Switch this toadd_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.
| #ifndef _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_ | ||
| #define _PHARE_AMR_DATA_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_ |
There was a problem hiding this comment.
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.
| 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("/"))); | ||
| } |
There was a problem hiding this comment.
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.
| 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("/"))); | |
| } |
| #ifndef _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_ | ||
| #define _PHARE_AMR_DATA_PARTICLE_INITIALIZERS_SAMRAI_HDF5_INITIALIZER_HPP_ |
There was a problem hiding this comment.
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.
| #ifndef _PHARE_HDF5_DETAIL_H5_GROUP_SCANNER_HPP_ | ||
| #define _PHARE_HDF5_DETAIL_H5_GROUP_SCANNER_HPP_ |
There was a problem hiding this comment.
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.
| void fillIonsMomentsGhosts() | ||
| { | ||
| using Interpolator = typename IonUpdater::Interpolator; | ||
| using Interpolator = IonUpdater::Interpolator; | ||
| Interpolator interpolate; | ||
|
|
There was a problem hiding this comment.
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.
| 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.
Summary by CodeRabbit
New Features
AMRToLocalfunction with new overloads for enhanced performance and flexibility.Bug Fixes
Chores