Warning: this documentation for the development version is under construction.
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