// Copyright (C) 2003-2009 Marc Duruflé
//
// This file is part of the linear-algebra library Seldon,
// http://seldon.sourceforge.net/.
//
// Seldon is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2.1 of the License, or (at your option)
// any later version.
//
// Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
// more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Seldon. If not, see http://www.gnu.org/licenses/.


#ifndef SELDON_FILE_ITERATIVE_CXX

#include <vector>

// headers of class Iteration and Preconditioner_Base
#include "Iterative.hxx"

// and all iterative solvers
#include "Cg.cxx"
#include "Cgne.cxx"
#include "Lsqr.cxx"
#include "Cgs.cxx"
#include "BiCg.cxx"
#include "BiCgStab.cxx"
#include "BiCgStabl.cxx"
#include "BiCgcr.cxx"
#include "Gcr.cxx"
#include "CoCg.cxx"
#include "Gmres.cxx"
#include "MinRes.cxx"
#include "Qmr.cxx"
#include "QmrSym.cxx"
#include "QCgs.cxx"
#include "TfQmr.cxx"
#include "Symmlq.cxx"


namespace Seldon
{
 
 
//! Default constructor
 
Preconditioner_Base::Preconditioner_Base()
 
{
 
}
 
 
 
//! Solves M z = r
 
/*!
    Identity preconditioner M = I
  */

 
template<class Matrix1, class Vector1>
 
void Preconditioner_Base::Solve(const Matrix1& A, const Vector1& r,
                                 
Vector1& z)
 
{
   
Copy(r,z);
 
}
 
 
 
//! Solves M^t z = r
 
/*!
    Identity preconditioner M = I
  */

 
template<class Matrix1, class Vector1>
 
void Preconditioner_Base::
 
TransSolve(const Matrix1& A, const Vector1 & r, Vector1 & z)
 
{
   
Solve(A, r, z);
 
}
 
 
 
//! Default constructor
 
template<class Titer>
 
Iteration<Titer>::Iteration()
 
{
    tolerance
= 1e-6;
    max_iter
= 100;
    nb_iter
= 0;
    error_code
= 0;
    fail_convergence
= false;
    print_level
= 1;
    init_guess_null
= true;
    type_solver
= 0; parameter_restart = 10;
    type_preconditioning
= 0;
 
}
 
 
 
//! Constructor with maximum number of iterations and stopping criterion
 
template<class Titer>
 
Iteration<Titer>::Iteration(int max_iteration, const Titer& tol)
 
{
    max_iter
= max_iteration;
    tolerance
= tol;
    nb_iter
= 0;
    error_code
= 0;
    fail_convergence
= false;
    print_level
= 1;
    init_guess_null
= true;
    type_solver
= 0; parameter_restart = 10;
    type_preconditioning
= 0;
 
}
 

 
//! Copy constructor
 
template<class Titer>
 
Iteration<Titer>::Iteration(const Iteration<Titer>& outer)
 
{
    tolerance
= outer.tolerance; facteur_reste = outer.facteur_reste;
    max_iter
= outer.max_iter;
    nb_iter
= 0;
    print_level
= outer.print_level; error_code = outer.error_code;
    init_guess_null
= true;
    type_solver
= outer.type_solver;
    parameter_restart
= outer.parameter_restart;
    type_preconditioning
= outer.type_preconditioning;
 
}
 
 
 
//! Returns the type of solver
 
template<class Titer>
 
int Iteration<Titer>::GetTypeSolver() const
 
{
   
return type_solver;
 
}
 
 
 
//! Returns the restart parameter
 
template<class Titer>
 
int Iteration<Titer>::GetRestart() const
 
{
   
return parameter_restart;
 
}
 
 
 
//! Returns used coefficient to compute relative residual
 
template<class Titer>
 
Titer Iteration<Titer>::GetFactor() const
 
{
   
return facteur_reste;
 
}
 
 
 
//! Returns stopping criterion
 
template<class Titer>
 
Titer Iteration<Titer>::GetTolerance() const
 
{
   
return tolerance;
 
}
 
 
 
//! Returns the number of iterations
 
template<class Titer>
 
int Iteration<Titer>::GetNumberIteration() const
 
{
   
return nb_iter;
 
}
 
 
 
//! Changes the type of solver and preconditioning
 
template<class Titer>
 
void Iteration<Titer>::SetSolver(int type_resolution,
                                   
int param_restart, int type_prec)
 
{
    type_solver
= type_resolution;
    parameter_restart
= param_restart;
    type_preconditioning
= type_prec;
 
}
 
 
 
//! Changes the restart parameter
 
template<class Titer>
 
void Iteration<Titer>::SetRestart(int m)
 
{
    parameter_restart
= m;
 
}
 
 
 
//! Changes the stopping criterion
 
template<class Titer>
 
void Iteration<Titer>::SetTolerance(Titer stopping_criterion)
 
{
    tolerance
= stopping_criterion;
 
}
 
 
 
//! Changes the maximum number of iterations
 
template<class Titer>
 
void Iteration<Titer>::SetMaxNumberIteration(int max_iteration)
 
{
    max_iter
=max_iteration;
 
}

 
 
//! Changes the number of iterations
 
template<class Titer>
 
void Iteration<Titer>::SetNumberIteration(int nb)
 
{
    nb_iter
= nb;
 
}
 
 
 
//! Sets to a normal display (residual each 100 iterations)
 
template<class Titer>
 
void Iteration<Titer>::ShowMessages()
 
{
    print_level
= 1;
 
}
 
 
 
//! Sets to a complete display (residual each iteration)
 
template<class Titer>
 
void Iteration<Titer>::ShowFullHistory()
 
{
    print_level
= 6;
 
}
 
 
 
//! Doesn't display any information
 
template<class Titer>
 
void Iteration<Titer>::HideMessages()
 
{
    print_level
= 0;
 
}
 
 
 
//! Initialization with the right hand side
 
template<class Titer> template<class Vector1>
 
int Iteration<Titer>::Init(const Vector1& r)
 
{
   
Titer norme_rhs = Titer(Norm2(r));
   
// test of a null right hand side
   
if (norme_rhs == Titer(0))
     
return -1;
   
   
// coefficient used later to compute relative residual
    facteur_reste
= Titer(1)/norme_rhs;
   
   
// initialization of iterations
    nb_iter
= 0;
   
return 0; // successful initialization
 
}
 
 
 
//! Returns true if it is the first iteration
 
template<class Titer>
 
inline bool Iteration<Titer>::First() const
 
{
   
if (nb_iter == 0)
     
return true;
   
   
return false;
 
}
 
 
 
//! Returns true if the initial guess is null
 
template<class Titer>
 
inline bool Iteration<Titer>::IsInitGuess_Null() const
 
{
   
return init_guess_null;
 
}
 
 
 
//! Returns true if the iterative solver has reached its end
 
template<class Titer> template<class Vector1>
 
inline bool Iteration<Titer>::
 
Finished(const Vector1& r) const
 
{
   
// absolute residual
   
Titer reste = Norm2(r);
   
// computation of relative residual
    reste
= facteur_reste*reste;
   
   
// displaying residual if required
   
if ((print_level >= 1)&&(nb_iter%100 == 0))
      cout
<<"Residu at iteration number "<<
       
GetNumberIteration()<<"  "<<reste<<endl;
   
else if (print_level >= 6)
      cout
<<"Residu at iteration number "<<
       
GetNumberIteration()<<"  "<<reste<<endl;
   
   
// end of iterative solver when residual is small enough
   
// or when the number of iterations is too high
   
if ((reste < tolerance)||(nb_iter >= max_iter))
     
return true;
   
   
return false;
 
}
 
 
 
//! Returns true if the iterative solver has reached its end
 
template<class Titer>
 
inline bool Iteration<Titer>::Finished(const Titer& r) const
 
{
   
// relative residual
   
Titer reste = facteur_reste*r;
   
   
// displaying residual if required
   
if ((print_level >= 1)&&(nb_iter%100 == 0))
      cout
<<"Residu at iteration number "<<
       
GetNumberIteration()<<"  "<<reste<<endl;
   
else if (print_level >= 6)
      cout
<<"Residu at iteration number "<<
       
GetNumberIteration()<<"  "<<reste<<endl;
   
   
// end of iterative solver when residual is small enough
   
// or when the number of iterations is too high
   
if ((reste < tolerance)||(nb_iter >= max_iter))
     
return true;
   
   
return false;
 
}
 
 
 
//! Informs of a failure in the iterative solver
 
template<class Titer>
 
void Iteration<Titer>::Fail(int i, const string& s)
 
{
    fail_convergence
= true;
    error_code
= i;
   
// displays information if required
   
if ((print_level >= 1)&&(nb_iter%100==0))
      cout
<<"Error during resolution : "<<s<<endl;
 
}
 
 
 
//! Increment the number of iterations
 
template<class Titer>
 
inline Iteration<Titer>& Iteration<Titer>::operator ++ (void)
 
{
   
++nb_iter;
   
return *this;
 
}
 
 
 
//! Returns the error code (if an error occured)
 
template<class Titer>
 
int Iteration<Titer>::ErrorCode() const
 
{
   
if (nb_iter >= max_iter)
     
return -2;
   
   
if (fail_convergence)
     
return error_code;
   
   
return 0;
 
}
 
} // end namespace

#define SELDON_FILE_ITERATIVE_CXX
#endif