OOFEM 3.0
Loading...
Searching...
No Matches
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 - 2025 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
35#include "dyncomprow.h"
36#include "floatarray.h"
37#include "engngm.h"
38#include "domain.h"
39#include "mathfem.h"
40#include "verbose.h"
41#include "element.h"
42#include "sparsemtrxtype.h"
43#include "activebc.h"
44#include "classfactory.h"
45#ifdef __MPM_MODULE
46#include "../mpm/integral.h"
47#endif
48
49#ifdef TIME_REPORT
50 #include "timer.h"
51#endif
52
53namespace oofem {
55
56
57DynCompRow :: DynCompRow(int n) : SparseMtrx(n, n),
58 base(0)
59{}
60
61
62DynCompRow :: DynCompRow(const DynCompRow &S) : SparseMtrx(S.nRows, S.nColumns),
63 rows(S.rows),
65 diag(S.diag),
66 base(S.base)
67{
68 this->version = S.version;
69}
70
71
72DynCompRow &DynCompRow :: operator = ( const DynCompRow & C )
73{
74 rows = C.rows;
75 colind = C.colind;
76 diag = C.diag;
77 base = C.base;
78
79 nRows = C.nRows;
81 version = C.version;
82 return * this;
83}
84
85std::unique_ptr<SparseMtrx> DynCompRow :: clone() const
86{
87 return std::make_unique<DynCompRow>(*this);
88}
89
90
91void DynCompRow :: times(const FloatArray &x, FloatArray &answer) const
92{
93 if ( x.giveSize() != nColumns ) {
94 OOFEM_ERROR("Error in CompRow -- incompatible dimensions");
95 }
96
97 answer.resize(nRows);
98 answer.zero();
99
100 for ( int j = 0; j < nRows; j++ ) {
101 double r = 0.0;
102 for ( int t = 1; t <= rows [ j ].giveSize(); t++ ) {
103 r += rows [ j ].at(t) * x[ colind [ j ].at(t) ];
104 }
105
106 answer(j) = r;
107 }
108}
109
110void DynCompRow :: times(double x)
111{
112 for ( auto &row : rows ) {
113 row.times(x);
114 }
115
116 this->version++;
117}
118
119int DynCompRow :: buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s)
120{
121 int neq = eModel->giveNumberOfDomainEquations(di, s);
122
123 IntArray loc;
124 Domain *domain = eModel->giveDomain(di);
125
126#ifdef TIME_REPORT
127 Timer timer;
128 timer.startTimer();
129#endif
130
131 this->colind.clear();
132 this->rows.clear();
133 this->growTo(neq);
134
135 for ( auto &elem : domain->giveElements() ) {
136 elem->giveLocationArray(loc, s);
137 for ( int i = 1; i <= loc.giveSize(); i++ ) { // row indx
138 int ii;
139 if ( ( ii = loc.at(i) ) ) {
140 for ( int j = 1; j <= loc.giveSize(); j++ ) { // col indx
141 int jj;
142 if ( ( jj = loc.at(j) ) ) {
143 this->insertColInRow(ii - 1, jj - 1);
144 }
145 }
146 }
147 }
148 }
149
150
151 std :: vector< IntArray >r_locs;
152 std :: vector< IntArray >c_locs;
153
154 for ( auto &gbc : domain->giveBcs() ) {
155 ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() );
156 if ( bc ) {
157 bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s);
158 for ( std :: size_t k = 0; k < r_locs.size(); k++ ) {
159 IntArray &krloc = r_locs [ k ];
160 IntArray &kcloc = c_locs [ k ];
161 for ( int i = 1; i <= krloc.giveSize(); i++ ) {
162 int ii;
163 if ( ( ii = krloc.at(i) ) ) {
164 for ( int j = 1; j <= kcloc.giveSize(); j++ ) {
165 int jj;
166 if ( ( jj = kcloc.at(j) ) ) {
167 this->insertColInRow(ii - 1, jj - 1);
168 }
169 }
170 }
171 }
172 }
173 }
174 }
175
176
177#ifdef __MPM_MODULE
178 IntArray locr, locc;
179 // loop over integrals
180 for (auto &in: eModel->giveIntegralList()) {
181 // loop over integral domain
182 for (auto &elem: in->set->giveElementList()) {
183 // get code numbers for integral.term on element
184 in->getElementTermCodeNumbers (locr, locc, domain->giveElement(elem), *in->term, s) ;
185 for ( int i = 1; i <= locr.giveSize(); i++ ) {
186 int ii;
187 if ( ( ii = locr.at(i) ) ) {
188 for ( int j = 1; j <= locc.giveSize(); j++ ) {
189 int jj;
190 if ( ( jj = locc.at(j) ) ) {
191 this->insertColInRow(ii - 1, jj - 1);
192 }
193 }
194 }
195 }
196 }
197 }
198#endif
199
200
201 int nz_ = 0;
202 for ( auto &col : this->colind ) {
203 nz_ += col.giveSize();
204 }
205
206 OOFEM_LOG_DEBUG("DynCompRow info: neq is %d, nelem is %d\n", neq, nz_);
207
208 this->version++;
209#ifdef TIME_REPORT
210 timer.stopTimer();
211 OOFEM_LOG_DEBUG( "DynCompRow::buildInternalStructure: user time consumed: %.2fs\n", timer.getUtime() );
212#endif
213
214 return true;
215}
216
217
218int DynCompRow :: assemble(const IntArray &loc, const FloatMatrix &mat)
219{
220 int dim = mat.giveNumberOfRows();
221
222# ifdef DEBUG
223 if ( dim != loc.giveSize() ) {
224 OOFEM_ERROR("dimension of 'k' and 'loc' mismatch");
225 }
226# endif
227
228 for ( int j = 1; j <= dim; j++ ) {
229 int jj = loc.at(j);
230 if ( jj ) {
231 for ( int i = 1; i <= dim; i++ ) {
232 int ii = loc.at(i);
233 if ( ii ) {
234 this->at(ii, jj) += mat.at(i, j);
235 }
236 }
237 }
238 }
239
240 this->version++;
241 return 1;
242}
243
244int DynCompRow :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat)
245{
246 // optimized low-end implementation
247 IntArray colsToAdd( rloc.giveSize() );
248 int rsize = rloc.giveSize();
249 int csize = cloc.giveSize();
250
251 for ( int i = 0; i < rsize; i++ ) {
252 int ii;
253 if ( ( ii = rloc[i] ) ) {
254 int ii1 = ii - 1;
255 for ( int j = 0; j < csize; j++ ) {
256 int jj;
257 if ( ( jj = cloc[j] ) ) {
258 int jj1 = jj - 1;
259
260 int colindx = this->insertColInRow(ii1, jj1);
261 rows [ ii1 ].at(colindx) += mat(i, j);
262 }
263 }
264 }
265 }
266
267 this->version++;
268 return 1;
269}
270
271void DynCompRow :: zero()
272{
273 for ( auto &row: rows ) {
274 row.zero();
275 }
276
277 this->version++;
278}
279
280
281void DynCompRow :: printStatistics() const
282{
283 int nz = 0;
284 for ( auto &row : rows ) {
285 nz += row.giveSize();
286 }
287
288 printf("\nDynCompRow info: neq is %d, nelem is %d\n", nRows, nz);
289}
290
291
292double &DynCompRow :: at(int i, int j)
293{
294 int colIndx;
295
296 this->version++;
297 if ( ( colIndx = this->giveColIndx(i - 1, j - 1) ) ) {
298 return rows [ i - 1 ].at(colIndx);
299 }
300
301 OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j);
302 return rows [ 0 ].at(1); // return to suppress compiler warning message
303}
304
305
306double DynCompRow :: at(int i, int j) const
307{
308 int colIndx;
309 if ( ( colIndx = this->giveColIndx(i - 1, j - 1) ) ) {
310 return rows [ i - 1 ].at(colIndx);
311 }
312
313 if ( i <= nRows && j <= nColumns ) {
314 return 0.0;
315 } else {
316 OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j);
317 return rows [ 0 ].at(1); // return to suppress compiler warning message
318 }
319}
320
321double DynCompRow :: operator() (int i, int j) const
322{
323 int colIndx;
324 if ( ( colIndx = this->giveColIndx(i, j) ) ) {
325 return rows [ i ].at(colIndx);
326 }
327
328 if ( i < nRows && j < nColumns ) {
329 return 0.0;
330 } else {
331 OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j);
332 return rows [ 0 ].at(1); // return to suppress compiler warning message
333 }
334}
335
336double &DynCompRow :: operator() (int i, int j)
337{
338 int colIndx;
339
340 // increment version
341 this->version++;
342
343 if ( ( colIndx = this->giveColIndx(i, j) ) ) {
344 return rows [ i ].at(colIndx);
345 }
346
347 OOFEM_ERROR("Array element (%d,%d) not in sparse structure -- cannot assign", i, j);
348 return rows [ 0 ].at(1); // return to suppress compiler warning message
349}
350
351void DynCompRow :: timesT(const FloatArray &x, FloatArray &answer) const
352{
353 // Check for compatible dimensions:
354 if ( x.giveSize() != nRows ) {
355 OOFEM_ERROR("Error in CompRow -- incompatible dimensions");
356 }
357
358 answer.resize(nColumns);
359 answer.zero();
360
361 for ( int i = 0; i < nColumns; i++ ) {
362 double r = x[i];
363 for ( int t = 1; t <= rows [ i ].giveSize(); t++ ) {
364 answer[ colind [ i ].at(t) ] += rows [ i ].at(t) * r;
365 }
366 }
367}
368
369
370
371void DynCompRow :: checkSizeTowards(IntArray &loc)
372{
373 int maxid = 0;
374 int size = loc.giveSize();
375 // adjust the size of receiver
376 for ( int i = 0; i < size; i++ ) {
377 maxid = max( maxid, loc[i] );
378 }
379
380 this->growTo(maxid);
381
382 for ( int i = 0; i < size; i++ ) {
383 int ii;
384 if ( ( ii = loc[i] ) ) {
385 for ( int j = 0; j < size; j++ ) {
386 int jj;
387 if ( ( jj = loc[j] ) ) {
388 this->insertColInRow(ii - 1, jj - 1);
389 }
390 }
391 }
392 }
393}
394
395
396void DynCompRow :: checkSizeTowards(const IntArray &rloc, const IntArray &cloc)
397{
398 int maxid = 0;
399 int rsize = rloc.giveSize();
400 int csize = cloc.giveSize();
401
402 // adjust the size of receiver
403 for ( int i = 0; i < rsize; i++ ) {
404 maxid = max( maxid, rloc[i] );
405 }
406
407 for ( int i = 0; i < csize; i++ ) {
408 maxid = max( maxid, cloc[i] );
409 }
410
411 this->growTo(maxid);
412
413 for ( int i = 0; i < rsize; i++ ) {
414 int ii;
415 if ( ( ii = rloc[i] ) ) {
416 for ( int j = 0; j < csize; j++ ) {
417 int jj;
418 if ( ( jj = cloc[j] ) ) {
419 this->insertColInRow(ii - 1, jj - 1);
420 }
421 }
422 }
423 }
424}
425
426
427void DynCompRow :: growTo(int ns)
428{
429 if ( ns > nRows ) {
430 this->rows.resize(ns);
431 this->colind.resize(ns);
432 nColumns = nRows = ns;
433 }
434}
435
436
437int DynCompRow :: giveColIndx(int row, int col) const
438{
439 // fast col indx search, based on assumption, that col indices are sorted
440 int left = 1, right = this->colind [ row ].giveSize();
441 int middle = ( left + right ) / 2;
442 int middleVal;
443
444 if ( right == 0 ) {
445 return 0;
446 }
447
448 if ( this->colind [ row ].at(right) == col ) {
449 return right;
450 }
451
452 while ( !( ( ( middleVal = this->colind [ row ].at(middle) ) == col ) || ( middle == left ) ) ) {
453 if ( col > middleVal ) {
454 left = middle;
455 } else {
456 right = middle;
457 }
458
459 middle = ( left + right ) / 2;
460 }
461
462 if ( middleVal == col ) {
463 return middle;
464 }
465
466 return 0;
467}
468
469
470int
471DynCompRow :: insertColInRow(int row, int col)
472{
473 // insert col entry into row, preserving order of col indexes.
474 int oldsize = this->colind [ row ].giveSize();
475 int left = 1, right = oldsize;
476 int middle = ( left + right ) / 2;
477 int middleVal;
478
479 if ( oldsize == 0 ) {
480 colind [ row ].resizeWithValues(1, DynCompRow_CHUNK);
481 rows [ row ].resizeWithValues(1, DynCompRow_CHUNK);
482 rows [ row ].at(1) = 0.0;
483 colind [ row ].at(1) = col;
484 return 1;
485 }
486
487 if ( this->colind [ row ].at(right) == col ) {
488 return right;
489 }
490
491 while ( !( ( ( middleVal = this->colind [ row ].at(middle) ) == col ) || ( middle == left ) ) ) {
492 if ( col > middleVal ) {
493 left = middle;
494 } else {
495 right = middle;
496 }
497
498 middle = ( left + right ) / 2;
499 }
500
501 if ( middleVal == col ) {
502 return middle;
503 }
504
505 // we have to insert new row entry
506 if ( col > this->colind [ row ].at(oldsize) ) {
507 right = oldsize + 1;
508 } else if ( col < this->colind [ row ].at(1) ) {
509 right = 1;
510 }
511
512 // insert col at middle+1 position
513 colind [ row ].resizeWithValues(oldsize + 1, DynCompRow_CHUNK);
514 rows [ row ].resizeWithValues(oldsize + 1, DynCompRow_CHUNK);
515
516 for ( int i = oldsize; i >= right; i-- ) {
517 colind [ row ].at(i + 1) = colind [ row ].at(i);
518 rows [ row ].at(i + 1) = rows [ row ].at(i);
519 }
520
521 rows [ row ].at(right) = 0.0;
522 colind [ row ].at(right) = col;
523 return right;
524}
525
526
527//#define ILU_0
528//#define ILU_DROP_TOL 1.e-8
529#define ILU_ROW_CHUNK 10
530//#define ILU_PART_FILL 5
531
532void
533DynCompRow :: ILUPYourself(int part_fill, double drop_tol)
534{
535 IntArray irw(nColumns), iw;
536 FloatArray w;
537 diag.resize(nRows);
538
539#ifdef TIME_REPORT
540 Timer timer;
541 timer.startTimer();
542#endif
543
544 for ( int i = 0; i < nRows; i++ ) { // row loop
545 if ( ( diag[i] = giveColIndx(i, i) ) == 0 ) { // giveColIndx returns 1-based indexing
546 OOFEM_ERROR("zero value on diagonal");
547 }
548 }
549
550 /* FACTOR MATRIX */
551
552 for ( int i = 1; i < nRows; i++ ) { // loop over rows
553 double inorm = 0.0;
554 for ( int ii = 1; ii <= rows [ i ].giveSize(); ii++ ) {
555 double val = rows [ i ].at(ii);
556 inorm += val * val;
557 }
558
559 inorm = sqrt(inorm);
560
561 w.resizeWithValues(rows [ i ].giveSize(), ILU_ROW_CHUNK);
562 iw.resizeWithValues(rows [ i ].giveSize(), ILU_ROW_CHUNK);
563 for ( int kk = 1; kk <= rows [ i ].giveSize(); kk++ ) {
564 irw[ colind [ i ].at(kk) ] = kk;
565 iw[kk - 1] = colind [ i ].at(kk);
566 w[kk - 1] = rows [ i ].at(kk);
567 }
568
569 //for (k=0; k < (diag(i)-1); k++) { // loop 1,...,i-1 for (i,k) \in NZ(A)
570 int k = 0;
571 while ( iw.at(k + 1) < i ) {
572 // initialize k-th row indexes
573 int krow = iw.at(k + 1);
574 //multiplier = (rows[i].at(k+1) /= rows[krow].at(diag(krow)));
575 double multiplier = ( w.at(k + 1) /= rows [ krow ].at( diag[krow] ) );
576
577#ifndef ILU_0
578 // first dropping rule for aik
579 if ( fabs(multiplier) >= drop_tol * inorm )
580#endif
581 { // first drop rule
582 for ( int j = 0; j < colind [ krow ].giveSize(); j++ ) {
583 int jcol = colind [ krow ].at(j + 1);
584 if ( jcol > krow ) {
585 if ( irw[jcol] ) {
586 //rows[i].at(irw(jcol)) -= multiplier*rows[krow].at(j+1);
587 w.at( irw[jcol] ) -= multiplier * rows [ krow ].at(j + 1);
588 } else {
589#ifndef ILU_0
590 // insert new entry
591 int newsize = w.giveSize() + 1;
593 iw.resizeWithValues(newsize, ILU_ROW_CHUNK);
594
595 iw.at(newsize) = jcol;
596 w.at(newsize) = -multiplier * rows [ krow ].at(j + 1);
597 irw[jcol] = newsize;
598#endif
599
600 /*
601 * ipos = insertColInRow (i,jcol) ;
602 * for (kk=ipos+1; kk<= rows[i].giveSize(); kk++)
603 * irw(colind[i].at(kk))++;
604 *
605 * ipos = insertColInRow (i,jcol) ;
606 * rows[i].at(ipos) = -multiplier*rows[krow].at(j+1);
607 * irw(jcol) = ipos;
608 * if (jcol < i) diag(i)++;
609 */
610 }
611 }
612 }
613 }
614
615 // scan iw to find closest index to krow
616 int ck = nColumns + 1;
617 for ( int kk = 0; kk < iw.giveSize(); kk++ ) {
618 if ( ( ( iw[kk] - krow ) > 0 ) && ( ( iw[kk] - krow ) < ( ck - krow ) ) ) {
619 ck = iw[kk];
620 }
621 }
622
623 k = irw[ck] - 1;
624 }
625
626#ifndef ILU_0
627
628 int end = iw.giveSize();
629 int curr = 1;
630 // second drop rule
631 while ( curr <= end ) {
632 if ( ( fabs( w.at(curr) ) < drop_tol * inorm ) && ( iw.at(curr) != i ) ) {
633 // remove entry
634 w.at(curr) = w.at(end);
635 irw[ iw.at(curr) ] = 0;
636 iw.at(curr) = iw.at(end);
637 if ( curr != end ) {
638 irw[ iw.at(curr) ] = curr;
639 }
640
641 end--;
642 } else {
643 curr++;
644 }
645 }
646
647 // cutt off
648 w.resize(end);
649 iw.resize(end);
650
651 int count = end;
652
653 // select only the p-largest w values
654 this->qsortRow(iw, irw, w, 0, iw.giveSize() - 1);
655 //
656 int lsizeLimit = diag[i] - 1;
657 int usizeLimit = rows [ i ].giveSize() - lsizeLimit;
658
659 lsizeLimit += part_fill;
660 usizeLimit += part_fill;
661
662 int lnums = 0;
663 int unums = 0;
664 count = 0;
665 for ( int kk = 1; kk <= iw.giveSize(); kk++ ) {
666 if ( iw.at(kk) < i ) { // lpart
667 if ( ++lnums > lsizeLimit ) {
668 irw[ iw.at(kk) ] = 0;
669 } else {
670 count++;
671 }
672 } else if ( iw.at(kk) > i ) { // upart
673 if ( ++unums > usizeLimit ) {
674 irw[ iw.at(kk) ] = 0;
675 } else {
676 count++;
677 }
678 } else { // diagonal is always kept
679 count++;
680 }
681 }
682
683#else
684 int count = iw.giveSize();
685#endif
686 rows [ i ].resize(count);
687 colind [ i ].resize(count);
688
689 int icount = 1;
690 int indx, idist, previndx = -1;
691 int kkend = iw.giveSize();
692
693 for ( int kk = 1; kk <= count; kk++ ) {
694 idist = nColumns + 2;
695 indx = 0;
696
697 for ( int kki = 1; kki <= kkend; kki++ ) {
698 if ( ( irw[ iw.at(kki) ] != 0 ) && ( iw.at(kki) > previndx ) && ( ( iw.at(kki) - previndx ) < idist ) ) {
699 idist = iw.at(kki) - previndx;
700 indx = kki;
701 }
702 }
703
704 if ( indx == 0 ) {
705 OOFEM_ERROR("internal error");
706 }
707
708 previndx = iw.at(indx);
709 rows [ i ].at(icount) = w.at(indx);
710 colind [ i ].at(icount) = iw.at(indx);
711 if ( colind [ i ].at(icount) == i ) {
712 diag[i] = icount;
713 }
714
715 icount++;
716
717 // exclude the indx entry from search by moving it to the end of list
718 irw[ iw.at(indx) ] = 0;
719 iw.at(indx) = iw.at(kkend);
720 w.at(indx) = w.at(kkend);
721 if ( irw[ iw.at(indx) ] != 0 ) {
722 irw[ iw.at(indx) ] = indx;
723 }
724
725 kkend--;
726
727 // exclude the indx entry from search by moving it to the end of list
728#if 0
729 std::swap(irw[iw.at(indx)], irw[iw.at(kkend)]);
730 std::swap(iw.at(indx), iw.at(kkend));
731 std::swap(w.at(indx), w.at(kkend));
732 kkend--;
733#endif
734 }
735
736
737#if 0
738 int icount = 1;
739 for (kk=1; kk<= nColumns; kk++) {
740 if ( irw.at(kk) > 0 ) {
741 rows[i].at(icount) = w.at(abs(irw[kk-1]));
742 colind[i].at(icount) = iw.at(abs(irw[kk-1]));
743 if (colind[i].at(icount) == i) diag[i] = icount;
744 icount++;
745 }
746 }
747#endif
748 if ( ( icount - count ) != 1 ) {
749 OOFEM_ERROR("%d - row errorr (%d,%d)\n", i, icount, count);
750 }
751
752 //Refresh all iw enries to zero
753 for ( int kk = 1; kk <= iw.giveSize(); kk++ ) {
754 irw[ iw.at(kk) ] = 0;
755 }
756
757 //irw.zero();
758 }
759
760#ifdef TIME_REPORT
761 timer.stopTimer();
762 OOFEM_LOG_DEBUG( "\nILUT(%d,%e): user time consumed by factorization: %.2fs\n", part_fill, drop_tol, timer.getUtime() );
763#endif
764
765 this->version++;
766}
767
768
769
770void
771DynCompRow :: ILUPsolve(const FloatArray &x, FloatArray &y) const
772{
773 int M = x.giveSize();
774 FloatArray work(M);
775
776 // solve Lw=x
777 for ( int i = 0; i < M; i++ ) {
778 double r = x[i];
779 for ( int t = 0; t < ( diag[i] - 1 ); t++ ) {
780 r -= rows [ i ].at(t + 1) * work( colind [ i ].at(t + 1) );
781 }
782
783 work[i] = r;
784 }
785
786 y.resize(M);
787 y.zero();
788 // solve Uy=w
789 for ( int i = M - 1; i >= 0; i-- ) {
790 double r = work[i];
791 for ( int t = diag[i]; t < rows [ i ].giveSize(); t++ ) {
792 r -= rows [ i ].at(t + 1) * y( colind [ i ].at(t + 1) );
793 }
794
795 y[i] = r / rows [ i ].at( diag[i] );
796 }
797}
798
799
800void
801DynCompRow :: ILUPtrans_solve(const FloatArray &x, FloatArray &y) const
802{
803 int M = x.giveSize();
804 FloatArray work(M);
805
806 y.resize(M);
807
808 // solve for U^Tw = x
809 for ( int i = 0; i < M; i++ ) {
810 work[i] = ( x[i] + work[i] ) / rows [ i ].at( diag[i] );
811 for ( int t = diag[i]; t < rows [ i ].giveSize(); t++ ) {
812 work( colind [ i ].at(t + 1) ) -= rows [ i ].at(t + 1) * work[i];
813 }
814 }
815
816 // solve for L^T y = w
817 for ( int i = M - 1; i >= 0; i-- ) {
818 y[i] = work[i];
819 for ( int t = 1; t < diag[i]; t++ ) {
820 work( colind [ i ].at(t) ) -= rows [ i ].at(t) * y[i];
821 }
822 }
823}
824
825
826void
827DynCompRow :: qsortRow(IntArray &ind, IntArray &ir, FloatArray &val, int l, int r)
828{
829 if ( r <= l ) {
830 return;
831 }
832
833 int i = qsortRowPartition(ind, ir, val, l, r);
834 qsortRow(ind, ir, val, l, i - 1);
835 qsortRow(ind, ir, val, i + 1, r);
836}
837
838
839int
840DynCompRow :: qsortRowPartition(IntArray &ind, IntArray &ir, FloatArray &val, int l, int r)
841{
842 int i = l - 1, j = r;
843 double v = fabs( val[r] );
844
845 for ( ; ; ) {
846 while ( ( fabs( val(++i) ) > v ) ) {
847 ;
848 }
849
850 while ( ( v > fabs( val(--j) ) ) ) {
851 if ( j == l ) {
852 break;
853 }
854 }
855
856 if ( i >= j ) {
857 break;
858 }
859
860 std::swap(ir[ ind[i] ], ir[ ind[j] ]);
861 std::swap(ind[i], ind[j]);
862 std::swap(val[i], val[j]);
863 }
864
865 std::swap(ir[ ind[i] ], ir[ ind[r] ]);
866 std::swap(ind[i], ind[r]);
867 std::swap(val[i], val[r]);
868
869 return i;
870}
871} // end namespace oofem
#define REGISTER_SparseMtrx(class, type)
virtual void giveLocationArrays(std ::vector< IntArray > &rows, std ::vector< IntArray > &cols, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s)
Definition activebc.h:137
std ::vector< std ::unique_ptr< GeneralBoundaryCondition > > & giveBcs()
Definition domain.h:349
Element * giveElement(int n)
Definition domain.C:165
std ::vector< std ::unique_ptr< Element > > & giveElements()
Definition domain.h:294
int giveColIndx(int row, int col) const
returns the column index of given column at given row, else returns zero.
Definition dyncomprow.C:437
std::vector< FloatArray > rows
data values per column
Definition dyncomprow.h:61
std::vector< IntArray > colind
row_ind per column
Definition dyncomprow.h:63
void qsortRow(IntArray &ind, IntArray &ir, FloatArray &val, int l, int r)
Definition dyncomprow.C:827
int qsortRowPartition(IntArray &ind, IntArray &ir, FloatArray &val, int l, int r)
Definition dyncomprow.C:840
IntArray diag
pointers to the diagonal elements; needed only for ILU
Definition dyncomprow.h:65
int base
index base: offset of first element
Definition dyncomprow.h:68
DynCompRow(int n=0)
Definition dyncomprow.C:57
double & at(int i, int j) override
Returns coefficient at position (i,j).
Definition dyncomprow.C:292
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:471
const FloatArray & row(int i) const
Returns row values.
Definition dyncomprow.h:112
virtual int giveNumberOfDomainEquations(int di, const UnknownNumberingScheme &num)
Definition engngm.C:452
Domain * giveDomain(int n)
Definition engngm.C:1936
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 resizeWithValues(Index s, std::size_t allocChunk=0)
Definition floatarray.C:103
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
int giveNumberOfRows() const
Returns number of rows of receiver.
double at(std::size_t i, std::size_t j) const
void resizeWithValues(int n, int allocChunk=0)
Definition intarray.C:64
void resize(int n)
Definition intarray.C:73
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
int nColumns
Number of columns.
Definition sparsemtrx.h:71
SparseMtrxVersionType version
Definition sparsemtrx.h:82
SparseMtrx(int n=0, int m=0)
Definition sparsemtrx.h:89
int nRows
Number of rows.
Definition sparsemtrx.h:69
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 ILU_ROW_CHUNK
Definition dyncomprow.C:529
#define DynCompRow_CHUNK
Definition dyncomprow.h:50
#define OOFEM_ERROR(...)
Definition error.h:79
#define OOFEM_LOG_DEBUG(...)
Definition logger.h:144
#define S(p)
Definition mdm.C:469
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
@ SMT_DynCompRow
Dynamically growing compressed row.

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