diff --git a/pyphare/pyphare/pharein/simulation.py b/pyphare/pyphare/pharein/simulation.py index 97ed32615..ee15a0b77 100644 --- a/pyphare/pyphare/pharein/simulation.py +++ b/pyphare/pyphare/pharein/simulation.py @@ -498,7 +498,7 @@ def check_diag_options(**kwargs): diag_options["options"]["dir"], "diagnostics" ) valid_modes = ["overwrite"] - if "mode" in diag_options["options"]: + if "options" in diag_options and "mode" in diag_options["options"]: mode = diag_options["options"]["mode"] if mode not in valid_modes: raise ValueError( diff --git a/tests/functional/harris/CMakeLists.txt b/tests/functional/harris/CMakeLists.txt index afaf7b4d8..1cbb8723f 100644 --- a/tests/functional/harris/CMakeLists.txt +++ b/tests/functional/harris/CMakeLists.txt @@ -8,10 +8,14 @@ if(NOT ${PHARE_PROJECT_DIR} STREQUAL ${CMAKE_BINARY_DIR}) endif() if(HighFive AND testMPI) + ## These test use dump diagnostics so require HighFive! - # exec level 11 - # mpirun -n 10 + if(testMPI) - phare_mpi_python3_exec(11 10 harris_2d harris_2d.py ${CMAKE_CURRENT_BINARY_DIR}) + + phare_mpi_python3_exec(11 4 harris_2d_100_x_100 harris_2d_100_x_100.py ${CMAKE_CURRENT_BINARY_DIR}) + phare_mpi_python3_exec(11 4 harris_2d_100_x_100_slow harris_2d_100_x_100_slow.py ${CMAKE_CURRENT_BINARY_DIR}) + endif(testMPI) + endif() diff --git a/tests/functional/harris/harris_2d.py b/tests/functional/harris/harris_2d.py index b9f06ced4..9ffd88576 100644 --- a/tests/functional/harris/harris_2d.py +++ b/tests/functional/harris/harris_2d.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -import os + import numpy as np import pyphare.pharein as ph @@ -7,34 +7,28 @@ from pyphare.simulator.simulator import Simulator from pyphare.simulator.simulator import startMPI -os.environ["PHARE_SCOPE_TIMING"] = "1" # turn on scope timing -""" - For scope timings to work - The env var PHARE_SCOPE_TIMING must be == "1" (or "true") - See src/phare/phare.hpp - CMake must be configured with: -DwithPhlop=ON - And a LOG_LEVEL must be defined via compile args: -DPHARE_LOG_LEVEL=1 - Or change the default value in src/core/logger.hpp - And phlop must be available on PYTHONPATH either from subprojects - or install phlop via pip -""" - ph.NO_GUI() cpp = cpp_lib() -startMPI() + + diag_outputs = "phare_outputs/test/harris/2d" time_step_nbr = 1000 time_step = 0.001 final_time = time_step * time_step_nbr -dt = 10 * time_step -nt = final_time / dt + 1 -timestamps = dt * np.arange(nt) -def config(): - sim = ph.Simulation( +def default_timestamps(): + dt = 10 * time_step + nt = final_time / dt + 1 + timestamps = dt * np.arange(nt) + + +def default_setup(): + startMPI() + + return ph.Simulation( smallest_patch_size=15, largest_patch_size=25, time_step_nbr=time_step_nbr, @@ -53,6 +47,13 @@ def config(): strict=True, ) + +def config(sim = None, timestamps = None, seed = 12334): + if sim is None: + sim = default_setup() + if timestamps is None: + timestamps = default_timestamps() + def density(x, y): L = sim.simulation_domain()[1] return ( @@ -141,7 +142,7 @@ def vthz(x, y): bx=bx, by=by, bz=bz, - protons={"charge": 1, "density": density, **vvv, "init": {"seed": 12334}}, + protons={"charge": 1, "density": density, **vvv, "init": {"seed": seed}}, ) ph.ElectronModel(closure="isothermal", Te=0.0) @@ -155,13 +156,7 @@ def vthz(x, y): def main(): Simulator(config()).run() - try: - from tools.python3 import plotting as m_plotting - m_plotting.plot_run_timer_data(diag_outputs, cpp.mpi_rank()) - except ImportError: - print("Phlop not found - install with: `pip install phlop`") - cpp.mpi_barrier() if __name__ == "__main__": diff --git a/tests/functional/harris/harris_2d_lb.py b/tests/functional/harris/harris_2d_100_x_100.py similarity index 54% rename from tests/functional/harris/harris_2d_lb.py rename to tests/functional/harris/harris_2d_100_x_100.py index 1153b6e8b..ecc6cdbb1 100644 --- a/tests/functional/harris/harris_2d_lb.py +++ b/tests/functional/harris/harris_2d_100_x_100.py @@ -11,42 +11,46 @@ from pyphare.simulator.simulator import Simulator, startMPI from tests.simulator import SimulatorTest -from tools.python3 import plotting as m_plotting + +import harris_2d as base mpl.use("Agg") -SCOPE_TIMING = os.getenv("PHARE_SCOPE_TIMING", "True").lower() in ("true", "1", "t") +SCOPE_TIMING = os.getenv("PHARE_SCOPE_TIMING", "False").lower() in ("true", "1", "t") +""" + For scope timings to work + The env var PHARE_SCOPE_TIMING must be == "1" (or "true") + See src/phare/phare.hpp + CMake must be configured with: -DwithPhlop=ON + And a LOG_LEVEL must be defined via compile args: -DPHARE_LOG_LEVEL=1 + Or change the default value in src/core/logger.hpp + And phlop must be available on PYTHONPATH either from subprojects + or install phlop via pip +""" + LOAD_BALANCE = os.getenv("LOAD_BALANCE", "True").lower() in ("true", "1", "t") cpp = cpp_lib() startMPI() -cells = (800, 800) -time_step = 0.005 +cells = (100, 100) final_time = 50 +time_step = 0.005 timestamps = np.arange(0, final_time + time_step, final_time / 5) -if cpp.mpi_rank() == 0: - print(LOAD_BALANCE, "diag timestamps:", timestamps) - -diag_dir = "phare_outputs/harris_lb" -if not LOAD_BALANCE: - diag_dir = "phare_outputs/harris" - +diag_dir = "phare_outputs/harris_2d_100_x_100" plot_dir = Path(f"{diag_dir}_plots") plot_dir.mkdir(parents=True, exist_ok=True) def config(): - L = 0.5 - sim = ph.Simulation( time_step=time_step, final_time=final_time, cells=cells, dl=(0.40, 0.40), - refinement="tagging", - max_nbr_levels=2, + # refinement="tagging", + # max_nbr_levels=1, nesting_buffer=1, clustering="tile", tag_buffer="1", @@ -56,91 +60,16 @@ def config(): "format": "phareh5", "options": {"dir": diag_dir, "mode": "overwrite"}, }, - restart_options={ - "dir": "checkpoints", - "mode": "overwrite", - "timestamps": timestamps, - # "restart_time": 0.0, - }, ) - def density(x, y): - Ly = sim.simulation_domain()[1] - return ( - 0.4 - + 1.0 / np.cosh((y - Ly * 0.3) / L) ** 2 - + 1.0 / np.cosh((y - Ly * 0.7) / L) ** 2 - ) - - def S(y, y0, l): - return 0.5 * (1.0 + np.tanh((y - y0) / l)) - - def by(x, y): - Lx = sim.simulation_domain()[0] - Ly = sim.simulation_domain()[1] - sigma = 1.0 - dB = 0.1 - - x0 = x - 0.5 * Lx - y1 = y - 0.3 * Ly - y2 = y - 0.7 * Ly - - dBy1 = 2 * dB * x0 * np.exp(-(x0**2 + y1**2) / (sigma) ** 2) - dBy2 = -2 * dB * x0 * np.exp(-(x0**2 + y2**2) / (sigma) ** 2) - - return dBy1 + dBy2 - - def bx(x, y): - Lx = sim.simulation_domain()[0] - Ly = sim.simulation_domain()[1] - sigma = 1.0 - dB = 0.1 + sim = base.config(sim, timestamps) - x0 = x - 0.5 * Lx - y1 = y - 0.3 * Ly - y2 = y - 0.7 * Ly - - dBx1 = -2 * dB * y1 * np.exp(-(x0**2 + y1**2) / (sigma) ** 2) - dBx2 = 2 * dB * y2 * np.exp(-(x0**2 + y2**2) / (sigma) ** 2) - - v1 = -1 - v2 = 1.0 - return v1 + (v2 - v1) * (S(y, Ly * 0.3, L) - S(y, Ly * 0.7, L)) + dBx1 + dBx2 - - def bz(x, y): - return 0.0 - - def b2(x, y): - return bx(x, y) ** 2 + by(x, y) ** 2 + bz(x, y) ** 2 - - def T(x, y): - K = 0.7 - temp = 1.0 / density(x, y) * (K - b2(x, y) * 0.5) - assert np.all(temp > 0) - return temp - - def vxyz(x, y): - return 0.0 - - def vthxyz(x, y): - return np.sqrt(T(x, y)) - - vvv = {**{f"vbulk{c}": vxyz for c in "xyz"}, **{f"vth{c}": vthxyz for c in "xyz"}} - - ph.MaxwellianFluidModel( - bx=bx, by=by, bz=bz, protons={"charge": 1, "density": density, **vvv} - ) - ph.ElectronModel(closure="isothermal", Te=0.0) - - for quantity in ["E", "B"]: - ph.ElectromagDiagnostics(quantity=quantity, write_timestamps=timestamps) for quantity in ["density", "bulkVelocity"]: ph.FluidDiagnostics(quantity=quantity, write_timestamps=timestamps) ph.FluidDiagnostics( quantity="density", write_timestamps=timestamps, population_name="protons" ) - ph.InfoDiagnostics(quantity="particle_count") if LOAD_BALANCE: ph.LoadBalancer(active=True, auto=True, mode="nppc", tol=0.05) @@ -201,8 +130,15 @@ def test_run(self): Simulator(config()).run().reset() if cpp.mpi_rank() == 0: plot(diag_dir) + if SCOPE_TIMING: - m_plotting.plot_run_timer_data(diag_dir, cpp.mpi_rank()) + try: + from tools.python3 import plotting as m_plotting + + m_plotting.plot_run_timer_data(diag_dir, cpp.mpi_rank()) + except ImportError: + print("Phlop not found - install with: `pip install phlop`") + cpp.mpi_barrier() return self diff --git a/tests/functional/harris/harris_2d_100_x_100_slow.py b/tests/functional/harris/harris_2d_100_x_100_slow.py new file mode 100644 index 000000000..cb744940c --- /dev/null +++ b/tests/functional/harris/harris_2d_100_x_100_slow.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 + +import os +import numpy as np +import matplotlib as mpl +from pathlib import Path + +import pyphare.pharein as ph +from pyphare.cpp import cpp_lib +from pyphare.pharesee.run import Run +from pyphare.simulator.simulator import Simulator, startMPI + +from tests.simulator import SimulatorTest + +import harris_2d as base + +mpl.use("Agg") + +SCOPE_TIMING = os.getenv("PHARE_SCOPE_TIMING", "False").lower() in ("true", "1", "t") +""" + For scope timings to work + The env var PHARE_SCOPE_TIMING must be == "1" (or "true") + See src/phare/phare.hpp + CMake must be configured with: -DwithPhlop=ON + And a LOG_LEVEL must be defined via compile args: -DPHARE_LOG_LEVEL=1 + Or change the default value in src/core/logger.hpp + And phlop must be available on PYTHONPATH either from subprojects + or install phlop via pip +""" + +LOAD_BALANCE = os.getenv("LOAD_BALANCE", "True").lower() in ("true", "1", "t") + +cpp = cpp_lib() +startMPI() + +cells = (100, 100) +final_time = 50 +time_step = 0.001 +timestamps = np.arange(0, final_time + time_step, final_time / 5) + +diag_dir = "phare_outputs/harris_2d_100_x_100_slow" +plot_dir = Path(f"{diag_dir}_plots") +plot_dir.mkdir(parents=True, exist_ok=True) + + +def config(): + sim = ph.Simulation( + time_step=time_step, + final_time=final_time, + cells=cells, + dl=(0.40, 0.40), + # refinement="tagging", + # max_nbr_levels=1, + nesting_buffer=1, + clustering="tile", + tag_buffer="1", + hyper_resistivity=0.002, + resistivity=0.001, + diag_options={ + "format": "phareh5", + "options": {"dir": diag_dir, "mode": "overwrite"}, + }, + ) + + sim = base.config(sim, timestamps) + + for quantity in ["density", "bulkVelocity"]: + ph.FluidDiagnostics(quantity=quantity, write_timestamps=timestamps) + + ph.FluidDiagnostics( + quantity="density", write_timestamps=timestamps, population_name="protons" + ) + + if LOAD_BALANCE: + ph.LoadBalancer(active=True, auto=True, mode="nppc", tol=0.05) + + return sim + + +def plot_file_for_qty(qty, time): + return f"{plot_dir}/harris_{qty}_t{time}.png" + + +def plot(diag_dir): + run = Run(diag_dir) + for time in timestamps: + run.GetDivB(time).plot( + filename=plot_file_for_qty("divb", time), + plot_patches=True, + vmin=1e-11, + vmax=2e-10, + ) + run.GetRanks(time).plot( + filename=plot_file_for_qty("Ranks", time), + plot_patches=True, + ) + run.GetN(time, pop_name="protons").plot( + filename=plot_file_for_qty("N", time), + plot_patches=True, + ) + for c in ["x", "y", "z"]: + run.GetB(time).plot( + filename=plot_file_for_qty(f"b{c}", time), + qty=f"{c}", + plot_patches=True, + ) + run.GetJ(time).plot( + filename=plot_file_for_qty("jz", time), + qty="z", + plot_patches=True, + vmin=-2, + vmax=2, + ) + + +class HarrisTest(SimulatorTest): + def __init__(self, *args, **kwargs): + super(HarrisTest, self).__init__(*args, **kwargs) + self.simulator = None + + def tearDown(self): + super(HarrisTest, self).tearDown() + if self.simulator is not None: + self.simulator.reset() + self.simulator = None + ph.global_vars.sim = None + + def test_run(self): + self.register_diag_dir_for_cleanup(diag_dir) + Simulator(config()).run().reset() + if cpp.mpi_rank() == 0: + plot(diag_dir) + + if SCOPE_TIMING: + try: + from tools.python3 import plotting as m_plotting + + m_plotting.plot_run_timer_data(diag_dir, cpp.mpi_rank()) + except ImportError: + print("Phlop not found - install with: `pip install phlop`") + + cpp.mpi_barrier() + return self + + +if __name__ == "__main__": + HarrisTest().test_run().tearDown() diff --git a/tests/simulator/CMakeLists.txt b/tests/simulator/CMakeLists.txt index 86274d16f..edef7be5f 100644 --- a/tests/simulator/CMakeLists.txt +++ b/tests/simulator/CMakeLists.txt @@ -25,9 +25,12 @@ if(HighFive) # doesn't make sense in serial phare_mpi_python3_exec(9 3 load_balancing test_load_balancing.py ${CMAKE_CURRENT_BINARY_DIR}) - endif(testMPI) - phare_python3_exec(11, test_diagnostic_timestamps test_diagnostic_timestamps.py ${CMAKE_CURRENT_BINARY_DIR}) + else() + phare_python3_exec(11 test_diagnostic_timestamps test_diagnostic_timestamps.py ${CMAKE_CURRENT_BINARY_DIR}) + + endif(testMPI) + endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.py ${CMAKE_CURRENT_BINARY_DIR}/config.py @ONLY) diff --git a/tests/simulator/refinement/CMakeLists.txt b/tests/simulator/refinement/CMakeLists.txt index 178fc46e9..31772ce5d 100644 --- a/tests/simulator/refinement/CMakeLists.txt +++ b/tests/simulator/refinement/CMakeLists.txt @@ -10,7 +10,12 @@ endif() if(HighFive) ## These test use dump diagnostics so require HighFive! if(testMPI) - phare_mpi_python3_exec(9 2 simple_2d_refinement test_2d_2_core.py ${CMAKE_CURRENT_BINARY_DIR}) - phare_mpi_python3_exec(11 10 complex_2d_refinement test_2d_10_core.py ${CMAKE_CURRENT_BINARY_DIR}) + + # disabled due to https://github.com/PHAREHUB/PHARE/issues/853 + # phare_mpi_python3_exec(11 10 complex_2d_refinement test_2d_10_core.py ${CMAKE_CURRENT_BINARY_DIR}) + endif(testMPI) + + phare_python3_exec(9 simple_2d_refinement test_2d_2_core.py ${CMAKE_CURRENT_BINARY_DIR}) + endif()