#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 coefficient, double _normalStress, FrictionData _fd) : fd(_fd), weight(coefficient), normalStress(_normalStress) {} double coefficientOfFriction(double V) const { if (V <= Vmin) return 0.0; return fd.a * std::log(V / Vmin); } double differential(double V) const { return weight * (fd.C - normalStress * coefficientOfFriction(V)); } double second_deriv(double V) const { if (V <= Vmin) return 0; return weight * (-normalStress) * (fd.a / V); } double regularity(double V) const { if (std::abs(V - Vmin) < 1e-14) // TODO return std::numeric_limits<double>::infinity(); return std::abs(second_deriv(V)); } void updateAlpha(double alpha) { 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 normalStress; double Vmin; }; class RegularisedRateState : public FrictionPotential { public: RegularisedRateState(double coefficient, double _normalStress, FrictionData _fd) : fd(_fd), weight(coefficient), normalStress(_normalStress) {} double coefficientOfFriction(double V) const { return fd.a * std::asinh(0.5 * V / Vmin); } double differential(double V) const { return weight * (fd.C - normalStress * coefficientOfFriction(V)); } double second_deriv(double V) const { return weight * (-normalStress) * fd.a / std::hypot(2.0 * Vmin, V); } double regularity(double V) const { return std::abs(second_deriv(V)); } void updateAlpha(double alpha) { 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 normalStress; double Vmin; }; class TrivialFunction : public FrictionPotential { public: double evaluate(double) const { return 0; } double coefficientOfFriction(double s) const { return 0; } double differential(double) const { return 0; } double second_deriv(double) const { return 0; } double regularity(double) const { return 0; } void updateAlpha(double) {} }; #endif