src/discrete_gradient.rs

Fri, 05 Sep 2025 00:56:59 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Fri, 05 Sep 2025 00:56:59 -0500
branch
dev
changeset 179
724413fc8d17
parent 133
2b13f8a0c8ba
child 186
afe04e6b4a5b
permissions
-rw-r--r--

wrap

67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1 /*!
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
2 Simple disrete gradient operators
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
3 */
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
4 use crate::error::DynResult;
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
5 use crate::instance::Instance;
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
6 use crate::linops::{Adjointable, BoundedLinear, Linear, Mapping, GEMV};
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
7 use crate::norms::{Norm, L2};
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
8 use crate::types::Float;
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
9 use nalgebra::{DVector, Dyn, Matrix, Storage, StorageMut, U1};
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
10 use numeric_literals::replace_float_literals;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
11
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
12 #[derive(Copy, Clone, Debug)]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
13 /// Forward differences with Neumann boundary conditions
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
14 pub struct ForwardNeumann;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
15
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
16 #[derive(Copy, Clone, Debug)]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
17 /// Forward differences with Dirichlet boundary conditions
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
18 pub struct ForwardDirichlet;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
19
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
20 #[derive(Copy, Clone, Debug)]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
21 /// Backward differences with Dirichlet boundary conditions
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
22 pub struct BackwardDirichlet;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
23
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
24 #[derive(Copy, Clone, Debug)]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
25 /// Backward differences with Neumann boundary conditions
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
26 pub struct BackwardNeumann;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
27
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
28 /// Finite differences gradient
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
29 pub struct Grad<F: Float + nalgebra::RealField, B: Discretisation<F>, const N: usize> {
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
30 dims: [usize; N],
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
31 h: F, // may be negative to implement adjoints!
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
32 discretisation: B,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
33 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
34
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
35 /// Finite differences divergence
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
36 pub struct Div<F: Float + nalgebra::RealField, B: Discretisation<F>, const N: usize> {
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
37 dims: [usize; N],
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
38 h: F, // may be negative to implement adjoints!
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
39 discretisation: B,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
40 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
41
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
42 /// Internal: classification of a point in a 1D discretisation
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
43 pub enum DiscretisationOrInterior {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
44 /// center, forward
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
45 LeftBoundary(usize, usize),
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
46 /// center, backward
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
47 RightBoundary(usize, usize),
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
48 /// center, (backward, forward)
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
49 Interior(usize, (usize, usize)),
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
50 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
51
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
52 use DiscretisationOrInterior::*;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
53
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
54 /// Trait for different discretisations
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
55 pub trait Discretisation<F: Float + nalgebra::RealField>: Copy {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
56 /// Opposite discretisation, appropriate for adjoints with negated cell width.
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
57 type Opposite: Discretisation<F>;
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
58
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
59 /// Add to appropiate index of `v` (as determined by `b`) the appropriate difference
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
60 /// of `x` with cell width `h`.
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
61 fn add_diff_mut<SMut, S>(
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
62 &self,
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
63 v: &mut Matrix<F, Dyn, U1, SMut>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
64 x: &Matrix<F, Dyn, U1, S>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
65 α: F,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
66 b: DiscretisationOrInterior,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
67 ) where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
68 SMut: StorageMut<F, Dyn, U1>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
69 S: Storage<F, Dyn, U1>;
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
70
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
71 /// Give the opposite discretisation, appropriate for adjoints with negated `h`.
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
72 fn opposite(&self) -> Self::Opposite;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
73
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
74 /// Bound for the corresponding operator norm.
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
75 #[replace_float_literals(F::cast_from(literal))]
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
76 fn opnorm_bound(&self, h: F) -> DynResult<F> {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
77 // See: Chambolle, “An Algorithm for Total Variation Minimization and Applications”.
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
78 // Ok for forward and backward differences.
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
79 //
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
80 // Fuck nalgebra for polluting everything with its own shit.
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
81 Ok(num_traits::Float::sqrt(8.0) / h)
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
82 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
83 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
84
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
85 impl<F: Float + nalgebra::RealField> Discretisation<F> for ForwardNeumann {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
86 type Opposite = BackwardDirichlet;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
87
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
88 #[inline]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
89 fn add_diff_mut<SMut, S>(
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
90 &self,
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
91 v: &mut Matrix<F, Dyn, U1, SMut>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
92 x: &Matrix<F, Dyn, U1, S>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
93 α: F,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
94 b: DiscretisationOrInterior,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
95 ) where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
96 SMut: StorageMut<F, Dyn, U1>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
97 S: Storage<F, Dyn, U1>,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
98 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
99 match b {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
100 Interior(c, (_, f)) | LeftBoundary(c, f) => v[c] += (x[f] - x[c]) * α,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
101 RightBoundary(_c, _b) => {}
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
102 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
103 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
104
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
105 #[inline]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
106 fn opposite(&self) -> Self::Opposite {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
107 BackwardDirichlet
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
108 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
109 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
110
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
111 impl<F: Float + nalgebra::RealField> Discretisation<F> for BackwardNeumann {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
112 type Opposite = ForwardDirichlet;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
113
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
114 #[inline]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
115 fn add_diff_mut<SMut, S>(
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
116 &self,
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
117 v: &mut Matrix<F, Dyn, U1, SMut>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
118 x: &Matrix<F, Dyn, U1, S>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
119 α: F,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
120 b: DiscretisationOrInterior,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
121 ) where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
122 SMut: StorageMut<F, Dyn, U1>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
123 S: Storage<F, Dyn, U1>,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
124 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
125 match b {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
126 Interior(c, (b, _)) | RightBoundary(c, b) => v[c] += (x[c] - x[b]) * α,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
127 LeftBoundary(_c, _f) => {}
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
128 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
129 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
130
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
131 #[inline]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
132 fn opposite(&self) -> Self::Opposite {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
133 ForwardDirichlet
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
134 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
135 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
136
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
137 impl<F: Float + nalgebra::RealField> Discretisation<F> for BackwardDirichlet {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
138 type Opposite = ForwardNeumann;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
139
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
140 #[inline]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
141 fn add_diff_mut<SMut, S>(
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
142 &self,
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
143 v: &mut Matrix<F, Dyn, U1, SMut>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
144 x: &Matrix<F, Dyn, U1, S>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
145 α: F,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
146 b: DiscretisationOrInterior,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
147 ) where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
148 SMut: StorageMut<F, Dyn, U1>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
149 S: Storage<F, Dyn, U1>,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
150 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
151 match b {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
152 Interior(c, (b, _f)) => v[c] += (x[c] - x[b]) * α,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
153 LeftBoundary(c, _f) => v[c] += x[c] * α,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
154 RightBoundary(c, b) => v[c] -= x[b] * α,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
155 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
156 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
157
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
158 #[inline]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
159 fn opposite(&self) -> Self::Opposite {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
160 ForwardNeumann
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
161 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
162 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
163
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
164 impl<F: Float + nalgebra::RealField> Discretisation<F> for ForwardDirichlet {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
165 type Opposite = BackwardNeumann;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
166
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
167 #[inline]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
168 fn add_diff_mut<SMut, S>(
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
169 &self,
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
170 v: &mut Matrix<F, Dyn, U1, SMut>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
171 x: &Matrix<F, Dyn, U1, S>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
172 α: F,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
173 b: DiscretisationOrInterior,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
174 ) where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
175 SMut: StorageMut<F, Dyn, U1>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
176 S: Storage<F, Dyn, U1>,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
177 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
178 match b {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
179 Interior(c, (_b, f)) => v[c] += (x[f] - x[c]) * α,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
180 LeftBoundary(c, f) => v[c] += x[f] * α,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
181 RightBoundary(c, _b) => v[c] -= x[c] * α,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
182 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
183 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
184
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
185 #[inline]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
186 fn opposite(&self) -> Self::Opposite {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
187 BackwardNeumann
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
188 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
189 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
190
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
191 struct Iter<'a, const N: usize> {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
192 /// Dimensions
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
193 dims: &'a [usize; N],
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
194 /// Dimension along which to calculate differences
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
195 d: usize,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
196 /// Stride along coordinate d
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
197 d_stride: usize,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
198 /// Cartesian indices
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
199 i: [usize; N],
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
200 /// Linear index
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
201 k: usize,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
202 /// Maximal linear index
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
203 len: usize,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
204 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
205
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
206 impl<'a, const N: usize> Iter<'a, N> {
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
207 fn new(dims: &'a [usize; N], d: usize) -> Self {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
208 let d_stride = dims[0..d].iter().product::<usize>();
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
209 let len = dims.iter().product::<usize>();
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
210 Iter {
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
211 dims,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
212 d,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
213 d_stride,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
214 i: [0; N],
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
215 k: 0,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
216 len,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
217 }
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
218 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
219 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
220
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
221 impl<'a, const N: usize> Iterator for Iter<'a, N> {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
222 type Item = DiscretisationOrInterior;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
223 fn next(&mut self) -> Option<Self::Item> {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
224 let res = if self.k >= self.len {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
225 None
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
226 } else {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
227 let cartesian_idx = self.i[self.d];
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
228 let cartesian_max = self.dims[self.d];
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
229 let k = self.k;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
230
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
231 if cartesian_idx == 0 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
232 Some(LeftBoundary(k, k + self.d_stride))
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
233 } else if cartesian_idx + 1 >= cartesian_max {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
234 Some(RightBoundary(k, k - self.d_stride))
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
235 } else {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
236 Some(Interior(k, (k - self.d_stride, k + self.d_stride)))
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
237 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
238 };
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
239 self.k += 1;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
240 for j in 0..N {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
241 if self.i[j] + 1 < self.dims[j] {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
242 self.i[j] += 1;
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
243 break;
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
244 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
245 self.i[j] = 0
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
246 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
247 res
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
248 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
249 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
250
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
251 impl<F, B, const N: usize> Mapping<DVector<F>> for Grad<F, B, N>
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
252 where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
253 B: Discretisation<F>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
254 F: Float + nalgebra::RealField,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
255 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
256 type Codomain = DVector<F>;
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
257 fn apply<I: Instance<DVector<F>>>(&self, i: I) -> DVector<F> {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
258 let mut y = DVector::zeros(N * self.len());
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
259 self.apply_add(&mut y, i);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
260 y
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
261 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
262 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
263
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
264 #[replace_float_literals(F::cast_from(literal))]
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
265 impl<F, B, const N: usize> GEMV<F, DVector<F>> for Grad<F, B, N>
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
266 where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
267 B: Discretisation<F>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
268 F: Float + nalgebra::RealField,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
269 {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
270 fn gemv<I: Instance<DVector<F>>>(&self, y: &mut DVector<F>, α: F, i: I, β: F) {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
271 if β == 0.0 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
272 y.as_mut_slice().iter_mut().for_each(|x| *x = 0.0);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
273 } else if β != 1.0 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
274 //*y *= β;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
275 y.as_mut_slice().iter_mut().for_each(|x| *x *= β);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
276 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
277 let h = self.h;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
278 let m = self.len();
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
279 i.eval(|x| {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
280 assert_eq!(x.len(), m);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
281 for d in 0..N {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
282 let mut v = y.generic_view_mut((d * m, 0), (Dyn(m), U1));
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
283 for b in Iter::new(&self.dims, d) {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
284 self.discretisation.add_diff_mut(&mut v, x, α / h, b)
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
285 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
286 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
287 })
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
288 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
289 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
290
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
291 impl<F, B, const N: usize> Mapping<DVector<F>> for Div<F, B, N>
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
292 where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
293 B: Discretisation<F>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
294 F: Float + nalgebra::RealField,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
295 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
296 type Codomain = DVector<F>;
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
297 fn apply<I: Instance<DVector<F>>>(&self, i: I) -> DVector<F> {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
298 let mut y = DVector::zeros(self.len());
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
299 self.apply_add(&mut y, i);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
300 y
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
301 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
302 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
303
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
304 #[replace_float_literals(F::cast_from(literal))]
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
305 impl<F, B, const N: usize> GEMV<F, DVector<F>> for Div<F, B, N>
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
306 where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
307 B: Discretisation<F>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
308 F: Float + nalgebra::RealField,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
309 {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
310 fn gemv<I: Instance<DVector<F>>>(&self, y: &mut DVector<F>, α: F, i: I, β: F) {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
311 if β == 0.0 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
312 y.as_mut_slice().iter_mut().for_each(|x| *x = 0.0);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
313 } else if β != 1.0 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
314 //*y *= β;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
315 y.as_mut_slice().iter_mut().for_each(|x| *x *= β);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
316 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
317 let h = self.h;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
318 let m = self.len();
133
2b13f8a0c8ba Replace Instance ref_instance and decompose by eval_* for flexibility
Tuomo Valkonen <tuomov@iki.fi>
parents: 124
diff changeset
319 i.eval_decompose(|x| {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
320 assert_eq!(x.len(), N * m);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
321 for d in 0..N {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
322 let v = x.generic_view((d * m, 0), (Dyn(m), U1));
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
323 for b in Iter::new(&self.dims, d) {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
324 self.discretisation.add_diff_mut(y, &v, α / h, b)
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
325 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
326 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
327 })
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
328 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
329 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
330
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
331 impl<F, B, const N: usize> Grad<F, B, N>
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
332 where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
333 B: Discretisation<F>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
334 F: Float + nalgebra::RealField,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
335 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
336 /// Creates a new discrete gradient operator for the vector `u`, verifying dimensions.
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
337 pub fn new_for(u: &DVector<F>, h: F, dims: [usize; N], discretisation: B) -> Option<Self> {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
338 if u.len() == dims.iter().product::<usize>() {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
339 Some(Grad {
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
340 dims,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
341 h,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
342 discretisation,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
343 })
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
344 } else {
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
345 None
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
346 }
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
347 }
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
348
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
349 fn len(&self) -> usize {
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
350 self.dims.iter().product::<usize>()
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
351 }
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
352 }
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
353
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
354 impl<F, B, const N: usize> Div<F, B, N>
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
355 where
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
356 B: Discretisation<F>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
357 F: Float + nalgebra::RealField,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
358 {
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
359 /// Creates a new discrete gradient operator for the vector `u`, verifying dimensions.
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
360 pub fn new_for(u: &DVector<F>, h: F, dims: [usize; N], discretisation: B) -> Option<Self> {
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
361 if u.len() == dims.iter().product::<usize>() * N {
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
362 Some(Div {
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
363 dims,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
364 h,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
365 discretisation,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
366 })
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
367 } else {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
368 None
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
369 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
370 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
371
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
372 fn len(&self) -> usize {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
373 self.dims.iter().product::<usize>()
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
374 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
375 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
376
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
377 impl<F, B, const N: usize> Linear<DVector<F>> for Grad<F, B, N>
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
378 where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
379 B: Discretisation<F>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
380 F: Float + nalgebra::RealField,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
381 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
382 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
383
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
384 impl<F, B, const N: usize> Linear<DVector<F>> for Div<F, B, N>
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
385 where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
386 B: Discretisation<F>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
387 F: Float + nalgebra::RealField,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
388 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
389 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
390
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
391 impl<F, B, const N: usize> BoundedLinear<DVector<F>, L2, L2, F> for Grad<F, B, N>
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
392 where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
393 B: Discretisation<F>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
394 F: Float + nalgebra::RealField,
124
6aa955ad8122 Transpose loc parameters to allow f64 defaults
Tuomo Valkonen <tuomov@iki.fi>
parents: 110
diff changeset
395 DVector<F>: Norm<L2, F>,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
396 {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
397 fn opnorm_bound(&self, _: L2, _: L2) -> DynResult<F> {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
398 // Fuck nalgebra.
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
399 self.discretisation
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
400 .opnorm_bound(num_traits::Float::abs(self.h))
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
401 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
402 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
403
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
404 impl<F, B, const N: usize> BoundedLinear<DVector<F>, L2, L2, F> for Div<F, B, N>
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
405 where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
406 B: Discretisation<F>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
407 F: Float + nalgebra::RealField,
124
6aa955ad8122 Transpose loc parameters to allow f64 defaults
Tuomo Valkonen <tuomov@iki.fi>
parents: 110
diff changeset
408 DVector<F>: Norm<L2, F>,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
409 {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
410 fn opnorm_bound(&self, _: L2, _: L2) -> DynResult<F> {
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
411 // Fuck nalgebra.
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
412 self.discretisation
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
413 .opnorm_bound(num_traits::Float::abs(self.h))
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
414 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
415 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
416
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
417 impl<F, B, const N: usize> Adjointable<DVector<F>, DVector<F>> for Grad<F, B, N>
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
418 where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
419 B: Discretisation<F>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
420 F: Float + nalgebra::RealField,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
421 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
422 type AdjointCodomain = DVector<F>;
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
423 type Adjoint<'a>
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
424 = Div<F, B::Opposite, N>
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
425 where
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
426 Self: 'a;
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
427
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
428 /// Form the adjoint operator of `self`.
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
429 fn adjoint(&self) -> Self::Adjoint<'_> {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
430 Div {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
431 dims: self.dims,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
432 h: -self.h,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
433 discretisation: self.discretisation.opposite(),
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
434 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
435 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
436 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
437
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
438 impl<F, B, const N: usize> Adjointable<DVector<F>, DVector<F>> for Div<F, B, N>
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
439 where
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
440 B: Discretisation<F>,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
441 F: Float + nalgebra::RealField,
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
442 {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
443 type AdjointCodomain = DVector<F>;
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
444 type Adjoint<'a>
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
445 = Grad<F, B::Opposite, N>
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
446 where
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
447 Self: 'a;
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
448
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
449 /// Form the adjoint operator of `self`.
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
450 fn adjoint(&self) -> Self::Adjoint<'_> {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
451 Grad {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
452 dims: self.dims,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
453 h: -self.h,
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
454 discretisation: self.discretisation.opposite(),
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
455 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
456 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
457 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
458
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
459 #[cfg(test)]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
460 mod tests {
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
461 use super::*;
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
462
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
463 #[test]
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
464 fn grad_adjoint() {
110
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
465 let im = DVector::from((0..9).map(|t| t as f64).collect::<Vec<_>>());
a1278320be26 Use DynResult for Lipschitz factors and operator norm bounds
Tuomo Valkonen <tuomov@iki.fi>
parents: 74
diff changeset
466 let v = DVector::from((0..18).map(|t| t as f64).collect::<Vec<_>>());
67
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
467
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
468 let grad = Grad::new_for(&im, 1.0, [3, 3], ForwardNeumann).unwrap();
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
469 let a = grad.apply(&im).dot(&v);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
470 let b = grad.adjoint().apply(&v).dot(&im);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
471 assert_eq!(a, b);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
472
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
473 let grad = Grad::new_for(&im, 1.0, [3, 3], ForwardDirichlet).unwrap();
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
474 let a = grad.apply(&im).dot(&v);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
475 let b = grad.adjoint().apply(&v).dot(&im);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
476 assert_eq!(a, b);
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
477 }
d7c0f431cbd6 Discrete gradients
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
478 }

mercurial