34template <
typename value_type,
typename gradient_type>
58 static constexpr bool value =
false;
62template <
typename value_type,
typename gradient_type>
65 static constexpr bool value =
true;
69template <
typename other_type,
typename value_type,
typename gradient_type,
70 typename =
typename std::enable_if<
71 std::is_arithmetic<other_type>::value ||
89template <
typename other_type,
typename value_type,
typename gradient_type,
90 typename =
typename std::enable_if<
91 std::is_arithmetic<other_type>::value ||
101template <
typename value_type_a,
typename gradient_type_a,
typename value_type_b,
typename gradient_type_b>
105 decltype(
a.gradient +
b.gradient)>
107 return {
a.
value +
b.value,
a.gradient +
b.gradient};
111template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
113dual<value_type, gradient_type>
115 return {-x.value, -x.gradient};
119template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
127template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
135template <
typename value_type_a,
typename gradient_type_a,
typename value_type_b,
typename gradient_type_b>
139 decltype(
a.gradient -
b.gradient)>
141 return {
a.
value -
b.value,
a.gradient -
b.gradient};
145template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
153template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
156dual<
decltype(
a *
b.value),
decltype(
a *
b.gradient)>
158 return {
a *
b.value,
a *
b.gradient};
162template <
typename value_type_a,
typename gradient_type_a,
typename value_type_b,
typename gradient_type_b>
166 decltype(
b.value *
a.gradient +
a.value *
b.gradient)>
168 return {
a.
value *
b.value,
b.value *
a.gradient +
a.value *
b.gradient};
172template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
180template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
183 decltype(-(
a / (
b.value *
b.value)) *
b.gradient)>
185 return {
a /
b.
value, -(
a / (
b.value *
b.value)) *
b.gradient};
189template <
typename value_type_a,
typename gradient_type_a,
typename value_type_b,
typename gradient_type_b>
193 decltype((
a.gradient /
b.value) -
194 (
a.value *
b.gradient) /
195 (
b.value *
b.value))>
197 return {
a.
value /
b.value, (
a.gradient /
b.value) - (
a.value *
b.gradient) / (
b.value *
b.value)};
205#define mfem_binary_comparator_overload(x) \
206 template <typename value_type, typename gradient_type> \
207 MFEM_HOST_DEVICE constexpr bool operator x( \
208 const dual<value_type, gradient_type>& a, \
211 return a.value x b; \
214 template <typename value_type, typename gradient_type> \
215 MFEM_HOST_DEVICE constexpr bool operator x( \
217 const dual<value_type, gradient_type>& b) \
219 return a x b.value; \
222 template <typename value_type_a, \
223 typename gradient_type_a, \
224 typename value_type_b, \
225 typename gradient_type_b> MFEM_HOST_DEVICE \
226 constexpr bool operator x( \
227 const dual<value_type_a, gradient_type_a>& a, \
228 const dual<value_type_b, gradient_type_b>& b) \
230 return a.value x b.value; \
239#undef mfem_binary_comparator_overload
242template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
247 a.gradient +=
b.gradient;
252template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
257 a.gradient -=
b.gradient;
262template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
271template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
280template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
283 return (x.
value >= 0) ? x : -x;
287template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
295template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
304template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
313template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
322template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
331template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
340template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
344 value_type
f =
tan(
a.value);
345 return {
f,
a.gradient * (value_type{1} +
f *
f)};
349template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
357template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
365template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
373template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
379 value_type value =
pow(
a.value,
b.value);
380 return {value, value * (
a.gradient * (
b.value /
a.value) +
b.gradient *
log(
a.value))};
384template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
389 value_type value =
pow(
a,
b.value);
390 return {value, value *
b.gradient *
log(
a)};
394template <
typename value_type > MFEM_HOST_DEVICE
395value_type
pow(value_type
a, value_type
b)
402template <
typename value_type,
typename gradient_type> MFEM_HOST_DEVICE
406 value_type value =
pow(
a.value,
b);
407 return {value, value *
a.gradient *
b /
a.value};
411template <
typename value_type,
typename gradient_type,
int... n>
422template <
typename T> MFEM_HOST_DEVICE T
get_value(
const T& arg) {
return arg; }
425template <
typename value_type,
typename gradient_type>
432template <
typename value_type,
typename gradient_type>
MFEM_HOST_DEVICE constexpr auto operator-(dual< value_type, gradient_type > x) -> dual< value_type, gradient_type >
unary negation of a dual number
MFEM_HOST_DEVICE constexpr auto operator+(dual< value_type, gradient_type > a, other_type b) -> dual< value_type, gradient_type >
addition of a dual number and a non-dual number
MFEM_HOST_DEVICE dual< value_type, gradient_type > tan(dual< value_type, gradient_type > a)
implementation of tan for dual numbers
MFEM_HOST_DEVICE T get_value(const T &arg)
return the "value" part from a given type. For non-dual types, this is just the identity function
gradient_type MFEM_HOST_DEVICE dual< value_type, gradient_type > & operator+=(dual< value_type, gradient_type > &a, const dual< value_type, gradient_type > &b)
MFEM_HOST_DEVICE dual< value_type, gradient_type > cos(dual< value_type, gradient_type > a)
implementation of cosine for dual numbers
MFEM_HOST_DEVICE dual< value_type, gradient_type > acos(dual< value_type, gradient_type > a)
implementation of acos for dual numbers
MFEM_HOST_DEVICE dual< value_type, gradient_type > abs(dual< value_type, gradient_type > x)
implementation of absolute value function for dual numbers
MFEM_HOST_DEVICE dual< value_type, gradient_type > sinh(dual< value_type, gradient_type > a)
implementation of sinh for dual numbers
MFEM_HOST_DEVICE dual< value_type, gradient_type > sin(dual< value_type, gradient_type > a)
implementation of sine for dual numbers
MFEM_HOST_DEVICE dual< value_type, gradient_type > & operator-=(dual< value_type, gradient_type > &a, const dual< value_type, gradient_type > &b)
compound assignment (-) for dual numbers
std::ostream & operator<<(std::ostream &os, dual< value_type, gradient_type > A)
overload of operator<< for dual to work with work with standard output streams
MFEM_HOST_DEVICE constexpr auto type(const tuple< T... > &values)
a function intended to be used for extracting the ith type from a tuple.
MFEM_HOST_DEVICE dual< value_type, gradient_type > log(dual< value_type, gradient_type > a)
implementation of the natural logarithm function for dual numbers
MFEM_HOST_DEVICE dual< value_type, gradient_type > exp(dual< value_type, gradient_type > a)
implementation of exponential function for dual numbers
MFEM_HOST_DEVICE dual< value_type, gradient_type > sqrt(dual< value_type, gradient_type > x)
implementation of square root for dual numbers
MFEM_HOST_DEVICE dual< value_type, gradient_type > asin(dual< value_type, gradient_type > a)
implementation of asin for dual numbers
MFEM_HOST_DEVICE constexpr dual< real_t, real_t > make_dual(real_t x)
promote a value to a dual number of the appropriate type
mfem_binary_comparator_overload(<) mfem_binary_comparator_overload(<
implement operator<= for dual numbers
MFEM_HOST_DEVICE constexpr auto operator*(const dual< value_type, gradient_type > &a, real_t b) -> dual< decltype(a.value *b), decltype(a.gradient *b)>
multiplication of a dual number and a non-dual number
MFEM_HOST_DEVICE constexpr auto operator/(const dual< value_type, gradient_type > &a, real_t b) -> dual< decltype(a.value/b), decltype(a.gradient/b)>
division of a dual number by a non-dual number
MFEM_HOST_DEVICE gradient_type get_gradient(dual< value_type, gradient_type > arg)
return the "gradient" part from a dual number type
MFEM_HOST_DEVICE dual< value_type, gradient_type > atan(dual< value_type, gradient_type > a)
implementation of atan for dual numbers
MFEM_HOST_DEVICE dual< value_type, gradient_type > pow(dual< value_type, gradient_type > a, dual< value_type, gradient_type > b)
implementation of a (dual) raised to the b (dual) power
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Dual number struct (value plus gradient)
MFEM_HOST_DEVICE auto operator=(real_t a) -> dual< value_type, gradient_type > &
assignment of a real_t to a value of a dual. Promotes a real_t to a dual with a zero gradient value.
gradient_type gradient
the partial derivatives of value w.r.t. some other quantity
value_type value
the actual numerical value
class for checking if a type is a dual number or not
static constexpr bool value
whether or not type T is a dual number