https://mooseframework.inl.gov
Loading...
Searching...
No Matches
CompileTimeDerivatives.h
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#pragma once
11
12#include "libmesh/utility.h"
13#include "libmesh/compare_types.h"
14#include "Conversion.h"
15#include <limits>
16
18{
19
25class CTBase
26{
27public:
29 constexpr static int precedence() { return 0; }
31 constexpr static bool leftAssociative() { return false; }
32};
33class CTNullBase : public CTBase
34{
35};
36class CTOneBase : public CTBase
37{
38};
39
40template <typename T>
41using CTCleanType = typename std::remove_const<typename std::remove_reference<T>::type>::type;
42
43template <typename... Ts>
45
46template <typename T>
47struct CTSuperType<T>
48{
49 typedef T type;
50};
51
52template <typename T1, typename T2, typename... Ts>
53struct CTSuperType<T1, T2, Ts...>
54{
55 typedef typename std::conditional<
56 (sizeof...(Ts) > 0),
59};
60
66using CTTag = int;
67constexpr CTTag CTNoTag = std::numeric_limits<CTTag>::max();
68
69template <CTTag tag>
70std::string
72{
73 if constexpr (tag == CTNoTag)
74 return "";
75 else
76 return Moose::stringify(tag);
77}
78
79template <typename B, typename E>
80auto pow(const B & base, const E & exp);
81template <int E, typename B>
82auto pow(const B &);
83
84template <typename T>
85auto exp(const T &);
86template <typename T>
87auto log(const T &);
88
93template <typename T>
94class CTNull : public CTNullBase
95{
96public:
97 CTNull() {}
99
100 ResultType operator()() const { return ResultType(0); }
101 std::string print() const { return "0"; }
102
103 template <CTTag dtag>
104 auto D() const
105 {
106 return CTNull<ResultType>();
107 }
108};
109
114template <typename T>
115class CTOne : public CTOneBase
116{
117public:
118 CTOne() {}
120
121 ResultType operator()() const { return ResultType(1); }
122 std::string print() const { return "1"; }
123
124 template <CTTag dtag>
125 auto D() const
126 {
127 return CTNull<ResultType>();
128 }
129};
130
134template <typename T>
135class CTUnary : public CTBase
136{
137public:
138 CTUnary(T arg) : _arg(arg) {}
139
140 template <typename Self>
141 std::string printParens(const Self *, const std::string & op) const
142 {
143 std::string out = op;
144 if constexpr (T::precedence() > Self::precedence())
145 out += "(" + _arg.print() + ")";
146 else
147 out += _arg.print();
148
149 return out;
150 }
151
152 typedef typename T::ResultType ResultType;
153
154protected:
155 const T _arg;
156};
157
161template <typename T>
162class CTUnaryMinus : public CTUnary<T>
163{
164public:
165 CTUnaryMinus(T arg) : CTUnary<T>(arg) {}
166 using typename CTUnary<T>::ResultType;
167
168 ResultType operator()() const { return -_arg(); }
169 std::string print() const { return this->printParens(this, "-"); }
170 constexpr static int precedence() { return 3; }
171
172 template <CTTag dtag>
173 auto D() const
174 {
175 return -_arg.template D<dtag>();
176 }
177
178 using CTUnary<T>::_arg;
179};
180
181template <typename T, class = std::enable_if_t<std::is_base_of<CTBase, T>::value>>
182auto
183operator-(const T & arg)
184{
185 return CTUnaryMinus<T>(arg);
186}
187
191template <typename L, typename R>
192class CTBinary : public CTBase
193{
194public:
195 CTBinary(L left, R right) : _left(left), _right(right) {}
196
199
200 template <typename Self>
201 std::string printParens(const Self *, const std::string & op) const
202 {
203 std::string out;
204 if constexpr (L::precedence() > Self::precedence())
205 out = "(" + _left.print() + ")";
206 else
207 out = _left.print();
208
209 out += op;
210
211 if (R::precedence() > Self::precedence() ||
212 (R::precedence() == Self::precedence() && Self::leftAssociative()))
213 out += "(" + _right.print() + ")";
214 else
215 out += _right.print();
216
217 return out;
218 }
219
220protected:
221 const L _left;
222 const R _right;
223};
224
225template <typename C, typename L, typename R>
226auto conditional(const C &, const L &, const R &);
227
231template <typename C, typename L, typename R>
232class CTConditional : public CTBinary<L, R>
233{
234public:
235 CTConditional(C condition, L left, R right) : CTBinary<L, R>(left, right), _condition(condition)
236 {
237 }
238 using typename CTBinary<L, R>::ResultType;
239
240 auto operator()() const { return _condition() ? _left() : _right(); }
241 template <CTTag dtag>
242 auto D() const
243 {
244 return conditional(_condition, _left.template D<dtag>(), _right.template D<dtag>());
245 }
246
247 template <typename Self>
248 std::string print() const
249 {
250 return "conditional(" + _condition.print() + ", " + _left.print() + ", " + _right.print() + ")";
251 }
252
253protected:
254 const C _condition;
255
256 using CTBinary<L, R>::_left;
257 using CTBinary<L, R>::_right;
258};
259
260template <typename C, typename L, typename R>
261auto
262conditional(const C & condition, const L & left, const R & right)
263{
264 return CTConditional<C, L, R>(condition, left, right);
265}
266
267template <typename L, typename R>
268auto
269min(const L & left, const R & right)
270{
271 return CTConditional<decltype(left < right), L, R>(left < right, left, right);
272}
273
274template <typename L, typename R>
275auto
276max(const L & left, const R & right)
277{
278 return CTConditional<decltype(left > right), L, R>(left > right, left, right);
279}
280
284template <CTTag tag, typename T>
285class CTValue : public CTBase
286{
287public:
288 CTValue(const T value) : _value(value) {}
289 typedef T ResultType;
290
291 auto operator()() const { return _value; }
292 template <CTTag dtag>
293 auto D() const
294 {
295 return CTNull<ResultType>();
296 }
297
298 std::string print() const { return Moose::stringify(_value); }
299
300protected:
302};
303
307template <CTTag tag = CTNoTag, typename T>
308auto
309makeValue(T value)
310{
311 return CTValue<tag, T>(value);
312}
313
314template <CTTag start_tag, typename... Values, CTTag... Tags>
315auto
316makeValuesHelper(const std::tuple<Values...> & values, std::integer_sequence<CTTag, Tags...>)
317{
318 if constexpr (start_tag == CTNoTag)
319 return std::make_tuple(CTValue<CTNoTag, Values>(std::get<Tags>(values))...);
320 else
321 return std::make_tuple(CTValue<Tags + start_tag, Values>(std::get<Tags>(values))...);
322}
323
327template <CTTag start_tag = CTNoTag, typename... Ts>
328auto
330{
331 return makeValuesHelper<start_tag>(std::tuple(values...),
332 std::make_integer_sequence<CTTag, sizeof...(values)>{});
333}
334
339template <CTTag tag, typename T>
340class CTRef : public CTBase
341{
342public:
343 CTRef(const T & ref) : _ref(ref) {}
344 const T & operator()() const { return _ref; }
345 std::string print() const { return "[v" + printTag<tag>() + "]"; }
346
347 template <CTTag dtag>
348 auto D() const
349 {
350 if constexpr (tag == dtag)
351 return CTOne<ResultType>();
352 else
353 return CTNull<ResultType>();
354 }
355
357
358protected:
359 const T & _ref;
360};
361
365template <CTTag tag = CTNoTag, typename T>
366auto
367makeRef(const T & ref)
368{
369 return CTRef<tag, T>(ref);
370}
371
372template <CTTag start_tag, typename... Refs, CTTag... Tags>
373auto
374makeRefsHelper(const std::tuple<Refs...> & refs, std::integer_sequence<CTTag, Tags...>)
375{
376 if constexpr (start_tag == CTNoTag)
377 return std::make_tuple(CTRef<CTNoTag, Refs>(std::get<Tags>(refs))...);
378 else
379 return std::make_tuple(CTRef<Tags + start_tag, Refs>(std::get<Tags>(refs))...);
380}
381
385template <CTTag start_tag = CTNoTag, typename... Ts>
386auto
387makeRefs(const Ts &... refs)
388{
389 return makeRefsHelper<start_tag>(std::tie(refs...),
390 std::make_integer_sequence<CTTag, sizeof...(refs)>{});
391}
392
398template <CTTag tag, typename T, typename I>
399class CTArrayRef : public CTBase
400{
401public:
402 CTArrayRef(const T & arr, const I & idx) : _arr(arr), _idx(idx) {}
403 auto operator()() const { return _arr[_idx]; }
404 std::string print() const { return "[a" + printTag<tag>() + "[" + Moose::stringify(_idx) + "]]"; }
405
406 template <CTTag dtag>
407 auto D() const
408 {
409 if constexpr (tag == dtag)
410 return CTOne<ResultType>();
411 else
412 return CTNull<ResultType>();
413 }
414
415 // get the value type returned by operator[]
417 static_assert(!std::is_same_v<ResultType, void>,
418 "Instantiation of CTArrayRef was attempted for a non-subscriptable type.");
419
420protected:
421 const T & _arr;
422 const I & _idx;
423};
424
428template <CTTag tag = CTNoTag, typename T, typename I>
429auto
430makeRef(const T & ref, const I & idx)
431{
432 return CTArrayRef<tag, T, I>(ref, idx);
433}
434
438template <typename L, typename R>
439class CTAdd : public CTBinary<L, R>
440{
441public:
442 CTAdd(L left, R right) : CTBinary<L, R>(left, right) {}
443 using typename CTBinary<L, R>::ResultType;
444
446 {
447 // compile time optimization to skip null terms
448 if constexpr (std::is_base_of<CTNullBase, L>::value && std::is_base_of<CTNullBase, R>::value)
449 return ResultType(0);
450
451 if constexpr (std::is_base_of<CTNullBase, L>::value)
452 return _right();
453
454 if constexpr (std::is_base_of<CTNullBase, R>::value)
455 return _left();
456
457 else
458 return _left() + _right();
459 }
460 std::string print() const { return this->printParens(this, "+"); }
461 constexpr static int precedence() { return 6; }
462
463 template <CTTag dtag>
464 auto D() const
465 {
466 return _left.template D<dtag>() + _right.template D<dtag>();
467 }
468
469 using CTBinary<L, R>::_left;
470 using CTBinary<L, R>::_right;
471};
472
476template <typename L, typename R>
477class CTSub : public CTBinary<L, R>
478{
479public:
480 CTSub(L left, R right) : CTBinary<L, R>(left, right) {}
481 using typename CTBinary<L, R>::ResultType;
482
484 {
485 if constexpr (std::is_base_of<CTNullBase, L>::value && std::is_base_of<CTNullBase, R>::value)
486 return ResultType(0);
487
488 if constexpr (std::is_base_of<CTNullBase, L>::value)
489 return -_right();
490
491 if constexpr (std::is_base_of<CTNullBase, R>::value)
492 return _left();
493
494 else
495 return _left() - _right();
496 }
497 std::string print() const { return this->printParens(this, "-"); }
498 constexpr static int precedence() { return 6; }
499 constexpr static bool leftAssociative() { return true; }
500
501 template <CTTag dtag>
502 auto D() const
503 {
504 return _left.template D<dtag>() - _right.template D<dtag>();
505 }
506
507 using CTBinary<L, R>::_left;
508 using CTBinary<L, R>::_right;
509};
510
514template <typename L, typename R>
515class CTMul : public CTBinary<L, R>
516{
517public:
518 CTMul(L left, R right) : CTBinary<L, R>(left, right) {}
519 using typename CTBinary<L, R>::ResultType;
520
522 {
523 if constexpr (std::is_base_of<CTNullBase, L>::value || std::is_base_of<CTNullBase, R>::value)
524 return ResultType(0);
525
526 if constexpr (std::is_base_of<CTOneBase, L>::value && std::is_base_of<CTOneBase, R>::value)
527 return ResultType(1);
528
529 if constexpr (std::is_base_of<CTOneBase, L>::value)
530 return _right();
531
532 if constexpr (std::is_base_of<CTOneBase, R>::value)
533 return _left();
534
535 else
536 return _left() * _right();
537 }
538 std::string print() const { return this->printParens(this, "*"); }
539 constexpr static int precedence() { return 5; }
540
541 template <CTTag dtag>
542 auto D() const
543 {
544 return _left.template D<dtag>() * _right + _right.template D<dtag>() * _left;
545 }
546
547 using CTBinary<L, R>::_left;
548 using CTBinary<L, R>::_right;
549};
550
554template <typename L, typename R>
555class CTDiv : public CTBinary<L, R>
556{
557public:
558 CTDiv(L left, R right) : CTBinary<L, R>(left, right) {}
559 using typename CTBinary<L, R>::ResultType;
560
562 {
563 if constexpr (std::is_base_of<CTOneBase, R>::value)
564 return _left();
565
566 if constexpr (std::is_base_of<CTNullBase, L>::value && !std::is_base_of<CTNullBase, R>::value)
567 return ResultType(0);
568
569 return _left() / _right();
570 }
571 std::string print() const { return this->printParens(this, "/"); }
572 constexpr static int precedence() { return 5; }
573 constexpr static bool leftAssociative() { return true; }
574
575 template <CTTag dtag>
576 auto D() const
577 {
578 return _left.template D<dtag>() / _right -
579 _left * _right.template D<dtag>() / (_right * _right);
580 }
581
582 using CTBinary<L, R>::_left;
583 using CTBinary<L, R>::_right;
584};
585
587{
588 Less,
589 LessEqual,
590 Greater,
592 Equal,
593 Unequal
594};
595
599template <CTComparisonEnum C, typename L, typename R>
600class CTCompare : public CTBinary<L, R>
601{
602public:
603 CTCompare(L left, R right) : CTBinary<L, R>(left, right) {}
604 typedef bool ResultType;
605
607 {
608 if constexpr (C == CTComparisonEnum::Less)
609 return _left() < _right();
610 if constexpr (C == CTComparisonEnum::LessEqual)
611 return _left() <= _right();
612 if constexpr (C == CTComparisonEnum::Greater)
613 return _left() > _right();
614 if constexpr (C == CTComparisonEnum::GreaterEqual)
615 return _left() >= _right();
616 if constexpr (C == CTComparisonEnum::Equal)
617 return _left() == _right();
618 if constexpr (C == CTComparisonEnum::Unequal)
619 return _left() != _right();
620 }
621 std::string print() const
622 {
623 if constexpr (C == CTComparisonEnum::Less)
624 return this->printParens(this, "<");
625 if constexpr (C == CTComparisonEnum::LessEqual)
626 return this->printParens(this, "<=");
627 if constexpr (C == CTComparisonEnum::Greater)
628 return this->printParens(this, ">");
629 if constexpr (C == CTComparisonEnum::GreaterEqual)
630 return this->printParens(this, ">=");
631 if constexpr (C == CTComparisonEnum::Equal)
632 return this->printParens(this, "==");
633 if constexpr (C == CTComparisonEnum::Unequal)
634 return this->printParens(this, "!=");
635 }
636 constexpr static int precedence() { return 9; }
637 constexpr static bool leftAssociative() { return true; }
638
639 template <CTTag dtag>
640 auto D() const
641 {
642 return CTNull<ResultType>();
643 }
644
645 using CTBinary<L, R>::_left;
646 using CTBinary<L, R>::_right;
647};
648
650template <typename L, typename R>
652template <typename L, typename R>
654template <typename L, typename R>
656template <typename L, typename R>
658template <typename L, typename R>
660template <typename L, typename R>
662
666template <typename L, typename R>
667class CTPow : public CTBinary<L, R>
668{
669public:
670 CTPow(L left, R right) : CTBinary<L, R>(left, right) {}
671 using typename CTBinary<L, R>::ResultType;
672
674 {
675 if constexpr (std::is_base_of<CTNullBase, L>::value)
676 return ResultType(0);
677
678 if constexpr (std::is_base_of<CTOneBase, L>::value || std::is_base_of<CTNullBase, R>::value)
679 return ResultType(1);
680
681 if constexpr (std::is_base_of<CTOneBase, R>::value)
682 return _left();
683
684 return std::pow(_left(), _right());
685 }
686 std::string print() const { return "pow(" + _left.print() + "," + _right.print() + ")"; }
687
688 template <CTTag dtag>
689 auto D() const
690 {
691 if constexpr (std::is_base_of<CTNullBase, decltype(_left.template D<dtag>())>::value &&
692 std::is_base_of<CTNullBase, decltype(_right.template D<dtag>())>::value)
693 return CTNull<ResultType>();
694
695 else if constexpr (std::is_base_of<CTNullBase, decltype(_left.template D<dtag>())>::value)
696 return pow(_left, _right) * _right.template D<dtag>() * log(_left);
697
698 else if constexpr (std::is_base_of<CTNullBase, decltype(_right.template D<dtag>())>::value)
699 return pow(_left, _right) * _right * _left.template D<dtag>() / _left;
700
701 else
702 return pow(_left, _right) *
703 (_right.template D<dtag>() * log(_left) + _right * _left.template D<dtag>() / _left);
704 }
705
706 using CTBinary<L, R>::_left;
707 using CTBinary<L, R>::_right;
708};
709
713template <typename B, typename E>
714auto
715pow(const B & base, const E & exp)
716{
717 if constexpr (std::is_base_of<CTBase, B>::value && std::is_base_of<CTBase, E>::value)
718 return CTPow(base, exp);
719 else if constexpr (std::is_base_of<CTBase, E>::value)
720 return CTPow(makeValue(base), exp);
721 else if constexpr (std::is_base_of<CTBase, B>::value)
722 return CTPow(base, makeValue(exp));
723 else
724 return CTPow(makeValue(base), makeValue(exp));
725}
726
730template <typename B, int E>
731class CTIPow : public CTUnary<B>
732{
733public:
734 CTIPow(B base) : CTUnary<B>(base) {}
735 using typename CTUnary<B>::ResultType;
736
738 {
739 if constexpr (std::is_base_of<CTNullBase, B>::value)
740 return ResultType(0);
741
742 else if constexpr (std::is_base_of<CTOneBase, B>::value || E == 0)
743 return ResultType(1);
744
745 else if constexpr (E == 1)
746 return _arg();
747
748 else if constexpr (E < 0)
749 return 1.0 / libMesh::Utility::pow<-E>(_arg());
750
751 else
752 return libMesh::Utility::pow<E>(_arg());
753 }
754 std::string print() const { return "pow<" + Moose::stringify(E) + ">(" + _arg.print() + ")"; }
755
756 template <CTTag dtag>
757 auto D() const
758 {
759 if constexpr (E == 1)
760 return _arg.template D<dtag>();
761
762 else if constexpr (E == 0)
763 return CTNull<ResultType>();
764
765 else
766 return pow<E - 1>(_arg) * E * _arg.template D<dtag>();
767 }
768
769 using CTUnary<B>::_arg;
770};
771
775template <int E, typename B>
776auto
777pow(const B & base)
778{
779 if constexpr (std::is_base_of<CTBase, B>::value)
780 return CTIPow<B, E>(base);
781 else
782 return CTIPow<CTValue<CTNoTag, B>, E>(makeValue(base));
783}
784
789#define CT_OPERATOR_BINARY(op, OP) \
790 template <typename L, \
791 typename R, \
792 class = std::enable_if_t<std::is_base_of<CTBase, L>::value || \
793 std::is_base_of<CTBase, R>::value>> \
794 auto operator op(const L & left, const R & right) \
795 { \
796 /* We need a template arguments here because: */ \
797 /* alias template deduction is only available with '-std=c++2a' or '-std=gnu++2a' */ \
798 if constexpr (std::is_base_of<CTBase, L>::value && std::is_base_of<CTBase, R>::value) \
799 return OP<L, R>(left, right); \
800 else if constexpr (std::is_base_of<CTBase, L>::value) \
801 return OP<L, decltype(makeValue(right))>(left, makeValue(right)); \
802 else if constexpr (std::is_base_of<CTBase, R>::value) \
803 return OP<decltype(makeValue(left)), R>(makeValue(left), right); \
804 else \
805 static_assert(libMesh::always_false<L>, "This should not be instantiated."); \
806 }
807
818
824#define CT_SIMPLE_UNARY_FUNCTION(name, derivative) \
825 template <typename T> \
826 class CTF##name : public CTUnary<T> \
827 { \
828 public: \
829 CTF##name(T arg) : CTUnary<T>(arg) {} \
830 auto operator()() const \
831 { \
832 using std::name; \
833 return name(_arg()); \
834 } \
835 template <CTTag dtag> \
836 auto D() const \
837 { \
838 return derivative; \
839 } \
840 std::string print() const { return #name "(" + _arg.print() + ")"; } \
841 constexpr static int precedence() { return 2; } \
842 using typename CTUnary<T>::ResultType; \
843 using CTUnary<T>::_arg; \
844 }; \
845 template <typename T> \
846 auto name(const T & v) \
847 { \
848 using namespace CompileTimeDerivatives; \
849 if constexpr (std::is_base_of<CTBase, T>::value) \
850 return CTF##name(v); \
851 else \
852 return CTF##name(makeValue(v)); \
853 }
854
855CT_SIMPLE_UNARY_FUNCTION(exp, exp(_arg) * _arg.template D<dtag>())
856CT_SIMPLE_UNARY_FUNCTION(log, _arg.template D<dtag>() / _arg)
857CT_SIMPLE_UNARY_FUNCTION(sin, cos(_arg) * _arg.template D<dtag>())
858CT_SIMPLE_UNARY_FUNCTION(cos, -1.0 * sin(_arg) * _arg.template D<dtag>())
859CT_SIMPLE_UNARY_FUNCTION(tan, (pow<2>(tan(_arg)) + 1.0) * _arg.template D<dtag>())
860CT_SIMPLE_UNARY_FUNCTION(sqrt, 1.0 / (2.0 * sqrt(_arg)) * _arg.template D<dtag>())
861CT_SIMPLE_UNARY_FUNCTION(tanh, (1.0 - pow<2>(tanh(_arg))) * _arg.template D<dtag>())
862CT_SIMPLE_UNARY_FUNCTION(sinh, cosh(_arg) * _arg.template D<dtag>())
863CT_SIMPLE_UNARY_FUNCTION(cosh, sinh(_arg) * _arg.template D<dtag>())
864CT_SIMPLE_UNARY_FUNCTION(erf,
865 2.0 * exp(-pow<2>(_arg)) / sqrt(libMesh::pi) * _arg.template D<dtag>())
866CT_SIMPLE_UNARY_FUNCTION(atan, 1.0 / (pow<2>(_arg) + 1.0) * _arg.template D<dtag>())
867
873#define CT_SIMPLE_BINARY_FUNCTION_CLASS(name, derivative) \
874 template <typename L, typename R> \
875 class CTF##name : public CTBinary<L, R> \
876 { \
877 public: \
878 CTF##name(L left, R right) : CTBinary<L, R>(left, right) {} \
879 auto operator()() const \
880 { \
881 using std::name; \
882 return name(_left(), _right()); \
883 } \
884 template <CTTag dtag> \
885 auto D() const \
886 { \
887 return derivative; \
888 } \
889 std::string print() const { return #name "(" + _left.print() + ", " + _right.print() + ")"; } \
890 constexpr static int precedence() { return 2; } \
891 using typename CTBinary<L, R>::ResultType; \
892 using CTBinary<L, R>::_left; \
893 using CTBinary<L, R>::_right; \
894 };
895#define CT_SIMPLE_BINARY_FUNCTION_FUNC(name) \
896 template <typename L, typename R> \
897 auto name(const L & l, const R & r) \
898 { \
899 using namespace CompileTimeDerivatives; \
900 if constexpr (std::is_base_of<CTBase, L>::value && std::is_base_of<CTBase, R>::value) \
901 return CTF##name(l, r); \
902 else if constexpr (std::is_base_of<CTBase, L>::value) \
903 return CTF##name(l, makeValue(r)); \
904 else if constexpr (std::is_base_of<CTBase, R>::value) \
905 return CTF##name(makeValue(l), r); \
906 else \
907 return CTF##name(makeValue(l), makeValue(r)); \
908 }
909
911 (-_left * _right.template D<dtag>() +
912 _left.template D<dtag>() * _right) /
913 (pow<2>(_left) + pow<2>(_right)))
914CT_SIMPLE_BINARY_FUNCTION_FUNC(atan2)
915
916template <typename T, int N, int M>
918{
919public:
920 template <typename... Ts>
921 CTMatrix(Ts... a) : _data({a...})
922 {
923 static_assert(sizeof...(a) == N * M, "Invalid number of matrix entries");
924 }
925 T & operator()(std::size_t n, std::size_t m) { return _data[M * n + m]; }
926 const T & operator()(std::size_t n, std::size_t m) const { return _data[M * n + m]; }
927
928protected:
929 std::array<T, N * M> _data;
930};
931
932template <typename... Ds>
934{
935public:
936 static constexpr auto N = sizeof...(Ds);
937
938 CTStandardDeviation(std::tuple<Ds...> derivatives, CTMatrix<Real, N, N> covariance)
939 : _derivatives(derivatives), _covariance(covariance)
940 {
941 }
942 auto operator()() const { return std::sqrt(evalHelper(std::make_index_sequence<N>{})); }
943
944 typedef typename CTSuperType<typename Ds::ResultType...>::type ResultType;
945
946protected:
947 template <int R, std::size_t... Is>
948 ResultType rowMul(std::index_sequence<Is...>, const std::array<ResultType, N> & d) const
949 {
950 return ((_covariance(R, Is) * d[Is]) + ...);
951 }
952
953 template <std::size_t... Is>
954 auto evalHelper(const std::index_sequence<Is...> & is) const
955 {
956 const std::array<ResultType, N> d{std::get<Is>(_derivatives)()...};
957 return ((rowMul<Is>(is, d) * d[Is]) + ...);
958 }
959
960 const std::tuple<Ds...> _derivatives;
962};
963
964template <CTTag start_tag, typename T, CTTag... Tags>
965auto
966makeStandardDeviationHelper(const T & f, std::integer_sequence<CTTag, Tags...>)
967{
968 return std::make_tuple(f.template D<Tags + start_tag>()...);
969}
970
975template <CTTag start_tag, typename T, int N>
976auto
977makeStandardDeviation(const T & f, const CTMatrix<Real, N, N> covariance)
978{
979 return CTStandardDeviation(
980 makeStandardDeviationHelper<start_tag>(f, std::make_integer_sequence<CTTag, N>{}),
981 covariance);
982}
983
984} // namespace CompileTimeDerivatives
std::array< Real, 2 > values
Definition MortarUtils.C:52
void ErrorVector unsigned int
Array variable value, referencing an entry in an indexable container of T types.
CTCleanType< decltype((static_cast< T >(0))[0])> ResultType
All compile time derivative system objects derive from this (empty) base class.
static constexpr bool leftAssociative()
left/right associative property should reflect C++ operator properties exactly
static constexpr int precedence()
precedence should reflect C++ operator precedence exactly (higher is binding tighter)
Base class for a binary operator/function.
libMesh::CompareTypes< typenameL::ResultType, typenameR::ResultType >::supertype ResultType
std::string printParens(const Self *, const std::string &op) const
Binary comparison operator node.
Base class for a ternary functions.
CTConditional(C condition, L left, R right)
static constexpr bool leftAssociative()
Integer exponent power operator.
const T & operator()(std::size_t n, std::size_t m) const
T & operator()(std::size_t n, std::size_t m)
Multiplication operator node.
Template class to represent a "zero" value.
Template class to represent a "one" value.
Power operator where both base and exponent can be arbitrary operators.
Variable value, referencing a variable of type T.
CTStandardDeviation(std::tuple< Ds... > derivatives, CTMatrix< Real, N, N > covariance)
ResultType rowMul(std::index_sequence< Is... >, const std::array< ResultType, N > &d) const
CTSuperType< typenameDs::ResultType... >::type ResultType
auto evalHelper(const std::index_sequence< Is... > &is) const
static constexpr bool leftAssociative()
Base class for a unary operator/function.
std::string printParens(const Self *, const std::string &op) const
auto max(const L &left, const R &right)
auto exp(const T &)
auto makeRefs(const Ts &... refs)
Helper function to build a list of tagged references to variables.
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template D< dtag >()/_arg) CT_SIMPLE_UNARY_FUNCTION(sin
auto makeStandardDeviation(const T &f, const CTMatrix< Real, N, N > covariance)
Helper function to build a standard deviation object for a function with N parameters with consecutiv...
auto makeRefsHelper(const std::tuple< Refs... > &refs, std::integer_sequence< CTTag, Tags... >)
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sin(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tan
auto makeRef(const T &ref)
Helper function to build a tagged reference to a variable.
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template pow< 2 >(tan(_arg))+1.0) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(sqrt
auto makeStandardDeviationHelper(const T &f, std::integer_sequence< CTTag, Tags... >)
auto makeValues(Ts... values)
Helper function to build a list of (potentially tagged) values.
auto min(const L &left, const R &right)
auto pow(const B &base, const E &exp)
pow(base, exponent) function overload.
auto makeValue(T value)
Helper function to build a (potentially tagged) value.
typename std::remove_const< typename std::remove_reference< T >::type >::type CTCleanType
auto conditional(const C &, const L &, const R &)
int CTTag
Operators representing variable values need to be tagged.
auto log(const T &)
CT_OPERATOR_BINARY(+, CTAdd) CT_OPERATOR_BINARY(-
auto makeValuesHelper(const std::tuple< Values... > &values, std::integer_sequence< CTTag, Tags... >)
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sqrt(_arg)) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tanh
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cos(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cos
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cosh(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cosh
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template sinh(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(erf
CT_SIMPLE_BINARY_FUNCTION_CLASS(atan2,(-_left *_right.template D< dtag >()+_left.template D< dtag >() *_right)/(pow< 2 >(_left)+pow< 2 >(_right))) CT_SIMPLE_BINARY_FUNCTION_FUNC(atan2) template< typename T
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
MooseUnits pow(const MooseUnits &, int)
Definition Units.C:537
std::conditional<(sizeof...(Ts)>0), typenameCTSuperType< typenamelibMesh::CompareTypes< T1, T2 >::supertype, Ts... >::type, typenamelibMesh::CompareTypes< T1, T2 >::supertype >::type type