1use super::implicit_base::ImplicitModuleBase;
2use super::{ImplicitModule, ScalarParameter};
3
4use std::rc::Rc;
5use std::cell::RefCell;
6
7pub enum FunctionGradientAxis {
8 X,
9 Y,
10 Z,
11 W,
12 U,
13 V,
14}
15
16pub struct ImplicitFunctionGradient {
17 base: ImplicitModuleBase,
18 axis: FunctionGradientAxis,
19 source: ScalarParameter,
20 spacing: f64,
21}
22
23impl ImplicitFunctionGradient {
24 pub fn with_axis(a: FunctionGradientAxis) -> ImplicitFunctionGradient {
25 ImplicitFunctionGradient {
26 base: Default::default(),
27 source: ScalarParameter::Value(0.0),
28 axis: a,
29 spacing: 0.0,
30 }
31 }
32
33 pub fn set_axis(&mut self, a: FunctionGradientAxis) {
34 self.axis = a;
35 }
36 pub fn set_spacing(&mut self, s: f64) {
37 self.spacing = s;
38 }
39
40 pub fn set_source_module(&mut self, m: Rc<RefCell<ImplicitModule>>) {
41 self.source = ScalarParameter::Source(m);
42 }
43 pub fn set_source_value(&mut self, v: f64) {
44 self.source = ScalarParameter::Value(v);
45 }
46}
47
48impl ImplicitModule for ImplicitFunctionGradient {
49 fn get_2d(&mut self, x: f64, y: f64) -> f64 {
50 match self.axis {
51 FunctionGradientAxis::X => (self.source.get_2d(x - self.spacing, y) - self.source.get_2d(x + self.spacing, y)) / self.spacing,
52 FunctionGradientAxis::Y => (self.source.get_2d(x, y - self.spacing) - self.source.get_2d(x, y + self.spacing)) / self.spacing,
53 FunctionGradientAxis::Z => 0.0,
54 FunctionGradientAxis::W => 0.0,
55 FunctionGradientAxis::U => 0.0,
56 FunctionGradientAxis::V => 0.0,
57 }
58 }
59 fn get_3d(&mut self, x: f64, y: f64, z: f64) -> f64 {
60 match self.axis {
61 FunctionGradientAxis::X => (self.source.get_3d(x - self.spacing, y, z) - self.source.get_3d(x + self.spacing, y, z)) / self.spacing,
62 FunctionGradientAxis::Y => (self.source.get_3d(x, y - self.spacing, z) - self.source.get_3d(x, y + self.spacing, z)) / self.spacing,
63 FunctionGradientAxis::Z => (self.source.get_3d(x, y, z - self.spacing) - self.source.get_3d(x, y, z + self.spacing)) / self.spacing,
64 FunctionGradientAxis::W => 0.0,
65 FunctionGradientAxis::U => 0.0,
66 FunctionGradientAxis::V => 0.0,
67 }
68 }
69 fn get_4d(&mut self, x: f64, y: f64, z: f64, w: f64) -> f64 {
70 match self.axis {
71 FunctionGradientAxis::X => (self.source.get_4d(x - self.spacing, y, z, w) - self.source.get_4d(x + self.spacing, y, z, w)) / self.spacing,
72 FunctionGradientAxis::Y => (self.source.get_4d(x, y - self.spacing, z, w) - self.source.get_4d(x, y + self.spacing, z, w)) / self.spacing,
73 FunctionGradientAxis::Z => (self.source.get_4d(x, y, z - self.spacing, w) - self.source.get_4d(x, y, z + self.spacing, w)) / self.spacing,
74 FunctionGradientAxis::W => (self.source.get_4d(x, y, z, w - self.spacing) - self.source.get_4d(x, y, z, w + self.spacing)) / self.spacing,
75 FunctionGradientAxis::U => 0.0,
76 FunctionGradientAxis::V => 0.0,
77 }
78 }
79 fn get_6d(&mut self, x: f64, y: f64, z: f64, w: f64, u: f64, v: f64) -> f64 {
80 match self.axis {
81 FunctionGradientAxis::X => (self.source.get_6d(x - self.spacing, y, z, w, u, v) - self.source.get_6d(x + self.spacing, y, z, w, u, v)) / self.spacing,
82 FunctionGradientAxis::Y => (self.source.get_6d(x, y - self.spacing, z, w, u, v) - self.source.get_6d(x, y + self.spacing, z, w, u, v)) / self.spacing,
83 FunctionGradientAxis::Z => (self.source.get_6d(x, y, z - self.spacing, w, u, v) - self.source.get_6d(x, y, z + self.spacing, w, u, v)) / self.spacing,
84 FunctionGradientAxis::W => (self.source.get_6d(x, y, z, w - self.spacing, u, v) - self.source.get_6d(x, y, z, w + self.spacing, u, v)) / self.spacing,
85 FunctionGradientAxis::U => (self.source.get_6d(x, y, z, w, u - self.spacing, v) - self.source.get_6d(x, y, z, w, u + self.spacing, v)) / self.spacing,
86 FunctionGradientAxis::V => (self.source.get_6d(x, y, z, w, u, v - self.spacing) - self.source.get_6d(x, y, z, w, u, v + self.spacing)) / self.spacing,
87 }
88 }
89
90 fn spacing(&self) -> f64 {
91 self.base.spacing
92 }
93 fn set_deriv_spacing(&mut self, s: f64) {
94 self.base.spacing = s;
95 }
96}