outram_foam_basic_lib/fields/
surface_field.rs1use std::ops::{Add, Div, Mul, Neg, Sub};
23use std::sync::Arc;
24
25use super::boundary::bc::PatchField;
26use super::field::Field;
27use crate::mesh::fv_mesh::FvMesh;
28use crate::primitives::Vector3;
29
30#[derive(Debug, Clone)]
42pub struct SurfaceField<T: Clone> {
43 pub name: String,
44 pub mesh: Arc<FvMesh>,
45 pub internal: Field<T>,
47 pub boundary: Vec<PatchField<T>>,
50}
51
52pub type SurfaceScalarField = SurfaceField<f64>;
55pub type SurfaceVectorField = SurfaceField<Vector3>;
56
57impl<T: Clone> SurfaceField<T> {
60 pub fn new(
61 name: impl Into<String>,
62 mesh: Arc<FvMesh>,
63 internal: Field<T>,
64 boundary: Vec<PatchField<T>>,
65 ) -> Self {
66 debug_assert_eq!(
67 internal.len(),
68 mesh.n_internal_faces,
69 "SurfaceField internal field length must equal n_internal_faces"
70 );
71 debug_assert_eq!(
72 boundary.len(),
73 mesh.patches.len(),
74 "SurfaceField boundary length must equal number of patches"
75 );
76 Self {
77 name: name.into(),
78 mesh,
79 internal,
80 boundary,
81 }
82 }
83}
84
85impl SurfaceScalarField {
86 pub fn zeros(name: impl Into<String>, mesh: Arc<FvMesh>) -> Self {
87 let n_int = mesh.n_internal_faces;
88 let boundary = mesh
89 .patches
90 .iter()
91 .map(|p| PatchField::zero_gradient(p.size))
92 .collect();
93 Self::new(name, mesh, Field::zeros(n_int), boundary)
94 }
95
96 pub fn uniform(name: impl Into<String>, mesh: Arc<FvMesh>, value: f64) -> Self {
97 let n_int = mesh.n_internal_faces;
98 let boundary = mesh
99 .patches
100 .iter()
101 .map(|p| PatchField::zero_gradient(p.size))
102 .collect();
103 Self::new(name, mesh, Field::uniform(n_int, value), boundary)
104 }
105}
106
107impl SurfaceVectorField {
108 pub fn zero(name: impl Into<String>, mesh: Arc<FvMesh>) -> Self {
109 let n_int = mesh.n_internal_faces;
110 let boundary = mesh
111 .patches
112 .iter()
113 .map(|p| PatchField::zero_gradient_vec(p.size))
114 .collect();
115 Self::new(name, mesh, Field::zero_vec(n_int), boundary)
116 }
117}
118
119impl<T: Clone + Default> SurfaceField<T> {
122 pub fn face_value(&self, f: usize) -> T {
125 if self.mesh.is_internal_face(f) {
126 self.internal[f].clone()
127 } else {
128 let (pi, fi) = self
129 .mesh
130 .patch_for_face(f)
131 .expect("face index out of range for boundary");
132 self.boundary[pi].values[fi].clone()
133 }
134 }
135}
136
137impl<T> Add for SurfaceField<T>
140where
141 T: Add<Output = T> + Clone + Default,
142{
143 type Output = Self;
144 fn add(mut self, rhs: Self) -> Self {
145 self.internal = self.internal + rhs.internal;
150 for (l, r) in self.boundary.iter_mut().zip(rhs.boundary) {
151 l.values = l.values.clone() + r.values;
152 }
153 self
154 }
155}
156
157impl<T> Sub for SurfaceField<T>
158where
159 T: Sub<Output = T> + Clone + Default,
160{
161 type Output = Self;
162 fn sub(mut self, rhs: Self) -> Self {
163 self.internal = self.internal - rhs.internal;
165 for (l, r) in self.boundary.iter_mut().zip(rhs.boundary) {
166 l.values = l.values.clone() - r.values;
167 }
168 self
169 }
170}
171
172impl<T> Neg for SurfaceField<T>
173where
174 T: Neg<Output = T> + Clone,
175{
176 type Output = Self;
177 fn neg(mut self) -> Self {
178 self.internal = -self.internal;
180 for p in self.boundary.iter_mut() {
181 p.values = -p.values.clone();
182 }
183 self
184 }
185}
186
187impl<T> Mul<f64> for SurfaceField<T>
188where
189 T: Mul<f64, Output = T> + Clone,
190{
191 type Output = Self;
192 fn mul(mut self, s: f64) -> Self {
193 self.internal = self.internal * s;
194 for p in self.boundary.iter_mut() {
195 p.values = p.values.clone() * s;
196 }
197 self
198 }
199}
200
201impl<T> Div<f64> for SurfaceField<T>
202where
203 T: Mul<f64, Output = T> + Clone,
204{
205 type Output = Self;
206 fn div(self, s: f64) -> Self {
207 self * (1.0 / s)
208 }
209}
210
211impl Mul for SurfaceScalarField {
213 type Output = Self;
214 fn mul(mut self, rhs: Self) -> Self {
215 self.internal = self.internal * rhs.internal;
216 for (l, r) in self.boundary.iter_mut().zip(rhs.boundary) {
217 l.values = l.values.clone() * r.values;
218 }
219 self
220 }
221}
222
223impl<T: Mul<f64, Output = T> + Clone> Mul<SurfaceField<T>> for f64 {
225 type Output = SurfaceField<T>;
226 fn mul(self, mut rhs: SurfaceField<T>) -> SurfaceField<T> {
227 rhs.internal = rhs.internal * self;
228 for p in rhs.boundary.iter_mut() {
229 p.values = p.values.clone() * self;
230 }
231 rhs
232 }
233}
234
235#[cfg(test)]
238mod tests {
239 use super::*;
240 use crate::mesh::fv_mesh::{BoundaryPatch, FvMeshBuilder, PatchKind};
241
242 fn unit_mesh() -> Arc<FvMesh> {
243 Arc::new(
244 FvMeshBuilder::new()
245 .n_cells(2)
246 .n_internal_faces(1)
247 .owner(vec![0, 1, 0])
248 .neighbour(vec![1])
249 .patches(vec![
250 BoundaryPatch::new("right", 1, 1, PatchKind::Wall),
251 BoundaryPatch::new("left", 2, 1, PatchKind::Wall),
252 ])
253 .cell_volumes(vec![1.0, 1.0])
254 .cell_centres(vec![
255 Vector3::new(0.25, 0.0, 0.0),
256 Vector3::new(0.75, 0.0, 0.0),
257 ])
258 .face_area_vectors(vec![
259 Vector3::new(1.0, 0.0, 0.0),
260 Vector3::new(1.0, 0.0, 0.0),
261 Vector3::new(-1.0, 0.0, 0.0),
262 ])
263 .face_centres(vec![
264 Vector3::new(0.5, 0.0, 0.0),
265 Vector3::new(1.0, 0.0, 0.0),
266 Vector3::new(0.0, 0.0, 0.0),
267 ])
268 .build()
269 .unwrap(),
270 )
271 }
272
273 #[test]
274 fn zeros_surface_scalar_field() {
275 let m = unit_mesh();
276 let phi = SurfaceScalarField::zeros("phi", m.clone());
277 assert_eq!(phi.internal.len(), 1);
279 assert_eq!(phi.boundary.len(), 2);
280 assert_eq!(phi.boundary[0].values.len(), 1);
281 }
282
283 #[test]
284 fn face_value_internal() {
285 let m = unit_mesh();
286 let phi = SurfaceScalarField::uniform("phi", m.clone(), 5.0);
287 assert!((phi.face_value(0) - 5.0).abs() < 1e-15); }
289
290 #[test]
291 fn add_surface_fields() {
292 let m = unit_mesh();
293 let a = SurfaceScalarField::uniform("a", m.clone(), 2.0);
294 let b = SurfaceScalarField::uniform("b", m, 3.0);
295 let c = a + b;
296 assert!((c.internal[0] - 5.0).abs() < 1e-15);
297 }
298
299 #[test]
300 fn mul_surface_field_by_scalar() {
301 let m = unit_mesh();
302 let a = SurfaceScalarField::uniform("a", m, 4.0);
303 let b = a * 0.5;
304 assert!((b.internal[0] - 2.0).abs() < 1e-15);
305 }
306}