Optimization¶
lume-ace3p is configured with Xopt to
allow single-batch-job optimization, run directly from a lume-ace3p
configuration file. Optimization is a mode (type: scalar_optimize) that
drives the declarative workflow: chain: the objective is declared in
output_parameters and referenced by name in the VOCS, so the Xopt driver is
workflow-agnostic — any workflow (S3P, Geant4, a multi-step chain) can be
optimized with the same code, not just S3P.
Optimization with S3P¶
To set up an S3P optimization problem, no additional files beyond those
needed for a typical lume-ace3p problem are required. The configuration
file must include:
a
workflow:list — the module chain to drive (e.g.cubit → s3p).mode:withtype: scalar_optimize.output_parameters— declares the scalar the objective pulls out of the workflow. For an S3P reflection objective this is the explicit form{module: s3p, quantity: 'S(0,0)', at: {frequency: 12.0e+09}}.vocs_parameters— variables (required), objectives (required), constants (optional), and constraints (optional) for the optimization problem.objectivesis the plain Xopt shape: it maps anoutput_parametersname to'MINIMIZE'or'MAXIMIZE'. For multi-objective optimization, declare more than one output/objective pair. A per-objective stopping threshold is supplied viaxopt_parameters.tolerance(not inside the objective).
xopt_parameters— choice of optimization algorithm and algorithm parameters.
xopt_parameters options¶
generator(required): the optimization algorithm. Currently supported:Nelder–Mead —
NelderMeadGeneratorExpected Improvement —
ExpectedImprovementGeneratorExpected Hypervolume Improvement —
ExpectedHypervolumeImprovementGeneratorUpper Confidence Bound —
UpperConfidenceBoundGeneratorMultifidelity Bayesian —
MultiFidelityGenerator
num_random(optional): number of random exploratory steps before optimization begins.
Exactly one termination criterion is required. These are the keys that end a run, and a config with none of them does nothing and says so:
num_step: fixed number of optimization steps.cost_budget: total time, in seconds, allowed for optimization.alotted_time: the same budget expressed asHH:MM:SS.cost_budgetandalotted_timeselect the multi-fidelity cost-limited loop.
Two further keys refine a criterion and do nothing on their own:
max_iterations(optional): caps the total steps anum_steprun may take. It is read only alongsidenum_stepand is ignored without it.tolerance(optional): a stopping test — the run ends early once every objective is at or below it — applied inside whichever criterion’s loop is running. It is not a criterion itself.
Every one of these counts the campaign, not this process, so they mean the same
thing to a run continued with mode.resume (see
Resuming an interrupted optimization).
save_model(optional): for algorithms that train a GP (e.g. multifidelity Bayesian),Truewrites agp_parameters.txtfile containing the trained GP parameters so that it can be re-loaded later.
Multifidelity Bayesian optimization adds:
fidelity_variable(required): the name of the parameter in the Cubit file that controls fidelity.cost_function(optional): the relationship between cost and fidelity. Options areexponential(explicit, exponential relationship between max- and min-fidelity cost) andgaussian_process(implicit, learned relationship). Defaults toexponential.
Upper-confidence-bound and expected-hypervolume-improvement also support:
generator_options(optional): list additional algorithm parameters, such asbetafor upper confidence bound.
Output files¶
Running lume-ace3p with an Xopt mode logs the full run trajectory to a single
file — sim_output.txt by default, or the path given as mode.output_file.
The file is the Xopt data table (all parameter tuples reached and the
corresponding output values), overwritten each step so it always holds the
complete trajectory.
Resuming an interrupted optimization¶
An optimization killed by a batch wall clock at evaluation 190 of 200 used to throw
away all 190 — worse than losing a sweep, because in an optimization the evaluations
are the expensive part. Add resume: True to the mode: block and it continues:
mode :
type : scalar_optimize
resume : True # continue from xopt_state.yml
xopt_state.yml is written beside sim_output.txt after every evaluation, whether
or not resume is set, and holds the optimizer’s whole state — the trajectory and
the generator’s own internal state, so a Nelder–Mead simplex carries on rather than
restarting on top of old data. run-lume-ace3p --status <config.yaml> reports what
it holds without running anything.
Important
A resumed optimization does not reproduce the trajectory an uninterrupted run
would have taken. The promise is that no evaluation is repeated and the search
continues from the same data — not that two sim_output.txt files will diff clean.
This is weaker than the sweep modes’ promise of an identical table, and deliberately
so: an equally informed generator is not the same generator a straight-through run
would have had.
Iteration budgets (num_random, num_step, max_iterations, cost_budget) are
totals for the campaign, so a resumed run continues to the same finish line and
resuming a finished optimization does nothing. See
resume in an optimization — continuing an interrupted search for the refusal cases — a state file written for a
different generator, objective direction or variable bounds is reported and
discarded rather than adopted.
One directory per evaluation¶
Set workflow_parameters: {workdir_mode: 'auto'} (as the shipped examples do) and
each evaluation runs in its own directory, numbered by iteration in evaluation
order: <workdir>_0, <workdir>_1, … matching the rows of sim_output.txt. So
the mesh, solver input, results and log of evaluation 7 are the ones in
<workdir>_7, and the best row of the trajectory can be traced back to the files
that produced it.
Without it — workdir_mode defaults to 'manual' — every evaluation runs in the
one workdir, overwriting the previous evaluation’s mesh, input files, results,
logs and run manifest; what is left on disk at the end describes only the last
evaluation. The run prints a warning when that is about to happen. See
workdir_mode — naming each evaluation’s folder for the full table, including why 'auto'
numbers by iteration here instead of naming by input value.
S3P Nelder–Mead example¶
This example (based on the 90-degree bend from the ACE3P tutorials, shipped as
examples/s3p_optimization)
sets up an optimization over the scattering parameter S(0,0) at 12 GHz, with
input parameters of waveguide width and chamfer length.
workflow_parameters :
'workdir' : 'lume-ace3p_xopt_workdir'
'workdir_mode' : 'auto' # one directory per evaluation: _0, _1, _2, …
workflow :
- module : cubit
journal : 'bend-90degree.jou'
- module : s3p
input : 'bend-90degree.s3p'
tasks : 16
cores : 8
opts : '--cpu-bind=cores'
mode :
type : scalar_optimize
The workflow: chain is the same cubit → s3p pipeline used for the 90-degree
bend parameter sweep; only the mode differs.
The objective is declared in output_parameters and referenced by name in the
VOCS:
output_parameters :
'reflection' : { module: s3p, quantity: 'S(0,0)', at: { frequency: 12.0e+09 } }
vocs_parameters :
'variables' :
'cornercut': [14,17]
'rcorner1': [0.5,2.5]
'objectives' :
'reflection' : 'MINIMIZE'
The variable names cornercut and rcorner1 must match the variable names
in the Cubit file. Each input variable has a range to explore. The objective is
an output_parameters name mapped to MINIMIZE/MAXIMIZE — the Xopt driver
never parses S-parameters itself, so to configure a multi-objective problem you
add more output_parameters entries and list each in objectives:
output_parameters :
'reflection' : { module: s3p, quantity: 'S(0,0)', at: { frequency: 12.0e+09 } }
'transmission' : { module: s3p, quantity: 'S(0,1)', at: { frequency: 10.424e+09 } }
vocs_parameters :
'objectives' :
'reflection' : 'MINIMIZE'
'transmission' : 'MINIMIZE'
Xopt parameters:
xopt_parameters :
'generator' : 'NelderMeadGenerator'
'num_random' : 0
'num_step' : 25
generator selects the optimization algorithm; num_random is the number
of initial random parameter-space guesses; num_step is the number of
iterations.
S3P multifidelity Bayesian example¶
This example optimizes S(1,1) at 12 GHz with input parameters of
waveguide width and chamfer length:
workflow_parameters :
'workdir' : 'lume-ace3p_xopt_workdir'
'workdir_mode' : 'auto' # one directory per evaluation: _0, _1, _2, …
workflow :
- module : cubit
journal : 'bend-90degree_mf.jou'
- module : s3p
input : 'bend-90degree_mf.s3p'
tasks : 16
cores : 8
opts : '--cpu-bind=cores'
mode :
type : scalar_optimize
The Cubit journal file must be configured for multifidelity optimization by specifying a variable that controls model fidelity. Here, fidelity is controlled by a parameter that changes mesh size.
output_parameters :
'reflection' : { module: s3p, quantity: 'S(1,1)', at: { frequency: 12.0e+09 } }
vocs_parameters :
'variables' :
'cornercut': [12.5,13.5]
'wgwidth': [21,22]
'objectives' :
'reflection' : 'MINIMIZE'
The tolerance (a stopping criterion) is set in xopt_parameters: if the
objective falls below 0.001, the optimization terminates.
xopt_parameters :
'generator' : 'MultiFidelityGenerator'
'fidelity_variable' : 'mesh_fidelity'
'cost_function' : 'exponential'
'alotted_time' : 00:30:00
'num_random' : 3
'tolerance' : 1e-03
The fidelity_variable parameter must match exactly the name of the
variable in the Cubit file that controls fidelity. The cost_function
expresses the relationship between fidelity and cost. alotted_time (here
30 minutes) is a stopping criterion: if the run is close to the allotted
time, the algorithm terminates. The algorithm starts with three random
steps to seed its internal GP model.
Optimizing other workflows¶
Because the objective is pulled from output_parameters and the workflow is
driven only through its evaluate seam, the same scalar_optimize mode
optimizes any chain — you change the workflow: list and point the objective at
a different module’s output. No custom sim function or workflow subclass is
needed (the pre-refactor Omega3PWorkflow / S3PWorkflow classes and the
hand-rolled Xopt loop no longer exist).
For an Omega3P R/Q optimization (shipped as
examples/omega3p_optimization),
the objective is an acdtool bare-form spec routed to the acdtool module. This
is the optimization counterpart of the omega3p_sweep example — same
cubit → omega3p → acdtool pipeline and the same pillbox-rtop.* inputs, with
mode: scalar_optimize in place of the sweep:
workflow :
- module : cubit
journal : 'pillbox-rtop.jou'
- module : omega3p
input : 'pillbox-rtop.omega3p'
tasks : 16
cores : 8
- module : acdtool
input : 'pillbox-rtop.rfpost'
mode :
type : scalar_optimize
input_parameters :
cubit :
'cav_radius' : 100.0
'ellipticity' : 0.5
output_parameters :
'R/Q' : {module: acdtool, section: RoverQ, quantity: RoQ, at: {mode: 0}}
'mode_freq' : {module: omega3p, quantity: Frequency, at: {mode: 0}}
vocs_parameters :
'variables' :
'cav_radius' : [95, 105]
'ellipticity' : [0.5, 1.2]
'objectives' :
'R/Q' : 'MAXIMIZE'
'observables' :
- 'mode_freq'
variables are the workflow input parameters and their bounds; objectives
selects an output_parameters name to maximize or minimize; observables are
tracked by Xopt but not optimized. constraints (optional) specify inequality
constraints on any declared output. Compute a derived constraint such as a
target-frequency error by declaring the underlying quantity (mode_freq) as an
observable and adding a constraint on it, rather than by writing a sim
function.
The input_parameters block gives each VOCS variable an explicit home. A VOCS
variables entry declares only a name and bounds — it is input_parameters
that routes that name to a bucket (cubit / ace3p / geant4 / particles)
and, for Cubit, to the matching name = … line in the journal file. As with the
S3P example, the scalar values here are nominal starting points that Xopt
overrides each step.
Note
If input_parameters is omitted, every VOCS variable name misses the routing
table and silently falls back to the cubit bucket. That happens to work when
all variables are Cubit journal variables (as above), but it masks typos — a
misspelled VOCS name becomes a junk Cubit variable that no-ops — and mis-routes
any non-Cubit knob. Declare input_parameters so the routing is explicit and
checked.
Viewing S3P optimization output¶
See Plotting tools for the optimization-output visualization tools.