use crate::numerical::BVP_Damp::BVP_traits::{MatrixType, VectorType};
use nalgebra::DMatrix;
use crate::numerical::BVP_Damp::NR_Damp_solver_damped::SolverParams;
use std::collections::HashMap;
pub fn bound_step_Cantera(
y: &dyn VectorType,
y_new: &dyn VectorType,
bounds: &Vec<(f64, f64)>,
) -> f64 {
let mut fbound = 1.0;
for (i, y_i) in y.iterate().enumerate() {
let below = bounds[i].0;
let above = bounds[i].1;
let y_new_i = y_new.get_val(i);
if y_i < below {
fbound = ((y_i - below) / (y_i - y_new_i)).min(fbound);
}
if y_i > above {
fbound = (((above - y_i) / (y_new_i - y_i)).min(fbound)).max(0.0);
}
}
fbound
}
pub fn bound_step_Cantera2(
x: &dyn VectorType,
step: &dyn VectorType,
bounds: &Vec<(f64, f64)>,
) -> f64 {
assert_eq!(x.len(), bounds.len());
let mut fbound: f64 = 1.0;
for (i, val) in x.iterate().enumerate() {
let below = bounds[i].0;
let above = bounds[i].1;
let step_i = step.get_val(i);
let newval = val + step_i;
if newval > above {
fbound = fbound.min((above - val) / (newval - val)).max(0.0);
} else if newval < below {
fbound = fbound.min((val - below) / (val - newval));
}
}
fbound
}
pub fn bound_step(y: &dyn VectorType, step: &dyn VectorType, bounds: &Vec<(f64, f64)>) -> f64 {
let mut fbound = 1.0;
let mut _entry = 0;
let mut _force = false;
let mut _value = 0.0;
let s0 = step;
for (i, y_i) in y.iterate().enumerate() {
let below = bounds[i].0;
let above = bounds[i].1;
let s_i = s0.get_val(i);
if s_i > f64::max(y_i - below, 0.0) {
let temp = (y_i - below) / s_i;
if temp < fbound {
fbound = temp;
_entry = i + 1; _force = true;
_value = below;
}
} else if s_i < f64::min(y_i - above, 0.0) {
let temp = (y_i - above) / s_i;
if temp < fbound {
fbound = temp;
_entry = i + 1; _force = true;
_value = above;
}
}
}
fbound
}
pub fn jac_recalc(
strategy_params: &Option<SolverParams>,
m: usize,
old_jac: &Option<Box<dyn MatrixType>>,
old_recalc_flag: &mut bool,
) -> bool {
let m_from_task = strategy_params
.as_ref()
.and_then(|p| p.max_jac)
.unwrap_or(3);
if old_jac.is_none() || m > m_from_task {
log::info!(
"\n number of iterations with old jac {} is higher then threshold {}",
m,
m_from_task
);
true
} else {
*old_recalc_flag
}
}
pub fn convergence_condition(
y: &dyn VectorType,
abs_tolerance: &f64,
rel_tolerance_vec: &Vec<f64>,
) -> f64 {
let mut sum = 0.0;
for (i, y_i) in y.iterate().enumerate() {
sum += (y_i).abs() * rel_tolerance_vec[i];
}
let conv = sum.max(*abs_tolerance);
conv
}
pub fn weighted_norm(
x: &dyn VectorType,
step: &dyn VectorType,
rel_tolerance_vec: &Vec<f64>,
abs_tolerance: f64,
n_components: usize,
n_points: usize,
) -> f64 {
let mut sum = 0.0;
for n in 0..n_components {
let mut esum = 0.0;
for j in 0..n_points {
let idx = j * n_components + n;
esum += x.get_val(idx).abs();
}
let ewt = rel_tolerance_vec[n] * esum / (n_points as f64) + abs_tolerance;
for j in 0..n_points {
let idx = j * n_components + n;
let f = step.get_val(idx) / ewt;
sum += f * f;
}
}
sum /= (n_components * n_points) as f64;
sum.sqrt()
}
pub fn if_initial_guess_inside_bounds(
initial_guess: &DMatrix<f64>,
Bounds: &Option<HashMap<String, (f64, f64)>>,
values: Vec<String>,
) -> () {
for (i, row) in initial_guess.row_iter().enumerate() {
let var_name = values[i].clone();
let bounds = Bounds.as_ref().unwrap().get(&var_name).unwrap();
let (lower, upper) = bounds;
if row.iter().any(|&x| x < *lower || x > *upper) {
panic!(
"\n, \n, Initial guess of the variable {} is outside the bounds {:?}.",
var_name, &bounds
);
}
}
}