OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
dyncomprow.C
Go to the documentation of this file.
1 /*
2  *
3  * ##### ##### ###### ###### ### ###
4  * ## ## ## ## ## ## ## ### ##
5  * ## ## ## ## #### #### ## # ##
6  * ## ## ## ## ## ## ## ##
7  * ## ## ## ## ## ## ## ##
8  * ##### ##### ## ###### ## ##
9  *
10  *
11  * OOFEM : Object Oriented Finite Element Code
12  *
13  * Copyright (C) 1993 - 2013 Borek Patzak
14  *
15  *
16  *
17  * Czech Technical University, Faculty of Civil Engineering,
18  * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 // Class DynCompRow
35 
36 // inspired by SL++
37 
38 #include "dyncomprow.h"
39 #include "floatarray.h"
40 #include "engngm.h"
41 #include "domain.h"
42 #include "mathfem.h"
43 #include "verbose.h"
44 #include "element.h"
45 #include "sparsemtrxtype.h"
46 #include "activebc.h"
47 #include "classfactory.h"
48 
49 #ifdef TIME_REPORT
50  #include "timer.h"
51 #endif
52 
53 namespace oofem {
55 
57 {
58  rows_ = NULL;
59  colind_ = NULL;
60 }
61 
62 
64 {
65  rows_ = NULL;
66  colind_ = NULL;
67 
68  nRows = nColumns = n;
69 }
70 
71 
72 /*****************************/
73 /* Copy constructor */
74 /*****************************/
75 
77 {
78  int i;
79  if ( S.rows_ ) {
80  this->rows_ = new FloatArray * [ S.nRows ];
81  for ( i = 0; i < S.nRows; i++ ) {
82  this->rows_ [ i ] = new FloatArray(*S.rows_ [ i ]);
83  }
84  } else {
85  this->rows_ = NULL;
86  }
87 
88  if ( S.colind_ ) {
89  this->colind_ = new IntArray * [ S.nRows ];
90  for ( i = 0; i < S.nRows; i++ ) {
91  this->colind_ [ i ] = new IntArray(*S.colind_ [ i ]);
92  }
93  } else {
94  this->colind_ = NULL;
95  }
96 
97  this->nRows = S.nRows;
98  this->nColumns = S.nColumns;
99  this->version = S.version;
100 }
101 
102 
103 // Destructor
105 {
106  int i;
107 
108  if ( this->rows_ ) {
109  for ( i = 0; i < nRows; i++ ) {
110  delete this->rows_ [ i ];
111  }
112 
113  delete this->rows_;
114  }
115 
116  if ( this->colind_ ) {
117  for ( i = 0; i < nRows; i++ ) {
118  delete this->colind_ [ i ];
119  }
120 
121  delete this->colind_;
122  }
123 }
124 
125 
126 
127 /***************************/
128 /* Assignment operator... */
129 /***************************/
130 
132 {
133  base_ = C.base_;
134 
135  int i;
136 
137  if ( this->rows_ ) {
138  for ( i = 0; i < nRows; i++ ) {
139  delete this->rows_ [ i ];
140  }
141 
142  delete this->rows_;
143  }
144 
145  if ( C.rows_ ) {
146  this->rows_ = new FloatArray * [ C.nRows ];
147  for ( i = 0; i < C.nRows; i++ ) {
148  this->rows_ [ i ] = new FloatArray(*C.rows_ [ i ]);
149  }
150  } else {
151  this->rows_ = NULL;
152  }
153 
154 
155  if ( this->colind_ ) {
156  for ( i = 0; i < nRows; i++ ) {
157  delete this->colind_ [ i ];
158  }
159 
160  delete this->colind_;
161  }
162 
163  if ( C.colind_ ) {
164  this->colind_ = new IntArray * [ C.nRows ];
165  for ( i = 0; i < C.nRows; i++ ) {
166  this->colind_ [ i ] = new IntArray(*C.colind_ [ i ]);
167  }
168  } else {
169  this->colind_ = NULL;
170  }
171 
172  nRows = C.nRows;
173  nColumns = C.nColumns;
174  version = C.version;
175  return * this;
176 }
177 
179 {
180  DynCompRow *result = new DynCompRow(*this);
181  return result;
182 }
183 
184 
185 void DynCompRow :: times(const FloatArray &x, FloatArray &answer) const
186 {
187  // Check for compatible dimensions:
188  if ( x.giveSize() != nColumns ) {
189  OOFEM_ERROR("Error in CompRow -- incompatible dimensions");
190  }
191 
192  answer.resize(nRows);
193  answer.zero();
194 
195  int j, t;
196  double r;
197 
198  for ( j = 0; j < nRows; j++ ) {
199  r = 0.0;
200  for ( t = 1; t <= rows_ [ j ]->giveSize(); t++ ) {
201  r += rows_ [ j ]->at(t) * x( colind_ [ j ]->at(t) );
202  }
203 
204  answer(j) = r;
205  }
206 }
207 
208 void DynCompRow :: times(double x)
209 {
210  for ( int j = 0; j < nRows; j++ ) {
211  rows_ [ j ]->times(x);
212  }
213 
214  // increment version
215  this->version++;
216 }
217 
219 {
220  int neq = eModel->giveNumberOfDomainEquations(di, s);
221 
222  IntArray loc;
223  Domain *domain = eModel->giveDomain(di);
224  int i, ii, j, jj;
225 
226 #ifdef TIME_REPORT
227  Timer timer;
228  timer.startTimer();
229 #endif
230 
231  nColumns = nRows = neq;
232 
233  if ( colind_ ) {
234  for ( i = 0; i < nRows; i++ ) {
235  delete this->colind_ [ i ];
236  }
237 
238  delete this->colind_;
239  }
240 
241  colind_ = ( IntArray ** ) new IntArray * [ neq ];
242  for ( j = 0; j < neq; j++ ) {
243  colind_ [ j ] = new IntArray();
244  }
245 
246  // allocate value array
247  if ( rows_ ) {
248  for ( i = 0; i < nRows; i++ ) {
249  delete this->rows_ [ i ];
250  }
251 
252  delete this->rows_;
253  }
254 
255  rows_ = ( FloatArray ** ) new FloatArray * [ neq ];
256  for ( j = 0; j < neq; j++ ) {
257  rows_ [ j ] = new FloatArray();
258  }
259 
260  for ( auto &elem : domain->giveElements() ) {
261  elem->giveLocationArray(loc, s);
262 
263  for ( i = 1; i <= loc.giveSize(); i++ ) { // row indx
264  if ( ( ii = loc.at(i) ) ) {
265  for ( j = 1; j <= loc.giveSize(); j++ ) { // col indx
266  if ( ( jj = loc.at(j) ) ) {
267  this->insertColInRow(ii - 1, jj - 1);
268  }
269  }
270  }
271  }
272  }
273 
274 
275  // loop over active boundary conditions
276  //int nbc = domain->giveNumberOfBoundaryConditions();
277  std :: vector< IntArray >r_locs;
278  std :: vector< IntArray >c_locs;
279 
280  for ( auto &gbc : domain->giveBcs() ) {
281  ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() );
282  if ( bc != NULL ) {
283  bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s);
284  for ( std :: size_t k = 0; k < r_locs.size(); k++ ) {
285  IntArray &krloc = r_locs [ k ];
286  IntArray &kcloc = c_locs [ k ];
287  for ( int i = 1; i <= krloc.giveSize(); i++ ) {
288  if ( ( ii = krloc.at(i) ) ) {
289  for ( int j = 1; j <= kcloc.giveSize(); j++ ) {
290  if ( ( jj = kcloc.at(j) ) ) {
291  this->insertColInRow(ii - 1, jj - 1);
292  }
293  }
294  }
295  }
296  }
297  }
298  }
299 
300 
301 
302 
303  int nz_ = 0;
304  for ( j = 0; j < neq; j++ ) {
305  nz_ += this->colind_ [ j ]->giveSize();
306  }
307 
308  OOFEM_LOG_DEBUG("DynCompRow info: neq is %d, nelem is %d\n", neq, nz_);
309 
310  // increment version
311  this->version++;
312 #ifdef TIME_REPORT
313  timer.stopTimer();
314  OOFEM_LOG_DEBUG( "DynCompRow::buildInternalStructure: user time consumed: %.2fs\n", timer.getUtime() );
315 #endif
316 
317  return true;
318 }
319 
320 
321 int DynCompRow :: assemble(const IntArray &loc, const FloatMatrix &mat)
322 {
323  int i, j, ii, jj, dim;
324 
325 # ifdef DEBUG
326  dim = mat.giveNumberOfRows();
327  if ( dim != loc.giveSize() ) {
328  OOFEM_ERROR("dimension of 'k' and 'loc' mismatch");
329  }
330 
331 # endif
332 
333  dim = mat.giveNumberOfRows();
334 
335  for ( j = 1; j <= dim; j++ ) {
336  jj = loc.at(j);
337  if ( jj ) {
338  for ( i = 1; i <= dim; i++ ) {
339  ii = loc.at(i);
340  if ( ii ) {
341  this->at(ii, jj) += mat.at(i, j);
342  }
343  }
344  }
345  }
346 
347  // increment version
348  this->version++;
349  return 1;
350 }
351 
352 int DynCompRow :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat)
353 {
354  // optimized low-end implementation
355  IntArray colsToAdd( rloc.giveSize() );
356  int i, ii, ii1, j, jj, jj1, colindx;
357  int rsize = rloc.giveSize();
358  int csize = cloc.giveSize();
359 
360  for ( i = 0; i < rsize; i++ ) {
361  if ( ( ii = rloc(i) ) ) {
362  ii1 = ii - 1;
363  for ( j = 0; j < csize; j++ ) {
364  if ( ( jj = cloc(j) ) ) {
365  jj1 = jj - 1;
366 
367  colindx = this->insertColInRow(ii1, jj1);
368  //if (rowind_[j-1]->at(t) == (i-1)) return columns_[j-1]->at(t);
369  rows_ [ ii1 ]->at(colindx) += mat(i, j);
370  }
371  }
372  }
373  }
374 
375  // increment version
376  this->version++;
377  return 1;
378 }
379 
381 {
382  for ( int j = 0; j < nRows; j++ ) {
383  rows_ [ j ]->zero();
384  }
385 
386  // increment version
387  this->version++;
388 }
389 
390 
392 {
393  int nz_ = 0;
394  for ( int j = 0; j < nRows; j++ ) {
395  nz_ += rows_ [ j ]->giveSize();
396  }
397 
398  printf("\nDynCompRow info: neq is %d, nelem is %d\n", nRows, nz_);
399 }
400 
401 
402 /*********************/
403 /* Array access */
404 /*********************/
405 
406 double &DynCompRow :: at(int i, int j)
407 {
408  int colIndx;
409 
410  // increment version
411  this->version++;
412  if ( ( colIndx = this->giveColIndx(i - 1, j - 1) ) ) {
413  return rows_ [ i - 1 ]->at(colIndx);
414  }
415 
416  OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j);
417  return rows_ [ 0 ]->at(1); // return to suppress compiler warning message
418 }
419 
420 
421 double DynCompRow :: at(int i, int j) const
422 {
423  int colIndx;
424  if ( ( colIndx = this->giveColIndx(i - 1, j - 1) ) ) {
425  return rows_ [ i - 1 ]->at(colIndx);
426  }
427 
428  if ( i <= nRows && j <= nColumns ) {
429  return 0.0;
430  } else {
431  OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j);
432  return rows_ [ 0 ]->at(1); // return to suppress compiler warning message
433  }
434 }
435 
436 double DynCompRow :: operator() (int i, int j) const
437 {
438  int colIndx;
439  if ( ( colIndx = this->giveColIndx(i, j) ) ) {
440  return rows_ [ i ]->at(colIndx);
441  }
442 
443  if ( i < nRows && j < nColumns ) {
444  return 0.0;
445  } else {
446  OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j);
447  return rows_ [ 0 ]->at(1); // return to suppress compiler warning message
448  }
449 }
450 
451 double &DynCompRow :: operator() (int i, int j)
452 {
453  int colIndx;
454 
455  // increment version
456  this->version++;
457 
458  if ( ( colIndx = this->giveColIndx(i, j) ) ) {
459  return rows_ [ i ]->at(colIndx);
460  }
461 
462  OOFEM_ERROR("Array element (%d,%d) not in sparse structure -- cannot assign", i, j);
463  return rows_ [ 0 ]->at(1); // return to suppress compiler warning message
464 }
465 
466 void DynCompRow :: timesT(const FloatArray &x, FloatArray &answer) const
467 {
468  // Check for compatible dimensions:
469  if ( x.giveSize() != nRows ) {
470  OOFEM_ERROR("Error in CompRow -- incompatible dimensions");
471  }
472 
473  answer.resize(nColumns);
474  answer.zero();
475 
476  int i, t;
477  double r;
478 
479  for ( i = 0; i < nColumns; i++ ) {
480  r = x(i);
481  for ( t = 1; t <= rows_ [ i ]->giveSize(); t++ ) {
482  answer( colind_ [ i ]->at(t) ) += rows_ [ i ]->at(t) * r;
483  }
484  }
485 }
486 
487 
488 
490 {
491  int i, maxid = 0;
492  int size = loc.giveSize();
493  // adjust the size of receiver
494  for ( i = 0; i < size; i++ ) {
495  maxid = max( maxid, loc(i) );
496  }
497 
498  this->growTo(maxid);
499 
500  int ii, j, jj;
501 
502  for ( i = 0; i < size; i++ ) {
503  if ( ( ii = loc(i) ) ) {
504  for ( j = 0; j < size; j++ ) {
505  if ( ( jj = loc(j) ) ) {
506  this->insertColInRow(ii - 1, jj - 1);
507  }
508  }
509  }
510  }
511 }
512 
513 
514 void DynCompRow :: checkSizeTowards(const IntArray &rloc, const IntArray &cloc)
515 {
516  int i, maxid = 0;
517  int rsize = rloc.giveSize();
518  int csize = cloc.giveSize();
519 
520  // adjust the size of receiver
521  for ( i = 0; i < rsize; i++ ) {
522  maxid = max( maxid, rloc(i) );
523  }
524 
525  for ( i = 0; i < csize; i++ ) {
526  maxid = max( maxid, cloc(i) );
527  }
528 
529  this->growTo(maxid);
530 
531  int ii, j, jj;
532 
533  for ( i = 0; i < rsize; i++ ) {
534  if ( ( ii = rloc(i) ) ) {
535  for ( j = 0; j < csize; j++ ) {
536  if ( ( jj = cloc(j) ) ) {
537  this->insertColInRow(ii - 1, jj - 1);
538  }
539  }
540  }
541  }
542 }
543 
544 
545 
547 {
548  if ( ns > nRows ) {
549  FloatArray **newrows_ = new FloatArray * [ ns ];
550  IntArray **newcolind_ = new IntArray * [ ns ];
551 
552  // copy existing columns
553  for ( int i = 0; i < nRows; i++ ) {
554  newrows_ [ i ] = rows_ [ i ];
555  newcolind_ [ i ] = colind_ [ i ];
556  }
557 
558  delete rows_;
559  delete colind_;
560 
561  rows_ = newrows_;
562  colind_ = newcolind_;
563 
564  nColumns = nRows = ns;
565  }
566 }
567 
568 
569 int DynCompRow :: giveColIndx(int row, int col) const
570 {
571  // fast col indx search, based on assumption, that col indices are sorted
572  int left = 1, right = this->colind_ [ row ]->giveSize();
573  int middle = ( left + right ) / 2;
574  int middleVal;
575 
576  if ( right == 0 ) {
577  return 0;
578  }
579 
580  if ( this->colind_ [ row ]->at(right) == col ) {
581  return right;
582  }
583 
584  while ( !( ( ( middleVal = this->colind_ [ row ]->at(middle) ) == col ) || ( middle == left ) ) ) {
585  if ( col > middleVal ) {
586  left = middle;
587  } else {
588  right = middle;
589  }
590 
591  middle = ( left + right ) / 2;
592  }
593 
594  if ( middleVal == col ) {
595  return middle;
596  }
597 
598  return 0;
599 }
600 
601 
602 
603 int
605 {
606  // insert col entry into row, preserving order of col indexes.
607  int i, oldsize = this->colind_ [ row ]->giveSize();
608  int left = 1, right = oldsize;
609  int middle = ( left + right ) / 2;
610  int middleVal;
611 
612  if ( oldsize == 0 ) {
615  rows_ [ row ]->at(1) = 0.0;
616  colind_ [ row ]->at(1) = col;
617  return 1;
618  }
619 
620  if ( this->colind_ [ row ]->at(right) == col ) {
621  return right;
622  }
623 
624  while ( !( ( ( middleVal = this->colind_ [ row ]->at(middle) ) == col ) || ( middle == left ) ) ) {
625  if ( col > middleVal ) {
626  left = middle;
627  } else {
628  right = middle;
629  }
630 
631  middle = ( left + right ) / 2;
632  }
633 
634  if ( middleVal == col ) {
635  return middle;
636  }
637 
638  // we have to insert new row entry
639  if ( col > this->colind_ [ row ]->at(oldsize) ) {
640  right = oldsize + 1;
641  } else if ( col < this->colind_ [ row ]->at(1) ) {
642  right = 1;
643  }
644 
645  // insert col at middle+1 position
646  colind_ [ row ]->resizeWithValues(oldsize + 1, DynCompRow_CHUNK);
647  rows_ [ row ]->resizeWithValues(oldsize + 1, DynCompRow_CHUNK);
648 
649  for ( i = oldsize; i >= right; i-- ) {
650  colind_ [ row ]->at(i + 1) = colind_ [ row ]->at(i);
651  rows_ [ row ]->at(i + 1) = rows_ [ row ]->at(i);
652  }
653 
654  rows_ [ row ]->at(right) = 0.0;
655  colind_ [ row ]->at(right) = col;
656  return right;
657 }
658 
659 
660 
661 
662 
663 /* reference ILU(0) version
664  * void
665  * DynCompRow::ILUPYourself ()
666  * {
667  * int i, j, k, kk, krow, colk;
668  * double multiplier;
669  *
670  * IntArray iw (nColumns);
671  * diag_rowptr_.resize(nRows);
672  *
673  **#ifndef DynCompRow_USE_STL_SETS
674  * for (i = 0; i < nRows; i++) // row loop
675  * if ((diag_rowptr_(i) = giveColIndx (i, i)) == 0) { // giveColIndx returns 1-based indexing
676  * printf ("DynCompRow:: Zero diagonal member\n");
677  * exit(1);
678  * }
679  *
680  **#else
681  * std::map<int, double>::iterator pos;
682  * for (i = 0; i < nRows; i++) {// row loop
683  * pos = this->rows[i]->find(i);
684  * if (pos != this->rows[i-1]->end())
685  * diag_rowptr_(i) = *pos->first;
686  * else {
687  * printf ("DynCompRow:: Zero diagonal member\n");
688  * exit(1);
689  * }
690  * }
691  **#endif
692  *
693  * // FACTOR MATRIX //
694  **#ifndef DynCompRow_USE_STL_SETS
695  *
696  * for (i=1; i< nRows; i++) { // loop over rows
697  * for (k=0; k < (diag_rowptr_(i)-1); k++) { // loop 1,...,i-1 for (i,k) \in NZ(A)
698  * // initialize k-th row indexes
699  * krow = colind_[i]->at(k+1);
700  * for (kk=1; kk<= rows_[krow]->giveSize(); kk++)
701  * iw(colind_[krow]->at(kk)) = kk;
702  * multiplier = (rows_[i]->at(k+1) /= rows_[krow]->at(diag_rowptr_(krow)));
703  * for (j=k+1; j < rows_[i]->giveSize(); j++) { // loop over k+1,...,n for (i,j) \in NZ(A)
704  * colk = iw (colind_[i]->at(j+1)); // column position of a(i,j) at row k
705  * if (colk) rows_[i]->at(j+1) -= multiplier * rows_[krow]->at(colk); // aij=aij-aik*akj
706  * }
707  * // Refresh all iw enries to zero
708  * for (kk=1; kk<= rows_[krow]->giveSize(); kk++)
709  * iw(colind_[krow]->at(kk)) = 0;
710  * }
711  * }
712  *
713  **#else
714  * NOT IMPLEMENTED NOW
715  **#endif
716  * }
717  */
718 
719 
720 //#define ILU_0
721 //#define ILU_DROP_TOL 1.e-8
722 #define ILU_ROW_CHUNK 10
723 //#define ILU_PART_FILL 5
724 
725 void
726 DynCompRow :: ILUPYourself(int part_fill, double drop_tol)
727 {
728  int i, ii, j, jcol, k, kk, krow, ck;
729  int end, curr;
730  double multiplier, inorm, val;
731 
732  IntArray irw(nColumns), iw;
733  FloatArray w;
735 
736 #ifdef TIME_REPORT
737  Timer timer;
738  timer.startTimer();
739 #endif
740 
741  for ( i = 0; i < nRows; i++ ) { // row loop
742  if ( ( diag_rowptr_(i) = giveColIndx(i, i) ) == 0 ) { // giveColIndx returns 1-based indexing
743  OOFEM_ERROR("zero value on diagonal");
744  }
745  }
746 
747  /* FACTOR MATRIX */
748 
749  for ( i = 1; i < nRows; i++ ) { // loop over rows
750  inorm = 0.0;
751  for ( ii = 1; ii <= rows_ [ i ]->giveSize(); ii++ ) {
752  val = rows_ [ i ]->at(ii);
753  inorm += val * val;
754  }
755 
756  inorm = sqrt(inorm);
757 
758  w.resizeWithValues(rows_ [ i ]->giveSize(), ILU_ROW_CHUNK);
759  iw.resizeWithValues(rows_ [ i ]->giveSize(), ILU_ROW_CHUNK);
760  for ( kk = 1; kk <= rows_ [ i ]->giveSize(); kk++ ) {
761  irw( colind_ [ i ]->at(kk) ) = kk;
762  iw(kk - 1) = colind_ [ i ]->at(kk);
763  w(kk - 1) = rows_ [ i ]->at(kk);
764  }
765 
766  //for (k=0; k < (diag_rowptr_(i)-1); k++) { // loop 1,...,i-1 for (i,k) \in NZ(A)
767  k = 0;
768  while ( iw.at(k + 1) < i ) {
769  // initialize k-th row indexes
770  krow = iw.at(k + 1);
771  //multiplier = (rows_[i]->at(k+1) /= rows_[krow]->at(diag_rowptr_(krow)));
772  multiplier = ( w.at(k + 1) /= rows_ [ krow ]->at( diag_rowptr_(krow) ) );
773 
774 
775 #ifndef ILU_0
776  // first dropping rule for aik
777  if ( fabs(multiplier) >= drop_tol * inorm )
778 #endif
779  { // first drop rule
780  for ( j = 0; j < colind_ [ krow ]->giveSize(); j++ ) {
781  jcol = colind_ [ krow ]->at(j + 1);
782  if ( jcol > krow ) {
783  if ( irw(jcol) ) {
784  //rows_[i]->at(irw(jcol)) -= multiplier*rows_[krow]->at(j+1);
785  w.at( irw(jcol) ) -= multiplier * rows_ [ krow ]->at(j + 1);
786  } else {
787 #ifndef ILU_0
788  // insert new entry
789  int newsize = w.giveSize() + 1;
790  w.resizeWithValues(newsize, ILU_ROW_CHUNK);
791  iw.resizeWithValues(newsize, ILU_ROW_CHUNK);
792 
793  iw.at(newsize) = jcol;
794  w.at(newsize) = -multiplier * rows_ [ krow ]->at(j + 1);
795  irw(jcol) = newsize;
796 #endif
797 
798  /*
799  * ipos = insertColInRow (i,jcol) ;
800  * for (kk=ipos+1; kk<= rows_[i]->giveSize(); kk++)
801  * irw(colind_[i]->at(kk))++;
802  *
803  * ipos = insertColInRow (i,jcol) ;
804  * rows_[i]->at(ipos) = -multiplier*rows_[krow]->at(j+1);
805  * irw(jcol) = ipos;
806  * if (jcol < i) diag_rowptr_(i)++;
807  */
808  }
809  }
810  }
811  }
812 
813  // scan iw to find closest index to krow
814  ck = nColumns + 1;
815  for ( kk = 0; kk < iw.giveSize(); kk++ ) {
816  if ( ( ( iw(kk) - krow ) > 0 ) && ( ( iw(kk) - krow ) < ( ck - krow ) ) ) {
817  ck = iw(kk);
818  }
819  }
820 
821  k = irw(ck) - 1;
822  }
823 
824 #ifndef ILU_0
825 
826  end = iw.giveSize();
827  curr = 1;
828  // second drop rule
829  while ( curr <= end ) {
830  if ( ( fabs( w.at(curr) ) < drop_tol * inorm ) && ( iw.at(curr) != i ) ) {
831  // remove entry
832  w.at(curr) = w.at(end);
833  irw( iw.at(curr) ) = 0;
834  iw.at(curr) = iw.at(end);
835  if ( curr != end ) {
836  irw( iw.at(curr) ) = curr;
837  }
838 
839  end--;
840  } else {
841  curr++;
842  }
843  }
844 
845  // cutt off
846  w.resize(end);
847  iw.resize(end);
848 
849  int count = end;
850 
851  // select only the p-largest w values
852  this->qsortRow(iw, irw, w, 0, iw.giveSize() - 1);
853  //
854  int lsizeLimit = diag_rowptr_(i) - 1;
855  int usizeLimit = rows_ [ i ]->giveSize() - lsizeLimit;
856 
857  lsizeLimit += part_fill;
858  usizeLimit += part_fill;
859 
860  int lnums = 0;
861  int unums = 0;
862  count = 0;
863  for ( kk = 1; kk <= iw.giveSize(); kk++ ) {
864  if ( iw.at(kk) < i ) { // lpart
865  if ( ++lnums > lsizeLimit ) {
866  irw( iw.at(kk) ) = 0;
867  } else {
868  count++;
869  }
870  } else if ( iw.at(kk) > i ) { // upart
871  if ( ++unums > usizeLimit ) {
872  irw( iw.at(kk) ) = 0;
873  } else {
874  count++;
875  }
876  } else { // diagonal is always kept
877  count++;
878  }
879  }
880 
881 #else
882  int count = iw.giveSize();
883 #endif
884  rows_ [ i ]->resize(count);
885  colind_ [ i ]->resize(count);
886 
887  int icount = 1;
888  int kki, indx, idist, previndx = -1;
889  int kkend = iw.giveSize();
890 
891  for ( kk = 1; kk <= count; kk++ ) {
892  idist = nColumns + 2;
893  indx = 0;
894 
895  for ( kki = 1; kki <= kkend; kki++ ) {
896  if ( ( irw( iw.at(kki) ) != 0 ) && ( iw.at(kki) > previndx ) && ( ( iw.at(kki) - previndx ) < idist ) ) {
897  idist = ( iw.at(kki) - previndx );
898  indx = kki;
899  }
900  }
901 
902  if ( indx == 0 ) {
903  OOFEM_ERROR("internal error");
904  }
905 
906  previndx = iw.at(indx);
907  rows_ [ i ]->at(icount) = w.at(indx);
908  colind_ [ i ]->at(icount) = iw.at(indx);
909  if ( colind_ [ i ]->at(icount) == i ) {
910  diag_rowptr_(i) = icount;
911  }
912 
913  icount++;
914 
915 
916  // exclude the indx entry from search by moving it to the end of list
917  irw( iw.at(indx) ) = 0;
918  iw.at(indx) = iw.at(kkend);
919  w.at(indx) = w.at(kkend);
920  if ( irw( iw.at(indx) ) != 0 ) {
921  irw( iw.at(indx) ) = indx;
922  }
923 
924  kkend--;
925 
926  // exclude the indx entry from search by moving it to the end of list
927  //swap = irw(iw.at(indx)); irw(iw.at(indx)) = irw(iw.at(kkend)); irw(iw.at(kkend)) = swap;
928  //swap = iw.at(indx); iw.at(indx) = iw.at(kkend); iw.at(kkend) = swap;
929  //dswap= w.at(indx); w.at(indx) = w.at(kkend); w.at(kkend) = dswap;
930 
931  //kkend--;
932  }
933 
934 
935  /*
936  * int icount = 1;
937  * for (kk=1; kk<= nColumns; kk++) {
938  * if ( irw.at(kk) > 0 ) {
939  * rows_[i]->at(icount) = w.at(abs(irw(kk-1)));
940  * colind_[i]->at(icount) = iw.at(abs(irw(kk-1)));
941  * if (colind_[i]->at(icount) == i) diag_rowptr_(i) = icount;
942  * icount++;
943  * }
944  * }
945  */
946  if ( ( icount - count ) != 1 ) {
947  OOFEM_ERROR("%d - row errorr (%d,%d)\n", i, icount, count);
948  }
949 
950  //Refresh all iw enries to zero
951  for ( kk = 1; kk <= iw.giveSize(); kk++ ) {
952  irw( iw.at(kk) ) = 0;
953  }
954 
955  //irw.zero();
956  }
957 
958 #ifdef TIME_REPORT
959  timer.stopTimer();
960  OOFEM_LOG_DEBUG( "\nILUT(%d,%e): user time consumed by factorization: %.2fs\n", part_fill, drop_tol, timer.getUtime() );
961 #endif
962 
963  // increment version
964  this->version++;
965 }
966 
967 
968 
969 void
971 {
972  int M = x.giveSize();
973  double r;
974  FloatArray work(M);
975 
976  int i, t;
977 
978  y.resize(M);
979 
980  work.zero();
981  // solve Lw=x
982  for ( i = 0; i < M; i++ ) {
983  r = x(i);
984  for ( t = 0; t < ( diag_rowptr_(i) - 1 ); t++ ) {
985  r -= rows_ [ i ]->at(t + 1) * work( colind_ [ i ]->at(t + 1) );
986  }
987 
988  work(i) = r;
989  }
990 
991  y.zero();
992  // solve Uy=w
993  for ( i = M - 1; i >= 0; i-- ) {
994  r = work(i);
995  for ( t = diag_rowptr_(i); t < rows_ [ i ]->giveSize(); t++ ) {
996  r -= rows_ [ i ]->at(t + 1) * y( colind_ [ i ]->at(t + 1) );
997  }
998 
999  y(i) = r / rows_ [ i ]->at( diag_rowptr_(i) );
1000  }
1001 
1002  //return y;
1003 }
1004 
1005 
1006 void
1008 {
1009  int M = x.giveSize();
1010  FloatArray work(M);
1011 
1012  int i, t;
1013 
1014  y.resize(M);
1015  //work.zero();
1016  // solve for U^Tw = x
1017  for ( i = 0; i < M; i++ ) {
1018  work(i) = ( x(i) + work(i) ) / rows_ [ i ]->at( diag_rowptr_(i) );
1019  for ( t = diag_rowptr_(i); t < rows_ [ i ]->giveSize(); t++ ) {
1020  work( colind_ [ i ]->at(t + 1) ) -= rows_ [ i ]->at(t + 1) * work(i);
1021  }
1022  }
1023 
1024  // solve for L^T y = w
1025  for ( i = M - 1; i >= 0; i-- ) {
1026  y(i) = work(i);
1027  for ( t = 1; t < diag_rowptr_(i); t++ ) {
1028  work( colind_ [ i ]->at(t) ) -= rows_ [ i ]->at(t) * y(i);
1029  }
1030  }
1031 
1032  //return y;
1033 }
1034 
1035 
1036 /*
1037  * void
1038  * DynCompRow::qsortRow (IntArray& ind, IntArray& ir, FloatArray& val, int l, int r)
1039  * {
1040  * if (r<=l) return;
1041  * int i = qsortRowPartition (ind, ir, val, l, r);
1042  * qsortRow (ind, ir, val, l, i-1);
1043  * qsortRow (ind, ir, val, i+1, r);
1044  * }
1045  *
1046  *
1047  * int
1048  * DynCompRow::qsortRowPartition (IntArray& ind, IntArray& ir, FloatArray& val, int l, int r)
1049  * {
1050  * int i=l-1, j=r;
1051  * double v = fabs(val(r));
1052  * int swap;
1053  * double dswap;
1054  *
1055  * for (;;) {
1056  * while (( fabs(val(++i)) > v ));
1057  * while (( v > fabs(val(--j)))) if (j==l) break;
1058  * if (i >= j) break;
1059  * swap = ir(ind(i)); ir(ind(i)) = ir(ind(j)); ir(ind(j)) = swap;
1060  * swap = ind(i); ind(i) = ind(j); ind(j) = swap;
1061  * dswap= val(i); val(i) = val(j); val(j) = dswap;
1062  * }
1063  * swap = ir(ind(i)); ir(ind(i)) = ir(ind(r)); ir(ind(r)) = swap;
1064  * swap = ind(i); ind(i) = ind(r); ind(r) = swap;
1065  * dswap= val(i); val(i) = val(r); val(r) = dswap;
1066  *
1067  * return i;
1068  * }
1069  */
1070 
1071 void
1072 DynCompRow :: qsortRow(IntArray &ind, IntArray &ir, FloatArray &val, int l, int r)
1073 {
1074  if ( r <= l ) {
1075  return;
1076  }
1077 
1078  int i = qsortRowPartition(ind, ir, val, l, r);
1079  qsortRow(ind, ir, val, l, i - 1);
1080  qsortRow(ind, ir, val, i + 1, r);
1081 }
1082 
1083 
1084 int
1086 {
1087  int i = l - 1, j = r;
1088  double v = fabs( val(r) );
1089  int swap;
1090  double dswap;
1091 
1092  for ( ; ; ) {
1093  while ( ( fabs( val(++i) ) > v ) ) {
1094  ;
1095  }
1096 
1097  while ( ( v > fabs( val(--j) ) ) ) {
1098  if ( j == l ) {
1099  break;
1100  }
1101  }
1102 
1103  if ( i >= j ) {
1104  break;
1105  }
1106 
1107  swap = ir( ind(i) );
1108  ir( ind(i) ) = ir( ind(j) );
1109  ir( ind(j) ) = swap;
1110  swap = ind(i);
1111  ind(i) = ind(j);
1112  ind(j) = swap;
1113  dswap = val(i);
1114  val(i) = val(j);
1115  val(j) = dswap;
1116  }
1117 
1118  swap = ir( ind(i) );
1119  ir( ind(i) ) = ir( ind(r) );
1120  ir( ind(r) ) = swap;
1121  swap = ind(i);
1122  ind(i) = ind(r);
1123  ind(r) = swap;
1124  dswap = val(i);
1125  val(i) = val(r);
1126  val(r) = dswap;
1127 
1128  return i;
1129 }
1130 } // end namespace oofem
int nColumns
Number of columns.
Definition: sparsemtrx.h:69
void ILUPsolve(const FloatArray &x, FloatArray &y) const
Definition: dyncomprow.C:970
const FloatArray * row(int i) const
Returns row values.
Definition: dyncomprow.h:114
Class and object Domain.
Definition: domain.h:115
virtual int giveNumberOfDomainEquations(int di, const UnknownNumberingScheme &num)
Returns number of equations for given domain in active (current time step) time step.
Definition: engngm.C:391
Base class for all matrices stored in sparse format.
Definition: sparsemtrx.h:60
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
int max(int i, int j)
Returns bigger value form two given decimals.
Definition: mathfem.h:71
virtual void times(const FloatArray &x, FloatArray &answer) const
Evaluates .
Definition: dyncomprow.C:185
DynCompRow & operator=(const DynCompRow &C)
Assignment operator.
Definition: dyncomprow.C:131
#define S(p)
Definition: mdm.C:481
#define OOFEM_LOG_DEBUG(...)
Definition: logger.h:128
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
virtual double & at(int i, int j)
Returns coefficient at position (i,j).
Definition: dyncomprow.C:406
int qsortRowPartition(IntArray &ind, IntArray &ir, FloatArray &val, int l, int r)
Definition: dyncomprow.C:1085
int insertColInRow(int row, int col)
insert column entry into row, preserving order of column indexes, returns the index of new row...
Definition: dyncomprow.C:604
double operator()(int i, int j) const
implements 0-based access
Definition: dyncomprow.C:436
IntArray ** colind_
Definition: dyncomprow.h:62
int nRows
Number of rows.
Definition: sparsemtrx.h:67
void ILUPtrans_solve(const FloatArray &x, FloatArray &y) const
Definition: dyncomprow.C:1007
#define ILU_ROW_CHUNK
Definition: dyncomprow.C:722
DynCompRow()
Constructor.
Definition: dyncomprow.C:56
std::vector< std::unique_ptr< GeneralBoundaryCondition > > & giveBcs()
Definition: domain.h:322
virtual int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &)
Builds internal structure of receiver.
Definition: dyncomprow.C:218
#define OOFEM_ERROR(...)
Definition: error.h:61
REGISTER_SparseMtrx(CompCol, SMT_CompCol)
Implementation of sparse matrix stored in compressed column storage.
Definition: dyncomprow.h:57
Abstract base class allowing to control the way, how equations are assigned to individual DOFs...
void qsortRow(IntArray &ind, IntArray &ir, FloatArray &val, int l, int r)
Definition: dyncomprow.C:1072
void resizeWithValues(int n, int allocChunk=0)
Checks size of receiver towards requested bounds.
Definition: intarray.C:115
Abstract base class for all active boundary conditions.
Definition: activebc.h:63
void resizeWithValues(int s, int allocChunk=0)
Checks size of receiver towards requested bounds.
Definition: floatarray.C:615
double at(int i, int j) const
Coefficient access function.
Definition: floatmatrix.h:176
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
virtual int assemble(const IntArray &loc, const FloatMatrix &mat)
Assembles sparse matrix from contribution of local elements.
Definition: dyncomprow.C:321
virtual void timesT(const FloatArray &x, FloatArray &answer) const
Evaluates .
Definition: dyncomprow.C:466
SparseMtrxVersionType version
Allows to track if receiver changes.
Definition: sparsemtrx.h:80
Initializes the variable VERBOSE, in order to get a few intermediate messages on screen: beginning an...
virtual ~DynCompRow()
Destructor.
Definition: dyncomprow.C:104
void checkSizeTowards(IntArray &)
Definition: dyncomprow.C:489
Class representing vector of real numbers.
Definition: floatarray.h:82
Implementation of matrix containing floating point numbers.
Definition: floatmatrix.h:94
Dynamically growing compressed row.
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
void times(double s)
Multiplies receiver with scalar.
Definition: floatarray.C:818
std::vector< std::unique_ptr< Element > > & giveElements()
Definition: domain.h:279
FloatArray ** rows_
Definition: dyncomprow.h:61
int giveColIndx(int row, int col) const
returns the column index of given column at given row, else returns zero.
Definition: dyncomprow.C:569
void ILUPYourself(int part_fill=5, double drop_tol=1.e-8)
Performs LU factorization on yourself; modifies receiver This routine computes the L and U factors of...
Definition: dyncomprow.C:726
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
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.
#define DynCompRow_CHUNK
Definition: dyncomprow.h:50
Domain * giveDomain(int n)
Service for accessing particular problem domain.
Definition: engngm.C:1720
SparseMtrx * GiveCopy() const
Returns a newly allocated copy of receiver.
Definition: dyncomprow.C:178
virtual void zero()
Zeroes the receiver.
Definition: dyncomprow.C:380
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition: floatmatrix.h:156
void startTimer()
Definition: timer.C:69
double getUtime()
Returns total user time elapsed in seconds.
Definition: timer.C:105
void growTo(int)
Definition: dyncomprow.C:546
void stopTimer()
Definition: timer.C:77
IntArray diag_rowptr_
Definition: dyncomprow.h:63
virtual void printStatistics() const
Prints the receiver statistics (one-line) to stdout.
Definition: dyncomprow.C:391
virtual void giveLocationArrays(std::vector< IntArray > &rows, std::vector< IntArray > &cols, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s)
Gives a list of location arrays that will be assembled.
Definition: activebc.h:138
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:28 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011