|
| BurnReport | summarise (Sequence[float] t, Sequence[float] thrust, Sequence[float] pressure, Sequence[float] mdot_oxidiser, Sequence[float] mdot_fuel, *, float before, Sequence[float]|None cstar=None, Sequence[float]|None stiffness_oxidiser=None, Sequence[float]|None stiffness_fuel=None, Sequence[bool]|None extrapolated=None, bool burning=False) |
| bool | is_burning (Sample sample) |
| list[BurnReport] | burns (Sequence[Sample] samples, Mapping[str, str]|None inlets=None) |
| BurnReport | _summarise_samples (Sequence[Sample] run, float before, Mapping[str, str] inlets, *, bool burning) |
| float | finite (float value) |
What the engine did over a burn, from the steps that burned.
One summary for every caller that fires an engine through a feed system: the
cockpit finds its burns in the session's history; a burn recorded as columns
(:class:`~feedtwin.session.burn.BurnTrace`) goes through :func:`summarise`.
Layer X keeps its own summary, and its impulse, mean thrust, O/F and Isp are
held to this arithmetic by ``EngineDesign/tests/test_layerx_cockpit_parity.py``,
so a disagreement between the tools is physics, not bookkeeping.
The rules
---------
* **A step burns** when both propellants reach the chamber, each above
:data:`~feedtwin.session.core.MIN_CHAMBER_FLOW`. A burn is a run of burning
steps; one quiet step ends it. One propellant alone is not a burn: when the
LOX runs out first the fuel keeps flowing for a step or two, and the
chamber model, clamped at the edge of its combustion table, still reports
thrust for it (~2 kN on LE4). Nothing is burning, and none of it is counted.
* **Totals are right-endpoint sums**: each burning sample carries the step that
ended at it, ``F_k (t_k - t_{k-1})``, where ``t_{k-1}`` is the sample before
it even when that one did not burn. That is how :func:`feedtwin.session.burn.burn`
steps, so the first step after Fire counts once, at its own thrust, and a
burn read from the cockpit's history totals exactly what Layer X totals from
the same steps.
* **Mean O/F is the mass ratio** of what was burned (ox kg over fuel kg), not
the mean of the instantaneous ratios. **Isp is delivered**: impulse over the
weight of the propellant burned.
* **Full flow** is the part of the burn whose total mass flow is at least
:data:`FULL_FLOW_FRACTION` of the burn's median. The start (valves still
travelling) and the tail-off are outside it. The minima a design rule is
judged on -- thrust, chamber pressure, injector stiffness -- are read there,
because a valve half open has no stiffness to speak of and that is not a
finding about the injector.
| list[BurnReport] feedtwin.session.report.burns |
( |
Sequence[Sample] | samples, |
|
|
Mapping[str, str] | None | inlets = None ) |
Every burn in ``samples``, oldest first.
``inlets`` maps ``oxidiser``/``fuel`` to the injector inlet node
(:attr:`feedtwin.session.burn.Probes.injector_inlet`). With it, stiffness
is the drop from that node to the chamber over chamber pressure -- the
line exit to the chamber, which is the whole of what an engine card owns.
Without it, a sample's mixture balance is used when it carries one.
A burn whose first step is the first sample given has no sample before it
to start from; it is timed from that sample's own clock less the next
step, which is right when the steps are even and is said by
:attr:`BurnReport.start_s` either way.
Definition at line 181 of file report.py.
References _summarise_samples(), and is_burning().