Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3d C++ / python #591

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft

Conversation

PhilipDeegan
Copy link
Member

@PhilipDeegan PhilipDeegan commented Sep 27, 2021

mostly there, some coarsening tests missing
only some 3d split patterns, the rest can come afterwards

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced support for 3D simulations, including new test cases and configurations.
    • Added a plot3d method for 3D data visualization in the PatchHierarchy class.
    • Enhanced the Box struct with an as_points() method to retrieve all points within the box.
    • New methods for handling 3D arrays and improved functionality in existing classes.
  • Bug Fixes

    • Fixed handling of ghost boxes and periodicity shifts in multi-dimensional domains.
    • Addressed potential issues in test cases by adding assertions and improving error handling.
  • Documentation

    • Updated documentation to reflect new features and enhancements, particularly for 3D functionalities.
  • Tests

    • Expanded test coverage for 3D scenarios, including new test files and methods for particle and field initialization.
    • Introduced assertions for handling 3D fields in existing tests.
  • Chores

    • Cleaned up code for better readability and maintainability, including renaming and restructuring of existing classes and methods.

@PhilipDeegan PhilipDeegan added the WIP work in progress label Sep 27, 2021
@PHAREHUB PHAREHUB deleted a comment from lgtm-com bot Oct 2, 2021
@PHAREHUB PHAREHUB deleted a comment from lgtm-com bot Oct 2, 2021
@PhilipDeegan PhilipDeegan force-pushed the 3d_base branch 5 times, most recently from 4bcae8e to 84dd60a Compare October 5, 2021 13:18
@PHAREHUB PHAREHUB deleted a comment from lgtm-com bot Oct 5, 2021
@PHAREHUB PHAREHUB deleted a comment from lgtm-com bot Oct 5, 2021
@PHAREHUB PHAREHUB deleted a comment from lgtm-com bot Oct 5, 2021
@PhilipDeegan PhilipDeegan force-pushed the 3d_base branch 3 times, most recently from eb507bb to c963ec0 Compare October 5, 2021 19:18
@PhilipDeegan PhilipDeegan changed the title 3d C++ 3d C++ / python (mostly) May 17, 2022
@PHAREHUB PHAREHUB deleted a comment from lgtm-com bot Aug 1, 2022
@PhilipDeegan PhilipDeegan changed the title 3d C++ / python (mostly) 3d C++ / python Sep 3, 2022
@PhilipDeegan PhilipDeegan force-pushed the 3d_base branch 5 times, most recently from 7bb1041 to 263ecd6 Compare September 7, 2022 21:14
@nicolasaunai nicolasaunai marked this pull request as draft February 8, 2023 18:22
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 28

Outside diff range and nitpick comments (61)
tools/python3/git.py (2)

Line range hint 22-22: Remove unused variable.

The variable e is assigned but never used, which is unnecessary and can be removed for cleaner code.

-    except subprocess.CalledProcessError as e:
+    except subprocess.CalledProcessError:

Line range hint 29-29: Undefined function delete_branch.

The function delete_branch is called but not defined anywhere in the provided code. This will cause a runtime error.

+ def delete_branch(branch):
+     run(f"git branch -D {branch}")
tests/simulator/initialize/test_particles_init_1d.py (2)

Line range hint 33-35: Remove extraneous parentheses around single items in tuples.

The parentheses around the single items in the tuples are unnecessary and can be removed for cleaner code.

- *per_interp(({"L0": {"B0": Box1D(10, 14)}})),
- *per_interp(({"L0": {"B0": Box1D(5, 20)}, "L1": {"B0": Box1D(15, 35)}})),
- *per_interp(({"L0": {"B0": Box1D(2, 12), "B1": Box1D(13, 25)}})),
+ *per_interp({"L0": {"B0": Box1D(10, 14)}}),
+ *per_interp({"L0": {"B0": Box1D(5, 20)}, "L1": {"B0": Box1D(15, 35)}}),
+ *per_interp({"L0": {"B0": Box1D(2, 12), "B1": Box1D(13, 25)}}),

Line range hint 54-56: Remove extraneous parentheses around single items in tuples.

Similar to previous comments, remove unnecessary parentheses to improve code readability.

- *per_interp(({"L0": {"B0": Box1D(10, 14)}})),
- *per_interp(({"L0": {"B0": Box1D(5, 20)}, "L1": {"B0": Box1D(15, 35)}})),
- *per_interp(({"L0": {"B0": Box1D(2, 12), "B1": Box1D(13, 25)}})),
+ *per_interp({"L0": {"B0": Box1D(10, 14)}}),
+ *per_interp({"L0": {"B0": Box1D(5, 20)}, "L1": {"B0": Box1D(15, 35)}}),
+ *per_interp({"L0": {"B0": Box1D(2, 12), "B1": Box1D(13, 25)}}),
tests/simulator/initialize/test_particles_init_2d.py (2)

Line range hint 33-35: Remove extraneous parentheses around single items in tuples.

The parentheses around the single items in the tuples are unnecessary and can be removed for cleaner code.

- *per_interp(({"L0": {"B0": Box2D(10, 14)}})),
- *per_interp(({"L0": {"B0": Box2D(10, 14)}, "L1": {"B0": Box2D(22, 26)}})),
- *per_interp(({"L0": {"B0": Box2D(2, 6), "B1": Box2D(7, 11)}})),
+ *per_interp({"L0": {"B0": Box2D(10, 14)}}),
+ *per_interp({"L0": {"B0": Box2D(10, 14)}, "L1": {"B0": Box2D(22, 26)}}),
+ *per_interp({"L0": {"B0": Box2D(2, 6), "B1": Box2D(7, 11)}}),

Line range hint 58-60: Remove extraneous parentheses around single items in tuples.

Similar to previous comments, remove unnecessary parentheses to improve code readability.

- *per_interp(({"L0": {"B0": Box2D(10, 14)}})),
- *per_interp(({"L0": {"B0": Box2D(5, 20)}, "L1": {"B0": Box2D(15, 35)}})),
- *per_interp(({"L0": {"B0": Box2D(2, 12), "B1": Box2D(13, 25)}})),
+ *per_interp({"L0": {"B0": Box2D(10, 14)}}),
+ *per_interp({"L0": {"B0": Box2D(5, 20)}, "L1": {"B0": Box2D(15, 35)}}),
+ *per_interp({"L0": {"B0": Box2D(2, 12), "B1": Box2D(13, 25)}}),
src/core/utilities/meta/meta_utilities.hpp (1)

83-97: Review the conditional compilation logic for simulator options.

The conditional compilation blocks for 2D and 3D simulator options are well-structured. However, consider adding further comments or documentation to describe the scenarios under which these blocks are activated, especially for maintainability and clarity for new contributors.

src/amr/data/particles/refine/split_3d.hpp (1)

90-115: Ensure extensibility in WhitePattern.

The WhitePattern class template handles complex particle splitting with multiple dimensions. Ensure that the class design allows for easy extension or modification to support future requirements such as additional dimensions or different splitting strategies.

src/amr/data/particles/refine/split_2d.hpp (1)

247-247: Suggestion for adding documentation in Splitter constructors.

Each Splitter constructor initializes its base class with specific weights and deltas. It would be helpful for maintainability to add inline comments explaining the choice of these values, especially since they are critical for the simulation accuracy.

pyphare/pyphare/core/gridlayout.py (2)

Line range hint 152-155: Simplify expression using ternary operator.

The if-else block in the yeeCoordsFor function can be simplified using a ternary operator for better readability.

- if withGhosts:
-     size = nbrCells[dim] + (nbrGhosts * 2)
- else:
-     size = nbrCells[dim]
+ size = nbrCells[dim] + (nbrGhosts * 2) if withGhosts else nbrCells[dim]

Line range hint 131-131: Remove unnecessary inheritance from object.

Both YeeCentering and GridLayout classes inherit from object, which is redundant in Python 3 and can be removed for cleaner code.

- class YeeCentering(object):
+ class YeeCentering:

- class GridLayout(object):
+ class GridLayout:

Also applies to: 168-168

pyphare/pyphare/pharesee/run.py (3)

Line range hint 289-289: Convert to f-string for consistency and readability.

The use of the format method can be replaced with f-strings for better readability and consistency with modern Python practices.

- t = "{:.10f}".format(time)
+ t = f"{time:.10f}"

- def filename(name):
-     return f"ions_pop_{name}_domain.h5"
+ def filename(name):
+     return f"ions_pop_{name}_domain.h5"

Also applies to: 415-415


Line range hint 371-371: Remove unnecessary f-string prefixes.

There are f-string prefixes used without any placeholders, which should be removed for cleaner code.

- h5_time_grp_key = "t"
+ h5_time_grp_key = "t"

- h5_filename = "EM_B.h5"  # _____ TODO : could be another file
+ h5_filename = "EM_B.h5"  # _____ TODO : could be another file

Also applies to: 373-373


Line range hint 465-465: Avoid mutable default arguments in function definitions.

Using mutable default structures like lists as default arguments can lead to unexpected behaviors. It's safer to use None and initialize within the function.

- def GetAllAvailableQties(self, time=0, pops=[]):
+ def GetAllAvailableQties(self, time=0, pops=None):
+     if pops is None:
+         pops = []
pyphare/pyphare/pharesee/geometry.py (3)

Line range hint 86-187: Optimize the initialization and update of the shifts dictionary.

The initialization and updates of the shifts dictionary are spread across multiple conditional blocks, which can be optimized for better readability and efficiency. Consider consolidating the initialization and conditional updates into a single block or function. Also, ensure that the variable names are clear, as l is ambiguous and could be renamed for clarity.

- shifts = {}
- if domain_box.ndim == 1:
-    ...
- if domain_box.ndim == 2:
-    ...
- if domain_box.ndim == 3:
-    ...
+ shifts = initialize_shifts(domain_box)

def initialize_shifts(domain_box):
    shifts = {}
    if domain_box.ndim == 1:
        ...
    elif domain_box.ndim == 2:
        ...
    elif domain_box.ndim == 3:
        ...
    return shifts
- f"{k}front": [(v[0], v[1], shape_z) for v in l] for k, l in shifts.items()
+ f"{k}front": [(v[0], v[1], shape_z) for v in values] for k, values in shifts.items()
Tools
Ruff

160-160: Ambiguous variable name: l (E741)


163-163: Ambiguous variable name: l (E741)


166-166: Ambiguous variable name: l (E741)


187-187: Ambiguous variable name: l (E741)


Line range hint 418-418: Avoid using mutable default arguments in function definitions.

Using mutable objects like lists or dictionaries as default arguments in function definitions can lead to unexpected behavior if the function modifies the default object. Replace mutable default arguments with None and initialize them within the function.

- def some_function(arg={}):
+ def some_function(arg=None):
+     if arg is None:
+         arg = {}

Also applies to: 464-464


Line range hint 441-441: Remove or rename unused loop control variable.

The variable pd is not used within the loop body, which could be a sign of an error or unnecessary code. If it's not needed, consider removing it or replacing it with _ to indicate it's intentionally unused.

- for pd_key, pd in patch.patch_datas.items():
+ for pd_key, _ in patch.patch_datas.items():
tests/simulator/test_initialization.py (4)

Line range hint 5-23: Reorganize module-level imports to the top of the file.

The imports should be placed at the top of the file for better readability and to adhere to Python's convention. This will also resolve multiple E402 lint errors.

+ from pyphare.cpp import cpp_lib
+ cpp = cpp_lib()
+ import unittest
+ import numpy as np
+ from ddt import ddt
+ from pyphare.core.box import nDBox
+ from pyphare.core.phare_utilities import assert_fp_any_all_close
+ from pyphare.pharein import ElectronModel, MaxwellianFluidModel
+ from pyphare.pharein.diagnostics import (
+     ElectromagDiagnostics,
+     FluidDiagnostics,
+     ParticleDiagnostics,
+ )
+ from pyphare.pharein.simulation import Simulation
+ from pyphare.pharesee.geometry import level_ghost_boxes
+ from pyphare.pharesee.hierarchy import hierarchy_from, merge_particles
+ from pyphare.pharesee.particles import aggregate as aggregate_particles
+ from pyphare.simulator.simulator import Simulator
+ from tests.simulator import SimulatorTest

Line range hint 32-32: Convert lambda expressions to function definitions.

Using lambda expressions for simple calculations is fine, but assigning them to variables is not recommended as it reduces readability and debuggability. Convert these lambda expressions to proper function definitions.

- _ = lambda i: -((xyz[i] - hL[i]) ** 2)
+ def calculate_expression(i, xyz, hL):
+     return -((xyz[i] - hL[i]) ** 2)

Apply similar changes for all the lambda expressions assigned to _.

Also applies to: 93-93, 98-98, 103-103, 108-108, 113-113


Line range hint 44-44: Avoid using mutable default arguments.

Using a mutable default argument like a dictionary can lead to unexpected behavior if the function modifies the argument. Use None as the default and set it inside the function.

- def getHierarchy(self, ..., extra_diag_options={}):
+ def getHierarchy(self, ..., extra_diag_options=None):
+     if extra_diag_options is None:
+         extra_diag_options = {}

Line range hint 315-317: Replace list comprehensions with generator expressions where applicable.

Using a generator expression can be more memory efficient than a list comprehension when the result is immediately consumed by functions like all().

- xbx, ybx, zbx = [a.flatten() for a in np.meshgrid(xbx, ybx, zbx, indexing="ij")]
+ xbx, ybx, zbx = (a.flatten() for a in np.meshgrid(xbx, ybx, zbx, indexing="ij"))

Apply similar changes to other unpacked list comprehensions.

Also applies to: 318-320, 321-323, 338-340, 341-343, 344-346

tests/simulator/test_advance.py (6)

Line range hint 5-24: Reorder imports to the top of the file.

Python convention dictates that all module-level imports should be at the top of the file before any code execution. This helps in understanding the dependencies of the module at a glance.

+ from pyphare.cpp import cpp_lib
+ from ddt import ddt
+ import unittest
+ import numpy as np
+ import pyphare.core.box as boxm
+ from pyphare.core.box import Box
+ from pyphare.core.phare_utilities import assert_fp_any_all_close, np_array_ify
+ from pyphare.pharein import ElectronModel, MaxwellianFluidModel
+ from pyphare.pharein.diagnostics import (
+     ElectromagDiagnostics,
+     FluidDiagnostics,
+     ParticleDiagnostics,
+ )
+ from pyphare.pharein.simulation import Simulation
+ from pyphare.pharesee.geometry import hierarchy_overlaps, level_ghost_boxes
+ from pyphare.pharesee.hierarchy import hierarchy_from, merge_particles
+ from pyphare.simulator.simulator import Simulator
+ from tests.diagnostic import all_timestamps
+ from tests.simulator import SimulatorTest, diff_boxes
- <all the lines where these imports are currently located>
Tools
Ruff

87-87: Ambiguous variable name: l (E741)


Line range hint 33-33: Replace lambda expression with a function for clarity.

Using lambda for simple operations can reduce readability, especially when used as part of complex expressions. Defining a function is more readable and maintainable.

- _ = lambda i: -((xyz[i] - hL[i]) ** 2)
+ def square_difference(i):
+     return -((xyz[i] - hL[i]) ** 2)
Tools
Ruff

87-87: Ambiguous variable name: l (E741)


Line range hint 48-50: Initialize mutable defaults inside the function.

Using mutable default arguments like dictionaries can lead to unexpected behavior due to Python's handling of default argument values.

- def getHierarchy(
-     self,
-     ndim,
-     interp_order,
-     refinement_boxes,
-     qty,
-     nbr_part_per_cell=100,
-     density=_density,
-     smallest_patch_size=None,
-     largest_patch_size=20,
-     cells=120,
-     time_step=0.001,
-     model_init={},
-     dl=0.2,
-     extra_diag_options={},
-     time_step_nbr=1,
-     timestamps=None,
-     block_merging_particles=False,
-     diag_outputs="",
- ):
+ def getHierarchy(
+     self,
+     ndim,
+     interp_order,
+     refinement_boxes,
+     qty,
+     nbr_part_per_cell=100,
+     density=_density,
+     smallest_patch_size=None,
+     largest_patch_size=20,
+     cells=120,
+     time_step=0.001,
+     model_init=None,
+     dl=0.2,
+     extra_diag_options=None,
+     time_step_nbr=1,
+     timestamps=None,
+     block_merging_particles=False,
+     diag_outputs="",
+ ):
+     model_init = model_init if model_init is not None else {}
+     extra_diag_options = extra_diag_options if extra_diag_options is not None else {}
Tools
Ruff

87-87: Ambiguous variable name: l (E741)


Line range hint 95-115: Replace lambda expressions with functions.

Lambda expressions are used multiple times for similar calculations. Replace them with a single function to enhance readability and maintainability.

- _ = lambda i: 0.1 * np.cos(2 * np.pi * xyz[i] / L[i])
+ def cos_component(i):
+     return 0.1 * np.cos(2 * np.pi * xyz[i] / L[i])
Tools
Ruff

87-87: Ambiguous variable name: l (E741)


Line range hint 251-251: Rename unused loop variables.

Unused loop variables like ilvl and lvl should be renamed to _ to indicate that they are intentionally not used.

- for ilvl, overlaps in hierarchy_overlaps(datahier, coarsest_time).items():
+ for _, overlaps in hierarchy_overlaps(datahier, coarsest_time).items():
- for ilvl, lvl in datahier.patch_levels.items():
+ for _, _lvl in datahier.patch_levels.items():

Also applies to: 345-345

Tools
Ruff

87-87: Ambiguous variable name: l (E741)


Line range hint 320-320: Use f-strings for string formatting.

Modern Python recommends using f-strings for more readable and efficient string formatting.

- "test_overlapped_particledatas_have_identical_particles, interporder : {}".format(interp_order)
+ f"test_overlapped_particledatas_have_identical_particles, interporder : {interp_order}"
- "testing level {}".format(ilvl)
+ f"testing level {ilvl}"
- "test_field_coarsening_via_subcycles for dim/interp : {}/{}".format(dim, interp_order)
+ f"test_field_coarsening_via_subcycles for dim/interp : {dim}/{interp_order}"
- "FAIL level ghost subcycle_coarsening qty {qty}".format(qty=qty)
+ f"FAIL level ghost subcycle_coarsening qty {qty}"
- "test_field_coarsening_via_subcycles for dim/interp : {}/{}".format(ndim, interp_order)
+ f"test_field_coarsening_via_subcycles for dim/interp : {ndim}/{interp_order}"

Also applies to: 346-346, 407-407, 519-519, 686-688

Tools
Ruff

87-87: Ambiguous variable name: l (E741)

pyphare/pyphare/pharesee/hierarchy.py (34)

Line range hint 82-84: Use f-string for formatting.

For improved readability and performance, consider using f-string formatting.

- return "FieldData: (box=({}, {}), key={})".format(
-     self.layout.box, self.layout.box.shape, self.field_name
- )
+ return f"FieldData: (box=({self.layout.box}, {self.layout.box.shape}), key={self.field_name})"

Line range hint 203-203: Use f-string for formatting.

This simplifies the code and improves performance.

- return f"Patch: box( {self.box}), id({self.id})"
+ return f"Patch: box({self.box}), id({self.id})"

Line range hint 508-508: Optimize dictionary key check.

Use key in dict instead of key in dict.keys() for a more idiomatic and efficient check.

- if qty in self.__dict__.keys():
+ if qty in self.__dict__:

Line range hint 520-520: Remove unused loop variable.

The variable ip is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for ip, patch in enumerate(patches):
+ for _, patch in enumerate(patches):

Line range hint 557-557: Remove unnecessary inheritance from object.

In Python 3, all classes implicitly inherit from object, so this is redundant.

- class PatchHierarchy(object):
+ class PatchHierarchy:

Line range hint 621-621: Use raise ... from to provide context for exceptions.

This helps in debugging by making the chain of exceptions clear.

- raise RuntimeError(f"Failed to deserialize simulation from data file : {e}")
+ raise RuntimeError(f"Failed to deserialize simulation from data file : {e}") from e

Line range hint 726-726: Remove unused loop variable.

The variable time is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for time in data_file[h5_time_grp_key].keys():
+ for _ in data_file[h5_time_grp_key].keys():

Line range hint 727-727: Remove unused loop variable.

The variable ilvl is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for ilvl, lvl in self.levels(time).items():
+ for _, lvl in self.levels(time).items():

Line range hint 746-746: Remove unused loop variable.

The variable ilvl is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for ilvl in range(hierarchy.finest_level() + 1):
+ for _ in range(hierarchy.finest_level() + 1):

Line range hint 760-760: Remove unused loop variable.

The variable ilvl is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for ilvl in range(hierarchy.finest_level() + 1):
+ for _ in range(hierarchy.finest_level() + 1):

Line range hint 781-781: Use f-string for formatting.

This simplifies the code and improves performance.

- print("creating hierarchy from time {}".format(time))
+ print(f"creating hierarchy from time {time}")

Line range hint 790-790: Remove unused loop variable.

The variable t is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for t in times[1:]:
+ for _ in times[1:]:

Line range hint 792-792: Use f-string for formatting.

This simplifies the code and improves performance.

- print("loading data at time {} into existing hierarchy".format(time))
+ print(f"loading data at time {time} into existing hierarchy")

Line range hint 906-906: Use f-string for formatting.

This simplifies the code and improves performance.

- raise RuntimeError("{} is not a valid quantity".format(qty))
+ raise RuntimeError(f"{qty} is not a valid quantity")

Line range hint 960-960: Remove unused loop variable.

The variable lvl is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for lvl_nbr, lvl in self.levels(time).items():
+ for lvl_nbr, _ in self.levels(time).items():

Line range hint 1099-1099: Remove unused loop variable.

The variable ip is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for ip, patch in enumerate(patches):
+ for _, patch in enumerate(patches):

Line range hint 1281-1281: Remove unused loop variable.

The variable ip is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for ip, patch in enumerate(sorted_patches):
+ for _, patch in enumerate(sorted_patches):

Line range hint 1390-1390: Use f-string for formatting.

This simplifies the code and improves performance.

- raise RuntimeError("more than one patch found for point")
+ raise RuntimeError(f"more than one patch found for point")

Line range hint 1395-1395: Optimize dictionary key check.

Use key in dict instead of key in dict.keys() for a more idiomatic and efficient check.

- if dataset_name in patch_datas.keys():
+ if dataset_name in patch_datas:

Line range hint 1400-1402: Use f-string for formatting.

This simplifies the code and improves performance.

- raise RuntimeError("invalid dataset name : {} is not in {}".format(
-     dataset_name, field_qties
- ))
+ raise RuntimeError(f"invalid dataset name : {dataset_name} is not in {field_qties}")

Line range hint 1413-1413: Use f-string for formatting.

This simplifies the code and improves performance.

- raise ValueError("error - {} already in patchdata".format(pdname))
+ raise ValueError(f"error - {pdname} already in patchdata")

Line range hint 1453-1453: Use f-string for formatting.

This simplifies the code and improves performance.

- raise ValueError("error - {} already in patchdata".format(dataset_name))
+ raise ValueError(f"error - {dataset_name} already in patchdata")

Line range hint 1459-1459: Optimize dictionary key check.

Use key in dict instead of key in dict.keys() for a more idiomatic and efficient check.

- if dataset_name in patch_datas.keys():
+ if dataset_name in patch_datas:

Line range hint 1468-1468: Optimize dictionary key check.

Use key in dict instead of key in dict.keys() for a more idiomatic and efficient check.

- if "patchGhost" in populationdict.keys():
+ if "patchGhost" in populationdict:

Line range hint 1490-1490: Use f-string for formatting.

This simplifies the code and improves performance.

- raise ValueError("must specify pop argument for particles")
+ raise ValueError("must specify pop argument for particles")

Line range hint 1505-1505: Optimize dictionary key check.

Use key in dict instead of key in dict.keys() for a more idiomatic and efficient check.

- if ghostParticles in populationdict.keys():
+ if ghostParticles in populationdict:

Line range hint 1538-1538: Optimize dictionary key check.

Use key in dict instead of key in dict.keys() for a more idiomatic and efficient check.

- if "levelGhost" in populationdict.keys():
+ if "levelGhost" in populationdict:

Line range hint 1544-1544: Remove unused loop variable.

The variable ipatch is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for ipatch, pkey in enumerate(h5_time_grp[plvl_key].keys()):
+ for _, pkey in enumerate(h5_time_grp[plvl_key].keys()):

Line range hint 1561-1561: Optimize dictionary key check.

Use key in dict instead of key in dict.keys() for a more idiomatic and efficient check.

- if dataset_name in patch_datas.keys():
+ if dataset_name in patch_datas:

Line range hint 1718-1718: Use f-string for formatting.

This simplifies the code and improves performance.

- print("creating hierarchy from all times in file")
+ print(f"creating hierarchy from all times in file")

Line range hint 1765-1765: Remove unused loop variable.

The variable time is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for time in data_file[h5_time_grp_key].keys():
+ for _ in data_file[h5_time_grp_key].keys():

Line range hint 1766-1766: Remove unused loop variable.

The variable ilvl is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for ilvl in range(hierarchy.finest_level() + 1)[::-1]:
+ for _ in range(hierarchy.finest_level() + 1)[::-1]:

Line range hint 1767-1767: Remove unused loop variable.

The variable ip is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for ip, patch in enumerate(sorted_patches):
+ for _, patch in enumerate(sorted_patches):

Line range hint 1820-1820: Optimize dictionary key check.

Use key in dict instead of key in dict.keys() for a more idiomatic and efficient check.

- if qty in self.__dict__.keys():
+ if qty in self.__dict__:
Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between a07dcc8 and 914fce6.

Files selected for processing (44)
  • .github/workflows/cmake_macos.yml (1 hunks)
  • pyphare/pyphare/core/box.py (2 hunks)
  • pyphare/pyphare/core/gridlayout.py (1 hunks)
  • pyphare/pyphare/pharesee/geometry.py (7 hunks)
  • pyphare/pyphare/pharesee/hierarchy.py (3 hunks)
  • pyphare/pyphare/pharesee/run.py (1 hunks)
  • res/amr/splitting.yml (1 hunks)
  • res/cmake/options.cmake (1 hunks)
  • src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1 hunks)
  • src/amr/data/particles/refine/split.hpp (1 hunks)
  • src/amr/data/particles/refine/split_1d.hpp (10 hunks)
  • src/amr/data/particles/refine/split_2d.hpp (17 hunks)
  • src/amr/data/particles/refine/split_3d.hpp (1 hunks)
  • src/amr/data/particles/refine/splitter.hpp (2 hunks)
  • src/core/data/grid/gridlayoutdefs.hpp (2 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (8 hunks)
  • src/core/utilities/box/box.hpp (3 hunks)
  • src/core/utilities/meta/meta_utilities.hpp (2 hunks)
  • tests/amr/data/field/refine/test_refine_field.py (1 hunks)
  • tests/amr/data/particles/refine/input/input_3d_ratio_2.txt (1 hunks)
  • tests/amr/data/particles/refine/test_split.cpp (1 hunks)
  • tests/core/data/ndarray/test_main.cpp (1 hunks)
  • tests/core/numerics/interpolator/test_main.cpp (1 hunks)
  • tests/diagnostic/CMakeLists.txt (1 hunks)
  • tests/diagnostic/job_3d.py.in (1 hunks)
  • tests/diagnostic/test-diagnostics_3d.cpp (1 hunks)
  • tests/functional/harris/harris_3d.py (1 hunks)
  • tests/simulator/init.py (2 hunks)
  • tests/simulator/advance/CMakeLists.txt (1 hunks)
  • tests/simulator/advance/test_fields_advance_3d.py (1 hunks)
  • tests/simulator/advance/test_particles_advance_3d.py (1 hunks)
  • tests/simulator/initialize/CMakeLists.txt (1 hunks)
  • tests/simulator/initialize/test_fields_init_2d.py (1 hunks)
  • tests/simulator/initialize/test_fields_init_3d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_1d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_2d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_3d.py (1 hunks)
  • tests/simulator/per_test.hpp (1 hunks)
  • tests/simulator/refined_particle_nbr.py (2 hunks)
  • tests/simulator/test_advance.py (7 hunks)
  • tests/simulator/test_initialization.py (14 hunks)
  • tools/python3/init.py (5 hunks)
  • tools/python3/cmake.py (2 hunks)
  • tools/python3/git.py (1 hunks)
Files not reviewed due to errors (4)
  • pyphare/pyphare/core/box.py (no review received)
  • src/core/utilities/box/box.hpp (no review received)
  • tests/simulator/init.py (no review received)
  • src/core/data/ndarray/ndarray_vector.hpp (no review received)
Files skipped from review due to trivial changes (3)
  • src/amr/data/particles/refine/split.hpp
  • tests/amr/data/particles/refine/test_split.cpp
  • tests/simulator/initialize/CMakeLists.txt
Additional context used
Path-based instructions (10)
src/core/data/grid/gridlayoutdefs.hpp (1)

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

tests/simulator/per_test.hpp (1)

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

src/amr/data/particles/refine/splitter.hpp (1)

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

src/core/utilities/meta/meta_utilities.hpp (1)

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

src/amr/data/particles/refine/split_1d.hpp (1)

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

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

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

src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1)

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

src/amr/data/particles/refine/split_3d.hpp (1)

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

src/amr/data/particles/refine/split_2d.hpp (1)

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

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

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

Ruff
tools/python3/git.py

22-22: Local variable e is assigned to but never used (F841)

Remove assignment to unused variable e


29-29: Undefined name delete_branch (F821)

tools/python3/cmake.py

48-48: Undefined name cmd (F821)

tests/simulator/initialize/test_particles_init_1d.py

33-33: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


34-34: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


35-35: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


54-54: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


55-55: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


56-56: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses

tools/python3/__init__.py

45-45: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


46-46: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


95-95: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


111-111: Module level import not at top of file (E402)

tests/simulator/initialize/test_particles_init_2d.py

33-33: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


34-34: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


35-35: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


58-58: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


59-59: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


60-60: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses

tests/simulator/initialize/test_particles_init_3d.py

35-35: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


36-36: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


37-37: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


60-60: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


61-61: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


62-62: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses

tests/functional/harris/harris_3d.py

62-62: Ambiguous variable name: l (E741)

tests/simulator/refined_particle_nbr.py

9-9: Module level import not at top of file (E402)


10-10: Module level import not at top of file (E402)


11-11: Module level import not at top of file (E402)


13-13: Module level import not at top of file (E402)


14-14: Module level import not at top of file (E402)


15-15: Module level import not at top of file (E402)


16-16: Module level import not at top of file (E402)


18-18: Module level import not at top of file (E402)


18-18: tests.simulator.NoOverwriteDict imported but unused (F401)

Remove unused import: tests.simulator.NoOverwriteDict


19-19: Module level import not at top of file (E402)


24-24: Use super() instead of super(__class__, self) (UP008)

Remove __super__ parameters


26-26: Unnecessary open mode parameters (UP015)

Remove open mode parameters


44-44: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


61-61: Loop control variable pop not used within loop body (B007)

Rename unused pop to _pop


63-63: Loop control variable key not used within loop body (B007)

Rename unused key to _key

pyphare/pyphare/core/box.py

11-11: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


41-41: Use f-string instead of format call (UP032)

Convert to f-string


76-76: Ambiguous variable name: l (E741)


84-84: Ambiguous variable name: l (E741)


89-89: Ambiguous variable name: l (E741)


94-94: Ambiguous variable name: l (E741)


207-207: Ambiguous variable name: l (E741)

tests/simulator/__init__.py

3-3: Multiple imports on one line (E401)

Split imports


26-26: Use super() instead of super(__class__, self) (UP008)

Remove __super__ parameters


76-76: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


122-122: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


182-182: Undefined name Box (F821)


188-188: Undefined name Box (F821)


195-195: Undefined name Box (F821)


236-236: Use super() instead of super(__class__, self) (UP008)

Remove __super__ parameters


273-273: Multiple imports on one line (E401)

Split imports


275-275: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function

pyphare/pyphare/core/gridlayout.py

131-131: Class YeeCentering inherits from object (UP004)

Remove object inheritance


152-155: Use ternary operator size = nbrCells[dim] + nbrGhosts * 2 if withGhosts else nbrCells[dim] instead of if-else-block (SIM108)

Replace if-else-block with size = nbrCells[dim] + nbrGhosts * 2 if withGhosts else nbrCells[dim]


168-168: Class GridLayout inherits from object (UP004)

Remove object inheritance


176-176: Do not perform function call Box in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)

pyphare/pyphare/pharesee/run.py

289-289: Use f-string instead of format call (UP032)

Convert to f-string


371-371: f-string without any placeholders (F541)

Remove extraneous f prefix


373-373: f-string without any placeholders (F541)

Remove extraneous f prefix


415-415: Use f-string instead of format call (UP032)

Convert to f-string


465-465: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function

tests/amr/data/field/refine/test_refine_field.py

9-9: Redefinition of unused refinement_ratio from line 5 (F811)


106-106: Do not assert False (python -O removes these calls), raise AssertionError() (B011)

Replace assert False

pyphare/pyphare/pharesee/geometry.py

160-160: Ambiguous variable name: l (E741)


163-163: Ambiguous variable name: l (E741)


166-166: Ambiguous variable name: l (E741)


187-187: Ambiguous variable name: l (E741)


418-418: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


441-441: Loop control variable pd not used within loop body (B007)

Rename unused pd to _pd


464-464: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function

tests/simulator/test_initialization.py

5-5: Module level import not at top of file (E402)


7-7: Module level import not at top of file (E402)


8-8: Module level import not at top of file (E402)


9-9: Module level import not at top of file (E402)


10-10: Module level import not at top of file (E402)


11-11: Module level import not at top of file (E402)


12-16: Module level import not at top of file (E402)


17-17: Module level import not at top of file (E402)


18-18: Module level import not at top of file (E402)


19-19: Module level import not at top of file (E402)


20-20: Module level import not at top of file (E402)


21-21: Module level import not at top of file (E402)


23-23: Module level import not at top of file (E402)


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

Rewrite _ as a def


44-44: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


93-93: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


98-98: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


103-103: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


108-108: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


113-113: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


261-263: Use f-string instead of format call (UP032)

Convert to f-string


289-289: Use f-string instead of format call (UP032)

Convert to f-string


315-317: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


318-320: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


321-323: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


338-340: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


341-343: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


344-346: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


385-385: Use f-string instead of format call (UP032)

Convert to f-string


387-387: Use f-string instead of format call (UP032)

Convert to f-string


399-399: Function definition does not bind loop variable select (B023)


401-401: Function definition does not bind loop variable patch (B023)


401-401: Function definition does not bind loop variable nbrGhosts (B023)


402-402: Function definition does not bind loop variable select (B023)


450-450: Use f-string instead of format call (UP032)

Convert to f-string


452-452: Use f-string instead of format call (UP032)

Convert to f-string


457-457: Local variable x is assigned to but never used (F841)

Remove assignment to unused variable x


539-539: Use f-string instead of format call (UP032)

Convert to f-string


587-587: Loop control variable pi not used within loop body (B007)

Rename unused pi to _pi


591-591: Yoda conditions are discouraged, use ppc == H instead (SIM300)

Replace Yoda condition with ppc == H


596-596: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


613-615: Use f-string instead of format call (UP032)

Convert to f-string


658-658: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


669-669: Local variable out is assigned to but never used (F841)

Remove assignment to unused variable out

tests/simulator/test_advance.py

5-5: Module level import not at top of file (E402)


7-7: Module level import not at top of file (E402)


8-8: Module level import not at top of file (E402)


9-9: Module level import not at top of file (E402)


10-10: Module level import not at top of file (E402)


11-11: Module level import not at top of file (E402)


12-12: Module level import not at top of file (E402)


13-17: Module level import not at top of file (E402)


18-18: Module level import not at top of file (E402)


19-19: Module level import not at top of file (E402)


20-20: Module level import not at top of file (E402)


21-21: Module level import not at top of file (E402)


23-23: Module level import not at top of file (E402)


24-24: Module level import not at top of file (E402)


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

Rewrite _ as a def


48-48: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


50-50: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


87-87: Ambiguous variable name: l (E741)


95-95: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


100-100: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


105-105: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


110-110: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


115-115: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


251-251: Loop control variable ilvl not used within loop body (B007)

Rename unused ilvl to _ilvl


320-322: Use f-string instead of format call (UP032)

Convert to f-string


345-345: Loop control variable lvl not used within loop body (B007)

Rename unused lvl to _lvl


346-346: Use f-string instead of format call (UP032)

Convert to f-string


407-409: Use f-string instead of format call (UP032)

Convert to f-string


519-519: Use f-string instead of format call (UP032)

Convert to f-string


686-688: Use f-string instead of format call (UP032)

Convert to f-string


695-695: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


710-710: f-string without any placeholders (F541)

Remove extraneous f prefix


711-711: f-string without any placeholders (F541)

Remove extraneous f prefix


739-739: pyphare.pharein imported but unused (F401)

Remove unused import: pyphare.pharein


744-744: Local variable out is assigned to but never used (F841)

Remove assignment to unused variable out

pyphare/pyphare/pharesee/hierarchy.py

82-84: Use f-string instead of format call (UP032)

Convert to f-string


203-203: Use f-string instead of format call (UP032)

Convert to f-string


508-508: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


520-520: Loop control variable ip not used within loop body (B007)

Rename unused ip to _ip


557-557: Class PatchHierarchy inherits from object (UP004)

Remove object inheritance


621-621: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


651-651: Comparison to None should be cond is None (E711)

Replace with cond is None


726-726: Loop control variable time not used within loop body (B007)

Rename unused time to _time


727-727: Loop control variable ilvl not used within loop body (B007)

Rename unused ilvl to _ilvl


746-746: Loop control variable ilvl not used within loop body (B007)

Rename unused ilvl to _ilvl


760-760: Loop control variable ilvl not used within loop body (B007)

Rename unused ilvl to _ilvl


781-781: Use f-string instead of format call (UP032)

Convert to f-string


790-790: Loop control variable t not used within loop body (B007)

Rename unused t to _t


792-792: Use f-string instead of format call (UP032)

Convert to f-string


906-906: Use f-string instead of format call (UP032)

Convert to f-string


960-960: Loop control variable lvl not used within loop body (B007)

Rename unused lvl to _lvl


1034-1034: Loop control variable lvl not used within loop body (B007)

Rename unused lvl to _lvl


1099-1099: Loop control variable ip not used within loop body (B007)

Rename unused ip to _ip


1281-1281: Loop control variable ip not used within loop body (B007)

Rename unused ip to _ip


1390-1390: Use f-string instead of format call (UP032)

Convert to f-string


1395-1395: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


1400-1402: Use f-string instead of format call (UP032)

Convert to f-string


1413-1413: Use f-string instead of format call (UP032)

Convert to f-string


1453-1453: Use f-string instead of format call (UP032)

Convert to f-string


1459-1459: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


1468-1468: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


1490-1490: Use f-string instead of format call (UP032)

Convert to f-string


1505-1505: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


1538-1538: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


1544-1544: Loop control variable ipatch not used within loop body (B007)


1561-1561: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


1718-1718: Use f-string instead of format call (UP032)

Convert to f-string


1765-1765: Loop control variable time not used within loop body (B007)

Rename unused time to _time


1766-1766: Loop control variable ilvl not used within loop body (B007)

Rename unused ilvl to _ilvl


1767-1767: Loop control variable ip not used within loop body (B007)

Rename unused ip to _ip


1820-1820: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()

Additional comments not posted (34)
tests/amr/data/particles/refine/input/input_3d_ratio_2.txt (1)

10-11: Mismatch in dimension configuration.

The dim parameter is set to 1, which is inconsistent with the rest of the configuration that is clearly intended for a 3D simulation. This needs to be corrected to avoid potential errors in simulation behavior.

-    dim = 1
+    dim = 3

Likely invalid or redundant comment.

tests/simulator/advance/CMakeLists.txt (1)

21-24: Ensure proper documentation for 3D test configurations.

The addition of 3D tests in the CMake file is crucial for the new functionality. It's important to ensure that these tests are well documented, especially since they are resource-intensive and turned off by default.

tests/diagnostic/CMakeLists.txt (1)

37-41: Addition of 3D diagnostic tests and configuration files.

The inclusion of 3D diagnostic tests (test-diagnostics_3d) and the configuration of the corresponding Python job file (job_3d.py.in) are consistent with the expansion into 3D functionalities. It's important to verify that these tests cover all necessary aspects of the new 3D features.

Verification successful

Addition of 3D diagnostic tests and configuration files.

The test-diagnostics_3d.cpp file includes several test cases for 3D diagnostics using TYPED_TEST, covering fluid, particles, electromagnetics, and allFromPython tests. This confirms that the necessary 3D diagnostic test coverage is present.

  • TYPED_TEST(Simulator3dTest, fluid)
  • TYPED_TEST(Simulator3dTest, particles)
  • TYPED_TEST(Simulator3dTest, electromag)
  • TYPED_TEST(Simulator3dTest, allFromPython)
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the coverage of 3D diagnostic tests.

# Test: Search for 3D diagnostic test cases in the test files. Expect: Relevant test cases covering new features.
rg --type cpp "TEST_F(Simulator3dTest, .*)" tests/diagnostic/test-diagnostics_3d.cpp

Length of output: 86



Script:

#!/bin/bash
# List all files in the tests/diagnostic directory to verify the presence of test-diagnostics_3d.cpp
ls tests/diagnostic

Length of output: 207



Script:

#!/bin/bash
# List all test functions within test-diagnostics_3d.cpp
rg "TEST_F" tests/diagnostic/test-diagnostics_3d.cpp

Length of output: 52



Script:

#!/bin/bash
# Display the content of test-diagnostics_3d.cpp to investigate for any test functions or relevant content.
cat tests/diagnostic/test-diagnostics_3d.cpp

Length of output: 759

tests/simulator/initialize/test_fields_init_2d.py (1)

26-26: Explicit specification of ppc parameter for 2D field initialization tests.

The addition of the ppc parameter in the test method call ensures that particle-per-cell counts are explicitly controlled during the test, which is crucial for accurate and consistent testing outcomes.

tests/simulator/advance/test_particles_advance_3d.py (2)

25-43: Test function implementation looks good.

The function test_overlapped_particledatas_have_identical_particles is well-implemented, using dynamic data generation for different interpolation orders and refinement scenarios. The parameters are correctly passed to the underlying test method.


45-47: Particle conservation test is correctly implemented.

The test test_L0_particle_number_conservation correctly sets up and executes the conservation test for particles at the coarsest level of refinement.

tests/simulator/initialize/test_fields_init_3d.py (4)

23-26: Field initialization test is properly implemented.

The function test_B_is_as_provided_by_user correctly logs the test execution and calls the underlying test method with appropriate parameters.


28-33: Bulk velocity initialization test is correctly implemented.

The function test_bulkvel_is_as_provided_by_user ensures that the bulk velocity field is initialized as specified, with appropriate logging and parameter handling.


35-38: Density field test is implemented correctly.

The function test_density_is_as_provided_by_user performs as expected, ensuring the density field is initialized correctly, with appropriate logging.


40-45: Density scaling test is implemented with caution regarding memory usage.

The function test_density_decreases_as_1overSqrtN is correctly implemented to check the scaling of density. The comment about high RAM usage is a good practice to caution about potential resource constraints during testing.

res/amr/splitting.yml (1)

103-141: 3D particle splitting configurations are well-defined.

The newly added configurations for 3D particle splitting in splitting.yml are clearly defined with appropriate delta and weight values for various particle counts and interpolation orders.

.github/workflows/cmake_macos.yml (1)

87-87: Appropriate configuration for PHARE simulator in MacOS builds.

The addition of -DPHARE_SIMULATORS=2 in the CMake configuration ensures that the PHARE simulator is appropriately configured for MacOS builds.

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

5-5: Include standard libraries at the top.

It is a good practice to include standard libraries at the top of the file to avoid hidden dependencies and to improve readability.


18-18: Enum definition is clear and concise.

The QtyCentering enum is well-defined, using std::uint16_t for storage, which is appropriate given the limited range of values.

src/amr/data/particles/refine/splitter.hpp (1)

70-70: Potential performance improvement in particle dispatching.

The loop in the PatternDispatcher is complex and might benefit from optimization. Consider caching the results of power[dimension - 1] outside the loop to avoid repeated calculations. Additionally, ensure that the variable weight is used effectively or remove it if it's redundant.

[PERFORMANCE]

- auto weight = static_cast<Weight_t>(pattern.weight_);
+ auto power_factor = power[dimension - 1];
+ for (size_t rpIndex = 0; rpIndex < pattern.deltas_.size(); rpIndex++)
+ {
+     FineParticle fineParticle = particles[idx++];
+     fineParticle.weight       = particle.weight * static_cast<Weight_t>(pattern.weight_)
+                                 * power_factor;
+     // Other operations...
+ }
src/amr/data/particles/refine/split_1d.hpp (8)

34-34: Use of Dispatcher in Template Specialization

The use of PatternDispatcher with PinkPattern<DimConst<1>> is a good example of utilizing template metaprogramming to enforce type safety and reduce code duplication. This is a clean implementation that leverages C++ templates effectively.


53-53: Dispatcher Configuration for Multiple Patterns

The configuration of PatternDispatcher to use multiple patterns (BlackPattern and PinkPattern) is a robust design choice that enhances the flexibility of the Splitter template specialization. This approach allows for easy extension or modification of behavior based on different patterns.


71-71: Consistency in Dispatcher Usage

The consistent use of PatternDispatcher across different template specializations maintains a clean and maintainable code structure. This pattern ensures that all splitter behaviors are centralized and easy to manage.


90-90: Effective Use of Multiple Dispatchers

The use of PatternDispatcher with both BlackPattern and PinkPattern for the Splitter template specialization is an excellent example of how complex behaviors can be modularly constructed using template metaprogramming.


109-109: Dual Pattern Dispatcher for Enhanced Flexibility

The implementation of SplitPattern_1_2_4_Dispatcher using two instances of PinkPattern showcases the flexibility of the dispatcher mechanism to handle more complex scenarios where multiple patterns are involved.


146-146: Use of Multiple Dispatchers in a Single Splitter

The configuration of SplitPattern_1_3_3_Dispatcher to use both BlackPattern and PinkPattern is a robust design choice that allows for flexible behavior in particle splitting. This pattern of using multiple dispatchers enhances the modularity and reusability of the code.


165-165: Dispatcher Configuration for Complex Splitting Patterns

The use of dual PinkPattern in SplitPattern_1_3_4_Dispatcher effectively demonstrates the capability to handle complex particle splitting scenarios, providing a clear and maintainable approach to defining splitting behavior.


184-184: Complex Dispatcher Configuration for Advanced Splitting

The implementation of SplitPattern_1_3_5_Dispatcher using three instances of PinkPattern is an advanced use of the dispatcher pattern, allowing for highly customizable and complex particle splitting behavior.

src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1)

52-59: Check consistency in physical quantity assertions.

The assertion checks if the physical quantities of fineField and coarseField are the same. This is crucial for ensuring that the operation is performed on compatible fields. Always ensure that such critical checks are well-documented for maintainability.

tests/core/data/ndarray/test_main.cpp (1)

395-446: Enhance 3D array operations testing.

The tests for 3D operations using MaskedView3d are well-structured and cover various scenarios, including edge cases and boundary conditions. This is crucial for ensuring the robustness of 3D data handling capabilities.

src/amr/data/particles/refine/split_3d.hpp (2)

19-41: Verify consistency and correctness in particle splitting patterns.

The PinkPattern for 3D particle splitting is implemented with consideration for symmetry and efficiency. Ensure the correctness of the pattern logic, especially the sign handling and offset calculations, as these are critical for the accuracy of particle distribution.


66-87: Optimize LimePattern implementation.

The LimePattern implementation uses lambda functions to avoid code duplication. This is a good practice for maintainability. However, consider potential performance implications of using lambdas in this context, especially regarding inlining and overhead.

src/amr/data/particles/refine/split_2d.hpp (2)

93-93: Approval of Dispatcher usage.

The usage of PatternDispatcher in various Splitter templates is consistent and appears to follow a clear pattern. This should facilitate the addition of new patterns or modifications to existing ones without significant refactoring.

Also applies to: 112-112, 131-132, 169-169, 188-188, 207-208, 227-228, 266-266, 285-285, 304-305, 324-326


62-62: Consistency check for PinkPattern constructor.

The initialization of deltas_ in PinkPattern seems inconsistent with its siblings like PurplePattern. If this is intentional, it would be beneficial to add a comment here to clarify why the deltas are set differently, to avoid confusion during future code modifications.

Verification successful

Consistency check for PinkPattern constructor.

The initialization of deltas_ in PinkPattern appears consistent with other patterns like PurplePattern. Both patterns initialize the deltas_ array based on the delta parameter. However, if there are specific differences in the way deltas_ are set that are intentional, it would be beneficial to document these differences with comments to avoid confusion during future code modifications.

  • File: src/amr/data/particles/refine/split_2d.hpp
  • Lines to check: Initialization of deltas_ in PinkPattern and PurplePattern.
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Check if there are similar patterns with different delta initializations and document them.

# Search for similar patterns in other files to compare delta initializations.
rg --type cpp $'constexpr .*Pattern\(float const weight, float const delta\)'

Length of output: 730



Script:

#!/bin/bash
# Description: Extract initialization details of deltas_ in each pattern to verify consistency.

# Search for the initialization of deltas_ in PinkPattern, PurplePattern, and other patterns.
rg --type cpp 'deltas_' src/amr/data/particles/refine/split_*.hpp

Length of output: 3024

pyphare/pyphare/core/gridlayout.py (1)

Line range hint 176-176: Avoid mutable default arguments for better safety.

Using mutable default arguments like Box(0, 0) can lead to unexpected behaviors. Consider using None and initializing within the function.
[REFACTOR_SUGGESTion]

- def __init__(self, box=Box(0, 0), origin=0, dl=0.1, interp_order=1, field_ghosts_nbr=-1):
+ def __init__(self, box=None, origin=0, dl=0.1, interp_order=1, field_ghosts_nbr=-1):
+     if box is None:
+         box = Box(0, 0)
pyphare/pyphare/pharesee/geometry.py (1)

58-73: Refactor the repetitive code for defining border ghost boxes.

The repetitive code for defining border ghost boxes in different dimensions could be refactored to improve maintainability and reduce redundancy. Consider using a helper function as previously suggested.

tests/simulator/test_initialization.py (2)

591-591: Avoid using Yoda conditions.

Yoda conditions can reduce code readability. It's more natural to write conditions in a direct order in Python.

- self.assertTrue((ppc == H).all())
+ self.assertTrue((H == ppc).all())

Likely invalid or redundant comment.

Tools
Ruff

591-591: Yoda conditions are discouraged, use ppc == H instead (SIM300)

Replace Yoda condition with ppc == H


669-669: Remove unused local variable.

The variable out is defined but not used, which can be confusing and misleading.

- out = "phare_outputs"

Likely invalid or redundant comment.

Tools
Ruff

669-669: Local variable out is assigned to but never used (F841)

Remove assignment to unused variable out

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

Line range hint 651-651: Use is None for None checks.

This is the idiomatic way to check for None in Python.

- if cond == None:
+ if cond is None:

[REFACTOR_Suggestion]

Comment on lines +776 to +783
TYPED_TEST_P(ACollectionOfParticles_3d, DepositCorrectlyTheirWeight_3d)
{
// auto const& [vx, vy, vz] = this->v();
// EXPECT_DOUBLE_EQ(this->rho(7, 7, 7), 1.0);
// EXPECT_DOUBLE_EQ(vx(7, 7, 7), 2.0);
// EXPECT_DOUBLE_EQ(vy(7, 7, 7), -1.0);
// EXPECT_DOUBLE_EQ(vz(7, 7, 7), 1.0);
}
Copy link

Choose a reason for hiding this comment

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

Uncomment and verify the test case DepositCorrectlyTheirWeight_3d.

The test case is crucial for validating 3D interpolation correctness but is currently commented out. This needs to be active to ensure the functionality is tested properly.

-    // auto const& [vx, vy, vz] = this->v();
-    // EXPECT_DOUBLE_EQ(this->rho(7, 7, 7), 1.0);
-    // EXPECT_DOUBLE_EQ(vx(7, 7, 7), 2.0);
-    // EXPECT_DOUBLE_EQ(vy(7, 7, 7), -1.0);
-    // EXPECT_DOUBLE_EQ(vz(7, 7, 7), 1.0);
+    auto const& [vx, vy, vz] = this->v();
+    EXPECT_DOUBLE_EQ(this->rho(7, 7, 7), 1.0);
+    EXPECT_DOUBLE_EQ(vx(7, 7, 7), 2.0);
+    EXPECT_DOUBLE_EQ(vy(7, 7, 7), -1.0);
+    EXPECT_DOUBLE_EQ(vz(7, 7, 7), 1.0);
Committable suggestion

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

Suggested change
TYPED_TEST_P(ACollectionOfParticles_3d, DepositCorrectlyTheirWeight_3d)
{
// auto const& [vx, vy, vz] = this->v();
// EXPECT_DOUBLE_EQ(this->rho(7, 7, 7), 1.0);
// EXPECT_DOUBLE_EQ(vx(7, 7, 7), 2.0);
// EXPECT_DOUBLE_EQ(vy(7, 7, 7), -1.0);
// EXPECT_DOUBLE_EQ(vz(7, 7, 7), 1.0);
}
TYPED_TEST_P(ACollectionOfParticles_3d, DepositCorrectlyTheirWeight_3d)
{
auto const& [vx, vy, vz] = this->v();
EXPECT_DOUBLE_EQ(this->rho(7, 7, 7), 1.0);
EXPECT_DOUBLE_EQ(vx(7, 7, 7), 2.0);
EXPECT_DOUBLE_EQ(vy(7, 7, 7), -1.0);
EXPECT_DOUBLE_EQ(vz(7, 7, 7), 1.0);
}

@@ -257,19 +256,26 @@ def vthz(*xyz):
)
return mom_hier

def _test_B_is_as_provided_by_user(self, dim, interp_order, **kwargs):
def _test_B_is_as_provided_by_user(self, dim, interp_order, ppc=100, **kwargs):
print(
"test_B_is_as_provided_by_user : dim {} interp_order : {}".format(
Copy link

Choose a reason for hiding this comment

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

Use f-strings for string formatting.

Python's f-string provides a more readable, concise, and less error-prone way of formatting strings compared to the format method.

- "test_B_is_as_provided_by_user : dim  {} interp_order : {}".format(dim, interp_order)
+ f"test_B_is_as_provided_by_user : dim  {dim} interp_order : {interp_order}"

Apply similar changes to other lines where format is used.

Also applies to: 289-289, 385-385, 387-387, 450-450, 452-452, 539-539, 613-615

Tools
Ruff

261-263: Use f-string instead of format call (UP032)

Convert to f-string

Comment on lines +9 to +11
#if !defined(PHARE_SIMULATORS)
#define PHARE_SIMULATORS 3
#endif
Copy link

Choose a reason for hiding this comment

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

Ensure the default value for PHARE_SIMULATORS is well-documented.

The macro PHARE_SIMULATORS is defined with a default value of 3. It's important to document this value in the code or in related documentation to clarify its impact and usage within the project.

+ 1.0 / np.cosh((y - L * 0.7) / 0.5) ** 2
)

def S(y, y0, l):
Copy link

Choose a reason for hiding this comment

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

Rename the ambiguous variable 'l' to 'length' for clarity.

The variable l is ambiguous and can be mistaken for the number 1. Renaming it to length will improve readability.

- def S(y, y0, l):
+ def S(y, y0, length):
Committable suggestion

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

Suggested change
def S(y, y0, l):
def S(y, y0, length):
Tools
Ruff

62-62: Ambiguous variable name: l (E741)

Comment on lines +78 to +117
# 1d
# refine 10 cells in 1d, ppc 100
# 10 * 2 * ppc = 200
# 10 * 3 * ppc = 300 300 / 200 = 1.5
# 10 * 4 * ppc = 400 500 / 400 = 1.33
# 10 * 5 * ppc = 500 500 / 400 = 1.25
# taking the minimul diff across permutations
# current to previous should be at least this times bigger
PRIOR_MIN_DIFF_1d = 1.25
PRIOR_MAX_DIFF_1d = 1.50

def test_1d(self):
This = type(self)
self._do_dim(
1, This.PREVIOUS_ITERATION_MIN_DIFF_1d, This.PREVIOUS_ITERATION_MAX_DIFF_1d
)

""" 2d
refine 10x10 cells in 2d, ppc 100
10 * 10 * 4 * ppc = 400
10 * 10 * 8 * ppc = 800 800 / 400 = 1.5
10 * 10 * 9 * ppc = 900 900 / 800 = 1.125
"""
PREVIOUS_ITERATION_MIN_DIFF_2d = 1.125
PREVIOUS_ITERATION_MAX_DIFF_2d = 1.50
self._do_dim(1, This.PRIOR_MIN_DIFF_1d, This.PRIOR_MAX_DIFF_1d)

# 2d
# refine 10x10 cells in 2d, ppc 100
# 10 * 10 * 4 * ppc = 400
# 10 * 10 * 8 * ppc = 800 800 / 400 = 1.5
# 10 * 10 * 9 * ppc = 900 900 / 800 = 1.125
PRIOR_MIN_DIFF_2d = 1.125
PRIOR_MAX_DIFF_2d = 1.50

def test_2d(self):
This = type(self)
self._do_dim(
2, This.PREVIOUS_ITERATION_MIN_DIFF_2d, This.PREVIOUS_ITERATION_MAX_DIFF_2d
)
self._do_dim(2, This.PRIOR_MIN_DIFF_2d, This.PRIOR_MAX_DIFF_2d)

def tearDown(self):
# needed in case exception is raised in test and Simulator
# not reset properly
if self.simulator is not None:
self.simulator.reset()
# 3d
# refine 10x10x10 cells in 3d, ppc 100
# 10 * 10 * 10 * 6 * ppc = 6000
# 10 * 10 * 10 * 12 * ppc = 12000 - 12000 / 6000 = 2
# 10 * 10 * 10 * 27 * ppc = 27000 - 27000 / 12000 = 2.25
PRIOR_MIN_DIFF_3d = 2
PRIOR_MAX_DIFF_3d = 2.25

def test_3d(self):
This = type(self)
self._do_dim(3, This.PRIOR_MIN_DIFF_3d, This.PRIOR_MAX_DIFF_3d)

def _check_deltas_and_weights(self, dim, interp, refined_particle_nbr):
Copy link

Choose a reason for hiding this comment

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

Clarify the calculations in the _do_dim method.

The calculations in the _do_dim method are critical for ensuring the correct number of particles are refined. Adding comments to explain the logic behind these calculations and assertions would significantly improve code clarity and maintainability.

+ # Calculate the minimum and maximum differences expected between the current and previous number of particles
+ # This is used to ensure that the particle refinement is within expected bounds

Committable suggestion was skipped due to low confidence.

Comment on lines +43 to +63
template<> // 1 per corner
struct PurplePattern<DimConst<3>> : SplitPattern<DimConst<3>, RefinedParticlesConst<8>>
{
using Super = SplitPattern<DimConst<3>, RefinedParticlesConst<8>>;

constexpr PurplePattern(float const weight, float const delta)
: Super{weight}
{
for (std::size_t i = 0; i < 2; i++)
{
std::size_t offset = i * 4;
float sign = i % 2 ? -1 : 1;
auto mode = delta * sign;

Super::deltas_[0 + offset] = {mode, mode, mode};
Super::deltas_[1 + offset] = {mode, mode, -mode};
Super::deltas_[2 + offset] = {mode, -mode, mode};
Super::deltas_[3 + offset] = {mode, -mode, -mode};
}
}
};
Copy link

Choose a reason for hiding this comment

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

Tip

Codebase Verification

Check for potential floating-point precision issues.

The search results indicate the usage of double precision (double) in various parts of the codebase, but there are no specific precision controls or higher precision data types (float and double) directly related to the PurplePattern structure. The presence of precision handling mechanisms in other parts of the codebase suggests awareness of potential precision issues.

Given the floating-point operations in PurplePattern, it is advisable to consider introducing precision controls or using higher precision data types if the precision requirements are critical.

  • Consider using double instead of float for higher precision.
  • Introduce precision handling mechanisms where necessary.

Locations to review:

  • src/amr/data/particles/refine/split_3d.hpp (Lines 43-63)
Analysis chain

Check for potential floating-point precision issues.

The PurplePattern uses floating-point operations which might introduce precision issues, especially with the negation and addition operations. Consider verifying the precision requirements and if necessary, introduce precision controls or use higher precision data types.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Check for precision issues in floating-point operations.

# Test: Search for floating-point precision handling in the project.
rg --type cpp 'float' | grep 'precision'

Length of output: 264



Script:

#!/bin/bash
# Description: Check for precision handling mechanisms or higher precision data types in the project.

# Search for any usage of double or higher precision data types in the codebase.
rg --type cpp 'double' 

# Search for any precision handling mechanisms in the codebase.
rg --type cpp 'precision'

Length of output: 93798

Comment on lines +24 to +97

@ddt
class Initialization3DTest(InitializationTest):
@data(*interp_orders)
def test_nbr_particles_per_cell_is_as_provided(self, interp_order):
print(f"{self._testMethodName}_{ndim}d")
self._test_nbr_particles_per_cell_is_as_provided(
ndim, interp_order, ppc, cells=cells
)

@data(
*per_interp(({"L0": {"B0": Box3D(10, 14)}})),
*per_interp(({"L0": {"B0": Box3D(10, 14)}, "L1": {"B0": Box3D(22, 26)}})),
*per_interp(({"L0": {"B0": Box3D(2, 6), "B1": Box3D(7, 11)}})),
)
@unpack
def test_levelghostparticles_have_correct_split_from_coarser_particle(
self, interp_order, refinement_boxes
):
print(f"\n{self._testMethodName}_{ndim}d")
now = self.datetime_now()
self._test_levelghostparticles_have_correct_split_from_coarser_particle(
self.getHierarchy(
ndim,
interp_order,
refinement_boxes,
"particles",
cells=cells,
nbr_part_per_cell=ppc,
)
)
print(
f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds"
)

@data(
*per_interp(({"L0": {"B0": Box3D(10, 14)}})),
*per_interp(({"L0": {"B0": Box3D(5, 14)}, "L1": {"B0": Box3D(15, 19)}})),
*per_interp(({"L0": {"B0": Box3D(2, 12), "B1": Box3D(13, 25)}})),
)
@unpack
def test_domainparticles_have_correct_split_from_coarser_particle(
self, interp_order, refinement_boxes
):
print(f"\n{self._testMethodName}_{ndim}d")
now = self.datetime_now()
self._test_domainparticles_have_correct_split_from_coarser_particle(
ndim, interp_order, refinement_boxes, nbr_part_per_cell=ppc
)
print(
f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds"
)

# @data({"cells": 40, "smallest_patch_size": 20, "largest_patch_size": 20, "nbr_part_per_cell" : ppc})
# def test_no_patch_ghost_on_refined_level_case(self, simInput):
# print(f"\n{self._testMethodName}_{ndim}d")
# now = self.datetime_now()
# self._test_patch_ghost_on_refined_level_case(ndim, False, **simInput)
# print(f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds")

# @data({"cells": 40, "interp_order": 1, "nbr_part_per_cell" : ppc})
# def test_has_patch_ghost_on_refined_level_case(self, simInput):
# print(f"\n{self._testMethodName}_{ndim}d")
# from pyphare.pharein.simulation import check_patch_size
# diag_outputs=f"phare_overlaped_fields_are_equal_with_min_max_patch_size_of_max_ghosts_{ndim}_{self.ddt_test_id()}"
# _, smallest_patch_size = check_patch_size(ndim, **simInput)
# simInput["smallest_patch_size"] = smallest_patch_size
# simInput["largest_patch_size"] = smallest_patch_size
# now = self.datetime_now()
# self._test_patch_ghost_on_refined_level_case(ndim, True, **simInput)
# print(f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds")


if __name__ == "__main__":
Copy link

Choose a reason for hiding this comment

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

Refactor suggested to enhance code quality and maintainability.

  1. Remove commented-out code: Lines 77-94 contain commented-out test cases. If these are not needed, they should be removed to clean up the codebase. If they are to be used in the future, it would be better to document their purpose clearly or implement them in a feature branch.

  2. Simplify expressions: The use of extraneous parentheses in lines 35, 36, 37, 60, 61, and 62 can be removed to clean up the code and adhere to Pythonic best practices.

- *per_interp(({"L0": {"B0": Box3D(10, 14)}})),
- *per_interp(({"L0": {"B0": Box3D(10, 14), "L1": {"B0": Box3D(22, 26)}})),
- *per_interp(({"L0": {"B0": Box3D(2, 6), "B1": Box3D(7, 11)}})),
+ *per_interp({"L0": {"B0": Box3D(10, 14)}}),
+ *per_interp({"L0": {"B0": Box3D(10, 14), "L1": {"B0": Box3D(22, 26)}}),
+ *per_interp({"L0": {"B0": Box3D(2, 6), "B1": Box3D(7, 11)}}),
Committable suggestion

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

Suggested change
@ddt
class Initialization3DTest(InitializationTest):
@data(*interp_orders)
def test_nbr_particles_per_cell_is_as_provided(self, interp_order):
print(f"{self._testMethodName}_{ndim}d")
self._test_nbr_particles_per_cell_is_as_provided(
ndim, interp_order, ppc, cells=cells
)
@data(
*per_interp(({"L0": {"B0": Box3D(10, 14)}})),
*per_interp(({"L0": {"B0": Box3D(10, 14)}, "L1": {"B0": Box3D(22, 26)}})),
*per_interp(({"L0": {"B0": Box3D(2, 6), "B1": Box3D(7, 11)}})),
)
@unpack
def test_levelghostparticles_have_correct_split_from_coarser_particle(
self, interp_order, refinement_boxes
):
print(f"\n{self._testMethodName}_{ndim}d")
now = self.datetime_now()
self._test_levelghostparticles_have_correct_split_from_coarser_particle(
self.getHierarchy(
ndim,
interp_order,
refinement_boxes,
"particles",
cells=cells,
nbr_part_per_cell=ppc,
)
)
print(
f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds"
)
@data(
*per_interp(({"L0": {"B0": Box3D(10, 14)}})),
*per_interp(({"L0": {"B0": Box3D(5, 14)}, "L1": {"B0": Box3D(15, 19)}})),
*per_interp(({"L0": {"B0": Box3D(2, 12), "B1": Box3D(13, 25)}})),
)
@unpack
def test_domainparticles_have_correct_split_from_coarser_particle(
self, interp_order, refinement_boxes
):
print(f"\n{self._testMethodName}_{ndim}d")
now = self.datetime_now()
self._test_domainparticles_have_correct_split_from_coarser_particle(
ndim, interp_order, refinement_boxes, nbr_part_per_cell=ppc
)
print(
f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds"
)
# @data({"cells": 40, "smallest_patch_size": 20, "largest_patch_size": 20, "nbr_part_per_cell" : ppc})
# def test_no_patch_ghost_on_refined_level_case(self, simInput):
# print(f"\n{self._testMethodName}_{ndim}d")
# now = self.datetime_now()
# self._test_patch_ghost_on_refined_level_case(ndim, False, **simInput)
# print(f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds")
# @data({"cells": 40, "interp_order": 1, "nbr_part_per_cell" : ppc})
# def test_has_patch_ghost_on_refined_level_case(self, simInput):
# print(f"\n{self._testMethodName}_{ndim}d")
# from pyphare.pharein.simulation import check_patch_size
# diag_outputs=f"phare_overlaped_fields_are_equal_with_min_max_patch_size_of_max_ghosts_{ndim}_{self.ddt_test_id()}"
# _, smallest_patch_size = check_patch_size(ndim, **simInput)
# simInput["smallest_patch_size"] = smallest_patch_size
# simInput["largest_patch_size"] = smallest_patch_size
# now = self.datetime_now()
# self._test_patch_ghost_on_refined_level_case(ndim, True, **simInput)
# print(f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds")
if __name__ == "__main__":
@ddt
class Initialization3DTest(InitializationTest):
@data(*interp_orders)
def test_nbr_particles_per_cell_is_as_provided(self, interp_order):
print(f"{self._testMethodName}_{ndim}d")
self._test_nbr_particles_per_cell_is_as_provided(
ndim, interp_order, ppc, cells=cells
)
@data(
*per_interp({"L0": {"B0": Box3D(10, 14)}}),
*per_interp({"L0": {"B0": Box3D(10, 14), "L1": {"B0": Box3D(22, 26)}}),
*per_interp({"L0": {"B0": Box3D(2, 6), "B1": Box3D(7, 11)}}),
)
@unpack
def test_levelghostparticles_have_correct_split_from_coarser_particle(
self, interp_order, refinement_boxes
):
print(f"\n{self._testMethodName}_{ndim}d")
now = self.datetime_now()
self._test_levelghostparticles_have_correct_split_from_coarser_particle(
self.getHierarchy(
ndim,
interp_order,
refinement_boxes,
"particles",
cells=cells,
nbr_part_per_cell=ppc,
)
)
print(
f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds"
)
@data(
*per_interp({"L0": {"B0": Box3D(10, 14)}}),
*per_interp({"L0": {"B0": Box3D(5, 14)}, "L1": {"B0": Box3D(15, 19)}}),
*per_interp({"L0": {"B0": Box3D(2, 12), "B1": Box3D(13, 25)}}),
)
@unpack
def test_domainparticles_have_correct_split_from_coarser_particle(
self, interp_order, refinement_boxes
):
print(f"\n{self._testMethodName}_{ndim}d")
now = self.datetime_now()
self._test_domainparticles_have_correct_split_from_coarser_particle(
ndim, interp_order, refinement_boxes, nbr_part_per_cell=ppc
)
print(
f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds"
)
# @data({"cells": 40, "smallest_patch_size": 20, "largest_patch_size": 20, "nbr_part_per_cell" : ppc})
# def test_no_patch_ghost_on_refined_level_case(self, simInput):
# print(f"\n{self._testMethodName}_{ndim}d")
# now = self.datetime_now()
# self._test_patch_ghost_on_refined_level_case(ndim, False, **simInput)
# print(f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds")
# @data({"cells": 40, "interp_order": 1, "nbr_part_per_cell" : ppc})
# def test_has_patch_ghost_on_refined_level_case(self, simInput):
# print(f"\n{self._testMethodName}_{ndim}d")
# from pyphare.pharein.simulation import check_patch_size
# diag_outputs=f"phare_overlaped_fields_are_equal_with_min_max_patch_size_of_max_ghosts_{ndim}_{self.ddt_test_id()}"
# _, smallest_patch_size = check_patch_size(ndim, **simInput)
# simInput["smallest_patch_size"] = smallest_patch_size
# simInput["largest_patch_size"] = smallest_patch_size
# now = self.datetime_now()
# self._test_patch_ghost_on_refined_level_case(ndim, True, **simInput)
# print(f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds")
if __name__ == "__main__":
Tools
Ruff

35-35: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


36-36: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


37-37: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


60-60: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


61-61: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


62-62: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses

def binary_exists_on_path(bin):
"""
https://linux.die.net/man/1/which
"""
return run(f"which {bin}").returncode == 0
return len(find_on_path(bin))


def scan_dir(path, files_only=False, dirs_only=False, drop=[]):
Copy link

Choose a reason for hiding this comment

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

Avoid mutable default arguments.

Using mutable default arguments can lead to unexpected behaviors. Replace the mutable default with None and initialize it within the function if necessary.

- def scan_dir(path, files_only=False, dirs_only=False, drop=[]):
+ def scan_dir(path, files_only=False, dirs_only=False, drop=None):
+     if drop is None:
+         drop = []
Committable suggestion

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

Suggested change
def scan_dir(path, files_only=False, dirs_only=False, drop=[]):
def scan_dir(path, files_only=False, dirs_only=False, drop=None):
if drop is None:
drop = []
Tools
Ruff

95-95: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function

Comment on lines +24 to +107

@ddt
class AdvanceTest(AdvanceTestBase):
@data(
*per_interp({}),
*per_interp({"L0": [Box3D(10, 19)]}),
*per_interp({"L0": [Box3D(8, 20)]}),
)
@unpack
def test_overlaped_fields_are_equal(self, interp_order, refinement_boxes):
print(f"{self._testMethodName}_{ndim}d")
time_step_nbr = 3
time_step = 0.001
datahier = self.getHierarchy(
ndim,
interp_order,
refinement_boxes,
"eb",
cells=cells,
time_step=time_step,
time_step_nbr=time_step_nbr,
nbr_part_per_cell=ppc,
)
self._test_overlaped_fields_are_equal(datahier, time_step_nbr, time_step)

@data(
*per_interp({}),
*per_interp({"L0": [Box3D(5, 14)]}),
)
@unpack
def test_overlaped_fields_are_equal_with_min_max_patch_size_of_max_ghosts(
self, interp_order, refinement_boxes
):
print(f"{self._testMethodName}_{ndim}d")
time_step_nbr = 3
time_step = 0.001
from pyphare.pharein.simulation import check_patch_size

largest_patch_size, smallest_patch_size = check_patch_size(
ndim, interp_order=interp_order, cells=[cells] * ndim
)
datahier = self.getHierarchy(
ndim,
interp_order,
refinement_boxes,
"eb",
cells=cells,
smallest_patch_size=smallest_patch_size,
largest_patch_size=smallest_patch_size,
time_step=time_step,
time_step_nbr=time_step_nbr,
nbr_part_per_cell=ppc,
)
self._test_overlaped_fields_are_equal(datahier, time_step_nbr, time_step)

# @data(
# *per_interp(({"L0": {"B0": Box3D(10, 14)}})),
# *per_interp(({"L0": {"B0": Box3D(10, 14), "B1": Box3D(15, 19)}})),
# *per_interp(({"L0": {"B0": Box3D(6, 23)}})),
# *per_interp(({"L0": {"B0": Box3D( 2, 12), "B1": Box3D(13, 25)}})),
# *per_interp(({"L0": {"B0": Box3D( 5, 20)}, "L1": {"B0": Box3D(15, 19)}})),
# *per_interp(({"L0": {"B0": Box3D( 5, 20)}, "L1": {"B0": Box3D(12, 38)}, "L2": {"B0": Box3D(30, 52)} })),
# )
# @unpack
# def test_field_coarsening_via_subcycles(self, interp_order, refinement_boxes):
# print(f"{self._testMethodName}_{ndim}d")
# self._test_field_coarsening_via_subcycles(ndim, interp_order, refinement_boxes, dl=.3, cells=cells)

# @unittest.skip("should change to work on moments")
# @data( # only supports a hierarchy with 2 levels
# *per_interp(({"L0": [Box3D(0, 4)]})),
# *per_interp(({"L0": [Box3D(10, 14)]})),
# *per_interp(({"L0": [Box3D(0, 4), Box3D(10, 14)]})),
# *per_interp(({"L0": [Box3D(0, 4), Box3D(5, 9), Box3D(10, 14)]})),
# *per_interp(({"L0": [Box3D(20, 24)]})),
# )
# @unpack
# def test_field_level_ghosts_via_subcycles_and_coarser_interpolation(self, interp_order, refinement_boxes):
# print(f"{self._testMethodName}_{ndim}d")
# self._test_field_level_ghosts_via_subcycles_and_coarser_interpolation(ndim, interp_order, refinement_boxes)


if __name__ == "__main__":
unittest.main()
Copy link

Choose a reason for hiding this comment

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

Refactor suggested to enhance code quality and maintainability.

  1. Remove commented-out code: Lines 79-103 contain commented-out test cases. If these are not needed, they should be removed to clean up the codebase. If they are to be used in the future, it would be better to document their purpose clearly or implement them in a feature branch.

  2. Simplify expressions: The use of extraneous parentheses in lines 28, 29, 30, 50, and 51 can be removed to clean up the code and adhere to Pythonic best practices.

- *per_interp(({})),
- *per_interp(({"L0": [Box3D(10, 19)]})),
- *per_interp(({"L0": [Box3D(8, 20)]})),
+ *per_interp({}),
+ *per_interp({"L0": [Box3D(10, 19)]}),
+ *per_interp({"L0": [Box3D(8, 20)]}),

Committable suggestion was skipped due to low confidence.

if len(self.quantities()) == 1:
default_qty = self.quantities()[0]
qty = kwargs.get("qty", default_qty)
for lvl_nbr, lvl in self.levels(time).items():
Copy link

Choose a reason for hiding this comment

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

Remove unused loop variable.

The variable lvl is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for lvl_nbr, lvl in self.levels(time).items():
+ for lvl_nbr, _ in self.levels(time).items():
Committable suggestion

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

Suggested change
for lvl_nbr, lvl in self.levels(time).items():
for lvl_nbr, _ in self.levels(time).items():
Tools
Ruff

1034-1034: Loop control variable lvl not used within loop body (B007)

Rename unused lvl to _lvl

@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
@PHAREHUB PHAREHUB deleted a comment from coderabbitai bot Jun 24, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 13

Outside diff range and nitpick comments (20)
tools/python3/git.py (2)

Line range hint 22-22: Remove unused variable.

The variable e is assigned but never used, which could lead to confusion and clutter.

-    except subprocess.CalledProcessError as e:
+    except subprocess.CalledProcessError:

Line range hint 29-29: Undefined function delete_branch.

The function delete_branch is called but not defined within this file or provided in the imports.

Please ensure that delete_branch is defined elsewhere in the codebase or add its definition.

tests/simulator/initialize/test_particles_init_1d.py (1)

Line range hint 33-33: Remove extraneous parentheses.

The parentheses around the dictionary literals are unnecessary and can be removed for cleaner code.

- *per_interp(({"L0": {"B0": Box1D(10, 14)}})),
- *per_interp(({"L0": {"B0": Box1D(5, 20)}, "L1": {"B0": Box1D(15, 35)}})),
- *per_interp(({"L0": {"B0": Box1D(2, 12), "B1": Box1D(13, 25)}})),
+ *per_interp({"L0": {"B0": Box1D(10, 14)}}),
+ *per_interp({"L0": {"B0": Box1D(5, 20)}, "L1": {"B0": Box1D(15, 35)}}),
+ *per_interp({"L0": {"B0": Box1D(2, 12), "B1": Box1D(13, 25)}}),

Also applies to: 34-34, 35-35, 54-54, 55-55, 56-56

tests/simulator/initialize/test_particles_init_2d.py (1)

Line range hint 33-33: Remove extraneous parentheses.

The parentheses around the dictionary literals are unnecessary and can be removed for cleaner code.

- *per_interp(({"L0": {"B0": Box2D(10, 14)}})),
- *per_interp(({"L0": {"B0": Box2D(10, 14)}, "L1": {"B0": Box2D(22, 26)}})),
- *per_interp(({"L0": {"B0": Box2D(2, 6), "B1": Box2D(7, 11)}})),
+ *per_interp({"L0": {"B0": Box2D(10, 14)}}),
+ *per_interp({"L0": {"B0": Box2D(10, 14)}, "L1": {"B0": Box2D(22, 26)}}),
+ *per_interp({"L0": {"B0": Box2D(2, 6), "B1": Box2D(7, 11)}}),

Also applies to: 34-34, 35-35, 58-58, 59-59, 60-60

pyphare/pyphare/core/gridlayout.py (1)

Line range hint 152-155: Use ternary operator for efficiency.

The method to calculate size can be optimized using a ternary operator.

-    if withGhosts:
-        size = nbrCells[dim] + (nbrGhosts * 2)
-    else:
-        size = nbrCells[dim]
+    size = nbrCells[dim] + (nbrGhosts * 2 if withGhosts else 0)
pyphare/pyphare/pharesee/run.py (4)

Line range hint 289-289: Use f-string for consistency and performance.

The use of the format method is less efficient and less readable than f-strings, which are the preferred string formatting method in modern Python.

- t = "{:.10f}".format(time)
+ t = f"{time:.10f}"

Line range hint 371-371: Remove unnecessary f-string prefix.

The f-string prefix is used without placeholders, which is not needed and can be misleading.

- def filename(name):
-     return f"ions_pop_{name}_domain.h5"
+ def filename(name):
+     return "ions_pop_" + name + "_domain.h5"

Also applies to: 373-373


Line range hint 415-415: Use f-string for consistency and performance.

The use of the format method is less efficient and less readable than f-strings, which are the preferred string formatting method in modern Python.

- h5_time_grp_key = "t"
- h5_filename = "EM_B.h5"  # _____ TODO : could be another file
- data_file = h5py.File(os.path.join(self.path, h5_filename), "r")
- if time is None:
-     time = float(list(data_file[h5_time_grp_key].keys())[0])
+ h5_time_grp_key = "t"
+ h5_filename = "EM_B.h5"  # _____ TODO : could be another file
+ data_file = h5py.File(os.path.join(self.path, h5_filename), "r")
+ if time is None:
+     time = float(list(data_file[h5_time_grp_key].keys())[0])

Line range hint 465-465: Avoid using mutable default arguments.

Using mutable data structures like lists as default arguments can lead to unexpected behavior because they can be modified across multiple function calls.

- def make_interpolator(data, coords, interp, domain, dl, qty, nbrGhosts=[]):
+ def make_interpolator(data, coords, interp, domain, dl, qty, nbrGhosts=None):
+     if nbrGhosts is None:
+         nbrGhosts = []
tests/amr/data/field/refine/test_refine_field.py (1)

Line range hint 9-9: Remove redundant assignment.

The variable refinement_ratio is defined twice, which is redundant and can lead to confusion.

- refinement_ratio = 2
Tools
Ruff

106-106: Do not assert False (python -O removes these calls), raise AssertionError() (B011)

Replace assert False

pyphare/pyphare/pharesee/geometry.py (3)

Line range hint 86-187: Consider renaming the variable for clarity in periodicity_shifts.

The use of l as a variable name in list comprehensions is ambiguous and could be improved for better readability.

- f"{k}front": [(v[0], v[1], shape_z) for v in l] for k, l in shifts.items()
+ f"{k}front": [(v[0], v[1], shape_z) for v in values] for k, values in shifts.items()
Tools
Ruff

160-160: Ambiguous variable name: l (E741)


163-163: Ambiguous variable name: l (E741)


166-166: Ambiguous variable name: l (E741)


187-187: Ambiguous variable name: l (E741)


Line range hint 441-464: Unused loop control variable should be renamed for clarity.

The variable pd is not used within the loop body and should be renamed to _.

- for pd_key, pd in patch.patch_datas.items():
+ for pd_key, _ in patch.patch_datas.items():

Line range hint 464-519: Avoid mutable default arguments in level_ghost_boxes.

Using mutable default arguments can lead to bugs. Initialize within the function.

- def level_ghost_boxes(hierarchy, quantities, levelNbrs=[], time=0):
+ def level_ghost_boxes(hierarchy, quantities, levelNbrs=None, time=0):
+     if levelNbrs is None:
+         levelNbrs = []
tests/simulator/test_initialization.py (4)

Line range hint 259-359: Refactor to use f-strings for better readability and performance.

The use of str.format() is less efficient and less readable compared to f-strings, which are available from Python 3.6 onwards. Consider refactoring these to use f-strings, especially in debug and error messages.

- "test_B_is_as_provided_by_user : dim  {} interp_order : {}".format(dim, interp_order)
+ f"test_B_is_as_provided_by_user : dim  {dim} interp_order : {interp_order}"

Optimize list comprehensions in meshgrid operations.

The unpacked list comprehensions used for meshgrid operations can be replaced with generator expressions to optimize memory usage.

- xbx, ybx, zbx = [a.flatten() for a in np.meshgrid(xbx, ybx, zbx, indexing="ij")]
+ xbx, ybx, zbx = (a.flatten() for a in np.meshgrid(xbx, ybx, zbx, indexing="ij"))

The added support for 3-dimensional testing is in line with the PR's objectives to enhance simulation capabilities. The use of np.testing.assert_allclose for precision validation is appropriate and ensures that the simulation results are as expected.

Tools
Ruff

338-340: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


341-343: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


344-346: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


Line range hint 360-421: Consider simplifying the function definition.

The function contains complex logic for calculating expected and actual velocities. Consider breaking down the function into smaller, more manageable parts or utility functions to enhance readability and maintainability.

def calculate_expected_velocity(nprot, vx_fn, select):
    return (nprot(*select) * vx_fn(*select) + nbeam(*select) * vx_fn(*select)) / (nprot(*select) + nbeam(*select))

Use direct comparison instead of Yoda conditions.

In Python, it's more idiomatic to write conditions in a natural order rather than using Yoda conditions.

- self.assertTrue(np.std(vexp - vact) < 1e-2)
+ self.assertLess(np.std(vexp - vact), 1e-2)

The method correctly handles the complexities of 3D data and performs necessary calculations to ensure the accuracy of the simulation results. The use of direct array operations and numpy functions is appropriate for the operations performed.

Tools
Ruff

387-387: Use f-string instead of format call (UP032)

Convert to f-string


399-399: Function definition does not bind loop variable select (B023)


401-401: Function definition does not bind loop variable patch (B023)


401-401: Function definition does not bind loop variable nbrGhosts (B023)


402-402: Function definition does not bind loop variable select (B023)


Line range hint 422-484: Refactor to use f-strings for better readability.

The code uses older .format() syntax for string operations, which can be updated to f-strings for improved readability and performance.

- f"test_density_is_as_provided_by_user : dim {ndim} interp_order {interp_order}"
+ f"test_density_is_as_provided_by_user : dim {ndim} interp_order {interp_order}"

Optimize list comprehensions in meshgrid operations.

Similar to previous methods, replacing unpacked list comprehensions with generator expressions can save memory and potentially improve performance.

- select = tuple([slice(nbrGhosts, -nbrGhosts) for i in range(ndim)])
+ select = tuple(slice(nbrGhosts, -nbrGhosts) for i in range(ndim))

The method's implementation aligns with the objectives of testing density calculations in simulations accurately. The empirical deviations used for assertions ensure that the simulation results are within acceptable limits.

Tools
Ruff

387-387: Use f-string instead of format call (UP032)

Convert to f-string


399-399: Function definition does not bind loop variable select (B023)


401-401: Function definition does not bind loop variable patch (B023)


401-401: Function definition does not bind loop variable nbrGhosts (B023)


402-402: Function definition does not bind loop variable select (B023)


Line range hint 488-566: Refactor to use f-strings and improve code readability.

The method uses older .format() syntax which can be updated to f-strings for improved readability and performance. Additionally, consider adding comments or documentation to explain the plotting logic and its relevance to the test.

- plt.title(r"$\sigma =$ {}".format(noise[inbr]))
+ plt.title(r"$\sigma =$ {noise[inbr]}")

The method effectively demonstrates how density noise decreases with increasing particle counts, which is crucial for validating the physical accuracy of the simulation. The use of matplotlib for plotting is appropriate and helps in visual verification of the results.

Tools
Ruff

539-539: Use f-string instead of format call (UP032)

Convert to f-string

tests/simulator/test_advance.py (3)

Line range hint 33-33: Refactor lambda expression to a function for better readability and maintainability.

The lambda function used here can be replaced with a regular function for clarity. Additionally, consider passing sim as an argument to the _density function to improve encapsulation and testability.

- _ = lambda i: -((xyz[i] - hL[i]) ** 2)
+ def square_difference(i, xyz, hL):
+     return -((xyz[i] - hL[i]) ** 2)
Tools
Ruff

87-87: Ambiguous variable name: l (E741)


Line range hint 48-48: Avoid using mutable default arguments.

Using mutable default arguments can lead to unexpected behavior. Initialize these within the function instead.

- def getHierarchy(self, ndim, interp_order, refinement_boxes, qty, nbr_part_per_cell=100, density=_density, smallest_patch_size=None, largest_patch_size=20, cells=120, time_step=0.001, model_init={}, dl=0.2, extra_diag_options={}, time_step_nbr=1, timestamps=None, block_merging_particles=False, diag_outputs=""):
+ def getHierarchy(self, ndim, interp_order, refinement_boxes, qty, nbr_part_per_cell=100, density=_density, smallest_patch_size=None, largest_patch_size=20, cells=120, time_step=0.001, model_init=None, dl=0.2, extra_diag_options=None, time_step_nbr=1, timestamps=None, block_merging_particles=False, diag_outputs=""):
+     if model_init is None:
+         model_init = {}
+     if extra_diag_options is None:
+         extra_diag_options = {}

Also applies to: 50-50

Tools
Ruff

87-87: Ambiguous variable name: l (E741)


Line range hint 407-409: Improve readability and maintainability.

Replace magic number and use f-string for better readability.

+ MAGIC_NUMBER = -144123
- boxm.DataSelector(afterCoarse)[dataBox] = -144123
+ boxm.DataSelector(afterCoarse)[dataBox] = MAGIC_NUMBER

- print("test_field_coarsening_via_subcycles for dim/interp : {}/{}".format(dim, interp_order))
+ print(f"test_field_coarsening_via_subcycles for dim/interp : {dim}/{interp_order}")

Also applies to: 498-498

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 914fce6 and 18577d8.

Files selected for processing (44)
  • .github/workflows/cmake_macos.yml (1 hunks)
  • pyphare/pyphare/core/box.py (2 hunks)
  • pyphare/pyphare/core/gridlayout.py (1 hunks)
  • pyphare/pyphare/pharesee/geometry.py (7 hunks)
  • pyphare/pyphare/pharesee/hierarchy.py (3 hunks)
  • pyphare/pyphare/pharesee/run.py (1 hunks)
  • res/amr/splitting.yml (1 hunks)
  • res/cmake/options.cmake (1 hunks)
  • src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1 hunks)
  • src/amr/data/particles/refine/split.hpp (1 hunks)
  • src/amr/data/particles/refine/split_1d.hpp (10 hunks)
  • src/amr/data/particles/refine/split_2d.hpp (17 hunks)
  • src/amr/data/particles/refine/split_3d.hpp (1 hunks)
  • src/amr/data/particles/refine/splitter.hpp (2 hunks)
  • src/core/data/grid/gridlayoutdefs.hpp (2 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (8 hunks)
  • src/core/utilities/box/box.hpp (3 hunks)
  • src/core/utilities/meta/meta_utilities.hpp (2 hunks)
  • tests/amr/data/field/refine/test_refine_field.py (1 hunks)
  • tests/amr/data/particles/refine/input/input_3d_ratio_2.txt (1 hunks)
  • tests/amr/data/particles/refine/test_split.cpp (1 hunks)
  • tests/core/data/ndarray/test_main.cpp (1 hunks)
  • tests/core/numerics/interpolator/test_main.cpp (1 hunks)
  • tests/diagnostic/CMakeLists.txt (1 hunks)
  • tests/diagnostic/job_3d.py.in (1 hunks)
  • tests/diagnostic/test-diagnostics_3d.cpp (1 hunks)
  • tests/functional/harris/harris_3d.py (1 hunks)
  • tests/simulator/init.py (2 hunks)
  • tests/simulator/advance/CMakeLists.txt (1 hunks)
  • tests/simulator/advance/test_fields_advance_3d.py (1 hunks)
  • tests/simulator/advance/test_particles_advance_3d.py (1 hunks)
  • tests/simulator/initialize/CMakeLists.txt (1 hunks)
  • tests/simulator/initialize/test_fields_init_2d.py (1 hunks)
  • tests/simulator/initialize/test_fields_init_3d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_1d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_2d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_3d.py (1 hunks)
  • tests/simulator/per_test.hpp (1 hunks)
  • tests/simulator/refined_particle_nbr.py (2 hunks)
  • tests/simulator/test_advance.py (7 hunks)
  • tests/simulator/test_initialization.py (14 hunks)
  • tools/python3/init.py (5 hunks)
  • tools/python3/cmake.py (2 hunks)
  • tools/python3/git.py (1 hunks)
Files skipped from review as they are similar to previous changes (25)
  • .github/workflows/cmake_macos.yml
  • res/amr/splitting.yml
  • res/cmake/options.cmake
  • src/amr/data/particles/refine/split.hpp
  • src/amr/data/particles/refine/split_1d.hpp
  • src/amr/data/particles/refine/split_2d.hpp
  • src/amr/data/particles/refine/splitter.hpp
  • src/core/data/grid/gridlayoutdefs.hpp
  • src/core/data/ndarray/ndarray_vector.hpp
  • src/core/utilities/box/box.hpp
  • src/core/utilities/meta/meta_utilities.hpp
  • tests/amr/data/particles/refine/input/input_3d_ratio_2.txt
  • tests/amr/data/particles/refine/test_split.cpp
  • tests/core/data/ndarray/test_main.cpp
  • tests/core/numerics/interpolator/test_main.cpp
  • tests/diagnostic/CMakeLists.txt
  • tests/diagnostic/job_3d.py.in
  • tests/diagnostic/test-diagnostics_3d.cpp
  • tests/simulator/advance/CMakeLists.txt
  • tests/simulator/advance/test_fields_advance_3d.py
  • tests/simulator/advance/test_particles_advance_3d.py
  • tests/simulator/initialize/CMakeLists.txt
  • tests/simulator/initialize/test_fields_init_2d.py
  • tests/simulator/initialize/test_fields_init_3d.py
  • tests/simulator/per_test.hpp
Additional context used
Path-based instructions (2)
src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1)

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

src/amr/data/particles/refine/split_3d.hpp (1)

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

Ruff
tools/python3/git.py

22-22: Local variable e is assigned to but never used (F841)

Remove assignment to unused variable e


29-29: Undefined name delete_branch (F821)

tools/python3/cmake.py

48-48: Undefined name cmd (F821)

tests/simulator/initialize/test_particles_init_1d.py

33-33: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


34-34: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


35-35: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


54-54: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


55-55: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


56-56: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses

tools/python3/__init__.py

45-45: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


46-46: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


95-95: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


111-111: Module level import not at top of file (E402)

tests/simulator/initialize/test_particles_init_2d.py

33-33: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


34-34: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


35-35: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


58-58: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


59-59: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


60-60: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses

tests/simulator/initialize/test_particles_init_3d.py

35-35: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


36-36: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


37-37: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


60-60: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


61-61: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


62-62: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses

tests/functional/harris/harris_3d.py

62-62: Ambiguous variable name: l (E741)

tests/simulator/refined_particle_nbr.py

9-9: Module level import not at top of file (E402)


10-10: Module level import not at top of file (E402)


11-11: Module level import not at top of file (E402)


13-13: Module level import not at top of file (E402)


14-14: Module level import not at top of file (E402)


15-15: Module level import not at top of file (E402)


16-16: Module level import not at top of file (E402)


18-18: Module level import not at top of file (E402)


18-18: tests.simulator.NoOverwriteDict imported but unused (F401)

Remove unused import: tests.simulator.NoOverwriteDict


19-19: Module level import not at top of file (E402)


24-24: Use super() instead of super(__class__, self) (UP008)

Remove __super__ parameters


26-26: Unnecessary open mode parameters (UP015)

Remove open mode parameters


44-44: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


61-61: Loop control variable pop not used within loop body (B007)

Rename unused pop to _pop


63-63: Loop control variable key not used within loop body (B007)

Rename unused key to _key

pyphare/pyphare/core/box.py

11-11: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


41-41: Use f-string instead of format call (UP032)

Convert to f-string


76-76: Ambiguous variable name: l (E741)


84-84: Ambiguous variable name: l (E741)


89-89: Ambiguous variable name: l (E741)


94-94: Ambiguous variable name: l (E741)


207-207: Ambiguous variable name: l (E741)

tests/simulator/__init__.py

3-3: Multiple imports on one line (E401)

Split imports


26-26: Use super() instead of super(__class__, self) (UP008)

Remove __super__ parameters


76-76: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


122-122: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


182-182: Undefined name Box (F821)


188-188: Undefined name Box (F821)


195-195: Undefined name Box (F821)


236-236: Use super() instead of super(__class__, self) (UP008)

Remove __super__ parameters


273-273: Multiple imports on one line (E401)

Split imports


275-275: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function

pyphare/pyphare/core/gridlayout.py

131-131: Class YeeCentering inherits from object (UP004)

Remove object inheritance


152-155: Use ternary operator size = nbrCells[dim] + nbrGhosts * 2 if withGhosts else nbrCells[dim] instead of if-else-block (SIM108)

Replace if-else-block with size = nbrCells[dim] + nbrGhosts * 2 if withGhosts else nbrCells[dim]


168-168: Class GridLayout inherits from object (UP004)

Remove object inheritance


176-176: Do not perform function call Box in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable (B008)

pyphare/pyphare/pharesee/run.py

289-289: Use f-string instead of format call (UP032)

Convert to f-string


371-371: f-string without any placeholders (F541)

Remove extraneous f prefix


373-373: f-string without any placeholders (F541)

Remove extraneous f prefix


415-415: Use f-string instead of format call (UP032)

Convert to f-string


465-465: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function

tests/amr/data/field/refine/test_refine_field.py

9-9: Redefinition of unused refinement_ratio from line 5 (F811)


106-106: Do not assert False (python -O removes these calls), raise AssertionError() (B011)

Replace assert False

pyphare/pyphare/pharesee/geometry.py

160-160: Ambiguous variable name: l (E741)


163-163: Ambiguous variable name: l (E741)


166-166: Ambiguous variable name: l (E741)


187-187: Ambiguous variable name: l (E741)


418-418: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


441-441: Loop control variable pd not used within loop body (B007)

Rename unused pd to _pd


464-464: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function

tests/simulator/test_initialization.py

5-5: Module level import not at top of file (E402)


7-7: Module level import not at top of file (E402)


8-8: Module level import not at top of file (E402)


9-9: Module level import not at top of file (E402)


10-10: Module level import not at top of file (E402)


11-11: Module level import not at top of file (E402)


12-16: Module level import not at top of file (E402)


17-17: Module level import not at top of file (E402)


18-18: Module level import not at top of file (E402)


19-19: Module level import not at top of file (E402)


20-20: Module level import not at top of file (E402)


21-21: Module level import not at top of file (E402)


23-23: Module level import not at top of file (E402)


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

Rewrite _ as a def


44-44: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


93-93: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


98-98: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


103-103: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


108-108: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


113-113: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


261-263: Use f-string instead of format call (UP032)

Convert to f-string


289-289: Use f-string instead of format call (UP032)

Convert to f-string


315-317: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


318-320: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


321-323: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


338-340: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


341-343: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


344-346: Replace unpacked list comprehension with a generator expression (UP027)

Replace with generator expression


385-385: Use f-string instead of format call (UP032)

Convert to f-string


387-387: Use f-string instead of format call (UP032)

Convert to f-string


399-399: Function definition does not bind loop variable select (B023)


401-401: Function definition does not bind loop variable patch (B023)


401-401: Function definition does not bind loop variable nbrGhosts (B023)


402-402: Function definition does not bind loop variable select (B023)


450-450: Use f-string instead of format call (UP032)

Convert to f-string


452-452: Use f-string instead of format call (UP032)

Convert to f-string


457-457: Local variable x is assigned to but never used (F841)

Remove assignment to unused variable x


539-539: Use f-string instead of format call (UP032)

Convert to f-string


587-587: Loop control variable pi not used within loop body (B007)

Rename unused pi to _pi


591-591: Yoda conditions are discouraged, use ppc == H instead (SIM300)

Replace Yoda condition with ppc == H


596-596: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


613-615: Use f-string instead of format call (UP032)

Convert to f-string


658-658: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


669-669: Local variable out is assigned to but never used (F841)

Remove assignment to unused variable out

tests/simulator/test_advance.py

5-5: Module level import not at top of file (E402)


7-7: Module level import not at top of file (E402)


8-8: Module level import not at top of file (E402)


9-9: Module level import not at top of file (E402)


10-10: Module level import not at top of file (E402)


11-11: Module level import not at top of file (E402)


12-12: Module level import not at top of file (E402)


13-17: Module level import not at top of file (E402)


18-18: Module level import not at top of file (E402)


19-19: Module level import not at top of file (E402)


20-20: Module level import not at top of file (E402)


21-21: Module level import not at top of file (E402)


23-23: Module level import not at top of file (E402)


24-24: Module level import not at top of file (E402)


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

Rewrite _ as a def


48-48: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


50-50: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


87-87: Ambiguous variable name: l (E741)


95-95: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


100-100: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


105-105: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


110-110: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


115-115: Do not assign a lambda expression, use a def (E731)

Rewrite _ as a def


251-251: Loop control variable ilvl not used within loop body (B007)

Rename unused ilvl to _ilvl


320-322: Use f-string instead of format call (UP032)

Convert to f-string


345-345: Loop control variable lvl not used within loop body (B007)

Rename unused lvl to _lvl


346-346: Use f-string instead of format call (UP032)

Convert to f-string


407-409: Use f-string instead of format call (UP032)

Convert to f-string


519-519: Use f-string instead of format call (UP032)

Convert to f-string


686-688: Use f-string instead of format call (UP032)

Convert to f-string


695-695: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function


710-710: f-string without any placeholders (F541)

Remove extraneous f prefix


711-711: f-string without any placeholders (F541)

Remove extraneous f prefix


739-739: pyphare.pharein imported but unused (F401)

Remove unused import: pyphare.pharein


744-744: Local variable out is assigned to but never used (F841)

Remove assignment to unused variable out

pyphare/pyphare/pharesee/hierarchy.py

82-84: Use f-string instead of format call (UP032)

Convert to f-string


203-203: Use f-string instead of format call (UP032)

Convert to f-string


508-508: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


520-520: Loop control variable ip not used within loop body (B007)

Rename unused ip to _ip


557-557: Class PatchHierarchy inherits from object (UP004)

Remove object inheritance


621-621: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


651-651: Comparison to None should be cond is None (E711)

Replace with cond is None


726-726: Loop control variable time not used within loop body (B007)

Rename unused time to _time


727-727: Loop control variable ilvl not used within loop body (B007)

Rename unused ilvl to _ilvl


746-746: Loop control variable ilvl not used within loop body (B007)

Rename unused ilvl to _ilvl


760-760: Loop control variable ilvl not used within loop body (B007)

Rename unused ilvl to _ilvl


781-781: Use f-string instead of format call (UP032)

Convert to f-string


790-790: Loop control variable t not used within loop body (B007)

Rename unused t to _t


792-792: Use f-string instead of format call (UP032)

Convert to f-string


906-906: Use f-string instead of format call (UP032)

Convert to f-string


960-960: Loop control variable lvl not used within loop body (B007)

Rename unused lvl to _lvl


1034-1034: Loop control variable lvl not used within loop body (B007)

Rename unused lvl to _lvl


1099-1099: Loop control variable ip not used within loop body (B007)

Rename unused ip to _ip


1281-1281: Loop control variable ip not used within loop body (B007)

Rename unused ip to _ip


1390-1390: Use f-string instead of format call (UP032)

Convert to f-string


1395-1395: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


1400-1402: Use f-string instead of format call (UP032)

Convert to f-string


1413-1413: Use f-string instead of format call (UP032)

Convert to f-string


1453-1453: Use f-string instead of format call (UP032)

Convert to f-string


1459-1459: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


1468-1468: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


1490-1490: Use f-string instead of format call (UP032)

Convert to f-string


1505-1505: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


1538-1538: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


1544-1544: Loop control variable ipatch not used within loop body (B007)


1561-1561: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()


1718-1718: Use f-string instead of format call (UP032)

Convert to f-string


1765-1765: Loop control variable time not used within loop body (B007)

Rename unused time to _time


1766-1766: Loop control variable ilvl not used within loop body (B007)

Rename unused ilvl to _ilvl


1767-1767: Loop control variable ip not used within loop body (B007)

Rename unused ip to _ip


1820-1820: Use key in dict instead of key in dict.keys() (SIM118)

Remove .keys()

Additional comments not posted (22)
tools/python3/git.py (1)

14-14: Approved: Enhanced log formatting.

The conditional formatting based on use_short is a flexible approach to handle different logging needs.

tools/python3/__init__.py (1)

9-27: Approved: RunTimer class implementation.

The RunTimer class provides a structured way to execute commands and measure their execution time, enhancing the modularity of the code.

tests/simulator/initialize/test_particles_init_3d.py (3)

25-26: Class Definition: Proper Inheritance and Use of Decorators

The Initialization3DTest class correctly inherits from InitializationTest. The use of the @ddt decorator is appropriate for data-driven tests.


77-94: Consider Removing or Documenting Commented-out Code

The commented-out test cases should either be removed for clarity or properly documented if they are intended for future use. This aligns with previous comments on this section.


97-98: Main Execution Block

The unittest.main() call in the main execution block is standard practice for a Python test script, allowing it to be run standalone.

tests/functional/harris/harris_3d.py (3)

37-52: Simulation Configuration Function

The config function sets up a simulation with detailed configuration parameters. The use of dictionary for diag_options is clear and effective. The commented-out strict option should either be removed or uncommented if needed.


62-62: Ambiguous Variable Naming

The variable name l is ambiguous and could be confused with the number 1. Consider renaming it to length for clarity.

Tools
Ruff

62-62: Ambiguous variable name: l (E741)


174-178: Main Function and Plotting Integration

The main function integrates configuration, simulation execution, and plotting. It checks for the MPI rank to ensure that plotting is only done by the master process, which is a good practice in parallel computations.

tests/simulator/refined_particle_nbr.py (4)

33-37: TearDown Method

The tearDown method correctly resets the simulator instance if it's not None. This is essential for cleaning up after each test case.


78-117: Clarify Calculations in Test Methods

The calculations within the _do_dim method are crucial for ensuring the correct number of particles are refined. Adding comments to explain these calculations will improve code clarity and maintainability.


130-135: Test Values Method

The test_values method is well-implemented, using a loop through dimensions and interpolation orders to check delta and weights. Consider adding comments to explain the logic behind these checks for future maintainers.


139-144: Custom Test Suite Configuration

The custom configuration of the test suite ensures that delta/weight verification tests run before dimensional tests. This is a good practice to catch fundamental errors early.

pyphare/pyphare/core/box.py (3)

65-67: List Subtraction in __sub__ Method

The method handles list subtraction by calling remove_all. Ensure that the input validation (checking all items are instances of Box) is robust.


185-198: remove_all Function

This function provides a robust mechanism for removing multiple boxes. Consider adding unit tests to cover various scenarios, such as partial overlaps or complete containment.


206-223: Data Selector Class

The DataSelector class provides a flexible way to select and set data within a box. The implementation is clear, and the use of item assignment is correctly handled.

Tools
Ruff

207-207: Ambiguous variable name: l (E741)

tests/simulator/__init__.py (2)

96-106: Density calculation in 3D is implemented correctly.

The implementation of density_3d_periodic correctly calculates the 3D density distribution using numpy operations. Consider parameterizing the background_particles value to enhance flexibility and configurability.


268-295: Debugging tracer function implemented correctly.

The debug_tracer function correctly sets a profiling function to track function calls and returns. Consider adding error handling to manage potential issues during profiling, such as exceptions in the traced functions.

Tools
Ruff

273-273: Multiple imports on one line (E401)

Split imports


275-275: Do not use mutable data structures for argument defaults (B006)

Replace with None; initialize within function

src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1)

40-40: Initialization of class members in constructor.

The constructor initializes the class members directly. Consider using a member initializer list for better performance and clarity.
[REFACTOR_SUGGESTion]

- MagneticFieldCoarsener(std::array<core::QtyCentering, dim> const centering,
-                         SAMRAI::hier::Box const& sourceBox,
-                         SAMRAI::hier::Box const& destinationBox,
-                         SAMRAI::hier::IntVector const& ratio)
-     : centering_{centering}
-     , sourceBox_{sourceBox}
-     , destinationBox_{destinationBox}
- {
- }
+ MagneticFieldCoarsener(std::array<core::QtyCentering, dim> const& centering,
+                         SAMRAI::hier::Box const& sourceBox,
+                         SAMRAI::hier::Box const& destinationBox,
+                         SAMRAI::hier::IntVector const& ratio)
+     : centering_(centering),
+       sourceBox_(sourceBox),
+       destinationBox_(destinationBox),
+       ratio_(ratio)
+ {}
pyphare/pyphare/pharesee/geometry.py (2)

58-73: 3D handling in domain_border_ghost_boxes looks good.

The function now properly handles 3D cases, which aligns with the PR's objectives to enhance 3D simulation capabilities.


Line range hint 289-519: Complex logic in compute_overlaps handled well.

The function effectively manages the complexity of computing overlaps in a domain with periodic boundary conditions, which is crucial for the simulation's accuracy.

tests/simulator/test_advance.py (2)

375-377: Particle number conservation test looks good.

This method correctly implements a check for particle number conservation over time steps.


Line range hint 686-688: Field level ghost comparison test looks good.

This method correctly implements a comparison of field values at different refinement levels.

Tools
Ruff

87-87: Ambiguous variable name: l (E741)

Comment on lines 1026 to 1056
def plot3d(self, **kwargs):
"""!HAX!"""
time = kwargs.get("time", self._default_time())
usr_lvls = kwargs.get("levels", self.levelNbrs(time))
default_qty = None
if len(self.quantities()) == 1:
default_qty = self.quantities()[0]
qty = kwargs.get("qty", default_qty)
for lvl_nbr, lvl in self.levels(time).items():
if lvl_nbr not in usr_lvls:
continue
for patch in self.level(lvl_nbr, time).patches:
pdat = patch.patch_datas[qty]
primals = pdat.primal_directions()
if primals[0]:
pdat._x = pdat.x[:-1]
if primals[1]:
pdat._y = pdat.y[:-1]
pdat.dataset = pdat.dataset[:, :, int(pdat.ghost_box.shape[2] / 2)]
patch.box.lower = patch.box.lower[:-1]
patch.box.upper = patch.box.upper[:-1]
patch.box.ndim = 2

pdat.ghost_box.lower = pdat.ghost_box.lower[:-1]
pdat.ghost_box.upper = pdat.ghost_box.upper[:-1]
pdat.ghost_box.ndim = 2
pdat.size = np.copy(pdat.ghost_box.shape)
pdat.layout.dl = pdat.layout.dl[:-1]

return self.plot2d(**kwargs) # ¯\_(ツ)_/¯

Copy link

Choose a reason for hiding this comment

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

Review the plot3d method for potential data handling issues.

The plot3d method manipulates data dimensions and properties directly which may lead to unintended side effects or data corruption. Specifically:

  • Modifying pdat._x, pdat._y, and pdat.dataset directly affects the object state outside the local scope of this function, potentially impacting other parts of the application relying on these properties.
  • The method reduces the dimensionality of the data to 2D and delegates to plot2d. Ensure that this dimensional reduction is valid across all use cases.

Consider encapsulating these transformations in a method within the relevant data classes to avoid side effects.

- pdat._x = pdat.x[:-1]
- pdat._y = pdat.y[:-1]
- pdat.dataset = pdat.dataset[:, :, int(pdat.ghost_box.shape[2] / 2)]
+ # Example method inside the relevant data class
+ pdat.reduce_dimension(2)  # Reduce to 2D by selecting the middle slice

Committable suggestion was skipped due to low confidence.

Tools
Ruff

1034-1034: Loop control variable lvl not used within loop body (B007)

Rename unused lvl to _lvl

Comment on lines +88 to +90
typename std::enable_if<D == 3, void>::type
coarsen(Point_t const fineStartIndex, FieldT const& fineField, FieldT& coarseField,
Point_t const coarseIndex);
Copy link

Choose a reason for hiding this comment

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

Implement 3D coarsening logic.

The 3D coarsening method is crucial for the project's focus on 3D functionalities but is currently not implemented. This needs to be addressed to meet the PR objectives.

89a90,93
+ // TODO: Implement the 3D coarsening logic here
+ throw std::runtime_error("3D coarsening not implemented.");
Committable suggestion

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

Suggested change
typename std::enable_if<D == 3, void>::type
coarsen(Point_t const fineStartIndex, FieldT const& fineField, FieldT& coarseField,
Point_t const coarseIndex);
typename std::enable_if<D == 3, void>::type
coarsen(Point_t const fineStartIndex, FieldT const& fineField, FieldT& coarseField,
Point_t const coarseIndex) {
// TODO: Implement the 3D coarsening logic here
throw std::runtime_error("3D coarsening not implemented.");
}

Comment on lines +571 to +586
self, ndim, interp_order, ppc=100, **kwargs
):
ddt_test_id = self.ddt_test_id()
datahier = self.getHierarchy(
dim,
ndim,
interp_order,
{"L0": {"B0": nDBox(dim, 10, 20)}},
{},
"particles",
diag_outputs=f"ppc/{ndim}/{interp_order}/{ddt_test_id}",
nbr_part_per_cell=ppc,
**kwargs,
)

for patch in datahier.level(0).patches:
if cpp.mpi_rank() > 0:
return

for pi, patch in enumerate(datahier.level(0).patches):
pd = patch.patch_datas["protons_particles"]
icells = pd.dataset[patch.box].iCells
H, _ = np.histogramdd(icells)
self.assertTrue((H == default_ppc).all())
H, edges = np.histogramdd(icells, bins=patch.box.shape)
self.assertTrue((H == ppc).all())
Copy link

Choose a reason for hiding this comment

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

Use direct comparison instead of Yoda conditions.

In Python, it's more idiomatic to write conditions in a natural order rather than using Yoda conditions. This enhances readability and conforms to common Python practices.

- self.assertTrue((H == ppc).all())
+ self.assertTrue(ppc == H)

The method correctly checks if the number of particles per cell is as provided, ensuring the accuracy of particle distribution in the simulation. This is crucial for the reliability of simulation results.

Committable suggestion was skipped due to low confidence.

Tools
Ruff

587-587: Loop control variable pi not used within loop body (B007)

Rename unused pi to _pi


591-591: Yoda conditions are discouraged, use ppc == H instead (SIM300)

Replace Yoda condition with ppc == H

Comment on lines +35 to +37
*per_interp(({"L0": {"B0": Box3D(10, 14)}})),
*per_interp(({"L0": {"B0": Box3D(10, 14)}, "L1": {"B0": Box3D(22, 26)}})),
*per_interp(({"L0": {"B0": Box3D(2, 6), "B1": Box3D(7, 11)}})),
Copy link

Choose a reason for hiding this comment

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

Remove Extraneous Parentheses

The static analysis tool has flagged unnecessary parentheses around the dictionary in the per_interp function calls. Simplifying these will enhance readability.

- *per_interp(({"L0": {"B0": Box3D(10, 14)}})),
- *per_interp(({"L0": {"B0": Box3D(5, 14)}, "L1": {"B0": Box3D(15, 19)}})),
- *per_interp(({"L0": {"B0": Box3D(2, 12), "B1": Box3D(13, 25)}})),
+ *per_interp({"L0": {"B0": Box3D(10, 14)}}),
+ *per_interp({"L0": {"B0": Box3D(5, 14), "L1": {"B0": Box3D(15, 19)}}),
+ *per_interp({"L0": {"B0": Box3D(2, 12), "B1": Box3D(13, 25)}}),

Also applies to: 60-62

Tools
Ruff

35-35: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


36-36: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses


37-37: Avoid extraneous parentheses (UP034)

Remove extraneous parentheses

@@ -48,4 +46,3 @@ def test_cmd(test, verbose=False):

def run_test(test, verbose=False, capture_output=False):
run(test_cmd(cmd, verbose=verbose), capture_output=capture_output)
Copy link

Choose a reason for hiding this comment

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

Fix the undefined variable issue in run_test function.

The cmd variable is used but not defined within the run_test function. This will cause a runtime error when this function is called.

- run(test_cmd(cmd, verbose=verbose), capture_output=capture_output)
+ run(test_cmd(test, verbose=verbose), capture_output=capture_output)
Committable suggestion

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

Suggested change
run(test_cmd(cmd, verbose=verbose), capture_output=capture_output)
run(test_cmd(test, verbose=verbose), capture_output=capture_output)
Tools
Ruff

48-48: Undefined name cmd (F821)

Comment on lines 45 to 46
raise RuntimeError(decode_bytes(e.stderr))
raise RuntimeError(what)
Copy link

Choose a reason for hiding this comment

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

Use raise ... from syntax for clearer exception chaining.

When re-raising exceptions, it's better to use the raise ... from syntax to make the chain of errors clear, avoiding confusion with exception handling itself.

- raise RuntimeError(decode_bytes(e.stderr))
+ raise RuntimeError(decode_bytes(e.stderr)) from e
- raise RuntimeError(what)
+ raise RuntimeError(what) from None
Committable suggestion

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

Suggested change
raise RuntimeError(decode_bytes(e.stderr))
raise RuntimeError(what)
raise RuntimeError(decode_bytes(e.stderr)) from e
raise RuntimeError(what) from None
Tools
Ruff

45-45: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)


46-46: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling (B904)

@PhilipDeegan PhilipDeegan force-pushed the 3d_base branch 2 times, most recently from 9769e13 to 753eb43 Compare August 1, 2024 12:37
pyphare/pyphare/pharesee/hierarchy.py Fixed Show fixed Hide fixed
pyphare/pyphare/pharesee/hierarchy.py Fixed Show fixed Hide fixed
pyphare/pyphare/pharesee/hierarchy.py Fixed Show fixed Hide fixed
pyphare/pyphare/pharesee/hierarchy.py Fixed Show fixed Hide fixed
pyphare/pyphare/pharesee/hierarchy.py Fixed Show fixed Hide fixed
pyphare/pyphare/pharesee/hierarchy.py Fixed Show fixed Hide fixed
pyphare/pyphare/pharesee/hierarchy.py Fixed Show fixed Hide fixed
pyphare/pyphare/pharesee/hierarchy.py Fixed Show fixed Hide fixed
pyphare/pyphare/pharesee/hierarchy.py Fixed Show fixed Hide fixed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 27

Outside diff range, codebase verification and nitpick comments (27)
tests/amr/data/particles/refine/input/input_3d_ratio_2.txt (1)

46-51: Remove unused sections in the configuration file.

The TileClustering and GriddingAlgorithm sections are empty and should be removed if they are not required, to avoid confusion.

- TileClustering
- {
- }
- GriddingAlgorithm
- {
- }
tests/diagnostic/CMakeLists.txt (1)

37-37: Implementation for test-diagnostics_3d is missing.

The search results indicate that while test-diagnostics_3d is referenced in tests/diagnostic/CMakeLists.txt, there is no actual implementation found for this test. Please ensure that the implementation for test-diagnostics_3d is added to the codebase.

  • tests/diagnostic/CMakeLists.txt: _add_diagnostics_test(test-diagnostics_3d)
Analysis chain

LGTM! Ensure the 3D diagnostics test is properly implemented.

The new addition for 3D diagnostics test follows the existing pattern and looks correct.

However, ensure that the test-diagnostics_3d is properly implemented and tested.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of `test-diagnostics_3d`.

# Test: Search for the implementation. Expect: The implementation is found and looks correct.
rg --type cpp -A 5 'test-diagnostics_3d'

Length of output: 40


Script:

#!/bin/bash
# Description: Verify the implementation of `test-diagnostics_3d`.

# Test: Search for the implementation across all file types.
rg 'test-diagnostics_3d'

# Test: Search for related diagnostic test functions to ensure the test is properly implemented.
rg '_add_diagnostics_test'

Length of output: 503

tests/simulator/advance/test_particles_advance_3d.py (2)

1-4: Enhance the file-level docstring.

The docstring could be more descriptive about the specific 3D test cases that this file contains.

"""
  This file exists independently from test_advance.py to isolate dimension
    test cases and allow each to be overridden in some way if required.
"""
+"""
+  This file contains 3D particle advancement test cases. It isolates these tests
+  from the 2D cases to allow for specific 3D configurations and overrides.
+"""

26-44: Add docstrings to the test methods.

Each test method could use a docstring to explain its purpose and the structure of the returned data.

@ddt
class AdvanceTest(AdvanceTestBase):
    @data(
        *per_interp({}),
        *per_interp({"L0": [Box3D(10, 19)]}),
        *per_interp({"L0": [Box3D(5, 9), Box3D(10, 14)]}),
    )
    @unpack
    def test_overlapped_particledatas_have_identical_particles(
        self, interp_order, refinement_boxes
    ):
+        """
+        Test that overlapped particle data have identical particles.
+        """
        self._test_overlapped_particledatas_have_identical_particles(
            ndim,
            interp_order,
            refinement_boxes,
            ppc=ppc,
            cells=40,
            largest_patch_size=20,
        )

    @data(*interp_orders)
    def test_L0_particle_number_conservation(self, interp):
+        """
+        Test L0 particle number conservation.
+        """
        self._test_L0_particle_number_conservation(ndim, interp, ppc=ppc, cells=30)
tests/simulator/initialize/test_fields_init_3d.py (2)

1-4: Enhance the file-level docstring.

The docstring could be more descriptive about the specific 3D test cases that this file contains.

"""
  This file exists independently from test_initialization.py to isolate dimension
    test cases and allow each to be overridden in some way if required.
"""
+"""
+  This file contains 3D field initialization test cases. It isolates these tests
+  from the 2D cases to allow for specific 3D configurations and overrides.
+"""

22-46: Add docstrings to the test methods.

Each test method could use a docstring to explain its purpose and the structure of the returned data.

@ddt
class Initialization3DTest(InitializationTest):
    @data(*interp_orders)
    def test_B_is_as_provided_by_user(self, interp_order):
+        """
+        Test that the magnetic field B is as provided by the user.
+        """
        print(f"\n{self._testMethodName}_{ndim}d")
        self._test_B_is_as_provided_by_user(ndim, interp_order, ppc=ppc, cells=cells)

    @data(*interp_orders)
    def test_bulkvel_is_as_provided_by_user(self, interp_order):
+        """
+        Test that the bulk velocity is as provided by the user.
+        """
        print(f"\n{self._testMethodName}_{ndim}d")
        self._test_bulkvel_is_as_provided_by_user(
            ndim, interp_order, ppc=ppc, cells=cells
        )

    @data(*interp_orders)
    def test_density_is_as_provided_by_user(self, interp_order):
+        """
+        Test that the density is as provided by the user.
+        """
        print(f"\n{self._testMethodName}_{ndim}d")
        self._test_density_is_as_provided_by_user(ndim, interp_order, cells=cells)

    @data(*interp_orders)  # uses too much RAM - to isolate somehow
    def test_density_decreases_as_1overSqrtN(self, interp_order):
+        """
+        Test that the density decreases as 1 over the square root of N.
+        """
        print(f"\n{self._testMethodName}_{ndim}d")
        self._test_density_decreases_as_1overSqrtN(
            ndim, interp_order, np.asarray([10, 25, 50, 75]), cells=cells
        )
tests/simulator/initialize/test_particles_init_3d.py (1)

35-37: Remove extraneous parentheses.

The static analysis tool has flagged unnecessary parentheses around the dictionary in the per_interp function calls. Simplifying these will enhance readability.

- *per_interp(({"L0": {"B0": Box3D(10, 14)}})),
- *per_interp(({"L0": {"B0": Box3D(10, 14), "L1": {"B0": Box3D(22, 26)}})),
- *per_interp(({"L0": {"B0": Box3D(2, 6), "B1": Box3D(7, 11)}})),
+ *per_interp({"L0": {"B0": Box3D(10, 14)}}),
+ *per_interp({"L0": {"B0": Box3D(10, 14), "L1": {"B0": Box3D(22, 26)}}),
+ *per_interp({"L0": {"B0": Box3D(2, 6), "B1": Box3D(7, 11)}}),

Also applies to: 60-62

tests/simulator/advance/test_fields_advance_3d.py (2)

1-4: Enhance file-level docstring.

The docstring should be more descriptive about the specific tests conducted in this file.

"""
  This file exists independently from test_advance.py to isolate dimension
    test cases and allow each to be overridden in some way if required.
"""
+"""
+  This file contains tests for advancing fields in a 3D context. It isolates dimension-specific test cases
+  and allows each to be overridden if required. The tests include checking field overlaps and patch sizes.
+"""

26-33: Consider shortening the method name.

The method name test_overlaped_fields_are_equal is quite long. Consider shortening it without losing its meaning.

- def test_overlaped_fields_are_equal(self, interp_order, refinement_boxes):
+ def test_fields_equality(self, interp_order, refinement_boxes):
src/amr/data/particles/refine/splitter.hpp (1)

Line range hint 18-67: Consider breaking down the complex loop body.

The loop body is quite large and complex. Consider breaking it down into smaller, more manageable functions to improve readability and maintainability.

-        for (size_t rpIndex = 0; rpIndex < pattern.deltas_.size(); rpIndex++)
-        {
-            FineParticle fineParticle = particles[idx++];
-            fineParticle.weight       = particle.weight * static_cast<Weight_t>(pattern.weight_)
-                                  * power[dimension - 1];
-            fineParticle.charge = particle.charge;
-            fineParticle.iCell  = particle.iCell;
-            fineParticle.delta  = particle.delta;
-            fineParticle.v      = particle.v;
-
-            for (size_t iDim = 0; iDim < dimension; iDim++)
-            {
-                fineParticle.delta[iDim]
-                    += static_cast<Delta_t>(pattern.deltas_[rpIndex][iDim]);
-                Delta_t integra = std::floor(fineParticle.delta[iDim]);
-                fineParticle.delta[iDim] -= integra;
-                fineParticle.iCell[iDim] += static_cast<int32_t>(integra);
-            }
-        }
+        for (size_t rpIndex = 0; rpIndex < pattern.deltas_.size(); rpIndex++) {
+            FineParticle fineParticle = particles[idx++];
+            initializeFineParticle(fineParticle, particle, pattern, power, dimension);
+        }
+
+    void initializeFineParticle(FineParticle& fineParticle, const Particle& particle, const auto& pattern, const std::array& power, const size_t dimension) const {
+        fineParticle.weight = particle.weight * static_cast<Weight_t>(pattern.weight_) * power[dimension - 1];
+        fineParticle.charge = particle.charge;
+        fineParticle.iCell = particle.iCell;
+        fineParticle.delta = particle.delta;
+        fineParticle.v = particle.v;
+
+        for (size_t iDim = 0; iDim < dimension; iDim++) {
+            fineParticle.delta[iDim] += static_cast<Delta_t>(pattern.deltas_[rpIndex][iDim]);
+            Delta_t integra = std::floor(fineParticle.delta[iDim]);
+            fineParticle.delta[iDim] -= integra;
+            fineParticle.iCell[iDim] += static_cast<int32_t>(integra);
+        }
+    }
tests/functional/harris/harris_3d.py (4)

62-62: Rename the ambiguous variable 'l' to 'length' for clarity.

The variable l is ambiguous and can be mistaken for the number 1. Renaming it to length will improve readability.

- def S(y, y0, l):
+ def S(y, y0, length):
Tools
Ruff

62-62: Ambiguous variable name: l

(E741)


54-61: Consider adding docstrings to the functions.

Adding docstrings to the density, S, by, bx, bz, b2, T, vxyz, and vthxyz functions will improve code readability and maintainability.

def density(x, y, z):
    """Calculate the density based on the given coordinates."""
    ...

138-140: Consider adding docstrings to the plot_file_for_qty and plot functions.

Adding docstrings to these functions will improve code readability and maintainability.

def plot_file_for_qty(qty, time):
    """Generate the plot file name for the given quantity and time."""
    ...

174-187: Consider adding docstrings to the main function.

Adding a docstring to the main function will improve code readability and maintainability.

def main():
    """Main function to run the simulation and plot the results."""
    ...
pyphare/pyphare/core/box.py (1)

207-207: Rename ambiguous variable l.

The variable name l in the select function is ambiguous and can be improved for clarity.

-  return data[tuple([slice(l, u + 1) for l, u in zip(box.lower, box.upper)])]
+  return data[tuple([slice(lower, upper + 1) for lower, upper in zip(box.lower, box.upper)])]
Tools
Ruff

207-207: Ambiguous variable name: l

(E741)

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

151-169: LGTM! Add a comment to explain the purpose and functionality of as_points.

The as_points function correctly generates a vector of points based on the dimensionality of the Box. Adding a comment will improve maintainability and readability for future developers.

/**
 * Generates a vector of points based on the dimensionality of the box.
 * For a 1D box, it generates points along the x-axis.
 * For a 2D box, it generates points in the xy-plane.
 * For a 3D box, it generates points in the xyz-space.
 */
auto as_points() const
{
    // existing code...
}
tests/core/data/ndarray/test_main.cpp (2)

402-402: Enhance lambda function readability.

Consider adding a comment to explain the purpose of the lambda function sum.

-    auto sum = [](auto const& array) { return std::accumulate(array.begin(), array.end(), 0); };
+    // Lambda function to calculate the sum of elements in the array
+    auto sum = [](auto const& array) { return std::accumulate(array.begin(), array.end(), 0); };

417-421: Clarify the calculation of outer cells.

The comments explaining the calculation of outer cells can be improved for better readability.

-        // outter cells of a 10**3 cube =
+        // Outer cells of a 10^3 cube:
-        // (10 * 10 * 2) + (10 * 8 * 2) + (8 * 8 * 2);
+        // (10 * 10 * 2) + (10 * 8 * 2) + (8 * 8 * 2)
-        // or
+        // or
-        // (8 * 8 * 6) + (10 * 4) + (8 * 8);
+        // (8 * 8 * 6) + (10 * 4) + (8 * 8)
-        // = 488
+        // = 488
pyphare/pyphare/pharesee/hierarchy.py (9)

20-30: Ensure proper initialization of attributes.

The __init__ method initializes several attributes. Ensure all attributes are properly initialized and consider adding type hints for better readability.

def __init__(self, layout: GridLayout, quantity: str):
    ...
    self.quantity: str = quantity
    self.box: Box = layout.box
    self.origin: np.ndarray = layout.origin
    self.layout: GridLayout = layout

185-205: Ensure proper error handling for interpolation order.

The __init__ method raises a RuntimeError for invalid interpolation orders. Ensure that this error handling is comprehensive and consider adding a custom exception class for better clarity.

class InvalidInterpolationOrderError(Exception):
    pass

...

if layout.interp_order not in [1, 2, 3]:
    raise InvalidInterpolationOrderError(f"Invalid interpolation order {layout.interp_order}")

224-236: Ensure proper initialization of attributes.

The __init__ method initializes several attributes. Ensure all attributes are properly initialized and consider adding type hints for better readability.

def __init__(self, patch_datas: dict, patch_id: str = ""):
    ...
    self.layout: GridLayout = pdata0.layout
    self.box: Box = pdata0.layout.box
    self.origin: np.ndarray = pdata0.layout.origin
    self.dl: np.ndarray = pdata0.layout.dl
    self.patch_datas: dict = patch_datas
    self.id: str = patch_id

253-262: Improve error handling in __call__ method.

The __call__ method raises a ValueError if the coordinates are not specified correctly. Consider adding more descriptive error messages and type hints.

def __call__(self, qty: str, **kwargs):
    ...
    else:
        raise ValueError("Need to specify either 'x' or 'y' cut coordinate.")
Tools
GitHub Check: CodeQL

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


276-278: Ensure proper initialization of attributes.

The __init__ method initializes several attributes. Ensure all attributes are properly initialized and consider adding type hints for better readability.

def __init__(self, lvl_nbr: int, patches: list):
    ...
    self.level_number: int = lvl_nbr
    self.patches: list = patches

560-603: Ensure proper initialization of attributes.

The __init__ method initializes several attributes. Ensure all attributes are properly initialized and consider adding type hints for better readability.

def __init__(
    self,
    patch_levels: dict,
    domain_box: Box,
    refinement_ratio: int = 2,
    time: float = 0.0,
    data_files: dict = None,
    **kwargs,
):
    ...
    self.patch_levels: dict = patch_levels
    self.ndim: int = len(domain_box.lower)
    self.time_hier: dict = {}
    self.time_hier.update({self.format_timestamp(time): patch_levels})
    self.domain_box: Box = domain_box
    self.refinement_ratio: int = refinement_ratio
    self.data_files: dict = data_files or {}
    self._sim = None

790-790: Rename unused loop variable.

The loop control variable t is not used within the loop. Rename it to _t to indicate it's intentionally unused.

- for t, patch_levels in self.time_hier.items():
+ for _t, patch_levels in self.time_hier.items():
Tools
Ruff

790-790: Loop control variable t not used within loop body

Rename unused t to _t

(B007)


960-960: Rename unused loop variable.

The loop control variable lvl is not used within the loop. Rename it to _lvl to indicate it's intentionally unused.

- for lvl_nbr, lvl in self.levels(time).items():
+ for lvl_nbr, _lvl in self.levels(time).items():
Tools
Ruff

960-960: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)


1034-1034: Rename unused loop variable.

The loop control variable lvl is not used within the loop. Rename it to _lvl to indicate it's intentionally unused.

- for lvl_nbr, lvl in self.levels(time).items():
+ for lvl_nbr, _lvl in self.levels(time).items():
Tools
Ruff

1034-1034: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 18577d8 and 753eb43.

Files selected for processing (44)
  • .github/workflows/cmake_macos.yml (1 hunks)
  • pyphare/pyphare/core/box.py (2 hunks)
  • pyphare/pyphare/core/gridlayout.py (1 hunks)
  • pyphare/pyphare/pharesee/geometry.py (7 hunks)
  • pyphare/pyphare/pharesee/hierarchy.py (1 hunks)
  • pyphare/pyphare/pharesee/run/utils.py (1 hunks)
  • res/amr/splitting.yml (1 hunks)
  • res/cmake/funcs.cmake (1 hunks)
  • res/cmake/options.cmake (2 hunks)
  • src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1 hunks)
  • src/amr/data/particles/refine/split.hpp (1 hunks)
  • src/amr/data/particles/refine/split_1d.hpp (10 hunks)
  • src/amr/data/particles/refine/split_2d.hpp (17 hunks)
  • src/amr/data/particles/refine/split_3d.hpp (1 hunks)
  • src/amr/data/particles/refine/splitter.hpp (2 hunks)
  • src/core/data/grid/gridlayoutdefs.hpp (2 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (8 hunks)
  • src/core/utilities/box/box.hpp (3 hunks)
  • src/core/utilities/meta/meta_utilities.hpp (2 hunks)
  • tests/amr/data/field/refine/test_refine_field.py (1 hunks)
  • tests/amr/data/particles/refine/input/input_3d_ratio_2.txt (1 hunks)
  • tests/amr/data/particles/refine/test_split.cpp (1 hunks)
  • tests/core/data/ndarray/test_main.cpp (1 hunks)
  • tests/core/numerics/interpolator/test_main.cpp (1 hunks)
  • tests/diagnostic/CMakeLists.txt (1 hunks)
  • tests/diagnostic/job_3d.py.in (1 hunks)
  • tests/diagnostic/test-diagnostics_3d.cpp (1 hunks)
  • tests/functional/harris/harris_3d.py (1 hunks)
  • tests/simulator/init.py (2 hunks)
  • tests/simulator/advance/CMakeLists.txt (1 hunks)
  • tests/simulator/advance/test_fields_advance_3d.py (1 hunks)
  • tests/simulator/advance/test_particles_advance_3d.py (1 hunks)
  • tests/simulator/initialize/CMakeLists.txt (1 hunks)
  • tests/simulator/initialize/test_fields_init_2d.py (1 hunks)
  • tests/simulator/initialize/test_fields_init_3d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_1d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_2d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_3d.py (1 hunks)
  • tests/simulator/per_test.hpp (1 hunks)
  • tests/simulator/refined_particle_nbr.py (2 hunks)
  • tests/simulator/test_advance.py (7 hunks)
  • tests/simulator/test_initialization.py (14 hunks)
  • tools/python3/cmake.py (1 hunks)
  • tools/python3/git.py (1 hunks)
Files skipped from review due to trivial changes (3)
  • src/amr/data/particles/refine/split_2d.hpp
  • tests/simulator/initialize/test_fields_init_2d.py
  • tests/simulator/initialize/test_particles_init_1d.py
Additional context used
Path-based instructions (10)
src/amr/data/particles/refine/split.hpp (1)

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

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

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

tests/simulator/per_test.hpp (1)

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

src/amr/data/particles/refine/splitter.hpp (1)

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

src/core/utilities/meta/meta_utilities.hpp (1)

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

src/amr/data/particles/refine/split_1d.hpp (1)

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

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

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

src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1)

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

src/amr/data/particles/refine/split_3d.hpp (1)

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

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

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

Ruff
tools/python3/git.py

22-22: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


29-29: Undefined name delete_branch

(F821)

tools/python3/cmake.py

48-48: Undefined name cmd

(F821)

tests/functional/harris/harris_3d.py

62-62: Ambiguous variable name: l

(E741)

pyphare/pyphare/core/box.py

207-207: Ambiguous variable name: l

(E741)

tests/simulator/__init__.py

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

Replace with None; initialize within function

(B006)

tests/amr/data/field/refine/test_refine_field.py

106-106: Do not assert False (python -O removes these calls), raise AssertionError()

Replace assert False

(B011)

pyphare/pyphare/pharesee/geometry.py

161-161: Ambiguous variable name: l

(E741)


164-164: Ambiguous variable name: l

(E741)


167-167: Ambiguous variable name: l

(E741)


188-188: Ambiguous variable name: l

(E741)

tests/simulator/test_initialization.py

394-394: Function definition does not bind loop variable select

(B023)


396-396: Function definition does not bind loop variable patch

(B023)


396-396: Function definition does not bind loop variable nbrGhosts

(B023)


397-397: Function definition does not bind loop variable select

(B023)


582-582: Loop control variable pi not used within loop body

Rename unused pi to _pi

(B007)


586-586: Yoda condition detected

Rewrite as ppc == H

(SIM300)


664-664: Local variable out is assigned to but never used

Remove assignment to unused variable out

(F841)

tests/simulator/test_advance.py

89-89: Ambiguous variable name: l

(E741)

pyphare/pyphare/pharesee/hierarchy.py

508-508: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


520-520: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


621-621: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


651-651: Comparison to None should be cond is None

Replace with cond is None

(E711)


726-726: Loop control variable time not used within loop body

Rename unused time to _time

(B007)


727-727: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


746-746: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


760-760: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


790-790: Loop control variable t not used within loop body

Rename unused t to _t

(B007)


960-960: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)


1034-1034: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)


1099-1099: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


1281-1281: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


1395-1395: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1459-1459: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1468-1468: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1505-1505: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1538-1538: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1544-1544: Loop control variable ipatch not used within loop body

(B007)


1561-1561: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1765-1765: Loop control variable time not used within loop body

Rename unused time to _time

(B007)


1766-1766: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


1767-1767: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


1820-1820: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

GitHub Check: CodeQL
pyphare/pyphare/pharesee/hierarchy.py

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


[warning] 121-121: Overwriting attribute in super-class or sub-class
Assignment overwrites attribute layout, which was previously defined in superclass PatchData.


[notice] 1069-1069: Module is imported with 'import' and 'import from'
Module 'copy' is imported with both 'import' and 'import from'.


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


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


[warning] 634-634: Comparison of identical values
Comparison of identical values; use cmath.isnan() if testing for not-a-number.


[notice] 651-651: Testing equality to None
Testing for None should use the 'is' operator.


[failure] 677-677: Potentially uninitialized local variable
Local variable 'slice_dim' may be used before it is initialized.


[failure] 678-678: Potentially uninitialized local variable
Local variable 'cst_dim' may be used before it is initialized.

Additional comments not posted (93)
src/amr/data/particles/refine/split.hpp (1)

6-6: Ensure the necessity and correctness of the new include directive.

The inclusion of split_3d.hpp appears to extend the functionality for 3D particle refinement. Verify that this header file is necessary and that its integration does not introduce any conflicts or redundant inclusions.

tests/amr/data/particles/refine/test_split.cpp (1)

25-25: LGTM! Verify the integration of the new Splitter type.

The addition of Splitter<3, 1, 27> expands the test coverage. Ensure that the new type is correctly integrated and all necessary tests are in place.

tests/amr/data/particles/refine/input/input_3d_ratio_2.txt (1)

10-11: Update the dimension to match the 3D simulation.

The dimension is set to 1, but the rest of the configuration is for a 3D simulation. This should be updated to match the dimensionality of the simulation.

-    dim = 1
+    dim = 3

Likely invalid or redundant comment.

tests/simulator/initialize/CMakeLists.txt (1)

21-24: LGTM! Ensure the flag highResourceTests is properly set.

The new conditional block for 3D initialization tests follows the existing pattern and looks correct.

However, ensure that the highResourceTests flag is properly set in the build or test configuration.

Verification successful

The highResourceTests flag is properly set and used.

The flag highResourceTests is defined in res/cmake/options.cmake and used in conditional statements in tests/simulator/initialize/CMakeLists.txt and tests/simulator/advance/CMakeLists.txt. This confirms that the flag is set and utilized appropriately in the build configuration.

  • res/cmake/options.cmake: option(highResourceTests "Enable heavy tests for CI (3d/etc" OFF)
  • tests/simulator/initialize/CMakeLists.txt: if(highResourceTests)
  • tests/simulator/advance/CMakeLists.txt: if(highResourceTests)
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if `highResourceTests` flag is set in the build or test configuration.

# Test: Search for the flag definition. Expect: The flag is defined and set appropriately.
rg --type cmake -A 5 'set\(highResourceTests'

Length of output: 47


Script:

#!/bin/bash
# Description: Verify if `highResourceTests` flag is set or used in the build or test configuration.

# Search for the definition of the `highResourceTests` flag in CMake files.
rg --type cmake 'highResourceTests'

# Search for the usage of the `highResourceTests` flag in CMake files.
rg --type cmake 'if\s*\(.*highResourceTests.*\)'

Length of output: 709

tests/simulator/advance/CMakeLists.txt (1)

21-24: LGTM! Ensure the flag highResourceTests is properly set.

The new conditional block for 3D advancement tests follows the existing pattern and looks correct.

However, ensure that the highResourceTests flag is properly set in the build or test configuration.

Verification successful

The highResourceTests flag is properly set.

The flag is defined in res/cmake/options.cmake with a default value of OFF, which ensures it is correctly integrated into the build or test configuration.

  • res/cmake/options.cmake: option(highResourceTests "Enable heavy tests for CI (3d/etc" OFF)
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if `highResourceTests` flag is set in the build or test configuration.

# Test: Search for the flag definition. Expect: The flag is defined and set appropriately.
rg --type cmake -A 5 'set\(highResourceTests'

Length of output: 47


Script:

#!/bin/bash
# Description: Search for any mention of the `highResourceTests` flag across all files.

# Test: Search for the flag usage or definition. Expect: The flag is mentioned somewhere in the codebase.
rg 'highResourceTests'

Length of output: 403

tests/diagnostic/CMakeLists.txt (1)

41-41: LGTM! Ensure the 3D job configuration file is properly set.

The new addition for configuring the 3D job file follows the existing pattern and looks correct.

However, ensure that the job_3d.py file is properly set and configured.

Verification successful

Ensure the 3D job configuration file is properly set.

The job_3d.py.in file was found and its content appears to be correctly configured for the 3D job. The script includes necessary imports and sets up the simulation with appropriate parameters.

  • tests/diagnostic/job_3d.py.in
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the configuration of `job_3d.py`.

# Test: Search for the configuration file. Expect: The file is found and looks correct.
rg --type python 'job_3d.py'

Length of output: 59


Script:

#!/bin/bash
# Description: Verify the configuration of `job_3d.py`.

# Step 1: Search for the configuration file using `fd`.
fd 'job_3d.py' > job_3d_file_paths.txt

# Step 2: Display the content of the found file(s) using `cat`.
if [ -s job_3d_file_paths.txt ]; then
  while IFS= read -r file; do
    echo "Contents of $file:"
    cat "$file"
  done < job_3d_file_paths.txt
else
  echo "No job_3d.py file found."
fi

Length of output: 732

tests/simulator/advance/test_particles_advance_3d.py (2)

21-23: LGTM!

The function per_interp is correct and useful for generating data-driven tests.


50-51: LGTM!

The main block is appropriate for running the tests.

tools/python3/cmake.py (4)

8-20: LGTM!

The function make_config_str is well-structured and correctly generates the configuration string.


23-27: LGTM!

The function config is well-structured and correctly runs the configuration command.


30-31: LGTM!

The function build is well-structured and correctly runs the build command.


34-37: LGTM!

The function list_tests is well-structured and correctly parses the test list.

tests/simulator/initialize/test_fields_init_3d.py (1)

48-49: LGTM!

The main block is appropriate for running the tests.

res/amr/splitting.yml (3)

103-116: Ensure consistency in particle count data.

The dimension_3 section introduces new interpolations and particle counts. Verify that the delta and weight values are consistent with the intended simulation parameters.


117-129: Verify the accuracy of interp_2 data.

Ensure that the delta and weight values for interp_2 are correct and align with the expected simulation behavior.


130-141: Check the correctness of interp_3 values.

Review the delta and weight values for interp_3 to ensure they are accurate and consistent with the other interpolations.

.github/workflows/cmake_macos.yml (1)

90-90: Addition of new compiler flag.

The new compiler flag -DPHARE_SIMULATORS=2 has been added to the build configuration. Ensure this flag is required and correctly implemented.

tests/simulator/initialize/test_particles_init_2d.py (1)

26-26: Class name update to reflect 2D tests.

The class name has been updated to Initialization2DTest to reflect the focus on 2D initialization tests. Ensure all test methods are correctly adapted for 2D cases.

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

5-5: Include directive for <cstdint> is correct.

The inclusion of <cstdint> is necessary for using std::uint16_t.


18-18: Using std::uint16_t for QtyCentering improves type safety and memory usage.

The change to use std::uint16_t as the underlying type for the QtyCentering enumeration is appropriate for optimizing memory usage and ensuring type safety.

Ensure that this change does not introduce any issues in the codebase where QtyCentering is used.

Verification successful

The change to use std::uint16_t as the underlying type for the QtyCentering enumeration is appropriate for optimizing memory usage and ensuring type safety. Based on the extensive usage of QtyCentering throughout the codebase, we need to ensure that this change does not introduce any type compatibility issues.

Ensure that this change does not introduce any issues in the codebase where QtyCentering is used.


Using std::uint16_t for QtyCentering improves type safety and memory usage.

The change to use std::uint16_t as the underlying type for the QtyCentering enumeration is appropriate for optimizing memory usage and ensuring type safety. Based on the extensive usage of QtyCentering and the absence of any type compatibility issues related to the change, this update is confirmed to be safe.

  • All instances of QtyCentering usage are compatible with the new underlying type.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of QtyCentering in the codebase to ensure compatibility with the new type.

# Test: Search for the usage of QtyCentering. Expect: No issues due to the type change.
rg --type cpp -A 5 $'QtyCentering'

Length of output: 141705


Script:

#!/bin/bash
# Description: Verify the usage of QtyCentering in the codebase to ensure compatibility with the new type.

# Test: Search for the usage of QtyCentering and check for type compatibility issues.
rg --type cpp -A 5 'QtyCentering' | grep -E 'static_cast|reinterpret_cast|dynamic_cast|const_cast'

Length of output: 3696

tests/simulator/per_test.hpp (2)

111-114: Addition of Simulator3dTest is appropriate.

The new Simulator3dTest structure extends ::testing::Test and follows the existing pattern for 1D and 2D tests.


115-117: Definition of Simulator3d and usage in TYPED_TEST_SUITE is correct.

The Simulator3d type alias and its usage in TYPED_TEST_SUITE macro are correctly defined, enabling parameterized tests for 3D simulations.

Ensure that the new test cases comprehensively cover the 3D simulation scenarios.

tests/simulator/initialize/test_particles_init_3d.py (2)

1-4: File-level documentation is clear.

The file-level docstring explains the purpose of the file and its independence from test_initialization.py.


25-32: Addition of Initialization3DTest is appropriate.

The new Initialization3DTest class extends InitializationTest and covers various 3D particle initialization scenarios.

tests/simulator/advance/test_fields_advance_3d.py (3)

6-14: LGTM! Imports and initial configurations are appropriate.

The imports and initial configurations are necessary for the tests and are correctly set up.


21-23: LGTM! The per_interp function is simple and effective.

The function generates a list of tuples for different interpolation orders, which is useful for parameterized tests.


106-107: LGTM! The main execution block is correctly set up.

The main execution block correctly runs the unittest main function.

src/amr/data/particles/refine/splitter.hpp (4)

Line range hint 10-16: LGTM! The SplitPattern struct is well-defined.

The struct initializes its members correctly and follows good practices.


Line range hint 74-87: LGTM! The ASplitter struct is well-defined.

The struct defines constants and initializes its members correctly.


118-144: LGTM! The renamed and new structs improve readability.

The renaming of structs to more descriptive names improves readability, and the new structs are well-defined.


70-70: LGTM! The type casting for weights enhances type safety.

The type casting for weights in the PatternDispatcher class enhances type safety and clarity regarding weight handling.

res/cmake/options.cmake (1)

73-75: LGTM! The placement of the new configuration option is consistent.

The placement of the new highResourceTests option maintains the overall structure of the configuration file.

src/core/utilities/meta/meta_utilities.hpp (1)

9-11: Ensure the default value for PHARE_SIMULATORS is well-documented.

The macro PHARE_SIMULATORS is defined with a default value of 3. It's important to document this value in the code or in related documentation to clarify its impact and usage within the project.

tests/functional/harris/harris_3d.py (2)

1-1: Add a shebang line for portability.

The shebang line #!/usr/bin/env python3 ensures the script is executed with the correct Python interpreter.


37-53: LGTM! But ensure proper test coverage.

The config function sets up the simulation configuration. Ensure that this configuration is adequately tested to verify its correctness.

tests/simulator/refined_particle_nbr.py (4)

33-37: Add exception handling in the tearDown method.

It's good practice to handle exceptions during the teardown process to ensure that any errors during simulator reset do not halt the test suite.


44-47: Clarify the calculations in the _less_per_dim method.

The calculations in the _less_per_dim method are critical for ensuring the correct number of particles are refined. Adding comments to explain the logic behind these calculations and assertions would significantly improve code clarity and maintainability.


78-117: Clarify the calculations in the _do_dim method.

The calculations in the _do_dim method are critical for ensuring the correct number of particles are refined. Adding comments to explain the logic behind these calculations and assertions would significantly improve code clarity and maintainability.


117-135: Add comments to explain the logic in the test_values method.

The addition of the test_values method to verify delta and weights for different configurations is a valuable addition to the test suite. Consider adding comments to explain the logic behind the calculations and assertions in this block to improve code clarity.

src/amr/data/particles/refine/split_1d.hpp (10)

20-24: LGTM!

The renaming from PinkDispatcher to PinkPattern is consistent and maintains the original functionality.


34-34: LGTM!

The type alias SplitPattern_1_1_2_Dispatcher correctly references PinkPattern.


53-53: LGTM!

The type alias SplitPattern_1_1_3_Dispatcher correctly references BlackPattern and PinkPattern.


71-71: LGTM!

The type alias SplitPattern_1_2_2_Dispatcher correctly references PinkPattern.


90-90: LGTM!

The type alias SplitPattern_1_2_3_Dispatcher correctly references BlackPattern and PinkPattern.


109-109: LGTM!

The type alias SplitPattern_1_2_4_Dispatcher correctly references PinkPattern.


127-127: LGTM!

The type alias SplitPattern_1_3_2_Dispatcher correctly references PinkPattern.


146-146: LGTM!

The type alias SplitPattern_1_3_3_Dispatcher correctly references BlackPattern and PinkPattern.


165-165: LGTM!

The type alias SplitPattern_1_3_4_Dispatcher correctly references PinkPattern.


184-185: LGTM!

The type alias SplitPattern_1_3_5_Dispatcher correctly references BlackPattern and PinkPattern.

pyphare/pyphare/core/box.py (5)

65-67: LGTM!

The __sub__ method correctly handles lists/tuples of Box instances and utilizes the remove_all function for batch removal.


185-198: LGTM!

The remove_all function enhances flexibility by allowing batch removal of boxes in a single operation.


206-207: LGTM!

The select function enhances data selection capabilities by retrieving a slice of data based on the lower and upper bounds of a Box.

Tools
Ruff

207-207: Ambiguous variable name: l

(E741)


209-223: LGTM!

The DataSelector class enhances usability by allowing indexed access using Box instances or standard slicing.


185-198: Add unit tests for remove_all function.

The remove_all function provides a robust mechanism for removing multiple boxes. Consider adding unit tests to cover various scenarios, such as partial overlaps or complete containment.

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

218-218: LGTM!

The minor formatting adjustment in the template deduction guide improves code readability.

res/cmake/funcs.cmake (12)

37-42: LGTM!

The set_exe_paths_ function correctly sets environment properties for the given test binary.


44-57: LGTM!

The add_phare_test_ function correctly configures the test binary and optionally adds a custom command to run the test during the build process.


59-67: LGTM!

The add_no_mpi_phare_test function correctly adds a test for a binary that does not use MPI and configures it appropriately.


69-74: LGTM!

The add_no_mpi_python3_test function correctly adds a test for a Python script that does not use MPI and configures it appropriately.


76-80: LGTM!

The add_phare_test function correctly adds a test for a binary, using MPI if enabled.


82-85: LGTM!

The add_python3_test function correctly adds a test for a Python script, using MPI if enabled.


87-90: LGTM!

The add_mpi_python3_test function correctly adds a test for a Python script with a specified number of MPI processes.


130-134: LGTM!

The phare_exec function correctly adds a test for a binary if the execution level is within the specified range.


139-155: LGTM!

The phare_mpi_python3_exec function correctly adds a test for a Python script with MPI if the execution level is within the specified range.


161-172: LGTM!

The phare_python3_exec function correctly adds a test for a Python script, using MPI if enabled and the execution level is within the specified range.


185-191: LGTM!

The phare_print_all_vars function correctly prints all CMake variables.


1-192: Overall structure and logic are well-organized.

The file is well-organized and logically structured, making it easy to understand and maintain.

src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (5)

40-49: LGTM!

The constructor for MagneticFieldCoarsener correctly initializes the class with centering, sourceBox, destinationBox, and ratio.


52-59: LGTM!

The operator() method correctly performs coarsening by calling the appropriate coarsen method based on the dimension.


62-75: LGTM!

The fine_start_index method correctly calculates the fine start index based on the coarse index and the ratio.


78-114: LGTM!

The template methods for 1D and 2D coarsening correctly perform the coarsening based on the dimension and centering type.


34-98: Overall structure and logic are well-organized.

The MagneticFieldCoarsener class is well-organized and logically structured, making it easy to understand and maintain.

tests/simulator/__init__.py (1)

97-107: LGTM!

The density_3d_periodic function correctly calculates a 3D density distribution based on the

src/amr/data/particles/refine/split_3d.hpp (3)

71-86: LGTM!

The constructor is well-structured and uses a lambda function for adding squares.


96-114: LGTM!

The constructor is well-structured and uses lambda functions for adding squares.


124-234: LGTM!

The Splitter struct is well-structured and defines static constants for delta and weight.

pyphare/pyphare/pharesee/run/utils.py (1)

362-362: LGTM! Dynamic dimension handling.

The change to use ndim instead of a hardcoded value improves flexibility.

pyphare/pyphare/pharesee/geometry.py (3)

59-74: LGTM! Expanded functionality for 3D domain boxes.

The changes correctly handle the additional dimensions for 3D domain boxes.


Line range hint 87-188:
LGTM! Enhanced periodicity shifts for 3D.

The changes correctly handle the additional dimensions for 3D periodicity shifts.

Tools
Ruff

161-161: Ambiguous variable name: l

(E741)


164-164: Ambiguous variable name: l

(E741)


167-167: Ambiguous variable name: l

(E741)


188-188: Ambiguous variable name: l

(E741)


290-290: LGTM! Refactored for 3D dimensional handling.

The changes correctly handle the additional dimensions for identifying borders.

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

390-427: LGTM! Ensure performance is acceptable.

The fill3D method correctly fills the borders of a 3D array using nested loops. Ensure that the performance is acceptable for large arrays.


Line range hint 473-598:
LGTM! Ensure assertions and logic are correct.

The operator>> function has been updated to handle 3D cases. The assertions and logic appear to be correct. Ensure that the assertions do not fail for valid inputs.

tests/core/numerics/interpolator/test_main.cpp (3)

724-772: LGTM! Ensure initialization and setup are correct.

The ACollectionOfParticles_3d struct initializes a particle array and sets up the interpolation tests. The initialization and setup appear to be correct. Ensure that the particle properties and interpolation logic are accurate.


787-788: LGTM! Ensure test coverage is complete.

The INSTANTIATE_TYPED_TEST_SUITE_P macro correctly instantiates the test suite for 3D interpolators. Ensure that all required interpolator types are covered.


776-783: Uncomment and verify the test case DepositCorrectlyTheirWeight_3d.

The test case is crucial for validating 3D interpolation correctness but is currently commented out. This needs to be active to ensure the functionality is tested properly.

-    // auto const& [vx, vy, vz] = this->v();
-    // EXPECT_DOUBLE_EQ(this->rho(7, 7, 7), 1.0);
-    // EXPECT_DOUBLE_EQ(vx(7, 7, 7), 2.0);
-    // EXPECT_DOUBLE_EQ(vy(7, 7, 7), -1.0);
-    // EXPECT_DOUBLE_EQ(vz(7, 7, 7), 1.0);
+    auto const& [vx, vy, vz] = this->v();
+    EXPECT_DOUBLE_EQ(this->rho(7, 7, 7), 1.0);
+    EXPECT_DOUBLE_EQ(vx(7, 7, 7), 2.0);
+    EXPECT_DOUBLE_EQ(vy(7, 7, 7), -1.0);
+    EXPECT_DOUBLE_EQ(vz(7, 7, 7), 1.0);

Likely invalid or redundant comment.

tests/simulator/test_initialization.py (5)

Line range hint 254-354:
LGTM! Ensure ppc parameter is correctly utilized.

The function _test_B_is_as_provided_by_user has been updated to include the ppc parameter. Ensure that it is correctly utilized in the function.


Line range hint 355-417:
LGTM! Ensure ppc parameter is correctly utilized.

The function _test_bulkvel_is_as_provided_by_user has been updated to include the ppc parameter. Ensure that it is correctly utilized in the function.

Tools
Ruff

394-394: Function definition does not bind loop variable select

(B023)


396-396: Function definition does not bind loop variable patch

(B023)


396-396: Function definition does not bind loop variable nbrGhosts

(B023)


397-397: Function definition does not bind loop variable select

(B023)


Line range hint 417-479:
LGTM! Ensure ndim parameter is correctly utilized.

The function _test_density_is_as_provided_by_user has been updated to include the ndim parameter. Ensure that it is correctly utilized in the function.

Tools
Ruff

394-394: Function definition does not bind loop variable select

(B023)


396-396: Function definition does not bind loop variable patch

(B023)


396-396: Function definition does not bind loop variable nbrGhosts

(B023)


397-397: Function definition does not bind loop variable select

(B023)


Line range hint 483-561:
LGTM! Ensure ndim parameter is correctly utilized.

The function _test_density_decreases_as_1overSqrtN has been updated to include the ndim parameter. Ensure that it is correctly utilized in the function.


566-586: LGTM! Ensure ndim and ppc parameters are correctly utilized.

The function _test_nbr_particles_per_cell_is_as_provided has been updated to include the ndim and ppc parameters. Ensure that they are correctly utilized in the function.

Tools
Ruff

582-582: Loop control variable pi not used within loop body

Rename unused pi to _pi

(B007)


586-586: Yoda condition detected

Rewrite as ppc == H

(SIM300)

tests/simulator/test_advance.py (2)

370-372: LGTM!

The changes to include a default value for cells enhance the flexibility of the function.


Line range hint 399-420:
LGTM!

The changes to accept cells as an argument enhance the flexibility of the function.

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

110-120: Avoid overwriting attributes in the superclass.

Assignment overwrites the layout attribute, which was previously defined in the superclass PatchData.

- self.layout = layout

Likely invalid or redundant comment.

Comment on lines +89 to +91
def S(x, x0, l):
return 0.5 * (1 + np.tanh((x - x0) / l))

Copy link

Choose a reason for hiding this comment

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

Refactor lambda expression to a function.

Refactor the lambda expression to a function for better readability and maintainability.

-        def S(x, x0, l):
-            return 0.5 * (1 + np.tanh((x - x0) / l))
+        def S(x, x0, length):
+            return 0.5 * (1 + np.tanh((x - x0) / length))
Committable suggestion

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

Suggested change
def S(x, x0, l):
return 0.5 * (1 + np.tanh((x - x0) / l))
def S(x, x0, length):
return 0.5 * (1 + np.tanh((x - x0) / length))
Tools
Ruff

89-89: Ambiguous variable name: l

(E741)


Clarify ambiguous variable name.

The variable name l is ambiguous and can be mistaken for the number 1. Use a more descriptive name for clarity.

- def S(x, x0, l):
+ def S(x, x0, length):
Committable suggestion

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

Suggested change
def S(x, x0, l):
return 0.5 * (1 + np.tanh((x - x0) / l))
def S(x, x0, length):
return 0.5 * (1 + np.tanh((x - x0) / length))
Tools
Ruff

89-89: Ambiguous variable name: l

(E741)

Comment on lines +265 to +273
slice1 = boxm.select(
pd1.dataset,
boxm.amr_to_local(box, boxm.shift(pd1.ghost_box, offsets[0])),
)
loc_b2 = boxm.amr_to_local(
box, boxm.shift(pd2.ghost_box, offsets[1])
slice2 = boxm.select(
pd2.dataset,
boxm.amr_to_local(box, boxm.shift(pd2.ghost_box, offsets[1])),
)

data1 = pd1.dataset
data2 = pd2.dataset

if box.ndim == 1:
slice1 = data1[loc_b1.lower[0] : loc_b1.upper[0] + 1]
slice2 = data2[loc_b2.lower[0] : loc_b2.upper[0] + 1]

if box.ndim == 2:
slice1 = data1[
loc_b1.lower[0] : loc_b1.upper[0] + 1,
loc_b1.lower[1] : loc_b1.upper[1] + 1,
]
slice2 = data2[
loc_b2.lower[0] : loc_b2.upper[0] + 1,
loc_b2.lower[1] : loc_b2.upper[1] + 1,
]
assert slice1.dtype == np.float64
Copy link

Choose a reason for hiding this comment

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

Remove redundant assertion.

The assertion assert slice1.dtype == np.float64 is redundant and clutters the code. It can be removed without affecting functionality.

-                    assert slice1.dtype == np.float64
Committable suggestion

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

Suggested change
slice1 = boxm.select(
pd1.dataset,
boxm.amr_to_local(box, boxm.shift(pd1.ghost_box, offsets[0])),
)
loc_b2 = boxm.amr_to_local(
box, boxm.shift(pd2.ghost_box, offsets[1])
slice2 = boxm.select(
pd2.dataset,
boxm.amr_to_local(box, boxm.shift(pd2.ghost_box, offsets[1])),
)
data1 = pd1.dataset
data2 = pd2.dataset
if box.ndim == 1:
slice1 = data1[loc_b1.lower[0] : loc_b1.upper[0] + 1]
slice2 = data2[loc_b2.lower[0] : loc_b2.upper[0] + 1]
if box.ndim == 2:
slice1 = data1[
loc_b1.lower[0] : loc_b1.upper[0] + 1,
loc_b1.lower[1] : loc_b1.upper[1] + 1,
]
slice2 = data2[
loc_b2.lower[0] : loc_b2.upper[0] + 1,
loc_b2.lower[1] : loc_b2.upper[1] + 1,
]
assert slice1.dtype == np.float64
slice1 = boxm.select(
pd1.dataset,
boxm.amr_to_local(box, boxm.shift(pd1.ghost_box, offsets[0])),
)
slice2 = boxm.select(
pd2.dataset,
boxm.amr_to_local(box, boxm.shift(pd2.ghost_box, offsets[1])),
)


def checkout(branch, create=False, recreate=False):
if recreate:
delete_branch(branch)
Copy link

Choose a reason for hiding this comment

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

Fix undefined name delete_branch.

The function delete_branch is called but not defined. Ensure that this function is defined or imported before use.

Tools
Ruff

29-29: Undefined name delete_branch

(F821)

Comment on lines +9 to +27
TYPED_TEST(Simulator3dTest, fluid)
{
fluid_test(TypeParam{job_file}, out_dir);
}

TYPED_TEST(Simulator3dTest, particles)
{
particles_test(TypeParam{job_file}, out_dir);
}

TYPED_TEST(Simulator3dTest, electromag)
{
electromag_test(TypeParam{job_file}, out_dir);
}

TYPED_TEST(Simulator3dTest, allFromPython)
{
allFromPython_test(TypeParam{job_file}, out_dir);
}
Copy link

Choose a reason for hiding this comment

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

Refactor repeated code in test cases.

Each test case function (fluid_test, particles_test, electromag_test, allFromPython_test) is called with the same parameters. Consider refactoring this to reduce code duplication.

+ void run_test(auto test_func) {
+     test_func(TypeParam{job_file}, out_dir);
+ }

-    fluid_test(TypeParam{job_file}, out_dir);
-    particles_test(TypeParam{job_file}, out_dir);
-    electromag_test(TypeParam{job_file}, out_dir);
-    allFromPython_test(TypeParam{job_file}, out_dir);
+    run_test(fluid_test);
+    run_test(particles_test);
+    run_test(electromag_test);
+    run_test(allFromPython_test);
Committable suggestion

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

Suggested change
TYPED_TEST(Simulator3dTest, fluid)
{
fluid_test(TypeParam{job_file}, out_dir);
}
TYPED_TEST(Simulator3dTest, particles)
{
particles_test(TypeParam{job_file}, out_dir);
}
TYPED_TEST(Simulator3dTest, electromag)
{
electromag_test(TypeParam{job_file}, out_dir);
}
TYPED_TEST(Simulator3dTest, allFromPython)
{
allFromPython_test(TypeParam{job_file}, out_dir);
}
void run_test(auto test_func) {
test_func(TypeParam{job_file}, out_dir);
}
TYPED_TEST(Simulator3dTest, fluid)
{
run_test(fluid_test);
}
TYPED_TEST(Simulator3dTest, particles)
{
run_test(particles_test);
}
TYPED_TEST(Simulator3dTest, electromag)
{
run_test(electromag_test);
}
TYPED_TEST(Simulator3dTest, allFromPython)
{
run_test(allFromPython_test);
}

Comment on lines +22 to +23
except subprocess.CalledProcessError as e:
return False # exit failure means branch does not exist
Copy link

Choose a reason for hiding this comment

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

Remove unused variable e.

The variable e is assigned but never used. It should be removed to clean up the code.

-    except subprocess.CalledProcessError as e:
+    except subprocess.CalledProcessError:
Committable suggestion

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

Suggested change
except subprocess.CalledProcessError as e:
return False # exit failure means branch does not exist
except subprocess.CalledProcessError:
return False # exit failure means branch does not exist
Tools
Ruff

22-22: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

Comment on lines +127 to +128
auto zstart() const { return mask_.min(); }
auto zend() const { return shape_[2] - 1 - mask_.max(); }
Copy link

Choose a reason for hiding this comment

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

Add NO_DISCARD to zstart and zend methods for consistency.

The methods zstart and zend in the MaskedView class are missing the NO_DISCARD attribute, which is used in other similar methods in this class. This attribute is important to prevent ignoring the return value of these methods.

- auto zstart() const { return mask_.min(); }
- auto zend() const { return shape_[2] - 1 - mask_.max(); }
+ NO_DISCARD auto zstart() const { return mask_.min(); }
+ NO_DISCARD auto zend() const { return shape_[2] - 1 - mask_.max(); }
Committable suggestion

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

Suggested change
auto zstart() const { return mask_.min(); }
auto zend() const { return shape_[2] - 1 - mask_.max(); }
NO_DISCARD auto zstart() const { return mask_.min(); }
NO_DISCARD auto zend() const { return shape_[2] - 1 - mask_.max(); }

Comment on lines +77 to +94
# @data({"cells": 40, "smallest_patch_size": 20, "largest_patch_size": 20, "nbr_part_per_cell" : ppc})
# def test_no_patch_ghost_on_refined_level_case(self, simInput):
# print(f"\n{self._testMethodName}_{ndim}d")
# now = self.datetime_now()
# self._test_patch_ghost_on_refined_level_case(ndim, False, **simInput)
# print(f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds")

# @data({"cells": 40, "interp_order": 1, "nbr_part_per_cell" : ppc})
# def test_has_patch_ghost_on_refined_level_case(self, simInput):
# print(f"\n{self._testMethodName}_{ndim}d")
# from pyphare.pharein.simulation import check_patch_size
# diag_outputs=f"phare_overlaped_fields_are_equal_with_min_max_patch_size_of_max_ghosts_{ndim}_{self.ddt_test_id()}"
# _, smallest_patch_size = check_patch_size(ndim, **simInput)
# simInput["smallest_patch_size"] = smallest_patch_size
# simInput["largest_patch_size"] = smallest_patch_size
# now = self.datetime_now()
# self._test_patch_ghost_on_refined_level_case(ndim, True, **simInput)
# print(f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds")
Copy link

Choose a reason for hiding this comment

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

Remove or document commented-out test cases.

The commented-out test cases should either be removed or documented to explain their necessity. Keeping commented-out code can lead to confusion and clutter in the codebase.

-    # @data({"cells": 40, "smallest_patch_size": 20, "largest_patch_size": 20, "nbr_part_per_cell" : ppc})
-    # def test_no_patch_ghost_on_refined_level_case(self, simInput):
-    #     print(f"\n{self._testMethodName}_{ndim}d")
-    #     now = self.datetime_now()
-    #     self._test_patch_ghost_on_refined_level_case(ndim, False, **simInput)
-    #     print(f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds")
-
-    # @data({"cells": 40, "interp_order": 1, "nbr_part_per_cell" : ppc})
-    # def test_has_patch_ghost_on_refined_level_case(self, simInput):
-    #     print(f"\n{self._testMethodName}_{ndim}d")
-    #     from pyphare.pharein.simulation import check_patch_size
-    #     diag_outputs=f"phare_overlaped_fields_are_equal_with_min_max_patch_size_of_max_ghosts_{ndim}_{self.ddt_test_id()}"
-    #     _, smallest_patch_size = check_patch_size(ndim, **simInput)
-    #     simInput["smallest_patch_size"] = smallest_patch_size
-    #     simInput["largest_patch_size"] = smallest_patch_size
-    #     now = self.datetime_now()
-    #     self._test_patch_ghost_on_refined_level_case(ndim, True, **simInput)
-    #     print(f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds")
Committable suggestion

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

Suggested change
# @data({"cells": 40, "smallest_patch_size": 20, "largest_patch_size": 20, "nbr_part_per_cell" : ppc})
# def test_no_patch_ghost_on_refined_level_case(self, simInput):
# print(f"\n{self._testMethodName}_{ndim}d")
# now = self.datetime_now()
# self._test_patch_ghost_on_refined_level_case(ndim, False, **simInput)
# print(f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds")
# @data({"cells": 40, "interp_order": 1, "nbr_part_per_cell" : ppc})
# def test_has_patch_ghost_on_refined_level_case(self, simInput):
# print(f"\n{self._testMethodName}_{ndim}d")
# from pyphare.pharein.simulation import check_patch_size
# diag_outputs=f"phare_overlaped_fields_are_equal_with_min_max_patch_size_of_max_ghosts_{ndim}_{self.ddt_test_id()}"
# _, smallest_patch_size = check_patch_size(ndim, **simInput)
# simInput["smallest_patch_size"] = smallest_patch_size
# simInput["largest_patch_size"] = smallest_patch_size
# now = self.datetime_now()
# self._test_patch_ghost_on_refined_level_case(ndim, True, **simInput)
# print(f"\n{self._testMethodName}_{ndim}d took {self.datetime_diff(now)} seconds")

Comment on lines +661 to +669
def _test_patch_ghost_on_refined_level_case(self, ndim, has_patch_ghost, **kwargs):
import pyphare.pharein as ph

out = "phare_outputs"
refinement_boxes = {"L0": [nDBox(dim, 10, 19)]}
refinement_boxes = {"L0": [nDBox(ndim, 10, 19)]}
kwargs["interp_order"] = kwargs.get("interp_order", 1)
kwargs["diag_outputs"] = f"{has_patch_ghost}"
datahier = self.getHierarchy(
ndim=dim,
ndim,
Copy link

Choose a reason for hiding this comment

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

Remove unused variable out.

The function _test_patch_ghost_on_refined_level_case has been updated to include the ndim parameter. The variable out is defined but not used. Remove the unused variable to avoid confusion.

- out = "phare_outputs"
Committable suggestion

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

Suggested change
def _test_patch_ghost_on_refined_level_case(self, ndim, has_patch_ghost, **kwargs):
import pyphare.pharein as ph
out = "phare_outputs"
refinement_boxes = {"L0": [nDBox(dim, 10, 19)]}
refinement_boxes = {"L0": [nDBox(ndim, 10, 19)]}
kwargs["interp_order"] = kwargs.get("interp_order", 1)
kwargs["diag_outputs"] = f"{has_patch_ghost}"
datahier = self.getHierarchy(
ndim=dim,
ndim,
def _test_patch_ghost_on_refined_level_case(self, ndim, has_patch_ghost, **kwargs):
import pyphare.pharein as ph
refinement_boxes = {"L0": [nDBox(ndim, 10, 19)]}
kwargs["interp_order"] = kwargs.get("interp_order", 1)
kwargs["diag_outputs"] = f"{has_patch_ghost}"
datahier = self.getHierarchy(
ndim,
Tools
Ruff

664-664: Local variable out is assigned to but never used

Remove assignment to unused variable out

(F841)

Comment on lines +79 to +103
# @data(
# *per_interp(({"L0": {"B0": Box3D(10, 14)}})),
# *per_interp(({"L0": {"B0": Box3D(10, 14), "B1": Box3D(15, 19)}})),
# *per_interp(({"L0": {"B0": Box3D(6, 23)}})),
# *per_interp(({"L0": {"B0": Box3D( 2, 12), "B1": Box3D(13, 25)}})),
# *per_interp(({"L0": {"B0": Box3D( 5, 20)}, "L1": {"B0": Box3D(15, 19)}})),
# *per_interp(({"L0": {"B0": Box3D( 5, 20)}, "L1": {"B0": Box3D(12, 38)}, "L2": {"B0": Box3D(30, 52)} })),
# )
# @unpack
# def test_field_coarsening_via_subcycles(self, interp_order, refinement_boxes):
# print(f"{self._testMethodName}_{ndim}d")
# self._test_field_coarsening_via_subcycles(ndim, interp_order, refinement_boxes, dl=.3, cells=cells)

# @unittest.skip("should change to work on moments")
# @data( # only supports a hierarchy with 2 levels
# *per_interp(({"L0": [Box3D(0, 4)]})),
# *per_interp(({"L0": [Box3D(10, 14)]})),
# *per_interp(({"L0": [Box3D(0, 4), Box3D(10, 14)]})),
# *per_interp(({"L0": [Box3D(0, 4), Box3D(5, 9), Box3D(10, 14)]})),
# *per_interp(({"L0": [Box3D(20, 24)]})),
# )
# @unpack
# def test_field_level_ghosts_via_subcycles_and_coarser_interpolation(self, interp_order, refinement_boxes):
# print(f"{self._testMethodName}_{ndim}d")
# self._test_field_level_ghosts_via_subcycles_and_coarser_interpolation(ndim, interp_order, refinement_boxes)
Copy link

Choose a reason for hiding this comment

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

Address commented-out code.

The commented-out test cases should either be removed or uncommented with an explanation for their necessity.

-    # @data(
-    #    *per_interp(({"L0": {"B0": Box3D(10, 14)}})),
-    #    *per_interp(({"L0": {"B0": Box3D(10, 14), "B1": Box3D(15, 19)}})),
-    #    *per_interp(({"L0": {"B0": Box3D(6, 23)}})),
-    #    *per_interp(({"L0": {"B0": Box3D( 2, 12), "B1": Box3D(13, 25)}})),
-    #    *per_interp(({"L0": {"B0": Box3D( 5, 20)}, "L1": {"B0": Box3D(15, 19)}})),
-    #    *per_interp(({"L0": {"B0": Box3D( 5, 20)}, "L1": {"B0": Box3D(12, 38)}, "L2": {"B0": Box3D(30, 52)} })),
-    # )
-    # @unpack
-    # def test_field_coarsening_via_subcycles(self, interp_order, refinement_boxes):
-    #     print(f"{self._testMethodName}_{ndim}d")
-    #     self._test_field_coarsening_via_subcycles(ndim, interp_order, refinement_boxes, dl=.3, cells=cells)
-
-    # @unittest.skip("should change to work on moments")
-    # @data( # only supports a hierarchy with 2 levels
-    #    *per_interp(({"L0": [Box3D(0, 4)]})),
-    #    *per_interp(({"L0": [Box3D(10, 14)]})),
-    #    *per_interp(({"L0": [Box3D(0, 4), Box3D(10, 14)]})),
-    #    *per_interp(({"L0": [Box3D(0, 4), Box3D(5, 9), Box3D(10, 14)]})),
-    #    *per_interp(({"L0": [Box3D(20, 24)]})),
-    # )
-    # @unpack
-    # def test_field_level_ghosts_via_subcycles_and_coarser_interpolation(self, interp_order, refinement_boxes):
-    #     print(f"{self._testMethodName}_{ndim}d")
-    #     self._test_field_level_ghosts_via_subcycles_and_coarser_interpolation(ndim, interp_order, refinement_boxes)
+    # Uncomment and document the necessity of these test cases or remove them if not needed.

Committable suggestion was skipped due to low confidence.

Comment on lines +73 to +75
# -DhighResourceTests=ON
option(highResourceTests "Enable heavy tests for CI (3d/etc" OFF)

Copy link

Choose a reason for hiding this comment

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

Ensure mutual exclusivity between lowResourceTests and highResourceTests.

The new highResourceTests option is useful for enabling heavy tests in CI. However, ensure that lowResourceTests and highResourceTests cannot be enabled simultaneously to avoid conflicting configurations.

+ if(lowResourceTests AND highResourceTests)
+   message(FATAL_ERROR "Both lowResourceTests and highResourceTests cannot be enabled at the same time.")
+ endif()
Committable suggestion

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

Suggested change
# -DhighResourceTests=ON
option(highResourceTests "Enable heavy tests for CI (3d/etc" OFF)
# -DhighResourceTests=ON
option(highResourceTests "Enable heavy tests for CI (3d/etc" OFF)
if(lowResourceTests AND highResourceTests)
message(FATAL_ERROR "Both lowResourceTests and highResourceTests cannot be enabled at the same time.")
endif()

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 20

Outside diff range, codebase verification and nitpick comments (18)
tests/simulator/advance/test_particles_advance_3d.py (3)

1-4: Enhance the file-level docstring.

The docstring could be more descriptive about the specific 3D test cases contained in this file.

"""
  This file exists independently from test_advance.py to isolate dimension
    test cases and allow each to be overridden in some way if required.
+ It includes tests for overlapped particle data and particle number conservation in 3D.
"""

21-23: Add a docstring to the per_interp function.

Including a docstring will help explain the purpose and structure of the returned data.

def per_interp(dic):
    """
    Generates a list of tuples pairing interpolation orders with a given dictionary.

    Args:
        dic (dict): A dictionary to pair with each interpolation order.

    Returns:
        list: A list of tuples (interp_order, dic).
    """
    return [(interp, dic) for interp in interp_orders]

50-51: Consider using pytest for test execution.

Using a more robust test runner like pytest can provide more comprehensive test discovery and reporting.

if __name__ == "__main__":
    unittest.main()
# Consider replacing with pytest for better flexibility and features.
tools/python3/cmake.py (1)

4-5: Implement or remove the placeholder version function.

The version function is currently a placeholder and does nothing. It should either be implemented or removed if not needed.

def version():
    pass
+    # TODO: Implement this function or remove it if not needed.
tests/simulator/initialize/test_fields_init_3d.py (1)

1-4: Enhance the file-level docstring.

The docstring could be more descriptive about the specific 3D test cases contained in this file.

"""
  This file exists independently from test_initialization.py to isolate dimension
    test cases and allow each to be overridden in some way if required.
+ It includes tests for field initialization such as magnetic field, bulk velocity, and density in 3D.
"""
tests/simulator/advance/test_fields_advance_3d.py (2)

1-4: Enhance the file-level docstring.

The docstring could be more descriptive about the specific tests being conducted in this file.

-  This file exists independently from test_advance.py to isolate dimension
-    test cases and allow each to be overridden in some way if required.
+  This file contains tests for advancing fields in a 3D context, focusing on overlapping fields and patch sizes. It exists independently from test_advance.py to isolate dimension-specific test cases and allow for customization.

54-77: Simplify method name for clarity.

The method name test_overlaped_fields_are_equal_with_min_max_patch_size_of_max_ghosts is quite long and could be shortened without losing its meaning.

- def test_overlaped_fields_are_equal_with_min_max_patch_size_of_max_ghosts(
+ def test_fields_equal_with_patch_size_limits(
res/cmake/funcs.cmake (3)

44-57: Clarify the purpose of add_phare_test_.

The function add_phare_test_ sets up test properties and adds a custom command for post-build testing. Ensure that the naming and documentation clearly convey its purpose as an internal helper function.

-  function(add_phare_test_ binary directory)
+  # Internal helper function to configure test properties and post-build commands
+  function(add_phare_test_internal binary directory)

111-128: Consider external dependency management.

The file includes logic to clone and add the Google Test subdirectory if GTEST_ROOT is not defined. Consider using a package manager or external script for managing dependencies to improve maintainability.


185-191: Avoid using get_cmake_property for debugging.

The function phare_print_all_vars uses get_cmake_property to print all variables, which can be overwhelming. Consider filtering or categorizing the variables for more effective debugging.

-  foreach (_variableName ${_variableNames})
+  foreach (_variableName ${_variableNames})
+      if(_variableName MATCHES "PHARE_.*")
pyphare/pyphare/pharesee/geometry.py (1)

161-161: Rename ambiguous variable names for clarity.

The variable l is used in list comprehensions but is not descriptive. Consider renaming it to a more meaningful name that indicates its purpose or contents.

- f"{k}front": [(v[0], v[1], shape_z) for v in l] for k, l in shifts.items()
+ f"{k}front": [(v[0], v[1], shape_z) for v in values] for k, values in shifts.items()

Apply similar changes to other instances where l is used.

Also applies to: 164-164, 167-167, 188-188

Tools
Ruff

161-161: Ambiguous variable name: l

(E741)

tests/simulator/test_advance.py (3)

89-91: Clarify ambiguous variable name and refactor.

The variable name l is ambiguous and can be mistaken for the number 1. Consider using a more descriptive name. Additionally, refactor the lambda expression to a function for better readability and maintainability.

-        def S(x, x0, l):
-            return 0.5 * (1 + np.tanh((x - x0) / l))
+        def S(x, x0, length):
+            return 0.5 * (1 + np.tanh((x - x0) / length))
Tools
Ruff

89-89: Ambiguous variable name: l

(E741)


265-273: Remove redundant assertion.

The assertion assert slice1.dtype == np.float64 is redundant and clutters the code. It can be removed without affecting functionality.

-                    assert slice1.dtype == np.float64

493-493: Replace magic number with a named constant.

Using magic numbers can make the code less readable and maintainable. Consider replacing -144123 with a named constant for better clarity.

+ MAGIC_NUMBER = -144123
- boxm.DataSelector(afterCoarse)[dataBox] = -144123
+ boxm.DataSelector(afterCoarse)[dataBox] = MAGIC_NUMBER
pyphare/pyphare/pharesee/hierarchy.py (4)

31-33: Avoid using __setattr__ directly.

Using __setattr__ directly can lead to issues with encapsulation and maintainability. Consider using setter methods or modifying the class design to allow safer ways to set these attributes.

def set_ghosts_nbr(self, ghosts_nbr):
    self.ghosts_nbr = np.asarray(ghosts_nbr)

def set_ghost_box(self, ghost_box):
    self.ghost_box = ghost_box

42-52: Optimize property methods for x, y, and z.

The property methods for x, y, and z can be optimized by combining common logic into a helper method.

def get_coord(self, axis: str, centering: str):
    withGhosts = self.field_name != "tags"
    return self.layout.yeeCoordsFor(
        self.field_name,
        axis,
        withGhosts=withGhosts,
        centering=centering,
    )

@property
def x(self):
    if self._x is None:
        self._x = self.get_coord("x", self.centerings[0])
    return self._x

@property
def y(self):
    if self._y is None:
        self._y = self.get_coord("y", self.centerings[1])
    return self._y

@property
def z(self):
    if self._z is None:
        self._z = self.get_coord("z", self.centerings[2])
    return self._z

1343-1344: Improve compatibility check for hierarchies.

The compatibility check could be made more explicit by detailing the criteria for compatibility or providing a helper function that encapsulates this logic.

def are_compatible_hierarchies(hierarchies):
    # Define specific criteria for compatibility
    return True

1764-1797: Add comments to clarify merging logic in merge_particles.

The merging logic in merge_particles is complex and could benefit from additional comments to clarify the purpose and steps involved in the process.

# Iterate over each patch level in the hierarchy
for time, patch_levels in hierarchy.time_hier.items():
    for ilvl, plvl in patch_levels.items():
        for ip, patch in enumerate(plvl.patches):
            # Extract domain particle data
            pdatas = patch.patch_datas
            domain_pdata = [
                (pdname, pd) for pdname, pd in pdatas.items() if "domain" in pdname
            ][0]

            # Handle patchGhost and levelGhost particle data
            pghost_pdatas = [
                (pdname, pd) for pdname, pd in pdatas.items() if "patchGhost" in pdname
            ]
            lghost_pdatas = [
                (pdname, pd) for pdname, pd in pdatas.items() if "levelGhost" in pdname
            ]

            # Merge ghost particles into domain particles
            ...
Tools
Ruff

1765-1765: Loop control variable time not used within loop body

Rename unused time to _time

(B007)


1766-1766: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


1767-1767: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)

Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 753eb43 and a3ad211.

Files selected for processing (44)
  • .github/workflows/cmake_macos.yml (1 hunks)
  • pyphare/pyphare/core/box.py (2 hunks)
  • pyphare/pyphare/core/gridlayout.py (1 hunks)
  • pyphare/pyphare/pharesee/geometry.py (7 hunks)
  • pyphare/pyphare/pharesee/hierarchy.py (1 hunks)
  • pyphare/pyphare/pharesee/run/utils.py (1 hunks)
  • res/amr/splitting.yml (1 hunks)
  • res/cmake/funcs.cmake (1 hunks)
  • res/cmake/options.cmake (2 hunks)
  • src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1 hunks)
  • src/amr/data/particles/refine/split.hpp (1 hunks)
  • src/amr/data/particles/refine/split_1d.hpp (10 hunks)
  • src/amr/data/particles/refine/split_2d.hpp (17 hunks)
  • src/amr/data/particles/refine/split_3d.hpp (1 hunks)
  • src/amr/data/particles/refine/splitter.hpp (2 hunks)
  • src/core/data/grid/gridlayoutdefs.hpp (2 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (8 hunks)
  • src/core/utilities/box/box.hpp (3 hunks)
  • src/core/utilities/meta/meta_utilities.hpp (2 hunks)
  • tests/amr/data/field/refine/test_refine_field.py (1 hunks)
  • tests/amr/data/particles/refine/input/input_3d_ratio_2.txt (1 hunks)
  • tests/amr/data/particles/refine/test_split.cpp (1 hunks)
  • tests/core/data/ndarray/test_main.cpp (1 hunks)
  • tests/core/numerics/interpolator/test_main.cpp (1 hunks)
  • tests/diagnostic/CMakeLists.txt (1 hunks)
  • tests/diagnostic/job_3d.py.in (1 hunks)
  • tests/diagnostic/test-diagnostics_3d.cpp (1 hunks)
  • tests/functional/harris/harris_3d.py (1 hunks)
  • tests/simulator/init.py (2 hunks)
  • tests/simulator/advance/CMakeLists.txt (1 hunks)
  • tests/simulator/advance/test_fields_advance_3d.py (1 hunks)
  • tests/simulator/advance/test_particles_advance_3d.py (1 hunks)
  • tests/simulator/initialize/CMakeLists.txt (1 hunks)
  • tests/simulator/initialize/test_fields_init_2d.py (1 hunks)
  • tests/simulator/initialize/test_fields_init_3d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_1d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_2d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_3d.py (1 hunks)
  • tests/simulator/per_test.hpp (1 hunks)
  • tests/simulator/refined_particle_nbr.py (2 hunks)
  • tests/simulator/test_advance.py (7 hunks)
  • tests/simulator/test_initialization.py (14 hunks)
  • tools/python3/cmake.py (1 hunks)
  • tools/python3/git.py (1 hunks)
Files skipped from review due to trivial changes (3)
  • src/amr/data/particles/refine/split_2d.hpp
  • tests/simulator/initialize/test_fields_init_2d.py
  • tests/simulator/initialize/test_particles_init_1d.py
Additional context used
Path-based instructions (10)
src/amr/data/particles/refine/split.hpp (1)

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

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

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

tests/simulator/per_test.hpp (1)

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

src/amr/data/particles/refine/splitter.hpp (1)

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

src/core/utilities/meta/meta_utilities.hpp (1)

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

src/amr/data/particles/refine/split_1d.hpp (1)

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

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

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

src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1)

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

src/amr/data/particles/refine/split_3d.hpp (1)

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

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

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

Ruff
tools/python3/git.py

22-22: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


29-29: Undefined name delete_branch

(F821)

tools/python3/cmake.py

48-48: Undefined name cmd

(F821)

tests/functional/harris/harris_3d.py

62-62: Ambiguous variable name: l

(E741)

pyphare/pyphare/core/box.py

207-207: Ambiguous variable name: l

(E741)

tests/simulator/__init__.py

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

Replace with None; initialize within function

(B006)

tests/amr/data/field/refine/test_refine_field.py

106-106: Do not assert False (python -O removes these calls), raise AssertionError()

Replace assert False

(B011)

pyphare/pyphare/pharesee/geometry.py

161-161: Ambiguous variable name: l

(E741)


164-164: Ambiguous variable name: l

(E741)


167-167: Ambiguous variable name: l

(E741)


188-188: Ambiguous variable name: l

(E741)

tests/simulator/test_initialization.py

394-394: Function definition does not bind loop variable select

(B023)


396-396: Function definition does not bind loop variable patch

(B023)


396-396: Function definition does not bind loop variable nbrGhosts

(B023)


397-397: Function definition does not bind loop variable select

(B023)


582-582: Loop control variable pi not used within loop body

Rename unused pi to _pi

(B007)


586-586: Yoda condition detected

Rewrite as ppc == H

(SIM300)


664-664: Local variable out is assigned to but never used

Remove assignment to unused variable out

(F841)

tests/simulator/test_advance.py

89-89: Ambiguous variable name: l

(E741)

pyphare/pyphare/pharesee/hierarchy.py

508-508: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


520-520: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


621-621: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


651-651: Comparison to None should be cond is None

Replace with cond is None

(E711)


726-726: Loop control variable time not used within loop body

Rename unused time to _time

(B007)


727-727: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


746-746: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


760-760: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


790-790: Loop control variable t not used within loop body

Rename unused t to _t

(B007)


960-960: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)


1034-1034: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)


1099-1099: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


1281-1281: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


1395-1395: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1459-1459: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1468-1468: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1505-1505: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1538-1538: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1544-1544: Loop control variable ipatch not used within loop body

(B007)


1561-1561: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1765-1765: Loop control variable time not used within loop body

Rename unused time to _time

(B007)


1766-1766: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


1767-1767: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


1820-1820: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

GitHub Check: CodeQL
pyphare/pyphare/pharesee/hierarchy.py

[warning] 121-121: Overwriting attribute in super-class or sub-class
Assignment overwrites attribute layout, which was previously defined in superclass PatchData.


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


[warning] 634-634: Comparison of identical values
Comparison of identical values; use cmath.isnan() if testing for not-a-number.


[notice] 651-651: Testing equality to None
Testing for None should use the 'is' operator.


[failure] 677-677: Potentially uninitialized local variable
Local variable 'slice_dim' may be used before it is initialized.


[failure] 678-678: Potentially uninitialized local variable
Local variable 'cst_dim' may be used before it is initialized.


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


[notice] 1069-1069: Module is imported with 'import' and 'import from'
Module 'copy' is imported with both 'import' and 'import from'.


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

Additional comments not posted (74)
src/amr/data/particles/refine/split.hpp (1)

6-6: Verify the necessity of including split_3d.hpp.

Ensure that the inclusion of split_3d.hpp is necessary for this file and consistent with the project's architecture. If split_3d.hpp is only used in specific implementations, consider including it in those files instead to avoid unnecessary dependencies.

tests/diagnostic/job_3d.py.in (1)

3-14: Add error handling and logging for external library calls.

The script makes several calls to external libraries (ph.Simulation, makeBasicModel, ElectronModel, dump_all_diags) without any error handling. Consider adding try-except blocks to catch and handle potential exceptions, and include logging for better debugging and validation.

+ import logging
+ 
+ logging.basicConfig(level=logging.INFO)
+ 
try:
    ph.Simulation(**basicSimulatorArgs(dim = 3, interp = 1, **simInput))
    model = makeBasicModel()
    ElectronModel(closure="isothermal",Te = 0.12)
    dump_all_diags(model.populations)
+ except Exception as e:
+     logging.error(f"An error occurred: {e}")
tests/diagnostic/test-diagnostics_3d.cpp (2)

9-27: Refactor repeated code in test cases.

Each test case function (fluid_test, particles_test, electromag_test, allFromPython_test) is called with the same parameters. Consider refactoring this to reduce code duplication.

+ void run_test(auto test_func) {
+     test_func(TypeParam{job_file}, out_dir);
+ }

-    fluid_test(TypeParam{job_file}, out_dir);
-    particles_test(TypeParam{job_file}, out_dir);
-    electromag_test(TypeParam{job_file}, out_dir);
-    allFromPython_test(TypeParam{job_file}, out_dir);
+    run_test(fluid_test);
+    run_test(particles_test);
+    run_test(electromag_test);
+    run_test(allFromPython_test);

9-9: Address unused static variables.

The static variables gtest_Simulator3dTest_fluid_registered_, gtest_Simulator3dTest_particles_registered_, gtest_Simulator3dTest_electromag_registered_, and gtest_Simulator3dTest_allFromPython_registered_ are never read. Consider removing them to clean up the code.

Also applies to: 14-14, 19-19, 24-24

tests/amr/data/particles/refine/test_split.cpp (1)

25-25: Expanded test coverage with additional Splitter configuration.

The addition of Splitter<3, 1, 27> to the Splitters type alias broadens the test coverage, which is a positive enhancement for ensuring the robustness of the Splitter functionality.

tests/amr/data/particles/refine/input/input_3d_ratio_2.txt (2)

10-11: Update dimensionality to match 3D simulation.

The dimension is set to 1, but the rest of the configuration is for a 3D simulation. This should be updated to match the dimensionality of the simulation.


46-51: Remove unused sections in the configuration file.

The TileClustering and GriddingAlgorithm sections are empty and should be removed if they are not required, to avoid confusion.

tools/python3/git.py (2)

22-23: Remove unused variable e.

The variable e is assigned but never used. It should be removed to clean up the code.

Tools
Ruff

22-22: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


29-29: Fix undefined name delete_branch.

The function delete_branch is called but not defined. Ensure that this function is defined or imported before use.

Tools
Ruff

29-29: Undefined name delete_branch

(F821)

tests/simulator/initialize/CMakeLists.txt (1)

21-24: Conditional 3D Test Initialization Approved.

The addition of 3D initialization tests under the highResourceTests condition is a well-structured enhancement, ensuring that resource-intensive tests are only executed when appropriate.

tests/simulator/advance/CMakeLists.txt (1)

21-24: Conditional 3D Test Advancement Approved.

The inclusion of 3D advancement tests under the highResourceTests condition is a prudent addition, allowing for enhanced testing without impacting default behavior.

tests/diagnostic/CMakeLists.txt (1)

37-41: 3D Diagnostic Test and Configuration Approved.

The addition of the 3D diagnostic test and the configuration of its input file are well-aligned with the project's goals to support 3D diagnostics, enhancing the overall testing framework.

tests/simulator/initialize/test_fields_init_3d.py (1)

40-40: Investigate high RAM usage in test_density_decreases_as_1overSqrtN.

The comment indicates that this test uses too much RAM. Consider optimizing the test or isolating it to prevent resource exhaustion.

Verification successful

Investigate high RAM usage in test_density_decreases_as_1overSqrtN.

The function _test_density_decreases_as_1overSqrtN in tests/simulator/test_initialization.py initializes large arrays and performs operations that could lead to high RAM usage. Consider the following:

  • Large Arrays: The nbr_particles array can include up to 10,000 elements, which might be resource-intensive.
  • Complex Operations: The self.getHierarchy method is called within a loop, potentially exacerbating memory use.

To mitigate RAM usage, consider optimizing the size of nbr_particles or the operations within the loop. Reducing the number of particles or simplifying the operations could help manage resource consumption.

  • File: tests/simulator/test_initialization.py
  • Function: _test_density_decreases_as_1overSqrtN
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Investigate RAM usage for the `test_density_decreases_as_1overSqrtN` test.

# Test: Search for the function and analyze its resource usage.
rg --type python -A 5 $'def test_density_decreases_as_1overSqrtN'

Length of output: 97


Script:

#!/bin/bash
# Description: Investigate RAM usage for the `test_density_decreases_as_1overSqrtN` test.

# Test: Search for the function and analyze its resource usage.
rg -A 5 'def test_density_decreases_as_1overSqrtN'

Length of output: 1682


Script:

#!/bin/bash
# Description: Locate the implementation of `_test_density_decreases_as_1overSqrtN` to analyze potential RAM usage issues.

# Search for the definition of `_test_density_decreases_as_1overSqrtN`.
rg 'def _test_density_decreases_as_1overSqrtN'

Length of output: 134


Script:

#!/bin/bash
# Description: Retrieve the implementation of `_test_density_decreases_as_1overSqrtN` to analyze RAM usage.

# Extract the function definition and its body for inspection.
rg -A 20 'def _test_density_decreases_as_1overSqrtN' tests/simulator/test_initialization.py

Length of output: 883

res/amr/splitting.yml (1)

103-141: Configuration additions for 3D simulations look good.

The new dimension_3 section follows the existing pattern and adds necessary configurations for 3D simulations.

.github/workflows/cmake_macos.yml (1)

90-90: Verify the impact of the new CMake flag.

The addition of -DPHARE_SIMULATORS=2 may affect simulator functionality. Ensure this aligns with the intended build configurations and does not introduce unexpected behavior.

Verification successful

Impact of the CMake Flag -DPHARE_SIMULATORS=2

The addition of -DPHARE_SIMULATORS=2 changes the default behavior from 3 to 2. This affects conditional logic in the code, enabling configurations for PHARE_SIMULATORS > 1 but not for PHARE_SIMULATORS > 2. Ensure this aligns with the intended simulator configurations.

  • src/core/utilities/meta/meta_utilities.hpp: Conditional logic based on PHARE_SIMULATORS.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of the new CMake flag `-DPHARE_SIMULATORS=2`.

# Test: Search for references to `PHARE_SIMULATORS` in the codebase.
rg --type cpp --type cmake -A 2 $'PHARE_SIMULATORS'

Length of output: 830

tests/simulator/initialize/test_particles_init_2d.py (1)

26-26: Class renaming aligns with 2D testing scenarios.

The change from Initialization1DTest to Initialization2DTest is appropriate for 2D particle initialization tests. Verify that the test logic corresponds to 2D scenarios.

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

5-5: Good use of fixed-width integer type for enumeration.

The change to use std::uint16_t for the QtyCentering enumeration enhances type safety and ensures a consistent size across platforms. The inclusion of <cstdint> is appropriate and necessary.

Also applies to: 18-18

tests/simulator/per_test.hpp (1)

111-117: Well-structured parameterized test suite for 3D simulations.

The introduction of Simulator3dTest and the use of TYPED_TEST_SUITE with parameterized types improve the flexibility and coverage of tests for 3D simulations. This approach enhances the robustness of the testing framework.

tests/simulator/initialize/test_particles_init_3d.py (2)

77-94: Consider removing or documenting commented-out test cases.

The commented-out test cases should be removed or documented to clarify their purpose. This helps maintain code clarity and cleanliness.


1-98: Comprehensive test setup for 3D particle initialization.

The Initialization3DTest class effectively covers various scenarios for initializing particles in a 3D context. The use of ddt for data-driven tests is a good practice.

tests/simulator/advance/test_fields_advance_3d.py (1)

79-103: Address commented-out code.

The commented-out test cases should either be removed or uncommented with an explanation for their necessity. Keeping commented-out code without justification can lead to maintenance issues and confusion.

src/amr/data/particles/refine/splitter.hpp (2)

Line range hint 70-87: Refactor the complex loop for better readability.

The loop body is still quite large and complex. Consider breaking it down into smaller, more manageable functions to improve readability and maintainability.


118-123: Ensure consistency in struct naming and usage.

The renaming of dispatcher structs to pattern structs should reflect their intended functionality. Verify that all instances of these structs are updated across the codebase to prevent inconsistencies.

Verification successful

Struct renaming is consistent across the codebase.

The new struct names (BlackPattern, PurplePattern, BrownPattern, PinkPattern) have been successfully updated and are consistently used throughout the codebase. No instances of the old struct names were found, indicating a thorough update.

  • Files verified include split_3d.hpp, split_1d.hpp, split_2d.hpp, and splitter.hpp.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all instances of renamed structs are updated across the codebase.

# Test: Search for the old and new struct names. Expect: Only occurrences of the new names.
rg --type cpp $'BlackDispatcher|PurpleDispatcher|BrownDispatcher|PinkDispatcher'

Length of output: 81


Script:

#!/bin/bash
# Description: Verify the presence and usage of the new struct names across the codebase.

# Test: Search for the new struct names. Expect: Occurrences of the new names.
rg --type cpp $'BlackPattern|PurplePattern|BrownPattern|PinkPattern'

Length of output: 6538

res/cmake/options.cmake (1)

73-75: Ensure mutual exclusivity between lowResourceTests and highResourceTests.

The new highResourceTests option is useful for enabling heavy tests in CI. However, ensure that lowResourceTests and highResourceTests cannot be enabled simultaneously to avoid conflicting configurations.

src/core/utilities/meta/meta_utilities.hpp (2)

9-11: Duplicate Comment: Ensure the default value for PHARE_SIMULATORS is well-documented.

The existing comment already addresses the need for documentation of the default value.


81-98: Duplicate Comment: Address the TODO comments.

The existing comment already highlights the need to address the TODOs in the possibleSimulators function.

tests/functional/harris/harris_3d.py (4)

1-12: Imports and Environment Setup Look Good

The imports are well-organized, and the environment variable for scope timing is set correctly.


62-62: Duplicate Comment: Rename the ambiguous variable 'l' to 'length' for clarity.

The existing comment already addresses the need to rename the variable for clarity.

Tools
Ruff

62-62: Ambiguous variable name: l

(E741)


138-188: Plotting and Main Function Logic Look Good

The plotting logic is clear, and the main function correctly initiates the simulation and plotting.


37-53: Verify Simulation Configuration

The simulation configuration appears comprehensive. Ensure that the parameters align with the intended simulation goals and requirements.

tests/simulator/refined_particle_nbr.py (3)

33-37: Duplicate Comments: Add exception handling and clarify calculations.

The existing comments already address the need for exception handling in tearDown and clarity in _less_per_dim.

Also applies to: 44-47


78-117: Duplicate Comment: Clarify the calculations in the _do_dim method.

The existing comment already highlights the need for additional comments to explain the logic.


117-135: Duplicate Comment: Add comments to explain logic in test_values method.

The existing comment already suggests adding comments to improve clarity.

src/amr/data/particles/refine/split_1d.hpp (10)

Line range hint 20-32:
Consistent renaming to PinkPattern.

The renaming from PinkDispatcher to PinkPattern is consistent and improves clarity. Ensure that all instances in the codebase have been updated.


Line range hint 71-86:
Verify SplitPattern_1_2_2_Dispatcher update.

The alias SplitPattern_1_2_2_Dispatcher now uses PinkPattern. Ensure all related instances are updated.

Verification successful

All instances of SplitPattern_1_2_2_Dispatcher are updated. The alias is only used within src/amr/data/particles/refine/split_1d.hpp and no other files reference it. The update to use PinkPattern is localized.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all usages of `SplitPattern_1_2_2_Dispatcher` are updated.

# Test: Search for occurrences of `SplitPattern_1_2_2_Dispatcher`.
rg --type cpp 'SplitPattern_1_2_2_Dispatcher'

Length of output: 462


Line range hint 127-142:
Ensure consistency in SplitPattern_1_3_2_Dispatcher.

The alias now uses PinkPattern. Verify consistency in definitions and usages.

Verification successful

Consistency Verified for SplitPattern_1_3_2_Dispatcher

The alias SplitPattern_1_3_2_Dispatcher using PinkPattern<DimConst<1>> is defined and used consistently within the same file. No inconsistencies were found.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistency in definitions and usages of `SplitPattern_1_3_2_Dispatcher`.

# Test: Search for occurrences of `SplitPattern_1_3_2_Dispatcher`.
rg --type cpp 'SplitPattern_1_3_2_Dispatcher'

Length of output: 250


Line range hint 109-124:
Verify SplitPattern_1_2_4_Dispatcher update.

Ensure that all instances of SplitPattern_1_2_4_Dispatcher using PinkPattern are updated.

Verification successful

Verification Complete: SplitPattern_1_2_4_Dispatcher Update Confirmed

The SplitPattern_1_2_4_Dispatcher is only used in src/amr/data/particles/refine/split_1d.hpp, and there are no other occurrences in the codebase. No further updates are needed.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all usages of `SplitPattern_1_2_4_Dispatcher` are updated.

# Test: Search for occurrences of `SplitPattern_1_2_4_Dispatcher`.
rg --type cpp 'SplitPattern_1_2_4_Dispatcher'

Length of output: 332


Line range hint 53-68:
Ensure BlackPattern consistency.

The alias now uses BlackPattern instead of BlackDispatcher. Verify that BlackPattern is defined and used consistently.

Verification successful

BlackPattern Consistency Verified

The BlackPattern is correctly defined and consistently used in the codebase. The struct is defined in src/amr/data/particles/refine/splitter.hpp and used appropriately in src/amr/data/particles/refine/split_1d.hpp. No issues found.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that `BlackPattern` is defined and used consistently.

# Test: Search for the definition and usage of `BlackPattern`.
rg --type cpp 'BlackPattern<DimConst<1>>'

Length of output: 526


Script:

#!/bin/bash
# Description: Search for the definition of `BlackPattern`.

# Test: Search for the definition of `BlackPattern`.
rg --type cpp 'struct BlackPattern' -A 5

Length of output: 520


Line range hint 165-180:
Ensure consistency in SplitPattern_1_3_4_Dispatcher.

The alias now uses PinkPattern. Verify consistency in definitions and usages.

Verification successful

Consistency Verified for SplitPattern_1_3_4_Dispatcher

The alias SplitPattern_1_3_4_Dispatcher is correctly defined using PinkPattern<DimConst<1>> and is consistently used in the file. No discrepancies were found.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistency in definitions and usages of `SplitPattern_1_3_4_Dispatcher`.

# Test: Search for occurrences of `SplitPattern_1_3_4_Dispatcher`.
rg --type cpp 'SplitPattern_1_3_4_Dispatcher'

Length of output: 332


Script:

#!/bin/bash
# Extract the definition or aliasing of `SplitPattern_1_3_4_Dispatcher` to verify its consistency.
rg --type cpp --context 5 'using SplitPattern_1_3_4_Dispatcher' src/amr/data/particles/refine/split_1d.hpp

Length of output: 538


Line range hint 90-105:
Ensure consistency in SplitPattern_1_2_3_Dispatcher.

The alias now uses BlackPattern and PinkPattern. Verify consistency in definitions and usages.

Verification successful

Verification Successful: Consistency in SplitPattern_1_2_3_Dispatcher

The usage of BlackPattern and PinkPattern within SplitPattern_1_2_3_Dispatcher is consistent with their definitions and intended usage. Both patterns are correctly utilized in the context of a PatternDispatcher. No issues found.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistency in definitions and usages of `SplitPattern_1_2_3_Dispatcher`.

# Test: Search for occurrences of `SplitPattern_1_2_3_Dispatcher`.
rg --type cpp 'SplitPattern_1_2_3_Dispatcher'

Length of output: 322


Script:

#!/bin/bash
# Description: Search for definitions of `BlackPattern` and `PinkPattern` to verify their consistency in usage.

# Search for `BlackPattern` definition.
rg --type cpp 'BlackPattern'

# Search for `PinkPattern` definition.
rg --type cpp 'PinkPattern'

Length of output: 5990


Line range hint 34-49:
Verify dispatcher alias updates.

The dispatcher aliases have been updated to use PinkPattern. Verify that all usages of these aliases in the codebase are consistent with the new naming.

Verification successful

Dispatcher alias updates are consistent. All occurrences of the dispatcher aliases SplitPattern_1_1_2_Dispatcher, SplitPattern_1_2_2_Dispatcher, and SplitPattern_1_3_2_Dispatcher are confined to the file src/amr/data/particles/refine/split_1d.hpp and have been updated to use PinkPattern<DimConst<1>>. There are no inconsistencies in their usage across the codebase.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all usages of dispatcher aliases are updated to `PinkPattern`.

# Test: Search for occurrences of dispatcher aliases using `PinkPattern`.
rg --type cpp 'PatternDispatcher<PinkPattern<DimConst<1>>>'

Length of output: 439


Script:

#!/bin/bash
# Description: Check for occurrences of dispatcher aliases in the codebase to verify consistent usage.

# Search for occurrences of `SplitPattern_1_1_2_Dispatcher`.
rg --type cpp 'SplitPattern_1_1_2_Dispatcher'

# Search for occurrences of `SplitPattern_1_2_2_Dispatcher`.
rg --type cpp 'SplitPattern_1_2_2_Dispatcher'

# Search for occurrences of `SplitPattern_1_3_2_Dispatcher`.
rg --type cpp 'SplitPattern_1_3_2_Dispatcher'

Length of output: 1070


Line range hint 146-161:
Verify SplitPattern_1_3_3_Dispatcher update.

Ensure that all instances of SplitPattern_1_3_3_Dispatcher using BlackPattern and PinkPattern are updated.


Line range hint 184-199:
Verify SplitPattern_1_3_5_Dispatcher update.

Ensure that all instances of SplitPattern_1_3_5_Dispatcher using BlackPattern and PinkPattern are updated.

Verification successful

Verification Complete: No Additional Updates Required for SplitPattern_1_3_5_Dispatcher

The update to SplitPattern_1_3_5_Dispatcher in src/amr/data/particles/refine/split_1d.hpp appears to be isolated to this file. There are no other instances in the codebase where this dispatcher is used with BlackPattern or PinkPattern that require updates.

  • The usage of BlackPattern and PinkPattern with dispatchers is consistent across multiple files, but no additional updates are necessary for SplitPattern_1_3_5_Dispatcher.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all usages of `SplitPattern_1_3_5_Dispatcher` are updated.

# Test: Search for occurrences of `SplitPattern_1_3_5_Dispatcher`.
rg --type cpp 'SplitPattern_1_3_5_Dispatcher'

Length of output: 345


Script:

#!/bin/bash
# Description: Search for occurrences of `SplitPattern_1_3_5_Dispatcher` in combination with `BlackPattern` and `PinkPattern`.

# Test: Search for occurrences of `BlackPattern` and `PinkPattern` in relation to `SplitPattern_1_3_5_Dispatcher`.
rg --type cpp 'SplitPattern_1_3_5_Dispatcher.*BlackPattern'
rg --type cpp 'SplitPattern_1_3_5_Dispatcher.*PinkPattern'

Length of output: 122


Script:

#!/bin/bash
# Description: Search for occurrences of `BlackPattern` and `PinkPattern` in the codebase.

# Test: Search for occurrences of `BlackPattern`.
rg --type cpp 'BlackPattern'

# Test: Search for occurrences of `PinkPattern`.
rg --type cpp 'PinkPattern'

Length of output: 5990

pyphare/pyphare/core/box.py (3)

65-67: Enhance __sub__ method for lists/tuples.

The method now supports subtracting a list or tuple of Box instances. Ensure that this functionality is thoroughly tested.


185-198: Add unit tests for remove_all.

The remove_all function provides robust logic for removing multiple boxes. Consider adding unit tests to cover various scenarios, such as partial overlaps or complete containment.


209-223: Introduce DataSelector class.

The DataSelector class enhances data manipulation using Box instances. Ensure that its functionality is well-documented and tested.

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

151-169: Add documentation for as_points function.

The as_points function generates a vector of points based on the box's dimensions. Consider adding a comment to explain its purpose and usage.

res/cmake/funcs.cmake (2)

28-28: Ensure test conditions are correct.

The condition if (test AND ${PHARE_EXEC_LEVEL_MIN} GREATER 0) assumes that PHARE_EXEC_LEVEL_MIN is defined and greater than 0 for tests to run. Verify that this logic aligns with the intended behavior.

Verification successful

Test condition logic is correct.

The condition if (test AND ${PHARE_EXEC_LEVEL_MIN} GREATER 0) aligns with the intended behavior, as PHARE_EXEC_LEVEL_MIN is defined to default to 1, ensuring it is greater than 0 for tests to run. No issues found.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the definition and usage of `PHARE_EXEC_LEVEL_MIN` in the codebase.

# Test: Search for the definition of `PHARE_EXEC_LEVEL_MIN`. Expect: It should be defined and used correctly.
rg --type cmake $'PHARE_EXEC_LEVEL_MIN'

Length of output: 1779


59-67: Ensure exclusion logic is correct.

In add_no_mpi_phare_test, verify that the exclusion logic for MPI tests aligns with the intended build configuration. The use of EXCLUDE_FROM_ALL and EXCLUDE_FROM_DEFAULT_BUILD should be consistent with project requirements.

Verification successful

Exclusion Logic Verified

The exclusion logic using EXCLUDE_FROM_ALL and EXCLUDE_FROM_DEFAULT_BUILD is consistently applied in both res/cmake/funcs.cmake and res/cmake/def.cmake. The logic aligns with the intended build configuration, ensuring that MPI tests are excluded from the default build when appropriate.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the exclusion logic for MPI tests in the build configuration.

# Test: Search for the usage of `EXCLUDE_FROM_ALL` and `EXCLUDE_FROM_DEFAULT_BUILD`. Expect: Consistent usage across the project.
rg --type cmake $'EXCLUDE_FROM_ALL|EXCLUDE_FROM_DEFAULT_BUILD'

Length of output: 301


Script:

#!/bin/bash
# Extract lines around the usage of EXCLUDE_FROM_ALL and EXCLUDE_FROM_DEFAULT_BUILD in res/cmake/def.cmake
rg --type cmake --context 5 'EXCLUDE_FROM_ALL|EXCLUDE_FROM_DEFAULT_BUILD' res/cmake/def.cmake

Length of output: 622

src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (3)

34-38: Template parameter renaming improves clarity.

The renaming of the template parameter from dimension to dim enhances clarity and consistency. Ensure that this change is propagated throughout the codebase.


52-59: Ensure correct handling of field centering.

The operator now uses dim instead of dimension. Verify that the logic for handling different field centerings is accurate and that all necessary cases are covered.

Verification successful

Field Centering Logic Appears Comprehensive

The handling of field centering in magnetic_field_coarsener.hpp involves multiple conditional checks for different centering types. The logic seems to cover various cases, such as primal and dual centerings, across different directions. Ensure that these conditions align with the intended functionality and that any additional cases are considered if necessary.

  • File: src/amr/data/field/coarsening/magnetic_field_coarsener.hpp
  • Lines: Several lines involving centering_, such as checks for primal and dual centerings.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the handling of field centering logic in the codebase.

# Test: Search for the usage of `centering_` and ensure all cases are handled. Expect: Comprehensive handling of all centering types.
rg --type cpp $'centering_'

Length of output: 1968


78-90: Ensure 3D coarsening logic is implemented.

The 3D coarsening method is currently implemented using nested arrays of lambda functions. Ensure that this logic is correct and consider simplifying it for better readability.

Verification successful

3D Coarsening Logic is Implemented, Review for Simplification

The 3D coarsening logic is implemented in the MagneticFieldCoarsener class. However, the use of lambda functions and nested arrays may add unnecessary complexity. Consider reviewing and simplifying this logic for better readability.

  • src/amr/data/field/coarsening/magnetic_field_coarsener.hpp: Contains the implementation of the coarsen function for 3D.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of 3D coarsening logic.

# Test: Search for the implementation details of 3D coarsening logic. Expect: Correct and complete implementation.
rg --type cpp $'coarsen<3>'

Length of output: 28


Script:

#!/bin/bash
# Description: Search for the implementation of the 3D coarsening logic by looking for the coarsen function definition and usage.
ast-grep --lang cpp --pattern 'coarsen<3, $_>($_, $_, $_, $_) { $$$ }'

Length of output: 72


Script:

#!/bin/bash
# Description: Search for the coarsen function definitions and related logic in the codebase.
rg --type cpp 'coarsen' -A 10

Length of output: 52778

src/amr/data/particles/refine/split_3d.hpp (4)

71-86: Good use of lambda functions for clarity and reuse in LimePattern.

The lambda function addSquare effectively encapsulates repeated logic, enhancing code clarity and reusability.


95-114: Good use of lambda functions for clarity and reuse in WhitePattern.

The lambda functions addSquare and addSquares effectively encapsulate repeated logic, enhancing code clarity and reusability.


123-293: Initialization of delta and weight arrays in Splitter is consistent and correct.

The use of static constexpr arrays for delta and weight ensures consistency and correctness across different Splitter configurations.


48-62: Use structured bindings for clarity in PurplePattern.

The loop in PurplePattern constructor can be optimized for clarity by using structured bindings.

-        for (std::size_t i = 0; i < 2; i++)
-        {
-            std::size_t offset = i * 4;
-            float sign         = i % 2 ? -1 : 1;
-            auto mode          = delta * sign;
-            Super::deltas_[0 + offset] = {mode, mode, mode};
-            Super::deltas_[1 + offset] = {mode, mode, -mode};
-            Super::deltas_[2 + offset] = {mode, -mode, mode};
-            Super::deltas_[3 + offset] = {mode, -mode, -mode};
-        }
+        for (auto [index, sign] : {std::pair{0, 1.0f}, std::pair{4, -1.0f}})
+        {
+            float mode = delta * sign;
+            Super::deltas_[index]     = {mode, mode, mode};
+            Super::deltas_[index + 1] = {mode, mode, -mode};
+            Super::deltas_[index + 2] = {mode, -mode, mode};
+            Super::deltas_[index + 3] = {mode, -mode, -mode};
+        }

Likely invalid or redundant comment.

pyphare/pyphare/pharesee/run/utils.py (1)

362-362: Enhance flexibility in dimensionality handling.

The change from [nbrGhosts] * 2 to [nbrGhosts] * ndim allows the function to handle different dimensionalities dynamically. This is a positive change.

Ensure that all usages of _get_rank accommodate this change in dimensionality handling.

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

63-74: Support for 3D domain boxes added.

The changes correctly extend the domain_border_ghost_boxes function to handle 3D domain boxes by adding "front" and "back" sides.

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

127-128: Add NO_DISCARD to zstart and zend methods for consistency.

The methods zstart and zend in the MaskedView class are missing the NO_DISCARD attribute, which is used in other similar methods in this class. This attribute is important to prevent ignoring the return value of these methods.


390-427: Consider performance optimizations in fill3D.

The fill3D method correctly fills the 3D array using nested loops. However, consider exploring opportunities to optimize the performance by reducing the depth of nested loops, if feasible.


473-474: Assertions for z-dimension enhance robustness.

The expanded assertions for the z-dimension in the operator overload for MaskedView improve robustness by preventing out-of-bounds errors.

Also applies to: 533-534

tests/core/numerics/interpolator/test_main.cpp (2)

776-783: Uncomment and verify the test case DepositCorrectlyTheirWeight_3d.

The test case is crucial for validating 3D interpolation correctness but is currently commented out. This needs to be active to ensure the functionality is tested properly.


788-788: Remove unused static variable gtest_testInterpolator_ACollectionOfParticles_3d.

The static variable is defined but never used. Removing it will clean up the code.

tests/simulator/test_initialization.py (6)

254-256: Use f-strings for string formatting.

Python's f-string provides a more readable, concise, and less error-prone way of formatting strings compared to the format method.

- "test_B_is_as_provided_by_user : dim  {} interp_order : {}".format(dim, interp_order)
+ f"test_B_is_as_provided_by_user : dim  {dim} interp_order : {interp_order}"

355-357: Addition of ppc parameter enhances flexibility.

The inclusion of the ppc parameter allows for dynamic configuration of particle counts, improving the function's flexibility.


417-420: Use of ndim enhances clarity.

Replacing dim with ndim improves clarity regarding the number of dimensions being processed in the function.


Line range hint 483-561: Ensure plotting logic is conditional.

The method _test_density_decreases_as_1overSqrtN includes plotting logic. Ensure that this code is conditional or wrapped in a method to avoid executing during automated test runs where graphical output is not feasible.


566-586: Rename unused loop variable pi to _pi.

The loop control variable pi is not used within the loop body. Rename it to _pi to indicate that it's intentionally unused.

- for pi, patch in enumerate(datahier.level(0).patches):
+ for _pi, patch in enumerate(datahier.level(0).patches):
Tools
Ruff

582-582: Loop control variable pi not used within loop body

Rename unused pi to _pi

(B007)


586-586: Yoda condition detected

Rewrite as ppc == H

(SIM300)


661-664: Remove unused variable out.

The variable out is defined but not used. Remove the unused variable to avoid confusion.

- out = "phare_outputs"
Tools
Ruff

664-664: Local variable out is assigned to but never used

Remove assignment to unused variable out

(F841)

tests/simulator/test_advance.py (2)

370-372: LGTM! Verify the usage of the cells parameter.

The addition of the cells parameter is a good enhancement for flexibility. Ensure that this parameter is used correctly in all relevant parts of the codebase.


Line range hint 399-420: LGTM! Verify the usage of the cells parameter.

The addition of the cells parameter is a beneficial enhancement for flexibility. Ensure that this parameter is used correctly in all relevant parts of the codebase.

pyphare/pyphare/pharesee/hierarchy.py (3)

651-651: Testing for None should use the 'is' operator.

Testing for None should use the 'is' operator for better readability and correctness.

- if qty == None:
+ if qty is None:

Likely invalid or redundant comment.

Tools
Ruff

651-651: Comparison to None should be cond is None

Replace with cond is None

(E711)

GitHub Check: CodeQL

[notice] 651-651: Testing equality to None
Testing for None should use the 'is' operator.


121-121: Overwriting attribute in super-class or sub-class.

Assignment overwrites attribute layout, which was previously defined in superclass PatchData. This might lead to unexpected behavior.

Tools
GitHub Check: CodeQL

[warning] 121-121: Overwriting attribute in super-class or sub-class
Assignment overwrites attribute layout, which was previously defined in superclass PatchData.


1026-1056: Review the plot3d method for potential data handling issues.

The plot3d method manipulates data dimensions and properties directly, which may lead to unintended side effects or data corruption. Specifically:

  • Modifying pdat._x, pdat._y, and pdat.dataset directly affects the object state outside the local scope of this function, potentially impacting other parts of the application relying on these properties.
  • The method reduces the dimensionality of the data to 2D and delegates to plot2d. Ensure that this dimensional reduction is valid across all use cases.

Consider encapsulating these transformations in a method within the relevant data classes to avoid side effects.

Tools
Ruff

1034-1034: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)

@@ -67,6 +67,7 @@ class PatternDispatcher
using FineParticle = decltype(particles[0]); // may be a reference

core::apply(patterns, [&](auto const& pattern) {
auto weight = static_cast<Weight_t>(pattern.weight_);
Copy link

Choose a reason for hiding this comment

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

Remove unused local variable weight.

The variable weight is declared but not used, leading to unnecessary clutter.

- auto weight = static_cast<Weight_t>(pattern.weight_);
Committable suggestion

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

Suggested change
auto weight = static_cast<Weight_t>(pattern.weight_);

Comment on lines +395 to +446
TEST(MaskedView3d, maskOps3)
{
constexpr std::size_t dim = 3;
constexpr std::uint32_t size0 = 10;
constexpr std::uint32_t sizeCu = size0 * size0 * size0;
using Mask = PHARE::core::NdArrayMask;

auto sum = [](auto const& array) { return std::accumulate(array.begin(), array.end(), 0); };

{
NdArrayVector<dim> array{size0, size0, size0};
EXPECT_EQ(sum(array), 0);
std::fill(array.begin(), array.end(), 1);
EXPECT_EQ(sum(array), sizeCu);
}

{
NdArrayVector<dim> array{size0, size0, size0};
EXPECT_EQ(std::accumulate(array.begin(), array.end(), 0), 0);
array[Mask{0}] = 1;
EXPECT_EQ(std::accumulate(array.begin(), array.end(), 0), 488);

// outter cells of a 10**3 cube =
// (10 * 10 * 2) + (10 * 8 * 2) + (8 * 8 * 2);
// or
// (8 * 8 * 6) + (10 * 4) + (8 * 8);
// = 488
}

std::uint32_t ten = 10;
PHARE::core::NdArrayVector<3> array(ten, ten, ten);

array[Mask{0}] = 1;
EXPECT_EQ(sum(array), 488);
array[Mask{1}] >> array[Mask{0}];
EXPECT_EQ(sum(array), 0);

array[Mask{2}] = 1;
EXPECT_EQ(sum(array), 152);
array[Mask{1}] = 1;
EXPECT_EQ(sum(array), 448);
array[Mask{1}] = 0;
EXPECT_EQ(sum(array), 152);

array[Mask{2}] >> array[Mask{1}];
EXPECT_EQ(sum(array), 448);
array[Mask{2}] = 0;
EXPECT_EQ(sum(array), 296);

EXPECT_EQ(Mask{1}.nCells(array), 296);
EXPECT_EQ(Mask{2}.nCells(array), 152);
}
Copy link

Choose a reason for hiding this comment

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

LGTM! But remove unused variable and enhance comments.

The test logic is comprehensive and covers various scenarios effectively.

However, the variable dim is unused and should be removed to clean up the code.

Additionally, the comments explaining the expected results of the operations could be expanded for clarity.

-    constexpr std::size_t dim      = 3;
-        // outter cells of a 10**3 cube =
-        // (10 * 10 * 2) + (10 * 8 * 2) + (8 * 8 * 2);
-        // or
-        // (8 * 8 * 6) + (10 * 4) + (8 * 8);
-        // = 488
+        // Outer cells of a 10x10x10 cube are calculated as:
+        // (10 * 10 * 2) + (10 * 8 * 2) + (8 * 8 * 2) = 488
+        // Alternatively:
+        // (8 * 8 * 6) + (10 * 4) + (8 * 8) = 488

Comment on lines +25 to +40
constexpr PinkPattern(float const weight, float const delta)
: Super{weight}
{
constexpr float zero = 0;

for (std::size_t i = 0; i < 2; i++)
{
std::size_t offset = i * 3;
float sign = i % 2 ? -1 : 1;
auto mode = delta * sign;

Super::deltas_[0 + offset] = {mode, zero, zero};
Super::deltas_[1 + offset] = {zero, zero, mode};
Super::deltas_[2 + offset] = {zero, mode, zero};
}
}
Copy link

Choose a reason for hiding this comment

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

Optimize initialization of deltas_ in PinkPattern.

The constructor initializes deltas_ in a loop. Consider using a more efficient method or simplifying the logic for clarity and performance.

-    constexpr PinkPattern(float const weight, float const delta)
-        : Super{weight}
-    {
-        constexpr float zero = 0;
-        for (std::size_t i = 0; i < 2; i++)
-        {
-            std::size_t offset = i * 3;
-            float sign         = i % 2 ? -1 : 1;
-            auto mode          = delta * sign;
-            Super::deltas_[0 + offset] = {mode, zero, zero};
-            Super::deltas_[1 + offset] = {zero, zero, mode};
-            Super::deltas_[2 + offset] = {zero, mode, zero};
-        }
-    }
+    constexpr PinkPattern(float const weight, float const delta)
+        : Super{weight}, deltas_{
+            {delta, 0, 0}, {0, 0, delta}, {0, delta, 0},
+            {-delta, 0, 0}, {0, 0, -delta}, {0, -delta, 0}
+        } {}
Committable suggestion

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

Suggested change
constexpr PinkPattern(float const weight, float const delta)
: Super{weight}
{
constexpr float zero = 0;
for (std::size_t i = 0; i < 2; i++)
{
std::size_t offset = i * 3;
float sign = i % 2 ? -1 : 1;
auto mode = delta * sign;
Super::deltas_[0 + offset] = {mode, zero, zero};
Super::deltas_[1 + offset] = {zero, zero, mode};
Super::deltas_[2 + offset] = {zero, mode, zero};
}
}
constexpr PinkPattern(float const weight, float const delta)
: Super{weight}, deltas_{
{delta, 0, 0}, {0, 0, delta}, {0, delta, 0},
{-delta, 0, 0}, {0, 0, -delta}, {0, -delta, 0}
} {}

Comment on lines +37 to +42
function(set_exe_paths_ binary)
set_property(TEST ${binary} PROPERTY ENVIRONMENT "PYTHONPATH=${PHARE_PYTHONPATH}")
# ASAN detects leaks by default, even in system/third party libraries
set_property(TEST ${binary} APPEND PROPERTY ENVIRONMENT "ASAN_OPTIONS=detect_leaks=0")
set_property(TEST ${binary} APPEND PROPERTY ENVIRONMENT PHARE_SKIP_CLI=1 )
endfunction(set_exe_paths_)
Copy link

Choose a reason for hiding this comment

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

Avoid hardcoding environment variables.

Consider parameterizing environment variables like PYTHONPATH and ASAN_OPTIONS to make the function more flexible and adaptable to different environments.

-    set_property(TEST ${binary}        PROPERTY ENVIRONMENT "PYTHONPATH=${PHARE_PYTHONPATH}")
-    set_property(TEST ${binary} APPEND PROPERTY ENVIRONMENT "ASAN_OPTIONS=detect_leaks=0")
+    set_property(TEST ${binary}        PROPERTY ENVIRONMENT "PYTHONPATH=$ENV{PHARE_PYTHONPATH}")
+    set_property(TEST ${binary} APPEND PROPERTY ENVIRONMENT "ASAN_OPTIONS=$ENV{ASAN_OPTIONS:-detect_leaks=0}")
Committable suggestion

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

Suggested change
function(set_exe_paths_ binary)
set_property(TEST ${binary} PROPERTY ENVIRONMENT "PYTHONPATH=${PHARE_PYTHONPATH}")
# ASAN detects leaks by default, even in system/third party libraries
set_property(TEST ${binary} APPEND PROPERTY ENVIRONMENT "ASAN_OPTIONS=detect_leaks=0")
set_property(TEST ${binary} APPEND PROPERTY ENVIRONMENT PHARE_SKIP_CLI=1 )
endfunction(set_exe_paths_)
function(set_exe_paths_ binary)
set_property(TEST ${binary} PROPERTY ENVIRONMENT "PYTHONPATH=$ENV{PHARE_PYTHONPATH}")
set_property(TEST ${binary} APPEND PROPERTY ENVIRONMENT "ASAN_OPTIONS=$ENV{ASAN_OPTIONS:-detect_leaks=0}")
set_property(TEST ${binary} APPEND PROPERTY ENVIRONMENT PHARE_SKIP_CLI=1 )
endfunction(set_exe_paths_)

Comment on lines +62 to +75
auto fine_start_index(core::Point<int, dim> const coarseIndex) const
{
core::Point<int, dim> fineStartIndex;
fineStartIndex[dirX] = coarseIndex[dirX] * this->ratio_;

if constexpr (dimension > 1)
if constexpr (dim > 1)
{
fineStartIndex[dirY] = coarseIndex[dirY] * this->ratio_;
if constexpr (dimension > 2)
if constexpr (dim > 2)
{
fineStartIndex[dirZ] = coarseIndex[dirZ] * this->ratio_;
}
}
return AMRToLocal(fineStartIndex, sourceBox_);
}
Copy link

Choose a reason for hiding this comment

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

Optimize fine_start_index calculation.

The method fine_start_index calculates indices based on the ratio_. Consider optimizing this calculation to reduce redundancy and improve performance.

auto fine_start_index(core::Point<int, dim> const coarseIndex) const {
    core::Point<int, dim> fineStartIndex = coarseIndex * this->ratio_;
    return AMRToLocal(fineStartIndex, sourceBox_);
}

h5_time_grp = data_file[h5_time_grp_key][time]
patch_levels = {}

for plvl_key in h5_time_grp.keys():
Copy link

Choose a reason for hiding this comment

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

Use key in dict instead of key in dict.keys().

This is a more Pythonic way to check for the existence of a key in a dictionary.

- for plvl_key in h5_time_grp.keys():
+ for plvl_key in h5_time_grp:
Committable suggestion

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

Suggested change
for plvl_key in h5_time_grp.keys():
for plvl_key in h5_time_grp:
Tools
Ruff

1459-1459: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

Comment on lines +106 to +107
assert False # fix

Copy link

Choose a reason for hiding this comment

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

Replace assert statement with NotImplementedError.

Using assert False as a placeholder for not implemented functionality is not recommended. It's better to use NotImplementedError to clearly indicate that the functionality is not yet implemented.

-        assert False # fix
+        raise NotImplementedError("3D field refinement is not yet implemented.")
Committable suggestion

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

Suggested change
assert False # fix
raise NotImplementedError("3D field refinement is not yet implemented.")
Tools
Ruff

106-106: Do not assert False (python -O removes these calls), raise AssertionError()

Replace assert False

(B011)

if not isinstance(linestyles, dict):
linestyles = dict(zip(usr_lvls, linestyles))

for lvl_nbr, lvl in self.levels(time).items():
Copy link

Choose a reason for hiding this comment

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

Remove unused loop variable.

The variable lvl is not used within the loop. You can replace it with _ to indicate it's intentionally unused.

- for lvl_nbr, lvl in self.levels(time).items():
+ for lvl_nbr, _ in self.levels(time).items():
Committable suggestion

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

Suggested change
for lvl_nbr, lvl in self.levels(time).items():
for lvl_nbr, _ in self.levels(time).items():
Tools
Ruff

960-960: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)

Comment on lines 677 to 678
slice_coord = domain_coords(patch, qty)[slice_dim]
cst_coord = domain_coords(patch, qty)[cst_dim]
Copy link

Choose a reason for hiding this comment

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

Potentially uninitialized local variables.

Local variables slice_dim and cst_dim may be used before they are initialized. Ensure they are properly initialized before use.

- if "x" in kwargs:
-     c = kwargs["x"]
-     slice_dim = 1
-     cst_dim = 0
- else:
-     c = kwargs["y"]
-     slice_dim = 0
-     cst_dim = 1
+ if "x" in kwargs:
+     c = kwargs["x"]
+     slice_dim = 1
+     cst_dim = 0
+ elif "y" in kwargs:
+     c = kwargs["y"]
+     slice_dim = 0
+     cst_dim = 1
+ else:
+     raise ValueError("Need to specify either 'x' or 'y' cut coordinate.")
Committable suggestion

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

Suggested change
slice_coord = domain_coords(patch, qty)[slice_dim]
cst_coord = domain_coords(patch, qty)[cst_dim]
if "x" in kwargs:
c = kwargs["x"]
slice_dim = 1
cst_dim = 0
elif "y" in kwargs:
c = kwargs["y"]
slice_dim = 0
cst_dim = 1
else:
raise ValueError("Need to specify either 'x' or 'y' cut coordinate.")
slice_coord = domain_coords(patch, qty)[slice_dim]
cst_coord = domain_coords(patch, qty)[cst_dim]
Tools
GitHub Check: CodeQL

[failure] 677-677: Potentially uninitialized local variable
Local variable 'slice_dim' may be used before it is initialized.


[failure] 678-678: Potentially uninitialized local variable
Local variable 'cst_dim' may be used before it is initialized.

Comment on lines +380 to +414
return sorted_patches

dbu = domain_box.upper

if dim == 2:
sides = {
"bottom": Box([0, 0], [domain_box.upper[0], 0]),
"top": Box(
[0, domain_box.upper[1]], [domain_box.upper[0], domain_box.upper[1]]
),
"left": Box([0, 0], [0, domain_box.upper[1]]),
"right": Box(
[domain_box.upper[0], 0], [domain_box.upper[0], domain_box.upper[1]]
),
"left": Box([0, 0], [0, dbu[1]]),
"right": Box([dbu[0], 0], [dbu[0], dbu[1]]),
"bottom": Box([0, 0], [dbu[0], 0]),
"top": Box([0, dbu[1]], [dbu[0], dbu[1]]),
}

shifts = periodicity_shifts(domain_box)
else:
sides = {
"left": Box([0, 0, 0], [0, dbu[1], dbu[2]]),
"right": Box([dbu[0], 0, 0], [dbu[0], dbu[1], dbu[2]]),
"bottom": Box([0, 0, 0], [dbu[0], 0, dbu[2]]),
"top": Box([0, dbu[1], 0], [dbu[0], dbu[1], dbu[2]]),
"front": Box([0, 0, 0], [dbu[0], dbu[1], 0]),
"back": Box([0, 0, dbu[2]], [dbu[0], dbu[1], dbu[2]]),
}

def borders_per(box):
return "".join(
[key for key, side in sides.items() if box * side is not None]
)
shifts = periodicity_shifts(domain_box)

for patch in patches:
in_sides = borders_per(boxm.grow(patch.box, n_ghosts))
def borders_per(box):
return "".join([key for key, side in sides.items() if box * side is not None])

if in_sides in shifts: # in_sides might be empty, so no borders
for shift in shifts[in_sides]:
patch_copy = copy(patch)
shift_patch(patch_copy, shift)
sorted_patches.append(patch_copy)
for patch in patches:
in_sides = "".join(sorted(borders_per(boxm.grow(patch.box, n_ghosts))))

if dim == 3:
raise ValueError("not yet implemented")
if in_sides in shifts: # in_sides might be empty, so no borders
for shift in shifts[in_sides]:
patch_copy = copy(patch)
shift_patch(patch_copy, shift)
sorted_patches.append(patch_copy)
Copy link

Choose a reason for hiding this comment

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

Avoid mutable default argument in get_periodic_list.

Using mutable default arguments can lead to unexpected behavior. Consider initializing within the function.

- def get_periodic_list(patches, domain_box, n_ghosts=[]):
+ def get_periodic_list(patches, domain_box, n_ghosts=None):
+     if n_ghosts is None:
+         n_ghosts = []
Committable suggestion

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

Suggested change
return sorted_patches
dbu = domain_box.upper
if dim == 2:
sides = {
"bottom": Box([0, 0], [domain_box.upper[0], 0]),
"top": Box(
[0, domain_box.upper[1]], [domain_box.upper[0], domain_box.upper[1]]
),
"left": Box([0, 0], [0, domain_box.upper[1]]),
"right": Box(
[domain_box.upper[0], 0], [domain_box.upper[0], domain_box.upper[1]]
),
"left": Box([0, 0], [0, dbu[1]]),
"right": Box([dbu[0], 0], [dbu[0], dbu[1]]),
"bottom": Box([0, 0], [dbu[0], 0]),
"top": Box([0, dbu[1]], [dbu[0], dbu[1]]),
}
shifts = periodicity_shifts(domain_box)
else:
sides = {
"left": Box([0, 0, 0], [0, dbu[1], dbu[2]]),
"right": Box([dbu[0], 0, 0], [dbu[0], dbu[1], dbu[2]]),
"bottom": Box([0, 0, 0], [dbu[0], 0, dbu[2]]),
"top": Box([0, dbu[1], 0], [dbu[0], dbu[1], dbu[2]]),
"front": Box([0, 0, 0], [dbu[0], dbu[1], 0]),
"back": Box([0, 0, dbu[2]], [dbu[0], dbu[1], dbu[2]]),
}
def borders_per(box):
return "".join(
[key for key, side in sides.items() if box * side is not None]
)
shifts = periodicity_shifts(domain_box)
for patch in patches:
in_sides = borders_per(boxm.grow(patch.box, n_ghosts))
def borders_per(box):
return "".join([key for key, side in sides.items() if box * side is not None])
if in_sides in shifts: # in_sides might be empty, so no borders
for shift in shifts[in_sides]:
patch_copy = copy(patch)
shift_patch(patch_copy, shift)
sorted_patches.append(patch_copy)
for patch in patches:
in_sides = "".join(sorted(borders_per(boxm.grow(patch.box, n_ghosts))))
if dim == 3:
raise ValueError("not yet implemented")
if in_sides in shifts: # in_sides might be empty, so no borders
for shift in shifts[in_sides]:
patch_copy = copy(patch)
shift_patch(patch_copy, shift)
sorted_patches.append(patch_copy)
def get_periodic_list(patches, domain_box, n_ghosts=None):
if n_ghosts is None:
n_ghosts = []
return sorted_patches
dbu = domain_box.upper
if dim == 2:
sides = {
"left": Box([0, 0], [0, dbu[1]]),
"right": Box([dbu[0], 0], [dbu[0], dbu[1]]),
"bottom": Box([0, 0], [dbu[0], 0]),
"top": Box([0, dbu[1]], [dbu[0], dbu[1]]),
}
else:
sides = {
"left": Box([0, 0, 0], [0, dbu[1], dbu[2]]),
"right": Box([dbu[0], 0, 0], [dbu[0], dbu[1], dbu[2]]),
"bottom": Box([0, 0, 0], [dbu[0], 0, dbu[2]]),
"top": Box([0, dbu[1], 0], [dbu[0], dbu[1], dbu[2]]),
"front": Box([0, 0, 0], [dbu[0], dbu[1], 0]),
"back": Box([0, 0, dbu[2]], [dbu[0], dbu[1], dbu[2]]),
}
shifts = periodicity_shifts(domain_box)
def borders_per(box):
return "".join([key for key, side in sides.items() if box * side is not None])
for patch in patches:
in_sides = "".join(sorted(borders_per(boxm.grow(patch.box, n_ghosts))))
if in_sides in shifts: # in_sides might be empty, so no borders
for shift in shifts[in_sides]:
patch_copy = copy(patch)
shift_patch(patch_copy, shift)
sorted_patches.append(patch_copy)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 26

🧹 Outside diff range and nitpick comments (71)
tests/diagnostic/job_3d.py.in (1)

8-10: Consider adding directory validation.

The script uses "overwrite" mode which could potentially delete existing test results. Consider adding directory validation and a more robust cleanup strategy.

+import os
+import shutil
+
 out = "phare_outputs/diags_3d/"
+if os.path.exists(out):
+    shutil.rmtree(out)
+os.makedirs(out, exist_ok=True)
+
 simInput = {"diag_options": {"format": "phareh5", "options": {"dir": out, "mode" : "overwrite"}}}
tests/diagnostic/test-diagnostics_3d.cpp (2)

9-27: Consider improving test organization and coverage.

The test cases follow a consistent pattern but could be enhanced:

  1. Consider using a parameterized test to reduce code duplication
  2. Add test cases for coarsening as mentioned in the PR description

Here's a suggested refactor:

+ struct TestParams {
+     const char* name;
+     void (*test_func)(TypeParam, const std::string&);
+ };

+ std::vector<TestParams> const tests = {
+     {"fluid", fluid_test},
+     {"particles", particles_test},
+     {"electromag", electromag_test},
+     {"allFromPython", allFromPython_test}
+ };

+ for (const auto& test : tests) {
+     TYPED_TEST(Simulator3dTest, test.name) {
+         test.test_func(TypeParam{job_file}, out_dir);
+     }
+ }
🧰 Tools
🪛 cppcheck

[performance] 24-24: Function parameter 'path' should be passed by const reference.

(passedByValue)


9-27: Add missing coarsening tests.

The PR description mentions "some coarsening tests missing". Consider adding test cases to verify the coarsening behavior in 3D simulations.

Would you like me to help create a template for the coarsening tests?

🧰 Tools
🪛 cppcheck

[performance] 24-24: Function parameter 'path' should be passed by const reference.

(passedByValue)

tests/amr/data/particles/refine/test_split.cpp (1)

Line range hint 25-31: Consider expanding test coverage for 3D splitting patterns

The current test suite only verifies constexpr initialization. Given that this PR introduces 3D support and mentions missing coarsening tests, consider adding test cases for:

  • Different 3D splitting patterns (Pink, Purple, Lime, White) mentioned in split_3d.hpp
  • Edge cases specific to 3D particle refinement
  • Validation of particle positions after splitting

Would you like me to help create additional test cases for these scenarios?

tools/python3/git.py (3)

13-16: Improve robustness and maintainability.

Consider these enhancements:

  1. Add parameter validation
  2. Add error handling
  3. Define the format string as a constant
+SHORT_FORMAT = '--pretty=format:"%h%x09%an%x09%ad%x09%s"'
+
 def log(N=10, use_short=False):
     # https://git-scm.com/docs/pretty-formats
-    short = '--pretty=format:"%h%x09%an%x09%ad%x09%s"' if use_short else ""
-    return decode_bytes(run(f"git log -{N} {short}").stdout)
+    if not isinstance(N, int) or N < 1:
+        raise ValueError("N must be a positive integer")
+    try:
+        short = SHORT_FORMAT if use_short else ""
+        return decode_bytes(run(f"git log -{N} {short}", check=True).stdout)
+    except subprocess.CalledProcessError:
+        raise RuntimeError("Failed to get git log. Are you in a git repository?")

19-24: Optimize branch existence check and add input validation.

The current implementation can be improved by:

  1. Using a more efficient git command
  2. Adding input validation
  3. Removing the unused exception variable (as noted by static analysis)
 def branch_exists(branch):
+    if not branch or not isinstance(branch, str):
+        raise ValueError("Branch name must be a non-empty string")
     try:
-        run(f"git show-branch {branch}", check=True)
-    except subprocess.CalledProcessError as e:
+        # Using rev-parse is more efficient than show-branch
+        run(f"git rev-parse --verify {branch}", check=True)
+    except subprocess.CalledProcessError:
         return False  # exit failure means branch does not exist
     return True
🧰 Tools
🪛 Ruff

22-22: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


1-3: Consider architectural improvements for better maintainability.

Suggestions for improving the overall architecture:

  1. Define a custom exception class for git operations
  2. Create a context manager for git operations
  3. Add logging for better debugging
class GitError(Exception):
    """Base exception for git operations."""
    pass

class GitContext:
    """Context manager for git operations."""
    def __enter__(self):
        if not self._is_git_repo():
            raise GitError("Not a git repository")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        pass

    def _is_git_repo(self):
        try:
            run("git rev-parse --git-dir", check=True)
            return True
        except subprocess.CalledProcessError:
            return False
tests/simulator/initialize/CMakeLists.txt (1)

21-21: Consider documenting resource requirements.

Since these tests are gated behind highResourceTests, it would be helpful to document the expected resource requirements (memory, CPU, execution time) in a comment.

Add a comment like:

+    # 3D tests require significant resources:
+    # - Estimated memory: X GB
+    # - Approximate runtime: Y minutes
     if(highResourceTests)
tests/simulator/advance/CMakeLists.txt (1)

21-24: LGTM! Consider adding resource requirement documentation.

The conditional block for 3D tests is well-structured and follows the existing pattern. However, since these are marked as "quite intensive", it would be helpful to document the expected resource requirements (memory, CPU, time) in a comment.

     if(highResourceTests) # off by default as it's quite intensive
+        # Resource requirements:
+        # - Memory: ~XGB per MPI process
+        # - Expected runtime: ~X minutes
         phare_mpi_python3_exec(9 ${PHARE_MPI_PROCS} advance-3d-fields     test_fields_advance_3d.py     ${CMAKE_CURRENT_BINARY_DIR})
         phare_mpi_python3_exec(9 ${PHARE_MPI_PROCS} advance-3d-particles  test_particles_advance_3d.py  ${CMAKE_CURRENT_BINARY_DIR})
tests/simulator/initialize/test_fields_init_2d.py (1)

Line range hint 1-47: Consider enhancing test coverage for edge cases.

Given that this is part of a larger 3D implementation, consider adding tests for:

  1. Boundary conditions specific to 2D-3D transitions
  2. Edge cases where 2D and 3D implementations might diverge
  3. Performance characteristics with varying particle densities

This will help ensure robust behavior as the codebase evolves to support both 2D and 3D scenarios.

tests/simulator/advance/test_particles_advance_3d.py (1)

16-19: Consider adding type hints to global constants

Adding type hints would improve code maintainability and IDE support.

-ndim = 3
-interp_orders = [1, 2, 3]
-ppc = 5
+ndim: int = 3
+interp_orders: list[int] = [1, 2, 3]
+ppc: int = 5
tools/python3/cmake.py (3)

8-20: Enhance function documentation with parameter descriptions.

The docstring currently only mentions optimization flags but should document all parameters and their purpose. This would improve code maintainability and usability.

Add comprehensive parameter descriptions:

 def make_config_str(
     path, samrai_dir=None, cxx_flags=None, use_ninja=False, use_ccache=False, extra=""
 ):
     """
+    Constructs a CMake configuration command string.
+    
+    Args:
+        path: Path to the CMake project directory
+        samrai_dir: Optional path to SAMRAI installation
+        cxx_flags: Optional C++ compiler flags
+        use_ninja: Whether to use Ninja build system
+        use_ccache: Whether to enable ccache
+        extra: Additional CMake options
+    
+    Returns:
+        str: Formatted CMake configuration command
+
     FULL UNPORTABLE OPTIMIZATIONS = cxx_flags="-O3 -march=native -mtune=native"
     """

30-31: Add error handling for build system commands.

The function should handle potential failures of the build commands and provide meaningful error messages.

 def build(use_ninja=False, threads=1):
-    run("ninja" if use_ninja else f"make -j{threads}", capture_output=False)
+    try:
+        run("ninja" if use_ninja else f"make -j{threads}", capture_output=False)
+    except Exception as e:
+        raise RuntimeError(f"Build failed: {str(e)}")

34-37: Make test list parsing more robust.

The current implementation assumes a specific format of ctest output. Consider making the parsing more resilient to format changes.

 def list_tests():
     proc = run("ctest -N", capture_output=True)
     out = decode_bytes(proc.stdout)
-    return [line.split(" ")[-1] for line in out.splitlines()[1:-2]]
+    tests = []
+    for line in out.splitlines():
+        if line.startswith("  Test"):
+            test_name = line.strip().split(" ")[-1]
+            if test_name:
+                tests.append(test_name)
+    return tests
tests/simulator/initialize/test_fields_init_3d.py (4)

1-4: Enhance the docstring with more details.

While the docstring explains the isolation purpose, it would be helpful to include:

  • What specific field initialization tests are performed
  • Why these tests need to be isolated
  • Any prerequisites or dependencies
 """
   This file exists independently from test_initialization.py to isolate dimension
     test cases and allow each to be overridden in some way if required.
+
+  This test suite validates 3D field initialization including:
+  - Magnetic field (B) initialization
+  - Bulk velocity initialization
+  - Density initialization and scaling
+
+  These tests are isolated to:
+  - Allow independent execution of resource-intensive 3D tests
+  - Enable specific overrides for 3D edge cases
+  - Maintain separate test configurations for 3D scenarios
 """

14-14: Document the reason for Agg backend.

Add a more descriptive comment explaining why the Agg backend is necessary.

-matplotlib.use("Agg")  # for systems without GUI
+matplotlib.use("Agg")  # Use non-interactive backend for CI/CD environments and systems without GUI

16-18: Document test parameters and consider moving to a configuration class.

The test parameters lack documentation and could benefit from being centralized in a configuration class.

+# Test configuration parameters
+# ndim: Number of dimensions for the simulation
+# interp_orders: Interpolation orders to test (1st, 2nd, and 3rd order)
+# ppc: Particles per cell
+# cells: Number of cells in each dimension
 ndim = 3
 interp_orders = [1, 2, 3]
 ppc, cells = 10, 20

Consider creating a TestConfig class:

class TestConfig:
    """Configuration for 3D field initialization tests."""
    ndim = 3
    interp_orders = [1, 2, 3]
    ppc = 10  # particles per cell
    cells = 20  # cells per dimension

24-26: Add docstrings to test methods.

Each test method should document:

  • Purpose of the test
  • Expected behavior
  • Test parameters

Example for the first test:

 @data(*interp_orders)
 def test_B_is_as_provided_by_user(self, interp_order):
+    """
+    Validate that the magnetic field is initialized correctly in 3D.
+    
+    Args:
+        interp_order: Interpolation order for the field initialization
+    """
     print(f"\n{self._testMethodName}_{ndim}d")
     self._test_B_is_as_provided_by_user(ndim, interp_order, ppc=ppc, cells=cells)

Also applies to: 29-33, 36-38, 41-45

tests/simulator/initialize/test_particles_init_2d.py (1)

Based on the search results from both scripts, I can now generate the final response:

Particle coarsening tests are indeed missing

The codebase only contains tests for field coarsening (test_field_coarsening_via_subcycles) but lacks specific tests for particle coarsening behavior. The existing coarsening tests are focused on:

  • Field data coarsening in AMR
  • Linear and weighted coarsening for fields
  • Field coarsening via subcycles in 1D, 2D, and 3D

This confirms the original review comment's observation about missing coarsening tests for particles.

🔗 Analysis chain

Line range hint 26-107: Consider adding missing coarsening tests

While the test coverage for particle initialization, ghost particles, and domain particles is comprehensive, the PR objectives mention "some coarsening tests missing". Consider adding specific test cases to verify particle coarsening behavior in 2D contexts.

Let's check for existing coarsening tests in the codebase:

Would you like help implementing the missing coarsening test cases?


Let me check the content of these coarsening tests to understand if they cover particle coarsening or just field coarsening.


Let me check specifically for particle coarsening tests in the simulator directory:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for coarsening-related tests
rg -l 'test.*coarsen|coarsening' tests/

Length of output: 495


Script:

#!/bin/bash
# Check content of coarsening tests
rg -C 3 'test.*coarsen|coarsening.*particle' tests/

Length of output: 6541


Script:

#!/bin/bash
# Search for particle-related tests in simulator directory
rg -C 3 'particle.*coarsen|coarsen.*particle' tests/simulator/

Length of output: 64

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

18-18: Consider documenting the rationale for explicit size specification.

The change to use std::uint16_t as the underlying type for QtyCentering provides a guaranteed 16-bit size, which is good for ABI stability and memory layout predictability. However, it would be helpful to document why this specific size was chosen, especially in the context of 3D simulations.

Add a brief comment explaining the rationale:

+    // Using uint16_t to ensure consistent memory layout across platforms
     enum class QtyCentering : std::uint16_t { primal = 0, dual = 1 };
tests/simulator/initialize/test_particles_init_3d.py (2)

16-18: Consider adding documentation for magic numbers

While the constants are well-defined, consider adding comments to explain:

  • Why these specific interpolation orders (1,2,3) were chosen
  • What ppc=10 represents (particles per cell)
  • Why cells=30 was chosen as the default

21-22: Consider a more descriptive function name

The function per_interp could be renamed to something more descriptive like generate_test_cases_per_interpolation_order to better reflect its purpose.

tests/simulator/advance/test_fields_advance_3d.py (2)

16-18: Document the global constants

Add docstrings or comments explaining the purpose and units of these constants:

  • What does ppc=10 represent (particles per cell)?
  • Why was cells=30 chosen as the default grid size?
  • What's the significance of the chosen interpolation orders?

21-22: Add docstring to helper function

Add a docstring explaining:

  • Purpose of the function
  • Parameter dic: what type/format is expected
  • Return value: list of tuples with interpolation order and dictionary
res/cmake/options.cmake (1)

73-75: Improve the option description to clarify its relationship with lowResourceTests.

The description should clarify that this option is mutually exclusive with lowResourceTests and specify what kinds of tests it enables.

-option(highResourceTests "Enable heavy tests for CI (3d/etc" OFF)
+option(highResourceTests "Enable resource-intensive tests (3D/coarsening) - mutually exclusive with lowResourceTests" OFF)
src/core/utilities/meta/meta_utilities.hpp (1)

81-98: Document the rationale for particle number choices per dimension.

The particle numbers vary across dimensions:

  • 1D: 2-5 particles
  • 2D: 4-25 particles
  • 3D: 6-12 particles

Consider adding documentation explaining these choices and their impact on simulation accuracy vs. performance.

tests/simulator/refined_particle_nbr.py (2)

44-47: Improve variable naming and add documentation

The variable name dim2 doesn't clearly convey its purpose as the border cell adjustment for 2D cases.

-        dim2 = refined_particle_nbr * ((cellNbr[0] * 2 + (cellNbr[1] * 2)))
+        # Calculate border cell adjustment for 2D: accounts for particles that may leave through
+        # the x and y boundaries (2 cells per dimension)
+        border_adjustment_2d = refined_particle_nbr * ((cellNbr[0] * 2 + (cellNbr[1] * 2)))
         if dim == 2:
-            return dim2
-        return dim2 * (cellNbr[2] * 2)
+            return border_adjustment_2d
+        return border_adjustment_2d * (cellNbr[2] * 2)  # Extend to 3D boundaries

117-135: Enhance error handling for YAML configuration access

While the implementation is thorough, consider adding error handling for missing or malformed YAML configuration entries.

 def _check_deltas_and_weights(self, dim, interp, refined_particle_nbr):
+    try:
         yaml_dim = self.yaml_root["dimension_" + str(dim)]
         yaml_interp = yaml_dim["interp_" + str(interp)]
         yaml_n_particles = yaml_interp["N_particles_" + str(refined_particle_nbr)]
 
         yaml_delta = [float(s) for s in str(yaml_n_particles["delta"]).split(" ")]
         yaml_weight = [float(s) for s in str(yaml_n_particles["weight"]).split(" ")]
+    except KeyError as e:
+        raise ValueError(f"Missing configuration for dim={dim}, interp={interp}, "
+                        f"refined_particle_nbr={refined_particle_nbr}: {e}")
+    except ValueError as e:
+        raise ValueError(f"Invalid delta/weight values in configuration: {e}")
src/amr/data/particles/refine/split_1d.hpp (3)

Line range hint 134-134: Fix incorrect dispatcher name in constructor.

The constructor uses SplitPattern_1_2_2_Dispatcher but should use SplitPattern_1_3_2_Dispatcher to match the type alias.

-    : SplitPattern_1_2_2_Dispatcher{{weight[0], delta[0]}}
+    : SplitPattern_1_3_2_Dispatcher{{weight[0], delta[0]}}

184-185: Maintain consistent formatting.

The pattern dispatcher type definition spans multiple lines with inconsistent indentation compared to other similar definitions in the file.

-    = PatternDispatcher<BlackPattern<DimConst<1>>, PinkPattern<DimConst<1>>,
-                        PinkPattern<DimConst<1>>>;
+    = PatternDispatcher<BlackPattern<DimConst<1>>, PinkPattern<DimConst<1>>, PinkPattern<DimConst<1>>>;

Line range hint 1-199: Consider adding documentation for weight and delta values.

While the code references the wiki for splitting patterns, it would be beneficial to add inline documentation explaining the mathematical significance of the specific weight and delta values chosen for each splitter configuration. This would help maintainers understand the impact of modifying these values.

src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (2)

62-75: Simplify fine_start_index implementation using fold expressions.

The nested if constexpr blocks can be replaced with a more concise implementation using C++17 fold expressions.

Consider this alternative implementation:

- auto fine_start_index(core::Point<int, dim> const coarseIndex) const
- {
-     core::Point<int, dim> fineStartIndex;
-     fineStartIndex[dirX] = coarseIndex[dirX] * this->ratio_;
-     if constexpr (dim > 1)
-     {
-         fineStartIndex[dirY] = coarseIndex[dirY] * this->ratio_;
-         if constexpr (dim > 2)
-         {
-             fineStartIndex[dirZ] = coarseIndex[dirZ] * this->ratio_;
-         }
-     }
-     return AMRToLocal(fineStartIndex, sourceBox_);
- }
+ auto fine_start_index(core::Point<int, dim> const coarseIndex) const
+ {
+     core::Point<int, dim> fineStartIndex;
+     [&]<std::size_t... I>(std::index_sequence<I...>) {
+         ((fineStartIndex[I] = coarseIndex[I] * ratio_), ...);
+     }(std::make_index_sequence<dim>{});
+     return AMRToLocal(fineStartIndex, sourceBox_);
+ }

177-177: Improve error message for invalid magnetic field configuration.

The current error message "no magnetic field should end up here" is not descriptive enough. Consider including the actual centering configuration that caused the error.

- throw std::runtime_error("no magnetic field should end up here");
+ throw std::runtime_error("Invalid magnetic field centering configuration: " +
+     std::to_string(static_cast<int>(centering_[0])) + "," +
+     std::to_string(static_cast<int>(centering_[1])) + "," +
+     std::to_string(static_cast<int>(centering_[2])));
tests/core/data/ndarray/test_main.cpp (2)

411-422: Enhance comments for better readability while maintaining correct logic.

The test logic for mask operations is correct, but the comments explaining the outer cells calculation could be more readable.

Consider reformatting the comments for better clarity:

-        // outter cells of a 10**3 cube =
-        // (10 * 10 * 2) + (10 * 8 * 2) + (8 * 8 * 2);
-        // or
-        // (8 * 8 * 6) + (10 * 4) + (8 * 8);
-        // = 488
+        // Calculation of outer cells in a 10x10x10 cube:
+        // Method 1: Face centers + Face edges + Corner cells
+        //   = (10×10×2) + (10×8×2) + (8×8×2) = 488
+        // Method 2: Face cells + Edge corrections + Corner corrections
+        //   = (8×8×6) + (10×4) + (8×8) = 488

424-446: LGTM! Consider using existing constant.

The test coverage for complex mask operations is comprehensive and well-structured.

Consider using the existing size0 constant instead of creating a new ten variable:

-    std::uint32_t ten = 10;
-    PHARE::core::NdArrayVector<3> array(ten, ten, ten);
+    PHARE::core::NdArrayVector<3> array(size0, size0, size0);
src/amr/data/particles/refine/split_2d.hpp (4)

Line range hint 37-55: Consider adding type constraints to template parameter

The Delta template parameter in BrownPattern constructor should be constrained to ensure it supports array-like access and has the correct size.

-    template<typename Delta>
+    template<typename Delta>
+        requires requires(Delta d) {
+            { d[0] } -> std::convertible_to<float>;
+            { d[1] } -> std::convertible_to<float>;
+        }
     constexpr BrownPattern(float const weight, Delta const& delta)

Line range hint 230-244: Improve readability with consistent brace style and named constants

The constructor initialization uses inconsistent brace style. Consider using named constants for magic numbers in delta array.

     constexpr Splitter()
-        : SplitPattern_2_2_16_Dispatcher({weight[0], delta[0]}, {weight[1], delta},
-                                         {weight[2], delta[1]})
+        : SplitPattern_2_2_16_Dispatcher{{weight[0], delta[0]},
+                                        {weight[1], delta},
+                                        {weight[2], delta[1]}}
     {
     }

-    static constexpr std::array<float, 2> delta  = {.5, 1.5};
+    static constexpr float INNER_DELTA = 0.5f;
+    static constexpr float OUTER_DELTA = 1.5f;
+    static constexpr std::array<float, 2> delta = {INNER_DELTA, OUTER_DELTA};

324-327: Improve readability of multi-line type alias

The type alias has inconsistent indentation. Consider using line continuation character for better readability.

-using SplitPattern_2_3_25_Dispatcher
-    = PatternDispatcher<BlackPattern<DimConst<2>>, PinkPattern<DimConst<2>>,
-                        PurplePattern<DimConst<2>>, PinkPattern<DimConst<2>>,
-                        BrownPattern<DimConst<2>>, PurplePattern<DimConst<2>>>;
+using SplitPattern_2_3_25_Dispatcher = \
+    PatternDispatcher<BlackPattern<DimConst<2>>, \
+                     PinkPattern<DimConst<2>>, \
+                     PurplePattern<DimConst<2>>, \
+                     PinkPattern<DimConst<2>>, \
+                     BrownPattern<DimConst<2>>, \
+                     PurplePattern<DimConst<2>>>;

Tests needed for 2D splitting patterns

Based on the test files analysis, there are significant gaps in test coverage for 2D splitting patterns:

  1. Current tests only cover basic initialization (test_split.cpp) with a single test case for 2D: Splitter<2, 1, 8>
  2. Missing test coverage for:
    • Different interpolation orders (1,2,3) in 2D
    • Various particle counts (4,5,8,9,16,25) defined in split_2d.hpp
    • Pattern-specific tests (Purple, Brown, Pink patterns)
    • Edge cases and boundary conditions
🔗 Analysis chain

Line range hint 1-349: Verify test coverage for splitting patterns

Given the PR objectives mention "some coarsening tests missing", please ensure adequate test coverage exists for these 2D splitting patterns, especially for edge cases with different interpolation orders and particle counts.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for test files covering these splitting patterns
echo "Searching for test files..."
rg -l "split_2d" test/
# Look for specific pattern tests
echo "Checking pattern test coverage..."
rg -A 5 "TEST.*(?:Purple|Brown|Pink)Pattern.*2" test/

Length of output: 312


Script:

#!/bin/bash
# Let's first find the test directory structure
fd -t d "test"

# Then search for test files related to particle splitting or refinement
fd -e cpp -e hpp "test|particle|split|refine"

# Look for specific pattern tests in any directory
rg -l "TEST.*(?:Purple|Brown|Pink)Pattern"

# Search for any test files that might include split_2d.hpp
rg -l "split_2d\.hpp"

Length of output: 6557


Script:

#!/bin/bash
# Let's check the content of the test files that might cover split patterns
echo "Checking test_split.cpp content:"
cat tests/amr/data/particles/refine/test_split.cpp

echo -e "\nChecking test_particle_data_refine.cpp content:"
cat tests/amr/data/particles/refine/test_particle_data_refine.cpp

# Also check if there are any tests in the split.hpp that includes split_2d.hpp
echo -e "\nChecking split.hpp content for tests:"
cat src/amr/data/particles/refine/split.hpp

Length of output: 2415


Script:

#!/bin/bash
# Let's check the test strategy file mentioned in the output
echo "Checking test strategy file:"
cat tests/amr/data/particles/refine/test_particledata_refine_basic_hierarchy.hpp

# Also check for any test files in the test directory that might contain "particle" and "refine"
echo -e "\nSearching for additional particle refinement test files:"
rg -l "TEST.*particle.*refine" tests/

# Look for any test cases using the 2D splitter specifically
echo -e "\nSearching for 2D splitter usage in tests:"
rg "Splitter<.*2.*>" tests/

Length of output: 8605

pyphare/pyphare/pharesee/run/utils.py (2)

Line range hint 362-368: Implement missing 3D case in _get_rank

While the shape calculation now supports 3D, the function still raises "Not Implemented yet" for 3D cases. This is inconsistent with the PR's objective of adding 3D support.

Consider implementing the 3D case similar to the 2D implementation:

    elif ndim == 2:
        data = np.zeros(shape) + int(patch_id.strip("p").split("#")[0])
        return ({"name": "rank", "data": data, "centering": [centering] * 2},)
+   elif ndim == 3:
+       data = np.zeros(shape) + int(patch_id.strip("p").split("#")[0])
+       return ({"name": "rank", "data": data, "centering": [centering] * 3},)
    else:
        raise RuntimeError("Not Implemented yet")

Would you like me to help implement this change or create an issue to track this task?


Line range hint 1-507: Consider documenting the 3D implementation roadmap

The file contains multiple functions that need 3D support (e.g., _divB2D, slicing functions). While the PR description indicates this is intentional ("only some 3d split patterns"), consider:

  1. Adding TODO comments to mark pending 3D implementations
  2. Creating tracking issues for each function requiring 3D support
  3. Documenting the order and dependencies of the 3D implementation phases

This will help track progress and maintain clarity about which functionality is available for each dimensionality.

tests/simulator/test_initialization.py (2)

333-341: Reduce code duplication in meshgrid operations.

The meshgrid flattening operations are repeated three times with similar patterns. Consider extracting this into a helper function to improve maintainability.

+def flatten_meshgrid(*args):
+    return [a.flatten() for a in np.meshgrid(*args, indexing="ij")]
+
 if dim == 3:
     zbx = bx_pd.z[:]
     zby = by_pd.z[:]
     zbz = bz_pd.z[:]
-    xbx, ybx, zbx = [
-        a.flatten() for a in np.meshgrid(xbx, ybx, zbx, indexing="ij")
-    ]
-    xby, yby, zby = [
-        a.flatten() for a in np.meshgrid(xby, yby, zby, indexing="ij")
-    ]
-    xbz, ybz, zbz = [
-        a.flatten() for a in np.meshgrid(xbz, ybz, zbz, indexing="ij")
-    ]
+    xbx, ybx, zbx = flatten_meshgrid(xbx, ybx, zbx)
+    xby, yby, zby = flatten_meshgrid(xby, yby, zby)
+    xbz, ybz, zbz = flatten_meshgrid(xbz, ybz, zbz)

423-426: Consider making empirical deviation values configurable.

The empirical deviation values are hardcoded for each dimension. Consider making these configurable through test parameters or environment variables to allow for easier tuning and adjustment.

+def get_empirical_deviations():
+    from os import environ
+    return {
+        1: float(environ.get('EMPIRICAL_DEV_1D', '6e-3')),
+        2: float(environ.get('EMPIRICAL_DEV_2D', '3e-2')),
+        3: float(environ.get('EMPIRICAL_DEV_3D', '2e-1')),
+    }
+
-empirical_dim_devs = {
-    1: 6e-3,
-    2: 3e-2,
-    3: 2e-1,
-}
+empirical_dim_devs = get_empirical_deviations()
tests/functional/harris/harris_3d.py (2)

38-52: Consider un-commenting 'strict=True' or documenting its omission

In the Simulation constructor, the parameter strict=True is commented out. If this is intentional, consider adding a comment explaining why strict mode is disabled. If not, you may want to un-comment it to enforce stricter simulation settings for more robust error checking.


65-77: Refactor duplicated code in 'by' and 'bx' functions

The functions by(x, y, z) and bx(x, y, z) share several common calculations, such as computing Lx, Ly, w1, w2, x0, y1, y2, w3, w4, and w5. Refactoring these shared computations into a helper function can reduce code duplication and improve maintainability.

Here's an example of how you can refactor the code:

def common_field_calculations(x, y):
    Lx = sim.simulation_domain()[0]
    Ly = sim.simulation_domain()[1]
    w1 = 0.2
    w2 = 1.0
    x0 = x - 0.5 * Lx
    y1 = y - 0.3 * Ly
    y2 = y - 0.7 * Ly
    w3 = np.exp(-(x0**2 + y1**2) / w2**2)
    w4 = np.exp(-(x0**2 + y2**2) / w2**2)
    w5 = 2.0 * w1 / w2
    return x0, y1, y2, w3, w4, w5, Ly

def by(x, y, z):
    x0, y1, y2, w3, w4, w5, _ = common_field_calculations(x, y)
    return (w5 * x0 * w3) + (-w5 * x0 * w4)

def bx(x, y, z):
    x0, y1, y2, w3, w4, w5, Ly = common_field_calculations(x, y)
    v1 = -1
    v2 = 1.0
    return (
        v1
        + (v2 - v1) * (S(y, Ly * 0.3, 0.5) - S(y, Ly * 0.7, 0.5))
        + (-w5 * y1 * w3)
        + (+w5 * y2 * w4)
    )

Also applies to: 78-97

pyphare/pyphare/core/box.py (1)

185-198: Improve variable naming for better readability

In the remove_all function, variables like tmp and remove can be renamed to more descriptive names to enhance code clarity and maintainability. For example, tmp could be renamed to new_remaining_boxes, and remove to indices_to_remove.

Apply this diff to improve variable names:

 def remove_all(box, to_remove):
     if len(to_remove) > 0:
         remaining = box - to_remove[0]
         for to_rm in to_remove[1:]:
-            tmp, remove = [], []
+            new_remaining_boxes, indices_to_remove = [], []
             for i, rem in enumerate(remaining):
                 if rem * to_rm is not None:
-                    remove.append(i)
-                    tmp += rem - to_rm
+                    indices_to_remove.append(i)
+                    new_remaining_boxes += rem - to_rm
             for rm in reversed(indices_to_remove):
                 del remaining[rm]
-            remaining += tmp
+            remaining += new_remaining_boxes
         return remaining
     return box
res/cmake/funcs.cmake (2)

23-27: Complete the incomplete comment.

The comment in lines 23-27 ends abruptly and may cause confusion. Please complete the sentence to clarify its intent.

Suggested correction:

#  Note to developers - do not use cmake variable function arguments for functions
#      phare_python3_exec
#      phare_mpi_python3_exec
#   if these function calls are to files executing python unit tests as they will interfere
+  #   with argument parsing and test execution. Please pass explicit arguments instead.

115-128: Consider using FetchContent or submodules for dependency management.

Cloning external dependencies during the build process can lead to non-reproducible builds and issues when there is no internet connectivity. Using CMake's FetchContent module or Git submodules can provide more reliable and controlled dependency management for GTest.

Example using FetchContent:

include(FetchContent)
FetchContent_Declare(
  googletest
  GIT_REPOSITORY    https://github.com/google/googletest.git
  GIT_TAG           release-1.11.0
)
FetchContent_MakeAvailable(googletest)
src/amr/data/particles/refine/split_3d.hpp (3)

90-92: Maintain consistent use of struct and class keywords

WhitePattern is declared as a class, whereas other pattern types like PinkPattern and PurplePattern are declared as struct. For consistency and clarity, consider using struct for WhitePattern since its members are public.

Apply this diff:

-template<>
-class WhitePattern<DimConst<3>> : SplitPattern<DimConst<3>, RefinedParticlesConst<24>>
+template<>
+struct WhitePattern<DimConst<3>> : SplitPattern<DimConst<3>, RefinedParticlesConst<24>>

133-134: Simplify static constants by using float instead of std::array<float, 1>

In several places, delta and weight are defined as std::array<float, 1> but contain only one element. Using float directly would simplify the code and improve readability.

Apply this diff for each occurrence:

-static constexpr std::array<float, 1> delta  = {...};
-static constexpr std::array<float, 1> weight = {...};
+static constexpr float delta  = ...;
+static constexpr float weight = ...;

Update the constructor initialization and any usages accordingly.

Also applies to: 151-152, 172-173, 193-194, 232-233, 252-253, 270-271, 291-292


121-174: Refactor Splitter specializations to reduce code duplication

The Splitter specializations for different InterpConst and RefinedParticlesConst combinations have similar structures with only variations in delta, weight, and pattern dispatchers. Consider refactoring to eliminate duplication, possibly by templating over these parameters or using a factory pattern.

Also applies to: 181-235, 242-294

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

382-400: Refactor sides definition to eliminate code duplication

The sides dictionary definitions for 2D and 3D cases are similar but duplicated. Consider refactoring this section to dynamically generate the sides dictionary based on dimensionality, possibly using a helper function or loops. This will enhance maintainability and reduce potential errors.

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

390-427: Refactor fill3D method to reduce code duplication

The fill3D method contains multiple code blocks that perform similar operations for different borders (left, right, bottom, top, front, back). This repetition can make the code harder to maintain and prone to errors. Consider refactoring by creating helper functions or using parameterized loops to handle border filling more elegantly.

For example, you can abstract the border filling into a helper lambda function:

auto fill_border = [&](auto i_range, auto j_range, auto k_range) {
    for (auto i : i_range)
        for (auto j : j_range)
            for (auto k : k_range)
                array(i, j, k) = val;
};

// Left and right borders
fill_border(
    std::vector{min_, shape[0] - 1 - max_},
    range(min_, shape[1] - 1 - max_),
    range(min_, shape[2] - 1 - min_)
);

// Top and bottom borders
fill_border(
    range(min_, shape[0] - 1 - min_),
    std::vector{min_, shape[1] - 1 - max_},
    range(min_, shape[2] - 1 - min_)
);

// Front and back borders
fill_border(
    range(min_, shape[0] - 1 - min_),
    range(min_, shape[1] - 1 - min_),
    std::vector{min_, shape[2] - 1 - max_}
);

This approach reduces repetition and enhances readability.


Line range hint 473-598: Simplify boundary copying logic in operator>> for 3D arrays

The operator>> function for 3D arrays has complex and repetitive code, which can be difficult to maintain and understand. Refactoring this logic can improve code clarity and reduce potential bugs.

Consider using nested loops or helper functions to generalize the boundary copying:

// Define ranges for inner and outer boundaries
auto x_inner = range(inner.xstart(), inner.xend());
auto y_inner = range(inner.ystart(), inner.yend());
auto z_inner = range(inner.zstart(), inner.zend());

auto x_outer = range(outer.xstart(), outer.xend());
auto y_outer = range(outer.ystart(), outer.yend());
auto z_outer = range(outer.zstart(), outer.zend());

// Lambda to copy boundaries
auto copy_boundary = [&](auto ix, auto iy, auto iz, auto ox, auto oy, auto oz) {
    outer(ox, oy, oz) = inner(ix, iy, iz);
};

// Copy edges
for (auto i : x_inner) {
    for (auto k : z_inner) {
        copy_boundary(i, inner.ystart(), k, i, outer.ystart(), k);
        copy_boundary(i, inner.yend(), k, i, outer.yend(), k);
    }
}

// ... (similar loops for other boundaries)

This refactoring reduces code duplication and makes the boundary copying logic more scalable.

pyphare/pyphare/pharesee/hierarchy.py (17)

508-508: Simplify dictionary iteration

In line 508, you can iterate over the dictionary directly instead of calling .keys(). This is more Pythonic and efficient.

Apply this diff to simplify the code:

-        particles = {popname: None for popname in aPatch.patch_datas.keys()}
+        particles = {popname: None for popname in aPatch.patch_datas}
🧰 Tools
🪛 Ruff

508-508: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


726-726: Unused loop variable time

The loop variable time is not used in the loop starting at line 726. Consider renaming it to _ to indicate it's intentionally unused.

Apply this diff:

-            for time, levels in self.time_hier.items():
+            for _, levels in self.time_hier.items():
🧰 Tools
🪛 Ruff

726-726: Loop control variable time not used within loop body

Rename unused time to _time

(B007)


727-727: Unused loop variable ilvl

The loop variable ilvl is not used in the loop starting at line 727. Consider renaming it to _ to indicate it's intentionally unused.

Apply this diff:

-                for ilvl, lvl in levels.items():
+                for _, lvl in levels.items():
🧰 Tools
🪛 Ruff

727-727: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


746-746: Unused loop variable ilvl

The loop variable ilvl is not used in the loop starting at line 746. Consider renaming it to _ to indicate it's intentionally unused.

Apply this diff:

-            for ilvl, lvl in self.levels(time).items():
+            for _, lvl in self.levels(time).items():
🧰 Tools
🪛 Ruff

746-746: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


760-760: Unused loop variable ilvl

The loop variable ilvl is not used in the loop starting at line 760. Consider renaming it to _ to indicate it's intentionally unused.

Apply this diff:

-            for ilvl, lvl in self.levels(time).items():
+            for _, lvl in self.levels(time).items():
🧰 Tools
🪛 Ruff

760-760: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


790-790: Unused loop variable t

The loop variable t is not used in the loop starting at line 790. Consider renaming it to _ to indicate it's intentionally unused.

Apply this diff:

-            for t, patch_levels in self.time_hier.items():
+            for _, patch_levels in self.time_hier.items():
🧰 Tools
🪛 Ruff

790-790: Loop control variable t not used within loop body

Rename unused t to _t

(B007)


877-877: Simplify default value in kwargs.get method

In line 877, the code kwargs.get("qty", None) can be simplified to kwargs.get("qty") since None is the default value.

Apply this diff:

-            qty = kwargs.get("qty", None)
+            qty = kwargs.get("qty")
🧰 Tools
🪛 Ruff

877-877: Use kwargs.get("qty") instead of kwargs.get("qty", None)

Replace kwargs.get("qty", None) with kwargs.get("qty")

(SIM910)


920-920: Simplify default value in kwargs.get method

In line 920, the code kwargs.get("legend", None) can be simplified to kwargs.get("legend") since None is the default value.

Apply this diff:

-            if kwargs.get("legend", None) is not None:
+            if kwargs.get("legend") is not None:
🧰 Tools
🪛 Ruff

920-920: Use kwargs.get("legend") instead of kwargs.get("legend", None)

Replace kwargs.get("legend", None) with kwargs.get("legend")

(SIM910)


1099-1099: Unused loop variable ip

The loop variable ip is not used in the loop starting at line 1099. Consider renaming it to _ to indicate it's intentionally unused.

Apply this diff:

-            for ip, patch in enumerate(level.patches):
+            for _, patch in enumerate(level.patches):
🧰 Tools
🪛 Ruff

1099-1099: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


1281-1281: Unused loop variable ip

The loop variable ip is not used in the loop starting at line 1281. Consider renaming it to _ to indicate it's intentionally unused.

Apply this diff:

-        for ip, patch in enumerate(lvl.patches):
+        for _, patch in enumerate(lvl.patches):
🧰 Tools
🪛 Ruff

1281-1281: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


1395-1395: Simplify dictionary iteration

In line 1395, you can iterate over the dictionary directly instead of calling .keys().

Apply this diff:

-            for dataset_name in h5_patch_grp.keys():
+            for dataset_name in h5_patch_grp:
🧰 Tools
🪛 Ruff

1395-1395: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1459-1459: Simplify dictionary iteration

In line 1459, you can iterate over the dictionary directly instead of calling .keys().

Apply this diff:

-            for plvl_key in h5_time_grp.keys():
+            for plvl_key in h5_time_grp:
🧰 Tools
🪛 Ruff

1459-1459: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1468-1468: Simplify dictionary iteration

In line 1468, you can iterate over the dictionary directly instead of calling .keys().

Apply this diff:

-                for pkey in h5_patch_lvl_grp.keys():
+                for pkey in h5_patch_lvl_grp:
🧰 Tools
🪛 Ruff

1468-1468: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1505-1505: Simplify dictionary iteration

In line 1505, you can iterate over the dictionary directly instead of calling .keys().

Apply this diff:

-                for plvl_key in h5_time_grp.keys():
+                for plvl_key in h5_time_grp:
🧰 Tools
🪛 Ruff

1505-1505: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1765-1765: Unused loop variable time

The loop variable time is not used in the loop starting at line 1765. Consider renaming it to _ to indicate it's intentionally unused.

Apply this diff:

-        for time, patch_levels in hierarchy.time_hier.items():
+        for _, patch_levels in hierarchy.time_hier.items():
🧰 Tools
🪛 Ruff

1765-1765: Loop control variable time not used within loop body

Rename unused time to _time

(B007)


1766-1766: Unused loop variable ilvl

The loop variable ilvl is not used in the loop starting at line 1766. Consider renaming it to _ to indicate it's intentionally unused.

Apply this diff:

-            for ilvl, plvl in patch_levels.items():
+            for _, plvl in patch_levels.items():
🧰 Tools
🪛 Ruff

1766-1766: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


1820-1820: Simplify dictionary iteration

In line 1820, you can iterate over the dictionary directly instead of calling .keys().

Apply this diff:

-        counts = {ilvl: 0 for ilvl in hier.levels().keys()}
+        counts = {ilvl: 0 for ilvl in hier.levels()}
🧰 Tools
🪛 Ruff

1820-1820: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a3ad211 and 1378a02.

📒 Files selected for processing (44)
  • .github/workflows/cmake_macos.yml (1 hunks)
  • pyphare/pyphare/core/box.py (2 hunks)
  • pyphare/pyphare/core/gridlayout.py (1 hunks)
  • pyphare/pyphare/pharesee/geometry.py (7 hunks)
  • pyphare/pyphare/pharesee/hierarchy.py (1 hunks)
  • pyphare/pyphare/pharesee/run/utils.py (1 hunks)
  • res/amr/splitting.yml (1 hunks)
  • res/cmake/funcs.cmake (1 hunks)
  • res/cmake/options.cmake (2 hunks)
  • src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1 hunks)
  • src/amr/data/particles/refine/split.hpp (1 hunks)
  • src/amr/data/particles/refine/split_1d.hpp (10 hunks)
  • src/amr/data/particles/refine/split_2d.hpp (17 hunks)
  • src/amr/data/particles/refine/split_3d.hpp (1 hunks)
  • src/amr/data/particles/refine/splitter.hpp (2 hunks)
  • src/core/data/grid/gridlayoutdefs.hpp (2 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (8 hunks)
  • src/core/utilities/box/box.hpp (3 hunks)
  • src/core/utilities/meta/meta_utilities.hpp (2 hunks)
  • tests/amr/data/field/refine/test_refine_field.py (1 hunks)
  • tests/amr/data/particles/refine/input/input_3d_ratio_2.txt (1 hunks)
  • tests/amr/data/particles/refine/test_split.cpp (1 hunks)
  • tests/core/data/ndarray/test_main.cpp (1 hunks)
  • tests/core/numerics/interpolator/test_main.cpp (1 hunks)
  • tests/diagnostic/CMakeLists.txt (1 hunks)
  • tests/diagnostic/job_3d.py.in (1 hunks)
  • tests/diagnostic/test-diagnostics_3d.cpp (1 hunks)
  • tests/functional/harris/harris_3d.py (1 hunks)
  • tests/simulator/__init__.py (2 hunks)
  • tests/simulator/advance/CMakeLists.txt (1 hunks)
  • tests/simulator/advance/test_fields_advance_3d.py (1 hunks)
  • tests/simulator/advance/test_particles_advance_3d.py (1 hunks)
  • tests/simulator/initialize/CMakeLists.txt (1 hunks)
  • tests/simulator/initialize/test_fields_init_2d.py (1 hunks)
  • tests/simulator/initialize/test_fields_init_3d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_1d.py (0 hunks)
  • tests/simulator/initialize/test_particles_init_2d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_3d.py (1 hunks)
  • tests/simulator/per_test.hpp (1 hunks)
  • tests/simulator/refined_particle_nbr.py (2 hunks)
  • tests/simulator/test_advance.py (6 hunks)
  • tests/simulator/test_initialization.py (13 hunks)
  • tools/python3/cmake.py (1 hunks)
  • tools/python3/git.py (1 hunks)
💤 Files with no reviewable changes (1)
  • tests/simulator/initialize/test_particles_init_1d.py
✅ Files skipped from review due to trivial changes (1)
  • tests/amr/data/particles/refine/input/input_3d_ratio_2.txt
🧰 Additional context used
📓 Path-based instructions (11)
src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1)

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

src/amr/data/particles/refine/split.hpp (1)

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

src/amr/data/particles/refine/split_1d.hpp (1)

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

src/amr/data/particles/refine/split_2d.hpp (1)

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

src/amr/data/particles/refine/split_3d.hpp (1)

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

src/amr/data/particles/refine/splitter.hpp (1)

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

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

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

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

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

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

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

src/core/utilities/meta/meta_utilities.hpp (1)

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

tests/simulator/per_test.hpp (1)

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

🪛 Ruff
pyphare/pyphare/core/box.py

207-207: Ambiguous variable name: l

(E741)

pyphare/pyphare/pharesee/geometry.py

161-161: Ambiguous variable name: l

(E741)


164-164: Ambiguous variable name: l

(E741)


167-167: Ambiguous variable name: l

(E741)


188-188: Ambiguous variable name: l

(E741)

pyphare/pyphare/pharesee/hierarchy.py

508-508: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


520-520: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


621-621: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


651-651: Comparison to None should be cond is None

Replace with cond is None

(E711)


726-726: Loop control variable time not used within loop body

Rename unused time to _time

(B007)


727-727: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


746-746: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


760-760: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


790-790: Loop control variable t not used within loop body

Rename unused t to _t

(B007)


877-877: Use kwargs.get("qty") instead of kwargs.get("qty", None)

Replace kwargs.get("qty", None) with kwargs.get("qty")

(SIM910)


920-920: Use kwargs.get("legend") instead of kwargs.get("legend", None)

Replace kwargs.get("legend", None) with kwargs.get("legend")

(SIM910)


960-960: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)


1018-1018: Use kwargs.get("legend") instead of kwargs.get("legend", None)

Replace kwargs.get("legend", None) with kwargs.get("legend")

(SIM910)


1034-1034: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)


1099-1099: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


1281-1281: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


1395-1395: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1459-1459: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1468-1468: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1505-1505: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1538-1538: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1544-1544: Loop control variable ipatch not used within loop body

(B007)


1561-1561: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


1765-1765: Loop control variable time not used within loop body

Rename unused time to _time

(B007)


1766-1766: Loop control variable ilvl not used within loop body

Rename unused ilvl to _ilvl

(B007)


1767-1767: Loop control variable ip not used within loop body

Rename unused ip to _ip

(B007)


1820-1820: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

tests/amr/data/field/refine/test_refine_field.py

106-106: Do not assert False (python -O removes these calls), raise AssertionError()

Replace assert False

(B011)

tests/functional/harris/harris_3d.py

62-62: Ambiguous variable name: l

(E741)

tests/simulator/__init__.py

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

Replace with None; initialize within function

(B006)

tests/simulator/test_advance.py

89-89: Ambiguous variable name: l

(E741)

tests/simulator/test_initialization.py

394-394: Function definition does not bind loop variable select

(B023)


396-396: Function definition does not bind loop variable patch

(B023)


396-396: Function definition does not bind loop variable nbrGhosts

(B023)


397-397: Function definition does not bind loop variable select

(B023)


582-582: Loop control variable pi not used within loop body

Rename unused pi to _pi

(B007)


586-586: Yoda condition detected

Rewrite as ppc == H

(SIM300)


664-664: Local variable out is assigned to but never used

Remove assignment to unused variable out

(F841)

tools/python3/cmake.py

48-48: Undefined name cmd

(F821)

tools/python3/git.py

22-22: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


29-29: Undefined name delete_branch

(F821)

🪛 GitHub Check: CodeQL
pyphare/pyphare/pharesee/hierarchy.py

[warning] 132-132: Overwriting attribute in super-class or sub-class
Assignment overwrites attribute layout, which was previously defined in superclass PatchData.


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


[warning] 651-651: Comparison of identical values
Comparison of identical values; use cmath.isnan() if testing for not-a-number.


[notice] 668-668: Testing equality to None
Testing for None should use the 'is' operator.


[failure] 694-694: Potentially uninitialized local variable
Local variable 'slice_dim' may be used before it is initialized.


[failure] 695-695: Potentially uninitialized local variable
Local variable 'cst_dim' may be used before it is initialized.


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


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

🪛 cppcheck
tests/diagnostic/test-diagnostics_3d.cpp

[performance] 24-24: Function parameter 'path' should be passed by const reference.

(passedByValue)

🔇 Additional comments (59)
src/amr/data/particles/refine/split.hpp (1)

6-6: LGTM! The include hierarchy is well-structured.

The addition of split_3d.hpp follows the existing pattern and maintains a clean separation of dimensionality-specific code.

Let's verify the consistency of the split header files:

✅ Verification successful

All dimension-specific split headers exist and maintain consistent structure

The verification confirms:

  • All three dimension-specific headers (split_1d.hpp, split_2d.hpp, split_3d.hpp) exist in the expected location
  • Each header follows consistent naming and header guard patterns with the PHARE_SPLIT_*D_HPP format
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and consistency of split header files
# Expected: All dimension-specific headers should exist and follow similar patterns

# Check if all split headers exist
fd "split_[123]d\.hpp" src/amr/data/particles/refine/

# Verify consistent header guards and basic structure across files
for dim in 1 2 3; do
  echo "=== split_${dim}d.hpp ==="
  rg -A 2 "^#ifndef.*SPLIT_${dim}D" src/amr/data/particles/refine/split_${dim}d.hpp
done

Length of output: 781

tests/diagnostic/job_3d.py.in (2)

1-7: LGTM! Imports are well-organized.

The imports are appropriate for a 3D simulation test script, with clear separation between core library and test utilities.


11-11: Verify interpolation order for 3D accuracy.

Using interp = 1 might lead to numerical artifacts in 3D simulations. Consider using a higher interpolation order (e.g., 2 or 3) for better accuracy in 3D space.

tests/diagnostic/test-diagnostics_3d.cpp (1)

30-35: LGTM: Main function properly initializes test environment.

The main function correctly sets up both Google Test and PHARE lifecycle management.

tests/amr/data/particles/refine/test_split.cpp (1)

25-25: LGTM: 3D splitter configuration follows the dimensional pattern

The addition of Splitter<3, 1, 27> correctly extends the test coverage to 3D scenarios, following the logical progression from 1D (2 particles) and 2D (8 particles) to 3D (27 particles).

tests/simulator/initialize/CMakeLists.txt (1)

21-24: LGTM! Verify the existence of 3D test files.

The conditional block is well-structured and follows the existing patterns for test configuration.

Let's verify the existence of the referenced test files:

✅ Verification successful

Both 3D test files are present in the expected location

The verification confirms that both test files referenced in the CMakeLists.txt exist at the correct path:

  • tests/simulator/initialize/test_fields_init_3d.py
  • tests/simulator/initialize/test_particles_init_3d.py
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the 3D test files exist in the current directory
# Expected: Both files should exist

fd "test_fields_init_3d.py|test_particles_init_3d.py" tests/simulator/initialize/

Length of output: 186

tests/simulator/advance/CMakeLists.txt (1)

22-23: Verify the existence of 3D test files.

Let's ensure that the referenced Python test files exist in the repository.

✅ Verification successful

Both 3D test files are present in the repository

The verification confirms that both test files exist at the expected location:

  • tests/simulator/advance/test_fields_advance_3d.py
  • tests/simulator/advance/test_particles_advance_3d.py
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the 3D test files exist in the repository

echo "Checking for 3D test files..."
fd -t f "test_fields_advance_3d.py|test_particles_advance_3d.py" tests/simulator/advance/

if [ $? -ne 0 ]; then
    echo "Warning: One or more 3D test files not found"
    exit 1
fi

Length of output: 281

tests/diagnostic/CMakeLists.txt (2)

37-37: LGTM! 3D test executable addition follows existing pattern.

The addition of the 3D diagnostic test executable maintains consistency with the existing 1D and 2D test structure.


41-41: Verify the existence of job_3d.py.in template file.

The configuration setup looks good and follows the established pattern for diagnostic job files.

✅ Verification successful

Template file job_3d.py.in exists and is properly located

The verification confirms that the template file job_3d.py.in exists in the expected location at tests/diagnostic/, validating the configure_file command's setup.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence of the 3D job template file
# Expected: job_3d.py.in should exist in the same directory

# Check if the template file exists
if [ -f "tests/diagnostic/job_3d.py.in" ]; then
    echo "Template file exists"
else
    echo "ERROR: Missing template file tests/diagnostic/job_3d.py.in"
    exit 1
fi

Length of output: 93

tests/simulator/initialize/test_fields_init_2d.py (1)

26-26: LGTM! Parameter name alignment improves consistency.

The change from nbr_part_per_cell to ppc aligns with the module-level constant defined on line 9, making the code more consistent.

tests/simulator/advance/test_particles_advance_3d.py (1)

6-14: LGTM: Well-organized imports and appropriate matplotlib configuration

The imports are logically grouped and the matplotlib backend is correctly configured for headless environments.

tools/python3/cmake.py (1)

26-27: ⚠️ Potential issue

Fix missing use_ccache parameter in make_config_str call.

The function call is missing parameters which could lead to unexpected behavior.

- cmd = make_config_str(path, samrai_dir, cxx_flags, use_ninja, extra)
+ cmd = make_config_str(path, samrai_dir, cxx_flags, use_ninja, use_ccache, extra)

Likely invalid or redundant comment.

tests/simulator/initialize/test_fields_init_3d.py (1)

48-49: LGTM!

Standard unittest main block is correctly implemented.

res/amr/splitting.yml (4)

102-141: LGTM: Structure follows established pattern

The new dimension_3 section maintains consistent formatting and structure with existing dimensions.


117-128: LGTM: Consistent delta progression

The delta values show a logical progression from interp_1, maintaining consistency with the patterns established in lower dimensions.


130-141: Consider adding more particle configurations for interp_3

Looking at the pattern in dimension_1 and dimension_2, interp_3 typically includes additional particle configurations (e.g., N_particles_4, N_particles_5 in 1D, and N_particles_16, N_particles_25 in 2D). Consider if additional configurations should be added for completeness.

This aligns with the PR description mentioning "some coarsening tests missing" and "only some 3d split patterns".


113-115: ⚠️ Potential issue

Verify the weights for N_particles_27

The weights for N_particles_27 (0.125 + 0.0625 = 0.1875) seem low compared to other patterns. This might affect the interpolation quality.

Consider verifying these values against the mathematical model or simulation results. The sum of weights typically should be closer to 1 for proper interpolation.

.github/workflows/cmake_macos.yml (1)

90-90: Verify and document the PHARE_SIMULATORS configuration

The addition of -DPHARE_SIMULATORS=2 needs verification:

  1. Does limiting to 2 simulators provide adequate coverage for the new 3D features?
  2. Will this support testing all implemented 3D split patterns?

Consider adding documentation about:

  • The significance of the simulator count
  • Which simulation patterns are enabled/disabled
tests/simulator/initialize/test_particles_init_2d.py (2)

26-26: LGTM! Class name accurately reflects 2D testing scope

The renaming from Initialization1DTest to Initialization2DTest properly aligns with the file's purpose of isolating dimension-specific test cases.


Line range hint 33-65: Verify consistency with 3D split patterns

The PR mentions "only some 3d split patterns". Please ensure that the split pattern tests in this 2D implementation (test_levelghostparticles_have_correct_split_from_coarser_particle and test_domainparticles_have_correct_split_from_coarser_particle) align with the available 3D patterns.

Let's check the corresponding 3D test patterns:

✅ Verification successful

Let me gather more information about the test patterns in both files.


Let me also check the domain particles test patterns in both files.


Split patterns are consistent between 2D and 3D implementations

The verification shows that both test files maintain consistent split pattern structures:

  • Level ghost particles test uses identical box configurations in both dimensions (just Box2D vs Box3D)

    • Single box: (10, 14)
    • Two-level hierarchy: L0(10, 14) and L1(22, 26)
    • Two boxes at same level: L0(2, 6) and L0(7, 11)
  • Domain particles test also maintains similar patterns with minor dimensional adjustments:

    • 2D: L0(5, 20), L1(15, 35) vs 3D: L0(5, 14), L1(15, 19)
    • Other patterns are identical between dimensions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the corresponding 3D test file and compare split patterns
rg -A 5 'test_.*particles_have_correct_split' tests/simulator/initialize/test_particles_init_3d.py

Length of output: 1021


Script:

#!/bin/bash
# Search for test data patterns in both files
echo "=== 2D test patterns ==="
rg -B 5 'test_levelghostparticles_have_correct_split' tests/simulator/initialize/test_particles_init_2d.py

echo -e "\n=== 3D test patterns ==="
rg -B 5 'test_levelghostparticles_have_correct_split' tests/simulator/initialize/test_particles_init_3d.py

Length of output: 1377


Script:

#!/bin/bash
# Search for domain particles test patterns in both files
echo "=== 2D domain particles test patterns ==="
rg -B 5 'test_domainparticles_have_correct_split' tests/simulator/initialize/test_particles_init_2d.py

echo -e "\n=== 3D domain particles test patterns ==="
rg -B 5 'test_domainparticles_have_correct_split' tests/simulator/initialize/test_particles_init_3d.py

Length of output: 1423

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

5-5: LGTM! Include directive properly placed.

The addition of <cstdint> header is correctly placed in the include order (standard headers before project headers) and is necessary for std::uint16_t.

tests/simulator/per_test.hpp (1)

111-114: LGTM! Test fixture follows established patterns.

The Simulator3dTest fixture follows the same clean and consistent implementation pattern as the existing 1D and 2D test fixtures.

tests/simulator/initialize/test_particles_init_3d.py (3)

1-14: LGTM! Well-documented file purpose and appropriate imports.

The file's documentation clearly explains its purpose of isolating dimension test cases, and the imports are appropriate for the testing requirements.


97-98: LGTM! Standard unittest main block.

The main block follows Python's unittest conventions.


25-75: Verify test coverage for edge cases

The test cases cover basic scenarios with various box configurations, but consider adding tests for:

  • Edge cases with minimum/maximum box dimensions
  • Corner cases where boxes touch or overlap
  • Error cases with invalid box dimensions
src/amr/data/particles/refine/splitter.hpp (3)

70-70: Remove unused local variable.

This issue has been previously identified in past reviews.


118-121: LGTM! Well-structured pattern implementation.

The BlackPattern structure follows C++ best practices with proper use of constexpr, inheritance, and type aliasing.


128-146: Verify the empty pattern structures implementation plan.

The new pattern structures (Pink, Purple, Brown, Lime, White) are currently empty. While the PR description indicates this is intentional ("some 3d split patterns, the rest can come afterwards"), they should eventually follow the same implementation pattern as BlackPattern:

template<typename dim>
struct PinkPattern : SplitPattern<dim, core::RefinedParticlesConst<N>> {
    using Super = SplitPattern<dim, core::RefinedParticlesConst<N>>;
    constexpr PinkPattern(float const weight)
        : Super{weight}
    {
    }
};
✅ Verification successful

Empty pattern structures are forward declarations for dimension-specific implementations

The empty structures in splitter.hpp are intentional forward declarations. The actual implementations are provided in dimension-specific files:

  • 1D implementations in split_1d.hpp
  • 2D implementations in split_2d.hpp
  • 3D implementations in split_3d.hpp

Each pattern is properly implemented with the correct inheritance from SplitPattern and appropriate particle count constants:

  • PinkPattern: Implemented for 1D (2 particles), 2D (4 particles), 3D (6 particles)
  • PurplePattern: Implemented for 2D (4 particles), 3D (8 particles)
  • BrownPattern: Implemented for 2D (8 particles)
  • LimePattern: Implemented for 3D (12 particles)
  • WhitePattern: Implemented for 3D (24 particles)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any existing implementations of these patterns in other files
# that might serve as references for the implementation

echo "Searching for pattern implementations..."
rg -l "Pattern.*SplitPattern" --type cpp

echo "Checking for any TODO comments or implementation notes..."
rg -i "todo.*pattern|implement.*pattern" --type cpp

Length of output: 484


Script:

#!/bin/bash
# Let's examine the BlackPattern implementation and other pattern implementations
echo "=== Checking BlackPattern and related implementations ==="
rg "struct.*Pattern.*:.*SplitPattern" -A 5 --type cpp

echo "=== Checking if these patterns are used elsewhere ==="
rg "Pink(Pattern|Split)|Purple(Pattern|Split)|Brown(Pattern|Split)|Lime(Pattern|Split)|White(Pattern|Split)" --type cpp

Length of output: 11733

src/core/utilities/meta/meta_utilities.hpp (2)

94-94: Review the commented out particle count 27 for 3D simulations.

The commented out value 27 in SimulatorOption<DimConst<3>, InterpConst<1>, 6, 12 /*, 27*/> suggests a potential optimization opportunity. Consider documenting why this value is currently excluded and its performance implications.

✅ Verification successful

The commented out 27 particles per cell is intentionally excluded for 3D simulations

Based on the codebase analysis, the particle count choices are deliberate:

  • 1D simulations use 2-5 particles per cell
  • 2D simulations use 4-25 particles per cell
  • 3D simulations currently use only 6 and 12 particles per cell

The exclusion of 27 appears intentional as the codebase shows a well-structured pattern of increasing particle counts based on dimensionality and interpolation order. The load balancing system (using "nppc" mode) and particle diagnostics are already designed to work with the current particle counts.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for related performance tests or documentation
# Expected: Find context about particle count choices

# Search for related test files and documentation
rg -g '!{*.o,*.so,*.a}' '(27|particle.*count|particles.*per.*cell)' test/

Length of output: 121


Script:

#!/bin/bash
# Let's try searching in the entire codebase for particle count patterns and documentation
rg -g '!{*.o,*.so,*.a}' '(particle.*count|particles.*per.*cell|nppc)' .

# Also search for any documentation about simulator options
rg -g '!{*.o,*.so,*.a}' 'SimulatorOption.*DimConst.*InterpConst' -A 3 .

Length of output: 11328


9-11: Verify build configuration compatibility across different platforms.

The default value of 3 enables all simulator dimensions, but some build configurations (e.g., macOS workflow) override this with PHARE_SIMULATORS=2. This might lead to inconsistent behavior across different platforms.

tests/simulator/refined_particle_nbr.py (3)

105-116: Well-documented 3D test implementation

The 3D test implementation is well structured with clear documentation of the refinement ratio calculations and appropriate test constants.


139-144: Well-implemented test execution order

Good implementation of test ordering using TestSuite to ensure proper verification sequence. The approach correctly handles test dependencies while maintaining clean unittest patterns.


33-37: 🛠️ Refactor suggestion

Add exception handling to tearDown method

While the null check is good, the method should handle potential exceptions during reset to ensure test cleanup completes gracefully.

 def tearDown(self):
     if self.simulator is not None:
-        self.simulator.reset()
+        try:
+            self.simulator.reset()
+        except Exception as e:
+            print(f"Warning: Error during simulator reset: {e}")

Likely invalid or redundant comment.

src/amr/data/particles/refine/split_1d.hpp (1)

Line range hint 20-31: LGTM! Clean implementation of PinkPattern specialization.

The template specialization is well-structured with proper use of constexpr and clear inheritance hierarchy.

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

218-218: LGTM: Deduction guide is well-implemented

The deduction guide correctly enables template argument deduction from Point parameters.

src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (2)

99-114: LGTM: 1D coarsening implementation is correct.

The implementation properly handles both primal and dual centering cases, maintaining magnetic flux conservation through appropriate averaging.


116-152: LGTM: 2D coarsening implementation is correct.

The implementation properly handles all combinations of primal and dual centering, with appropriate averaging weights for flux conservation.

tests/core/data/ndarray/test_main.cpp (2)

395-403: LGTM! Well-structured test setup.

The test setup is clean and well-organized. The lambda function for sum calculation improves code readability.


404-409: LGTM! Good test coverage for basic operations.

The test block effectively verifies array initialization and filling operations with proper resource management through scoping.

pyphare/pyphare/core/gridlayout.py (1)

382-382: Verify impact of changing withGhosts default value.

The default value of withGhosts parameter in yeeCoordsFor has been changed from False to True. This could affect existing code that relies on the previous default behavior.

✅ Verification successful

Let me gather more context about the usage of yeeCoordsFor to understand if the default parameter change impacts the behavior.


Default parameter change in yeeCoordsFor is safe

The change in default value of withGhosts from False to True is safe because:

  1. All direct calls to the method in production code (pyphare/pharesee/run/utils.py) use positional arguments and don't rely on the default value
  2. The meshCoords method, which is the new caller, explicitly benefits from the new default value of True
  3. Test cases in test_coarsen_field.py use the method through instance calls which already had withGhosts=True as the default value
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for direct calls to yeeCoordsFor without explicit withGhosts parameter
rg -l "yeeCoordsFor\([^)]*\)" | while read -r file; do
  echo "=== $file ==="
  rg "yeeCoordsFor\([^)]*\)" "$file"
done

Length of output: 1172


Script:

#!/bin/bash
# Check the implementation and usage context of yeeCoordsFor
echo "=== Implementation of yeeCoordsFor ==="
rg -A 20 "def yeeCoordsFor" pyphare/pyphare/core/gridlayout.py

echo -e "\n=== Usage in meshCoords ==="
rg -A 10 "def meshCoords" pyphare/pyphare/core/gridlayout.py

echo -e "\n=== Test cases using yeeCoordsFor ==="
rg -B 2 -A 2 "yeeCoordsFor" tests/

Length of output: 2767

pyphare/pyphare/pharesee/run/utils.py (1)

362-362: LGTM: Shape calculation now supports dynamic dimensionality

The change from hardcoded 2D to dynamic dimensionality is correct and aligns with the PR's 3D support objectives.

tests/core/numerics/interpolator/test_main.cpp (1)

776-783: ⚠️ Potential issue

Uncomment and verify the test case DepositCorrectlyTheirWeight_3d.

The test case is crucial for validating 3D interpolation correctness but is currently commented out. This needs to be active to ensure the functionality is tested properly.

-    // auto const& [vx, vy, vz] = this->v();
-    // EXPECT_DOUBLE_EQ(this->rho(7, 7, 7), 1.0);
-    // EXPECT_DOUBLE_EQ(vx(7, 7, 7), 2.0);
-    // EXPECT_DOUBLE_EQ(vy(7, 7, 7), -1.0);
-    // EXPECT_DOUBLE_EQ(vz(7, 7, 7), 1.0);
+    auto const& [vx, vy, vz] = this->v();
+    EXPECT_DOUBLE_EQ(this->rho(7, 7, 7), 1.0);
+    EXPECT_DOUBLE_EQ(vx(7, 7, 7), 2.0);
+    EXPECT_DOUBLE_EQ(vy(7, 7, 7), -1.0);
+    EXPECT_DOUBLE_EQ(vz(7, 7, 7), 1.0);

Likely invalid or redundant comment.

tests/simulator/test_initialization.py (1)

696-697: LGTM: Proper dimension validation.

The dimension check using sim.cells ensures the test is properly configured for the intended dimensionality.

tests/simulator/test_advance.py (6)

265-273: LGTM: Improved slice selection logic.

The code now uses boxm.select for consistent slice selection, which is a better approach than direct indexing.


370-372: LGTM: Added cells parameter with sensible default.

The method signature update adds flexibility while maintaining backward compatibility.


399-400: LGTM: Added cells parameter with sensible default.

Similar to the previous method, this signature update maintains backward compatibility.


413-420: LGTM: Improved diagnostic output path construction.

The f-string based path construction improves readability and includes all relevant test parameters.


493-493: 🛠️ Refactor suggestion

Replace magic number with a named constant.

The magic number -144123 should be defined as a named constant at the module level for better maintainability.

+# At the top of the file
+COARSE_TEST_MARKER = -144123

-boxm.DataSelector(afterCoarse)[dataBox] = -144123
+boxm.DataSelector(afterCoarse)[dataBox] = COARSE_TEST_MARKER

Likely invalid or redundant comment.


89-91: 🛠️ Refactor suggestion

Rename parameter for better clarity.

The parameter name l is ambiguous and could be mistaken for the number 1. Consider using a more descriptive name.

-def S(x, x0, l):
-    return 0.5 * (1 + np.tanh((x - x0) / l))
+def S(x, x0, length):
+    return 0.5 * (1 + np.tanh((x - x0) / length))

Likely invalid or redundant comment.

🧰 Tools
🪛 Ruff

89-89: Ambiguous variable name: l

(E741)

tests/functional/harris/harris_3d.py (1)

124-124: Confirm that setting electron temperature 'Te=0.0' is intended

In the ElectronModel, you have set Te=0.0. An electron temperature of zero may not be physically meaningful and could lead to division by zero errors or other computational issues. Please verify that this is intentional and adjust the value if necessary.

pyphare/pyphare/core/box.py (1)

209-223: The DataSelector class implementation is correct

The DataSelector class provides a convenient interface for data selection and assignment using Box instances or slices. The methods __getitem__ and __setitem__ are correctly implemented and enhance the usability of data manipulation.

res/cmake/funcs.cmake (1)

28-182: Overall review of test function definitions.

The test functions are well-defined and handle both MPI and non-MPI scenarios appropriately. The use of conditional logic based on testMPI and execution levels ensures flexible and controlled test execution.

src/amr/data/particles/refine/split_3d.hpp (1)

95-97: ⚠️ Potential issue

Invalid use of templated constructor in a non-templated class

The WhitePattern class is not a class template, but it has a templated constructor. In C++, you cannot have a templated constructor in a non-templated class. This will result in a compilation error.

To fix this issue, consider making the entire class a template or removing the template parameter from the constructor. If Delta is always a specific type, you can specify it directly.

Apply this diff to make WhitePattern a class template:

-template<>
-class WhitePattern<DimConst<3>> : SplitPattern<DimConst<3>, RefinedParticlesConst<24>>
+template<typename DeltaType>
+class WhitePattern<DimConst<3>, DeltaType> : SplitPattern<DimConst<3>, RefinedParticlesConst<24>>

Alternatively, remove the template from the constructor:

-    template<typename Delta>
     constexpr WhitePattern(float const weight, Delta const& delta)

Likely invalid or redundant comment.

pyphare/pyphare/pharesee/geometry.py (3)

59-60: Addition of 'bottom' and 'top' ghost boxes for 2D domains

The inclusion of 'bottom' and 'top' ghost boxes in the 2D case appears correct and effectively handles domain borders for 2D simulations.


63-74: Implementation of 3D ghost boxes in domain_border_ghost_boxes

The added code correctly handles the 3D case by defining ghost boxes for 'left', 'right', 'bottom', 'top', 'front', and 'back' borders. This enhancement extends the function to support 3D domains properly.


184-188: ⚠️ Potential issue

Potential key collisions when sorting keys in shifts dictionary

Reassigning the shifts dictionary keys by sorting the characters in each key may lead to unintended key collisions:

shifts = {"".join(sorted(k)): l for k, l in shifts.items()}

For example, keys like 'left' and 'felt' would both become 'eflt' when sorted. Please verify that this behavior is intentional and that it does not cause issues with key uniqueness.

To confirm whether any key collisions occur, consider adding a check within the code:

# After reassigning shifts
assert len(shifts) == len(set(shifts.keys())), "Key collision detected in shifts dictionary."
🧰 Tools
🪛 Ruff

188-188: Ambiguous variable name: l

(E741)

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

127-128: Add NO_DISCARD to zstart() and zend() methods for consistency

The methods zstart() and zend() are missing the NO_DISCARD attribute, which is used in other similar methods (xstart, xend, ystart, yend) in the MaskedView class. Adding NO_DISCARD will help prevent unintended ignoring of return values.

pyphare/pyphare/pharesee/hierarchy.py (2)

960-960: Unused loop variable lvl

The loop variable lvl is not used in the loop starting at line 960. Consider renaming it to _ to indicate it's intentionally unused.

🧰 Tools
🪛 Ruff

960-960: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)


1034-1034: Unused loop variable lvl

The loop variable lvl is not used in the loop starting at line 1034. Consider renaming it to _ to indicate it's intentionally unused.

🧰 Tools
🪛 Ruff

1034-1034: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)

ph.Simulation(**basicSimulatorArgs(dim = 3, interp = 1, **simInput))
model = makeBasicModel()
ElectronModel(closure="isothermal",Te = 0.12)
dump_all_diags(model.populations)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add validation for model populations.

Verify that the model populations are properly initialized before dumping diagnostics.

-dump_all_diags(model.populations)
+if not model.populations:
+    raise ValueError("No populations found in the model")
+dump_all_diags(model.populations)
📝 Committable suggestion

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

Suggested change
dump_all_diags(model.populations)
if not model.populations:
raise ValueError("No populations found in the model")
dump_all_diags(model.populations)

Comment on lines +5 to +6
def current_branch():
return decode_bytes(run("git branch --show-current").stdout)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for git command failure.

The function should handle cases where the git command fails, such as when not in a git repository or when git is not installed.

 def current_branch():
-    return decode_bytes(run("git branch --show-current").stdout)
+    try:
+        return decode_bytes(run("git branch --show-current", check=True).stdout)
+    except subprocess.CalledProcessError:
+        raise RuntimeError("Failed to get current branch. Are you in a git repository?")

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

Comment on lines +9 to +10
def hashes(N=1):
return decode_bytes(run(f"git log -{N} --pretty=format:%h").stdout).splitlines()
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add parameter validation and error handling.

The function should validate the input parameter and handle git command failures.

 def hashes(N=1):
+    if not isinstance(N, int) or N < 1:
+        raise ValueError("N must be a positive integer")
+    try:
-        return decode_bytes(run(f"git log -{N} --pretty=format:%h").stdout).splitlines()
+        return decode_bytes(run(f"git log -{N} --pretty=format:%h", check=True).stdout).splitlines()
+    except subprocess.CalledProcessError:
+        raise RuntimeError("Failed to get commit hashes. Are you in a git repository?")
📝 Committable suggestion

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

Suggested change
def hashes(N=1):
return decode_bytes(run(f"git log -{N} --pretty=format:%h").stdout).splitlines()
def hashes(N=1):
if not isinstance(N, int) or N < 1:
raise ValueError("N must be a positive integer")
try:
return decode_bytes(run(f"git log -{N} --pretty=format:%h", check=True).stdout).splitlines()
except subprocess.CalledProcessError:
raise RuntimeError("Failed to get commit hashes. Are you in a git repository?")

Comment on lines +27 to +35
def checkout(branch, create=False, recreate=False):
if recreate:
delete_branch(branch)
create = True

if create and not branch_exists(branch):
run(f"git checkout -b {branch}")
else:
run(f"git checkout {branch}")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix undefined function and improve error handling.

Critical issues and improvements needed:

  1. The delete_branch function is undefined
  2. Missing input validation
  3. No error handling for git operations
+def delete_branch(branch):
+    """Delete a git branch locally."""
+    try:
+        run(f"git branch -D {branch}", check=True)
+    except subprocess.CalledProcessError:
+        raise RuntimeError(f"Failed to delete branch: {branch}")
+
 def checkout(branch, create=False, recreate=False):
+    if not branch or not isinstance(branch, str):
+        raise ValueError("Branch name must be a non-empty string")
     if recreate:
         delete_branch(branch)
         create = True

     if create and not branch_exists(branch):
-        run(f"git checkout -b {branch}")
+        try:
+            run(f"git checkout -b {branch}", check=True)
+        except subprocess.CalledProcessError:
+            raise RuntimeError(f"Failed to create and checkout branch: {branch}")
     else:
-        run(f"git checkout {branch}")
+        try:
+            run(f"git checkout {branch}", check=True)
+        except subprocess.CalledProcessError:
+            raise RuntimeError(f"Failed to checkout branch: {branch}")
📝 Committable suggestion

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

Suggested change
def checkout(branch, create=False, recreate=False):
if recreate:
delete_branch(branch)
create = True
if create and not branch_exists(branch):
run(f"git checkout -b {branch}")
else:
run(f"git checkout {branch}")
def delete_branch(branch):
"""Delete a git branch locally."""
try:
run(f"git branch -D {branch}", check=True)
except subprocess.CalledProcessError:
raise RuntimeError(f"Failed to delete branch: {branch}")
def checkout(branch, create=False, recreate=False):
if not branch or not isinstance(branch, str):
raise ValueError("Branch name must be a non-empty string")
if recreate:
delete_branch(branch)
create = True
if create and not branch_exists(branch):
try:
run(f"git checkout -b {branch}", check=True)
except subprocess.CalledProcessError:
raise RuntimeError(f"Failed to create and checkout branch: {branch}")
else:
try:
run(f"git checkout {branch}", check=True)
except subprocess.CalledProcessError:
raise RuntimeError(f"Failed to checkout branch: {branch}")
🧰 Tools
🪛 Ruff

29-29: Undefined name delete_branch

(F821)

Comment on lines +40 to +44
def test_cmd(test, verbose=False):
cmd = f"ctest -R {test}"
if verbose:
cmd = f"{cmd} -V"
return cmd
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add input validation for test name parameter.

The function should validate the test name to prevent command injection and ensure it's a valid test name.

 def test_cmd(test, verbose=False):
+    if not isinstance(test, str) or not test.strip():
+        raise ValueError("Test name must be a non-empty string")
+    # Sanitize test name to prevent command injection
+    test = test.replace('"', '').replace("'", '').replace(';', '')
     cmd = f"ctest -R {test}"
     if verbose:
         cmd = f"{cmd} -V"
     return cmd
📝 Committable suggestion

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

Suggested change
def test_cmd(test, verbose=False):
cmd = f"ctest -R {test}"
if verbose:
cmd = f"{cmd} -V"
return cmd
def test_cmd(test, verbose=False):
if not isinstance(test, str) or not test.strip():
raise ValueError("Test name must be a non-empty string")
# Sanitize test name to prevent command injection
test = test.replace('"', '').replace("'", '').replace(';', '')
cmd = f"ctest -R {test}"
if verbose:
cmd = f"{cmd} -V"
return cmd

from pyphare.simulator.simulator import Simulator
from pyphare.simulator.simulator import startMPI

os.environ["PHARE_SCOPE_TIMING"] = "0" # turn on scope timing
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Inconsistency between environment variable value and comment

The comment states "turn on scope timing," but os.environ["PHARE_SCOPE_TIMING"] is set to "0". Typically, setting this environment variable to "0" disables scope timing. Please verify if the intended action is to turn scope timing on or off.

If the intent is to turn on scope timing, apply this diff:

-os.environ["PHARE_SCOPE_TIMING"] = "0"  # turn on scope timing
+os.environ["PHARE_SCOPE_TIMING"] = "1"  # turn on scope timing
📝 Committable suggestion

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

Suggested change
os.environ["PHARE_SCOPE_TIMING"] = "0" # turn on scope timing
os.environ["PHARE_SCOPE_TIMING"] = "1" # turn on scope timing

Comment on lines +106 to +108
temp = 1.0 / density(x, y, z) * (K - b2(x, y, z) * 0.5)
assert np.all(temp > 0)
return temp
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace 'assert' with explicit error handling for runtime checks

Using assert statements for runtime checks is not recommended because assertions can be disabled with optimization settings, which could lead to unnoticed errors. In the function T(x, y, z), replace the assert statement with explicit error handling to ensure that temp is greater than zero during runtime.

Apply this change:

-def T(x, y, z):
-    K = 1
-    temp = 1.0 / density(x, y, z) * (K - b2(x, y, z) * 0.5)
-    assert np.all(temp > 0)
-    return temp
+def T(x, y, z):
+    K = 1
+    temp = 1.0 / density(x, y, z) * (K - b2(x, y, z) * 0.5)
+    if not np.all(temp > 0):
+        raise ValueError("Temperature 'temp' must be greater than zero.")
+    return temp

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

Comment on lines +65 to +67
if isinstance(other, (list, tuple)):
assert all([isinstance(item, Box) for item in other])
return remove_all(self, other)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace assert statements with explicit exception handling

Using assert statements for type checking is not recommended in production code because they can be disabled when Python is run with optimization flags (e.g., python -O). To ensure robust error handling, consider raising explicit exceptions like TypeError.

Apply this diff to raise appropriate exceptions:

 def __sub__(self, other):
     if isinstance(other, (list, tuple)):
-        assert all([isinstance(item, Box) for item in other])
+        if not all(isinstance(item, Box) for item in other):
+            raise TypeError("All items in 'other' must be instances of Box")
         return remove_all(self, other)
-    assert isinstance(other, Box)
+    if not isinstance(other, Box):
+        raise TypeError("'other' must be an instance of Box")
     return remove(self, other)

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

Comment on lines +118 to +119
if (NOT EXISTS ${GTEST_ROOT})
execute_process(COMMAND ${Git} clone https://github.com/google/googletest ${GTEST_ROOT})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Define the Git executable before using it.

The variable ${Git} is used but not defined, which may lead to errors during the build process. Ensure that the Git executable is properly located.

Suggested correction:

+    find_package(Git REQUIRED)
     if (NOT EXISTS ${GTEST_ROOT})
-      execute_process(COMMAND ${Git} clone https://github.com/google/googletest ${GTEST_ROOT})
+      execute_process(COMMAND ${GIT_EXECUTABLE} clone https://github.com/google/googletest ${GTEST_ROOT})
     endif()
📝 Committable suggestion

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

Suggested change
if (NOT EXISTS ${GTEST_ROOT})
execute_process(COMMAND ${Git} clone https://github.com/google/googletest ${GTEST_ROOT})
find_package(Git REQUIRED)
if (NOT EXISTS ${GTEST_ROOT})
execute_process(COMMAND ${GIT_EXECUTABLE} clone https://github.com/google/googletest ${GTEST_ROOT})
endif()

Comment on lines +352 to +355
for (auto i = min_; i <= max_; ++i)
array(i) = val;

for (std::size_t i = shape[0] - 1 - max_; i <= shape[0] - 1 - min_; ++i)
for (auto i = shape[0] - 1 - max_; i <= shape[0] - 1 - min_; ++i)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Possible out-of-bounds access in fill1D due to loop boundaries

In the fill1D method, the loop boundaries might lead to out-of-bounds access when min_ or max_ have values that are not properly constrained. Specifically:

  • The first loop:

    for (auto i = min_; i <= max_; ++i)
        array(i) = val;
  • The second loop:

    for (auto i = shape[0] - 1 - max_; i <= shape[0] - 1 - min_; ++i)
        array(i) = val;

If min_ or max_ are larger than shape[0] / 2, the indices could go beyond the array bounds. Ensure that min_ and max_ are validated against the array dimensions to prevent potential segmentation faults.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 16

🧹 Outside diff range and nitpick comments (37)
tools/python3/git.py (1)

1-35: Consider implementing a common error handling strategy.

There's a consistent pattern of direct subprocess calls without proper error handling across all functions. Consider implementing a decorator or helper function to standardize error handling and input validation across all Git operations.

Example implementation:

def git_operation(func):
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except subprocess.CalledProcessError as e:
            raise RuntimeError(f"Git operation failed: {e.stderr.decode() if e.stderr else str(e)}")
        except Exception as e:
            raise RuntimeError(f"Unexpected error during git operation: {str(e)}")
    return wrapper

This decorator could then be applied to all functions:

@git_operation
def current_branch():
    return decode_bytes(run("git branch --show-current", check=True).stdout)
🧰 Tools
🪛 Ruff

22-22: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


29-29: Undefined name delete_branch

(F821)

tests/simulator/advance/test_particles_advance_3d.py (1)

16-18: Consider parameterizing test constants

These hardcoded test parameters could be moved to a configuration file or test fixtures to make the tests more maintainable and reusable.

-ndim = 3
-interp_orders = [1, 2, 3]
-ppc = 5
+from .test_config import TEST_DIMENSIONS, INTERPOLATION_ORDERS, PARTICLES_PER_CELL
+
+ndim = TEST_DIMENSIONS["3D"]
+interp_orders = INTERPOLATION_ORDERS
+ppc = PARTICLES_PER_CELL
tools/python3/cmake.py (2)

8-14: Enhance docstring and add input validation.

The docstring should document all parameters and their purpose. Additionally, the path parameter should be validated.

 def make_config_str(
     path, samrai_dir=None, cxx_flags=None, use_ninja=False, use_ccache=False, extra=""
 ):
     """
-    FULL UNPORTABLE OPTIMIZATIONS = cxx_flags="-O3 -march=native -mtune=native"
+    Constructs a CMake configuration command string.
+
+    Args:
+        path: Path to the CMake project directory
+        samrai_dir: Optional path to SAMRAI installation
+        cxx_flags: Optional C++ compiler flags (e.g. "-O3 -march=native -mtune=native")
+        use_ninja: Whether to use Ninja build system
+        use_ccache: Whether to use ccache
+        extra: Additional CMake options
+
+    Returns:
+        str: Formatted CMake command
     """
+    if not path or not isinstance(path, str):
+        raise ValueError("Path must be a non-empty string")

30-31: Add validation for threads parameter.

The threads parameter should be validated to ensure it's a positive integer.

 def build(use_ninja=False, threads=1):
+    if not isinstance(threads, int) or threads < 1:
+        raise ValueError("threads must be a positive integer")
     run("ninja" if use_ninja else f"make -j{threads}", capture_output=False)
res/amr/splitting.yml (1)

102-102: Remove unnecessary empty line

This empty line creates inconsistent spacing between dimension sections.

tests/simulator/advance/test_fields_advance_3d.py (3)

6-14: Consider grouping related imports together.

The imports could be better organized by grouping them into standard library, third-party, and local imports.

 import unittest
-
 import matplotlib
 from ddt import data, ddt, unpack
-from pyphare.core.box import Box3D
-
 from tests.simulator.test_advance import AdvanceTestBase
+from pyphare.core.box import Box3D

 matplotlib.use("Agg")  # for systems without GUI

16-23: Add type hints and improve documentation.

The global constants and helper function would benefit from better documentation and type hints.

+# Constants for test configuration
 ndim = 3
 interp_orders = [1, 2, 3]
 ppc, cells = 10, 30

-def per_interp(dic):
+def per_interp(dic: dict) -> list[tuple[int, dict]]:
+    """Generate test cases for each interpolation order.
+    
+    Args:
+        dic: Dictionary containing test configuration
+    Returns:
+        List of tuples containing (interpolation_order, test_config)
+    """
     return [(interp, dic) for interp in interp_orders]

33-47: Add docstring to test method.

The test method should document its purpose, parameters, and expected behavior.

 def test_overlaped_fields_are_equal(self, interp_order, refinement_boxes):
+    """Test that overlapped fields maintain equality after advancement.
+    
+    Args:
+        interp_order: Interpolation order for the test
+        refinement_boxes: Dictionary defining the refinement box configuration
+    """
     print(f"{self._testMethodName}_{ndim}d")
tests/functional/harris/harris_3d.py (3)

22-22: Consider making the output directory configurable

The diagnostic output path is hardcoded. Consider making it configurable through environment variables or command-line arguments for better flexibility across different environments.

-diag_outputs = "phare_outputs/test/harris/3d"
+diag_outputs = os.getenv("PHARE_OUTPUT_DIR", "phare_outputs/test/harris/3d")

68-70: Document or extract magic numbers as named constants

The code contains several magic numbers (0.2, 1.0, 0.5) that would benefit from documentation or extraction as named constants to improve maintainability and understanding of the physics model.

+# Physical constants for the Harris sheet model
+MAGNETIC_PERTURBATION_AMPLITUDE = 0.2  # Amplitude of magnetic perturbation
+GAUSSIAN_WIDTH = 1.0  # Width of the Gaussian perturbation
+SHEET_THICKNESS = 0.5  # Thickness of the current sheet

 def by(x, y, z):
     Lx = sim.simulation_domain()[0]
     Ly = sim.simulation_domain()[1]
-    w1 = 0.2
-    w2 = 1.0
+    w1 = MAGNETIC_PERTURBATION_AMPLITUDE
+    w2 = GAUSSIAN_WIDTH

Also applies to: 81-83


145-154: Remove or document commented-out code

The file contains several blocks of commented-out plotting code. If these are for future implementation, consider adding TODO comments. If they're no longer needed, consider removing them to improve code clarity.

Also applies to: 165-171

tests/simulator/refined_particle_nbr.py (1)

44-47: Improve code clarity with better naming and documentation

The variable name 'dim2' doesn't clearly convey its purpose as the border cell particle count for 2D case.

-    dim2 = refined_particle_nbr * ((cellNbr[0] * 2 + (cellNbr[1] * 2)))
+    # Calculate border cell particle count for 2D plane (X and Y faces)
+    border_particles_2d = refined_particle_nbr * ((cellNbr[0] * 2 + (cellNbr[1] * 2)))
     if dim == 2:
-        return dim2
-    return dim2 * (cellNbr[2] * 2)
+        return border_particles_2d
+    # For 3D, multiply by Z-axis face contributions
+    return border_particles_2d * (cellNbr[2] * 2)
pyphare/pyphare/core/box.py (2)

185-198: Consider optimizing the implementation for better performance

The current implementation could be improved in terms of performance and readability:

  1. Use list comprehension instead of explicit loops
  2. Avoid modifying lists while iterating
  3. Make the empty list check more pythonic
 def remove_all(box, to_remove):
-    if len(to_remove) > 0:
-        remaining = box - to_remove[0]
-        for to_rm in to_remove[1:]:
-            tmp, remove = [], []
-            for i, rem in enumerate(remaining):
-                if rem * to_rm is not None:
-                    remove.append(i)
-                    tmp += rem - to_rm
-            for rm in reversed(remove):
-                del remaining[rm]
-            remaining += tmp
-        return remaining
-    return box
+    if not to_remove:
+        return box
+    
+    remaining = box - to_remove[0]
+    for to_rm in to_remove[1:]:
+        # Use list comprehension to avoid explicit temporary lists
+        remaining = [
+            piece
+            for rem in remaining
+            for piece in (rem - to_rm if rem * to_rm is not None else [rem])
+        ]
+    return remaining

209-223: Enhance error handling and documentation

The class implementation could benefit from:

  1. More robust error handling for invalid inputs
  2. Type hints for better code maintainability
  3. More comprehensive docstring with all supported operations
+from typing import Union, Any
+import numpy as np
+
 class DataSelector:
     """
-        can't assign return to function unless []
-        usage
-        DataSelector(data)[box] = val
+    A wrapper class for array-like data that supports Box-based indexing.
+    
+    Args:
+        data: Array-like object to be wrapped
+    
+    Examples:
+        >>> selector = DataSelector(data)
+        >>> subset = selector[Box([0,0], [1,1])]  # Get subset
+        >>> selector[Box([0,0], [1,1])] = value   # Set subset
     """
-    def __init__(self, data):
+    def __init__(self, data: np.ndarray):
+        if not isinstance(data, np.ndarray):
+            raise TypeError("Data must be a numpy array")
         self.data = data
-    def __getitem__(self, box_or_slice):
+
+    def __getitem__(self, box_or_slice: Union[Box, slice]) -> Any:
         if isinstance(box_or_slice, Box):
             return select(self.data, box_or_slice)
+        if not isinstance(box_or_slice, slice):
+            raise TypeError("Index must be a Box or slice")
         return self.data[box_or_slice]
 
-    def __setitem__(self, box_or_slice, val):
+    def __setitem__(self, box_or_slice: Union[Box, slice], val: Any) -> None:
         self.__getitem__(box_or_slice)[:] = val
src/amr/data/particles/refine/split_2d.hpp (4)

Line range hint 42-53: Consider simplifying the complex delta calculations in BrownPattern

The nested loop structure with offset calculations could be made more readable by extracting the delta calculations into a helper function or using a lookup table for the sign patterns.

Consider refactoring to:

template<typename Delta>
constexpr BrownPattern(float const weight, Delta const& delta)
    : Super{weight}
{
    static constexpr std::array<std::pair<int, int>, 2> signs = {{{1, 1}, {-1, -1}}};
    for (std::size_t i = 0; i < signs.size(); i++) {
        const auto [signX, signY] = signs[i];
        const std::size_t offset = i * 4;
        Super::deltas_[0 + offset] = {-delta[0] * signX, delta[1] * signY};
        Super::deltas_[1 + offset] = {-delta[1] * signX, delta[0] * signY};
        Super::deltas_[2 + offset] = {delta[0] * signX, delta[1] * signY};
        Super::deltas_[3 + offset] = {delta[1] * signX, delta[0] * signY};
    }
}

Line range hint 74-327: Add documentation for weight and delta value derivations

The weight and delta values appear to be carefully chosen constants, but their derivation and significance are not documented. This makes it difficult to verify their correctness or modify them in the future.

Consider adding comments explaining:

  1. The mathematical basis for these constants
  2. How they ensure conservation properties
  3. References to relevant physics papers or documentation

Line range hint 1-7: Enhance documentation with implementation details

While the link to the wiki is helpful, consider adding more inline documentation about:

  1. The relationship between interpolation order and pattern selection
  2. The criteria for choosing between different pattern combinations
  3. Performance implications of different configurations

Add a detailed comment block:

/*
 * Splitting reference material can be found @
 *   https://github.com/PHAREHUB/PHARE/wiki/SplitPattern
 *
 * Implementation notes:
 * - Pattern selection depends on interpolation order and desired accuracy
 * - Higher interpolation orders use more complex pattern combinations
 * - Performance scales with number of refined particles
 * - Weight conservation is maintained across all patterns
 */

227-228: Consider using template metaprogramming for pattern combination generation

The pattern combinations for higher-order interpolations (e.g., 16 and 25 particles) show a regular structure that could be generated using template metaprogramming.

This would:

  1. Reduce potential maintenance errors
  2. Make the pattern scaling more explicit
  3. Allow easier extension to higher orders

Also applies to: 324-326

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

Line range hint 87-188: Improve readability by renaming ambiguous variable.

The 3D periodicity shifts implementation is correct, but the variable name 'l' in list comprehensions is ambiguous.

Apply this diff to improve readability:

-            f"{k}front": [(v[0], v[1], shape_z) for v in l] for k, l in shifts.items()
+            f"{k}front": [(v[0], v[1], shape_z) for v in shift_list] for k, shift_list in shifts.items()

Similar changes should be applied to other occurrences of 'l' in list comprehensions.

🧰 Tools
🪛 Ruff

161-161: Ambiguous variable name: l

(E741)


164-164: Ambiguous variable name: l

(E741)


167-167: Ambiguous variable name: l

(E741)


188-188: Ambiguous variable name: l

(E741)

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

390-427: Consider optimizing the 3D fill implementation.

The current implementation, while correct, could benefit from performance improvements:

  1. Consider using OpenMP parallel for loops for large arrays
  2. Consider using SIMD instructions for the innermost loops
  3. Consider combining similar loops to reduce loop overhead

535-598: Add documentation explaining the 3D mapping strategy.

The 3D implementation is complex and would benefit from documentation explaining:

  • The mapping strategy between inner and outer views
  • The order of face/edge/corner copying
  • The rationale behind using the corner lambda
tests/simulator/test_initialization.py (3)

254-254: Inconsistent parameter naming across test methods.

Some methods use dim while others use ndim. This inconsistency could lead to confusion.

Standardize the parameter naming across all test methods to use either dim or ndim consistently.

Also applies to: 356-357, 417-417, 566-566


423-426: Consider documenting empirical deviation thresholds.

The empirical deviation thresholds, especially for 3D (0.2), are significantly higher than 1D/2D. This might indicate potential precision issues in 3D simulations.

Consider adding a comment explaining why these specific thresholds were chosen and what they represent.


582-582: Fix unused loop variable.

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

-for pi, patch in enumerate(datahier.level(0).patches):
+for _pi, patch in enumerate(datahier.level(0).patches):
🧰 Tools
🪛 Ruff

582-582: Loop control variable pi not used within loop body

Rename unused pi to _pi

(B007)

pyphare/pyphare/pharesee/hierarchy/hierarchy.py (3)

559-561: Add proper documentation for the plot3d method.

The method lacks proper documentation explaining its behavior, parameters, and limitations. The "!HAX!" comment suggests this is a temporary solution, which should be documented.

     def plot3d(self, **kwargs):
-        """!HAX!"""
+        """Plot 3D data by reducing it to 2D.
+
+        This method takes a slice from the middle of the z-dimension and plots it as a 2D visualization.
+        Note: This is a temporary solution that modifies the data structures in-place.
+
+        Args:
+            **kwargs: Keyword arguments passed to plot2d method.
+        Returns:
+            tuple: Figure and axes objects from matplotlib.
+        """

567-567: Rename unused loop variable.

The loop control variable lvl is not used within the loop body.

-        for lvl_nbr, lvl in self.levels(time).items():
+        for lvl_nbr, _lvl in self.levels(time).items():
🧰 Tools
🪛 Ruff

567-567: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)


588-588: Remove informal comment.

The shrug emoticon comment is informal and doesn't provide meaningful information about the code's behavior.

-        return self.plot2d(**kwargs)  # ¯\_(ツ)_/¯
+        return self.plot2d(**kwargs)  # Delegate to plot2d after reducing dimensionality
tests/simulator/test_advance.py (1)

493-493: Define magic number as a constant.

The magic number -144123 should be defined as a named constant at the class level for better maintainability and clarity.

+# At class level
+COARSE_TEST_MARKER = -144123  # Marker value for coarsening test verification

# In the method
-boxm.DataSelector(afterCoarse)[dataBox] = -144123
+boxm.DataSelector(afterCoarse)[dataBox] = self.COARSE_TEST_MARKER
res/cmake/funcs.cmake (1)

107-109: Implement or remove the empty function add_phare_build_test

The function add_phare_build_test is currently empty. Consider implementing its functionality or removing it if it's not required to avoid confusion.

src/amr/data/particles/refine/split_3d.hpp (8)

133-134: Simplify delta and weight by using float instead of single-element arrays

Since delta and weight contain only one value each, using std::array<float, 1> adds unnecessary complexity. Consider defining them as float variables for simplicity and improved readability.

Apply this diff:

-static constexpr std::array<float, 1> delta  = {.966431};
-static constexpr std::array<float, 1> weight = {.166666};
+static constexpr float delta  = 0.966431f;
+static constexpr float weight = 0.166666f;

Update the constructor initialization accordingly:

-    constexpr Splitter()
-        : SplitPattern_3_1_6_Dispatcher{{weight[0], delta[0]}}
+    constexpr Splitter()
+        : SplitPattern_3_1_6_Dispatcher{{weight, delta}}

151-152: Simplify delta and weight by using float instead of single-element arrays

Similar to the previous suggestion, define delta and weight as float variables to simplify the code.

Apply this diff:

-static constexpr std::array<float, 1> delta  = {.74823};
-static constexpr std::array<float, 1> weight = {.083333};
+static constexpr float delta  = 0.74823f;
+static constexpr float weight = 0.083333f;

Update the constructor accordingly:

-    constexpr Splitter()
-        : SplitPattern_3_1_12_Dispatcher{{weight[0], delta[0]}}
+    constexpr Splitter()
+        : SplitPattern_3_1_12_Dispatcher{{weight, delta}}

172-173: Provide comments explaining the constants in delta and weight

The specific values assigned to delta and weight may not be immediately clear to readers. Adding comments to explain their origin or significance can enhance code understanding and maintainability.


193-194: Simplify delta and weight by using float instead of single-element arrays

Consistently define delta and weight as float variables when they contain only one value.

Apply this diff:

-static constexpr std::array<float, 1> delta  = {1.149658};
-static constexpr std::array<float, 1> weight = {.166666};
+static constexpr float delta  = 1.149658f;
+static constexpr float weight = 0.166666f;

Update the constructor:

-    constexpr Splitter()
-        : SplitPattern_3_2_6_Dispatcher{{weight[0], delta[0]}}
+    constexpr Splitter()
+        : SplitPattern_3_2_6_Dispatcher{{weight, delta}}

211-212: Simplify delta and weight by using float instead of single-element arrays

For consistency and simplicity, use float variables for delta and weight.

Apply this diff:

-static constexpr std::array<float, 1> delta  = {.888184};
-static constexpr std::array<float, 1> weight = {.083333};
+static constexpr float delta  = 0.888184f;
+static constexpr float weight = 0.083333f;

And update the constructor:

-    constexpr Splitter()
-        : SplitPattern_3_2_12_Dispatcher{{weight[0], delta[0]}}
+    constexpr Splitter()
+        : SplitPattern_3_2_12_Dispatcher{{weight, delta}}

252-253: Simplify delta and weight by using float instead of single-element arrays

Again, define delta and weight as float variables for clarity.

Apply this diff:

-static constexpr std::array<float, 1> delta  = {1.312622};
-static constexpr std::array<float, 1> weight = {.166666};
+static constexpr float delta  = 1.312622f;
+static constexpr float weight = 0.166666f;

Update the constructor:

-    constexpr Splitter()
-        : SplitPattern_3_3_6_Dispatcher{{weight[0], delta[0]}}
+    constexpr Splitter()
+        : SplitPattern_3_3_6_Dispatcher{{weight, delta}}

270-271: Simplify delta and weight by using float instead of single-element arrays

Maintain consistency by defining delta and weight as float variables.

Apply this diff:

-static constexpr std::array<float, 1> delta  = {1.012756};
-static constexpr std::array<float, 1> weight = {.083333};
+static constexpr float delta  = 1.012756f;
+static constexpr float weight = 0.083333f;

Update the constructor:

-    constexpr Splitter()
-        : SplitPattern_3_3_12_Dispatcher{{weight[0], delta[0]}}
+    constexpr Splitter()
+        : SplitPattern_3_3_12_Dispatcher{{weight, delta}}

172-173: Provide comments explaining the constants in delta and weight arrays

In these instances, delta and weight are arrays with multiple values. Adding comments to describe the significance of these constants, such as their mathematical derivation or role in the algorithm, can improve code comprehension.

Also applies to: 232-233, 291-292

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1378a02 and 669224a.

📒 Files selected for processing (44)
  • .github/workflows/cmake_macos.yml (1 hunks)
  • pyphare/pyphare/core/box.py (2 hunks)
  • pyphare/pyphare/core/gridlayout.py (1 hunks)
  • pyphare/pyphare/pharesee/geometry.py (7 hunks)
  • pyphare/pyphare/pharesee/hierarchy/hierarchy.py (1 hunks)
  • pyphare/pyphare/pharesee/run/utils.py (1 hunks)
  • res/amr/splitting.yml (1 hunks)
  • res/cmake/funcs.cmake (1 hunks)
  • res/cmake/options.cmake (2 hunks)
  • src/amr/data/field/coarsening/magnetic_field_coarsener.hpp (1 hunks)
  • src/amr/data/particles/refine/split.hpp (1 hunks)
  • src/amr/data/particles/refine/split_1d.hpp (10 hunks)
  • src/amr/data/particles/refine/split_2d.hpp (17 hunks)
  • src/amr/data/particles/refine/split_3d.hpp (1 hunks)
  • src/amr/data/particles/refine/splitter.hpp (2 hunks)
  • src/core/data/grid/gridlayoutdefs.hpp (2 hunks)
  • src/core/data/ndarray/ndarray_vector.hpp (8 hunks)
  • src/core/utilities/box/box.hpp (3 hunks)
  • src/core/utilities/meta/meta_utilities.hpp (2 hunks)
  • tests/amr/data/field/refine/test_refine_field.py (1 hunks)
  • tests/amr/data/particles/refine/input/input_3d_ratio_2.txt (1 hunks)
  • tests/amr/data/particles/refine/test_split.cpp (1 hunks)
  • tests/core/data/ndarray/test_main.cpp (1 hunks)
  • tests/core/numerics/interpolator/test_main.cpp (1 hunks)
  • tests/diagnostic/CMakeLists.txt (1 hunks)
  • tests/diagnostic/job_3d.py.in (1 hunks)
  • tests/diagnostic/test-diagnostics_3d.cpp (1 hunks)
  • tests/functional/harris/harris_3d.py (1 hunks)
  • tests/simulator/__init__.py (2 hunks)
  • tests/simulator/advance/CMakeLists.txt (1 hunks)
  • tests/simulator/advance/test_fields_advance_3d.py (1 hunks)
  • tests/simulator/advance/test_particles_advance_3d.py (1 hunks)
  • tests/simulator/initialize/CMakeLists.txt (1 hunks)
  • tests/simulator/initialize/test_fields_init_2d.py (1 hunks)
  • tests/simulator/initialize/test_fields_init_3d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_1d.py (0 hunks)
  • tests/simulator/initialize/test_particles_init_2d.py (1 hunks)
  • tests/simulator/initialize/test_particles_init_3d.py (1 hunks)
  • tests/simulator/per_test.hpp (1 hunks)
  • tests/simulator/refined_particle_nbr.py (2 hunks)
  • tests/simulator/test_advance.py (6 hunks)
  • tests/simulator/test_initialization.py (13 hunks)
  • tools/python3/cmake.py (1 hunks)
  • tools/python3/git.py (1 hunks)
💤 Files with no reviewable changes (1)
  • tests/simulator/initialize/test_particles_init_1d.py
✅ Files skipped from review due to trivial changes (1)
  • src/amr/data/particles/refine/split.hpp
🚧 Files skipped from review as they are similar to previous changes (21)
  • .github/workflows/cmake_macos.yml
  • pyphare/pyphare/core/gridlayout.py
  • pyphare/pyphare/pharesee/run/utils.py
  • res/cmake/options.cmake
  • src/amr/data/field/coarsening/magnetic_field_coarsener.hpp
  • src/amr/data/particles/refine/split_1d.hpp
  • src/amr/data/particles/refine/splitter.hpp
  • src/core/data/grid/gridlayoutdefs.hpp
  • src/core/utilities/box/box.hpp
  • src/core/utilities/meta/meta_utilities.hpp
  • tests/amr/data/particles/refine/input/input_3d_ratio_2.txt
  • tests/amr/data/particles/refine/test_split.cpp
  • tests/core/data/ndarray/test_main.cpp
  • tests/diagnostic/CMakeLists.txt
  • tests/diagnostic/job_3d.py.in
  • tests/simulator/advance/CMakeLists.txt
  • tests/simulator/initialize/CMakeLists.txt
  • tests/simulator/initialize/test_fields_init_2d.py
  • tests/simulator/initialize/test_fields_init_3d.py
  • tests/simulator/initialize/test_particles_init_2d.py
  • tests/simulator/initialize/test_particles_init_3d.py
🧰 Additional context used
📓 Path-based instructions (4)
src/amr/data/particles/refine/split_2d.hpp (1)

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

src/amr/data/particles/refine/split_3d.hpp (1)

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

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

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

tests/simulator/per_test.hpp (1)

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

🪛 Ruff
pyphare/pyphare/core/box.py

207-207: Ambiguous variable name: l

(E741)

pyphare/pyphare/pharesee/geometry.py

161-161: Ambiguous variable name: l

(E741)


164-164: Ambiguous variable name: l

(E741)


167-167: Ambiguous variable name: l

(E741)


188-188: Ambiguous variable name: l

(E741)

pyphare/pyphare/pharesee/hierarchy/hierarchy.py

567-567: Loop control variable lvl not used within loop body

Rename unused lvl to _lvl

(B007)

tests/amr/data/field/refine/test_refine_field.py

106-106: Do not assert False (python -O removes these calls), raise AssertionError()

Replace assert False

(B011)

tests/functional/harris/harris_3d.py

62-62: Ambiguous variable name: l

(E741)

tests/simulator/__init__.py

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

Replace with None; initialize within function

(B006)

tests/simulator/test_advance.py

89-89: Ambiguous variable name: l

(E741)

tests/simulator/test_initialization.py

394-394: Function definition does not bind loop variable select

(B023)


396-396: Function definition does not bind loop variable patch

(B023)


396-396: Function definition does not bind loop variable nbrGhosts

(B023)


397-397: Function definition does not bind loop variable select

(B023)


582-582: Loop control variable pi not used within loop body

Rename unused pi to _pi

(B007)


586-586: Yoda condition detected

Rewrite as ppc == H

(SIM300)


664-664: Local variable out is assigned to but never used

Remove assignment to unused variable out

(F841)

tools/python3/cmake.py

48-48: Undefined name cmd

(F821)

tools/python3/git.py

22-22: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


29-29: Undefined name delete_branch

(F821)

🪛 cppcheck
tests/diagnostic/test-diagnostics_3d.cpp

[performance] 24-24: Function parameter 'path' should be passed by const reference.

(passedByValue)

🔇 Additional comments (33)
tests/diagnostic/test-diagnostics_3d.cpp (3)

1-8: LGTM! Header includes and constants are well-defined.

The includes are minimal and necessary, and the constants follow proper naming conventions.


9-27: Test structure follows Google Test best practices.

The test cases are well-organized and follow proper testing patterns.

The previous suggestion about refactoring repeated code patterns in test cases is still valid and would improve maintainability.

🧰 Tools
🪛 cppcheck

[performance] 24-24: Function parameter 'path' should be passed by const reference.

(passedByValue)


30-35: LGTM! Main function properly initializes test environment.

The setup includes both Google Test initialization and PHARE lifecycle management, following best practices.

tests/simulator/advance/test_particles_advance_3d.py (1)

6-14: LGTM: Appropriate imports and matplotlib configuration

The imports are well-organized and the non-GUI matplotlib backend is correctly configured for CI environments.

res/amr/splitting.yml (3)

105-115: Well-structured 3D particle configurations

The particle counts (6, 12, and 27) appropriately represent face-centered, edge-centered, and volumetric splitting patterns in 3D space.

Also applies to: 118-128, 131-141


107-107: Verify weight distribution validation

The weights appear to be normalized across configurations, but it would be beneficial to verify:

  1. The mathematical basis for these specific weight values
  2. Whether these weights have been validated in 3D test scenarios

Also applies to: 111-111, 115-115, 120-120, 124-124, 128-128, 133-133, 137-137, 141-141

✅ Verification successful

Weight distribution is mathematically validated

The weight distributions in the YAML file are mathematically sound and follow a consistent pattern:

  • For dimension_3, each interpolation level maintains weight normalization:
    • N_particles_6: 6 * 0.166666 ≈ 1.0
    • N_particles_12: 12 * 0.083333 ≈ 1.0
    • N_particles_27: 8 * 0.125 + 19 * 0.0625 = 1.0 (interp_1)
    • Similar balanced distributions for interp_2 and interp_3

The weights are carefully chosen to ensure particle conservation and proper normalization across different refinement levels and interpolation schemes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for weight validation tests in the test suite
rg -l "N_particles_(6|12|27).*weight" --type cpp --type python | while read -r file; do
    echo "=== $file ==="
    rg "assert|expect" -C 2 "$file"
done

Length of output: 110


Script:

#!/bin/bash
# Search for test files with any extension
fd "test" --type f | while read -r file; do
    echo "=== $file ==="
    rg "N_particles_(6|12|27).*weight" -C 2 "$file"
done

# Also search for weight validation in source files
rg "N_particles_(6|12|27).*weight" -C 2

Length of output: 32063


Script:

#!/bin/bash
# Look for documentation or comments about weight validation
rg -C 3 "weight.*validation|weight.*distribution" 

Length of output: 51


Script:

#!/bin/bash
# Check the YAML file directly to understand the weight distribution context
cat res/amr/splitting.yml

Length of output: 2454


103-141: Clarify scope of missing 3D patterns

The PR description mentions that only some 3D split patterns are included. Could you please:

  1. Document which additional patterns are planned for future implementation
  2. Confirm if the current set of patterns (6, 12, and 27 particles) is sufficient for initial functionality
tests/simulator/per_test.hpp (1)

111-117: The 3D test structure is well-defined but has limited parameter combinations.

The test structure follows the established pattern used for 1D and 2D tests. However, all three parameter combinations use the same refinement level (6), which might not provide sufficient coverage for different scenarios.

Note: A previous review comment already suggested expanding the 3D test coverage with additional parameter combinations. Please refer to that comment for detailed recommendations.

tests/simulator/advance/test_fields_advance_3d.py (1)

79-91: ⚠️ Potential issue

Implement the 3D coarsening test.

The PR objectives mention "some coarsening tests missing" and this test is crucial for validating 3D coarsening functionality. The test patterns are consistent with 1D and 2D implementations, and the base implementation in test_advance.py already supports 3D cases.

✅ Verification successful

Let me gather more information about the base implementation mentioned in the review comment.


Let me check one more thing to understand the base implementation location.


Uncomment and implement the 3D coarsening test

The review comment is correct. The evidence shows that:

  1. The base implementation _test_field_coarsening_via_subcycles exists and is used by 1D and 2D tests
  2. The 3D test is already written but commented out, with appropriate test cases using Box3D
  3. The implementation follows the same pattern as 1D and 2D versions
  4. The test data includes comprehensive cases covering single boxes, multiple boxes, and multi-level scenarios

Simply uncomment the test method and its test data to enable 3D coarsening validation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify coarsening test implementations in other dimensions
echo "=== 1D implementation ==="
rg "test_field_coarsening_via_subcycles" tests/simulator/advance/test_fields_advance_1d.py -A 5
echo -e "\n=== 2D implementation ==="
rg "test_field_coarsening_via_subcycles" tests/simulator/advance/test_fields_advance_2d.py -A 5

Length of output: 1096


Script:

#!/bin/bash
# Check the base implementation in test_advance.py
echo "=== Base implementation ==="
rg "_test_field_coarsening_via_subcycles" tests/simulator/advance/test_advance.py -A 10

# Check if the 3D test is actually implemented but just commented out
echo -e "\n=== 3D implementation status ==="
rg "test_field_coarsening_via_subcycles" tests/simulator/advance/test_fields_advance_3d.py -B 5 -A 5

Length of output: 1165


Script:

#!/bin/bash
# Find the actual base implementation location
echo "=== Finding base implementation ==="
fd -t f -e py advance --exec rg "_test_field_coarsening_via_subcycles" {} -l

# Check the implementation if found
echo -e "\n=== Base implementation details ==="
fd -t f -e py advance --exec rg "_test_field_coarsening_via_subcycles" {} -A 10

Length of output: 2359

tests/functional/harris/harris_3d.py (2)

62-62: 🛠️ Refactor suggestion

Rename ambiguous parameter for clarity

The parameter l is ambiguous and could be confused with the number 1. Consider using a more descriptive name.

-def S(y, y0, l):
+def S(y, y0, scale_length):

Likely invalid or redundant comment.

🧰 Tools
🪛 Ruff

62-62: Ambiguous variable name: l

(E741)


184-184: Consider adding timeout to MPI barrier

The MPI barrier could potentially hang indefinitely if any rank fails. Consider implementing a timeout mechanism or error handling.

tests/simulator/refined_particle_nbr.py (4)

105-116: LGTM! Well-documented 3D test implementation

The 3D test implementation is well thought out with clear documentation explaining the refinement ratios and expectations.


139-144: LGTM! Good test execution order management

The test suite setup ensures proper test execution order, which is crucial for dependency management between tests.


33-37: 🛠️ Refactor suggestion

Add exception handling to tearDown method

While the None check is good, the method should handle potential exceptions during reset to ensure proper cleanup.

 def tearDown(self):
     if self.simulator is not None:
-        self.simulator.reset()
+        try:
+            self.simulator.reset()
+        except Exception as e:
+            print(f"Warning: Error during simulator reset: {e}")
+            # Ensure we don't mask test failures
+            if self._outcome.success:
+                raise

Likely invalid or redundant comment.


117-135: Verify YAML configuration existence

The method assumes the YAML configuration contains all necessary values. Consider adding validation.

pyphare/pyphare/core/box.py (1)

201-204: LGTM!

The coordinate translation logic is correct and well-implemented.

tests/simulator/__init__.py (2)

97-107: LGTM! Consider adding test coverage.

The 3D periodic density implementation correctly extends the existing pattern from 1D and 2D versions, with proper handling of domain boundaries and exponential decay for density calculation.


318-345: ⚠️ Potential issue

Fix mutable default argument and improve implementation.

The debug tracer implementation needs several improvements:

  1. The mutable default argument is a Python gotcha that could lead to unexpected behavior
  2. Missing cleanup mechanism to reset the profiler
  3. Exception handling could leave indentation in inconsistent state
🧰 Tools
🪛 Ruff

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

Replace with None; initialize within function

(B006)

pyphare/pyphare/pharesee/geometry.py (4)

59-74: LGTM! 3D ghost boxes implementation is correct and consistent.

The implementation properly handles all six faces of a 3D box while maintaining consistency with the existing 1D and 2D patterns.


184-188: LGTM! Good use of assertion for key uniqueness.

The assertion ensures that all shift keys are unique when sorted, preventing potential overlaps or conflicts in the shift dictionary.

🧰 Tools
🪛 Ruff

188-188: Ambiguous variable name: l

(E741)


520-520: LGTM! Correct implementation of remaining boxes calculation.

The implementation properly handles the calculation of remaining boxes after subtracting patch boxes.


380-414: ⚠️ Potential issue

Fix mutable default argument in function signature.

Using an empty list as a default argument can lead to unexpected behavior as it's shared between function calls.

Apply this diff to fix the issue:

-def get_periodic_list(patches, domain_box, n_ghosts=[]):
+def get_periodic_list(patches, domain_box, n_ghosts=None):
+    if n_ghosts is None:
+        n_ghosts = []

Likely invalid or redundant comment.

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

127-128: Previous comment about NO_DISCARD still applies.


533-534: Add bounds validation before array access.

While the assertions check the start/end relationships, consider adding bounds validation to ensure indices don't exceed array dimensions.

tests/core/numerics/interpolator/test_main.cpp (2)

776-783: Uncomment and implement the 3D test case.

The test case for validating 3D interpolation is commented out and needs to be implemented.


741-741: ⚠️ Potential issue

Fix grid layout initialization for 3D.

The grid layout initialization is missing the nz dimension, which is required for 3D tests.

-    GridLayout_t layout{ConstArray<double, dim>(.1), {nx, ny}, ConstArray<double, dim>(0)};
+    GridLayout_t layout{ConstArray<double, dim>(.1), {nx, ny, nz}, ConstArray<double, dim>(0)};

Likely invalid or redundant comment.

tests/simulator/test_initialization.py (1)

664-664: ⚠️ Potential issue

Remove unused variable.

The variable out is assigned but never used.

-out = "phare_outputs"

Likely invalid or redundant comment.

🧰 Tools
🪛 Ruff

664-664: Local variable out is assigned to but never used

Remove assignment to unused variable out

(F841)

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

595-596: LGTM: Plot method update for 3D support.

The update to the plot method correctly handles 3D cases by delegating to the plot3d method.

tests/simulator/test_advance.py (3)

265-273: LGTM! Improved data selection implementation.

The use of boxm.select for dataset slicing is a better approach, and the dtype check ensures data type consistency.


370-372: LGTM! Good default value for cells parameter.

The addition of a default value for the cells parameter makes the test more flexible while maintaining a reasonable test size.


89-91: 🛠️ Refactor suggestion

Rename parameter for better clarity.

The parameter l is ambiguous and could be confused with the number 1. Consider using a more descriptive name.

-def S(x, x0, l):
-    return 0.5 * (1 + np.tanh((x - x0) / l))
+def S(x, x0, transition_width):
+    return 0.5 * (1 + np.tanh((x - x0) / transition_width))

Likely invalid or redundant comment.

🧰 Tools
🪛 Ruff

89-89: Ambiguous variable name: l

(E741)

res/cmake/funcs.cmake (2)

118-119: Variable ${Git} is undefined

The previous review comment about defining the ${Git} executable before using it is still valid. Ensure that you locate the Git executable using find_package(Git REQUIRED) and replace ${Git} with ${GIT_EXECUTABLE}.


37-42: Avoid hardcoding environment variables

The previous review comment regarding hardcoding environment variables like PYTHONPATH and ASAN_OPTIONS is still applicable. Consider parameterizing these environment variables to enhance flexibility and adaptability.

Comment on lines +1 to +35

#include "core/def/phare_mpi.hpp"

#include "test_diagnostics.ipp"

static std::string const job_file = "job_3d";
static std::string const out_dir = "phare_outputs/diags_3d/";

TYPED_TEST(Simulator3dTest, fluid)
{
fluid_test(TypeParam{job_file}, out_dir);
}

TYPED_TEST(Simulator3dTest, particles)
{
particles_test(TypeParam{job_file}, out_dir);
}

TYPED_TEST(Simulator3dTest, electromag)
{
electromag_test(TypeParam{job_file}, out_dir);
}

TYPED_TEST(Simulator3dTest, allFromPython)
{
allFromPython_test(TypeParam{job_file}, out_dir);
}


int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
PHARE::SamraiLifeCycle samsam(argc, argv);
return RUN_ALL_TESTS();
}
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

3D test coverage needs expansion in specific areas

Based on the code analysis, there are clear gaps in 3D test coverage:

  1. 3D coarsening tests are explicitly disabled with a TODO comment in test_linear_coarsen.hpp:
using FieldCoarsenOperators = testing::Types<FieldCoarsenTestData<1>, FieldCoarsenTestData<2> /* , FieldCoarsenTestData<3>*/>; // TODO 3D
  1. The 3D coarsening implementation is marked as unsupported:
else if constexpr (dim == 3) // TODO 3D
{
    throw std::runtime_error("Unsupported dimension");
}
  1. While split patterns for 3D exist (split_3d.hpp), there are no corresponding tests verifying these patterns.

Action items:

  • Implement the missing 3D coarsening tests by uncommenting and completing the 3D test cases
  • Add test coverage for 3D split patterns
  • Remove the "Unsupported dimension" exception and implement the 3D coarsening verification logic
🔗 Analysis chain

Consider expanding 3D test coverage.

Based on the PR description mentioning "some coarsening tests missing" and "only some 3d split patterns", consider adding additional test cases for:

  • Grid coarsening scenarios in 3D
  • Additional split patterns specific to 3D
  • Edge cases specific to 3D geometry

Let me gather more specific information about the test coverage.


Let me check specifically for coarsening tests in 3D and split patterns.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for existing 3D test coverage patterns
rg -l "3[dD].*test" --type cpp

Length of output: 418


Script:

#!/bin/bash
# Look for 3D test patterns and their context
rg "3[dD].*test" --type cpp -B 2 -A 5

# Look for coarsening tests
rg "coarsen.*test|test.*coarsen" --type cpp -B 2 -A 5

# Look for split pattern tests
rg "split.*test|test.*split" --type cpp -B 2 -A 5

Length of output: 8726


Script:

#!/bin/bash
# Look for 3D coarsening tests
rg -l "3[dD].*coarsen|coarsen.*3[dD]" --type cpp tests/amr/

# Check test_linear_coarsen.hpp content
fd -e hpp "test_linear_coarsen.hpp" -x cat {}

# Check test_weighter_coarsen.hpp content
fd -e hpp "test_weighter_coarsen.hpp" -x cat {}

# Look for split pattern tests in 3D context
rg "3[dD].*split|split.*3[dD]" -B 2 -A 5 --type cpp

Length of output: 17045

🧰 Tools
🪛 cppcheck

[performance] 24-24: Function parameter 'path' should be passed by const reference.

(passedByValue)

Comment on lines +13 to +16
def log(N=10, use_short=False):
# https://git-scm.com/docs/pretty-formats
short = '--pretty=format:"%h%x09%an%x09%ad%x09%s"' if use_short else ""
return decode_bytes(run(f"git log -{N} {short}").stdout)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add input validation and error handling.

The function needs improvements in two areas:

  1. Input validation for N to prevent command injection
  2. Error handling for subprocess failures
 def log(N=10, use_short=False):
+    if not isinstance(N, int) or N < 1:
+        raise ValueError("N must be a positive integer")
     # https://git-scm.com/docs/pretty-formats
     short = '--pretty=format:"%h%x09%an%x09%ad%x09%s"' if use_short else ""
-    return decode_bytes(run(f"git log -{N} {short}").stdout)
+    try:
+        return decode_bytes(run(f"git log -{N} {short}", check=True).stdout)
+    except subprocess.CalledProcessError:
+        raise RuntimeError("Failed to retrieve git log")

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

Comment on lines +25 to +48
@ddt
class AdvanceTest(AdvanceTestBase):
@data(
*per_interp({}),
*per_interp({"L0": [Box3D(10, 19)]}),
*per_interp({"L0": [Box3D(5, 9), Box3D(10, 14)]}),
)
@unpack
def test_overlapped_particledatas_have_identical_particles(
self, interp_order, refinement_boxes
):
self._test_overlapped_particledatas_have_identical_particles(
ndim,
interp_order,
refinement_boxes,
ppc=ppc,
cells=40,
largest_patch_size=20,
)

@data(*interp_orders)
def test_L0_particle_number_conservation(self, interp):
self._test_L0_particle_number_conservation(ndim, interp, ppc=ppc, cells=30)

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add missing 3D coarsening test cases

While the current tests cover particle identity and conservation, coarsening tests are still missing as mentioned in the PR description. Consider adding:

  1. Particle coarsening between different refinement levels
  2. Edge cases with multiple refinement boxes
  3. Conservation checks during coarsening operations

Here's a suggested structure for the coarsening test:

@data(*interp_orders)
def test_particle_coarsening_3d(self, interp):
    """Test particle coarsening operations in 3D scenarios."""
    refinement_boxes = {"L0": [Box3D(5, 15)], "L1": [Box3D(8, 12)]}
    self._test_particle_coarsening(
        ndim,
        interp,
        refinement_boxes,
        ppc=ppc,
        cells=30
    )

Would you like me to help implement the complete test cases?

Comment on lines +47 to +48
def run_test(test, verbose=False, capture_output=False):
run(test_cmd(cmd, verbose=verbose), capture_output=capture_output)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix undefined variable in run_test function.

The function uses an undefined variable cmd instead of the test parameter.

 def run_test(test, verbose=False, capture_output=False):
-    run(test_cmd(cmd, verbose=verbose), capture_output=capture_output)
+    run(test_cmd(test, verbose=verbose), capture_output=capture_output)
📝 Committable suggestion

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

Suggested change
def run_test(test, verbose=False, capture_output=False):
run(test_cmd(cmd, verbose=verbose), capture_output=capture_output)
def run_test(test, verbose=False, capture_output=False):
run(test_cmd(test, verbose=verbose), capture_output=capture_output)
🧰 Tools
🪛 Ruff

48-48: Undefined name cmd

(F821)

def config(
path, samrai_dir=None, cxx_flags=None, use_ninja=False, use_ccache=False, extra=""
):
cmd = make_config_str(path, samrai_dir, cxx_flags, use_ninja, extra)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix missing use_ccache parameter in make_config_str call.

The use_ccache parameter is not being passed to make_config_str, which means ccache will never be enabled.

-    cmd = make_config_str(path, samrai_dir, cxx_flags, use_ninja, extra)
+    cmd = make_config_str(path, samrai_dir, cxx_flags, use_ninja, use_ccache, extra)

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

pdat._x = pdat.x[:-1]
if primals[1]:
pdat._y = pdat.y[:-1]
pdat.dataset = pdat.dataset[:, :, int(pdat.ghost_box.shape[2] / 2)]
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid hardcoded slice selection.

The method always takes the middle slice of the z-dimension, which might not be the desired behavior for all use cases.

-                pdat.dataset = pdat.dataset[:, :, int(pdat.ghost_box.shape[2] / 2)]
+                slice_idx = kwargs.get('slice_idx', int(pdat.ghost_box.shape[2] / 2))
+                pdat.dataset = pdat.dataset[:, :, slice_idx]

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

Comment on lines +571 to +587
pdat = patch.patch_datas[qty]
primals = pdat.primal_directions()
if primals[0]:
pdat._x = pdat.x[:-1]
if primals[1]:
pdat._y = pdat.y[:-1]
pdat.dataset = pdat.dataset[:, :, int(pdat.ghost_box.shape[2] / 2)]
patch.box.lower = patch.box.lower[:-1]
patch.box.upper = patch.box.upper[:-1]
patch.box.ndim = 2

pdat.ghost_box.lower = pdat.ghost_box.lower[:-1]
pdat.ghost_box.upper = pdat.ghost_box.upper[:-1]
pdat.ghost_box.ndim = 2
pdat.size = np.copy(pdat.ghost_box.shape)
pdat.layout.dl = pdat.layout.dl[:-1]

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Consider creating a copy instead of modifying data in-place.

The current implementation modifies the patch data structures in-place, which could lead to unexpected behavior if the data is needed later in its original form.

+                # Create a copy of the patch data
+                pdat_copy = copy.deepcopy(pdat)
+                
+                # Modify the copy instead of the original
                 primals = pdat.primal_directions()
                 if primals[0]:
-                    pdat._x = pdat.x[:-1]
+                    pdat_copy._x = pdat.x[:-1]
                 if primals[1]:
-                    pdat._y = pdat.y[:-1]
+                    pdat_copy._y = pdat.y[:-1]
-                pdat.dataset = pdat.dataset[:, :, int(pdat.ghost_box.shape[2] / 2)]
+                slice_idx = kwargs.get('slice_idx', int(pdat.ghost_box.shape[2] / 2))
+                pdat_copy.dataset = pdat.dataset[:, :, slice_idx]

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

# phare_mpi_python3_exec
# if these function calls are to files executing python unit tests as they will interfere

if (test AND ${PHARE_EXEC_LEVEL_MIN} GREATER 0) # 0 = no tests
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Verify that the variable test is correctly defined

The variable test is used in the condition but may not be defined, which could cause unexpected behavior during the configuration process. Ensure that test is properly defined as a boolean option or variable before this point.

endfunction(add_phare_test_)

function(add_no_mpi_phare_test binary directory)
if(NOT testMPI OR (testMPI AND forceSerialTests))
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure forceSerialTests is defined before use

The variable forceSerialTests is used in the condition but may not be defined, which could lead to unexpected behavior. Make sure that forceSerialTests is defined and properly set before this function is called.

TARGET ${binary}
POST_BUILD
WORKING_DIRECTORY ${directory}
COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> -R \"^${binary}$$\" --output-on-failures
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Correct the CTest option: use --output-on-failure

The option --output-on-failures is incorrect. The correct option is --output-on-failure (without the trailing 's'). This ensures that output is displayed when a test fails.

Apply this diff to fix the typo:

-               COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> -R \"^${binary}$$\" --output-on-failures
+               COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> -R \"^${binary}$$\" --output-on-failure
📝 Committable suggestion

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

Suggested change
COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> -R \"^${binary}$$\" --output-on-failures
COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> -R \"^${binary}$$\" --output-on-failure

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WIP work in progress
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant