DUNE-FEM (unstable)

umfpacksolver.hh
1#ifndef DUNE_FEM_UMFPACKSOLVER_HH
2#define DUNE_FEM_UMFPACKSOLVER_HH
3
4#include <algorithm>
5#include <iostream>
6#include <tuple>
7#include <utility>
8#include <vector>
9
10#include <dune/common/hybridutilities.hh>
11#include <dune/fem/function/adaptivefunction.hh>
12#include <dune/fem/function/blockvectorfunction.hh>
13#include <dune/fem/function/tuplediscretefunction.hh>
14#include <dune/fem/io/parameter.hh>
15#include <dune/fem/operator/common/operator.hh>
16#include <dune/fem/operator/linear/spoperator.hh>
17#include <dune/fem/operator/matrix/colcompspmatrix.hh>
18#include <dune/fem/operator/linear/spoperator.hh>
19#include <dune/fem/solver/inverseoperatorinterface.hh>
20
21#if HAVE_SUITESPARSE_UMFPACK
22#include <dune/fem/misc/umfpack.hh>
23
24namespace Dune
25{
26namespace Fem
27{
28
38template<class DiscreteFunction, class Matrix>
39class UMFPACKInverseOperator;
40
41template<class DiscreteFunction, class Matrix>
42struct UMFPACKInverseOperatorTraits
43{
44 typedef DiscreteFunction DiscreteFunctionType;
45 typedef AdaptiveDiscreteFunction< typename DiscreteFunction::DiscreteFunctionSpaceType > SolverDiscreteFunctionType;
46
48 typedef OperatorType PreconditionerType;
49
50 typedef Fem::SparseRowLinearOperator< DiscreteFunction, DiscreteFunction, Matrix > AssembledOperatorType;
51
52 typedef UMFPACKInverseOperator< DiscreteFunction,Matrix> InverseOperatorType;
53 typedef SolverParameter SolverParameterType;
54};
55
63template<class DiscreteFunction,
64 class Matrix = SparseRowMatrix< typename DiscreteFunction::DiscreteFunctionSpaceType::RangeFieldType > >
65class UMFPACKInverseOperator :
66 public InverseOperatorInterface< UMFPACKInverseOperatorTraits< DiscreteFunction, Matrix > >
67{
68public:
69 typedef UMFPACKInverseOperatorTraits< DiscreteFunction, Matrix > Traits;
70 typedef InverseOperatorInterface< Traits > BaseType;
71
72 typedef typename BaseType :: SolverDiscreteFunctionType
73 SolverDiscreteFunctionType;
74
75 typedef typename BaseType :: OperatorType OperatorType;
76 typedef typename BaseType :: AssembledOperatorType AssembledOperatorType;
77
78 typedef UMFPACKInverseOperator< DiscreteFunction,Matrix> ThisType;
79
80 typedef DiscreteFunction DiscreteFunctionType;
81
82 // \brief The column-compressed matrix type.
83 // Use index type from SuiteSparse (see SuiteSparse_config.h)
84 typedef ColCompMatrix<typename AssembledOperatorType::MatrixType::MatrixBaseType, SuiteSparse_long> CCSMatrixType;
85 typedef typename DiscreteFunctionType::DofType DofType;
86 typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
87
88 using BaseType :: parameter_;
89 using BaseType :: bind;
90
92 static const bool preconditioningAvailable = false;
93
97 UMFPACKInverseOperator(const SolverParameter &parameter = SolverParameter(Parameter::container()) )
98 : BaseType(parameter),
99 ccsmat_(),
100 UMF_Symbolic( nullptr ),
101 UMF_Numeric( nullptr )
102 {
103 Caller::defaults(UMF_Control);
104 UMF_Control[UMFPACK_PRL] = 4;
105 }
106
107 // \brief Destructor.
108 ~UMFPACKInverseOperator()
109 {
110 unbind();
111 }
112
113 void bind( const OperatorType& op )
114 {
115 // clear old storage
116 finalize();
117 BaseType::bind( op );
118 assert( assembledOperator_ );
119 }
120
121 void unbind ()
122 {
123 finalize();
124 BaseType::unbind();
125 }
126
127 // \brief Decompose matrix.
128 template<typename... A>
129 void prepare(A... ) const
130 {
131 if(assembledOperator_ && !ccsmat_)
132 {
133 ccsmat_ = std::make_unique<CCSMatrixType>(assembledOperator_->exportMatrix());
134 decompose();
135 }
136 }
137
138 // \brief Free allocated memory.
139 virtual void finalize()
140 {
141 if( ccsmat_ )
142 {
143 getCCSMatrix().free();
144 ccsmat_.reset();
145 Caller::free_symbolic(&UMF_Symbolic); UMF_Symbolic = nullptr;
146 Caller::free_numeric(&UMF_Numeric); UMF_Numeric = nullptr;
147 }
148 }
149
156 int apply(const DofType* arg, DofType* dest) const
157 {
158 prepare();
159
160 double UMF_Apply_Info[UMFPACK_INFO];
161 Caller::solve(UMFPACK_A, getCCSMatrix().getColStart(), getCCSMatrix().getRowIndex(), getCCSMatrix().getValues(),
162 dest, const_cast<DofType*>(arg), UMF_Numeric, UMF_Control, UMF_Apply_Info);
163 if( Parameter::verbose( Parameter::solverStatistics ) && parameter_->verbose() )
164 {
165 Caller::report_status(UMF_Control, UMF_Apply_Info[UMFPACK_STATUS]);
166 std::cout <<"[UMFPack Solve]" << std::endl;
167 std::cout << "Wallclock Time: " << UMF_Apply_Info[UMFPACK_SOLVE_WALLTIME]
168 << " (CPU Time: " << UMF_Apply_Info[UMFPACK_SOLVE_TIME] << ")" << std::endl;
169 std::cout << "Flops Taken: " << UMF_Apply_Info[UMFPACK_SOLVE_FLOPS] << std::endl;
170 std::cout << "Iterative Refinement steps taken: " << UMF_Apply_Info[UMFPACK_IR_TAKEN] << std::endl;
171 std::cout << "Error Estimate: " << UMF_Apply_Info[UMFPACK_OMEGA1] << " resp. " << UMF_Apply_Info[UMFPACK_OMEGA2] << std::endl;
172 }
173
174 const_cast<ThisType*>(this)->finalize();
175
176 return 1;
177 }
178
185 int apply(const SolverDiscreteFunctionType& arg, SolverDiscreteFunctionType& dest) const
186 {
187 return apply(arg.leakPointer(), dest.leakPointer());
188 }
189
196 template<typename... DFs>
197 int apply(const TupleDiscreteFunction<DFs...>& arg,TupleDiscreteFunction<DFs...>& dest) const
198 {
199 // copy DOF's arg into a consecutive vector
200 std::vector<DofType> vecArg(arg.size());
201 auto vecArgIt(vecArg.begin());
202 Hybrid::forEach(std::make_index_sequence<sizeof...(DFs)>{},
203 [&](auto i){vecArgIt=std::copy(std::get<i>(arg).dbegin(),std::get<i>(arg).dend(),vecArgIt);});
204 std::vector<DofType> vecDest(dest.size());
205 // apply operator
206 apply(vecArg.data(),vecDest.data());
207 // copy back solution into dest
208 auto vecDestIt(vecDest.begin());
209 Hybrid::forEach(std::make_index_sequence<sizeof...(DFs)>{},[&](auto i){for(auto& dof:dofs(std::get<i>(dest))) dof=(*(vecDestIt++));});
210 return 1;
211 }
212
213 void printTexInfo(std::ostream& out) const
214 {
215 out<<"Solver: UMFPACK direct solver"<<std::endl;
216 }
217
218 void setMaxIterations ( int ) {}
219
223 CCSMatrixType& getCCSMatrix() const
224 {
225 assert( ccsmat_ );
226 return *ccsmat_;
227 }
228
229 // \brief Print some statistics about the UMFPACK decomposition.
230 void printDecompositionInfo() const
231 {
232 Caller::report_info(UMF_Control,UMF_Decomposition_Info);
233 }
234
235 UMFPACKInverseOperator(const UMFPACKInverseOperator &other)
236 : BaseType(other),
237 ccsmat_(),
238 UMF_Symbolic(other.UMF_Symbolic),
239 UMF_Numeric(other.UMF_Numeric)
240 {
241 for (int i=0;i<UMFPACK_CONTROL;++i) UMF_Control[i] = other.UMF_Control[i];
242 for (int i=0;i<UMFPACK_INFO;++i) UMF_Decomposition_Info[i] = other.UMF_Decomposition_Info[i];
243 }
244
245protected:
246 using BaseType::assembledOperator_;
247 mutable std::unique_ptr<CCSMatrixType> ccsmat_;
248 mutable void *UMF_Symbolic;
249 mutable void *UMF_Numeric;
250 mutable double UMF_Control[UMFPACK_CONTROL];
251 mutable double UMF_Decomposition_Info[UMFPACK_INFO];
252
253 typedef typename Dune::UMFPackMethodChooser<DofType> Caller;
254
255 // \brief Computes the UMFPACK decomposition.
256 void decompose() const
257 {
258 const std::size_t dimMat(getCCSMatrix().N());
259 Caller::symbolic(static_cast<int>(dimMat), static_cast<int>(dimMat), getCCSMatrix().getColStart(), getCCSMatrix().getRowIndex(),
260 reinterpret_cast<double*>(getCCSMatrix().getValues()), &UMF_Symbolic, UMF_Control, UMF_Decomposition_Info);
261 Caller::numeric(getCCSMatrix().getColStart(), getCCSMatrix().getRowIndex(), reinterpret_cast<double*>(getCCSMatrix().getValues()),
262 UMF_Symbolic, &UMF_Numeric, UMF_Control, UMF_Decomposition_Info);
263 if( Parameter::verbose( Parameter::solverStatistics ) && parameter_->verbose() )
264 {
265 Caller::report_status(UMF_Control,UMF_Decomposition_Info[UMFPACK_STATUS]);
266 std::cout << "[UMFPack Decomposition]" << std::endl;
267 std::cout << "Wallclock Time taken: " << UMF_Decomposition_Info[UMFPACK_NUMERIC_WALLTIME]
268 << " (CPU Time: " << UMF_Decomposition_Info[UMFPACK_NUMERIC_TIME] << ")" << std::endl;
269 std::cout << "Flops taken: " << UMF_Decomposition_Info[UMFPACK_FLOPS] << std::endl;
270 std::cout << "Peak Memory Usage: " << UMF_Decomposition_Info[UMFPACK_PEAK_MEMORY]*UMF_Decomposition_Info[UMFPACK_SIZE_OF_UNIT]
271 << " bytes" << std::endl;
272 std::cout << "Condition number estimate: " << 1./UMF_Decomposition_Info[UMFPACK_RCOND] << std::endl;
273 std::cout << "Numbers of non-zeroes in decomposition: L: " << UMF_Decomposition_Info[UMFPACK_LNZ]
274 << " U: " << UMF_Decomposition_Info[UMFPACK_UNZ] << std::endl;
275 }
276 }
277};
278
279}
280}
281
282#endif // #if HAVE_SUITESPARSE_UMFPACK
283
284#endif // #ifndef DUNE_FEM_UMFPACKSOLVER_HH
Inverse operator base on CG method. Uses a runtime parameter fem.preconditioning which enables diagon...
Definition: cginverseoperator.hh:408
static bool verbose()
obtain the cached value for fem.verbose with default verbosity level 2
Definition: parameter.hh:466
forward declaration
Definition: discretefunction.hh:51
TupleDiscreteFunctionSpace< typename DiscreteFunctions::DiscreteFunctionSpaceType ... > DiscreteFunctionSpaceType
type for the discrete function space this function lives in
Definition: discretefunction.hh:69
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:256
Dune namespace.
Definition: alignedallocator.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)