diff --git a/MathLib/CMakeLists.txt b/MathLib/CMakeLists.txt index d36ba1f15b63244666ee1fdc9ae93a904dae4073..c9163e823dfe730ce1833efb2339bfe330a70750 100644 --- a/MathLib/CMakeLists.txt +++ b/MathLib/CMakeLists.txt @@ -20,6 +20,8 @@ SET( HEADERS LinAlg/Solvers/TriangularSolve.h LinAlg/Solvers/IterativeLinearSolver.h LinAlg/Solvers/solver.h + LinAlg/Solvers/CG.h + LinAlg/Solvers/BiCGStab.h LinAlg/Sparse/amuxCRS.h LinAlg/Sparse/CRSMatrix.h LinAlg/Sparse/CRSMatrixPThreads.h @@ -36,6 +38,7 @@ SET( SOURCES LinkedTriangle.cpp LinAlg/Sparse/amuxCRS.cpp LinAlg/Solvers/CG.cpp + LinAlg/Solvers/BiCGStab.cpp LinAlg/Solvers/GaussAlgorithm.cpp LinAlg/Solvers/TriangularSolve.cpp LinAlg/Preconditioner/generateDiagPrecond.cpp diff --git a/MathLib/LinAlg/Solvers/BiCGStab.cpp b/MathLib/LinAlg/Solvers/BiCGStab.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bfd57b11377e20433343510affc282ab4e533ad3 --- /dev/null +++ b/MathLib/LinAlg/Solvers/BiCGStab.cpp @@ -0,0 +1,135 @@ +/* + * BiCGStab.cpp + * + * Created on: Oct 4, 2011 + * Author: TF + */ + +#include "BiCGStab.h" + +#include "MathTools.h" +#include "blas.h" + +namespace MathLib { + +unsigned BiCGStab(CRSMatrix<double> const& A, double* const b, double* const x, + double& eps, unsigned& nsteps) +{ + unsigned N(A.getNRows()); + double *v (new double[8* N]); + double *p (v + N); + double *phat (p + N); + double *s (phat + N); + double *shat (s + N); + double *t (shat + N); + double *r (t + N); + double *r0 (r + N); + double resid; + + // normb = |b| + double nrmb = blas::nrm2(N, b); + if (nrmb < D_PREC) nrmb = D_ONE; + + // r = r0 = b - A x0 + blas::copy(N, b, r0); + A.amux(D_MONE, x, r0); + blas::copy(N, r0, r); + + resid = blas::nrm2(N, r) / nrmb; + + if (resid < eps) { + eps = resid; + nsteps = 0; + delete[] v; + return 0; + } + + double alpha = D_ZERO, omega = D_ZERO, rho2 = D_ZERO; + + for (unsigned l = 1; l <= nsteps; ++l) { + // rho1 = r0 * r + const double rho1 = blas::scpr(N, r0, r); + if (fabs(rho1) < D_PREC) { + eps = blas::nrm2(N, r) / nrmb; + delete[] v; + return 2; + } + + if (l == 1) + blas::copy(N, r, p); // p = r + else { + blas::axpy(N, -omega, v, p); // p = (p-omega v)*beta+r + const double beta = rho1 * alpha / (rho2 * omega); + blas::scal(N, beta, p); + blas::axpy(N, D_ONE, r, p); + } + + // p^ = C p + blas::copy(N, p, phat); + A.precondApply(phat); + // v = A p^ + blas::setzero(N, v); + A.amux(D_ONE, phat, v); + + alpha = rho1 / blas::scpr(N, r0, v); + + // s = r - alpha v + blas::copy(N, r, s); + blas::axpy(N, -alpha, v, s); + + resid = blas::nrm2(N, s) / nrmb; +#ifndef NDEBUG + std::cout << "Step " << l << ", resid=" << resid << std::endl; +#endif + if (resid < eps) { + // x += alpha p^ + blas::axpy(N, alpha, phat, x); + eps = resid; + nsteps = l; + delete[] v; + return 0; + } + + // s^ = C s + blas::copy(N, s, shat); + A.precondApply(shat); + + // t = A s^ + blas::setzero(N, t); + A.amux(D_ONE, shat, t); + + // omega = t*s / t*t + omega = blas::scpr(N, t, s) / blas::scpr(N, t, t); + + // x += alpha p^ + omega s^ + blas::axpy(N, alpha, phat, x); + blas::axpy(N, omega, shat, x); + + // r = s - omega t + blas::copy(N, s, r); + blas::axpy(N, -omega, t, r); + + rho2 = rho1; + + resid = blas::nrm2(N, r) / nrmb; + + if (resid < eps) { + eps = resid; + nsteps = l; + delete[] v; + return 0; + } + + if (fabs(omega) < D_PREC) { + eps = resid; + delete[] v; + return 3; + } + } + + eps = resid; + delete[] v; + return 1; +} + +} // end namespace MathLib diff --git a/MathLib/LinAlg/Solvers/BiCGStab.h b/MathLib/LinAlg/Solvers/BiCGStab.h new file mode 100644 index 0000000000000000000000000000000000000000..1f7821b7f29494955e229bfa7d0d9923013ce725 --- /dev/null +++ b/MathLib/LinAlg/Solvers/BiCGStab.h @@ -0,0 +1,22 @@ +/* + * BiCGStab.h + * + * Created on: Oct 4, 2011 + * Author: TF + */ + +#ifndef BICGSTAB_H_ +#define BICGSTAB_H_ + +#include "blas.h" +#include "../Sparse/CRSMatrix.h" +#include "../Sparse/CRSMatrixDiagPrecond.h" + +namespace MathLib { + +unsigned BiCGStab(CRSMatrix<double> const& A, double* const b, double* const x, + double& eps, unsigned& nsteps); + +} // end namespace MathLib + +#endif /* BICGSTAB_H_ */ diff --git a/MathLib/LinAlg/Solvers/solver.h b/MathLib/LinAlg/Solvers/solver.h index d89a01b897ba2a07e99a3539b26318241ef468d7..280a62ac9afdea49467446ab5a61417d06b748a2 100644 --- a/MathLib/LinAlg/Solvers/solver.h +++ b/MathLib/LinAlg/Solvers/solver.h @@ -8,11 +8,7 @@ #ifndef SOLVER_H_ #define SOLVER_H_ -namespace MathLib { - -unsigned CG(CRSMatrix<double> const * mat, double const * const b, - double* const x, double& eps, unsigned& nsteps, unsigned num_threads = 1); - -} // end namespace MathLib +#include "CG.h" +#include "BiCGStab.h" #endif /* SOLVER_H_ */ diff --git a/SimpleTests/SolverTests/BiCGStabDiagPrecond.cpp b/SimpleTests/SolverTests/BiCGStabDiagPrecond.cpp new file mode 100644 index 0000000000000000000000000000000000000000..764ad1b963e5de459d7bf975c5f84a9fd611dac0 --- /dev/null +++ b/SimpleTests/SolverTests/BiCGStabDiagPrecond.cpp @@ -0,0 +1,82 @@ +#include <fstream> +#include <iostream> +#include <cmath> +#include <cstdlib> +#include <omp.h> +#include "LinAlg/Solvers/BiCGStab.h" +#include "LinAlg/Sparse/CRSMatrixDiagPrecond.h" +#include "sparse.h" +#include "vector_io.h" +#include "RunTimeTimer.h" +#include "CPUTimeTimer.h" + +int main(int argc, char *argv[]) +{ + if (argc != 4) { + std::cout << "Usage: " << argv[0] << " matrix rhs number-of-threads" << std::endl; + return -1; + } + + // read number of threads + unsigned num_omp_threads (1); + num_omp_threads = atoi (argv[3]); + + // *** reading matrix in crs format from file + std::string fname(argv[1]); + MathLib::CRSMatrixDiagPrecond *mat (new MathLib::CRSMatrixDiagPrecond(fname)); + + unsigned n (mat->getNRows()); + bool verbose (true); + if (verbose) + std::cout << "Parameters read: n=" << n << std::endl; + + double *x(new double[n]); + double *b(new double[n]); + + // *** init start vector x + for (size_t k(0); k<n; k++) { + x[k] = 0.0; + } + // *** read rhs + fname = argv[2]; + std::ifstream in(fname.c_str()); + if (in) { + read (in, n, b); + in.close(); + } else { + std::cout << "problem reading rhs - initializing b with 1.0" << std::endl; + for (size_t k(0); k<n; k++) { + b[k] = 1.0; + } + } + + + if (verbose) + std::cout << "solving system with PCG method (diagonal preconditioner) ... " << std::flush; + + double eps (1.0e-6); + unsigned steps (4000); + RunTimeTimer run_timer; + CPUTimeTimer cpu_timer; + run_timer.start(); + cpu_timer.start(); + + MathLib::BiCGStab ((*mat), b, x, eps, steps); + + cpu_timer.stop(); + run_timer.stop(); + + if (verbose) { + std::cout << " in " << steps << " iterations" << std::endl; + std::cout << "\t(residuum is " << eps << ") took " << cpu_timer.elapsed() << " sec time and " << run_timer.elapsed() << " sec" << std::endl; + } else { + std::cout << cpu_timer.elapsed() << std::endl; + } + + delete mat; + delete [] x; + delete [] b; + + return 0; +} + diff --git a/SimpleTests/SolverTests/CMakeLists.txt b/SimpleTests/SolverTests/CMakeLists.txt index 439de4a1d68c60c31c5d62213b7168bcf08e945f..952fb044734203e65de086dbc7d61f869b9613dd 100644 --- a/SimpleTests/SolverTests/CMakeLists.txt +++ b/SimpleTests/SolverTests/CMakeLists.txt @@ -31,6 +31,12 @@ ADD_EXECUTABLE( ConjugateGradientDiagPrecond ${HEADERS} ) +ADD_EXECUTABLE( BiCGStabDiagPrecond + BiCGStabDiagPrecond.cpp + ${SOURCES} + ${HEADERS} +) + TARGET_LINK_LIBRARIES ( ConjugateGradientUnpreconditioned ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES} @@ -45,3 +51,10 @@ TARGET_LINK_LIBRARIES ( ConjugateGradientDiagPrecond Base ) +TARGET_LINK_LIBRARIES( BiCGStabDiagPrecond + ${BLAS_LIBRARIES} + ${LAPACK_LIBRARIES} + MathLib + Base +) +