1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
#[cfg(test)] mod test; mod detail; use nalgebra::{DVector, Scalar}; /// This trait allows us to pass vector valued functions `$\vec{f}(\vec{x},\alpha_1,...\alpha_N$)` in a generic fashion, where /// /// * `$\vec{x}$` is an independent variable, like time, spatial coordinates and so on, /// * `$\alpha_j$` are scalar parameter of this function /// The functions must have at least one parameter argument additional ot the location parameter, i.e. a function /// `$f(\vec{x})$` does not satisfy the trait, but e.g. `$f(\vec{x},\alpha_1)$` does. The function /// must be vector valued and should produce a vector of the same size as `\vec{x}`. (If you want to /// add this function to a model this is actually a requirement that will lead to errors, even panics /// if violated). /// Unfortunately, requirement on the length of the output vector cannot be enforced by the type system. /// If it is violated, then calculations using the basis function will return errors in the [SeparableModel](crate::model::SeparableModel). /// /// # Variadic Functions /// Since Rust does not have variadic functions or generics, this trait is implemented for all functions up to /// a maximum number of arguments. Right now this is implemented for up to 10 arguments. /// /// # Generic Parameters /// ## Scalar Type /// The functions must have an interface `Fn(&DVector<ScalarType>,ScalarType)-> DVector<ScalarType>`, /// `Fn(&DVector<ScalarType>,ScalarType,ScalarType)-> DVector<ScalarType>` and so on. /// All numeric types, including the return value must be of the same scalar type. /// ## ArgList : The argument list /// This type is of no consequence for the user because it will be correctly inferred when /// passing a function. It is a [nifty trick](https://geo-ant.github.io/blog/2021/rust-traits-and-variadic-functions/) /// that allows us to implement this trait for functions taking different arguments. Just FYI: The /// type reflects the list of parameters `\alpha_j$`, so that for a function `Fn(&DVector<ScalarType>,ScalarType) -> DVector<ScalarType>` /// it follows that `ArgList=ScalarType`, while for `Fn(&DVector<ScalarType>,ScalarType)-> DVector<ScalarType>` it is `ArgList=(ScalarType,ScalarType)`. pub trait BasisFunction<ScalarType, ArgList> where ScalarType: Scalar + Clone, { /// A common calling interface to evaluate this function `$\vec{f}(\vec{x},\alpha_1,...\alpha_N)$` by passing a slice of scalar types /// that is dispatched to the arguments in order. /// /// # Arguments /// * `x`: the vector `$\vec{x}$` /// * `params`: The parameters `$(\alpha_1,...,\alpha_N)$` as a slice. The slice must have /// the correct number of arguments for calling the function (no more, no less). /// /// # Effect and Panics /// If the slice has fewer elements than the parameter argument list. If the slice has more element, /// only the first `$N$` elements are used and dispatched to the parameters in order, i.e. /// `$\alpha_1$`=`param[0]`, ..., `$\alpha_N$`=`param[N-1]`. Calling eval will result in evaluating /// the implementing callable at the location and arguments given. /// /// **Attention** The `varpro` library takes care that no panics can be caused by calls to `eval` (from /// within this library) by making sure the parameter slice has the correct length. Therefore /// it is not recommended (and not necessary) to use this function in other code than inside this library. fn eval(&self, x: &DVector<ScalarType>, params: &[ScalarType]) -> DVector<ScalarType>; /// This gives the number of parameter arguments to the callable. So for a function `$f(\vec{x},\alpha_1,...\alpha_N)$` /// this is equal to `$N$`. const ARGUMENT_COUNT: usize; }