STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
feedtwin.vessels.vapour Namespace Reference

Classes

class  VapourExchange
class  VapourModel
class  NoVapour
class  SaturatedVapour

Functions

float latent_heat (Fluid liquid, float temperature)
None register_vapour_model (str name, Callable[[], VapourModel] build)
VapourModel vapour_model (str name)
list[str] registered_vapour_models ()

Variables

dict _MODELS

Detailed Description

Propellant vapour in the ullage, and what it does to a pressure trace.

The tank model without this is two species with one interface: pressurant above,
liquid below, nothing crossing. That is a good model of a warm-gas system on a
short burn and a poor one of a cryogen, for a reason worth stating precisely.

**Where the interfacial heat goes.** The ullage loses heat to the cold surface --
:mod:`feedtwin.vessels.collapse` computes how much. Without a vapour model that
heat has exactly one place to go: raising the bulk liquid temperature. For
ethanol at 293 K that is right, and it is a few millikelvin over a burn. For LOX
sitting at its normal boiling point it is wrong, because a saturated liquid
cannot warm. It **boils**, at ``mdot = q / h_fg``, and the mass goes into the
ullage where it carries its own partial pressure.

That single difference is the one that decides three things a propulsion engineer
actually asks about:

* **A cryogenic tank vent.** Without vapour, opening a vent empties the ullage
  gas and the trace collapses in tens of milliseconds -- 2.65 g of helium is
  simply not much. With it, the falling pressure drives boil-off that replenishes
  the ullage, and the tank vents for as long as there is liquid and heat. The
  difference is not a correction, it is the shape of the curve.
* **Pressurant consumption.** Vapour is free ullage. A tank that boils needs less
  pressurant to hold pressure than one that does not, so a COPV sized against the
  no-vapour model is sized conservatively -- which is the safe direction, but not
  a free one when the bottle is already the limiting item.
* **Nitrogen over LOX.** Condensation, the case :mod:`collapse` names as moving
  "an order of magnitude more energy per unit area than sensible cooling does".
  It is the same interface running backwards, and it is why the GN2 curves in the
  COPV study are optimistic.

Why partial pressures and not a mixture EOS
-------------------------------------------
The ullage is treated as pressurant and vapour sharing a volume and a
temperature, each on its own equation of state, with **Dalton's law** summing the
partials. Not a real mixture EOS.

That is a deliberate approximation and it is a good one here: at ullage
conditions -- a few tens of bar, well above both species' critical temperature
for helium and far from the vapour's critical point -- the mixture is nearly
ideal in the sense that matters, while a real mixture EOS costs a CoolProp
mixture model per evaluation and a whole class of convergence failures at the
composition extremes this model spends most of its time at (pure pressurant at
t=0, pure vapour in a vented tank). The error is a percent-level fugacity
correction; the cost avoided is a solver that stops converging.

Off by default, and why
-----------------------
:class:`NoVapour` is the default, so nothing changes for an existing model unless
someone asks. Two reasons, and the second is the honest one:

1. For a storable at room temperature it genuinely is negligible -- ethanol's
   vapour pressure at 293 K is 5.8 kPa against a 38 bar ullage, 0.015%.
2. It is the more fragile model. Saturation properties near a critical point,
   a tank driven below its triple point by a fast vent, a liquid that runs out
   mid-step -- these are real states an integrator will visit, and a run that
   fails is worse than a run that is 2% optimistic. Turning it on should be a
   decision with a reason behind it.

Function Documentation

◆ latent_heat()

float feedtwin.vessels.vapour.latent_heat ( Fluid liquid,
float temperature )
``h_fg`` [J/kg] at a temperature, from the saturation line.

The difference of the two saturated enthalpies rather than a correlation, so
it comes from the same equation of state as everything else and goes to zero
at the critical point on its own.

Definition at line 221 of file vapour.py.

Referenced by feedtwin.vessels.vapour.SaturatedVapour.exchange().

◆ register_vapour_model()

None feedtwin.vessels.vapour.register_vapour_model ( str name,
Callable[[], VapourModel] build )
Add a named vapour model.

The registry exists for the same reason :mod:`feedtwin.vessels.collapse` has
one: condensation of nitrogen over LOX, interfacial mass-transfer
correlations and a fitted boil-off rate are all real models with different
assumptions, and each should arrive as a named thing a run report can print
rather than as a coefficient inside this one.

Definition at line 239 of file vapour.py.

◆ registered_vapour_models()

list[str] feedtwin.vessels.vapour.registered_vapour_models ( )

Definition at line 259 of file vapour.py.

◆ vapour_model()

VapourModel feedtwin.vessels.vapour.vapour_model ( str name)

Definition at line 251 of file vapour.py.

Variable Documentation

◆ _MODELS

dict feedtwin.vessels.vapour._MODELS
protected
Initial value:
1= {
2 "none": NoVapour,
3 "saturated": SaturatedVapour,
4}

Definition at line 233 of file vapour.py.