use crate::equilibrium::{EquilibriumModel, FdmError};
use crate::iterative::IterativeConfig;
use crate::network::Network;
use crate::state::EquilibriumState;
use crate::structure::Structure;
#[derive(Clone, Debug)]
pub struct FdmOptions {
pub sparse: bool,
pub iterative: IterativeConfig,
}
impl Default for FdmOptions {
fn default() -> Self {
Self {
sparse: false,
iterative: IterativeConfig::linear(),
}
}
}
impl FdmOptions {
pub fn nonlinear(tmax: u32, eta: f64, sparse: bool) -> Self {
Self {
sparse,
iterative: IterativeConfig {
tmax,
eta,
use_sparse: sparse,
..IterativeConfig::default()
},
}
}
}
pub fn fdm(network: &Network) -> Result<EquilibriumState, FdmError> {
fdm_with_options(network, &FdmOptions::default())
}
pub fn fdm_with_options(
network: &Network,
options: &FdmOptions,
) -> Result<EquilibriumState, FdmError> {
network.validate().map_err(FdmError::Validation)?;
let structure = Structure::from_network(network);
fdm_with_structure(network, &structure, options)
}
pub fn fdm_with_structure(
network: &Network,
structure: &Structure,
options: &FdmOptions,
) -> Result<EquilibriumState, FdmError> {
let load_state = network.load_state();
let mut iterative = options.iterative.clone();
iterative.use_sparse = options.sparse;
let mesh = network.mesh_structure();
EquilibriumModel::equilibrium_with_config(
&network.q,
&network.xyz,
&load_state,
structure,
&network.edges,
&iterative,
mesh.as_ref(),
)
}
pub fn apply_equilibrium(network: &mut Network, state: &EquilibriumState) {
network.xyz.clone_from(&state.xyz);
}