-
Notifications
You must be signed in to change notification settings - Fork 225
openpmd.py plugin for PICMI #5353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
openpmd.py plugin for PICMI #5353
Conversation
if self.data_preparation_strategy is not None and self.data_preparation_strategy not in [ | ||
"doubleBuffer", | ||
"adios", | ||
"mappedMemory", | ||
"hdf5", | ||
]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we might want to use Literals and enforce them via the type system in the constructor
source: Optional[Source] = None, | ||
range: Optional[str] = None, | ||
file: Optional[str] = None, | ||
ext: Optional[str] = None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the ext parameter should defined as a literal not a str
def __init__( | ||
self, | ||
period: TimeStepSpec, | ||
source: Optional[Source] = None, | ||
range: Optional[str] = None, | ||
file: Optional[str] = None, | ||
ext: Optional[str] = None, | ||
infix: Optional[str] = None, | ||
json: Optional[Union[str, Dict]] = None, | ||
json_restart: Optional[Union[str, Dict]] = None, | ||
data_preparation_strategy: Optional[str] = None, | ||
toml: Optional[str] = None, | ||
particle_io_chunk_size: Optional[int] = None, | ||
file_access: Optional[str] = None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the default value slisted in the documentation do not match the actual constructor defaults
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
follwoing here we have
--openPMD.source | Select data sources and filters to dump. Default is species_all,fields_all,
for this reason self.source = source if source is not None else Source(["species_all", "fields_all"]). is it still wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's not what I meant, for example
the default for ext
is bp
following the documentation, but the constructor default argument is None
it should be bp
instead.
Please match the default arguments in the documentation to the defaults specified by the constructor.
And more general, most of the settings are currently PIConGPU specific. That is fine for now but we have to figure out a way to abstract that in the future
""" | ||
Specifies the parameters for the openPMD plugin in PIConGPU simulations. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the PICMI implementation should not reference PIConGPU
source: Source, optional | ||
Data sources and filters to dump (e.g., Source([ChargeDensity(filter="filterX"), "species_all"])). | ||
Default: Source(["species_all", "fields_all"]). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not a fan of allowing "str" specification of sources, that jsut adds another way to get the same results and I would prefer just one good way to specify stuff.
class Source: | ||
""" | ||
Consolidates data sources for the openPMD plugin in PIConGPU. | ||
This class aggregates individual data sources (e.g., ChargeDensity) or predefined | ||
keywords (species_all, fields_all) to define the --openPMD.source parameter: | ||
https://picongpu.readthedocs.io/en/latest/usage/plugins/openPMD.html | ||
Parameters | ||
---------- | ||
sources: List[Union[str, <DataSourceClasses>]] | ||
List of data sources, either as strings (e.g., "species_all", "fields_all") or | ||
as data source objects (e.g., ChargeDensity, Density). | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mafshari64 could you please comment on why you consider the aggregator functionality class necessary? I currently don' see why it is needed, it looks like the entire functionality could be moved to the openPMD plugin.
Instead I would use this class as an interface for all source implementations
@typeguard.typechecked | ||
class BoundElectronDensity: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this class should inherit from a common interface of all Sources for the openPMD plugin
The dataset name with optional filter (e.g., "bound_electron_density" or | ||
"bound_electron_density:filterX"). | ||
""" | ||
if self.filter: | ||
return f"bound_electron_density:{self.filter}" | ||
return "bound_electron_density" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the conversion to strings should not happen on the PICMI side, that string is already PIConGPU specific
def get_source_string(self) -> str: | ||
""" | ||
Return the source string for use in --openPMD.source. | ||
Returns | ||
------- | ||
str | ||
The dataset name with optional filter (e.g., "charge_density" or "charge_density:filterX"). | ||
""" | ||
if self.filter: | ||
return f"charge_density:{self.filter}" | ||
return "charge_density" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same problem here, the source string should happen at the earliest in PyPIConGPU, as the generated string is PIConGPU specific.
also the generated string is wrong, it should be source_all
str, | ||
ChargeDensity, | ||
BoundElectronDensity, | ||
Counter, | ||
Density, | ||
Energy, | ||
EnergyDensity, | ||
EnergyDensityCutoff, | ||
LarmorPower, | ||
MacroCounter, | ||
MidCurrentDensityComponent, | ||
Momentum, | ||
MomentumDensity, | ||
WeightedVelocity, | ||
] | ||
] | ||
) | ||
|
||
def __init__( | ||
self, | ||
sources: typing.List[ | ||
typing.Union[ | ||
str, | ||
ChargeDensity, | ||
BoundElectronDensity, | ||
Counter, | ||
Density, | ||
Energy, | ||
EnergyDensity, | ||
EnergyDensityCutoff, | ||
LarmorPower, | ||
MacroCounter, | ||
MidCurrentDensityComponent, | ||
Momentum, | ||
MomentumDensity, | ||
WeightedVelocity, | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not a fan of the many repeats of the all the different source,please switch to using interfaces and testing with isinstance for the interface
fundamentally and in summary, the current PR lacks an common interface for all the current sources of the openPMD plugin and this interface is required. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
general the current version is still missing the configuration of species contributing to the derived field sources.
def __init__(self, filter: typing.Optional[str] = None): | ||
self.filter = filter | ||
self.check() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
default filter should be all
, as this is the PIConGPU standard. And since we will stick to str for now, I would like to avoid using Optional here as it only complicates the implementation.
In addition, this class is missing the option to configure the species contributing to this source, please add a list of species that should contribute to this source.
def __init__(self, filter: typing.Optional[str] = None): | ||
self.filter = filter | ||
self.check() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same problem as charge density source, the user must be able to specify the species that will contribute to the derived field source
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks generally good, but documentation strings should use doxygen annotations
""" | ||
Specifies parameters for openPMD diagnostic output in particle-in-cell simulations. | ||
This diagnostic outputs simulation data (fields and particles) to disk using the openPMD | ||
standard, with configurable periods, data sources, and backend settings. | ||
Attention: **period is mandatory.** | ||
Parameters | ||
---------- | ||
period: TimeStepSpec | ||
Specifies the time steps for data output. | ||
Unit: simulation time steps. Required. | ||
source: List[SourceBase], optional | ||
List of data source objects to dump (e.g., [ChargeDensity(filter="all")]). | ||
Default: None (no sources specified). | ||
range: str, optional | ||
Contiguous range of cells per dimension to dump (e.g., ":,:,:"). | ||
Format: comma-separated ranges like "begin:end,begin:end,begin:end". | ||
Default: ":,::,:" (all cells). | ||
file: str, optional | ||
Relative or absolute file prefix for openPMD output files. | ||
If relative, files are stored under the simulation output directory. | ||
Default: None (backend-dependent default). | ||
ext: Literal["bp", "h5", "sst"], optional | ||
File extension controlling the openPMD backend. | ||
Options: "bp" (ADIOS2), "h5" (HDF5), "sst" (ADIOS2/SST for streaming). | ||
Default: "bp" (ADIOS2 backend). | ||
infix: str, optional | ||
Filename infix for iteration layout (e.g., "_%06T"). | ||
Use "NULL" for group-based layout. Required as "NULL" if ext="sst". | ||
Default: "NULL" (group-based layout). | ||
json: Union[str, Dict], optional | ||
Backend-specific parameters for writing, as a JSON string, dictionary, or filename | ||
(filename must be prepended with "@"). | ||
Default: {} (empty dictionary). | ||
json_restart: Union[str, Dict], optional | ||
Backend-specific parameters for restarting, as a JSON string, dictionary, or filename | ||
(filename must be prepended with "@"). | ||
Default: {} (empty dictionary). | ||
data_preparation_strategy: Literal["doubleBuffer", "adios", "mappedMemory", "hdf5"], optional | ||
Strategy for particle data preparation. | ||
Options: "doubleBuffer" or "adios" (ADIOS2-based), "mappedMemory" or "hdf5" (HDF5-based). | ||
Default: None (backend-dependent). | ||
toml: str, optional | ||
Path to a TOML file for openPMD configuration. | ||
Default: None. | ||
particle_io_chunk_size: int, optional | ||
Size of particle data chunks for writing (in MiB). | ||
Reduces host memory footprint for certain backends. | ||
Default: None (backend-dependent). | ||
file_access: Literal["create", "append"], optional | ||
File access mode for writing. | ||
Options: "create" (new files), "append" (for checkpoint-restart workflows). | ||
Default: "create" (new files). | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
""" | |
Specifies parameters for openPMD diagnostic output in particle-in-cell simulations. | |
This diagnostic outputs simulation data (fields and particles) to disk using the openPMD | |
standard, with configurable periods, data sources, and backend settings. | |
Attention: **period is mandatory.** | |
Parameters | |
---------- | |
period: TimeStepSpec | |
Specifies the time steps for data output. | |
Unit: simulation time steps. Required. | |
source: List[SourceBase], optional | |
List of data source objects to dump (e.g., [ChargeDensity(filter="all")]). | |
Default: None (no sources specified). | |
range: str, optional | |
Contiguous range of cells per dimension to dump (e.g., ":,:,:"). | |
Format: comma-separated ranges like "begin:end,begin:end,begin:end". | |
Default: ":,::,:" (all cells). | |
file: str, optional | |
Relative or absolute file prefix for openPMD output files. | |
If relative, files are stored under the simulation output directory. | |
Default: None (backend-dependent default). | |
ext: Literal["bp", "h5", "sst"], optional | |
File extension controlling the openPMD backend. | |
Options: "bp" (ADIOS2), "h5" (HDF5), "sst" (ADIOS2/SST for streaming). | |
Default: "bp" (ADIOS2 backend). | |
infix: str, optional | |
Filename infix for iteration layout (e.g., "_%06T"). | |
Use "NULL" for group-based layout. Required as "NULL" if ext="sst". | |
Default: "NULL" (group-based layout). | |
json: Union[str, Dict], optional | |
Backend-specific parameters for writing, as a JSON string, dictionary, or filename | |
(filename must be prepended with "@"). | |
Default: {} (empty dictionary). | |
json_restart: Union[str, Dict], optional | |
Backend-specific parameters for restarting, as a JSON string, dictionary, or filename | |
(filename must be prepended with "@"). | |
Default: {} (empty dictionary). | |
data_preparation_strategy: Literal["doubleBuffer", "adios", "mappedMemory", "hdf5"], optional | |
Strategy for particle data preparation. | |
Options: "doubleBuffer" or "adios" (ADIOS2-based), "mappedMemory" or "hdf5" (HDF5-based). | |
Default: None (backend-dependent). | |
toml: str, optional | |
Path to a TOML file for openPMD configuration. | |
Default: None. | |
particle_io_chunk_size: int, optional | |
Size of particle data chunks for writing (in MiB). | |
Reduces host memory footprint for certain backends. | |
Default: None (backend-dependent). | |
file_access: Literal["create", "append"], optional | |
File access mode for writing. | |
Options: "create" (new files), "append" (for checkpoint-restart workflows). | |
Default: "create" (new files). | |
""" | |
""" | |
openPMD diagnostic output | |
This diagnostic writes simulation data (base fields , derived fields and/or particles) to disk using the openPMD | |
standard, with configurable periods, data sources and backend settings. | |
@param period specification of the the time steps for data output, outputs will always be written at the end of a PIC time step. | |
@param source list of data source objects to include in the dump (e.g., [ChargeDensity(filter="all")]), | |
Setting this to None will cause an empty dump | |
@param range contiguous range of cells to dump the base- and derived field for | |
specification as comma-separated "begin:end" range for each dimension, i.e. "begin:end,begin:end,begin:end" | |
Notes: Values will be clipped to the simulation box. Begin and/or end may be omitted to indicate the limit of the simulation box in the dimension. The Default value ":,::,:" indicates that fields should be dumped for all cells. | |
@param file relative or absolute file path prefix for openPMD output files. Relative path are interpreted as relative to the simulation output directory, the default value None indicates the backend's default. | |
@param ext file extension controlling the openPMD backend, options are "bp" (default backend ADIOS2), "bp4" (bp4 backend ADIOS2), "bp5" (bp5 backend ADIOS2), "h5" (HDF5), "sst" (ADIOS2/SST for streaming). | |
@param infix filename infix for the iteration layout (e.g., "_%06T"), use "NULL" for the group-based layout, ext="sst" requires infix="NULL". | |
@param json openPMD backend configuration as a JSON string, dictionary, or filename (filename must be prepended with "@"). | |
@param json_restart: backend-specific parameters for restarting, as a JSON string, dictionary, or filename (filenames must be prepended with "@"). | |
@param data_preparation_strategy: strategy for particle data preparation, options: "doubleBuffer" or "adios" (ADIOS2-based), "mappedMemory" or "hdf5" (HDF5-based), the default value None indicates the backend default | |
@param toml path to a TOML file for openPMD configuration. Replaces the JSON or keyword configuration. | |
@param particle_io_chunk_size size of particle data chunks used in writing (in MiB), reduces host memory footprint for certain backends, default "None" indicates the backend default. | |
@param file_access file access mode for writing, options: "create" (new files), "append" (for checkpoint-restart workflows). | |
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please use the doxygen annotations for the documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for review,
a short question: in other picmi/diagnositcs files I used standard Python docstring format eg lib/python/picongpu/picmi/diagnostics/macro_particle_count.py and not oxygen annotations. just for this file
lib/python/picongpu/picmi/diagnostics/openpmd.py
for documentation or do for all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a first review - no test yet
Contiguous range of cells per dimension to dump (e.g., ":,:,:"). | ||
Format: comma-separated ranges like "begin:end,begin:end,begin:end". | ||
Default: None (all cells). | ||
Default: ":,::,:" (all cells). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a typo, right?
Default: ":,::,:" (all cells). | |
Default: ":,:,:" (all cells). |
File extension controlling the openPMD backend. | ||
Options: "bp" (ADIOS2), "h5" (HDF5), "sst" (ADIOS2/SST for streaming). | ||
Default: None (backend-dependent). | ||
Default: "bp" (ADIOS2 backend). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not ensured, as we might compile with hdf5 only
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you really want to hard code your selection below here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just mentioned bp
as the default as it is in documentation not hardcoded. users can specify what they want.
@@ -0,0 +1,59 @@ | |||
""" | |||
This file is part of PIConGPU. | |||
Copyright 2021-2024 PIConGPU contributors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright 2021-2024 PIConGPU contributors | |
Copyright 2021-2025 PIConGPU contributors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does it start in 2021? Was it copied from somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry I forgot to change it. I will do
Represents a default data source for openPMD output in particle-in-cell simulations. | ||
This class specifies a backend-specific default source for dumping simulation data | ||
using the openPMD standard. For example, in some backends, it may dump all particle |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why only in some backends. As I understand it, backends are e.g. ADIOS or HDF5, but that doesn't determine what you write out.
---------- | ||
filter: str, optional | ||
Name of a filter to select data contributing to the source. | ||
Default: None (backend-dependent). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the filter backend dependent. Our filters are defined in PIConGPU.
""" | ||
This file is part of PIConGPU. | ||
Copyright 2021-2025 PIConGPU contributors | ||
Copyright 2021-2024 PIConGPU contributors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright 2021-2024 PIConGPU contributors | |
Copyright 2021-2025 PIConGPU contributors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does it start in 2021? Was it copied from some file?
""" | ||
This file is part of PIConGPU. | ||
Copyright 2021-2025 PIConGPU contributors | ||
Copyright 2021-2024 PIConGPU contributors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
@@ -0,0 +1,34 @@ | |||
""" | |||
This file is part of PIConGPU. | |||
Copyright 2021-2024 PIConGPU contributors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
@mafshari64 There seems to be conflicts with the current PR. See info. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Offline discussion: We need further testing before approval.
""" | ||
This file is part of PIConGPU. | ||
Copyright 2024 PIConGPU contributors | ||
Authors: Julian Lenz, Masoud Afshari | ||
License: GPLv3+ | ||
""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why's this removed?
from .timestepspec import TimeStepSpec | ||
from .checkpoint import Checkpoint | ||
from .openpmd import OpenPMD | ||
from .openpmd_sources.source_base import SourceBase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that this should be here. We don't want to expose this to the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so delete it?
@param range contiguous range of cells to dump the base- and derived field for | ||
specification as comma-separated "begin:end" range for each dimension, i.e. "begin:end,begin:end,begin:end" | ||
Notes: Values will be clipped to the simulation box. Begin and/or end may be omitted to indicate the limit of the simulation box in the dimension. The Default value ":,::,:" indicates that fields should be dumped for all cells. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should become a class similar to TimeStepSpec
. But be aware that there are subtle differences in semantics that would need to be represented in that new class.
if self.period is None: | ||
raise ValueError("period is mandatory") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can't happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean should I delete it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I retained for defensive programming probably in future other external users might subclass or modify behavior in unexpected ways. but if you want I can remove it.
Hi Julian, @chillenzer, I have finally solved the issues and finalized this branch. In a separate PR I will add all CI tests for picim and pypicongpu. agree? |
b753779
to
b7c3c53
Compare
@mafshari64 Please rebase your PR to the current |
@mafshari64 I do not see a fix of this PR yet, do you have problems resolving the conflict? This feature would be great to have in |
Superseded by #5461 which includes these commits. |
@chillenzer
@BrianMarre