STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
engine.core.spray Namespace Reference

Functions

float momentum_flux_ratio (float rho_O, float u_O, float rho_F, float u_F)
float thrust_momentum_ratio (float J, float MR)
float spray_angle_from_J (float J, float k, float n)
float spray_angle_from_TMR (float TMR)
float weber_number (float rho, float u, float d_char, float sigma)
float ohnesorge_number (float mu, float rho, float sigma, float d_or)
float smd_lefebvre (float d_or, float We, float Oh, float C, float m, float p)
float tn4222_property_factor (str transfer, *, float rho_liq, float mu_liq, float sigma, float rho_gas)
str tn4222_transfer_model (smd_cfg)
float smd_impinging_tn4222 (float d_jet, float v_jet, float rho_liq, float mu_liq, float sigma, float rho_gas, *, Optional[float] dv=None, bool scale_properties=True, Optional[str] transfer=None)
float evaporation_constant_m2_s (*, float Tc, float Pc, float rho_g, float rho_l, float L_vap, float T_boil, float cp_g=2200.0, float D0=2.0e-5, float C_evap=1.562)
float tau_evap_from_k (float D32, float k_evap_m2_s)
float spray_axial_velocity (*, float mdot_O, float u_O, float theta_O_deg, float mdot_F, float u_F, float theta_F_deg)
float tau_evap (float D32, float K)
float xstar (float U_rel, float tau_evap)
Tuple[bool, List[str]] check_spray_constraints (float We_O, float We_F, float x_star, SprayConfig config)
float smd_pintle (float L_open, float V_rel, float rho_f, float mu_f, float sigma_f, float C, float B, float n, float p)

Variables

float TN4222_RHO_AIR = 29.3 * 3386.389 / (287.05 * ((82.0 - 32.0) * 5.0 / 9.0 + 273.15))
float TN4222_HEPTANE_SIGMA = 0.0197
float TN4222_HEPTANE_MU = 3.8e-4
float TN4222_HEPTANE_RHO = 684.0
float TN4222_D32_OVER_D30 = 5.0 / 3.915
tuple TN4222_PROPERTY_TRANSFERS = ("tn4087", "dombrowski_johns", "none")

Detailed Description

Spray and mixing models (J, We, SMD, x*; TMR and theta are diagnostic only)

Function Documentation

◆ check_spray_constraints()

Tuple[bool, List[str]] engine.core.spray.check_spray_constraints ( float We_O,
float We_F,
float x_star,
SprayConfig config )
Check if spray constraints are satisfied.

Constraints:
- We_i ≥ We_min
- x* < x_limit

Parameters:
-----------
We_O : float
    Oxidizer Weber number
We_F : float
    Fuel Weber number
x_star : float
    Evaporation length [m]
config : SprayConfig
    Spray configuration

Returns:
--------
constraints_satisfied : bool
violations : list[str]
    List of violated constraint names

Definition at line 452 of file spray.py.

◆ evaporation_constant_m2_s()

float engine.core.spray.evaporation_constant_m2_s ( * ,
float Tc,
float Pc,
float rho_g,
float rho_l,
float L_vap,
float T_boil,
float cp_g = 2200.0,
float D0 = 2.0e-5,
float C_evap = 1.562 )
d²-law evaporation constant k_evap [m²/s], derived from propellant properties.

Replaces a single hardcoded ``K`` that was identical in all 14 configs and for every
propellant. That constant's VALUE was defensible for ethanol at ~3100 K (it implies
k_evap = 3.33e-6 m²/s, within 10% of a T^2 extrapolation of measured ethanol data), but its
SHAPE was wrong: it could not distinguish ethanol from methane from RP-1, and it did not
move with chamber temperature or pressure at all -- so a 200 psi design and a 600 psi design
evaporated at identical rates.

    k_evap = C * (8 * rho_g * D_v / rho_l) * ln(1 + B_M)
    B_M    = cp_g * (Tc - T_boil) / L_vap          (Spalding mass transfer number)
    D_v    = D0 * (Tc/300)^1.75 * (101325/Pc)      (vapor diffusivity)

Every input except C and D0 already exists in the propellant presets, so this needs no new
tables. ``C_evap`` is the one calibration constant, anchored so ethanol at 3094 K / 450 psi
reproduces the 3.33e-6 m²/s the old fixed K implied -- i.e. this is a re-shaping of a value
that was already right for the propellant it was tuned on, not a change of magnitude.

The same form is already written (and disabled) in combustion_physics.py under
``SPALDING_DIAGNOSTIC_ENABLED``, where it also hardcodes ``fuel="RP-1"``.

Definition at line 332 of file spray.py.

References max.

◆ momentum_flux_ratio()

float engine.core.spray.momentum_flux_ratio ( float rho_O,
float u_O,
float rho_F,
float u_F )
Calculate momentum flux ratio J.

J = (ρ_O × u_O²) / (ρ_F × u_F²)

Parameters:
-----------
rho_O : float
    Oxidizer density [kg/m³]
u_O : float
    Oxidizer velocity [m/s]
rho_F : float
    Fuel density [kg/m³]
u_F : float
    Fuel velocity [m/s]

Returns:
--------
J : float

Definition at line 12 of file spray.py.

◆ ohnesorge_number()

float engine.core.spray.ohnesorge_number ( float mu,
float rho,
float sigma,
float d_or )
Calculate Ohnesorge number.

Oh = μ / √(ρ × σ × d_or)

Parameters:
-----------
mu : float
    Dynamic viscosity [Pa·s]
rho : float
    Density [kg/m³]
sigma : float
    Surface tension [N/m]
d_or : float
    Orifice diameter [m]

Returns:
--------
Oh : float

Definition at line 161 of file spray.py.

References max.

◆ smd_impinging_tn4222()

float engine.core.spray.smd_impinging_tn4222 ( float d_jet,
float v_jet,
float rho_liq,
float mu_liq,
float sigma,
float rho_gas,
* ,
Optional[float] dv = None,
bool scale_properties = True,
Optional[str] transfer = None )
Sauter mean diameter of an impinging-jet pair, Ingebo, NACA TN 4222 (1958).

    Dj / D30 = 2.64 (Dj Vj)^(1/2) + 0.97 Dj dV          (Dj, D30 in inches; Vj, dV in ft/s)
    D32 = (5 / 3.915) D30                                 (Nukiyama-Tanasawa, as fitted)

``v_jet`` is the stream's own jet velocity and ``dv`` the jet-to-gas velocity difference; a
face-injected jet enters gas at rest, dV = Vj (TN 4222 eq. 11), the default.

TN 4222 measured n-heptane only. ``transfer`` (see ``tn4222_property_factor``) carries it to
other liquids and gas densities; None means "tn4087" when ``scale_properties`` else "none".
That transfer is an assumption: measure D32 and set ``spray.smd.smd_scale``.

Raises ValueError on a non-positive or non-finite input (it used to return d_jet, a drop the
size of the orifice, without saying so).

Replaces an earlier function that cited this report but ran TN 4087's crossflow form with the
We*Re product on the jets' closing speed, and read its D30 as D32: about half the drop size
TN 4222 measured.

Definition at line 286 of file spray.py.

References tn4222_property_factor().

◆ smd_lefebvre()

float engine.core.spray.smd_lefebvre ( float d_or,
float We,
float Oh,
float C,
float m,
float p )
Calculate Sauter Mean Diameter (SMD) using Lefebvre correlation.

D32 = C × d_or × We^(-m) × (1 + Oh)^p

Raises ValueError when We or d_or is not positive and finite (it used to return d_or).

Parameters:
-----------
d_or : float
    Orifice diameter [m]
We : float
    Weber number
Oh : float
    Ohnesorge number
C : float
    Model constant
m : float
    Weber exponent
p : float
    Ohnesorge exponent

Returns:
--------
D32 : float [m]

Definition at line 191 of file spray.py.

◆ smd_pintle()

float engine.core.spray.smd_pintle ( float L_open,
float V_rel,
float rho_f,
float mu_f,
float sigma_f,
float C,
float B,
float n,
float p )
Calculate Sauter Mean Diameter (SMD) for pintle injector using relative velocity physics.

Formula: SMD = C * L_open * We_rel^(-n) * (1 + B * Oh_f)^p

Parameters:
-----------
L_open : float
    Characteristic length (Pintle Opening / Gap Height) [m]
V_rel : float
    Relative velocity magnitude between streams [m/s]
rho_f : float
    Fuel (sheet) density [kg/m³]
mu_f : float
    Fuel (sheet) dynamic viscosity [Pa·s]
sigma_f : float
    Fuel surface tension [N/m]
C, B, n, p : float
    Correlation constants
    
Returns:
--------
D32 : float [m]

Definition at line 503 of file spray.py.

◆ spray_angle_from_J()

float engine.core.spray.spray_angle_from_J ( float J,
float k,
float n )
Calculate spray angle from momentum flux ratio J.

Uses half-angle tangent form: tan(θ/2) = k × J^n

PHYSICS INTUITION:
------------------
Imagine the spray as a cone coming out of the injector:

1. **Momentum Vector Decomposition**:
   - The fuel (RP-1) flows RADIALLY outward (perpendicular to axis)
   - The oxidizer (LOX) flows AXIALLY (along the axis, with some angle)
   - When they collide, the combined spray has both radial and axial momentum

2. **Why Half-Angle?**:
   - The spray is SYMMETRIC about the axis
   - We measure angles FROM THE AXIS, not from the opposite edge
   - A particle at the edge of the spray travels at angle θ/2 from the axis
   - Its momentum vector makes angle θ/2 with the axis (not θ!)
   - When we decompose momentum: p_radial = p × sin(θ/2), p_axial = p × cos(θ/2)
   - Full angle θ = 2×(θ/2) is just a convention - we use θ/2 in calculations

3. **Why Tangent?**:
   - In a conical spray, momentum vectors decompose as:
     * Radial component: p_radial = p_total × sin(θ/2)
     * Axial component: p_axial = p_total × cos(θ/2)
   - The RATIO of radial to axial momentum is:
     p_radial / p_axial = sin(θ/2) / cos(θ/2) = tan(θ/2)
   - This ratio determines how "spread out" the spray is

4. **Connection to J**:
   - J = (ρ_O u_O²) / (ρ_F u_F²) measures relative momentum flux
   - High J → more oxidizer momentum → spray more axial (smaller angle)
   - Low J → more fuel momentum → spray more radial (larger angle)
   - The spray angle emerges from balancing these momentum components

5. **Why Not Direct θ = k×J^n?**:
   - Direct form treats angle as arbitrary scalar
   - But spray angle comes from VECTOR balance of momenta
   - tan(θ/2) captures this vector relationship naturally
   - Also provides natural bounds: tan(θ/2) → ∞ as θ → 90°

Parameters:
-----------
J : float
    Momentum flux ratio
k : float
    Model coefficient
n : float
    Model exponent

Returns:
--------
theta : float [rad]

Definition at line 51 of file spray.py.

◆ spray_angle_from_TMR()

float engine.core.spray.spray_angle_from_TMR ( float TMR)
theta = arccos(1/(1 + TMR^0.75)) [rad]. DIAGNOSTIC ONLY.

An invented law on the invented TMR above; no source gives it, and no model reads the angle
(the injectors publish it as ``theta``). The vaporization march takes its axial drop speed
from ``spray_axial_velocity``.

Definition at line 120 of file spray.py.

◆ spray_axial_velocity()

float engine.core.spray.spray_axial_velocity ( * ,
float mdot_O,
float u_O,
float theta_O_deg,
float mdot_F,
float u_F,
float theta_F_deg )
Axial velocity of the combined spray after the doublet collides [m/s].

Momentum balance on the pair: the two jets arrive canted at theta_O / theta_F from the
chamber axis, and what survives downstream is the momentum-weighted axial component

    u_axial = (mdot_O*u_O*cos(theta_O) + mdot_F*u_F*cos(theta_F)) / (mdot_O + mdot_F)

This is the velocity that TRANSPORTS droplets down the chamber, and therefore the one that
belongs in x* = u * tau_evap. The code previously used ``u_rel``, the jet-to-jet RELATIVE
velocity -- correct for atomisation (it is what shears the sheet, and it belongs in the
Ingebo Weber number) but wrong for transport: droplets do not travel downstream at the
closing speed of two jets. Measured on a converged design, u_rel was 28.4 m/s against a true
axial 13.8 m/s, so x* -- and hence the required chamber length -- was over-predicted 2.06x.

Definition at line 382 of file spray.py.

◆ tau_evap()

float engine.core.spray.tau_evap ( float D32,
float K )
Calculate evaporation time.

τ_evap = K × D32²

Parameters:
-----------
D32 : float
    Sauter Mean Diameter [m]
K : float
    Evaporation constant [s/m²]

Returns:
--------
tau : float [s]

Definition at line 410 of file spray.py.

◆ tau_evap_from_k()

float engine.core.spray.tau_evap_from_k ( float D32,
float k_evap_m2_s )
Standard d²-law evaporation time: τ = D32² / k_evap. Note k is in m²/s, NOT its reciprocal.

Definition at line 375 of file spray.py.

◆ thrust_momentum_ratio()

float engine.core.spray.thrust_momentum_ratio ( float J,
float MR )
TMR = J/(1 + MR). DIAGNOSTIC ONLY.

Not a published parameter: the pintle literature's TMR is the radial-to-axial momentum ratio
(mdot_r v_r)/(mdot_a v_a), which this is not. Nothing in the model reads it; it is reported
for continuity with old runs.

Definition at line 40 of file spray.py.

◆ tn4222_property_factor()

float engine.core.spray.tn4222_property_factor ( str transfer,
* ,
float rho_liq,
float mu_liq,
float sigma,
float rho_gas )
D32(liquid, gas) / D32(n-heptane, air at TN 4222's conditions), same jets and speeds.

- "tn4087": Ingebo's crossflow exponents (NACA TN 4087: D30 ~ (We Re)^(-1/4)), so
  (sigma mu_l / rho_l)^(1/4) rho_g^(-1/4).
- "dombrowski_johns": the inviscid sheet-breakup length scale of Dombrowski & Johns (Chem. Eng.
  Sci. 18, 1963), D ~ (sigma^2 / (rho_g rho_l U^4))^(1/6) at fixed sheet geometry and speed, so
  (sigma^2 / (rho_g rho_l))^(1/6) relative to heptane/air.
- "none": 1 (heptane in air as measured).
The spread between them is the uncertainty of carrying a single-liquid correlation to
LOX/ethanol at chamber density; a measured D32 (smd_scale) replaces it.

Definition at line 251 of file spray.py.

Referenced by smd_impinging_tn4222().

◆ tn4222_transfer_model()

str engine.core.spray.tn4222_transfer_model ( smd_cfg)
The property transfer a spray.smd config asks for: 'none' when smd_property_scaling is off,
else smd_property_transfer (default 'tn4087').

Definition at line 278 of file spray.py.

◆ weber_number()

float engine.core.spray.weber_number ( float rho,
float u,
float d_char,
float sigma )
Calculate Weber number.

We = (ρ × u² × d_char) / σ

Parameters:
-----------
rho : float
    Density [kg/m³]
u : float
    Velocity [m/s]
d_char : float
    Characteristic diameter [m] (port diameter or annulus hydraulic diameter)
sigma : float
    Surface tension [N/m]

Returns:
--------
We : float

Definition at line 133 of file spray.py.

◆ xstar()

float engine.core.spray.xstar ( float U_rel,
float tau_evap )
Calculate evaporation length x*.

x* = U_rel × τ_evap

Parameters:
-----------
U_rel : float
    Relative velocity [m/s]
tau_evap : float
    Evaporation time [s]

Returns:
--------
x_star : float [m]

Definition at line 431 of file spray.py.

Variable Documentation

◆ TN4222_D32_OVER_D30

float engine.core.spray.TN4222_D32_OVER_D30 = 5.0 / 3.915

Definition at line 244 of file spray.py.

◆ TN4222_HEPTANE_MU

float engine.core.spray.TN4222_HEPTANE_MU = 3.8e-4

Definition at line 240 of file spray.py.

◆ TN4222_HEPTANE_RHO

float engine.core.spray.TN4222_HEPTANE_RHO = 684.0

Definition at line 241 of file spray.py.

◆ TN4222_HEPTANE_SIGMA

float engine.core.spray.TN4222_HEPTANE_SIGMA = 0.0197

Definition at line 239 of file spray.py.

◆ TN4222_PROPERTY_TRANSFERS

tuple engine.core.spray.TN4222_PROPERTY_TRANSFERS = ("tn4087", "dombrowski_johns", "none")

Definition at line 248 of file spray.py.

◆ TN4222_RHO_AIR

float engine.core.spray.TN4222_RHO_AIR = 29.3 * 3386.389 / (287.05 * ((82.0 - 32.0) * 5.0 / 9.0 + 273.15))

Definition at line 238 of file spray.py.