From 14a40c3a0a6fa158277f9f363825b76bda78342c Mon Sep 17 00:00:00 2001
From: Elias Pipping <elias.pipping@fu-berlin.de>
Date: Sat, 1 Jun 2013 22:12:55 +0200
Subject: [PATCH] Update the state

As a consequence, the nonlinearity is only assembled once
---
 dune/tectonic/frictionpotential.hh       | 28 ++++++++++++------------
 dune/tectonic/globalnonlinearity.hh      |  5 +++++
 dune/tectonic/globalruinanonlinearity.hh | 12 ++++++----
 dune/tectonic/localfriction.hh           |  5 +++++
 src/assemblers.cc                        |  5 ++---
 src/assemblers.hh                        |  3 +--
 src/assemblers_tmpl.cc                   |  3 +--
 src/one-body-sample.cc                   |  6 ++---
 8 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/dune/tectonic/frictionpotential.hh b/dune/tectonic/frictionpotential.hh
index e2a8c87f..c88afb32 100644
--- a/dune/tectonic/frictionpotential.hh
+++ b/dune/tectonic/frictionpotential.hh
@@ -27,26 +27,15 @@ class FrictionPotentialWrapper {
   // Between 0 and this point, the function is constantly zero (and
   // thus so are all derivatives)
   double virtual smallestPositivePoint() const = 0;
+  void virtual updateState(double) = 0;
 };
 
 // phi(V) = V log(V/V_m) - V + V_m  if V >= V_m
 //        = 0                       otherwise
-// with V_m = V_0 exp(-K/a),
-// i.e.   K = -a log(V_m / V_0) = mu_0 + b log(V_0 / L) + b alpha
 class FrictionPotential : public FrictionPotentialWrapper {
 public:
-  FrictionPotential(double coefficient, FrictionData const &fd, double state)
-      : FrictionPotentialWrapper(),
-        coefficientProduct(coefficient * fd.a * fd.normalStress),
-        // state is assumed to be logarithmic
-        V_m(fd.V0 *
-            std::exp(-(fd.mu0 + fd.b * (state + std::log(fd.V0 / fd.L))) /
-                     fd.a))
-        // We could also compute V_m as
-        // V_0 * std::exp(-(mu_0 + b * state)/a)
-        //     * std::pow(V_0 / L, -b/a)
-        // which would avoid the std::exp(std::log())
-  {}
+  FrictionPotential(double coefficient, FrictionData const &fd)
+      : fd(fd), coefficientProduct(coefficient * fd.a * fd.normalStress) {}
 
   double evaluate(double V) const {
     assert(V >= 0);
@@ -89,7 +78,16 @@ class FrictionPotential : public FrictionPotentialWrapper {
 
   double smallestPositivePoint() const { return V_m; }
 
+  //    V_m = V_0 exp(-K/a),
+  // with K = -a log(V_m / V_0) = mu_0 + b [ alpha + log(V_0 / L) ]
+  void updateState(double state) {
+    // state is assumed to be logarithmic
+    V_m = fd.V0 *
+          std::exp(-(fd.mu0 + fd.b * (state + std::log(fd.V0 / fd.L))) / fd.a);
+  }
+
 private:
+  FrictionData const &fd;
   double const coefficientProduct;
   double V_m;
 };
@@ -107,6 +105,8 @@ class TrivialFunction : public FrictionPotentialWrapper {
   double smallestPositivePoint() const {
     return std::numeric_limits<double>::infinity();
   }
+
+  void updateState(double) {}
 };
 }
 #endif
diff --git a/dune/tectonic/globalnonlinearity.hh b/dune/tectonic/globalnonlinearity.hh
index 246cc7f1..0e1b71e0 100644
--- a/dune/tectonic/globalnonlinearity.hh
+++ b/dune/tectonic/globalnonlinearity.hh
@@ -14,6 +14,9 @@
 namespace Dune {
 template <class MatrixTypeTEMPLATE, class VectorTypeTEMPLATE>
 class GlobalNonlinearity {
+private:
+  using dataref = BlockVector<FieldVector<double, 1>> const &;
+
 public:
   using MatrixType = MatrixTypeTEMPLATE;
   using VectorType = VectorTypeTEMPLATE;
@@ -74,6 +77,8 @@ class GlobalNonlinearity {
     auto const res = restriction(i);
     return res->regularity(x);
   }
+
+  virtual void updateState(dataref state) = 0;
 };
 }
 #endif
diff --git a/dune/tectonic/globalruinanonlinearity.hh b/dune/tectonic/globalruinanonlinearity.hh
index 81b8d902..f57e447c 100644
--- a/dune/tectonic/globalruinanonlinearity.hh
+++ b/dune/tectonic/globalruinanonlinearity.hh
@@ -24,20 +24,24 @@ class GlobalRuinaNonlinearity
   using GlobalNonlinearity<MatrixType, VectorType>::dim;
 
   GlobalRuinaNonlinearity(Dune::BitSetVector<1> const &frictionalNodes,
-                          dataref nodalIntegrals, FrictionData const &fd,
-                          dataref state)
+                          dataref nodalIntegrals, FrictionData const &fd)
       : restrictions(nodalIntegrals.size()) {
     auto trivialNonlinearity =
         make_shared<LocalFriction<dim>>(make_shared<TrivialFunction>());
     for (size_t i = 0; i < restrictions.size(); ++i) {
       restrictions[i] =
           frictionalNodes[i][0]
-              ? make_shared<LocalFriction<dim>>(make_shared<FrictionPotential>(
-                    nodalIntegrals[i], fd, state[i]))
+              ? make_shared<LocalFriction<dim>>(
+                    make_shared<FrictionPotential>(nodalIntegrals[i], fd))
               : trivialNonlinearity;
     }
   }
 
+  void updateState(dataref state) override {
+    for (size_t i = 0; i < restrictions.size(); ++i)
+      restrictions[i]->updateState(state[i]);
+  }
+
   /*
     Return a restriction of the outer function to the i'th node.
   */
diff --git a/dune/tectonic/localfriction.hh b/dune/tectonic/localfriction.hh
index 01138327..bfac47f6 100644
--- a/dune/tectonic/localfriction.hh
+++ b/dune/tectonic/localfriction.hh
@@ -25,6 +25,11 @@ template <int dimension> class LocalFriction {
     return func->evaluate(x.two_norm());
   }
 
+  void updateState(double state) {
+    func->updateState(state);
+    smp = func->smallestPositivePoint();
+  }
+
   double regularity(VectorType const &x) const {
     double const xnorm = x.two_norm();
     if (xnorm < 1e-14 && xnorm >= smp)
diff --git a/src/assemblers.cc b/src/assemblers.cc
index 74f3a4e8..1449acc2 100644
--- a/src/assemblers.cc
+++ b/src/assemblers.cc
@@ -52,11 +52,10 @@ Dune::shared_ptr<Dune::GlobalNonlinearity<MatrixType, VectorType>>
 assemble_nonlinearity(
     Dune::BitSetVector<1> const &frictionalNodes,
     Dune::BlockVector<Dune::FieldVector<double, 1>> const &nodalIntegrals,
-    FrictionData const &fd,
-    Dune::BlockVector<Dune::FieldVector<double, 1>> const &state) {
+    FrictionData const &fd) {
   return Dune::make_shared<
       Dune::GlobalRuinaNonlinearity<MatrixType, VectorType>>(
-      frictionalNodes, nodalIntegrals, fd, state);
+      frictionalNodes, nodalIntegrals, fd);
 }
 
 #include "assemblers_tmpl.cc"
diff --git a/src/assemblers.hh b/src/assemblers.hh
index 22b19e69..053a336b 100644
--- a/src/assemblers.hh
+++ b/src/assemblers.hh
@@ -28,6 +28,5 @@ Dune::shared_ptr<Dune::GlobalNonlinearity<MatrixType, VectorType>>
 assemble_nonlinearity(
     Dune::BitSetVector<1> const &frictionalNodes,
     Dune::BlockVector<Dune::FieldVector<double, 1>> const &nodalIntegrals,
-    FrictionData const &fd,
-    Dune::BlockVector<Dune::FieldVector<double, 1>> const &state);
+    FrictionData const &fd);
 #endif
diff --git a/src/assemblers_tmpl.cc b/src/assemblers_tmpl.cc
index 87a44928..325eaee8 100644
--- a/src/assemblers_tmpl.cc
+++ b/src/assemblers_tmpl.cc
@@ -35,5 +35,4 @@ template Dune::shared_ptr<Dune::GlobalNonlinearity<MatrixType, VectorType>>
 assemble_nonlinearity<MatrixType, VectorType>(
     Dune::BitSetVector<1> const &frictionalNodes,
     Dune::BlockVector<Dune::FieldVector<double, 1>> const &nodalIntegrals,
-    FrictionData const &fd,
-    Dune::BlockVector<Dune::FieldVector<double, 1>> const &state);
+    FrictionData const &fd);
diff --git a/src/one-body-sample.cc b/src/one-body-sample.cc
index 50459522..61bcf846 100644
--- a/src/one-body-sample.cc
+++ b/src/one-body-sample.cc
@@ -321,6 +321,8 @@ int main(int argc, char *argv[]) {
 
     auto const nodalIntegrals = assemble_frictional<GridView, SmallVector>(
         leafView, p1Assembler, frictionalNodes);
+    auto myGlobalNonlinearity = assemble_nonlinearity<MatrixType, VectorType>(
+        frictionalNodes, *nodalIntegrals, frictionData);
 
     // {{{ Initial conditions
     VectorType u_initial(finestSize);
@@ -407,9 +409,7 @@ int main(int argc, char *argv[]) {
       size_t iterationCounter;
       auto solveVelocityProblem = [&](VectorType &_problem_iterate,
                                       SingletonVectorType const &_alpha) {
-        auto myGlobalNonlinearity =
-            assemble_nonlinearity<MatrixType, VectorType>(
-                frictionalNodes, *nodalIntegrals, frictionData, _alpha);
+        myGlobalNonlinearity->updateState(_alpha);
 
         using MyConvexProblemType = MyConvexProblem<MatrixType, VectorType>;
         MyConvexProblemType const myConvexProblem(
-- 
GitLab