conspire/math/tensor/quantity/vec/
mod.rs1use super::Quantity;
2use crate::math::{
3 Jacobian, Solution, Tensor, TensorRank0, Vector, assert::FiniteDifference,
4 tensor::vec::TensorVector,
5};
6use crate::units::{Dimensionless, UnitDiv};
7use std::ops::{Div, Sub};
8
9use super::sparse_vec_2d::QuantitySparseVec2D;
10
11pub type QuantityVector<U = Dimensionless> = TensorVector<Quantity<U>>;
13
14impl<U> QuantityVector<U> {
15 pub fn zero(len: usize) -> Self {
16 (0..len).map(|_| Quantity::new(0.0)).collect()
17 }
18}
19
20impl<U> From<Vector> for QuantityVector<U> {
21 fn from(vector: Vector) -> Self {
22 vector.iter().map(|&entry| Quantity::new(entry)).collect()
23 }
24}
25
26impl<U> Jacobian for QuantityVector<U> {
27 fn fill_into(&self, vector: &mut Vector) {
28 self.iter()
29 .zip(vector.iter_mut())
30 .for_each(|(self_a, vector_a)| *vector_a = self_a.value())
31 }
32 fn fill_into_chained(self, other: Vector, vector: &mut Vector) {
33 self.into_iter()
34 .map(|entry| entry.value())
35 .chain(other)
36 .zip(vector.iter_mut())
37 .for_each(|(self_a, vector_a)| *vector_a = self_a)
38 }
39 fn retain_from(self, retained: &[bool]) -> Vector {
40 self.into_iter()
41 .zip(retained.iter())
42 .filter(|(_, retained)| **retained)
43 .map(|(entry, _)| entry.value())
44 .collect()
45 }
46 fn zero_out(&mut self, indices: &[usize]) {
47 indices
48 .iter()
49 .for_each(|&index| self[index] = Quantity::new(0.0))
50 }
51}
52
53impl<U> Solution for QuantityVector<U> {
54 fn decrement_from(&mut self, other: &Vector) {
55 self.iter_mut()
56 .zip(other.iter())
57 .for_each(|(self_a, vector_a)| *self_a -= Quantity::new(*vector_a))
58 }
59 fn decrement_from_chained(&mut self, other: &mut Vector, vector: &Vector) {
60 self.iter_mut()
61 .zip(vector.iter())
62 .for_each(|(self_a, vector_a)| *self_a -= Quantity::new(*vector_a));
63 other
64 .iter_mut()
65 .zip(vector.iter().skip(self.len()))
66 .for_each(|(other_a, vector_a)| *other_a -= vector_a)
67 }
68 fn decrement_from_retained(&mut self, retained: &[bool], other: &Vector) {
69 self.iter_mut()
70 .zip(retained.iter())
71 .filter(|(_, retained_a)| **retained_a)
72 .zip(other.iter())
73 .for_each(|((self_a, _), vector_a)| *self_a -= Quantity::new(*vector_a))
74 }
75}
76
77impl<U> Sub<Vector> for QuantityVector<U> {
78 type Output = Self;
79 fn sub(mut self, vector: Vector) -> Self::Output {
80 self.iter_mut()
81 .zip(vector.iter())
82 .for_each(|(self_a, vector_a)| *self_a -= Quantity::new(*vector_a));
83 self
84 }
85}
86
87impl<U> Sub<&Vector> for QuantityVector<U> {
88 type Output = Self;
89 fn sub(mut self, vector: &Vector) -> Self::Output {
90 self.iter_mut()
91 .zip(vector.iter())
92 .for_each(|(self_a, vector_a)| *self_a -= Quantity::new(*vector_a));
93 self
94 }
95}
96
97impl<U, V> Div<QuantitySparseVec2D<V>> for &QuantityVector<U>
98where
99 U: UnitDiv<V>,
100{
101 type Output = QuantityVector<<U as UnitDiv<V>>::Output>;
102 fn div(self, _quantity_sparse_vec_2d: QuantitySparseVec2D<V>) -> Self::Output {
103 unimplemented!(
104 "A mesh-scale step wants the sparse solver the caller supplies, which a division has nowhere to hold."
105 )
106 }
107}
108
109impl<U> FiniteDifference for QuantityVector<U> {
110 fn error_fd(&self, comparator: &Self, epsilon: TensorRank0) -> Option<(bool, usize)> {
111 let error_count = self
112 .iter()
113 .zip(comparator.iter())
114 .filter(|(entry, comparator_entry)| entry.differs(**comparator_entry, epsilon))
115 .count();
116 if error_count > 0 {
117 let auxiliary = self
118 .iter()
119 .zip(comparator.iter())
120 .filter(|(entry, comparator_entry)| {
121 entry.differs_severely(**comparator_entry, epsilon)
122 })
123 .count()
124 > 0;
125 Some((auxiliary, error_count))
126 } else {
127 None
128 }
129 }
130}