14) -> Tuple[float, float, List[str]]:
15 """Compute A_eff_O, A_eff_F from closure diagnostics Cd_O/Cd_F.
17 If Cd is missing, non-finite, or <= 0 for a stream, fall back to geometric area
18 for that stream and record a warning tag (caller may attach to diagnostics).
23 Injector / closure diagnostics dict containing optional ``Cd_O``, ``Cd_F``.
25 Geometric flow areas [m²] (sum of orifice areas per stream).
29 A_eff_O, A_eff_F, warnings
30 Effective areas [m²] and a list of warning tokens, e.g.
31 ``Cd_O_fallback_geometric``.
33 warnings: List[str] = []
34 ag_o = float(A_geom_O)
35 ag_f = float(A_geom_F)
37 if not isinstance(diagnostics, dict):
38 warnings.append(
"no_diagnostics")
39 return ag_o, ag_f, warnings
41 def _one(cd_key: str, ag: float) -> float:
42 cd = diagnostics.get(cd_key)
43 if cd
is None or not np.isfinite(cd)
or float(cd) <= 0.0:
44 warnings.append(f
"{cd_key}_fallback_geometric")
48 return _one(
"Cd_O", ag_o), _one(
"Cd_F", ag_f), warnings