sim_lib_femm_function/
implementation.rs1#![forbid(unsafe_code)]
2use sim_kernel::{Cx, Symbol};
5use sim_lib_femm_core::FemmResult;
6use sim_lib_femm_post::{QuantitySpec, quantity};
7use sim_lib_femm_query::{ModelCallable, resolve_excitation};
8use sim_lib_femm_sensitiv::total_gradient;
9use sim_lib_femm_solve::{GradientTrust, SolveCertificate, SteadySolve};
10
11#[derive(Clone, Debug)]
13pub struct QualityAnswer {
14 pub value: f64,
16 pub certificate: SolveCertificate,
18 pub gradient: Option<(Vec<f64>, GradientTrust)>,
20}
21
22pub fn quality(
28 cx: &mut Cx,
29 solve: &SteadySolve,
30 quantity_spec: &QuantitySpec,
31 wrt: Option<&[Symbol]>,
32) -> FemmResult<QualityAnswer> {
33 let excitation = resolve_excitation(cx, &solve.model, &solve.solution.params, quantity_spec)?;
34 let value = quantity(&solve.solution, quantity_spec, &excitation)?;
35 let mut certificate = solve.certificate.clone();
36 let gradient = match wrt {
37 None => None,
38 Some(params) => {
39 let callable = ModelCallable {
40 model: solve.model.clone(),
41 };
42 let mut solve_for_gradient = SteadySolve {
43 model: solve.model.clone(),
44 solution: solve.solution.clone(),
45 factor: solve.factor.clone(),
46 certificate: solve.certificate.clone(),
47 };
48 let result = total_gradient(
49 cx,
50 &callable,
51 &mut solve_for_gradient,
52 std::slice::from_ref(quantity_spec),
53 params,
54 )?;
55 let values = result.gradient.into_iter().next().unwrap_or_default();
56 let trust = result
57 .trust
58 .into_iter()
59 .next()
60 .unwrap_or(GradientTrust::FiniteDifferenceOnly);
61 certificate.set_gradient_trust(trust.clone());
62 Some((values, trust))
63 }
64 };
65 Ok(QualityAnswer {
66 value,
67 certificate,
68 gradient,
69 })
70}