12#include "libmesh/utility.h"
13#include "libmesh/compare_types.h"
41using CTCleanType =
typename std::remove_const<typename std::remove_reference<T>::type>::type;
43template <
typename... Ts>
52template <
typename T1,
typename T2,
typename... Ts>
55 typedef typename std::conditional<
79template <
typename B,
typename E>
80auto pow(
const B & base,
const E &
exp);
81template <
int E,
typename B>
101 std::string
print()
const {
return "0"; }
103 template <CTTag dtag>
122 std::string
print()
const {
return "1"; }
124 template <CTTag dtag>
140 template <
typename Self>
141 std::string
printParens(
const Self *,
const std::string & op)
const
143 std::string out = op;
144 if constexpr (T::precedence() > Self::precedence())
145 out +=
"(" +
_arg.print() +
")";
172 template <CTTag dtag>
181template <typename T, class = std::enable_if_t<std::is_base_of<CTBase, T>::value>>
191template <
typename L,
typename R>
200 template <
typename Self>
201 std::string
printParens(
const Self *,
const std::string & op)
const
204 if constexpr (L::precedence() > Self::precedence())
205 out =
"(" +
_left.print() +
")";
211 if (R::precedence() > Self::precedence() ||
212 (R::precedence() == Self::precedence() && Self::leftAssociative()))
213 out +=
"(" +
_right.print() +
")";
225template <
typename C,
typename L,
typename R>
231template <
typename C,
typename L,
typename R>
241 template <CTTag dtag>
247 template <
typename Self>
260template <
typename C,
typename L,
typename R>
267template <
typename L,
typename R>
269min(
const L & left,
const R & right)
274template <
typename L,
typename R>
276max(
const L & left,
const R & right)
278 return CTConditional<
decltype(left > right), L, R>(left > right, left, right);
284template <CTTag tag,
typename T>
292 template <CTTag dtag>
307template <CTTag tag = CTNoTag,
typename T>
314template <
CTTag start_tag,
typename... Values,
CTTag... Tags>
318 if constexpr (start_tag ==
CTNoTag)
331 return makeValuesHelper<start_tag>(std::tuple(
values...),
332 std::make_integer_sequence<
CTTag,
sizeof...(values)>{});
339template <CTTag tag,
typename T>
345 std::string
print()
const {
return "[v" + printTag<tag>() +
"]"; }
347 template <CTTag dtag>
350 if constexpr (tag == dtag)
365template <CTTag tag = CTNoTag,
typename T>
372template <
CTTag start_tag,
typename... Refs,
CTTag... Tags>
374makeRefsHelper(
const std::tuple<Refs...> & refs, std::integer_sequence<CTTag, Tags...>)
376 if constexpr (start_tag ==
CTNoTag)
389 return makeRefsHelper<start_tag>(std::tie(refs...),
390 std::make_integer_sequence<
CTTag,
sizeof...(refs)>{});
398template <CTTag tag,
typename T,
typename I>
406 template <CTTag dtag>
409 if constexpr (tag == dtag)
417 static_assert(!std::is_same_v<ResultType, void>,
418 "Instantiation of CTArrayRef was attempted for a non-subscriptable type.");
428template <CTTag tag = CTNoTag,
typename T,
typename I>
438template <
typename L,
typename R>
448 if constexpr (std::is_base_of<CTNullBase, L>::value && std::is_base_of<CTNullBase, R>::value)
451 if constexpr (std::is_base_of<CTNullBase, L>::value)
454 if constexpr (std::is_base_of<CTNullBase, R>::value)
463 template <CTTag dtag>
476template <
typename L,
typename R>
485 if constexpr (std::is_base_of<CTNullBase, L>::value && std::is_base_of<CTNullBase, R>::value)
488 if constexpr (std::is_base_of<CTNullBase, L>::value)
491 if constexpr (std::is_base_of<CTNullBase, R>::value)
501 template <CTTag dtag>
514template <
typename L,
typename R>
523 if constexpr (std::is_base_of<CTNullBase, L>::value || std::is_base_of<CTNullBase, R>::value)
526 if constexpr (std::is_base_of<CTOneBase, L>::value && std::is_base_of<CTOneBase, R>::value)
529 if constexpr (std::is_base_of<CTOneBase, L>::value)
532 if constexpr (std::is_base_of<CTOneBase, R>::value)
541 template <CTTag dtag>
554template <
typename L,
typename R>
563 if constexpr (std::is_base_of<CTOneBase, R>::value)
566 if constexpr (std::is_base_of<CTNullBase, L>::value && !std::is_base_of<CTNullBase, R>::value)
575 template <CTTag dtag>
599template <CTComparisonEnum C,
typename L,
typename R>
639 template <CTTag dtag>
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>
666template <
typename L,
typename R>
675 if constexpr (std::is_base_of<CTNullBase, L>::value)
678 if constexpr (std::is_base_of<CTOneBase, L>::value || std::is_base_of<CTNullBase, R>::value)
681 if constexpr (std::is_base_of<CTOneBase, R>::value)
688 template <CTTag dtag>
713template <
typename B,
typename E>
717 if constexpr (std::is_base_of<CTBase, B>::value && std::is_base_of<CTBase, E>::value)
719 else if constexpr (std::is_base_of<CTBase, E>::value)
721 else if constexpr (std::is_base_of<CTBase, B>::value)
730template <
typename B,
int E>
739 if constexpr (std::is_base_of<CTNullBase, B>::value)
742 else if constexpr (std::is_base_of<CTOneBase, B>::value || E == 0)
745 else if constexpr (E == 1)
748 else if constexpr (E < 0)
749 return 1.0 / libMesh::Utility::pow<-E>(
_arg());
752 return libMesh::Utility::pow<E>(
_arg());
756 template <CTTag dtag>
759 if constexpr (E == 1)
762 else if constexpr (E == 0)
775template <
int E,
typename B>
779 if constexpr (std::is_base_of<CTBase, B>::value)
789#define CT_OPERATOR_BINARY(op, OP) \
790 template <typename L, \
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) \
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); \
805 static_assert(libMesh::always_false<L>, "This should not be instantiated."); \
824#define CT_SIMPLE_UNARY_FUNCTION(name, derivative) \
825 template <typename T> \
826 class CTF##name : public CTUnary<T> \
829 CTF##name(T arg) : CTUnary<T>(arg) {} \
830 auto operator()() const \
833 return name(_arg()); \
835 template <CTTag dtag> \
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; \
845 template <typename T> \
846 auto name(const T & v) \
848 using namespace CompileTimeDerivatives; \
849 if constexpr (std::is_base_of<CTBase, T>::value) \
850 return CTF##name(v); \
852 return CTF##name(makeValue(v)); \
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,
866CT_SIMPLE_UNARY_FUNCTION(atan, 1.0 / (
pow<2>(_arg) + 1.0) * _arg.template D<dtag>())
873#define CT_SIMPLE_BINARY_FUNCTION_CLASS(name, derivative) \
874 template <typename L, typename R> \
875 class CTF##name : public CTBinary<L, R> \
878 CTF##name(L left, R right) : CTBinary<L, R>(left, right) {} \
879 auto operator()() const \
882 return name(_left(), _right()); \
884 template <CTTag dtag> \
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; \
895#define CT_SIMPLE_BINARY_FUNCTION_FUNC(name) \
896 template <typename L, typename R> \
897 auto name(const L & l, const R & r) \
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); \
907 return CTF##name(makeValue(l), makeValue(r)); \
911 (-_left * _right.template
D<dtag>() +
912 _left.template
D<dtag>() * _right) /
914CT_SIMPLE_BINARY_FUNCTION_FUNC(atan2)
916template <typename T,
int N,
int M>
920 template <
typename... Ts>
923 static_assert(
sizeof...(a) ==
N * M,
"Invalid number of matrix entries");
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]; }
932template <
typename... Ds>
936 static constexpr auto N =
sizeof...(Ds);
947 template <
int R, std::size_t... Is>
953 template <std::size_t... Is>
956 const std::array<ResultType, N> d{std::get<Is>(
_derivatives)()...};
957 return ((rowMul<Is>(is, d) * d[Is]) + ...);
964template <
CTTag start_tag,
typename T,
CTTag... Tags>
968 return std::make_tuple(f.template D<Tags + start_tag>()...);
975template <CTTag start_tag,
typename T,
int N>
980 makeStandardDeviationHelper<start_tag>(f, std::make_integer_sequence<CTTag, N>{}),
std::array< Real, 2 > values
void ErrorVector unsigned int
static constexpr int precedence()
ResultType operator()() const
std::string print() const
Array variable value, referencing an entry in an indexable container of T types.
CTArrayRef(const T &arr, const I &idx)
CTCleanType< decltype((static_cast< T >(0))[0])> ResultType
std::string print() const
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.
CTBinary(L left, R right)
libMesh::CompareTypes< typenameL::ResultType, typenameR::ResultType >::supertype ResultType
std::string printParens(const Self *, const std::string &op) const
Binary comparison operator node.
static constexpr bool leftAssociative()
static constexpr int precedence()
CTCompare(L left, R right)
ResultType operator()() const
std::string print() const
Base class for a ternary functions.
CTConditional(C condition, L left, R right)
std::string print() const
static constexpr bool leftAssociative()
ResultType operator()() const
static constexpr int precedence()
std::string print() const
Integer exponent power operator.
ResultType operator()() const
std::string print() const
const T & operator()(std::size_t n, std::size_t m) const
T & operator()(std::size_t n, std::size_t m)
std::array< T, N *M > _data
Multiplication operator node.
static constexpr int precedence()
std::string print() const
ResultType operator()() const
Template class to represent a "zero" value.
std::string print() const
ResultType operator()() const
CTCleanType< T > ResultType
Template class to represent a "one" value.
std::string print() const
ResultType operator()() const
CTCleanType< T > ResultType
Power operator where both base and exponent can be arbitrary operators.
ResultType operator()() const
std::string print() const
Variable value, referencing a variable of type T.
const T & operator()() const
CTCleanType< T > ResultType
std::string print() const
CTStandardDeviation(std::tuple< Ds... > derivatives, CTMatrix< Real, N, N > covariance)
const CTMatrix< Real, N, N > _covariance
const std::tuple< Ds... > _derivatives
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
Subtraction operator node.
static constexpr bool leftAssociative()
static constexpr int precedence()
ResultType operator()() const
std::string print() const
std::string print() const
static constexpr int precedence()
ResultType operator()() const
Base class for a unary operator/function.
std::string printParens(const Self *, const std::string &op) const
std::string print() const
auto max(const L &left, const R &right)
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 operator-(const T &arg)
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.
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
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
MooseUnits pow(const MooseUnits &, int)
std::conditional<(sizeof...(Ts)>0), typenameCTSuperType< typenamelibMesh::CompareTypes< T1, T2 >::supertype, Ts... >::type, typenamelibMesh::CompareTypes< T1, T2 >::supertype >::type type