From 6fafe8bc8541ffeaebfadf1b2a0567c4725f2d1a Mon Sep 17 00:00:00 2001
From: Christoph Lehmann <christoph.lehmann@ufz.de>
Date: Wed, 17 Feb 2016 17:32:31 +0100
Subject: [PATCH] [NL] comments from code review

---
 NumLib/ODESolver/MatrixTranslator.h         |  1 +
 NumLib/ODESolver/NonlinearSolver-impl.h     | 17 +++++++++++-----
 NumLib/ODESolver/NonlinearSolver.h          |  9 +++++----
 NumLib/ODESolver/NonlinearSystem.h          |  8 +++++++-
 NumLib/ODESolver/ODESystem.h                |  5 +++--
 NumLib/ODESolver/TimeDiscretization.h       | 22 +++++++++++++--------
 NumLib/ODESolver/TimeDiscretizedODESystem.h |  6 ------
 NumLib/ODESolver/TimeLoop.h                 |  3 +++
 8 files changed, 45 insertions(+), 26 deletions(-)

diff --git a/NumLib/ODESolver/MatrixTranslator.h b/NumLib/ODESolver/MatrixTranslator.h
index dc0162c6e20..8ab72fbe636 100644
--- a/NumLib/ODESolver/MatrixTranslator.h
+++ b/NumLib/ODESolver/MatrixTranslator.h
@@ -64,6 +64,7 @@ public:
     //! Computes the Jacobian of the residual and writes it to \c Jac_out.
     virtual void getJacobian(Matrix const& Jac_in, Matrix& Jac_out) const = 0;
 
+    // TODO check (void)
     /*! Allows to store the given matrices internally for later use.
      *
      * \remark
diff --git a/NumLib/ODESolver/NonlinearSolver-impl.h b/NumLib/ODESolver/NonlinearSolver-impl.h
index 5fc9b8ed11a..8cf2e92032e 100644
--- a/NumLib/ODESolver/NonlinearSolver-impl.h
+++ b/NumLib/ODESolver/NonlinearSolver-impl.h
@@ -43,12 +43,15 @@ solve(NonlinearSystem<Matrix, Vector, NonlinearSolverTag::Picard> &sys, Vector &
 
     bool success = false;
 
+    BLAS::copy(x, _x_new); // set initial guess, TODO save the copy
+
     for (unsigned iteration=1; iteration<_maxiter; ++iteration)
     {
-        sys.assembleMatricesPicard(x);
+        sys.assembleMatricesPicard(_x_new);
         sys.getA(_A);
         sys.getRhs(_rhs);
-        // TODO _x_new might not have been initialized
+
+        // Here _x_new has to be used and it has to be equal to x!
         sys.applyKnownComponentsPicard(_A, _rhs, _x_new);
 
         // std::cout << "A:\n" << Eigen::MatrixXd(A) << "\n";
@@ -56,12 +59,11 @@ solve(NonlinearSystem<Matrix, Vector, NonlinearSolverTag::Picard> &sys, Vector &
 
         oneShotLinearSolve(_A, _rhs, _x_new);
 
+        // x is used as delta_x in order to compute the error.
         BLAS::aypx(x, -1.0, _x_new); // x = _x_new - x
         auto const error = norm(x);
         // INFO("  picard iteration %u error: %e", iteration, error);
 
-        x = _x_new;
-
         if (error < _tol) {
             success = true;
             break;
@@ -74,6 +76,8 @@ solve(NonlinearSystem<Matrix, Vector, NonlinearSolverTag::Picard> &sys, Vector &
         }
     }
 
+    x = _x_new; // always set to what we computed last
+
     return success;
 }
 
@@ -96,6 +100,8 @@ solve(NonlinearSystem<Matrix, Vector, NonlinearSolverTag::Newton> &sys, Vector &
 
     bool success = false;
 
+    // TODO init _minus_delta_x to right size and 0.0
+
     for (unsigned iteration=1; iteration<_maxiter; ++iteration)
     {
         sys.assembleResidualNewton(x);
@@ -103,6 +109,7 @@ solve(NonlinearSystem<Matrix, Vector, NonlinearSolverTag::Newton> &sys, Vector &
 
         // std::cout << "  res:\n" << res << std::endl;
 
+        // TODO streamline the, make consistent with Picard.
         if (norm(_res) < _tol) {
             success = true;
             break;
@@ -120,7 +127,7 @@ solve(NonlinearSystem<Matrix, Vector, NonlinearSolverTag::Newton> &sys, Vector &
         // auto const dx_norm = _minus_delta_x.norm();
         // INFO("  newton iteration %u, norm of delta x: %e", iteration, dx_norm);
 
-        BLAS::axpy(x, -1.0, _minus_delta_x);
+        BLAS::axpy(x, -_alpha, _minus_delta_x);
 
         if (sys.isLinear()) {
             // INFO("  newton linear system. not looping");
diff --git a/NumLib/ODESolver/NonlinearSolver.h b/NumLib/ODESolver/NonlinearSolver.h
index 02f1ca009d9..896e8d44107 100644
--- a/NumLib/ODESolver/NonlinearSolver.h
+++ b/NumLib/ODESolver/NonlinearSolver.h
@@ -80,10 +80,11 @@ private:
     const double _tol;       //!< tolerance of the solver
     const unsigned _maxiter; //!< maximum number of iterations
 
-    Vector _res;           //!< The residual.
-    Matrix _J;             //!< The Jacobian of the residual.
-    Vector _minus_delta_x; //!< The Newton-Raphson method solves the linearized equation
-                           //!< \f$ J \cdot (-\Delta x) = r \f$ repeatedly.
+    Vector _res;             //!< The residual.
+    Matrix _J;               //!< The Jacobian of the residual.
+    Vector _minus_delta_x;   //!< The Newton-Raphson method solves the linearized equation
+                             //!< \f$ J \cdot (-\Delta x) = r \f$ repeatedly.
+    double const _alpha = 1; //!< damping factor
 };
 
 
diff --git a/NumLib/ODESolver/NonlinearSystem.h b/NumLib/ODESolver/NonlinearSystem.h
index 5af8a865616..c61847442d3 100644
--- a/NumLib/ODESolver/NonlinearSystem.h
+++ b/NumLib/ODESolver/NonlinearSystem.h
@@ -62,6 +62,7 @@ public:
      */
     virtual void getJacobian(Matrix& Jac) const = 0;
 
+    // TODO solutions
     //! Apply known solutions to the linearized equation system
     //! \f$ \mathit{Jac} \cdot (-\Delta x) = \mathit{res} \f$.
     virtual void applyKnownComponentsNewton(
@@ -76,10 +77,12 @@ public:
      */
     virtual bool isLinear() const = 0;
 
+    // TODO add getNumEquations()
+
     virtual ~NonlinearSystem() = default;
 };
 
-
+// TODO common base class
 /*! A System of nonlinear equations to be solved with the Picard fixpoint
  *  iteration method.
  *
@@ -102,6 +105,7 @@ public:
     //! Writes the linearized equation system right-hand side to \c rhs.
     virtual void getRhs(Vector& rhs) const = 0;
 
+    // TODO components
     //! Apply known solutions to the linearized equation system
     //! \f$ A \cdot x = \mathit{rhs} \f$.
     virtual void applyKnownComponentsPicard(
@@ -116,6 +120,8 @@ public:
      */
     virtual bool isLinear() const = 0;
 
+    // TODO add getNumEquations()
+
     virtual ~NonlinearSystem() = default;
 };
 
diff --git a/NumLib/ODESolver/ODESystem.h b/NumLib/ODESolver/ODESystem.h
index 37db8a9d30e..9c457754006 100644
--- a/NumLib/ODESolver/ODESystem.h
+++ b/NumLib/ODESolver/ODESystem.h
@@ -73,7 +73,7 @@ public:
 
     using Index = typename MatrixTraits<Matrix>::Index;
 
-    // TODO doc
+    // TODO solutions
     virtual std::vector<ProcessLib::DirichletBc<Index> > const* getKnownComponents() const
     {
         return nullptr; // by default there are no known components
@@ -85,7 +85,8 @@ public:
 
 /*! Interface for a first-order implicit quasi-linear ODE.
  *
- * ODEs using this interface also provide a Jacobian.
+ * ODEs using this interface also provide a Jacobian in addition
+ * to the functionality of the Picard-related interface.
  */
 template<typename Matrix, typename Vector>
 class ODESystem<Matrix, Vector,
diff --git a/NumLib/ODESolver/TimeDiscretization.h b/NumLib/ODESolver/TimeDiscretization.h
index 45efa40c52b..05721c62aa8 100644
--- a/NumLib/ODESolver/TimeDiscretization.h
+++ b/NumLib/ODESolver/TimeDiscretization.h
@@ -153,17 +153,18 @@ public:
 
         auto const dxdot_dx = getCurrentXWeight();
 
+        // xdot = dxdot_dx * x_at_new_timestep - x_old
         getWeightedOldX(xdot);
-        BLAS::axpby(xdot, dxdot_dx, -1.0, x_at_new_timestep);
+        BLAS::axpby(xdot, dxdot_dx, -1.0, x_at_new_timestep); // TODO consistent
     }
 
     //! Returns \f$ \alpha = \partial \hat x / \partial x_C \f$.
-    virtual double getCurrentXWeight() const = 0;
+    virtual double getCurrentXWeight() const = 0;  // TODO maybe getNewXWeight
 
     //! Returns \f$ x_O \f$.
     virtual void getWeightedOldX(Vector& y) const = 0; // = x_old
 
-    ~TimeDiscretization() = default;
+    virtual ~TimeDiscretization() = default; // TODO virtual needed?
 
     //! \name Extended Interface
     //! These methods are provided primarily to make certain concrete time discretizations
@@ -212,9 +213,8 @@ public:
         _x_old = x0;
     }
 
-    void pushState(const double t, Vector const& x, InternalMatrixStorage const&) override
+    void pushState(const double /*t*/, Vector const& x, InternalMatrixStorage const&) override
     {
-        (void) t;
         _x_old = x;
     }
 
@@ -234,6 +234,8 @@ public:
     void getWeightedOldX(Vector& y) const override
     {
         namespace BLAS = MathLib::BLAS;
+
+        // y = x_old / delta_t
         BLAS::copy(_x_old, y);
         BLAS::scale(y, 1.0/_delta_t);
     }
@@ -256,9 +258,8 @@ public:
         _x_old = x0;
     }
 
-    void pushState(const double t, Vector const& x, InternalMatrixStorage const&) override
+    void pushState(const double /*t*/, Vector const& x, InternalMatrixStorage const&) override
     {
-        (void) t;
         _x_old = x;
     }
 
@@ -283,6 +284,8 @@ public:
     void getWeightedOldX(Vector& y) const override
     {
         namespace BLAS = MathLib::BLAS;
+
+        // y = x_old / delta_t
         BLAS::copy(_x_old, y);
         BLAS::scale(y, 1.0/_delta_t);
     }
@@ -351,6 +354,8 @@ public:
     void getWeightedOldX(Vector& y) const override
     {
         namespace BLAS = MathLib::BLAS;
+
+        // y = x_old / delta_t
         BLAS::copy(_x_old, y);
         BLAS::scale(y, 1.0/_delta_t);
     }
@@ -384,7 +389,7 @@ const double BDF_Coeffs[6][7] = {
     {   1.5,         2.0, -0.5 },
     {  11.0 /  6.0,  3.0, -1.5,  1.0 / 3.0 },
     {  25.0 / 12.0,  4.0, -3.0,  4.0 / 3.0, -0.25 },
-    { 137.0 / 60.0,  5.0, -5.0, 10.0 / 3.0, -1.25,  0.2 },
+    { 137.0 / 60.0,  5.0, -5.0, 10.0 / 3.0, -1.25,  0.2 }, // TODO change to rational numbers
     { 147.0 / 60.0,  6.0, -7.5, 20.0 / 3.0, -3.75,  1.2, -1.0/6.0 }
     // coefficient of (for BDF(6), the oldest state, x_n, is always rightmost)
     //        x_+6, x_+5, x_+4,       x_+3,  x_+2, x_+1,     x_n
@@ -424,6 +429,7 @@ public:
     void pushState(const double t, Vector const& x, InternalMatrixStorage const&) override
     {
         (void) t;
+        // TODO use boost cirular buffer?
 
         // until _xs_old is filled, lower-order BDF formulas are used.
         if (_xs_old.size() < _num_steps) {
diff --git a/NumLib/ODESolver/TimeDiscretizedODESystem.h b/NumLib/ODESolver/TimeDiscretizedODESystem.h
index 42be649191c..ef7f70b8653 100644
--- a/NumLib/ODESolver/TimeDiscretizedODESystem.h
+++ b/NumLib/ODESolver/TimeDiscretizedODESystem.h
@@ -133,12 +133,6 @@ public:
 
     void getResidual(Vector const& x_new_timestep, Vector& res) const override
     {
-        // TODO Maybe the duplicate calculation of xdot here and in assembleJacobian
-        //      can be optimuized. However, that would make the interface a bit more
-        //      fragile.
-        _time_disc.getXdot(x_new_timestep, _xdot);
-
-        // TODO change to calculate
         _mat_trans->getResidual(_M, _K, _b, x_new_timestep, _xdot, res);
     }
 
diff --git a/NumLib/ODESolver/TimeLoop.h b/NumLib/ODESolver/TimeLoop.h
index 699c9d26796..60d0fad9447 100644
--- a/NumLib/ODESolver/TimeLoop.h
+++ b/NumLib/ODESolver/TimeLoop.h
@@ -68,6 +68,7 @@ private:
 
 //! @}
 
+// TODO rename class
 template<typename Matrix, typename Vector, NonlinearSolverTag NLTag>
 template<typename Callback>
 bool
@@ -86,6 +87,7 @@ loop(const double t0, const Vector x0, const double t_end, const double delta_t,
         time_disc.pushState(t0, x0, _ode_sys); // TODO: that might do duplicate work
     }
 
+    // TODO change n*delta_t
     double t;
     unsigned timestep = 0;
     bool nl_slv_succeeded = true;
@@ -99,6 +101,7 @@ loop(const double t0, const Vector x0, const double t_end, const double delta_t,
 
         time_disc.pushState(t, x, _ode_sys);
 
+        // TODO check const ref
         auto const  t_cb = t; // make sure the callback cannot overwrite anything.
         auto const& x_cb = x; // ditto.
         post_timestep(t_cb, x_cb);
-- 
GitLab