dune-istl 2.12-git
Loading...
Searching...
No Matches
umfpack.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4// vi: set et ts=4 sw=2 sts=2:
5#ifndef DUNE_ISTL_UMFPACK_HH
6#define DUNE_ISTL_UMFPACK_HH
7
8#if HAVE_SUITESPARSE_UMFPACK || defined DOXYGEN
9
10#include<complex>
11#include<type_traits>
12
13#include<umfpack.h>
14
21#include<dune/istl/matrix.hh>
28
29
30
31namespace Dune {
43 // FORWARD DECLARATIONS
44 template<class M, class T, class TM, class TD, class TA>
45 class SeqOverlappingSchwarz;
46
47 template<class T, bool tag>
48 struct SeqOverlappingSchwarzAssemblerHelper;
49
50 // wrapper class for C-Function Calls in the backend. Choose the right function namespace
51 // depending on the template parameter used.
52 template<typename T>
54 {
55 static constexpr bool valid = false ;
56 };
57
58 template<>
59 struct UMFPackMethodChooser<double>
60 {
61 static constexpr bool valid = true ;
62
63 template<typename... A>
64 static void defaults(A... args)
65 {
66 umfpack_dl_defaults(args...);
67 }
68 template<typename... A>
69 static void free_numeric(A... args)
70 {
71 umfpack_dl_free_numeric(args...);
72 }
73 template<typename... A>
74 static void free_symbolic(A... args)
75 {
76 umfpack_dl_free_symbolic(args...);
77 }
78 template<typename... A>
79 static int load_numeric(A... args)
80 {
81 return umfpack_dl_load_numeric(args...);
82 }
83 template<typename... A>
84 static void numeric(A... args)
85 {
86 umfpack_dl_numeric(args...);
87 }
88 template<typename... A>
89 static void report_info(A... args)
90 {
91 umfpack_dl_report_info(args...);
92 }
93 template<typename... A>
94 static void report_status(A... args)
95 {
96 umfpack_dl_report_status(args...);
97 }
98 template<typename... A>
99 static int save_numeric(A... args)
100 {
101 return umfpack_dl_save_numeric(args...);
102 }
103 template<typename... A>
104 static void solve(A... args)
105 {
106 umfpack_dl_solve(args...);
107 }
108 template<typename... A>
109 static void symbolic(A... args)
110 {
111 umfpack_dl_symbolic(args...);
112 }
113 };
114
115 template<>
116 struct UMFPackMethodChooser<std::complex<double> >
117 {
118 static constexpr bool valid = true ;
119 using size_type = SuiteSparse_long;
120
121 template<typename... A>
122 static void defaults(A... args)
123 {
124 umfpack_zl_defaults(args...);
125 }
126 template<typename... A>
127 static void free_numeric(A... args)
128 {
129 umfpack_zl_free_numeric(args...);
130 }
131 template<typename... A>
132 static void free_symbolic(A... args)
133 {
134 umfpack_zl_free_symbolic(args...);
135 }
136 template<typename... A>
137 static int load_numeric(A... args)
138 {
139 return umfpack_zl_load_numeric(args...);
140 }
141 template<typename... A>
142 static void numeric(const size_type* cs, const size_type* ri, const double* val, A... args)
143 {
144 umfpack_zl_numeric(cs,ri,val,NULL,args...);
145 }
146 template<typename... A>
147 static void report_info(A... args)
148 {
149 umfpack_zl_report_info(args...);
150 }
151 template<typename... A>
152 static void report_status(A... args)
153 {
154 umfpack_zl_report_status(args...);
155 }
156 template<typename... A>
157 static int save_numeric(A... args)
158 {
159 return umfpack_zl_save_numeric(args...);
160 }
161 template<typename... A>
162 static void solve(size_type m, const size_type* cs, const size_type* ri, std::complex<double>* val, double* x, const double* b,A... args)
163 {
164 const double* cval = reinterpret_cast<const double*>(val);
165 umfpack_zl_solve(m,cs,ri,cval,NULL,x,NULL,b,NULL,args...);
166 }
167 template<typename... A>
168 static void symbolic(size_type m, size_type n, const size_type* cs, const size_type* ri, const double* val, A... args)
169 {
170 umfpack_zl_symbolic(m,n,cs,ri,val,NULL,args...);
171 }
172 };
173
174 namespace Impl
175 {
176 template<class M, class = void>
177 struct UMFPackVectorChooser;
178
180 template<class M> using UMFPackDomainType = typename UMFPackVectorChooser<M>::domain_type;
181
183 template<class M> using UMFPackRangeType = typename UMFPackVectorChooser<M>::range_type;
184
185 template<class M>
186 struct UMFPackVectorChooser<M,
187 std::enable_if_t<(std::is_same<M,double>::value) || (std::is_same<M,std::complex<double> >::value)>>
188 {
189 using domain_type = M;
190 using range_type = M;
191 };
192
193 template<typename T, int n, int m>
194 struct UMFPackVectorChooser<FieldMatrix<T,n,m>,
195 std::enable_if_t<(std::is_same<T,double>::value) || (std::is_same<T,std::complex<double> >::value)>>
196 {
198 using domain_type = FieldVector<T,m>;
200 using range_type = FieldVector<T,n>;
201 };
202
203 template<typename T, typename A>
204 struct UMFPackVectorChooser<BCRSMatrix<T,A>,
205 std::void_t<UMFPackDomainType<T>, UMFPackRangeType<T>>>
206 {
207 // In case of recursive deduction (e.g., BCRSMatrix<FieldMatrix<...>, Allocator<FieldMatrix<...>>>)
208 // the allocator needs to be converted to the sub-block allocator type too (e.g., Allocator<FieldVector<...>>).
209 // Note that matrix allocator is assumed to be the same as the domain/range type of allocators
211 using domain_type = BlockVector<UMFPackDomainType<T>, typename std::allocator_traits<A>::template rebind_alloc<UMFPackDomainType<T>>>;
213 using range_type = BlockVector<UMFPackRangeType<T>, typename std::allocator_traits<A>::template rebind_alloc<UMFPackRangeType<T>>>;
214 };
215
216 template<typename T, typename P, typename A>
217 struct UMFPackVectorChooser<Dune::Experimental::BCRSMatrix<T,P,A>,
218 std::void_t<UMFPackDomainType<T>, UMFPackRangeType<T>>>
219 : public UMFPackVectorChooser<BCRSMatrix<T,A>, std::void_t<UMFPackDomainType<T>, UMFPackRangeType<T>>>
220 {};
221
222 template<typename T, typename A>
223 struct UMFPackVectorChooser<Matrix<T,A>,
224 std::void_t<UMFPackDomainType<T>, UMFPackRangeType<T>>>
225 : public UMFPackVectorChooser<BCRSMatrix<T,A>, std::void_t<UMFPackDomainType<T>, UMFPackRangeType<T>>>
226 {};
227
228 // to make the `UMFPackVectorChooser` work with `MultiTypeBlockMatrix`, we need to add an intermediate step for the rows, which are typically `MultiTypeBlockVector`
229 template<typename FirstBlock, typename... Blocks>
230 struct UMFPackVectorChooser<MultiTypeBlockVector<FirstBlock, Blocks...>,
231 std::void_t<UMFPackDomainType<FirstBlock>, UMFPackRangeType<FirstBlock>, UMFPackDomainType<Blocks>...>>
232 {
234 using domain_type = MultiTypeBlockVector<UMFPackDomainType<FirstBlock>, UMFPackDomainType<Blocks>...>;
236 using range_type = UMFPackRangeType<FirstBlock>;
237 };
238
239 // specialization for `MultiTypeBlockMatrix` with `MultiTypeBlockVector` rows
240 template<typename FirstRow, typename... Rows>
241 struct UMFPackVectorChooser<MultiTypeBlockMatrix<FirstRow, Rows...>,
242 std::void_t<UMFPackDomainType<FirstRow>, UMFPackRangeType<FirstRow>, UMFPackRangeType<Rows>...>>
243 {
245 using domain_type = UMFPackDomainType<FirstRow>;
247 using range_type = MultiTypeBlockVector< UMFPackRangeType<FirstRow>, UMFPackRangeType<Rows>... >;
248 };
249
250 // dummy class to represent no BitVector
251 struct NoBitVector
252 {};
253
254
255 }
256
270 template<typename M>
271 class UMFPack : public InverseOperator<Impl::UMFPackDomainType<M>,Impl::UMFPackRangeType<M>>
272 {
273 using T = typename M::field_type;
274
275 public:
276 using size_type = SuiteSparse_long;
277
279 using Matrix = M;
280 using matrix_type = M;
282 using UMFPackMatrix = ISTL::Impl::BCCSMatrix<typename Matrix::field_type, size_type>;
284 using MatrixInitializer = ISTL::Impl::BCCSMatrixInitializer<M, size_type>;
286 using domain_type = Impl::UMFPackDomainType<M>;
288 using range_type = Impl::UMFPackRangeType<M>;
289
295
304 UMFPack(const Matrix& matrix, int verbose=0) : matrixIsLoaded_(false)
305 {
306 //check whether T is a supported type
308 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
309 Caller::defaults(UMF_Control);
310 setVerbosity(verbose);
311 setMatrix(matrix);
312 }
313
322 UMFPack(const Matrix& matrix, int verbose, bool) : matrixIsLoaded_(false)
323 {
324 //check whether T is a supported type
326 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
327 Caller::defaults(UMF_Control);
328 setVerbosity(verbose);
329 setMatrix(matrix);
330 }
331
350 UMFPack(const Matrix& mat_, const ParameterTree& config) : matrixIsLoaded_(false)
351 {
352 //check whether T is a supported type
354 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
355 Caller::defaults(UMF_Control);
356 setVerbosity(config.get<int>("verbose", 0));
357 if (config.hasKey("ordering")) {
358 const auto &ordering = config["ordering"];
359 if (ordering == "cholmod") setOption(UMFPACK_ORDERING, UMFPACK_ORDERING_CHOLMOD);
360 else if (ordering == "default") setOption(UMFPACK_ORDERING, UMFPACK_DEFAULT_ORDERING);
361 else if (ordering == "amd") setOption(UMFPACK_ORDERING, UMFPACK_ORDERING_AMD);
362 else if (ordering == "metis") setOption(UMFPACK_ORDERING, UMFPACK_ORDERING_METIS);
363 else if (ordering == "best") setOption(UMFPACK_ORDERING, UMFPACK_ORDERING_BEST);
364 else if (ordering == "none") setOption(UMFPACK_ORDERING, UMFPACK_ORDERING_NONE);
365 #if defined(UMFPACK_VER) && (UMFPACK_VER >= UMFPACK_VER_CODE(6, 0))
366 else if (ordering == "metis_guard") setOption(UMFPACK_ORDERING, UMFPACK_ORDERING_METIS_GUARD);
367 #endif
368 else DUNE_THROW(Dune::NotImplemented, "The UMFPACK ordering '" << ordering << "' is not implemented");
369 }
370 setMatrix(mat_);
371 }
372
375 UMFPack() : matrixIsLoaded_(false), verbosity_(0)
376 {
377 //check whether T is a supported type
379 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
380 Caller::defaults(UMF_Control);
381 }
382
393 UMFPack(const Matrix& mat_, const char* file, int verbose=0)
394 {
395 //check whether T is a supported type
397 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
398 Caller::defaults(UMF_Control);
399 setVerbosity(verbose);
400 int errcode = Caller::load_numeric(&UMF_Numeric, const_cast<char*>(file));
401 if ((errcode == UMFPACK_ERROR_out_of_memory) || (errcode == UMFPACK_ERROR_file_IO))
402 {
403 matrixIsLoaded_ = false;
404 setMatrix(mat_);
405 saveDecomposition(file);
406 }
407 else
408 {
409 matrixIsLoaded_ = true;
410 std::cout << "UMFPack decomposition successfully loaded from " << file << std::endl;
411 }
412 }
413
420 UMFPack(const char* file, int verbose=0)
421 {
422 //check whether T is a supported type
424 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
425 Caller::defaults(UMF_Control);
426 int errcode = Caller::load_numeric(&UMF_Numeric, const_cast<char*>(file));
427 if (errcode == UMFPACK_ERROR_out_of_memory)
428 DUNE_THROW(Dune::Exception, "ran out of memory while loading UMFPack decomposition");
429 if (errcode == UMFPACK_ERROR_file_IO)
430 DUNE_THROW(Dune::Exception, "IO error while loading UMFPack decomposition");
431 matrixIsLoaded_ = true;
432 std::cout << "UMFPack decomposition successfully loaded from " << file << std::endl;
433 setVerbosity(verbose);
434 }
435
436 virtual ~UMFPack()
437 {
438 if ((umfpackMatrix_.N() + umfpackMatrix_.M() > 0) || matrixIsLoaded_)
439 free();
440 }
441
446 {
447 if (umfpackMatrix_.N() != b.dim())
448 DUNE_THROW(Dune::ISTLError, "Size of right-hand-side vector b does not match the number of matrix rows!");
449 if (umfpackMatrix_.M() != x.dim())
450 DUNE_THROW(Dune::ISTLError, "Size of solution vector x does not match the number of matrix columns!");
451 if (b.size() == 0)
452 return;
453
454 // we have to convert x and b into flat structures
455 // however, this is linear in time
456 std::vector<T> xFlat(x.dim()), bFlat(b.dim());
457
458 flatVectorForEach(x, [&](auto&& entry, auto&& offset)
459 {
460 xFlat[ offset ] = entry;
461 });
462
463 flatVectorForEach(b, [&](auto&& entry, auto&& offset)
464 {
465 bFlat[ offset ] = entry;
466 });
467
468 double UMF_Apply_Info[UMFPACK_INFO];
469 Caller::solve(UMFPACK_A,
470 umfpackMatrix_.getColStart(),
471 umfpackMatrix_.getRowIndex(),
472 umfpackMatrix_.getValues(),
473 reinterpret_cast<double*>(&xFlat[0]),
474 reinterpret_cast<double*>(&bFlat[0]),
475 UMF_Numeric,
476 UMF_Control,
477 UMF_Apply_Info);
478
479 // copy back to blocked vector
480 flatVectorForEach(x, [&](auto&& entry, auto offset)
481 {
482 entry = xFlat[offset];
483 });
484
485 //this is a direct solver
486 res.iterations = 1;
487 res.converged = true;
488 res.elapsed = UMF_Apply_Info[UMFPACK_SOLVE_WALLTIME];
489
490 printOnApply(UMF_Apply_Info);
491 }
492
496 void apply (domain_type& x, range_type& b, [[maybe_unused]] double reduction, InverseOperatorResult& res) override
497 {
498 apply(x,b,res);
499 }
500
508 void apply(T* x, T* b)
509 {
510 double UMF_Apply_Info[UMFPACK_INFO];
511 Caller::solve(UMFPACK_A,
512 umfpackMatrix_.getColStart(),
513 umfpackMatrix_.getRowIndex(),
514 umfpackMatrix_.getValues(),
515 x,
516 b,
517 UMF_Numeric,
518 UMF_Control,
519 UMF_Apply_Info);
520 printOnApply(UMF_Apply_Info);
521 }
522
534 void setOption(unsigned int option, double value)
535 {
536 if (option >= UMFPACK_CONTROL)
537 DUNE_THROW(RangeError, "Requested non-existing UMFPack option");
538
539 UMF_Control[option] = value;
540 }
541
545 void saveDecomposition(const char* file)
546 {
547 int errcode = Caller::save_numeric(UMF_Numeric, const_cast<char*>(file));
548 if (errcode != UMFPACK_OK)
549 DUNE_THROW(Dune::Exception,"IO ERROR while trying to save UMFPack decomposition");
550 }
551
561 template<class BitVector = Impl::NoBitVector>
562 void setMatrix(const Matrix& matrix, const BitVector& bitVector = {})
563 {
564 if ((umfpackMatrix_.N() + umfpackMatrix_.M() > 0) || matrixIsLoaded_)
565 free();
566 if (matrix.N() == 0 or matrix.M() == 0)
567 return;
568
569 if (umfpackMatrix_.N() + umfpackMatrix_.M() + umfpackMatrix_.nonzeroes() != 0)
570 umfpackMatrix_.free();
571
572 constexpr bool useBitVector = not std::is_same_v<BitVector,Impl::NoBitVector>;
573
574 // use a dynamic flat vector for the bitset
575 std::vector<bool> flatBitVector;
576 // and a mapping from the compressed indices
577 std::vector<size_type> subIndices;
578
579 [[maybe_unused]] int numberOfIgnoredDofs = 0;
580 int nonZeros = 0;
581
582 if constexpr ( useBitVector )
583 {
584 auto flatSize = flatVectorForEach(bitVector, [](auto&&, auto&&){});
585 flatBitVector.resize(flatSize);
586
587 flatVectorForEach(bitVector, [&](auto&& entry, auto&& offset)
588 {
589 flatBitVector[ offset ] = entry;
590 if ( entry )
591 {
592 numberOfIgnoredDofs++;
593 }
594 });
595 }
596
597 // compute the flat dimension and the number of nonzeros of the matrix
598 auto [flatRows,flatCols] = flatMatrixForEach( matrix, [&](auto&& /*entry*/, auto&& row, auto&& col){
599 // do not count ignored entries
600 if constexpr ( useBitVector )
601 if ( flatBitVector[row] or flatBitVector[col] )
602 return;
603
604 nonZeros++;
605 });
606
607 if constexpr ( useBitVector )
608 {
609 // use the original flatRows!
610 subIndices.resize(flatRows,std::numeric_limits<std::size_t>::max());
611
612 size_type subIndexCounter = 0;
613 for ( size_type i=0; i<size_type(flatRows); i++ )
614 if ( not flatBitVector[ i ] )
615 subIndices[ i ] = subIndexCounter++;
616
617 // update the original matrix size
618 flatRows -= numberOfIgnoredDofs;
619 flatCols -= numberOfIgnoredDofs;
620 }
621
622
623 umfpackMatrix_.setSize(flatRows,flatCols);
624 umfpackMatrix_.Nnz_ = nonZeros;
625
626 // prepare the arrays
627 umfpackMatrix_.colstart = new size_type[flatCols+1];
628 umfpackMatrix_.rowindex = new size_type[nonZeros];
629 umfpackMatrix_.values = new T[nonZeros];
630
631 for ( size_type i=0; i<size_type(flatCols+1); i++ )
632 {
633 umfpackMatrix_.colstart[i] = 0;
634 }
635
636 // at first, we need to compute the column start indices
637 // therefore, we count all entries in each column and in the end we accumulate everything
638 flatMatrixForEach(matrix, [&](auto&& /*entry*/, auto&& flatRowIndex, auto&& flatColIndex)
639 {
640 // do nothing if entry is excluded
641 if constexpr ( useBitVector )
642 if ( flatBitVector[flatRowIndex] or flatBitVector[flatColIndex] )
643 return;
644
645 // pick compressed or uncompressed index
646 // compiler will hopefully do some constexpr optimization here
647 auto colIdx = useBitVector ? subIndices[flatColIndex] : flatColIndex;
648
649 umfpackMatrix_.colstart[colIdx+1]++;
650 });
651
652 // now accumulate
653 for ( size_type i=0; i<(size_type)flatCols; i++ )
654 {
655 umfpackMatrix_.colstart[i+1] += umfpackMatrix_.colstart[i];
656 }
657
658 // we need a compressed position counter in each column
659 std::vector<size_type> colPosition(flatCols,0);
660
661 // now we can set the entries: the procedure below works with both row- or column major index ordering
662 flatMatrixForEach(matrix, [&](auto&& entry, auto&& flatRowIndex, auto&& flatColIndex)
663 {
664 // do nothing if entry is excluded
665 if constexpr ( useBitVector )
666 if ( flatBitVector[flatRowIndex] or flatBitVector[flatColIndex] )
667 return;
668
669 // pick compressed or uncompressed index
670 // compiler will hopefully do some constexpr optimization here
671 auto rowIdx = useBitVector ? subIndices[flatRowIndex] : flatRowIndex;
672 auto colIdx = useBitVector ? subIndices[flatColIndex] : flatColIndex;
673
674 // the start index of each column is already fixed
675 auto colStart = umfpackMatrix_.colstart[colIdx];
676 // get the current number of picked elements in this column
677 auto colPos = colPosition[colIdx];
678 // assign the corresponding row index and the value of this element
679 umfpackMatrix_.rowindex[ colStart + colPos ] = rowIdx;
680 umfpackMatrix_.values[ colStart + colPos ] = entry;
681 // increase the number of picked elements in this column
682 colPosition[colIdx]++;
683 });
684
685 decompose();
686 }
687
688 // Keep legacy version using a set of scalar indices
689 // The new version using a bitVector type for marking the active matrix indices is
690 // directly given in `setMatrix` with an additional BitVector argument.
691 // The new version is more flexible and allows, e.g., marking single components of a matrix block.
692 void setSubMatrix(const Matrix& _mat, const std::set<typename Matrix::size_type>& rowIndexSet)
693 {
694 if ((umfpackMatrix_.N() + umfpackMatrix_.M() > 0) || matrixIsLoaded_)
695 free();
696
697 if (umfpackMatrix_.N() + umfpackMatrix_.M() + umfpackMatrix_.nonzeroes() != 0)
698 umfpackMatrix_.free();
699
700 umfpackMatrix_.setSize(rowIndexSet.size()*MatrixDimension<Matrix>::rowdim(_mat) / _mat.N(),
701 rowIndexSet.size()*MatrixDimension<Matrix>::coldim(_mat) / _mat.M());
702 ISTL::Impl::BCCSMatrixInitializer<Matrix, SuiteSparse_long> initializer(umfpackMatrix_);
703
704 copyToBCCSMatrix(initializer, ISTL::Impl::MatrixRowSubset<Matrix,std::set<typename Matrix::size_type> >(_mat,rowIndexSet));
705
706 decompose();
707 }
708
716 void setVerbosity(int v)
717 {
718 verbosity_ = v;
719 // set the verbosity level in UMFPack
720 if (verbosity_ == 0)
721 UMF_Control[UMFPACK_PRL] = 1;
722 if (verbosity_ == 1)
723 UMF_Control[UMFPACK_PRL] = 2;
724 if (verbosity_ == 2)
725 UMF_Control[UMFPACK_PRL] = 4;
726 }
727
733 {
734 return UMF_Numeric;
735 }
736
742 {
743 return umfpackMatrix_;
744 }
745
750 void free()
751 {
752 if (!matrixIsLoaded_)
753 {
754 Caller::free_symbolic(&UMF_Symbolic);
755 umfpackMatrix_.free();
756 }
757 Caller::free_numeric(&UMF_Numeric);
758 matrixIsLoaded_ = false;
759 }
760
761 const char* name() { return "UMFPACK"; }
762
763 private:
764 typedef typename Dune::UMFPackMethodChooser<T> Caller;
765
766 template<class Mat,class X, class TM, class TD, class T1>
769
771 void decompose()
772 {
773 double UMF_Decomposition_Info[UMFPACK_INFO];
774 Caller::symbolic(static_cast<SuiteSparse_long>(umfpackMatrix_.N()),
775 static_cast<SuiteSparse_long>(umfpackMatrix_.N()),
776 umfpackMatrix_.getColStart(),
777 umfpackMatrix_.getRowIndex(),
778 reinterpret_cast<double*>(umfpackMatrix_.getValues()),
779 &UMF_Symbolic,
780 UMF_Control,
781 UMF_Decomposition_Info);
782 Caller::numeric(umfpackMatrix_.getColStart(),
783 umfpackMatrix_.getRowIndex(),
784 reinterpret_cast<double*>(umfpackMatrix_.getValues()),
785 UMF_Symbolic,
786 &UMF_Numeric,
787 UMF_Control,
788 UMF_Decomposition_Info);
789 Caller::report_status(UMF_Control,UMF_Decomposition_Info[UMFPACK_STATUS]);
790 if (verbosity_ == 1)
791 {
792 std::cout << "[UMFPack Decomposition]" << std::endl;
793 std::cout << "Wallclock Time taken: " << UMF_Decomposition_Info[UMFPACK_NUMERIC_WALLTIME] << " (CPU Time: " << UMF_Decomposition_Info[UMFPACK_NUMERIC_TIME] << ")" << std::endl;
794 std::cout << "Flops taken: " << UMF_Decomposition_Info[UMFPACK_FLOPS] << std::endl;
795 std::cout << "Peak Memory Usage: " << UMF_Decomposition_Info[UMFPACK_PEAK_MEMORY]*UMF_Decomposition_Info[UMFPACK_SIZE_OF_UNIT] << " bytes" << std::endl;
796 std::cout << "Condition number estimate: " << 1./UMF_Decomposition_Info[UMFPACK_RCOND] << std::endl;
797 std::cout << "Numbers of non-zeroes in decomposition: L: " << UMF_Decomposition_Info[UMFPACK_LNZ] << " U: " << UMF_Decomposition_Info[UMFPACK_UNZ] << std::endl;
798 }
799 if (verbosity_ == 2)
800 {
801 Caller::report_info(UMF_Control,UMF_Decomposition_Info);
802 }
803 }
804
805 void printOnApply(double* UMF_Info)
806 {
807 Caller::report_status(UMF_Control,UMF_Info[UMFPACK_STATUS]);
808 if (verbosity_ > 0)
809 {
810 std::cout << "[UMFPack Solve]" << std::endl;
811 std::cout << "Wallclock Time: " << UMF_Info[UMFPACK_SOLVE_WALLTIME] << " (CPU Time: " << UMF_Info[UMFPACK_SOLVE_TIME] << ")" << std::endl;
812 std::cout << "Flops Taken: " << UMF_Info[UMFPACK_SOLVE_FLOPS] << std::endl;
813 std::cout << "Iterative Refinement steps taken: " << UMF_Info[UMFPACK_IR_TAKEN] << std::endl;
814 std::cout << "Error Estimate: " << UMF_Info[UMFPACK_OMEGA1] << " resp. " << UMF_Info[UMFPACK_OMEGA2] << std::endl;
815 }
816 }
817
818 UMFPackMatrix umfpackMatrix_;
819 bool matrixIsLoaded_;
820 int verbosity_;
821 void *UMF_Symbolic;
822 void *UMF_Numeric;
823 double UMF_Control[UMFPACK_CONTROL];
824 };
825
826 template<typename M>
828 {
829 enum { value=true};
830 };
831
832 template<typename T, typename A>
834 {
835 enum { value = true };
836 };
837
838 template<typename B, typename P, typename A>
840 {
841 enum { value = true };
842 };
843
844 namespace UMFPackImpl {
845 template<class OpTraits, class=void> struct isValidBlock : std::false_type{};
846 template<class OpTraits> struct isValidBlock<OpTraits,
847 std::enable_if_t<
848 std::is_same_v<Impl::UMFPackDomainType<typename OpTraits::matrix_type>, typename OpTraits::domain_type>
849 && std::is_same_v<Impl::UMFPackRangeType<typename OpTraits::matrix_type>, typename OpTraits::range_type>
850 && std::is_same_v<typename FieldTraits<typename OpTraits::domain_type::field_type>::real_type, double>
851 && std::is_same_v<typename FieldTraits<typename OpTraits::range_type::field_type>::real_type, double>
852 >> : std::true_type {};
853 }
855 [](auto opTraits, const auto& op, const Dune::ParameterTree& config)
856 -> std::shared_ptr<typename decltype(opTraits)::solver_type>
857 {
858 using OpTraits = decltype(opTraits);
859 // works only for sequential operators
860 if constexpr (OpTraits::isParallel){
861 if(opTraits.getCommOrThrow(op).communicator().size() > 1)
862 DUNE_THROW(Dune::InvalidStateException, "UMFPack works only for sequential operators.");
863 }
864 if constexpr (OpTraits::isAssembled){
865 using M = typename OpTraits::matrix_type;
866 // check if UMFPack<M>* is convertible to
867 // InverseOperator*. This checks compatibility of the
868 // domain and range types
870 const auto& A = opTraits.getAssembledOpOrThrow(op);
871 const M& mat = A->getmat();
872 return std::make_shared<Dune::UMFPack<M>>(mat, config);
873 }
874 }
876 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
877 return nullptr;
878 });
879} // end namespace Dune
880
881#endif // HAVE_SUITESPARSE_UMFPACK
882
883#endif //DUNE_ISTL_UMFPACK_HH
Some handy generic functions for ISTL matrices.
#define DUNE_REGISTER_SOLVER(name,...)
Definition solverregistry.hh:16
A dynamic dense block matrix class.
Implementation of the BCRSMatrix class.
Templates characterizing the type of a solver.
Implementations of the inverse operator interface.
void setSubMatrix(const Matrix &_mat, const std::set< typename Matrix::size_type > &rowIndexSet)
Definition umfpack.hh:692
void free()
free allocated space.
Definition umfpack.hh:750
SuiteSparse_long size_type
Definition umfpack.hh:276
static void symbolic(size_type m, size_type n, const size_type *cs, const size_type *ri, const double *val, A... args)
Definition umfpack.hh:168
static void solve(size_type m, const size_type *cs, const size_type *ri, std::complex< double > *val, double *x, const double *b, A... args)
Definition umfpack.hh:162
M matrix_type
Definition umfpack.hh:280
static void numeric(const size_type *cs, const size_type *ri, const double *val, A... args)
Definition umfpack.hh:142
static void report_info(A... args)
Definition umfpack.hh:147
UMFPack(const Matrix &mat_, const ParameterTree &config)
Construct a solver object from a matrix.
Definition umfpack.hh:350
static int load_numeric(A... args)
Definition umfpack.hh:137
static int load_numeric(A... args)
Definition umfpack.hh:79
static void report_status(A... args)
Definition umfpack.hh:94
UMFPack(const Matrix &mat_, const char *file, int verbose=0)
Try loading a decomposition from file and do a decomposition if unsuccessful.
Definition umfpack.hh:393
Impl::UMFPackRangeType< M > range_type
The type of the range of the solver.
Definition umfpack.hh:288
UMFPack()
default constructor
Definition umfpack.hh:375
static void symbolic(A... args)
Definition umfpack.hh:109
static void report_info(A... args)
Definition umfpack.hh:89
static void free_symbolic(A... args)
Definition umfpack.hh:74
static int save_numeric(A... args)
Definition umfpack.hh:157
static void free_numeric(A... args)
Definition umfpack.hh:127
static int save_numeric(A... args)
Definition umfpack.hh:99
static void report_status(A... args)
Definition umfpack.hh:152
Impl::UMFPackDomainType< M > domain_type
The type of the domain of the solver.
Definition umfpack.hh:286
void apply(T *x, T *b)
additional apply method with c-arrays in analogy to superlu
Definition umfpack.hh:508
SolverCategory::Category category() const override
Category of the solver (see SolverCategory::Category)
Definition umfpack.hh:291
static void defaults(A... args)
Definition umfpack.hh:122
static void free_numeric(A... args)
Definition umfpack.hh:69
void setVerbosity(int v)
sets the verbosity level for the UMFPack solver
Definition umfpack.hh:716
UMFPack(const char *file, int verbose=0)
try loading a decomposition from file
Definition umfpack.hh:420
static void numeric(A... args)
Definition umfpack.hh:84
void apply(domain_type &x, range_type &b, double reduction, InverseOperatorResult &res) override
apply inverse operator, with given convergence criteria.
Definition umfpack.hh:496
static constexpr bool valid
Definition umfpack.hh:55
virtual ~UMFPack()
Definition umfpack.hh:436
const char * name()
Definition umfpack.hh:761
void setMatrix(const Matrix &matrix, const BitVector &bitVector={})
Initialize data from given matrix.
Definition umfpack.hh:562
void saveDecomposition(const char *file)
saves a decomposition to a file
Definition umfpack.hh:545
UMFPackMatrix & getInternalMatrix()
Return the column compress matrix from UMFPack.
Definition umfpack.hh:741
SuiteSparse_long size_type
Definition umfpack.hh:119
UMFPack(const Matrix &matrix, int verbose=0)
Construct a solver object from a matrix.
Definition umfpack.hh:304
ISTL::Impl::BCCSMatrixInitializer< M, size_type > MatrixInitializer
Type of an associated initializer class.
Definition umfpack.hh:284
ISTL::Impl::BCCSMatrix< typename Matrix::field_type, size_type > UMFPackMatrix
The corresponding (scalar) UMFPack matrix type.
Definition umfpack.hh:282
void setOption(unsigned int option, double value)
Set UMFPack-specific options.
Definition umfpack.hh:534
static void free_symbolic(A... args)
Definition umfpack.hh:132
M Matrix
The matrix type.
Definition umfpack.hh:279
static void defaults(A... args)
Definition umfpack.hh:64
void apply(domain_type &x, range_type &b, InverseOperatorResult &res) override
Apply inverse operator,.
Definition umfpack.hh:445
static void solve(A... args)
Definition umfpack.hh:104
UMFPack(const Matrix &matrix, int verbose, bool)
Constructor for compatibility with SuperLU standard constructor.
Definition umfpack.hh:322
void * getFactorization()
Return the matrix factorization.
Definition umfpack.hh:732
Col col
Definition matrixmatrix.hh:351
Matrix & mat
Definition matrixmatrix.hh:347
STL namespace.
typename Impl::voider< Types... >::type void_t
static constexpr size_type M()
#define DUNE_THROW(E,...)
std::pair< std::size_t, std::size_t > flatMatrixForEach(Matrix &&matrix, F &&f, std::size_t rowOffset=0, std::size_t colOffset=0)
Traverse a blocked matrix and call a functor at each scalar entry.
Definition foreach.hh:139
std::size_t flatVectorForEach(Vector &&vector, F &&f, std::size_t offset=0)
Traverse a blocked vector and call a functor at each scalar entry.
Definition foreach.hh:102
Definition matrixutils.hh:221
A sparse block matrix with compressed row storage.
Definition bcrsmatrix.hh:468
Block compressed row storage matrix.
Definition experimental/bcrsmatrix.hh:82
std::string get(const std::string &key, const std::string &defaultValue) const
bool hasKey(const std::string &key) const
derive error class from the base class in common
Definition istlexception.hh:19
Sequential overlapping Schwarz preconditioner.
Definition overlappingschwarz.hh:755
Definition overlappingschwarz.hh:694
Statistics about the application of an inverse operator.
Definition solver.hh:50
double elapsed
Elapsed time in seconds.
Definition solver.hh:84
int iterations
Number of iterations.
Definition solver.hh:69
bool converged
True if convergence criterion has been met.
Definition solver.hh:75
Abstract base class for all solvers.
Definition solver.hh:101
Category
Definition solvercategory.hh:23
@ sequential
Category for sequential solvers.
Definition solvercategory.hh:25
Definition solverregistry.hh:97
Definition solvertype.hh:16
@ value
Whether this is a direct solver.
Definition solvertype.hh:24
Definition solvertype.hh:30
@ value
whether the solver internally uses column compressed storage
Definition solvertype.hh:36
Definition umfpack.hh:54
The UMFPack direct sparse solver.
Definition umfpack.hh:272
Definition umfpack.hh:845
T endl(T... args)
T resize(T... args)
T size(T... args)