#ifndef DUNE_TECTONIC_FRICTIONPOTENTIAL_HH #define DUNE_TECTONIC_FRICTIONPOTENTIAL_HH #include <algorithm> #include <cassert> #include <cmath> #include <limits> #include <dune/common/exceptions.hh> #include <dune/common/function.hh> #include <dune/tectonic/frictiondata.hh> class FrictionPotential { public: virtual ~FrictionPotential() {} double virtual differential(double s) const = 0; double virtual second_deriv(double x) const = 0; double virtual regularity(double s) const = 0; double virtual coefficientOfFriction(double s) const = 0; double virtual evaluate(double x) const { DUNE_THROW(Dune::NotImplemented, "evaluation not implemented"); } void virtual updateAlpha(double) = 0; }; class TruncatedRateState : public FrictionPotential { public: TruncatedRateState(double _weight, double _weightedNormalStress, FrictionData _fd) : fd(_fd), weight(_weight), weightedNormalStress(_weightedNormalStress) {} double coefficientOfFriction(double V) const override { if (V <= Vmin) return 0.0; return fd.a * std::log(V / Vmin); } double differential(double V) const override { return weight * fd.C - weightedNormalStress * coefficientOfFriction(V); } double second_deriv(double V) const override { if (V <= Vmin) return 0; return -weightedNormalStress * (fd.a / V); } double regularity(double V) const override { if (std::abs(V - Vmin) < 1e-14) // TODO return std::numeric_limits<double>::infinity(); return std::abs(second_deriv(V)); } void updateAlpha(double alpha) override { double const logrest = (fd.mu0 + fd.b * alpha) / fd.a; Vmin = fd.V0 / std::exp(logrest); } private: FrictionData const fd; double const weight; double const weightedNormalStress; double Vmin; }; class RegularisedRateState : public FrictionPotential { public: RegularisedRateState(double _weight, double _weightedNormalStress, FrictionData _fd) : fd(_fd), weight(_weight), weightedNormalStress(_weightedNormalStress) {} double coefficientOfFriction(double V) const override { return fd.a * std::asinh(0.5 * V / Vmin); } double differential(double V) const override { return weight * fd.C - weightedNormalStress * coefficientOfFriction(V); } double second_deriv(double V) const override { return -weightedNormalStress * fd.a / std::hypot(2.0 * Vmin, V); } double regularity(double V) const override { return std::abs(second_deriv(V)); } void updateAlpha(double alpha) override { double const logrest = (fd.mu0 + fd.b * alpha) / fd.a; Vmin = fd.V0 / std::exp(logrest); } private: FrictionData const fd; double const weight; double const weightedNormalStress; double Vmin; }; class ZeroFunction : public FrictionPotential { public: template <typename... Args> ZeroFunction(Args... args) {} double evaluate(double) const override { return 0; } double coefficientOfFriction(double s) const override { return 0; } double differential(double) const override { return 0; } double second_deriv(double) const override { return 0; } double regularity(double) const override { return 0; } void updateAlpha(double) override {} }; #endif