Loading [MathJax]/extensions/tex2jax.js
ug4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
lu.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3 * Author: Martin Rupp
4 *
5 * This file is part of UG4.
6 *
7 * UG4 is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License version 3 (as published by the
9 * Free Software Foundation) with the following additional attribution
10 * requirements (according to LGPL/GPL v3 §7):
11 *
12 * (1) The following notice must be displayed in the Appropriate Legal Notices
13 * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 *
15 * (2) The following notice must be displayed at a prominent place in the
16 * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 *
18 * (3) The following bibliography is recommended for citation and must be
19 * preserved in all covered files:
20 * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 * parallel geometric multigrid solver on hierarchically distributed grids.
22 * Computing and visualization in science 16, 4 (2013), 151-164"
23 * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 * flexible software system for simulating pde based models on high performance
25 * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU Lesser General Public License for more details.
31 */
32
33#ifndef __H__LIB_ALGEBRA__LAPACK_LU_OPERATOR__
34#define __H__LIB_ALGEBRA__LAPACK_LU_OPERATOR__
35#include <iostream>
36#include <sstream>
37
38#include "common/common.h"
40
41#ifdef UG_PARALLEL
43#endif
44#include "../preconditioner/ilut_scalar.h"
45#include "../interface/preconditioned_linear_operator_inverse.h"
46#include "linear_solver.h"
47
49
50#include "../operator_util.h"
51namespace ug{
52
53template <typename TAlgebra>
54class LU
55 : public IMatrixOperatorInverse<typename TAlgebra::matrix_type,
56 typename TAlgebra::vector_type>
57{
58 public:
60 typedef TAlgebra algebra_type;
61
63 typedef typename TAlgebra::vector_type vector_type;
64
66 typedef typename TAlgebra::matrix_type matrix_type;
67
70
71 using base_type::init;
72
73 protected:
75
76 public:
78 LU() : m_spOperator(NULL), m_mat(), m_bSortSparse(true), m_bInfo(false), m_bShowProgress(true)
79 {
80#ifdef LAPACK_AVAILABLE
82#else
84#endif
85 };
86
88 virtual bool supports_parallel() const {return false;}
89
92 {
94 }
95
96 void set_sort_sparse(bool b)
97 {
98 m_bSortSparse = b;
99 }
100
101 void set_info(bool b)
102 {
103 m_bInfo = b;
104 }
105
106 void set_show_progress(bool b)
107 {
108 m_bShowProgress = b;
109 }
110
111 virtual const char* name() const {return "LU";}
112
113 private:
114
115 void print_info(const matrix_type &A)
116 {
118 UG_LOG("Matrix " << A.num_rows() << " x " << A.num_rows() << " with " << blockSize << " x " << blockSize << " blocks");
119 }
120
122 bool init_dense(const matrix_type &A)
123 {
124 PROFILE_FUNC();
125 m_bDense = true;
126
127 if(m_bInfo)
128 {
129 UG_LOG("LU, using DenseLU on ");
130 print_info(A);
131 UG_LOG("\n DenseLU needs " << GetBytesSizeString(m_size*m_size*sizeof(double)) << " of memory.\n");
132 }
133
135
136 if(m_mat.invert() == false)
137 {
138 UG_THROW("ERROR in Matrix is singular");
139 return false;
140 }
141 else
142 return true;
143 }
144
145 void init_var(const matrix_type &A)
146 {
147 UG_ASSERT(0, "not yet tested");
148 /*m_size = 0;
149 std::vector<size_t> blockbegin(A.num_rows()+1);
150
151 for(size_t i=0; i<A.num_rows(); i++)
152 {
153 bool bFound;
154 typename matrix_type::const_row_iterator it = A.get_connection(i,i, bFound);
155 UG_ASSERT(bFound, "Matrix has to have entry A(" << i << ", " << i << ")");
156 size_t s = GetRows(it.value());
157 UG_ASSERT(s == GetCols(it.value()), "diagonal elements have to be square");
158 if(i == 0)
159 blockbegin[i] = m_size;
160 m_size += s;
161 }
162 blockbegin[A.num_rows()] = m_size;
163
164 m_mat.resize(m_size);
165
166 for(size_t r=0; r<A.num_rows(); r++)
167 for(typename matrix_type::const_row_iterator it = A.begin_row(r); it != A.end_row(r); ++it)
168 {
169 size_t c = it.index();
170 const typename matrix_type::value_type &val = it.value();
171 UG_ASSERT(blockbegin[r]+GetRows(val) == blockbegin[r+1], "blocksizes in matrix inconsistent");
172 UG_ASSERT(blockbegin[c]+GetCols(val) == blockbegin[c+1], "blocksizes in matrix inconsistent");
173 for(size_t r2=0; r2 < GetRows(val); r2++)
174 for(size_t c2=0; c2 < GetCols(val); c2++)
175 m_mat(blockbegin[r] + r2, blockbegin[c]+c2) = BlockRef(val, r2, c2);
176 }
177*/
178 }
179
180
182 {
183 try{
184 PROFILE_FUNC();
185 m_bDense = false;
186
187 if(m_bInfo)
188 {
189 UG_LOG("LU using Sparse LU on ");
190 print_info(A);
191 UG_LOG("\n");
192 }
194 ilut_scalar->set_sort(m_bSortSparse);
195 ilut_scalar->set_info(m_bInfo);
196 ilut_scalar->set_show_progress(m_bShowProgress);
197 ilut_scalar->preprocess(A);
198
199 }UG_CATCH_THROW("LU::" << __FUNCTION__ << " failed")
200 return true;
201 }
202
204 {
205 try{
206 PROFILE_FUNC();
207 x = b;
208 m_tmp.resize(m_size);
209 for(size_t i=0, k=0; i<b.size(); i++)
210 {
211 for(size_t j=0; j<GetSize(b[i]); j++)
212 m_tmp[k++] = BlockRef(b[i],j);
213 }
214 m_mat.apply(m_tmp);
215
216
217 for(size_t i=0, k=0; i<b.size(); i++)
218 {
219 for(size_t j=0; j<GetSize(b[i]); j++)
220 BlockRef(x[i],j) = m_tmp[k++];
221 }
222
223 }UG_CATCH_THROW("LU::" << __FUNCTION__ << " failed")
224 return true;
225 }
226
228 {
229 PROFILE_FUNC();
230 ilut_scalar->solve(x, b);
231 return true;
232 }
233
234 public:
236 bool init_lu(const matrix_type *pA)
237 {
238 try{
239 // get matrix of Operator
240 m_pMatrix = pA;
241 if(m_pMatrix->num_rows() == 0) return true;
242
243 // check that matrix exist
244 if(m_pMatrix == NULL)
245 {
246 UG_LOG("ERROR in 'LU::init': No Matrix given.\n");
247 return false;
248 }
249
250 const matrix_type &A = *pA;
251
252 PROFILE_FUNC();
253 PROFILE_BEGIN_GROUP(LU_init_lu, "algebra lu");
255 {
257 UG_ASSERT(nrOfRows == block_traits<typename matrix_type::value_type>::static_num_cols, "only square matrices supported");
258 m_size = A.num_rows() * nrOfRows;
259
261 init_sparse(A);
262 else
263 init_dense(A);
264 }
265 else
266 init_var(A);
267 }UG_CATCH_THROW("LU::" << __FUNCTION__ << " failed")
268 return true;
269 }
270
272 {
273 if(m_pMatrix->num_rows() == 0) return true;
274 try{
275 PROFILE_BEGIN_GROUP(LU_apply_lu, "algebra lu");
276#ifndef NDEBUG
278 {
280 UG_ASSERT(m_size == b.size() * static_size && m_size == x.size() * static_size,
281 " wrong size! has to be " << m_size << ", but is " << b << " and " << x);
282 }
283 else
284 {
285 size_t b_size = 0;
286 for(size_t i=0; i<b.size(); i++)
287 {
288 UG_ASSERT(GetSize(b[i]) == GetSize(x[i]), "wrong size! Sizes of b and x must be the same, but is "
289 << GetSize(b[i]) << " and " << GetSize(x[i]) << "!");
290 b_size += GetSize(b[i]);
291 }
292 UG_ASSERT(m_size == b_size, " wrong size! has to be " << m_size << ", but is " << b_size << "!");
293 }
294#endif
295
296 if(m_bDense)
297 return solve_dense(x, b);
298 else
299 return solve_sparse(x, b);
300
301 }UG_CATCH_THROW("LU::" << __FUNCTION__ << " failed")
302 }
303
306 {
307 // remember operator
308 m_spOperator = Op;
309
310 // init LU operator
312 {
313 UG_LOG("ERROR in 'LU::init': Cannot init LU Decomposition.\n");
314 return false;
315 }
316
317 // we're done
318 return true;
319 }
320
322 virtual bool apply(vector_type& u, const vector_type& f)
323 {
324 PROFILE_FUNC();
325 convergence_check()->set_symbol('%');
326 convergence_check()->set_name("LU Solver");
327
328#ifdef UG_PARALLEL
329 if(!f.has_storage_type(PST_ADDITIVE))
330 {
331 UG_LOG("ERROR: In 'LU::apply': "
332 "Inadequate storage format of Vector f.\n");
333 return false;
334 }
335 if(!u.has_storage_type(PST_CONSISTENT))
336 {
337 UG_LOG("ERROR: In 'LU::apply': "
338 "Inadequate storage format of Vector u.\n");
339 return false;
340 }
341#endif
342 UG_ASSERT(f.size() == m_pMatrix->num_rows(), "Vector ["<<f.size()<<"] and Row "<<m_pMatrix->num_rows()<<" size mismatch");
343 UG_ASSERT(u.size() == m_pMatrix->num_cols(), "Vector ["<<u.size()<<"] and Col "<<m_pMatrix->num_cols()<<" size mismatch");
344 UG_ASSERT(f.size() == u.size(), "Vector sizes have to match!");
345
346 if(!apply_lu(u, f))
347 {
348 UG_LOG("ERROR in 'LU::apply': "
349 "Cannot apply LU decomposition.\n");
350 return false;
351 }
352
353#ifdef UG_PARALLEL
354 // todo: we set solution to consistent here, but that is only true for
355 // serial case. Handle parallel case.
356 u.set_storage_type(PST_CONSISTENT);
357#endif
358
359 // we're done
360 return true;
361 }
362
365 {
366 PROFILE_BEGIN_GROUP(LU_apply_return_defect, "algebra lu");
367 // solve u
368 if(!apply(u, f)) return false;
369
370 // update defect
371 if(!m_pMatrix->matmul_minus(f, u))
372 {
373 UG_LOG("ERROR in 'LU::apply_return_defect': "
374 "Cannot apply matmul_minus.\n");
375 return false;
376 }
377
378 // we're done
379 return true;
380 }
381
382 virtual std::string config_string() const
383 {
384 std::stringstream ss;
385 ss << "LU Decomposition: Direct Solver for Linear Equation Systems.\n";
386 ss << " Minimum Entries for Sparse LU: " << m_iMinimumForSparse;
388 ss << " (= always Sparse LU)";
389 return ss.str();
390 }
391
392
394 virtual ~LU() {};
395
396 protected:
399
402
408 size_t m_size;
409
414};
415
416} // end namespace ug
417
418#endif /* __H__LIB_ALGEBRA__LAPACK_LU_OPERATOR__ */
Definition smart_pointer.h:108
Definition lapack_densematrix_inverse.h:51
Definition densevector.h:101
Definition ilut_scalar.h:53
ConstSmartPtr< IConvergenceCheck< X > > convergence_check() const
returns the convergence check
Definition linear_operator_inverse.h:202
describes an inverse linear mapping X->Y based on a matrix
Definition matrix_operator_inverse.h:64
virtual bool init(SmartPtr< MatrixOperator< M, Y, X > > A)=0
initializes this inverse operator for a matrix-based operator
Definition lu.h:57
DenseVector< VariableArray1< double > > m_tmp
Definition lu.h:405
bool solve_dense(vector_type &x, const vector_type &b)
Definition lu.h:203
virtual bool apply_return_defect(vector_type &u, vector_type &f)
Compute u = L^{-1} * f AND return defect f := f - L*u.
Definition lu.h:364
bool init_lu(const matrix_type *pA)
initializes the solver for a matrix A
Definition lu.h:236
bool init_sparse(const matrix_type &A)
Definition lu.h:181
virtual const char * name() const
returns the name of the operator inverse
Definition lu.h:111
size_t m_size
Definition lu.h:408
TAlgebra::matrix_type matrix_type
Matrix type.
Definition lu.h:66
bool m_bDense
Definition lu.h:410
virtual bool supports_parallel() const
returns if parallel solving is supported
Definition lu.h:88
void set_info(bool b)
Definition lu.h:101
bool init_dense(const matrix_type &A)
returns name of solver
Definition lu.h:122
LU()
constructor
Definition lu.h:78
CPUAlgebra::vector_type m_u
Definition lu.h:406
bool m_bSortSparse
Definition lu.h:413
size_t m_iMinimumForSparse
Definition lu.h:412
SmartPtr< MatrixOperator< matrix_type, vector_type > > m_spOperator
Operator to invert.
Definition lu.h:398
void set_show_progress(bool b)
Definition lu.h:106
virtual bool apply(vector_type &u, const vector_type &f)
Compute u = L^{-1} * f.
Definition lu.h:322
virtual std::string config_string() const
returns information about configuration parameters
Definition lu.h:382
void print_info(const matrix_type &A)
Definition lu.h:115
SmartPtr< ILUTScalarPreconditioner< algebra_type > > ilut_scalar
Definition lu.h:411
virtual ~LU()
Destructor.
Definition lu.h:394
void set_sort_sparse(bool b)
Definition lu.h:96
IMatrixOperatorInverse< matrix_type, vector_type > base_type
Base type.
Definition lu.h:69
bool m_bShowProgress
Definition lu.h:413
TAlgebra algebra_type
Algebra type.
Definition lu.h:60
bool apply_lu(vector_type &x, const vector_type &b)
Definition lu.h:271
bool m_bInfo
Definition lu.h:413
bool solve_sparse(vector_type &x, const vector_type &b)
Definition lu.h:227
DenseMatrixInverse< DenseMatrix< VariableArray2< double > > > m_mat
inverse
Definition lu.h:404
void set_minimum_for_sparse(size_t N)
Definition lu.h:91
virtual bool init(SmartPtr< MatrixOperator< matrix_type, vector_type > > Op)
set operator L, that will be inverted
Definition lu.h:305
void init_var(const matrix_type &A)
Definition lu.h:145
CPUAlgebra::vector_type m_b
Definition lu.h:407
TAlgebra::vector_type vector_type
Vector type.
Definition lu.h:63
const matrix_type * m_pMatrix
matrix to invert
Definition lu.h:401
Definition matrix_operator.h:49
virtual M & get_matrix()
Definition matrix_operator.h:74
@ PST_CONSISTENT
Definition parallel_storage_type.h:68
@ PST_ADDITIVE
Definition parallel_storage_type.h:69
size_t GetDenseDoubleFromSparse(TDenseType &A, const TSparseMatrix &S)
Definition sparsematrix_util.h:1207
#define UG_ASSERT(expr, msg)
Definition assert.h:70
#define UG_CATCH_THROW(msg)
Definition error.h:64
#define UG_THROW(msg)
Definition error.h:57
#define UG_LOG(msg)
Definition log.h:367
the ug namespace
double & BlockRef(T &vec, size_t i)
Definition blocks.h:66
string GetBytesSizeString(size_t s, int length)
Definition string_util.cpp:489
size_t GetSize(const T &t)
#define PROFILE_BEGIN_GROUP(name, groups)
Definition profiler.h:255
#define PROFILE_FUNC()
Definition profiler.h:257
SmartPtr< T, FreePolicy > make_sp(T *inst)
returns a SmartPtr for the passed raw pointer
Definition smart_pointer.h:836
Definition communication_policies.h:58