Flow123d  master-130ae5c
fem_tools.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file mapping.hh
15  * @brief Class Mapping calculates data related to the mapping
16  * of the reference cell to the actual cell, such as Jacobian
17  * and normal vectors.
18  * @author Jan Stebel
19  */
20 
21 #ifndef MAPPING_HH_
22 #define MAPPING_HH_
23 
24 #include <armadillo>
25 #include <vector>
26 #include <limits>
27 #include "system/fmt/posix.h" // for FMT_UNUSED
28 
29 
30 
31 
32 //#include <Eigen/Core>
33 //#include <Eigen/Dense>
34 //
35 //template <unsigned int size>
36 //class VectorCol {
37 //public:
38 // typename Eigen::Array<double,size,1> data;
39 //
40 // VectorCol() {}
41 //
42 // VectorCol(FMT_UNUSED int n) {}
43 //
44 // inline double & operator[](std::size_t item) {
45 // return data[item];
46 // }
47 //
48 // inline double & operator()(std::size_t item) {
49 // return data[item];
50 // }
51 //
52 // inline VectorCol<size> operator+(const VectorCol<size> &other) const {
53 // VectorCol<size> res;
54 // res.data = this->data + other.data;
55 // return res;
56 // }
57 //
58 // /// Binary operator minus
59 // inline VectorCol<size> operator-(const VectorCol<size> &other) const {
60 // VectorCol<size> res;
61 // res.data = this->data - other.data;
62 // return res;
63 // }
64 //
65 // /// Unary operator minus
66 // inline VectorCol<size> operator-() const {
67 // VectorCol<size> res;
68 // res.data = - this->data;
69 // return res;
70 // }
71 //
72 // inline VectorCol<size> operator*(const double &coef) const {
73 // VectorCol<size> res;
74 // res.data = this->data * coef;
75 // return res;
76 // }
77 //
78 // inline VectorCol<size> operator/(const double &coef) const {
79 // VectorCol<size> res;
80 // res.data = this->data / coef;
81 // return res;
82 // }
83 //
84 // inline VectorCol<size> operator*(const VectorCol<size> &other) const {
85 // VectorCol<size> res;
86 // res.data = this->data * other.data;
87 // return res;
88 // }
89 //
90 // inline VectorCol<size> operator/(const VectorCol<size> &other) const {
91 // VectorCol<size> res;
92 // res.data = this->data / other.data;
93 // return res;
94 // }
95 //
96 // inline VectorCol<size> inverse() const {
97 // VectorCol<size> res;
98 // res.data = 1 / this->data;
99 // return res;
100 // }
101 //
102 // inline VectorCol<size> sqrt() const {
103 // VectorCol<size> res;
104 // res.data = this->data.abs().sqrt();
105 // return res;
106 // }
107 //
108 //};
109 //
110 //template class VectorCol<8>;
111 //template class VectorCol<200>;
112 //
113 //
114 //namespace Eigen {
115 // template<> struct NumTraits<VectorCol<8>> : GenericNumTraits<VectorCol<8>>
116 // {
117 // typedef VectorCol<8> Real;
118 // typedef VectorCol<8> NonInteger;
119 // typedef VectorCol<8> Nested;
120 //
121 // enum {
122 // IsInteger = 0,
123 // IsSigned = 1,
124 // IsComplex = 0,
125 // RequireInitialization = 1,
126 // ReadCost = 6,
127 // AddCost = 150,
128 // MulCost = 100
129 // };
130 // };
131 // template<> struct NumTraits<VectorCol<200>> : GenericNumTraits<VectorCol<200>>
132 // {
133 // typedef VectorCol<200> Real;
134 // typedef VectorCol<200> NonInteger;
135 // typedef VectorCol<200> Nested;
136 //
137 // enum {
138 // IsInteger = 0,
139 // IsSigned = 1,
140 // IsComplex = 0,
141 // RequireInitialization = 1,
142 // ReadCost = 6,
143 // AddCost = 150,
144 // MulCost = 100
145 // };
146 // };
147 //}
148 
149 
150 namespace fe_tools {
151 
152 
153 
154 /**
155  * @brief Calculates determinant of a rectangular matrix.
156  */
157 template<class T>
158 double determinant(const T &M);
159 
160 
161 
162 inline arma::mat::fixed<1,1> normal_matrix(const arma::mat::fixed<1,2> &A) {
163  arma::mat::fixed<1,1> res;
164  res(0,0) = A(0,0)*A(0,0)+A(0,1)*A(0,1);
165  return res;
166 }
167 
168 inline arma::mat::fixed<1,1> normal_matrix(const arma::mat::fixed<2,1> &A) {
169  arma::mat::fixed<1,1> res;
170  res(0,0) = A(0,0)*A(0,0)+A(1,0)*A(1,0);
171  return res;
172 }
173 
174 inline arma::mat::fixed<1,1> normal_matrix(const arma::mat::fixed<1,3> &A) {
175  arma::mat::fixed<1,1> res;
176  res(0,0) = A(0,0)*A(0,0)+A(0,1)*A(0,1)+A(0,2)*A(0,2);
177  return res;
178 }
179 
180 inline arma::mat::fixed<1,1> normal_matrix(const arma::mat::fixed<3,1> &A) {
181  arma::mat::fixed<1,1> res;
182  res(0,0) = A(0,0)*A(0,0)+A(1,0)*A(1,0)+A(2,0)*A(2,0);
183  return res;
184 }
185 
186 inline arma::mat::fixed<2,2> normal_matrix(const arma::mat::fixed<2,3> &A) {
187  arma::mat::fixed<2,2> res;
188  res(0,0) = A(0,0)*A(0,0)+A(0,1)*A(0,1)+A(0,2)*A(0,2);
189  res(0,1) = A(0,0)*A(1,0)+A(0,1)*A(1,1)+A(0,2)*A(1,2);
190  res(1,0) = A(1,0)*A(0,0)+A(1,1)*A(0,1)+A(1,2)*A(0,2);
191  res(1,1) = A(1,0)*A(1,0)+A(1,1)*A(1,1)+A(1,2)*A(1,2);
192  return res;
193 }
194 
195 inline arma::mat::fixed<2,2> normal_matrix(const arma::mat::fixed<3,2> &A) {
196  arma::mat::fixed<2,2> res;
197  res(0,0) = A(0,0)*A(0,0)+A(1,0)*A(1,0)+A(2,0)*A(2,0);
198  res(0,1) = A(0,0)*A(0,1)+A(1,0)*A(1,1)+A(2,0)*A(2,1);
199  res(1,0) = A(0,1)*A(0,0)+A(1,1)*A(1,0)+A(2,1)*A(2,0);
200  res(1,1) = A(0,1)*A(0,1)+A(1,1)*A(1,1)+A(2,1)*A(2,1);
201  return res;
202 }
203 
204 
205 
206 template<> inline double determinant(const arma::mat::fixed<1,1> &M)
207 {
208  return M(0,0);
209 }
210 
211 template<> inline double determinant(const arma::mat::fixed<2,2> &M)
212 {
213  return M(0,0)*M(1,1) - M(1,0)*M(0,1);
214 }
215 
216 template<> inline double determinant(const arma::mat::fixed<3,3> &M)
217 {
218  return ( M(0,0)*M(1,1)*M(2,2) + M(0,1)*M(1,2)*M(2,0) + M(0,2)*M(1,0)*M(2,1) )
219  - ( M(2,0)*M(1,1)*M(0,2) + M(2,1)*M(1,2)*M(0,0) + M(2,2)*M(1,0)*M(0,1) );
220 }
221 
222 template<> inline double determinant(FMT_UNUSED const arma::mat::fixed<0,3> &M)
223 {
224  return 0;
225 }
226 
227 template<> inline double determinant(FMT_UNUSED const arma::mat::fixed<3,0> &M)
228 {
229  return 0;
230 }
231 
232 template<> inline double determinant(const arma::mat::fixed<1,2> &M)
233 {
234  return sqrt( determinant(normal_matrix(M)) );
235 }
236 
237 template<> inline double determinant(const arma::mat::fixed<2,1> &M)
238 {
239  return sqrt( determinant(normal_matrix(M)) );
240 }
241 
242 template<> inline double determinant(const arma::mat::fixed<1,3> &M)
243 {
244  return sqrt( determinant(normal_matrix(M)) );
245 }
246 
247 template<> inline double determinant(const arma::mat::fixed<3,1> &M)
248 {
249  return sqrt( determinant(normal_matrix(M)) );
250 }
251 
252 template<> inline double determinant(const arma::mat::fixed<2,3> &M)
253 {
254  return sqrt( determinant(normal_matrix(M)) );
255 }
256 
257 template<> inline double determinant(const arma::mat::fixed<3,2> &M)
258 {
259  return sqrt( determinant(normal_matrix(M)) );
260 }
261 
262 
263 /**
264  * @brief Calculates inverse of rectangular matrix or pseudoinverse of non-rectangular matrix.
265  */
266 template<arma::uword m, arma::uword n>
267 arma::mat::fixed<n,m> inverse(const arma::mat::fixed<m,n> &A) {
268  if (m<n) return A.t() * inverse(normal_matrix(A));
269  else return inverse(normal_matrix(A)) * A.t();
270 }
271 
272 
273 template<> inline arma::mat::fixed<1,1> inverse(const arma::mat::fixed<1,1> &A)
274 {
275  arma::mat::fixed<1,1> B;
276  B(0,0) = 1/A(0,0);
277  return B;
278 }
279 
280 template<> inline arma::mat::fixed<2,2> inverse(const arma::mat::fixed<2,2> &A)
281 {
282  arma::mat::fixed<2,2> B;
283  double det = determinant(A);
284 
285  B(0,0) = A(1,1) / det;
286  B(0,1) = -A(0,1) / det;
287  B(1,0) = -A(1,0) / det;
288  B(1,1) = A(0,0) / det;
289  return B;
290 }
291 
292 template<> inline arma::mat::fixed<3,3> inverse(const arma::mat::fixed<3,3> &A)
293 {
294  arma::mat::fixed<3,3> B;
295 
296  B(0,0) = A(1,1)*A(2,2) - A(2,1)*A(1,2);
297  B(1,0) = -A(1,0)*A(2,2) + A(2,0)*A(1,2);
298  B(2,0) = A(1,0)*A(2,1) - A(2,0)*A(1,1);
299 
300  double det = A(0,0)*B(0,0) + A(0,1)*B(1,0) + A(0,2)*B(2,0);
301  B(0,0)/=det; B(1,0)/=det; B(2,0)/=det;
302 
303  B(0,1) = (-A(0,1)*A(2,2) + A(2,1)*A(0,2)) / det;
304  B(1,1) = (A(0,0)*A(2,2) - A(2,0)*A(0,2)) / det;
305  B(2,1) = (-A(0,0)*A(2,1) + A(2,0)*A(0,1)) / det;
306 
307  B(0,2) = (A(0,1)*A(1,2) - A(1,1)*A(0,2)) / det;
308  B(1,2) = (-A(0,0)*A(1,2) + A(1,0)*A(0,2)) / det;
309  B(2,2) = (A(0,0)*A(1,1) - A(1,0)*A(0,1)) / det;
310 
311  return B;
312 }
313 
314 
315 } // closing namespace fe_tools
316 
317 
318 
319 //namespace eigen_tools {
320 //
321 //// use only one of the following typedef
322 //typedef VectorCol<200> Vec200;
323 ////typedef Eigen::Array<double,200,1> Vec200;
324 //
325 //
326 //
327 ///**
328 // * @brief Calculates determinant of a rectangular matrix.
329 // */
330 //template<class T>
331 //Vec200 determinant(const T &M);
332 //
333 //
334 //
335 //inline Eigen::Matrix<Vec200,1,1> normal_matrix(const Eigen::Matrix<Vec200,1,2> &A) {
336 // Eigen::Matrix<Vec200,1,1> res;
337 // res(0,0) = A(0,0)*A(0,0)+A(0,1)*A(0,1);
338 // return res;
339 //}
340 //
341 //inline Eigen::Matrix<Vec200,1,1> normal_matrix(const Eigen::Matrix<Vec200,2,1> &A) {
342 // Eigen::Matrix<Vec200,1,1> res;
343 // res(0,0) = A(0,0)*A(0,0)+A(1,0)*A(1,0);
344 // return res;
345 //}
346 //
347 //inline Eigen::Matrix<Vec200,1,1> normal_matrix(const Eigen::Matrix<Vec200,1,3> &A) {
348 // Eigen::Matrix<Vec200,1,1> res;
349 // res(0,0) = A(0,0)*A(0,0)+A(0,1)*A(0,1)+A(0,2)*A(0,2);
350 // return res;
351 //}
352 //
353 //inline Eigen::Matrix<Vec200,1,1> normal_matrix(const Eigen::Matrix<Vec200,3,1> &A) {
354 // Eigen::Matrix<Vec200,1,1> res;
355 // res(0,0) = A(0,0)*A(0,0)+A(1,0)*A(1,0)+A(2,0)*A(2,0);
356 // return res;
357 //}
358 //
359 //inline Eigen::Matrix<Vec200,2,2> normal_matrix(const Eigen::Matrix<Vec200,2,3> &A) {
360 // Eigen::Matrix<Vec200,2,2> res;
361 // res(0,0) = A(0,0)*A(0,0)+A(0,1)*A(0,1)+A(0,2)*A(0,2);
362 // res(0,1) = A(0,0)*A(1,0)+A(0,1)*A(1,1)+A(0,2)*A(1,2);
363 // res(1,0) = A(1,0)*A(0,0)+A(1,1)*A(0,1)+A(1,2)*A(0,2);
364 // res(1,1) = A(1,0)*A(1,0)+A(1,1)*A(1,1)+A(1,2)*A(1,2);
365 // return res;
366 //}
367 //
368 //inline Eigen::Matrix<Vec200,2,2> normal_matrix(const Eigen::Matrix<Vec200,3,2> &A) {
369 // Eigen::Matrix<Vec200,2,2> res;
370 // res(0,0) = A(0,0)*A(0,0)+A(1,0)*A(1,0)+A(2,0)*A(2,0);
371 // res(0,1) = A(0,0)*A(0,1)+A(1,0)*A(1,1)+A(2,0)*A(2,1);
372 // res(1,0) = A(0,1)*A(0,0)+A(1,1)*A(1,0)+A(2,1)*A(2,0);
373 // res(1,1) = A(0,1)*A(0,1)+A(1,1)*A(1,1)+A(2,1)*A(2,1);
374 // return res;
375 //}
376 //
377 //
378 //
379 //template<> inline Vec200 determinant(const Eigen::Matrix<Vec200,1,1> &M)
380 //{
381 // return M(0,0);
382 //}
383 //
384 //template<> inline Vec200 determinant(const Eigen::Matrix<Vec200,2,2> &M)
385 //{
386 // return M(0,0)*M(1,1) - M(1,0)*M(0,1);
387 //}
388 //
389 //template<> inline Vec200 determinant(const Eigen::Matrix<Vec200,3,3> &M)
390 //{
391 // return ( M(0,0)*M(1,1)*M(2,2) + M(0,1)*M(1,2)*M(2,0) + M(0,2)*M(1,0)*M(2,1) )
392 // - ( M(2,0)*M(1,1)*M(0,2) + M(2,1)*M(1,2)*M(0,0) + M(2,2)*M(1,0)*M(0,1) );
393 //}
394 //
395 //template<> inline Vec200 determinant(FMT_UNUSED const Eigen::Matrix<Vec200,0,3> &M)
396 //{
397 // return Vec200();
398 //}
399 //
400 //template<> inline Vec200 determinant(FMT_UNUSED const Eigen::Matrix<Vec200,3,0> &M)
401 //{
402 // return Vec200();
403 //}
404 //
405 //template<> inline Vec200 determinant(const Eigen::Matrix<Vec200,1,2> &M)
406 //{
407 // return determinant(normal_matrix(M)).sqrt();
408 //}
409 //
410 //template<> inline Vec200 determinant(const Eigen::Matrix<Vec200,2,1> &M)
411 //{
412 // return determinant(normal_matrix(M)).sqrt();
413 //}
414 //
415 //template<> inline Vec200 determinant(const Eigen::Matrix<Vec200,1,3> &M)
416 //{
417 // return determinant(normal_matrix(M)).sqrt();
418 //}
419 //
420 //template<> inline Vec200 determinant(const Eigen::Matrix<Vec200,3,1> &M)
421 //{
422 // return determinant(normal_matrix(M)).sqrt();
423 //}
424 //
425 //template<> inline Vec200 determinant(const Eigen::Matrix<Vec200,2,3> &M)
426 //{
427 // return determinant(normal_matrix(M)).sqrt();
428 //}
429 //
430 //template<> inline Vec200 determinant(const Eigen::Matrix<Vec200,3,2> &M)
431 //{
432 // return determinant(normal_matrix(M)).sqrt();
433 //}
434 //
435 //
436 ///**
437 // * @brief Calculates inverse of rectangular matrix or pseudoinverse of non-rectangular matrix.
438 // */
439 //template<int m, int n>
440 //Eigen::Matrix<Vec200,n,m> inverse(const Eigen::Matrix<Vec200,m,n> &A) {
441 // // only for cases m > n
442 // return inverse(normal_matrix(A)) * A.transpose();
443 //}
444 //
445 //
446 //template<> inline Eigen::Matrix<Vec200,1,1> inverse<1,1>(const Eigen::Matrix<Vec200,1,1> &A)
447 //{
448 // Eigen::Matrix<Vec200,1,1> B;
449 // B(0,0) = A(0,0).inverse(); // 1/A(0,0)
450 // return B;
451 //}
452 //
453 //template<> inline Eigen::Matrix<Vec200,2,2> inverse<2,2>(const Eigen::Matrix<Vec200,2,2> &A)
454 //{
455 // Eigen::Matrix<Vec200,2,2> B;
456 // Vec200 det = determinant(A);
457 //
458 // B(0,0) = A(1,1) / det;
459 // B(0,1) = -A(0,1) / det;
460 // B(1,0) = -A(1,0) / det;
461 // B(1,1) = A(0,0) / det;
462 // return B;
463 //}
464 //
465 //template<> inline Eigen::Matrix<Vec200,3,3> inverse<3,3>(const Eigen::Matrix<Vec200,3,3> &A)
466 //{
467 // Eigen::Matrix<Vec200,3,3> B;
468 //
469 // B(0,0) = A(1,1)*A(2,2) - A(2,1)*A(1,2);
470 // B(0,1) = A(2,0)*A(1,2) - A(1,0)*A(2,2);
471 // B(0,2) = A(1,0)*A(2,1) - A(2,0)*A(1,1);
472 //
473 // Vec200 det = A(0,0)*B(0,0) + A(0,1)*B(0,1) + A(0,2)*B(0,2);
474 // B(0,0) = B(0,0) / det;
475 // B(0,1) = B(0,1) / det;
476 // B(0,2) = B(0,2) / det;
477 //
478 // B(1,0) = (A(2,1)*A(0,2) - A(0,1)*A(2,2)) / det;
479 // B(1,1) = (A(0,0)*A(2,2) - A(2,0)*A(0,2)) / det;
480 // B(1,2) = (A(2,0)*A(0,1) - A(0,0)*A(2,1)) / det;
481 //
482 // B(2,0) = (A(0,1)*A(1,2) - A(1,1)*A(0,2)) / det;
483 // B(2,1) = (A(1,0)*A(0,2) - A(0,0)*A(1,2)) / det;
484 // B(2,2) = (A(0,0)*A(1,1) - A(1,0)*A(0,1)) / det;
485 //
486 // return B;
487 //}
488 //
489 //template<> inline Eigen::Matrix<Vec200,2,1> inverse<1,2>(const Eigen::Matrix<Vec200,1,2> &A)
490 //{
491 // return A.transpose() * inverse(normal_matrix(A));
492 //}
493 //
494 //template<> inline Eigen::Matrix<Vec200,3,1> inverse<1,3>(const Eigen::Matrix<Vec200,1,3> &A)
495 //{
496 // return A.transpose() * inverse(normal_matrix(A));
497 //}
498 //
499 //template<> inline Eigen::Matrix<Vec200,3,2> inverse<2,3>(const Eigen::Matrix<Vec200,2,3> &A)
500 //{
501 // return A.transpose() * inverse(normal_matrix(A));
502 //}
503 //
504 //
505 //} // closing namespace eigen_tools
506 
507 
508 
509 #endif /* MAPPING_HH_ */
arma::mat::fixed< n, m > inverse(const arma::mat::fixed< m, n > &A)
Calculates inverse of rectangular matrix or pseudoinverse of non-rectangular matrix.
Definition: fem_tools.hh:267
arma::mat::fixed< 1, 1 > normal_matrix(const arma::mat::fixed< 1, 2 > &A)
Definition: fem_tools.hh:162
double determinant(const T &M)
Calculates determinant of a rectangular matrix.
#define FMT_UNUSED
Definition: posix.h:75