OOFEM 3.0
Loading...
Searching...
No Matches
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
41namespace oofem {
42CompCol_ILUPreconditioner ::
43CompCol_ILUPreconditioner(const SparseMtrx &A, InputRecord &attributes) : Preconditioner(A, attributes)
44{ }
45
46void
47CompCol_ILUPreconditioner :: initializeFrom(InputRecord &ir)
48{
49 Preconditioner :: initializeFrom(ir);
50}
51
52
53void
54CompCol_ILUPreconditioner :: init(const SparseMtrx &A)
55{
56#ifdef TIME_REPORT
57 Timer timer;
58 timer.startTimer();
59#endif
60
61 if ( dynamic_cast< const CompCol * >(&A) ) {
62 this->initialize( static_cast< const CompCol & >(A) );
63 } else if ( dynamic_cast< const DynCompCol * >(&A) ) {
64 this->initialize( static_cast< const DynCompCol & >(A) );
65 } else {
66 OOFEM_ERROR("unsupported sparse matrix type");
67 }
68
69#ifdef TIME_REPORT
70 timer.stopTimer();
71 OOFEM_LOG_INFO( "ILUP: user time consumed by factorization: %.2fs\n", timer.getUtime() );
72#endif
73}
74
75
76void
77CompCol_ILUPreconditioner :: initialize(const CompCol &A)
78{
79 int pn, qn, rn;
80
81 // Copy
82 dim [ 0 ] = A.giveNumberOfRows();
83 dim [ 1 ] = A.giveNumberOfColumns();
84
85 l_colptr.resize(dim [ 1 ] + 1);
86 u_colptr.resize(dim [ 1 ] + 1);
87
88 l_nz = 0;
89 u_nz = 0;
90
91 // Get size of l and u
92 for ( int i = 0; i < dim [ 1 ]; i++ ) {
93 for ( int j = A.col_ptr(i); j < A.col_ptr(i + 1); j++ ) {
94 if ( A.row_ind(j) > i ) {
95 l_nz++;
96 } else {
97 u_nz++;
98 }
99 }
100 }
101
102 l_val.resize(l_nz);
103 u_val.resize(u_nz);
104 l_rowind.resize(l_nz);
105 u_rowind.resize(u_nz);
106
107 l_colptr[0] = u_colptr[0] = 0;
108
109 // Split up A into l and u
110 for ( int i = 0; i < dim [ 1 ]; i++ ) {
111 l_colptr[i + 1] = l_colptr[i];
112 u_colptr[i + 1] = u_colptr[i];
113
114 for ( int j = A.col_ptr(i); j < A.col_ptr(i + 1); j++ ) {
115 if ( A.row_ind(j) > i ) {
116 int k = l_colptr[i + 1]++;
117 l_val[k] = A.values(j);
118 l_rowind[k] = A.row_ind(j);
119 } else if ( A.row_ind(j) <= i ) {
120 int k = u_colptr[i + 1]++;
121 u_val[k] = A.values(j);
122 u_rowind[k] = A.row_ind(j);
123 }
124 }
125 }
126
127 /* sort entries to assure entries stored with increasing row index */
128 /*
129 * for (i = 0; i < dim[1]; i++) {
130 * QSort(l_rowind_, l_val_, l_colptr[i], l_colptr[i+1] - l_colptr[i]);
131 * QSort(u_rowind_, u_val_, u_colptr[i], u_colptr[i+1] - u_colptr[i]);
132 * }
133 */
134 // Factor matrix
135 for ( int i = 0; i < dim [ 0 ] - 1; i++ ) {
136 double multiplier = u_val[u_colptr[i + 1] - 1];
137
138 for ( int j = l_colptr[i]; j < l_colptr[i + 1]; j++ ) {
139 l_val[j] /= multiplier;
140 }
141
142 for ( int j = u_colptr[i + 1]; j < u_colptr[i + 2] - 1; j++ ) {
143 multiplier = u_val[j];
144 qn = j + 1;
145 rn = l_colptr[i + 1];
146 for ( pn = l_colptr[ u_rowind[j] ]; pn < l_colptr[u_rowind[j] + 1] && l_rowind[pn] <= i + 1; pn++ ) {
147 while ( qn < u_colptr[i + 2] && u_rowind[qn] < l_rowind[pn] ) {
148 qn++;
149 }
150
151 if ( qn < u_colptr[i + 2] && l_rowind[pn] == u_rowind[qn] ) {
152 u_val[qn] -= multiplier * l_val[pn];
153 }
154 }
155
156 for ( ; pn < l_colptr[u_rowind[j] + 1]; pn++ ) {
157 while ( rn < l_colptr[i + 2] && l_rowind[rn] < l_rowind[pn] ) {
158 rn++;
159 }
160
161 if ( rn < l_colptr[i + 2] && l_rowind[pn] == l_rowind[rn] ) {
162 l_val[rn] -= multiplier * l_val[pn];
163 }
164 }
165 }
166 }
167}
168
169
170void
171CompCol_ILUPreconditioner :: initialize(const DynCompCol &A)
172{
173 int pn, qn, rn;
174
175 // Copy
176 dim [ 0 ] = A.giveNumberOfRows();
177 dim [ 1 ] = A.giveNumberOfColumns();
178
179 l_colptr.resize(A.giveNumberOfColumns() + 1);
180 u_colptr.resize(A.giveNumberOfColumns() + 1);
181
182 l_nz = 0;
183 u_nz = 0;
184
185 // Get size of l and u
186 for ( int i = 0; i < dim [ 1 ]; i++ ) {
187 for ( int j = 0; j < A.row_ind(i).giveSize(); j++ ) {
188 if ( A.row_ind(i).at(j + 1) > i ) {
189 l_nz++;
190 } else {
191 u_nz++;
192 }
193 }
194 }
195
196 l_val.resize(l_nz);
197 u_val.resize(u_nz);
198 l_rowind.resize(l_nz);
199 u_rowind.resize(u_nz);
200
201 l_colptr[0] = u_colptr[0] = 0;
202
203 // Split up A into l and u
204 for ( int i = 0; i < dim [ 1 ]; i++ ) {
205 l_colptr[i + 1] = l_colptr[i];
206 u_colptr[i + 1] = u_colptr[i];
207
208 for ( int j = 0; j < A.row_ind(i).giveSize(); j++ ) {
209 if ( A.row_ind(i).at(j + 1) > i ) {
210 int k = l_colptr[i + 1]++;
211 l_val[k] = A.column(i).at(j + 1);
212 l_rowind[k] = A.row_ind(i).at(j + 1);
213 } else if ( A.row_ind(i).at(j + 1) <= i ) {
214 int k = u_colptr[i + 1]++;
215 u_val[k] = A.column(i).at(j + 1);
216 u_rowind[k] = A.row_ind(i).at(j + 1);
217 }
218 }
219 }
220
221 /* sort entries to assure entries stored with increasing row index */
222
223 for ( int i = 0; i < dim [ 1 ]; i++ ) {
224 qsortRow(l_rowind, l_val, l_colptr[i], l_colptr[i + 1] - 1);
225 qsortRow(u_rowind, u_val, u_colptr[i], u_colptr[i + 1] - 1);
226 }
227
228 // Factor matrix
229 for ( int i = 0; i < dim [ 0 ] - 1; i++ ) {
230 double multiplier = u_val[u_colptr[i + 1] - 1];
231
232 for ( int j = l_colptr[i]; j < l_colptr[i + 1]; j++ ) {
233 l_val[j] /= multiplier;
234 }
235
236 for ( int j = u_colptr[i + 1]; j < u_colptr[i + 2] - 1; j++ ) {
237 multiplier = u_val[j];
238 qn = j + 1;
239 rn = l_colptr[i + 1];
240 for ( pn = l_colptr[ u_rowind[j] ]; pn < l_colptr[u_rowind[j] + 1] && l_rowind[pn] <= i + 1; pn++ ) {
241 while ( qn < u_colptr[i + 2] && u_rowind[qn] < l_rowind[pn] ) {
242 qn++;
243 }
244
245 if ( qn < u_colptr[i + 2] && l_rowind[pn] == u_rowind[qn] ) {
246 u_val[qn] -= multiplier * l_val[pn];
247 }
248 }
249
250 for ( ; pn < l_colptr[u_rowind[j] + 1]; pn++ ) {
251 while ( rn < l_colptr[i + 2] && l_rowind[rn] < l_rowind[pn] ) {
252 rn++;
253 }
254
255 if ( rn < l_colptr[i + 2] && l_rowind[pn] == l_rowind[rn] ) {
256 l_val[rn] -= multiplier * l_val[pn];
257 }
258 }
259 }
260 }
261}
262
263
264void
265CompCol_ILUPreconditioner :: solve(const FloatArray &x, FloatArray &y) const
266{
267 int M = x.giveSize();
268 FloatArray work(M);
269
270 y.resize(M);
271
272 // solve Lw=x
273 for ( int i = 0; i < M; i++ ) {
274 work[i] += x[i];
275 for ( int t = l_colptr[i]; t < l_colptr[i + 1]; t++ ) {
276 work[ l_rowind[t] ] -= l_val[t] * work[i];
277 }
278 }
279
280 y.zero();
281 // solve Uy=w
282 for ( int i = M - 1; i >= 0; i-- ) {
283 y[i] = ( work[i] ) / u_val[u_colptr[i + 1] - 1];
284 for ( int t = u_colptr[i]; t < u_colptr[i + 1] - 1; t++ ) {
285 work[ u_rowind[t] ] -= u_val[t] * y[i];
286 }
287 }
288}
289
290
291void
292CompCol_ILUPreconditioner :: trans_solve(const FloatArray &x, FloatArray &y) const
293{
294 int M = x.giveSize();
295 FloatArray work(M);
296
297 y.resize(M);
298
299 // solve for U^Tw = x
300 for ( int i = 0; i < M; i++ ) {
301 double val = 0.0;
302 for ( int t = u_colptr[i]; t < u_colptr[i + 1] - 1; t++ ) {
303 val += u_val[t] * x[ u_rowind[t] ];
304 }
305
306 work[i] = ( x[i] - val ) / u_val[u_colptr[i + 1] - 1];
307 }
308
309
310 // solve for L^T y = w
311 for ( int i = M - 1; i >= 0; i-- ) {
312 double val = 0.0;
313 for ( int t = l_colptr[i]; t < l_colptr[i + 1]; t++ ) {
314 val += l_val[t] * work( l_rowind[t] );
315 }
316
317 y[i] = work[i] - val;
318 }
319}
320
321
322void
323CompCol_ILUPreconditioner :: qsortRow(IntArray &src, FloatArray &val, int l, int r)
324{
325 if ( r <= l ) {
326 return;
327 }
328
329 int i = qsortRowPartition(src, val, l, r);
330 qsortRow(src, val, l, i - 1);
331 qsortRow(src, val, i + 1, r);
332}
333
334
335int
336CompCol_ILUPreconditioner :: qsortRowPartition(IntArray &src, FloatArray &val, int l, int r)
337{
338 int i = l - 1, j = r;
339 int v = src[r];
340
341 for ( ; ; ) {
342 while ( ( src[++i] < v ) ) {
343 ;
344 }
345
346 while ( ( v < src[--j] ) ) {
347 if ( j == l ) {
348 break;
349 }
350 }
351
352 if ( i >= j ) {
353 break;
354 }
355
356 std::swap(src[i], src[j]);
357 std::swap(val[i], val[j]);
358 }
359
360 std::swap(src[i], src[r]);
361 std::swap(val[i], val[r]);
362
363 return i;
364}
365} // end namespace oofem
void qsortRow(IntArray &, FloatArray &, int l, int r)
Definition iluprecond.C:323
void initialize(const CompCol &A)
Definition iluprecond.C:77
int qsortRowPartition(IntArray &, FloatArray &, int l, int r)
Definition iluprecond.C:336
const int & row_ind(int i) const
Definition compcol.h:134
const int & col_ptr(int i) const
Definition compcol.h:135
const double & values(int i) const
Definition compcol.h:133
const IntArray & row_ind(int i) const
Returns row index for i-th column.
Definition dyncompcol.h:98
const FloatArray & column(int i) const
Returns column values.
Definition dyncompcol.h:100
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
int & at(std::size_t i)
Definition intarray.h:104
Preconditioner(const SparseMtrx &a, InputRecord &attributes)
Definition precond.C:38
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition sparsemtrx.h:114
int giveNumberOfColumns() const
Returns number of columns of receiver.
Definition sparsemtrx.h:116
double getUtime()
Returns total user time elapsed in seconds.
Definition timer.C:105
void startTimer()
Definition timer.C:69
void stopTimer()
Definition timer.C:77
#define OOFEM_ERROR(...)
Definition error.h:79
#define OOFEM_LOG_INFO(...)
Definition logger.h:143

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011