Parameter sweeping¶
lume-ace3p has two main use-cases: parameter sweeping and optimization. For
both, an ACE3P workflow is evaluated many times according to parameters set in
a YAML file. A parameter sweep is a mode (type: parameter_sweep) that
drives the declarative workflow: chain over the full tensor product of the
swept input axes. The examples below are intended as templates.
To set up a parameter sweep, provide in the lume-ace3p input file:
a
workflow:list — the ordered module chain to run (e.g.cubit → omega3p → acdtool, orcubit → s3p). Solver settings (tasks,cores,opts, the input file) live on the module entries.mode:withtype: parameter_sweepand anoutput_filefor the result table.input_parameters— the swept input space, organized into per-code sub-blocks so every variable’s home is explicit:cubit:— names and vector values for Cubit journal (geometry) knobs.ace3p:(optional) — parameters inside the ACE3P input file.geant4:(optional) — overrides for the Geant4 input file.
A single sweep can span all three sub-blocks at once (the full tensor product of every array-valued leaf across them). The old flat keys (
cubit_input_parameters,ace3p_input_parameters,geant4_input_parameters, and a bareinput_parameterstreated as the cubit block) are still accepted for back-compat, but the nested notation is the standard and is used throughout the examples below.output_parameters(optional) — output quantities to extract into the result table.
Once these are defined in the .yaml file, the parameter sweep is run with the
run-lume-ace3p entry point.
Omega3P parameter sweep example¶
This example (based on the rounded-top pillbox from the
ACE3P tutorials,
shipped as
examples/omega3p_sweep)
configures lume-ace3p to run a parameter sweep over cavity radius and cavity
wall ellipticity. The goal is to automate the entire mesh-generation,
Omega3P calculation, and mode postprocessing pipeline into a single job
submitted to HPC resources.
The script begins with the workflow-level settings, the module chain, and the mode:
workflow_parameters :
'workdir' : 'lume-ace3p_omega3p_workdir'
'workdir_mode' : 'auto'
workflow :
- module : cubit
journal : 'pillbox-rtop.jou'
- module : omega3p
input : 'pillbox-rtop.omega3p'
tasks : 16
cores : 16
opts : '--cpu-bind=cores'
- module : acdtool
input : 'pillbox-rtop.rfpost'
mode :
type : parameter_sweep
output_file : 'omega3p_sweep_output.txt'
workflow_parameters holds only directory settings here: workflows are run in
separate sub-directories (workdir_mode: auto, auto-named from input values).
Each module entry names its own input file and, for the solver, its MPI settings
(16 tasks × 16 cores/task with --cpu-bind=cores). The mode block enables the
result table written to output_file. See YAML configuration reference for full
details.
Next, Cubit input parameters:
input_parameters :
cubit :
'cav_radius' :
'min' : 90.0
'max' : 120.0
'num' : 4
'ellipticity' :
'min' : 0.5
'max' : 1.25
'num' : 4
The cubit: sub-block is a key-value mapping where each key is the exact
name of a variable defined in the Cubit journal file, and each value is either
a list of numeric inputs or a nested dict with min, max, num (linearly
spaced).
ACE3P input parameters live in the ace3p: sub-block of the same
input_parameters mapping:
input_parameters :
ace3p :
'ModelInfo' :
'SurfaceMaterial' :
'ReferenceNumber' : 6
'Sigma' : [5.8e7, 1.04e7]
The ace3p: sub-block is a nested mapping organized by ACE3P file hierarchy.
Here the swept parameter is the conductivity of the surface with
ReferenceNumber 6. Values can use min/max/num, a list, or a single value
if not swept. (In practice the cubit: and ace3p: sub-blocks are written
under one input_parameters: header — see
examples/omega3p_ace3p_param_sweep.)
In this example cav_radius and ellipticity are length-4 vectors, and
Sigma has two values, giving 4 × 4 × 2 = 32 workflow evaluations. Because
workdir_mode is auto, each evaluation creates a folder named from the
workdir base plus the swept scalar values (e.g.
lume-ace3p_omega3p_workdir_90.0_0.5_58000000.0) for a total of 32 folders. The
full cubit → omega3p → acdtool chain — including the in-cubit meshconvert —
re-runs in each folder.
Then, output parameters:
output_parameters :
'R/Q' : {module: acdtool, section: RoverQ, quantity: RoQ, at: {mode: 0}}
'Mode_freq' : {module: omega3p, quantity: Frequency, at: {mode: 0}}
'E_max' : {module: acdtool, section: maxFieldsOnSurface, quantity: Emax, at: {surface: 6}}
'loc_x' : {module: acdtool, section: maxFieldsOnSurface, quantity: Emax_location, component: x, at: {surface: 6}}
'loc_y' : {module: acdtool, section: maxFieldsOnSurface, quantity: Emax_location, component: y, at: {surface: 6}}
'loc_z' : {module: acdtool, section: maxFieldsOnSurface, quantity: Emax_location, component: z, at: {surface: 6}}
output_parameters maps user-chosen labels to an extraction spec naming the
module, the thing wanted, and — for an indexed result — which index. R/Q and
E_max come from acdtool, which reads them out of rfpost.out; Mode_freq
comes from Omega3P’s own eigenmode output, so it needs no postprocessing
block at all. Dropping the at: from a mode-indexed acdtool spec asks for every
mode instead of one, which is what a dispersion curve or an HOM catalog wants. The
full spec grammar is in output_parameters; the .rfpost
block surface is in acdtool reference.
The output_file is a tab-delimited table with one column per input or output,
one row per workflow evaluation.
In this example the table has 9 columns — one per swept axis (cav_radius,
ellipticity, and the swept ACE3P leaf, whose column is labeled by its path
ace3p:ModelInfo.SurfaceMaterial.Sigma) followed by the 6 declared outputs
(R/Q, Mode_freq, E_max, loc_x, loc_y, loc_z) — with one row per
workflow evaluation. See YAML configuration reference for the full list of supported
output sections.
If no output dict is specified, the parameter sweep still runs but
rfpost.out data will not be parsed or tabulated (useful when only the
per-combination output folders are wanted).
Each workflow evaluation is run serially. Future versions may allow concurrent evaluations.
Resuming a sweep that was cut off¶
A sweep of long solves rarely fits in one allocation, and a point interrupted
partway used to be lost entirely — the next run rebuilt its mesh and re-solved
from scratch. Two additions change that: every evaluation records what it did in a
run manifest in its own workdir, and
mode: {resume: true} reads that record back.
workflow_parameters :
'workdir' : 'lume-ace3p_omega3p_workdir'
'workdir_mode' : 'indexed' # per-point directories: _0, _1, _2, …
mode :
type : parameter_sweep
resume : True
output_file : 'omega3p_sweep_output.txt'
Re-run the same command after a job dies and the sweep picks up where it stopped: finished points contribute their rows without launching a single solver, a point that died halfway restarts at the step that did not finish, and points that never started run normally. The result table is the same table it would have been, so resuming is not a different kind of run — it is the same sweep, minus the work already done.
Before re-running, --status shows what is there:
$ run-lume-ace3p --status omega3p_sweep.yaml
- 32 point(s) implied by this configuration: 19 complete, 1 failed, 12 absent
Two requirements. workdir_mode must not be manual (points must have their own
directories to have their own state — resume: true with manual is refused,
naming indexed), and resume is opt-in: a sweep that silently adopted whatever
was lying in its workdirs would be worse than no resume at all. Each point’s
manifest also carries a hash of the resolved configuration, so a point whose module
settings or input values have changed since is re-run, and says so.
The full per-point rules, including what happens when a completed point’s output files have been deleted, are in resume — picking a campaign up where it stopped.
S3P parameter sweep example¶
This example (based on a 90-degree bend from the ACE3P tutorials) runs a parameter sweep over outer corner cut radius and inner corner rounding radius. The S-parameter results are stored in a text file with all combinations of parameters and frequencies.
workflow_parameters :
'workdir' : 'lume-ace3p_s3p_workdir'
'workdir_mode' : 'auto'
workflow :
- module : cubit
journal : 'bend-90degree.jou'
- module : s3p
input : 'bend-90degree.s3p'
tasks : 32
cores : 4
opts : '--cpu-bind=cores'
mode :
type : parameter_sweep
output_file : 's3p_sweep_output.txt'
input_parameters :
cubit :
'cornercut' :
'min' : 12.0
'max' : 16.0
'num' : 5
'rcorner2' :
'min' : 4.0
'max' : 16.0
'num' : 3
Note
Frequencies to scan with S3P are not “inputs” set here — they are set in the
.s3p input file directly.
In this example cornercut and rcorner2 are length 5 and 3, giving 5 × 3 =
15 workflow evaluations and 15 distinct folders.
S3P exposes a frequency field index, so its sweep table is emitted in
long format: one row per (grid-point, frequency) rather than one row per
grid point. output_parameters are optional here — even with none declared, the
per-frequency S-parameters are tabulated because the frequency index alone
drives the long-format rows.
In the example, S3P scans 13 frequencies for each of the 15 workflow
evaluations, giving 195 rows in output_file. Each row has cornercut,
rcorner2, and Frequency, followed by the four S-parameters of the 2-port
system (S(0,0), S(0,1), S(1,0), S(1,1)).
S3P parameter sweep with no separate ACE3P file¶
Identical to the previous example, except no .s3p file is submitted. All
S3P parameters are specified in the ace3p: sub-block of input_parameters.
Modify the S3P sweep .batch file to run s3p_sweep_no_s3p_file.yaml.
input_parameters :
ace3p :
'ModelInfo' :
'File' : './bend-90degree.ncdf'
'BoundaryCondition' :
'Exterior' : 6
'Waveguide' : 7,8
'FiniteElement' :
'Order' : 2
'CurvedSurfaces' : 'on'
'FrequencyScan':
'Start' : 9.424e+9
'End' : 12.424e+9
'Interval' : 0.25e+9
'Port':
'ReferenceNumber' : 7
'NumberOfModes' : 1
'Port' :
'ReferenceNumber': 8
'NumberOfModes' : 1
Note the two 'Port' blocks at the same indentation level. ACE3P
allows duplicate-named sibling sections (one per port, surface,
boundary condition, …), and the ace3p: parser preserves them verbatim —
entries are matched positionally with the ACE3P input file rather than
collapsed into a Python dict. See
input_parameters.ace3p for details.
This functions exactly the same as the previous example. Errors may arise if a necessary ACE3P input parameter is missing.
Viewing S3P parameter sweep output¶
A simple plotting tool is included with lume-ace3p which reads the S3P sweep
result table (the mode.output_file) and plots the results in an interactive
plot. To use it, run s3p_sweep_plot.py and load the appropriate S3P
output_file from the file prompt. Try s3p_demo_sweep_output.txt in the
plotting folder for an interactive demo. See Plotting tools for details.
Gaussian-process (low-fidelity) parameter sweep¶
lume-ace3p also supports a Bayesian-exploration sweep mode that fits a
Gaussian Process to the simulator output and then samples the GP posterior mean
on a tensor grid — useful for cheaply exploring parameter space without running
every grid point through the solver. The mode is selected with
mode: {type: gp_parameter_sweep}.
Three sections must be supplied in addition to the workflow: chain:
sweep_parameters— the tensor grid the trained GP is evaluated on.vocs_parameters— Xopt VOCS for the exploration phase. Theobjectivesblock maps anoutput_parametersname to'explore'.xopt_parameters— Xopt driver settings.max_stepscaps the GP-guided exploration steps;num_random(default 5) controls the random-seeding phase;improvement_threshold(default 0.01) andpatience(default 5) configure early stopping.
A complete example is shipped as examples/s3p_bayesian_sweep/s3p_bayesian_sweep.yaml:
workflow_parameters :
'workdir' : 'lume-ace3p_mf_workdir'
workflow :
- module : cubit
journal : 'bend-90degree_mf.jou'
- module : s3p
input : 'bend-90degree_mf.s3p'
tasks : 16
cores : 4
opts : '--cpu-bind=cores'
mode :
type : gp_parameter_sweep
output_file : 'sim_output.txt'
sweep_output_file : 'sweep_output.txt'
output_parameters :
'S(1,1)_12.0e+09' : { module: s3p, quantity: 'S(1,1)', at: { frequency: 12.0e+09 } }
sweep_parameters :
'cornercut' :
min : 12.5
max : 13.5
num : 10
'wgwidth' :
min : 21
max : 22
num : 10
vocs_parameters :
'variables' :
'cornercut': [12.5, 13.5]
'wgwidth': [21, 22]
'objectives' :
'S(1,1)_12.0e+09': 'explore'
xopt_parameters :
max_steps : 3
The explored objective (S(1,1)_12.0e+09) is an output_parameters name, so
the driver pulls it from the workflow generically. The GP posterior-mean grid is
written to the sweep_output_file; the actual S3P evaluations performed during
exploration are logged to the output_file trajectory table.
Track3P particle weighting¶
Field-emission particle weighting is the particles module — a
post-processing step that reads a Track3P particle dump, filters by impact order
/ face id, bins by axial position, and writes a weighted-particle file suitable
as a Geant4 source. There is no ACE3P solver in this chain; the external dump is
supplied by a track3p_source module and the whole thing runs in single mode
(the weighting is pure Python). This is
examples/track3p_particle_weight:
workflow_parameters :
'workdir' : 'lume-ace3p_track3p_workdir'
'workdir_mode' : 'manual'
workflow :
- module : track3p_source
file : 'sample_track3p_particles.txt'
- module : particles
impact_order : 1
impact_face_id : 4
work_function : 4.5
dt : 1.0e-10
num_bins : 8
beta : [50, 55, 60, 65, 65, 60, 55, 50]
output_format : 'track3p'
output : 'track3p_particles_weighted.txt'
mode :
type : single
output_format: 'track3p' writes the weighted-Track3P dump (all filtered
columns plus Bin and ParticleWeight); the module default 'geant4' instead
writes the 10-column Geant4 source file. See
particles module keys for the full key list.
Geant4 dose-calculation workflow¶
The geant4 module drives a Geant4 application using a single plain-text input
file (key = value lines, # comments) that names its own geometry STL files,
scoring mesh, thread count, and output files. The particle source is supplied by
an upstream module in the chain — either a particles weighting step (fed by a
track3p_source) or a particle_source module naming a prebuilt Geant4-format
file directly. The geant4 module writes the source filename into the input
file (the executable auto-derives the event count from the particle file),
stages the STL files it names into each working directory, and reads the
dose / energy-deposit output files after the run. STLs named in the input file
are located next to it by default; when they live elsewhere (e.g. a shared
assets/ directory), list them under geant4_geometry_files so the module can
find and stage them.
The full runnable chain (track3p_source → particles → geant4) is shipped as
examples/geant4_track3p_beta
(a beta sweep) and
examples/geant4_dose_single
(a single evaluation). A minimal skeleton:
workflow_parameters :
'workdir' : 'lume-ace3p_dose_workdir'
'workdir_mode' : 'manual'
workflow :
- module : track3p_source
file : 'sample_track3p_particles.txt'
- module : particles
impact_order : 1
impact_face_id : 6
work_function : 4.5
dt : 1.0e-10
num_bins : 8
beta : [50, 55, 60, 65, 65, 60, 55, 50]
output_format : 'geant4'
output : 'particles.data' # must match the 'particles = ...' line in the Geant4 input
- module : geant4
geant4_input : 'input_7cell.geant4'
mode :
type : single
output_file : 'dose_single_output.txt'
output_parameters :
'total_dose' : {module: geant4, section: dose, quantity: total}
'peak_dose' : {module: geant4, section: dose, quantity: peak}
'total_edep' : {module: geant4, section: edep, quantity: total}
Optional Geant4 input-file overrides go in the geant4: sub-block of
input_parameters (plain keys, no /); a swept override there becomes an
additional sweep axis alongside any cubit:/ace3p: axes. Geant4
paths are resolved through the same precedence chain as ACE3P — see
Executable paths. If GEANT4_APP_PATH / GEANT4_APP_EXE
(or YAML / site-default equivalents) are unset, dry-run mode is auto-enabled
(the particles weighting still runs for real; only the Geant4 binary is
skipped).