From 27efa025f784c88363680ab08531b264f430b01b Mon Sep 17 00:00:00 2001
From: Elias Pipping <elias.pipping@fu-berlin.de>
Date: Sun, 13 Nov 2011 23:00:55 +0100
Subject: [PATCH] Add Ruina's approach

---
 dune/tectonic/globalruinanonlinearity.hh | 44 ++++++++++++++++++
 dune/tectonic/nicefunction.hh            | 58 ++++++++++++++++++++++++
 src/one-body-sample.cc                   | 22 +++++++--
 src/one-body-sample.parset               |  2 +
 4 files changed, 122 insertions(+), 4 deletions(-)
 create mode 100644 dune/tectonic/globalruinanonlinearity.hh

diff --git a/dune/tectonic/globalruinanonlinearity.hh b/dune/tectonic/globalruinanonlinearity.hh
new file mode 100644
index 00000000..aed66653
--- /dev/null
+++ b/dune/tectonic/globalruinanonlinearity.hh
@@ -0,0 +1,44 @@
+/* -*- mode:c++; mode:semantic -*- */
+
+#ifndef DUNE_TECTONIC_GLOBAL_RUINA_NONLINEARITY_HH
+#define DUNE_TECTONIC_GLOBAL_RUINA_NONLINEARITY_HH
+
+#include <dune/common/fvector.hh>
+
+#include "localnonlinearity.hh"
+#include "globalnonlinearity.hh"
+
+namespace Dune {
+template <int dim>
+class GlobalRuinaNonlinearity
+    : public Dune::GlobalNonlinearity<dim, Dune::RuinaFunction> {
+public:
+  GlobalRuinaNonlinearity(
+      std::vector<Dune::FieldVector<double, 1>> const &nodalIntegrals,
+      std::vector<double> const &a,
+      std::vector<double> const &coefficientOfFriction,
+      std::vector<double> const &eta, std::vector<double> const &normalStress)
+      : nodalIntegrals(nodalIntegrals),
+        a(a),
+        coefficientOfFriction(coefficientOfFriction),
+        eta(eta),
+        normalStress(normalStress) {}
+
+  /*
+    Return a restriction of the outer function to the i'th node.
+  */
+  RuinaFunction virtual restriction(int i) const {
+    return Dune::RuinaFunction(nodalIntegrals[i][0], a[i],
+                               coefficientOfFriction[i], eta[i],
+                               normalStress[i]);
+  }
+
+private:
+  std::vector<Dune::FieldVector<double, 1>> nodalIntegrals;
+  std::vector<double> a;
+  std::vector<double> coefficientOfFriction;
+  std::vector<double> eta;
+  std::vector<double> normalStress;
+};
+}
+#endif
diff --git a/dune/tectonic/nicefunction.hh b/dune/tectonic/nicefunction.hh
index a3614c03..cc582278 100644
--- a/dune/tectonic/nicefunction.hh
+++ b/dune/tectonic/nicefunction.hh
@@ -16,6 +16,64 @@ class NiceFunction : public VirtualFunction<double, double> {
   virtual double rightDifferential(double s) const = 0;
 };
 
+class RuinaFunction : public NiceFunction {
+public:
+  RuinaFunction() {}
+
+  RuinaFunction(double coefficient, double a, double mu, double eta,
+                double normalStress)
+      : coefficient(coefficient),
+        a(a),
+        mu(mu),
+        rho(exp(-mu / a)),
+        eta(eta),
+        normalStress(normalStress) {}
+
+  /*
+    If mu and sigma_n denote the coefficient of friction and the
+    normal stress, respectively, this function is given by
+
+    1/eta sigma_n h(max(eta id, rho)) + a rho + mu
+
+    with the constants a and b from Ruina's model and
+
+    h(beta) = beta (a (log beta - 1) + mu)
+
+    as well as
+
+    rho = exp(-mu/a)
+  */
+  void virtual evaluate(double const &x, double &y) const {
+    double const arg = std::max(eta * x, rho);
+    double const h = arg * (a * (std::log(arg) - 1) + mu);
+    y = 1 / eta * normalStress * h + a * rho + mu;
+    y *= coefficient;
+  }
+
+  double virtual leftDifferential(double s) const {
+    if (eta * s <= rho)
+      return 0;
+
+    return normalStress * (a * std::log(s) + mu);
+  }
+
+  double virtual rightDifferential(double s) const {
+    if (eta * s <= rho)
+      return 0;
+
+    return normalStress * (a * std::log(s) + mu);
+  }
+
+private:
+  double coefficient;
+  double a;
+  double mu;
+  double eta;
+  double normalStress;
+
+  double rho;
+};
+
 class LinearFunction : public NiceFunction {
 public:
   LinearFunction() {}
diff --git a/src/one-body-sample.cc b/src/one-body-sample.cc
index 3b0b6146..720f80be 100644
--- a/src/one-body-sample.cc
+++ b/src/one-body-sample.cc
@@ -42,6 +42,7 @@
 #include <dune/tnnmg/iterationsteps/genericnonlineargs.hh>
 
 #include <dune/tectonic/globallaursennonlinearity.hh>
+#include <dune/tectonic/globalruinanonlinearity.hh>
 #include <dune/tectonic/myconvexproblem.hh>
 #include <dune/tectonic/myblockproblem.hh>
 
@@ -186,6 +187,8 @@ int main(int argc, char *argv[]) {
 
     typedef MyConvexProblem<OperatorType, VectorType, Dune::LinearFunction>
     MyConvexProblemType;
+    // typedef MyConvexProblem<OperatorType, VectorType, Dune::RuinaFunction>
+    // MyConvexProblemType;
     typedef MyBlockProblem<MyConvexProblemType> MyBlockProblemType;
     GenericNonlinearGS<MyBlockProblemType> nonlinearGSStep;
     nonlinearGSStep.ignoreNodes_ = &ignoreNodes;
@@ -216,18 +219,29 @@ int main(int argc, char *argv[]) {
       stiffnessMatrix.umv(u3, b3);
 
       // {{{ Assemble terms for the nonlinearity
-      std::vector<double> normalStress;
-      normalStress.resize(grid.size(grid.maxLevel(), dim));
-      std::fill(normalStress.begin(), normalStress.end(),
-                parset.get<double>("boundary.normalstress"));
+      std::vector<double> a;
+      a.resize(grid.size(grid.maxLevel(), dim));
+      std::fill(a.begin(), a.end(), parset.get<double>("boundary.a"));
 
       std::vector<double> coefficientOfFriction;
       coefficientOfFriction.resize(grid.size(grid.maxLevel(), dim));
       std::fill(coefficientOfFriction.begin(), coefficientOfFriction.end(),
                 parset.get<double>("boundary.mu"));
 
+      std::vector<double> eta;
+      eta.resize(grid.size(grid.maxLevel(), dim));
+      std::fill(eta.begin(), eta.end(), parset.get<double>("boundary.eta"));
+
+      std::vector<double> normalStress;
+      normalStress.resize(grid.size(grid.maxLevel(), dim));
+      std::fill(normalStress.begin(), normalStress.end(),
+                parset.get<double>("boundary.normalstress"));
+
       Dune::GlobalLaursenNonlinearity<dim, Dune::LinearFunction>
       myGlobalNonlinearity(coefficientOfFriction, normalStress, nodalIntegrals);
+      // Dune::GlobalRuinaNonlinearity<dim>
+      //   myGlobalNonlinearity(nodalIntegrals, a, coefficientOfFriction, eta,
+      // normalStress);
       // }}}
 
       {
diff --git a/src/one-body-sample.parset b/src/one-body-sample.parset
index ef20f2b1..cb061d7c 100644
--- a/src/one-body-sample.parset
+++ b/src/one-body-sample.parset
@@ -12,5 +12,7 @@ maxiterations = 100000
 tolerance = 1e-6
 
 [boundary]
+a = 0.0015
 normalstress = 0.1
 mu = 0.75
+eta = 1
\ No newline at end of file
-- 
GitLab