16#ifndef __B2GMM_SOLVER_H__ 
   17#define __B2GMM_SOLVER_H__ 
   22#include "gmm/gmm_dense_Householder.h" 
   23#include "gmm/gmm_interface.h" 
   24#include "gmm/gmm_precond_diagonal.h" 
   25#include "gmm/gmm_precond_ildlt.h" 
   26#include "gmm/gmm_precond_ildltt.h" 
   27#include "gmm/gmm_precond_ilu.h" 
   28#include "gmm/gmm_precond_ilut.h" 
   29#include "gmm/gmm_precond_ilutp.h" 
   30#include "gmm/gmm_precond_mr_approx_inverse.h" 
   31#include "gmm/gmm_solver_cg.h" 
   32#include "gmm/gmm_solver_gmres.h" 
   36#include "b2ppconfig.h" 
   39namespace b2000 { 
namespace b2linalg {
 
   41template <
typename T, 
template <
typename MATRIX> 
class PRECOND>
 
   42class gmm_cg_iterative_solver : 
public LDLt_sparse_solver<T> {
 
   44    typedef gmm::csc_matrix<T> gmm_matrix_t;
 
   45    typedef PRECOND<gmm_matrix_t> precond_type;
 
   47    gmm_cg_iterative_solver(precond_type* precond_, 
const Dictionary& dictionary_)
 
   53          dictionary(dictionary_) {}
 
   55    ~gmm_cg_iterative_solver() { 
delete precond; }
 
   58          size_t s_, 
size_t nnz_, 
const size_t* colind_, 
const size_t* rowind_, 
const T* value_,
 
   59          int connectivity, 
const Dictionary& dictionary_) {
 
   65        size_t nnz = colind[gmm_matrix.nc];
 
   66        nnz = nnz * 2 - gmm_matrix.nc;
 
   68        gmm_matrix.pr.resize(nnz);
 
   69        gmm_matrix.ir.resize(nnz);
 
   70        gmm_matrix.jc.resize(gmm_matrix.nc + 2);
 
   72        gmm_matrix.pr = 
new T[nnz];
 
   73        gmm_matrix.ir = 
new typename gmm_matrix_t::IND_TYPE[nnz];
 
   74        gmm_matrix.jc = 
new typename gmm_matrix_t::IND_TYPE[gmm_matrix.nc + 2];
 
   79    void update_value() { modified_value = 
true; }
 
   82          size_t s, 
size_t nrhs, 
const T* b, 
size_t ldb, T* x, 
size_t ldx,
 
   83          char left_or_right = 
' ') {
 
   85            size_t nnz = colind[gmm_matrix.nc];
 
   86            nnz = nnz * 2 - gmm_matrix.nc;
 
   87            size_t size = gmm_matrix.nc;
 
   89            typename gmm_matrix_t::IND_TYPE* colptr1 = &gmm_matrix.jc[0];
 
   91            typename gmm_matrix_t::IND_TYPE* colptr1 = gmm_matrix.jc;
 
   93            colptr1[0] = colptr1[1] = 0;
 
   95            for (
size_t j = 0; j != size; ++j) { colptr1[j] = colind[j + 1] - colind[j]; }
 
   96            for (
size_t j = 0; j != size; ++j) {
 
   97                const size_t i_end = colind[j + 1];
 
   98                for (
size_t i = colind[j] + 1; i < i_end; ++i) { ++colptr1[rowind[i]]; }
 
  101            for (
size_t j = 0; j != size; ++j) { colptr1[j + 1] += colptr1[j]; }
 
  103            typename gmm_matrix_t::IND_TYPE* rowind1 = &gmm_matrix.ir[0];
 
  104            T* nzval1 = &gmm_matrix.pr[0];
 
  106            typename gmm_matrix_t::IND_TYPE* rowind1 = gmm_matrix.ir;
 
  107            T* nzval1 = gmm_matrix.pr;
 
  109            for (
size_t j = 0; j != size; ++j) {
 
  110                size_t i = colind[j];
 
  111                const size_t i_end = colind[j + 1];
 
  112                typename gmm_matrix_t::IND_TYPE ii = colptr1[j];
 
  113                colptr1[j] += i_end - i;
 
  114                std::copy(rowind + i, rowind + i_end, rowind1 + ii);
 
  115                std::copy(value + i, value + i_end, nzval1 + ii);
 
  116                for (++i; i < i_end; ++i) {
 
  117                    int ii = colptr1[rowind[i]]++;
 
  119                    nzval1[ii] = value[i];
 
  122            precond->build_with(gmm_matrix);
 
  123            modified_value = 
false;
 
  129              dictionary.get_double(
"SLS_TOL_RESIDUUM", 1.0E-8),
 
  130              dictionary.get_int(
"SLS_VERBOSITY", 0), dictionary.get_int(
"SLS_MAX_ITER", -1));
 
  132        if (b == x) { tmp = 
new T[s]; }
 
  133        for (
size_t i = 0; i != nrhs; ++i) {
 
  134            if (b == x) { std::copy(b + ldb * i, b + ldb * (i + 1), tmp); }
 
  135            gmm::array1D_reference<const T*> B(b == x ? tmp : b + ldb * i, s);
 
  136            gmm::array1D_reference<T*> X(x + ldx * i, s);
 
  137            gmm::cg(gmm_matrix, X, B, *precond, iter);
 
  138            if (!iter.converged()) {
 
  139                Exception() << 
"The iterative sparse linear solver did not converge" << 
THROW;
 
  142        if (b == x) { 
delete[] tmp; }
 
  146    const size_t* colind;
 
  147    const size_t* rowind;
 
  149    gmm_matrix_t gmm_matrix;
 
  150    precond_type* precond;
 
  152    const Dictionary& dictionary;
 
  156LDLt_sparse_solver<T>* new_gmm_cg_iterative_solver(
const Dictionary& dictionary) {
 
  157    std::string precond_name = dictionary.get_string(
"SLS_PRECOND", 
"ILDLT");
 
  158    if (precond_name == 
"ILDLT") {
 
  159        typedef gmm_cg_iterative_solver<T, gmm::ildlt_precond> s_t;
 
  160        return new s_t(
new typename s_t::precond_type(), dictionary);
 
  162    if (precond_name == 
"ILDLTT") {
 
  163        typedef gmm_cg_iterative_solver<T, gmm::ildltt_precond> s_t;
 
  164        return new s_t(
new typename s_t::precond_type(), dictionary);
 
  166    if (precond_name == 
"DIAGONAL") {
 
  167        typedef gmm_cg_iterative_solver<T, gmm::diagonal_precond> s_t;
 
  168        return new s_t(
new typename s_t::precond_type(), dictionary);
 
  174    Exception() << 
"Unknown GMM++ cg preconditioner " << precond_name << 
"." << 
THROW;
 
  178template <
typename T, 
template <
typename MATRIX> 
class PRECOND>
 
  179class extension_gmm_cg_iterative_solver : 
public LDLt_extension_sparse_solver<T>,
 
  180                                          public gmm_cg_iterative_solver<T, PRECOND> {
 
  182    extension_gmm_cg_iterative_solver(
 
  183          typename gmm_cg_iterative_solver<T, PRECOND>::precond_type* precond_,
 
  184          const Dictionary& dictionary_)
 
  185        : gmm_cg_iterative_solver<T, PRECOND>(precond_, dictionary_) {}
 
  187    ~extension_gmm_cg_iterative_solver() {}
 
  190          size_t size_, 
size_t nnz_, 
const size_t* colind_, 
const size_t* rowind_, 
const T* value_,
 
  191          size_t size_ext_, 
const int connectivity, 
const Dictionary& dictionary) {
 
  194        gmm_cg_iterative_solver<T, PRECOND>::init(
 
  195              size_, nnz_, colind_, rowind_, value_, connectivity, dictionary);
 
  200    void update_value() { gmm_cg_iterative_solver<T, PRECOND>::update_value(); }
 
  203          size_t s, 
size_t nrhs, 
const T* b, 
size_t ldb, T* x, 
size_t ldx, 
const T* ma_ = 0,
 
  204          const T* mb_ = 0, 
const T* mc_ = 0, 
char left_or_right = 
' ') {
 
  205        if (ma_ != 0 && mb_ != 0 && mc_ != 0) {
 
  206            gmm_cg_iterative_solver<T, PRECOND>::resolve(s - 1, 1, ma_, s - 1, &m_a[0], s - 1);
 
  207            gmm_cg_iterative_solver<T, PRECOND>::resolve(s - 1, 1, mb_, s - 1, &m_b[0], s - 1);
 
  208            div = 1 / (*mc_ - blas::dot(s - 1, ma_, 1, &m_b[0], 1));
 
  211        for (
size_t i = 0; i != nrhs; ++i) {
 
  212            const double x2 = x[ldx * i + s - 1] =
 
  213                  div * (b[ldb * i + s - 1] - blas::dot(s - 1, b + ldb * i, 1, &m_b[0], 1));
 
  214            gmm_cg_iterative_solver<T, PRECOND>::resolve(
 
  215                  s - 1, 1, b + ldb * i, s - 1, x + ldx * i, s - 1);
 
  216            blas::axpy(s - 1, -x2, &m_a[0], 1, x + ldx * i, 1);
 
  227LDLt_extension_sparse_solver<T>* new_extension_gmm_cg_iterative_solver(
 
  228      const Dictionary& dictionary) {
 
  229    std::string precond_name = dictionary.get_string(
"SLS_PRECOND", 
"ILDLT");
 
  230    if (precond_name == 
"ILDLT") {
 
  231        typedef extension_gmm_cg_iterative_solver<T, gmm::ildlt_precond> s_t;
 
  232        return new s_t(
new typename s_t::precond_type(), dictionary);
 
  234    if (precond_name == 
"ILDLTT") {
 
  235        typedef extension_gmm_cg_iterative_solver<T, gmm::ildltt_precond> s_t;
 
  236        return new s_t(
new typename s_t::precond_type(), dictionary);
 
  238    if (precond_name == 
"DIAGONAL") {
 
  239        typedef extension_gmm_cg_iterative_solver<T, gmm::diagonal_precond> s_t;
 
  240        return new s_t(
new typename s_t::precond_type(), dictionary);
 
  247    Exception() << 
"Unknow GMM++ cg preconditioner " << precond_name << 
"." << 
THROW;
 
  251template <
typename T, 
template <
typename MATRIX> 
class PRECOND>
 
  252class gmm_gmres_iterative_solver : 
public LU_sparse_solver<T> {
 
  254    typedef gmm::csc_matrix_ref<const T*, const size_t*, const size_t*> gmm_matrix_ref_t;
 
  255    typedef PRECOND<gmm_matrix_ref_t> precond_type;
 
  257    gmm_gmres_iterative_solver(precond_type* precond_, 
const Dictionary& dictionary_)
 
  258        : precond(precond_), modified_value(true), dictionary(dictionary_) {}
 
  260    ~gmm_gmres_iterative_solver() { 
delete precond; }
 
  263          size_t s, 
size_t nnz, 
const size_t* colind, 
const size_t* rowind, 
const T* value,
 
  264          int connectivity, 
const Dictionary& dictionary_) {
 
  265        gmm_matrix_ref = gmm_matrix_ref_t(value, rowind, colind, s, s);
 
  269    void update_value() { modified_value = 
true; }
 
  272          size_t s, 
size_t nrhs, 
const T* b, 
size_t ldb, T* x, 
size_t ldx,
 
  273          char left_or_right = 
' ') {
 
  274        if (modified_value) {
 
  275            precond->build_with(gmm_matrix_ref);
 
  276            modified_value = 
false;
 
  279              dictionary.get_double(
"SLS_TOL_RESIDUUM", 1.0E-8),
 
  280              dictionary.get_int(
"SLS_VERBOSITY", 0), dictionary.get_int(
"SLS_MAX_ITER", -1));
 
  282        if (b == x) { tmp = 
new T[s]; }
 
  283        size_t restart = dictionary.get_int(
"SLS_RESTART", 200);
 
  284        for (
size_t i = 0; i != nrhs; ++i) {
 
  285            if (b == x) { std::copy(b + ldb * i, b + ldb * (i + 1), tmp); }
 
  286            gmm::array1D_reference<const T*> B(b == x ? tmp : b + ldb * i, s);
 
  287            gmm::array1D_reference<T*> X(x + ldx * i, s);
 
  288            gmm::gmres(gmm_matrix_ref, X, B, *precond, restart, iter);
 
  289            if (!iter.converged()) {
 
  290                Exception() << 
"The iterative sparse linear solver did not converge" << 
THROW;
 
  293        if (b == x) { 
delete[] tmp; }
 
  297    gmm_matrix_ref_t gmm_matrix_ref;
 
  298    precond_type* precond;
 
  300    const Dictionary& dictionary;
 
  304LU_sparse_solver<T>* new_gmm_gmres_iterative_solver(
const Dictionary& dictionary) {
 
  305    std::string precond_name = dictionary.get_string(
"SLS_PRECOND", 
"ILU");
 
  306    if (precond_name == 
"ILU") {
 
  307        typedef gmm_gmres_iterative_solver<T, gmm::ilu_precond> s_t;
 
  308        return new s_t(
new typename s_t::precond_type(), dictionary);
 
  310    if (precond_name == 
"ILUT") {
 
  311        typedef gmm_gmres_iterative_solver<T, gmm::ilut_precond> s_t;
 
  312        return new s_t(
new typename s_t::precond_type(), dictionary);
 
  314    if (precond_name == 
"ILUTP") {
 
  315        typedef gmm_gmres_iterative_solver<T, gmm::ilutp_precond> s_t;
 
  316        return new s_t(
new typename s_t::precond_type(), dictionary);
 
  318    if (precond_name == 
"DIAGONAL") {
 
  319        typedef gmm_gmres_iterative_solver<T, gmm::diagonal_precond> s_t;
 
  320        return new s_t(
new typename s_t::precond_type(), dictionary);
 
  322    if (precond_name == 
"MR_APPROX_INVERSE") {
 
  323        typedef gmm_gmres_iterative_solver<T, gmm::mr_approx_inverse_precond> s_t;
 
  324        return new s_t(
new typename s_t::precond_type(), dictionary);
 
  327    Exception() << 
"Unknown GMM++ gmres preconditioner " << precond_name << 
"." << 
THROW;
 
#define THROW
Definition b2exception.H:198
 
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
 
GenericException< UnimplementedError_name > UnimplementedError
Definition b2exception.H:314