OOFEM 3.0
Loading...
Searching...
No Matches
symcompcol.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
36/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
37/* ******** *** SparseLib++ */
38/* ******* ** *** *** *** v. 1.5c */
39/* ***** *** ******** ******** */
40/* ***** *** ******** ******** R. Pozo */
41/* ** ******* *** ** *** *** K. Remington */
42/* ******** ******** A. Lumsdaine */
43/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
44/* */
45/* */
46/* SparseLib++ : Sparse Matrix Library */
47/* */
48/* National Institute of Standards and Technology */
49/* University of Notre Dame */
50/* Authors: R. Pozo, K. Remington, A. Lumsdaine */
51/* */
52/* NOTICE */
53/* */
54/* Permission to use, copy, modify, and distribute this software and */
55/* its documentation for any purpose and without fee is hereby granted */
56/* provided that the above notice appear in all copies and supporting */
57/* documentation. */
58/* */
59/* Neither the Institutions (National Institute of Standards and Technology, */
60/* University of Notre Dame) nor the Authors make any representations about */
61/* the suitability of this software for any purpose. This software is */
62/* provided ``as is'' without expressed or implied warranty. */
63/* */
64/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
65
66#include "symcompcol.h"
67#include "floatarray.h"
68#include "engngm.h"
69#include "domain.h"
70#include "element.h"
71#include "sparsemtrxtype.h"
72#include "activebc.h"
73#include "classfactory.h"
74#ifdef __MPM_MODULE
75#include "../mpm/integral.h"
76#endif
77
78#include <set>
79
80namespace oofem {
82
83
84SymCompCol :: SymCompCol(int n) : CompCol(n)
85{ }
86
87
88SymCompCol :: SymCompCol(const SymCompCol &S) : CompCol(S)
89{ }
90
91
92std::unique_ptr<SparseMtrx> SymCompCol :: clone() const
93{
94 return std::make_unique<SymCompCol>(*this);
95}
96
97
98int SymCompCol :: buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s)
99{
100 IntArray loc;
101 Domain *domain = eModel->giveDomain(di);
102 int neq = eModel->giveNumberOfDomainEquations(di, s);
103 int indx;
104 // allocation map
105 std :: vector< std :: set< int > > columns(neq);
106
107 this->nz = 0;
108
109 for ( auto &elem : domain->giveElements() ) {
110 elem->giveLocationArray(loc, s);
111
112 for ( int ii : loc ) {
113 if ( ii > 0 ) {
114 for ( int jj : loc ) {
115 if ( jj > 0 && ii >= jj ) {
116 columns [ jj - 1 ].insert(ii - 1);
117 }
118 }
119 }
120 }
121 }
122
123 // loop over active boundary conditions
124 std :: vector< IntArray >r_locs;
125 std :: vector< IntArray >c_locs;
126
127 for ( auto &gbc : domain->giveBcs() ) {
128 ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() );
129 if ( bc ) {
130 bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s);
131 for ( std :: size_t k = 0; k < r_locs.size(); k++ ) {
132 IntArray &krloc = r_locs [ k ];
133 IntArray &kcloc = c_locs [ k ];
134 for ( int ii : krloc ) {
135 if ( ii > 0 ) {
136 for ( int jj : kcloc ) {
137 if ( jj > 0 && ii >= jj ) {
138 columns [ jj - 1 ].insert(ii - 1);
139 }
140 }
141 }
142 }
143 }
144 }
145 }
146
147#ifdef __MPM_MODULE
148 IntArray locr, locc;
149 // loop over integrals
150 for (auto &in: eModel->giveIntegralList()) {
151 // loop over integral domain
152 for (auto &elem: in->set->giveElementList()) {
153 // get code numbers for integral.term on element
154 in->getElementTermCodeNumbers (locr, locc, domain->giveElement(elem), *in->term, s) ;
155 for ( int ii : locr ) {
156 if ( ii > 0 ) {
157 for ( int jj : locc ) {
158 if ( jj > 0 && ii >= jj ) {
159 columns [ jj - 1 ].insert(ii - 1);
160 }
161 }
162 }
163 }
164 }
165 }
166#endif
167
168
169 for ( auto &val : columns ) {
170 this->nz += val.size();
171 }
172
173 rowind.resize(nz);
174 colptr.resize(neq + 1);
175 indx = 0;
176
177 for ( int j = 0; j < neq; j++ ) {
178 colptr[j] = indx;
179 for ( int row: columns [ j ] ) {
180 rowind[indx++] = row;
181 }
182 }
183
184 colptr[neq] = indx;
185
186 // allocate value array
187 val.resize(nz);
188 val.zero();
189
190 OOFEM_LOG_INFO("SymCompCol info: neq is %d, nwk is %d\n", neq, nz);
191
192 nColumns = nRows = neq;
193
194 this->version++;
195
196 return true;
197}
198
199
200
201void SymCompCol :: times(const FloatArray &x, FloatArray &answer) const
202{
203#if DEBUG
204 if ( x.giveSize() != this->giveNumberOfColumns() ) {
205 OOFEM_ERROR("incompatible dimensions");
206 }
207#endif
208
209 answer.resize(this->giveNumberOfRows());
210 answer.zero();
211
212 for ( int j = 0; j < this->giveNumberOfColumns(); j++ ) {
213 double rhs = x[j];
214 double sum = 0.0;
215 for ( int t = colptr[j] + 1; t < colptr[j + 1]; t++ ) {
216 answer[ rowind[t] ] += val[t] * rhs; // column loop
217 sum += val[t] * x[ rowind[t] ]; // row loop
218 }
219
220 answer[j] += sum + val[ colptr[j] ] * rhs; // include diagonal
221 }
222}
223
224void SymCompCol :: times(double x)
225{
226 val.times(x);
227
228 this->version++;
229}
230
231
232int SymCompCol :: assemble(const IntArray &loc, const FloatMatrix &mat)
233{
234 int dim = mat.giveNumberOfRows();
235
236# ifdef DEBUG
237 if ( dim != loc.giveSize() ) {
238 OOFEM_ERROR("dimension of 'k' and 'loc' mismatch");
239 }
240# endif
241
242 for ( int j = 0; j < dim; j++ ) {
243 int jj = loc[j];
244 if ( jj ) {
245 int cstart = colptr[jj - 1];
246 int t = cstart;
247 int last_ii = this->nRows + 1; // Ensures that t is set correctly the first time.
248 for ( int i = 0; i < dim; i++ ) {
249 int ii = loc[i];
250 if ( ii >= jj ) { // assemble only lower triangular part
251 // Some heuristics that speed up most cases ( benifits are large for incremental sub-blocks, e.g. locs = [123, 124, 125, 245, 246, 247] ):
252 if ( ii < last_ii )
253 t = cstart;
254 else if ( ii > last_ii )
255 t++;
256 for ( ; rowind[t] < ii - 1; t++ ) {
257# ifdef DEBUG
258 if ( t >= colptr[jj] )
259 OOFEM_ERROR("Couldn't find row %d in the sparse structure", ii);
260# endif
261 }
262 val[t] += mat(i, j);
263 last_ii = ii;
264 }
265 }
266 }
267 }
268
269 this->version++;
270
271 return 1;
272}
273
274
275int SymCompCol :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat)
276{
277 int dim1 = mat.giveNumberOfRows();
278 int dim2 = mat.giveNumberOfColumns();
279
280 for ( int j = 0; j < dim2; j++ ) {
281 int jj = cloc[j];
282 if ( jj ) {
283 int cstart = colptr[jj - 1];
284 int t = cstart;
285 int last_ii = this->nRows + 1; // Ensures that t is set correctly the first time.
286 for ( int i = 0; i < dim1; i++ ) {
287 int ii = rloc[i];
288 if ( ii >= jj ) { // assemble only lower triangular part
289 // Some heuristics that speed up most cases ( benifits are large for incremental sub-blocks, e.g. locs = [123, 124, 125, 245, 246, 247] ):
290 if ( ii < last_ii )
291 t = cstart;
292 else if ( ii > last_ii )
293 t++;
294 for ( ; rowind[t] < ii - 1; t++ ) {
295# ifdef DEBUG
296 if ( t >= colptr[jj] )
297 OOFEM_ERROR("Couldn't find row %d in the sparse structure", ii);
298# endif
299 }
300 val[t] += mat(i, j);
301 last_ii = ii;
302 }
303 }
304 }
305 }
306
307 this->version++;
308
309 return 1;
310}
311
312
313void SymCompCol :: zero()
314{
315 val.zero();
316
317 this->version++;
318}
319
320
321double &SymCompCol :: at(int i, int j)
322{
323 if ( i < j ) {
324 std::swap(i, j);
325 }
326
327 this->version++;
328
329 for ( int t = colptr[j - 1]; t < colptr[j]; t++ ) {
330 if ( rowind[t] == ( i - 1 ) ) {
331 return val[t];
332 }
333 }
334
335 OOFEM_ERROR("Array accessing exception -- out of bounds");
336}
337
338
339double SymCompCol :: at(int i, int j) const
340{
341 if ( i < j ) {
342 std::swap(i, j);
343 }
344
345 for ( int t = colptr[j - 1]; t < colptr[j]; t++ ) {
346 if ( rowind[t] == ( i - 1 ) ) {
347 return val[t];
348 }
349 }
350
351 if ( i <= this->giveNumberOfColumns() && j <= this->giveNumberOfRows() ) {
352 return 0.0;
353 } else {
354 OOFEM_ERROR("Array accessing exception -- index out of bounds (%d,%d)", i, j);
355 }
356}
357
358double SymCompCol :: operator() (int i, int j) const
359{
360 if ( i < j ) {
361 std::swap(i, j);
362 }
363
364 for ( int t = colptr[j]; t < colptr[j + 1]; t++ ) {
365 if ( rowind[t] == i ) {
366 return val[t];
367 }
368 }
369
370 if ( i < this->giveNumberOfColumns() && j < this->giveNumberOfRows() ) {
371 return 0.0;
372 } else {
373 OOFEM_ERROR("Array accessing exception, index out of bounds (%d,%d)", i, j);
374 }
375}
376
377double &SymCompCol :: operator() (int i, int j)
378{
379 if ( i < j ) {
380 std::swap(i, j);
381 }
382
383 this->version++;
384
385 for ( int t = colptr[j]; t < colptr[j + 1]; t++ ) {
386 if ( rowind[t] == i ) {
387 return val[t];
388 }
389 }
390
391 OOFEM_ERROR("Array element (%d,%d) not in sparse structure -- cannot assign", i, j);
392}
393} // 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
FloatArray val
Definition compcol.h:88
CompCol(int n=0)
Definition compcol.C:88
IntArray colptr
Definition compcol.h:90
IntArray rowind
Definition compcol.h:89
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
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.
int giveSize() const
Definition intarray.h:211
int nColumns
Number of columns.
Definition sparsemtrx.h:71
SparseMtrxVersionType version
Definition sparsemtrx.h:82
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
int nRows
Number of rows.
Definition sparsemtrx.h:69
SymCompCol(int n=0)
Definition symcompcol.C:84
#define OOFEM_ERROR(...)
Definition error.h:79
#define OOFEM_LOG_INFO(...)
Definition logger.h:143
#define S(p)
Definition mdm.C:469
double sum(const FloatArray &x)
@ SMT_SymCompCol
Symmetric 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