Mission
The initial conditions a run starts from, and the ladder that converges the hard ones.
This module is the direct counterpart of set_values(prob, num_nodes) in OpenConcept’s
B738.py and of set_mission_profile(prob) in its B738_sizing.py. Both are functions
that write a list of values into a problem before running it:
prob.set_val("climb.fltcond|vs", np.linspace(2300.0, 600.0, num_nodes), units="ft/min")
prob.set_val("climb.fltcond|Ueas", np.linspace(230, 220, num_nodes), units="kn")
prob.set_val("cruise|h0", 33000.0, units="ft")
prob.set_val("mission_range", 2050, units="NM")
InitialConditions is that list written as data instead of as statements, with the same
names. A value may be a single number, a pair of endpoints to interpolate across the phase
exactly as np.linspace does above, or one number per analysis node.
ContinuationStep and ContinuationLadder are the second half of
set_mission_profile: the part that converges an easy mission first and steps up to the
design one, because a Newton solver started cold on a 2800 nmi mission at 35,000 ft does not
reach it. OpenConcept writes that as two run_model() calls between blocks of assignments;
here it is a list of rungs, so it travels with the case it converges.
Nothing here imports OpenConcept or OpenMDAO. Conditions are written into anything that accepts
set(name, value, units), run() and shape_of(name).
- class cdadt.mission.ContinuationLadder(steps=())[source]
Bases:
objectThe rungs walked before the design mission, and the walk itself.
- Parameters:
steps (sequence of ContinuationStep, optional) – Progressively harder missions, converged in order. Empty attempts the design mission directly, which for a long-range mission generally fails.
- property steps: tuple[ContinuationStep, ...]
The rungs, in the order they are walked.
- converge(box, conditions, verbose=False)[source]
Walk every rung, then converge the design conditions.
Each rung is written on top of the design conditions and converged, so the solver enters the next rung from a converged neighbour. The final run is the design mission itself.
- Parameters:
box (SupportsConditions)
conditions (InitialConditions)
verbose (bool)
- Return type:
None
- class cdadt.mission.ContinuationStep(description, conditions=None)[source]
Bases:
objectOne rung of the ladder up to the design mission.
- Parameters:
description (str) – What this rung relaxes, for the run log.
conditions (mapping, optional) – Initial-condition overrides for this rung, as
name -> (value, units). A rung states only what it changes; everything else is the design condition.
- property description: str
What this rung relaxes.
- property conditions: dict[str, tuple[Any, str | None]]
The overrides this rung applies.
- class cdadt.mission.InitialConditions(values, mission_path='mission')[source]
Bases:
objectThe values a run starts from, by name.
- Parameters:
values (mapping) –
name -> (value, units). The value may be a float, a two-element sequence of endpoints, or one value per analysis node.mission_path (str, optional) –
Subsystem the mission lives under inside the black box. Default
"mission".Names are written exactly as OpenConcept’s own run scripts write them –
cruise|h0,climb.fltcond|vs– because in those scripts the mission is promoted to the top of the model. In the sizing analysis it is a subsystem, so a name that is not settable on its own is retried under this path. A name that resolves either way resolves the same way every time, andresolve()is what a message quotes when it does not resolve at all.
Examples
>>> conditions = InitialConditions({"cruise|h0": (35000.0, "ft")}) >>> conditions.resolve("cruise|h0", box) 'mission.cruise|h0'
- property mission_path: str
Subsystem the mission lives under inside the black box.
- property values: dict[str, tuple[Any, str | None]]
Return the conditions as
name -> (value, units).
- merged_with(other)[source]
Return these conditions with
otherwritten on top.How a continuation rung is applied: the design conditions first, then whatever the rung overrides, so a rung states only what it relaxes.
- Parameters:
other (InitialConditions | Mapping[str, tuple[Any, str | None]])
- Return type:
- resolve(name, box)[source]
Return the name the black box actually publishes this condition under.
Tries the name as written, then under the mission path. Raises naming both attempts, because “is it
cruise|h0ormission.cruise|h0” is the first question a failure here raises and the message should answer it.- Parameters:
name (str)
box (Any)
- Return type:
str
- resample(value, shape, name)[source]
Return
valueshaped to fitshape.A float is left alone and broadcast by OpenMDAO. A two-element sequence is interpolated across the target, which is what
np.linspace(2300.0, 600.0, num_nodes)does in OpenConcept’s own run script. A full-length sequence is used as given.- Raises:
MissionError – For any other length. Broadcasting a wrong-length schedule would quietly fly a different mission than the one the case file asks for.
- Parameters:
value (Any)
shape (tuple[int, ...])
name (str)
- Return type:
Any
- apply(box)[source]
Write every condition into the box, without converging it.
- Parameters:
box (SupportsConditions)
- Return type:
None
- exception cdadt.mission.MissionError[source]
Bases:
ExceptionRaised when an initial condition cannot be resampled onto the grid it is written to.
- class cdadt.mission.SupportsConditions(*args, **kwargs)[source]
Bases:
ProtocolAnything initial conditions can be written into.
Deliberately narrow: the profile needs to set a value, ask how big the target is so a pair of endpoints can be interpolated across it, and converge. That keeps this module free of any OpenMDAO import and testable without building a model.
- set(name, value, units=None)[source]
Set
nametovalue, interpreting it inunits.- Parameters:
name (str)
value (Any)
units (str | None)
- Return type:
None