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_STAB_H
00035 #define __BICG_STAB_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
00086 template< class T_, class M_, class P_ >
00087 int BiCGStab(const M_ &A, const P_ &P, const Vect<T_> &b, Vect<T_> &x, int max_it,
00088 double &toler, int verbose)
00089 {
00090 int it;
00091 size_t size = x.getSize();
00092 T_ rho_1=0, rho_2=0, alpha=0, beta=0, omega=0;
00093 Vect<T_> p(size), pp(size), s(size), ss(size), t(size), v(size), r(size), rr(size);
00094 double res, nrm = b.getNorm2();
00095 A.Mult(x,r);
00096 r = b - r;
00097 rr = r;
00098
00099 if (nrm == 0.0)
00100 nrm = 1;
00101 if ((res = r.getNorm2() / nrm) <= toler) {
00102 if (verbose > 1)
00103 cout << "Convergence after 0 iterations." << endl;
00104 return 0;
00105 }
00106
00107 for (it=1; it<=max_it; it++) {
00108 rho_1 = Dot(rr,r);
00109 if (rho_1 == T_(0)) {
00110 toler = r.getNorm2() / nrm;
00111 return 2;
00112 }
00113 if (it == 1)
00114 p = r;
00115 else {
00116 beta = (rho_1/rho_2) * (alpha/omega);
00117 p = r + beta*(p - omega*v);
00118 }
00119 P.Solve(p,pp);
00120 A.Mult(pp,v);
00121 alpha = rho_1/Dot(rr,v);
00122 s = r - alpha * v;
00123 if ((res = s.getNorm2()/nrm) < toler) {
00124 x += alpha*pp;
00125 if (verbose > 1) {
00126 cout << "Iteration : " << setw(4) << it;
00127 cout << " ... Residual : " << res << endl;
00128 }
00129 toler = res;
00130 return it;
00131 }
00132 P.Solve(s,ss);
00133 A.Mult(ss,t);
00134 omega = Dot(t,s)/Dot(t,t);
00135 x += alpha*pp + omega*ss;
00136 r = s - omega*t;
00137
00138 rho_2 = rho_1;
00139 if (verbose > 1) {
00140 cout << "Iteration : " << setw(4) << it;
00141 cout << " ... Residual : " << res << endl;
00142 }
00143 if (verbose > 2)
00144 cout << x;
00145 if ((res = r.getNorm2() / nrm) < toler) {
00146 toler = res;
00147 if (verbose)
00148 cout << "Convergence after " << it << " iterations." << endl;
00149 return it;
00150 }
00151 if (omega == T_(0)) {
00152 toler = r.getNorm2() / nrm;
00153 return 3;
00154 }
00155 }
00156 if (verbose)
00157 cout << "Convergence after " << it << " iterations." << endl;
00158 toler = res;
00159 return -it;
00160 }
00161
00162
00163 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00164 template<class T_>
00165 int _BiCGStab(Matrix<T_> *A, Prec<T_> *P, const Vect<T_> &b, Vect<T_> &x, int max_it,
00166 double &toler, int verbose)
00167 {
00168 int it;
00169 size_t size = x.getSize();
00170 T_ rho_1=0, rho_2=0, alpha=0, beta=0, omega=0;
00171 Vect<T_> p(size), pp(size), s(size), ss(size), t(size), v(size), r(size), rr(size);
00172 double res, nrm = b.getNorm2();
00173 A->Mult(x,r);
00174 r = b - r;
00175 rr = r;
00176
00177 if (nrm == 0.0)
00178 nrm = 1;
00179 if ((res = r.getNorm2() / nrm) <= toler) {
00180 if (verbose > 1)
00181 cout << "Convergence after 0 iterations." << endl;
00182 return 0;
00183 }
00184
00185 for (it=1; it<=max_it; it++) {
00186 rho_1 = Dot(rr,r);
00187 if (rho_1 == T_(0)) {
00188 toler = r.getNorm2() / nrm;
00189 return 2;
00190 }
00191 if (it == 1)
00192 p = r;
00193 else {
00194 beta = (rho_1/rho_2) * (alpha/omega);
00195 p = r + beta*(p - omega*v);
00196 }
00197 P->Solve(p,pp);
00198 A->Mult(pp,v);
00199 alpha = rho_1/Dot(rr,v);
00200 s = r - alpha * v;
00201 if ((res = s.getNorm2()/nrm) < toler) {
00202 x += alpha*pp;
00203 if (verbose > 1) {
00204 cout << "Iteration : " << setw(4) << it;
00205 cout << " ... Residual : " << res << endl;
00206 }
00207 toler = res;
00208 return it;
00209 }
00210 P->Solve(s,ss);
00211 A->Mult(ss,t);
00212 omega = Dot(t,s)/Dot(t,t);
00213 x += alpha*pp + omega*ss;
00214 r = s - omega*t;
00215
00216 rho_2 = rho_1;
00217 if (verbose > 1) {
00218 cout << "Iteration : " << setw(4) << it;
00219 cout << " ... Residual : " << res << endl;
00220 }
00221 if (verbose > 2)
00222 cout << x;
00223 if ((res = r.getNorm2() / nrm) < toler) {
00224 toler = res;
00225 if (verbose)
00226 cout << "Convergence after " << it << " iterations." << endl;
00227 return it;
00228 }
00229 if (omega == T_(0)) {
00230 toler = r.getNorm2() / nrm;
00231 return 3;
00232 }
00233 }
00234 if (verbose)
00235 cout << "Convergence after " << it << " iterations." << endl;
00236 toler = res;
00237 return -it;
00238 }
00239 #endif
00240
00241 }
00242
00243 #endif