From 7db7854f85ee95a7f1406aa14cf8cf21421c1dc5 Mon Sep 17 00:00:00 2001
From: podlesny <podlesny@zedat.fu-berlin.de>
Date: Tue, 9 Feb 2021 00:00:42 +0100
Subject: [PATCH] work in progress: not working remainder

---
 dune/tectonic/data-structures/body/body.cc    |   8 +
 .../tectonic/data-structures/program_state.hh | 182 ++------------
 .../spatial-solving/fixedpointiterator.cc     | 162 ++----------
 .../spatial-solving/fixedpointiterator.hh     |   8 +-
 src/foam/foam-2D.cfg                          |   8 +-
 src/foam/foam.cc                              | 230 ++++++++++++++----
 src/foam/foam.cfg                             |  62 ++---
 src/strikeslip/strikeslip-2D.cfg              |   4 +-
 src/strikeslip/strikeslip.cfg                 |  50 ++--
 9 files changed, 290 insertions(+), 424 deletions(-)

diff --git a/dune/tectonic/data-structures/body/body.cc b/dune/tectonic/data-structures/body/body.cc
index cd63c1d5..83fb4fa8 100644
--- a/dune/tectonic/data-structures/body/body.cc
+++ b/dune/tectonic/data-structures/body/body.cc
@@ -5,6 +5,8 @@
 #include <dune/common/hybridutilities.hh>
 #include "body.hh"
 
+#include <dune/tectonic/utils/debugutils.hh>
+
 // -------------------------------
 // --- LeafBody Implementation ---
 // -------------------------------
@@ -50,11 +52,17 @@ void LeafBody<GridTEMPLATE, VectorType>::assemble() {
 
     // assemble matrices
     assembler_->assembleElasticity(bodyData_->getYoungModulus(), bodyData_->getPoissonRatio(), *matrices_.elasticity);
+    //print(*matrices_.elasticity, "elasticity");
+
     assembler_->assembleViscosity(bodyData_->getShearViscosityField(), bodyData_->getBulkViscosityField(), *matrices_.damping);
+    //print(*matrices_.damping, "viscosity");
+
     assembler_->assembleMass(bodyData_->getDensityField(), *matrices_.mass);
+    //print(*matrices_.mass, "mass");
 
     // assemble forces
     assembler_->assembleBodyForce(bodyData_->getGravityField(), gravityFunctional_);
+    //print(gravityFunctional_, "gravity");
 }
 
 // setter and getter
diff --git a/dune/tectonic/data-structures/program_state.hh b/dune/tectonic/data-structures/program_state.hh
index 9e1f63f5..d6a921c2 100644
--- a/dune/tectonic/data-structures/program_state.hh
+++ b/dune/tectonic/data-structures/program_state.hh
@@ -19,8 +19,10 @@
 #include "network/contactnetwork.hh"
 #include "matrices.hh"
 #include "../spatial-solving/preconditioners/multilevelpatchpreconditioner.hh"
+#include "../spatial-solving/makelinearsolver.hh"
+#include "../spatial-solving/nonlinearsolver.hh"
 #include "../spatial-solving/solverfactory.hh"
-#include "../spatial-solving/solverfactory.cc"
+#include "../spatial-solving/functionalfactory.hh"
 #include "../spatial-solving/tnnmg/functional.hh"
 #include "../spatial-solving/tnnmg/zerononlinearity.hh"
 #include "../utils/debugutils.hh"
@@ -99,60 +101,15 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState {
   // Set up initial conditions
   template <class ContactNetwork>
   void setupInitialConditions(const Dune::ParameterTree& parset, const ContactNetwork& contactNetwork) {
-    using Matrix = typename ContactNetwork::Matrix;
-    const auto& nBodyAssembler = contactNetwork.nBodyAssembler();
 
     std::cout << "-- setupInitialConditions --" << std::endl;
     std::cout << "----------------------------" << std::endl;
 
-    // make linear solver for linear correction in TNNMGStep
-    using Norm =  EnergyNorm<Matrix, Vector>;
-    using Preconditioner = MultilevelPatchPreconditioner<ContactNetwork, Matrix, Vector>;
-    using LinearSolver = typename Dune::Solvers::LoopSolver<Vector>;
-
- /*   const auto& preconditionerParset = parset.sub("solver.tnnmg.preconditioner");
-
-    Dune::BitSetVector<1> activeLevels(contactNetwork.nLevels(), true);
-    Preconditioner preconditioner(preconditionerParset, contactNetwork, activeLevels);
-    preconditioner.setPatchDepth(preconditionerParset.template get<size_t>("patchDepth"));
-
-    std::cout << "Building preconditioner..." << std::endl;
-    preconditioner.build();
-
-    auto cgStep = std::make_shared<Dune::Solvers::CGStep<Matrix, Vector>>();
-    cgStep->setPreconditioner(preconditioner);
-
-    Norm norm(*cgStep);
-
-    auto linearSolver = std::make_shared<LinearSolver>(cgStep, parset.get<int>("solver.tnnmg.main.multi"),
-                                                       parset.get<double>("solver.tnnmg.preconditioner.basesolver.tolerance"),
-                                                       norm, Solver::QUIET);
-
-*/
-    // set multigrid solver
-    auto smoother = TruncatedBlockGSStep<Matrix, Vector>();
-
-    using TransferOperator = NBodyContactTransfer<ContactNetwork, Vector>;
-    using TransferOperators = std::vector<std::shared_ptr<TransferOperator>>;
-
-    TransferOperators transfer(contactNetwork.nLevels()-1);
-    for (size_t i=0; i<transfer.size(); i++) {
-        transfer[i] = std::make_shared<TransferOperator>();
-        transfer[i]->setup(contactNetwork, i, i+1);
-    }
-
-    // Remove any recompute filed so that initially the full transferoperator is assembled
-    for (size_t i=0; i<transfer.size(); i++)
-        std::dynamic_pointer_cast<TruncatedMGTransfer<Vector> >(transfer[i])->setRecomputeBitField(nullptr);
-
-    auto linearMultigridStep = std::make_shared<Dune::Solvers::MultigridStep<Matrix, Vector> >();
-    linearMultigridStep->setMGType(1, 3, 3);
-    linearMultigridStep->setSmoother(smoother);
-    linearMultigridStep->setTransferOperators(transfer);
-
-    Norm norm(*linearMultigridStep);
+    using Matrix = typename ContactNetwork::Matrix;
+    const auto& nBodyAssembler = contactNetwork.nBodyAssembler();
 
-    auto linearSolver = std::make_shared<LinearSolver>(linearMultigridStep, parset.get<int>("solver.tnnmg.main.multi"), parset.get<double>("solver.tnnmg.preconditioner.basesolver.tolerance"), norm, Solver::QUIET);
+    auto linearSolver = makeLinearSolver<ContactNetwork, Vector>(parset, contactNetwork);
+    auto nonlinearity = ZeroNonlinearity();
 
     // Solving a linear problem with a multigrid solver
     auto const solveLinearProblem = [&](
@@ -160,126 +117,17 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState {
         const std::vector<Vector>& _rhs, std::vector<Vector>& _x,
         Dune::ParameterTree const &_localParset) {
 
-      std::vector<const Matrix*> matrices_ptr(_matrices.size());
-      for (size_t i=0; i<matrices_ptr.size(); i++) {
-            matrices_ptr[i] = _matrices[i].get();
-      }
-
-      /*std::vector<Matrix> matrices(velocityMatrices.size());
-          std::vector<Vector> rhs(velocityRHSs.size());
-          for (size_t i=0; i<globalFriction_.size(); i++) {
-            matrices[i] = velocityMatrices[i];
-            rhs[i] = velocityRHSs[i];
-
-            globalFriction_[i]->addHessian(v_rel[i], matrices[i]);
-            globalFriction_[i]->addGradient(v_rel[i], rhs[i]);
-
-            matrices_ptr[i] = &matrices[i];
-          }*/
-
-      // assemble full global contact problem
-      Matrix bilinearForm;
-
-      nBodyAssembler.assembleJacobian(matrices_ptr, bilinearForm);
-
-      Vector totalRhs, oldTotalRhs;
-      nBodyAssembler.assembleRightHandSide(_rhs, totalRhs);
-      oldTotalRhs = totalRhs;
-
-      Vector totalX, oldTotalX;
-      nBodyAssembler.nodalToTransformed(_x, totalX);
-      oldTotalX = totalX;
-
-      // get lower and upper obstacles
-      const auto& totalObstacles = nBodyAssembler.totalObstacles_;
-      Vector lower(totalObstacles.size());
-      Vector upper(totalObstacles.size());
-
-      for (size_t j=0; j<totalObstacles.size(); ++j) {
-          const auto& totalObstaclesj = totalObstacles[j];
-          auto& lowerj = lower[j];
-          auto& upperj = upper[j];
-        for (size_t d=0; d<dims; ++d) {
-            lowerj[d] = totalObstaclesj[d][0];
-            upperj[d] = totalObstaclesj[d][1];
-        }
-      }
-
-      // print problem
-     /* print(bilinearForm, "bilinearForm");
-      print(totalRhs, "totalRhs");
-      print(_dirichletNodes, "ignore");
-      print(totalObstacles, "totalObstacles");
-      print(lower, "lower");
-      print(upper, "upper");*/
-
-      // set up functional
-      using Functional = Functional<Matrix&, Vector&, ZeroNonlinearity&, Vector&, Vector&, typename Matrix::field_type>;
-      Functional J(bilinearForm, totalRhs, ZeroNonlinearity(), lower, upper); //TODO
-
-      // set up TNMMG solver
-      using Factory = SolverFactory<Functional, BitVector>;
-      //Factory factory(parset.sub("solver.tnnmg"), J, linearSolver, _dirichletNodes);
-      Factory factory(parset.sub("solver.tnnmg"), J, _dirichletNodes);
-      factory.build(linearSolver);
-
-     /* std::vector<BitVector> bodyDirichletNodes;
-      nBodyAssembler.postprocess(_dirichletNodes, bodyDirichletNodes);
-      for (size_t i=0; i<bodyDirichletNodes.size(); i++) {
-        print(bodyDirichletNodes[i], "bodyDirichletNodes_" + std::to_string(i) + ": ");
-      }*/
-
-     /* print(bilinearForm, "matrix: ");
-      print(totalX, "totalX: ");
-      print(totalRhs, "totalRhs: ");*/
-
-      auto tnnmgStep = factory.step();
-      factory.setProblem(totalX);
-
-      const EnergyNorm<Matrix, Vector> norm(bilinearForm);
-
-      LoopSolver<Vector> solver(
-          *tnnmgStep.get(), _localParset.get<size_t>("maximumIterations"),
-          _localParset.get<double>("tolerance"), norm,
-          _localParset.get<Solver::VerbosityMode>("verbosity")); // absolute error
-
-      solver.preprocess();
-      solver.solve();
-
-      std::cout << "ProgramState: Energy of TNNMG solution: " << J(tnnmgStep->getSol()) << std::endl;
-
-      nBodyAssembler.postprocess(tnnmgStep->getSol(), _x);
-
-      Vector res = totalRhs;
-      bilinearForm.mmv(tnnmgStep->getSol(), res);
-      std::cout << "TNNMG Res - energy norm: " << norm.operator ()(res) << std::endl;
-
-      // TODO: remove after debugging
-  /*    using DeformedGridType = typename LevelContactNetwork<GridType, dims>::DeformedGridType;
-      using OldLinearFactory = SolverFactoryOld<DeformedGridType, GlobalFriction<Matrix, Vector>, Matrix, Vector>;
-      OldLinearFactory oldFactory(parset.sub("solver.tnnmg"), nBodyAssembler, _dirichletNodes);
-
-      auto oldStep = oldFactory.getStep();
-      oldStep->setProblem(bilinearForm, oldTotalX, oldTotalRhs);
-
-          LoopSolver<Vector> oldSolver(
-              oldStep.get(), _localParset.get<size_t>("maximumIterations"),
-              _localParset.get<double>("tolerance"), &norm,
-              _localParset.get<Solver::VerbosityMode>("verbosity"),
-              false); // absolute error
+        Vector totalX;
+        nBodyAssembler.nodalToTransformed(_x, totalX);
 
-          oldSolver.preprocess();
-          oldSolver.solve();
+        FunctionalFactory<std::decay_t<decltype(nBodyAssembler)>, decltype(nonlinearity), Matrix, Vector> functionalFactory(nBodyAssembler, nonlinearity, _matrices, _rhs);
+        functionalFactory.build();
+        auto functional = functionalFactory.functional();
 
-      Vector oldRes = totalRhs;
-      bilinearForm.mmv(oldStep->getSol(), oldRes);
-      std::cout << "Old Res - energy norm: " << norm.operator ()(oldRes) << std::endl;*/
+        NonlinearSolver<std::remove_reference_t<decltype(*functional)>, BitVector> solver(parset.sub("solver.tnnmg"), linearSolver, functional, _dirichletNodes);
+        solver.solve(_localParset, totalX);
 
-   //   print(tnnmgStep->getSol(), "TNNMG Solution: ");
-   /*   print(oldStep->getSol(), "Old Solution: ");
-      auto diff = tnnmgStep->getSol();
-      diff -= oldStep->getSol();
-      std::cout << "Energy norm: " << norm.operator ()(diff) << std::endl;*/
+        nBodyAssembler.postprocess(totalX, _x);
     };
 
     timeStep = parset.get<size_t>("initialTime.timeStep");
diff --git a/dune/tectonic/spatial-solving/fixedpointiterator.cc b/dune/tectonic/spatial-solving/fixedpointiterator.cc
index a36d76f2..bef1fea2 100644
--- a/dune/tectonic/spatial-solving/fixedpointiterator.cc
+++ b/dune/tectonic/spatial-solving/fixedpointiterator.cc
@@ -6,41 +6,13 @@
 
 #include <dune/matrix-vector/axpy.hh>
 
-#include <dune/solvers/norms/energynorm.hh>
-#include <dune/solvers/solvers/loopsolver.hh>
-
-#include <dune/contact/assemblers/nbodyassembler.hh>
-#include <dune/contact/common/dualbasisadapter.hh>
-
-#include <dune/localfunctions/lagrange/pqkfactory.hh>
-
-#include <dune/functions/gridfunctions/gridfunction.hh>
-
-#include <dune/geometry/quadraturerules.hh>
-#include <dune/geometry/type.hh>
-#include <dune/geometry/referenceelements.hh>
-
-#include <dune/fufem/functions/basisgridfunction.hh>
-
-#include "../data-structures/enums.hh"
-#include "../data-structures/enumparser.hh"
-
+#include <dune/tectonic/utils/reductionfactors.hh>
 
+#include "functionalfactory.hh"
+#include "nonlinearsolver.hh"
 
-#include "../utils/tobool.hh"
 #include "../utils/debugutils.hh"
 
-#include <dune/solvers/solvers/loopsolver.hh>
-#include <dune/solvers/iterationsteps/truncatedblockgsstep.hh>
-#include <dune/solvers/iterationsteps/multigridstep.hh>
-
-#include "../spatial-solving/contact/nbodycontacttransfer.hh"
-
-#include "tnnmg/functional.hh"
-#include "tnnmg/zerononlinearity.hh"
-
-#include <dune/tectonic/utils/reductionfactors.hh>
-
 #include "fixedpointiterator.hh"
 
 void FixedPointIterationCounter::operator+=(
@@ -65,9 +37,7 @@ FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorms>::FixedPointIte
       fixedPointMaxIterations_(parset.get<size_t>("v.fpi.maximumIterations")),
       fixedPointTolerance_(parset.get<double>("v.fpi.tolerance")),
       lambda_(parset.get<double>("v.fpi.lambda")),
-      velocityMaxIterations_(parset.get<size_t>("v.solver.maximumIterations")),
-      velocityTolerance_(parset.get<double>("v.solver.tolerance")),
-      verbosity_(parset.get<Solver::VerbosityMode>("v.solver.verbosity")),
+      solverParset_(parset.sub("v.solver")),
       errorNorms_(errorNorms) {}
 
 template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorms>
@@ -80,110 +50,28 @@ FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorms>::run(
 
   //std::cout << "FixedPointIterator::run()" << std::endl;
 
+  const auto nBodies = nBodyAssembler_.nGrids();
+
   // debugging
   /*const auto& contactCouplings = nBodyAssembler_.getContactCouplings();
   for (size_t i=0; i<contactCouplings.size(); i++) {
     print(*contactCouplings[i]->nonmortarBoundary().getVertices(), "nonmortarBoundaries:");
   }*/
 
-  const auto nBodies = nBodyAssembler_.nGrids();
-
-  std::vector<const Matrix*> matrices_ptr(nBodies);
-  for (int i=0; i<nBodies; i++) {
-      matrices_ptr[i] = &velocityMatrices[i];
-  }
-
-  // assemble full global contact problem
-  Matrix bilinearForm;
-  nBodyAssembler_.assembleJacobian(matrices_ptr, bilinearForm);
+  FunctionalFactory<std::decay_t<decltype(nBodyAssembler_)>, decltype(globalFriction_), Matrix, Vector> functionalFactory(nBodyAssembler_, globalFriction_, velocityMatrices, velocityRHSs);
+  functionalFactory.build();
+  auto functional = functionalFactory.functional();
 
-  //print(bilinearForm, "bilinearForm:");
-
-  Vector totalRhs;
-  nBodyAssembler_.assembleRightHandSide(velocityRHSs, totalRhs);
-
-  //print(totalRhs, "totalRhs:");
-
-  // get lower and upper obstacles
-  const auto& totalObstacles = nBodyAssembler_.totalObstacles_;
-  Vector lower(totalObstacles.size());
-  Vector upper(totalObstacles.size());
-
-  for (size_t j=0; j<totalObstacles.size(); ++j) {
-      const auto& totalObstaclesj = totalObstacles[j];
-      auto& lowerj = lower[j];
-      auto& upperj = upper[j];
-    for (size_t d=0; d<dims; ++d) {
-        lowerj[d] = totalObstaclesj[d][0];
-        upperj[d] = totalObstaclesj[d][1];
-    }
-  }
-
-  //print(totalObstacles, "totalObstacles:");
-
-  //print(lower, "lower obstacles:");
-  //print(upper, "upper obstacles:");
-
-  // compute velocity obstacles
-  /*Vector vLower, vUpper;
-  std::vector<Vector> u0, v0;
-  updaters.rate_->extractOldVelocity(v0);
-  updaters.rate_->extractOldDisplacement(u0);
-
-  Vector totalu0, totalv0;
-  nBodyAssembler_.concatenateVectors(u0, totalu0);
-  nBodyAssembler_.concatenateVectors(v0, totalv0);
-
-  updaters.rate_->velocityObstacles(totalu0, lower, totalv0, vLower);
-  updaters.rate_->velocityObstacles(totalu0, upper, totalv0, vUpper); */
-
-  //print(vLower, "vLower obstacles:");
-  //print(vUpper, "vUpper obstacles:");
-
-  //std::cout << "- Problem assembled: success" << std::endl;
-
-  //print(ignoreNodes_, "ignoreNodes:");
-
-  // set up functional and TNMMG solver
-  //using ZeroSolverFactory = SolverFactory<Functional, IgnoreVector>;
-  //Functional J(bilinearForm, totalRhs, ZeroNonlinearity(), vLower, vUpper);
-  //ZeroSolverFactory solverFactory(parset_.sub("solver.tnnmg"), J, mgSolver, ignoreNodes_);
-  Functional J(bilinearForm, totalRhs, globalFriction_, lower, upper);
-  Factory solverFactory(parset_.sub("solver.tnnmg"), J, ignoreNodes_);
-  solverFactory.build(linearSolver);
-
-  auto step = solverFactory.step();
-
-  //std::cout << "- Functional and TNNMG step setup: success" << std::endl;
-
-  EnergyNorm<Matrix, Vector> energyNorm(bilinearForm);
-  LoopSolver<Vector> velocityProblemSolver(*step.get(), velocityMaxIterations_,
-                                           velocityTolerance_, energyNorm,
-                                           verbosity_);
+  NonlinearSolver<std::remove_reference_t<decltype(*functional)>, IgnoreVector> solver(parset_.sub("solver.tnnmg"), linearSolver, functional, ignoreNodes_);
 
   size_t fixedPointIteration;
   size_t multigridIterations = 0;
   std::vector<ScalarVector> alpha(nBodies);
   updaters.state_->extractAlpha(alpha);
 
-  Vector totalVelocityIterate;
+  Vector totalVelocityIterate, old_v;
   nBodyAssembler_.nodalToTransformed(velocityIterates, totalVelocityIterate);
-
-  // project in onto admissible set
-  const size_t blocksize = Vector::block_type::dimension;
-  for (size_t i=0; i<totalVelocityIterate.size(); i++) {
-      for (size_t j=0; j<blocksize; j++) {
-          if (totalVelocityIterate[i][j] < lower[i][j]) {
-              totalVelocityIterate[i][j] = lower[i][j];
-          }
-
-          if (totalVelocityIterate[i][j] > upper[i][j]) {
-              totalVelocityIterate[i][j] = upper[i][j];
-          }
-      }
-  }
-
-  Vector old_v = totalVelocityIterate;
+  old_v = totalVelocityIterate;
 
   for (fixedPointIteration = 0; fixedPointIteration < fixedPointMaxIterations_;
        ++fixedPointIteration) {
@@ -193,25 +81,9 @@ FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorms>::run(
     // contribution from nonlinearity
     globalFriction_.updateAlpha(alpha);
 
-    //print(velocityIterates, "velocityIterates:");
-    //print(totalVelocityIterate, "totalVelocityIterate:");
-    //std::cout << "- FixedPointIteration iterate" << std::endl;
-
-    // solve a velocity problem
-    solverFactory.setProblem(totalVelocityIterate);
+    auto res = solver.solve(solverParset_, totalVelocityIterate);
 
-    //std::cout << "- Velocity problem set" << std::endl;
-
-    velocityProblemSolver.preprocess();
-    //std::cout << "-- Preprocessed" << std::endl;
-    velocityProblemSolver.solve();
-    //std::cout << "-- Solved" << std::endl;
-
-    const auto& tnnmgSol = step->getSol();
-
-    //std::cout << "FixPointIterator: Energy of TNNMG solution: " << J(tnnmgSol) << std::endl;
-
-    nBodyAssembler_.postprocess(tnnmgSol, velocityIterates);
+    nBodyAssembler_.postprocess(totalVelocityIterate, velocityIterates);
     //nBodyAssembler_.postprocess(totalVelocityIterate, velocityIterates);
 
     //print(totalVelocityIterate, "totalVelocityIterate:");
@@ -219,11 +91,11 @@ FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorms>::run(
 
     //DUNE_THROW(Dune::Exception, "Just need to stop here!");
 
-    multigridIterations += velocityProblemSolver.getResult().iterations;
+    multigridIterations += res.iterations;
 
     Vector v_m = old_v;
     v_m *= 1.0 - lambda_;
-    Dune::MatrixVector::addProduct(v_m, lambda_, tnnmgSol);
+    Dune::MatrixVector::addProduct(v_m, lambda_, totalVelocityIterate);
 
     // extract relative velocities in mortar basis
     std::vector<Vector> v_rel;
@@ -259,6 +131,8 @@ FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorms>::run(
         }
     }
 
+    //std::cout << fixedPointIteration << std::endl;
+
     if (lambda_ < 1e-12 or breakCriterion) {
       //std::cout << "-FixedPointIteration finished! " << (lambda_ < 1e-12 ? "lambda" : "breakCriterion") << std::endl;
       fixedPointIteration++;
diff --git a/dune/tectonic/spatial-solving/fixedpointiterator.hh b/dune/tectonic/spatial-solving/fixedpointiterator.hh
index 183f2f8d..3742ed98 100644
--- a/dune/tectonic/spatial-solving/fixedpointiterator.hh
+++ b/dune/tectonic/spatial-solving/fixedpointiterator.hh
@@ -13,8 +13,6 @@
 
 #include <dune/contact/assemblers/nbodyassembler.hh>
 
-#include "tnnmg/functional.hh"
-#include "tnnmg/zerononlinearity.hh"
 #include "solverfactory.hh"
 
 struct FixedPointIterationCounter {
@@ -33,7 +31,6 @@ class FixedPointIterator {
   using Vector = typename Factory::Vector;
   using Matrix = typename Factory::Matrix;
 
-  using Functional = typename Factory::Functional; //Functional<Matrix&, Vector&, &, Vector&, Vector&, double>; //;
   using Nonlinearity = typename Factory::Functional::Nonlinearity;
 
   const static int dims = Vector::block_type::dimension;
@@ -76,9 +73,8 @@ class FixedPointIterator {
   size_t fixedPointMaxIterations_;
   double fixedPointTolerance_;
   double lambda_;
-  size_t velocityMaxIterations_;
-  double velocityTolerance_;
-  Solver::VerbosityMode verbosity_;
+  const Dune::ParameterTree& solverParset_;
+
   const ErrorNorms& errorNorms_;
 };
 
diff --git a/src/foam/foam-2D.cfg b/src/foam/foam-2D.cfg
index d911706c..6f7c2ecc 100644
--- a/src/foam/foam-2D.cfg
+++ b/src/foam/foam-2D.cfg
@@ -1,12 +1,12 @@
 # -*- mode:conf -*-
 [body0]
-smallestDiameter = 0.05  # 2e-3 [m]
+smallestDiameter = 0.5  # 2e-3 [m]
 
 [body1]
-smallestDiameter = 0.01 # 2e-3 [m]
+smallestDiameter = 0.5 # 2e-3 [m]
 
 [timeSteps]
-refinementTolerance = 1e-5 # 1e-5
+refinementTolerance = 1e-3 # 1e-5
 
 [u0.solver]
 tolerance         = 1e-8
@@ -18,7 +18,7 @@ tolerance         = 1e-8
 tolerance         = 1e-8
 
 [v.fpi]
-tolerance         = 1e-5
+tolerance         = 1e-3
 
 [solver.tnnmg.preconditioner.basesolver]
 tolerance          = 1e-10
diff --git a/src/foam/foam.cc b/src/foam/foam.cc
index 59660df5..324bcd88 100644
--- a/src/foam/foam.cc
+++ b/src/foam/foam.cc
@@ -69,8 +69,9 @@
 //#include <dune/tectonic/spatial-solving/preconditioners/multilevelpatchpreconditioner.hh>
 #include <dune/tectonic/spatial-solving/tnnmg/localbisectionsolver.hh>
 #include <dune/tectonic/spatial-solving/solverfactory.hh>
+#include <dune/tectonic/spatial-solving/makelinearsolver.hh>
 
-#include <dune/tectonic/time-stepping/adaptivetimestepper.hh>
+#include <dune/tectonic/time-stepping/uniformtimestepper.hh>
 #include <dune/tectonic/time-stepping/rate.hh>
 #include <dune/tectonic/time-stepping/state.hh>
 #include <dune/tectonic/time-stepping/updaters.hh>
@@ -79,6 +80,13 @@
 #include <dune/tectonic/utils/diameter.hh>
 #include <dune/tectonic/utils/geocoordinate.hh>
 
+#include <dune/matrix-vector/axpy.hh>
+
+#include <dune/contact/assemblers/nbodyassembler.hh>
+#include "dune/tectonic/spatial-solving/tnnmg/zerononlinearity.hh"
+
+
+
 // for getcwd
 #include <unistd.h>
 
@@ -188,6 +196,172 @@ int main(int argc, char *argv[]) {
       programState.setupInitialConditions(parset, contactNetwork);
     }
 
+    /*
+    // setup initial conditions in program state
+    programState.alpha[0] = 0;
+    programState.alpha[1] = parset.get<double>("boundary.friction.initialAlpha"); */
+
+    /*auto myGlobalNonlinearity = myAssembler.assembleFrictionNonlinearity(
+          frictionalBoundary, frictionData);
+      myGlobalNonlinearity->updateLogState(alpha_initial);
+*/
+
+    /*
+    // Solving a linear problem with a multigrid solver
+    auto linearSolver = makeLinearSolver<ContactNetwork, Vector>(parset, contactNetwork);
+    const auto& nBodyAssembler = contactNetwork.nBodyAssembler();
+
+    auto const solveLinearProblem = [&](
+        const BitVector& _dirichletNodes, const std::vector<std::shared_ptr<Matrix>>& _matrices,
+        const std::vector<Vector>& _rhs, std::vector<Vector>& _x,
+        Dune::ParameterTree const &_localParset) {
+
+      std::vector<const Matrix*> matrices_ptr(_matrices.size());
+      for (size_t i=0; i<matrices_ptr.size(); i++) {
+            matrices_ptr[i] = _matrices[i].get();
+      }
+
+      // assemble full global contact problem
+      Matrix bilinearForm;
+      nBodyAssembler.assembleJacobian(matrices_ptr, bilinearForm);
+
+      Vector totalRhs, oldTotalRhs;
+      nBodyAssembler.assembleRightHandSide(_rhs, totalRhs);
+      oldTotalRhs = totalRhs;
+
+      Vector totalX, oldTotalX;
+      nBodyAssembler.nodalToTransformed(_x, totalX);
+      oldTotalX = totalX;
+
+      // get lower and upper obstacles
+      const auto& totalObstacles = nBodyAssembler.totalObstacles_;
+      Vector lower(totalObstacles.size());
+      Vector upper(totalObstacles.size());
+
+      for (size_t j=0; j<totalObstacles.size(); ++j) {
+          const auto& totalObstaclesj = totalObstacles[j];
+          auto& lowerj = lower[j];
+          auto& upperj = upper[j];
+        for (size_t d=0; d<dims; ++d) {
+            lowerj[d] = totalObstaclesj[d][0];
+            upperj[d] = totalObstaclesj[d][1];
+        }
+      }
+
+      // set up functional
+      using Functional = Functional<Matrix&, Vector&, ZeroNonlinearity&, Vector&, Vector&, typename Matrix::field_type>;
+      Functional J(bilinearForm, totalRhs, ZeroNonlinearity(), lower, upper);
+
+      // set up TNMMG solver
+      using Factory = SolverFactory<Functional, BitVector>;
+      //Factory factory(parset.sub("solver.tnnmg"), J, linearSolver, _dirichletNodes);
+      Factory factory(parset.sub("solver.tnnmg"), J, _dirichletNodes);
+      factory.build(linearSolver); */
+
+     /* std::vector<BitVector> bodyDirichletNodes;
+      nBodyAssembler.postprocess(_dirichletNodes, bodyDirichletNodes);
+      for (size_t i=0; i<bodyDirichletNodes.size(); i++) {
+        print(bodyDirichletNodes[i], "bodyDirichletNodes_" + std::to_string(i) + ": ");
+      }*/
+
+    /*
+      auto tnnmgStep = factory.step();
+      factory.setProblem(totalX);
+
+      const EnergyNorm<Matrix, Vector> norm(bilinearForm);
+
+      LoopSolver<Vector> solver(
+          *tnnmgStep.get(), _localParset.get<size_t>("maximumIterations"),
+          _localParset.get<double>("tolerance"), norm,
+          _localParset.get<Solver::VerbosityMode>("verbosity")); // absolute error
+
+      solver.preprocess();
+      solver.solve();
+
+      nBodyAssembler.postprocess(tnnmgStep->getSol(), _x);
+    }; */
+
+     /*using LinearFactory = SolverFactory<
+          dims, BlockNonlinearTNNMGProblem<ConvexProblem<
+                    ZeroNonlinearity<LocalVector, LocalMatrix>, Matrix>>,
+          Grid>;
+      ZeroNonlinearity<LocalVector, LocalMatrix> zeroNonlinearity;*/
+
+  /*
+    // TODO: clean up once generic lambdas arrive
+      auto const solveLinearProblem = [&](
+          Dune::BitSetVector<dims> const &_dirichletNodes, Matrix const &_matrix,
+          Vector const &_rhs, Vector &_x, EnergyNorm<Matrix, Vector> _norm,
+          Dune::ParameterTree const &_localParset) {
+
+
+
+        typename LinearFactory::ConvexProblem convexProblem(
+            1.0, _matrix, zeroNonlinearity, _rhs, _x);
+        typename LinearFactory::BlockProblem problem(parset, convexProblem);
+
+        auto multigridStep = factory.getSolver();
+        multigridStep->setProblem(_x, problem);
+        LoopSolver<Vector> solver(
+            multigridStep, _localParset.get<size_t>("maximumIterations"),
+            _localParset.get<double>("tolerance"), &_norm,
+            _localParset.get<Solver::VerbosityMode>("verbosity"),
+            false); // absolute error
+
+        solver.preprocess();
+        solver.solve();
+      };
+
+      // Solve the stationary problem
+      programState.u[0] = 0.0;
+      programState.u[1] = 0.0;
+
+      solveLinearProblem(dirichletNodes, contactNetwork.matrices().elasticity, ell0, programState.u,
+                         parset.sub("u0.solver"));
+
+      programState.v[0] = 0.0;
+      programState.v[1] = 0.0;
+
+
+      programState.a[0] = 0.0;
+      programState.a[1] = 0.0;
+      {
+          // Initial acceleration: Computed in agreement with Ma = ell0 - Au
+          // (without Dirichlet constraints), again assuming dPhi(v = 0) = 0
+          std::vector<Vector> accelerationRHS = ell0;
+
+          for (size_t i=0; i<bodyCount; i++) {
+            const auto& body = contactNetwork.body(i);
+            Dune::MatrixVector::subtractProduct(accelerationRHS[i], *body->matrices().elasticity, u[i]);
+          }
+
+          BitVector noNodes(dirichletNodes.size(), false);
+          solveLinearProblem(noNodes, contactNetwork.matrices().mass, accelerationRHS, programState.a,
+                             parset.sub("a0.solver"));
+
+      }
+
+      for (size_t i=0; i<contactNetwork.nCouplings(); i++) {
+        const auto& coupling = contactNetwork.coupling(i);
+        const auto& contactCoupling = contactNetwork.nBodyAssembler().getContactCouplings()[i];
+
+        const auto nonmortarIdx = coupling->gridIdx_[0];
+        const auto& body = contactNetwork.body(nonmortarIdx);
+
+        ScalarVector frictionBoundaryStress(weightedNormalStress[nonmortarIdx].size());
+
+        body->assembler()->assembleWeightedNormalStress(
+          contactCoupling->nonmortarBoundary(), frictionBoundaryStress, body->data()->getYoungModulus(),
+          body->data()->getPoissonRatio(), u[nonmortarIdx]);
+
+        weightedNormalStress[nonmortarIdx] += frictionBoundaryStress;
+      }
+
+
+*/
+
+
+
     auto& nBodyAssembler = contactNetwork.nBodyAssembler();
     for (size_t i=0; i<bodyCount; i++) {
       contactNetwork.body(i)->setDeformation(programState.u[i]);
@@ -198,6 +372,8 @@ int main(int argc, char *argv[]) {
     // ------------------------
     // assemble global friction
     // ------------------------
+    print(programState.weightedNormalStress, "weightedNormalStress");
+
     contactNetwork.assembleFriction(parset.get<Config::FrictionModel>("boundary.friction.frictionModel"), programState.weightedNormalStress);
 
     auto& globalFriction = contactNetwork.globalFriction();
@@ -279,43 +455,6 @@ int main(int argc, char *argv[]) {
 
     const auto& stateEnergyNorms = contactNetwork.stateEnergyNorms();
 
-    auto const mustRefine = [&](Updaters &coarseUpdater,
-                                Updaters &fineUpdater) {
-
-        //return false;
-      //std::cout << "Step 1" << std::endl;
-
-      std::vector<ScalarVector> coarseAlpha;
-      coarseAlpha.resize(bodyCount);
-      coarseUpdater.state_->extractAlpha(coarseAlpha);
-
-      //print(coarseAlpha, "coarseAlpha:");
-
-      std::vector<ScalarVector> fineAlpha;
-      fineAlpha.resize(bodyCount);
-      fineUpdater.state_->extractAlpha(fineAlpha);
-
-      //print(fineAlpha, "fineAlpha:");
-
-      //std::cout << "Step 3" << std::endl;
-
-      ScalarVector::field_type energyNorm = 0;
-      for (size_t i=0; i<stateEnergyNorms.size(); i++) {
-          //std::cout << "for " << i << std::endl;
-
-          //std::cout << not stateEnergyNorms[i] << std::endl;
-
-          if (coarseAlpha[i].size()==0 || fineAlpha[i].size()==0)
-              continue;
-
-          energyNorm += stateEnergyNorms[i]->diff(fineAlpha[i], coarseAlpha[i]);
-      }
-      //std::cout << "energy norm: " << energyNorm << " tol: " << refinementTolerance <<  std::endl;
-      //std::cout << "must refine: " << (energyNorm > refinementTolerance) <<  std::endl;
-      return energyNorm > refinementTolerance;
-    };
-
-
     std::signal(SIGXCPU, handleSignal);
     std::signal(SIGINT, handleSignal);
     std::signal(SIGTERM, handleSignal);
@@ -348,21 +487,20 @@ int main(int argc, char *argv[]) {
         stepBase(parset, contactNetwork, totalDirichletNodes, globalFriction, frictionNodes,
                  externalForces, stateEnergyNorms);
 
-    AdaptiveTimeStepper<NonlinearFactory, std::decay_t<decltype(contactNetwork)>, Updaters, std::decay_t<decltype(stateEnergyNorms)>>
-        adaptiveTimeStepper(stepBase, contactNetwork, current,
-                            programState.relativeTime, programState.relativeTau,
-                            mustRefine);
+    UniformTimeStepper<NonlinearFactory, std::decay_t<decltype(contactNetwork)>, Updaters, std::decay_t<decltype(stateEnergyNorms)>>
+        timeStepper(stepBase, contactNetwork, current,
+                            programState.relativeTime, programState.relativeTau);
 
     size_t timeSteps = parset.get<size_t>("timeSteps.timeSteps");
 
-    while (!adaptiveTimeStepper.reachedEnd()) {
+    while (!timeStepper.reachedEnd()) {
       programState.timeStep++;
 
       //preconditioner.build();
-      iterationCount = adaptiveTimeStepper.advance();
+      iterationCount = timeStepper.advance();
 
-      programState.relativeTime = adaptiveTimeStepper.relativeTime_;
-      programState.relativeTau = adaptiveTimeStepper.relativeTau_;
+      programState.relativeTime = timeStepper.relativeTime_;
+      programState.relativeTau = timeStepper.relativeTau_;
       current.rate_->extractDisplacement(programState.u);
       current.rate_->extractVelocity(programState.v);
       current.rate_->extractAcceleration(programState.a);
diff --git a/src/foam/foam.cfg b/src/foam/foam.cfg
index b5f4216c..cf375466 100644
--- a/src/foam/foam.cfg
+++ b/src/foam/foam.cfg
@@ -1,77 +1,79 @@
 # -*- mode:conf -*-
+outPath = test  # output written to ./output/outPath
+
 gravity         = 9.81     # [m/s^2]
 
 [body0]
-length          = 0.4      # [m]
-height          = 0.04     # [m]
-depth           = 0.04     # [m]
-bulkModulus     = 1.5e5    # [Pa] #2190
-poissonRatio    = 0.11     # [1]  #0.11
+length          = 5.0      # [m]
+height          = 1.0     # [m]
+bulkModulus     = 4.12e7    # [Pa] #2190
+poissonRatio    = 0.3     # [1]  #0.11
 [body0.elastic]
-density         = 1300      # [kg/m^3] #750
+density         = 5e3      # [kg/m^3] #750
 shearViscosity  = 0     # [Pas]
 bulkViscosity   = 0     # [Pas]
 [body0.viscoelastic]
-density         = 1300     # [kg/m^3]
+density         = 5e3      # [kg/m^3] #750
 shearViscosity  = 0     # [Pas]
 bulkViscosity   = 0     # [Pas]
 
 [body1]
-length          = 0.04     # [m]
-height          = 0.04     # [m]
-depth           = 0.04     # [m]
-bulkModulus     = 1.5e5    # [Pa]
-poissonRatio    = 0.11     # [1]
+length          = 5.00     # [m]
+height          = 1.00     # [m]
+bulkModulus     = 4.12e7    # [Pa]
+poissonRatio    = 0.3     # [1]
 [body1.elastic]
-density         = 1300      # [kg/m^3]
+density         = 5e3      # [kg/m^3]
 shearViscosity  = 0     # [Pas]
 bulkViscosity   = 0     # [Pas]
 [body1.viscoelastic]
-density         = 1300     # [kg/m^3]
+density         = 5e3      # [kg/m^3]
 shearViscosity  = 0     # [Pas]
 bulkViscosity   = 0     # [Pas]
 
+
 [boundary.friction]
-C               = 6       # [Pa]
-mu0             = 0.48      # [ ]
-V0              = 1e-3     # [m/s]
-L               = 1e-6  # [m]
-initialAlpha    = 0        # [ ]
+C               = 0.0       # [Pa]
+mu0             = 0.6      # [ ]
+V0              = 1e-6     # [m/s]
+L               = 1e-5  # [m]
+initialAlpha    = -10.0  # [ ]
 stateModel      = AgeingLaw
 frictionModel   = Truncated #Regularised
 [boundary.friction.weakening]
-a               = 0.054    # [ ]
-b               = 0.074    # [ ]
+a               = 0.010    # [ ]
+b               = 0.015    # [ ]
 [boundary.friction.strengthening]
-a               = 0.054    # [ ]
-b               = 0.074    # [ ]
+a               = 0.010    # [ ]
+b               = 0.015    # [ ]
+
 
 [boundary.neumann]
-sigmaN          = 10000.0      # [Pa]
+sigmaN          = 0.0      # [Pa]
 
 [boundary.dirichlet]
-finalVelocity   = 3e-3     # [m/s]
+finalVelocity   = 2e-4     # [m/s]
 
 [io]
-data.write      = false
+data.write      = true
 printProgress   = true
 restarts.first  = 0
 restarts.spacing= 20
-restarts.write  = false #true
+restarts.write  = true #true
 vtk.write       = true
 
 [problem]
-finalTime       = 1000     # [s] #1000
+finalTime       = 15     # [s] #1000
 bodyCount       = 2
 
 [initialTime]
 timeStep = 0
 relativeTime = 0.0
-relativeTau = 5e-6 # 1e-6
+relativeTau = 1e-4 # 1e-6
 
 [timeSteps]
 scheme = newmark
-timeSteps = 1
+timeSteps = 1e4
 
 [u0.solver]
 maximumIterations = 100
diff --git a/src/strikeslip/strikeslip-2D.cfg b/src/strikeslip/strikeslip-2D.cfg
index cabe495a..9fd7ce5c 100644
--- a/src/strikeslip/strikeslip-2D.cfg
+++ b/src/strikeslip/strikeslip-2D.cfg
@@ -1,9 +1,9 @@
 # -*- mode:conf -*-
 [body0]
-smallestDiameter = 0.006 # 2e-3 [m]
+smallestDiameter = 0.02 # 2e-3 [m]
 
 [body1]
-smallestDiameter = 0.006  # 2e-3 [m]
+smallestDiameter = 0.02  # 2e-3 [m]
 
 [timeSteps]
 refinementTolerance = 1e-3# 1e-5
diff --git a/src/strikeslip/strikeslip.cfg b/src/strikeslip/strikeslip.cfg
index dc73ee1e..dc92ad1a 100644
--- a/src/strikeslip/strikeslip.cfg
+++ b/src/strikeslip/strikeslip.cfg
@@ -1,21 +1,21 @@
 outPath = test  # output written to ./output/strikeslip/outPath
 
 # -*- mode:conf -*-
-gravity         = 9.81     # [m/s^2]
+gravity         = 0.0     # [m/s^2]
 
 [body0]
 length          = 0.5      # [m]
 height          = 0.5     # [m]
 depth           = 0.12     # [m]
-bulkModulus     = 1.5e5    # [Pa] #2190
-poissonRatio    = 0.11     # [1]  #0.11
+bulkModulus     = 0.5e5    # [Pa] #2190
+poissonRatio    = 0.3     # [1]  #0.11
 [body0.elastic]
 distFromDiag    = 0.2
-density         = 1300      # [kg/m^3] #750
-shearViscosity  = 0     # [Pas]
-bulkViscosity   = 0     # [Pas]
+density         = 900      # [kg/m^3] #750
+shearViscosity  = 1e3     # [Pas]
+bulkViscosity   = 1e3     # [Pas]
 [body0.viscoelastic]
-density         = 1300     # [kg/m^3]
+density         = 1000     # [kg/m^3]
 shearViscosity  = 1e4     # [Pas]
 bulkViscosity   = 1e4     # [Pas]
 
@@ -23,32 +23,32 @@ bulkViscosity   = 1e4     # [Pas]
 length          = 0.5     # [m]
 height          = 0.5     # [m]
 depth           = 0.12     # [m]
-bulkModulus     = 1.5e5    # [Pa]
-poissonRatio    = 0.11     # [1]
+bulkModulus     = 1e5    # [Pa]
+poissonRatio    = 0.0     # [1]
 [body1.elastic]
 distFromDiag    = 0.2
-density         = 1300      # [kg/m^3]
-shearViscosity  = 0     # [Pas]
-bulkViscosity   = 0     # [Pas]
+density         = 900      # [kg/m^3]
+shearViscosity  = 0.0    # [Pas]
+bulkViscosity   = 0.0     # [Pas]
 [body1.viscoelastic]
-density         = 1300     # [kg/m^3]
-shearViscosity  = 1e4     # [Pas]
-bulkViscosity   = 1e4     # [Pas]
+density         = 1000     # [kg/m^3]
+shearViscosity  = 0.0     # [Pas]
+bulkViscosity   = 0.0     # [Pas]
 
 [boundary.friction]
-C               = 6       # [Pa]
-mu0             = 0.48      # [ ]
-V0              = 1e-3     # [m/s]
-L               = 1e-6  # [m]
+C               = 10       # [Pa]
+mu0             = 0.7      # [ ]
+V0              = 5e-5     # [m/s]
+L               = 2.25e-5  # [m]
 initialAlpha    = 0        # [ ]
 stateModel      = AgeingLaw
 frictionModel   = Truncated #Regularised
 [boundary.friction.weakening]
-a               = 0.054    # [ ]
-b               = 0.074    # [ ]
+a               = 0.002    # [ ]
+b               = 0.017    # [ ]
 [boundary.friction.strengthening]
-a               = 0.054    # [ ]
-b               = 0.074    # [ ]
+a               = 0.020    # [ ]
+b               = 0.005    # [ ]
 
 [boundary.neumann]
 sigmaN          = 200.0      # [Pa]
@@ -60,7 +60,7 @@ finalVelocity   = 1e-4     # [m/s]
 data.write      = true
 printProgress   = true
 restarts.first  = 0
-restarts.spacing= 1
+restarts.spacing= 50
 restarts.write  = true #true
 vtk.write       = true
 
@@ -75,7 +75,7 @@ relativeTau = 2e-2 # 1e-6
 
 [timeSteps]
 scheme = newmark
-timeSteps = 15
+timeSteps = 10
 
 [u0.solver]
 maximumIterations = 100
-- 
GitLab