diffsol/op/
unit.rs

1// unit is a callable that returns returns the input vector
2
3use crate::{
4    LinearOp, LinearOpSens, LinearOpTranspose, Matrix, NonLinearOp, NonLinearOpAdjoint,
5    NonLinearOpJacobian, NonLinearOpSens, NonLinearOpSensAdjoint, Op, Vector,
6};
7use num_traits::{One, Zero};
8
9use super::{BuilderOp, ParameterisedOp};
10
11/// A dummy operator that returns the input vector. Can be used either as a [NonLinearOp] or [LinearOp].
12pub struct UnitCallable<M: Matrix> {
13    n: usize,
14    ctx: M::C,
15}
16
17impl<M: Matrix> Default for UnitCallable<M> {
18    fn default() -> Self {
19        Self::new(1, M::C::default())
20    }
21}
22
23impl<M: Matrix> UnitCallable<M> {
24    pub fn new(n: usize, ctx: M::C) -> Self {
25        Self { n, ctx }
26    }
27}
28
29impl<M: Matrix> Op for UnitCallable<M> {
30    type T = M::T;
31    type V = M::V;
32    type M = M;
33    type C = M::C;
34    fn nstates(&self) -> usize {
35        self.n
36    }
37    fn nout(&self) -> usize {
38        self.n
39    }
40    fn nparams(&self) -> usize {
41        0
42    }
43    fn context(&self) -> &Self::C {
44        &self.ctx
45    }
46}
47
48impl<M: Matrix> BuilderOp for UnitCallable<M> {
49    fn calculate_sparsity(&mut self, _y0: &Self::V, _t0: Self::T, _p: &Self::V) {
50        // Do nothing
51    }
52    fn set_nout(&mut self, nout: usize) {
53        self.n = nout;
54    }
55    fn set_nparams(&mut self, _nparams: usize) {
56        // Do nothing
57    }
58    fn set_nstates(&mut self, nstates: usize) {
59        self.n = nstates;
60    }
61}
62
63impl<M: Matrix> LinearOp for ParameterisedOp<'_, UnitCallable<M>> {
64    fn gemv_inplace(&self, x: &Self::V, _t: Self::T, beta: Self::T, y: &mut Self::V) {
65        y.axpy(Self::T::one(), x, beta);
66    }
67}
68
69impl<M: Matrix> NonLinearOp for ParameterisedOp<'_, UnitCallable<M>> {
70    fn call_inplace(&self, x: &Self::V, _t: Self::T, y: &mut Self::V) {
71        y.copy_from(x);
72    }
73}
74
75impl<M: Matrix> NonLinearOpJacobian for ParameterisedOp<'_, UnitCallable<M>> {
76    fn jac_mul_inplace(&self, _x: &Self::V, _t: Self::T, v: &Self::V, y: &mut Self::V) {
77        y.copy_from(v);
78    }
79}
80
81impl<M: Matrix> NonLinearOpAdjoint for ParameterisedOp<'_, UnitCallable<M>> {
82    fn jac_transpose_mul_inplace(&self, _x: &Self::V, _t: Self::T, v: &Self::V, y: &mut Self::V) {
83        y.copy_from(v);
84    }
85}
86
87impl<M: Matrix> NonLinearOpSens for ParameterisedOp<'_, UnitCallable<M>> {
88    fn sens_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
89        y.fill(Self::T::zero());
90    }
91}
92
93impl<M: Matrix> NonLinearOpSensAdjoint for ParameterisedOp<'_, UnitCallable<M>> {
94    fn sens_transpose_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
95        y.fill(Self::T::zero());
96    }
97}
98
99impl<M: Matrix> LinearOpSens for ParameterisedOp<'_, UnitCallable<M>> {
100    fn sens_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
101        y.fill(Self::T::zero());
102    }
103}
104
105impl<M: Matrix> LinearOpTranspose for ParameterisedOp<'_, UnitCallable<M>> {
106    fn gemv_transpose_inplace(&self, x: &Self::V, _t: Self::T, beta: Self::T, y: &mut Self::V) {
107        y.axpy(Self::T::one(), x, beta);
108    }
109}
110
111impl<M: Matrix> LinearOp for UnitCallable<M> {
112    fn gemv_inplace(&self, x: &Self::V, _t: Self::T, beta: Self::T, y: &mut Self::V) {
113        y.axpy(Self::T::one(), x, beta);
114    }
115}
116
117impl<M: Matrix> NonLinearOp for UnitCallable<M> {
118    fn call_inplace(&self, x: &Self::V, _t: Self::T, y: &mut Self::V) {
119        y.copy_from(x);
120    }
121}
122
123impl<M: Matrix> NonLinearOpJacobian for UnitCallable<M> {
124    fn jac_mul_inplace(&self, _x: &Self::V, _t: Self::T, v: &Self::V, y: &mut Self::V) {
125        y.copy_from(v);
126    }
127}
128
129impl<M: Matrix> NonLinearOpAdjoint for UnitCallable<M> {
130    fn jac_transpose_mul_inplace(&self, _x: &Self::V, _t: Self::T, v: &Self::V, y: &mut Self::V) {
131        y.copy_from(v);
132    }
133}
134
135impl<M: Matrix> NonLinearOpSens for UnitCallable<M> {
136    fn sens_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
137        y.fill(Self::T::zero());
138    }
139}
140
141impl<M: Matrix> NonLinearOpSensAdjoint for UnitCallable<M> {
142    fn sens_transpose_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
143        y.fill(Self::T::zero());
144    }
145}
146
147impl<M: Matrix> LinearOpSens for UnitCallable<M> {
148    fn sens_mul_inplace(&self, _x: &Self::V, _t: Self::T, _v: &Self::V, y: &mut Self::V) {
149        y.fill(Self::T::zero());
150    }
151}
152
153impl<M: Matrix> LinearOpTranspose for UnitCallable<M> {
154    fn gemv_transpose_inplace(&self, x: &Self::V, _t: Self::T, beta: Self::T, y: &mut Self::V) {
155        y.axpy(Self::T::one(), x, beta);
156    }
157}