STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
discharge.py
Go to the documentation of this file.
1"""Injector discharge coefficient model Cd(Re, orifice geometry).
2
3A declared orifice inlet (``inlet_geometry`` / ``inlet_radius_ratio``) and L/d set Cd_inf: the
4short-tube table with the Lichtarowicz (1965) length fit, which is what a drilled doublet hole
5is (the shipped configs declare sharp, L/d 4). Without one, Cd_inf is the thin-plate
6sharp-orifice value (ASME / ISO 5167: Cd ≈ 0.60–0.61 at high Re), keyed to d_jet.
7"""
8
9from __future__ import annotations
10
11import math
12from typing import Dict, Optional
13
14import numpy as np
15from engine.pipeline.config_schemas import DischargeConfig
16
17
19 d_hyd_m: Optional[float],
20 config: DischargeConfig,
21) -> float:
22 """Asymptotic Cd at high Re for a circular injector hole.
23
24 A declared inlet (``inlet_geometry`` / ``inlet_radius_ratio``) wins: the short-tube value at
25 the hole's L/d (cd_inf_from_inlet_geometry). Otherwise this is a THIN-PLATE model:
26 - **d = d_ref** (default 2 mm): ``Cd_inf`` equals config baseline (default **0.60**),
27 matching thin-plate sharp-edged orifice data (Cd ≈ 0.595–0.602, Re > 10⁴).
28 - **d < d_ref**: ``(d/d_ref)^cd_small_hole_exponent``, default 0 (no change). ISO 5167 and
29 Sutton & Biblarz Table 8-2 have small sharp holes flowing slightly MORE; the old 0.2
30 penalty had the wrong sign.
31 - **d > d_ref**: small logarithmic rise toward ``cd_inf_max`` (≤ ~0.62).
32 - Result clamped to ``[cd_inf_min_geom, cd_inf_max]``.
33 A drilled hole of L/d 2-10 is not a thin plate (0.79 at L/d 4, Lichtarowicz 1965); this
34 path under-predicts its flow by ~24%.
35
36 When ``use_geometry_cd`` is False or diameter is missing, returns ``config.Cd_inf``.
37 """
38 # Inlet treatment, when declared, is the physical determinant and wins over both the
39 # diameter scaling and the raw Cd_inf. Checked FIRST because the impinging injector calls
40 # this function directly (impinging.py:174) and never goes through cd_from_re, so putting
41 # the override only there left the solve on the old path.
42 _cd_inlet = cd_inf_from_inlet_geometry(config)
43 if _cd_inlet is not None:
44 return float(_cd_inlet)
45 if not getattr(config, "use_geometry_cd", False):
46 return float(config.Cd_inf)
47 if d_hyd_m is None or not np.isfinite(float(d_hyd_m)) or float(d_hyd_m) <= 0.0:
48 return float(config.Cd_inf)
49
50 d_min = float(getattr(config, "d_min_m", 4.0e-4))
51 d_ref = float(getattr(config, "d_ref_m", 2.0e-3))
52 cd_base = float(config.Cd_inf)
53 exp_small = float(getattr(config, "cd_small_hole_exponent", 0.20))
54 log_gain = float(getattr(config, "cd_large_hole_log_gain", 0.015))
55 cd_max = float(getattr(config, "cd_inf_max", 0.62))
56 cd_floor = float(getattr(config, "cd_inf_min_geom", 0.48))
57
58 d = float(max(d_min, float(d_hyd_m)))
59 if d_ref <= 0.0:
60 return float(np.clip(cd_base, cd_floor, cd_max))
61
62 ratio = d / d_ref
63 if ratio < 1.0:
64 cd_geom = cd_base * (ratio ** max(0.0, exp_small))
65 else:
66 cd_geom = cd_base + log_gain * math.log(ratio)
67
68 return float(np.clip(cd_geom, cd_floor, cd_max))
69
70
72 d_hyd_O: float,
73 d_hyd_F: float,
74 discharge_O: DischargeConfig,
75 discharge_F: DischargeConfig,
76) -> float:
77 """High-Re Cd_inf,O / Cd_inf,F from orifice diameters (≈1 when jets share the same hole style)."""
78 cd_f = cd_inf_from_orifice_diameter(d_hyd_F, discharge_F)
79 if cd_f <= 0.0:
80 return 1.0
81 cd_o = cd_inf_from_orifice_diameter(d_hyd_O, discharge_O)
82 return float(cd_o / cd_f)
83
84
86 Re: float,
87 config: DischargeConfig,
88 P_inlet: float = None,
89 T_inlet: float = None,
90 d_hyd_m: Optional[float] = None,
91) -> float:
92 """
93 Calculate discharge coefficient as function of Reynolds number, optional orifice
94 diameter, pressure, and temperature.
95
96 ``Re`` is on the bulk hole velocity mdot/(rho A) and the hole diameter.
97
98 Re law, when the block declares an inlet, an ``orifice_l_over_d`` and
99 ``length_model: lichtarowicz`` (the default) -- Lichtarowicz, Duggins & Markland (1965):
100 1/Cd = 1/Cd_u + 20 (1 + 2.25 L/d)/Re - 0.0015 (L/d) / (1 + 7.5 [log10(0.00015 Re)]^2)
101 with Cd_u the orifice's own high-Re Cd as this module anchors it (inlet table x
102 cd_length_factor, cd_u_from_inlet_geometry), then the counterbore approach
103 (approach_beta) and the 0.98 cap exactly as cd_inf_from_inlet_geometry applies them.
104
105 Otherwise (``length_model: piecewise``, or no declared inlet / L/d): the LEGACY, unsourced
106 form Cd(Re) = Cd_inf,eff - a_Re / √Re. ``a_Re`` is a tuned coefficient with no reference
107 and is ignored whenever the Lichtarowicz law applies.
108
109 ``Cd_inf,eff`` is ``cd_inf_from_orifice_diameter(d_hyd_m, config)`` when geometry
110 mode is enabled; otherwise ``config.Cd_inf``.
111
112 Corrections (unsourced; off by default):
113 - Pressure correction: Cd(P) = Cd(Re) × [1 + a_P × (P/P_ref - 1)]
114 - Temperature correction: Cd(T) = Cd(Re) × [1 + a_T × (T/T_ref - 1)]
115
116 Clamped to [Cd_min, Cd_inf,eff]
117 """
118 # Inlet geometry, when the config declares one, is the PHYSICAL determinant of Cd and
119 # overrides the diameter-scaled value. See cd_inf_from_inlet_geometry: it returns None
120 # unless inlet_geometry / inlet_radius_ratio is set, so old configs are untouched.
121 cd_inf_eff = cd_inf_from_orifice_diameter(d_hyd_m, config)
122
123 if Re <= 0:
124 return float(config.Cd_min)
125
126 lich = lichtarowicz_re_inputs(config)
127 if lich is not None:
128 cd_u, lod, beta = lich
129 Cd = min(cd_with_approach(cd_lichtarowicz_re(cd_u, Re, lod), beta), 0.98)
130 else:
131 Cd = cd_inf_eff - config.a_Re / np.sqrt(max(Re, 1e-6))
132
133 if config.use_pressure_correction and P_inlet is not None and config.P_ref > 0:
134 P_correction = 1.0 + config.a_P * (P_inlet / config.P_ref - 1.0)
135 Cd *= P_correction
136
137 if config.use_temperature_correction and T_inlet is not None and config.T_ref > 0:
138 T_correction = 1.0 + config.a_T * (T_inlet / config.T_ref - 1.0)
139 Cd *= T_correction
140
141 Cd = np.clip(Cd, config.Cd_min, cd_inf_eff)
142 return float(Cd)
143
144
146 rho: float,
147 u: float,
148 d_hyd: float,
149 mu: float
150) -> float:
151 """
152 Calculate Reynolds number.
153
154 Re = (ρ × u × d_hyd) / μ
155 """
156 if mu <= 0:
157 return 1e6
158
159 Re = (rho * u * d_hyd) / mu
160 return float(Re)
161
162
163# =====================================================================================
164# ORIFICE INLET GEOMETRY -> Cd. This is a DESIGN KNOB, not a fudge factor.
165#
166# The model above scales Cd_inf by hole DIAMETER, which is a manufacturing proxy, not
167# physics -- diameter enters the real problem only through Reynolds number and relative
168# roughness. What actually sets an orifice's discharge coefficient is (a) what the INLET
169# edge looks like and (b) the length-to-diameter ratio.
170#
171# INLET EDGE. A sharp edge separates the flow at entry, forming a vena contracta the
172# stream never fully recovers from: Cd ~ 0.61 for a thin plate. Rounding or chamfering the
173# entry lets the flow hug the wall instead, and Cd climbs to 0.85-0.95 at r/d = 0.1-0.2.
174# Nurick (1976) showed inlet condition also sets cavitation inception -- the critical
175# pressure ratio rises linearly with inlet roundness -- so rounding buys cavitation margin
176# as well as flow.
177#
178# LENGTH. Lichtarowicz, Duggins & Markland (1965), "Discharge Coefficients for
179# Incompressible Non-Cavitating Flow through Long Orifices": Cd rises steeply from L/d = 0,
180# peaks near L/d ~ 2 where the controlled expansion recovers part of the dynamic pressure
181# lost at the vena contracta, then falls slowly as wall friction takes over. Above
182# Re ~ 1e4 Cd is essentially Reynolds-independent for a given orifice, which is the regime
183# every one of these injectors runs in.
184#
185# WHY THIS IS USEFUL: Cd is per-orifice, and `discharge.oxidizer` / `discharge.fuel` are
186# already separate config blocks. So you can deliberately give one propellant a higher Cd
187# than the other by filleting only that side's inlet -- a way to move the momentum ratio or
188# trim O/F WITHOUT changing hole size, element count or angles. It is a real tuning knob
189# that costs one extra machining op.
190#
191# Values below are the practitioner table (Huzel & Huang, "Modern Engineering for Design of
192# Liquid-Propellant Rocket Engines", injector orifice Cd) cross-checked against the rounded
193# -inlet range reported in the cold-flow literature.
194# =====================================================================================
195
196#: Named inlet treatments -> Cd for a SHORT TUBE (L/d ~ 2-5, i.e. a normally drilled hole
197#: in a plate) at Re > 1e4. Apply cd_length_factor() for other L/d.
198#:
199#: CAREFUL -- the widely-quoted "sharp-edged orifice, Cd = 0.61" is the THIN-PLATE value
200#: (L/d -> 0), where the jet leaves at the vena contracta and never recovers. A drilled hole
201#: of L/d 2-5 with the same sharp entry reattaches inside the bore and recovers to ~0.80.
202#: Conflating the two under-predicts a real injector's flow by ~24%. Both anchors are
203#: reproduced here: 0.80 at L/d 2-5, and 0.80 * cd_length_factor(0) = 0.61 at the plate limit.
204INLET_GEOMETRY_CD: Dict[str, float] = {
205 "sharp": 0.80, # plain drilled hole, sharp entry, reattached
206 "chamfered": 0.84, # ~45 deg x 0.1d break on the entry edge
207 "conical": 0.86, # conical/countersunk entrance, included ~60-90 deg
208 "rounded_light": 0.85, # r/d ~ 0.05
209 "rounded": 0.88, # r/d ~ 0.1-0.15 -- "short tube with rounded entrance"
210 "bellmouth": 0.95, # r/d >= 0.2, fully faired entry
211}
212
213#: r/d at which each named treatment is nominally achieved (for the continuous model).
214INLET_GEOMETRY_RD: Dict[str, float] = {
215 "sharp": 0.0, "chamfered": 0.03, "conical": 0.04,
216 "rounded_light": 0.05, "rounded": 0.125, "bellmouth": 0.20,
217}
218
219
220def cd_from_inlet_radius_ratio(r_over_d: float) -> float:
221 """Cd at Re > 1e4 and L/d ~ 2-5 as a continuous function of inlet rounding r/d.
222
223 Saturating fit through the practitioner anchors for a SHORT TUBE: 0.80 sharp entry
224 (r/d = 0), ~0.88 at r/d = 0.1-0.125, 0.95 at r/d >= 0.2. Rounding past r/d ~ 0.2 buys
225 almost nothing, which is why bellmouth entries are specified at that ratio, not deeper.
226 For the thin-plate limit multiply by cd_length_factor(L/d), which recovers 0.61 at L/d 0.
227 """
228 x = max(0.0, float(r_over_d))
229 # k fitted so r/d = 0.10 lands on the published 0.88 ("short tube with rounded
230 # entrance"), with the asymptote near 0.95-0.96 reached by r/d ~ 0.25-0.3.
231 cd_sharp, cd_max, k = 0.80, 0.96, 7.622
232 return float(cd_sharp + (cd_max - cd_sharp) * (1.0 - np.exp(-k * x)))
233
234
235#: Lichtarowicz, Duggins & Markland (1965), ultimate (high-Re) Cd of a sharp-inlet long
236#: orifice, valid 2 <= L/d <= 10: Cd_u = A - B L/d.
237LICHTAROWICZ_A = 0.827
238LICHTAROWICZ_B = 0.0085
239#: L/d at which that fit equals the inlet table's short-tube value (0.80 sharp), so the table
240#: stays the anchor and the fit supplies the slope.
241LICHTAROWICZ_REF_LD = (LICHTAROWICZ_A - 0.80) / LICHTAROWICZ_B
242#: Longest L/d in the fit's data.
243LICHTAROWICZ_LD_MAX = 10.0
244#: Sharp-edged entrance from a large plenum into the counterbore (Idelchik, Handbook of
245#: Hydraulic Resistance, diagram 3-1, thin-walled flush inlet: 0.5).
246COUNTERBORE_ENTRANCE_K = 0.5
247
248
249def cd_length_factor(l_over_d: float, model: str = "lichtarowicz") -> float:
250 """Multiplier on Cd for orifice length.
251
252 ``lichtarowicz`` (default): the published sharp-inlet fit Cd_u = 0.827 - 0.0085 L/d over
253 2 <= L/d <= 10, divided by its value at LICHTAROWICZ_REF_LD so the inlet table stays the
254 anchor. Past 10 (outside the data) the same slope continues, floored at 0.85, and the
255 extrapolation is recorded. Below 2 it blends linearly to the thin-plate anchor at L/d 0.
256
257 ``piecewise`` (legacy, unsourced): 1.0 over L/d = 2-5, a steep rise from the thin-plate end
258 below 2 and a 1.2 %/L/d decline above 5.
259
260 Lichtarowicz et al. (1965): steep rise from L/d = 0, maximum near L/d ~ 2 where the
261 expansion downstream of the vena contracta recovers dynamic pressure, then a slow decline
262 from wall friction. Below L/d ~ 1 the orifice behaves as a thin plate and loses that
263 recovery; above ~10 friction dominates.
264 """
265 x = float(l_over_d)
266 if not np.isfinite(x) or x <= 0.0:
267 return 1.0
268 if model == "lichtarowicz":
269 ref = LICHTAROWICZ_A - LICHTAROWICZ_B * LICHTAROWICZ_REF_LD
270 at2 = (LICHTAROWICZ_A - LICHTAROWICZ_B * 2.0) / ref
271 if x < 2.0:
272 return float(0.7625 + (at2 - 0.7625) * x / 2.0)
273 if x > LICHTAROWICZ_LD_MAX:
274 from engine.pipeline.assumptions import assume
275 assume("discharge.orifice_l_over_d_past_fit", x,
276 reason="Lichtarowicz (1965) fit covers 2 <= L/d <= 10; extrapolated at its slope")
277 return float(max(0.85, (LICHTAROWICZ_A - LICHTAROWICZ_B * x) / ref))
278 if x < 2.0: # thin-plate end: lose the reattachment recovery
279 # 0.7625 at L/d -> 0 so that sharp (0.80) * 0.7625 = 0.61, the thin-plate anchor.
280 return float(0.7625 + 0.11875 * x) # 0.7625 at L/d->0, 1.00 at L/d=2
281 if x <= 5.0:
282 return 1.0
283 return float(max(0.85, 1.0 - 0.012 * (x - 5.0))) # friction roll-off
284
285
286def cd_with_approach(cd: float, beta: Optional[float], k_entrance: float = COUNTERBORE_ENTRANCE_K) -> float:
287 """Cd of an orifice fed through a counterbore of diameter d / beta, referred to the
288 plenum-to-chamber drop.
289
290 Energy from the plenum: the counterbore entrance costs (1 + K) of the counterbore's
291 velocity head, and the orifice, with its static tap in the counterbore, discharges
292 Cd A sqrt(2 rho dp / (1 - beta^4)). Adding the two drops:
293
294 dp_total = rho v^2 / 2 * [ (1 - beta^4) / Cd^2 + beta^4 (1 + K) ]
295
296 Wall friction in the counterbore (f L/D ~ 0.05) is neglected: it adds under 0.2 % of the
297 already-small beta^4 term.
298 """
299 if beta is None or not np.isfinite(beta) or beta <= 0.0 or cd <= 0.0:
300 return float(cd)
301 b4 = float(beta) ** 4
302 return float(1.0 / math.sqrt((1.0 - b4) / cd ** 2 + b4 * (1.0 + k_entrance)))
303
304
305def cd_inf_from_inlet_geometry(config) -> Optional[float]:
306 """Asymptotic Cd from the orifice's INLET treatment and L/d, or None if not configured.
307
308 Returns None when neither ``inlet_geometry`` nor ``inlet_radius_ratio`` is set, so the
309 caller keeps its existing diameter-based behaviour and nothing changes for old configs.
310 This is the orifice's own ultimate Cd (cd_u_from_inlet_geometry) seen through the
311 counterbore approach, capped at 0.98.
312 """
313 cd = cd_u_from_inlet_geometry(config)
314 if cd is None:
315 return None
316 cd = cd_with_approach(cd, getattr(config, "approach_beta", None))
317 return float(min(cd, 0.98))
318
319
320def cd_u_from_inlet_geometry(config) -> Optional[float]:
321 """The ORIFICE's high-Re Cd, inlet table x length factor, before any counterbore approach.
322
323 This is Cd_u of Lichtarowicz et al. (1965) as anchored here (sharp 0.80 at
324 LICHTAROWICZ_REF_LD). None when the config declares no inlet.
325 """
326 name = getattr(config, "inlet_geometry", None)
327 rd = getattr(config, "inlet_radius_ratio", None)
328 if name is None and rd is None:
329 return None
330 if rd is not None and np.isfinite(float(rd)):
331 cd = cd_from_inlet_radius_ratio(float(rd))
332 else:
333 key = str(name).strip().lower()
334 if key not in INLET_GEOMETRY_CD:
335 raise ValueError(
336 f"Unknown inlet_geometry {name!r}. Valid: {', '.join(sorted(INLET_GEOMETRY_CD))}, "
337 f"or give inlet_radius_ratio (r/d) for a continuous value."
338 )
339 cd = INLET_GEOMETRY_CD[key]
340 lod = getattr(config, "orifice_l_over_d", None)
341 if lod is not None and np.isfinite(float(lod)):
342 cd *= cd_length_factor(float(lod), getattr(config, "length_model", "lichtarowicz"))
343 return float(cd)
344
345
346#: Lichtarowicz, Duggins & Markland (1965), J. Mech. Eng. Sci. 7(2):210-219, eq. for a
347#: sharp-inlet long orifice (2 <= L/d <= 10), non-cavitating:
348#: 1/Cd = 1/Cd_u + A (1 + B L/d)/Re - C (L/d) / (1 + D [log10(E Re)]^2)
349LICHTAROWICZ_RE_A = 20.0
350LICHTAROWICZ_RE_B = 2.25
351LICHTAROWICZ_RE_C = 0.0015
352LICHTAROWICZ_RE_D = 7.5
353LICHTAROWICZ_RE_E = 0.00015
354
355
356def cd_lichtarowicz_re(cd_u: float, Re: float, l_over_d: float) -> float:
357 """Lichtarowicz et al. (1965) Cd at Reynolds number ``Re`` (bulk velocity mdot/(rho A), hole
358 diameter) for an orifice whose ultimate (high-Re) Cd is ``cd_u`` and length is ``l_over_d``.
359
360 Mirrored by ``engine.accel.kernels._cd_lichtarowicz_re``; keep the operation order identical.
361 """
362 x = float(l_over_d)
363 lg = math.log10(LICHTAROWICZ_RE_E * Re)
364 inv = (1.0 / cd_u
365 + LICHTAROWICZ_RE_A * (1.0 + LICHTAROWICZ_RE_B * x) / Re
366 - LICHTAROWICZ_RE_C * x / (1.0 + LICHTAROWICZ_RE_D * lg * lg))
367 return float(1.0 / inv)
368
369
370def lichtarowicz_re_inputs(config) -> Optional[tuple]:
371 """``(Cd_u, L/d, approach_beta)`` when cd_from_re uses the Lichtarowicz Re law, else None.
372
373 It applies when the block declares an inlet (so Cd_u exists), an L/d, and
374 ``length_model: lichtarowicz`` (the default). Otherwise cd_from_re keeps the legacy a_Re form.
375 """
376 if getattr(config, "length_model", "lichtarowicz") != "lichtarowicz":
377 return None
378 lod = getattr(config, "orifice_l_over_d", None)
379 if lod is None or not np.isfinite(float(lod)) or float(lod) <= 0.0:
380 return None
381 cd_u = cd_u_from_inlet_geometry(config)
382 if cd_u is None:
383 return None
384 return float(cd_u), float(lod), getattr(config, "approach_beta", None)
385
386
387# =====================================================================================
388# CAVITATION / HYDRAULIC FLIP (reporting only -- nothing here changes a flow)
389#
390# Nurick (1976), "Orifice Cavitation and Its Effect on Spray Mixing": once the static
391# pressure at the vena contracta reaches the vapour pressure, flow through a sharp orifice
392# stops depending on the downstream pressure and follows Cd = Cc * sqrt(K), with the
393# cavitation number K = (P_in - P_v) / (P_in - P_c) and Cc the contraction coefficient.
394# The orifice therefore cavitates once Cc sqrt(K) falls below its non-cavitating Cd, i.e.
395# below K_crit = (Cd / Cc)^2. A cavitating short orifice can go on to hydraulic flip -- the
396# jet detaches from the bore, Cd drops toward Cc, and the doublet's momentum ratio is gone.
397# Nurick's inlet-rounding fit for the contraction: Cc = (1/Cc0^2 - 11.4 r/d)^-1/2, Cc0 = 0.62,
398# for r/d up to ~0.14.
399# =====================================================================================
400
401NURICK_CC0 = 0.62
402NURICK_RD_GAIN = 11.4
403
404
405def contraction_coefficient(r_over_d: float) -> float:
406 """Vena-contracta contraction coefficient for inlet rounding r/d (Nurick 1976)."""
407 rd = max(0.0, float(r_over_d)) if np.isfinite(r_over_d) else 0.0
408 inv2 = 1.0 / NURICK_CC0 ** 2 - NURICK_RD_GAIN * rd
409 return float(min(0.98, 1.0 / math.sqrt(inv2))) if inv2 > 1.0 / 0.98 ** 2 else 0.98
410
411
412def cavitation_margin(*, P_in: float, Pc: float, Pv: float, Cd: float, r_over_d: float = 0.0) -> Dict[str, float]:
413 """K, K_crit = (Cd/Cc)^2 and their ratio for one orifice. Ratio < 1 means it cavitates."""
414 Cc = contraction_coefficient(r_over_d)
415 dp = float(P_in) - float(Pc)
416 if not (np.isfinite(dp) and dp > 0 and np.isfinite(Cd) and Cd > 0):
417 return {"K": float("nan"), "K_crit": float("nan"), "margin": float("nan"), "Cc": Cc, "Pv": float(Pv)}
418 K = (float(P_in) - float(Pv)) / dp
419 K_crit = (float(Cd) / Cc) ** 2
420 return {"K": K, "K_crit": K_crit, "margin": K / K_crit, "Cc": Cc, "Pv": float(Pv)}
421
422
423def inlet_radius_ratio_of(config) -> float:
424 """r/d a discharge block describes: inlet_radius_ratio, else the named inlet's, else 0 (sharp)."""
425 rd = getattr(config, "inlet_radius_ratio", None)
426 if rd is not None and np.isfinite(float(rd)):
427 return float(rd)
428 name = getattr(config, "inlet_geometry", None)
429 return float(INLET_GEOMETRY_RD.get(str(name).strip().lower(), 0.0)) if name else 0.0
#define min(a, b)
Definition Arduino.h:42
#define max(a, b)
Definition Arduino.h:43
float cd_from_inlet_radius_ratio(float r_over_d)
Definition discharge.py:220
Optional[float] cd_u_from_inlet_geometry(config)
Definition discharge.py:320
float contraction_coefficient(float r_over_d)
Definition discharge.py:405
Optional[tuple] lichtarowicz_re_inputs(config)
Definition discharge.py:370
float inlet_radius_ratio_of(config)
Definition discharge.py:423
float cd_with_approach(float cd, Optional[float] beta, float k_entrance=COUNTERBORE_ENTRANCE_K)
Definition discharge.py:286
float cd_length_factor(float l_over_d, str model="lichtarowicz")
Definition discharge.py:249
float cd_from_re(float Re, DischargeConfig config, float P_inlet=None, float T_inlet=None, Optional[float] d_hyd_m=None)
Definition discharge.py:91
float cd_inf_from_orifice_diameter(Optional[float] d_hyd_m, DischargeConfig config)
Definition discharge.py:21
float calculate_reynolds_number(float rho, float u, float d_hyd, float mu)
Definition discharge.py:150
float cd_lichtarowicz_re(float cd_u, float Re, float l_over_d)
Definition discharge.py:356
Dict[str, float] cavitation_margin(*, float P_in, float Pc, float Pv, float Cd, float r_over_d=0.0)
Definition discharge.py:412
float discharge_cd_inf_ratio(float d_hyd_O, float d_hyd_F, DischargeConfig discharge_O, DischargeConfig discharge_F)
Definition discharge.py:76
Optional[float] cd_inf_from_inlet_geometry(config)
Definition discharge.py:305