MFEM v2.0
|
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 }