MFEM v2.0
cgsolver.cpp
Go to the documentation of this file.
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
00003 // reserved. See file COPYRIGHT for details.
00004 //
00005 // This file is part of the MFEM library. For more information and source code
00006 // availability see http://mfem.googlecode.com.
00007 //
00008 // MFEM is free software; you can redistribute it and/or modify it under the
00009 // terms of the GNU Lesser General Public License (as published by the Free
00010 // Software Foundation) version 2.1 dated February 1999.
00011 
00012 #include <iostream>
00013 #include <iomanip>
00014 #include "vector.hpp"
00015 #include "matrix.hpp"
00016 #include "sparsemat.hpp"
00017 
00018 // Conjugate Gradient solver
00019 
00020 void CG( const Operator &A, const Vector &b, Vector &x,
00021          int print_iter=0, int max_num_iter=1000,
00022          double RTOLERANCE=10e-12, double ATOLERANCE=10e-24){
00023 
00024    int i, dim = x.Size();
00025    double den, nom, nom0, betanom, alpha, beta, r0;
00026    Vector r(dim), d(dim), Ad(dim);
00027 
00028    A.Mult( x, r);
00029    subtract( b, r, r);                         // r = b - A x
00030    d = r;
00031    nom0 = nom = r * r;
00032 
00033    if (print_iter == 1)
00034       cout << "   Iteration : " << setw(3) << 0 << "  (r, r) = "
00035            << nom << endl;
00036 
00037    if ( (r0 = nom * RTOLERANCE) < ATOLERANCE) r0 = ATOLERANCE;
00038    if (nom < r0)
00039       return;
00040 
00041    A.Mult( d, Ad);
00042    den = d * Ad;
00043 
00044 
00045    if (den <= 0.0) {
00046       if (nom0 > 0.0)
00047          cout <<"Operator A is not postive definite. (Ar,r) = "
00048               << den << endl;
00049       return;
00050    }
00051 
00052    // start iteration                          //  d = r, Ad = A r
00053    for(i = 1; i<max_num_iter ;i++) {
00054       alpha= nom/den;                           // alpha = (r_o,r_o)/(Ar_o,r_o)
00055 
00056       add(x, alpha, d, x);                      //   x =   x + alpha * d
00057       add(r, -alpha, Ad, r);                    // r_n = r_o - alpha * Ad
00058       betanom = r*r;                            // betanom = (r_o, r_o)
00059 
00060       if (print_iter == 1)
00061          cout << "   Iteration : " << setw(3) << i << "  (r, r) = "
00062               << betanom << endl;
00063 
00064       if ( betanom < r0) {
00065          if (print_iter == 2)
00066             cout << "Number of CG iterations: " << i << endl;
00067          else
00068             if (print_iter == 3)
00069                cout << "(r_0, r_0) = " << nom0 << endl
00070                     << "(r_N, r_N) = " << betanom << endl
00071                     << "Number of CG iterations: " << i << endl;
00072          break;
00073       }
00074 
00075       beta = betanom/nom;                       // beta = (r_n,r_n)/(r_o,r_o)
00076       add(r, beta, d, d);                       //    d = r_n + beta * d
00077       A.Mult(d, Ad);                            //   Ad = A d
00078       den = d * Ad;                             //  den = (d , A d)
00079       if (den <= 0.0)
00080       {
00081          if (d * d > 0.0)
00082             cout <<"Operator A is not postive definite. (Ad,d) = "
00083                  << den << endl;
00084       }
00085       nom = betanom;                            //  nom = (r_n, r_n)
00086    }
00087    if (i == max_num_iter && print_iter >= 0)
00088    {
00089       cerr << "CG: No convergence!" << endl;
00090       cout << "(r_0, r_0) = " << nom0 << endl
00091            << "(r_N, r_N) = " << betanom << endl
00092            << "Number of CG iterations: " << i << endl;
00093    }
00094 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines