FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
wrappers.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/analytic/function.hpp>
10
11namespace FEAT
12{
13 namespace Analytic
14 {
25 template<typename Function_>
26 class Gradient :
28 {
29 public:
30 // ensure that the input function is scalar
31 static_assert(Function_::ImageType::is_scalar, "only scalar functions are supported");
32
34 static constexpr int domain_dim = Function_::domain_dim;
35
38
39 static constexpr bool can_value = Function_::can_grad;
40 static constexpr bool can_grad = Function_::can_hess;
41 static constexpr bool can_hess = false;
42
43 template<typename Traits_>
44 class Evaluator :
45 public Analytic::Function::Evaluator<Traits_>
46 {
47 public:
48 typedef typename Traits_::DataType DataType;
49 typedef typename Traits_::PointType PointType;
50 typedef typename Traits_::ValueType ValueType;
51 typedef typename Traits_::GradientType GradientType;
52 typedef typename Traits_::HessianType HessianType;
53
54 private:
57
58 public:
59 explicit Evaluator(const Gradient& function) :
60 _func_eval(function._function)
61 {
62 }
63
64 ValueType value(const PointType& point)
65 {
66 return _func_eval.gradient(point);
67 }
68
69 GradientType gradient(const PointType& point)
70 {
71 return _func_eval.hessian(point);
72 }
73 };
74
75 private:
76 const Function_& _function;
77
78 public:
85 explicit Gradient(const Function_& function) :
86 _function(function)
87 {
88 }
89 }; // class Gradient<...>
90
101 template<typename Function_>
103 public Analytic::Function
104 {
105 public:
106 // ensure that the input function is scalar
107 static_assert(Function_::ImageType::is_vector, "only vector fields are supported");
108
110 static constexpr int domain_dim = Function_::domain_dim;
111
114
115 static constexpr bool can_value = Function_::can_grad;
116 static constexpr bool can_grad = false; //Function_::can_hess;
117 static constexpr bool can_hess = false;
118
119 template<typename Traits_>
120 class Evaluator :
121 public Function::Evaluator<Traits_>
122 {
123 public:
124 typedef typename Traits_::DataType DataType;
125 typedef typename Traits_::PointType PointType;
126 typedef typename Traits_::ValueType ValueType;
127 typedef typename Traits_::GradientType GradientType;
128 typedef typename Traits_::HessianType HessianType;
129
130 private:
133 typename Function_::template Evaluator<FuncEvalTraits> _func_eval;
134
135 public:
136 explicit Evaluator(const Divergence& function) :
137 _func_eval(function._function)
138 {
139 }
140
141 ValueType value(const PointType& point)
142 {
143 return _func_eval.gradient(point).trace();
144 }
145
147 /*void gradient(GradientType& grad, const PointType& point)
148 {
149 typename FuncEvalTraits::HessianType hess;
150 _func_eval.hessian(hess, point);
151 for(int i(0); i < domain_dim; ++i)
152 {
153 grad[i] = DataType(0);
154 for(int j()
155 }
156 }*/
157 };
158
159 private:
160 const Function_& _function;
161
162 public:
169 explicit Divergence(const Function_& function) :
170 _function(function)
171 {
172 }
173 }; // class Divergence<...>
174
185 template<typename Function_>
186 class Curl :
187 public Analytic::Function
188 {
189 public:
190 // ensure that the input function is scalar
191 static_assert(Function_::ImageType::is_vector, "only vector fields are supported; use ScalarCurl for scalar functions");
192
194 static constexpr int domain_dim = Function_::domain_dim;
195
198
199 static constexpr bool can_value = Function_::can_grad;
200 static constexpr bool can_grad = Function_::can_hess;
201 static constexpr bool can_hess = false;
202
203 template<typename Traits_>
204 class Evaluator :
205 public Analytic::Function::Evaluator<Traits_>
206 {
207 public:
208 typedef typename Traits_::DataType DataType;
209 typedef typename Traits_::PointType PointType;
210 typedef typename Traits_::ValueType ValueType;
211 typedef typename Traits_::GradientType GradientType;
212 typedef typename Traits_::HessianType HessianType;
213
214 private:
217 typename Function_::template Evaluator<FuncEvalTraits> _func_eval;
218
220 template<typename T_, int s_, int sm_, int sn_>
222 {
224 curl[0] = -grad[1][0];
225 curl[1] = +grad[0][1];
226 return curl;
227 }
228
229 template<typename T_, int n_, int sm1_, int sn1_, int sl_, int sm_, int sn_>
231 {
233 curl[0] = -grad[1][0];
234 curl[1] = +grad[0][1];
235 return curl;
236 }
237
239 template<typename T_, int s_, int sm_, int sn_>
241 {
243 curl[0] = grad[1][2] - grad[2][1];
244 curl[1] = grad[2][0] - grad[0][2];
245 curl[2] = grad[0][1] - grad[1][0];
246 return curl;
247 }
248
249 template<typename T_, int n_, int sm1_, int sn1_, int sl_, int sm_, int sn_>
251 {
253 curl[0] = grad[1][2] - grad[2][1];
254 curl[1] = grad[2][0] - grad[0][2];
255 curl[2] = grad[0][1] - grad[1][0];
256 return curl;
257 }
258
259 public:
260 explicit Evaluator(const Curl& function) :
261 _func_eval(function._function)
262 {
263 }
264
265 ValueType value(const PointType& point)
266 {
267 return compute(_func_eval.gradient(point));
268 }
269
270 GradientType gradient(const PointType& point)
271 {
272 return compute(_func_eval.hessian(point));
273 }
274 };
275
276 private:
277 const Function_& _function;
278
279 public:
286 explicit Curl(const Function_& function) :
287 _function(function)
288 {
289 }
290 }; // class Curl<...>
291
302 template<typename Function_>
304 public Analytic::Function
305 {
306 public:
307 // ensure that the input function is scalar
308 static_assert(Function_::ImageType::is_scalar, "only scalar functions are supported; use Curl for vector fields");
309
311 static constexpr int domain_dim = Function_::domain_dim;
312
315
316 static constexpr bool can_value = Function_::can_grad;
317 static constexpr bool can_grad = Function_::can_hess;
318 static constexpr bool can_hess = false;
319
320 template<typename Traits_>
321 class Evaluator :
322 public Analytic::Function::Evaluator<Traits_>
323 {
324 public:
325 typedef typename Traits_::DataType DataType;
326 typedef typename Traits_::PointType PointType;
327 typedef typename Traits_::ValueType ValueType;
328 typedef typename Traits_::GradientType GradientType;
329 typedef typename Traits_::HessianType HessianType;
330
331 private:
334 typename Function_::template Evaluator<FuncEvalTraits> _func_eval;
335
337 template<typename T_, int s_, int sn_>
339 {
341 curl[0] = -grad[1];
342 curl[1] = +grad[0];
343 return curl;
344 }
345
346 template<typename T_, int sa_, int sb_, int sm_, int sn_>
348 {
350 curl[0] = -grad[1];
351 curl[1] = +grad[0];
352 return curl;
353 }
354
356 template<typename T_, int s_, int sn_>
358 {
360 curl[0] = grad[1] - grad[2];
361 curl[1] = grad[2] - grad[0];
362 curl[2] = grad[0] - grad[1];
363 return curl;
364 }
365
366 template<typename T_, int sa_, int sb_, int sm_, int sn_>
368 {
370 curl[0] = grad[1] - grad[2];
371 curl[1] = grad[2] - grad[0];
372 curl[2] = grad[0] - grad[1];
373 return curl;
374 }
375
376 public:
377 explicit Evaluator(const ScalarCurl& function) :
378 _func_eval(function._function)
379 {
380 }
381
382 ValueType value(const PointType& point)
383 {
384 return compute(_func_eval.gradient(point));
385 }
386
387 GradientType gradient(const PointType& point)
388 {
389 return compute(_func_eval.hessian(point));
390 }
391 };
392
393 private:
394 const Function_& _function;
395
396 public:
403 explicit ScalarCurl(const Function_& function) :
404 _function(function)
405 {
406 }
407 }; // class ScalarCurl<...>
408
431 template<typename Function_, bool pos_range_ = true>
433 public Analytic::Function
434 {
435 public:
436 // ensure that the input function is scalar
437 static_assert(Function_::ImageType::is_scalar, "For now, we only allow scalar functions... although this should be doable without any major problems.");
438
440 static constexpr int domain_dim = Function_::domain_dim;
441 static constexpr bool pos_range = pos_range_;
442
443 static_assert(domain_dim == 2, "PolarCoordinates are only available for 2 dimenions!");
444
446 typedef typename Function_::ImageType ImageType;
447 typedef typename Function_::DataType DataType;
448
449 static constexpr bool can_value = Function_::can_value;
450 static constexpr bool can_grad = Function_::can_grad;
451 static constexpr bool can_hess = Function_::can_hess;
452
453 //our rotation matrix defined as x = rot * x' <- ie. the inverse rotation to the theta given in the ctors
456
457 PolarCoordinate(const Function_& func) :
458 _rotation(),
459 _shift(Tiny::Vector<DataType, 2>::null()),
460 _function(func)
461 {
462 _rotation.set_identity();
463 }
464
468 PolarCoordinate(const Function_& func, DataType theta) :
469 _rotation(),
470 _shift(Tiny::Vector<DataType, 2>::null()),
471 _function(func)
472 {
473 _rotation.set_rotation_2d(-theta);
474 }
475
477 PolarCoordinate(const Function_& func, Tiny::Vector<DataType, 2> shift, DataType theta = DataType(0)) :
478 _rotation(),
479 _shift(std::move(shift)),
480 _function(func)
481 {
482 _rotation.set_rotation_2d(-theta);
483 }
484
487 _rotation(),
488 _shift(std::move(shift)),
489 _function(func)
490 {
491 // theta to rotate (1,0) into x_base
492 DataType rot_theta = Math::calc_opening_angle(DataType(1), DataType(0), x_base[0], x_base[1]);
493 _rotation.set_rotation_2d(-rot_theta);
494
495 }
496
497 template<typename Traits_>
498 class Evaluator :
499 public Analytic::Function::Evaluator<Traits_>
500 {
501 public:
502 typedef typename Traits_::DataType DataType;
503 typedef typename Traits_::PointType PointType;
504 typedef typename Traits_::ValueType ValueType;
505 typedef typename Traits_::GradientType GradientType;
506 typedef typename Traits_::HessianType HessianType;
507
508 private:
511 typename Function_::template Evaluator<FuncEvalTraits> _func_eval;
512 const Tiny::Matrix<DataType, 2, 2>& _rotation;
514 const Tiny::Vector<DataType, 2>& _shift;
515
516
517 PointType transform(const PointType& point)
518 {
519 PointType pcoords;
520 //shift and rotate
521 auto p_n = _rotation * (point - _shift);
522 //and now calculate the actual polar coordinates
523 pcoords[0] = p_n.norm_euclid();
524 pcoords[1] = (pcoords[0] < DataType(5)*Math::eps<DataType>()) ? DataType(0) : Math::acos(p_n[0]/pcoords[0]);
525 //annoying fix in case of float precision...
526 if constexpr(pos_range_)
527 pcoords[1] = ((p_n[1] >= DataType(0)) || (pcoords[1] < DataType(3)*Math::eps<DataType>())) ? pcoords[1] : DataType(2)*Math::pi<DataType>()-pcoords[1];
528 else
529 pcoords[1] = (p_n[1] < DataType(0)) ? -pcoords[1] : pcoords[1];
530 return pcoords;
531 }
532
533 GradientType compute(const GradientType& grad_p, const PointType& pcoords)
534 {
535 GradientType grad;
536 grad[0] = grad_p[0] * Math::cos(pcoords[1]);
537 grad[1] = grad_p[0] * Math::sin(pcoords[1]);
538 if(pcoords[0] > DataType(5) * Math::eps<DataType>())
539 {
540 grad[0] -= grad_p[1] * Math::sin(pcoords[1]) / pcoords[0];
541 grad[1] += grad_p[1] * Math::cos(pcoords[1]) / pcoords[0];
542 }
543 return _rotation_t * grad;
544 }
545
546 HessianType compute(const HessianType& hess_p, const GradientType& grad_p, const PointType& pcoords)
547 {
548 HessianType hess;
549 const DataType valsin = Math::sin(pcoords[1]);
550 const DataType valcos = Math::cos(pcoords[1]);
551 hess[0][0] = hess_p[0][0] * Math::sqr(valcos);
552 hess[1][1] = hess_p[0][0] * Math::sqr(valsin);
553 hess[0][1] = hess_p[0][0] * valsin * valcos;
554 if(pcoords[0] > DataType(5) * Math::sqrt(Math::eps<DataType>()))
555 {
556 const DataType r_re = DataType(1) / pcoords[0];
557 hess[0][0] += grad_p[0] * Math::sqr(valsin) * r_re + DataType(2) * grad_p[1] * valsin * valcos * Math::sqr(r_re)
558 - DataType(2) * hess_p[0][1] * valsin * valcos * r_re + hess_p[1][1] * Math::sqr(valsin * r_re);
559 hess[1][1] += grad_p[0] * Math::sqr(valcos) * r_re - DataType(2) * grad_p[1] * valsin * valcos * Math::sqr(r_re)
560 + DataType(2) * hess_p[0][1] * valsin * valcos * r_re + hess_p[1][1] * Math::sqr(valcos * r_re);
561 hess[0][1] += - grad_p[0] * valsin * valcos * r_re + grad_p[1] * (Math::sqr(valsin) - Math::sqr(valcos)) * Math::sqr(r_re)
562 + hess_p[0][1] * (Math::sqr(valcos) - Math::sqr(valsin)) * r_re - hess_p[1][1] * valsin * valcos * Math::sqr(r_re);
563
564 }
565 hess[1][0] = hess[0][1];
566 return _rotation_t * hess * _rotation;
567
568 }
569
570 public:
571 explicit Evaluator(const PolarCoordinate& function) :
572 _func_eval(function._function),
573 _rotation(function._rotation),
574 _shift(function._shift)
575 {
576 _rotation_t.set_transpose(_rotation);
577 }
578
579 ValueType value(const PointType& point)
580 {
581 return _func_eval.value(this->transform(point));
582 }
583
584 GradientType gradient(const PointType& point)
585 {
586 auto p = this->transform(point);
587 return compute(_func_eval.gradient(p), p);
588 }
589
590 HessianType hessian(const PointType& point)
591 {
592 auto p = this->transform(point);
593 return compute(_func_eval.hessian(p), _func_eval.gradient(p), p);
594 }
595 };
596
597 private:
598 const Function_& _function;
599 }; // class PolarCoordinate<...>
600
601 } // namespace Analytic
602} // namespace FEAT
static Tiny::Vector< T_, 3, s_ > compute(const Tiny::Matrix< T_, 3, 3, sm_, sn_ > &grad)
3D vector curl operator
Definition: wrappers.hpp:240
Function_::template Evaluator< FuncEvalTraits > _func_eval
our original function evaluator
Definition: wrappers.hpp:217
static Tiny::Vector< T_, 2, s_ > compute(const Tiny::Matrix< T_, 2, 2, sm_, sn_ > &grad)
2D vector curl operator
Definition: wrappers.hpp:221
Analytic Function Curl wrapper.
Definition: wrappers.hpp:188
Curl(const Function_ &function)
Constructor.
Definition: wrappers.hpp:286
Image::Vector< domain_dim > ImageType
this is a vector-valued function
Definition: wrappers.hpp:197
static constexpr int domain_dim
our domain dimension is the same as the input function's
Definition: wrappers.hpp:194
Function_::template Evaluator< FuncEvalTraits > _func_eval
our original function evaluator
Definition: wrappers.hpp:133
Analytic Function Divergence wrapper.
Definition: wrappers.hpp:104
Divergence(const Function_ &function)
Constructor.
Definition: wrappers.hpp:169
Image::Scalar ImageType
this is a vector-valued function
Definition: wrappers.hpp:113
static constexpr int domain_dim
our domain dimension is the same as the input function's
Definition: wrappers.hpp:110
Analytic Function Evaluator base-class template.
Definition: function.hpp:157
Analytic Function interface.
Definition: function.hpp:112
Function_::template Evaluator< EvalTraits< DataType, Function_ > > _func_eval
our original function evaluator
Definition: wrappers.hpp:56
Analytic Function Gradient wrapper.
Definition: wrappers.hpp:28
Image::Vector< domain_dim > ImageType
this is a vector-valued function
Definition: wrappers.hpp:37
Gradient(const Function_ &function)
Constructor.
Definition: wrappers.hpp:85
static constexpr int domain_dim
our domain dimension is the same as the input function's
Definition: wrappers.hpp:34
Function_::template Evaluator< FuncEvalTraits > _func_eval
our original function evaluator
Definition: wrappers.hpp:511
This class is a wrapper transforming a polar-basis function to a euclidean base one.
Definition: wrappers.hpp:434
PolarCoordinate(const Function_ &func, Tiny::Vector< DataType, 2 > shift, Tiny::Vector< DataType, 2 > x_base)
provide shift vector and the first x' basis vector
Definition: wrappers.hpp:486
Function_::ImageType ImageType
this is a vector-valued function
Definition: wrappers.hpp:446
PolarCoordinate(const Function_ &func, DataType theta)
Definition: wrappers.hpp:468
PolarCoordinate(const Function_ &func, Tiny::Vector< DataType, 2 > shift, DataType theta=DataType(0))
theta rot angle, so that x' = rot(theta) * x
Definition: wrappers.hpp:477
static constexpr int domain_dim
our domain dimension is the same as the input function's
Definition: wrappers.hpp:440
static Tiny::Vector< T_, 2, s_ > compute(const Tiny::Vector< T_, 2, sn_ > &grad)
2D scalar curl operator
Definition: wrappers.hpp:338
Function_::template Evaluator< FuncEvalTraits > _func_eval
our original function evaluator
Definition: wrappers.hpp:334
static Tiny::Vector< T_, 3, s_ > compute(const Tiny::Vector< T_, 3, sn_ > &grad)
3D scalar curl operator
Definition: wrappers.hpp:357
Analytic Scalar Function Curl wrapper.
Definition: wrappers.hpp:305
ScalarCurl(const Function_ &function)
Constructor.
Definition: wrappers.hpp:403
static constexpr int domain_dim
our domain dimension is the same as the input function's
Definition: wrappers.hpp:311
Image::Vector< domain_dim > ImageType
this is a vector-valued function
Definition: wrappers.hpp:314
Tiny Matrix class template.
CUDA_HOST_DEVICE Matrix & set_transpose(const Matrix< T_, n_, m_, sma_, sna_ > &a)
Sets this matrix to the transpose of another matrix.
CUDA_HOST_DEVICE Matrix & set_rotation_2d(T_ angle)
Sets this matrix to a 2D rotation matrix.
CUDA_HOST_DEVICE Matrix & set_identity()
Sets this matrix to the identity matrix.
Tiny Tensor3 class template.
Tiny Vector class template.
T_ sqrt(T_ x)
Returns the square-root of a value.
Definition: math.hpp:300
T_ acos(T_ x)
Returns the arccosine of a value.
Definition: math.hpp:967
DT_ calc_opening_angle(DT_ x1, DT_ x2, DT_ y1, DT_ y2)
Calculates the opening angle of two 2D vectors.
Definition: math.hpp:1450
T_ sin(T_ x)
Returns the sine of a value.
Definition: math.hpp:344
T_ sqr(T_ x)
Returns the square of a value.
Definition: math.hpp:95
T_ cos(T_ x)
Returns the cosine of a value.
Definition: math.hpp:386
FEAT namespace.
Definition: adjactor.hpp:12
@ value
specifies whether the space should supply basis function values
@ hess
specifies whether the space should supply basis function hessians
@ grad
specifies whether the space should supply basis function gradients
Scalar Function Image tag class.
Definition: function.hpp:28
Vector Field Image tag class.
Definition: function.hpp:47