OOFEM 3.0
Loading...
Searching...
No Matches
dyncompcol.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// inspired by SL++
36
37#include "dyncompcol.h"
38#include "floatarray.h"
39#include "engngm.h"
40#include "domain.h"
41#include "mathfem.h"
42#include "element.h"
43#include "sparsemtrxtype.h"
44#include "activebc.h"
45#include "classfactory.h"
46#ifdef __MPM_MODULE
47#include "../mpm/integral.h"
48#endif
49
50namespace oofem {
52
53
54DynCompCol :: DynCompCol(int n) : SparseMtrx(n, n),
55 base(0)
56{}
57
58
59DynCompCol :: DynCompCol(const DynCompCol &S) : SparseMtrx(S.nRows, S.nColumns),
62 base(S.base)
63{
64 this->version = S.version;
65}
66
67
68DynCompCol &DynCompCol :: operator = ( const DynCompCol & C )
69{
70 columns = C.columns;
71 rowind = C.rowind;
72 base = C.base;
73
74 nRows = C.nRows;
76 version = C.version;
77
78 return * this;
79}
80
81std::unique_ptr<SparseMtrx> DynCompCol :: clone() const
82{
83 return std::make_unique<DynCompCol>(*this);
84}
85
86void DynCompCol :: times(const FloatArray &x, FloatArray &answer) const
87{
88 if ( x.giveSize() != nColumns ) {
89 OOFEM_ERROR("incompatible dimensions");
90 }
91
92 answer.resize(nRows);
93 answer.zero();
94
95 for ( int j = 0; j < nColumns; j++ ) {
96 double rhs = x[j];
97 for ( int t = 1; t <= columns[ j ].giveSize(); t++ ) {
98 answer[ rowind[ j ].at(t) ] += columns[ j ].at(t) * rhs;
99 }
100 }
101}
102
103void DynCompCol :: times(double x)
104{
105 for ( auto &column : columns ) {
106 column.times(x);
107 }
108
109 this->version++;
110}
111
112int DynCompCol :: buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s)
113{
114 int neq = eModel->giveNumberOfDomainEquations(di, s);
115
116 IntArray loc;
117 Domain *domain = eModel->giveDomain(di);
118
119 nColumns = nRows = neq;
120
121 rowind.clear();
122 columns.clear();
123 this->growTo(neq);
124
125 for ( auto &elem : domain->giveElements() ) {
126 elem->giveLocationArray(loc, s);
127
128 for ( int ii : loc ) {
129 if ( ii > 0 ) {
130 for ( int jj : loc ) {
131 if ( jj > 0 ) {
132 this->insertRowInColumn(ii - 1, jj - 1);
133 }
134 }
135 }
136 }
137 }
138
139 // loop over active boundary conditions
140 std :: vector< IntArray >r_locs;
141 std :: vector< IntArray >c_locs;
142
143 for ( auto &gbc : domain->giveBcs() ) {
144 ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() );
145 if ( bc ) {
146 bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s);
147 for ( std :: size_t k = 0; k < r_locs.size(); k++ ) {
148 IntArray &krloc = r_locs [ k ];
149 IntArray &kcloc = c_locs [ k ];
150 for ( int ii : krloc ) {
151 if ( ii > 0 ) {
152 for ( int jj : kcloc ) {
153 if ( jj > 0 ) {
154 this->insertRowInColumn(jj - 1, ii - 1);
155 }
156 }
157 }
158 }
159 }
160 }
161 }
162
163#ifdef __MPM_MODULE
164 IntArray locr, locc;
165 // loop over integrals
166 for (auto &in: eModel->giveIntegralList()) {
167 // loop over integral domain
168 for (auto &elem: in->set->giveElementList()) {
169 // get code numbers for integral.term on element
170 in->getElementTermCodeNumbers (locr, locc, domain->giveElement(elem), *in->term, s) ;
171 for ( int ii : locr ) {
172 if ( ii > 0 ) {
173 for ( int jj : locc ) {
174 if ( jj > 0 ) {
175 this->insertRowInColumn(jj - 1, ii - 1);
176 }
177 }
178 }
179 }
180 }
181 }
182#endif
183
184 int nz_ = 0;
185 for ( int j = 0; j < neq; j++ ) {
186 nz_ += this->rowind[ j ].giveSize();
187 }
188
189 OOFEM_LOG_DEBUG("DynCompCol info: neq is %d, nelem is %d\n", neq, nz_);
190
191 this->version++;
192
193 return true;
194}
195
196
197int DynCompCol :: assemble(const IntArray &loc, const FloatMatrix &mat)
198{
199 int dim = mat.giveNumberOfRows();
200
201# ifdef DEBUG
202 if ( dim != loc.giveSize() ) {
203 OOFEM_ERROR("dimension of 'k' and 'loc' mismatch");
204 }
205# endif
206
207 for ( int j = 1; j <= dim; j++ ) {
208 int jj = loc.at(j);
209 if ( jj ) {
210 for ( int i = 1; i <= dim; i++ ) {
211 int ii = loc.at(i);
212 if ( ii ) {
213 this->at(ii, jj) += mat.at(i, j);
214 }
215 }
216 }
217 }
218
219 this->version++;
220
221 return 1;
222}
223
224int DynCompCol :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat)
225{
226#if 0
227 // slow and safe
228 this->checkSizeTowards(rloc, cloc);
229 int dim1 = mat.giveNumberOfRows();
230 int dim2 = mat.giveNumberOfColumns();
231 for (int i = 1 ; i <= dim1; i++) {
232 int ii = rloc.at(i);
233 if (ii)
234 for (j=1 ; j<= dim2; j++) {
235 int jj = cloc.at(j);
236 if (jj) this->at(ii,jj) += mat.at(i,j);
237 }
238 }
239 return 1;
240#endif
241
242 // optimized low-end implementation
243 IntArray rowsToAdd( rloc.giveSize() );
244 int rsize = rloc.giveSize();
245 int csize = cloc.giveSize();
246
247#if 0
248 // adjust the size of receiver
249 int maxid = 0;
250 for (int i = 0; i < rsize; i++) maxid = max(maxid, rloc[i]);
251 for (int i = 0; i < csize; i++) maxid = max(maxid, cloc[i]);
252 this->growTo(maxid);
253#endif
254
255 for ( int i = 0; i < csize; i++ ) {
256 int ii = cloc[i];
257 if ( ii ) {
258 int ii1 = ii - 1;
259 for ( int j = 0; j < rsize; j++ ) {
260 int jj = rloc[j];
261 if ( jj ) {
262 int jj1 = jj - 1;
263
264 int rowindx = this->insertRowInColumn(ii1, jj1);
265 columns[ ii1 ].at(rowindx) += mat(j, i);
266 }
267 }
268 }
269 }
270
271 this->version++;
272
273 return 1;
274}
275
276
277void DynCompCol :: zero()
278{
279 for ( auto &column : columns ) {
280 column.zero();
281 }
282
283 this->version++;
284}
285
286
287void DynCompCol :: printStatistics() const
288{
289 int nz_ = 0;
290 for ( auto &row : rowind ) {
291 nz_ += row.giveSize();
292 }
293
294 OOFEM_LOG_DEBUG("DynCompCol info: neq is %d, nelem is %d\n", nColumns, nz_);
295}
296
297
298double &DynCompCol :: at(int i, int j)
299{
300 this->version++;
301
302 int rowIndx = this->giveRowIndx(j - 1, i - 1);
303 if ( rowIndx ) {
304 return columns[ j - 1 ].at(rowIndx);
305 }
306
307 OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j);
308 return columns[ 0 ].at(1); // return to suppress compiler warning message
309}
310
311
312double DynCompCol :: at(int i, int j) const
313{
314 int rowIndx = this->giveRowIndx(j - 1, i - 1);
315 if ( rowIndx ) {
316 return columns[ j - 1 ].at(rowIndx);
317 }
318
319 if ( i <= nRows && j <= nColumns ) {
320 return 0.0;
321 } else {
322 OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j);
323 return columns[ 0 ].at(1); // return to suppress compiler warning message
324 }
325}
326
327double DynCompCol :: operator() (int i, int j) const
328{
329 int rowIndx;
330 if ( ( rowIndx = this->giveRowIndx(j, i) ) ) {
331 return columns[ j ].at(rowIndx);
332 }
333
334 if ( i < nRows && j < nColumns ) {
335 return 0.0;
336 } else {
337 OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j);
338 return columns[ 0 ].at(1); // return to suppress compiler warning message
339 }
340}
341
342double &DynCompCol :: operator() (int i, int j)
343{
344 this->version++;
345
346 int rowIndx = this->giveRowIndx(j, i);
347 if ( rowIndx ) {
348 return columns[ j ].at(rowIndx);
349 }
350
351 OOFEM_ERROR("Array element (%d,%d) not in sparse structure -- cannot assign", i, j);
352 return columns[ 0 ].at(1); // return to suppress compiler warning message
353}
354
355
356void DynCompCol :: timesT(const FloatArray &x, FloatArray &answer) const
357{
358 if ( x.giveSize() != nRows ) {
359 OOFEM_ERROR("Error in CompCol -- incompatible dimensions");
360 }
361 answer.resize(nColumns);
362 answer.zero();
363
364 for ( int i = 0; i < nColumns; i++ ) {
365 double r = 0.0;
366 for ( int t = 1; t <= columns[ i ].giveSize(); t++ ) {
367 r += columns[ i ].at(t) * x[ rowind[ i ].at(t) ];
368 }
369
370 answer[i] = r;
371 }
372}
373
374
375void DynCompCol :: checkSizeTowards(IntArray &loc)
376{
377 int maxid = 0;
378 int size = loc.giveSize();
379 // adjust the size of receiver
380 for ( int i = 0; i < size; i++ ) {
381 maxid = max( maxid, loc[i] );
382 }
383
384 this->growTo(maxid);
385
386 for ( int i = 0; i < size; i++ ) {
387 int ii = loc[i];
388 if ( ii ) {
389 for ( int j = 0; j < size; j++ ) {
390 int jj = loc[j];
391 if ( jj ) {
392 this->insertRowInColumn(ii - 1, jj - 1);
393 }
394 }
395 }
396 }
397}
398
399
400void DynCompCol :: checkSizeTowards(const IntArray &rloc, const IntArray &cloc)
401{
402 int maxid = 0;
403 int rsize = rloc.giveSize();
404 int csize = cloc.giveSize();
405
406 // adjust the size of receiver
407 for ( int i = 0; i < rsize; i++ ) {
408 maxid = max( maxid, rloc[i] );
409 }
410
411 for ( int i = 0; i < csize; i++ ) {
412 maxid = max( maxid, cloc[i] );
413 }
414
415 this->growTo(maxid);
416
417 IntArray rowsToAdd( rloc.giveSize() );
418
419 for ( int i = 0; i < csize; i++ ) {
420 int ii = cloc[i];
421 if ( ii ) {
422 for ( int j = 0; j < rsize; j++ ) {
423 int jj = rloc[j];
424 if ( jj ) {
425 insertRowInColumn(ii - 1, jj - 1);
426 }
427 }
428 }
429 }
430}
431
432
433
434void DynCompCol :: growTo(int ns)
435{
436 if ( ns > nColumns ) {
437 columns.resize(ns);
438 rowind.resize(ns);
439 nColumns = nRows = ns;
440 }
441}
442
443
444int DynCompCol :: giveRowIndx(int col, int row) const
445{
446 // fast row indx search, based on assumption, that row indices are sorted
447 int left = 1, right = this->rowind[ col ].giveSize();
448 int middle = ( left + right ) / 2;
449 int middleVal;
450
451 if ( right == 0 ) {
452 return 0;
453 }
454
455 if ( this->rowind[ col ].at(right) == row ) {
456 return right;
457 }
458
459 while ( !( ( ( middleVal = this->rowind[ col ].at(middle) ) == row ) || ( middle == left ) ) ) {
460 if ( row > middleVal ) {
461 left = middle;
462 } else {
463 right = middle;
464 }
465
466 middle = ( left + right ) / 2;
467 }
468
469 if ( middleVal == row ) {
470 return middle;
471 }
472
473 return 0;
474}
475
476
477int
478DynCompCol :: insertRowInColumn(int col, int row)
479{
480 // insert row into column, preserving order of row indexes.
481 int oldsize = this->rowind[ col ].giveSize();
482 int left = 1, right = oldsize;
483 int middle = ( left + right ) / 2;
484 int middleVal;
485
486 if ( oldsize == 0 ) {
487 rowind[ col ].resizeWithValues(1, DynCompCol_CHUNK);
488 columns[ col ].resizeWithValues(1, DynCompCol_CHUNK);
489 columns[ col ].at(1) = 0.0;
490 rowind[ col ].at(1) = row;
491 return 1;
492 }
493
494 if ( this->rowind[ col ].at(right) == row ) {
495 return right;
496 }
497
498 while ( !( ( ( middleVal = this->rowind[ col ].at(middle) ) == row ) || ( middle == left ) ) ) {
499 if ( row > middleVal ) {
500 left = middle;
501 } else {
502 right = middle;
503 }
504
505 middle = ( left + right ) / 2;
506 }
507
508 if ( middleVal == row ) {
509 return middle;
510 }
511
512 // we have to insert new row entry
513 if ( row > this->rowind[ col ].at(oldsize) ) {
514 right = oldsize + 1;
515 } else if ( row < this->rowind[ col ].at(1) ) {
516 right = 1;
517 }
518
519 // insert row at middle+1 position
520 rowind[ col ].resizeWithValues(oldsize + 1, DynCompCol_CHUNK);
521 columns[ col ].resizeWithValues(oldsize + 1, DynCompCol_CHUNK);
522
523 for ( int i = oldsize; i >= right; i-- ) {
524 rowind[ col ].at(i + 1) = rowind[ col ].at(i);
525 columns[ col ].at(i + 1) = columns[ col ].at(i);
526 }
527
528 columns[ col ].at(right) = 0.0;
529 rowind[ col ].at(right) = row;
530 return right;
531}
532
533} // 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
DynCompCol(int n=0)
Definition dyncompcol.C:54
std::vector< IntArray > rowind
Definition dyncompcol.h:61
std::vector< FloatArray > columns
Definition dyncompcol.h:60
int insertRowInColumn(int col, int row)
Insert row entry into column, preserving order of row indexes, returns the index of new row.
Definition dyncompcol.C:478
int giveRowIndx(int col, int row) const
Returns the row index of given row at given column, else returns zero.
Definition dyncompcol.C:444
double & at(int i, int j) override
Returns coefficient at position (i,j).
Definition dyncompcol.C:298
void checkSizeTowards(IntArray &)
Definition dyncompcol.C:375
const FloatArray & column(int i) const
Returns column values.
Definition dyncompcol.h:100
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
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
int giveNumberOfColumns() const
Returns number of columns of receiver.
int giveNumberOfRows() const
Returns number of rows of receiver.
double at(std::size_t i, std::size_t j) const
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
#define DynCompCol_CHUNK
Definition dyncompcol.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_DynCompCol
Dynamically growing compressed column.

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