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 
16 #include<dune/common/fmatrix.hh>
17 #include<dune/common/fvector.hh>
18 #include<dune/istl/bccsmatrixinitializer.hh>
20 #include<dune/istl/foreach.hh>
21 #include<dune/istl/multitypeblockmatrix.hh>
22 #include<dune/istl/multitypeblockvector.hh>
23 #include<dune/istl/solvers.hh>
25 #include <dune/istl/solverfactory.hh>
26 
27 
28 
29 namespace 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>
241  class UMFPack
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:99
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:185
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, [[maybe_unused]] double reduction, InverseOperatorResult &res)
apply inverse operator, with given convergence criteria.
Definition: umfpack.hh:442
virtual void apply(domain_type &x, range_type &b, InverseOperatorResult &res)
Apply inverse operator,.
Definition: umfpack.hh:391
void * getFactorization()
Return the matrix factorization.
Definition: umfpack.hh:679
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
UMFPackMatrix & getInternalMatrix()
Return the column compress matrix from UMFPack.
Definition: umfpack.hh:688
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
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
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
Dune namespace.
Definition: alignedallocator.hh:13
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
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
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
Implementations of the inverse operator interface.
Templates characterizing the type of a solver.
Statistics about the application of an inverse operator.
Definition: solver.hh:48
double elapsed
Elapsed time in seconds.
Definition: solver.hh:82
int iterations
Number of iterations.
Definition: solver.hh:67
bool converged
True if convergence criterion has been met.
Definition: solver.hh:73
Category
Definition: solvercategory.hh:23
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 1, 22:29, 2024)