00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef __BICG_H
00035 #define __BICG_H
00036
00037 #include <iostream>
00038 using std::ostream;
00039 using std::endl;
00040
00041 #include <iomanip>
00042 using std::setw;
00043 using std::ios;
00044 using std::setprecision;
00045
00046 #include "OFELI_Config.h"
00047 #include "Vect.h"
00048 #include "Precond.h"
00049 #include "util.h"
00050 #include "output.h"
00051
00052 namespace OFELI {
00053
00088 template< class T_, class M_, class P_ >
00089 int BiCG(const M_ &A, const P_ &P, const Vect<T_> &b, Vect<T_> &x, int max_it,
00090 double &toler, int verbose)
00091 {
00092 int it;
00093 size_t size = x.getSize();
00094 double res;
00095 T_ alpha=0, beta=0, rho_1=0, rho_2=0;
00096 Vect<T_> r(size), z(size), zz(size), p(size), pp(size), q(size), qq(size);
00097
00098 double nrm = b.getNorm2();
00099 A.Mult(x,r);
00100 r = b - r;
00101 Vect<T_> rr(r);
00102
00103 if (nrm == 0.0)
00104 nrm = 1;
00105 if ((res = r.getNorm2() / nrm) <= toler) {
00106 toler = res;
00107 if (verbose > 1)
00108 cout << "Convergence after 0 iterations." << endl;
00109 return 0;
00110 }
00111
00112 for (it=1; it<=max_it; it++) {
00113 P.Solve(r,z);
00114 P.TransSolve(rr,zz);
00115 rho_1 = Dot(z,rr);
00116 if (rho_1 == T_(0)) {
00117 toler = r.getNorm2() / nrm;
00118 if (verbose > 1)
00119 cout << "Convergence after " << it << " iterations." << endl;
00120 return it;
00121 }
00122 if (it == 1) {
00123 p = z;
00124 pp = zz;
00125 } else {
00126 beta = rho_1 / rho_2;
00127 p = z + beta*p;
00128 pp = zz + beta*pp;
00129 }
00130 A.Mult(p,q);
00131 A.TMult(pp,qq);
00132 alpha = rho_1/Dot(pp,q);
00133 Axpy( alpha,p,x);
00134 Axpy(-alpha,q,r);
00135 Axpy(-alpha,qq,rr);
00136 rho_2 = rho_1;
00137
00138 if (verbose > 0)
00139 cout << "Iteration: " << setw(4) << it << " ... Residual: " << res << endl;
00140 if (verbose > 2)
00141 cout << x;
00142 if ((res = r.getNorm2() / b.getNorm2()) < toler) {
00143 toler = res;
00144 if (verbose > 1)
00145 cout << "Convergence after " << it << " iterations." << endl;
00146 return it;
00147 }
00148 }
00149 toler = res;
00150 return it;
00151 }
00152
00153
00154 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00155 template<class T_>
00156 int _BiCG(Matrix<T_> *A, Prec<T_> *P, const Vect<T_> &b, Vect<T_> &x, int max_it,
00157 double &toler, int verbose)
00158 {
00159 int it;
00160 size_t size = x.getSize();
00161 double res;
00162 T_ alpha=0, beta=0, rho_1=0, rho_2=0;
00163 Vect<T_> r(size), z(size), zz(size), p(size), pp(size), q(size), qq(size);
00164
00165 double nrm = b.getNorm2();
00166 A->Mult(x,r);
00167 r = b - r;
00168 Vect<T_> rr(r);
00169
00170 if (nrm == 0.0)
00171 nrm = 1;
00172 if ((res = r.getNorm2() / nrm) <= toler) {
00173 toler = res;
00174 if (verbose > 1)
00175 cout << "Convergence after 0 iterations." << endl;
00176 return 0;
00177 }
00178
00179 for (it=1; it<=max_it; it++) {
00180 P->Solve(r,z);
00181 P->TransSolve(rr,zz);
00182 rho_1 = Dot(z,rr);
00183 if (rho_1 == T_(0)) {
00184 toler = r.getNorm2() / nrm;
00185 if (verbose > 1)
00186 cout << "Convergence after " << it << " iterations." << endl;
00187 return it;
00188 }
00189 if (it == 1) {
00190 p = z;
00191 pp = zz;
00192 } else {
00193 beta = rho_1 / rho_2;
00194 p = z + beta*p;
00195 pp = zz + beta*pp;
00196 }
00197 A->Mult(p,q);
00198 A->TMult(pp,qq);
00199 alpha = rho_1/Dot(pp,q);
00200 Axpy( alpha,p,x);
00201 Axpy(-alpha,q,r);
00202 Axpy(-alpha,qq,rr);
00203 rho_2 = rho_1;
00204
00205 if (verbose > 0)
00206 cout << "Iteration: " << setw(4) << it << " ... Residual: " << res << endl;
00207 if (verbose > 2)
00208 cout << x;
00209 if ((res = r.getNorm2() / b.getNorm2()) < toler) {
00210 toler = res;
00211 if (verbose > 1)
00212 cout << "Convergence after " << it << " iterations." << endl;
00213 return it;
00214 }
00215 }
00216 toler = res;
00217 return it;
00218 }
00219 #endif
00220
00221 }
00222
00223 #endif