7#if HAVE_SUITESPARSE_CHOLMOD || defined DOXYGEN
9#include <dune/common/fmatrix.hh>
10#include <dune/common/fvector.hh>
14#include <dune/istl/solverfactory.hh>
15#include <dune/istl/foreach.hh>
36 const NoIgnore& operator[](std::size_t)
const {
return *
this; }
37 explicit operator bool()
const {
return false; }
38 static constexpr std::size_t size() {
return 0; }
43 template<
class BlockedVector,
class FlatVector>
44 void copyToFlatVector(
const BlockedVector& blockedVector, FlatVector& flatVector)
47 std::size_t len = flatVectorForEach(blockedVector, [&](
auto&&,
auto...){});
48 flatVector.resize(len);
50 flatVectorForEach(blockedVector, [&](
auto&& entry,
auto offset){
51 flatVector[offset] = entry;
56 template<
class FlatVector>
57 void copyToFlatVector(
const NoIgnore&, FlatVector&)
63 template<
class FlatVector,
class BlockedVector>
64 void copyToBlockedVector(
const FlatVector& flatVector, BlockedVector& blockedVector)
66 flatVectorForEach(blockedVector, [&](
auto& entry,
auto offset){
67 entry = flatVector[offset];
73 template <
class Index>
74 struct CholmodMethodChooser;
78 struct CholmodMethodChooser<int>
81 static cholmod_dense* allocate_dense(
size_t nrow,
size_t ncol,
size_t d,
int xtype, cholmod_common *c)
83 return ::cholmod_allocate_dense(nrow,ncol,d,xtype,c);
87 static cholmod_sparse* allocate_sparse(
size_t nrow,
size_t ncol,
size_t nzmax,
int sorted,
int packed,
int stype,
int xtype, cholmod_common *c)
89 return ::cholmod_allocate_sparse(nrow,ncol,nzmax,sorted,packed,stype,xtype,c);
93 static cholmod_factor* analyze(cholmod_sparse *A, cholmod_common *c)
95 return ::cholmod_analyze(A,c);
98 static int defaults(cholmod_common *c)
100 return ::cholmod_defaults(c);
103 static int factorize(cholmod_sparse *A, cholmod_factor *L, cholmod_common *c)
105 return ::cholmod_factorize(A,L,c);
108 static int finish(cholmod_common *c)
110 return ::cholmod_finish(c);
113 static int free_dense (cholmod_dense **X, cholmod_common *c)
115 return ::cholmod_free_dense(X,c);
118 static int free_factor(cholmod_factor **L, cholmod_common *c)
120 return ::cholmod_free_factor(L,c);
123 static int free_sparse(cholmod_sparse **A, cholmod_common *c)
125 return ::cholmod_free_sparse(A,c);
129 static cholmod_dense* solve(
int sys, cholmod_factor *L, cholmod_dense *B, cholmod_common *c)
131 return ::cholmod_solve(sys,L,B,c);
134 static int start(cholmod_common *c)
136 return ::cholmod_start(c);
142 struct CholmodMethodChooser<SuiteSparse_long>
145 static cholmod_dense* allocate_dense(
size_t nrow,
size_t ncol,
size_t d,
int xtype, cholmod_common *c)
147 return ::cholmod_l_allocate_dense(nrow,ncol,d,xtype,c);
151 static cholmod_sparse* allocate_sparse(
size_t nrow,
size_t ncol,
size_t nzmax,
int sorted,
int packed,
int stype,
int xtype, cholmod_common *c)
153 return ::cholmod_l_allocate_sparse(nrow,ncol,nzmax,sorted,packed,stype,xtype,c);
157 static cholmod_factor* analyze(cholmod_sparse *A, cholmod_common *c)
159 return ::cholmod_l_analyze(A,c);
162 static int defaults(cholmod_common *c)
164 return ::cholmod_l_defaults(c);
167 static int factorize(cholmod_sparse *A, cholmod_factor *L, cholmod_common *c)
169 return ::cholmod_l_factorize(A,L,c);
172 static int finish(cholmod_common *c)
174 return ::cholmod_l_finish(c);
177 static int free_dense (cholmod_dense **X, cholmod_common *c)
179 return ::cholmod_l_free_dense(X,c);
182 static int free_factor (cholmod_factor **L, cholmod_common *c)
184 return ::cholmod_l_free_factor(L,c);
187 static int free_sparse(cholmod_sparse **A, cholmod_common *c)
189 return ::cholmod_l_free_sparse(A,c);
193 static cholmod_dense* solve(
int sys, cholmod_factor *L, cholmod_dense *B, cholmod_common *c)
195 return ::cholmod_l_solve(sys,L,B,c);
198 static int start(cholmod_common *c)
200 return ::cholmod_l_start(c);
214template<
class Vector,
class Index=
int>
217 static_assert(std::is_same_v<Index,int> || std::is_same_v<Index,SuiteSparse_long>,
218 "Index type must be either 'int' or 'SuiteSparse_long'!");
220 using CholmodMethod = Impl::CholmodMethodChooser<Index>;
231 CholmodMethod::start(&c_);
242 CholmodMethod::free_factor(&L_, &c_);
243 CholmodMethod::finish(&c_);
271 if (x.size() != b.size())
272 DUNE_THROW(Exception,
"Error in apply(): sizes of x and b do not match!");
275 auto b2 = std::make_unique<double[]>(L_->n);
276 auto x2 = std::make_unique<double[]>(L_->n);
281 flatVectorForEach(b, [&](
auto&& entry,
auto&& flatIndex){
282 if ( subIndices_.empty() )
283 bp[ flatIndex ] = entry;
285 if( subIndices_[ flatIndex ] != std::numeric_limits<std::size_t>::max() )
286 bp[ subIndices_[ flatIndex ] ] = entry;
290 auto b3 = make_cholmod_dense(CholmodMethod::allocate_dense(L_->n, 1, L_->n, CHOLMOD_REAL, &c_), &c_);
293 auto b4 =
static_cast<double*
>(b3->x);
294 std::copy(b2.get(), b2.get() + L_->n, b4);
297 auto x3 = make_cholmod_dense(CholmodMethod::solve(CHOLMOD_A, L_, b3.get(), &c_), &c_);
299 auto xp =
static_cast<double*
>(x3->x);
302 flatVectorForEach(x, [&](
auto&& entry,
auto&& flatIndex){
303 if ( subIndices_.empty() )
304 entry = xp[ flatIndex ];
306 if( subIndices_[ flatIndex ] != std::numeric_limits<std::size_t>::max() )
307 entry = xp[ subIndices_[ flatIndex ] ];
321 template<
class Matrix>
324 const Impl::NoIgnore* noIgnore =
nullptr;
342 template<
class Matrix,
class Ignore>
347 size_t numberOfIgnoredDofs = 0;
350 auto [flatRows,flatCols] = flatMatrixForEach( matrix, [&](
auto&& ,
auto&& flatRowIndex,
auto&& flatColIndex){
351 if( flatRowIndex <= flatColIndex )
355 std::vector<bool> flatIgnore;
359 Impl::copyToFlatVector(*ignore,flatIgnore);
360 numberOfIgnoredDofs = std::count(flatIgnore.begin(),flatIgnore.end(),
true);
363 nIsZero_ = (size_t(flatRows) <= numberOfIgnoredDofs);
371 size_t N = flatRows - numberOfIgnoredDofs;
378 const auto deleter = [c = &this->c_](
auto* p) {
379 CholmodMethod::free_sparse(&p, c);
381 auto M = std::unique_ptr<cholmod_sparse, decltype(deleter)>(
382 CholmodMethod::allocate_sparse(N,
393 Index* Ap =
static_cast<Index*
>(M->p);
394 Index* Ai =
static_cast<Index*
>(M->i);
395 double* Ax =
static_cast<double*
>(M->x);
401 subIndices_.resize(flatRows,std::numeric_limits<std::size_t>::max());
403 std::size_t subIndexCounter = 0;
405 for ( std::size_t i=0; i<flatRows; i++ )
407 if ( not flatIgnore[ i ] )
409 subIndices_[ i ] = subIndexCounter++;
416 flatMatrixForEach(matrix, [&](
auto&& ,
auto&& flatRowIndex,
auto&& flatColIndex){
419 if ( ignore and ( flatIgnore[flatRowIndex] or flatIgnore[flatColIndex] ) )
423 if ( flatRowIndex > flatColIndex )
427 auto idx = ignore ? subIndices_[flatRowIndex] : flatRowIndex;
434 for (
size_t i=0; i<N; i++ )
440 std::vector<std::size_t> rowPosition(N,0);
443 flatMatrixForEach(matrix, [&](
auto&& entry,
auto&& flatRowIndex,
auto&& flatColIndex){
446 if ( ignore and ( flatIgnore[flatRowIndex] or flatIgnore[flatColIndex] ) )
450 if ( flatRowIndex > flatColIndex )
454 auto rowIdx = ignore ? subIndices_[flatRowIndex] : flatRowIndex;
455 auto colIdx = ignore ? subIndices_[flatColIndex] : flatColIndex;
456 auto rowStart = Ap[rowIdx];
457 auto rowPos = rowPosition[rowIdx];
458 Ai[ rowStart + rowPos ] = colIdx;
459 Ax[ rowStart + rowPos ] = entry;
460 rowPosition[rowIdx]++;
466 CholmodMethod::free_factor(&L_, &c_);
469 L_ = CholmodMethod::analyze(M.get(), &c_);
472 CholmodMethod::factorize(M.get(), L_, &c_);
477 return SolverCategory::Category::sequential;
513 auto make_cholmod_dense(cholmod_dense* x, cholmod_common* c)
515 const auto deleter = [c](
auto* p) {
516 CholmodMethod::free_dense(&p, c);
518 return std::unique_ptr<cholmod_dense, decltype(deleter)>(x, deleter);
522 cholmod_factor* L_ =
nullptr;
525 bool nIsZero_ =
false;
528 std::vector<std::size_t> subIndices_;
531 struct CholmodCreator{
532 template<
class F>
struct isValidBlock : std::false_type{};
533 template<
int k>
struct isValidBlock<FieldVector<double,k>> : std::true_type{};
534 template<
int k>
struct isValidBlock<FieldVector<float,k>> : std::true_type{};
536 template<
class TL,
typename M>
537 std::shared_ptr<Dune::InverseOperator<typename Dune::TypeListElement<1, TL>::type,
538 typename Dune::TypeListElement<2, TL>::type>>
539 operator()(TL ,
const M& mat,
const Dune::ParameterTree& ,
540 std::enable_if_t<isValidBlock<
typename Dune::TypeListElement<1, TL>::type::block_type>::value,
int> = 0)
const
542 using D =
typename Dune::TypeListElement<1, TL>::type;
543 auto solver = std::make_shared<Dune::Cholmod<D>>();
544 solver->setMatrix(mat);
549 template<
typename TL,
typename M>
550 std::shared_ptr<Dune::InverseOperator<typename Dune::TypeListElement<1, TL>::type,
551 typename Dune::TypeListElement<2, TL>::type>>
552 operator() (TL ,
const M& ,
const Dune::ParameterTree& ,
553 std::enable_if_t<!isValidBlock<
typename Dune::TypeListElement<1, TL>::type::block_type>::value,
int> = 0)
const
555 DUNE_THROW(UnsupportedType,
"Unsupported Type in Cholmod");
558 DUNE_REGISTER_DIRECT_SOLVER(
"cholmod", Dune::CholmodCreator());
Implementation of the BCRSMatrix class.
This file implements a vector space as a tensor product of a given vector space. The number of compon...
Dune wrapper for SuiteSparse/CHOLMOD solver.
Definition: cholmod.hh:216
cholmod_common & cholmodCommonObject()
return a reference to the CHOLMOD common object for advanced option settings
Definition: cholmod.hh:485
void setMatrix(const Matrix &matrix)
Set matrix without ignore nodes.
Definition: cholmod.hh:322
cholmod_factor & cholmodFactor()
The CHOLMOD data structure that stores the factorization.
Definition: cholmod.hh:495
~Cholmod()
Destructor.
Definition: cholmod.hh:239
virtual SolverCategory::Category category() const
Category of the solver (see SolverCategory::Category)
Definition: cholmod.hh:475
void apply(Vector &x, Vector &b, InverseOperatorResult &res)
solve the linear system Ax=b (possibly with respect to some ignore field)
Definition: cholmod.hh:263
const cholmod_factor & cholmodFactor() const
The CHOLMOD data structure that stores the factorization.
Definition: cholmod.hh:505
void apply(Vector &x, Vector &b, double reduction, InverseOperatorResult &res)
simple forward to apply(X&, Y&, InverseOperatorResult&)
Definition: cholmod.hh:253
Cholmod()
Default constructor.
Definition: cholmod.hh:229
void setMatrix(const Matrix &matrix, const Ignore *ignore)
Set matrix and ignore nodes.
Definition: cholmod.hh:343
Abstract base class for all solvers.
Definition: solver.hh:101
A generic dynamic dense matrix.
Definition: matrix.hh:561
Define general, extensible interface for inverse operators.
Statistics about the application of an inverse operator.
Definition: solver.hh:50
int iterations
Number of iterations.
Definition: solver.hh:69
bool converged
True if convergence criterion has been met.
Definition: solver.hh:75
Category
Definition: solvercategory.hh:23