diff --git a/dune/tectonic/globallaursennonlinearity.hh b/dune/tectonic/globallaursennonlinearity.hh index c4701b9f00cd172e6237498f56aee406c3e232d3..0b69101c1dd557064d93e4859b279e1ac889a8ad 100644 --- a/dune/tectonic/globallaursennonlinearity.hh +++ b/dune/tectonic/globallaursennonlinearity.hh @@ -13,8 +13,11 @@ #include "nicefunction.hh" namespace Dune { -template <int dim, class OuterFunctionType> -class GlobalLaursenNonlinearity : public GlobalNonlinearity<dim> { +template <int dim, class OuterFunctionType, + class VectorType = BlockVector<FieldVector<double, dim>>, + class MatrixType = BCRSMatrix<FieldMatrix<double, dim, dim>>> +class GlobalLaursenNonlinearity + : public GlobalNonlinearity<dim, VectorType, MatrixType> { public: GlobalLaursenNonlinearity( shared_ptr<BlockVector<FieldVector<double, 1>> const> mu, diff --git a/dune/tectonic/globalnonlinearity.hh b/dune/tectonic/globalnonlinearity.hh index 3a1bc3739fb37cf286c9c475948d411cae08427f..73042d741c95c8ac8f30c4bca6e31d977f28ea50 100644 --- a/dune/tectonic/globalnonlinearity.hh +++ b/dune/tectonic/globalnonlinearity.hh @@ -10,12 +10,22 @@ #include "localnonlinearity.hh" namespace Dune { -template <int dim> class GlobalNonlinearity { +template <int dim, class VectorType = BlockVector<FieldVector<double, dim>>, + class MatrixType = BCRSMatrix<FieldMatrix<double, dim, dim>>> +class GlobalNonlinearity { public: /* Return a restriction of the outer function to the i'th node. */ virtual shared_ptr<LocalNonlinearity<dim> const> restriction(int i) const = 0; + + virtual void addHessian(const VectorType& v, MatrixType& hessian) const { + // TODO: is this correct? + for (size_t i = 0; i < v.size(); ++i) { + auto res = restriction(i); + res->addHessian(v[i], hessian[i][i]); + } + } }; } #endif diff --git a/dune/tectonic/globalruinanonlinearity.hh b/dune/tectonic/globalruinanonlinearity.hh index 90e8af367feb0bc683eaaf22050a66a35ee20d32..2ff49ef05284dd1d2efbc98571aafdbe5c0e1471 100644 --- a/dune/tectonic/globalruinanonlinearity.hh +++ b/dune/tectonic/globalruinanonlinearity.hh @@ -13,8 +13,10 @@ #include "nicefunction.hh" namespace Dune { -template <int dim> -class GlobalRuinaNonlinearity : public GlobalNonlinearity<dim> { +template <int dim, class VectorType = BlockVector<FieldVector<double, dim>>, + class MatrixType = BCRSMatrix<FieldMatrix<double, dim, dim>>> +class GlobalRuinaNonlinearity + : public GlobalNonlinearity<dim, VectorType, MatrixType> { public: GlobalRuinaNonlinearity( shared_ptr<BlockVector<FieldVector<double, 1>> const> nodalIntegrals, diff --git a/dune/tectonic/localnonlinearity.hh b/dune/tectonic/localnonlinearity.hh index 34e595f0a49970a98cc5f68650b75468afb8df76..3dc5e53b149d2483c169e1fc9cea27ea04f5de90 100644 --- a/dune/tectonic/localnonlinearity.hh +++ b/dune/tectonic/localnonlinearity.hh @@ -1,6 +1,7 @@ #ifndef DUNE_TECTONIC_LOCAL_NONLINEARITY_HH #define DUNE_TECTONIC_LOCAL_NONLINEARITY_HH +#include <cmath> #include <limits> #include <dune/common/fvector.hh> @@ -45,6 +46,38 @@ template <int dimension> class LocalNonlinearity { } } + /* + H''(|x|) x \otimes x / |x|^2 + + H'(|x|) [|x|^2 id - x \otimes x] / |x|^3 + + For i == j, this is (writing k and using the notation from below) + + h2 * x[k] * x[k] / normX2 + h1 [normX2 - x[k]^2]/normX^3 + = h2 * x[k] * x[k] / normX2 + h1ox - h1 x[k]^2/normX^3 + = (h2-h1ox) * x[k] * x[k] / normX2 + h1ox + + For i != j, this is (again, using the notation from below) + + h2 * x[i] * x[j] / normX2 - h1 * x[i] * x[j]/normX^3 + = (h2 - h1ox) * x[i] * x[j] / normX2 + */ + void addHessian(VectorType const &x, MatrixType &A) const { + double const normX2 = x.two_norm2(); + double const normX = sqrt(normX2); + double const h1ox = func_->rightDifferential(normX) / normX; + double const h2 = func_->second_deriv(normX); + + for (int i = 0; i < dimension; ++i) + for (int j = 0; j < i; ++j) { + double const entry = (h2 - h1ox) * x[i] * x[j] / normX2; + A[i][j] += entry; + A[j][i] += entry; + } + + for (int k = 0; k < dimension; ++k) + A[k][k] += (h2 - h1ox) * x[k] * x[k] / normX2 + h1ox; + } + void upperGradient(VectorType const &x, VectorType &ret) const { ret = x; ret *= func_->rightDifferential(x.two_norm()) / x.two_norm(); diff --git a/dune/tectonic/nicefunction.hh b/dune/tectonic/nicefunction.hh index 4b926f9c6d116ae259fca2dccf8973120f88dd5e..ed6dc388752cbb74aa59e8916d29dc3867b9a00a 100644 --- a/dune/tectonic/nicefunction.hh +++ b/dune/tectonic/nicefunction.hh @@ -14,6 +14,8 @@ class NiceFunction : public VirtualFunction<double, double> { virtual double leftDifferential(double s) const = 0; virtual double rightDifferential(double s) const = 0; + + double virtual second_deriv(double s) const = 0; }; class RuinaFunction : public NiceFunction { @@ -110,6 +112,8 @@ class LinearFunction : public NiceFunction { double virtual rightDifferential(double s) const { return coefficient; } + double virtual second_deriv(double) const { return 0; } + private: double coefficient; }; @@ -145,6 +149,8 @@ class TrivialFunction : public NiceFunction { double virtual leftDifferential(double) const { return 0; } double virtual rightDifferential(double) const { return 0; } + + double virtual second_deriv(double) const { return 0; } }; // slope in [n-1,n] is n