use super::material::Q;
pub fn bernoulli(x: f64) -> f64 {
if x.abs() < 1e-3 {
1.0 - x / 2.0 + x * x / 12.0 - x * x * x * x / 720.0
} else {
x / (x.exp() - 1.0)
}
}
pub fn bernoulli_deriv(x: f64) -> f64 {
if x.abs() < 1e-3 {
-0.5 + x / 6.0 - x * x * x / 180.0
} else {
let ex = x.exp();
let em1 = ex - 1.0;
(em1 - x * ex) / (em1 * em1)
}
}
pub fn sg_flux_n(n_l: f64, n_r: f64, psi_l: f64, psi_r: f64, vt: f64, dn: f64, dx: f64) -> f64 {
let dpsi = (psi_r - psi_l) / vt;
-(Q * dn / dx) * (n_r * bernoulli(dpsi) - n_l * bernoulli(-dpsi))
}
pub fn sg_flux_p(p_l: f64, p_r: f64, psi_l: f64, psi_r: f64, vt: f64, dp: f64, dx: f64) -> f64 {
let dpsi = (psi_r - psi_l) / vt;
(Q * dp / dx) * (p_r * bernoulli(-dpsi) - p_l * bernoulli(dpsi))
}
pub fn sg_flux_n_derivs(
n_l: f64,
n_r: f64,
psi_l: f64,
psi_r: f64,
vt: f64,
dn: f64,
dx: f64,
) -> (f64, f64, f64, f64) {
let dpsi = (psi_r - psi_l) / vt;
let b_pos = bernoulli(dpsi);
let b_neg = bernoulli(-dpsi);
let db_pos = bernoulli_deriv(dpsi);
let db_neg = bernoulli_deriv(-dpsi);
let coeff = -Q * dn / dx;
let djn_dn_l = -coeff * b_neg;
let djn_dn_r = coeff * b_pos;
let djn_dpsi_l = coeff / vt * (-n_r * db_pos - n_l * db_neg);
let djn_dpsi_r = coeff / vt * (n_r * db_pos + n_l * db_neg);
(djn_dn_l, djn_dn_r, djn_dpsi_l, djn_dpsi_r)
}
pub fn sg_flux_p_derivs(
p_l: f64,
p_r: f64,
psi_l: f64,
psi_r: f64,
vt: f64,
dp: f64,
dx: f64,
) -> (f64, f64, f64, f64) {
let dpsi = (psi_r - psi_l) / vt;
let b_pos = bernoulli(dpsi);
let b_neg = bernoulli(-dpsi);
let db_pos = bernoulli_deriv(dpsi);
let db_neg = bernoulli_deriv(-dpsi);
let coeff = Q * dp / dx;
let djp_dp_l = coeff * (-b_pos);
let djp_dp_r = coeff * b_neg;
let djp_dpsi_l = coeff / vt * (p_r * db_neg + p_l * db_pos);
let djp_dpsi_r = -coeff / vt * (p_r * db_neg + p_l * db_pos);
(djp_dp_l, djp_dp_r, djp_dpsi_l, djp_dpsi_r)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bernoulli_at_zero_is_one() {
let b = bernoulli(0.0);
assert!((b - 1.0).abs() < 1e-12, "B(0) = {b}");
}
#[test]
fn bernoulli_symmetry() {
for x in [0.5_f64, 1.0, 2.0, 5.0, 10.0] {
let diff = bernoulli(x) - bernoulli(-x);
assert!(
(diff + x).abs() < 1e-10,
"B(x)-B(-x)+x = {} for x={x}",
diff + x
);
}
}
#[test]
fn bernoulli_taylor_matches_full_formula() {
let x = 1.5e-3_f64;
let b_exact = x / (x.exp() - 1.0);
let b_taylor = bernoulli(x); assert!((b_exact - b_taylor).abs() / b_exact < 1e-9);
}
#[test]
fn bernoulli_deriv_zero() {
let db = bernoulli_deriv(0.0);
assert!((db + 0.5).abs() < 1e-12, "B'(0) = {db}");
}
}