Skip to main content

pmcore/model/
mod.rs

1use anyhow::Result;
2use pharmsol::equation::Equation;
3use pharmsol::{Analytical, ValidatedModelMetadata, ODE, SDE};
4
5pub mod metadata;
6pub mod parameter_space;
7
8pub use metadata::ModelMetadata;
9pub use parameter_space::{
10    BoundedParameter, Parameter, ParameterMeta, ParameterScale, ParameterSpace, UnboundedParameter,
11};
12
13#[derive(Debug, Clone)]
14pub struct Model<E: Equation> {
15    pub equation: E,
16}
17
18impl<E: Equation> Model<E> {
19    pub fn builder(equation: E) -> ModelBuilder<E> {
20        ModelBuilder { equation }
21    }
22}
23
24impl<E: EquationMetadataSource> Model<E> {
25    pub fn parameter_count(&self) -> usize {
26        self.equation
27            .equation_metadata()
28            .map_or(0, |metadata| metadata.parameters().len())
29    }
30
31    pub fn parameter_name(&self, index: usize) -> Option<&str> {
32        self.equation
33            .equation_metadata()
34            .and_then(|metadata| metadata.parameters().get(index))
35            .map(|parameter| parameter.name())
36    }
37
38    pub fn parameter_index(&self, name: &str) -> Option<usize> {
39        self.equation
40            .equation_metadata()
41            .and_then(|metadata| metadata.parameter_index(name))
42    }
43
44    pub fn output_count(&self) -> usize {
45        self.equation
46            .equation_metadata()
47            .map_or(0, |metadata| metadata.outputs().len())
48    }
49
50    pub fn output_name(&self, outeq: usize) -> Option<&str> {
51        self.equation
52            .equation_metadata()
53            .and_then(|metadata| metadata.outputs().get(outeq))
54            .map(|output| output.name())
55    }
56
57    pub fn output_index(&self, name: &str) -> Option<usize> {
58        self.equation.equation_metadata().and_then(|metadata| {
59            metadata
60                .outputs()
61                .iter()
62                .position(|output| output.name() == name)
63        })
64    }
65}
66
67pub struct ModelBuilder<E: Equation> {
68    equation: E,
69}
70
71impl<E: Equation> ModelBuilder<E> {
72    pub fn build(self) -> Result<Model<E>> {
73        Ok(Model {
74            equation: self.equation,
75        })
76    }
77}
78
79impl<E: EquationMetadataSource> ModelBuilder<E> {
80    pub(crate) fn parameter_index(&self, name: &str) -> Option<usize> {
81        self.equation
82            .equation_metadata()
83            .and_then(|metadata| metadata.parameter_index(name))
84    }
85
86    pub(crate) fn parameter_names(&self) -> Vec<String> {
87        self.equation
88            .equation_metadata()
89            .map(|metadata| {
90                metadata
91                    .parameters()
92                    .iter()
93                    .map(|parameter| parameter.name().to_string())
94                    .collect()
95            })
96            .unwrap_or_default()
97    }
98
99    pub(crate) fn output_names(&self) -> Vec<String> {
100        self.equation
101            .equation_metadata()
102            .map(|metadata| {
103                metadata
104                    .outputs()
105                    .iter()
106                    .map(|output| output.name().to_string())
107                    .collect()
108            })
109            .unwrap_or_default()
110    }
111
112    pub(crate) fn output_index(&self, name: &str) -> Option<usize> {
113        self.equation.equation_metadata().and_then(|metadata| {
114            metadata
115                .outputs()
116                .iter()
117                .position(|output| output.name() == name)
118        })
119    }
120}
121
122pub trait EquationMetadataSource: Equation {
123    fn equation_metadata(&self) -> Option<&ValidatedModelMetadata>;
124}
125
126// Macro for standard pharmsol equations
127macro_rules! impl_metadata_opt {
128    ($($t:ty),+) => {
129        $(impl EquationMetadataSource for $t {
130            fn equation_metadata(&self) -> Option<&ValidatedModelMetadata> {
131                self.metadata()
132            }
133        })+
134    };
135}
136impl_metadata_opt!(ODE, Analytical, SDE);
137
138// Macro for runtime/JIT models
139macro_rules! impl_metadata_some {
140    ($($t:ty),+) => {
141        $(
142            #[cfg(any(
143                feature = "dsl-jit",
144                all(feature = "dsl-aot", feature = "dsl-aot-load"),
145                all(feature = "dsl-wasm", not(all(target_arch = "wasm32", target_os = "unknown")))
146            ))]
147            impl EquationMetadataSource for $t {
148                fn equation_metadata(&self) -> Option<&ValidatedModelMetadata> {
149                    Some(self.metadata())
150                }
151            }
152        )+
153    };
154}
155impl_metadata_some!(
156    pharmsol::dsl::RuntimeOdeModel,
157    pharmsol::dsl::RuntimeAnalyticalModel,
158    pharmsol::dsl::RuntimeSdeModel
159);