00001 #ifndef TNT_IML_H
00002 #define TNT_IML_H
00003
00004
00005 namespace TNT {
00006 namespace Linear_Algebra {
00007
00041 template <class SCALAR>
00042 class Diagonal_Preconditioner
00043 {
00044
00045 public:
00046
00047
00054 Diagonal_Preconditioner(int N, const SCALAR *V) : one_over_diag_(N)
00055 {
00056 for (int i=0; i<N; i++)
00057 one_over_diag_[0] = 1.0/ V[0];
00058 }
00059
00066 Diagonal_Preconditioner(const Vector<SCALAR> &V) : one_over_diag_(V.dim())
00067 {
00068 for (int i=0; i<V.dim(); i++)
00069 one_over_diag_[0] = 1.0/ V[0];
00070 }
00071
00080 Vector<SCALAR> operator()(const Vector<SCALAR> &b) const
00081 {
00082 int N = one_over_diag_.dim();
00083 Vector<SCALAR> x(N);
00084 for (int i=0; i<N; i++)
00085 x[i] = b[i] * one_over_diag_[i];
00086
00087 return x;
00088 }
00089
00090
00091 private:
00092 Vector<SCALAR> one_over_diag_;
00093 };
00094
00104 template <class SCALAR>
00105 class Identity_Preconditioner
00106 {
00107
00108 public:
00109
00110
00111 Vector<SCALAR> operator()(const Vector<SCALAR> &b) const
00112 {
00113 return b;
00114 }
00115 };
00116
00139 template <class MATRIX, class VECTOR, class PRECONDITIONER, class REAL>
00140 int PCG(const MATRIX &A, VECTOR &x, const VECTOR &b,
00141 const PRECONDITIONER &M, int &max_iter, REAL &tol)
00142 {
00143 REAL residual;
00144 VECTOR p, z, q;
00145 typename VECTOR::value_type alpha, beta, rho, rho_old;
00146
00147 REAL normb = norm(b);
00148 VECTOR r = b - A*x;
00149
00150 if (normb == 0.0)
00151 normb = 1;
00152
00153 if ((residual = norm(r) / normb) <= tol)
00154 {
00155 tol = residual;
00156 max_iter = 0;
00157 return 0;
00158 }
00159
00160 for (int i = 1; i <= max_iter; i++)
00161 {
00162 z = M(r);
00163 rho = r * z;
00164
00165 if (i == 1)
00166 p = z;
00167 else
00168 {
00169 beta = rho / rho_old;
00170 p = z + beta * p;
00171 }
00172
00173 q = A*p;
00174 alpha = rho / (p * q);
00175
00176 x += alpha * p;
00177 r -= alpha * q;
00178
00179 residual = norm(r)/ normb;
00180
00181 if (residual <= tol)
00182 {
00183 tol = residual;
00184 max_iter = i;
00185 return 0;
00186 }
00187
00188 rho_old = rho;
00189 }
00190
00191 tol = residual;
00192 return 1;
00193 }
00194
00195
00196
00197
00226 template < class const_MATRIX, class VECTOR, class const_VECTOR,
00227 class const_PRECONDITIONER, class const_TRANSPOSE_PRECONDITIONER,
00228 class REAL >
00229 int PBiCG(const_MATRIX &A, VECTOR &x, const_VECTOR &b,
00230 const_PRECONDITIONER &M, const_TRANSPOSE_PRECONDITIONER &Mt,
00231 int &max_iter, REAL &tol)
00232 {
00233 REAL resid;
00234 typename VECTOR::value_type rho, rho_old, alpha, beta;
00235 VECTOR z, ztilde, p, ptilde, q, qtilde;
00236
00237 REAL normb = norm(b);
00238 VECTOR r = b - A * x;
00239 VECTOR rtilde = r;
00240
00241 if (normb == 0.0)
00242 normb = 1;
00243
00244 if ((resid = norm(r) / normb) <= tol) {
00245 tol = resid;
00246 max_iter = 0;
00247 return 0;
00248 }
00249
00250 for (int i = 1; i <= max_iter; i++) {
00251 z = M(r);
00252 ztilde = Mt(rtilde);
00253 rho = dot_product(z, rtilde);
00254 if (rho == 0) {
00255 tol = norm(r) / normb;
00256 max_iter = i;
00257 return 2;
00258 }
00259 if (i == 1) {
00260 p = z;
00261 ptilde = ztilde;
00262 } else {
00263 beta = rho / rho_old;
00264 p = z + beta * p;
00265 ptilde = ztilde + beta * ptilde;
00266 }
00267 q = A * p;
00268 qtilde = transpose_mult(A, ptilde);
00269 alpha = rho / dot_product(ptilde, q);
00270 x += alpha * p;
00271 r -= alpha * q;
00272 rtilde -= alpha * qtilde;
00273
00274 rho_old = rho;
00275 if ((resid = norm(r) / normb) < tol) {
00276 tol = resid;
00277 max_iter = i;
00278 return 0;
00279 }
00280 }
00281
00282 tol = resid;
00283 return 1;
00284 }
00285
00315 template < class const_MATRIX, class VECTOR, class const_VECTOR,
00316 class const_PRECONDITIONER, class REAL >
00317 int BiCGSTAB(const_MATRIX &A, VECTOR &x, const_VECTOR &b,
00318 const_PRECONDITIONER &M, int &max_iter, REAL &tol)
00319 {
00320 REAL resid;
00321 typename VECTOR::value_type rho_1, rho_2, alpha, beta, omega;
00322 VECTOR p, phat, s, shat, t, v;
00323
00324 REAL normb = norm(b);
00325 VECTOR r = b - A * x;
00326 VECTOR rtilde = r;
00327
00328 if (normb == 0.0)
00329 normb = 1;
00330
00331 if ((resid = norm(r) / normb) <= tol) {
00332 tol = resid;
00333 max_iter = 0;
00334 return 0;
00335 }
00336
00337 for (int i = 1; i <= max_iter; i++) {
00338 rho_1 = dot_product(rtilde, r);
00339 if (rho_1 == 0) {
00340 tol = norm(r) / normb;
00341 return 2;
00342 }
00343 if (i == 1)
00344 p = r;
00345 else {
00346 beta = (rho_1/rho_2) * (alpha/omega);
00347 p = r + beta * (p - omega * v);
00348 }
00349 phat = M.solve(p);
00350 v = A * phat;
00351 alpha = rho_1 / dot_product(rtilde, v);
00352 s = r - alpha * v;
00353 if ((resid = norm(s)/normb) < tol) {
00354 x += alpha * phat;
00355 tol = resid;
00356 return 0;
00357 }
00358 shat = M.solve(s);
00359 t = A * shat;
00360 omega = dot_product(t,s) / dot_product(t,t);
00361 x += alpha * phat + omega * shat;
00362 r = s - omega * t;
00363
00364 rho_2 = rho_1;
00365 if ((resid = norm(r) / normb) < tol) {
00366 tol = resid;
00367 max_iter = i;
00368 return 0;
00369 }
00370 if (omega == 0) {
00371 tol = norm(r) / normb;
00372 return 3;
00373 }
00374 }
00375
00376 tol = resid;
00377 return 1;
00378 }
00379
00380
00381
00409 template < class const_MATRIX, class VECTOR, class const_VECTOR,
00410 class const_PRECONDITIONER, class REAL >
00411 int
00412 CGS(const_MATRIX &A, VECTOR &x, const_VECTOR &b,
00413 const_PRECONDITIONER &M, int &max_iter, REAL &tol)
00414 {
00415 REAL resid;
00416 typename VECTOR::value_type rho_1, rho_2, alpha, beta;
00417 VECTOR p, phat, q, qhat, vhat, u, uhat;
00418
00419 REAL normb = norm(b);
00420 VECTOR r = b - A*x;
00421 VECTOR rtilde = r;
00422
00423 if (normb == 0.0)
00424 normb = 1;
00425
00426 if ((resid = norm(r) / normb) <= tol) {
00427 tol = resid;
00428 max_iter = 0;
00429 return 0;
00430 }
00431
00432 for (int i = 1; i <= max_iter; i++) {
00433 rho_1 = dot_product(rtilde, r);
00434 if (rho_1 == 0) {
00435 tol = norm(r) / normb;
00436 return 2;
00437 }
00438 if (i == 1) {
00439 u = r;
00440 p = u;
00441 } else {
00442 beta = rho_1 / rho_2;
00443 u = r + beta * q;
00444 p = u + beta * (q + beta * p);
00445 }
00446 phat = M.solve(p);
00447 vhat = A*phat;
00448 alpha = rho_1 / dot_product(rtilde, vhat);
00449 q = u - alpha * vhat;
00450 uhat = M(u + q);
00451 x += alpha * uhat;
00452 qhat = A * uhat;
00453 r -= alpha * qhat;
00454 rho_2 = rho_1;
00455 if ((resid = norm(r) / normb) < tol) {
00456 tol = resid;
00457 max_iter = i;
00458 return 0;
00459 }
00460 }
00461
00462 tol = resid;
00463 return 1;
00464 }
00465
00466
00498 template < class const_MATRIX, class const_VECTOR, class VECTOR,
00499 class const_PRECONDITIONER, class REAL, class SCALAR >
00500 int
00501 CHEBY(const_MATRIX &A, VECTOR &x, const_VECTOR &b,
00502 const_PRECONDITIONER &M, int &max_iter, REAL &tol,
00503 SCALAR eigmin, SCALAR eigmax)
00504 {
00505 REAL resid;
00506 SCALAR alpha, beta, c, d;
00507 VECTOR p, q, z;
00508
00509 REAL normb = norm(b);
00510 VECTOR r = b - A * x;
00511
00512 if (normb == 0.0)
00513 normb = 1;
00514
00515 if ((resid = norm(r) / normb) <= tol) {
00516 tol = resid;
00517 max_iter = 0;
00518 return 0;
00519 }
00520
00521 c = (eigmax - eigmin) / 2.0;
00522 d = (eigmax + eigmin) / 2.0;
00523
00524 for (int i = 1; i <= max_iter; i++) {
00525 z = M(r);
00526
00527 if (i == 1) {
00528 p = z;
00529 alpha = 2.0 / d;
00530 } else {
00531 beta = c * alpha / 2.0;
00532 beta = beta * beta;
00533 alpha = 1.0 / (d - beta);
00534 p = z + beta * p;
00535 }
00536
00537 q = A * p;
00538 x += alpha * p;
00539 r -= alpha * q;
00540
00541 if ((resid = norm(r) / normb) <= tol) {
00542 tol = resid;
00543 max_iter = i;
00544 return 0;
00545 }
00546 }
00547
00548 tol = resid;
00549 return 1;
00550 }
00551
00552 template < class MATRIX, class VECTOR >
00553 void
00554 Update(VECTOR &x, int k, MATRIX &h, VECTOR &s, VECTOR v[])
00555 {
00556 VECTOR y(s);
00557
00558
00559 for (int i = k; i >= 0; i--) {
00560 y(i) /= h(i,i);
00561 for (int j = i - 1; j >= 0; j--)
00562 y(j) -= h(j,i) * y(i);
00563 }
00564
00565 for (int j = 0; j <= k; j++)
00566 x += v[j] * y(j);
00567 }
00568
00569
00570 template < class REAL >
00571 REAL
00572 abs(REAL x)
00573 {
00574 return (x > 0 ? x : -x);
00575 }
00576
00577
00612 template < class Operator, class VECTOR, class PRECONDITIONER,
00613 class MATRIX, class REAL >
00614 int
00615 GMRES(const Operator &A, VECTOR &x, const VECTOR &b,
00616 const PRECONDITIONER &M, MATRIX &H, int &m, int &max_iter,
00617 REAL &tol)
00618 {
00619 REAL resid;
00620 int i, j = 1, k;
00621 VECTOR s(m+1), cs(m+1), sn(m+1), w;
00622
00623 REAL normb = norm(M(b));
00624 VECTOR r = M(b - A * x);
00625 REAL beta = norm(r);
00626
00627 if (normb == 0.0)
00628 normb = 1;
00629
00630 if ((resid = norm(r) / normb) <= tol) {
00631 tol = resid;
00632 max_iter = 0;
00633 return 0;
00634 }
00635
00636 VECTOR *v = new VECTOR[m+1];
00637
00638 while (j <= max_iter) {
00639 v[0] = r * (1.0 / beta);
00640 s = 0.0;
00641 s = beta;
00642
00643 for (i = 0; i < m && j <= max_iter; i++, j++) {
00644 w = M(A * v[i]);
00645 for (k = 0; k <= i; k++) {
00646 H(k, i) = dot_product(w, v[k]);
00647 w -= H(k, i) * v[k];
00648 }
00649 H(i+1, i) = norm(w);
00650 v[i+1] = w * (1.0 / H(i+1, i));
00651
00652 for (k = 0; k < i; k++)
00653 ApplyPlaneRotation(H(k,i), H(k+1,i), cs(k), sn(k));
00654
00655 GeneratePlaneRotation(H(i,i), H(i+1,i), cs(i), sn(i));
00656 ApplyPlaneRotation(H(i,i), H(i+1,i), cs(i), sn(i));
00657 ApplyPlaneRotation(s(i), s(i+1), cs(i), sn(i));
00658
00659 if ((resid = abs(s(i+1)) / normb) < tol) {
00660 Update(x, i, H, s, v);
00661 tol = resid;
00662 max_iter = j;
00663 delete [] v;
00664 return 0;
00665 }
00666 }
00667 Update(x, i - 1, H, s, v);
00668 r = M(b - A * x);
00669 beta = norm(r);
00670 if ((resid = beta / normb) < tol) {
00671 tol = resid;
00672 max_iter = j;
00673 delete [] v;
00674 return 0;
00675 }
00676 }
00677
00678 tol = resid;
00679 delete [] v;
00680 return 1;
00681 }
00682
00683
00684 #include <math.h>
00685
00686
00687 template<class REAL>
00688 void GeneratePlaneRotation(REAL &dx, REAL &dy, REAL &cs, REAL &sn)
00689 {
00690 if (dy == 0.0) {
00691 cs = 1.0;
00692 sn = 0.0;
00693 } else if (abs(dy) > abs(dx)) {
00694 REAL temp = dx / dy;
00695 sn = 1.0 / sqrt( 1.0 + temp*temp );
00696 cs = temp * sn;
00697 } else {
00698 REAL temp = dy / dx;
00699 cs = 1.0 / sqrt( 1.0 + temp*temp );
00700 sn = temp * cs;
00701 }
00702 }
00703
00704
00705 template<class REAL>
00706 void ApplyPlaneRotation(REAL &dx, REAL &dy, REAL &cs, REAL &sn)
00707 {
00708 REAL temp = cs * dx + sn * dy;
00709 dy = -sn * dx + cs * dy;
00710 dx = temp;
00711 }
00712
00739 template < class MATRIX, class VECTOR, class PRECONDITIONER, class REAL >
00740 int
00741 IR(const MATRIX &A, VECTOR &x, const VECTOR &b,
00742 const PRECONDITIONER &M, int &max_iter, REAL &tol)
00743 {
00744 REAL resid;
00745 VECTOR z;
00746
00747 REAL normb = norm(b);
00748 VECTOR r = b - A*x;
00749
00750 if (normb == 0.0)
00751 normb = 1;
00752
00753 if ((resid = norm(r) / normb) <= tol) {
00754 tol = resid;
00755 max_iter = 0;
00756 return 0;
00757 }
00758
00759 for (int i = 1; i <= max_iter; i++) {
00760 z = M(r);
00761 x += z;
00762 r = b - A * x;
00763
00764 if ((resid = norm(r) / normb) <= tol) {
00765 tol = resid;
00766 max_iter = i;
00767 return 0;
00768 }
00769 }
00770
00771 tol = resid;
00772 return 1;
00773 }
00774
00775
00776 #include <math.h>
00777
00825 template < class const_MATRIX, class const_VECTOR, class VECTOR,
00826 class const_PRECONDITIONER1, class const_PRECONDITIONER1t,
00827 class const_PRECONDITIONER2, class const_PRECONDITIONER2t,
00828 class REAL >
00829 int
00830 QMR(const_MATRIX &A, VECTOR &x, const_VECTOR &b,
00831 const_PRECONDITIONER1 &M1, const_PRECONDITIONER1t &M1t,
00832 const_PRECONDITIONER2 &M2, const_PRECONDITIONER2t &M2t,
00833 int &max_iter, REAL &tol)
00834 {
00835 REAL resid;
00836
00837 typename VECTOR::value_type rho, rho_1, xi, gamma;
00838 typename VECTOR::value_type gamma_1, theta, theta_1;
00839 typename VECTOR::value_type eta, delta, ep, beta;
00840
00841 VECTOR r, v_tld, y, w_tld, z;
00842 VECTOR v, w, y_tld, z_tld;
00843 VECTOR p, q, p_tld, d, s;
00844
00845 REAL normb = norm(b);
00846
00847 r = b - A * x;
00848
00849 if (normb == 0.0)
00850 normb = 1;
00851
00852 if ((resid = norm(r) / normb) <= tol) {
00853 tol = resid;
00854 max_iter = 0;
00855 return 0;
00856 }
00857
00858 v_tld = r;
00859 y = M1(v_tld);
00860 rho = norm(y);
00861
00862 w_tld = r;
00863 z = M2(w_tld);
00864 xi = norm(z);
00865
00866 gamma = 1.0;
00867 eta = -1.0;
00868 theta = 0.0;
00869
00870 for (int i = 1; i <= max_iter; i++) {
00871
00872 if (rho == 0.0)
00873 return 2;
00874
00875 if (xi == 0.0)
00876 return 7;
00877
00878 v = (1. / rho) * v_tld;
00879 y = (1. / rho) * y;
00880
00881 w = (1. / xi) * w_tld;
00882 z = (1. / xi) * z;
00883
00884 delta = dot_product(z, y);
00885 if (delta == 0.0)
00886 return 5;
00887
00888 y_tld = M2(y);
00889 z_tld = M1t(z);
00890
00891 if (i > 1) {
00892 p = y_tld - (xi * delta / ep) * p;
00893 q = z_tld - (rho * delta / ep) * q;
00894 } else {
00895 p = y_tld;
00896 q = z_tld;
00897 }
00898
00899 p_tld = A * p;
00900 ep = dot_product(q, p_tld);
00901 if (ep == 0.0)
00902 return 6;
00903
00904 beta = ep / delta;
00905 if (beta == 0.0)
00906 return 3;
00907
00908 v_tld = p_tld - beta * v;
00909 y = M1.solve(v_tld);
00910
00911 rho_1 = rho;
00912 rho = norm(y);
00913 w_tld = transpose_mult(A,q) - beta * w;
00914 z = M2t(w_tld);
00915
00916 xi = norm(z);
00917
00918 gamma_1 = gamma;
00919 theta_1 = theta;
00920
00921 theta = rho / (gamma_1 * beta);
00922 gamma = 1.0 / sqrt(1.0 + theta * theta);
00923
00924 if (gamma == 0.0)
00925 return 4;
00926
00927 eta = -eta * rho_1 * gamma * gamma /
00928 (beta * gamma_1 * gamma_1);
00929
00930 if (i > 1) {
00931 d = eta * p + (theta_1 * theta_1 * gamma * gamma) * d;
00932 s = eta * p_tld + (theta_1 * theta_1 * gamma * gamma) * s;
00933 } else {
00934 d = eta * p;
00935 s = eta * p_tld;
00936 }
00937
00938 x += d;
00939 r -= s;
00940
00941 if ((resid = norm(r) / normb) <= tol) {
00942 tol = resid;
00943 max_iter = i;
00944 return 0;
00945 }
00946 }
00947
00948 tol = resid;
00949 return 1;
00950 }
00951
00952 }
00953 }
00954
00955 #endif
00956