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