matrix_sparse/Relaxation_MatVect.cxx

00001 // Copyright (C) 2003-2009 Marc Duruflé
00002 // Copyright (C) 2001-2009 Vivien Mallet
00003 //
00004 // This file is part of the linear-algebra library Seldon,
00005 // http://seldon.sourceforge.net/.
00006 //
00007 // Seldon is free software; you can redistribute it and/or modify it under the
00008 // terms of the GNU Lesser General Public License as published by the Free
00009 // Software Foundation; either version 2.1 of the License, or (at your option)
00010 // any later version.
00011 //
00012 // Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
00013 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
00015 // more details.
00016 //
00017 // You should have received a copy of the GNU Lesser General Public License
00018 // along with Seldon. If not, see http://www.gnu.org/licenses/.
00019 
00020 
00021 #ifndef SELDON_FILE_RELAXATION_MATVECT_CXX
00022 
00023 /*
00024   Functions defined in this file
00025 
00026   SOR(A, X, B, omega, iter, type_ssor)
00027 
00028 */
00029 
00030 namespace Seldon
00031 {
00032 
00034 
00041   template <class T0, class Prop0, class Allocator0,
00042             class T1, class Storage1, class Allocator1,
00043             class T2, class Storage2, class Allocator2, class T3>
00044   void SOR(const Matrix<T0, Prop0, RowSparse, Allocator0>& A,
00045            Vector<T2, Storage2, Allocator2>& X,
00046            const Vector<T1, Storage1, Allocator1>& B,
00047            const T3& omega, int iter, int type_ssor = 2)
00048   {
00049     T1 temp(0);
00050 
00051     int ma = A.GetM();
00052 
00053 #ifdef SELDON_CHECK_BOUNDS
00054     int na = A.GetN();
00055     if (na != ma)
00056       throw WrongDim("SOR", "Matrix must be squared.");
00057 
00058     if (ma != X.GetLength() || ma != B.GetLength())
00059       throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
00060 #endif
00061 
00062     int* ptr = A.GetPtr();
00063     int* ind = A.GetInd();
00064     typename Matrix<T0, Prop0, RowSparse, Allocator0>::pointer data
00065       = A.GetData();
00066     T0 ajj(1);
00067 
00068     // Forward sweep.
00069     if (type_ssor % 2 == 0)
00070       for (int i = 0; i < iter; i++)
00071         for (int j = 0; j < ma; j++)
00072           {
00073             temp = T1(0);
00074             ajj = A(j, j);
00075             for (int k = ptr[j] ; k < ptr[j+1]; k++)
00076               temp += data[k] * X(ind[k]);
00077 
00078             temp = B(j) - temp + ajj * X(j);
00079             X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
00080           }
00081 
00082     // Backward sweep.
00083     if (type_ssor % 3 == 0)
00084       for (int i = 0; i < iter; i++)
00085         for (int j = ma-1 ; j >= 0; j--)
00086           {
00087             temp = T1(0);
00088             ajj = A(j, j);
00089             for (int k = ptr[j]; k < ptr[j+1]; k++)
00090               temp += data[k] * X(ind[k]);
00091 
00092             temp = B(j) - temp + ajj * X(j);
00093             X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
00094           }
00095   }
00096 
00097 
00099 
00106   template <class T0, class Prop0, class Allocator0,
00107             class T1, class Storage1, class Allocator1,
00108             class T2, class Storage2, class Allocator2, class T3>
00109   void SOR(const Matrix<T0, Prop0, ArrayRowSparse, Allocator0>& A,
00110            Vector<T2, Storage2, Allocator2>& X,
00111            const Vector<T1, Storage1, Allocator1>& B,
00112            const T3& omega,
00113            int iter, int type_ssor = 2)
00114   {
00115     T1 temp(0);
00116 
00117     int ma = A.GetM();
00118 
00119 #ifdef SELDON_CHECK_BOUNDS
00120     int na = A.GetN();
00121     if (na != ma)
00122       throw WrongDim("SOR", "Matrix must be squared.");
00123 
00124     if (ma != X.GetLength() || ma != B.GetLength())
00125       throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
00126 #endif
00127 
00128     T0 ajj(1);
00129 
00130     // Forward sweep.
00131     if (type_ssor % 2 == 0)
00132       for (int i = 0; i < iter; i++)
00133         for (int j = 0; j < ma; j++)
00134           {
00135             temp = T1(0);
00136             ajj = T0(0);
00137             for (int k = 0; k < A.GetRowSize(j); k++)
00138               {
00139                 temp += A.Value(j,k) * X(A.Index(j,k));
00140                 if (A.Index(j,k) == j)
00141                   ajj += A.Value(j,k);
00142               }
00143 
00144             temp = B(j) - temp + ajj * X(j);
00145             X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
00146           }
00147 
00148     // Backward sweep.
00149     if (type_ssor % 3 == 0)
00150       for (int i = 0; i < iter; i++)
00151         for (int j = ma-1; j >= 0; j--)
00152           {
00153             temp = T1(0);
00154             ajj = T0(0);
00155             for (int k = 0; k < A.GetRowSize(j); k++)
00156               {
00157                 temp += A.Value(j,k) * X(A.Index(j,k));
00158                 if (A.Index(j,k) == j)
00159                   ajj += A.Value(j,k);
00160               }
00161 
00162             temp = B(j) - temp + ajj * X(j);
00163             X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
00164           }
00165   }
00166 
00167 
00169 
00176   template <class T0, class Prop0, class Allocator0,
00177             class T1, class Storage1, class Allocator1,
00178             class T2, class Storage2, class Allocator2, class T3>
00179   void SOR(const Matrix<T0, Prop0, RowSymSparse, Allocator0>& A,
00180            Vector<T2, Storage2, Allocator2>& X,
00181            const Vector<T1, Storage1, Allocator1>& B,
00182            const T3& omega,int iter, int type_ssor = 2)
00183   {
00184     T1 temp(0);
00185 
00186     int ma = A.GetM();
00187 
00188 #ifdef SELDON_CHECK_BOUNDS
00189     int na = A.GetN();
00190     if (na != ma)
00191       throw WrongDim("SOR", "Matrix must be squared.");
00192 
00193     if (ma != X.GetLength() || ma != B.GetLength())
00194       throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
00195 #endif
00196 
00197     int* ptr = A.GetPtr();
00198     int* ind = A.GetInd();
00199     T0* data = A.GetData();
00200 
00201     Vector<T2, Storage2, Allocator2> Y(ma);
00202     Y.Zero();
00203     T0 ajj(1);
00204     int p;
00205     T0 val(0);
00206     // Let us consider the following splitting : A = D - L - U
00207     // D diagonal of A
00208     // L lower part of A
00209     // U upper part of A, A is symmetric, so L = U^t
00210 
00211     // Forward sweep
00212     // (D/omega - L) X^{n+1/2} = (U + (1-omega)/omega D) X^n + B
00213     if (type_ssor % 2 == 0)
00214       for (int i = 0; i < iter; i++)
00215         {
00216           for (int j = 0; j < ma; j++)
00217             {
00218               // First we do X = (U + (1-omega)/omega D) X + B
00219               temp = T1(0);
00220               ajj = T0(0);
00221               for (int k = ptr[j]; k < ptr[j+1]; k++)
00222                 {
00223                   p = ind[k];
00224                   val = data[k];
00225                   if (p == j)
00226                     ajj += val;
00227                   else
00228                     temp += val * X(p);
00229                 }
00230 
00231               temp = B(j) - temp;
00232               X(j) = (T2(1) - omega) / omega * ajj * X(j) + temp;
00233             }
00234 
00235           for (int j = 0; j < ma; j++)
00236             {
00237               ajj = T0(0);
00238               // Then we solve (D/omega - L) X = X
00239               for (int k = ptr[j]; k < ptr[j+1]; k++)
00240                 {
00241                   p = ind[k];
00242                   val = data[k];
00243                   if (p == j)
00244                     ajj += val;
00245                 }
00246               X(j) *= omega / ajj;
00247               for (int k = ptr[j]; k < ptr[j+1]; k++)
00248                 {
00249                   p = ind[k];
00250                   val = data[k];
00251                   if (p != j)
00252                     X(p) -= val*X(j);
00253                 }
00254             }
00255         }
00256 
00257 
00258     // Backward sweep.
00259     // (D/omega - U) X^{n+1} = (L + (1-omega)/omega D) X^{n+1/2} + B
00260     if (type_ssor % 3 == 0)
00261       for (int i = 0; i < iter; i++)
00262         {
00263           Y.Zero();
00264           for (int j = 0; j < ma; j++)
00265             {
00266               ajj = T0(0);
00267               // Then we compute X = (L + (1-omega)/omega D) X + B.
00268               for (int k = ptr[j]; k < ptr[j+1]; k++)
00269                 {
00270                   p = ind[k];
00271                   val = data[k];
00272                   if (p == j)
00273                     ajj += val;
00274                   else
00275                     Y(p) += val*X(j);
00276                 }
00277 
00278               X(j) = (T2(1) - omega) / omega * ajj * X(j) + B(j) - Y(j);
00279             }
00280 
00281           for (int j = ma-1; j >= 0; j--)
00282             {
00283               temp = T1(0);
00284               ajj = T0(0);
00285               // Then we solve (D/omega - U) X = X.
00286               for (int k = ptr[j]; k < ptr[j+1]; k++)
00287                 {
00288                   p = ind[k];
00289                   val = data[k];
00290                   if (p == j)
00291                     ajj += val;
00292                   else
00293                     temp += val*X(p);
00294                 }
00295               X(j) = (X(j) - temp) * omega / ajj;
00296             }
00297         }
00298   }
00299 
00300 
00302 
00309   template <class T0, class Prop0, class Allocator0,
00310             class T1, class Storage1, class Allocator1,
00311             class T2, class Storage2, class Allocator2, class T3>
00312   void SOR(const Matrix<T0, Prop0, ArrayRowSymSparse, Allocator0>& A,
00313            Vector<T2, Storage2, Allocator2>& X,
00314            const Vector<T1, Storage1, Allocator1>& B,
00315            const T3& omega,int iter, int type_ssor = 2)
00316   {
00317     T1 temp(0);
00318 
00319     int ma = A.GetM();
00320 
00321 #ifdef SELDON_CHECK_BOUNDS
00322     int na = A.GetN();
00323     if (na != ma)
00324       throw WrongDim("SOR", "Matrix must be squared.");
00325 
00326     if (ma != X.GetLength() || ma != B.GetLength())
00327       throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
00328 #endif
00329 
00330 
00331     Vector<T2,Storage2,Allocator2> Y(ma);
00332     Y.Zero();
00333     T0 ajj(1);
00334     int p; T0 val(0);
00335     // Let us consider the following splitting : A = D - L - U
00336     // D diagonal of A
00337     // L lower part of A
00338     // U upper part of A, A is symmetric, so L = U^t
00339 
00340     // Forward sweep.
00341     // (D/omega - L) X^{n+1/2} = (U + (1-omega)/omega D) X^n + B
00342     if (type_ssor % 2 == 0)
00343       for (int i = 0; i < iter; i++)
00344         {
00345           for (int j = 0; j < ma; j++)
00346             {
00347               // First we do X = (U + (1-omega)/omega D) X + B.
00348               temp = T1(0);
00349               ajj = T0(0);
00350               for (int k = 0; k < A.GetRowSize(j); k++)
00351                 {
00352                   p = A.Index(j,k);
00353                   val = A.Value(j,k);
00354                   if (p == j)
00355                     ajj += val;
00356                   else
00357                     temp += val * X(p);
00358                 }
00359 
00360               temp = B(j) - temp;
00361               X(j) = (T2(1) - omega) / omega * ajj * X(j) + temp;
00362             }
00363 
00364           for (int j = 0; j < ma; j++)
00365             {
00366               ajj = T0(0);
00367               // Then we solve (D/omega - L) X = X.
00368               for (int k = 0; k < A.GetRowSize(j); k++)
00369                 {
00370                   p = A.Index(j,k);
00371                   val = A.Value(j,k);
00372                   if (p == j)
00373                     ajj += val;
00374                 }
00375               X(j) *= omega / ajj;
00376               for (int k = 0 ; k < A.GetRowSize(j); k++)
00377                 {
00378                   p = A.Index(j,k);
00379                   val = A.Value(j,k);
00380                   if (p != j)
00381                     X(p) -= val*X(j);
00382                 }
00383             }
00384         }
00385 
00386 
00387     // Backward sweep.
00388     // (D/omega - U) X^{n+1} = (L + (1-omega)/omega D) X^{n+1/2} + B
00389     if (type_ssor % 3 == 0)
00390       for (int i = 0; i < iter; i++)
00391         {
00392           Y.Zero();
00393           for (int j = 0; j < ma; j++)
00394             {
00395               ajj = T0(0);
00396               // Then we compute X = (L + (1-omega)/omega D) X + B.
00397               for (int k = 0; k < A.GetRowSize(j); k++)
00398                 {
00399                   p = A.Index(j,k);
00400                   val = A.Value(j,k);
00401                   if (p == j)
00402                     ajj += val;
00403                   else
00404                     Y(p) += val*X(j);
00405                 }
00406 
00407               X(j) = (T2(1) - omega) / omega * ajj * X(j) + B(j) - Y(j);
00408             }
00409 
00410           for (int j = ma-1; j >= 0; j--)
00411             {
00412               temp = T1(0);
00413               ajj = T0(0);
00414               // Then we solve (D/omega - U) X = X.
00415               for (int k = 0; k < A.GetRowSize(j); k++)
00416                 {
00417                   p = A.Index(j,k);
00418                   val = A.Value(j,k);
00419                   if (p == j)
00420                     ajj += val;
00421                   else
00422                     temp += val * X(p);
00423                 }
00424               X(j) = (X(j) - temp) * omega / ajj;
00425             }
00426         }
00427 
00428   }
00429 
00430 
00432 
00439   template <class T0, class Prop0, class Allocator0,
00440             class T1, class Storage1, class Allocator1,
00441             class T2, class Storage2, class Allocator2, class T3>
00442   void SOR(const Matrix<T0, Prop0, RowComplexSparse, Allocator0>& A,
00443            Vector<complex<T2>, Storage2, Allocator2>& X,
00444            const Vector<complex<T1>, Storage1, Allocator1>& B,
00445            const T3& omega, int iter, int type_ssor = 2)
00446   {
00447     complex<T1> temp(0);
00448 
00449     int ma = A.GetM();
00450 
00451 #ifdef SELDON_CHECK_BOUNDS
00452     int na = A.GetN();
00453     if (na != ma)
00454       throw WrongDim("SOR", "Matrix must be squared.");
00455 
00456     if (ma != X.GetLength() || ma != B.GetLength())
00457       throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
00458 #endif
00459 
00460     int* ptr_real = A.GetRealPtr();
00461     int* ptr_imag = A.GetImagPtr();
00462     int* ind_real = A.GetRealInd();
00463     int* ind_imag = A.GetImagInd();
00464     typename Matrix<T0, Prop0, RowComplexSparse, Allocator0>::pointer
00465       data_real = A.GetRealData();
00466     typename Matrix<T0, Prop0, RowComplexSparse, Allocator0>::pointer
00467       data_imag = A.GetImagData();
00468     complex<T0> ajj(1);
00469 
00470     if (type_ssor % 2 == 0)
00471       for (int i = 0; i < iter; i++)
00472         for (int j = 0; j < ma; j++)
00473           {
00474             temp = complex<T1>(0);
00475             ajj = A(j,j);
00476             for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
00477               temp += data_real[k] * X(ind_real[k]);
00478 
00479             for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
00480               temp += complex<T1>(0, data_imag[k]) * X(ind_imag[k]);
00481 
00482             temp = B(j) - temp + ajj*X(j);
00483             X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
00484           }
00485 
00486     if (type_ssor % 3 == 0)
00487       for (int i = 0; i < iter; i++)
00488         for (int j = ma-1; j >= 0; j--)
00489           {
00490             temp = complex<T1>(0);
00491             ajj = A(j,j);
00492             for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
00493               temp += data_real[k] * X(ind_real[k]);
00494 
00495             for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
00496               temp += complex<T1>(0, data_imag[k]) * X(ind_imag[k]);
00497 
00498             temp = B(j) - temp + ajj * X(j);
00499             X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
00500           }
00501   }
00502 
00503 
00505 
00512   template <class T0, class Prop0, class Allocator0,
00513             class T1, class Storage1, class Allocator1,
00514             class T2, class Storage2, class Allocator2, class T3>
00515   void SOR(const Matrix<T0, Prop0, ArrayRowComplexSparse, Allocator0>& A,
00516            Vector<complex<T2>, Storage2, Allocator2>& X,
00517            const Vector<complex<T1>, Storage1, Allocator1>& B,
00518            const T3& omega, int iter, int type_ssor = 2)
00519   {
00520     complex<T1> temp(0);
00521 
00522     int ma = A.GetM();
00523 
00524 #ifdef SELDON_CHECK_BOUNDS
00525     int na = A.GetN();
00526     if (na != ma)
00527       throw WrongDim("SOR", "Matrix must be squared.");
00528 
00529     if (ma != X.GetLength() || ma != B.GetLength())
00530       throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
00531 #endif
00532 
00533     complex<T0> ajj(1);
00534 
00535     if (type_ssor%2 == 0)
00536       for (int i = 0; i < iter; i++)
00537         {
00538           for (int j = 0; j < ma; j++)
00539             {
00540               temp = complex<T1>(0);
00541               ajj = complex<T0>(0);
00542               for (int k = 0; k < A.GetRealRowSize(j); k++)
00543                 {
00544                   temp += A.ValueReal(j,k) * X(A.IndexReal(j,k));
00545                   if (A.IndexReal(j,k) == j)
00546                     ajj += complex<T0>(A.ValueReal(j,k), 0);
00547                 }
00548               for (int k = 0; k < A.GetImagRowSize(j); k++)
00549                 {
00550                   temp += complex<T0>(0,A.ValueImag(j,k))
00551                     * X(A.IndexImag(j,k));
00552                   if (A.IndexImag(j,k) == j)
00553                     ajj += complex<T0>(0, A.ValueImag(j,k));
00554                 }
00555 
00556               temp = B(j) - temp + ajj * X(j);
00557               X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
00558             }
00559         }
00560 
00561     if (type_ssor % 3 == 0)
00562       for (int i = 0; i < iter; i++)
00563         for (int j = ma-1; j >= 0; j--)
00564           {
00565             temp = complex<T1>(0);
00566             ajj = complex<T0>(0);
00567             for (int k = 0; k < A.GetRealRowSize(j); k++)
00568               {
00569                 temp += A.ValueReal(j,k) * X(A.IndexReal(j,k));
00570                 if (A.IndexReal(j,k) == j)
00571                   ajj += complex<T0>(A.ValueReal(j,k), 0);
00572               }
00573             for (int k = 0; k < A.GetImagRowSize(j); k++)
00574               {
00575                 temp += complex<T0>(0, A.ValueImag(j,k))
00576                   * X(A.IndexImag(j,k));
00577                 if (A.IndexImag(j,k) == j)
00578                   ajj += complex<T0>(0, A.ValueImag(j,k));
00579               }
00580 
00581             temp = B(j) - temp + ajj * X(j);
00582             X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
00583           }
00584   }
00585 
00586 
00588 
00595   template <class T0, class Prop0, class Allocator0,
00596             class T1, class Storage1, class Allocator1,
00597             class T2, class Storage2, class Allocator2, class T3>
00598   void SOR(const Matrix<T0, Prop0, RowSymComplexSparse, Allocator0>& A,
00599            Vector<complex<T2>, Storage2, Allocator2>& X,
00600            const Vector<complex<T1>, Storage1, Allocator1>& B,
00601            const T3& omega, int iter, int type_ssor = 2)
00602   {
00603     complex<T1> temp(0);
00604 
00605     int ma = A.GetM();
00606 
00607 #ifdef SELDON_CHECK_BOUNDS
00608     int na = A.GetN();
00609     if (na != ma)
00610       throw WrongDim("SOR", "Matrix must be squared.");
00611 
00612     if (ma != X.GetLength() || ma != B.GetLength())
00613       throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
00614 #endif
00615 
00616     int* ptr_real = A.GetRealPtr();
00617     int* ptr_imag = A.GetImagPtr();
00618     int* ind_real = A.GetRealInd();
00619     int* ind_imag = A.GetImagInd();
00620     T0* data_real = A.GetRealData();
00621     T0* data_imag = A.GetImagData();
00622 
00623     Vector<complex<T2>, Storage2, Allocator2> Y(ma);
00624     Y.Zero();
00625     complex<T0> ajj(1);
00626     int p;
00627     complex<T0> val(0);
00628 
00629     // Let us consider the following splitting : A = D - L - U
00630     // D diagonal of A
00631     // L lower part of A
00632     // U upper part of A, A is symmetric, so L = U^t
00633     // forward sweep
00634     // (D/omega - L) X^{n+1/2} = (U + (1-omega)/omega D) X^n + B
00635     if (type_ssor % 2 == 0)
00636       for (int i = 0; i < iter; i++)
00637         {
00638           for (int j = 0; j < ma; j++)
00639             {
00640               // first we do X = (U + (1-omega)/omega D) X + B
00641               temp = complex<T1>(0);
00642               ajj = complex<T0>(0);
00643               for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
00644                 {
00645                   p = ind_real[k];
00646                   val = complex<T0>(data_real[k], 0);
00647                   if (p == j)
00648                     ajj += val;
00649                   else
00650                     temp += val * X(p);
00651                 }
00652               for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
00653                 {
00654                   p = ind_imag[k];
00655                   val = complex<T0>(0, data_imag[k]);
00656                   if (p == j)
00657                     ajj += val;
00658                   else
00659                     temp += val * X(p);
00660                 }
00661 
00662               temp = B(j) - temp;
00663               X(j) = (T2(1) - omega) / omega * ajj * X(j) + temp;
00664             }
00665 
00666           for (int j = 0; j < ma; j++)
00667             {
00668               ajj = complex<T0>(0);
00669               // Then we solve (D/omega - L) X = X.
00670               for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
00671                 {
00672                   p = ind_real[k];
00673                   val = complex<T0>(data_real[k], 0);
00674                   if (p == j)
00675                     ajj += val;
00676                 }
00677 
00678               for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
00679                 {
00680                   p = ind_imag[k];
00681                   val = complex<T0>(0, data_imag[k]);
00682                   if (p == j)
00683                     ajj += val;
00684                 }
00685               X(j) *= omega / ajj;
00686 
00687               for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
00688                 {
00689                   p = ind_real[k];
00690                   val = complex<T0>(data_real[k], 0);
00691                   if (p != j)
00692                     X(p) -= val*X(j);
00693                 }
00694 
00695               for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
00696                 {
00697                   p = ind_imag[k];
00698                   val = complex<T0>(0, data_imag[k]);
00699                   if (p != j)
00700                     X(p) -= val*X(j);
00701                 }
00702             }
00703         }
00704 
00705     // Backward sweep.
00706     // (D/omega - U) X^{n+1} = (L + (1-omega)/omega D) X^{n+1/2} + B
00707     if (type_ssor % 3 == 0)
00708       for (int i = 0; i < iter; i++)
00709         {
00710           Y.Zero();
00711 
00712           for (int j = 0; j < ma; j++)
00713             {
00714               ajj = complex<T0>(0);
00715               // Then we compute X = (L + (1-omega)/omega D) X + B.
00716               for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
00717                 {
00718                   p = ind_real[k];
00719                   val = complex<T0>(data_real[k], 0);
00720                   if (p == j)
00721                     ajj += val;
00722                   else
00723                     Y(p) += val * X(j);
00724                 }
00725 
00726               for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
00727                 {
00728                   p = ind_imag[k];
00729                   val = complex<T0>(0, data_imag[k]);
00730                   if (p == j)
00731                     ajj += val;
00732                   else
00733                     Y(p) += val * X(j);
00734                 }
00735               X(j) = (T2(1) - omega) / omega * ajj * X(j) + B(j) - Y(j);
00736             }
00737 
00738           for (int j = (ma-1); j >= 0; j--)
00739             {
00740               temp = complex<T1>(0);
00741               ajj = complex<T0>(0);
00742               // Then we solve (D/omega - U) X = X.
00743               for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
00744                 {
00745                   p = ind_real[k];
00746                   val = complex<T0>(data_real[k], 0);
00747                   if (p == j)
00748                     ajj += val;
00749                   else
00750                     temp += val * X(p);
00751                 }
00752 
00753               for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
00754                 {
00755                   p = ind_imag[k];
00756                   val = complex<T0>(0, data_imag[k]);
00757                   if (p == j)
00758                     ajj += val;
00759                   else
00760                     temp += val * X(p);
00761                 }
00762               X(j) = (X(j) - temp) * omega / ajj;
00763             }
00764         }
00765   }
00766 
00767 
00769 
00776   template <class T0, class Prop0, class Allocator0,
00777             class T1, class Storage1, class Allocator1,
00778             class T2, class Storage2, class Allocator2, class T3>
00779   void SOR(const Matrix<T0, Prop0, ArrayRowSymComplexSparse, Allocator0>& A,
00780            Vector<complex<T2>, Storage2, Allocator2>& X,
00781            const Vector<complex<T1>, Storage1, Allocator1>& B,
00782            const T3& omega, int iter, int type_ssor = 2)
00783   {
00784     complex<T1> temp(0);
00785 
00786     int ma = A.GetM();
00787 
00788 #ifdef SELDON_CHECK_BOUNDS
00789     int na = A.GetN();
00790     if (na != ma)
00791       throw WrongDim("SOR", "Matrix must be squared.");
00792 
00793     if (ma != X.GetLength() || ma != B.GetLength())
00794       throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
00795 #endif
00796 
00797     Vector<complex<T2>, Storage2, Allocator2> Y(ma);
00798     Y.Zero();
00799     complex<T0> ajj(1);
00800     int p;
00801     complex<T0> val(0);
00802     // Let us consider the following splitting : A = D - L - U
00803     // D diagonal of A
00804     // L lower part of A
00805     // U upper part of A, A is symmetric, so L = U^t
00806     // forward sweep
00807     // (D/omega - L) X^{n+1/2} = (U + (1-omega)/omega D) X^n + B
00808     if (type_ssor % 2 == 0)
00809       for (int i = 0; i < iter; i++)
00810         {
00811           for (int j = 0; j < ma; j++)
00812             {
00813               // First we do X = (U + (1-omega)/omega D) X + B
00814               temp = complex<T1>(0);
00815               ajj = complex<T0>(0);
00816               for (int k = 0; k < A.GetRealRowSize(j); k++)
00817                 {
00818                   p = A.IndexReal(j,k);
00819                   val = complex<T0>(A.ValueReal(j,k), 0);
00820                   if (p == j)
00821                     ajj += val;
00822                   else
00823                     temp += val * X(p);
00824                 }
00825               for (int k = 0; k < A.GetImagRowSize(j); k++)
00826                 {
00827                   p = A.IndexImag(j,k);
00828                   val = complex<T0>(0, A.ValueImag(j,k));
00829                   if (p == j)
00830                     ajj += val;
00831                   else
00832                     temp += val * X(p);
00833                 }
00834 
00835               temp = B(j) - temp;
00836               X(j) = (T2(1) - omega) / omega * ajj * X(j) + temp;
00837             }
00838 
00839           for (int j = 0; j < ma; j++)
00840             {
00841               ajj = complex<T0>(0);
00842               // Then we solve (D/omega - L) X = X.
00843               for (int k = 0; k < A.GetRealRowSize(j); k++)
00844                 {
00845                   p = A.IndexReal(j,k);
00846                   val = complex<T0>(A.ValueReal(j,k), 0);
00847                   if (p == j)
00848                     ajj += val;
00849                 }
00850               for (int k = 0; k < A.GetImagRowSize(j); k++)
00851                 {
00852                   p = A.IndexImag(j,k);
00853                   val = complex<T0>(0, A.ValueImag(j,k));
00854                   if (p == j)
00855                     ajj += val;
00856                 }
00857               X(j) *= omega / ajj;
00858               for (int k = 0; k < A.GetRealRowSize(j); k++)
00859                 {
00860                   p = A.IndexReal(j,k);
00861                   val = complex<T0>(A.ValueReal(j,k), 0);
00862                   if (p != j)
00863                     X(p) -= val * X(j);
00864                 }
00865               for (int k = 0; k < A.GetImagRowSize(j); k++)
00866                 {
00867                   p = A.IndexImag(j,k);
00868                   val = complex<T0>(0, A.ValueImag(j,k));
00869                   if (p != j)
00870                     X(p) -= val*X(j);
00871                 }
00872             }
00873         }
00874 
00875     // Backward sweep.
00876     // (D/omega - U) X^{n+1} = (L + (1-omega)/omega D) X^{n+1/2} + B
00877     if (type_ssor % 3 == 0)
00878       for (int i = 0; i < iter; i++)
00879         {
00880           Y.Zero();
00881 
00882           for (int j = 0; j < ma; j++)
00883             {
00884               ajj = complex<T0>(0);
00885               // Then we compute X = (L + (1-omega)/omega D) X + B.
00886               for (int k = 0; k < A.GetRealRowSize(j); k++)
00887                 {
00888                   p = A.IndexReal(j,k);
00889                   val = complex<T0>(A.ValueReal(j,k), 0);
00890                   if (p == j)
00891                     ajj += val;
00892                   else
00893                     Y(p) += val * X(j);
00894                 }
00895               for (int k = 0; k < A.GetImagRowSize(j); k++)
00896                 {
00897                   p = A.IndexImag(j,k);
00898                   val = complex<T0>(0, A.ValueImag(j,k));
00899                   if (p == j)
00900                     ajj += val;
00901                   else
00902                     Y(p) += val * X(j);
00903                 }
00904               X(j) = (T2(1) - omega) / omega * ajj * X(j) + B(j) - Y(j);
00905             }
00906 
00907           for (int j = ma-1; j >= 0; j--)
00908             {
00909               temp = complex<T1>(0);
00910               ajj = complex<T0>(0);
00911               // Then we solve (D/omega - U) X = X.
00912               for (int k = 0; k < A.GetRealRowSize(j); k++)
00913                 {
00914                   p = A.IndexReal(j,k);
00915                   val = complex<T0>(A.ValueReal(j,k), 0);
00916                   if (p == j)
00917                     ajj += val;
00918                   else
00919                     temp += val * X(p);
00920                 }
00921               for (int k = 0; k < A.GetImagRowSize(j); k++)
00922                 {
00923                   p = A.IndexImag(j,k);
00924                   val = complex<T0>(0, A.ValueImag(j,k));
00925                   if (p == j)
00926                     ajj += val;
00927                   else
00928                     temp += val * X(p);
00929                 }
00930               X(j) = (X(j) - temp) * omega / ajj;
00931             }
00932         }
00933   }
00934 
00935 
00936 } // end namespace
00937 
00938 #define SELDON_FILE_RELAXATION_MATVECT_CXX
00939 #endif