diff --git a/doc/source/conf.py b/doc/source/conf.py index 9e8528cc9..f605eda19 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -21,7 +21,7 @@ # -- Project information ----------------------------------------------------- project = "PHARE" -copyright = "2018-2023, Nicolas Aunai, Roch Smets, Philip Deegan" +copyright = "2018-2024, Nicolas Aunai, Roch Smets, Philip Deegan" author = "Nicolas Aunai, Roch Smets, Philip Deegan" # The short X.Y version @@ -43,22 +43,28 @@ "sphinx.ext.autodoc", "sphinx.ext.mathjax", "sphinx.ext.githubpages", - "sphinx.ext.autodoc", "sphinx.ext.viewcode", "sphinx.ext.doctest", "sphinx.ext.intersphinx", "sphinx.ext.autosectionlabel", "sphinx_gallery.load_style", "sphinx_codeautolink", - "sphinxcontrib.apidoc", + # "sphinxcontrib.apidoc", "nbsphinx", - "numpydoc", + # "numpydoc", ] -apidoc_module_dir = "../../pyphare" -apidoc_output_dir = "development" -apidoc_separate_modules = True -apidoc_module_first = True +# apidoc_module_dir = "../../pyphare" +# apidoc_output_dir = "development" +# apidoc_separate_modules = True +# apidoc_module_first = True + +# autosummary_generate = False +autodoc_default_options = { + "members": True, + "private-members": False, + "special-members": False, +} autosectionlabel_prefix_document = True codeautolink_custom_blocks = { @@ -104,7 +110,8 @@ exclude_patterns = [] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = None +# pygments_style = None +pygments_style = "sphinx" # -- Options for HTML output ------------------------------------------------- diff --git a/doc/source/development/tests.rst b/doc/source/development/tests.rst deleted file mode 100644 index a643246cc..000000000 --- a/doc/source/development/tests.rst +++ /dev/null @@ -1,20 +0,0 @@ - -=========== -PHARE tests -=========== - - - - -Continuous integration ----------------------- - - - -Unit tests ----------- - - - -Functional tests ----------------- diff --git a/doc/source/index.rst b/doc/source/index.rst index 4af1a6ff3..8bfaf71d9 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -76,9 +76,9 @@ the mesh resolution wherever the solution needs it. :maxdepth: 1 :hidden: + usage/simulation_inputs usage/run_from_python usage/run_from_exe - usage/simulation_inputs usage/examples @@ -98,14 +98,6 @@ the mesh resolution wherever the solution needs it. -.. Development -.. ----------- -.. toctree:: - :caption: DEVELOPMENT - :maxdepth: 1 - :hidden: - - development/tests .. Indices and tables .. ------------------ diff --git a/doc/source/modules.rst b/doc/source/modules.rst deleted file mode 100644 index fde202562..000000000 --- a/doc/source/modules.rst +++ /dev/null @@ -1,8 +0,0 @@ -pyphare -======= - -.. toctree:: - :maxdepth: 4 - - pyphare - pyphare_tests diff --git a/doc/source/pyphare.core.rst b/doc/source/pyphare.core.rst deleted file mode 100644 index 00d51ca3b..000000000 --- a/doc/source/pyphare.core.rst +++ /dev/null @@ -1,38 +0,0 @@ -pyphare.core package -==================== - -Submodules ----------- - -pyphare.core.box module ------------------------ - -.. automodule:: pyphare.core.box - :members: - :undoc-members: - :show-inheritance: - -pyphare.core.gridlayout module ------------------------------- - -.. automodule:: pyphare.core.gridlayout - :members: - :undoc-members: - :show-inheritance: - -pyphare.core.phare\_utilities module ------------------------------------- - -.. automodule:: pyphare.core.phare_utilities - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: pyphare.core - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/pyphare.cpp.rst b/doc/source/pyphare.cpp.rst deleted file mode 100644 index b858f32a0..000000000 --- a/doc/source/pyphare.cpp.rst +++ /dev/null @@ -1,10 +0,0 @@ -pyphare.cpp package -=================== - -Module contents ---------------- - -.. automodule:: pyphare.cpp - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/pyphare.data.rst b/doc/source/pyphare.data.rst deleted file mode 100644 index 7045c1874..000000000 --- a/doc/source/pyphare.data.rst +++ /dev/null @@ -1,22 +0,0 @@ -pyphare.data package -==================== - -Submodules ----------- - -pyphare.data.wrangler module ----------------------------- - -.. automodule:: pyphare.data.wrangler - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: pyphare.data - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/pyphare.pharein.rst b/doc/source/pyphare.pharein.rst deleted file mode 100644 index 05f71048a..000000000 --- a/doc/source/pyphare.pharein.rst +++ /dev/null @@ -1,70 +0,0 @@ -pyphare.pharein package -======================= - -Submodules ----------- - -pyphare.pharein.diagnostics module ----------------------------------- - -.. automodule:: pyphare.pharein.diagnostics - :members: - :undoc-members: - :show-inheritance: - -pyphare.pharein.electron\_model module --------------------------------------- - -.. automodule:: pyphare.pharein.electron_model - :members: - :undoc-members: - :show-inheritance: - -pyphare.pharein.global\_vars module ------------------------------------ - -.. automodule:: pyphare.pharein.global_vars - :members: - :undoc-members: - :show-inheritance: - -pyphare.pharein.init module ---------------------------- - -.. automodule:: pyphare.pharein.init - :members: - :undoc-members: - :show-inheritance: - -pyphare.pharein.maxwellian\_fluid\_model module ------------------------------------------------ - -.. automodule:: pyphare.pharein.maxwellian_fluid_model - :members: - :undoc-members: - :show-inheritance: - -pyphare.pharein.simulation module ---------------------------------- - -.. automodule:: pyphare.pharein.simulation - :members: - :undoc-members: - :show-inheritance: - -pyphare.pharein.uniform\_model module -------------------------------------- - -.. automodule:: pyphare.pharein.uniform_model - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: pyphare.pharein - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/pyphare.pharesee.rst b/doc/source/pyphare.pharesee.rst deleted file mode 100644 index c0e4d0ba5..000000000 --- a/doc/source/pyphare.pharesee.rst +++ /dev/null @@ -1,54 +0,0 @@ -pyphare.pharesee package -======================== - -Submodules ----------- - -pyphare.pharesee.geometry module --------------------------------- - -.. automodule:: pyphare.pharesee.geometry - :members: - :undoc-members: - :show-inheritance: - -pyphare.pharesee.hierarchy module ---------------------------------- - -.. automodule:: pyphare.pharesee.hierarchy - :members: - :undoc-members: - :show-inheritance: - -pyphare.pharesee.particles module ---------------------------------- - -.. automodule:: pyphare.pharesee.particles - :members: - :undoc-members: - :show-inheritance: - -pyphare.pharesee.plotting module --------------------------------- - -.. automodule:: pyphare.pharesee.plotting - :members: - :undoc-members: - :show-inheritance: - -pyphare.pharesee.run module ---------------------------- - -.. automodule:: pyphare.pharesee.run - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: pyphare.pharesee - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/pyphare.rst b/doc/source/pyphare.rst deleted file mode 100644 index eb4d4ca46..000000000 --- a/doc/source/pyphare.rst +++ /dev/null @@ -1,22 +0,0 @@ -pyphare package -=============== - -Subpackages ------------ - -.. toctree:: - - pyphare.core - pyphare.cpp - pyphare.data - pyphare.pharein - pyphare.pharesee - pyphare.simulator - -Module contents ---------------- - -.. automodule:: pyphare - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/pyphare.simulator.rst b/doc/source/pyphare.simulator.rst deleted file mode 100644 index caa8bfb98..000000000 --- a/doc/source/pyphare.simulator.rst +++ /dev/null @@ -1,22 +0,0 @@ -pyphare.simulator package -========================= - -Submodules ----------- - -pyphare.simulator.simulator module ----------------------------------- - -.. automodule:: pyphare.simulator.simulator - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: pyphare.simulator - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/pyphare_tests.rst b/doc/source/pyphare_tests.rst deleted file mode 100644 index c4c30ef8a..000000000 --- a/doc/source/pyphare_tests.rst +++ /dev/null @@ -1,18 +0,0 @@ -pyphare\_tests package -====================== - -Subpackages ------------ - -.. toctree:: - - pyphare_tests.test_core - pyphare_tests.test_pharesee - -Module contents ---------------- - -.. automodule:: pyphare_tests - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/pyphare_tests.test_core.rst b/doc/source/pyphare_tests.test_core.rst deleted file mode 100644 index beb9bb8cc..000000000 --- a/doc/source/pyphare_tests.test_core.rst +++ /dev/null @@ -1,22 +0,0 @@ -pyphare\_tests.test\_core package -================================= - -Submodules ----------- - -pyphare\_tests.test\_core.test\_box module ------------------------------------------- - -.. automodule:: pyphare_tests.test_core.test_box - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: pyphare_tests.test_core - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/pyphare_tests.test_pharesee.rst b/doc/source/pyphare_tests.test_pharesee.rst deleted file mode 100644 index 9762d34e7..000000000 --- a/doc/source/pyphare_tests.test_pharesee.rst +++ /dev/null @@ -1,30 +0,0 @@ -pyphare\_tests.test\_pharesee package -===================================== - -Submodules ----------- - -pyphare\_tests.test\_pharesee.test\_geometry module ---------------------------------------------------- - -.. automodule:: pyphare_tests.test_pharesee.test_geometry - :members: - :undoc-members: - :show-inheritance: - -pyphare\_tests.test\_pharesee.test\_geometry\_2d module -------------------------------------------------------- - -.. automodule:: pyphare_tests.test_pharesee.test_geometry_2d - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: pyphare_tests.test_pharesee - :members: - :undoc-members: - :show-inheritance: diff --git a/doc/source/usage/maxwellian_fluid_model.rst b/doc/source/usage/maxwellian_fluid_model.rst new file mode 100644 index 000000000..ac1e408c2 --- /dev/null +++ b/doc/source/usage/maxwellian_fluid_model.rst @@ -0,0 +1,13 @@ + + +====================== +Maxwellian Fluid Model +====================== + +MaxwellianFluidModel +--------------------- + +.. autoclass:: pyphare.pharein.MaxwellianFluidModel + :members: + :inherited-members: + diff --git a/doc/source/usage/run_from_python.rst b/doc/source/usage/run_from_python.rst index 91841a0aa..08b5137a8 100644 --- a/doc/source/usage/run_from_python.rst +++ b/doc/source/usage/run_from_python.rst @@ -30,18 +30,66 @@ Running PHARE ------------- First, make sure it is accessible to python. Assuming PHARE source directory is in `/path/to/PHARE`, and the build directory is - `/path/to/build/`, then use the following to let python know where to find PHARE: +`/path/to/build/`, then use the following to let python know where to find PHARE: .. code-block:: bash export PYTHONPATH=/path/to/PHARE/pyphare:/path/to/build:$PYTHONPATH - -Write a [simulation input script](../simulation_inputs.md) and run the following command: +Write a :doc:`simulation_inputs` and run the following command: .. code-block:: bash python3 /path/to/my_script.py + +Executable PHARE initialization script +-------------------------------------- + +Running PHARE from python basically consists in declaring desired blocks +detailed in a :doc:`simulation_inputs` file, and adding a `main` function to run +the simulation. + +If running the simulation from python, you need to define a `main` function that +basically runs the simulation. Heere is a small example: + + +.. code-block:: python + + from pyphare.simulator.simulator import Simulator + from pyphare.pharein import Simulation + from pyphare.pharein import MaxwellianFluidModel + + + # define your simulation parameters + # and initial condition... + + sim = Simulation( + # ... + ) + + MaxwellianFluidModel( + # ... + ) + + + def main(): + simulator = Simulator(sim) + simulator.run() + + + +The Simulator +------------- + +The simulator is used to initialize and run the simulation. +It is given the `Simulation` object as an argument, as in the +simple example above. The simplest way to start the simulation is +then to call the `run()` method. + + +.. autoclass:: pyphare.simulator.simulator.Simulator + :members: + diff --git a/doc/source/usage/simulation_inputs.rst b/doc/source/usage/simulation_inputs.rst index 0917ca348..f6b81ebb8 100644 --- a/doc/source/usage/simulation_inputs.rst +++ b/doc/source/usage/simulation_inputs.rst @@ -5,10 +5,14 @@ Simulation inputs ================= -Python script structure ------------------------ -PHARE takes python scripts as inputs. They consists in declaring various -blocks as follows. +Python initialization blocks +---------------------------- + +PHARE is initialized from Python objects. +These objects are declared by users in a script to define simulation +parameters, and to describe the initial conditionn. + +The following shows the various objects to declare in a pseudo-script: .. code-block:: python @@ -68,45 +72,270 @@ The Simulation block -------------------- -The Simulation class is used to set general parameters to the simulation -like the integration time, domain size, interpolation order, or adaptive meshing. +The Simulation block is used to set general parameters of the simulation +like the integration time, domain size, interpolation order, adaptive meshing, +restart and diagnostcs options. The ``Simulation`` must be the first block defined in an input script .. autoclass:: pyphare.pharein.Simulation - Magnetic field and ions ----------------------- +The typical way to initialize a Hybrid-PIC model is to parametrize the +different ion populations with fluid moments, assuming an underlying +velocity distributotion function. +The `MaxwellianFluidModel` block allows just that, assuming a Maxwellian +distribution for each population. +It also allows to set the magnetic field profile. + + +Below is an example of a `MaxwellianFluidModel` block for which a single +population of protons is initialized. + +.. code-block:: python + + ph.MaxwellianFluidModel( + bx=bx, + by=by, + bz=bz, + protons={"charge": 1, + "density": density, + "vbulkx": vx, + "vbulky": vy, + "vbulkz": vz, + "vthx": vthx, + "vthy": vthy, + "vthz": vthz, + "nbr_part_per_cell": 100} + ) + + +In the example above, `bx`, `by`, `bz` are the components of the magnetic field, +`density` is the density of the protons, `vx`, `vy`, `vz` are the bulk velocities +and `vthx`, `vthy`, `vthz` are the thermal velocities of the protons. +All these parameters are (previously defined) functions of the spatial coordinates. + + +As an example, the function below defines a density profile. +This function will be called by the C++ code to load the population to which +this density is assigned. +In this example, we create two current sheets at y = 0.3 and y = 0.7 of the +simulation domain along the y direction, of half-width 0.5. + +.. code-block:: python + + # assume the simulation is created and accessed by the variable `sim` + + import numpy as np + + def density(x, y): + + # L[1] is the length of the simulation domain in the y direction + L = sim.simulation_domain()[1] + return ( + 0.2 + + 1.0 / np.cosh((y - L * 0.3) / 0.5) ** 2 + + 1.0 / np.cosh((y - L * 0.7) / 0.5) ** 2 + ) + + +The magnetic field function could be defined as follows: + +.. code-block:: python + + def S(y, y0, l): + return 0.5 * (1.0 + np.tanh((y - y0) / l)) + + def bx(x, y): + Ly = sim.simulation_domain()[1] + v1 = -1.0 + v2 = 1.0 + return ( + v1 + + (v2 - v1) * (S(y, Ly * 0.3, 0.5) - S(y, Ly * 0.7, 0.5)) + ) + +Note here that the function `bx` uses the other function `S`. +This underlines the great power that comes with initializing the simulation +with Python since the initialization script can be as complex as needed. + + + +Adding a population is simple. In the example below a beam proton poulation +is added with more particles per cells and different moments.: + + +.. code-block:: python + + ph.MaxwellianFluidModel( + bx=bx, + by=by, + bz=bz, + protons={"charge": 1, + "density": density, + "vbulkx": vx, + "vbulky": vy, + "vbulkz": vz, + "vthx": vthx, + "vthy": vthy, + "vthz": vthz, + "nbr_part_per_cell": 100}, + + beam={"charge": 1, + "density": beam_density, + "vbulkx": vx_beam, + "vbulky": vy_beam, + "vbulkz": vz_beam, + "vthx": vthx_beam, + "vthy": vthy_beam, + "vthz": vthz_beam, + "nbr_part_per_cell": 500} + ) + + +Examples +^^^^^^^^ +- See tests/functional/harris/harris_2d.py for a complete example with one population. +- See tests/functional/ionIon/beam_ions.py for a complete example with two populations. + +Details +^^^^^^^ +- See the :doc:`maxwellian_fluid_model` class for more details. Electron model -------------- +The `ElectronModel` block is used to set the electron fluid properties. +Below is an example of an `ElectronModel` block: + +.. code-block:: python + from pyphare.pharein import ElectronModel + + ElectronModel(closure="isothermal", Te=0.2) + + +For now, the only closure available is the isothermal closure, the given +temperatureis thus constantin space and time. Diagnostics ----------- +Diagnostics blocks are used to set parameters of the different diagnostics +output PHARE produces. There are three types of diagnostics blocks: + +- `ElectromagDiagnostics` for electromagnetic field outputs +- `FluidDiagnostics` for ion moment outputs +- `ParticleDiagnostics` for particle outputs + + Electromagnetic Diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Electromagnetic diagnostics are used to write either the electric or magnetic +field to disk. Below is an example of an `ElectromagDiagnostics` block. + +.. code-block:: python + + from pyphare.pharein import ElectromagDiagnostics + + 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) + + ElectromagDiagnostics(quantity="E", write_timestamps=timestamps) + ElectromagDiagnostics(quantity="B", write_timestamps=timestamps) + +In this example, the electric and magnetic field will be written to disk every +10 time steps. Note that although here the timestamps are equally spaced, they +do not have to be. The `write_timestamps` parameter can be any list of times. +Times are provided in simulation units. +Fluid Diagnostics +^^^^^^^^^^^^^^^^^ +Fluid quantities represent the moments of the ion populations. +Quantities available are of two kinds: +Total ion quantities: +""""""""""""""""""""" -Moment Diagnostics -^^^^^^^^^^^^^^^^^^ +These diagnostics are properties of the ion populations as a whole. +- density: represents the total particle density of the ions +- mass density: represents the total mass density of the ions +- bulk velocity: represents the total bulk velocity of the ions +- pressure_tensory: represent the total pressure tensor of the ions + +Ion population quantities: +"""""""""""""""""""""""""" + +These diagnostics are properties of each ion population. +The name of the population must be provided. + +- flux: represents the flux of a given population +- momentum_tensor: represents the momentum tensor of a given population + +Example +""""""" + +.. code-block:: python + + from pyphare.pharein import FluidDiagnostics + from pyphare.pharein import MaxwellianFluidModel + + # assume bx, by, ... are defined + # ... + MaxwellianFluidModel( + bx=bx, + by=by, + bz=bz, + protons={"charge": 1, + "density": density, + "vbulkx": vx, + "vbulky": vy, + "vbulkz": vz, + "vthx": vthx, + "vthy": vthy, + "vthz": vthz, + "nbr_part_per_cell": 100} + ) + + 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) + + FluidDiagnostics( + quantity="density", + write_timestamps=timestamps + ) + + FluidDiagnostics( + quantity="flux", + write_timestamps=timestamps, + population_name="protons" + ) Particle Diagnostics ^^^^^^^^^^^^^^^^^^^^ +These diagnostics are used to write particle data to disk. +They are typically much heavier than any other diagnostics. + + diff --git a/pyphare/pyphare/core/__init__.py b/pyphare/pyphare/core/__init__.py index 1e3f7500b..23862ed60 100644 --- a/pyphare/pyphare/core/__init__.py +++ b/pyphare/pyphare/core/__init__.py @@ -12,12 +12,16 @@ import sys import dataclasses +import os def disabled_for_testing(): # check if any module is loaded from PHARE tests directory from pathlib import Path + if "PHARE_SKIP_CLI" in os.environ: + return os.environ["PHARE_SKIP_CLI"] == "1" + test_dir = Path(__file__).resolve().parent.parent.parent.parent / "tests" if test_dir.exists(): test_dir = str(test_dir) @@ -34,7 +38,7 @@ class CliArgs: def parse_cli_args(): - default_off = len(sys.argv) == 1 and disabled_for_testing() + default_off = len(sys.argv) == 1 or disabled_for_testing() if default_off: return CliArgs() diff --git a/pyphare/pyphare/pharein/maxwellian_fluid_model.py b/pyphare/pyphare/pharein/maxwellian_fluid_model.py index 6bff2fe24..6561565ce 100644 --- a/pyphare/pyphare/pharein/maxwellian_fluid_model.py +++ b/pyphare/pyphare/pharein/maxwellian_fluid_model.py @@ -6,6 +6,48 @@ class MaxwellianFluidModel(object): + """ + MaxwellianFluidModel is used to setup ion populations in a simulation + along with the magnetic field. + + **Usage example:** + + .. code-block:: python + + ph.MaxwellianFluidModel( + bx=bx, + by=by, + bz=bz, + protons={"charge": 1, + "density": density, + "vbulkx": vx, + "vbulky": vy, + "vbulkz": vz, + "vthx": vthx, + "vthy": vthy, + "vthz": vthz, + "nbr_part_per_cell": 100}, + + beam={"charge": 1, + "density": beam_density, + "vbulkx": vx_beam, + "vbulky": vy_beam, + "vbulkz": vz_beam, + "vthx": vthx_beam, + "vthy": vthy_beam, + "vthz": vthz_beam, + "nbr_part_per_cell": 500} + ) + + **Parameters**: + + * **bx** (*function*): magnetic field in x direction + * **by** (*function*): magnetic field in y direction + * **bz** (*function*): magnetic field in z direction + + + """ + def defaulter(self, input, value): if input is not None: import inspect @@ -78,12 +120,12 @@ def add_population( add_population(name,charge=1, mass=1, nbrPartCell=100, density=1, vbulk=(0,0,0), beta=1, anisotropy=1) - Parameters: - ----------- + Parameters + ---------- name : name of the species, str - Optional Parameters: - ------------------- + Other Parameters + ---------------- charge : charge of the species particles, float (default = 1.) nbrPartCell : number of particles per cell, int (default = 100) density : particle density, float (default = 1.) diff --git a/pyphare/pyphare/pharein/simulation.py b/pyphare/pyphare/pharein/simulation.py index 17c6e45bc..49abda6bd 100644 --- a/pyphare/pyphare/pharein/simulation.py +++ b/pyphare/pyphare/pharein/simulation.py @@ -690,126 +690,204 @@ def wrapper(simulation_object, **kwargs): class Simulation(object): """ + + **Usage example:** + + This declares a 2D simulation of 100x100 cells + with an isotropic mesh size of 0.2. The simulation will run + 1000 time steps of dt=0.001 and so will stop at t=1 + + The simulation will run with adaptive mesh refinement and evolve up to 3 levels, + i.e. a base coarsest mesh with up to 2 additional refinement levels. + + Diagnostics, if declared, will be saved as native PHARE HDF5 (default format) + in the directory `diag_outputs` and will overwrite any existing h5 files there. + + The resistivity and hyper-resistivity are set to constant custom values. + .. code-block:: python from pyphare.pharein import Simulation - # This declares a 2D simulation of 100x100 cells - # with an isotropic mesh size of 0.2. The simulation will run - # 1000 time steps of dt=0.001 and so will stop at t=1 - # there is no refinement boxes set and since max_nbr_levels defaults to 1 - # this simulation will consists of only 1 level with no refinement. - # diagnostics, if declared, will be saved as native PHARE HDF5 - # in the directory 'diag_outputs' and will overwrite any existing h5 files there - # the resistivity and hyper-resistivity are set to constant custom values - # the smallest and largest patch sizes are set to 15 and 25 cells, respectively - Simulation(smallest_patch_size=15, - largest_patch_size=25, + + Simulation( + # time evolution parameters time_step_nbr=1000, time_step=0.001, - # boundary_types="periodic", + + # Domain parameters cells=(100,100), dl=(0.2, 0.2), - refinement_boxes={}, + + # AMR parameters + max_nbr_levels=3, + + # general physics parameters hyper_resistivity=0.001, resistivity=0.001, + + # diagnostics and restart parameters diag_options={"format": "phareh5", "options": {"dir": diag_outputs, "mode":"overwrite"}}, - restart_options={"dir": restart_outputs, - "mode": "overwrite" or "conserve", - "timestamps" : [.009, 99999] - "elapsed_timestamps" : [datetime.timedelta(hours=1)], - "restart_time" : 99999.99999 }, - strict=True (turns warnings to errors, false by default), ) - Setting time parameters: + **Time parameters:** + + * **final_time** (``float``), final simulation time. Use with time_step OR time_step_nbr + * **time_step** (``float``), simulation time step. Use with time_step_nbr OR final_time + * **time_step_nbr** (``int``), number of time step to perform. Use with final_time OR time_step + + + .. code-block:: python + + Simulation( + time_step_nbr=1000, + time_step=0.001, + + # .... + ) + + is equivalent to: + + .. code-block:: python + + Simulation( + time_step_nbr=1000, + final_time=1., + + # .... + ) - :Keyword Arguments: - * *final_time* (``float``)-- - final simulation time. Use with time_step OR time_step_nbr - * *time_step* (``float``)-- - simulation time step. Use with time_step_nbr OR final_time - * *time_step_nbr* (``int``) -- number of time step to perform. - Use with final_time OR time_step + or even to: + .. code-block:: python + + Simulation( + time_step=0.001, + final_time=1., + + # .... + ) - Setting domain/grid parameters: + **Domain/grid parameters:** The number of dimensions of the simulation is deduced from the length of these parameters. - :Keyword Arguments: - * *dl* (``float``, ``tuple``) -- - grid spacing dx, (dx,dy) or (dx,dy,dz) in 1D, 2D or 3D. - A single float value in 2D or 3D are assumed equal for each dimension. - Use this parameter with either domain_size OR cells - * *domain_size* (``float`` or ``tuple``) -- - size of the physical domain Lx, (Lx,Ly), (Lx,Ly,Lz) in 1D, 2D or 3D - Single float is assumed equal for each direction. - Use this parameter with either cells or dl - * *cells* (``int`` or ``tuple``) -- - number of cells nx or (nx, ny) or (nx, ny, nz) in 1, 2 and 3D. - Single int is assumed equal for each direction - Use this parameter with either domain_size or dl - * *layout* (``str``)-- - layout of the physical quantities on the mesh (default = "yee") - * *origin* (``int`` or ``tuple``) -- - origin of the physical domain, (default (0,0,0) in 3D) - - - Setting particle parameters: - - :Keyword Arguments: - * *interp_order* (``int``)-- - 1, 2 or 3 (default=1) particle b-spline order - * *particle_pusher* (``str``) -- - algo to push particles (default = "modifiedBoris") - - - Setting diagnostics output parameters: - - :Keyword Arguments: - * *path* (``str``) - path for outputs (default : './') - * *boundary_types* (``str`` or ``tuple``) - type of boundary conditions (default is "periodic" for each direction) - * *diag_export_format* (``str``) - format of the output diagnostics (default= "phareh5") + * **dl** (``float``, ``tuple``) grid spacing dx, (dx,dy) or (dx,dy,dz) in 1D, 2D or 3D. + A single float value in 2D or 3D are assumed equal for each dimension. + Use this parameter with either `domain_size` OR `cells` + + * **domain_size** (``float`` or ``tuple``) + size of the physical domain Lx, (Lx,Ly), (Lx,Ly,Lz) in 1D, 2D or 3D + Single float is assumed equal for each direction. Use this parameter with either `cells` or `dl` + + * **cells** (``int`` or ``tuple``) + number of cells nx or (nx, ny) or (nx, ny, nz) in 1, 2 and 3D. + Single int is assumed equal for each direction + Use this parameter with either `domain_size` or `dl` + + **Expert parameters:** + + These parameters are more advanced, modify them at your own risk + + * **layout** (``str``), layout of the physical quantities on the mesh (default = "yee") + * **origin** (``int`` or ``tuple``), origin of the physical domain, (default (0,0,0) in 3D) + + + For instance: + + .. code-block:: python + + Simulation( + dl=(0.1, 0.1), + domain_size=(100,100), + + # .... + ) + + is equivalent to: + + + .. code-block:: python + + Simulation( + cells=(1000, 1000), + domain_size=(100,100), + + # .... + ) + + or even to: + + .. code-block:: python + + Simulation( + cells=(1000, 1000), + dl=(0.1,0.1), + + # .... + ) + + **Macro-particle parameters:** + + * **interp_order** (``int``), 1, 2 or 3 (default=1) particle b-spline order + * **particle_pusher** (``str``), algo to push particles (default = "modifiedBoris") + + + **Diagnostics output parameters:** + + * **diag_options** (``dict``) + * **path** (``str``) path for outputs (default : './') + * **diag_export_format** (``str``) format of the output diagnostics (default= "phareh5") + * **mode** (``str``) mode of the output diagnostics (default= "overwrite" will write over existing files) + + **Adaptive Mesh Refinement (AMR) parameters:** + + * **max_nbr_levels** (``int``), default=1, max number of levels in the hierarchy. Used if no `refinement_boxes` are set + * **tag_buffer** (``int``), default=1, value representing the number of cells by which tagged cells are buffered before clustering into boxes. The larger `tag_buffer`, the wider refined regions will be around tagged cells. + * **clustering** (``str``), {"berger" (default), "tile"}, type of clustering to use for AMR. `tile` results in wider patches, less artifacts and better scalability + + **Expert parameters:** + + These parameters are more advanced, modify them at your own risk + + * **refined_particle_nbr** (``ìnt``), number of refined particle per coarse particle. + * **nesting_buffer** (``ìnt``), default=0 minimum gap in coarse cells from the border of a level and any refined patch border + * **refinement_boxes**, default=None, {"L0":{"B0":[(lox,loy,loz),(upx,upy,upz)],...,"Bi":[(),()]},..."Li":{B0:[(),()]}} + * **smallest_patch_size** (``int`` or ``tuple``), minimum number of cells in a patch in each direction + This parameter cannot be smaller than the number of field ghost nodes + * **largest_patch_size** (``int`` or ``tuple``), maximum size of a patch in each direction + + + + **Restart parameters:** + + These parameters are used to restart a simulation from a previous state and dump chekpoints. + + * **restart_options** (``dict``) + * **dir** (``str``) path for restart files (default : './') + * **mode** (``str``) mode of the restart files + * "conserve" - (default), will conserve existing files + * "overwrite" - will overwrite existing files + + * **restart_time** (``float``) time at which to restart the simulation (default=0) + * **timestamps** (``list``) list of timestamps at which to restart the simulation + Misc: - :Keyword Arguments: - * *strict* (``bool``)-- - turns warnings into errors (default False) - - - - Adaptive Mesh Refinement (AMR) parameters - - :Keyword Arguments: - * *nesting_buffer* (``ìnt``)-- - [default=0] minimum gap in coarse cells from the border of a level and any refined patch border - * *refinement_boxes* -- - [default=None] {"L0":{"B0":[(lox,loy,loz),(upx,upy,upz)],...,"Bi":[(),()]},..."Li":{B0:[(),()]}} - * *smallest_patch_size* (``int`` or ``tuple``)-- - minimum number of cells in a patch in each direction - This parameter cannot be smaller than the number of field ghost nodes - * *largest_patch_size* (``int`` or ``tuple``)-- - maximum size of a patch in each direction - * *max_nbr_levels* (``int``)-- - [default=1] max number of levels in the hierarchy. Used if no refinement_boxes are set - * *refined_particle_nbr* (``ìnt``) -- - number of refined particle per coarse particle. - * *tag_buffer* (``int``) -- - [default=1] value representing the number of cells by which tagged cells are buffered before clustering into boxes. - * *description* (``string``) -- - [default=None] arbitrary string for per simulation context - injected in output files when feasible + * **description** (``string``), [default=None] arbitrary string for per simulation context - injected in output files when feasible + * **strict** (``bool``), turns warnings into errors (default False) + * **resistivity** (``float``), resistivity value (default=0.0) + * **hyper-resistivity** (``float``), hyper-resistivity value (default=0.0) + * **boundary_types** (``str`` or ``tuple``) type of boundary conditions (default is "periodic" for each direction) + """ @checker @@ -883,6 +961,11 @@ def __setstate__(self, state): # ------------------------------------------------------------------------------ def add_diagnostics(self, diag): + """ + + :meta private: + + """ if diag.name in self.diagnostics: raise ValueError( "Error: diagnostics {} already registered".format(diag.name) @@ -899,6 +982,10 @@ def add_diagnostics(self, diag): # ------------------------------------------------------------------------------ def is_restartable_compared_to(self, sim): + """ + + :meta private: + """ # to be considered https://github.com/PHAREHUB/PHARE/issues/666 check = ["cells", "dl"] are_comparable = all([getattr(self, k) == getattr(sim, k)] for k in check) @@ -907,6 +994,10 @@ def is_restartable_compared_to(self, sim): # ------------------------------------------------------------------------------ def count_diagnostics(self, type_name): + """ + + :meta private: + """ return len( [ diag @@ -918,9 +1009,17 @@ def count_diagnostics(self, type_name): # ------------------------------------------------------------------------------ def set_model(self, model): + """ + + :meta private: + """ self.model = model def set_electrons(self, electrons): + """ + + :meta private: + """ self.electrons = electrons @@ -928,6 +1027,10 @@ def set_electrons(self, electrons): def serialize(sim): + """ + + :meta private: + """ # pickle cannot handle simulation objects import dill, codecs @@ -935,6 +1038,7 @@ def serialize(sim): def deserialize(hex): + """:meta private:""" import dill, codecs return dill.loads(codecs.decode(hex, "hex")) diff --git a/pyphare/pyphare/pharein/uniform_model.py b/pyphare/pyphare/pharein/uniform_model.py index 45ed32592..9d079d012 100644 --- a/pyphare/pyphare/pharein/uniform_model.py +++ b/pyphare/pyphare/pharein/uniform_model.py @@ -59,12 +59,12 @@ def add_population( add_population(name,charge=1, mass=1, nbrPartCell=100, density=1, vbulk=(0,0,0), beta=1, anisotropy=1) - Parameters: - ----------- + Parameters + ---------- name : name of the species, str - Optional Parameters: - ------------------- + Other Parameters + ---------------- charge : charge of the species particles, float (default = 1.) nbrPartCell : number of particles per cell, int (default = 100) density : particle density, float (default = 1.) diff --git a/pyphare/pyphare/pharesee/geometry.py b/pyphare/pyphare/pharesee/geometry.py index 370f7da4f..4548bd0cb 100644 --- a/pyphare/pyphare/pharesee/geometry.py +++ b/pyphare/pyphare/pharesee/geometry.py @@ -430,11 +430,10 @@ def level_ghost_boxes(hierarchy, quantities, levelNbrs=[], time=None): return : {level_number : [{"pdata":patch_data1, "boxes":lvl_ghost_boxes}, {"pdata":patch_data2, "boxes":lvl_ghost_boxes}, ...]} - optional parameters - ----- + Other parameters + ---------------- levelNbrs : limit working set of hierarchy levels to those requested, if scalar, returns just that level time : the simulation time to access the appropriate data for the requested time - ----- """ quantities = listify(quantities) diff --git a/pyphare/pyphare/simulator/simulator.py b/pyphare/pyphare/simulator/simulator.py index 784593e67..906ae2593 100644 --- a/pyphare/pyphare/simulator/simulator.py +++ b/pyphare/pyphare/simulator/simulator.py @@ -37,6 +37,24 @@ def startMPI(): class Simulator: + """ + + **Mandatory arguments** + + * **simulation**: a `Simulation` object + + + **Optional expert arguments** + + These arguments have good default, change them at your own risk. + + * **print_one_line**: (``bool``), default True, will print simulator info per advance on one line (erasing the previous) + * **auto_dump**: (``bool``), if True (default), will dump diagnostics automatically at requested timestamps + * **post_advance**: (``Function``), default None. A python function to execute after each advance() + * **log_to_file**: if True (default), will log prints made from C++ code per MPI rank to the .log directory + + """ + def __init__(self, simulation, auto_dump=True, **kwargs): assert isinstance(simulation, ph.Simulation) # pylint: disable=no-member self.simulation = simulation @@ -152,6 +170,9 @@ def times(self): ) def run(self): + """ + Run the simulation until the end time + """ from pyphare.cpp import cpp_lib self._check_init()