Warning: this documentation for the development version is under construction.
00001 // Copyright (C) 2003-2009 Marc Duruflé 00002 // 00003 // This file is part of the linear-algebra library Seldon, 00004 // http://seldon.sourceforge.net/. 00005 // 00006 // Seldon is free software; you can redistribute it and/or modify it under the 00007 // terms of the GNU Lesser General Public License as published by the Free 00008 // Software Foundation; either version 2.1 of the License, or (at your option) 00009 // any later version. 00010 // 00011 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY 00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00013 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 00014 // more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public License 00017 // along with Seldon. If not, see http://www.gnu.org/licenses/. 00018 00019 00020 #ifndef SELDON_FILE_ITERATIVE_CGNE_CXX 00021 00022 namespace Seldon 00023 { 00024 00026 00040 template <class Titer, class Matrix1, class Vector1, class Preconditioner> 00041 int Cgne(Matrix1& A, Vector1& x, const Vector1& b, 00042 Preconditioner& M, Iteration<Titer> & iter) 00043 { 00044 const int N = A.GetM(); 00045 if (N <= 0) 00046 return 0; 00047 00048 typedef typename Vector1::value_type Complexe; 00049 Complexe rho(1), rho_1(0), alpha, beta, delta; 00050 Vector1 p(b), q(b), r(b), z(b); 00051 Titer dp; 00052 00053 // x should be equal to 0 00054 // see Cg to understand implementation 00055 // we solve A^t A x = A^t b 00056 // left-preconditioner is equal to M M^t 00057 00058 // q = A^t b 00059 Mlt(SeldonTrans, A, b, q); 00060 // we initialize iter 00061 int success_init = iter.Init(q); 00062 if (success_init != 0) 00063 return iter.ErrorCode(); 00064 00065 if (!iter.IsInitGuess_Null()) 00066 { 00067 // r = A^t b - A^t A x 00068 Mlt(A, x, p); 00069 Mlt(SeldonTrans, A, p, r); Mlt(Complexe(-1), r); 00070 Add(Complexe(1), q, r); 00071 } 00072 else 00073 { 00074 Copy(q, r); 00075 x.Zero(); 00076 } 00077 00078 dp = Norm2(q); 00079 iter.SetNumberIteration(0); 00080 // Loop until the stopping criteria are satisfied 00081 while (! iter.Finished(dp)) 00082 { 00083 // Preconditioning 00084 M.TransSolve(A, r, q); 00085 M.Solve(A, q, z); 00086 00087 rho = DotProd(r,z); 00088 if (rho == Complexe(0)) 00089 { 00090 iter.Fail(1, "Cgne breakdown #1"); 00091 break; 00092 } 00093 00094 if (iter.First()) 00095 Copy(z, p); 00096 else 00097 { 00098 beta = rho / rho_1; 00099 Mlt(beta, p); 00100 Add(Complexe(1), z, p); 00101 } 00102 00103 // instead of q = A*p, we compute q = A^t A *p 00104 Mlt(A, p, q); 00105 Mlt(SeldonTrans, A, q, z); 00106 00107 delta = DotProd(p, z); 00108 if (delta == Complexe(0)) 00109 { 00110 iter.Fail(2, "Cgne breakdown #2"); 00111 break; 00112 } 00113 alpha = rho / delta; 00114 00115 Add(alpha, p, x); 00116 Add(-alpha, z, r); 00117 00118 rho_1 = rho; 00119 dp = Norm2(r); 00120 00121 // two iterations, because of two multiplications with A 00122 ++iter; 00123 ++iter; 00124 } 00125 00126 return iter.ErrorCode(); 00127 } 00128 00129 00130 } // end namespace 00131 00132 #define SELDON_FILE_ITERATIVE_CGNE_CXX 00133 #endif