///|
pub(all) struct ReactorStage {
kind : ReactorKind
volume : Double
thermal_mode : ThermalMode
exchange : HeatExchange?
} derive(Debug, ToJson)
///|
pub(all) struct NetworkResult {
stages : Array[DesignPoint]
final_conversion : Double
final_concentration : Double
final_temperature : Double
total_volume : Double
} derive(Debug, ToJson)
///|
pub fn ReactorStage::cstr(
volume~ : Double,
thermal_mode? : ThermalMode = Isothermal,
exchange? : HeatExchange,
) -> ReactorStage {
{ kind: Cstr, volume, thermal_mode, exchange }
}
///|
pub fn ReactorStage::pfr(
volume~ : Double,
thermal_mode? : ThermalMode = Isothermal,
exchange? : HeatExchange,
) -> ReactorStage {
{ kind: Pfr, volume, thermal_mode, exchange }
}
///|
pub fn ReactorStage::batch(
time~ : Double,
thermal_mode? : ThermalMode = Isothermal,
exchange? : HeatExchange,
) -> ReactorStage {
{ kind: Batch, volume: time, thermal_mode, exchange }
}
///|
pub fn run_network(
reaction : Reaction,
feed : Feed,
stages : ArrayView[ReactorStage],
) -> NetworkResult {
let results : Array[DesignPoint] = []
let final_feed = for i = 0, current = feed, total_x = 0.0
i < stages.length()
i = i + 1 {
let stage = stages[i]
let point = run_stage(reaction, current, stage)
results.push({
..point,
conversion: combine_conversion(total_x, point.conversion),
})
continue i + 1,
{
concentration: point.outlet_concentration,
volumetric_flow: current.volumetric_flow,
temperature: point.outlet_temperature,
heat_capacity_flow: current.heat_capacity_flow,
},
combine_conversion(total_x, point.conversion)
} nobreak {
current
}
let total_volume = for i = 0, acc = 0.0; i < stages.length(); i = i + 1 {
continue i + 1, acc + stages[i].volume
} nobreak {
acc
}
{
stages: results,
final_conversion: if feed.concentration <= 0.0 {
0.0
} else {
clamp_conversion(1.0 - final_feed.concentration / feed.concentration)
},
final_concentration: final_feed.concentration,
final_temperature: final_feed.temperature,
total_volume,
}
}
///|
fn run_stage(
reaction : Reaction,
feed : Feed,
stage : ReactorStage,
) -> DesignPoint {
match stage.kind {
Cstr =>
match stage.exchange {
Some(hx) =>
design_cstr(
reaction,
feed,
stage.volume,
thermal_mode=stage.thermal_mode,
exchange=hx,
)
None =>
design_cstr(
reaction,
feed,
stage.volume,
thermal_mode=stage.thermal_mode,
)
}
Pfr =>
match stage.exchange {
Some(hx) =>
design_pfr(
reaction,
feed,
stage.volume,
thermal_mode=stage.thermal_mode,
exchange=hx,
)
None =>
design_pfr(
reaction,
feed,
stage.volume,
thermal_mode=stage.thermal_mode,
)
}
Batch =>
match stage.exchange {
Some(hx) =>
design_batch(
reaction,
feed,
stage.volume,
thermal_mode=stage.thermal_mode,
exchange=hx,
)
None =>
design_batch(
reaction,
feed,
stage.volume,
thermal_mode=stage.thermal_mode,
)
}
}
}
///|
fn combine_conversion(previous : Double, stage_conversion : Double) -> Double {
clamp_conversion(1.0 - (1.0 - previous) * (1.0 - stage_conversion))
}
///|
pub fn equal_volume_cstr_train(
stages : Int,
total_volume : Double,
thermal_mode? : ThermalMode = Isothermal,
) -> Array[ReactorStage] {
let n = stages.max(1)
let volume = total_volume / Double::from_int(n)
let out : Array[ReactorStage] = []
for _ in 0.. Array[ReactorStage] {
let n = stages.max(1)
let volume = total_volume / Double::from_int(n)
let out : Array[ReactorStage] = []
for _ in 0..