MFEM v2.0
pcgsolver.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 <fstream>
00014 #include <iomanip>
00015 #include <math.h>
00016 #include "vector.hpp"
00017 #include "matrix.hpp"
00018 #include "sparsemat.hpp"
00019 
00020 // Preconditined conjugate gradient
00021 
00022 void PCG ( const Operator &A, const Operator &B,
00023            const Vector &b, Vector &x,
00024            int print_iter=0, int max_num_iter=1000,
00025            double RTOLERANCE=10e-12, double ATOLERANCE=10e-24,
00026            int save = 0)
00027 {
00028    int i, dim = x.Size();
00029    double r0, den, nom, nom0, betanom, alpha, beta;
00030    Vector r(dim), d(dim), z(dim);
00031 
00032    A.Mult(x, r);                               //    r = A x
00033    subtract(b, r, r);                          //    r = b  - r
00034    B.Mult(r, z);                               //    z = B r
00035    d = z;
00036    nom0 = nom = z * r;
00037 
00038    if (print_iter == 1)
00039       cout << "   Iteration : " << setw(3) << 0 << "  (B r, r) = "
00040            << nom << endl;
00041 
00042    if ( (r0 = nom * RTOLERANCE) < ATOLERANCE) r0 = ATOLERANCE;
00043    if (nom < r0)
00044       return;
00045 
00046    A.Mult(d, z);
00047    den = z * d;
00048 
00049    if (den < 0.0)
00050    {
00051       cout << "Negative denominator in step 0 of PCG: ";
00052       cout << den << endl;
00053       //    return;
00054    }
00055 
00056    if (den == 0.0)
00057       return;
00058 
00059    // start iteration
00060    for (i = 1; i <= max_num_iter; i++)
00061    {
00062       if (save)
00063          if (i % save == 0)
00064          {
00065             cout << "saving the solution vector on iteration " << i << endl;
00066             ofstream out("pcg.x");
00067             x.Print(out, 1);
00068          }
00069 
00070       alpha = nom/den;
00071       add(x, alpha, d, x);                  //  x = x + alpha d
00072       add(r,-alpha, z, r);                  //  r = r - alpha z
00073 
00074       B.Mult(r, z);                         //  z = B r
00075       betanom = r * z;
00076 
00077       if (print_iter == 1)
00078          cout << "   Iteration : " << setw(3) << i << "  (B r, r) = "
00079               << betanom << endl;
00080 
00081       if (betanom < r0)
00082       {
00083          if (print_iter == 2)
00084             cout << "Number of PCG iterations: " << i << endl;
00085          else
00086             if (print_iter == 3)
00087                cout << "(B r_0, r_0) = " << nom0 << endl
00088                     << "(B r_N, r_N) = " << betanom << endl
00089                     << "Number of PCG iterations: " << i << endl;
00090          break;
00091       }
00092 
00093       beta = betanom/nom;
00094       add(z, beta, d, d);                   //  d = z + beta d
00095       A.Mult(d, z);
00096       den = d * z;
00097       nom = betanom;
00098    }
00099    if (i > max_num_iter)
00100    {
00101       cerr << "PCG: No convergence!" << endl;
00102       cout << "(B r_0, r_0) = " << nom0 << endl
00103            << "(B r_N, r_N) = " << betanom << endl
00104            << "Number of PCG iterations: " << (i-1) << endl;
00105    }
00106    if (print_iter >= 1 || i > max_num_iter)
00107    {
00108       if (i > max_num_iter)  i--;
00109       cout << "Average reduction factor = "
00110            << pow (betanom/nom0, 0.5/i) << endl;
00111    }
00112 }
00113 
00114 // Preconditioned stationary linear iteration
00115 void SLI (const Operator &A, const Operator &B,
00116           const Vector &b, Vector &x,
00117           int print_iter=0, int max_num_iter=1000,
00118           double RTOLERANCE=10e-12, double ATOLERANCE=10e-24)
00119 {
00120    int i, dim = x.Size();
00121    double r0, nom, nomold = 1, nom0, cf;
00122    Vector r(dim),  z(dim);
00123 
00124    r0 = -1.0;
00125 
00126    for(i = 1; i < max_num_iter ; i++) {
00127       A.Mult(x, r);         //    r = A x
00128       subtract(b, r, r);    //    r = b  - A x
00129       B.Mult(r, z);         //    z = B r
00130 
00131       nom = z * r;
00132 
00133       if (r0 == -1.0) {
00134          nom0 = nom;
00135          r0 = nom * RTOLERANCE;
00136          if (r0 < ATOLERANCE) r0 = ATOLERANCE;
00137       }
00138 
00139       cf = sqrt(nom/nomold);
00140       if (print_iter == 1) {
00141          cout << "   Iteration : " << setw(3) << i << "  (B r, r) = "
00142               << nom;
00143          if (i > 1)
00144             cout << "\tConv. rate: " << cf;
00145          cout << endl;
00146       }
00147       nomold = nom;
00148 
00149       if (nom < r0) {
00150          if (print_iter == 2)
00151             cout << "Number of iterations: " << i << endl
00152                  << "Conv. rate: " << cf << endl;
00153          else
00154             if (print_iter == 3)
00155                cout << "(B r_0, r_0) = " << nom0 << endl
00156                     << "(B r_N, r_N) = " << nom << endl
00157                     << "Number of iterations: " << i << endl;
00158          break;
00159       }
00160 
00161       add(x, 1.0, z, x);  //  x = x + B (b - A x)
00162    }
00163 
00164    if (i == max_num_iter)
00165    {
00166       cerr << "No convergence!" << endl;
00167       cout << "(B r_0, r_0) = " << nom0 << endl
00168            << "(B r_N, r_N) = " << nom << endl
00169            << "Number of iterations: " << i << endl;
00170    }
00171 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines