Skip to content
Snippets Groups Projects
Commit ef039d44 authored by Elias Pipping's avatar Elias Pipping
Browse files

[Extend] Handle descent at zero properly

parent aae2defb
No related branches found
No related tags found
No related merge requests found
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <dune/common/stdstreams.hh> #include <dune/common/stdstreams.hh>
#include <dune/fufem/arithmetic.hh> #include <dune/fufem/arithmetic.hh>
#include <dune/solvers/common/interval.hh>
#include "localfriction.hh" #include "localfriction.hh"
...@@ -30,14 +31,33 @@ template <size_t dim> class EllipticEnergy { ...@@ -30,14 +31,33 @@ template <size_t dim> class EllipticEnergy {
std::shared_ptr<Nonlinearity const> const phi; std::shared_ptr<Nonlinearity const> const phi;
typename Dune::BitSetVector<dim>::const_reference const ignore; typename Dune::BitSetVector<dim>::const_reference const ignore;
void gradient(LocalVector const &x, LocalVector &y) const { void descentDirection(LocalVector const &x, LocalVector &y) const {
A.mv(x, y); if (x.two_norm() >= 0.0) {
y -= b; A.mv(x, y);
phi->addGradient(x, y); y -= b;
phi->addGradient(x, y);
for (size_t i = 0; i < dim; ++i)
if (ignore[i]) for (size_t i = 0; i < dim; ++i)
y[i] = 0; if (ignore[i])
y[i] = 0;
y *= -1;
} else {
A.mv(x, y);
y -= b;
for (size_t i = 0; i < dim; ++i)
if (ignore[i])
y[i] = 0;
y *= -1;
// The contribution of phi to the directional derivative is the
// same for all directions here! Choose the one that is best of
// the smooth part and check if we have overall decline
Dune::Solvers::Interval<double> D;
phi->directionalSubDiff(x, y, D);
if (D[1] - y.two_norm2() >= 0.0)
y = 0.0;
}
} }
}; };
#endif #endif
...@@ -39,12 +39,12 @@ void minimise(Functional const &J, typename Functional::LocalVector &x, ...@@ -39,12 +39,12 @@ void minimise(Functional const &J, typename Functional::LocalVector &x,
for (size_t step = 0; step < steps; ++step) { for (size_t step = 0; step < steps; ++step) {
LocalVector v; LocalVector v;
J.gradient(x, v); J.descentDirection(x, v);
double const vnorm = v.two_norm(); double const vnorm = v.two_norm();
if (vnorm <= 0.0) if (vnorm <= 0.0)
return; return;
v /= -vnorm; // normalise for numerical stability; note the minus v /= vnorm;
double const alpha = lineSearch(J, x, v, bisection); double const alpha = lineSearch(J, x, v, bisection);
Arithmetic::addProduct(x, alpha, v); Arithmetic::addProduct(x, alpha, v);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment