// Copyright (C) 2003-2009 Marc Duruflé
// Copyright (C) 2001-2009 Vivien Mallet
//
// This file is part of the linear-algebra library Seldon,
// http://seldon.sourceforge.net/.
//
// Seldon is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2.1 of the License, or (at your option)
// any later version.
//
// Seldon is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
// more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Seldon. If not, see http://www.gnu.org/licenses/.
#ifndef SELDON_FILE_RELAXATION_MATVECT_CXX
/*
Functions defined in this file
SOR(A, X, B, omega, iter, type_ssor)
*/
namespace Seldon
{
//! Successive overrelaxation.
/*!
Solving A X = B by using S.O.R algorithm.
omega is the relaxation parameter, iter the number of iterations.
type_ssor = 2 forward sweep
type_ssor = 3 backward sweep
type_ssor = 0 forward and backward sweep
*/
template <class T0, class Prop0, class Allocator0,
class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2, class T3>
void SOR(const Matrix<T0, Prop0, RowSparse, Allocator0>& A,
Vector<T2, Storage2, Allocator2>& X,
const Vector<T1, Storage1, Allocator1>& B,
const T3& omega, int iter, int type_ssor = 2)
{
T1 temp(0);
int ma = A.GetM();
#ifdef SELDON_CHECK_BOUNDS
int na = A.GetN();
if (na != ma)
throw WrongDim("SOR", "Matrix must be squared.");
if (ma != X.GetLength() || ma != B.GetLength())
throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
#endif
int* ptr = A.GetPtr();
int* ind = A.GetInd();
typename Matrix<T0, Prop0, RowSparse, Allocator0>::pointer data
= A.GetData();
T0 ajj(1);
// Forward sweep.
if (type_ssor % 2 == 0)
for (int i = 0; i < iter; i++)
for (int j = 0; j < ma; j++)
{
temp = T1(0);
ajj = A(j, j);
for (int k = ptr[j] ; k < ptr[j+1]; k++)
temp += data[k] * X(ind[k]);
temp = B(j) - temp + ajj * X(j);
X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
}
// Backward sweep.
if (type_ssor % 3 == 0)
for (int i = 0; i < iter; i++)
for (int j = ma-1 ; j >= 0; j--)
{
temp = T1(0);
ajj = A(j, j);
for (int k = ptr[j]; k < ptr[j+1]; k++)
temp += data[k] * X(ind[k]);
temp = B(j) - temp + ajj * X(j);
X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
}
}
//! Successive overrelaxation.
/*!
Solving A X = B by using S.O.R algorithm.
omega is the relaxation parameter, iter the number of iterations.
type_ssor = 2 forward sweep
type_ssor = 3 backward sweep
type_ssor = 0 forward and backward sweep
*/
template <class T0, class Prop0, class Allocator0,
class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2, class T3>
void SOR(const Matrix<T0, Prop0, ArrayRowSparse, Allocator0>& A,
Vector<T2, Storage2, Allocator2>& X,
const Vector<T1, Storage1, Allocator1>& B,
const T3& omega,
int iter, int type_ssor = 2)
{
T1 temp(0);
int ma = A.GetM();
#ifdef SELDON_CHECK_BOUNDS
int na = A.GetN();
if (na != ma)
throw WrongDim("SOR", "Matrix must be squared.");
if (ma != X.GetLength() || ma != B.GetLength())
throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
#endif
T0 ajj(1);
// Forward sweep.
if (type_ssor % 2 == 0)
for (int i = 0; i < iter; i++)
for (int j = 0; j < ma; j++)
{
temp = T1(0);
ajj = T0(0);
for (int k = 0; k < A.GetRowSize(j); k++)
{
temp += A.Value(j,k) * X(A.Index(j,k));
if (A.Index(j,k) == j)
ajj += A.Value(j,k);
}
temp = B(j) - temp + ajj * X(j);
X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
}
// Backward sweep.
if (type_ssor % 3 == 0)
for (int i = 0; i < iter; i++)
for (int j = ma-1; j >= 0; j--)
{
temp = T1(0);
ajj = T0(0);
for (int k = 0; k < A.GetRowSize(j); k++)
{
temp += A.Value(j,k) * X(A.Index(j,k));
if (A.Index(j,k) == j)
ajj += A.Value(j,k);
}
temp = B(j) - temp + ajj * X(j);
X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
}
}
//! Successive overrelaxation.
/*!
Solving A X = B by using S.O.R algorithm.
omega is the relaxation parameter, iter the number of iterations.
type_ssor = 2 forward sweep
type_ssor = 3 backward sweep
type_ssor = 0 forward and backward sweep
*/
template <class T0, class Prop0, class Allocator0,
class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2, class T3>
void SOR(const Matrix<T0, Prop0, RowSymSparse, Allocator0>& A,
Vector<T2, Storage2, Allocator2>& X,
const Vector<T1, Storage1, Allocator1>& B,
const T3& omega,int iter, int type_ssor = 2)
{
T1 temp(0);
int ma = A.GetM();
#ifdef SELDON_CHECK_BOUNDS
int na = A.GetN();
if (na != ma)
throw WrongDim("SOR", "Matrix must be squared.");
if (ma != X.GetLength() || ma != B.GetLength())
throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
#endif
int* ptr = A.GetPtr();
int* ind = A.GetInd();
T0* data = A.GetData();
Vector<T2, Storage2, Allocator2> Y(ma);
Y.Zero();
T0 ajj(1);
int p;
T0 val(0);
// Let us consider the following splitting : A = D - L - U
// D diagonal of A
// L lower part of A
// U upper part of A, A is symmetric, so L = U^t
// Forward sweep
// (D/omega - L) X^{n+1/2} = (U + (1-omega)/omega D) X^n + B
if (type_ssor % 2 == 0)
for (int i = 0; i < iter; i++)
{
for (int j = 0; j < ma; j++)
{
// First we do X = (U + (1-omega)/omega D) X + B
temp = T1(0);
ajj = T0(0);
for (int k = ptr[j]; k < ptr[j+1]; k++)
{
p = ind[k];
val = data[k];
if (p == j)
ajj += val;
else
temp += val * X(p);
}
temp = B(j) - temp;
X(j) = (T2(1) - omega) / omega * ajj * X(j) + temp;
}
for (int j = 0; j < ma; j++)
{
ajj = T0(0);
// Then we solve (D/omega - L) X = X
for (int k = ptr[j]; k < ptr[j+1]; k++)
{
p = ind[k];
val = data[k];
if (p == j)
ajj += val;
}
X(j) *= omega / ajj;
for (int k = ptr[j]; k < ptr[j+1]; k++)
{
p = ind[k];
val = data[k];
if (p != j)
X(p) -= val*X(j);
}
}
}
// Backward sweep.
// (D/omega - U) X^{n+1} = (L + (1-omega)/omega D) X^{n+1/2} + B
if (type_ssor % 3 == 0)
for (int i = 0; i < iter; i++)
{
Y.Zero();
for (int j = 0; j < ma; j++)
{
ajj = T0(0);
// Then we compute X = (L + (1-omega)/omega D) X + B.
for (int k = ptr[j]; k < ptr[j+1]; k++)
{
p = ind[k];
val = data[k];
if (p == j)
ajj += val;
else
Y(p) += val*X(j);
}
X(j) = (T2(1) - omega) / omega * ajj * X(j) + B(j) - Y(j);
}
for (int j = ma-1; j >= 0; j--)
{
temp = T1(0);
ajj = T0(0);
// Then we solve (D/omega - U) X = X.
for (int k = ptr[j]; k < ptr[j+1]; k++)
{
p = ind[k];
val = data[k];
if (p == j)
ajj += val;
else
temp += val*X(p);
}
X(j) = (X(j) - temp) * omega / ajj;
}
}
}
//! Successive overrelaxation.
/*!
Solving A X = B by using S.O.R algorithm.
omega is the relaxation parameter, iter the number of iterations.
type_ssor = 2 forward sweep
type_ssor = 3 backward sweep
type_ssor = 0 forward and backward sweep
*/
template <class T0, class Prop0, class Allocator0,
class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2, class T3>
void SOR(const Matrix<T0, Prop0, ArrayRowSymSparse, Allocator0>& A,
Vector<T2, Storage2, Allocator2>& X,
const Vector<T1, Storage1, Allocator1>& B,
const T3& omega,int iter, int type_ssor = 2)
{
T1 temp(0);
int ma = A.GetM();
#ifdef SELDON_CHECK_BOUNDS
int na = A.GetN();
if (na != ma)
throw WrongDim("SOR", "Matrix must be squared.");
if (ma != X.GetLength() || ma != B.GetLength())
throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
#endif
Vector<T2,Storage2,Allocator2> Y(ma);
Y.Zero();
T0 ajj(1);
int p; T0 val(0);
// Let us consider the following splitting : A = D - L - U
// D diagonal of A
// L lower part of A
// U upper part of A, A is symmetric, so L = U^t
// Forward sweep.
// (D/omega - L) X^{n+1/2} = (U + (1-omega)/omega D) X^n + B
if (type_ssor % 2 == 0)
for (int i = 0; i < iter; i++)
{
for (int j = 0; j < ma; j++)
{
// First we do X = (U + (1-omega)/omega D) X + B.
temp = T1(0);
ajj = T0(0);
for (int k = 0; k < A.GetRowSize(j); k++)
{
p = A.Index(j,k);
val = A.Value(j,k);
if (p == j)
ajj += val;
else
temp += val * X(p);
}
temp = B(j) - temp;
X(j) = (T2(1) - omega) / omega * ajj * X(j) + temp;
}
for (int j = 0; j < ma; j++)
{
ajj = T0(0);
// Then we solve (D/omega - L) X = X.
for (int k = 0; k < A.GetRowSize(j); k++)
{
p = A.Index(j,k);
val = A.Value(j,k);
if (p == j)
ajj += val;
}
X(j) *= omega / ajj;
for (int k = 0 ; k < A.GetRowSize(j); k++)
{
p = A.Index(j,k);
val = A.Value(j,k);
if (p != j)
X(p) -= val*X(j);
}
}
}
// Backward sweep.
// (D/omega - U) X^{n+1} = (L + (1-omega)/omega D) X^{n+1/2} + B
if (type_ssor % 3 == 0)
for (int i = 0; i < iter; i++)
{
Y.Zero();
for (int j = 0; j < ma; j++)
{
ajj = T0(0);
// Then we compute X = (L + (1-omega)/omega D) X + B.
for (int k = 0; k < A.GetRowSize(j); k++)
{
p = A.Index(j,k);
val = A.Value(j,k);
if (p == j)
ajj += val;
else
Y(p) += val*X(j);
}
X(j) = (T2(1) - omega) / omega * ajj * X(j) + B(j) - Y(j);
}
for (int j = ma-1; j >= 0; j--)
{
temp = T1(0);
ajj = T0(0);
// Then we solve (D/omega - U) X = X.
for (int k = 0; k < A.GetRowSize(j); k++)
{
p = A.Index(j,k);
val = A.Value(j,k);
if (p == j)
ajj += val;
else
temp += val * X(p);
}
X(j) = (X(j) - temp) * omega / ajj;
}
}
}
//! Successive overrelaxation.
/*!
Solving A X = B by using S.O.R algorithm.
omega is the relaxation parameter, iter the number of iterations.
type_ssor = 2 forward sweep
type_ssor = 3 backward sweep
type_ssor = 0 forward and backward sweep
*/
template <class T0, class Prop0, class Allocator0,
class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2, class T3>
void SOR(const Matrix<T0, Prop0, RowComplexSparse, Allocator0>& A,
Vector<complex<T2>, Storage2, Allocator2>& X,
const Vector<complex<T1>, Storage1, Allocator1>& B,
const T3& omega, int iter, int type_ssor = 2)
{
complex<T1> temp(0);
int ma = A.GetM();
#ifdef SELDON_CHECK_BOUNDS
int na = A.GetN();
if (na != ma)
throw WrongDim("SOR", "Matrix must be squared.");
if (ma != X.GetLength() || ma != B.GetLength())
throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
#endif
int* ptr_real = A.GetRealPtr();
int* ptr_imag = A.GetImagPtr();
int* ind_real = A.GetRealInd();
int* ind_imag = A.GetImagInd();
typename Matrix<T0, Prop0, RowComplexSparse, Allocator0>::pointer
data_real = A.GetRealData();
typename Matrix<T0, Prop0, RowComplexSparse, Allocator0>::pointer
data_imag = A.GetImagData();
complex<T0> ajj(1);
if (type_ssor % 2 == 0)
for (int i = 0; i < iter; i++)
for (int j = 0; j < ma; j++)
{
temp = complex<T1>(0);
ajj = A(j,j);
for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
temp += data_real[k] * X(ind_real[k]);
for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
temp += complex<T1>(0, data_imag[k]) * X(ind_imag[k]);
temp = B(j) - temp + ajj*X(j);
X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
}
if (type_ssor % 3 == 0)
for (int i = 0; i < iter; i++)
for (int j = ma-1; j >= 0; j--)
{
temp = complex<T1>(0);
ajj = A(j,j);
for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
temp += data_real[k] * X(ind_real[k]);
for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
temp += complex<T1>(0, data_imag[k]) * X(ind_imag[k]);
temp = B(j) - temp + ajj * X(j);
X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
}
}
//! Successive overrelaxation.
/*!
Solving A X = B by using S.O.R algorithm.
omega is the relaxation parameter, iter the number of iterations.
type_ssor = 2 forward sweep
type_ssor = 3 backward sweep
type_ssor = 0 forward and backward sweep
*/
template <class T0, class Prop0, class Allocator0,
class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2, class T3>
void SOR(const Matrix<T0, Prop0, ArrayRowComplexSparse, Allocator0>& A,
Vector<complex<T2>, Storage2, Allocator2>& X,
const Vector<complex<T1>, Storage1, Allocator1>& B,
const T3& omega, int iter, int type_ssor = 2)
{
complex<T1> temp(0);
int ma = A.GetM();
#ifdef SELDON_CHECK_BOUNDS
int na = A.GetN();
if (na != ma)
throw WrongDim("SOR", "Matrix must be squared.");
if (ma != X.GetLength() || ma != B.GetLength())
throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
#endif
complex<T0> ajj(1);
if (type_ssor%2 == 0)
for (int i = 0; i < iter; i++)
{
for (int j = 0; j < ma; j++)
{
temp = complex<T1>(0);
ajj = complex<T0>(0);
for (int k = 0; k < A.GetRealRowSize(j); k++)
{
temp += A.ValueReal(j,k) * X(A.IndexReal(j,k));
if (A.IndexReal(j,k) == j)
ajj += complex<T0>(A.ValueReal(j,k), 0);
}
for (int k = 0; k < A.GetImagRowSize(j); k++)
{
temp += complex<T0>(0,A.ValueImag(j,k))
* X(A.IndexImag(j,k));
if (A.IndexImag(j,k) == j)
ajj += complex<T0>(0, A.ValueImag(j,k));
}
temp = B(j) - temp + ajj * X(j);
X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
}
}
if (type_ssor % 3 == 0)
for (int i = 0; i < iter; i++)
for (int j = ma-1; j >= 0; j--)
{
temp = complex<T1>(0);
ajj = complex<T0>(0);
for (int k = 0; k < A.GetRealRowSize(j); k++)
{
temp += A.ValueReal(j,k) * X(A.IndexReal(j,k));
if (A.IndexReal(j,k) == j)
ajj += complex<T0>(A.ValueReal(j,k), 0);
}
for (int k = 0; k < A.GetImagRowSize(j); k++)
{
temp += complex<T0>(0, A.ValueImag(j,k))
* X(A.IndexImag(j,k));
if (A.IndexImag(j,k) == j)
ajj += complex<T0>(0, A.ValueImag(j,k));
}
temp = B(j) - temp + ajj * X(j);
X(j) = (T2(1) - omega) * X(j) + omega * temp / ajj;
}
}
//! Successive overrelaxation.
/*!
Solving A X = B by using S.O.R algorithm.
omega is the relaxation parameter, iter the number of iterations.
type_ssor = 2 forward sweep
type_ssor = 3 backward sweep
type_ssor = 0 forward and backward sweep
*/
template <class T0, class Prop0, class Allocator0,
class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2, class T3>
void SOR(const Matrix<T0, Prop0, RowSymComplexSparse, Allocator0>& A,
Vector<complex<T2>, Storage2, Allocator2>& X,
const Vector<complex<T1>, Storage1, Allocator1>& B,
const T3& omega, int iter, int type_ssor = 2)
{
complex<T1> temp(0);
int ma = A.GetM();
#ifdef SELDON_CHECK_BOUNDS
int na = A.GetN();
if (na != ma)
throw WrongDim("SOR", "Matrix must be squared.");
if (ma != X.GetLength() || ma != B.GetLength())
throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
#endif
int* ptr_real = A.GetRealPtr();
int* ptr_imag = A.GetImagPtr();
int* ind_real = A.GetRealInd();
int* ind_imag = A.GetImagInd();
T0* data_real = A.GetRealData();
T0* data_imag = A.GetImagData();
Vector<complex<T2>, Storage2, Allocator2> Y(ma);
Y.Zero();
complex<T0> ajj(1);
int p;
complex<T0> val(0);
// Let us consider the following splitting : A = D - L - U
// D diagonal of A
// L lower part of A
// U upper part of A, A is symmetric, so L = U^t
// forward sweep
// (D/omega - L) X^{n+1/2} = (U + (1-omega)/omega D) X^n + B
if (type_ssor % 2 == 0)
for (int i = 0; i < iter; i++)
{
for (int j = 0; j < ma; j++)
{
// first we do X = (U + (1-omega)/omega D) X + B
temp = complex<T1>(0);
ajj = complex<T0>(0);
for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
{
p = ind_real[k];
val = complex<T0>(data_real[k], 0);
if (p == j)
ajj += val;
else
temp += val * X(p);
}
for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
{
p = ind_imag[k];
val = complex<T0>(0, data_imag[k]);
if (p == j)
ajj += val;
else
temp += val * X(p);
}
temp = B(j) - temp;
X(j) = (T2(1) - omega) / omega * ajj * X(j) + temp;
}
for (int j = 0; j < ma; j++)
{
ajj = complex<T0>(0);
// Then we solve (D/omega - L) X = X.
for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
{
p = ind_real[k];
val = complex<T0>(data_real[k], 0);
if (p == j)
ajj += val;
}
for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
{
p = ind_imag[k];
val = complex<T0>(0, data_imag[k]);
if (p == j)
ajj += val;
}
X(j) *= omega / ajj;
for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
{
p = ind_real[k];
val = complex<T0>(data_real[k], 0);
if (p != j)
X(p) -= val*X(j);
}
for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
{
p = ind_imag[k];
val = complex<T0>(0, data_imag[k]);
if (p != j)
X(p) -= val*X(j);
}
}
}
// Backward sweep.
// (D/omega - U) X^{n+1} = (L + (1-omega)/omega D) X^{n+1/2} + B
if (type_ssor % 3 == 0)
for (int i = 0; i < iter; i++)
{
Y.Zero();
for (int j = 0; j < ma; j++)
{
ajj = complex<T0>(0);
// Then we compute X = (L + (1-omega)/omega D) X + B.
for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
{
p = ind_real[k];
val = complex<T0>(data_real[k], 0);
if (p == j)
ajj += val;
else
Y(p) += val * X(j);
}
for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
{
p = ind_imag[k];
val = complex<T0>(0, data_imag[k]);
if (p == j)
ajj += val;
else
Y(p) += val * X(j);
}
X(j) = (T2(1) - omega) / omega * ajj * X(j) + B(j) - Y(j);
}
for (int j = (ma-1); j >= 0; j--)
{
temp = complex<T1>(0);
ajj = complex<T0>(0);
// Then we solve (D/omega - U) X = X.
for (int k = ptr_real[j]; k < ptr_real[j+1]; k++)
{
p = ind_real[k];
val = complex<T0>(data_real[k], 0);
if (p == j)
ajj += val;
else
temp += val * X(p);
}
for (int k = ptr_imag[j]; k < ptr_imag[j+1]; k++)
{
p = ind_imag[k];
val = complex<T0>(0, data_imag[k]);
if (p == j)
ajj += val;
else
temp += val * X(p);
}
X(j) = (X(j) - temp) * omega / ajj;
}
}
}
//! Successive overrelaxation.
/*!
Solving A X = B by using S.O.R algorithm.
omega is the relaxation parameter, iter the number of iterations.
type_ssor = 2 forward sweep
type_ssor = 3 backward sweep
type_ssor = 0 forward and backward sweep
*/
template <class T0, class Prop0, class Allocator0,
class T1, class Storage1, class Allocator1,
class T2, class Storage2, class Allocator2, class T3>
void SOR(const Matrix<T0, Prop0, ArrayRowSymComplexSparse, Allocator0>& A,
Vector<complex<T2>, Storage2, Allocator2>& X,
const Vector<complex<T1>, Storage1, Allocator1>& B,
const T3& omega, int iter, int type_ssor = 2)
{
complex<T1> temp(0);
int ma = A.GetM();
#ifdef SELDON_CHECK_BOUNDS
int na = A.GetN();
if (na != ma)
throw WrongDim("SOR", "Matrix must be squared.");
if (ma != X.GetLength() || ma != B.GetLength())
throw WrongDim("SOR", "Matrix and vector dimensions are incompatible.");
#endif
Vector<complex<T2>, Storage2, Allocator2> Y(ma);
Y.Zero();
complex<T0> ajj(1);
int p;
complex<T0> val(0);
// Let us consider the following splitting : A = D - L - U
// D diagonal of A
// L lower part of A
// U upper part of A, A is symmetric, so L = U^t
// forward sweep
// (D/omega - L) X^{n+1/2} = (U + (1-omega)/omega D) X^n + B
if (type_ssor % 2 == 0)
for (int i = 0; i < iter; i++)
{
for (int j = 0; j < ma; j++)
{
// First we do X = (U + (1-omega)/omega D) X + B
temp = complex<T1>(0);
ajj = complex<T0>(0);
for (int k = 0; k < A.GetRealRowSize(j); k++)
{
p = A.IndexReal(j,k);
val = complex<T0>(A.ValueReal(j,k), 0);
if (p == j)
ajj += val;
else
temp += val * X(p);
}
for (int k = 0; k < A.GetImagRowSize(j); k++)
{
p = A.IndexImag(j,k);
val = complex<T0>(0, A.ValueImag(j,k));
if (p == j)
ajj += val;
else
temp += val * X(p);
}
temp = B(j) - temp;
X(j) = (T2(1) - omega) / omega * ajj * X(j) + temp;
}
for (int j = 0; j < ma; j++)
{
ajj = complex<T0>(0);
// Then we solve (D/omega - L) X = X.
for (int k = 0; k < A.GetRealRowSize(j); k++)
{
p = A.IndexReal(j,k);
val = complex<T0>(A.ValueReal(j,k), 0);
if (p == j)
ajj += val;
}
for (int k = 0; k < A.GetImagRowSize(j); k++)
{
p = A.IndexImag(j,k);
val = complex<T0>(0, A.ValueImag(j,k));
if (p == j)
ajj += val;
}
X(j) *= omega / ajj;
for (int k = 0; k < A.GetRealRowSize(j); k++)
{
p = A.IndexReal(j,k);
val = complex<T0>(A.ValueReal(j,k), 0);
if (p != j)
X(p) -= val * X(j);
}
for (int k = 0; k < A.GetImagRowSize(j); k++)
{
p = A.IndexImag(j,k);
val = complex<T0>(0, A.ValueImag(j,k));
if (p != j)
X(p) -= val*X(j);
}
}
}
// Backward sweep.
// (D/omega - U) X^{n+1} = (L + (1-omega)/omega D) X^{n+1/2} + B
if (type_ssor % 3 == 0)
for (int i = 0; i < iter; i++)
{
Y.Zero();
for (int j = 0; j < ma; j++)
{
ajj = complex<T0>(0);
// Then we compute X = (L + (1-omega)/omega D) X + B.
for (int k = 0; k < A.GetRealRowSize(j); k++)
{
p = A.IndexReal(j,k);
val = complex<T0>(A.ValueReal(j,k), 0);
if (p == j)
ajj += val;
else
Y(p) += val * X(j);
}
for (int k = 0; k < A.GetImagRowSize(j); k++)
{
p = A.IndexImag(j,k);
val = complex<T0>(0, A.ValueImag(j,k));
if (p == j)
ajj += val;
else
Y(p) += val * X(j);
}
X(j) = (T2(1) - omega) / omega * ajj * X(j) + B(j) - Y(j);
}
for (int j = ma-1; j >= 0; j--)
{
temp = complex<T1>(0);
ajj = complex<T0>(0);
// Then we solve (D/omega - U) X = X.
for (int k = 0; k < A.GetRealRowSize(j); k++)
{
p = A.IndexReal(j,k);
val = complex<T0>(A.ValueReal(j,k), 0);
if (p == j)
ajj += val;
else
temp += val * X(p);
}
for (int k = 0; k < A.GetImagRowSize(j); k++)
{
p = A.IndexImag(j,k);
val = complex<T0>(0, A.ValueImag(j,k));
if (p == j)
ajj += val;
else
temp += val * X(p);
}
X(j) = (X(j) - temp) * omega / ajj;
}
}
}
} // end namespace
#define SELDON_FILE_RELAXATION_MATVECT_CXX
#endif