diff --git a/Docs/source/index.rst b/Docs/source/index.rst index ffceeccad2b..4c5f791ca6b 100644 --- a/Docs/source/index.rst +++ b/Docs/source/index.rst @@ -75,9 +75,8 @@ Usage :hidden: usage/how_to_run - usage/domain_decomposition - usage/parameters usage/python + usage/parameters usage/examples usage/workflows usage/faq @@ -125,10 +124,10 @@ Development :hidden: developers/contributing - developers/workflows developers/developers developers/doxygen developers/gnumake + developers/workflows developers/faq .. good to have in the future: .. developers/repostructure diff --git a/Docs/source/usage/parameters.rst b/Docs/source/usage/parameters.rst index 9109324620c..16502a5ed65 100644 --- a/Docs/source/usage/parameters.rst +++ b/Docs/source/usage/parameters.rst @@ -1,7 +1,11 @@ .. _running-cpp-parameters: -Input Parameters -================ +Parameters: Inputs File +======================= + +This documents on how to use WarpX with an inputs file (e.g., ``warpx.3d input_3d``). + +Complete example input files can be found in :ref:`the examples section `. .. note:: @@ -1084,11 +1088,12 @@ Particle initialization the above mentioned function. .. note:: - When accessing the data via Python, the scraped particle buffer relies on the user - to clear the buffer after processing the data. The - buffer will grow unbounded as particles are scraped and therefore could - lead to memory issues if not periodically cleared. To clear the buffer - call ``warpx_clearParticleBoundaryBuffer()``. + + When accessing the data via Python, the scraped particle buffer relies on the user + to clear the buffer after processing the data. The + buffer will grow unbounded as particles are scraped and therefore could + lead to memory issues if not periodically cleared. To clear the buffer + call ``clear_buffer()``. * ``.do_field_ionization`` (`0` or `1`) optional (default `0`) Do field ionization for this species (using the ADK theory). diff --git a/Docs/source/usage/pwfa.rst b/Docs/source/usage/pwfa.rst index 44d62384699..fc26f5db31a 100644 --- a/Docs/source/usage/pwfa.rst +++ b/Docs/source/usage/pwfa.rst @@ -1,3 +1,5 @@ +.. _examples-pwfa-boost: + In-Depth: PWFA ============== diff --git a/Docs/source/usage/python.rst b/Docs/source/usage/python.rst index a32aa02aa42..c9d846b41e7 100644 --- a/Docs/source/usage/python.rst +++ b/Docs/source/usage/python.rst @@ -1,256 +1,178 @@ .. _usage-picmi: +.. _usage-picmi-run: + +Parameters: Python (PICMI) +========================== -Python (PICMI) -============== +This documents on how to use WarpX as a Python script (e.g., ``python3 PICMI_script.py``). WarpX uses the `PICMI standard `__ for its Python input files. -Python version 3.8 or newer is required. +Complete example input files can be found in :ref:`the examples section `. -Example input files can be found in :ref:`the examples section `. In the input file, instances of classes are created defining the various aspects of the simulation. -The `Simulation` object is the central object, where the instances are passed, -defining the simulation time, field solver, registered species, etc. +A variable of type :py:class:`pywarpx.picmi.Simulation` is the central object to which all other options are passed, defining the simulation time, field solver, registered species, etc. -.. _usage-picmi-parameters: +Once the simulation is fully configured, it can be used in one of two modes. +**Interactive** use is the most common and can be :ref:`extended with custom runtime functionality `: -Classes -------- +.. tab-set:: -Simulation and grid setup -^^^^^^^^^^^^^^^^^^^^^^^^^ + .. tab-item:: Interactive -Simulation -"""""""""" -.. autoclass:: pywarpx.picmi.Simulation - :members: step, add_species, add_laser, write_input_file + :py:meth:`~pywarpx.picmi.Simulation.step`: run directly from Python -Constants -""""""""" -For convenience, the PICMI interface defines the following constants, -which can be used directly inside any PICMI script. The values are in SI units. + .. tab-item:: Preprocessor -- ``picmi.constants.c``: The speed of light in vacuum. -- ``picmi.constants.ep0``: The vacuum permittivity :math:`\epsilon_0` -- ``picmi.constants.mu0``: The vacuum permeability :math:`\mu_0` -- ``picmi.constants.q_e``: The elementary charge (absolute value of the charge of an electron). -- ``picmi.constants.m_e``: The electron mass -- ``picmi.constants.m_p``: The proton mass + :py:meth:`~pywarpx.picmi.Simulation.write_input_file`: create an :ref:`inputs file for a WarpX executable ` -Field solvers define the updates of electric and magnetic fields. -ElectromagneticSolver -""""""""""""""""""""" -.. autoclass:: pywarpx.picmi.ElectromagneticSolver +.. _usage-picmi-parameters: -ElectrostaticSolver -""""""""""""""""""" -.. autoclass:: pywarpx.picmi.ElectrostaticSolver +Simulation and Grid Setup +------------------------- + +.. autoclass:: pywarpx.picmi.Simulation + :members: step, add_species, add_laser, write_input_file -Cartesian3DGrid -""""""""""""""" .. autoclass:: pywarpx.picmi.Cartesian3DGrid -Cartesian2DGrid -""""""""""""""" .. autoclass:: pywarpx.picmi.Cartesian2DGrid -Cartesian1DGrid -""""""""""""""" .. autoclass:: pywarpx.picmi.Cartesian1DGrid -CylindricalGrid -""""""""""""""" .. autoclass:: pywarpx.picmi.CylindricalGrid -EmbeddedBoundary -"""""""""""""""" .. autoclass:: pywarpx.picmi.EmbeddedBoundary +Field solvers define the updates of electric and magnetic fields. + +.. autoclass:: pywarpx.picmi.ElectromagneticSolver + +.. autoclass:: pywarpx.picmi.ElectrostaticSolver + +Constants +--------- + +For convenience, the PICMI interface defines the following constants, +which can be used directly inside any PICMI script. The values are in SI units. + +- ``picmi.constants.c``: The speed of light in vacuum. +- ``picmi.constants.ep0``: The vacuum permittivity :math:`\epsilon_0` +- ``picmi.constants.mu0``: The vacuum permeability :math:`\mu_0` +- ``picmi.constants.q_e``: The elementary charge (absolute value of the charge of an electron). +- ``picmi.constants.m_e``: The electron mass +- ``picmi.constants.m_p``: The proton mass + Applied fields -^^^^^^^^^^^^^^ +-------------- -AnalyticInitialField -"""""""""""""""""""" .. autoclass:: pywarpx.picmi.AnalyticInitialField -ConstantAppliedField -"""""""""""""""""""" .. autoclass:: pywarpx.picmi.ConstantAppliedField -AnalyticAppliedField -"""""""""""""""""""" .. autoclass:: pywarpx.picmi.AnalyticAppliedField -PlasmaLens -"""""""""" .. autoclass:: pywarpx.picmi.PlasmaLens -Mirror -"""""" .. autoclass:: pywarpx.picmi.Mirror Diagnostics -^^^^^^^^^^^ +----------- -ParticleDiagnostic -"""""""""""""""""" .. autoclass:: pywarpx.picmi.ParticleDiagnostic -FieldDiagnostic -""""""""""""""" .. autoclass:: pywarpx.picmi.FieldDiagnostic -ElectrostaticFieldDiagnostic -"""""""""""""""""""""""""""" .. autoclass:: pywarpx.picmi.ElectrostaticFieldDiagnostic +.. autoclass:: pywarpx.picmi.Checkpoint + Lab-frame diagnostics diagnostics are used when running boosted-frame simulations. -LabFrameFieldDiagnostic -""""""""""""""""""""""" .. autoclass:: pywarpx.picmi.LabFrameFieldDiagnostic -Checkpoint -"""""""""" -.. autoclass:: pywarpx.picmi.Checkpoint - Particles -^^^^^^^^^ +--------- Species objects are a collection of particles with similar properties. For instance, background plasma electrons, background plasma ions and an externally injected beam could each be their own particle species. -Species -""""""" .. autoclass:: pywarpx.picmi.Species -MultiSpecies -"""""""""""" .. autoclass:: pywarpx.picmi.MultiSpecies Particle distributions can be used for to initialize particles in a particle species. -GaussianBunchDistribution -""""""""""""""""""""""""" .. autoclass:: pywarpx.picmi.GaussianBunchDistribution -UniformDistribution -""""""""""""""""""" .. autoclass:: pywarpx.picmi.UniformDistribution -AnalyticDistribution -"""""""""""""""""""" .. autoclass:: pywarpx.picmi.AnalyticDistribution -ParticleListDistribution -"""""""""""""""""""""""" .. autoclass:: pywarpx.picmi.ParticleListDistribution Particle layouts determine how to microscopically place macro particles in a grid cell. -GriddedLayout -""""""""""""" .. autoclass:: pywarpx.picmi.GriddedLayout -PseudoRandomLayout -"""""""""""""""""" .. autoclass:: pywarpx.picmi.PseudoRandomLayout -Other operations related to particles +Other operations related to particles: -CoulombCollisions -""""""""""""""""" .. autoclass:: pywarpx.picmi.CoulombCollisions -MCCCollisions -""""""""""""" .. autoclass:: pywarpx.picmi.MCCCollisions -FieldIonization -""""""""""""""" .. autoclass:: pywarpx.picmi.FieldIonization -Lasers -^^^^^^ +Laser Pulses +------------ Laser profiles can be used to initialize laser pulses in the simulation. -GaussianLaser -""""""""""""" .. autoclass:: pywarpx.picmi.GaussianLaser -AnalyticLaser -""""""""""""" .. autoclass:: pywarpx.picmi.AnalyticLaser Laser injectors control where to initialize laser pulses on the simulation grid. -LaserAntenna -"""""""""""" .. autoclass:: pywarpx.picmi.LaserAntenna -.. _usage-picmi-run: - -Running -------- - -WarpX can be run in one of two modes. It can run as a preprocessor, using the -Python input file to generate an input file to be used by the C++ version, or -it can be run directly from Python. -The examples support running in both modes by commenting and uncommenting the appropriate lines. - -In either mode, if using a `virtual environment `__, be sure to activate it before compiling and running WarpX. - - -Running WarpX directly from Python -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -For this, a full Python installation of WarpX is required, as described in :ref:`the install documentation ` (:ref:`developers `). - -In order to run a new simulation: - -* Create a **new directory**, where the simulation will be run. +.. _usage-picmi-extend: -* Add a **Python script** in the directory. +Extending a Simulation from Python +---------------------------------- -The input file should have the line ``sim.step()`` which runs the simulation. +When running WarpX directly from Python it is possible to interact with the simulation. -* **Run** the script with Python: +For instance, with the :py:meth:`~pywarpx.picmi.Simulation.step` method of the simulation class, one could run ``sim.step(nsteps=1)`` in a loop: -.. code-block:: bash +.. code-block:: python3 - mpirun -np python + # Preparation: set up the simulation + # sim = picmi.Simulation(...) + # ... -where ```` is the number of MPI ranks used, and ```` -is the name of the script. + steps = 1000 + for _ in range(steps): + sim.step(nsteps=1) + # do something custom with the sim object -.. _usage-picmi-extend: - -Extending a Simulation from Python -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -When running WarpX directly from Python it is possible to interact with the simulation -by installing ``CallbackFunctions``, which will execute a given Python function at a +As a more flexible alternative, one can install `callback functions `__, which will execute a given Python function at a specific location in the WarpX simulation loop. -.. autoclass:: pywarpx.callbacks.CallbackFunctions +.. automodule:: pywarpx.callbacks + :members: installcallback, uninstallcallback, isinstalled -Places in the WarpX loop where callbacks are available include: -``afterinit``, ``beforecollisions``, ``aftercollisions``, ``beforeEsolve``, ``afterEsolve``, -``beforeInitEsolve``, ``afterInitEsolve``, ``beforedeposition``, ``afterdeposition``, -``beforestep``, ``afterstep``, ``afterdiagnostics``,``afterrestart`` and ``oncheckpointsignal``. -See the examples in ``Examples/Tests/ParticleDataPython`` for references on how to use -``callbacks``. +Data Access +^^^^^^^^^^^ -There are several "hooks" available via the ``libwarpx`` shared library to access and manipulate -simulation objects (particles, fields and memory buffers) as well as general properties -(such as processor number). These "hooks" are accessible through the `Simulation.extension` object. +While the simulation is running, callbacks can access the WarpX simulation data *in situ*. -An important object is ``Simulation.extension.warpx``, which is available during simulation run. -This object is the Python equivalent to the central ``WarpX`` simulation class and provides access to -field ``MultiFab`` and ``ParticleContainer`` data. +An important object for data access is ``Simulation.extension.warpx``, which is available only during the simulation run. +This object is the Python equivalent to the C++ ``WarpX`` simulation class and provides access to field ``MultiFab`` and ``ParticleContainer`` data. .. py:function:: pywarpx.picmi.Simulation.extension.warpx.getistep() @@ -282,8 +204,7 @@ After the simulation is initialized, pyAMReX can be accessed via .. py:function:: amr.ParallelDescriptor.IOProcessorNumber() -Particles can be added to the simulation at specific positions and with specific -attribute values: +Particles can be added to the simulation at specific positions and with specific attribute values: .. code-block:: python @@ -295,8 +216,7 @@ attribute values: .. autofunction:: pywarpx.particle_containers.ParticleContainerWrapper.add_particles -Properties of the particles already in the simulation can be obtained with various -functions. +Properties of the particles already in the simulation can be obtained with various functions. .. autofunction:: pywarpx.particle_containers.ParticleContainerWrapper.get_particle_count @@ -314,10 +234,8 @@ New components can be added via Python. .. autofunction:: pywarpx.particle_containers.ParticleContainerWrapper.add_real_comp Various diagnostics are also accessible from Python. -This includes getting the deposited or total charge density from a given species -as well as accessing the scraped particle buffer. See the example in -``Examples/Tests/ParticleBoundaryScrape`` for a reference on how to interact -with scraped particle data. +This includes getting the deposited or total charge density from a given species as well as accessing the scraped particle buffer. +See the example in ``Examples/Tests/ParticleBoundaryScrape`` for a reference on how to interact with scraped particle data. .. autofunction:: pywarpx.particle_containers.ParticleContainerWrapper.get_species_charge_sum @@ -329,31 +247,8 @@ with scraped particle data. .. autofunction:: pywarpx.particle_containers.ParticleBoundaryBufferWrapper.get_particle_boundary_buffer -.. autofunction:: pywarpx.particle_containers.ParticleBoundaryBufferWrapper.clearParticleBoundaryBuffer +.. autofunction:: pywarpx.particle_containers.ParticleBoundaryBufferWrapper.clear_buffer The embedded boundary conditions can be modified when using the electrostatic solver. .. py:function:: pywarpx.picmi.Simulation.extension.warpx.set_potential_on_eb() - -Using Python Input as a Preprocessor -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In this case, only the pure Python version needs to be installed, as described :ref:`here `. - -In order to run a new simulation: - -* Create a **new directory**, where the simulation will be run. - -* Add a **Python script** in the directory. - -The input file should have the line like ``sim.write_input_file(file_name = 'inputs_from_PICMI')`` -which runs the preprocessor, generating the AMReX inputs file. - -* **Run** the script with Python: - -.. code-block:: bash - - python - -where ```` is the name of the script. -This creates the WarpX input file that you can run as normal with the WarpX executable. diff --git a/Docs/source/usage/workflows.rst b/Docs/source/usage/workflows.rst index 6fefcd9a243..4fe1b9e155a 100644 --- a/Docs/source/usage/workflows.rst +++ b/Docs/source/usage/workflows.rst @@ -8,6 +8,7 @@ This section collects typical user workflows and best practices for WarpX. .. toctree:: :maxdepth: 2 + workflows/domain_decomposition workflows/debugging workflows/libensemble workflows/plot_timestep_duration diff --git a/Docs/source/usage/domain_decomposition.rst b/Docs/source/usage/workflows/domain_decomposition.rst similarity index 98% rename from Docs/source/usage/domain_decomposition.rst rename to Docs/source/usage/workflows/domain_decomposition.rst index d3df5b78f5c..1340ecc10d9 100644 --- a/Docs/source/usage/domain_decomposition.rst +++ b/Docs/source/usage/workflows/domain_decomposition.rst @@ -66,7 +66,7 @@ and the details of the on-node parallelization and computer architecture used fo Because these parameters put additional constraints on the domain size for a simulation, it can be cumbersome to calculate the number of cells and the physical size of the computational domain for a given resolution. This -:download:`Python script <../../../Tools/DevUtils/compute_domain.py>` does it +:download:`Python script <../../../../Tools/DevUtils/compute_domain.py>` does it automatically. When using the RZ spectral solver, the values of ``amr.max_grid_size`` and ``amr.blocking_factor`` are constrained since the solver diff --git a/Python/pywarpx/callbacks.py b/Python/pywarpx/callbacks.py index b8824d0ef16..11ec7a279de 100644 --- a/Python/pywarpx/callbacks.py +++ b/Python/pywarpx/callbacks.py @@ -1,65 +1,71 @@ -# Copyright 2017-2022 The WarpX Community +# Copyright 2017-2023 The WarpX Community # # This file is part of WarpX. # -# Authors: David Grote, Roelof Groenewald +# Authors: David Grote, Roelof Groenewald, Axel Huebl # # License: BSD-3-Clause-LBNL -"""call back operations -===================== +"""Callback Locations +================== These are the functions which allow installing user created functions so that they are called at various places along the time step. The following three functions allow the user to install, uninstall and verify the different call back types. - - installcallback: Installs a function to be called at that specified time - - uninstallcallback: Uninstalls the function (so it won't be called anymore) - - isinstalled: Checks if the function is installed + +* :py:func:`installcallback`: Installs a function to be called at that specified time +* :py:func:`uninstallcallback`: Uninstalls the function (so it won't be called anymore) +* :py:func:`isinstalled`: Checks if the function is installed These functions all take a callback location name (string) and function or instance method as an argument. Note that if an instance method is used, an extra reference to the method's object is saved. -The install can be done using a decorator, which has the prefix "callfrom". See +The install can be done using a decorator, which has the prefix ``callfrom``. See example below. Functions can be called at the following times: - - beforeInitEsolve: before the initial solve for the E fields (i.e. before the PIC loop starts) - - afterinit: immediately after the init is complete - - beforeEsolve: before the solve for E fields - - poissonsolver: In place of the computePhi call but only in an electrostatic simulation - - afterEsolve: after the solve for E fields - - beforedeposition: before the particle deposition (for charge and/or current) - - afterdeposition: after particle deposition (for charge and/or current) - - beforestep: before the time step - - afterstep: after the time step - - afterdiagnostics: after diagnostic output - - oncheckpointsignal: on a checkpoint signal - - onbreaksignal: on a break signal. These callbacks will be the last ones executed before the simulation ends. - - particlescraper: just after the particle boundary conditions are applied - but before lost particles are processed - - particleloader: at the time that the standard particle loader is called - - particleinjection: called when particle injection happens, after the position - advance and before deposition is called, allowing a user - defined particle distribution to be injected each time step - - appliedfields: allows directly specifying any fields to be applied to the particles - during the advance + +* ``beforeInitEsolve``: before the initial solve for the E fields (i.e. before the PIC loop starts) +* ``afterinit``: immediately after the init is complete +* ``beforeEsolve``: before the solve for E fields +* ``poissonsolver``: In place of the computePhi call but only in an electrostatic simulation +* ``afterEsolve``: after the solve for E fields +* ``beforedeposition``: before the particle deposition (for charge and/or current) +* ``afterdeposition``: after particle deposition (for charge and/or current) +* ``beforestep``: before the time step +* ``afterstep``: after the time step +* ``afterdiagnostics``: after diagnostic output +* ``oncheckpointsignal``: on a checkpoint signal +* ``onbreaksignal``: on a break signal. These callbacks will be the last ones executed before the simulation ends. +* ``particlescraper``: just after the particle boundary conditions are applied + but before lost particles are processed +* ``particleloader``: at the time that the standard particle loader is called +* ``particleinjection``: called when particle injection happens, after the position + advance and before deposition is called, allowing a user + defined particle distribution to be injected each time step +* ``appliedfields``: allows directly specifying any fields to be applied to the particles + during the advance To use a decorator, the syntax is as follows. This will install the function ``myplots`` to be called after each step. -@callfromafterstep -def myplots(): - ppzx() +.. code-block:: python3 + + @callfromafterstep + def myplots(): + ppzx() This is equivalent to the following: -def myplots(): - ppzx() -installcallback('afterstep', myplots) +.. code-block:: python3 + + def myplots(): + ppzx() + installcallback('afterstep', myplots) """ import copy import sys @@ -282,15 +288,20 @@ def callfuncsinlist(self,*args,**kw): callback_instances[key] = CallbackFunctions(name=key, **val) def installcallback(name, f): - "Adds a function to the list of functions called by this callback" + """Installs a function to be called at that specified time. + + Adds a function to the list of functions called by this callback. + """ callback_instances[name].installfuncinlist(f) def uninstallcallback(name, f): - "Removes the function from the list of functions called by this callback" + """Uninstalls the function (so it won't be called anymore). + + Removes the function from the list of functions called by this callback.""" callback_instances[name].uninstallfuncinlist(f) def isinstalled(name, f): - "Checks if the function is called by this callback" + """Checks if a function is installed for this callback.""" return callback_instances[name].isinstalledfuncinlist(f) def clear_all(): diff --git a/Python/pywarpx/particle_containers.py b/Python/pywarpx/particle_containers.py index cece7968079..84f78a029ad 100644 --- a/Python/pywarpx/particle_containers.py +++ b/Python/pywarpx/particle_containers.py @@ -200,7 +200,7 @@ def get_particle_structs(self, level, copy_to_host=False): Note that cupy does not support structs: https://github.com/cupy/cupy/issues/2031 - and will return arrays of binary blobs for the AoS (DP: "|V24"). If copied + and will return arrays of binary blobs for the AoS (DP: ``"|V24"``). If copied to host via copy_to_host, we correct for the right numpy AoS type. Parameters @@ -652,9 +652,10 @@ def getbz(self): def deposit_charge_density(self, level, clear_rho=True, sync_rho=True): - ''' + """ Deposit this species' charge density in rho_fp in order to access that data via pywarpx.fields.RhoFPWrapper(). + Parameters ---------- species_name : str @@ -665,7 +666,7 @@ def deposit_charge_density(self, level, clear_rho=True, sync_rho=True): If True, zero out rho_fp before deposition. sync_rho : bool If True, perform MPI exchange and properly set boundary cells for rho_fp. - ''' + """ rho_fp = libwarpx.warpx.multifab(f'rho_fp[level={level}]') if rho_fp is None: @@ -734,7 +735,7 @@ def get_particle_boundary_buffer_structs( Note that cupy does not support structs: https://github.com/cupy/cupy/issues/2031 - and will return arrays of binary blobs for the AoS (DP: "|V24"). If copied + and will return arrays of binary blobs for the AoS (DP: ``"|V24"``). If copied to host via copy_to_host, we correct for the right numpy AoS type. Parameters diff --git a/Python/pywarpx/picmi.py b/Python/pywarpx/picmi.py index 2998cd6747e..08f96238703 100644 --- a/Python/pywarpx/picmi.py +++ b/Python/pywarpx/picmi.py @@ -561,7 +561,7 @@ class CylindricalGrid(picmistandard.PICMI_CylindricalGrid): See `Input Parameters `__ for more information. Parameters - --------- + ---------- warpx_max_grid_size: integer, default=32 Maximum block size in either direction @@ -681,7 +681,7 @@ class Cartesian1DGrid(picmistandard.PICMI_Cartesian1DGrid): See `Input Parameters `__ for more information. Parameters - --------- + ---------- warpx_max_grid_size: integer, default=32 Maximum block size in either direction @@ -770,7 +770,7 @@ class Cartesian2DGrid(picmistandard.PICMI_Cartesian2DGrid): See `Input Parameters `__ for more information. Parameters - --------- + ---------- warpx_max_grid_size: integer, default=32 Maximum block size in either direction @@ -879,7 +879,7 @@ class Cartesian3DGrid(picmistandard.PICMI_Cartesian3DGrid): See `Input Parameters `__ for more information. Parameters - --------- + ---------- warpx_max_grid_size: integer, default=32 Maximum block size in either direction @@ -1828,9 +1828,11 @@ class Simulation(picmistandard.PICMI_Simulation): warpx_sort_idx_type: list of int, optional (default: 0 0 0) This controls the type of grid used to sort the particles when sort_particles_for_deposition is true. Possible values are: - idx_type = {0, 0, 0}: Sort particles to a cell centered grid, - idx_type = {1, 1, 1}: Sort particles to a node centered grid, - idx_type = {2, 2, 2}: Compromise between a cell and node centered grid. + + * idx_type = {0, 0, 0}: Sort particles to a cell centered grid, + * idx_type = {1, 1, 1}: Sort particles to a node centered grid, + * idx_type = {2, 2, 2}: Compromise between a cell and node centered grid. + In 2D (XZ and RZ), only the first two elements are read. In 1D, only the first element is read. warpx_sort_bin_size: list of int, optional (default 1 1 1)