dune-fem  2.4.1-rc
ldlsolver.hh
Go to the documentation of this file.
1 #ifndef DUNE_FEM_LDLSOLVER_HH
2 #define DUNE_FEM_LDLSOLVER_HH
3 
4 #include <limits>
5 #include <iostream>
6 #include <type_traits>
7 #include <vector>
8 #include <algorithm>
9 
12 
14 #include <dune/fem/io/parameter.hh>
16 
17 #if HAVE_LDL
18 #ifdef __cplusplus
19 extern "C"
20 {
21 #include "ldl.h"
22 #include "amd.h"
23 }
24 #endif
25 
26 namespace Dune
27 {
28 namespace Fem
29 {
30 
47 template<class DF, class Op>
48 class LDLOp:public Operator<DF, DF>
49 {
50  public:
51  typedef DF DiscreteFunctionType;
52  typedef Op OperatorType;
53 
54  // \brief The column-compressed matrix type.
55  typedef ColCompMatrix<typename OperatorType::MatrixType::MatrixBaseType> CCSMatrixType;
56  typedef typename DiscreteFunctionType::DofType DofType;
57  typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
58 
66  LDLOp(const OperatorType& op, const double& redEps, const double& absLimit, const int& maxIter, const bool& verbose,
67  const ParameterReader &parameter = Parameter::container() ) :
68  op_(op), verbose_(verbose), ccsmat_(), isloaded_(false)
69  {}
70 
77  LDLOp(const OperatorType& op, const double& redEps, const double& absLimit, const int& maxIter,
78  const ParameterReader &parameter = Parameter::container() ) :
79  op_(op), verbose_(parameter.getValue<bool>("fem.solver.verbose",false)), ccsmat_(), isloaded_(false)
80  {}
81 
82  LDLOp(const OperatorType& op, const ParameterReader &parameter = Parameter::container() ) :
83  op_(op), verbose_(parameter.getValue<bool>("fem.solver.verbose",false)), ccsmat_(), isloaded_(false)
84  {}
85  // \brief Destructor.
86  ~LDLOp()
87  {}
88 
93  void operator()(const DiscreteFunctionType& arg, DiscreteFunctionType& dest) const
94  {
95  prepare();
96  apply(arg,dest);
97  finalize();
98  }
99 
100  // \brief Decompose matrix.
101  template<typename... A>
102  void prepare(A... ) const
103  {
104  if(!isloaded_)
105  {
106  ccsmat_ = op_.systemMatrix().matrix();
107  decompose();
108  isloaded_ = true;
109  }
110  }
111 
112  // \brief Free allocated memory.
113  inline void finalize() const
114  {
115  if(isloaded_)
116  {
117  ccsmat_.free();
118  delete [] D_;
119  delete [] Y_;
120  delete [] Lp_;
121  delete [] Lx_;
122  delete [] Li_;
123  delete [] P_;
124  delete [] Pinv_;
125  isloaded_ = false;
126  }
127  }
128 
135  void apply(const DofType*& arg, DofType*& dest) const
136  {
137  const std::size_t dimMat(ccsmat_.N());
138  ldl_perm(dimMat, Y_, const_cast<DofType*>(arg), P_);
139  ldl_lsolve(dimMat, Y_, Lp_, Li_, Lx_);
140  ldl_dsolve(dimMat, Y_, D_);
141  ldl_ltsolve(dimMat, Y_, Lp_, Li_, Lx_);
142  ldl_permt(dimMat, dest, Y_, P_);
143  }
144 
151  void apply(const AdaptiveDiscreteFunction<DiscreteFunctionSpaceType>& arg,
152  AdaptiveDiscreteFunction<DiscreteFunctionSpaceType>& dest) const
153  {
154  const DofType* argPtr(arg.leakPointer());
155  DofType* destPtr(dest.leakPointer());
156  apply(argPtr,destPtr);
157  }
158 
165  void apply(const ISTLBlockVectorDiscreteFunction<DiscreteFunctionSpaceType>& arg,
166  ISTLBlockVectorDiscreteFunction<DiscreteFunctionSpaceType>& dest) const
167  {
168  // copy DOF arg into a consecutive vector
169  std::vector<DofType> vecArg(arg.size());
170  std::copy(arg.dbegin(),arg.dend(),vecArg.begin());
171  std::vector<DofType> vecDest(dest.size());
172  // apply operator
173  const DofType* argDataPtr(vecArg.data());
174  DofType* destDataPtr(vecDest.data());
175  apply(argDataPtr,destDataPtr);
176  // copy back solution into dest
177  std::copy(vecDest.begin(),vecDest.end(),dest.dbegin());
178  }
179 
180  inline void printTexInfo(std::ostream& out) const
181  {
182  out<<"Solver: LDL direct solver";
183  out<<"\\\\ \n";
184  }
185 
186  inline double averageCommTime() const
187  {
188  return 0.0;
189  }
190 
191  inline int iterations() const
192  {
193  return 0;
194  }
195 
199  inline DofType*& getD()
200  {
201  return D_;
202  }
203 
207  inline int*& getLp()
208  {
209  return Lp_;
210  }
211 
215  inline int*& getLi()
216  {
217  return Li_;
218  }
219 
223  inline DofType*& getLx()
224  {
225  return Lx_;
226  }
227 
231  inline CCSMatrixType& getCCSMatrix()
232  {
233  return ccsmat_;
234  }
235 
236  private:
237  const OperatorType& op_;
238  const bool verbose_;
239  mutable CCSMatrixType ccsmat_;
240  mutable bool isloaded_;
241  mutable int* Lp_;
242  mutable int* Parent_;
243  mutable int* Lnz_;
244  mutable int* Flag_;
245  mutable int* Pattern_;
246  mutable int* P_;
247  mutable int* Pinv_;
248  mutable DofType* D_;
249  mutable DofType* Y_;
250  mutable DofType* Lx_;
251  mutable int* Li_;
252 
253  // /brief Computes the LDL decomposition.
254  void decompose() const
255  {
256  // allocate vectors
257  const std::size_t dimMat(ccsmat_.N());
258  D_ = new DofType [dimMat];
259  Y_ = new DofType [dimMat];
260  Lp_ = new int [dimMat + 1];
261  Parent_ = new int [dimMat];
262  Lnz_ = new int [dimMat];
263  Flag_ = new int [dimMat];
264  Pattern_ = new int [dimMat];
265  P_ = new int [dimMat];
266  Pinv_ = new int [dimMat];
267 
268  double Info [AMD_INFO];
269  if(amd_order (dimMat, ccsmat_.getColStart(), ccsmat_.getRowIndex(), P_, (DofType *) NULL, Info) < AMD_OK)
270  std::cout<<"WARNING: call to AMD failed."<<std::endl;
271  if(verbose_)
272  amd_info (Info);
273  // compute the symbolic factorisation
274  ldl_symbolic(dimMat, ccsmat_.getColStart(), ccsmat_.getRowIndex(), Lp_, Parent_, Lnz_, Flag_, P_, Pinv_);
275  // initialise those entries of additionalVectors_ whose dimension is known only now
276  Lx_ = new DofType [Lp_[dimMat]];
277  Li_ = new int [Lp_[dimMat]];
278  // compute the numeric factorisation
279  const int rank(ldl_numeric(dimMat, ccsmat_.getColStart(), ccsmat_.getRowIndex(), ccsmat_.getValues(),
280  Lp_, Parent_, Lnz_, Li_, Lx_, D_, Y_, Pattern_, Flag_, P_, Pinv_));
281  // free temporary vectors
282  delete [] Flag_;
283  delete [] Pattern_;
284  delete [] Parent_;
285  delete [] Lnz_;
286 
287  if(rank!=dimMat)
288  std::cout<<"WARNING: matrix is singular."<<std::endl;
289  }
290 };
291 
292 }
293 }
294 
295 #endif // #if HAVE_SPQR
296 
297 #endif // #ifndef DUNE_FEM_SPQRSOLVER_HH
BasicParameterReader< std::function< const std::string *(const std::string &, const std::string *) > > ParameterReader
Definition: reader.hh:264
Definition: coordinate.hh:4
static ParameterContainer & container()
Definition: io/parameter.hh:190