Skip to content

Commit

Permalink
build PyPIConGPu and PICMI interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
BrianMarre committed Jul 13, 2024
1 parent b38a6e1 commit 472fb9c
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 44 deletions.
1 change: 1 addition & 0 deletions lib/python/picongpu/picmi/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ sympy >= 1.9
chevron >= 0.13.1
jsonschema == 4.17.3
scipy >= 1.7.1
pydantic >= 2.6.4
picmistandard >= 0.27.0
16 changes: 14 additions & 2 deletions lib/python/picongpu/picmi/simulation.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"""
This file is part of PIConGPU.
Copyright 2021-2023 PIConGPU contributors
Copyright 2021-2024 PIConGPU contributors
Authors: Hannes Troepgen, Brian Edward Marre
License: GPLv3+
"""

from ..pypicongpu import simulation, runner, util, species
from ..pypicongpu import simulation, runner, util, species, movingwindow
from . import constants
from .grid import Cartesian3DGrid
from .species import Species as PicongpuPicmiSpecies
Expand Down Expand Up @@ -99,6 +99,8 @@ def __init__(
self,
picongpu_template_dir: typing.Optional[typing.Union[str, pathlib.Path]] = None,
picongpu_typical_ppc: typing.Optional[int] = None,
picongpu_moving_window_move_point: typing.Optional[float] = None,
picongpu_moving_window_stop_iteration: typing.Optional[int] = None,
**kw,
):
# delegate actual work to parent
Expand All @@ -119,6 +121,9 @@ def __init__(
assert template_path.is_dir(), "picongpu_template_dir must be existing dir"
self.picongpu_template_dir = str(template_path)

self.moving_window_move_point = picongpu_moving_window_move_point
self.moving_window_stop_iteration = picongpu_moving_window_stop_iteration

self.picongpu_typical_ppc = picongpu_typical_ppc

# store runner state
Expand Down Expand Up @@ -441,6 +446,13 @@ def get_as_pypicongpu(self) -> simulation.Simulation:
# todo: check grid compatibility
s.grid = self.solver.grid.get_as_pypicongpu()

if self.moving_window_move_point is None:
s.moving_window = None
else:
s.moving_window = movingwindow.MovingWindow(
move_point=self.moving_window_move_point, stop_iteration=self.moving_window_stop_iteration
)

# any injection method != None is not supported
if len(self.laser_injection_methods) != self.laser_injection_methods.count(None):
util.unsupported("laser injection method", self.laser_injection_methods, [])
Expand Down
36 changes: 36 additions & 0 deletions lib/python/picongpu/pypicongpu/movingwindow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""
This file is part of the PIConGPU.
Copyright 2024 PIConGPU contributors
Authors: Brian Edward Marre
License: GPLv3+
"""

import pydantic
import typing

from .rendering import RenderedObject


class MovingWindow(RenderedObject, pydantic.BaseModel):
move_point: float
"""
point a light ray reaches in y from the left border until we begin sliding the simulation window with the speed of
light
in multiples of the simulation window size
@attention if moving window is active, one gpu in y direction is reserved for initializing new spaces,
thereby reducing the simulation window size according
"""

stop_iteration: typing.Optional[int]
"""iteration, at which to stop moving the simulation window"""

def check(self) -> None:
if self.move_point < 0.0:
raise ValueError("window_move point must be >= 0.")
if self.stop_iteration <= 0:
raise ValueError("stop iteration must be > 0.")

def _get_serialized(self) -> dict:
return {"move_point": self.move_point, "stop_iteration": self.stop_iteration}
9 changes: 9 additions & 0 deletions lib/python/picongpu/pypicongpu/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from .grid import Grid3D
from .laser import GaussianLaser
from .movingwindow import MovingWindow
from .solver import Solver
from . import species
from . import util
Expand Down Expand Up @@ -62,6 +63,9 @@ class Simulation(RenderedObject):
@attention custom user input is global to the simulation
"""

moving_window = util.build_typesafe_property(typing.Optional[MovingWindow])
"""used moving Window, set to None to disable"""

def __get_output_context(self) -> dict:
"""retrieve all output objects"""
auto = output.Auto()
Expand Down Expand Up @@ -129,6 +133,11 @@ def _get_serialized(self) -> dict:
else:
serialized["laser"] = None

if self.moving_window is not None:
serialized["moving_window"] = self.moving_window.get_rendering_context()
else:
serialized["moving_window"] = None

if self.custom_user_input is not None:
serialized["customuserinput"] = self.__render_custom_user_input_list()
self.__foundCustomInput(serialized)
Expand Down
1 change: 1 addition & 0 deletions share/ci/pypicongpu_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ def print_job_yaml(test_pkg_versions: Dict[str, List[str]]):
"typeguard": get_all_major_pypi_versions,
"jsonschema": get_all_pypi_versions, # @todo change back, Brian Marre, 2023
"picmistandard": get_all_pypi_versions,
"pydantic": get_all_major_pypi_versions,
}

if __name__ == "__main__":
Expand Down
21 changes: 0 additions & 21 deletions share/picongpu/pypicongpu/schema/movingWindowVelocity.json

This file was deleted.

24 changes: 24 additions & 0 deletions share/picongpu/pypicongpu/schema/movingwindow.MovingWindow.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"$id": "https://registry.hzdr.de/crp/picongpu/schema/picongpu.pypicongpu.movingwindow.MovingWindow",
"type": "object",
"description": "moving window setting of picongpu",
"unevaluatedProperties": false,
"required": ["move_point", "stop_iteration"],
"properties": {
"move_point": {
"type": "number",
"minimum" : 0
},
"stop_iteration": {
"anyOf": [
{
"type": "null"
},
{
"type": "integer",
"exclusiveMinimum" : 0
}
]
}
}
}
6 changes: 3 additions & 3 deletions share/picongpu/pypicongpu/schema/simulation.Simulation.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@
}
]
},
"moving_window_velocity": {
"moving_window": {
"anyOf": [
{
"type": "null"
},
{
"$ref": "https://registry.hzdr.de/crp/picongpu/schema/picongpu.pypicongpu.movingWindowVelocity"
"$ref": "https://registry.hzdr.de/crp/picongpu/schema/picongpu.pypicongpu.movingwindow.MovingWindow"
}
]
},
Expand Down Expand Up @@ -81,7 +81,7 @@
"solver",
"grid",
"laser",
"moving_window_velocity",
"moving_window",
"customuserinput"
],
"unevaluatedProperties": false
Expand Down
44 changes: 27 additions & 17 deletions share/picongpu/pypicongpu/template/etc/picongpu/N.cfg.mustache
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright 2013-2023 Axel Huebl, Rene Widera, Felix Schmitt, Franz Poeschel
# Copyright 2013-2023 Axel Huebl, Rene Widera, Felix Schmitt, Franz Poeschel,
# Hannes Tropegen, Brian Marre
#
# This file is part of PIConGPU.
#
Expand Down Expand Up @@ -60,15 +61,13 @@ TBG_wallTime="1:00:00"

TBG_steps="{{{time_steps}}}"

{{#grid.boundary_condition}}
TBG_periodic="--periodic {{{x}}} {{{y}}} {{{z}}}"
{{/grid.boundary_condition}}


#################################
## Section: Optional Variables ##
#################################

{{#grid.boundary_condition}}
TBG_periodic="--periodic {{{x}}} {{{y}}} {{{z}}}"
{{/grid.boundary_condition}}

{{#output.auto}}
# only use charge conservation if solver is yee AND using cuda backend
Expand All @@ -80,6 +79,14 @@ else
fi
{{/output.auto}}

{{#moving_window}}
TBG_movingWindow="-m"
TBG_windowMovePoint="--windowMovePoint {{{move_point}}}"
{{#stop_iteration}}
TBG_stopWindow="--stopWindow {{{stop_iteration}}}"
{{/stop_iteration}}
{{/moving_window}}

pypicongpu_output_with_newlines="
{{#output.auto}}
--fields_energy.period {{{period}}}
Expand Down Expand Up @@ -114,23 +121,26 @@ TBG_pypicongpu_output=$(sed -z 's/\n/ /g' <<< "$pypicongpu_output_with_newlines"

TBG_plugins="!TBG_pypicongpu_output"



#################################
## Section: Program Parameters ##
#################################

TBG_deviceDist="!TBG_devices_x !TBG_devices_y !TBG_devices_z"

TBG_programParams="
{{#moving_window_velocity}}
--moving_window_velocity_X = {{{x}}} \
--moving_window_velocity_Y = {{{y}}} \
--moving_window_velocity_Z = {{{z}}} \
{{/moving_window_velocity}}
-d !TBG_deviceDist \
-g !TBG_gridSize \
-s !TBG_steps \
!TBG_periodic \
!TBG_plugins \
TBG_programParams="-d !TBG_deviceDist \
-g !TBG_gridSize \
-s !TBG_steps \
!TBG_periodic \
!TBG_plugins \
{{#moving_window}}
!TBG_movingWindow \
!TBG_windowMovePoint \
{{#stop_iteration}}
!TBG_stopWindow \
{{/stop_iteration}}
{{/moving_window}}
--versionOnce"

# TOTAL number of devices
Expand Down
19 changes: 18 additions & 1 deletion test/python/picongpu/compiling/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from picongpu import pypicongpu, picmi

import typeguard

import unittest
import tempfile
import os
Expand All @@ -29,6 +28,17 @@ def get_grid(delta_x: float, delta_y: float, delta_z: float, n: int):


class TestSimulation(unittest.TestCase):
def _set_up_sim(self, **kw):
grid = picmi.Cartesian3DGrid(
number_of_cells=[192, 2048, 12],
lower_bound=[0, 0, 0],
upper_bound=[3.40992e-5, 9.07264e-5, 2.1312e-6],
lower_boundary_conditions=["open", "open", "periodic"],
upper_boundary_conditions=["open", "open", "periodic"],
)
solver = picmi.ElectromagneticSolver(method="Yee", grid=grid)
return picmi.Simulation(time_step_size=1.39e-16, max_steps=int(2048), solver=solver, **kw)

def test_minimal(self):
"""smallest possible example"""
sim = pypicongpu.Simulation()
Expand All @@ -48,6 +58,7 @@ def test_minimal(self):
sim.grid.boundary_condition_z = pypicongpu.grid.BoundaryCondition.PERIODIC
sim.laser = None
sim.custom_user_input = None
sim.moving_window = None
sim.solver = pypicongpu.solver.YeeSolver()
sim.init_manager = pypicongpu.species.InitManager()

Expand All @@ -56,6 +67,12 @@ def test_minimal(self):
runner.build()
runner.run()

def test_moving_window(self):
picmi_sim = self._set_up_sim(picongpu_moving_window_move_point=0.9)
runner = pypicongpu.Runner(picmi_sim)
runner.generate(printDirToConsole=True)
runner.build()

def test_custom_template_dir(self):
"""may pass custom template dir"""

Expand Down
18 changes: 18 additions & 0 deletions test/python/picongpu/quick/picmi/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,24 @@ def test_operation_momentum(self):
)
self.assertAlmostEqual(1.491037242289643, mom_op.drift.gamma)

def test_moving_window(self):
"""test that the user may set moving window"""
grid = picmi.Cartesian3DGrid(
number_of_cells=[192, 2048, 12],
lower_bound=[0, 0, 0],
upper_bound=[3.40992e-5, 9.07264e-5, 2.1312e-6],
lower_boundary_conditions=["open", "open", "periodic"],
upper_boundary_conditions=["open", "open", "periodic"],
)
solver = picmi.ElectromagneticSolver(method="Yee", grid=grid)
sim = picmi.Simulation(
time_step_size=1.39e-16, max_steps=int(2048), solver=solver, picongpu_moving_window_move_point=0.9
)
pypic = sim.get_as_pypicongpu()

self.assertAlmostEqual(pypic.moving_window.move_point, 0.9)
self.assertEqual(pypic.moving_window.stop_iteration, None)

def test_ionization_electron_explicit(self):
"""electrons for ionization can be specified explicitly"""
# note: the difficulty here is preserving the PICMI- -> PICMI-object
Expand Down
1 change: 1 addition & 0 deletions test/python/picongpu/quick/pypicongpu/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def setUp(self):
self.s.solver = solver.YeeSolver()
self.s.laser = None
self.s.custom_user_input = None
self.s.moving_window = None
self.s.init_manager = species.InitManager()

self.laser = GaussianLaser()
Expand Down

0 comments on commit 472fb9c

Please sign in to comment.