OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
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 - 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 
35 // Class SymCompCol
36 
37 // inspired by
38 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
39 /* ******** *** SparseLib++ */
40 /* ******* ** *** *** *** v. 1.5c */
41 /* ***** *** ******** ******** */
42 /* ***** *** ******** ******** R. Pozo */
43 /* ** ******* *** ** *** *** K. Remington */
44 /* ******** ******** A. Lumsdaine */
45 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
46 /* */
47 /* */
48 /* SparseLib++ : Sparse Matrix Library */
49 /* */
50 /* National Institute of Standards and Technology */
51 /* University of Notre Dame */
52 /* Authors: R. Pozo, K. Remington, A. Lumsdaine */
53 /* */
54 /* NOTICE */
55 /* */
56 /* Permission to use, copy, modify, and distribute this software and */
57 /* its documentation for any purpose and without fee is hereby granted */
58 /* provided that the above notice appear in all copies and supporting */
59 /* documentation. */
60 /* */
61 /* Neither the Institutions (National Institute of Standards and Technology, */
62 /* University of Notre Dame) nor the Authors make any representations about */
63 /* the suitability of this software for any purpose. This software is */
64 /* provided ``as is'' without expressed or implied warranty. */
65 /* */
66 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
67 
68 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
69 /* Compressed column symmetric sparse matrix (0-based) */
70 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
71 
72 #include "symcompcol.h"
73 #include "floatarray.h"
74 #include "engngm.h"
75 #include "domain.h"
76 #include "element.h"
77 #include "sparsemtrxtype.h"
78 #include "activebc.h"
79 #include "classfactory.h"
80 
81 #include <set>
82 
83 namespace oofem {
85 
87 { }
88 
89 
91 { }
92 
93 
94 /*****************************/
95 /* Copy constructor */
96 /*****************************/
97 
99 { }
100 
101 
103 {
104  SymCompCol *result = new SymCompCol(*this);
105  return result;
106 }
107 
108 
109 #define MAP(i, j) map [ ( j ) * neq - ( j ) * ( ( j ) + 1 ) / 2 + ( i ) ]
110 
112 {
113  IntArray loc;
114  Domain *domain = eModel->giveDomain(di);
115  int neq = eModel->giveNumberOfDomainEquations(di, s);
116  int indx;
117  // allocation map
118  std :: vector< std :: set< int > > columns(neq);
119 
120  this->nz_ = 0;
121 
122  for ( auto &elem : domain->giveElements() ) {
123  elem->giveLocationArray(loc, s);
124 
125  for ( int ii : loc ) {
126  if ( ii > 0 ) {
127  for ( int jj : loc ) {
128  if ( jj > 0 && ii >= jj ) {
129  columns [ jj - 1 ].insert(ii - 1);
130  }
131  }
132  }
133  }
134  }
135 
136  // loop over active boundary conditions
137  std :: vector< IntArray >r_locs;
138  std :: vector< IntArray >c_locs;
139 
140  for ( auto &gbc : domain->giveBcs() ) {
141  ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() );
142  if ( bc != NULL ) {
143  bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s);
144  for ( std :: size_t k = 0; k < r_locs.size(); k++ ) {
145  IntArray &krloc = r_locs [ k ];
146  IntArray &kcloc = c_locs [ k ];
147  for ( int ii : krloc ) {
148  if ( ii > 0 ) {
149  for ( int jj : kcloc ) {
150  if ( jj > 0 && ii >= jj ) {
151  columns [ jj - 1 ].insert(ii - 1);
152  }
153  }
154  }
155  }
156  }
157  }
158  }
159 
160 
161 
162  for ( auto &val : columns ) {
163  this->nz_ += val.size();
164  }
165 
166  rowind_.resize(nz_);
167  colptr_.resize(neq + 1);
168  indx = 0;
169 
170  for ( int j = 0; j < neq; j++ ) { // column loop
171  colptr_(j) = indx;
172  for ( int row: columns [ j ] ) { // row loop
173  rowind_(indx++) = row;
174  }
175  }
176 
177  colptr_(neq) = indx;
178 
179  // allocate value array
180  val_.resize(nz_);
181  val_.zero();
182 
183  OOFEM_LOG_INFO("SymCompCol info: neq is %d, nwk is %d\n", neq, nz_);
184 
185  dim_ [ 0 ] = dim_ [ 1 ] = nColumns = nRows = neq;
186 
187  // increment version
188  this->version++;
189 
190  return true;
191 }
192 
193 
194 
195 void SymCompCol :: times(const FloatArray &x, FloatArray &answer) const
196 {
197  int M = dim_ [ 0 ];
198  int N = dim_ [ 1 ];
199 
200 #if DEBUG
201  if ( x.giveSize() != N ) {
202  OOFEM_ERROR("incompatible dimensions");
203  }
204 #endif
205 
206  answer.resize(M);
207  answer.zero();
208 
209  for ( int j = 0; j < N; j++ ) {
210  double rhs = x(j);
211  double sum = 0.0;
212  for ( int t = colptr_(j) + 1; t < colptr_(j + 1); t++ ) {
213  answer( rowind_(t) ) += val_(t) * rhs; // column loop
214  sum += val_(t) * x( rowind_(t) ); // row loop
215  }
216 
217  answer(j) += sum;
218  answer(j) += val_( colptr_(j) ) * rhs; // diagonal
219  }
220 }
221 
222 void SymCompCol :: times(double x)
223 {
224  val_.times(x);
225 
226  // increment version
227  this->version++;
228 }
229 
230 
231 
232 int 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  // increment version
270  this->version++;
271 
272  return 1;
273 }
274 
275 int SymCompCol :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat)
276 {
277  int dim1, dim2;
278 
279  dim1 = mat.giveNumberOfRows();
280  dim2 = mat.giveNumberOfColumns();
281 
282  for ( int j = 0; j < dim2; j++ ) {
283  int jj = cloc[j];
284  if ( jj ) {
285  int cstart = colptr_[jj - 1];
286  int t = cstart;
287  int last_ii = this->nRows + 1; // Ensures that t is set correctly the first time.
288  for ( int i = 0; i < dim1; i++ ) {
289  int ii = rloc[i];
290  if ( ii >= jj ) { // assemble only lower triangular part
291  // Some heuristics that speed up most cases ( benifits are large for incremental sub-blocks, e.g. locs = [123, 124, 125, 245, 246, 247] ):
292  if ( ii < last_ii )
293  t = cstart;
294  else if ( ii > last_ii )
295  t++;
296  for ( ; rowind_[t] < ii - 1; t++ ) {
297 # ifdef DEBUG
298  if ( t >= colptr_[jj] )
299  OOFEM_ERROR("Couldn't find row %d in the sparse structure", ii);
300 # endif
301  }
302  val_[t] += mat(i, j);
303  last_ii = ii;
304  }
305  }
306  }
307  }
308 
309  // increment version
310  this->version++;
311 
312  return 1;
313 }
314 
316 {
317  val_.zero();
318 
319  // increment version
320  this->version++;
321 }
322 
323 /*********************/
324 /* Array access */
325 /*********************/
326 
327 double &SymCompCol :: at(int i, int j)
328 {
329  int ii = i, jj = j;
330  if ( ii < jj ) {
331  ii = j;
332  jj = i;
333  }
334 
335  // increment version
336  this->version++;
337 
338  for ( int t = colptr_(jj - 1); t < colptr_(jj); t++ ) {
339  if ( rowind_(t) == ( ii - 1 ) ) {
340  return val_(t);
341  }
342  }
343 
344  OOFEM_ERROR("Array accessing exception -- out of bounds");
345  return val_(0); // return to suppress compiler warning message
346 }
347 
348 
349 double SymCompCol :: at(int i, int j) const
350 {
351  int ii = i, jj = j;
352  if ( ii < jj ) {
353  ii = j;
354  jj = i;
355  }
356 
357  for ( int t = colptr_(jj - 1); t < colptr_(jj); t++ ) {
358  if ( rowind_(t) == ( ii - 1 ) ) {
359  return val_(t);
360  }
361  }
362 
363  if ( i <= dim_ [ 0 ] && j <= dim_ [ 1 ] ) {
364  return 0.0;
365  } else {
366  OOFEM_ERROR("Array accessing exception -- index out of bounds (%d,%d)", i, j);
367  return ( 0 ); // return to suppress compiler warning message
368  }
369 }
370 
371 double SymCompCol :: operator() (int i, int j) const
372 {
373  int ii = i, jj = j;
374  if ( ii < jj ) {
375  ii = j;
376  jj = i;
377  }
378 
379  for ( int t = colptr_(jj); t < colptr_(jj + 1); t++ ) {
380  if ( rowind_(t) == ii ) {
381  return val_(t);
382  }
383  }
384 
385  if ( i < dim_ [ 0 ] && j < dim_ [ 1 ] ) {
386  return 0.0;
387  } else {
388  OOFEM_ERROR("Array accessing exception, index out of bounds (%d,%d)", i, j);
389  return ( 0 ); // return to suppress compiler warning message
390  }
391 }
392 
393 double &SymCompCol :: operator() (int i, int j)
394 {
395  int ii = i, jj = j;
396  if ( ii < jj ) {
397  ii = j;
398  jj = i;
399  }
400 
401  // increment version
402  this->version++;
403 
404  for ( int t = colptr_(jj); t < colptr_(jj + 1); t++ ) {
405  if ( rowind_(t) == ii ) {
406  return val_(t);
407  }
408  }
409 
410  OOFEM_ERROR("Array element (%d,%d) not in sparse structure -- cannot assign", i, j);
411  return val_(0); // return to suppress compiler warning message
412 }
413 } // end namespace oofem
int dim_[2]
Definition: compcol.h:94
int giveNumberOfColumns() const
Returns number of columns of receiver.
Definition: floatmatrix.h:158
int nColumns
Number of columns.
Definition: sparsemtrx.h:69
virtual int assemble(const IntArray &loc, const FloatMatrix &mat)
Assembles sparse matrix from contribution of local elements.
Definition: symcompcol.C:232
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
SymCompCol()
Constructor.
Definition: symcompcol.C:86
virtual void times(const FloatArray &x, FloatArray &answer) const
Evaluates .
Definition: symcompcol.C:195
double operator()(int i, int j) const
implements 0-based access
Definition: symcompcol.C:371
#define S(p)
Definition: mdm.C:481
Class implementing an array of integers.
Definition: intarray.h:61
int nRows
Number of rows.
Definition: sparsemtrx.h:67
std::vector< std::unique_ptr< GeneralBoundaryCondition > > & giveBcs()
Definition: domain.h:322
#define OOFEM_LOG_INFO(...)
Definition: logger.h:127
const double & val(int i) const
Definition: symcompcol.h:119
#define OOFEM_ERROR(...)
Definition: error.h:61
REGISTER_SparseMtrx(CompCol, SMT_CompCol)
Symmetric compressed column.
virtual double & at(int i, int j)
Returns coefficient at position (i,j).
Definition: symcompcol.C:327
Abstract base class allowing to control the way, how equations are assigned to individual DOFs...
virtual int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &)
Builds internal structure of receiver.
Definition: symcompcol.C:111
#define N(p, q)
Definition: mdm.C:367
Abstract base class for all active boundary conditions.
Definition: activebc.h:63
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
Implementation of symmetric sparse matrix stored using compressed column/row storage.
Definition: symcompcol.h:81
IntArray rowind_
Definition: compcol.h:89
SparseMtrxVersionType version
Allows to track if receiver changes.
Definition: sparsemtrx.h:80
Class representing vector of real numbers.
Definition: floatarray.h:82
Implementation of matrix containing floating point numbers.
Definition: floatmatrix.h:94
void zero()
Zeroes all coefficients of receiver.
Definition: floatarray.C:658
void times(double s)
Multiplies receiver with scalar.
Definition: floatarray.C:818
std::vector< std::unique_ptr< Element > > & giveElements()
Definition: domain.h:279
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
int giveSize() const
Definition: intarray.h:203
IntArray colptr_
Definition: compcol.h:90
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.
virtual SparseMtrx * GiveCopy() const
Returns a newly allocated copy of receiver.
Definition: symcompcol.C:102
Domain * giveDomain(int n)
Service for accessing particular problem domain.
Definition: engngm.C:1720
virtual void zero()
Zeroes the receiver.
Definition: symcompcol.C:315
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition: floatmatrix.h:156
FloatArray val_
Definition: compcol.h:88
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
int dim(int i) const
Definition: symcompcol.h:122
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:31 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011