use crate::constants::{BIG_VALUE, MperFT, PSIperFT, RQ_TOL, SMALL_VALUE};
use crate::model::options::SimulationOptions;
use crate::model::units::{Cfs, UnitConversion, UnitSystem};
use crate::model::demand::Demand;
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Junction {
pub emitter_coefficient: f64,
pub demands: Vec<Demand>,
}
impl Junction {
pub fn demand_coefficients(
&self,
demand: Cfs,
demand_full: Cfs,
dp: f64,
n: f64,
) -> (f64, f64) {
let factor = demand / demand_full;
if factor <= 0.0 {
(1.0 / BIG_VALUE, BIG_VALUE * demand)
} else if factor < 1.0 {
let hgrad = n * dp * factor.powf(n - 1.0) / demand_full;
if hgrad < RQ_TOL {
return (1.0 / RQ_TOL, demand * RQ_TOL);
}
let y = hgrad * demand / n;
(1.0 / hgrad, y)
} else {
(1.0 / BIG_VALUE, dp + BIG_VALUE * (demand - demand_full))
}
}
pub fn emitter_coefficients(&self, q: Cfs, q_exp: f64) -> (f64, f64) {
let ke = self.emitter_coefficient.max(SMALL_VALUE);
let hgrad = q_exp * ke * q.abs().powf(q_exp - 1.0);
if hgrad < RQ_TOL {
let hgrad = RQ_TOL;
return (1.0 / hgrad, q * hgrad);
}
let y = hgrad * q / q_exp;
(1.0 / hgrad, y)
}
}
impl UnitConversion for Junction {
fn convert_to_standard(&mut self, options: &SimulationOptions) {
for demand in self.demands.iter_mut() {
demand.convert_to_standard(options);
}
if self.emitter_coefficient > 0.0 {
let pressure_factor = if options.unit_system == UnitSystem::US {
PSIperFT
} else {
MperFT
};
let conversion_factor =
options.flow_units.per_cfs().powf(options.emitter_exponent) / pressure_factor;
self.emitter_coefficient =
conversion_factor / self.emitter_coefficient.powf(options.emitter_exponent);
}
}
fn convert_from_standard(&mut self, options: &SimulationOptions) {
for demand in self.demands.iter_mut() {
demand.convert_from_standard(options);
}
if self.emitter_coefficient > 0.0 {
let pressure_factor = if options.unit_system == UnitSystem::US {
PSIperFT
} else {
MperFT
};
let conversion_factor =
options.flow_units.per_cfs().powf(options.emitter_exponent) / pressure_factor;
self.emitter_coefficient =
(conversion_factor / self.emitter_coefficient).powf(1.0 / options.emitter_exponent);
}
}
}