| 1 /*! |
1 /*! |
| 2 Simple disrete gradient operators |
2 Simple disrete gradient operators |
| 3 */ |
3 */ |
| 4 use crate::error::DynResult; |
4 use crate::error::DynResult; |
| 5 use crate::instance::Instance; |
5 use crate::instance::Instance; |
| 6 use crate::linops::{Adjointable, BoundedLinear, Linear, Mapping, GEMV}; |
6 use crate::linops::{Adjointable, BoundedLinear, Linear, Mapping, SimplyAdjointable, GEMV}; |
| 7 use crate::norms::{Norm, L2}; |
7 use crate::norms::{Norm, L2}; |
| 8 use crate::types::Float; |
8 use crate::types::Float; |
| 9 use nalgebra::{DVector, Dyn, Matrix, Storage, StorageMut, U1}; |
9 use nalgebra::{DVector, Dyn, Matrix, Storage, StorageMut, U1}; |
| 10 use numeric_literals::replace_float_literals; |
10 use numeric_literals::replace_float_literals; |
| 11 |
11 |
| 205 |
205 |
| 206 impl<'a, const N: usize> Iter<'a, N> { |
206 impl<'a, const N: usize> Iter<'a, N> { |
| 207 fn new(dims: &'a [usize; N], d: usize) -> Self { |
207 fn new(dims: &'a [usize; N], d: usize) -> Self { |
| 208 let d_stride = dims[0..d].iter().product::<usize>(); |
208 let d_stride = dims[0..d].iter().product::<usize>(); |
| 209 let len = dims.iter().product::<usize>(); |
209 let len = dims.iter().product::<usize>(); |
| 210 Iter { |
210 Iter { dims, d, d_stride, i: [0; N], k: 0, len } |
| 211 dims, |
|
| 212 d, |
|
| 213 d_stride, |
|
| 214 i: [0; N], |
|
| 215 k: 0, |
|
| 216 len, |
|
| 217 } |
|
| 218 } |
211 } |
| 219 } |
212 } |
| 220 |
213 |
| 221 impl<'a, const N: usize> Iterator for Iter<'a, N> { |
214 impl<'a, const N: usize> Iterator for Iter<'a, N> { |
| 222 type Item = DiscretisationOrInterior; |
215 type Item = DiscretisationOrInterior; |
| 334 F: Float + nalgebra::RealField, |
327 F: Float + nalgebra::RealField, |
| 335 { |
328 { |
| 336 /// Creates a new discrete gradient operator for the vector `u`, verifying dimensions. |
329 /// Creates a new discrete gradient operator for the vector `u`, verifying dimensions. |
| 337 pub fn new_for(u: &DVector<F>, h: F, dims: [usize; N], discretisation: B) -> Option<Self> { |
330 pub fn new_for(u: &DVector<F>, h: F, dims: [usize; N], discretisation: B) -> Option<Self> { |
| 338 if u.len() == dims.iter().product::<usize>() { |
331 if u.len() == dims.iter().product::<usize>() { |
| 339 Some(Grad { |
332 Some(Grad { dims, h, discretisation }) |
| 340 dims, |
|
| 341 h, |
|
| 342 discretisation, |
|
| 343 }) |
|
| 344 } else { |
333 } else { |
| 345 None |
334 None |
| 346 } |
335 } |
| 347 } |
336 } |
| 348 |
337 |
| 357 F: Float + nalgebra::RealField, |
346 F: Float + nalgebra::RealField, |
| 358 { |
347 { |
| 359 /// Creates a new discrete gradient operator for the vector `u`, verifying dimensions. |
348 /// Creates a new discrete gradient operator for the vector `u`, verifying dimensions. |
| 360 pub fn new_for(u: &DVector<F>, h: F, dims: [usize; N], discretisation: B) -> Option<Self> { |
349 pub fn new_for(u: &DVector<F>, h: F, dims: [usize; N], discretisation: B) -> Option<Self> { |
| 361 if u.len() == dims.iter().product::<usize>() * N { |
350 if u.len() == dims.iter().product::<usize>() * N { |
| 362 Some(Div { |
351 Some(Div { dims, h, discretisation }) |
| 363 dims, |
|
| 364 h, |
|
| 365 discretisation, |
|
| 366 }) |
|
| 367 } else { |
352 } else { |
| 368 None |
353 None |
| 369 } |
354 } |
| 370 } |
355 } |
| 371 |
356 |
| 423 type Adjoint<'a> |
408 type Adjoint<'a> |
| 424 = Div<F, B::Opposite, N> |
409 = Div<F, B::Opposite, N> |
| 425 where |
410 where |
| 426 Self: 'a; |
411 Self: 'a; |
| 427 |
412 |
| 428 /// Form the adjoint operator of `self`. |
|
| 429 fn adjoint(&self) -> Self::Adjoint<'_> { |
413 fn adjoint(&self) -> Self::Adjoint<'_> { |
| 430 Div { |
414 Div { dims: self.dims, h: -self.h, discretisation: self.discretisation.opposite() } |
| 431 dims: self.dims, |
415 } |
| 432 h: -self.h, |
416 } |
| 433 discretisation: self.discretisation.opposite(), |
417 |
| 434 } |
418 impl<F, B, const N: usize> SimplyAdjointable<DVector<F>, DVector<F>> for Grad<F, B, N> |
| |
419 where |
| |
420 B: Discretisation<F>, |
| |
421 F: Float + nalgebra::RealField, |
| |
422 { |
| |
423 type AdjointCodomain = DVector<F>; |
| |
424 type SimpleAdjoint = Div<F, B::Opposite, N>; |
| |
425 |
| |
426 fn adjoint(&self) -> Self::SimpleAdjoint { |
| |
427 Div { dims: self.dims, h: -self.h, discretisation: self.discretisation.opposite() } |
| 435 } |
428 } |
| 436 } |
429 } |
| 437 |
430 |
| 438 impl<F, B, const N: usize> Adjointable<DVector<F>, DVector<F>> for Div<F, B, N> |
431 impl<F, B, const N: usize> Adjointable<DVector<F>, DVector<F>> for Div<F, B, N> |
| 439 where |
432 where |
| 444 type Adjoint<'a> |
437 type Adjoint<'a> |
| 445 = Grad<F, B::Opposite, N> |
438 = Grad<F, B::Opposite, N> |
| 446 where |
439 where |
| 447 Self: 'a; |
440 Self: 'a; |
| 448 |
441 |
| 449 /// Form the adjoint operator of `self`. |
|
| 450 fn adjoint(&self) -> Self::Adjoint<'_> { |
442 fn adjoint(&self) -> Self::Adjoint<'_> { |
| 451 Grad { |
443 Grad { dims: self.dims, h: -self.h, discretisation: self.discretisation.opposite() } |
| 452 dims: self.dims, |
444 } |
| 453 h: -self.h, |
445 } |
| 454 discretisation: self.discretisation.opposite(), |
446 |
| 455 } |
447 impl<F, B, const N: usize> SimplyAdjointable<DVector<F>, DVector<F>> for Div<F, B, N> |
| |
448 where |
| |
449 B: Discretisation<F>, |
| |
450 F: Float + nalgebra::RealField, |
| |
451 { |
| |
452 type AdjointCodomain = DVector<F>; |
| |
453 type SimpleAdjoint = Grad<F, B::Opposite, N>; |
| |
454 |
| |
455 fn adjoint(&self) -> Self::SimpleAdjoint { |
| |
456 Grad { dims: self.dims, h: -self.h, discretisation: self.discretisation.opposite() } |
| 456 } |
457 } |
| 457 } |
458 } |
| 458 |
459 |
| 459 #[cfg(test)] |
460 #[cfg(test)] |
| 460 mod tests { |
461 mod tests { |