HeatTransPlan / frontend /src /utils /streamInfo.ts
drzg15's picture
Initial code commit with LFS for binaries
c993983
/**
* Extract stream info (Tin, Tout, mdot, cp, CP, Q) from a stream object,
* checking multiple fallback sources in the same order as the original
* Streamlit app:
* 1. stream_values / product_values dict
* 2. properties/values mapping (prop1→val1 …)
* 3. top-level temp_in / temp_out / mdot / cp
*/
export interface StreamInfo {
tin: number | null;
tout: number | null;
mdot: number | null;
cp: number | null;
CP: number | null;
Q: number | null;
type: 'hot' | 'cold' | null;
density: string | null;
pressure: string | null;
water_in: string | null;
water_out: string | null;
}
function tryFloat(v: unknown): number | null {
if (v == null || v === '') return null;
const n = Number(v);
return isNaN(n) ? null : n;
}
export function extractStreamInfo(stream: Record<string, any>): StreamInfo {
const sv: Record<string, any> =
stream.stream_values || stream.product_values || {};
const properties: Record<string, string> = stream.properties || {};
const values: Record<string, string> = stream.values || {};
let tin: number | null = null;
let tout: number | null = null;
let mdot: number | null = null;
let cpVal: number | null = null;
let cpDirect: number | null = null;
// 1. stream_values
if (sv.Tin != null) tin = tryFloat(sv.Tin);
if (sv.Tout != null) tout = tryFloat(sv.Tout);
if (sv['ṁ'] != null) mdot = tryFloat(sv['ṁ']);
if (sv.cp != null) cpVal = tryFloat(sv.cp);
if (sv.CP != null) cpDirect = tryFloat(sv.CP);
// 2. properties / values mapping (prop1→val1, prop2→val2 …)
for (const [pk, pname] of Object.entries(properties)) {
const vk = pk.replace('prop', 'val');
const v = values[vk];
if (!v) continue;
if (pname === 'Tin' && tin == null) tin = tryFloat(v);
else if (pname === 'Tout' && tout == null) tout = tryFloat(v);
else if (pname === 'ṁ' && mdot == null) mdot = tryFloat(v);
else if (pname === 'cp' && cpVal == null) cpVal = tryFloat(v);
else if (pname === 'CP' && cpDirect == null) cpDirect = tryFloat(v);
}
// 3. top-level fallback
if (tin == null) tin = tryFloat(stream.temp_in);
if (tout == null) tout = tryFloat(stream.temp_out);
if (mdot == null) mdot = tryFloat(stream.mdot);
if (cpVal == null) cpVal = tryFloat(stream.cp);
const density = sv.Density || null;
const pressure = sv.Pressure || null;
const water_in = sv['Water Content In'] || null;
const water_out = sv['Water Content Out'] || null;
// Compute CP (heat capacity flow rate)
let CP: number | null =
cpDirect ?? (mdot != null && cpVal != null ? mdot * cpVal : null);
// Compute Q
const Q =
CP != null && tin != null && tout != null
? Math.abs(CP * (tout - tin))
: null;
// Stream type
const type: 'hot' | 'cold' | null =
tin != null && tout != null ? (tin > tout ? 'hot' : 'cold') : null;
return { tin, tout, mdot, cp: cpVal, CP, Q, type, density, pressure, water_in, water_out };
}