https://mooseframework.inl.gov
MathUtils.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 "Moose.h"
13 #include "MooseError.h"
14 #include "MooseTypes.h"
15 #include "libmesh/libmesh.h"
16 #include "libmesh/utility.h"
17 #include "libmesh/numeric_vector.h"
18 #include "libmesh/compare_types.h"
19 #include "libmesh/point.h"
20 
21 namespace MathUtils
22 {
23 
25 static constexpr Real sqrt2 = 1.4142135623730951;
26 
27 Real poly1Log(Real x, Real tol, unsigned int derivative_order);
28 Real poly2Log(Real x, Real tol, unsigned int derivative_order);
29 Real poly3Log(Real x, Real tol, unsigned int derivative_order);
30 Real poly4Log(Real x, Real tol, unsigned int derivative_order);
31 Real taylorLog(Real x);
40 Point barycentricToCartesian2D(const Point & p0,
41  const Point & p1,
42  const Point & p2,
43  const Real b0,
44  const Real b1,
45  const Real b2);
54 Point barycentricToCartesian3D(const Point & p0,
55  const Point & p1,
56  const Point & p2,
57  const Point & p3,
58  const Real b0,
59  const Real b1,
60  const Real b2,
61  const Real b3);
67 Point circumcenter2D(const Point & p0, const Point & p1, const Point & p2);
73 Point circumcenter3D(const Point & p0, const Point & p1, const Point & p2, const Point & p3);
74 
75 template <typename T>
76 T
77 round(T x)
78 {
79  return ::round(x); // use round from math.h
80 }
81 
82 template <typename T>
83 T
84 sign(T x)
85 {
86  return x >= 0.0 ? 1.0 : -1.0;
87 }
88 
89 template <typename T>
90 T
91 pow(T x, int e)
92 {
93  bool neg = false;
94  T result = 1.0;
95 
96  if (e < 0)
97  {
98  neg = true;
99  e = -e;
100  }
101 
102  while (e)
103  {
104  // if bit 0 is set multiply the current power of two factor of the exponent
105  if (e & 1)
106  result *= x;
107 
108  // x is incrementally set to consecutive powers of powers of two
109  x *= x;
110 
111  // bit shift the exponent down
112  e >>= 1;
113  }
114 
115  return neg ? 1.0 / result : result;
116 }
117 
118 template <typename T>
119 T
121 {
122  return x < 0.0 ? 0.0 : 1.0;
123 }
124 
125 template <typename T>
126 T
127 regularizedHeavyside(const T & x, Real smoothing_length)
128 {
129  if (x <= -smoothing_length)
130  return 0.0;
131  else if (x < smoothing_length)
132  {
133  using std::sin;
134  return 0.5 * (1 + sin(libMesh::pi * x / 2 / smoothing_length));
135  }
136  else
137  return 1.0;
138 }
139 
140 template <typename T>
141 T
142 regularizedHeavysideDerivative(const T & x, Real smoothing_length)
143 {
144  if (x < smoothing_length && x > -smoothing_length)
145  {
146  using std::cos;
147  return 0.25 * libMesh::pi / smoothing_length * (cos(libMesh::pi * x / 2 / smoothing_length));
148  }
149  else
150  return 0.0;
151 }
152 
153 template <typename T>
154 T
156 {
157  return x > 0.0 ? x : 0.0;
158 }
159 
160 template <typename T>
161 T
163 {
164  return x < 0.0 ? x : 0.0;
165 }
166 
167 template <
168  typename T,
169  typename T2,
170  typename T3,
171  typename std::enable_if<libMesh::ScalarTraits<T>::value && libMesh::ScalarTraits<T2>::value &&
173  int>::type = 0>
174 void
175 addScaled(const T & a, const T2 & b, T3 & result)
176 {
177  result += a * b;
178 }
179 
180 template <typename T,
181  typename T2,
182  typename T3,
183  typename std::enable_if<libMesh::ScalarTraits<T>::value, int>::type = 0>
184 void
185 addScaled(const T & scalar,
186  const libMesh::NumericVector<T2> & numeric_vector,
188 {
189  result.add(scalar, numeric_vector);
190 }
191 
192 template <
193  typename T,
194  typename T2,
195  template <typename>
196  class W,
197  template <typename>
198  class W2,
199  typename std::enable_if<std::is_same<typename W<T>::index_type, unsigned int>::value &&
200  std::is_same<typename W2<T2>::index_type, unsigned int>::value,
201  int>::type = 0>
203 dotProduct(const W<T> & a, const W2<T2> & b)
204 {
205  return a * b;
206 }
207 
208 template <typename T,
209  typename T2,
210  template <typename>
211  class W,
212  template <typename>
213  class W2,
214  typename std::enable_if<std::is_same<typename W<T>::index_type,
215  std::tuple<unsigned int, unsigned int>>::value &&
216  std::is_same<typename W2<T2>::index_type,
217  std::tuple<unsigned int, unsigned int>>::value,
218  int>::type = 0>
220 dotProduct(const W<T> & a, const W2<T2> & b)
221 {
222  return a.contract(b);
223 }
224 
238 template <typename C,
239  typename T,
241 R
242 poly(const C & c, const T x, const bool derivative = false)
243 {
244  const auto size = c.size();
245  if (size == 0)
246  return 0.0;
247 
248  R value = c[0];
249  if (derivative)
250  {
251  value *= size - 1;
252  for (std::size_t i = 1; i < size - 1; ++i)
253  value = value * x + c[i] * (size - i - 1);
254  }
255  else
256  {
257  for (std::size_t i = 1; i < size; ++i)
258  value = value * x + c[i];
259  }
260 
261  return value;
262 }
263 
273 template <typename C,
274  typename T,
276 R
277 polynomial(const C & c, const T x)
278 {
279  auto size = c.size();
280  if (size == 0)
281  return 0.0;
282 
283  size--;
284  R value = c[size];
285  for (std::size_t i = 1; i <= size; ++i)
286  value = value * x + c[size - i];
287 
288  return value;
289 }
290 
294 template <typename C,
295  typename T,
297 R
298 polynomialDerivative(const C & c, const T x)
299 {
300  auto size = c.size();
301  if (size <= 1)
302  return 0.0;
303 
304  size--;
305  R value = c[size] * size;
306  for (std::size_t i = 1; i < size; ++i)
307  value = value * x + c[size - i] * (size - i);
308 
309  return value;
310 }
311 
312 template <typename T, typename T2>
313 T
314 clamp(const T & x, T2 lowerlimit, T2 upperlimit)
315 {
316  if (x < lowerlimit)
317  return lowerlimit;
318  if (x > upperlimit)
319  return upperlimit;
320  return x;
321 }
322 
323 template <typename T, typename T2>
324 T
325 smootherStep(T x, T2 start, T2 end, bool derivative = false)
326 {
327  mooseAssert("start < end", "Start value must be lower than end value for smootherStep");
328  if (x <= start)
329  return 0.0;
330  else if (x >= end)
331  {
332  if (derivative)
333  return 0.0;
334  else
335  return 1.0;
336  }
337  x = (x - start) / (end - start);
338  if (derivative)
339  return 30.0 * libMesh::Utility::pow<2>(x) * (x * (x - 2.0) + 1.0) / (end - start);
340  return libMesh::Utility::pow<3>(x) * (x * (x * 6.0 - 15.0) + 10.0);
341 }
342 
343 enum class ComputeType
344 {
345  value,
346  derivative
347 };
348 
349 template <ComputeType compute_type, typename X, typename S, typename E>
350 auto
351 smootherStep(const X & x, const S & start, const E & end)
352 {
353  mooseAssert("start < end", "Start value must be lower than end value for smootherStep");
354  if (x <= start)
355  return 0.0;
356  else if (x >= end)
357  {
358  if constexpr (compute_type == ComputeType::derivative)
359  return 0.0;
360  if constexpr (compute_type == ComputeType::value)
361  return 1.0;
362  }
363  const auto u = (x - start) / (end - start);
364  if constexpr (compute_type == ComputeType::derivative)
365  return 30.0 * libMesh::Utility::pow<2>(u) * (u * (u - 2.0) + 1.0) / (end - start);
366  if constexpr (compute_type == ComputeType::value)
367  return libMesh::Utility::pow<3>(u) * (u * (u * 6.0 - 15.0) + 10.0);
368 }
369 
375 template <typename T>
376 inline void
378 {
384  v = 0;
385 }
386 template <typename T>
387 inline void
389 {
390  mooseError("mooseSetToZero does not accept pointers");
391 }
392 
393 template <>
394 inline void
395 mooseSetToZero(std::vector<Real> & vec)
396 {
397  for (auto & v : vec)
398  v = 0.;
399 }
400 
418 std::vector<std::vector<unsigned int>> multiIndex(unsigned int dim, unsigned int order);
419 
420 template <ComputeType compute_type, typename X, typename X1, typename X2, typename Y1, typename Y2>
421 auto
422 linearInterpolation(const X & x, const X1 & x1, const X2 & x2, const Y1 & y1, const Y2 & y2)
423 {
424  const auto m = (y2 - y1) / (x2 - x1);
425  if constexpr (compute_type == ComputeType::derivative)
426  return m;
427  if constexpr (compute_type == ComputeType::value)
428  return m * (x - x1) + y1;
429 }
430 
437 template <typename T1, typename T2>
438 std::size_t
439 euclideanMod(T1 dividend, T2 divisor)
440 {
441  return (dividend % divisor + divisor) % divisor;
442 }
443 
448 template <typename T>
449 T
450 gradName(const T & base_prop_name)
451 {
452  return "grad_" + base_prop_name;
453 }
454 
459 template <typename T>
460 T
461 timeDerivName(const T & base_prop_name)
462 {
463  return "d" + base_prop_name + "_dt";
464 }
465 
472 void kron(RealEigenMatrix & product, const RealEigenMatrix & mat_A, const RealEigenMatrix & mat_B);
473 
474 } // namespace MathUtils
475 
477 std::vector<std::vector<unsigned int>> multiIndexHelper(unsigned int N, unsigned int K);
void addScaled(const T &a, const T2 &b, T3 &result)
Definition: MathUtils.h:175
void mooseSetToZero(T &v)
Helper function templates to set a variable to zero.
Definition: MathUtils.h:377
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sin(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tan
R poly(const C &c, const T x, const bool derivative=false)
Evaluate a polynomial with the coefficients c at x.
Definition: MathUtils.h:242
Point circumcenter2D(const Point &p0, const Point &p1, const Point &p2)
Evaluate circumcenter of a triangle given three arbitrary points.
Definition: MathUtils.C:260
Point barycentricToCartesian2D(const Point &p0, const Point &p1, const Point &p2, const Real b0, const Real b1, const Real b2)
Evaluate Cartesian coordinates of any center point of a triangle given Barycentric coordinates of cen...
Definition: MathUtils.C:217
void kron(RealEigenMatrix &product, const RealEigenMatrix &mat_A, const RealEigenMatrix &mat_B)
Computes the Kronecker product of two matrices.
Definition: MathUtils.C:17
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:323
Real poly1Log(Real x, Real tol, unsigned int derivative_order)
Definition: MathUtils.C:49
Real poly2Log(Real x, Real tol, unsigned int derivative_order)
Definition: MathUtils.C:76
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:162
Point barycentricToCartesian3D(const Point &p0, const Point &p1, const Point &p2, const Point &p3, const Real b0, const Real b1, const Real b2, const Real b3)
Evaluate Cartesian coordinates of any center point of a tetrahedron given Barycentric coordinates of ...
Definition: MathUtils.C:237
T regularizedHeavysideDerivative(const T &x, Real smoothing_length)
Definition: MathUtils.h:142
std::size_t euclideanMod(T1 dividend, T2 divisor)
perform modulo operator for Euclidean division that ensures a non-negative result ...
Definition: MathUtils.h:439
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cos(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cos
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
T round(T x)
Definition: MathUtils.h:77
libMesh::CompareTypes< T, T2 >::supertype dotProduct(const W< T > &a, const W2< T2 > &b)
Definition: MathUtils.h:203
T sign(T x)
Definition: MathUtils.h:84
Real taylorLog(Real x)
Definition: MathUtils.C:172
R polynomial(const C &c, const T x)
Evaluate a polynomial with the coefficients c at x.
Definition: MathUtils.h:277
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic > RealEigenMatrix
Definition: MooseTypes.h:151
Real poly3Log(Real x, Real tol, unsigned int derivative_order)
Definition: MathUtils.C:104
T negativePart(T x)
Definition: MathUtils.h:162
T smootherStep(T x, T2 start, T2 end, bool derivative=false)
Definition: MathUtils.h:325
Point circumcenter3D(const Point &p0, const Point &p1, const Point &p2, const Point &p3)
Evaluate circumcenter of a tetrahedrom given four arbitrary points.
Definition: MathUtils.C:289
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
T gradName(const T &base_prop_name)
automatic prefixing for naming material properties based on gradients of coupled variables/functors ...
Definition: MathUtils.h:450
T timeDerivName(const T &base_prop_name)
automatic prefixing for naming material properties based on time derivatives of coupled variables/fun...
Definition: MathUtils.h:461
T positivePart(T x)
Definition: MathUtils.h:155
std::vector< std::vector< unsigned int > > multiIndex(unsigned int dim, unsigned int order)
generate a complete multi index table for given dimension and order i.e.
Definition: MathUtils.C:186
T heavyside(T x)
Definition: MathUtils.h:120
T regularizedHeavyside(const T &x, Real smoothing_length)
Definition: MathUtils.h:127
Real poly4Log(Real x, Real tol, unsigned int derivative_order)
Definition: MathUtils.C:133
T clamp(const T &x, T2 lowerlimit, T2 upperlimit)
Definition: MathUtils.h:314
T pow(T x, int e)
Definition: MathUtils.h:91
virtual void add(const numeric_index_type i, const T value)=0
std::vector< std::vector< unsigned int > > multiIndexHelper(unsigned int N, unsigned int K)
A helper function for MathUtils::multiIndex.
Definition: MathUtils.C:333
static constexpr Real sqrt2
std::sqrt is not constexpr, so we add sqrt(2) as a constant (used in Mandel notation) ...
Definition: MathUtils.h:25
auto linearInterpolation(const X &x, const X1 &x1, const X2 &x2, const Y1 &y1, const Y2 &y2)
Definition: MathUtils.h:422
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
R polynomialDerivative(const C &c, const T x)
Returns the derivative of polynomial(c, x) with respect to x.
Definition: MathUtils.h:298
const Real pi