Dune Core Modules (unstable)

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
18#include<dune/istl/bccsmatrixinitializer.hh>
20#include<dune/istl/foreach.hh>
21#include<dune/istl/multitypeblockmatrix.hh>
22#include<dune/istl/multitypeblockvector.hh>
25#include <dune/istl/solverfactory.hh>
26
27
28
29namespace Dune {
41 // FORWARD DECLARATIONS
42 template<class M, class T, class TM, class TD, class TA>
43 class SeqOverlappingSchwarz;
44
45 template<class T, bool tag>
46 struct SeqOverlappingSchwarzAssemblerHelper;
47
48 // wrapper class for C-Function Calls in the backend. Choose the right function namespace
49 // depending on the template parameter used.
50 template<typename T>
51 struct UMFPackMethodChooser
52 {
53 static constexpr bool valid = false ;
54 };
55
56 template<>
57 struct UMFPackMethodChooser<double>
58 {
59 static constexpr bool valid = true ;
60
61 template<typename... A>
62 static void defaults(A... args)
63 {
64 umfpack_dl_defaults(args...);
65 }
66 template<typename... A>
67 static void free_numeric(A... args)
68 {
69 umfpack_dl_free_numeric(args...);
70 }
71 template<typename... A>
72 static void free_symbolic(A... args)
73 {
74 umfpack_dl_free_symbolic(args...);
75 }
76 template<typename... A>
77 static int load_numeric(A... args)
78 {
79 return umfpack_dl_load_numeric(args...);
80 }
81 template<typename... A>
82 static void numeric(A... args)
83 {
84 umfpack_dl_numeric(args...);
85 }
86 template<typename... A>
87 static void report_info(A... args)
88 {
89 umfpack_dl_report_info(args...);
90 }
91 template<typename... A>
92 static void report_status(A... args)
93 {
94 umfpack_dl_report_status(args...);
95 }
96 template<typename... A>
97 static int save_numeric(A... args)
98 {
99 return umfpack_dl_save_numeric(args...);
100 }
101 template<typename... A>
102 static void solve(A... args)
103 {
104 umfpack_dl_solve(args...);
105 }
106 template<typename... A>
107 static void symbolic(A... args)
108 {
109 umfpack_dl_symbolic(args...);
110 }
111 };
112
113 template<>
114 struct UMFPackMethodChooser<std::complex<double> >
115 {
116 static constexpr bool valid = true ;
117 using size_type = SuiteSparse_long;
118
119 template<typename... A>
120 static void defaults(A... args)
121 {
122 umfpack_zl_defaults(args...);
123 }
124 template<typename... A>
125 static void free_numeric(A... args)
126 {
127 umfpack_zl_free_numeric(args...);
128 }
129 template<typename... A>
130 static void free_symbolic(A... args)
131 {
132 umfpack_zl_free_symbolic(args...);
133 }
134 template<typename... A>
135 static int load_numeric(A... args)
136 {
137 return umfpack_zl_load_numeric(args...);
138 }
139 template<typename... A>
140 static void numeric(const size_type* cs, const size_type* ri, const double* val, A... args)
141 {
142 umfpack_zl_numeric(cs,ri,val,NULL,args...);
143 }
144 template<typename... A>
145 static void report_info(A... args)
146 {
147 umfpack_zl_report_info(args...);
148 }
149 template<typename... A>
150 static void report_status(A... args)
151 {
152 umfpack_zl_report_status(args...);
153 }
154 template<typename... A>
155 static int save_numeric(A... args)
156 {
157 return umfpack_zl_save_numeric(args...);
158 }
159 template<typename... A>
160 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)
161 {
162 const double* cval = reinterpret_cast<const double*>(val);
163 umfpack_zl_solve(m,cs,ri,cval,NULL,x,NULL,b,NULL,args...);
164 }
165 template<typename... A>
166 static void symbolic(size_type m, size_type n, const size_type* cs, const size_type* ri, const double* val, A... args)
167 {
168 umfpack_zl_symbolic(m,n,cs,ri,val,NULL,args...);
169 }
170 };
171
172 namespace Impl
173 {
174 template<class M>
175 struct UMFPackVectorChooser
176 {};
177
178 template<typename T, typename A, int n, int m>
179 struct UMFPackVectorChooser<BCRSMatrix<FieldMatrix<T,n,m>,A > >
180 {
182 using domain_type = BlockVector<
183 FieldVector<T,m>,
184 typename std::allocator_traits<A>::template rebind_alloc<FieldVector<T,m> > >;
186 using range_type = BlockVector<
187 FieldVector<T,n>,
188 typename std::allocator_traits<A>::template rebind_alloc<FieldVector<T,n> > >;
189 };
190
191 template<typename T, typename A>
192 struct UMFPackVectorChooser<BCRSMatrix<T,A> >
193 {
195 using domain_type = BlockVector<T, A>;
197 using range_type = BlockVector<T, A>;
198 };
199
200 // to make the `UMFPackVectorChooser` work with `MultiTypeBlockMatrix`, we need to add an intermediate step for the rows, which are typically `MultiTypeBlockVector`
201 template<typename FirstBlock, typename... Blocks>
202 struct UMFPackVectorChooser<MultiTypeBlockVector<FirstBlock, Blocks...> >
203 {
205 using domain_type = MultiTypeBlockVector<typename UMFPackVectorChooser<FirstBlock>::domain_type,typename UMFPackVectorChooser<Blocks>::domain_type... >;
207 using range_type = typename UMFPackVectorChooser<FirstBlock>::range_type;
208 };
209
210 // specialization for `MultiTypeBlockMatrix` with `MultiTypeBlockVector` rows
211 template<typename FirstRow, typename... Rows>
212 struct UMFPackVectorChooser<MultiTypeBlockMatrix<FirstRow, Rows...> >
213 {
215 using domain_type = typename UMFPackVectorChooser<FirstRow>::domain_type;
217 using range_type = MultiTypeBlockVector< typename UMFPackVectorChooser<FirstRow>::range_type, typename UMFPackVectorChooser<Rows>::range_type... >;
218 };
219
220 // dummy class to represent no BitVector
221 struct NoBitVector
222 {};
223
224
225 }
226
240 template<typename M>
242 : public InverseOperator<
243 typename Impl::UMFPackVectorChooser<M>::domain_type,
244 typename Impl::UMFPackVectorChooser<M>::range_type >
245 {
246 using T = typename M::field_type;
247
248
249 public:
250 using size_type = SuiteSparse_long;
251
253 using Matrix = M;
254 using matrix_type = M;
256 using UMFPackMatrix = ISTL::Impl::BCCSMatrix<typename Matrix::field_type, size_type>;
258 using MatrixInitializer = ISTL::Impl::BCCSMatrixInitializer<M, size_type>;
260 using domain_type = typename Impl::UMFPackVectorChooser<M>::domain_type;
262 using range_type = typename Impl::UMFPackVectorChooser<M>::range_type;
263
266 {
267 return SolverCategory::Category::sequential;
268 }
269
278 UMFPack(const Matrix& matrix, int verbose=0) : matrixIsLoaded_(false)
279 {
280 //check whether T is a supported type
281 static_assert((std::is_same<T,double>::value) || (std::is_same<T,std::complex<double> >::value),
282 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
283 Caller::defaults(UMF_Control);
284 setVerbosity(verbose);
285 setMatrix(matrix);
286 }
287
296 UMFPack(const Matrix& matrix, int verbose, bool) : matrixIsLoaded_(false)
297 {
298 //check whether T is a supported type
299 static_assert((std::is_same<T,double>::value) || (std::is_same<T,std::complex<double> >::value),
300 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
301 Caller::defaults(UMF_Control);
302 setVerbosity(verbose);
303 setMatrix(matrix);
304 }
305
315 UMFPack(const Matrix& mat_, const ParameterTree& config)
316 : UMFPack(mat_, config.get<int>("verbose", 0))
317 {}
318
321 UMFPack() : matrixIsLoaded_(false), verbosity_(0)
322 {
323 //check whether T is a supported type
324 static_assert((std::is_same<T,double>::value) || (std::is_same<T,std::complex<double> >::value),
325 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
326 Caller::defaults(UMF_Control);
327 }
328
339 UMFPack(const Matrix& mat_, const char* file, int verbose=0)
340 {
341 //check whether T is a supported type
342 static_assert((std::is_same<T,double>::value) || (std::is_same<T,std::complex<double> >::value),
343 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
344 Caller::defaults(UMF_Control);
345 setVerbosity(verbose);
346 int errcode = Caller::load_numeric(&UMF_Numeric, const_cast<char*>(file));
347 if ((errcode == UMFPACK_ERROR_out_of_memory) || (errcode == UMFPACK_ERROR_file_IO))
348 {
349 matrixIsLoaded_ = false;
350 setMatrix(mat_);
351 saveDecomposition(file);
352 }
353 else
354 {
355 matrixIsLoaded_ = true;
356 std::cout << "UMFPack decomposition successfully loaded from " << file << std::endl;
357 }
358 }
359
366 UMFPack(const char* file, int verbose=0)
367 {
368 //check whether T is a supported type
369 static_assert((std::is_same<T,double>::value) || (std::is_same<T,std::complex<double> >::value),
370 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
371 Caller::defaults(UMF_Control);
372 int errcode = Caller::load_numeric(&UMF_Numeric, const_cast<char*>(file));
373 if (errcode == UMFPACK_ERROR_out_of_memory)
374 DUNE_THROW(Dune::Exception, "ran out of memory while loading UMFPack decomposition");
375 if (errcode == UMFPACK_ERROR_file_IO)
376 DUNE_THROW(Dune::Exception, "IO error while loading UMFPack decomposition");
377 matrixIsLoaded_ = true;
378 std::cout << "UMFPack decomposition successfully loaded from " << file << std::endl;
379 setVerbosity(verbose);
380 }
381
382 virtual ~UMFPack()
383 {
384 if ((umfpackMatrix_.N() + umfpackMatrix_.M() > 0) || matrixIsLoaded_)
385 free();
386 }
387
392 {
393 if (umfpackMatrix_.N() != b.dim())
394 DUNE_THROW(Dune::ISTLError, "Size of right-hand-side vector b does not match the number of matrix rows!");
395 if (umfpackMatrix_.M() != x.dim())
396 DUNE_THROW(Dune::ISTLError, "Size of solution vector x does not match the number of matrix columns!");
397 if (b.size() == 0)
398 return;
399
400 // we have to convert x and b into flat structures
401 // however, this is linear in time
402 std::vector<T> xFlat(x.dim()), bFlat(b.dim());
403
404 flatVectorForEach(x, [&](auto&& entry, auto&& offset)
405 {
406 xFlat[ offset ] = entry;
407 });
408
409 flatVectorForEach(b, [&](auto&& entry, auto&& offset)
410 {
411 bFlat[ offset ] = entry;
412 });
413
414 double UMF_Apply_Info[UMFPACK_INFO];
415 Caller::solve(UMFPACK_A,
416 umfpackMatrix_.getColStart(),
417 umfpackMatrix_.getRowIndex(),
418 umfpackMatrix_.getValues(),
419 reinterpret_cast<double*>(&xFlat[0]),
420 reinterpret_cast<double*>(&bFlat[0]),
421 UMF_Numeric,
422 UMF_Control,
423 UMF_Apply_Info);
424
425 // copy back to blocked vector
426 flatVectorForEach(x, [&](auto&& entry, auto offset)
427 {
428 entry = xFlat[offset];
429 });
430
431 //this is a direct solver
432 res.iterations = 1;
433 res.converged = true;
434 res.elapsed = UMF_Apply_Info[UMFPACK_SOLVE_WALLTIME];
435
436 printOnApply(UMF_Apply_Info);
437 }
438
442 virtual void apply (domain_type& x, range_type& b, [[maybe_unused]] double reduction, InverseOperatorResult& res)
443 {
444 apply(x,b,res);
445 }
446
454 void apply(T* x, T* b)
455 {
456 double UMF_Apply_Info[UMFPACK_INFO];
457 Caller::solve(UMFPACK_A,
458 umfpackMatrix_.getColStart(),
459 umfpackMatrix_.getRowIndex(),
460 umfpackMatrix_.getValues(),
461 x,
462 b,
463 UMF_Numeric,
464 UMF_Control,
465 UMF_Apply_Info);
466 printOnApply(UMF_Apply_Info);
467 }
468
480 void setOption(unsigned int option, double value)
481 {
482 if (option >= UMFPACK_CONTROL)
483 DUNE_THROW(RangeError, "Requested non-existing UMFPack option");
484
485 UMF_Control[option] = value;
486 }
487
491 void saveDecomposition(const char* file)
492 {
493 int errcode = Caller::save_numeric(UMF_Numeric, const_cast<char*>(file));
494 if (errcode != UMFPACK_OK)
495 DUNE_THROW(Dune::Exception,"IO ERROR while trying to save UMFPack decomposition");
496 }
497
507 template<class BitVector = Impl::NoBitVector>
508 void setMatrix(const Matrix& matrix, const BitVector& bitVector = {})
509 {
510 if ((umfpackMatrix_.N() + umfpackMatrix_.M() > 0) || matrixIsLoaded_)
511 free();
512 if (matrix.N() == 0 or matrix.M() == 0)
513 return;
514
515 if (umfpackMatrix_.N() + umfpackMatrix_.M() + umfpackMatrix_.nonzeroes() != 0)
516 umfpackMatrix_.free();
517
518 constexpr bool useBitVector = not std::is_same_v<BitVector,Impl::NoBitVector>;
519
520 // use a dynamic flat vector for the bitset
521 std::vector<bool> flatBitVector;
522 // and a mapping from the compressed indices
523 std::vector<size_type> subIndices;
524
525 int numberOfIgnoredDofs = 0;
526 int nonZeros = 0;
527
528 if constexpr ( useBitVector )
529 {
530 auto flatSize = flatVectorForEach(bitVector, [](auto&&, auto&&){});
531 flatBitVector.resize(flatSize);
532
533 flatVectorForEach(bitVector, [&](auto&& entry, auto&& offset)
534 {
535 flatBitVector[ offset ] = entry;
536 if ( entry )
537 {
538 numberOfIgnoredDofs++;
539 }
540 });
541 }
542
543 // compute the flat dimension and the number of nonzeros of the matrix
544 auto [flatRows,flatCols] = flatMatrixForEach( matrix, [&](auto&& /*entry*/, auto&& row, auto&& col){
545 // do not count ignored entries
546 if constexpr ( useBitVector )
547 if ( flatBitVector[row] or flatBitVector[col] )
548 return;
549
550 nonZeros++;
551 });
552
553 if constexpr ( useBitVector )
554 {
555 // use the original flatRows!
556 subIndices.resize(flatRows,std::numeric_limits<std::size_t>::max());
557
558 size_type subIndexCounter = 0;
559 for ( size_type i=0; i<size_type(flatRows); i++ )
560 if ( not flatBitVector[ i ] )
561 subIndices[ i ] = subIndexCounter++;
562
563 // update the original matrix size
564 flatRows -= numberOfIgnoredDofs;
565 flatCols -= numberOfIgnoredDofs;
566 }
567
568
569 umfpackMatrix_.setSize(flatRows,flatCols);
570 umfpackMatrix_.Nnz_ = nonZeros;
571
572 // prepare the arrays
573 umfpackMatrix_.colstart = new size_type[flatCols+1];
574 umfpackMatrix_.rowindex = new size_type[nonZeros];
575 umfpackMatrix_.values = new T[nonZeros];
576
577 for ( size_type i=0; i<size_type(flatCols+1); i++ )
578 {
579 umfpackMatrix_.colstart[i] = 0;
580 }
581
582 // at first, we need to compute the column start indices
583 // therefore, we count all entries in each column and in the end we accumulate everything
584 flatMatrixForEach(matrix, [&](auto&& /*entry*/, auto&& flatRowIndex, auto&& flatColIndex)
585 {
586 // do nothing if entry is excluded
587 if constexpr ( useBitVector )
588 if ( flatBitVector[flatRowIndex] or flatBitVector[flatColIndex] )
589 return;
590
591 // pick compressed or uncompressed index
592 // compiler will hopefully do some constexpr optimization here
593 auto colIdx = useBitVector ? subIndices[flatColIndex] : flatColIndex;
594
595 umfpackMatrix_.colstart[colIdx+1]++;
596 });
597
598 // now accumulate
599 for ( size_type i=0; i<(size_type)flatCols; i++ )
600 {
601 umfpackMatrix_.colstart[i+1] += umfpackMatrix_.colstart[i];
602 }
603
604 // we need a compressed position counter in each column
605 std::vector<size_type> colPosition(flatCols,0);
606
607 // now we can set the entries: the procedure below works with both row- or column major index ordering
608 flatMatrixForEach(matrix, [&](auto&& entry, auto&& flatRowIndex, auto&& flatColIndex)
609 {
610 // do nothing if entry is excluded
611 if constexpr ( useBitVector )
612 if ( flatBitVector[flatRowIndex] or flatBitVector[flatColIndex] )
613 return;
614
615 // pick compressed or uncompressed index
616 // compiler will hopefully do some constexpr optimization here
617 auto rowIdx = useBitVector ? subIndices[flatRowIndex] : flatRowIndex;
618 auto colIdx = useBitVector ? subIndices[flatColIndex] : flatColIndex;
619
620 // the start index of each column is already fixed
621 auto colStart = umfpackMatrix_.colstart[colIdx];
622 // get the current number of picked elements in this column
623 auto colPos = colPosition[colIdx];
624 // assign the corresponding row index and the value of this element
625 umfpackMatrix_.rowindex[ colStart + colPos ] = rowIdx;
626 umfpackMatrix_.values[ colStart + colPos ] = entry;
627 // increase the number of picked elements in this column
628 colPosition[colIdx]++;
629 });
630
631 decompose();
632 }
633
634 // Keep legacy version using a set of scalar indices
635 // The new version using a bitVector type for marking the active matrix indices is
636 // directly given in `setMatrix` with an additional BitVector argument.
637 // The new version is more flexible and allows, e.g., marking single components of a matrix block.
638 template<typename S>
639 void setSubMatrix(const Matrix& _mat, const S& rowIndexSet)
640 {
641 if ((umfpackMatrix_.N() + umfpackMatrix_.M() > 0) || matrixIsLoaded_)
642 free();
643
644 if (umfpackMatrix_.N() + umfpackMatrix_.M() + umfpackMatrix_.nonzeroes() != 0)
645 umfpackMatrix_.free();
646
647 umfpackMatrix_.setSize(rowIndexSet.size()*MatrixDimension<Matrix>::rowdim(_mat) / _mat.N(),
648 rowIndexSet.size()*MatrixDimension<Matrix>::coldim(_mat) / _mat.M());
649 ISTL::Impl::BCCSMatrixInitializer<Matrix, SuiteSparse_long> initializer(umfpackMatrix_);
650
651 copyToBCCSMatrix(initializer, ISTL::Impl::MatrixRowSubset<Matrix,std::set<std::size_t> >(_mat,rowIndexSet));
652
653 decompose();
654 }
655
663 void setVerbosity(int v)
664 {
665 verbosity_ = v;
666 // set the verbosity level in UMFPack
667 if (verbosity_ == 0)
668 UMF_Control[UMFPACK_PRL] = 1;
669 if (verbosity_ == 1)
670 UMF_Control[UMFPACK_PRL] = 2;
671 if (verbosity_ == 2)
672 UMF_Control[UMFPACK_PRL] = 4;
673 }
674
680 {
681 return UMF_Numeric;
682 }
683
689 {
690 return umfpackMatrix_;
691 }
692
697 void free()
698 {
699 if (!matrixIsLoaded_)
700 {
701 Caller::free_symbolic(&UMF_Symbolic);
702 umfpackMatrix_.free();
703 }
704 Caller::free_numeric(&UMF_Numeric);
705 matrixIsLoaded_ = false;
706 }
707
708 const char* name() { return "UMFPACK"; }
709
710 private:
711 typedef typename Dune::UMFPackMethodChooser<T> Caller;
712
713 template<class Mat,class X, class TM, class TD, class T1>
714 friend class SeqOverlappingSchwarz;
715 friend struct SeqOverlappingSchwarzAssemblerHelper<UMFPack<Matrix>,true>;
716
718 void decompose()
719 {
720 double UMF_Decomposition_Info[UMFPACK_INFO];
721 Caller::symbolic(static_cast<SuiteSparse_long>(umfpackMatrix_.N()),
722 static_cast<SuiteSparse_long>(umfpackMatrix_.N()),
723 umfpackMatrix_.getColStart(),
724 umfpackMatrix_.getRowIndex(),
725 reinterpret_cast<double*>(umfpackMatrix_.getValues()),
726 &UMF_Symbolic,
727 UMF_Control,
728 UMF_Decomposition_Info);
729 Caller::numeric(umfpackMatrix_.getColStart(),
730 umfpackMatrix_.getRowIndex(),
731 reinterpret_cast<double*>(umfpackMatrix_.getValues()),
732 UMF_Symbolic,
733 &UMF_Numeric,
734 UMF_Control,
735 UMF_Decomposition_Info);
736 Caller::report_status(UMF_Control,UMF_Decomposition_Info[UMFPACK_STATUS]);
737 if (verbosity_ == 1)
738 {
739 std::cout << "[UMFPack Decomposition]" << std::endl;
740 std::cout << "Wallclock Time taken: " << UMF_Decomposition_Info[UMFPACK_NUMERIC_WALLTIME] << " (CPU Time: " << UMF_Decomposition_Info[UMFPACK_NUMERIC_TIME] << ")" << std::endl;
741 std::cout << "Flops taken: " << UMF_Decomposition_Info[UMFPACK_FLOPS] << std::endl;
742 std::cout << "Peak Memory Usage: " << UMF_Decomposition_Info[UMFPACK_PEAK_MEMORY]*UMF_Decomposition_Info[UMFPACK_SIZE_OF_UNIT] << " bytes" << std::endl;
743 std::cout << "Condition number estimate: " << 1./UMF_Decomposition_Info[UMFPACK_RCOND] << std::endl;
744 std::cout << "Numbers of non-zeroes in decomposition: L: " << UMF_Decomposition_Info[UMFPACK_LNZ] << " U: " << UMF_Decomposition_Info[UMFPACK_UNZ] << std::endl;
745 }
746 if (verbosity_ == 2)
747 {
748 Caller::report_info(UMF_Control,UMF_Decomposition_Info);
749 }
750 }
751
752 void printOnApply(double* UMF_Info)
753 {
754 Caller::report_status(UMF_Control,UMF_Info[UMFPACK_STATUS]);
755 if (verbosity_ > 0)
756 {
757 std::cout << "[UMFPack Solve]" << std::endl;
758 std::cout << "Wallclock Time: " << UMF_Info[UMFPACK_SOLVE_WALLTIME] << " (CPU Time: " << UMF_Info[UMFPACK_SOLVE_TIME] << ")" << std::endl;
759 std::cout << "Flops Taken: " << UMF_Info[UMFPACK_SOLVE_FLOPS] << std::endl;
760 std::cout << "Iterative Refinement steps taken: " << UMF_Info[UMFPACK_IR_TAKEN] << std::endl;
761 std::cout << "Error Estimate: " << UMF_Info[UMFPACK_OMEGA1] << " resp. " << UMF_Info[UMFPACK_OMEGA2] << std::endl;
762 }
763 }
764
765 UMFPackMatrix umfpackMatrix_;
766 bool matrixIsLoaded_;
767 int verbosity_;
768 void *UMF_Symbolic;
769 void *UMF_Numeric;
770 double UMF_Control[UMFPACK_CONTROL];
771 };
772
773 template<typename T, typename A, int n, int m>
774 struct IsDirectSolver<UMFPack<BCRSMatrix<FieldMatrix<T,n,m>,A> > >
775 {
776 enum { value=true};
777 };
778
779 template<typename T, typename A>
780 struct StoresColumnCompressed<UMFPack<BCRSMatrix<T,A> > >
781 {
782 enum { value = true };
783 };
784
785 struct UMFPackCreator {
786 template<class F,class=void> struct isValidBlock : std::false_type{};
787 template<class B> struct isValidBlock<B, std::enable_if_t<std::is_same<typename FieldTraits<B>::real_type,double>::value>> : std::true_type {};
788
789 template<typename TL, typename M>
790 std::shared_ptr<Dune::InverseOperator<typename Dune::TypeListElement<1, TL>::type,
791 typename Dune::TypeListElement<2, TL>::type>>
792 operator() (TL /*tl*/, const M& mat, const Dune::ParameterTree& config,
793 std::enable_if_t<
794 isValidBlock<typename Dune::TypeListElement<1, TL>::type::block_type>::value,int> = 0) const
795 {
796 int verbose = config.get("verbose", 0);
797 return std::make_shared<Dune::UMFPack<M>>(mat,verbose);
798 }
799
800 // second version with SFINAE to validate the template parameters of UMFPack
801 template<typename TL, typename M>
802 std::shared_ptr<Dune::InverseOperator<typename Dune::TypeListElement<1, TL>::type,
803 typename Dune::TypeListElement<2, TL>::type>>
804 operator() (TL /*tl*/, const M& /*mat*/, const Dune::ParameterTree& /*config*/,
805 std::enable_if_t<
806 !isValidBlock<typename Dune::TypeListElement<1, TL>::type::block_type>::value,int> = 0) const
807 {
808 DUNE_THROW(UnsupportedType,
809 "Unsupported Type in UMFPack (only double and std::complex<double> supported)");
810 }
811 };
812 DUNE_REGISTER_DIRECT_SOLVER("umfpack",Dune::UMFPackCreator());
813} // end namespace Dune
814
815#endif // HAVE_SUITESPARSE_UMFPACK
816
817#endif //DUNE_ISTL_UMFPACK_HH
Implementation of the BCRSMatrix class.
Base class for Dune-Exceptions.
Definition: exceptions.hh:96
derive error class from the base class in common
Definition: istlexception.hh:19
Abstract base class for all solvers.
Definition: solver.hh:101
Hierarchical structure of string parameters.
Definition: parametertree.hh:37
std::string get(const std::string &key, const std::string &defaultValue) const
get value as string
Definition: parametertree.cc:181
Default exception class for range errors.
Definition: exceptions.hh:254
The UMFPack direct sparse solver.
Definition: umfpack.hh:245
A few common exception classes.
Implements a matrix constructed from a given type representing a field and compile-time given number ...
Implements a vector constructed from a given type representing a field and a compile-time given size.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:484
void free()
free allocated space.
Definition: umfpack.hh:697
virtual void apply(domain_type &x, range_type &b, InverseOperatorResult &res)
Apply inverse operator,.
Definition: umfpack.hh:391
virtual SolverCategory::Category category() const
Category of the solver (see SolverCategory::Category)
Definition: umfpack.hh:265
UMFPack(const Matrix &mat_, const ParameterTree &config)
Construct a solver object from a matrix.
Definition: umfpack.hh:315
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:339
typename Impl::UMFPackVectorChooser< M >::range_type range_type
The type of the range of the solver.
Definition: umfpack.hh:262
UMFPack()
default constructor
Definition: umfpack.hh:321
void apply(T *x, T *b)
additional apply method with c-arrays in analogy to superlu
Definition: umfpack.hh:454
void setVerbosity(int v)
sets the verbosity level for the UMFPack solver
Definition: umfpack.hh:663
UMFPack(const char *file, int verbose=0)
try loading a decomposition from file
Definition: umfpack.hh:366
void setMatrix(const Matrix &matrix, const BitVector &bitVector={})
Initialize data from given matrix.
Definition: umfpack.hh:508
void saveDecomposition(const char *file)
saves a decomposition to a file
Definition: umfpack.hh:491
UMFPackMatrix & getInternalMatrix()
Return the column compress matrix from UMFPack.
Definition: umfpack.hh:688
typename Impl::UMFPackVectorChooser< M >::domain_type domain_type
The type of the domain of the solver.
Definition: umfpack.hh:260
UMFPack(const Matrix &matrix, int verbose=0)
Construct a solver object from a matrix.
Definition: umfpack.hh:278
ISTL::Impl::BCCSMatrixInitializer< M, size_type > MatrixInitializer
Type of an associated initializer class.
Definition: umfpack.hh:258
virtual void apply(domain_type &x, range_type &b, double reduction, InverseOperatorResult &res)
apply inverse operator, with given convergence criteria.
Definition: umfpack.hh:442
ISTL::Impl::BCCSMatrix< typename Matrix::field_type, size_type > UMFPackMatrix
The corresponding (scalar) UMFPack matrix type.
Definition: umfpack.hh:256
void setOption(unsigned int option, double value)
Set UMFPack-specific options.
Definition: umfpack.hh:480
M Matrix
The matrix type.
Definition: umfpack.hh:253
UMFPack(const Matrix &matrix, int verbose, bool)
Constructor for compatibility with SuperLU standard constructor.
Definition: umfpack.hh:296
void * getFactorization()
Return the matrix factorization.
Definition: umfpack.hh:679
Dune namespace.
Definition: alignedallocator.hh:13
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:132
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:95
constexpr auto get(std::integer_sequence< T, II... >, std::integral_constant< std::size_t, pos >={})
Return the entry at position pos of the given sequence.
Definition: integersequence.hh:22
STL namespace.
Implementations of the inverse operator interface.
Templates characterizing the type of a solver.
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
Category
Definition: solvercategory.hh:23
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)