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// includes, FEAT
9#include <kernel/space/parametric_evaluator.hpp>
10
11namespace FEAT
12{
13 namespace Space
14 {
15 namespace Hermite3
16 {
23
25 namespace Intern
26 {
27 // p1, p2, q1 and q2 are the 1D basis functions on the reference interval [-1,+1].
28 // These are used for the tensor-product approach in the evaluators.
29
30 template<typename T_>
31 inline T_ p1(T_ x)
32 {
33 return T_(0.5) + T_(0.25) * x * (x*x - T_(3));
34 }
35
36 template<typename T_>
37 inline T_ p2(T_ x)
38 {
39 return T_(0.5) - T_(0.25) * x * (x*x - T_(3));
40 }
41
42 template<typename T_>
43 inline T_ q1(T_ x)
44 {
45 return T_(0.25) * (x + T_(1)) * Math::sqr(x - T_(1));
46 }
47
48 template<typename T_>
49 inline T_ q2(T_ x)
50 {
51 return T_(0.25) * (x - T_(1)) * Math::sqr(x + T_(1));
52 }
53
54 // first order derivatives follow
55 template<typename T_>
56 inline T_ dp1(T_ x)
57 {
58 return +T_(0.75) * (x*x - T_(1));
59 }
60
61 template<typename T_>
62 inline T_ dp2(T_ x)
63 {
64 return -T_(0.75) * (x*x - T_(1));
65 }
66
67 template<typename T_>
68 inline T_ dq1(T_ x)
69 {
70 return T_(0.25) * (T_(3)*x + T_(1)) * (x - T_(1));
71 }
72
73 template<typename T_>
74 inline T_ dq2(T_ x)
75 {
76 return T_(0.25) * (T_(3)*x - T_(1)) * (x + T_(1));
77 }
78
79 // second order derivatives follow
80 template<typename T_>
81 inline T_ ddp1(T_ x)
82 {
83 return +T_(1.5) * x;
84 }
85
86 template<typename T_>
87 inline T_ ddp2(T_ x)
88 {
89 return -T_(1.5) * x;
90 }
91
92 template<typename T_>
93 inline T_ ddq1(T_ x)
94 {
95 return T_(0.5) * (T_(3)*x - T_(1));
96 }
97
98 template<typename T_>
99 inline T_ ddq2(T_ x)
100 {
101 return T_(0.5) * (T_(3)*x + T_(1));
102 }
103 } // namespace Intern
105
111 template<
112 typename Space_,
113 typename TrafoEvaluator_,
114 typename SpaceEvalTraits_,
115 typename Shape_ = typename Space_::ShapeType>
116 class Evaluator DOXY({});
117
123 template<
124 typename Space_,
125 typename TrafoEvaluator_,
126 typename SpaceEvalTraits_>
127 class Evaluator<Space_, TrafoEvaluator_, SpaceEvalTraits_, Shape::Hypercube<1> > :
128 public ParametricEvaluator<
129 Evaluator<
130 Space_,
131 TrafoEvaluator_,
132 SpaceEvalTraits_,
133 Shape::Hypercube<1> >,
134 TrafoEvaluator_,
135 SpaceEvalTraits_,
136 ref_caps>
137 {
138 public:
141
143 typedef Space_ SpaceType;
144
146 typedef SpaceEvalTraits_ SpaceEvalTraits;
147
149 typedef TrafoEvaluator_ TrafoEvaluator;
150
152 typedef typename SpaceEvalTraits::EvalPolicy EvalPolicy;
153
155 typedef typename EvalPolicy::DomainPointType DomainPointType;
156
158 typedef typename SpaceEvalTraits::DataType DataType;
159
160 protected:
163
164 public:
171 explicit Evaluator(const SpaceType& DOXY(space))
172 {
173 }
174
182 {
183 return 4;
184 }
185
192 void prepare(const TrafoEvaluator& trafo_eval)
193 {
194 // domain point
196
197 // evaluate trafo in interval midpoint
198 typedef typename TrafoEvaluator::template ConfigTraits<TrafoTags::jac_mat>::EvalDataType CoeffEvalData;
199 CoeffEvalData coeff_data;
200 trafo_eval(coeff_data, dom_point);
201
202 // store coefficient
203 _coeff = coeff_data.jac_mat(0,0);
204 }
205
215 template<typename EvalData_>
217 EvalData_& data,
218 const DomainPointType& point) const
219 {
220 // P1(x) = 1/2 + 1/4 * x * (x^2 - 3)
221 data.phi[0].ref_value = Intern::p1(DataType(point[0]));
222 // Q1(x) = c/4 * (x + 1) * (x - 1)^2
223 data.phi[1].ref_value = _coeff * Intern::q1(DataType(point[0]));
224 // P2(x) = 1/2 - 1/4 * x * (x^2 - 3)
225 data.phi[2].ref_value = Intern::p2(DataType(point[0]));
226 // Q2(x) = c/4 * (x - 1) * (x + 1)^2
227 data.phi[3].ref_value = _coeff * Intern::q2(DataType(point[0]));
228 }
229
239 template<typename EvalData_>
241 EvalData_& data,
242 const DomainPointType& point) const
243 {
244 // dx P1(x) = +3/4 * (x^2 - 1)
245 data.phi[0].ref_grad[0] = Intern::dp1(DataType(point[0]));
246 // dx Q1(x) = c/4 * (3*x + 1) * (x - 1)
247 data.phi[1].ref_grad[0] = _coeff * Intern::dq1(DataType(point[0]));
248 // dx P2(x) = -3/4 * (x^2 - 1)
249 data.phi[2].ref_grad[0] = Intern::dp2(DataType(point[0]));
250 // dx Q2(x) = c/4 * (3*x - 1) * (x + 1)
251 data.phi[3].ref_grad[0] = _coeff * Intern::dq2(DataType(point[0]));
252 }
253
263 template<typename EvalData_>
265 EvalData_& data,
266 const DomainPointType& point) const
267 {
268 // dxx P1(x) = +3/2 * x
269 data.phi[0].ref_hess[0][0] = Intern::ddp1(DataType(point[0]));
270 // dxx Q1(x) = 1/2 * (3*x - 1)
271 data.phi[1].ref_hess[0][0] = _coeff * Intern::ddq1(DataType(point[0]));
272 // dxx P2(x) = -3/2 * x
273 data.phi[2].ref_hess[0][0] = Intern::ddp2(DataType(point[0]));
274 // dxx Q2(x) = 1/2 * (3*x + 1)
275 data.phi[3].ref_hess[0][0] = _coeff * Intern::ddq2(DataType(point[0]));
276 }
277 }; // class Evaluator<...,Hypercube<1>>
278
284 template<
285 typename Space_,
286 typename TrafoEvaluator_,
287 typename SpaceEvalTraits_>
288 class Evaluator<Space_, TrafoEvaluator_, SpaceEvalTraits_, Shape::Hypercube<2> > :
289 public ParametricEvaluator<
290 Evaluator<
291 Space_,
292 TrafoEvaluator_,
293 SpaceEvalTraits_,
294 Shape::Hypercube<2> >,
295 TrafoEvaluator_,
296 SpaceEvalTraits_,
297 ref_caps>
298 {
299 public:
302
304 typedef Space_ SpaceType;
305
307 typedef SpaceEvalTraits_ SpaceEvalTraits;
308
310 typedef TrafoEvaluator_ TrafoEvaluator;
311
313 typedef typename SpaceEvalTraits::EvalPolicy EvalPolicy;
314
316 typedef typename EvalPolicy::DomainPointType DomainPointType;
317
319 typedef typename SpaceEvalTraits::DataType DataType;
320
321 protected:
324
338 {
339 return _coeff_fod[i](0,0) * rx + _coeff_fod[i](0,1) * ry;
340 }
341
355 {
356 return _coeff_fod[i](1,0) * rx + _coeff_fod[i](1,1) * ry;
357 }
358
359 public:
366 explicit Evaluator(const SpaceType& DOXY(space))
367 {
368 }
369
377 {
378 return 16;
379 }
380
387 void prepare(const TrafoEvaluator& trafo_eval)
388 {
389 // domain point
391
392 // evaluate trafo in interval midpoint
393 typedef typename TrafoEvaluator::template ConfigTraits<TrafoTags::jac_mat>::EvalDataType CoeffEvalData;
394 CoeffEvalData coeff_data;
395
396 // loop over all four vertices of the quad
397 for(int i(0); i < 4; ++i)
398 {
399 // compute reference vertex coordinates
400 dom_point[0] = DataType(-1 + ((i << 1) & 2));
401 dom_point[1] = DataType(-1 + ((i ) & 2));
402
403 // evaluate trafo data
404 trafo_eval(coeff_data, dom_point);
405
406 // store jacobian matrix
407 _coeff_fod[i] = coeff_data.jac_mat;
408 }
409 }
410
420 template<typename EvalData_>
422 EvalData_& data,
423 const DomainPointType& point) const
424 {
425 const DataType x(point[0]), y(point[1]);
426 DataType d0, d1;
427
428 // Vertex 1: (-1,-1)
429 data.phi[ 0].ref_value = Intern::p1(x) * Intern::p1(y);
430 d0 = Intern::q1(x) * Intern::p1(y);
431 d1 = Intern::p1(x) * Intern::q1(y);
432 data.phi[ 1].ref_value = _trans_dx(0, d0, d1);
433 data.phi[ 2].ref_value = _trans_dy(0, d0, d1);
434
435 // Vertex 2: (+1,-1)
436 data.phi[ 3].ref_value = Intern::p2(x) * Intern::p1(y);
437 d0 = Intern::q2(x) * Intern::p1(y);
438 d1 = Intern::p2(x) * Intern::q1(y);
439 data.phi[ 4].ref_value = _trans_dx(1, d0, d1);
440 data.phi[ 5].ref_value = _trans_dy(1, d0, d1);
441
442 // Vertex 3: (-1,+1)
443 data.phi[ 6].ref_value = Intern::p1(x) * Intern::p2(y);
444 d0 = Intern::q1(x) * Intern::p2(y);
445 d1 = Intern::p1(x) * Intern::q2(y);
446 data.phi[ 7].ref_value = _trans_dx(2, d0, d1);
447 data.phi[ 8].ref_value = _trans_dy(2, d0, d1);
448
449 // Vertex 4: (+1,+1)
450 data.phi[ 9].ref_value = Intern::p2(x) * Intern::p2(y);
451 d0 = Intern::q2(x) * Intern::p2(y);
452 d1 = Intern::p2(x) * Intern::q2(y);
453 data.phi[10].ref_value = _trans_dx(3, d0, d1);
454 data.phi[11].ref_value = _trans_dy(3, d0, d1);
455
456 // inner basis functions
457 data.phi[12].ref_value = Intern::q1(x) * Intern::q1(y);
458 data.phi[13].ref_value = Intern::q2(x) * Intern::q1(y);
459 data.phi[14].ref_value = Intern::q1(x) * Intern::q2(y);
460 data.phi[15].ref_value = Intern::q2(x) * Intern::q2(y);
461 }
462
472 template<typename EvalData_>
474 EvalData_& data,
475 const DomainPointType& point) const
476 {
477 const DataType x(point[0]), y(point[1]);
478 DataType d0x, d0y, d1x, d1y;
479
480 // Vertex 1: (-1,-1)
481 data.phi[ 0].ref_grad[0] = Intern::dp1(x) * Intern::p1(y);
482 data.phi[ 0].ref_grad[1] = Intern::p1(x) * Intern::dp1(y);
483 d0x = Intern::dq1(x) * Intern::p1(y);
484 d0y = Intern::q1(x) * Intern::dp1(y);
485 d1x = Intern::dp1(x) * Intern::q1(y);
486 d1y = Intern::p1(x) * Intern::dq1(y);
487 data.phi[ 1].ref_grad[0] = _trans_dx(0, d0x, d1x);
488 data.phi[ 1].ref_grad[1] = _trans_dx(0, d0y, d1y);
489 data.phi[ 2].ref_grad[0] = _trans_dy(0, d0x, d1x);
490 data.phi[ 2].ref_grad[1] = _trans_dy(0, d0y, d1y);
491
492 // Vertex 2: (+1,-1)
493 data.phi[ 3].ref_grad[0] = Intern::dp2(x) * Intern::p1(y);
494 data.phi[ 3].ref_grad[1] = Intern::p2(x) * Intern::dp1(y);
495 d0x = Intern::dq2(x) * Intern::p1(y);
496 d0y = Intern::q2(x) * Intern::dp1(y);
497 d1x = Intern::dp2(x) * Intern::q1(y);
498 d1y = Intern::p2(x) * Intern::dq1(y);
499 data.phi[ 4].ref_grad[0] = _trans_dx(1, d0x, d1x);
500 data.phi[ 4].ref_grad[1] = _trans_dx(1, d0y, d1y);
501 data.phi[ 5].ref_grad[0] = _trans_dy(1, d0x, d1x);
502 data.phi[ 5].ref_grad[1] = _trans_dy(1, d0y, d1y);
503
504 // Vertex 3: (-1,+1)
505 data.phi[ 6].ref_grad[0] = Intern::dp1(x) * Intern::p2(y);
506 data.phi[ 6].ref_grad[1] = Intern::p1(x) * Intern::dp2(y);
507 d0x = Intern::dq1(x) * Intern::p2(y);
508 d0y = Intern::q1(x) * Intern::dp2(y);
509 d1x = Intern::dp1(x) * Intern::q2(y);
510 d1y = Intern::p1(x) * Intern::dq2(y);
511 data.phi[ 7].ref_grad[0] = _trans_dx(2, d0x, d1x);
512 data.phi[ 7].ref_grad[1] = _trans_dx(2, d0y, d1y);
513 data.phi[ 8].ref_grad[0] = _trans_dy(2, d0x, d1x);
514 data.phi[ 8].ref_grad[1] = _trans_dy(2, d0y, d1y);
515
516 // Vertex 4: (+1,+1)
517 data.phi[ 9].ref_grad[0] = Intern::dp2(x) * Intern::p2(y);
518 data.phi[ 9].ref_grad[1] = Intern::p2(x) * Intern::dp2(y);
519 d0x = Intern::dq2(x) * Intern::p2(y);
520 d0y = Intern::q2(x) * Intern::dp2(y);
521 d1x = Intern::dp2(x) * Intern::q2(y);
522 d1y = Intern::p2(x) * Intern::dq2(y);
523 data.phi[10].ref_grad[0] = _trans_dx(3, d0x, d1x);
524 data.phi[10].ref_grad[1] = _trans_dx(3, d0y, d1y);
525 data.phi[11].ref_grad[0] = _trans_dy(3, d0x, d1x);
526 data.phi[11].ref_grad[1] = _trans_dy(3, d0y, d1y);
527
528 // inner basis functions
529 data.phi[12].ref_grad[0] = Intern::dq1(x) * Intern::q1(y);
530 data.phi[12].ref_grad[1] = Intern::q1(x) * Intern::dq1(y);
531 data.phi[13].ref_grad[0] = Intern::dq2(x) * Intern::q1(y);
532 data.phi[13].ref_grad[1] = Intern::q2(x) * Intern::dq1(y);
533 data.phi[14].ref_grad[0] = Intern::dq1(x) * Intern::q2(y);
534 data.phi[14].ref_grad[1] = Intern::q1(x) * Intern::dq2(y);
535 data.phi[15].ref_grad[0] = Intern::dq2(x) * Intern::q2(y);
536 data.phi[15].ref_grad[1] = Intern::q2(x) * Intern::dq2(y);
537 }
538
548 template<typename EvalData_>
550 EvalData_& data,
551 const DomainPointType& point) const
552 {
553 const DataType x(point[0]), y(point[1]);
554 DataType d0xx, d0xy, d0yy, d1xx, d1xy, d1yy;
555
556 // Vertex 1: (-1,-1)
557 data.phi[ 0].ref_hess[0][0] = Intern::ddp1(x) * Intern::p1(y);
558 data.phi[ 0].ref_hess[0][1] =
559 data.phi[ 0].ref_hess[1][0] = Intern::dp1(x) * Intern::dp1(y);
560 data.phi[ 0].ref_hess[1][1] = Intern::p1(x) * Intern::ddp1(y);
561 d0xx = Intern::ddq1(x) * Intern::p1(y);
562 d0xy = Intern::dq1(x) * Intern::dp1(y);
563 d0yy = Intern::q1(x) * Intern::ddp1(y);
564 d1xx = Intern::ddp1(x) * Intern::q1(y);
565 d1xy = Intern::dp1(x) * Intern::dq1(y);
566 d1yy = Intern::p1(x) * Intern::ddq1(y);
567 data.phi[ 1].ref_hess[0][0] = _trans_dx(0, d0xx, d1xx);
568 data.phi[ 1].ref_hess[0][1] =
569 data.phi[ 1].ref_hess[1][0] = _trans_dx(0, d0xy, d1xy);
570 data.phi[ 1].ref_hess[1][1] = _trans_dx(0, d0yy, d1yy);
571 data.phi[ 2].ref_hess[0][0] = _trans_dy(0, d0xx, d1xx);
572 data.phi[ 2].ref_hess[0][1] =
573 data.phi[ 2].ref_hess[1][0] = _trans_dy(0, d0xy, d1xy);
574 data.phi[ 2].ref_hess[1][1] = _trans_dy(0, d0yy, d1yy);
575
576 // Vertex 2: (+1,-1)
577 data.phi[ 3].ref_hess[0][0] = Intern::ddp2(x) * Intern::p1(y);
578 data.phi[ 3].ref_hess[0][1] =
579 data.phi[ 3].ref_hess[1][0] = Intern::dp2(x) * Intern::dp1(y);
580 data.phi[ 3].ref_hess[1][1] = Intern::p2(x) * Intern::ddp1(y);
581 d0xx = Intern::ddq2(x) * Intern::p1(y);
582 d0xy = Intern::dq2(x) * Intern::dp1(y);
583 d0yy = Intern::q2(x) * Intern::ddp1(y);
584 d1xx = Intern::ddp2(x) * Intern::q1(y);
585 d1xy = Intern::dp2(x) * Intern::dq1(y);
586 d1yy = Intern::p2(x) * Intern::ddq1(y);
587 data.phi[ 4].ref_hess[0][0] = _trans_dx(1, d0xx, d1xx);
588 data.phi[ 4].ref_hess[0][1] =
589 data.phi[ 4].ref_hess[1][0] = _trans_dx(1, d0xy, d1xy);
590 data.phi[ 4].ref_hess[1][1] = _trans_dx(1, d0yy, d1yy);
591 data.phi[ 5].ref_hess[0][0] = _trans_dy(1, d0xx, d1xx);
592 data.phi[ 5].ref_hess[0][1] =
593 data.phi[ 5].ref_hess[1][0] = _trans_dy(1, d0xy, d1xy);
594 data.phi[ 5].ref_hess[1][1] = _trans_dy(1, d0yy, d1yy);
595
596 // Vertex 3: (-1,+1)
597 data.phi[ 6].ref_hess[0][0] = Intern::ddp1(x) * Intern::p2(y);
598 data.phi[ 6].ref_hess[0][1] =
599 data.phi[ 6].ref_hess[1][0] = Intern::dp1(x) * Intern::dp2(y);
600 data.phi[ 6].ref_hess[1][1] = Intern::p1(x) * Intern::ddp2(y);
601 d0xx = Intern::ddq1(x) * Intern::p2(y);
602 d0xy = Intern::dq1(x) * Intern::dp2(y);
603 d0yy = Intern::q1(x) * Intern::ddp2(y);
604 d1xx = Intern::ddp1(x) * Intern::q2(y);
605 d1xy = Intern::dp1(x) * Intern::dq2(y);
606 d1yy = Intern::p1(x) * Intern::ddq2(y);
607 data.phi[ 7].ref_hess[0][0] = _trans_dx(2, d0xx, d1xx);
608 data.phi[ 7].ref_hess[0][1] =
609 data.phi[ 7].ref_hess[1][0] = _trans_dx(2, d0xy, d1xy);
610 data.phi[ 7].ref_hess[1][1] = _trans_dx(2, d0yy, d1yy);
611 data.phi[ 8].ref_hess[0][0] = _trans_dy(2, d0xx, d1xx);
612 data.phi[ 8].ref_hess[0][1] =
613 data.phi[ 8].ref_hess[1][0] = _trans_dy(2, d0xy, d1xy);
614 data.phi[ 8].ref_hess[1][1] = _trans_dy(2, d0yy, d1yy);
615
616 // Vertex 4: (+1,+1)
617 data.phi[ 9].ref_hess[0][0] = Intern::ddp2(x) * Intern::p2(y);
618 data.phi[ 9].ref_hess[0][1] =
619 data.phi[ 9].ref_hess[1][0] = Intern::dp2(x) * Intern::dp2(y);
620 data.phi[ 9].ref_hess[1][1] = Intern::p2(x) * Intern::ddp2(y);
621 d0xx = Intern::ddq2(x) * Intern::p2(y);
622 d0xy = Intern::dq2(x) * Intern::dp2(y);
623 d0yy = Intern::q2(x) * Intern::ddp2(y);
624 d1xx = Intern::ddp2(x) * Intern::q2(y);
625 d1xy = Intern::dp2(x) * Intern::dq2(y);
626 d1yy = Intern::p2(x) * Intern::ddq2(y);
627 data.phi[10].ref_hess[0][0] = _trans_dx(3, d0xx, d1xx);
628 data.phi[10].ref_hess[0][1] =
629 data.phi[10].ref_hess[1][0] = _trans_dx(3, d0xy, d1xy);
630 data.phi[10].ref_hess[1][1] = _trans_dx(3, d0yy, d1yy);
631 data.phi[11].ref_hess[0][0] = _trans_dy(3, d0xx, d1xx);
632 data.phi[11].ref_hess[0][1] =
633 data.phi[11].ref_hess[1][0] = _trans_dy(3, d0xy, d1xy);
634 data.phi[11].ref_hess[1][1] = _trans_dy(3, d0yy, d1yy);
635
636 // inner basis functions
637 data.phi[12].ref_hess[0][0] = Intern::ddq1(x) * Intern::q1(y);
638 data.phi[12].ref_hess[0][1] =
639 data.phi[12].ref_hess[1][0] = Intern::dq1(x) * Intern::dq1(y);
640 data.phi[12].ref_hess[1][1] = Intern::q1(x) * Intern::ddq1(y);
641 data.phi[13].ref_hess[0][0] = Intern::ddq2(x) * Intern::q1(y);
642 data.phi[13].ref_hess[0][1] =
643 data.phi[13].ref_hess[1][0] = Intern::dq2(x) * Intern::dq1(y);
644 data.phi[13].ref_hess[1][1] = Intern::q2(x) * Intern::ddq1(y);
645 data.phi[14].ref_hess[0][0] = Intern::ddq1(x) * Intern::q2(y);
646 data.phi[14].ref_hess[0][1] =
647 data.phi[14].ref_hess[1][0] = Intern::dq1(x) * Intern::dq2(y);
648 data.phi[14].ref_hess[1][1] = Intern::q1(x) * Intern::ddq2(y);
649 data.phi[15].ref_hess[0][0] = Intern::ddq2(x) * Intern::q2(y);
650 data.phi[15].ref_hess[0][1] =
651 data.phi[15].ref_hess[1][0] = Intern::dq2(x) * Intern::dq2(y);
652 data.phi[15].ref_hess[1][1] = Intern::q2(x) * Intern::ddq2(y);
653 }
654 }; // class Evaluator<...,Hypercube<2>>
655
661 template<
662 typename Space_,
663 typename TrafoEvaluator_,
664 typename SpaceEvalTraits_>
665 class Evaluator<Space_, TrafoEvaluator_, SpaceEvalTraits_, Shape::Simplex<2> > :
666 public ParametricEvaluator<
667 Evaluator<
668 Space_,
669 TrafoEvaluator_,
670 SpaceEvalTraits_,
671 Shape::Simplex<2> >,
672 TrafoEvaluator_,
673 SpaceEvalTraits_,
674 ref_caps>
675 {
676 public:
679
681 typedef Space_ SpaceType;
682
684 typedef SpaceEvalTraits_ SpaceEvalTraits;
685
687 typedef TrafoEvaluator_ TrafoEvaluator;
688
690 typedef typename SpaceEvalTraits::EvalPolicy EvalPolicy;
691
693 typedef typename EvalPolicy::DomainPointType DomainPointType;
694
696 typedef typename SpaceEvalTraits::DataType DataType;
697
698 protected:
701
712 {
713 return _coeff_fod(0,0) * rx + _coeff_fod(0,1) * ry;
714 }
715
726 {
727 return _coeff_fod(1,0) * rx + _coeff_fod(1,1) * ry;
728 }
729
730 public:
737 explicit Evaluator(const SpaceType& DOXY(space))
738 {
739 }
740
748 {
749 return 10;
750 }
751
758 void prepare(const TrafoEvaluator& trafo_eval)
759 {
760 // domain point: barycentre
762 dom_point[0] = dom_point[1] = DataType(1) / DataType(3);
763
764 // evaluate trafo in interval midpoint
765 typedef typename TrafoEvaluator::template ConfigTraits<TrafoTags::jac_mat>::EvalDataType CoeffEvalData;
766 CoeffEvalData coeff_data;
767
768 // evaluate trafo data
769 trafo_eval(coeff_data, dom_point);
770
771 // store jacobian matrix
772 _coeff_fod = coeff_data.jac_mat;
773 }
774
784 template<typename EvalData_>
786 EvalData_& data,
787 const DomainPointType& point) const
788 {
789 const DataType x(point[0]), y(point[1]);
790 DataType d0, d1;
791
792 static const DataType T1(DataType(1));
793 static const DataType T2(DataType(2));
794 static const DataType T3(DataType(3));
795 static const DataType T7(DataType(7));
796 static const DataType T13(DataType(13));
797 static const DataType T27(DataType(27));
798
799 // Vertex 1: (0,0)
800 data.phi[ 0].ref_value = T13*x*y*(x + y - T1) + y*y*(T2*y - T3) + x*x*(T2*x - T3) + T1;
801 d0 = x*(T1 + x*(x - T2) + y*(T3*(x - T1) + T2*y));
802 d1 = y*(T1 + y*(y - T2) + x*(T3*(y - T1) + T2*x));
803 data.phi[ 1].ref_value = _trans_dx(d0, d1);
804 data.phi[ 2].ref_value = _trans_dy(d0, d1);
805
806 // Vertex 2: (1,0)
807 data.phi[ 3].ref_value = x*(x*(T3 - T2*x) + T7*y*(x + y - T1));
808 d0 = x*(x*(x - T1) - T2*y*(x + y - T1));
809 d1 = x*y*(T2*x + y - T1);
810 data.phi[ 4].ref_value = _trans_dx(d0, d1);
811 data.phi[ 5].ref_value = _trans_dy(d0, d1);
812
813 // Vertex 3: (0,1)
814 data.phi[ 6].ref_value = y*(y*(T3 - T2*y) + T7*x*(y + x - T1));
815 d0 = y*x*(T2*y + x - T1);
816 d1 = y*(y*(y - T1) - T2*x*(y + x - T1));
817 data.phi[ 7].ref_value = _trans_dx(d0, d1);
818 data.phi[ 8].ref_value = _trans_dy(d0, d1);
819
820 // barycentre
821 data.phi[ 9].ref_value = T27*x*y*(T1 - x - y);
822 }
823
833 template<typename EvalData_>
835 EvalData_& data,
836 const DomainPointType& point) const
837 {
838 const DataType x(point[0]), y(point[1]);
839 DataType d0x, d0y, d1x, d1y;
840
841 static const DataType T1(DataType(1));
842 static const DataType T2(DataType(2));
843 static const DataType T3(DataType(3));
844 static const DataType T4(DataType(4));
845 static const DataType T6(DataType(6));
846 static const DataType T7(DataType(7));
847 static const DataType T13(DataType(13));
848 static const DataType T27(DataType(27));
849
850 // Vertex 0: (0, 0)
851 data.phi[ 0].ref_grad[0] = T6*x*(x - T1) + T13*y*(T2*x + y - T1);
852 data.phi[ 0].ref_grad[1] = T6*y*(y - T1) + T13*x*(T2*y + x - T1);
853 d0x = x*(T3*x - T4) + y*(T6*x + T2*y - T3) + T1;
854 d0y = x*(T4*y + T3*(x - T1));
855 d1x = y*(T4*x + T3*(y - T1));
856 d1y = y*(T3*y - T4) + x*(T6*y + T2*x - T3) + T1;
857 data.phi[ 1].ref_grad[0] = _trans_dx(d0x, d1x);
858 data.phi[ 1].ref_grad[1] = _trans_dx(d0y, d1y);
859 data.phi[ 2].ref_grad[0] = _trans_dy(d0x, d1x);
860 data.phi[ 2].ref_grad[1] = _trans_dy(d0y, d1y);
861
862 // Vertex 1: (1, 0)
863 data.phi[ 3].ref_grad[0] = T6*x*(T1 - x) + T7*y*(T2*x + y - T1);
864 data.phi[ 3].ref_grad[1] = T7*x*(T2*y + x - T1);
865 d0x = x*(T3*x - T2) + T2*y*(T1 - y - T2*x);
866 d0y = T2*x*(T1 - x - T2*y);
867 d1x = y*(T4*x + y - T1);
868 d1y = x*(T2*(y + x) - T1);
869 data.phi[ 4].ref_grad[0] = _trans_dx(d0x, d1x);
870 data.phi[ 4].ref_grad[1] = _trans_dx(d0y, d1y);
871 data.phi[ 5].ref_grad[0] = _trans_dy(d0x, d1x);
872 data.phi[ 5].ref_grad[1] = _trans_dy(d0y, d1y);
873
874 // Vertex 2: (0, 1)
875 data.phi[ 6].ref_grad[0] = T7*y*(T2*x + y - T1);
876 data.phi[ 6].ref_grad[1] = T6*y*(T1 - y) + T7*x*(T2*y + x - T1);
877 d0x = y*(T2*(x + y) - T1);
878 d0y = x*(T4*y + x - T1);
879 d1x = T2*y*(T1 - y - T2*x);
880 d1y = y*(T3*y - T2) + T2*x*(T1 - x - T2*y);
881 data.phi[ 7].ref_grad[0] = _trans_dx(d0x, d1x);
882 data.phi[ 7].ref_grad[1] = _trans_dx(d0y, d1y);
883 data.phi[ 8].ref_grad[0] = _trans_dy(d0x, d1x);
884 data.phi[ 8].ref_grad[1] = _trans_dy(d0y, d1y);
885
886 // barycentre
887 data.phi[ 9].ref_grad[0] = T27*y*(T1 - T2*x - y);
888 data.phi[ 9].ref_grad[1] = T27*x*(T1 - T2*y - x);
889 }
890
900 template<typename EvalData_>
902 EvalData_& data,
903 const DomainPointType& point) const
904 {
905 const DataType x(point[0]), y(point[1]);
906 DataType d0xx, d0xy, d0yy, d1xx, d1xy, d1yy;
907
908 static const DataType T1(DataType(1));
909 static const DataType T2(DataType(2));
910 static const DataType T3(DataType(3));
911 static const DataType T4(DataType(4));
912 static const DataType T6(DataType(6));
913 static const DataType T7(DataType(7));
914 static const DataType T13(DataType(13));
915 static const DataType T14(DataType(14));
916 static const DataType T26(DataType(26));
917 static const DataType T27(DataType(27));
918 static const DataType T54(DataType(54));
919
920 // Vertex 1: (0,0)
921 data.phi[ 0].ref_hess[0][0] = T26*y + T6*(T2*x - T1);
922 data.phi[ 0].ref_hess[0][1] =
923 data.phi[ 0].ref_hess[1][0] = T13*(T2*(x + y) - T1);
924 data.phi[ 0].ref_hess[1][1] = T26*x + T6*(T2*y - T1);
925 d0xx = T6*(x + y) - T4;
926 d0xy = T4*y + T3*(T2*x - T1);
927 d0yy = T4*x;
928 d1xx = T4*y;
929 d1xy = T4*x + T3*(T2*y - T1);
930 d1yy = T6*(x + y) - T4;
931 data.phi[ 1].ref_hess[0][0] = _trans_dx(d0xx, d1xx);
932 data.phi[ 1].ref_hess[0][1] =
933 data.phi[ 1].ref_hess[1][0] = _trans_dx(d0xy, d1xy);
934 data.phi[ 1].ref_hess[1][1] = _trans_dx(d0yy, d1yy);
935 data.phi[ 2].ref_hess[0][0] = _trans_dy(d0xx, d1xx);
936 data.phi[ 2].ref_hess[0][1] =
937 data.phi[ 2].ref_hess[1][0] = _trans_dy(d0xy, d1xy);
938 data.phi[ 2].ref_hess[1][1] = _trans_dy(d0yy, d1yy);
939
940 // Vertex 2: (1,0)
941 data.phi[ 3].ref_hess[0][0] = T14*y + T6*(T1 - T2*x);
942 data.phi[ 3].ref_hess[0][1] =
943 data.phi[ 3].ref_hess[1][0] = T7*(T2*(x + y) - T1);
944 data.phi[ 3].ref_hess[1][1] = T14*x;
945 d0xx = T6*x - T2*(T2*y + T1);
946 d0xy = T2 - T4*(x + y);
947 d0yy = -T4*x;
948 d1xx = T4*y;
949 d1xy = T2*(T2*x + y) - T1;
950 d1yy = T2*x;
951 data.phi[ 4].ref_hess[0][0] = _trans_dx(d0xx, d1xx);
952 data.phi[ 4].ref_hess[0][1] =
953 data.phi[ 4].ref_hess[1][0] = _trans_dx(d0xy, d1xy);
954 data.phi[ 4].ref_hess[1][1] = _trans_dx(d0yy, d1yy);
955 data.phi[ 5].ref_hess[0][0] = _trans_dy(d0xx, d1xx);
956 data.phi[ 5].ref_hess[0][1] =
957 data.phi[ 5].ref_hess[1][0] = _trans_dy(d0xy, d1xy);
958 data.phi[ 5].ref_hess[1][1] = _trans_dy(d0yy, d1yy);
959
960 // Vertex 3: (0,1)
961 data.phi[ 6].ref_hess[0][0] = T14*y;
962 data.phi[ 6].ref_hess[0][1] =
963 data.phi[ 6].ref_hess[1][0] = T7*(T2*(x + y) - T1);
964 data.phi[ 6].ref_hess[1][1] = T14*x + T6*(T1 - T2*y);
965 d0xx = T2*y;
966 d0xy = T2*(T2*y + x) - T1;
967 d0yy = T4*x;
968 d1xx = -T4*y;
969 d1xy = T2 - T4*(y + x);
970 d1yy = T6*y - T2*(T2*x + T1);
971 data.phi[ 7].ref_hess[0][0] = _trans_dx(d0xx, d1xx);
972 data.phi[ 7].ref_hess[0][1] =
973 data.phi[ 7].ref_hess[1][0] = _trans_dx(d0xy, d1xy);
974 data.phi[ 7].ref_hess[1][1] = _trans_dx(d0yy, d1yy);
975 data.phi[ 8].ref_hess[0][0] = _trans_dy(d0xx, d1xx);
976 data.phi[ 8].ref_hess[0][1] =
977 data.phi[ 8].ref_hess[1][0] = _trans_dy(d0xy, d1xy);
978 data.phi[ 8].ref_hess[1][1] = _trans_dy(d0yy, d1yy);
979
980 // barycentre
981 data.phi[ 9].ref_hess[0][0] = -T54*y;
982 data.phi[ 9].ref_hess[0][1] =
983 data.phi[ 9].ref_hess[1][0] = T27*(T1 - T2*(x + y));
984 data.phi[ 9].ref_hess[1][1] = -T54*x;
985 }
986 }; // class Evaluator<...,Simplex<2>>
987 } // namespace Hermite3
988 } // namespace Space
989} // namespace FEAT
void eval_ref_gradients(EvalData_ &data, const DomainPointType &point) const
Evaluates the basis function gradients on the reference cell.
Definition: evaluator.hpp:834
void eval_ref_hessians(EvalData_ &data, const DomainPointType &point) const
Evaluates the basis function hessians on the reference cell.
Definition: evaluator.hpp:901
Tiny::Matrix< DataType, 2, 2 > _coeff_fod
first-order derivative transform coefficients
Definition: evaluator.hpp:700
ParametricEvaluator< Evaluator, TrafoEvaluator_, SpaceEvalTraits_, ref_caps > BaseClass
base-class typedef
Definition: evaluator.hpp:678
void prepare(const TrafoEvaluator &trafo_eval)
Prepares the evaluator for a given cell.
Definition: evaluator.hpp:758
DataType _trans_dy(DataType rx, DataType ry) const
Transforms the Y-derivative basis function.
Definition: evaluator.hpp:725
DataType _trans_dx(DataType rx, DataType ry) const
Transforms the X-derivative basis function.
Definition: evaluator.hpp:711
void eval_ref_values(EvalData_ &data, const DomainPointType &point) const
Evaluates the basis function values on the reference cell.
Definition: evaluator.hpp:785
void eval_ref_values(EvalData_ &data, const DomainPointType &point) const
Evaluates the basis function values on the reference cell.
Definition: evaluator.hpp:421
void eval_ref_hessians(EvalData_ &data, const DomainPointType &point) const
Evaluates the basis function hessians on the reference cell.
Definition: evaluator.hpp:549
void prepare(const TrafoEvaluator &trafo_eval)
Prepares the evaluator for a given cell.
Definition: evaluator.hpp:387
DataType _trans_dx(Index i, DataType rx, DataType ry) const
Transforms the X-derivative basis function.
Definition: evaluator.hpp:337
DataType _trans_dy(Index i, DataType rx, DataType ry) const
Transforms the Y-derivative basis function.
Definition: evaluator.hpp:354
void eval_ref_gradients(EvalData_ &data, const DomainPointType &point) const
Evaluates the basis function gradients on the reference cell.
Definition: evaluator.hpp:473
ParametricEvaluator< Evaluator, TrafoEvaluator_, SpaceEvalTraits_, ref_caps > BaseClass
base-class typedef
Definition: evaluator.hpp:301
void prepare(const TrafoEvaluator &trafo_eval)
Prepares the evaluator for a given cell.
Definition: evaluator.hpp:192
void eval_ref_gradients(EvalData_ &data, const DomainPointType &point) const
Evaluates the basis function gradients on the reference cell.
Definition: evaluator.hpp:240
void eval_ref_hessians(EvalData_ &data, const DomainPointType &point) const
Evaluates the basis function hessians on the reference cell.
Definition: evaluator.hpp:264
ParametricEvaluator< Evaluator, TrafoEvaluator_, SpaceEvalTraits_, ref_caps > BaseClass
base-class typedef
Definition: evaluator.hpp:140
void eval_ref_values(EvalData_ &data, const DomainPointType &point) const
Evaluates the basis function values on the reference cell.
Definition: evaluator.hpp:216
Hermite-3 Element Evaluator class template declaration.
Definition: evaluator.hpp:116
Finite-Element Parametric Evaluator CRTP base-class template.
Tiny Matrix class template.
static constexpr SpaceTags ref_caps
Hermite-3 Element Evaluator reference capabilities.
Definition: evaluator.hpp:22
FEAT namespace.
Definition: adjactor.hpp:12
SpaceTags
Space configuration tags enum.
Definition: eval_tags.hpp:97
@ ref_value
specifies whether the space should supply reference basis function values
@ ref_hess
specifies whether the space should supply reference basis function hessians
@ ref_grad
specifies whether the space should supply reference basis function gradients
std::uint64_t Index
Index data type.
@ dom_point
specifies whether the trafo should supply domain point coordinates