Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ docs/doxyhtml/
docs/doxyxml/

### Output ####
## Plot files
**/plt*
## Plot files (e.g., plt00000 and test outputs like plt_read_hdr,
## but not source files such as pltfile_to_openpmd.py)
**/plt[0-9]*
**/plt_*
## Checkpoints
**/chk*
1 change: 1 addition & 0 deletions docs/source/usage/workflows.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This section collects typical user workflows and best practices for pyAMReX.
:maxdepth: 2

workflows/read_plotfiles
workflows/pltfile_to_openpmd
.. workflows/parallelization
.. workflows/profiling
.. workflows/debugging
Expand Down
46 changes: 46 additions & 0 deletions docs/source/usage/workflows/pltfile_to_openpmd.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.. _usage-how-to-pltfile-to-openpmd:

Convert Plotfiles to openPMD
============================

The ``pltfile-to-openpmd`` tool converts native AMReX plotfiles (mesh fields and particles) to `openPMD <https://www.openpmd.org>`__ series, readable by openPMD-viewer, ParaView, VisIt and the wider openPMD ecosystem.
The openPMD backend - HDF5 (``.h5``), ADIOS2 (``.bp``) or JSON (``.json``) - is selected by the output file extension.
It requires the `openpmd-api <https://openpmd-api.readthedocs.io>`__ Python package (``pip install openpmd-api``).

Each plotfile becomes one openPMD iteration, indexed by its level-0 step number:

.. code-block:: bash

pltfile-to-openpmd -o sim_%T.h5 diags/plt00000 diags/plt00100

# equivalent, e.g., if the entry point is not on PATH:
python -m amrex.tools.pltfile_to_openpmd -o sim_%T.h5 diags/plt?????

or, from Python:

.. code-block:: python

from amrex.tools.pltfile_to_openpmd import convert

convert(["diags/plt00000", "diags/plt00100"], "sim_%T.h5")

Run ``pltfile-to-openpmd --help`` for all options (field/species selection, skipping particles, recording a time step, quiet mode).
The plotfile's dimensionality is detected automatically and the matching ``amrex.space{1,2,3}d`` module is used.

Data Mapping
------------

The conversion is information-preserving:

* Field data is copied at its on-disk precision, per AMR level, with every AMReX grid stored as one chunk of the level's dataset.
AMReX's Fortran axis order is reversed into openPMD's C order (``axisLabels`` e.g. ``["z", "y", "x"]``).
* Mesh refinement levels follow the openPMD `PatchBasedMeshRefinement <https://github.com/openPMD/openPMD-standard/pull/252>`__ extension proposal: the coarsest level keeps the plain record name (readable by every openPMD tool), finer levels are suffixed ``_lvl<N>`` and carry a ``refinementRatio`` attribute.
* Particles are converted per species (discovered via :py:func:`~amrex.space3d.list_particle_species` and read via :py:func:`~amrex.space3d.read_particles`, see :ref:`Read Back Plotfiles <usage-how-to-read-plotfiles>`), with their component names verbatim, unpacked ``id`` and ``amrex_cpu`` records, and a constant ``positionOffset`` of zero.
* AMReX metadata without an openPMD equivalent is stored in ``amrex_``-prefixed attributes: per-level steps, box arrays, ghost-cell widths, the coordinate system, and per-species file metadata.
Together with the chunk layout, this suffices to reconstruct the plotfile structure.

Limitations, by design of the source format and this tool:

* Plotfiles carry no unit metadata, so ``unitSI`` is 1 and ``unitDimension`` is dimensionless; record a time step with ``--dt`` if needed.
* The on-disk *ordering* of particles is not preserved (identities are, via ``id``/``amrex_cpu``); their mesh-refinement level assignment is recoverable from positions and the stored per-level box arrays - the same rule AMReX applies in ``Redistribute()``.
* Ghost cell *values* are not written (the valid region is); the ghost width is recorded in ``amrex_n_grow``.
8 changes: 8 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,14 @@ def build_extension(self, ext):
python_requires=">=3.11",
tests_require=["pytest"],
install_requires=install_requires,
extras_require={
"openpmd": ["openpmd-api"],
},
entry_points={
"console_scripts": [
"pltfile-to-openpmd = amrex.tools.pltfile_to_openpmd:main",
],
},
# cmdclass={'test': PyTest},
# platforms='any',
classifiers=[
Expand Down
2 changes: 2 additions & 0 deletions src/amrex/tools/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
"""Standalone tools built on pyAMReX, usable as modules and CLIs."""
Loading
Loading