From 19dcc1beace9f25d75bebecd6d3fe3cb2819660c Mon Sep 17 00:00:00 2001
From: podlesny <podlesny@mi.fu-berlin.de>
Date: Fri, 2 Aug 2019 10:38:07 +0200
Subject: [PATCH] .

---
 src/CMakeLists.txt                            |   2 +
 src/multi-body-problem-2D.cfg                 |   2 +-
 src/multi-body-problem.cfg                    |   4 +-
 src/solverfactorytest.cc                      |  96 +++++++++++--
 src/spatial-solving/solverfactory.cc          |   4 +-
 src/spatial-solving/solverfactory.hh          |   8 +-
 src/spatial-solving/tnnmg/functional.hh       | 126 +++++++++---------
 .../tnnmg/localbisectionsolver.hh             |  79 +++++++----
 8 files changed, 209 insertions(+), 112 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b9748ffc..6a92ecf9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -106,6 +106,8 @@ foreach(_dim 2 3)
 
   set_property(TARGET ${_sw_target} APPEND PROPERTY COMPILE_DEFINITIONS "MY_DIM=${_dim}")
   set_property(TARGET ${_msw_target} APPEND PROPERTY COMPILE_DEFINITIONS "MY_DIM=${_dim}")
+  #set_property(TARGET ${_msw_target} APPEND PROPERTY COMPILE_DEFINITIONS "NEW_TNNMG_COMPUTE_ITERATES_DIRECTLY=1")
   set_property(TARGET ${_ugw_target} APPEND PROPERTY COMPILE_DEFINITIONS "MY_DIM=${_dim}")
   set_property(TARGET ${_sft_target} APPEND PROPERTY COMPILE_DEFINITIONS "MY_DIM=${_dim}")
+  #set_property(TARGET ${_sft_target} APPEND PROPERTY COMPILE_DEFINITIONS "NEW_TNNMG_COMPUTE_ITERATES_DIRECTLY=1")
 endforeach()
diff --git a/src/multi-body-problem-2D.cfg b/src/multi-body-problem-2D.cfg
index 647e99cb..a308c80b 100644
--- a/src/multi-body-problem-2D.cfg
+++ b/src/multi-body-problem-2D.cfg
@@ -1,6 +1,6 @@
 # -*- mode:conf -*-
 [boundary.friction]
-smallestDiameter = 0.05  # 2e-3 [m]
+smallestDiameter = 0.01  # 2e-3 [m]
 
 [timeSteps]
 refinementTolerance = 1e-5 # 1e-5
diff --git a/src/multi-body-problem.cfg b/src/multi-body-problem.cfg
index b3a4ff9e..d58f80cf 100644
--- a/src/multi-body-problem.cfg
+++ b/src/multi-body-problem.cfg
@@ -47,10 +47,10 @@ relativeTau = 1e-4 # 1e-6
 
 [timeSteps]
 scheme = newmark
-timeSteps = 5
+timeSteps = 1
 
 [u0.solver]
-maximumIterations = 100
+maximumIterations = 20
 verbosity         = full
 
 [a0.solver]
diff --git a/src/solverfactorytest.cc b/src/solverfactorytest.cc
index 5365726f..3a4ceebe 100644
--- a/src/solverfactorytest.cc
+++ b/src/solverfactorytest.cc
@@ -74,6 +74,31 @@ size_t timeSteps = 0;
 const std::string path = "";
 const std::string outputFile = "solverfactorytest.log";
 
+std::vector<std::vector<double>> allReductionFactors;
+
+template<class IterationStepType, class NormType, class ReductionFactorContainer>
+Dune::Solvers::Criterion reductionFactorCriterion(
+      const IterationStepType& iterationStep,
+      const NormType& norm,
+      ReductionFactorContainer& reductionFactors)
+{
+  double normOfOldCorrection = 1;
+  auto lastIterate = std::make_shared<typename IterationStepType::Vector>(*iterationStep.getIterate());
+
+  return Dune::Solvers::Criterion(
+      [&, lastIterate, normOfOldCorrection] () mutable {
+        double normOfCorrection = norm.diff(*lastIterate, *iterationStep.getIterate());
+        double convRate = (normOfOldCorrection > 0) ? normOfCorrection / normOfOldCorrection : 0.0;
+
+        normOfOldCorrection = normOfCorrection;
+        *lastIterate = *iterationStep.getIterate();
+
+        reductionFactors.push_back(convRate);
+        return std::make_tuple(convRate < 0, Dune::formatString(" % '.5f", convRate));
+      },
+      " reductionFactor");
+}
+
 template <class ContactNetwork>
 void solveProblem(const ContactNetwork& contactNetwork,
                   const Matrix& mat, const Vector& rhs, Vector& x,
@@ -141,15 +166,15 @@ void solveProblem(const ContactNetwork& contactNetwork,
 
     refSolver.addCriterion(
             [&](){
-            return Dune::formatString("   % 12.5e", I(x));
+            return Dune::formatString("   % 12.5e", I(refX));
             },
             "   energy      ");
 
-    double initialEnergy = I(x);
+    double initialEnergy = I(refX);
     refSolver.addCriterion(
             [&](){
             static double oldEnergy=initialEnergy;
-            double currentEnergy = I(x);
+            double currentEnergy = I(refX);
             double decrease = currentEnergy - oldEnergy;
             oldEnergy = currentEnergy;
             return Dune::formatString("   % 12.5e", decrease);
@@ -169,13 +194,13 @@ void solveProblem(const ContactNetwork& contactNetwork,
             },
             "   truncated   ");
 
-
-    std::vector<double> correctionNorms;
-    refSolver.addCriterion(Dune::Solvers::correctionNormCriterion(step, norm, 1e-10, correctionNorms));
+    if (timeStep>0 and initial) {
+        allReductionFactors[timeStep].resize(0);
+        refSolver.addCriterion(reductionFactorCriterion(step, norm, allReductionFactors[timeStep]));
+    }
 
     refSolver.preprocess();
     refSolver.solve();
-    std::cout << correctionNorms.size() << std::endl;
 
     /*if (initial) {
         x = refX;
@@ -216,6 +241,35 @@ void solveProblem(const ContactNetwork& contactNetwork,
                 parset.get<double>("u0.solver.tolerance"), &norm,
         Solver::FULL, true, &refX); // absolute error
 
+    solver.addCriterion(
+            [&](){
+            return Dune::formatString("   % 12.5e", J(x));
+            },
+            "   energy      ");
+
+    initialEnergy = J(x);
+    solver.addCriterion(
+            [&](){
+            static double oldEnergy=initialEnergy;
+            double currentEnergy = J(x);
+            double decrease = currentEnergy - oldEnergy;
+            oldEnergy = currentEnergy;
+            return Dune::formatString("   % 12.5e", decrease);
+            },
+            "   decrease    ");
+
+    solver.addCriterion(
+            [&](){
+            return Dune::formatString("   % 12.5e", step.lastDampingFactor());
+            },
+            "   damping     ");
+
+    solver.addCriterion(
+            [&](){
+            return Dune::formatString("   % 12d", tnnmgStep->linearization().truncated().count());
+            },
+            "   truncated   ");
+
     solver.preprocess();
     solver.solve();
 
@@ -479,7 +533,7 @@ void run(Updaters& updaters, ContactNetwork& contactNetwork,
     // contribution from nonlinearity
     globalFriction.updateAlpha(alpha);
 
-    solveProblem(contactNetwork, bilinearForm, totalRhs, totalVelocityIterate, totalDirichletNodes, lower, upper);
+    solveProblem(contactNetwork, bilinearForm, totalRhs, totalVelocityIterate, totalDirichletNodes, lower, upper, false);
 
     nBodyAssembler.postprocess(totalVelocityIterate, velocityIterates);
 
@@ -619,6 +673,8 @@ int main(int argc, char *argv[]) { try {
     // -----------------
     // init input/output
     // -----------------
+    timeSteps = parset.get<size_t>("timeSteps.timeSteps");
+    allReductionFactors.resize(timeSteps+1);
 
     setupInitialConditions(contactNetwork);
 
@@ -739,7 +795,6 @@ int main(int argc, char *argv[]) { try {
 
     //const auto& stateEnergyNorms = contactNetwork.stateEnergyNorms();
 
-    timeSteps = parset.get<size_t>("timeSteps.timeSteps");
     for (timeStep=1; timeStep<=timeSteps; timeStep++) {
 
       advanceStep(current, contactNetwork);
@@ -756,6 +811,29 @@ int main(int argc, char *argv[]) { try {
       report();
     }
 
+    // output reduction factors
+    size_t count = 0;
+    for (size_t i=0; i<allReductionFactors.size(); i++) {
+        count = std::max(count, allReductionFactors[i].size());
+    }
+    std::vector<double> avgReductionFactors(count);
+    for (size_t i=0; i<count; i++) {
+        avgReductionFactors[i] = 1;
+        size_t c = 0;
+
+        for (size_t j=0; j<allReductionFactors.size(); j++) {
+            if (!(i<allReductionFactors[j].size()))
+                continue;
+
+            avgReductionFactors[i] *= allReductionFactors[j][i];
+            c++;
+        }
+
+        avgReductionFactors[i] = std::pow(avgReductionFactors[i], 1.0/((double)c));
+    }
+
+    print(avgReductionFactors, "average reduction factors: ");
+
     bool passed = true;
 
     std::cout << "Overall, the test " << (passed ? "was successful!" : "failed!") << std::endl;
diff --git a/src/spatial-solving/solverfactory.cc b/src/spatial-solving/solverfactory.cc
index 7084672a..d682cd05 100644
--- a/src/spatial-solving/solverfactory.cc
+++ b/src/spatial-solving/solverfactory.cc
@@ -26,9 +26,9 @@ SolverFactory<Functional, BitVector>::SolverFactory(
 
     auto linearSolver_ptr = Dune::Solvers::wrap_own_share<std::decay_t<LinearSolver>>(std::forward<LinearSolver>(linearSolver));
 
-    //tnnmgStep_ = std::make_shared<Step>(*J_, dummyIterate_, nonlinearSmoother_, linearSolver_ptr, 10, DefectProjection(), LineSearchSolver());
+    tnnmgStep_ = std::make_shared<Step>(*J_, dummyIterate_, nonlinearSmoother_, linearSolver_ptr, DefectProjection(), Dune::TNNMG::ScalarObstacleSolver());
 
-    tnnmgStep_ = std::make_shared<Step>(*J_, dummyIterate_, nonlinearSmoother_, linearSolver_ptr, DefectProjection(), LineSearchSolver());
+    //tnnmgStep_ = std::make_shared<Step>(*J_, dummyIterate_, nonlinearSmoother_, linearSolver_ptr, DefectProjection(), LineSearchSolver());
     tnnmgStep_->setPreSmoothingSteps(parset.get<int>("main.pre"));
     tnnmgStep_->setIgnore(ignoreNodes);
 }
diff --git a/src/spatial-solving/solverfactory.hh b/src/spatial-solving/solverfactory.hh
index a68755ec..2e1855e0 100644
--- a/src/spatial-solving/solverfactory.hh
+++ b/src/spatial-solving/solverfactory.hh
@@ -1,7 +1,7 @@
 #ifndef SRC_SPATIAL_SOLVING_SOLVERFACTORY_HH
 #define SRC_SPATIAL_SOLVING_SOLVERFACTORY_HH
 
-#define NEW_TNNMG_COMPUTE_ITERATES_DIRECTLY
+//#define NEW_TNNMG_COMPUTE_ITERATES_DIRECTLY
 
 #include <dune/common/bitsetvector.hh>
 #include <dune/common/parametertree.hh>
@@ -28,13 +28,13 @@ class SolverFactory {
     using Vector = typename Functional::Vector;
     using BitVector = BitVectorType;
 
-    using LocalSolver = LocalBisectionSolver;//Dune::TNNMG::ScalarObstacleSolver;//LocalBisectionSolver;
-    using NonlinearSmoother = Dune::TNNMG::NonlinearGSStep<Functional, LocalBisectionSolver, BitVector>;//Dune::TNNMG::NonlinearGSStep<Functional, Dune::TNNMG::GaussSeidelLocalSolver<LocalSolver>, BitVector>;
+    using LocalSolver = LocalBisectionSolver; //Dune::TNNMG::ScalarObstacleSolver;//LocalBisectionSolver;
+    using NonlinearSmoother = Dune::TNNMG::NonlinearGSStep<Functional, LocalBisectionSolver, BitVector>; //Dune::TNNMG::NonlinearGSStep<Functional, Dune::TNNMG::GaussSeidelLocalSolver<LocalSolver>, BitVector>;
     using Linearization = Linearization<Functional, BitVector>;
     using DefectProjection = typename Dune::TNNMG::ObstacleDefectProjection;
 
     //using Step = Dune::TNNMG::TNNMGStep<Functional, BitVector, Linearization, DefectProjection, LineSearchSolver>;
-    using Step = Dune::TNNMG::TNNMGStep<Functional, BitVector, Linearization, DefectProjection, LineSearchSolver>;
+    using Step = Dune::TNNMG::TNNMGStep<Functional, BitVector, Linearization, DefectProjection, Dune::TNNMG::ScalarObstacleSolver>;
 
   template <class LinearSolver>
   SolverFactory(const Dune::ParameterTree&,
diff --git a/src/spatial-solving/tnnmg/functional.hh b/src/spatial-solving/tnnmg/functional.hh
index 8305b04b..5a1d3b37 100644
--- a/src/spatial-solving/tnnmg/functional.hh
+++ b/src/spatial-solving/tnnmg/functional.hh
@@ -16,6 +16,9 @@
 
 #include <dune/tnnmg/functionals/boxconstrainedquadraticfunctional.hh>
 
+template<class M, class V, class N, class L, class U, class R>
+class DirectionalRestriction;
+
 template<class M, class V, class N, class R>
 class ShiftedFunctional;
 
@@ -60,6 +63,12 @@ class ShiftedFunctional : public Dune::TNNMG::ShiftedBoxConstrainedQuadraticFunc
       return phi_;
   }
 
+  friend auto directionalRestriction(const ShiftedFunctional& f, const Vector& origin, const Vector& direction)
+    -> DirectionalRestriction<Matrix, Vector, Nonlinearity, LowerObstacle, UpperObstacle, Range>
+  {
+    return DirectionalRestriction<Matrix, Vector, Nonlinearity, LowerObstacle, UpperObstacle, Range>(f.quadraticPart(), f.originalLinearPart(), f.phi(), f.originalLowerObstacle(), f.originalUpperObstacle(), origin, direction);
+  }
+
 protected:
   const Nonlinearity& phi_;
 };
@@ -148,6 +157,7 @@ class DirectionalRestriction :
   Interval domain_;
 };
 
+
 /** \brief Box constrained quadratic functional with nonlinearity
  *         Note: call setIgnore() to set up functional in affine subspace with ignore information
  *
@@ -157,7 +167,7 @@ class DirectionalRestriction :
  *  \tparam U Upper obstacle type
  *  \tparam R Range type
  */
-template<class V, class N, class L, class U, class O, class D, class R>
+/*template<class V, class N, class L, class U, class O, class D, class R>
 class FirstOrderModelFunctional {
     using Interval = typename Dune::Solvers::Interval<R>;
 
@@ -170,10 +180,30 @@ class FirstOrderModelFunctional {
 
     using field_type = typename Vector::field_type;
 
-private:
-    void init() {
-        auto origin = origin_.get();
-        auto direction = direction_.get();
+public:
+    template <class VV1, class NN, class LL, class UU, class VV2>
+    FirstOrderModelFunctional(
+            const Range& maxEigenvalue,
+            VV1&& linearTerm,
+            NN&& phi,
+            LL&& lower,
+            UU&& upper,
+            VV2&& origin) :
+        maxEigenvalue_(maxEigenvalue),
+        linearTerm_(std::forward<VV1>(linearTerm)),
+        lower_(std::forward<LL>(lower)),
+        upper_(std::forward<UU>(upper)),
+        origin_(std::forward<VV2>(origin)),
+        //direction_(linearTerm_),
+        phi_(std::forward<NN>(phi)) {
+
+        auto& origin = origin_.get();
+        auto& direction = direction_.get();
+
+        auto v = ri;
+        double const vnorm = v.two_norm();
+        if (vnorm > 1.0)
+              v /= vnorm;
 
         // set defect obstacles
         defectLower_ = -std::numeric_limits<field_type>::max();
@@ -190,61 +220,10 @@ class FirstOrderModelFunctional {
         if (domain_[1] > defectUpper_) {
            domain_[1] = defectUpper_;
         }
-
-        // set quadratic and linear parts of functional
-        quadraticPart_ = direction*direction;
-        quadraticPart_ *= maxEigenvalue_;
-
-        linearPart_ = linearTerm_.get()*direction - maxEigenvalue_*(direction*origin);
-    }
-
-public:
-    template <class MM, class VV1, class NN, class LL, class UU, class VV2, class VV3>
-    FirstOrderModelFunctional(
-            const MM& matrix,
-            VV1&& linearTerm,
-            NN&& phi,
-            LL&& lower,
-            UU&& upper,
-            VV2&& origin,
-            VV3&& direction) :
-        linearTerm_(std::forward<VV1>(linearTerm)),
-        lower_(std::forward<LL>(lower)),
-        upper_(std::forward<UU>(upper)),
-        origin_(std::forward<VV2>(origin)),
-        direction_(std::forward<VV3>(direction)),
-        phi_(std::forward<NN>(phi)) {
-
-        // set maxEigenvalue_ from matrix
-        Vector eigenvalues;
-        Dune::FMatrixHelp::eigenValues(matrix, eigenvalues);
-        maxEigenvalue_ = *std::max_element(std::begin(eigenvalues), std::end(eigenvalues));
-
-        init();
-    }
-
-    template <class VV1, class NN, class LL, class UU, class VV2, class VV3>
-    FirstOrderModelFunctional(
-            const Range& maxEigenvalue,
-            VV1&& linearTerm,
-            NN&& phi,
-            LL&& lower,
-            UU&& upper,
-            VV2&& origin,
-            VV3&& direction) :
-        linearTerm_(std::forward<VV1>(linearTerm)),
-        lower_(std::forward<LL>(lower)),
-        upper_(std::forward<UU>(upper)),
-        origin_(std::forward<VV2>(origin)),
-        direction_(std::forward<VV3>(direction)),
-        phi_(std::forward<NN>(phi)),
-        maxEigenvalue_(maxEigenvalue) {
-
-        init();
     }
 
   template <class BitVector>
-  auto getIgnoreFunctional(const BitVector& ignore) const {
+  auto setIgnore(const BitVector& ignore) const {
       Vector direction = direction_.get();
       Vector origin = origin_.get();
      // Dune::Solvers::resizeInitializeZero(direction, linearPart());
@@ -254,7 +233,9 @@ class FirstOrderModelFunctional {
         else
           origin[j] = 0; // shift affine offset
 
-      return FirstOrderModelFunctional<Vector, Nonlinearity&, LowerObstacle, UpperObstacle, Vector, Vector, Range>(maxEigenvalue_, linearTerm_, phi_, lower_, upper_, std::move(origin), std::move(direction));
+      // set quadratic and linear parts of functional
+      quadraticPart_ = maxEigenvalue_ * direction.two_norm2();
+      linearPart_ = linearTerm_.get() * direction;
   }
 
   Range operator()(const Vector& v) const
@@ -315,7 +296,7 @@ class FirstOrderModelFunctional {
 
   field_type defectLower_;
   field_type defectUpper_;
-};
+};*/
 
 // \ToDo This should be an inline friend of ShiftedBoxConstrainedQuadraticFunctional
 // but gcc-4.9.2 shipped with debian jessie does not accept
@@ -345,6 +326,18 @@ auto coordinateRestriction(const ShiftedFunctional<M, V, Nonlinearity, R>& f, co
       Dune::TNNMG::Imp::mmv(Aij, f.origin()[j], ri, Dune::PriorityTag<1>());
   });
 
+  // set maxEigenvalue from matrix
+  LocalVector eigenvalues;
+  Dune::FMatrixHelp::eigenValues(*Aii_p, eigenvalues);
+  auto maxEigenvalue = *std::max_element(std::begin(eigenvalues), std::end(eigenvalues));
+
+  Dune::MatrixVector::addProduct(ri, maxEigenvalue, f.origin()[i]);
+
+  LocalMatrix Aii = 0;
+  for (size_t d=0; d<Aii.N(); d++) {
+      Aii[d][d] = maxEigenvalue;
+  }
+
   LocalLowerObstacle dli = f.originalLowerObstacle()[i];
   LocalUpperObstacle dui = f.originalUpperObstacle()[i];
   dli -= f.origin()[i];
@@ -352,13 +345,16 @@ auto coordinateRestriction(const ShiftedFunctional<M, V, Nonlinearity, R>& f, co
 
   auto&& phii = f.phi().restriction(i);
 
-  auto v = ri;
-  double const vnorm = v.two_norm();
-  if (vnorm > 1.0)
-        v /= vnorm;
+  /*std::cout << "maxEigenvalue matrix: " << std::endl;
+  for (size_t i=0; i<Aii.N(); i++) {
+        for (size_t j=0; j<Aii.M(); j++) {
+            std::cout << Aii[i][j] << " ";
+        }
+        std::cout << std::endl;
+  }*/
 
-  return FirstOrderModelFunctional<LocalVector, decltype(phii), LocalLowerObstacle, LocalUpperObstacle, LocalVector, LocalVector, Range>(*Aii_p, std::move(ri), std::move(phii), std::move(dli), std::move(dui), std::move(f.origin()[i]), std::move(v));
-  //return Functional<LocalMatrix&, LocalVector, decltype(phii), LocalLowerObstacle, LocalUpperObstacle, Range>(*Aii_p, std::move(ri), std::move(phii), std::move(dli), std::move(dui));
+  //return FirstOrderModelFunctional<LocalVector, decltype(phii), LocalLowerObstacle, LocalUpperObstacle, LocalVector, LocalVector, Range>(maxEigenvalue, std::move(ri), std::move(phii), std::move(dli), std::move(dui), std::move(f.origin()[i]));
+  return ShiftedFunctional<LocalMatrix, LocalVector, decltype(phii), Range>(std::move(Aii), std::move(ri), std::move(phii), std::move(dli), std::move(dui), f.origin()[i]);
 }
 
 
diff --git a/src/spatial-solving/tnnmg/localbisectionsolver.hh b/src/spatial-solving/tnnmg/localbisectionsolver.hh
index 50618dd6..33f69e95 100644
--- a/src/spatial-solving/tnnmg/localbisectionsolver.hh
+++ b/src/spatial-solving/tnnmg/localbisectionsolver.hh
@@ -3,7 +3,9 @@
 #ifndef DUNE_TECTONIC_LOCALBISECTIONSOLVER_HH
 #define DUNE_TECTONIC_LOCALBISECTIONSOLVER_HH
 
+#include <dune/tnnmg/localsolvers/scalarobstaclesolver.hh>
 #include <dune/tnnmg/problem-classes/bisection.hh>
+#include "../../utils/debugutils.hh"
 
 /**
  * \brief A local solver for quadratic obstacle problems with nonlinearity
@@ -14,48 +16,67 @@ class LocalBisectionSolver
 public:
   template<class Vector, class Functional, class BitVector>
   void operator()(Vector& x, const Functional& f, const BitVector& ignore) const {
+      double safety = 1e-14; //or (f.upperObstacle()-f.lowerObstacle()<safety)
       if (ignore.all()) {
           return;
       }
 
-      double safety = 1e-14;
-      if (f.defectUpper() - f.defectLower() < safety) {
-          x = f.origin();
-          return;
-      }
+      Vector origin = f.origin();
+      Vector direction = f.originalLinearPart();
 
-      int bisectionsteps = 0;
-      const Bisection globalBisection;
+      for (size_t j = 0; j < ignore.size(); ++j)
+        if (ignore[j])
+          direction[j] = 0; // makes sure result remains in subspace after correction
+        else
+          origin[j] = 0; // shift affine offset
 
-      if (ignore.any()) {
-            auto&& restrictedf = f.getIgnoreFunctional(ignore);
-            const auto alpha = globalBisection.minimize(restrictedf, 0.0, 0.0, bisectionsteps);
+      double const directionNorm = direction.two_norm();
+      if (directionNorm <= 0.0)
+        return;
+      direction /= directionNorm;
 
-#ifdef NEW_TNNMG_COMPUTE_ITERATES_DIRECTLY
-            x = restrictedf.origin();
-            auto correction = restrictedf.direction();
-            correction *= alpha;
-            x += correction;
-#else
-            auto x = restrictedf.direction();
-            x *= alpha;
-#endif
+      auto&& directionalF = directionalRestriction(f, origin, direction);
+
+      // scalar obstacle solver without nonlinearity
+      typename Functional::Range alpha;
+      Dune::TNNMG::ScalarObstacleSolver obstacleSolver;
+      obstacleSolver(alpha, directionalF, false);
 
+      //direction *= alpha;
 
-      } else { // ignore.none()
-          const auto alpha = globalBisection.minimize(f, 0.0, 0.0, bisectionsteps);
+      /*const auto& A = f.quadraticPart();
+      std::cout << "f.quadratic(): " << std::endl;
+      for (size_t i=0; i<A.N(); i++) {
+            for (size_t j=0; j<A.M(); j++) {
+                std::cout << A[i][j] << " ";
+            }
+            std::cout << std::endl;
+      }*/
+      //std::cout << f.quadraticPart() << std::endl;
+      //std::cout << "A: " << directionalF.quadraticPart() << " " << (directionalF.quadraticPart()==f.quadraticPart()[0][0]) << std::endl;
+      /*std::cout << "b: " << directionalF.linearPart() << std::endl;
+      std::cout << "domain: " << directionalF.domain()[0] << " " << directionalF.domain()[1] << std::endl;
+      auto D = directionalF.subDifferential(0);
+      std::cout << "subDiff at x: " << D[0] << " " << D[1] << std::endl;*/
+
+      const auto& domain = directionalF.domain();
+      if (std::abs(domain[0]-domain[1])>safety) {
+        int bisectionsteps = 0;
+        const Bisection globalBisection;
+
+        alpha = globalBisection.minimize(directionalF, alpha, 0.0, bisectionsteps);
+      }
+
+      direction *= alpha;
 
 #ifdef NEW_TNNMG_COMPUTE_ITERATES_DIRECTLY
-          x = f.origin();
-          auto correction = f.direction();
-          correction *= alpha;
-          x += correction;
+      x = origin;
+      x += direction;
 #else
-          auto x = f.direction();
-          x *= alpha;
+      //x = origin;
+      x -= f.origin();
+      x += direction;
 #endif
-
-      }
   }
 };
 
-- 
GitLab