OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
iluprecond.C
Go to the documentation of this file.
1 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
2 /* ******** *** SparseLib++ */
3 /* ******* ** *** *** *** v. 1.5c */
4 /* ***** *** ******** ******** */
5 /* ***** *** ******** ******** R. Pozo */
6 /* ** ******* *** ** *** *** K. Remington */
7 /* ******** ******** A. Lumsdaine */
8 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9 /* */
10 /* */
11 /* SparseLib++ : Sparse Matrix Library */
12 /* */
13 /* National Institute of Standards and Technology */
14 /* University of Notre Dame */
15 /* Authors: R. Pozo, K. Remington, A. Lumsdaine */
16 /* */
17 /* NOTICE */
18 /* */
19 /* Permission to use, copy, modify, and distribute this software and */
20 /* its documentation for any purpose and without fee is hereby granted */
21 /* provided that the above notice appear in all copies and supporting */
22 /* documentation. */
23 /* */
24 /* Neither the Institutions (National Institute of Standards and Technology, */
25 /* University of Notre Dame) nor the Authors make any representations about */
26 /* the suitability of this software for any purpose. This software is */
27 /* provided ``as is'' without expressed or implied warranty. */
28 /* */
29 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
30 
31 // adapted & optimized by Borek Patzak
32 
33 #include "dyncompcol.h"
34 #include "iluprecond.h"
35 #include "verbose.h"
36 
37 #ifdef TIME_REPORT
38  #include "timer.h"
39 #endif
40 
41 #ifdef DynCompCol_USE_STL_SETS
42  #include <map>
43 #endif
44 
45 namespace oofem {
47 CompCol_ILUPreconditioner(const SparseMtrx &A, InputRecord &attributes) : Preconditioner(A, attributes)
48 { }
49 
52 {
54 }
55 
56 
57 void
59 {
60 #ifdef TIME_REPORT
61  Timer timer;
62  timer.startTimer();
63 #endif
64 
65  if ( dynamic_cast< const CompCol * >(&A) ) {
66  this->initialize( * ( ( CompCol * ) & A ) );
67  } else if ( dynamic_cast< const DynCompCol * >(&A) ) {
68  this->initialize( * ( ( DynCompCol * ) & A ) );
69  } else {
70  OOFEM_ERROR("unsupported sparse matrix type");
71  }
72 
73 #ifdef TIME_REPORT
74  timer.stopTimer();
75  OOFEM_LOG_INFO( "ILUP: user time consumed by factorization: %.2fs\n", timer.getUtime() );
76 #endif
77 }
78 
79 
80 void
82 {
83  int i, j, k, pn, qn, rn;
84  double multiplier;
85 
86  // Copy
87  dim_ [ 0 ] = A.giveNumberOfRows();
88  dim_ [ 1 ] = A.giveNumberOfColumns();
89 
90  l_colptr_.resize(A.dim(1) + 1);
91  u_colptr_.resize(A.dim(1) + 1);
92 
93  l_nz_ = 0;
94  u_nz_ = 0;
95 
96  // Get size of l and u
97  for ( i = 0; i < dim_ [ 1 ]; i++ ) {
98  for ( j = A.col_ptr(i); j < A.col_ptr(i + 1); j++ ) {
99  if ( A.row_ind(j) > i ) {
100  l_nz_++;
101  } else {
102  u_nz_++;
103  }
104  }
105  }
106 
111 
112  l_colptr_(0) = u_colptr_(0) = 0;
113 
114  // Split up A into l and u
115  for ( i = 0; i < dim_ [ 1 ]; i++ ) {
116  l_colptr_(i + 1) = l_colptr_(i);
117  u_colptr_(i + 1) = u_colptr_(i);
118 
119  for ( j = A.col_ptr(i); j < A.col_ptr(i + 1); j++ ) {
120  if ( A.row_ind(j) > i ) {
121  k = l_colptr_(i + 1)++;
122  l_val_(k) = A.val(j);
123  l_rowind_(k) = A.row_ind(j);
124  } else if ( A.row_ind(j) <= i ) {
125  k = u_colptr_(i + 1)++;
126  u_val_(k) = A.val(j);
127  u_rowind_(k) = A.row_ind(j);
128  }
129  }
130  }
131 
132  /* sort entries to assure entries stored with increasing row index */
133  /*
134  * for (i = 0; i < dim_[1]; i++) {
135  * QSort(l_rowind_, l_val_, l_colptr_[i], l_colptr_[i+1] - l_colptr_[i]);
136  * QSort(u_rowind_, u_val_, u_colptr_[i], u_colptr_[i+1] - u_colptr_[i]);
137  * }
138  */
139  // Factor matrix
140  for ( i = 0; i < dim_ [ 0 ] - 1; i++ ) {
141  multiplier = u_val_(u_colptr_(i + 1) - 1);
142 
143  for ( j = l_colptr_(i); j < l_colptr_(i + 1); j++ ) {
144  l_val_(j) /= multiplier;
145  }
146 
147  for ( j = u_colptr_(i + 1); j < u_colptr_(i + 2) - 1; j++ ) {
148  multiplier = u_val_(j);
149  qn = j + 1;
150  rn = l_colptr_(i + 1);
151  for ( pn = l_colptr_( u_rowind_(j) );
152  pn < l_colptr_(u_rowind_(j) + 1) && l_rowind_(pn) <= i + 1; pn++ ) {
153  while ( qn < u_colptr_(i + 2) && u_rowind_(qn) < l_rowind_(pn) ) {
154  qn++;
155  }
156 
157  if ( qn < u_colptr_(i + 2) && l_rowind_(pn) == u_rowind_(qn) ) {
158  u_val_(qn) -= multiplier * l_val_(pn);
159  }
160  }
161 
162  for ( ; pn < l_colptr_(u_rowind_(j) + 1); pn++ ) {
163  while ( rn < l_colptr_(i + 2) && l_rowind_(rn) < l_rowind_(pn) ) {
164  rn++;
165  }
166 
167  if ( rn < l_colptr_(i + 2) && l_rowind_(pn) == l_rowind_(rn) ) {
168  l_val_(rn) -= multiplier * l_val_(pn);
169  }
170  }
171  }
172  }
173 }
174 
175 
176 void
178 {
179  int i, j, k, pn, qn, rn;
180  double multiplier;
181 
182  // Copy
183  dim_ [ 0 ] = A.giveNumberOfRows();
184  dim_ [ 1 ] = A.giveNumberOfColumns();
185 
188 
189  l_nz_ = 0;
190  u_nz_ = 0;
191 
192 #ifndef DynCompCol_USE_STL_SETS
193  // Get size of l and u
194  for ( i = 0; i < dim_ [ 1 ]; i++ ) {
195  for ( j = 0; j < A.row_ind(i)->giveSize(); j++ ) {
196  if ( A.row_ind(i)->at(j + 1) > i ) {
197  l_nz_++;
198  } else {
199  u_nz_++;
200  }
201  }
202  }
203 
208 
209  l_colptr_(0) = u_colptr_(0) = 0;
210 
211  // Split up A into l and u
212  for ( i = 0; i < dim_ [ 1 ]; i++ ) {
213  l_colptr_(i + 1) = l_colptr_(i);
214  u_colptr_(i + 1) = u_colptr_(i);
215 
216  for ( j = 0; j < A.row_ind(i)->giveSize(); j++ ) {
217  if ( A.row_ind(i)->at(j + 1) > i ) {
218  k = l_colptr_(i + 1)++;
219  l_val_(k) = A.column(i)->at(j + 1);
220  l_rowind_(k) = A.row_ind(i)->at(j + 1);
221  } else if ( A.row_ind(i)->at(j + 1) <= i ) {
222  k = u_colptr_(i + 1)++;
223  u_val_(k) = A.column(i)->at(j + 1);
224  u_rowind_(k) = A.row_ind(i)->at(j + 1);
225  }
226  }
227  }
228 
229 #else
230  // Get size of l and u
231  for ( i = 0; i < dim_ [ 1 ]; i++ ) {
232  for ( auto &val: A.column(i) ) {
233  if ( val.first > i ) {
234  l_nz_++;
235  } else {
236  u_nz_++;
237  }
238  }
239  }
240 
245 
246  l_colptr_(0) = u_colptr_(0) = 0;
247 
248  // Split up A into l and u
249  for ( i = 0; i < dim_ [ 1 ]; i++ ) {
250  l_colptr_(i + 1) = l_colptr_(i);
251  u_colptr_(i + 1) = u_colptr_(i);
252 
253  for ( auto &val: A.column(i) ) {
254  if ( val.first > i ) {
255  k = l_colptr_(i + 1)++;
256  l_val_(k) = val.second;
257  l_rowind_(k) = val.first;
258  } else if ( val.first <= i ) {
259  k = u_colptr_(i + 1)++;
260  u_val_(k) = val.second;
261  u_rowind_(k) = val.first;
262  }
263  }
264  }
265 
266 #endif
267  /* sort entries to assure entries stored with increasing row index */
268 
269  for ( i = 0; i < dim_ [ 1 ]; i++ ) {
270  qsortRow(l_rowind_, l_val_, l_colptr_(i), l_colptr_(i + 1) - 1);
271  qsortRow(u_rowind_, u_val_, u_colptr_(i), u_colptr_(i + 1) - 1);
272  }
273 
274  // Factor matrix
275  for ( i = 0; i < dim_ [ 0 ] - 1; i++ ) {
276  multiplier = u_val_(u_colptr_(i + 1) - 1);
277 
278  for ( j = l_colptr_(i); j < l_colptr_(i + 1); j++ ) {
279  l_val_(j) /= multiplier;
280  }
281 
282  for ( j = u_colptr_(i + 1); j < u_colptr_(i + 2) - 1; j++ ) {
283  multiplier = u_val_(j);
284  qn = j + 1;
285  rn = l_colptr_(i + 1);
286  for ( pn = l_colptr_( u_rowind_(j) );
287  pn < l_colptr_(u_rowind_(j) + 1) && l_rowind_(pn) <= i + 1; pn++ ) {
288  while ( qn < u_colptr_(i + 2) && u_rowind_(qn) < l_rowind_(pn) ) {
289  qn++;
290  }
291 
292  if ( qn < u_colptr_(i + 2) && l_rowind_(pn) == u_rowind_(qn) ) {
293  u_val_(qn) -= multiplier * l_val_(pn);
294  }
295  }
296 
297  for ( ; pn < l_colptr_(u_rowind_(j) + 1); pn++ ) {
298  while ( rn < l_colptr_(i + 2) && l_rowind_(rn) < l_rowind_(pn) ) {
299  rn++;
300  }
301 
302  if ( rn < l_colptr_(i + 2) && l_rowind_(pn) == l_rowind_(rn) ) {
303  l_val_(rn) -= multiplier * l_val_(pn);
304  }
305  }
306  }
307  }
308 }
309 
310 
311 void
313 {
314  int M = x.giveSize();
315  FloatArray work(M);
316 
317  int i, t;
318 
319  y.resize(M);
320  work.zero();
321  // solve Lw=x
322  for ( i = 0; i < M; i++ ) {
323  work(i) = x(i) + work(i);
324  for ( t = l_colptr_(i); t < l_colptr_(i + 1); t++ ) {
325  work( l_rowind_(t) ) -= l_val_(t) * work(i);
326  }
327  }
328 
329  y.zero();
330  // solve Uy=w
331  for ( i = M - 1; i >= 0; i-- ) {
332  y(i) = ( work(i) ) / u_val_(u_colptr_(i + 1) - 1);
333  for ( t = u_colptr_(i); t < u_colptr_(i + 1) - 1; t++ ) {
334  work( u_rowind_(t) ) -= u_val_(t) * y(i);
335  }
336  }
337 
338  //return y;
339 }
340 
341 
342 void
344 {
345  int M = x.giveSize();
346  FloatArray work(M);
347 
348  int i, t;
349  double val;
350 
351  y.resize(M);
352  //work.zero();
353  // solve for U^Tw = x
354  for ( i = 0; i < M; i++ ) {
355  val = 0.0;
356  for ( t = u_colptr_(i); t < u_colptr_(i + 1) - 1; t++ ) {
357  val += u_val_(t) * x( u_rowind_(t) );
358  }
359 
360  work(i) = ( x(i) - val ) / u_val_(u_colptr_(i + 1) - 1);
361  }
362 
363 
364  // solve for L^T y = w
365  for ( i = M - 1; i >= 0; i-- ) {
366  val = 0.0;
367  for ( t = l_colptr_(i); t < l_colptr_(i + 1); t++ ) {
368  val += l_val_(t) * work( l_rowind_(t) );
369  }
370 
371  y.at(i) = work(i) - val;
372  }
373 
374  //return y;
375 }
376 
377 
378 void
380 {
381  if ( r <= l ) {
382  return;
383  }
384 
385  int i = qsortRowPartition(src, val, l, r);
386  qsortRow(src, val, l, i - 1);
387  qsortRow(src, val, i + 1, r);
388 }
389 
390 
391 int
393 {
394  int i = l - 1, j = r;
395  int v = src(r);
396  int swap;
397  double dswap;
398 
399  for ( ; ; ) {
400  while ( ( src(++i) < v ) ) {
401  ;
402  }
403 
404  while ( ( v < src(--j) ) ) {
405  if ( j == l ) {
406  break;
407  }
408  }
409 
410  if ( i >= j ) {
411  break;
412  }
413 
414  swap = src(i);
415  src(i) = src(j);
416  src(j) = swap;
417  dswap = val(i);
418  val(i) = val(j);
419  val(j) = dswap;
420  }
421 
422  swap = src(i);
423  src(i) = src(r);
424  src(r) = swap;
425  dswap = val(i);
426  val(i) = val(r);
427  val(r) = dswap;
428 
429  return i;
430 }
431 } // end namespace oofem
Base class for all matrices stored in sparse format.
Definition: sparsemtrx.h:60
void initialize(const CompCol &A)
Definition: iluprecond.C:81
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
const int & row_ind(int i) const
Definition: compcol.h:139
const FloatArray * column(int i) const
Returns column values.
Definition: dyncompcol.h:115
void trans_solve(const FloatArray &x, FloatArray &y) const
Solves the transposed system.
Definition: iluprecond.C:343
const int & col_ptr(int i) const
Definition: compcol.h:140
int qsortRowPartition(IntArray &, FloatArray &, int l, int r)
Definition: iluprecond.C:392
void solve(const FloatArray &x, FloatArray &y) const
Solves the linear system.
Definition: iluprecond.C:312
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
Implementation of sparse matrix stored in compressed column storage.
Definition: dyncompcol.h:62
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition: sparsemtrx.h:114
#define OOFEM_LOG_INFO(...)
Definition: logger.h:127
#define OOFEM_ERROR(...)
Definition: error.h:61
void qsortRow(IntArray &, FloatArray &, int l, int r)
Definition: iluprecond.C:379
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes receiver from given record. Empty implementation.
Definition: iluprecond.C:51
int dim(int i) const
Definition: compcol.h:141
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
virtual void init(const SparseMtrx &)
Initializes the receiver (constructs the preconditioning matrix M) of given matrix.
Definition: iluprecond.C:58
Initializes the variable VERBOSE, in order to get a few intermediate messages on screen: beginning an...
Class representing vector of real numbers.
Definition: floatarray.h:82
const IntArray * row_ind(int i) const
Returns row index for i-th column.
Definition: dyncompcol.h:113
Abstract class for IML++ compatible preconditioner.
Definition: precond.h:53
IRResultType
Type defining the return values of InputRecord reading operations.
Definition: irresulttype.h:47
const double & val(int i) const
Definition: compcol.h:138
Class representing the general Input Record.
Definition: inputrecord.h:101
void zero()
Zeroes all coefficients of receiver.
Definition: floatarray.C:658
Class implementing single timer, providing wall clock and user time capabilities. ...
Definition: timer.h:46
CompCol_ILUPreconditioner()
Constructor. The user should call initializeFrom and init services in this given order to ensure cons...
Definition: iluprecond.h:64
int giveNumberOfColumns() const
Returns number of columns of receiver.
Definition: sparsemtrx.h:116
int giveSize() const
Definition: intarray.h:203
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
the oofem namespace is to define a context or scope in which all oofem names are defined.
void startTimer()
Definition: timer.C:69
double getUtime()
Returns total user time elapsed in seconds.
Definition: timer.C:105
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes receiver from given record. Empty implementation.
Definition: precond.h:115
void stopTimer()
Definition: timer.C:77
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:29 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011