From d49dfbc17af9e81b28489eb79972e60c7a8b636c Mon Sep 17 00:00:00 2001
From: Elias Pipping <elias.pipping@fu-berlin.de>
Date: Wed, 14 Dec 2011 14:54:33 +0100
Subject: [PATCH] Handle irregularity

---
 dune/tectonic/globalnonlinearity.hh |  5 +++++
 dune/tectonic/localnonlinearity.hh  | 12 ++++++++++--
 dune/tectonic/myblockproblem.hh     | 19 +++----------------
 dune/tectonic/nicefunction.hh       | 20 +++++++++++++++++---
 src/one-body-sample.parset          |  2 +-
 5 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/dune/tectonic/globalnonlinearity.hh b/dune/tectonic/globalnonlinearity.hh
index dc773dfc..9a284eaa 100644
--- a/dune/tectonic/globalnonlinearity.hh
+++ b/dune/tectonic/globalnonlinearity.hh
@@ -33,6 +33,11 @@ class GlobalNonlinearity {
       res->addGradient(v[i], gradient[i]);
     }
   }
+
+  double regularity(int i, typename VectorType::block_type const &x) const {
+    auto res = restriction(i);
+    return res->regularity(x);
+  }
 };
 }
 #endif
diff --git a/dune/tectonic/localnonlinearity.hh b/dune/tectonic/localnonlinearity.hh
index a6ce8e3b..81c81552 100644
--- a/dune/tectonic/localnonlinearity.hh
+++ b/dune/tectonic/localnonlinearity.hh
@@ -26,6 +26,13 @@ template <int dimension> class LocalNonlinearity {
     return ret;
   }
 
+  double regularity(VectorType const &x) const {
+    if (x.two_norm() < 1e-8) // TODO
+      return std::numeric_limits<double>::infinity();
+
+    return func_->regularity(x.two_norm());
+  }
+
   // directional subdifferential: at u on the line u + t*v
   // u and v are assumed to be non-zero
   void directionalSubDiff(VectorType const &u, VectorType const &v,
@@ -83,11 +90,12 @@ template <int dimension> class LocalNonlinearity {
 
   // TODO: do not evaluate at zero
   void addGradient(VectorType const &x, VectorType &y) const {
-    if (x == VectorType(0))
+    if (x.two_norm() <
+        1e-8 or std::isinf(func_->regularity(x.two_norm()))) // TODO
       return;
 
     VectorType tmp;
-    upperGradient(x, tmp); // TODO
+    upperGradient(x, tmp); // upper and lower gradient coincide in this case
     y += tmp;
   }
 
diff --git a/dune/tectonic/myblockproblem.hh b/dune/tectonic/myblockproblem.hh
index 70f70581..d571ae7b 100644
--- a/dune/tectonic/myblockproblem.hh
+++ b/dune/tectonic/myblockproblem.hh
@@ -83,22 +83,9 @@ template <class MyConvexProblemTypeTEMPLATE> class MyBlockProblem {
     // determine truncation pattern
     linearization.truncation.resize(u.size());
     linearization.truncation.unsetAll();
-    Interval<double> ab;
-    for (int i = 0; i < u.size(); ++i) {
-      for (int j = 0; j < block_size; ++j) {
-        // TODO: handle smooth domain
-        // problem.phi.smoothDomain(i, u[i][j], regularity_tol, ab, j);
-
-        // // if (phi is not regular at u) or (u is not in smooth domain) or
-        // (component should be ignored)
-        // // truncate this component
-        // if ((problem.phi.regularity(i, u[i][j], j) > regularity_tol)
-        //     or (u[i][j] < ab[0])
-        //     or (u[i][j] > ab[1])
-        //     or ignore[i][j])
-        //   linearization.truncation[i][j] = true;
-      }
-    }
+    for (int i = 0; i < u.size(); ++i)
+      if (problem.phi.regularity(i, u[i]) > 1e8) // TODO
+        linearization.truncation[i] = true;
 
     // construct sparsity pattern for linearization
     Dune::MatrixIndexSet indices(problem.A.N(), problem.A.M());
diff --git a/dune/tectonic/nicefunction.hh b/dune/tectonic/nicefunction.hh
index 6dedd620..575b473e 100644
--- a/dune/tectonic/nicefunction.hh
+++ b/dune/tectonic/nicefunction.hh
@@ -18,6 +18,10 @@ class NiceFunction : public VirtualFunction<double, double> {
   double virtual second_deriv(double x) const {
     DUNE_THROW(NotImplemented, "second derivative not implemented");
   }
+
+  double virtual regularity(double s) const {
+    DUNE_THROW(NotImplemented, "regularity not implemented");
+  }
 };
 
 class RuinaFunction : public NiceFunction {
@@ -82,14 +86,20 @@ class RuinaFunction : public NiceFunction {
     = a/x
   */
   double virtual second_deriv(double s) const {
-    if (eta * s < rho)
+    // includes the case eta * s = rho for which there is no second derivative
+    if (eta * s <= rho)
       return 0;
-    else if (eta * s == rho)
-      return 37; // TODO: not differentiable;
     else
       return coefficient * normalStress * (a / s);
   }
 
+  double virtual regularity(double s) const {
+    if (eta * s == rho)
+      return std::numeric_limits<double>::infinity();
+
+    return std::abs(second_deriv(s));
+  }
+
 private:
   double coefficient;
   double a;
@@ -116,6 +126,8 @@ class LinearFunction : public NiceFunction {
 
   double virtual second_deriv(double) const { return 0; }
 
+  double virtual regularity(double s) const { return 0; }
+
 private:
   double coefficient;
 };
@@ -153,6 +165,8 @@ class TrivialFunction : public NiceFunction {
   double virtual rightDifferential(double) const { return 0; }
 
   double virtual second_deriv(double) const { return 0; }
+
+  double virtual regularity(double) const { return 0; }
 };
 
 // slope in [n-1,n] is n
diff --git a/src/one-body-sample.parset b/src/one-body-sample.parset
index 32366667..d5f9d7a6 100644
--- a/src/one-body-sample.parset
+++ b/src/one-body-sample.parset
@@ -49,7 +49,7 @@ normalstress = 0.1 # laursen depends a lot more on this
 #    http://earthquake.usgs.gov/research/physics/lab/prediction.pdf
 mu = 0.5
 eta = 1
-model = Ruina # TODO: Laursen doesn't work with TNNMG
+model = Ruina
 
 [boundary.friction.ruina]
 # "For rocks, typical values of A and B range from 0.005 to 0.015"
-- 
GitLab