Repository: yt-project/yt

Issue:
BUG: upcoming incompatibility with numpy 2.0
### Bug report

**Bug summary**

nightly tests failed with a new deprecation warning from numpy: https://github.com/yt-project/yt/actions/runs/4320097513/jobs/7539982200

This should be resolved by just changing all our calls from `np.product` to `np.prod`


Discussion:

Resolving patch:
diff --git a/doc/source/cookbook/power_spectrum_example.py b/doc/source/cookbook/power_spectrum_example.py
--- a/doc/source/cookbook/power_spectrum_example.py
+++ b/doc/source/cookbook/power_spectrum_example.py
@@ -31,7 +31,7 @@ def doit(ds):
 
     max_level = ds.index.max_level
 
-    ref = int(np.product(ds.ref_factors[0:max_level]))
+    ref = int(np.prod(ds.ref_factors[0:max_level]))
 
     low = ds.domain_left_edge
     dims = ds.domain_dimensions * ref
diff --git a/yt/frontends/boxlib/io.py b/yt/frontends/boxlib/io.py
--- a/yt/frontends/boxlib/io.py
+++ b/yt/frontends/boxlib/io.py
@@ -78,7 +78,7 @@ def _read_raw_field(self, grid, field):
         with open(filename, "rb") as f:
             f.seek(offset)
             f.readline()  # always skip the first line
-            arr = np.fromfile(f, "float64", np.product(shape))
+            arr = np.fromfile(f, "float64", np.prod(shape))
             arr = arr.reshape(shape, order="F")
         return arr[
             tuple(
diff --git a/yt/utilities/decompose.py b/yt/utilities/decompose.py
--- a/yt/utilities/decompose.py
+++ b/yt/utilities/decompose.py
@@ -29,12 +29,12 @@ def evaluate_domain_decomposition(n_d, pieces, ldom):
     BEWARE: lot's of magic here"""
     eff_dim = (n_d > 1).sum()
     exp = float(eff_dim - 1) / float(eff_dim)
-    ideal_bsize = eff_dim * pieces ** (1.0 / eff_dim) * np.product(n_d) ** exp
+    ideal_bsize = eff_dim * pieces ** (1.0 / eff_dim) * np.prod(n_d) ** exp
     mask = np.where(n_d > 1)
     nd_arr = np.array(n_d, dtype=np.float64)[mask]
-    bsize = int(np.sum(ldom[mask] / nd_arr * np.product(nd_arr)))
-    load_balance = float(np.product(n_d)) / (
-        float(pieces) * np.product((n_d - 1) // ldom + 1)
+    bsize = int(np.sum(ldom[mask] / nd_arr * np.prod(nd_arr)))
+    load_balance = float(np.prod(n_d)) / (
+        float(pieces) * np.prod((n_d - 1) // ldom + 1)
     )
 
     # 0.25 is magic number


Test patch:
diff --git a/yt/data_objects/tests/test_covering_grid.py b/yt/data_objects/tests/test_covering_grid.py
--- a/yt/data_objects/tests/test_covering_grid.py
+++ b/yt/data_objects/tests/test_covering_grid.py
@@ -227,7 +227,7 @@ def test_arbitrary_grid():
                 dims = np.array(dims)
 
                 dds = (RE - LE) / dims
-                volume = ds.quan(np.product(dds), "cm**3")
+                volume = ds.quan(np.prod(dds), "cm**3")
 
                 obj = ds.arbitrary_grid(LE, RE, dims)
                 deposited_mass = obj[("deposit", "all_density")].sum() * volume
diff --git a/yt/utilities/tests/test_particle_generator.py b/yt/utilities/tests/test_particle_generator.py
--- a/yt/utilities/tests/test_particle_generator.py
+++ b/yt/utilities/tests/test_particle_generator.py
@@ -54,7 +54,7 @@ def test_particle_generator():
 
     def new_indices():
         # We just add new indices onto the existing ones
-        return np.arange(np.product(pdims)) + num_particles
+        return np.arange(np.prod(pdims)) + num_particles
 
     le = np.array([0.25, 0.25, 0.25])
     re = np.array([0.75, 0.75, 0.75])
@@ -97,7 +97,7 @@ def new_indices():
     # Test the uniqueness of tags
     tags = np.concatenate([grid[("all", "particle_index")] for grid in ds.index.grids])
     tags.sort()
-    assert_equal(tags, np.arange(np.product(pdims) + num_particles))
+    assert_equal(tags, np.arange(np.prod(pdims) + num_particles))
 
     del tags
 
@@ -108,7 +108,7 @@ def new_indices():
         pdata[field] = dd[field]
 
     # Test the "from-list" generator and particle field overwrite
-    num_particles3 = num_particles + np.product(pdims)
+    num_particles3 = num_particles + np.prod(pdims)
     particles3 = FromListParticleGenerator(ds, num_particles3, pdata)
     particles3.apply_to_stream(overwrite=True)