https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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 "MooseUtils.h"
16#include "libmesh/libmesh.h"
17#include "libmesh/utility.h"
18#include "libmesh/numeric_vector.h"
19#include "libmesh/compare_types.h"
20#include "libmesh/point.h"
21
22namespace MathUtils
23{
24
26static constexpr Real sqrt2 = 1.4142135623730951;
27
28Real poly1Log(Real x, Real tol, unsigned int derivative_order);
29Real poly2Log(Real x, Real tol, unsigned int derivative_order);
30Real poly3Log(Real x, Real tol, unsigned int derivative_order);
31Real poly4Log(Real x, Real tol, unsigned int derivative_order);
32Real taylorLog(Real x);
41Point barycentricToCartesian2D(const Point & p0,
42 const Point & p1,
43 const Point & p2,
44 const Real b0,
45 const Real b1,
46 const Real b2);
55Point barycentricToCartesian3D(const Point & p0,
56 const Point & p1,
57 const Point & p2,
58 const Point & p3,
59 const Real b0,
60 const Real b1,
61 const Real b2,
62 const Real b3);
68Point circumcenter2D(const Point & p0, const Point & p1, const Point & p2);
74Point circumcenter3D(const Point & p0, const Point & p1, const Point & p2, const Point & p3);
75
76template <typename T>
77T
79{
80 return ::round(x); // use round from math.h
81}
82
83template <typename T>
84T
85sign(T x)
86{
87 return x >= 0.0 ? 1.0 : -1.0;
88}
89
90template <typename T>
91T
92pow(T x, int e)
93{
94 bool neg = false;
95 T result = 1.0;
96
97 if (e < 0)
98 {
99 neg = true;
100 e = -e;
101 }
102
103 while (e)
104 {
105 // if bit 0 is set multiply the current power of two factor of the exponent
106 if (e & 1)
107 result *= x;
108
109 // x is incrementally set to consecutive powers of powers of two
110 x *= x;
111
112 // bit shift the exponent down
113 e >>= 1;
114 }
115
116 return neg ? 1.0 / result : result;
117}
118
119template <typename T>
120T
122{
123 return x < 0.0 ? 0.0 : 1.0;
124}
125
126template <typename T>
127T
128regularizedHeavyside(const T & x, Real smoothing_length)
129{
130 if (x <= -smoothing_length)
131 return 0.0;
132 else if (x < smoothing_length)
133 {
134 using std::sin;
135 return 0.5 * (1 + sin(libMesh::pi * x / 2 / smoothing_length));
136 }
137 else
138 return 1.0;
139}
140
141template <typename T>
142T
143regularizedHeavysideDerivative(const T & x, Real smoothing_length)
144{
145 if (x < smoothing_length && x > -smoothing_length)
146 {
147 using std::cos;
148 return 0.25 * libMesh::pi / smoothing_length * (cos(libMesh::pi * x / 2 / smoothing_length));
149 }
150 else
151 return 0.0;
152}
153
154template <typename T>
155T
157{
158 return x > 0.0 ? x : 0.0;
159}
160
161template <typename T>
162T
164{
165 return x < 0.0 ? x : 0.0;
166}
167
168template <
169 typename T,
170 typename T2,
171 typename T3,
172 typename std::enable_if<libMesh::ScalarTraits<T>::value && libMesh::ScalarTraits<T2>::value &&
174 int>::type = 0>
175void
176addScaled(const T & a, const T2 & b, T3 & result)
177{
178 result += a * b;
179}
180
181template <typename T,
182 typename T2,
183 typename T3,
184 typename std::enable_if<libMesh::ScalarTraits<T>::value, int>::type = 0>
185void
186addScaled(const T & scalar,
187 const libMesh::NumericVector<T2> & numeric_vector,
189{
190 result.add(scalar, numeric_vector);
191}
192
193template <
194 typename T,
195 typename T2,
196 template <typename> class W,
197 template <typename> class W2,
198 typename std::enable_if<std::is_same<typename W<T>::index_type, unsigned int>::value &&
199 std::is_same<typename W2<T2>::index_type, unsigned int>::value,
200 int>::type = 0>
202dotProduct(const W<T> & a, const W2<T2> & b)
203{
204 return a * b;
205}
206
207template <typename T,
208 typename T2,
209 template <typename> class W,
210 template <typename> class W2,
211 typename std::enable_if<std::is_same<typename W<T>::index_type,
212 std::tuple<unsigned int, unsigned int>>::value &&
213 std::is_same<typename W2<T2>::index_type,
214 std::tuple<unsigned int, unsigned int>>::value,
215 int>::type = 0>
217dotProduct(const W<T> & a, const W2<T2> & b)
218{
219 return a.contract(b);
220}
221
230template <typename T>
231auto
233{
234 if constexpr (MooseUtils::Has_size<T>::value)
235 {
236 decltype(normSquared(*value.begin())) sum{};
237 for (const auto & component : value)
238 sum += normSquared(component);
239 return sum;
240 }
241 else if constexpr (libMesh::TensorTools::TensorTraits<T>::rank == 0)
242 return value * value;
243 else if constexpr (libMesh::TensorTools::TensorTraits<T>::rank == 1)
244 {
245 auto sum = value(0) * value(0);
246 for (const auto i : make_range(std::size_t(1), Moose::dim))
247 sum += value(i) * value(i);
248 return sum;
249 }
250 else
251 {
252 auto sum = value(0, 0) * value(0, 0);
253 for (const auto j : make_range(std::size_t(1), Moose::dim))
254 sum += value(0, j) * value(0, j);
255 for (const auto i : make_range(std::size_t(1), Moose::dim))
256 for (const auto j : make_range(Moose::dim))
257 sum += value(i, j) * value(i, j);
258 return sum;
259 }
260}
261
271template <typename T>
272auto
273norm(const T & value)
274{
275 using std::sqrt;
276 if (MooseUtils::isZero(value))
277 return decltype(normSquared(value)){};
278 return sqrt(normSquared(value));
279}
280
294template <typename C,
295 typename T,
297R
298poly(const C & c, const T x, const bool derivative = false)
299{
300 const auto size = c.size();
301 if (size == 0)
302 return 0.0;
303
304 R value = c[0];
305 if (derivative)
306 {
307 value *= size - 1;
308 for (std::size_t i = 1; i < size - 1; ++i)
309 value = value * x + c[i] * (size - i - 1);
310 }
311 else
312 {
313 for (std::size_t i = 1; i < size; ++i)
314 value = value * x + c[i];
315 }
316
317 return value;
318}
319
329template <typename C,
330 typename T,
332R
333polynomial(const C & c, const T x)
334{
335 auto size = c.size();
336 if (size == 0)
337 return 0.0;
338
339 size--;
340 R value = c[size];
341 for (std::size_t i = 1; i <= size; ++i)
342 value = value * x + c[size - i];
343
344 return value;
345}
346
350template <typename C,
351 typename T,
353R
354polynomialDerivative(const C & c, const T x)
355{
356 auto size = c.size();
357 if (size <= 1)
358 return 0.0;
359
360 size--;
361 R value = c[size] * size;
362 for (std::size_t i = 1; i < size; ++i)
363 value = value * x + c[size - i] * (size - i);
364
365 return value;
366}
367
368template <typename T, typename T2>
369T
370clamp(const T & x, T2 lowerlimit, T2 upperlimit)
371{
372 if (x < lowerlimit)
373 return lowerlimit;
374 if (x > upperlimit)
375 return upperlimit;
376 return x;
377}
378
379template <typename T, typename T2>
380T
381smootherStep(T x, T2 start, T2 end, bool derivative = false)
382{
383 mooseAssert("start < end", "Start value must be lower than end value for smootherStep");
384 if (x <= start)
385 return 0.0;
386 else if (x >= end)
387 {
388 if (derivative)
389 return 0.0;
390 else
391 return 1.0;
392 }
393 x = (x - start) / (end - start);
394 if (derivative)
395 return 30.0 * libMesh::Utility::pow<2>(x) * (x * (x - 2.0) + 1.0) / (end - start);
396 return libMesh::Utility::pow<3>(x) * (x * (x * 6.0 - 15.0) + 10.0);
397}
398
399enum class ComputeType
400{
401 value,
403};
404
405template <ComputeType compute_type, typename X, typename S, typename E>
406auto
407smootherStep(const X & x, const S & start, const E & end)
408{
409 mooseAssert("start < end", "Start value must be lower than end value for smootherStep");
410 if (x <= start)
411 return 0.0;
412 else if (x >= end)
413 {
414 if constexpr (compute_type == ComputeType::derivative)
415 return 0.0;
416 if constexpr (compute_type == ComputeType::value)
417 return 1.0;
418 }
419 const auto u = (x - start) / (end - start);
420 if constexpr (compute_type == ComputeType::derivative)
421 return 30.0 * libMesh::Utility::pow<2>(u) * (u * (u - 2.0) + 1.0) / (end - start);
422 if constexpr (compute_type == ComputeType::value)
423 return libMesh::Utility::pow<3>(u) * (u * (u * 6.0 - 15.0) + 10.0);
424}
425
431template <typename T>
432inline void
434{
440 v = 0;
441}
442template <typename T>
443inline void
445{
446 mooseError("mooseSetToZero does not accept pointers");
447}
448
449template <>
450inline void
451mooseSetToZero(std::vector<Real> & vec)
452{
453 for (auto & v : vec)
454 v = 0.;
455}
456
474std::vector<std::vector<unsigned int>> multiIndex(unsigned int dim, unsigned int order);
475
476template <ComputeType compute_type, typename X, typename X1, typename X2, typename Y1, typename Y2>
477auto
478linearInterpolation(const X & x, const X1 & x1, const X2 & x2, const Y1 & y1, const Y2 & y2)
479{
480 const auto m = (y2 - y1) / (x2 - x1);
481 if constexpr (compute_type == ComputeType::derivative)
482 return m;
483 if constexpr (compute_type == ComputeType::value)
484 return m * (x - x1) + y1;
485}
486
493template <typename T1, typename T2>
494std::size_t
495euclideanMod(T1 dividend, T2 divisor)
496{
497 return (dividend % divisor + divisor) % divisor;
498}
499
504template <typename T>
505T
506gradName(const T & base_prop_name)
507{
508 return "grad_" + base_prop_name;
509}
510
515template <typename T>
516T
517timeDerivName(const T & base_prop_name)
518{
519 return "d" + base_prop_name + "_dt";
520}
521
528void kron(RealEigenMatrix & product, const RealEigenMatrix & mat_A, const RealEigenMatrix & mat_B);
529
530} // namespace MathUtils
531
533std::vector<std::vector<unsigned int>> multiIndexHelper(unsigned int N, unsigned int K);
std::vector< std::vector< unsigned int > > multiIndexHelper(unsigned int N, unsigned int K)
A helper function for MathUtils::multiIndex.
Definition MathUtils.C:333
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
virtual void add(const numeric_index_type i, const T value)=0
void mooseSetToZero(T &v)
Helper function templates to set a variable to zero.
Definition MathUtils.h:433
Real poly1Log(Real x, Real tol, unsigned int derivative_order)
Definition MathUtils.C:49
void kron(RealEigenMatrix &product, const RealEigenMatrix &mat_A, const RealEigenMatrix &mat_B)
Computes the Kronecker product of two matrices.
Definition MathUtils.C:17
T pow(T x, int e)
Definition MathUtils.h:92
T regularizedHeavyside(const T &x, Real smoothing_length)
Definition MathUtils.h:128
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
auto normSquared(const T &value)
Return the square of the Euclidean (L2) norm of value.
Definition MathUtils.h:232
Real taylorLog(Real x)
Definition MathUtils.C:172
T positivePart(T x)
Definition MathUtils.h:156
T negativePart(T x)
Definition MathUtils.h:163
auto linearInterpolation(const X &x, const X1 &x1, const X2 &x2, const Y1 &y1, const Y2 &y2)
Definition MathUtils.h:478
T sign(T x)
Definition MathUtils.h:85
T gradName(const T &base_prop_name)
automatic prefixing for naming material properties based on gradients of coupled variables/functors
Definition MathUtils.h:506
void addScaled(const T &a, const T2 &b, T3 &result)
Definition MathUtils.h:176
T clamp(const T &x, T2 lowerlimit, T2 upperlimit)
Definition MathUtils.h:370
T timeDerivName(const T &base_prop_name)
automatic prefixing for naming material properties based on time derivatives of coupled variables/fun...
Definition MathUtils.h:517
T smootherStep(T x, T2 start, T2 end, bool derivative=false)
Definition MathUtils.h:381
Real poly2Log(Real x, Real tol, unsigned int derivative_order)
Definition MathUtils.C:76
R polynomial(const C &c, const T x)
Evaluate a polynomial with the coefficients c at x.
Definition MathUtils.h:333
Real poly4Log(Real x, Real tol, unsigned int derivative_order)
Definition MathUtils.C:133
auto norm(const T &value)
Return the Euclidean (L2) norm of value.
Definition MathUtils.h:273
R poly(const C &c, const T x, const bool derivative=false)
Evaluate a polynomial with the coefficients c at x.
Definition MathUtils.h:298
Point circumcenter2D(const Point &p0, const Point &p1, const Point &p2)
Evaluate circumcenter of a triangle given three arbitrary points.
Definition MathUtils.C:260
libMesh::CompareTypes< T, T2 >::supertype dotProduct(const W< T > &a, const W2< T2 > &b)
Definition MathUtils.h:202
Real poly3Log(Real x, Real tol, unsigned int derivative_order)
Definition MathUtils.C:104
T regularizedHeavysideDerivative(const T &x, Real smoothing_length)
Definition MathUtils.h:143
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
std::size_t euclideanMod(T1 dividend, T2 divisor)
perform modulo operator for Euclidean division that ensures a non-negative result
Definition MathUtils.h:495
static constexpr Real sqrt2
std::sqrt is not constexpr, so we add sqrt(2) as a constant (used in Mandel notation)
Definition MathUtils.h:26
R polynomialDerivative(const C &c, const T x)
Returns the derivative of polynomial(c, x) with respect to x.
Definition MathUtils.h:354
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
T round(T x)
Definition MathUtils.h:78
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
T heavyside(T x)
Definition MathUtils.h:121
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition Moose.h:175
const Real pi