///|
pub struct StreamSnapshot {
id : String
temperature : Double
molar_flow : Double
enthalpy_flow : Double
heat_capacity_flow : Double
component_count : Int
} derive(Debug)
///|
pub struct StreamAggregate {
count : Int
total_molar_flow : Double
total_enthalpy_flow : Double
weighted_temperature : Double
total_heat_capacity_flow : Double
} derive(Debug)
///|
pub fn snapshot_stream(stream : Stream) -> StreamSnapshot {
{
id: stream.id,
temperature: stream.temperature,
molar_flow: stream.molar_flow(),
enthalpy_flow: stream.enthalpy_flow(),
heat_capacity_flow: stream.heat_capacity_flow(),
component_count: stream.component_count(),
}
}
///|
pub fn snapshot_streams(streams : Array[Stream]) -> Array[StreamSnapshot] {
let snapshots : Array[StreamSnapshot] = []
for stream in streams {
snapshots.push(snapshot_stream(stream))
}
snapshots
}
///|
pub fn aggregate_streams(streams : Array[Stream]) -> StreamAggregate {
let mut total_flow = 0.0
let mut total_enthalpy = 0.0
let mut weighted_temperature = 0.0
let mut heat_capacity = 0.0
for stream in streams {
let flow = stream.molar_flow().max(0.0)
total_flow += flow
total_enthalpy += stream.enthalpy_flow()
weighted_temperature += stream.temperature * flow
heat_capacity += stream.heat_capacity_flow()
}
{
count: streams.length(),
total_molar_flow: total_flow,
total_enthalpy_flow: total_enthalpy,
weighted_temperature: if total_flow <= 0.0 {
0.0
} else {
weighted_temperature / total_flow
},
total_heat_capacity_flow: heat_capacity,
}
}
///|
pub fn snapshot_csv_header() -> String {
"id,temperature,molar_flow,enthalpy_flow,heat_capacity_flow,component_count"
}
///|
pub fn snapshot_csv_row(snapshot : StreamSnapshot) -> String {
"\{snapshot.id},\{snapshot.temperature},\{snapshot.molar_flow},\{snapshot.enthalpy_flow},\{snapshot.heat_capacity_flow},\{snapshot.component_count}"
}
///|
pub fn snapshots_csv(snapshots : Array[StreamSnapshot]) -> String {
let mut output = snapshot_csv_header() + "\n"
for snapshot in snapshots {
output = output + snapshot_csv_row(snapshot) + "\n"
}
output
}
///|
pub fn snapshot_delta(
first : StreamSnapshot,
second : StreamSnapshot,
) -> StreamSnapshot {
{
id: second.id,
temperature: second.temperature - first.temperature,
molar_flow: second.molar_flow - first.molar_flow,
enthalpy_flow: second.enthalpy_flow - first.enthalpy_flow,
heat_capacity_flow: second.heat_capacity_flow - first.heat_capacity_flow,
component_count: second.component_count - first.component_count,
}
}
///|
pub fn snapshot_relative_change(first : Double, second : Double) -> Double {
if first.abs() < 1.0e-12 {
0.0
} else {
(second - first) / first.abs()
}
}
///|
pub fn process_total_heat_capacity(streams : Array[Stream]) -> Double {
let mut total = 0.0
for stream in streams {
total += stream.heat_capacity_flow()
}
total
}
///|
pub fn process_total_mass_flow(
streams : Array[Stream],
molar_mass_g_per_mol : Double,
) -> Double {
molar_flow_to_mass_flow(
aggregate_streams(streams).total_molar_flow,
molar_mass_g_per_mol,
)
}
///|
pub fn process_temperature_range(streams : Array[Stream]) -> (Double, Double) {
if streams.length() == 0 {
(0.0, 0.0)
} else {
let mut low = streams[0].temperature
let mut high = streams[0].temperature
for stream in streams {
low = low.min(stream.temperature)
high = high.max(stream.temperature)
}
(low, high)
}
}
///|
pub fn process_isothermal(streams : Array[Stream], tolerance : Double) -> Bool {
let (low, high) = process_temperature_range(streams)
(high - low).abs() <= tolerance.abs()
}