1use crate::traits::Map;
3use rlst::{Array, MutableArrayImpl, RlstScalar, ValueArrayImpl};
4
5pub struct IdentityMap {}
10
11impl Map for IdentityMap {
12 fn push_forward<
13 T: RlstScalar,
14 TGeo: RlstScalar,
15 Array3GeoImpl: ValueArrayImpl<TGeo, 3>,
16 Array4Impl: ValueArrayImpl<T, 4>,
17 Array4MutImpl: MutableArrayImpl<T, 4>,
18 >(
19 &self,
20 reference_values: &Array<Array4Impl, 4>,
21 nderivs: usize,
22 _jacobians: &Array<Array3GeoImpl, 3>,
23 _jacobian_determinants: &[TGeo],
24 _inverse_jacobians: &Array<Array3GeoImpl, 3>,
25 physical_values: &mut Array<Array4MutImpl, 4>,
26 ) {
27 if nderivs > 0 {
28 unimplemented!();
29 }
30
31 physical_values.fill_from(reference_values);
32 }
33 fn pull_back<
34 T: RlstScalar,
35 TGeo: RlstScalar,
36 Array3GeoImpl: ValueArrayImpl<TGeo, 3>,
37 Array4Impl: ValueArrayImpl<T, 4>,
38 Array4MutImpl: MutableArrayImpl<T, 4>,
39 >(
40 &self,
41 physical_values: &Array<Array4Impl, 4>,
42 nderivs: usize,
43 _jacobians: &Array<Array3GeoImpl, 3>,
44 _jacobian_determinants: &[TGeo],
45 _inverse_jacobians: &Array<Array3GeoImpl, 3>,
46 reference_values: &mut Array<Array4MutImpl, 4>,
47 ) {
48 if nderivs > 0 {
49 unimplemented!();
50 }
51
52 reference_values.fill_from(physical_values);
53 }
54 fn physical_value_shape(&self, _gdim: usize) -> Vec<usize> {
55 vec![1]
56 }
57}
58
59pub struct CovariantPiolaMap {}
71
72impl Map for CovariantPiolaMap {
73 fn push_forward<
74 T: RlstScalar,
75 TGeo: RlstScalar,
76 Array3GeoImpl: ValueArrayImpl<TGeo, 3>,
77 Array4Impl: ValueArrayImpl<T, 4>,
78 Array4MutImpl: MutableArrayImpl<T, 4>,
79 >(
80 &self,
81 reference_values: &Array<Array4Impl, 4>,
82 nderivs: usize,
83 _jacobians: &Array<Array3GeoImpl, 3>,
84 _jacobian_determinants: &[TGeo],
85 inverse_jacobians: &Array<Array3GeoImpl, 3>,
86 physical_values: &mut Array<Array4MutImpl, 4>,
87 ) {
88 let tdim = inverse_jacobians.shape()[1];
89 let gdim = inverse_jacobians.shape()[2];
90 assert_eq!(reference_values.shape()[0], physical_values.shape()[0]);
91 assert_eq!(reference_values.shape()[1], physical_values.shape()[1]);
92 assert_eq!(reference_values.shape()[2], physical_values.shape()[2]);
93 assert_eq!(reference_values.shape()[3], tdim);
94 assert_eq!(physical_values.shape()[3], gdim);
95 if nderivs > 0 {
96 unimplemented!();
97 }
98 for p in 0..reference_values.shape()[1] {
99 for b in 0..reference_values.shape()[2] {
100 for gd in 0..gdim {
101 unsafe {
102 *physical_values.get_unchecked_mut([0, p, b, gd]) = (0..tdim)
103 .map(|td| {
104 T::from(inverse_jacobians.get_value_unchecked([p, td, gd])).unwrap()
105 * reference_values.get_value_unchecked([0, p, b, td])
106 })
107 .sum::<T>();
108 }
109 }
110 }
111 }
112 }
113 fn pull_back<
114 T: RlstScalar,
115 TGeo: RlstScalar,
116 Array3GeoImpl: ValueArrayImpl<TGeo, 3>,
117 Array4Impl: ValueArrayImpl<T, 4>,
118 Array4MutImpl: MutableArrayImpl<T, 4>,
119 >(
120 &self,
121 physical_values: &Array<Array4Impl, 4>,
122 nderivs: usize,
123 jacobians: &Array<Array3GeoImpl, 3>,
124 _jacobian_determinants: &[TGeo],
125 _inverse_jacobians: &Array<Array3GeoImpl, 3>,
126 reference_values: &mut Array<Array4MutImpl, 4>,
127 ) {
128 let gdim = jacobians.shape()[1];
129 let tdim = jacobians.shape()[2];
130 assert_eq!(reference_values.shape()[0], physical_values.shape()[0]);
131 assert_eq!(reference_values.shape()[1], physical_values.shape()[1]);
132 assert_eq!(reference_values.shape()[2], physical_values.shape()[2]);
133 assert_eq!(reference_values.shape()[3], tdim);
134 assert_eq!(physical_values.shape()[3], gdim);
135 if nderivs > 0 {
136 unimplemented!();
137 }
138 for p in 0..physical_values.shape()[1] {
139 for b in 0..physical_values.shape()[2] {
140 for td in 0..tdim {
141 unsafe {
142 *reference_values.get_unchecked_mut([0, p, b, td]) = (0..gdim)
143 .map(|gd| {
144 T::from(jacobians.get_value_unchecked([p, gd, td])).unwrap()
145 * physical_values.get_value_unchecked([0, p, b, gd])
146 })
147 .sum::<T>();
148 }
149 }
150 }
151 }
152 }
153 fn physical_value_shape(&self, gdim: usize) -> Vec<usize> {
154 vec![gdim]
155 }
156}
157
158pub struct ContravariantPiolaMap {}
170
171impl Map for ContravariantPiolaMap {
172 fn push_forward<
173 T: RlstScalar,
174 TGeo: RlstScalar,
175 Array3GeoImpl: ValueArrayImpl<TGeo, 3>,
176 Array4Impl: ValueArrayImpl<T, 4>,
177 Array4MutImpl: MutableArrayImpl<T, 4>,
178 >(
179 &self,
180 reference_values: &Array<Array4Impl, 4>,
181 nderivs: usize,
182 jacobians: &Array<Array3GeoImpl, 3>,
183 jacobian_determinants: &[TGeo],
184 _inverse_jacobians: &Array<Array3GeoImpl, 3>,
185 physical_values: &mut Array<Array4MutImpl, 4>,
186 ) {
187 let gdim = jacobians.shape()[1];
188 let tdim = jacobians.shape()[2];
189 assert_eq!(reference_values.shape()[0], physical_values.shape()[0]);
190 assert_eq!(reference_values.shape()[1], physical_values.shape()[1]);
191 assert_eq!(reference_values.shape()[2], physical_values.shape()[2]);
192 assert_eq!(reference_values.shape()[3], tdim);
193 assert_eq!(physical_values.shape()[3], gdim);
194 if nderivs > 0 {
195 unimplemented!();
196 }
197 for p in 0..physical_values.shape()[1] {
198 for b in 0..physical_values.shape()[2] {
199 for gd in 0..gdim {
200 unsafe {
201 *physical_values.get_unchecked_mut([0, p, b, gd]) = (0..tdim)
202 .map(|td| {
203 T::from(jacobians.get_value_unchecked([p, gd, td])).unwrap()
204 * reference_values.get_value_unchecked([0, p, b, td])
205 })
206 .sum::<T>()
207 / T::from(*jacobian_determinants.get_unchecked(p)).unwrap();
208 }
209 }
210 }
211 }
212 }
213 fn pull_back<
214 T: RlstScalar,
215 TGeo: RlstScalar,
216 Array3GeoImpl: ValueArrayImpl<TGeo, 3>,
217 Array4Impl: ValueArrayImpl<T, 4>,
218 Array4MutImpl: MutableArrayImpl<T, 4>,
219 >(
220 &self,
221 physical_values: &Array<Array4Impl, 4>,
222 nderivs: usize,
223 _jacobians: &Array<Array3GeoImpl, 3>,
224 jacobian_determinants: &[TGeo],
225 inverse_jacobians: &Array<Array3GeoImpl, 3>,
226 reference_values: &mut Array<Array4MutImpl, 4>,
227 ) {
228 let tdim = inverse_jacobians.shape()[1];
229 let gdim = inverse_jacobians.shape()[2];
230 assert_eq!(reference_values.shape()[0], physical_values.shape()[0]);
231 assert_eq!(reference_values.shape()[1], physical_values.shape()[1]);
232 assert_eq!(reference_values.shape()[2], physical_values.shape()[2]);
233 assert_eq!(reference_values.shape()[3], tdim);
234 assert_eq!(physical_values.shape()[3], gdim);
235 if nderivs > 0 {
236 unimplemented!();
237 }
238 for p in 0..physical_values.shape()[1] {
239 for b in 0..physical_values.shape()[2] {
240 for td in 0..tdim {
241 unsafe {
242 *reference_values.get_unchecked_mut([0, p, b, td]) = (0..gdim)
243 .map(|gd| {
244 T::from(inverse_jacobians.get_value_unchecked([p, td, gd])).unwrap()
245 * physical_values.get_value_unchecked([0, p, b, gd])
246 })
247 .sum::<T>()
248 * T::from(*jacobian_determinants.get_unchecked(p)).unwrap();
249 }
250 }
251 }
252 }
253 }
254 fn physical_value_shape(&self, gdim: usize) -> Vec<usize> {
255 vec![gdim]
256 }
257}
258
259#[cfg(test)]
260mod test {
261 use super::*;
262 use approx::*;
263 use rlst::{Array, rlst_dynamic_array};
264
265 fn fill_jacobians<T: RlstScalar, Array3MutImpl: MutableArrayImpl<T, 3>>(
266 j: &mut Array<Array3MutImpl, 3>,
267 jdet: &mut [T],
268 jinv: &mut Array<Array3MutImpl, 3>,
269 ) {
270 *j.get_mut([0, 0, 0]).unwrap() = T::from(1.0).unwrap();
271 *j.get_mut([0, 0, 1]).unwrap() = T::from(1.0).unwrap();
272 *j.get_mut([0, 1, 0]).unwrap() = T::from(0.0).unwrap();
273 *j.get_mut([0, 1, 1]).unwrap() = T::from(1.0).unwrap();
274 *j.get_mut([1, 0, 0]).unwrap() = T::from(2.0).unwrap();
275 *j.get_mut([1, 0, 1]).unwrap() = T::from(0.0).unwrap();
276 *j.get_mut([1, 1, 0]).unwrap() = T::from(0.0).unwrap();
277 *j.get_mut([1, 1, 1]).unwrap() = T::from(3.0).unwrap();
278 jdet[0] = T::from(1.0).unwrap();
279 jdet[1] = T::from(6.0).unwrap();
280 *jinv.get_mut([0, 0, 0]).unwrap() = T::from(1.0).unwrap();
281 *jinv.get_mut([0, 0, 1]).unwrap() = T::from(-1.0).unwrap();
282 *jinv.get_mut([0, 1, 0]).unwrap() = T::from(0.0).unwrap();
283 *jinv.get_mut([0, 1, 1]).unwrap() = T::from(1.0).unwrap();
284 *jinv.get_mut([1, 0, 0]).unwrap() = T::from(0.5).unwrap();
285 *jinv.get_mut([1, 0, 1]).unwrap() = T::from(0.0).unwrap();
286 *jinv.get_mut([1, 1, 0]).unwrap() = T::from(0.0).unwrap();
287 *jinv.get_mut([1, 1, 1]).unwrap() = T::from(1.0 / 3.0).unwrap();
288 }
289
290 #[test]
291 fn test_identity() {
292 let map = IdentityMap {};
293 let mut values = rlst_dynamic_array!(f64, [1, 2, 2, 1]);
294 *values.get_mut([0, 0, 0, 0]).unwrap() = 1.0;
295 *values.get_mut([0, 1, 0, 0]).unwrap() = 0.0;
296 *values.get_mut([0, 0, 1, 0]).unwrap() = 0.5;
297 *values.get_mut([0, 1, 1, 0]).unwrap() = 2.0;
298
299 let mut j = rlst_dynamic_array!(f64, [2, 2, 2]);
300 let mut jdet = vec![0.0; 2];
301 let mut jinv = rlst_dynamic_array!(f64, [2, 2, 2]);
302 fill_jacobians(&mut j, &mut jdet, &mut jinv);
303
304 let mut physical_values = rlst_dynamic_array!(f64, [1, 2, 2, 1]);
305
306 map.push_forward(&values, 0, &j, &jdet, &jinv, &mut physical_values);
307
308 assert_relative_eq!(
309 *physical_values.get([0, 0, 0, 0]).unwrap(),
310 1.0,
311 epsilon = 1e-14
312 );
313 assert_relative_eq!(
314 *physical_values.get([0, 1, 0, 0]).unwrap(),
315 0.0,
316 epsilon = 1e-14
317 );
318 assert_relative_eq!(
319 *physical_values.get([0, 0, 1, 0]).unwrap(),
320 0.5,
321 epsilon = 1e-14
322 );
323 assert_relative_eq!(
324 *physical_values.get([0, 1, 1, 0]).unwrap(),
325 2.0,
326 epsilon = 1e-14
327 );
328
329 values.set_zero();
330
331 map.pull_back(&physical_values, 0, &j, &jdet, &jinv, &mut values);
332
333 assert_relative_eq!(*values.get([0, 0, 0, 0]).unwrap(), 1.0, epsilon = 1e-14);
334 assert_relative_eq!(*values.get([0, 1, 0, 0]).unwrap(), 0.0, epsilon = 1e-14);
335 assert_relative_eq!(*values.get([0, 0, 1, 0]).unwrap(), 0.5, epsilon = 1e-14);
336 assert_relative_eq!(*values.get([0, 1, 1, 0]).unwrap(), 2.0, epsilon = 1e-14);
337 }
338
339 #[test]
340 fn test_covariant_piola() {
341 let map = CovariantPiolaMap {};
342 let mut values = rlst_dynamic_array!(f64, [1, 2, 2, 2]);
343 *values.get_mut([0, 0, 0, 0]).unwrap() = 1.0;
344 *values.get_mut([0, 0, 0, 1]).unwrap() = 0.0;
345 *values.get_mut([0, 1, 0, 0]).unwrap() = 0.0;
346 *values.get_mut([0, 1, 0, 1]).unwrap() = 1.0;
347 *values.get_mut([0, 0, 1, 0]).unwrap() = 0.5;
348 *values.get_mut([0, 0, 1, 1]).unwrap() = 1.5;
349 *values.get_mut([0, 1, 1, 0]).unwrap() = 2.0;
350 *values.get_mut([0, 1, 1, 1]).unwrap() = 2.0;
351
352 let mut j = rlst_dynamic_array!(f64, [2, 2, 2]);
353 let mut jdet = vec![0.0; 2];
354 let mut jinv = rlst_dynamic_array!(f64, [2, 2, 2]);
355 fill_jacobians(&mut j, &mut jdet, &mut jinv);
356
357 let mut physical_values = rlst_dynamic_array!(f64, [1, 2, 2, 2]);
358
359 map.push_forward(&values, 0, &j, &jdet, &jinv, &mut physical_values);
360
361 assert_relative_eq!(
362 *physical_values.get([0, 0, 0, 0]).unwrap(),
363 1.0,
364 epsilon = 1e-14
365 );
366 assert_relative_eq!(
367 *physical_values.get([0, 0, 0, 1]).unwrap(),
368 -1.0,
369 epsilon = 1e-14
370 );
371 assert_relative_eq!(
372 *physical_values.get([0, 1, 0, 0]).unwrap(),
373 0.0,
374 epsilon = 1e-14
375 );
376 assert_relative_eq!(
377 *physical_values.get([0, 1, 0, 1]).unwrap(),
378 1.0 / 3.0,
379 epsilon = 1e-14
380 );
381 assert_relative_eq!(
382 *physical_values.get([0, 0, 1, 0]).unwrap(),
383 0.5,
384 epsilon = 1e-14
385 );
386 assert_relative_eq!(
387 *physical_values.get([0, 0, 1, 1]).unwrap(),
388 1.0,
389 epsilon = 1e-14
390 );
391 assert_relative_eq!(
392 *physical_values.get([0, 1, 1, 0]).unwrap(),
393 1.0,
394 epsilon = 1e-14
395 );
396 assert_relative_eq!(
397 *physical_values.get([0, 1, 1, 1]).unwrap(),
398 2.0 / 3.0,
399 epsilon = 1e-14
400 );
401
402 values.set_zero();
403 map.pull_back(&physical_values, 0, &j, &jdet, &jinv, &mut values);
404
405 assert_relative_eq!(*values.get([0, 0, 0, 0]).unwrap(), 1.0, epsilon = 1e-14);
406 assert_relative_eq!(*values.get([0, 0, 0, 1]).unwrap(), 0.0, epsilon = 1e-14);
407 assert_relative_eq!(*values.get([0, 1, 0, 0]).unwrap(), 0.0, epsilon = 1e-14);
408 assert_relative_eq!(*values.get([0, 1, 0, 1]).unwrap(), 1.0, epsilon = 1e-14);
409 assert_relative_eq!(*values.get([0, 0, 1, 0]).unwrap(), 0.5, epsilon = 1e-14);
410 assert_relative_eq!(*values.get([0, 0, 1, 1]).unwrap(), 1.5, epsilon = 1e-14);
411 assert_relative_eq!(*values.get([0, 1, 1, 0]).unwrap(), 2.0, epsilon = 1e-14);
412 assert_relative_eq!(*values.get([0, 1, 1, 1]).unwrap(), 2.0, epsilon = 1e-14);
413 }
414
415 #[test]
416 fn test_contravariant_piola() {
417 let map = ContravariantPiolaMap {};
418 let mut values = rlst_dynamic_array!(f64, [1, 2, 2, 2]);
419 *values.get_mut([0, 0, 0, 0]).unwrap() = 1.0;
420 *values.get_mut([0, 0, 0, 1]).unwrap() = 0.0;
421 *values.get_mut([0, 1, 0, 0]).unwrap() = 0.0;
422 *values.get_mut([0, 1, 0, 1]).unwrap() = 1.0;
423 *values.get_mut([0, 0, 1, 0]).unwrap() = 0.5;
424 *values.get_mut([0, 0, 1, 1]).unwrap() = 1.5;
425 *values.get_mut([0, 1, 1, 0]).unwrap() = 2.0;
426 *values.get_mut([0, 1, 1, 1]).unwrap() = 2.0;
427
428 let mut j = rlst_dynamic_array!(f64, [2, 2, 2]);
429 let mut jdet = vec![0.0; 2];
430 let mut jinv = rlst_dynamic_array!(f64, [2, 2, 2]);
431 fill_jacobians(&mut j, &mut jdet, &mut jinv);
432
433 let mut physical_values = rlst_dynamic_array!(f64, [1, 2, 2, 2]);
434
435 map.push_forward(&values, 0, &j, &jdet, &jinv, &mut physical_values);
436
437 assert_relative_eq!(
438 *physical_values.get([0, 0, 0, 0]).unwrap(),
439 1.0,
440 epsilon = 1e-14
441 );
442 assert_relative_eq!(
443 *physical_values.get([0, 0, 0, 1]).unwrap(),
444 0.0,
445 epsilon = 1e-14
446 );
447 assert_relative_eq!(
448 *physical_values.get([0, 1, 0, 0]).unwrap(),
449 0.0,
450 epsilon = 1e-14
451 );
452 assert_relative_eq!(
453 *physical_values.get([0, 1, 0, 1]).unwrap(),
454 0.5,
455 epsilon = 1e-14
456 );
457 assert_relative_eq!(
458 *physical_values.get([0, 0, 1, 0]).unwrap(),
459 2.0,
460 epsilon = 1e-14
461 );
462 assert_relative_eq!(
463 *physical_values.get([0, 0, 1, 1]).unwrap(),
464 1.5,
465 epsilon = 1e-14
466 );
467 assert_relative_eq!(
468 *physical_values.get([0, 1, 1, 0]).unwrap(),
469 2.0 / 3.0,
470 epsilon = 1e-14
471 );
472 assert_relative_eq!(
473 *physical_values.get([0, 1, 1, 1]).unwrap(),
474 1.0,
475 epsilon = 1e-14
476 );
477
478 values.set_zero();
479 map.pull_back(&physical_values, 0, &j, &jdet, &jinv, &mut values);
480
481 assert_relative_eq!(*values.get([0, 0, 0, 0]).unwrap(), 1.0, epsilon = 1e-14);
482 assert_relative_eq!(*values.get([0, 0, 0, 1]).unwrap(), 0.0, epsilon = 1e-14);
483 assert_relative_eq!(*values.get([0, 1, 0, 0]).unwrap(), 0.0, epsilon = 1e-14);
484 assert_relative_eq!(*values.get([0, 1, 0, 1]).unwrap(), 1.0, epsilon = 1e-14);
485 assert_relative_eq!(*values.get([0, 0, 1, 0]).unwrap(), 0.5, epsilon = 1e-14);
486 assert_relative_eq!(*values.get([0, 0, 1, 1]).unwrap(), 1.5, epsilon = 1e-14);
487 assert_relative_eq!(*values.get([0, 1, 1, 0]).unwrap(), 2.0, epsilon = 1e-14);
488 assert_relative_eq!(*values.get([0, 1, 1, 1]).unwrap(), 2.0, epsilon = 1e-14);
489 }
490}