8#ifdef FEAT_HAVE_UMFPACK
9#include <kernel/solver/umfpack.hpp>
51 template<
typename Idx_,
int s
idx_ = sizeof(Idx_),
bool eq_ = (sizeof(
int) == sizeof(SuiteSparse_
long))>
52 struct UmfpackWrapper;
55 template<
typename Idx_,
bool eq_>
56 struct UmfpackWrapper<Idx_, sizeof(int), eq_>
58 static void init_defaults(
double* control)
60 ::umfpack_di_defaults(control);
63 static int init_symbolic(Idx_ nrows, Idx_ ncols,
const Idx_* row_ptr,
const Idx_* col_idx,
64 const double* data,
void** symb,
const double* ctrl,
double* info)
66 static_assert(
sizeof(Idx_) ==
sizeof(
int),
"invalid index size");
67 return int(::umfpack_di_symbolic(
static_cast<int>(nrows),
static_cast<int>(ncols),
68 reinterpret_cast<const int*
>(row_ptr),
reinterpret_cast<const int*
>(col_idx),
69 data, symb, ctrl, info));
72 static int init_numeric(
const Idx_* row_ptr,
const Idx_* col_idx,
73 const double* data,
void* symb,
void** nume,
const double* ctrl,
double* info)
75 static_assert(
sizeof(Idx_) ==
sizeof(
int),
"invalid index size");
76 return int(::umfpack_di_numeric(
77 reinterpret_cast<const int*
>(row_ptr),
reinterpret_cast<const int*
>(col_idx),
78 data, symb, nume, ctrl, info));
81 static void free_symbolic(
void** symb)
83 ::umfpack_di_free_symbolic(symb);
86 static void free_numeric(
void** nume)
88 ::umfpack_di_free_numeric(nume);
91 static int solve(
int sys,
const Idx_* row_ptr,
const Idx_* col_idx,
const double* data,
92 double* x,
const double* b,
void* nume,
const double* control,
double* info)
94 static_assert(
sizeof(Idx_) ==
sizeof(
int),
"invalid index size");
95 return int(::umfpack_di_solve(
static_cast<int>(sys),
96 reinterpret_cast<const int*
>(row_ptr),
reinterpret_cast<const int*
>(col_idx),
97 data, x, b, nume, control, info));
102 template<
typename Idx_>
103 struct UmfpackWrapper<Idx_, sizeof(SuiteSparse_long), false>
105 static void init_defaults(
double* control)
107 ::umfpack_dl_defaults(control);
110 static int init_symbolic(Idx_ nrows, Idx_ ncols,
const Idx_* row_ptr,
const Idx_* col_idx,
111 const double* data,
void** symb,
const double* ctrl,
double* info)
113 static_assert(
sizeof(Idx_) ==
sizeof(SuiteSparse_long),
"invalid index size");
114 return int(::umfpack_dl_symbolic(
static_cast<SuiteSparse_long
>(nrows),
static_cast<SuiteSparse_long
>(ncols),
115 reinterpret_cast<const SuiteSparse_long*
>(row_ptr),
reinterpret_cast<const SuiteSparse_long*
>(col_idx),
116 data, symb, ctrl, info));
119 static int init_numeric(
const Idx_* row_ptr,
const Idx_* col_idx,
120 const double* data,
void* symb,
void** nume,
const double* ctrl,
double* info)
122 static_assert(
sizeof(Idx_) ==
sizeof(SuiteSparse_long),
"invalid index size");
123 return int(::umfpack_dl_numeric(
124 reinterpret_cast<const SuiteSparse_long*
>(row_ptr),
reinterpret_cast<const SuiteSparse_long*
>(col_idx),
125 data, symb, nume, ctrl, info));
128 static void free_symbolic(
void** symb)
130 ::umfpack_dl_free_symbolic(symb);
133 static void free_numeric(
void** nume)
135 ::umfpack_dl_free_numeric(nume);
138 static int solve(
int sys,
const Idx_* row_ptr,
const Idx_* col_idx,
const double* data,
139 double* x,
const double* b,
void* nume,
const double* control,
double* info)
141 static_assert(
sizeof(Idx_) ==
sizeof(SuiteSparse_long),
"invalid index size");
142 return int(::umfpack_dl_solve(sys,
reinterpret_cast<const SuiteSparse_long*
>(row_ptr),
143 reinterpret_cast<const SuiteSparse_long*
>(col_idx), data, x, b, nume, control, info));
152 _system_matrix(system_matrix),
153 _umf_control(new double[UMFPACK_CONTROL]),
154 _umf_symbolic(nullptr),
155 _umf_numeric(nullptr),
162 UmfpackWrapper<Index>::init_defaults(_umf_control);
169 if(_umf_control !=
nullptr)
170 delete [] _umf_control;
173 void Umfpack::init_symbolic()
175 BaseClass::init_symbolic();
178 if(_umf_symbolic !=
nullptr)
179 throw SolverException(
"UMFPACK: already have symbolic factorization");
182 double info[UMFPACK_INFO];
185 int status = UmfpackWrapper<Index>::init_symbolic(
186 _system_matrix.rows(),
187 _system_matrix.columns(),
188 _system_matrix.row_ptr(),
189 _system_matrix.col_ind(),
201 case UMFPACK_ERROR_out_of_memory:
202 throw SolverException(
"UMFPACK: out of memory");
203 case UMFPACK_ERROR_invalid_matrix:
204 throw InvalidMatrixStructureException(
"UMFPACK: invalid matrix structure");
205 case UMFPACK_ERROR_internal_error:
206 throw SolverException(
"UMFPACK: internal error");
208 throw SolverException(
"UMFPACK: unknown error");
212 _sym_peak_size = std::size_t(info[UMFPACK_SIZE_OF_UNIT] * info[UMFPACK_SYMBOLIC_PEAK_MEMORY]);
213 _sym_mem_size = std::size_t(info[UMFPACK_SIZE_OF_UNIT] * info[UMFPACK_SYMBOLIC_SIZE]);
216 void Umfpack::done_symbolic()
218 if(_umf_symbolic ==
nullptr)
221 UmfpackWrapper<Index>::free_symbolic(&_umf_symbolic);
223 _umf_symbolic =
nullptr;
225 BaseClass::done_symbolic();
228 void Umfpack::init_numeric()
230 BaseClass::init_numeric();
232 if(_umf_symbolic ==
nullptr)
233 throw SolverException(
"UFMPACK: symbolic factorization missing");
236 double info[UMFPACK_INFO];
239 int status = UmfpackWrapper<Index>::init_numeric(
240 _system_matrix.row_ptr(),
241 _system_matrix.col_ind(),
242 _system_matrix.val(),
254 case UMFPACK_ERROR_out_of_memory:
255 throw SolverException(
"UMFPACK: out of memory");
256 case UMFPACK_ERROR_invalid_matrix:
257 throw InvalidMatrixStructureException(
"UMFPACK: invalid matrix structure");
258 case UMFPACK_WARNING_singular_matrix:
259 throw SingularMatrixException(
"UMFPACK: singular matrix");
260 case UMFPACK_ERROR_different_pattern:
261 throw SolverException(
"UMFPACK: different pattern");
262 case UMFPACK_ERROR_internal_error:
263 throw SolverException(
"UMFPACK: internal error");
265 throw SolverException(
"UMFPACK: unknown error");
269 _umf_peak_size = std::size_t(info[UMFPACK_SIZE_OF_UNIT] * info[UMFPACK_PEAK_MEMORY]);
270 _num_mem_size = std::size_t(info[UMFPACK_SIZE_OF_UNIT] * info[UMFPACK_NUMERIC_SIZE]);
273 void Umfpack::done_numeric()
275 if(_umf_numeric ==
nullptr)
278 UmfpackWrapper<Index>::free_numeric(&_umf_numeric);
280 _umf_numeric =
nullptr;
281 BaseClass::done_numeric();
284 Status Umfpack::apply(VectorType& x,
const VectorType& b)
287 double info[UMFPACK_INFO];
290 int status = UmfpackWrapper<Index>::solve(
292 _system_matrix.row_ptr(),
293 _system_matrix.col_ind(),
294 _system_matrix.val(),
302 return (status == UMFPACK_OK) ? Status::success : Status::aborted;
309 UmfpackMean::UmfpackMean(
const MatrixType& system_matrix,
const VectorType& weight_vector) :
311 _system_matrix(system_matrix),
312 _weight_vector(weight_vector),
313 _umfpack(_solver_matrix)
317 void UmfpackMean::init_symbolic()
319 BaseClass::init_symbolic();
322 const Index n = _weight_vector.size();
323 if((n != _system_matrix.rows()) || (n != _system_matrix.columns()))
324 throw InvalidMatrixStructureException(
"system matrix/weight vector dimension mismatch");
327 const Index nnze = _system_matrix.used_elements();
330 _solver_matrix = MatrixType(n+1, n+1, nnze + 2*n);
333 const Index* irow_ptr = _system_matrix.row_ptr();
334 const Index* icol_idx = _system_matrix.col_ind();
337 Index* orow_ptr = _solver_matrix.row_ptr();
338 Index* ocol_idx = _solver_matrix.col_ind();
341 orow_ptr[0] =
Index(0);
342 for(Index i(0); i < n; ++i)
344 Index op = orow_ptr[i];
346 for(Index ip(irow_ptr[i]); ip < irow_ptr[i+1]; ++ip, ++op)
348 ocol_idx[op] = icol_idx[ip];
353 orow_ptr[i+1] = ++op;
357 Index op(orow_ptr[n]);
358 for(Index j(0); j < n; ++j, ++op)
368 _vec_x = _solver_matrix.create_vector_r();
369 _vec_b = _solver_matrix.create_vector_r();
372 _umfpack.init_symbolic();
375 void UmfpackMean::done_symbolic()
377 _umfpack.done_symbolic();
380 _solver_matrix.clear();
382 BaseClass::done_symbolic();
385 void UmfpackMean::init_numeric()
387 BaseClass::init_numeric();
389 const Index n = _system_matrix.rows();
392 const Index* irow_ptr = _system_matrix.row_ptr();
393 const double* idata = _system_matrix.val();
396 const double* weight = _weight_vector.elements();
399 const Index* orow_ptr = _solver_matrix.row_ptr();
400 double* odata = _solver_matrix.val();
403 for(Index i(0); i < n; ++i)
405 Index op(orow_ptr[i]);
407 for(Index ip(irow_ptr[i]); ip < irow_ptr[i+1]; ++ip, ++op)
409 odata[op] = idata[ip];
412 odata[op] = weight[i];
416 Index op(orow_ptr[n]);
417 for(Index j(0); j < n; ++j, ++op)
419 odata[op] = weight[j];
425 _umfpack.init_numeric();
428 void UmfpackMean::done_numeric()
430 _umfpack.done_numeric();
432 BaseClass::done_numeric();
435 Status UmfpackMean::apply(VectorType& vec_sol,
const VectorType& vec_rhs)
437 const Index n = vec_sol.size();
440 const double* vr = vec_rhs.elements();
441 double* vb = _vec_b.elements();
442 for(Index i(0); i < n; ++i)
449 Status status = _umfpack.apply(_vec_x, _vec_b);
452 const double* vx = _vec_x.elements();
453 double* vs = vec_sol.elements();
454 for(Index i(0); i < n; ++i)
467void dummy_function_umfpack() {}
LAFEM::SparseMatrixCSR< double, Index > MatrixType
compatible matrix type
Umfpack(const MatrixType &system_matrix)
Constructor.
Status
Solver status return codes enumeration.
Status solve(SolverBase< Vector_ > &solver, Vector_ &vec_sol, const Vector_ &vec_rhs, const Matrix_ &matrix, const Filter_ &filter)
Solve linear system with initial solution guess.
std::uint64_t Index
Index data type.