#ifndef DUNE_TECTONIC_MINIMISATION_HH
#define DUNE_TECTONIC_MINIMISATION_HH

#include <dune/common/fmatrix.hh>
#include <dune/common/fvector.hh>
#include <dune/common/stdstreams.hh>

#include <dune/fufem/arithmetic.hh>
#include <dune/fufem/interval.hh>
#include <dune/tnnmg/problem-classes/bisection.hh>

#include <dune/tectonic/mydirectionalconvexfunction.hh>

// Warning: this exploits the property v*x = 0
template <class Functional>
double lineSearch(Functional const &J,
                  typename Functional::LocalVector const &x,
                  typename Functional::LocalVector const &v,
                  Bisection const &bisection) {
  MyDirectionalConvexFunction<typename Functional::Nonlinearity> const JRest(
      J.alpha * v.two_norm2(), J.b * v, *J.phi, x, v);
  int count;
  return bisection.minimize(JRest, 0.0, 0.0, count);
}

/** Minimise a quadratic problem, for which both the quadratic and the
    nonlinear term have gradients which point in the direction of
    their arguments */
template <class Functional>
void minimise(Functional const &J, typename Functional::LocalVector &x,
              Bisection const &bisection) {
  auto v = J.b;
  double const vnorm = v.two_norm();
  if (vnorm <= 0.0)
    return;
  v /= vnorm;

  double const alpha = lineSearch(J, x, v, bisection);
  Arithmetic::addProduct(x, alpha, v);
}
#endif