Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
809dde8
adding openpmd.py and charge_density.py
mafshari64 Apr 28, 2025
43d75d9
common interface for all the current sources of the openPMD plugin
mafshari64 Apr 28, 2025
c25e8cb
adding species to openpmd sources
mafshari64 Apr 29, 2025
d29e104
adding other openpmd picongpu sources
mafshari64 May 6, 2025
7557c96
providing openpmd sources for pypicongpu
mafshari64 May 7, 2025
d3d0d40
adding schema for openpmd plugin
mafshari64 May 8, 2025
0320db9
updating openpmd files
mafshari64 May 9, 2025
0515b28
finalizing openpmd plugin
mafshari64 May 12, 2025
d69e0d5
adding rangespec class to openpmd
mafshari64 Jul 31, 2025
95cfb14
editing pypicongpu/output/openpmd.py
mafshari64 Jul 31, 2025
8f3052a
removing Default simulation_box to fix CI LWFA
mafshari64 Aug 1, 2025
2ddd015
add simulation_box to s.plugin in picmi.simulation.py
mafshari64 Aug 1, 2025
8925047
Fix TypeError in PhaseSpace and Auto by adding simulation_box parameter
mafshari64 Aug 1, 2025
9cd6366
Fix TypeError for openpmd plugin
mafshari64 Aug 4, 2025
759b589
Fix simulation_box usage in simulation.py to resolve ruff F841 error
mafshari64 Aug 4, 2025
98a099c
Add EnergyHistogram test suite and CI pipeline
mafshari64 Aug 5, 2025
768076e
Add pypicongpu/output/macro_particle_count.py test
mafshari64 Aug 5, 2025
36a75dc
Add checkpoint CI test
mafshari64 Aug 6, 2025
6152432
Add png CI test
mafshari64 Aug 6, 2025
df01c14
Add openpmd CI test
mafshari64 Aug 7, 2025
50036b5
Add rangespec CI test
mafshari64 Aug 7, 2025
be37b06
removing bugs for energy_histogram and checkpoint CI test
mafshari64 Aug 7, 2025
12498ad
removing bugs for macro_particle_count and png CI tests
mafshari64 Aug 8, 2025
4009cb2
removing bugs for png and rangespec CI tests
mafshari64 Aug 8, 2025
3d6ea49
removing bugs for openpmd CI test
mafshari64 Aug 11, 2025
73dc051
added openpmd_sources subclasses CI test
mafshari64 Aug 12, 2025
96d04f5
added rangespec and auto PICMI CI test
mafshari64 Aug 13, 2025
be97bd5
added rangespec and energy_histogram and macro_particle_count PICMI C…
mafshari64 Aug 18, 2025
cc9180c
updating PICMI CI tests by adding int´to period alongwith timestepspec
mafshari64 Aug 18, 2025
d461cf1
debugging PICMI CI timestepspec and auto
mafshari64 Aug 19, 2025
7e1ecd1
debugging PICMI CI energy_histogram
mafshari64 Aug 20, 2025
4c8e7b8
debugging PICMI CI phase_space
mafshari64 Aug 21, 2025
2a35e21
debugging PICMI CI phase_space 1
mafshari64 Aug 21, 2025
214be48
debugging PICMI CI phase_space finished
mafshari64 Aug 21, 2025
4fc1187
debugging PICMI CI macro_particle_count
mafshari64 Aug 21, 2025
da2f5f8
debugging PICMI CI png and auto
mafshari64 Aug 22, 2025
83bf897
debugging PICMI CI png and auto phasespce histogram
mafshari64 Aug 25, 2025
b89c965
debugging PICMI CI openpmd
mafshari64 Aug 26, 2025
67b132b
debugging PICMI CI openpmd 1
mafshari64 Aug 27, 2025
b68451b
debugging PICMI CI openpmd 1
mafshari64 Aug 28, 2025
44c97e5
all CI tests ran successfullly with no failures
mafshari64 Aug 29, 2025
d816894
all CI tests ran successfullly with no failures 1
mafshari64 Aug 29, 2025
e374ef3
correcting folder_name to folder to match png plugin
mafshari64 Sep 1, 2025
aff59ed
add more axis to png axis
mafshari64 Sep 1, 2025
357d64b
fix main.py LWFA example
mafshari64 Sep 1, 2025
4a7818b
fix HOME/src/picongpu issue
mafshari64 Sep 1, 2025
92ae438
delete test.log and checkpoint docstring
mafshari64 Sep 1, 2025
694e16b
modifying pypicongpu CI test
mafshari64 Sep 5, 2025
5a2332e
repacking multi sources to a single source file
mafshari64 Sep 12, 2025
bc39fa8
classifying all openpmd sources CI test
mafshari64 Sep 12, 2025
d8de6b5
finalizing PICMI - pypicongpu CI tests
mafshari64 Sep 16, 2025
80c57ab
fixing some conflicts
mafshari64 Sep 18, 2025
51a0708
fixing a0 E0 condition for base_laser
mafshari64 Sep 23, 2025
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: 6 additions & 0 deletions lib/python/picongpu/picmi/diagnostics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
from .macro_particle_count import MacroParticleCount
from .png import Png
from .timestepspec import TimeStepSpec
from .rangespec import RangeSpec
from .checkpoint import Checkpoint
from .openpmd import OpenPMD
from .openpmd_sources import SourceBase

__all__ = [
"Auto",
Expand All @@ -22,5 +25,8 @@
"MacroParticleCount",
"Png",
"TimeStepSpec",
"RangeSpec",
"Checkpoint",
"OpenPMD",
"SourceBase",
]
35 changes: 22 additions & 13 deletions lib/python/picongpu/picmi/diagnostics/auto.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
"""
This file is part of PIConGPU.
Copyright 2025 PIConGPU contributors
Authors: Pawel Ordyna
Authors: Pawel Ordyna, Masoud Afshari
License: GPLv3+
"""


from ...pypicongpu.output.auto import Auto as PyPIConGPUAuto
from ...pypicongpu.species.species import Species as PyPIConGPUSpecies

from ..species import Species as PICMISpecies
from .timestepspec import TimeStepSpec

import typeguard
import warnings


@typeguard.typechecked
Expand All @@ -22,28 +20,39 @@ class Auto:

Parameters
----------
period: int
Number of simulation steps between consecutive outputs.
period: int or TimeStepSpec
Number of simulation steps between consecutive outputs (e.g., 10 for every 10 steps).
Use 0 to disable output.
Alternatively, a TimeStepSpec can be provided for PIConGPU-specific step selection
(e.g., TimeStepSpec[5, 10], TimeStepSpec[-10:]).
Unit: steps (simulation time steps).
"""

period: TimeStepSpec
"""Number of simulation steps between consecutive outputs. Unit: steps (simulation time steps)."""

def __init__(self, period: TimeStepSpec) -> None:
self.period = period
def __init__(self, period: int | TimeStepSpec) -> None:
if not isinstance(period, (int, TimeStepSpec)):
raise TypeError("period must be an integer or TimeStepSpec")
if isinstance(period, int):
if period < 0:
raise ValueError("period must be non-negative")
self.period = TimeStepSpec[::period]("steps") if period > 0 else TimeStepSpec()("steps")
else:
self.period = period
if self.period.unit_system is None:
self.period = self.period("steps")

def check(self):
pass
if not self.period.get_as_pypicongpu(1.0, 100).get_rendering_context().get("specs", []):
warnings.warn("Auto output is disabled because period is set to 0 or an empty TimeStepSpec")

def get_as_pypicongpu(
self,
# not used here, but needed for the interface
dict_species_picmi_to_pypicongpu: dict[PICMISpecies, PyPIConGPUSpecies],
time_step_size,
num_steps,
simulation_box=None, # Added to match OpenPMD signature, not used
) -> PyPIConGPUAuto:
self.check()
pypicongpu_auto = PyPIConGPUAuto()
pypicongpu_auto.period = self.period.get_as_pypicongpu(time_step_size, num_steps)

return pypicongpu_auto
99 changes: 50 additions & 49 deletions lib/python/picongpu/picmi/diagnostics/checkpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

from ...pypicongpu.output.checkpoint import Checkpoint as PyPIConGPUCheckpoint
from .timestepspec import TimeStepSpec

import typeguard
from typing import Optional, Dict
import warnings
from typing import Optional, Union, Dict


@typeguard.typechecked
Expand All @@ -24,62 +24,42 @@ class Checkpoint:

Parameters
----------
period: TimeStepSpec, optional
Specify on which time steps to create checkpoints.
Unit: steps (simulation time steps). Required if timePeriod is not provided.

period: int or TimeStepSpec, optional
Number of simulation steps between consecutive checkpoints (e.g., 10 for every 10 steps).
Use 0 to disable checkpointing.
Alternatively, a TimeStepSpec can be provided for specific step selection
(e.g., TimeStepSpec([5, 10]), TimeStepSpec([slice(-10, None, 1)])).
Unit: steps or seconds (via TimeStepSpec unit).
timePeriod: int, optional
Specify the interval in minutes for creating checkpoints.
Unit: minutes (must be a non-negative integer). Required if period is not provided.

Time interval between checkpoints in simulation time steps.
Use 0 or None to disable time-based checkpointing.
directory: str, optional
Directory inside simOutput for writing checkpoints (default: "checkpoints").

Directory inside simOutput for writing checkpoints (default: "checkpoints").
file: str, optional
Relative or absolute fileset prefix for checkpoint files.

Relative or absolute fileset prefix for checkpoint files. Default: None.
restart: bool, optional
If True, restart simulation from the latest checkpoint.

Enable restarting from checkpoints. Default: None.
tryRestart: bool, optional
If True, restart from the latest checkpoint if available, else start from scratch.

If True, restart from the latest checkpoint if available, else start from scratch. Default: None.
restartStep: int, optional
Specific checkpoint step to restart from.

Specific step to restart from. Default: None.
restartDirectory: str, optional
Directory inside simOutput containing checkpoints for restart (default: "checkpoints").

Directory inside simOutput containing checkpoints for restart.
restartFile: str, optional
Relative or absolute fileset prefix for reading checkpoints.

Specific file to restart from. Default: None.
restartChunkSize: int, optional
Number of particles processed in one kernel call during restart.

Chunk size for reading restart data. Default: None.
restartLoop: int, optional
Number of times to restart the simulation after it finishes.

openPMD: Dict, optional
Dictionary of openPMD-specific settings (e.g., ext, json, infix).
Number of restart loops. Default: None.
openPMD: dict, optional
Configuration for openPMD output (e.g., {"ext": "h5"}). Default: None.
"""

def check(self):
if self.period is None and self.timePeriod is None:
raise ValueError("At least one of period or timePeriod must be provided")
if self.timePeriod is not None and self.timePeriod < 0:
raise ValueError("timePeriod must be a non-negative integer")
if self.restartStep is not None and self.restartStep < 0:
raise ValueError("restartStep must be non-negative")
if self.restartChunkSize is not None and self.restartChunkSize < 1:
raise ValueError("restartChunkSize must be positive")
if self.restartLoop is not None and self.restartLoop < 0:
raise ValueError("restartLoop must be non-negative")

def __init__(
self,
period: Optional[TimeStepSpec] = None,
period: Optional[Union[int, TimeStepSpec]] = None,
timePeriod: Optional[int] = None,
directory: Optional[str] = None,
directory: Optional[str] = "checkpoints",
file: Optional[str] = None,
restart: Optional[bool] = None,
tryRestart: Optional[bool] = None,
Expand All @@ -90,7 +70,16 @@ def __init__(
restartLoop: Optional[int] = None,
openPMD: Optional[Dict] = None,
):
self.period = period
if period is None and timePeriod is None:
raise ValueError("At least one of period or timePeriod must be provided to enable checkpointing")
if period is not None and not isinstance(period, (int, TimeStepSpec)):
raise TypeError("period must be an integer or TimeStepSpec")
if isinstance(period, int):
if period < 0:
raise ValueError("period must be non-negative")
self.period = TimeStepSpec([slice(None, None, period)] if period > 0 else [])("steps")
else:
self.period = period if period is not None else TimeStepSpec([])("steps")
self.timePeriod = timePeriod
self.directory = directory
self.file = file
Expand All @@ -102,19 +91,32 @@ def __init__(
self.restartChunkSize = restartChunkSize
self.restartLoop = restartLoop
self.openPMD = openPMD
self.check()

def check(self):
if self.timePeriod is not None and (not isinstance(self.timePeriod, int) or self.timePeriod < 0):
raise ValueError("timePeriod must be a non-negative integer")
if self.restartStep is not None and self.restartStep < 0:
raise ValueError("restartStep must be non-negative")
if self.restartChunkSize is not None and self.restartChunkSize <= 0:
raise ValueError("restartChunkSize must be positive")
if self.restartLoop is not None and self.restartLoop < 0:
raise ValueError("restartLoop must be non-negative")
if not self.period.specs and (self.timePeriod is None or self.timePeriod == 0):
warnings.warn(
"Checkpoint is disabled because period is set to 0 or an empty TimeStepSpec and timePeriod is None or 0"
)

def get_as_pypicongpu(
self,
pypicongpu_by_picmi_species: Dict,
time_step_size: float,
num_steps: int,
simulation_box=None, # Added to match OpenPMD signature, not used
) -> PyPIConGPUCheckpoint:
self.check()

pypicongpu_checkpoint = PyPIConGPUCheckpoint()
pypicongpu_checkpoint.period = (
self.period.get_as_pypicongpu(time_step_size, num_steps) if self.period is not None else None
)
pypicongpu_checkpoint.period = self.period.get_as_pypicongpu(time_step_size, num_steps) if self.period else None
pypicongpu_checkpoint.timePeriod = self.timePeriod
pypicongpu_checkpoint.directory = self.directory
pypicongpu_checkpoint.file = self.file
Expand All @@ -126,5 +128,4 @@ def get_as_pypicongpu(
pypicongpu_checkpoint.restartChunkSize = self.restartChunkSize
pypicongpu_checkpoint.restartLoop = self.restartLoop
pypicongpu_checkpoint.openPMD = self.openPMD

return pypicongpu_checkpoint
88 changes: 41 additions & 47 deletions lib/python/picongpu/picmi/diagnostics/energy_histogram.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
This file is part of PIConGPU.
Copyright 2021-2024 PIConGPU contributors
Copyright 2021-2025 PIConGPU contributors
Authors: Masoud Afshari
License: GPLv3+
"""
Expand All @@ -10,11 +10,9 @@
EnergyHistogram as PyPIConGPUEnergyHistogram,
)
from ...pypicongpu.species.species import Species as PyPIConGPUSpecies


from ..species import Species as PICMISpecies

import typeguard
from typing import Union


@typeguard.typechecked
Expand All @@ -27,75 +25,71 @@ class EnergyHistogram:

Parameters
----------
species: string
Name of the particle species to track (e.g., "electron", "proton").

period: int
Number of simulation steps between consecutive outputs.
If set to a non-zero value, the energy histogram of all electrons is computed.
By default, the value is 0 and no histogram for the electrons is computed.
Unit: steps (simulation time steps).

species: PICMISpecies
Particle species to count (e.g., an instance with name="electron" or "proton").
period: int or TimeStepSpec
Number of simulation steps between consecutive outputs (e.g., 10 for every 10 steps).
Use 0 to disable output. Alternatively, a TimeStepSpec can be provided for
PyPIConGPU-specific step selection (e.g., TimeStepSpec([slice(0, None, 10)])).
bin_count: int
Number of bins for the energy histogram.

Number of bins for the energy histogram. Must be positive.
min_energy: float
Minimum value for the energy histogram range.
Unit: keV
Default is 0, meaning 0 keV.

max_energy: float
Maximum value for the energy histogram range.
Maximum value for the energy histogram range. Must be greater than min_energy.
Unit: keV
There is no default value.

name: string, optional
Optional name for the energy histogram plugin.
"""

def check(self):
if self.min_energy >= self.max_energy:
raise ValueError("min_energy must be less than max_energy")
if self.bin_count <= 0:
raise ValueError("bin_count must be > 0")

def __init__(
self,
species: PICMISpecies,
period: TimeStepSpec,
period: Union[int, TimeStepSpec],
bin_count: int,
min_energy: float,
max_energy: float,
):
if isinstance(period, int):
if period < 0:
raise ValueError("period must be non-negative")
self.period = TimeStepSpec([slice(None, None, period)]) if period > 0 else TimeStepSpec()
else:
self.period = period
self.species = species
self.period = period
self.bin_count = bin_count
self.min_energy = min_energy
self.max_energy = max_energy

def check(self):
if not isinstance(self.species, PICMISpecies):
raise TypeError("species must be a PICMISpecies")
if not isinstance(self.species.name, str) or not self.species.name:
raise TypeError("species must have a non-empty name")
if not isinstance(self.period, TimeStepSpec):
raise TypeError("period must be a TimeStepSpec")
if self.bin_count <= 0:
raise ValueError("bin_count must be > 0")
if self.min_energy >= self.max_energy:
raise ValueError("min_energy must be less than max_energy")

def get_as_pypicongpu(
# to get the corresponding PyPIConGPUSpecies instance for the given PICMISpecies.
self,
dict_species_picmi_to_pypicongpu: dict[PICMISpecies, PyPIConGPUSpecies],
time_step_size,
num_steps,
time_step_size: float,
num_steps: int,
simulation_box=None, # Added to match OpenPMD signature, not used
) -> PyPIConGPUEnergyHistogram:
self.check()

if self.species not in dict_species_picmi_to_pypicongpu.keys():
if self.species not in dict_species_picmi_to_pypicongpu:
raise ValueError(f"Species {self.species} is not known to Simulation")

# checks if PICMISpecies instance exists in the dictionary. If yes, it returns the corresponding PyPIConGPUSpecies instance.
pypicongpu_species = dict_species_picmi_to_pypicongpu.get(self.species)

pypicongpu_species = dict_species_picmi_to_pypicongpu[self.species]
if pypicongpu_species is None:
raise ValueError(f"Species {self.species} is not mapped to a PyPIConGPUSpecies.")

pypicongpu_energy_histogram = PyPIConGPUEnergyHistogram()
pypicongpu_energy_histogram.species = pypicongpu_species
pypicongpu_energy_histogram.period = self.period.get_as_pypicongpu(time_step_size, num_steps)
pypicongpu_energy_histogram.bin_count = self.bin_count
pypicongpu_energy_histogram.min_energy = self.min_energy
pypicongpu_energy_histogram.max_energy = self.max_energy

pypicongpu_energy_histogram = PyPIConGPUEnergyHistogram(
species=pypicongpu_species,
period=self.period.get_as_pypicongpu(time_step_size, num_steps),
bin_count=self.bin_count,
min_energy=self.min_energy,
max_energy=self.max_energy,
)
return pypicongpu_energy_histogram
Loading