12#ifndef DUMUX_NONLINEAR_LEASTSQUARES_HH 
   13#define DUMUX_NONLINEAR_LEASTSQUARES_HH 
   19#include <dune/common/exceptions.hh> 
   20#include <dune/istl/bvector.hh> 
   21#include <dune/istl/matrix.hh> 
   22#if HAVE_SUITESPARSE_CHOLMOD 
   23#include <dune/istl/cholmod.hh> 
   25#include <dune/istl/io.hh> 
   35template<
class Variables>
 
   40    virtual bool apply(Variables& vars) = 0;
 
 
 
   49template<
class T, 
class F>
 
   54    using JacobianMatrix = Dune::Matrix<T>;
 
   55    using ResidualType = Dune::BlockVector<T>;
 
   56    using SolutionVector = Dune::BlockVector<T>;
 
   57    using Variables = Dune::BlockVector<T>;
 
   65    Assembler(
const F& f, 
const SolutionVector& x0, std::size_t residualSize)
 
   66    : prevSol_(x0), f_(f), solSize_(x0.size()), residualSize_(residualSize)
 
   67    , JT_(solSize_, residualSize_), regularizedJTJ_(solSize_, solSize_)
 
   68    , residual_(residualSize_), projectedResidual_(solSize_)
 
   75    void setLinearSystem()
 
   77        std::cout << 
"Setting up linear system with " << solSize_ << 
" variables and " 
   78                  << residualSize_ << 
" residuals." << std::endl;
 
   81        regularizedJTJ_ = 0.0;
 
   83        projectedResidual_ = 0.0;
 
   87    JacobianMatrix& jacobian() { 
return regularizedJTJ_; }
 
   90    ResidualType& residual() { 
return projectedResidual_; }
 
   93    void setLambda(
const T lambda) { lambda_ = lambda; }
 
   94    T lambda() { 
return lambda_; }
 
   97    void assembleResidual(
const SolutionVector& x)
 
   99        projectedResidual_ = 0.0;
 
  103        for (
auto rowIt = JT_.begin(); rowIt != JT_.end(); ++rowIt)
 
  105            const auto paramIdx = rowIt.index();
 
  106            const auto residual = f_(x);
 
  108            const auto eps = baseEpsilon_;
 
  109            p[paramIdx] = x[paramIdx] + eps;
 
  110            auto deflectedResidual = f_(p);
 
  111            deflectedResidual -= residual;
 
  112            deflectedResidual /= eps;
 
  113            for (
auto colIt = rowIt->begin(); colIt != rowIt->end(); ++colIt)
 
  114                *colIt += deflectedResidual[colIt.index()];
 
  116            projectedResidual_[paramIdx] = residual * deflectedResidual;
 
  121            std::cout << std::endl << 
"J^T = " << std::endl;
 
  122            Dune::printmatrix(std::cout, JT_, 
"", 
"");
 
  127    void assembleJacobianAndResidual(
const SolutionVector& x)
 
  131        regularizedJTJ_ = 0.0;
 
  132        for (
auto rowIt = regularizedJTJ_.begin(); rowIt != regularizedJTJ_.end(); ++rowIt)
 
  134            for (
auto colIt = rowIt->begin(); colIt != rowIt->end(); ++colIt)
 
  136                for (
int j = 0; j < residualSize_; ++j)
 
  137                    *colIt += JT_[rowIt.index()][j]*JT_[colIt.index()][j];
 
  139                if (rowIt.index() == colIt.index())
 
  141                    *colIt += lambda_*(*colIt);
 
  144                        *colIt = 1e-6*lambda_;
 
  151            std::cout << std::endl << 
"J^T J + λ diag(J^T J) = " << std::endl;
 
  152            Dune::printmatrix(std::cout, regularizedJTJ_, 
"", 
"");
 
  157    T computeMeanSquaredError(
const SolutionVector& x)
 const 
  158    { 
return f_(x).two_norm2(); }
 
  161    const SolutionVector& prevSol()
 const 
  165    SolutionVector prevSol_; 
 
  167    std::size_t solSize_, residualSize_;
 
  170    JacobianMatrix regularizedJTJ_; 
 
  171    ResidualType residual_; 
 
  172    ResidualType projectedResidual_; 
 
  174    Scalar lambda_ = 0.0; 
 
  177    bool printMatrix_ = 
false;
 
  180#if HAVE_SUITESPARSE_CHOLMOD 
  181template<
class Matrix, 
class Vector>
 
  182class CholmodLinearSolver
 
  185    void setResidualReduction(
double residualReduction) {}
 
  187    bool solve(
const Matrix& A, Vector& x, 
const Vector& b)
 const 
  189        Dune::Cholmod<Vector> solver; 
 
  191        Dune::InverseOperatorResult r;
 
  194        solver.apply(xCopy, bCopy, r);
 
  195        checkResult_(xCopy, r);
 
  197            DUNE_THROW(NumericalProblem, 
"Linear solver did not converge.");
 
  202    auto norm(
const Vector& residual)
 const 
  203    { 
return residual.two_norm(); }
 
  206    void checkResult_(Vector& x, Dune::InverseOperatorResult& result)
 const 
  208        flatVectorForEach(x, [&](
auto&& entry, std::size_t){
 
  209            using std::isnan, std::isinf;
 
  210            if (isnan(entry) || isinf(entry))
 
  211                result.converged = 
false;
 
  229template<
class Assembler, 
class LinearSolver>
 
  233    using Scalar = 
typename Assembler::Scalar;
 
  234    using Variables = 
typename Assembler::Variables;
 
  235    using SolutionVector = 
typename Assembler::SolutionVector;
 
  236    using ResidualVector = 
typename Assembler::ResidualType;
 
  239    using ParentType::ParentType;
 
  262    bool apply(Variables& vars)
 override 
  265        for (std::size_t i = 0; i <= maxLambdaDivisions_; ++i)
 
  273            else if (!converged && i < maxLambdaDivisions_)
 
  276                    std::cout << Fmt::format(
"LevenbergMarquardt solver did not converge with λ = {:.2e}. ", 
ParentType::assembler().lambda())
 
  288                    std::cout << Fmt::format(
"Choose best solution so far with a MSE of {:.4e}", minResidual_) << std::endl;
 
 
  298    void newtonEndStep(Variables &vars, 
const SolutionVector &uLastIter)
 override 
  339            bestSol_ = uLastIter;
 
 
  344                           const SolutionVector& uLastIter,
 
  345                           const ResidualVector& deltaU)
 override 
  348        auto uCurrentIter = uLastIter;
 
  352            Backend::axpy(-alpha_, deltaU, uCurrentIter);
 
  368            uCurrentIter = uLastIter;
 
 
  372    Scalar minResidual_ = std::numeric_limits<Scalar>::max();
 
  373    SolutionVector bestSol_;
 
  374    std::size_t maxLambdaDivisions_ = 10;
 
 
  378#if HAVE_SUITESPARSE_CHOLMOD 
  379template<
class T, 
class F>
 
  380class NonlinearLeastSquaresSolver : 
public Solver<typename Optimization::Detail::Assembler<T, F>::Variables>
 
  382    using Assembler = Optimization::Detail::Assembler<T, F>;
 
  383    using LinearSolver = Optimization::Detail::CholmodLinearSolver<typename Assembler::JacobianMatrix, typename Assembler::ResidualType>;
 
  386    using Variables = 
typename Assembler::Variables;
 
  388    NonlinearLeastSquaresSolver(
const F& f, 
const Dune::BlockVector<T>& x0, std::size_t size)
 
  389    : solver_(std::make_unique<Optimizer>(std::make_shared<Assembler>(f, x0, size), std::make_shared<
LinearSolver>(), 2))
 
  392    bool apply(Variables& vars)
 override 
  393    { 
return solver_->apply(vars); }
 
  396    std::unique_ptr<Optimizer> solver_;
 
 
  404#if HAVE_SUITESPARSE_CHOLMOD 
  416template<
class T, 
class F>
 
  417auto makeNonlinearLeastSquaresSolver(
const F& f, 
const Dune::BlockVector<T>& x0, std::size_t size)
 
  418-> std::unique_ptr<Solver<Dune::BlockVector<T>>>
 
  419{ 
return std::make_unique<Optimization::Detail::NonlinearLeastSquaresSolver<T, F>>(f, x0, size); }
 
Base class for linear solvers.
Definition solver.hh:27
An implementation of a Newton solver. The comprehensive documentation is in Newton solver,...
Definition nonlinear/newtonsolver.hh:183
const std::string & paramGroup() const
Definition nonlinear/newtonsolver.hh:822
Scalar reduction_
Definition nonlinear/newtonsolver.hh:891
int numSteps_
Definition nonlinear/newtonsolver.hh:888
int verbosity() const
Definition nonlinear/newtonsolver.hh:804
virtual void newtonEndStep(Variables &vars, const SolutionVector &uLastIter)
Definition nonlinear/newtonsolver.hh:609
virtual void solutionChanged_(Variables &vars, const SolutionVector &uCurrentIter)
Definition nonlinear/newtonsolver.hh:856
bool apply(Variables &vars) override
Definition nonlinear/newtonsolver.hh:378
Scalar initialResidual_
Definition nonlinear/newtonsolver.hh:894
Scalar lastReduction_
Definition nonlinear/newtonsolver.hh:893
void setUseLineSearch(bool val=true)
Definition nonlinear/newtonsolver.hh:810
std::ostringstream endIterMsgStream_
Definition nonlinear/newtonsolver.hh:901
VariablesBackend< typename ParentType::Variables > Backend
Definition nonlinear/newtonsolver.hh:187
void setMaxRelativeShift(Scalar tolerance)
Definition nonlinear/newtonsolver.hh:249
Scalar residualNorm_
Definition nonlinear/newtonsolver.hh:892
A nonlinear least squares solver with  model parameters and  observations.
Definition leastsquares.hh:231
bool apply(Variables &vars) override
Solve the nonlinear least squares problem.
Definition leastsquares.hh:262
LevenbergMarquardt(std::shared_ptr< Assembler > assembler, std::shared_ptr< LinearSolver > linearSolver, int verbosity=0)
Definition leastsquares.hh:241
void lineSearchUpdate_(Variables &vars, const SolutionVector &uLastIter, const ResidualVector &deltaU) override
Definition leastsquares.hh:343
void newtonEndStep(Variables &vars, const SolutionVector &uLastIter) override
Definition leastsquares.hh:298
a solver base class
Definition leastsquares.hh:37
virtual ~Solver()=default
virtual bool apply(Variables &vars)=0
const LinearSolver & linearSolver() const
Definition common/pdesolver.hh:133
const Assembler & assembler() const
Definition common/pdesolver.hh:121
Some exceptions thrown in DuMux
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:149
Definition leastsquares.hh:220
Definition leastsquares.hh:32
Reference implementation of a Newton solver.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.