FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
evaluator.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8#include <kernel/trafo/standard/evaluator.hpp>
9#include <kernel/geometry/atlas/chart.hpp>
10#include <kernel/cubature/scalar/gauss_legendre_driver.hpp>
11#include <kernel/cubature/scalar/newton_cotes_closed_driver.hpp>
12#include <kernel/cubature/scalar/newton_cotes_open_driver.hpp>
13#include <kernel/cubature/scalar/gauss_lobatto_driver.hpp>
14
15namespace FEAT
16{
17 namespace Trafo
18 {
19 namespace Isoparam
20 {
21 template<
22 typename Trafo_,
23 typename EvalPolicy_,
24 int degree_,
25 typename Shape_ = typename EvalPolicy_::ShapeType>
26 class Evaluator DOXY({});
27
28
30 namespace Intern
31 {
32 template<int n_>
33 struct Basis
34 {
35 // interpolation points
36 template<typename T_>
37 static inline void points(T_ v[])
38 {
39 static const T_ s = T_(2) / T_(n_);
40 for(int i(0); i <= n_; ++i)
41 v[i] *= (T_(i)*s - T_(1));
42 }
43
44 // basis function values for generic P_n
45 template<typename T_>
46 static inline void val(T_ v[], const T_ x)
47 {
48 static const T_ s = T_(2) / T_(n_);
49
50 for(int j(0); j <= n_; ++j)
51 {
52 v[j] = T_(1);
53 for(int i(0); i <= n_; ++i)
54 v[j] *= (i != j ? (T_(1) + x - T_(i)*s) / (T_(j)*s - T_(i)*s) : T_(1));
55 }
56 }
57
58 // first order derivatives
59 template<typename T_>
60 static inline void d1(T_ v[], const T_ x)
61 {
62 static const T_ s = T_(2) / T_(n_);
63
64 for(int j(0); j <= n_; ++j)
65 {
66 v[j] = T_(0);
67 for(int k(0); k <= n_; ++k)
68 {
69 if(k == j)
70 continue;
71 T_ t = T_(1);
72 for(int i(0); i <= n_; ++i)
73 t *= ((i != k) && (i != j) ? (T_(1) + x - T_(i)*s) / (T_(j)*s - T_(i)*s) : T_(1));
74 v[j] += t / (T_(j)*s - T_(k)*s);
75 }
76 }
77 }
78
79 // second order derivatives
80 template<typename T_>
81 static inline void d2(T_ v[], const T_ x)
82 {
83 static const T_ s = T_(2) / T_(n_);
84
85 for(int j(0); j <= n_; ++j)
86 {
87 v[j] = T_(0);
88 for(int k(0); k <= n_; ++k)
89 {
90 if(k == j)
91 continue;
92 T_ t = T_(0);
93 for(int i(0); i <= n_; ++i)
94 {
95 if((i == k) || (i == j))
96 continue;
97 T_ r = T_(1);
98 for(int l(0); l <= n_; ++l)
99 r *= ((l != k) && (l != j) && (l != i) ? (T_(1) + x - T_(l)*s) / (T_(j)*s - T_(l)*s) : T_(1));
100 t += r / (T_(j)*s - T_(i)*s);
101 }
102 v[j] += t / (T_(j)*s - T_(k)*s);
103 }
104 }
105 }
106 }; // struct Basis<n_>
107
108 template<>
109 struct Basis<1>
110 {
111 // interpolation points for P1
112 template<typename T_>
113 static inline void points(T_ v[])
114 {
115 v[0] = -T_(1);
116 v[1] = +T_(1);
117 }
118
119 // basis function values for P1
120 template<typename T_>
121 static inline void val(T_ v[], const T_ x)
122 {
123 v[0] = T_(0.5) * (T_(1) - x);
124 v[1] = T_(0.5) * (T_(1) + x);
125 }
126
127 // first order derivatives
128 template<typename T_>
129 static inline void d1(T_ v[], const T_)
130 {
131 v[0] = -T_(0.5);
132 v[1] = +T_(0.5);
133 }
134
135 // second order derivatives
136 template<typename T_>
137 static inline void d2(T_ v[], const T_)
138 {
139 v[0] = T_(0);
140 v[1] = T_(0);
141 }
142 }; // Basis<1>
143
144 template<>
145 struct Basis<2>
146 {
147 // interpolation points for P2
148 template<typename T_>
149 static inline void points(T_ v[])
150 {
151 v[0] = -T_(1);
152 v[1] = T_(0);
153 v[2] = +T_(1);
154 }
155
156 // basis function values for P2
157 template<typename T_>
158 static inline void val(T_ v[], const T_ x)
159 {
160 v[0] = T_(0.5) * x * (x - T_(1));
161 v[1] = (T_(1) - x) * (T_(1) + x);
162 v[2] = T_(0.5) * x * (x + T_(1));
163 }
164
165 // first order derivatives
166 template<typename T_>
167 static inline void d1(T_ v[], const T_ x)
168 {
169 v[0] = x - T_(0.5);
170 v[1] = -T_(2) * x;
171 v[2] = x + T_(0.5);
172 }
173
174 // second order derivatives
175 template<typename T_>
176 static inline void d2(T_ v[], const T_)
177 {
178 v[0] = T_(1);
179 v[1] = -T_(2);
180 v[2] = T_(1);
181 }
182 }; // Basis<2>
183
184 template<>
185 struct Basis<3>
186 {
187 // interpolation points for P3
188 template<typename T_>
189 static inline void points(T_ v[])
190 {
191 v[0] = -T_(1);
192 v[1] = -T_(1)/T_(3);
193 v[2] = +T_(1)/T_(3);
194 v[3] = +T_(1);
195 }
196
197 // basis function values for P3
198 template<typename T_>
199 static inline void val(T_ v[], const T_ x)
200 {
201 v[0] = T_(0.0625) * (-T_(1) + x*( T_(1) + T_(9)*x*(T_(1) - x)));
202 v[1] = T_(0.5625) * (T_(1) + x*(-T_(3) + x*(-T_(1) + T_(3)*x)));
203 v[2] = T_(0.5625) * (T_(1) + x*( T_(3) + x*(-T_(1) - T_(3)*x)));
204 v[3] = T_(0.0625) * (-T_(1) + x*(-T_(1) + T_(9)*x*(T_(1) + x)));
205 }
206
207 // first order derivatives
208 template<typename T_>
209 static inline void d1(T_ v[], const T_ x)
210 {
211 v[0] = T_(0.0625) * ( T_(1) + x*(T_(18) - T_(27)*x));
212 v[1] = T_(0.0625) * (-T_(27) + x*(-T_(18) + T_(81)*x));
213 v[2] = T_(0.0625) * ( T_(27) + x*(-T_(18) - T_(81)*x));
214 v[3] = T_(0.0625) * (-T_(1) + x*(T_(18) + T_(27)*x));
215 }
216
217 // second order derivatives
218 template<typename T_>
219 static inline void d2(T_ v[], const T_ x)
220 {
221 v[0] = T_(1.125) * (T_(1) - T_(3)*x);
222 v[1] = T_(1.125) * (-T_(1) + T_(9)*x);
223 v[2] = T_(1.125) * (-T_(1) - T_(9)*x);
224 v[3] = T_(1.125) * (T_(1) + T_(3)*x);
225 }
226 }; // Basis<3>
227
228 /*
229 // experimental: use Gauss-Quadrature points
230 template<>
231 struct Basis<3>
232 {
233 // interpolation points for P3
234 template<typename T_>
235 static inline void points(T_ v[])
236 {
237 v[0] = -T_(1);
238 v[1] = -(v[2] = Math::sqrt(T_(1)/T_(3)));
239 v[3] = +T_(1);
240 }
241
242 // basis function values for P3
243 template<typename T_>
244 static inline void val(T_ v[], const T_ x)
245 {
246 static const T_ S3 = Math::sqrt(T_(3));
247 v[0] = T_(0.25)*(-T_(1) + x*( T_(1) + T_(3)*x*(T_(1) - x)));
248 v[1] = T_(0.75)*( T_(1) + x*(-S3 + x*(-T_(1) + S3*x)));
249 v[2] = T_(0.75)*( T_(1) + x*( S3 + x*(-T_(1) - S3*x)));
250 v[3] = T_(0.25)*(-T_(1) + x*(-T_(1) + T_(3)*x*(T_(1) + x)));
251 }
252
253 // first order derivatives
254 template<typename T_>
255 static inline void d1(T_ v[], const T_ x)
256 {
257 static const T_ S3 = Math::sqrt(T_(3));
258 static const T_ S27 = Math::sqrt(T_(27));
259 v[0] = T_(0.25)*( T_(1) + x*(T_(6) - T_(9)*x));
260 v[1] = T_(0.75)*(-S3 + x*(-T_(2) + S27*x));
261 v[2] = T_(0.75)*( S3 + x*(-T_(2) - S27*x));
262 v[3] = T_(0.25)*(-T_(1) + x*(T_(6) + T_(9)*x));
263 }
264
265 // second order derivatives
266 template<typename T_>
267 static inline void d2(T_ v[], const T_ x)
268 {
269 static const T_ S27 = Math::sqrt(T_(27));
270 v[0] = T_(1.5)*( T_(1) - T_(3)*x);
271 v[1] = T_(1.5)*(-T_(1) + sqrt(27)*x);
272 v[2] = T_(1.5)*(-T_(1) - sqrt(27)*x);
273 v[3] = T_(1.5)*(-T_(1) + T_(3)*x);
274 }
275 }; // Basis<3>
276 */
277 } // namespace Intern
279
280 /* ************************************************************************************* */
281
287 template<
288 typename Trafo_,
289 typename EvalPolicy_,
290 int degree_>
291 class Evaluator<Trafo_, EvalPolicy_, degree_, Shape::Vertex > :
292 public EvaluatorBase<Trafo_, Evaluator<Trafo_, EvalPolicy_, degree_, Shape::Vertex >, EvalPolicy_>
293 {
294 public:
300 typedef Trafo_ TrafoType;
302 typedef EvalPolicy_ EvalPolicy;
303
305 typedef typename TrafoType::MeshType MeshType;
306
308 typedef typename EvalPolicy::DataType DataType;
310 typedef typename EvalPolicy::DomainPointType DomainPointType;
312 typedef typename EvalPolicy::ImagePointType ImagePointType;
314 typedef typename EvalPolicy::JacobianMatrixType JacobianMatrixType;
316 typedef typename EvalPolicy::JacobianInverseType JacobianInverseType;
318 typedef typename EvalPolicy::JacobianDeterminantType JacobianDeterminantType;
320 typedef typename EvalPolicy::HessianTensorType HessianTensorType;
322 typedef typename EvalPolicy::HessianInverseType HessianInverseType;
323
325 static constexpr int domain_dim = EvalPolicy::domain_dim;
327 static constexpr int image_dim = EvalPolicy::image_dim;
328
331
332 protected:
334 DataType _coeff[image_dim];
335
336 public:
343 explicit Evaluator(const TrafoType& trafo) :
344 BaseClass(trafo)
345 {
346 }
347
354 void prepare(Index cell_index)
355 {
356 // prepare base-class
357 BaseClass::prepare(cell_index);
358
359 // fetch the mesh from the trafo
360 const MeshType& mesh = this->_trafo.get_mesh();
361
362 // fetch the vertex set from the mesh
363 typedef typename MeshType::VertexSetType VertexSetType;
364 const VertexSetType& vertex_set = mesh.get_vertex_set();
365
366 // fetch the vertex
367 typedef typename VertexSetType::VertexType VertexType;
368 const VertexType& vtx = vertex_set[cell_index];
369
370 // calculate transformation coefficients
371 for(int i(0); i < image_dim; ++i)
372 {
373 _coeff[i] = DataType(vtx[i]);
374 }
375 }
376
387 {
388 for(int i(0); i < image_dim; ++i)
389 {
390 img_point[i] = _coeff[i];
391 }
392 }
393 }; // class Evaluator<Vertex,...>
394
395 /* ************************************************************************************* */
396
402 template<
403 typename Trafo_,
404 typename EvalPolicy_,
405 int degree_>
406 class Evaluator<Trafo_, EvalPolicy_, degree_, Shape::Hypercube<1> > :
407 public EvaluatorBase<Trafo_, Evaluator<Trafo_, EvalPolicy_, degree_, Shape::Hypercube<1> >, EvalPolicy_>
408 {
409 public:
415 typedef Trafo_ TrafoType;
417 typedef EvalPolicy_ EvalPolicy;
418
420 typedef typename TrafoType::MeshType MeshType;
423
425 typedef typename EvalPolicy::DataType DataType;
427 typedef typename EvalPolicy::DomainPointType DomainPointType;
429 typedef typename EvalPolicy::ImagePointType ImagePointType;
431 typedef typename EvalPolicy::JacobianMatrixType JacobianMatrixType;
433 typedef typename EvalPolicy::JacobianInverseType JacobianInverseType;
435 typedef typename EvalPolicy::JacobianDeterminantType JacobianDeterminantType;
437 typedef typename EvalPolicy::HessianTensorType HessianTensorType;
439 typedef typename EvalPolicy::HessianInverseType HessianInverseType;
440
442 static constexpr int domain_dim = EvalPolicy::domain_dim;
444 static constexpr int image_dim = EvalPolicy::image_dim;
445
448 static constexpr TrafoTags eval_caps =
451 (domain_dim == image_dim ? (TrafoTags::jac_inv | TrafoTags::hess_inv) : TrafoTags::none);
452
453 protected:
455 const std::vector<const ChartType*>& _charts;
458
459 public:
466 explicit Evaluator(const TrafoType& trafo) :
467 BaseClass(trafo),
468 _charts(trafo.get_charts_vector(1))
469 {
470 }
471
478 void prepare(Index cell_index)
479 {
480 // prepare base-class
481 BaseClass::prepare(cell_index);
482
483 // fetch the mesh from the trafo
484 const MeshType& mesh = this->_trafo.get_mesh();
485
486 // fetch the vertex set from the mesh
487 typedef typename MeshType::VertexSetType VertexSetType;
488 const VertexSetType& vertex_set = mesh.get_vertex_set();
489
490 // fetch the index set
491 typedef typename MeshType::template IndexSet<domain_dim, 0>::Type IndexSetType;
492 const IndexSetType& index_set = mesh.template get_index_set<domain_dim, 0>();
493
494 // for shorter indexing
495 static constexpr int n = degree_;
496
497 // store vertex points
498 _iso_coeff[0] = vertex_set[index_set(cell_index, 0)];
499 _iso_coeff[n] = vertex_set[index_set(cell_index, 1)];
500
501 // interpolate inner edge points linearly
502 //DataType v[degree_+1];
503 //Intern::Basis<degree_>::points(v);
504 for(int i(1); i < n; ++i)
505 _iso_coeff[i].set_convex(DataType(i) / DataType(n), _iso_coeff[0], _iso_coeff[n]);
506 //_iso_coeff[i].set_convex((v[i]+DataType(1))*DataType(0.5), _iso_coeff[0], _iso_coeff[n]);
507
508 // get chart for this edge
509 const ChartType* chart = _charts.at(cell_index);
510 if(chart != nullptr)
511 {
512 // loop over all inner edge points and project them
513 for(int i(1); i < degree_; ++i)
514 {
515 _iso_coeff[i] = chart->project(_iso_coeff[i]);
516 }
517 }
518 }
519
530 {
531 DataType v[degree_+1];
532 Intern::Basis<degree_>::val(v, dom_point[0]);
533
534 img_point.format();
535 for(int k(0); k <= degree_; ++k)
536 img_point.axpy(v[k], _iso_coeff[k]);
537 }
538
549 {
550 DataType v[degree_+1];
551
552 Intern::Basis<degree_>::d1(v, dom_point[0]);
553
554 jac_mat.format();
555 for(int k(0); k < image_dim; ++k)
556 {
557 for(int i(0); i <= degree_; ++i)
558 jac_mat(k,0) += v[i] * _iso_coeff[i][k];
559 }
560 }
561
572 {
573 DataType v[degree_+1];
574
575 Intern::Basis<degree_>::d2(v, dom_point[0]);
576
577 hess_ten.format();
578 for(int i(0); i < image_dim; ++i)
579 {
580 for(int k(0); k <= degree_; ++k)
581 hess_ten(i,0,0) += v[k] * _iso_coeff[k][i];
582 }
583 }
584
596 {
597 // for higher order, compute edge length by 3-point Gauss
598 if(degree_ > 2)
599 return volume_g3();
600
601 // first, compute the squared distance of the two edge end-points
602 const DataType a2 = (_iso_coeff[degree_] - _iso_coeff[0]).norm_euclid_sqr();
603 const DataType a = Math::sqrt(a2);
604
605 // degree = 1?
606 if(degree_ == 1)
607 return a;
608
609 // we're in the second degree case; so compute the squared distance between the edge midpoint
610 // and the midpoint between the two edge end-points
611 const DataType b2 = (_iso_coeff[1] - DataType(0.5) * (_iso_coeff[2] + _iso_coeff[0])).norm_euclid_sqr();
612
613 // if b2 = 0, then we have a straight edge, so its length is equal to a
614 if(b2 <= DataType(1E-5)*a2)
615 return a;
616
617 // now we have to compute the arc length of the polynomial (b/a^2)*x^2 over the interval [-a/2,+a/2],
618 // which can be computed by using the following magic formula:
619 const DataType b = DataType(4) * Math::sqrt(b2);
620 const DataType q = Math::sqrt(DataType(1) + DataType(16)*b2/a2);
621 return DataType(0.5) * a * (a * Math::log(q + b/a) / b + q);
622 }
623
634 {
635 // 3-point Gauss-Legendre coordinate
636 static const DataType G = DataType(FEAT_F128C(0.77459666924148337703585307995647992216658434105));
637
638 DataType v = DataType(0);
641
642 // use 2x2 Gauss-Legendre rule to integrate the area/volume
643 dom_point[0] = DataType(0);
644 this->calc_jac_mat(jac_mat, dom_point);
645 v += DataType(8) * jac_mat.vol();
646
647 dom_point[0] = -G;
648 this->calc_jac_mat(jac_mat, dom_point);
649 v += DataType(5) * jac_mat.vol();
650
651 dom_point[0] = +G;
652 this->calc_jac_mat(jac_mat, dom_point);
653 v += DataType(5) * jac_mat.vol();
654
655 return v / DataType(9);
656 }
657
670 {
671 XABORTM("cell width computation not available for isoparametric trafo");
672 return DataType(0);
673 }
674 }; // class Evaluator<Hypercube<1>,...>
675
676 /* ************************************************************************************* */
677
683 template<
684 typename Trafo_,
685 typename EvalPolicy_,
686 int degree_>
687 class Evaluator<Trafo_, EvalPolicy_, degree_, Shape::Hypercube<2> > :
688 public EvaluatorBase<Trafo_, Evaluator<Trafo_, EvalPolicy_, degree_, Shape::Hypercube<2> >, EvalPolicy_>
689 {
690 public:
696 typedef Trafo_ TrafoType;
698 typedef EvalPolicy_ EvalPolicy;
699
701 typedef typename TrafoType::MeshType MeshType;
702
705
707 typedef typename EvalPolicy::DataType DataType;
709 typedef typename EvalPolicy::DomainPointType DomainPointType;
711 typedef typename EvalPolicy::ImagePointType ImagePointType;
713 typedef typename EvalPolicy::JacobianMatrixType JacobianMatrixType;
715 typedef typename EvalPolicy::JacobianInverseType JacobianInverseType;
717 typedef typename EvalPolicy::JacobianDeterminantType JacobianDeterminantType;
719 typedef typename EvalPolicy::HessianTensorType HessianTensorType;
721 typedef typename EvalPolicy::HessianInverseType HessianInverseType;
722
724 static constexpr int domain_dim = EvalPolicy::domain_dim;
726 static constexpr int image_dim = EvalPolicy::image_dim;
727
730 static constexpr TrafoTags eval_caps =
733 (domain_dim == image_dim ? (TrafoTags::jac_inv | TrafoTags::hess_inv) : TrafoTags::none);
734
735 protected:
737 const std::vector<const ChartType*>& _charts_1;
738 const std::vector<const ChartType*>& _charts_2;
740 Tiny::Vector<DataType, image_dim> _iso_coeff[degree_+1][degree_+1];
741
742 public:
749 explicit Evaluator(const TrafoType& trafo) :
750 BaseClass(trafo),
751 _charts_1(trafo.get_charts_vector(1)),
752 _charts_2(trafo.get_charts_vector(2))
753 {
754 }
755
762 void prepare(Index cell_index)
763 {
764 // prepare base-class
765 BaseClass::prepare(cell_index);
766
767 // fetch the mesh from the trafo
768 const MeshType& mesh = this->_trafo.get_mesh();
769
770 // fetch the vertex set from the mesh
771 typedef typename MeshType::VertexSetType VertexSetType;
772 const VertexSetType& vertex_set = mesh.get_vertex_set();
773
774 // fetch the vertex-index set
775 typedef typename MeshType::template IndexSet<2, 0>::Type IndexSetType;
776 const IndexSetType& index_set = mesh.template get_index_set<2, 0>();
777
778 // fetch the edge-index set
779 typedef typename MeshType::template IndexSet<2, 1>::Type EdgeIndexSetType;
780 const EdgeIndexSetType& edges_at_quad = mesh.template get_index_set<2, 1>();
781
782 // for shorter indexing
783 static constexpr int n = degree_;
784
785 // store vertex points
786 _iso_coeff[0][0].convert(vertex_set[index_set(cell_index, 0)]);
787 _iso_coeff[0][n].convert(vertex_set[index_set(cell_index, 1)]);
788 _iso_coeff[n][0].convert(vertex_set[index_set(cell_index, 2)]);
789 _iso_coeff[n][n].convert(vertex_set[index_set(cell_index, 3)]);
790
791 // vN0---vNN
792 // | | ^ y
793 // | | |
794 // v00---v0N +--> x
795
796 // interpolate inner edge points linearly
797 //DataType v[degree_+1];
798 //Intern::Basis<degree_>::points(v);
799 for(int i(1); i < degree_; ++i)
800 {
801 const DataType alpha = DataType(i) / DataType(degree_);
802 //const DataType alpha = (v[i] + DataType(1)) * DataType(0.5);
803
804 // bottom edge
805 _iso_coeff[0][i].set_convex(alpha, _iso_coeff[0][0], _iso_coeff[0][n]);
806 // top edge
807 _iso_coeff[n][i].set_convex(alpha, _iso_coeff[n][0], _iso_coeff[n][n]);
808 // left edge
809 _iso_coeff[i][0].set_convex(alpha, _iso_coeff[0][0], _iso_coeff[n][0]);
810 // right edge
811 _iso_coeff[i][n].set_convex(alpha, _iso_coeff[0][n], _iso_coeff[n][n]);
812 }
813
814 // iso-coeff array index offsets and increments
815 const int ox[4] = {1, 1, 0, n};
816 const int oy[4] = {0, n, 1, 1};
817 const int ix[4] = {1, 1, 0, 0};
818 const int iy[4] = {0, 0, 1, 1};
819
820 // an auxiliary world point for conversion
821 typename ChartType::WorldPoint point;
822
823 // loop over all four edges of the element
824 for(int e = 0; e < 4; ++e)
825 {
826 // get global edge index
827 const Index edge_idx = edges_at_quad(cell_index, e);
828
829 // get chart for that edge
830 const ChartType* chart = _charts_1.at(edge_idx);
831
832 // no chart?
833 if(chart == nullptr)
834 continue;
835
836 // initialize indices for this edge
837 int y = oy[e];
838 int x = ox[e];
839
840 // loop over all edge points and project them
841 for(int k(1); k < degree_; ++k, y += iy[e], x += ix[e])
842 {
843 // _iso_coeff and point may have different data types
844 point.convert(_iso_coeff[y][x]);
845 point = chart->project(point);
846 _iso_coeff[y][x].convert(point);
847 }
848 }
849
851
852 // interpolate inner quad points bilinearly
853 for(int i(1); i < degree_; ++i)
854 {
855 const DataType alpha_v = DataType(i) / DataType(degree_);
856 //const DataType alpha_v = (v[i] + DataType(1)) * DataType(0.5);
857
858 for(int j(1); j < degree_; ++j)
859 {
860 const DataType alpha_h = DataType(j) / DataType(degree_);
861 //const DataType alpha_h = (v[j] + DataType(1)) * DataType(0.5);
862
863 // interpolate horizontally (between left and right edge)
864 p_horz.set_convex(alpha_h, _iso_coeff[i][0], _iso_coeff[i][n]);
865
866 // interpolate vertically between bottom and top edge
867 p_vert.set_convex(alpha_v, _iso_coeff[0][j], _iso_coeff[n][j]);
868
869 // combine both to obtain iso point
870 _iso_coeff[i][j].set_convex(DataType(0.5), p_horz, p_vert);
871 }
872 }
873
874 // get chart for this quad
875 const ChartType* chart = _charts_2.at(cell_index);
876 if(chart != nullptr)
877 {
878 // loop over all inner quad points and project them
879 for(int i(1); i < degree_; ++i)
880 {
881 for(int j(1); j < degree_; ++j)
882 {
883 // _iso_coeff and point may have different data types
884 point.convert(_iso_coeff[i][j]);
885 point = chart->project(point);
886 _iso_coeff[i][j].convert(point);
887 }
888 }
889 }
890 }
891
902 {
903 DataType vx[degree_+1], vy[degree_+1];
904 Intern::Basis<degree_>::val(vx, dom_point[0]);
905 Intern::Basis<degree_>::val(vy, dom_point[1]);
906
907 img_point.format();
908 for(int i(0); i <= degree_; ++i)
909 {
910 for(int j(0); j <= degree_; ++j)
911 img_point.axpy(vy[i]*vx[j], _iso_coeff[i][j]);
912 }
913 }
914
925 {
926 DataType vx[degree_+1], vy[degree_+1];
927 DataType dx[degree_+1], dy[degree_+1];
928
929 Intern::Basis<degree_>::val(vx, dom_point[0]);
930 Intern::Basis<degree_>::val(vy, dom_point[1]);
931 Intern::Basis<degree_>::d1(dx, dom_point[0]);
932 Intern::Basis<degree_>::d1(dy, dom_point[1]);
933
934 jac_mat.format();
935 for(int k(0); k < image_dim; ++k)
936 {
937 for(int i(0); i <= degree_; ++i)
938 {
939 for(int j(0); j <= degree_; ++j)
940 {
941 jac_mat(k,0) += vy[i] * dx[j] * _iso_coeff[i][j][k];
942 jac_mat(k,1) += dy[i] * vx[j] * _iso_coeff[i][j][k];
943 }
944 }
945 }
946 }
947
958 {
959 DataType vx[degree_+1], vy[degree_+1];
960 DataType dx[degree_+1], dy[degree_+1];
961 DataType qx[degree_+1], qy[degree_+1];
962
963 Intern::Basis<degree_>::val(vx, dom_point[0]);
964 Intern::Basis<degree_>::val(vy, dom_point[1]);
965 Intern::Basis<degree_>::d1(dx, dom_point[0]);
966 Intern::Basis<degree_>::d1(dy, dom_point[1]);
967 Intern::Basis<degree_>::d2(qx, dom_point[0]);
968 Intern::Basis<degree_>::d2(qy, dom_point[1]);
969
970 hess_ten.format();
971 for(int k(0); k < image_dim; ++k)
972 {
973 for(int i(0); i <= degree_; ++i)
974 {
975 for(int j(0); j <= degree_; ++j)
976 {
977 hess_ten(k,0,0) += vy[i] * qx[j] * _iso_coeff[i][j][k];
978 hess_ten(k,0,1) += dy[i] * dx[j] * _iso_coeff[i][j][k];
979 hess_ten(k,1,1) += qy[i] * vx[j] * _iso_coeff[i][j][k];
980 }
981 }
982 hess_ten(k,1,0) = hess_ten(k,0,1);
983 }
984 }
985
993 {
994 // 2-point Gauss-Legendre coordinate
995 static const DataType G = DataType(FEAT_F128C(0.57735026918962576450914878050195745564760175127));
996
997 DataType v = DataType(0);
1000
1001 // use 2x2 Gauss-Legendre rule to integrate the area/volume
1002 for(int i(0); i < 2; ++i)
1003 {
1004 dom_point[0] = DataType(2*i-1) * G;
1005 for(int j(0); j < 2; ++j)
1006 {
1007 dom_point[1] = DataType(2*j-1) * G;
1008 this->calc_jac_mat(jac_mat, dom_point);
1009 v += jac_mat.vol();
1010 }
1011 }
1012 return v;
1013 }
1014
1030 {
1033 DomainPointType ref_ray, cub_pt;
1034 cub_pt = DataType(0);
1035
1036 // compute jacobian matrix at barycentre
1037 calc_jac_mat(jac_mat, cub_pt);
1038
1039 // invert jacobian matrix and multiply by ray vector
1040 jac_inv.set_inverse(jac_mat);
1041 ref_ray.set_mat_vec_mult(jac_inv, ray);
1042
1043 // return scaled inverse ray norm
1044 return DataType(2) / ref_ray.norm_euclid();
1045 }
1046 }; // class Evaluator<Hypercube<2>,...>
1047
1048 /* ************************************************************************************* */
1049
1055 template<
1056 typename Trafo_,
1057 typename EvalPolicy_,
1058 int degree_>
1059 class Evaluator<Trafo_, EvalPolicy_, degree_, Shape::Hypercube<3> > :
1060 public EvaluatorBase<Trafo_, Evaluator<Trafo_, EvalPolicy_, degree_, Shape::Hypercube<3> >, EvalPolicy_>
1061 {
1062 public:
1068 typedef Trafo_ TrafoType;
1070 typedef EvalPolicy_ EvalPolicy;
1071
1073 typedef typename TrafoType::MeshType MeshType;
1074
1077
1079 typedef typename EvalPolicy::DataType DataType;
1081 typedef typename EvalPolicy::DomainPointType DomainPointType;
1083 typedef typename EvalPolicy::ImagePointType ImagePointType;
1085 typedef typename EvalPolicy::JacobianMatrixType JacobianMatrixType;
1087 typedef typename EvalPolicy::JacobianInverseType JacobianInverseType;
1089 typedef typename EvalPolicy::JacobianDeterminantType JacobianDeterminantType;
1091 typedef typename EvalPolicy::HessianTensorType HessianTensorType;
1093 typedef typename EvalPolicy::HessianInverseType HessianInverseType;
1094
1096 static constexpr int domain_dim = EvalPolicy::domain_dim;
1098 static constexpr int image_dim = EvalPolicy::image_dim;
1099
1102 static constexpr TrafoTags eval_caps =
1105 (domain_dim == image_dim ? (TrafoTags::jac_inv | TrafoTags::hess_inv) : TrafoTags::none);
1106
1107 protected:
1109 const std::vector<const ChartType*>& _charts_1;
1110 const std::vector<const ChartType*>& _charts_2;
1111 const std::vector<const ChartType*>& _charts_3;
1113 Tiny::Vector<DataType, image_dim> _iso_coeff[degree_+1][degree_+1][degree_+1];
1114
1115 // auxiliary helper functions for convex combinations:
1116
1117 // q <- u1 + x*(u2-u1)
1118 template<typename T_, typename C_>
1119 static void _c1(C_& q, T_ x, const C_& u1, const C_& u2)
1120 {
1121 for(int i(0); i < C_::n; ++i)
1122 q[i] = u1[i] + x * (u2[i] - u1[i]);
1123 }
1124
1125 // q <- 1/2 * (u1 + v1 + x*(u2-u1) + y*(v2-v1))
1126 template<typename T_, typename C_>
1127 static void _c2(C_& q, T_ x, const C_& u1, const C_& u2, T_ y, const C_& v1, const C_& v2)
1128 {
1129 for(int i(0); i < C_::n; ++i)
1130 q[i] = T_(0.5) * (u1[i] + v1[i] + x * (u2[i] - u1[i]) + y * (v2[i] - v1[i]));
1131 }
1132
1133 // q <- 1/3 * (u1 + v1 + w1 + x*(u2-u1) + y*(v2-v1) + z*(w2-w1))
1134 template<typename T_, typename C_>
1135 static void _c3(C_& q, T_ x, const C_& u1, const C_& u2, T_ y, const C_& v1, const C_& v2, T_ z, const C_& w1, const C_& w2)
1136 {
1137 for(int i(0); i < C_::n; ++i)
1138 q[i] = (u1[i] + v1[i] + w1[i] + x * (u2[i] - u1[i]) + y * (v2[i] - v1[i]) + z * (w2[i] - w1[i])) / T_(3);
1139 }
1140
1141 public:
1148 explicit Evaluator(const TrafoType& trafo) :
1149 BaseClass(trafo),
1150 _charts_1(trafo.get_charts_vector(1)),
1151 _charts_2(trafo.get_charts_vector(2)),
1152 _charts_3(trafo.get_charts_vector(3))
1153 {
1154 }
1155
1162 void prepare(Index cell_index)
1163 {
1164 // prepare base-class
1165 BaseClass::prepare(cell_index);
1166
1167 // fetch the mesh from the trafo
1168 const MeshType& mesh = this->_trafo.get_mesh();
1169
1170 // fetch the vertex set from the mesh
1171 typedef typename MeshType::VertexSetType VertexSetType;
1172 const VertexSetType& vertex_set = mesh.get_vertex_set();
1173
1174 // fetch the vertex-index set
1175 typedef typename MeshType::template IndexSet<3, 0>::Type IndexSetType;
1176 const IndexSetType& index_set = mesh.template get_index_set<3, 0>();
1177
1178 // fetch the edge-index set
1179 typedef typename MeshType::template IndexSet<3, 1>::Type EdgeIndexSetType;
1180 const EdgeIndexSetType& edges_at_hexa = mesh.template get_index_set<3, 1>();
1181
1182 // fetch the quad-index set
1183 typedef typename MeshType::template IndexSet<3, 2>::Type QuadIndexSetType;
1184 const QuadIndexSetType& quads_at_hexa = mesh.template get_index_set<3, 2>();
1185
1186 // for shorter indexing
1187 static constexpr int n = degree_;
1188
1189 // store vertex points
1190 _iso_coeff[0][0][0].convert(vertex_set[index_set(cell_index, 0)]);
1191 _iso_coeff[0][0][n].convert(vertex_set[index_set(cell_index, 1)]);
1192 _iso_coeff[0][n][0].convert(vertex_set[index_set(cell_index, 2)]);
1193 _iso_coeff[0][n][n].convert(vertex_set[index_set(cell_index, 3)]);
1194 _iso_coeff[n][0][0].convert(vertex_set[index_set(cell_index, 4)]);
1195 _iso_coeff[n][0][n].convert(vertex_set[index_set(cell_index, 5)]);
1196 _iso_coeff[n][n][0].convert(vertex_set[index_set(cell_index, 6)]);
1197 _iso_coeff[n][n][n].convert(vertex_set[index_set(cell_index, 7)]);
1198
1199 // vNN0------vNNN
1200 // ./'| ./'|
1201 // vN00------vN0N |
1202 // | | | | z
1203 // | v0N0----|-v0NN ^ y
1204 // |./' |./' |./'
1205 // v000------v00N +--> x
1206
1207 // interpolate inner edge points linearly
1208 for(int i(1); i < degree_; ++i)
1209 {
1210 const DataType alpha = DataType(i) / DataType(degree_);
1211
1212 // edges parallel to X axis
1213 // 00x edge
1214 _c1(_iso_coeff[0][0][i], alpha, _iso_coeff[0][0][0], _iso_coeff[0][0][n]);
1215 // 0Nx edge
1216 _c1(_iso_coeff[0][n][i], alpha, _iso_coeff[0][n][0], _iso_coeff[0][n][n]);
1217 // N0x edge
1218 _c1(_iso_coeff[n][0][i], alpha, _iso_coeff[n][0][0], _iso_coeff[n][0][n]);
1219 // NNx edge
1220 _c1(_iso_coeff[n][n][i], alpha, _iso_coeff[n][n][0], _iso_coeff[n][n][n]);
1221
1222 // edges parallel to Y axis
1223 // 0y0 edge
1224 _c1(_iso_coeff[0][i][0], alpha, _iso_coeff[0][0][0], _iso_coeff[0][n][0]);
1225 // 0yN edge
1226 _c1(_iso_coeff[0][i][n], alpha, _iso_coeff[0][0][n], _iso_coeff[0][n][n]);
1227 // Ny0 edge
1228 _c1(_iso_coeff[n][i][0], alpha, _iso_coeff[n][0][0], _iso_coeff[n][n][0]);
1229 // NyN edge
1230 _c1(_iso_coeff[n][i][n], alpha, _iso_coeff[n][0][n], _iso_coeff[n][n][n]);
1231
1232 // edges parallel to Z axis
1233 // z00 edge
1234 _c1(_iso_coeff[i][0][0], alpha, _iso_coeff[0][0][0], _iso_coeff[n][0][0]);
1235 // z0N edge
1236 _c1(_iso_coeff[i][0][n], alpha, _iso_coeff[0][0][n], _iso_coeff[n][0][n]);
1237 // zN0 edge
1238 _c1(_iso_coeff[i][n][0], alpha, _iso_coeff[0][n][0], _iso_coeff[n][n][0]);
1239 // zNN edge
1240 _c1(_iso_coeff[i][n][n], alpha, _iso_coeff[0][n][n], _iso_coeff[n][n][n]);
1241 }
1242
1243 // iso-coeff array index offsets and increments
1244 const int eox[12] = {1, 1, 1, 1, 0, n, 0, n, 0, n, 0, n};
1245 const int eoy[12] = {0, n, 0, n, 1, 1, 1, 1, 0, 0, n, n};
1246 const int eoz[12] = {0, 0, n, n, 0, 0, n, n, 1, 1, 1, 1};
1247 const int eix[12] = {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
1248 const int eiy[12] = {0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0};
1249 const int eiz[12] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1};
1250
1251 // an auxiliary world point for conversion
1252 typename ChartType::WorldPoint point;
1253
1254 // loop over all twelve edges of the element
1255 for(int e = 0; e < 12; ++e)
1256 {
1257 // get global edge index
1258 const Index edge_idx = edges_at_hexa(cell_index, e);
1259
1260 // get chart for that edge
1261 const ChartType* chart = _charts_1.at(edge_idx);
1262
1263 // no chart?
1264 if(chart == nullptr)
1265 continue;
1266
1267 // initialize indices for this edge
1268 int z = eoz[e];
1269 int y = eoy[e];
1270 int x = eox[e];
1271
1272 // loop over all edge points and project them
1273 for(int i(1); i < degree_; ++i, z += eiz[e], y += eiy[e], x += eix[e])
1274 {
1275 //_iso_coeff[z][y][x] = chart->project(_iso_coeff[z][y][x]);
1276 point.convert(_iso_coeff[z][y][x]);
1277 point = chart->project(point);
1278 _iso_coeff[z][y][x].convert(point);
1279 }
1280 }
1281
1282 // interpolate inner quad points bilinearly
1283 for(int i(1); i < degree_; ++i)
1284 {
1285 const DataType alpha_i = DataType(i) / DataType(degree_);
1286
1287 for(int j(1); j < degree_; ++j)
1288 {
1289 const DataType alpha_j = DataType(j) / DataType(degree_);
1290
1291 // quads parallel to XY plane
1292 _c2(_iso_coeff[0][i][j],
1293 alpha_i, _iso_coeff[0][0][j], _iso_coeff[0][n][j],
1294 alpha_j, _iso_coeff[0][i][0], _iso_coeff[0][i][n]);
1295 _c2(_iso_coeff[n][i][j],
1296 alpha_i, _iso_coeff[n][0][j], _iso_coeff[n][n][j],
1297 alpha_j, _iso_coeff[n][i][0], _iso_coeff[n][i][n]);
1298
1299 // quads parallel to XZ plane
1300 _c2(_iso_coeff[i][0][j],
1301 alpha_i, _iso_coeff[0][0][j], _iso_coeff[n][0][j],
1302 alpha_j, _iso_coeff[i][0][0], _iso_coeff[i][0][n]);
1303 _c2(_iso_coeff[i][n][j],
1304 alpha_i, _iso_coeff[0][n][j], _iso_coeff[n][n][j],
1305 alpha_j, _iso_coeff[i][n][0], _iso_coeff[i][n][n]);
1306
1307 // quads parallel to YZ plane
1308 _c2(_iso_coeff[i][j][0],
1309 alpha_i, _iso_coeff[0][j][0], _iso_coeff[n][j][0],
1310 alpha_j, _iso_coeff[i][0][0], _iso_coeff[i][n][0]);
1311 _c2(_iso_coeff[i][j][n],
1312 alpha_i, _iso_coeff[0][j][n], _iso_coeff[n][j][n],
1313 alpha_j, _iso_coeff[i][0][n], _iso_coeff[i][n][n]);
1314 }
1315 }
1316
1317 // iso-coeff array index offsets and i/j increments
1318 const int qox[6] = {1, 1, 1, 1, 0, n};
1319 const int qoy[6] = {1, 1, 0, n, 1, 1};
1320 const int qoz[6] = {0, n, 1, 1, 1, 1};
1321 const int qix[6] = {0, 0, 0, 0, 0, 0};
1322 const int qjx[6] = {1, 1, 1, 1, 0, 0};
1323 const int qiy[6] = {1, 1, 0, 0, 0, 0};
1324 const int qjy[6] = {0, 0, 0, 0, 1, 1};
1325 const int qiz[6] = {0, 0, 1, 1, 1, 1};
1326 const int qjz[6] = {0, 0, 0, 0, 0, 0};
1327
1328 // loop over all six quads of the element
1329 for(int q = 0; q < 6; ++q)
1330 {
1331 // get global quad index
1332 const Index quad_idx = quads_at_hexa(cell_index, q);
1333
1334 // get chart for that quad
1335 const ChartType* chart = _charts_2.at(quad_idx);
1336
1337 // no chart?
1338 if(chart == nullptr)
1339 continue;
1340
1341 // initialize indices for this quad
1342 int z = qoz[q];
1343 int y = qoy[q];
1344 int x = qox[q];
1345
1346 // loop over all inner quad points and project them
1347 for(int i(1); i < degree_; ++i, z += qiz[q], y += qiy[q], x += qix[q])
1348 {
1349 for(int j(1); j < degree_; ++j, z += qjz[q], y += qjy[q], x += qjx[q])
1350 {
1351 //_iso_coeff[z][y][x] = chart->project(_iso_coeff[z][y][x]);
1352 point.convert(_iso_coeff[z][y][x]);
1353 point = chart->project(point);
1354 _iso_coeff[z][y][x].convert(point);
1355 }
1356 }
1357 }
1358
1359 // interpolate inner hexa points linearly
1360 for(int i(1); i < degree_; ++i)
1361 {
1362 const DataType alpha_i = DataType(i) / DataType(degree_);
1363 for(int j(1); j < degree_; ++j)
1364 {
1365 const DataType alpha_j = DataType(j) / DataType(degree_);
1366 for(int k(1); k < degree_; ++k)
1367 {
1368 const DataType alpha_k = DataType(k) / DataType(degree_);
1369 _c3(_iso_coeff[i][j][k],
1370 alpha_i, _iso_coeff[0][j][k], _iso_coeff[n][j][k],
1371 alpha_j, _iso_coeff[i][0][k], _iso_coeff[i][n][k],
1372 alpha_k, _iso_coeff[i][j][0], _iso_coeff[i][j][n]);
1373 }
1374 }
1375 }
1376
1377 // get chart for this hexa
1378 const ChartType* chart = _charts_3.at(cell_index);
1379 if(chart != nullptr)
1380 {
1381 // loop over all inner hexa points and project them
1382 for(int i(1); i < degree_; ++i)
1383 {
1384 for(int j(1); j < degree_; ++j)
1385 {
1386 for(int k(1); k < degree_; ++k)
1387 {
1388 //_iso_coeff[i][j][k] = chart->project(_iso_coeff[i][j][k]);
1389 point.convert(_iso_coeff[i][j][k]);
1390 point = chart->project(point);
1391 _iso_coeff[i][j][k].convert(point);
1392 }
1393 }
1394 }
1395 }
1396 }
1397
1408 {
1409 DataType vx[degree_+1], vy[degree_+1], vz[degree_+1];
1410 Intern::Basis<degree_>::val(vx, dom_point[0]);
1411 Intern::Basis<degree_>::val(vy, dom_point[1]);
1412 Intern::Basis<degree_>::val(vz, dom_point[2]);
1413
1414 img_point.format();
1415 for(int i(0); i <= degree_; ++i)
1416 {
1417 for(int j(0); j <= degree_; ++j)
1418 {
1419 for(int k(0); k <= degree_; ++k)
1420 {
1421 img_point.axpy(vz[i]*vy[j]*vx[k], _iso_coeff[i][j][k]);
1422 }
1423 }
1424 }
1425 }
1426
1437 {
1438 DataType vx[degree_+1], vy[degree_+1], vz[degree_+1];
1439 DataType dx[degree_+1], dy[degree_+1], dz[degree_+1];
1440
1441 Intern::Basis<degree_>::val(vx, dom_point[0]);
1442 Intern::Basis<degree_>::val(vy, dom_point[1]);
1443 Intern::Basis<degree_>::val(vz, dom_point[2]);
1444 Intern::Basis<degree_>::d1(dx, dom_point[0]);
1445 Intern::Basis<degree_>::d1(dy, dom_point[1]);
1446 Intern::Basis<degree_>::d1(dz, dom_point[2]);
1447
1448 jac_mat.format();
1449 for(int l(0); l < image_dim; ++l)
1450 {
1451 for(int i(0); i <= degree_; ++i)
1452 {
1453 for(int j(0); j <= degree_; ++j)
1454 {
1455 for(int k(0); k <= degree_; ++k)
1456 {
1457 jac_mat(l,0) += vz[i] * vy[j] * dx[k] * _iso_coeff[i][j][k][l];
1458 jac_mat(l,1) += vz[i] * dy[j] * vx[k] * _iso_coeff[i][j][k][l];
1459 jac_mat(l,2) += dz[i] * vy[j] * vx[k] * _iso_coeff[i][j][k][l];
1460 }
1461 }
1462 }
1463 }
1464 }
1465
1476 {
1477 DataType vx[degree_+1], vy[degree_+1], vz[degree_+1];
1478 DataType dx[degree_+1], dy[degree_+1], dz[degree_+1];
1479 DataType qx[degree_+1], qy[degree_+1], qz[degree_+1];
1480
1481 Intern::Basis<degree_>::val(vx, dom_point[0]);
1482 Intern::Basis<degree_>::val(vy, dom_point[1]);
1483 Intern::Basis<degree_>::val(vz, dom_point[2]);
1484 Intern::Basis<degree_>::d1(dx, dom_point[0]);
1485 Intern::Basis<degree_>::d1(dy, dom_point[1]);
1486 Intern::Basis<degree_>::d1(dz, dom_point[2]);
1487 Intern::Basis<degree_>::d2(qx, dom_point[0]);
1488 Intern::Basis<degree_>::d2(qy, dom_point[1]);
1489 Intern::Basis<degree_>::d2(qz, dom_point[2]);
1490
1491 hess_ten.format();
1492 for(int l(0); l < image_dim; ++l)
1493 {
1494 for(int i(0); i <= degree_; ++i)
1495 {
1496 for(int j(0); j <= degree_; ++j)
1497 {
1498 for(int k(0); k <= degree_; ++k)
1499 {
1500 hess_ten(l,0,0) += vz[i] * vy[j] * qx[k] * _iso_coeff[i][j][k][l];
1501 hess_ten(l,0,1) += vz[i] * dy[j] * dx[k] * _iso_coeff[i][j][k][l];
1502 hess_ten(l,0,2) += dz[i] * vy[j] * dx[k] * _iso_coeff[i][j][k][l];
1503 hess_ten(l,1,1) += vz[i] * qy[j] * vx[k] * _iso_coeff[i][j][k][l];
1504 hess_ten(l,1,2) += dz[i] * dy[j] * vx[k] * _iso_coeff[i][j][k][l];
1505 hess_ten(l,2,2) += qz[i] * vy[j] * vx[k] * _iso_coeff[i][j][k][l];
1506 }
1507 }
1508 }
1509 hess_ten(l,1,0) = hess_ten(l,0,1);
1510 hess_ten(l,2,0) = hess_ten(l,0,2);
1511 hess_ten(l,2,1) = hess_ten(l,1,2);
1512 }
1513 }
1514
1522 {
1523 // 2-point Gauss-Legendre coordinate
1524 const DataType cx = DataType(FEAT_F128C(0.57735026918962576450914878050195745564760175127));
1525
1527 DomainPointType cub_pt;
1528 DataType vol = DataType(0);
1529
1530 // loop over all 8 cubature points
1531 for(int i(0); i < 8; ++i)
1532 {
1533 // set cubature point coords by magic bitshifts
1534 for(int j(0); j < 3; ++j)
1535 cub_pt[j] = DataType((((i >> j) & 1) << 1) - 1) * cx;
1536
1537 // compute jacobian matrix and add its volume
1538 calc_jac_mat(jac_mat, cub_pt);
1539 vol += jac_mat.vol();
1540 }
1541
1542 return vol;
1543 }
1544
1560 {
1563 DomainPointType ref_ray, cub_pt;
1564 cub_pt = DataType(0);
1565
1566 // compute jacobian matrix at barycentre
1567 calc_jac_mat(jac_mat, cub_pt);
1568
1569 // invert jacobian matrix and multiply by ray vector
1570 jac_inv.set_inverse(jac_mat);
1571 ref_ray.set_mat_vec_mult(jac_inv, ray);
1572
1573 // return scaled inverse ray norm
1574 return DataType(2) / ref_ray.norm_euclid();
1575 }
1576 }; // class Evaluator<Hypercube<3>,...>
1577 } // namespace Isoparam
1578 } // namespace Trafo
1579} // namespace FEAT
#define XABORTM(msg)
Abortion macro definition with custom message.
Definition: assertion.hpp:192
VertexSetType::VertexType WorldPoint
Type of a single vertex.
Definition: chart.hpp:41
Tiny Vector class template.
CUDA_HOST_DEVICE Vector & set_convex(DataType alpha, const Vector< T_, n_, sna_ > &a, const Vector< T_, n_, snb_ > &b)
Sets this vector to the convex combination of two other vectors.
CUDA_HOST_DEVICE void convert(const Vector< Tx_, n_, sx_ > &x)
conversion operator
Trafo Evaluator CRTP base-class template.
EvalPolicy::JacobianInverseType JacobianInverseType
jacobian inverse matrix type
Definition: evaluator.hpp:1087
EvalPolicy::HessianInverseType HessianInverseType
hessian inverse tensor type
Definition: evaluator.hpp:1093
void calc_hess_ten(HessianTensorType &hess_ten, const DomainPointType &dom_point) const
Computes the hessian tensor for a given domain point.
Definition: evaluator.hpp:1475
EvalPolicy::JacobianDeterminantType JacobianDeterminantType
jacobian determinant type
Definition: evaluator.hpp:1089
DataType volume() const
Computes and returns the volume of the current cell.
Definition: evaluator.hpp:1521
void calc_jac_mat(JacobianMatrixType &jac_mat, const DomainPointType &dom_point) const
Calculates the jacobian matrix for a given point.
Definition: evaluator.hpp:1436
void prepare(Index cell_index)
Prepares the evaluator for a given cell.
Definition: evaluator.hpp:1162
DataType width_directed(const ImagePointType &ray) const
Computes and returns the directed mesh width.
Definition: evaluator.hpp:1559
void map_point(ImagePointType &img_point, const DomainPointType &dom_point) const
Maps a point from the reference cell to the selected cell.
Definition: evaluator.hpp:1407
const std::vector< const ChartType * > & _charts_1
the chart pointer arrays
Definition: evaluator.hpp:1109
EvaluatorBase< Trafo_, Evaluator, EvalPolicy_ > BaseClass
base-class typedef
Definition: evaluator.hpp:1064
EvalPolicy::HessianInverseType HessianInverseType
hessian inverse tensor type
Definition: evaluator.hpp:721
EvalPolicy::JacobianInverseType JacobianInverseType
jacobian inverse matrix type
Definition: evaluator.hpp:715
const std::vector< const ChartType * > & _charts_1
the chart pointer arrays
Definition: evaluator.hpp:737
void prepare(Index cell_index)
Prepares the evaluator for a given cell.
Definition: evaluator.hpp:762
void calc_jac_mat(JacobianMatrixType &jac_mat, const DomainPointType &dom_point) const
Calculates the jacobian matrix for a given point.
Definition: evaluator.hpp:924
DataType width_directed(const ImagePointType &ray) const
Computes and returns the directed mesh width.
Definition: evaluator.hpp:1029
EvaluatorBase< Trafo_, Evaluator, EvalPolicy_ > BaseClass
base-class typedef
Definition: evaluator.hpp:692
void calc_hess_ten(HessianTensorType &hess_ten, const DomainPointType &dom_point) const
Computes the hessian tensor for a given domain point.
Definition: evaluator.hpp:957
Geometry::Atlas::ChartBase< MeshType > ChartType
type of the chart
Definition: evaluator.hpp:704
EvalPolicy::JacobianDeterminantType JacobianDeterminantType
jacobian determinant type
Definition: evaluator.hpp:717
DataType volume() const
Computes and returns the volume of the current cell.
Definition: evaluator.hpp:992
void map_point(ImagePointType &img_point, const DomainPointType &dom_point) const
Maps a point from the reference cell to the selected cell.
Definition: evaluator.hpp:901
EvaluatorBase< Trafo_, Evaluator, EvalPolicy_ > BaseClass
base-class typedef
Definition: evaluator.hpp:296
EvalPolicy::JacobianDeterminantType JacobianDeterminantType
jacobian determinant type
Definition: evaluator.hpp:318
EvalPolicy::HessianTensorType HessianTensorType
hessian tensor type
Definition: evaluator.hpp:320
EvalPolicy::JacobianInverseType JacobianInverseType
jacobian inverse matrix type
Definition: evaluator.hpp:316
void map_point(ImagePointType &img_point, const DomainPointType &dom_point) const
Maps a point from the reference cell to the selected cell.
Definition: evaluator.hpp:386
EvalPolicy::HessianInverseType HessianInverseType
hessian inverse tensor type
Definition: evaluator.hpp:322
EvalPolicy::JacobianMatrixType JacobianMatrixType
jacobian matrix type
Definition: evaluator.hpp:314
void prepare(Index cell_index)
Prepares the evaluator for a given cell.
Definition: evaluator.hpp:354
void map_point(ImagePointType &img_point, const DomainPointType &dom_point) const
Maps a point from the reference cell to the selected cell.
Definition: evaluator.hpp:529
void prepare(Index cell_index)
Prepares the evaluator for a given cell.
Definition: evaluator.hpp:478
void calc_jac_mat(JacobianMatrixType &jac_mat, const DomainPointType &dom_point) const
Calculates the jacobian matrix for a given point.
Definition: evaluator.hpp:548
DataType volume() const
Computes and returns the volume of the current cell.
Definition: evaluator.hpp:595
DataType width_directed(const ImagePointType &) const
Computes and returns the directed mesh width.
Definition: evaluator.hpp:669
DataType volume_g3() const
Approximates the edge length using a 3-point Gauss quadrature rule.
Definition: evaluator.hpp:633
EvalPolicy::HessianInverseType HessianInverseType
hessian inverse tensor type
Definition: evaluator.hpp:439
EvaluatorBase< Trafo_, Evaluator, EvalPolicy_ > BaseClass
base-class typedef
Definition: evaluator.hpp:411
EvalPolicy::JacobianDeterminantType JacobianDeterminantType
jacobian determinant type
Definition: evaluator.hpp:435
EvalPolicy::JacobianInverseType JacobianInverseType
jacobian inverse matrix type
Definition: evaluator.hpp:433
Geometry::Atlas::ChartBase< MeshType > ChartType
type of the chart
Definition: evaluator.hpp:422
void calc_hess_ten(HessianTensorType &hess_ten, const DomainPointType &dom_point) const
Computes the hessian tensor for a given domain point.
Definition: evaluator.hpp:571
const std::vector< const ChartType * > & _charts
the chart pointer array
Definition: evaluator.hpp:455
T_ sqrt(T_ x)
Returns the square-root of a value.
Definition: math.hpp:300
T_ log(T_ x)
Returns the natural logarithm of a value.
Definition: math.hpp:580
FEAT namespace.
Definition: adjactor.hpp:12
std::uint64_t Index
Index data type.
TrafoTags
Trafo configuration tags enum.
Definition: eval_tags.hpp:22
@ img_point
specifies whether the trafo should supply image point coordinates
@ hess_inv
specifies whether the trafo should supply inverse hessian tensors
@ dom_point
specifies whether the trafo should supply domain point coordinates
@ hess_ten
specifies whether the trafo should supply hessian tensors
@ jac_inv
specifies whether the trafo should supply inverse jacobian matrices
@ jac_mat
specifies whether the trafo should supply jacobian matrices
@ jac_det
specifies whether the trafo should supply jacobian determinants
Hypercube shape tag struct template.
Definition: shape.hpp:64
Vertex shape tag struct.
Definition: shape.hpp:26