dzahui/solvers/fem/basis/two_variables/
polynomials_2d.rs

1// Internal dependencies
2use crate::solvers::basis::functions::{Function2D, Function2D2D, Composable2D, Differentiable2D};
3
4#[derive(PartialEq, Debug)]
5/// # General Information
6///
7/// A simple, first degree polynomial in two variables.
8///
9/// # Fields
10///
11/// * `x_coefficient` - constant that multiplies x variable.
12/// * `y_coefficient` - constant that multiplies y variable.
13/// * `independent_term` - constant that adds to variable.
14///
15pub struct FirstDegreePolynomial2D {
16    pub(crate) x_coefficient: f64,
17    pub(crate) y_coefficient: f64,
18    pub(crate) independent_term: f64
19}
20
21#[derive(PartialEq, Debug)]
22/// # General Information
23///
24/// A simple, second degree polynomial in two variables
25///
26/// # Fields
27///
28/// * `x_quadratic_coefficient` - constant that multiplies x quadratic term.
29/// * `y_quadratic_coefficient` - constant that multiplies y quadratic term.
30/// * `xy_coefficient` - constant that multiplies xy term.
31/// * `x_linear_coefficient` - constant that multiplies x linear term.
32/// * `y_linear_coefficient` - constant that multiplies y linear term.
33/// * `independent_term` - constant that is added to varaibles.
34///
35pub struct SecondDegreePolynomial2D {
36    x_quadratic_coefficient: f64,
37    y_quadratic_coefficient: f64,
38    xy_coefficient: f64,
39    x_linear_coefficient: f64,
40    y_linear_coefficient: f64,
41    independent_term: f64,
42}
43
44/// # General Information
45/// 
46/// Represents a matrix transformation in 2D. A normal matrix composed of vectors or arrays is not used since
47/// more control over the traits that are implemented on the struct makes latter implementations easier.
48/// 
49/// # Fields
50/// 
51/// * `a` - Element [0,0] in matrix
52/// * `b` - Element [0,1] in matrix
53/// * `c` - Element [1,0] in matrix
54/// * `d` - Element [1,1] in matrix
55/// 
56pub struct Transformation2D {
57    a: f64,
58    b: f64,
59    c: f64,
60    d: f64
61}
62
63impl Transformation2D {
64
65    ///  New instance
66    pub fn new(a: f64, b: f64, c: f64, d: f64) -> Transformation2D {
67        Transformation2D {
68            a,
69            b,
70            c,
71            d
72        }
73    }
74
75    /// Inverse of a  2x2 matrix
76    pub fn inverse(self) -> Transformation2D {
77        
78        let determinant = 1_f64 / (self.a * self.d - self.b * self.c);
79        
80        Transformation2D {
81             a: self.d * determinant,
82             b: - self.b * determinant,
83             c: - self.c * determinant,
84             d: self.a * determinant
85        }
86    }
87
88}
89
90impl Function2D2D for Transformation2D {
91    fn evaluate(&self, x: f64, y: f64) -> (f64,f64) {
92        (self.a * x + self.b * y, self.c * x + self.d * y)
93    }
94}
95
96
97impl FirstDegreePolynomial2D {
98    /// Normal constructor.
99    pub fn new(x_coefficient: f64, y_coefficient: f64, independent_term: f64) -> FirstDegreePolynomial2D {
100        FirstDegreePolynomial2D {
101            x_coefficient,
102            y_coefficient,
103            independent_term,
104        }
105    }
106
107    /// Zero function factory.
108    pub fn zero() -> FirstDegreePolynomial2D {
109        Self {
110            x_coefficient: 0_f64,
111            y_coefficient: 0_f64,
112            independent_term: 0_f64,
113        }
114    }
115
116    /// Constant function factory.
117    pub fn constant(independent_term: f64) -> FirstDegreePolynomial2D {
118        Self {
119            x_coefficient: 0_f64,
120            y_coefficient: 0_f64,
121            independent_term,
122        }
123    }
124
125    /// Translate a function by a given point
126    pub fn translate(self, w: f64, z: f64) -> FirstDegreePolynomial2D {
127        Self {
128            x_coefficient: self.x_coefficient,
129            y_coefficient: self.y_coefficient,
130            independent_term: self.independent_term - self.x_coefficient * w - self.y_coefficient * z,
131        }
132    } 
133
134    /// One of three basis functions on unit triangle {(0,0),(1,0),(0,1)}
135    pub fn psi_1() -> FirstDegreePolynomial2D {
136        FirstDegreePolynomial2D {
137            x_coefficient: -1_f64,
138            y_coefficient: -1_f64,
139            independent_term: 1_f64,
140        }
141    }
142
143    /// One of three basis functions on unit triangle {(0,0),(1,0),(0,1)}
144    pub fn psi_2() -> FirstDegreePolynomial2D {
145        FirstDegreePolynomial2D {
146            x_coefficient: 1_f64,
147            y_coefficient: 0_f64,
148            independent_term: 0_f64,
149        }
150    }
151
152    /// One of three basis functions on unit triangle {(0,0),(1,0),(0,1)}
153    pub fn psi_3() -> FirstDegreePolynomial2D {
154        FirstDegreePolynomial2D {
155            x_coefficient: 0_f64,
156            y_coefficient: 1_f64,
157            independent_term: 0_f64
158        }
159    }
160}
161
162impl Function2D for FirstDegreePolynomial2D {
163    fn evaluate(&self, x: f64, y: f64) -> f64 {
164        self.x_coefficient * x + self.y_coefficient * y + self.independent_term
165    }
166}
167
168impl Composable2D<Transformation2D, FirstDegreePolynomial2D> for FirstDegreePolynomial2D {
169    
170    fn compose(self, other: Transformation2D) -> Result<FirstDegreePolynomial2D,crate::Error> {
171
172        let x_coefficient = other.a * self.x_coefficient + other.c * self.y_coefficient;
173        let y_coefficient = other.b * self.x_coefficient + other.d *  self.y_coefficient;
174
175        Ok(FirstDegreePolynomial2D {
176            x_coefficient,
177            y_coefficient,
178            independent_term: self.independent_term,
179        })
180
181    }
182}
183
184impl Differentiable2D<FirstDegreePolynomial2D,FirstDegreePolynomial2D> for FirstDegreePolynomial2D {
185    
186    fn differentiate_x(&self) -> Result<FirstDegreePolynomial2D,crate::Error> {
187        Ok(
188            FirstDegreePolynomial2D {
189                x_coefficient: 0_f64,
190                y_coefficient: 0_f64,
191                independent_term: self.x_coefficient
192            }
193        )
194
195    }
196
197    fn differentiate_y(&self) -> Result<FirstDegreePolynomial2D,crate::Error> {
198        Ok(
199            FirstDegreePolynomial2D {
200                x_coefficient: 0_f64,
201                y_coefficient: 0_f64,
202                independent_term: self.y_coefficient
203            }
204        )
205
206    }
207}