DUNE-FEM (unstable)

ldlsolver.hh
1#ifndef DUNE_FEM_LDLSOLVER_HH
2#define DUNE_FEM_LDLSOLVER_HH
3
4#include <algorithm>
5#include <iostream>
6#include <tuple>
7#include <vector>
8#include <utility>
9
11#include <dune/common/hybridutilities.hh>
12#include <dune/fem/function/adaptivefunction.hh>
13#include <dune/fem/function/blockvectorfunction.hh>
14#include <dune/fem/function/tuplediscretefunction.hh>
15#include <dune/fem/io/parameter.hh>
16#include <dune/fem/operator/linear/spoperator.hh>
17#include <dune/fem/operator/matrix/colcompspmatrix.hh>
18#include <dune/fem/solver/inverseoperatorinterface.hh>
19
20#if HAVE_SUITESPARSE_LDL
21
22#ifdef __cplusplus
23extern "C"
24{
25#include "ldl.h"
26#include "amd.h"
27}
28#endif
29
30namespace Dune
31{
32namespace Fem
33{
34
45template< class DiscreteFunction,
46 class Matrix = SparseRowMatrix< typename DiscreteFunction::DiscreteFunctionSpaceType::RangeFieldType > >
47class LDLInverseOperator;
48
49template< class DiscreteFunction, class Matrix >
50struct LDLInverseOperatorTraits
51{
52 typedef DiscreteFunction DiscreteFunctionType;
53 typedef AdaptiveDiscreteFunction< typename DiscreteFunction::DiscreteFunctionSpaceType > SolverDiscreteFunctionType;
54
56 typedef OperatorType PreconditionerType;
57
58 typedef Fem::SparseRowLinearOperator< DiscreteFunction, DiscreteFunction, Matrix > AssembledOperatorType;
59
60 typedef LDLInverseOperator< DiscreteFunction, Matrix > InverseOperatorType;
61 typedef SolverParameter SolverParameterType;
62};
63
64
65
73template< class DF, class Matrix >
74class LDLInverseOperator : public InverseOperatorInterface< LDLInverseOperatorTraits< DF, Matrix > >
75{
76 typedef LDLInverseOperatorTraits< DF, Matrix > Traits;
77 typedef InverseOperatorInterface< Traits > BaseType;
78
79 friend class InverseOperatorInterface< Traits >;
80public:
82 static const bool preconditioningAvailable = false;
83
84 typedef LDLInverseOperator< DF, Matrix > ThisType;
85
86 typedef typename BaseType :: SolverDiscreteFunctionType
87 SolverDiscreteFunctionType;
88
89 typedef typename BaseType :: OperatorType OperatorType;
90 typedef typename BaseType :: AssembledOperatorType AssembledOperatorType;
91
92 // \brief The column-compressed matrix type.
93 typedef ColCompMatrix<typename AssembledOperatorType::MatrixType::MatrixBaseType,int> CCSMatrixType;
94
95 typedef typename SolverDiscreteFunctionType::DofType DofType;
96 typedef typename SolverDiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
97
104 LDLInverseOperator(const double& redEps, const double& absLimit, const int& maxIter, const bool& verbose,
105 const ParameterReader &parameter = Parameter::container() ) :
106 verbose_(verbose && Parameter::verbose(Parameter::solverStatistics )), ccsmat_()
107 {}
108
114 LDLInverseOperator(const double& redEps, const double& absLimit, const int& maxIter,
115 const ParameterReader &parameter = Parameter::container() ) :
116 verbose_(parameter.getValue<bool>("fem.solver.verbose",false) && Parameter::verbose(Parameter::solverStatistics )),
117 ccsmat_()
118 {}
119
120 LDLInverseOperator(const SolverParameter &parameter = SolverParameter(Parameter::container()) )
121 : BaseType(parameter), verbose_(BaseType::verbose())
122 {}
123
131 LDLInverseOperator(const OperatorType& op, const double& redEps, const double& absLimit, const int& maxIter, const bool& verbose,
132 const ParameterReader &parameter = Parameter::container() ) :
133 verbose_(verbose), ccsmat_(), isloaded_(false)
134 {
135 bind(op);
136 }
137
144 LDLInverseOperator(const OperatorType& op, const double& redEps, const double& absLimit, const int& maxIter,
145 const ParameterReader &parameter = Parameter::container() ) :
146 verbose_(parameter.getValue<bool>("fem.solver.verbose",false)), ccsmat_(), isloaded_(false)
147 {
148 bind(op);
149 }
150
151 LDLInverseOperator(const OperatorType& op, const ParameterReader &parameter = Parameter::container() ) :
152 verbose_(parameter.getValue<bool>("fem.solver.verbose",false)), ccsmat_(), isloaded_(false)
153 {
154 bind(op);
155 }
156
157 // \brief Destructor.
158 ~LDLInverseOperator()
159 {
160 unbind();
161 }
162
163 void bind( const OperatorType& op )
164 {
165 // clear old storage
166 finalize();
167 BaseType::bind( op );
168 }
169
170 void unbind ()
171 {
172 finalize();
173 BaseType::unbind();
174 }
175
176 // \brief Decompose matrix.
177 template<typename... A>
178 void prepare(A... ) const
179 {
180 if( ! assembledOperator_ )
181 DUNE_THROW(NotImplemented,"LDLInverseOperator only works for assembled systems!");
182
183 if(!isloaded_)
184 {
185 ccsmat_ = assembledOperator_->exportMatrix();
186 decompose();
187 isloaded_ = true;
188 }
189 }
190
191 // \brief Free allocated memory.
192 virtual void finalize()
193 {
194 if(isloaded_)
195 {
196 ccsmat_.free();
197 delete [] D_;
198 delete [] Y_;
199 delete [] Lp_;
200 delete [] Lx_;
201 delete [] Li_;
202 delete [] P_;
203 delete [] Pinv_;
204 isloaded_ = false;
205 }
206 }
207
214 template<typename... DFs>
215 void apply(const TupleDiscreteFunction<DFs...>& arg,TupleDiscreteFunction<DFs...>& dest) const
216 {
217 // copy DOF's arg into a consecutive vector
218 std::vector<DofType> vecArg(arg.size());
219 auto vecArgIt(vecArg.begin());
220 Hybrid::forEach(std::make_index_sequence<sizeof...(DFs)>{},
221 [&](auto i){vecArgIt=std::copy(std::get<i>(arg).dbegin(),std::get<i>(arg).dend(),vecArgIt);});
222 std::vector<DofType> vecDest(dest.size());
223 // apply operator
224 apply(vecArg.data(),vecDest.data());
225 // copy back solution into dest
226 auto vecDestIt(vecDest.begin());
227 Hybrid::forEach(std::make_index_sequence<sizeof...(DFs)>{},[&](auto i){for(auto& dof:dofs(std::get<i>(dest))) dof=(*(vecDestIt++));});
228 }
229
230protected:
231 void printTexInfo(std::ostream& out) const
232 {
233 out<<"Solver: LDL direct solver"<<std::endl;
234 }
235
236 // \brief Print some statistics about the LDL decomposition.
237 void printDecompositionInfo() const
238 {
239 amd_info(info_);
240 }
241
245 DofType* getD()
246 {
247 return D_;
248 }
249
253 int* getLp()
254 {
255 return Lp_;
256 }
257
261 int* getLi()
262 {
263 return Li_;
264 }
265
269 DofType* getLx()
270 {
271 return Lx_;
272 }
273
277 CCSMatrixType& getCCSMatrix()
278 {
279 return ccsmat_;
280 }
281
282protected:
289 void apply(const DofType* arg, DofType* dest) const
290 {
291 prepare();
292
293 // apply part of the call
294 const std::size_t dimMat(ccsmat_.N());
295 ldl_perm(dimMat, Y_, const_cast<DofType*>(arg), P_);
296 ldl_lsolve(dimMat, Y_, Lp_, Li_, Lx_);
297 ldl_dsolve(dimMat, Y_, D_);
298 ldl_ltsolve(dimMat, Y_, Lp_, Li_, Lx_);
299 ldl_permt(dimMat, dest, Y_, P_);
300
301 const_cast<ThisType*>(this)->finalize();
302 }
303
310 int apply(const SolverDiscreteFunctionType& arg,
311 SolverDiscreteFunctionType& dest) const
312 {
313 apply(arg.leakPointer(),dest.leakPointer());
314 return 0;
315 }
316
317
318protected:
319 using BaseType :: assembledOperator_;
320 const bool verbose_;
321
322 mutable CCSMatrixType ccsmat_;
323 mutable bool isloaded_ = false;
324 mutable int* Lp_;
325 mutable int* Parent_;
326 mutable int* Lnz_;
327 mutable int* Flag_;
328 mutable int* Pattern_;
329 mutable int* P_;
330 mutable int* Pinv_;
331 mutable DofType* D_;
332 mutable DofType* Y_;
333 mutable DofType* Lx_;
334 mutable int* Li_;
335 mutable double info_[AMD_INFO];
336
337 // \brief Computes the LDL decomposition.
338 void decompose() const
339 {
340 // allocate vectors
341 const std::size_t dimMat(ccsmat_.N());
342 D_ = new DofType [dimMat];
343 Y_ = new DofType [dimMat];
344 Lp_ = new int [dimMat + 1];
345 Parent_ = new int [dimMat];
346 Lnz_ = new int [dimMat];
347 Flag_ = new int [dimMat];
348 Pattern_ = new int [dimMat];
349 P_ = new int [dimMat];
350 Pinv_ = new int [dimMat];
351
352 if(amd_order (dimMat, ccsmat_.getColStart(), ccsmat_.getRowIndex(), P_, (DofType *) NULL, info_) < AMD_OK)
353 DUNE_THROW(InvalidStateException,"LDL Error: AMD failed!");
354 if(verbose_)
355 printDecompositionInfo();
356 // compute the symbolic factorisation
357 ldl_symbolic(dimMat, ccsmat_.getColStart(), ccsmat_.getRowIndex(), Lp_, Parent_, Lnz_, Flag_, P_, Pinv_);
358 // initialise those entries of additionalVectors_ whose dimension is known only now
359 Lx_ = new DofType [Lp_[dimMat]];
360 Li_ = new int [Lp_[dimMat]];
361 // compute the numeric factorisation
362 const std::size_t k(ldl_numeric(dimMat, ccsmat_.getColStart(), ccsmat_.getRowIndex(), ccsmat_.getValues(),
363 Lp_, Parent_, Lnz_, Li_, Lx_, D_, Y_, Pattern_, Flag_, P_, Pinv_));
364 // free temporary vectors
365 delete [] Flag_;
366 delete [] Pattern_;
367 delete [] Parent_;
368 delete [] Lnz_;
369
370 if(k!=dimMat)
371 {
372 std::cerr<<"LDL Error: D("<<k<<","<<k<<") is zero!"<<std::endl;
373 DUNE_THROW(InvalidStateException,"LDL Error: factorisation failed!");
374 }
375 }
376};
377
378// deprecated old type
379template<class DF, class Op, bool symmetric=false>
380using LDLOp = LDLInverseOperator< DF, typename Op::MatrixType >;
381
382} // end namespace Fem
383} // end namespace Dune
384
385#endif // #if HAVE_SUITESPARSE_LDL
386
387#endif // #ifndef DUNE_FEM_LDLSOLVER_HH
Inverse operator base on CG method. Uses a runtime parameter fem.preconditioning which enables diagon...
Definition: cginverseoperator.hh:408
forward declaration
Definition: discretefunction.hh:51
A few common exception classes.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
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 (Jul 27, 22:29, 2024)