20#include <dune/common/typetraits.hh> 
   21#include <dune/common/fvector.hh> 
   22#include <dune/common/fmatrix.hh> 
   23#include <dune/common/dynmatrix.hh> 
   24#include <dune/common/float_cmp.hh> 
   37template <
class Scalar>
 
   38constexpr Scalar 
arithmeticMean(Scalar x, Scalar y, Scalar wx = 1.0, Scalar wy = 1.0) noexcept
 
   40    static_assert(Dune::IsNumber<Scalar>::value, 
"The arguments x, y, wx, and wy have to be numbers!");
 
   44    return (x * wx + y * wy)/(wx + wy);
 
 
   56template <
class Scalar>
 
   57constexpr Scalar 
harmonicMean(Scalar x, Scalar y, Scalar wx = 1.0, Scalar wy = 1.0) noexcept
 
   59    static_assert(Dune::IsNumber<Scalar>::value, 
"The arguments x, y, wx, and wy have to be numbers!");
 
   63    return (wx + wy) * x * y / (wy * x + wx * y);
 
 
   74template <
class Scalar>
 
   77    static_assert(Dune::IsNumber<Scalar>::value, 
"The arguments x and y have to be numbers!");
 
   82    return sqrt(x*y)*
sign(x);
 
 
   96template <
class Scalar, 
int m, 
int n>
 
   98                        const Dune::FieldMatrix<Scalar, m, n> &Ki,
 
   99                        const Dune::FieldMatrix<Scalar, m, n> &Kj)
 
  101    for (
int rowIdx=0; rowIdx < m; rowIdx++){
 
  102        for (
int colIdx=0; colIdx< n; colIdx++){
 
  103            if (Dune::FloatCmp::ne<Scalar>(Ki[rowIdx][colIdx], Kj[rowIdx][colIdx])) {
 
  109                K[rowIdx][colIdx] = Ki[rowIdx][colIdx];
 
 
  123template<
class Scalar>
 
  124Scalar 
smoothMin(
const Scalar a, 
const Scalar b, 
const Scalar k)
 
  126    using std::max; 
using std::min; 
using std::abs;
 
  127    const auto h = max(k-abs(a-b), 0.0 )/k;
 
  128    return min(a, b) - h*h*h*k*(1.0/6.0);
 
 
  139template<
class Scalar>
 
  140Scalar 
smoothMax(
const Scalar a, 
const Scalar b, 
const Scalar k)
 
 
  157template <
class Scalar, 
class SolContainer>
 
  185template <
class Scalar, 
class SolContainer>
 
  196    Scalar Delta = b*b - 4*a*c;
 
  202    sol[0] = (- b + Delta)/(2*a);
 
  203    sol[1] = (- b - Delta)/(2*a);
 
  209        swap(sol[0], sol[1]);
 
 
  215template <
class Scalar, 
class SolContainer>
 
  216void invertCubicPolynomialPostProcess_(SolContainer &sol,
 
  218                                       Scalar a, Scalar b, Scalar c, Scalar d,
 
  219                                       std::size_t numIterations = 1)
 
  221    const auto eval = [&](
auto x){ 
return d + x*(c + x*(b + x*a)); };
 
  222    const auto evalDeriv = [&](
auto x){ 
return c + x*(2*b + x*3*a); };
 
  226    for (
int i = 0; i < numSol; ++i)
 
  229        Scalar fCurrent = eval(x);
 
  230        const Scalar fOld = fCurrent;
 
  231        for (
int j = 0; j < numIterations; ++j)
 
  233            const Scalar fPrime = evalDeriv(x);
 
  236            x -= fCurrent/fPrime;
 
  241        if (abs(fCurrent) < abs(fOld))
 
  268template <
class Scalar, 
class SolContainer>
 
  270                          Scalar a, Scalar b, Scalar c, Scalar d,
 
  271                          std::size_t numPostProcessIterations = 1)
 
  284    Scalar p = c - b*b/3;
 
  285    Scalar q = d + (2*b*b*b - 9*b*c)/27;
 
  289    if (p == 0.0 && q == 0.0) {
 
  291        sol[0] = sol[1] = sol[2] = 0.0 - b/3;
 
  294    else if (p == 0.0 && q != 0.0) {
 
  304    else if (p != 0.0 && q == 0.0) {
 
  315        sol[0] = -sqrt(-p) - b/3;
 
  317        sol[2] = sqrt(-p) - b/3;
 
  352    Scalar wDisc = q*q/4 + p*p*p/27;
 
  362        const Scalar 
u = [&]{
 
  363            return q > 0 ? cbrt(-0.5*q - sqrt(wDisc)) : cbrt(-0.5*q + sqrt(wDisc));
 
  367        sol[0] = 
u - p/(3*
u) - b/3;
 
  371        invertCubicPolynomialPostProcess_(sol, 1, a, b, c, d, numPostProcessIterations);
 
  375        Scalar uCubedRe = - q/2;
 
  377        Scalar uCubedIm = sqrt(-wDisc);
 
  380        Scalar uAbs  = cbrt(sqrt(uCubedRe*uCubedRe + uCubedIm*uCubedIm));
 
  382        Scalar phi = atan2(uCubedIm, uCubedRe)/3;
 
  423        for (
int i = 0; i < 3; ++i) {
 
  425            sol[i] = cos(phi)*(uAbs - p/(3*uAbs)) - b/3;
 
  431        invertCubicPolynomialPostProcess_(sol, 3, a, b, c, d, numPostProcessIterations);
 
 
  456template <
class Scalar, 
int dim>
 
  457bool isLarger(
const Dune::FieldVector<Scalar, dim> &pos,
 
  458              const Dune::FieldVector<Scalar, dim> &smallerVec)
 
  460    for (
int i=0; i < dim; i++)
 
  462        if (pos[i]<= smallerVec[i])
 
 
  482template <
class Scalar, 
int dim>
 
  483bool isSmaller(
const Dune::FieldVector<Scalar, dim> &pos,
 
  484               const Dune::FieldVector<Scalar, dim> &largerVec)
 
  486    for (
int i=0; i < dim; i++)
 
  488        if (pos[i]>= largerVec[i])
 
 
  512template <
class Scalar, 
int dim>
 
  513bool isBetween(
const Dune::FieldVector<Scalar, dim> &pos,
 
  514              const Dune::FieldVector<Scalar, dim> &smallerVec,
 
  515              const Dune::FieldVector<Scalar, dim> &largerVec)
 
 
  536{ 
return Policy::interpolate(ip, std::forward<Parameter>(params) ...); }
 
 
  542namespace InterpolationPolicy  {
 
  555    template<
class Scalar>
 
  556    static constexpr Scalar 
interpolate(Scalar ip, 
const std::array<Scalar, 2>& params)
 
  558        return params[0]*(1.0 - ip) + params[1]*ip;
 
 
 
  575    template<
class Scalar, 
class RandomAccessContainer0, 
class RandomAccessContainer1>
 
  576    static constexpr Scalar 
interpolate(Scalar ip, 
const RandomAccessContainer0& range, 
const RandomAccessContainer1& values)
 
  579        if (ip > range[range.size()-1]) 
return values[values.size()-1];
 
  580        if (ip < range[0]) 
return values[0];
 
  583        const auto lookUpIndex = std::distance(range.begin(), std::lower_bound(range.begin(), range.end(), ip));
 
  584        if (lookUpIndex == 0)
 
  587        const auto ipLinear = (ip - range[lookUpIndex-1])/(range[lookUpIndex] - range[lookUpIndex-1]);
 
 
  591    template<
class Scalar, 
class RandomAccessContainer>
 
  592    static constexpr Scalar 
interpolate(Scalar ip, 
const std::pair<RandomAccessContainer, RandomAccessContainer>& table)
 
  594        const auto& [range, values] = table;
 
 
 
  610template <
class Scalar>
 
  611std::vector<Scalar> 
linspace(
const Scalar begin, 
const Scalar end,
 
  613                             bool endPoint = 
true)
 
  616    samples = max(std::size_t{2}, samples); 
 
  617    const Scalar divisor = endPoint ? samples-1 : samples;
 
  618    const Scalar delta = (end-begin)/divisor;
 
  619    std::vector<Scalar> vec(samples);
 
  620    for (std::size_t i = 0; i < samples; ++i)
 
  621        vec[i] = begin + i*delta;
 
 
  638template <
class Scalar>
 
  644    const Scalar ln10 = 2.3025850929940459;
 
  646    return exp(ln10*(A - B/(C + temperature)));
 
 
  657template<
class ValueType>
 
  658constexpr int sign(
const ValueType& value) 
noexcept 
  660    return (ValueType(0) < value) - (value < ValueType(0));
 
 
  670template <
class Scalar>
 
  671Dune::FieldVector<Scalar, 3> 
crossProduct(
const Dune::FieldVector<Scalar, 3> &vec1,
 
  672                                          const Dune::FieldVector<Scalar, 3> &vec2)
 
  674    return {vec1[1]*vec2[2]-vec1[2]*vec2[1],
 
  675            vec1[2]*vec2[0]-vec1[0]*vec2[2],
 
  676            vec1[0]*vec2[1]-vec1[1]*vec2[0]};
 
 
  686template <
class Scalar>
 
  688                    const Dune::FieldVector<Scalar, 2> &vec2)
 
  689{   
return vec1[0]*vec2[1]-vec1[1]*vec2[0]; }
 
 
  699template <
class Scalar>
 
  701                     const Dune::FieldVector<Scalar, 3> &vec2,
 
  702                     const Dune::FieldVector<Scalar, 3> &vec3)
 
 
  711template <
class Scalar, 
int m, 
int n>
 
  712Dune::FieldMatrix<Scalar, n, m> 
getTransposed(
const Dune::FieldMatrix<Scalar, m, n>& M)
 
  714    Dune::FieldMatrix<Scalar, n, m> T;
 
  715    for (std::size_t i = 0; i < m; ++i)
 
  716        for (std::size_t j = 0; j < n; ++j)
 
 
  728template <
class Scalar>
 
  729Dune::DynamicMatrix<Scalar> 
getTransposed(
const Dune::DynamicMatrix<Scalar>& M)
 
  731    std::size_t rows_T = M.M();
 
  732    std::size_t cols_T = M.N();
 
  734    Dune::DynamicMatrix<Scalar> M_T(rows_T, cols_T, 0.0);
 
  736    for (std::size_t i = 0; i < rows_T; ++i)
 
  737        for (std::size_t j = 0; j < cols_T; ++j)
 
 
  750template <
class Scalar>
 
  752                                             const Dune::DynamicMatrix<Scalar> &M2)
 
  754    using size_type = 
typename Dune::DynamicMatrix<Scalar>::size_type;
 
  755    const size_type rows = M1.N();
 
  756    const size_type cols = M2.M();
 
  758    DUNE_ASSERT_BOUNDS(M1.M() == M2.N());
 
  760    Dune::DynamicMatrix<Scalar> result(rows, cols, 0.0);
 
  761    for (size_type i = 0; i < rows; i++)
 
  762        for (size_type j = 0; j < cols; j++)
 
  763            for (size_type k = 0; k < M1.M(); k++)
 
  764                result[i][j] += M1[i][k]*M2[k][j];
 
 
  776template <
class Scalar, 
int rows1, 
int cols1, 
int cols2>
 
  777Dune::FieldMatrix<Scalar, rows1, cols2> 
multiplyMatrices(
const Dune::FieldMatrix<Scalar, rows1, cols1> &M1,
 
  778                                                         const Dune::FieldMatrix<Scalar, cols1, cols2> &M2)
 
  780    using size_type = 
typename Dune::FieldMatrix<Scalar, rows1, cols2>::size_type;
 
  782    Dune::FieldMatrix<Scalar, rows1, cols2> result(0.0);
 
  783    for (size_type i = 0; i < rows1; i++)
 
  784        for (size_type j = 0; j < cols2; j++)
 
  785            for (size_type k = 0; k < cols1; k++)
 
  786                result[i][j] += M1[i][k]*M2[k][j];
 
 
  798template <
class MatrixType>
 
  799typename Dune::DenseMatrix<MatrixType>::field_type
 
  800trace(
const Dune::DenseMatrix<MatrixType>& M)
 
  802    const auto rows = M.N();
 
  803    DUNE_ASSERT_BOUNDS(rows == M.M()); 
 
  805    using MatType = Dune::DenseMatrix<MatrixType>;
 
  806    typename MatType::field_type 
trace = 0.0;
 
  808    for (
typename MatType::size_type i = 0; i < rows; ++i)
 
 
  827template <
class MAT, 
class V>
 
  828typename Dune::DenseVector<V>::derived_type
 
  829mv(
const Dune::DenseMatrix<MAT>& M,
 
  830   const Dune::DenseVector<V>& v)
 
  832    typename Dune::DenseVector<V>::derived_type res(v);
 
 
  854template <
class FieldScalar, 
class V>
 
  855typename std::enable_if_t<Dune::IsNumber<FieldScalar>::value,
 
  856                          typename Dune::DenseVector<V>::derived_type>
 
  857mv(
const FieldScalar m, 
const Dune::DenseVector<V>& v)
 
  859    typename Dune::DenseVector<V>::derived_type res(v);
 
 
  878template <
class V1, 
class MAT, 
class V2>
 
  879typename Dune::DenseMatrix<MAT>::value_type
 
  880vtmv(
const Dune::DenseVector<V1>& v1,
 
  881     const Dune::DenseMatrix<MAT>& M,
 
  882     const Dune::DenseVector<V2>& v2)
 
 
  906template <
class V1, 
class FieldScalar, 
class V2>
 
  907typename std::enable_if_t<Dune::IsNumber<FieldScalar>::value, FieldScalar>
 
  908vtmv(
const Dune::DenseVector<V1>& v1,
 
  910     const Dune::DenseVector<V2>& v2)
 
 
  926template <
class Scalar>
 
  928                                       const std::vector<Scalar>& y)
 
  930    if (x.size() != y.size())
 
  931        DUNE_THROW(Dune::InvalidStateException, 
"x and y array must have the same length.");
 
  933    const Scalar averageX = std::accumulate(x.begin(), x.end(), 0.0)/x.size();
 
  934    const Scalar averageY = std::accumulate(y.begin(), y.end(), 0.0)/y.size();
 
  937    const Scalar numerator = std::inner_product(
 
  938        x.begin(), x.end(), y.begin(), 0.0, std::plus<Scalar>(),
 
  939        [&](
auto xx, 
auto yy) { return (xx - averageX) * (yy - averageY); }
 
  941    const Scalar denominator = std::inner_product(
 
  942        x.begin(), x.end(), x.begin(), 0.0, std::plus<Scalar>(),
 
  943        [&](
auto xx, 
auto yy) { return (xx - averageX) * (yy - averageX); }
 
  947    const Scalar slope = numerator / denominator;
 
  948    const Scalar intercept = averageY - slope * averageX;
 
  950    return {intercept, slope};
 
 
constexpr Scalar harmonicMean(Scalar x, Scalar y, Scalar wx=1.0, Scalar wy=1.0) noexcept
Calculate the (weighted) harmonic mean of two scalar values.
Definition math.hh:57
int invertCubicPolynomial(SolContainer *sol, Scalar a, Scalar b, Scalar c, Scalar d, std::size_t numPostProcessIterations=1)
Invert a cubic polynomial analytically.
Definition math.hh:269
Dune::DenseMatrix< MAT >::value_type vtmv(const Dune::DenseVector< V1 > &v1, const Dune::DenseMatrix< MAT > &M, const Dune::DenseVector< V2 > &v2)
Evaluates the scalar product of a vector v2, projected by a matrix M, with a vector v1.
Definition math.hh:880
Dune::DynamicMatrix< Scalar > multiplyMatrices(const Dune::DynamicMatrix< Scalar > &M1, const Dune::DynamicMatrix< Scalar > &M2)
Multiply two dynamic matrices.
Definition math.hh:751
Scalar geometricMean(Scalar x, Scalar y) noexcept
Calculate the geometric mean of two scalar values.
Definition math.hh:75
int invertLinearPolynomial(SolContainer &sol, Scalar a, Scalar b)
Invert a linear polynomial analytically.
Definition math.hh:158
bool isBetween(const Dune::FieldVector< Scalar, dim > &pos, const Dune::FieldVector< Scalar, dim > &smallerVec, const Dune::FieldVector< Scalar, dim > &largerVec)
Comparison of three position vectors.
Definition math.hh:513
void harmonicMeanMatrix(Dune::FieldMatrix< Scalar, m, n > &K, const Dune::FieldMatrix< Scalar, m, n > &Ki, const Dune::FieldMatrix< Scalar, m, n > &Kj)
Calculate the harmonic mean of a fixed-size matrix.
Definition math.hh:97
Dune::FieldVector< Scalar, 3 > crossProduct(const Dune::FieldVector< Scalar, 3 > &vec1, const Dune::FieldVector< Scalar, 3 > &vec2)
Cross product of two vectors in three-dimensional Euclidean space.
Definition math.hh:671
Scalar smoothMax(const Scalar a, const Scalar b, const Scalar k)
A smoothed maximum function (using cubic interpolation)
Definition math.hh:140
Scalar smoothMin(const Scalar a, const Scalar b, const Scalar k)
A smoothed minimum function (using cubic interpolation)
Definition math.hh:124
Scalar interpolate(Scalar ip, Parameter &&... params)
a generic function to interpolate given a set of parameters and an interpolation point
Definition math.hh:535
bool isSmaller(const Dune::FieldVector< Scalar, dim > &pos, const Dune::FieldVector< Scalar, dim > &largerVec)
Comparison of two position vectors.
Definition math.hh:483
Dune::DenseVector< V >::derived_type mv(const Dune::DenseMatrix< MAT > &M, const Dune::DenseVector< V > &v)
Returns the result of the projection of a vector v with a Matrix M.
Definition math.hh:829
Dune::DenseMatrix< MatrixType >::field_type trace(const Dune::DenseMatrix< MatrixType > &M)
Trace of a dense matrix.
Definition math.hh:800
Dune::FieldMatrix< Scalar, n, m > getTransposed(const Dune::FieldMatrix< Scalar, m, n > &M)
Transpose a FieldMatrix.
Definition math.hh:712
bool isLarger(const Dune::FieldVector< Scalar, dim > &pos, const Dune::FieldVector< Scalar, dim > &smallerVec)
Comparison of two position vectors.
Definition math.hh:457
int invertQuadraticPolynomial(SolContainer &sol, Scalar a, Scalar b, Scalar c)
Invert a quadratic polynomial analytically.
Definition math.hh:186
std::array< Scalar, 2 > linearRegression(const std::vector< Scalar > &x, const std::vector< Scalar > &y)
Returns the [intercept, slope] of the regression line fitted to a set of (x, y) data points.
Definition math.hh:927
std::vector< Scalar > linspace(const Scalar begin, const Scalar end, std::size_t samples, bool endPoint=true)
Generates linearly spaced vectors.
Definition math.hh:611
Scalar tripleProduct(const Dune::FieldVector< Scalar, 3 > &vec1, const Dune::FieldVector< Scalar, 3 > &vec2, const Dune::FieldVector< Scalar, 3 > &vec3)
Triple product of three vectors in three-dimensional Euclidean space retuning scalar.
Definition math.hh:700
constexpr int sign(const ValueType &value) noexcept
Sign or signum function.
Definition math.hh:658
Scalar antoine(Scalar temperature, Scalar A, Scalar B, Scalar C)
Evaluates the Antoine equation used to calculate the vapour pressure of various liquids.
Definition math.hh:639
constexpr Scalar arithmeticMean(Scalar x, Scalar y, Scalar wx=1.0, Scalar wy=1.0) noexcept
Calculate the (weighted) arithmetic mean of two scalar values.
Definition math.hh:38
forward declaration of the linear interpolation policy (default)
Definition math.hh:526
const Scalar PengRobinsonMixture< Scalar, StaticParameters >::u
Definition pengrobinsonmixture.hh:138
interpolate linearly between two given values
Definition math.hh:549
static constexpr Scalar interpolate(Scalar ip, const std::array< Scalar, 2 > ¶ms)
interpolate linearly between two given values
Definition math.hh:556
interpolate linearly in a piecewise linear function (tabularized function)
Definition math.hh:567
static constexpr Scalar interpolate(Scalar ip, const std::pair< RandomAccessContainer, RandomAccessContainer > &table)
Definition math.hh:592
static constexpr Scalar interpolate(Scalar ip, const RandomAccessContainer0 &range, const RandomAccessContainer1 &values)
interpolate linearly in a piecewise linear function (tabularized function)
Definition math.hh:576