From 4f66a8f2e3dba3e431e3efadec356ada77fc680d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= <klinkjak@fjfi.cvut.cz>
Date: Mon, 22 Feb 2016 21:33:44 +0100
Subject: [PATCH] Adding preconditioner support into the TFQMR solver.

---
 src/solvers/linear/krylov/tnlTFQMRSolver.h    |  4 +-
 .../linear/krylov/tnlTFQMRSolver_impl.h       | 64 +++++++++++++------
 2 files changed, 49 insertions(+), 19 deletions(-)

diff --git a/src/solvers/linear/krylov/tnlTFQMRSolver.h b/src/solvers/linear/krylov/tnlTFQMRSolver.h
index ab25f3e349..32d250f52a 100644
--- a/src/solvers/linear/krylov/tnlTFQMRSolver.h
+++ b/src/solvers/linear/krylov/tnlTFQMRSolver.h
@@ -75,7 +75,9 @@ class tnlTFQMRSolver : public tnlObject,
 
    bool setSize( IndexType size );
 
-   tnlVector< RealType, Device, IndexType >  d, r, w, u, v, r_ast, Au;
+   tnlVector< RealType, Device, IndexType >  d, r, w, u, v, r_ast, Au, M_tmp;
+
+   IndexType size;
 
    const MatrixType* matrix;
    const PreconditionerType* preconditioner;
diff --git a/src/solvers/linear/krylov/tnlTFQMRSolver_impl.h b/src/solvers/linear/krylov/tnlTFQMRSolver_impl.h
index b5e72e6456..5ddb54a5ec 100644
--- a/src/solvers/linear/krylov/tnlTFQMRSolver_impl.h
+++ b/src/solvers/linear/krylov/tnlTFQMRSolver_impl.h
@@ -18,17 +18,12 @@
 #ifndef tnlTFQMRSolver_implH
 #define tnlTFQMRSolver_implH
 
-template< typename RealType,
-          typename Vector >
-RealType computeTFQMRNewP( Vector& p,
-                           const Vector&r,
-                           const RealType& beta,
-                           const RealType& omega,
-                           const Vector& Ap );
-
 template< typename Matrix,
           typename Preconditioner >
 tnlTFQMRSolver< Matrix, Preconditioner > :: tnlTFQMRSolver()
+: size( 0 ),
+  matrix( 0 ),
+  preconditioner( 0 )
 {
 }
 
@@ -83,15 +78,29 @@ bool tnlTFQMRSolver< Matrix, Preconditioner > :: solve( const Vector& b, Vector&
    dbgFunctionName( "tnlTFQMRSolver", "Solve" );
    if( ! this -> setSize( matrix -> getRows() ) ) return false;
 
-   RealType tau, theta, eta, rho, alpha, w_norm;
-   RealType b_norm = b. lpNorm( 2.0 );
-   if( b_norm == 0.0 )
-       b_norm = 1.0;
+   RealType tau, theta, eta, rho, alpha, b_norm, w_norm;
 
-   this -> matrix -> vectorProduct( x, r );
-   r. addVector( b, 1.0, -1.0 );
+   if( preconditioner ) {
+      preconditioner -> solve( b, M_tmp );
+      b_norm = M_tmp. lpNorm( ( RealType ) 2.0 );
+
+      matrix -> vectorProduct( x, M_tmp );
+      M_tmp.addVector( b, 1.0, -1.0 );
+      preconditioner -> solve( M_tmp, r );
+   }
+   else {
+      b_norm = b. lpNorm( 2.0 );
+      matrix -> vectorProduct( x, r );
+      r.addVector( b, 1.0, -1.0 );
+   }
    w = u = r;
-   matrix -> vectorProduct( u, Au );
+   if( preconditioner ) {
+      matrix -> vectorProduct( u, M_tmp );
+      preconditioner -> solve( M_tmp, Au );
+   }
+   else {
+      matrix -> vectorProduct( u, Au );
+   }
    v = Au;
    d. setValue( 0.0 );
    tau = r. lpNorm( 2.0 );
@@ -101,6 +110,9 @@ bool tnlTFQMRSolver< Matrix, Preconditioner > :: solve( const Vector& b, Vector&
    // only to avoid compiler warning; alpha is initialized inside the loop
    alpha = 0.0;
 
+   if( b_norm == 0.0 )
+       b_norm = 1.0;
+
    this->resetIterations();
    this->setResidue( tau / b_norm );
 
@@ -114,7 +126,13 @@ bool tnlTFQMRSolver< Matrix, Preconditioner > :: solve( const Vector& b, Vector&
       else {
          // not necessary in odd iter since the previous iteration
          // already computed v_{m+1} = A*u_{m+1}
-         matrix -> vectorProduct( u, Au );
+         if( preconditioner ) {
+            matrix -> vectorProduct( u, M_tmp );
+            preconditioner -> solve( M_tmp, Au );
+         }
+         else {
+            matrix -> vectorProduct( u, Au );
+         }
       }
       w.addVector( Au, -alpha );
       d.addVector( u, 1.0, theta * theta * eta / alpha );
@@ -137,7 +155,13 @@ bool tnlTFQMRSolver< Matrix, Preconditioner > :: solve( const Vector& b, Vector&
 
          u.addVector( w, 1.0, beta );
          v.addVector( Au, beta, beta * beta );
-         matrix -> vectorProduct( u, Au );
+         if( preconditioner ) {
+            matrix -> vectorProduct( u, M_tmp );
+            preconditioner -> solve( M_tmp, Au );
+         }
+         else {
+            matrix -> vectorProduct( u, Au );
+         }
          v.addVector( Au, 1.0 );
       }
       else {
@@ -165,13 +189,17 @@ template< typename Matrix,
           typename Preconditioner >
 bool tnlTFQMRSolver< Matrix, Preconditioner > :: setSize( IndexType size )
 {
+   if( this->size == size )
+      return true;
+   this->size = size;
    if( ! d. setSize( size ) ||
        ! r. setSize( size ) ||
        ! w. setSize( size ) ||
        ! u. setSize( size ) ||
        ! v. setSize( size ) ||
        ! r_ast. setSize( size ) ||
-       ! Au. setSize( size ) )
+       ! Au. setSize( size ) ||
+       ! M_tmp. setSize( size ) )
    {
       cerr << "I am not able to allocate all supporting vectors for the TFQMR solver." << endl;
       return false;
-- 
GitLab