setup-simulation
Use when creating or editing a Struphy simulation parameter file (params_*.py) - choosing a model, configuring domain/grid/time-stepping, species/backgrounds/perturbations and propagator options, then
Files1
View on GitHubSKILL.mdsrc/struphy/agent_guides/skills/setup-simulation/SKILL.md
GitHubSetting up a Struphy simulation
Struphy simulations are configured as plain Python scripts (params_<name>.py) that
build a Simulation object from the Struphy API, then call sim.run(). The params
file can use real Python (loops, conditionals, computed values) to derive parameters.
Each run writes run_metadata.json, containing a configuration snapshot and runtime
facts such as the MPI rank count. Post-processing reads this saved metadata directly.
This skill ships with the installed Struphy package, so it matches the installed version.
struphy agents prints the general usage guide and the examples URL for that version.
Workflow
Confirm Struphy is installed and compiled if this is a fresh environment:
struphy compile --statusmust report all kernels compiled; otherwise runstruphy compile. Install help: https://struphy-hub.github.io/struphy/sections/install.html. Skip this if the user is clearly iterating on an existing working setup.Pick a starting point, in this order of preference:
- Find the closest existing example and adapt it. Examples live in
<ModelName>/<case>/params_*.pyof https://github.com/struphy-hub/struphy-examples (not in the pip package;struphy agentsprints the URL of the tag for the installed version, clone it withgit clone --branch vX.Y.Z ...). They are the most reliable reference because model-specific options (which propagators exist, what each species needs) vary per model and are easiest to get right by copying a working case. - If no example matches, scaffold a default with the CLI:
struphy params <ModelName>writesparams_<ModelName>.pyin the cwd with every option pre-filled to defaults and commented (-yskips the prompt). - List available models with
struphy params --help(all model names), orstruphy --fluid,struphy --kinetic,struphy --hybridfor one group. Model descriptions: https://struphy-hub.github.io/struphy/sections/models.html. - Read the model's docstring for its species, variables and propagators before wiring options,
e.g.
python -c "from struphy.models import Maxwell; help(Maxwell)". Don't guess propagator names.
- Find the closest existing example and adapt it. Examples live in
Edit the params file following the structure below.
Check it with
struphy params <ModelName> --check-file params_<name>.py.Run it:
python params_<name>.pympirun -n <N> python params_<name>.pyfor multiple MPI processes (all Struphy data structures are MPI-aware, so this works unchanged; requirespip install mpi4py).
Post-process with a sibling
pproc_<name>.pyscript if the user wants plots or derived quantities beyond what's dumped live. See the postprocess-simulation skill.
Anatomy of a params file
Based on the example VlasovAmpereOneSpecies/two_stream/params_two_stream.py and the
quickstart (https://struphy-hub.github.io/struphy/sections/quickstart.html). Sections, in order:
# 1. Free-text description (printed at run start, keeps runs traceable)
description = """..."""
# 2. Imports from the top-level struphy API
from pathlib import Path
from struphy import (
BaseUnits, DerhamOptions, EnvironmentOptions, FieldsBackground,
Simulation, Time, domains, equils, grids, perturbations,
)
# Kinetic species only:
from struphy import (
BinningPlot, BoundaryParameters, KernelDensityPlot, LoadingParameters,
SavingParameters, SortingParameters, WeightsParameters, maxwellians,
)
from struphy.models import <ModelName>
# 3. Model instance (constructor kwargs are model-specific, e.g. alpha/epsilon/with_B0)
model = <ModelName>(...)
model.<species>.<variable>.save_data = True # opt in/out of saving each variable
# 4. Simulation-level config (all optional, sensible defaults exist)
base_units = BaseUnits() # x, B, n, kBT -> derived units
env = EnvironmentOptions(
out_folders=str(Path(__file__).resolve().parent),
sim_folder="sim_data",
) # output beside the script, independent of the working directory
time_opts = Time(dt=0.1, Tend=50.0, split_algo="LieTrotter")
domain = domains.Cuboid(r1=31.42) # see help(domains.Cuboid)
equil = None # or e.g. equils.HomogenSlab()
grid = grids.TensorProductGrid(num_elements=(32, 1, 1))
derham_opts = DerhamOptions(degree=(3, 1, 1)) # spline degree, bcs, quadrature
# 5. Build the Simulation (this is what sim.run() acts on)
sim = Simulation(
model=model, params_path=__file__, env=env, time_opts=time_opts,
domain=domain, equil=equil, grid=grid, derham_opts=derham_opts,
)
# 6. Kinetic species only: markers (loading/weights/boundary/sorting/saving)
loading_params = LoadingParameters(ppc=1000, moments=(...))
weights_params = WeightsParameters(control_variate=True)
boundary_params = BoundaryParameters()
sorting_params = SortingParameters(boxes_per_dim=(16, 1, 1), do_sort=True)
saving_params = SavingParameters(binning_plots=(BinningPlot(...),))
model.<kinetic_species>.set_markers(
loading_params=loading_params, weights_params=weights_params,
boundary_params=boundary_params, sorting_params=sorting_params,
saving_params=saving_params,
)
# 7. Propagator options — wire each propagator listed in the model to its variables.
# Names/required args are model-specific; check help(<ModelName>), `struphy params <ModelName>` or an example.
model.propagators.<name>.options = model.propagators.<name>.Options(...)
# 8. Backgrounds, perturbations, initial conditions
# - Fields: model.<species>.<var>.add_background(FieldsBackground())
# model.<species>.<var>.add_perturbation(perturbations.ModesCos(...))
# - Kinetic: background is mandatory; if add_initial_condition() is never called,
# the background doubles as the initial condition. Perturbations for kinetic
# species are added to distribution moments, not the variable directly:
maxwellian = maxwellians.Maxwellian3D(n=(0.5, None), u1=(3.0, None))
model.<kinetic_species>.var.add_background(maxwellian)
perturbation = perturbations.ModesCos(amps=(0.001,), ls=(1,))
init = maxwellians.Maxwellian3D(n=(0.5, perturbation), u1=(3.0, None))
model.<kinetic_species>.var.add_initial_condition(init)
# 9. Run only when the parameter script is executed directly.
if __name__ == "__main__":
sim.run()
Key building blocks and where to look them up. Every class has a full docstring
(help(...) in Python); the module's file is printed by e.g.
python -c "import struphy.geometry.domains as m; print(m.__file__)".
| Piece | Module |
|---|---|
Domains (Cuboid, HollowTorus, Tokamak, ...) |
struphy.domains (struphy.geometry.domains) |
Grid (TensorProductGrid) |
struphy.grids (struphy.topology.grids) |
| Fluid equilibria | struphy.equils (struphy.fields_background.equils) |
| Perturbations | struphy.perturbations (struphy.initial.perturbations) |
| Kinetic backgrounds | struphy.maxwellians (struphy.kinetic_background.maxwellians) |
Options dataclasses (Time, BaseUnits, DerhamOptions, EnvironmentOptions, FieldsBackground) |
struphy.io.options (docstrings list every field) |
| Models and their propagators/species | struphy.models.<Model> |
Lists of what is available, with parameters, under https://struphy-hub.github.io/struphy/sections/:
domains.html, fluid-equils.html, perturbations.html, kinetic-equils.html and
models.html (models and their propagators).
Common pitfalls
- Don't invent propagator or option names — every model has a different propagator
set; read
help(<ModelName>), generatestruphy params <ModelName>or copy from a matching example instead of guessing. - The output folder is
EnvironmentOptions.sim_folder(defaultsim_1) insideout_folders; the post-processing script must open the same folder. - For kinetic species, a background is required even if only using perturbations;
perturbations attach to distribution moments (via
maxwellians.*), not directly to the species variable like field perturbations do. - Keep
sim.run()behindif __name__ == "__main__":to avoid starting a run on import. Post-processing scripts should open the saved output folder directly.