WarpX Configuration Reference
This document describes how to construct a configuration file for the warpx solver — and how
that YAML manifest relates to the native WarpX inputs file it wraps.
Like the OSIRIS wrapper (and unlike the native adept solvers), the WarpX wrapper does not define
the physics in YAML. The native WarpX inputs file is the source of truth: the manifest points
at an inputs file, optionally patches it with overrides, and configures how the run is executed
and logged. WarpX inputs are SI throughout and form a flat AMReX ParmParse
namespace, so overrides are a flat key: value mapping rather than the OSIRIS section machinery.
Top-Level Structure
solver: warpx # required, dispatch key
mlflow:
experiment: my-experiment # required
run: my-run # required
warpx:
deck: decks/srs-1d # required — the native WarpX inputs file
reference_density: 9.05e21 # cm^-3; fixes the wp0/skin-depth normalization
binary: /path/to/warpx.1d # optional, see binary resolution
mpi_ranks: 1
overrides:
amr.n_cell: 512
warpx
Field |
Type |
Description |
|---|---|---|
|
string |
Path to the native WarpX inputs file, repo-relative or absolute (required). This file is parsed, optionally patched by |
|
string | float |
Physical reference density that fixes the normalization used for MLflow comparability and (in M2+) for converting diagnostics to code units. A pint-parsable string ( |
|
string |
Path to the built WarpX executable. Optional — see Binary resolution. |
|
int |
|
|
string |
Launcher for |
|
list[string] |
Extra arguments passed to the launcher, e.g. |
|
string |
Parent directory for per-run working dirs (default |
|
mapping |
Flat deck patches applied before rendering. See below. |
Note on
run_root: as with the OSIRIS wrapper, the default sits insidecheckpoints/deliberately — sync scripts exclude it, so in-flight and finished WarpX outputs survive a sync.
Binary resolution
The runner resolves the WarpX executable in this order:
warpx.binaryin the manifestWARPX_BIN_<dim>Denvironment variable (e.g.WARPX_BIN_1D), where the dimensionality is read from the deck’sgeometry.dims(falling back to the length ofamr.n_cell)WARPX_BINenvironment variable
Overrides: patching the deck
overrides is a flat mapping from full ParmParse keys to values, applied to the parsed deck
before rendering:
warpx:
overrides:
amr.n_cell: 512
max_step: 2000
electrons.density_function: "n0*exp(z/Ln)" # base name resolves to the (x,y,z) key
laser1.e_max: 3.66e10
A key may be given without its parser-argument spec (
electrons.density_functionmatcheselectrons.density_function(x,y,z)) when unambiguous.Unknown keys are appended — WarpX ignores unused parameters, and a new key (e.g. an extra diagnostic) is a legitimate override.
List values are rendered space-separated, matching ParmParse syntax.
Multi-valued parameters must be YAML lists, not strings. The override’s YAML type selects the ParmParse type:
warpx.numprocs: [2, 16]renders as= 2 16(an int array), whilewarpx.numprocs: "2 16"is a string and renders quoted (= "2 16", one token — strings with whitespace must be re-quoted to survive the parse/render round trip), which makes WarpX abort at startup insideReadParameters(queryArrWithParser). Nothing validates an override’s type against the deck value it replaces; the run fails at launch with theReadParametersabort in the error. A non-zero exit is only salvaged (logged, exit code recorded as a metric, post-processing run on the partial data) when diagnostic data exists at the locations the deck configures: an openPMD dump or plotfile data chunk under a full diagnostic’sfile_prefix, or a reduced table with at least one sample. What a run leaves behind before its first sample —warpx_used_inputs,Backtrace.*, the openPMDparaview.pmdpattern file, header-only or empty reduced tables, plotfile headers — does not count.
The post-override deck is what runs, is logged key-by-key to MLflow (under deck.*), and is
archived as the inputs artifact; WarpX’s own warpx_used_inputs is archived too for provenance.
Units
write_units derives the same canonical scales the other adept solvers log (wp0, tp0, n0,
x0 = skin depth, v0 = c) from reference_density, plus the physical laser drive scales
(w_laser, laser_wavelength, laser_a0, laser_intensity) from the first laser’s
wavelength and e_max. WarpX decks are SI, so this is an SI → normalized derivation — the
inverse direction of the OSIRIS wrapper.
output
Optional block controlling post-processing, mirroring the OSIRIS wrapper:
Field |
Type |
Description |
|---|---|---|
|
list[string] |
Whitelist of diagnostics to convert/upload, matched on the contract key ( |
|
float |
Electron thermal velocity (units of c) for the Langmuir/Bohm–Gross overlay on ω–k plots |
|
float | null |
|
|
float |
Density (units of |
|
bool |
Shade the beam-acoustic-mode band on ω–k plots (needs |
Warning
diagnostics_to_log is passed straight to
adept.warpx.io.save_run_datasets() as its diagnostics= argument, so a
non-whitelisted diagnostic is never written into binary/ — it is not
merely withheld from the MLflow upload. Every downstream consumer reads
binary/, so using this field to keep bulk off the tracking server also
disables the analyses that depend on it.
Excluding the full-field maps (FLD/e1…b3, DENSITY/*) on a 2D run
silently removes: the srs2d bundle figures (F1–F9 — bundle2d is on by
default and simply gets no input), energy_vs_time /
energy_components_vs_time / epw_energy_vs_time, the non-native
epw_growth_rate, and the k-t spectrogram. It also makes warpx_lpi.native
fall back to the 1-D Poynting normalization — it reads the transverse box
width off a converted 2-D FLD/*.nc — yielding a spurious
laser_reflectivity_poynting ≈ −1.
Unaffected: PHA/*, REDUCED/*, HIST/*, and the FieldProbe line series
FLD/<comp>-line-*, which are one-dimensional in space. Note that each line
series is its own contract key, so whitelisting e2 does not carry
e2-line-x2-0024 along with it.
Note
The boundary-light products — the dump-cadence laser energy budget
(laser_reflectivity, laser_transmissivity, laser_absorbed_frac), the EM
boundary-light spectrum, and its spectrogram — are absent on any 2D run
regardless of this whitelist. They are built by
adept.osiris.plots.transverse_field_boundary_slabs(), which loads a
candidate field only when ser.ndim == 2; a converted 2-D map is
(t, x2, x1), so no pair is ever formed and the caller reports “no transverse
field pairs (need e2/b3 or e3/b2)”. Widening the whitelist will not fix this.
Post-processing artifacts
After the run, post.collect converts the WarpX output into the same per-diagnostic NetCDF
contract the OSIRIS wrapper emits, in code units fixed by reference_density (time in
1/ω_p, length in c/ω_p, fields in m_e c ω_p / e, current in e n_0 c; SI passthrough
when no reference density is available). The 1D axis mapping is the handedness-preserving
cyclic relabeling (z, x, y) → (1, 2, 3), so E_z → e1 (longitudinal), E_x → e2,
E_y → e3, and the OSIRIS sign conventions (including the left/right Riemann pairs) carry
over:
binary/FLD/e1.nc … stacked (t, x1) field series, OSIRIS naming
binary/DENSITY/<sp>/charge.nc rho_<species> in e·n0 units (when dumped)
binary/RAW/<species>.nc long-form particle dumps (x1, p1–p3 in m_s c, ene = γ−1,
q = signed macro-charge, w = openPMD weighting)
binary/PHA/<name>/<sp>.nc ParticleHistogram2D phase spaces / ParticleHistogram
spectra in OSIRIS phase-space conventions (see below)
binary/SCRAPED/<sp>/<edge>.nc BoundaryScraping buffers, long-form + t_scraped
binary/REDUCED/<name>.nc native SI reduced-diagnostic tables
binary/HIST/energy.nc OSIRIS energy-history schema from FieldEnergy+ParticleEnergy
plots/… the OSIRIS canned plot set + reduced/<name>.png traces
Phase-space histograms (PHA/)
ParticleHistogram2D reduced diagnostics (openPMD dirs under
diags/reducedfiles/<name>/) and 1-D ParticleHistogram tables become
OSIRIS-style phase spaces keyed PHA/<name>/<species> — so naming a
reduced diagnostic after the OSIRIS phase space it mirrors (p1x1,
x1log_gamma_q1, log_gamma) makes downstream OSIRIS-convention consumers
(e.g. osiris_lpi.collect_srs) dispatch on it unchanged. The run’s rendered
inputs deck drives the conversion:
the ordinate dim is named from
histogram_function_ord:log10(...)→gamma(the OSIRIS log-γ axis), bareuz/ux/uy→p1/p2/p3;value_function = w(a count deposit) is stored as the charge-signed density(q/|q|)·fnormalized soΣ f·d(axis) = n(x)/n0— the OSIRIS cartesian phase-space convention;any other value function is treated as a flux deposit and must be written in the
m_e c^3-reduced form (e.g.w*(g-1)*(uz/g)for the OSIRISx1gl_q1energy-flux depositKE·v1); the stored field integrates over the ordinate to a flux inn0 m_e c^3units — the same unit asI0 = (a0 ω0)^2/2;axes carry the adept-OSIRIS edge-style labels (
linspace(min, max, n)over the bin range) and the deck’sgeometry.prob_lo/hibecomesim.XMIN/XMAX.
Conversion: one walk, one slab
Both the field records and the ParticleHistogram2D phase spaces are converted
a dump at a time, through the same StreamWriter the OSIRIS drainer uses.
Two properties follow, and both are load-bearing at production cadences:
Peak memory is one slab plus a ~1 MiB write batch, not the stacked history.
A production x1log_gamma_q1 (11705 dumps × 1000 × 1024) is a 47.9 GB cube,
and the eager load_particle_histogram2d → series_to_dataset path held two
copies of it. The field path stacked a list of float64 slabs — ~6.3 GB per
component at 88k dumps of 3594 cells, and far worse in 2D.
Each dump is opened once, not once per record. openPMD bundles every record
of a dump into one file, but the converter used to re-walk the whole tree per
component. At a field cadence giving a 2 ω₀ Nyquist (a dump every 7–9 steps at
dt = 0.178/ω₀, so ~88k dumps over a 23 ps run) that is 614k opens against
88k files; at the ~6.5 ms/file measured on Perlmutter’s Lustre the redundant
six-sevenths alone cost ~57 min per simulation. Everything a record needs —
axes, code-unit scaling, binary/ key, storage-order transpose — comes from
the first dump, so diagnostics_to_log now also skips records before they
are read rather than loading and discarding them.
StreamWriter chunks each variable (chunk_t, …) with chunk_t sized to
~1 MiB (1 dump per chunk at production bin counts), so the per-dump reads in
osiris_lpi are chunk-aligned; the batch path’s default h5netcdf chunking
spread one time slice over 2016 chunks. load_field_series and
load_particle_histogram2d still return whole histories for interactive use
and remain the reference implementations the streamed output is tested
against.
Because the contract matches, adept.osiris.io.list_diagnostics / load_series and the
OSIRIS canned plots read these files unchanged. Logged metrics include final_step,
completed_steps_frac (the exit-0 early-termination tripwire — WarpX exits 0 on
break_signals and silently ignores typo’d parameters), field/efield/bfield_energy_final
(code units, from the FieldEnergy reduced diagnostic), and energy_drift_frac.
Regenerate the plot set offline from the saved NetCDFs (or convert a raw run directory in place):
python -m adept.warpx.regen <run-or-binary-dir> [--out DIR] [--v-th 0.0885] [...]
Status
M1 (wrapper skeleton): deck parsing/overrides/logging, subprocess runner with
salvage-on-partial-output, units, provenance upload. M2 (io + plots): openPMD → NetCDF
conversion to the OSIRIS binary/ contract, code-units conversion, reduced-diagnostic
parsers, canned plots, regen. M3 (SRS parity): phase-space histogram / boundary-scraping
conversion (PHA/, SCRAPED/) feeding the osiris_lpi SRS analyses unchanged; the SRS
deck and the WarpxLPI adapter live in the warpx-lpi repo. See
dev_docs/warpx-wrapper-plan.md on the warpx-wrapper branch for the plan of record.