///|
pub fn heater(inlet : Stream, outlet_temperature : Double) -> HeaterResult {
let outlet = inlet
.with_temperature(outlet_temperature)
.with_id("\{inlet.id}-heated")
{ outlet, duty: heat_duty(inlet, outlet) }
}
///|
pub fn cooler(inlet : Stream, outlet_temperature : Double) -> HeaterResult {
let outlet = inlet
.with_temperature(outlet_temperature)
.with_id("\{inlet.id}-cooled")
{ outlet, duty: heat_duty(inlet, outlet) }
}
///|
pub fn mixer(
id~ : String,
streams : Array[Stream],
temperature : Double,
) -> Stream {
let components : Array[ComponentFlow] = []
for stream in streams {
for component in stream.components {
components.push(component)
}
}
Stream::mixture(id~, components~, temperature~)
}
///|
pub fn split(stream : Stream, first_fraction : Double) -> (Stream, Stream) {
let first_components : Array[ComponentFlow] = []
let second_components : Array[ComponentFlow] = []
for component in stream.components {
first_components.push({
substance: component.substance,
molar_flow: component.molar_flow * first_fraction,
})
second_components.push({
substance: component.substance,
molar_flow: component.molar_flow * (1.0 - first_fraction),
})
}
(
Stream::mixture(
id="\{stream.id}-split-a",
components=first_components,
temperature=stream.temperature,
),
Stream::mixture(
id="\{stream.id}-split-b",
components=second_components,
temperature=stream.temperature,
),
)
}
///|
pub fn flash_vaporize(
feed : Stream,
vapor_substance : Substance,
liquid_substance : Substance,
vapor_fraction : Double,
temperature : Double,
) -> FlashResult {
let total = feed.molar_flow()
let vapor = Stream::pure(
id="\{feed.id}-vapor",
substance=vapor_substance,
molar_flow=total * vapor_fraction,
temperature~,
)
let liquid = Stream::pure(
id="\{feed.id}-liquid",
substance=liquid_substance,
molar_flow=total * (1.0 - vapor_fraction),
temperature~,
)
{
vapor,
liquid,
duty: required_heat([feed], [vapor, liquid]),
vapor_fraction,
}
}
///|
pub fn steam_required(duty : Double, latent_heat : Double) -> Double {
if latent_heat == 0.0 {
0.0
} else {
duty.max(0.0) / latent_heat
}
}
///|
pub fn cooling_water_required(
duty : Double,
cp : Double,
delta_t : Double,
) -> Double {
if cp == 0.0 || delta_t == 0.0 {
0.0
} else {
duty.abs() / (cp * delta_t.abs())
}
}
///|
pub fn utility_estimate(
name~ : String,
duty~ : Double,
cp~ : Double,
inlet_temperature~ : Double,
outlet_temperature~ : Double,
) -> UtilityEstimate {
{
name,
duty,
required_flow: cooling_water_required(
duty,
cp,
outlet_temperature - inlet_temperature,
),
inlet_temperature,
outlet_temperature,
}
}