OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
compcol.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 CompCol
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 sparse matrix (0-based) */
70 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
71 
72 #include "compcol.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 
86 CompCol :: CompCol(void) : SparseMtrx(), val_(0), rowind_(0), colptr_(0), base_(0), nz_(0)
87 {
88  dim_ [ 0 ] = 0;
89  dim_ [ 1 ] = 0;
90 }
91 
92 
93 CompCol :: CompCol(int n) : SparseMtrx(n, n), val_(0), rowind_(0), colptr_(n), base_(0), nz_(0)
94 {
95  dim_ [ 0 ] = n;
96  dim_ [ 1 ] = n;
97 }
98 
99 
100 /*****************************/
101 /* Copy constructor */
102 /*****************************/
103 
105  val_(S.val_), rowind_(S.rowind_), colptr_(S.colptr_),
106  base_(S.base_), nz_(S.nz_)
107 {
108  dim_ [ 0 ] = S.dim_ [ 0 ];
109  dim_ [ 1 ] = S.dim_ [ 1 ];
110  nRows = S.nRows;
111  nColumns = S.nColumns;
112 }
113 
114 
115 
116 /***************************/
117 /* Assignment operator... */
118 /***************************/
119 
121 {
122  dim_ [ 0 ] = C.dim_ [ 0 ];
123  dim_ [ 1 ] = C.dim_ [ 1 ];
124  nRows = C.nRows;
125  nColumns = C.nColumns;
126 
127  base_ = C.base_;
128  nz_ = C.nz_;
129  val_ = C.val_;
130  rowind_ = C.rowind_;
131  colptr_ = C.colptr_;
132  this->version = C.version;
133 
134  return * this;
135 }
136 
137 
138 
140 {
141  CompCol *result = new CompCol(*this);
142  return result;
143 }
144 
145 
146 void CompCol :: times(const FloatArray &x, FloatArray &answer) const
147 {
148  int M = dim_ [ 0 ];
149  int N = dim_ [ 1 ];
150 
151  // Check for compatible dimensions:
152  if ( x.giveSize() != N ) {
153  OOFEM_ERROR("incompatible dimensions");
154  }
155 
156  answer.resize(M);
157  answer.zero();
158 
159  for ( int j = 0; j < N; j++ ) {
160  double rhs = x(j);
161  for ( int t = colptr_(j); t < colptr_(j + 1); t++ ) {
162  answer( rowind_(t) ) += val_(t) * rhs;
163  }
164  }
165 }
166 
167 void CompCol :: times(double x)
168 {
169  val_.times(x);
170 
171  // increment version
172  this->version++;
173 }
174 
176 {
177  IntArray loc;
178  Domain *domain = eModel->giveDomain(di);
179  int neq = eModel->giveNumberOfDomainEquations(di, s);
180  int indx;
181  // allocation map
182  std :: vector< std :: set< int > > columns(neq);
183 
184  this->nz_ = 0;
185 
186  for ( auto &elem : domain->giveElements() ) {
187  elem->giveLocationArray(loc, s);
188 
189  for ( int ii : loc ) {
190  if ( ii > 0 ) {
191  for ( int jj : loc ) {
192  if ( jj > 0 ) {
193  columns [ jj - 1 ].insert(ii - 1);
194  }
195  }
196  }
197  }
198  }
199 
200 
201  // loop over active boundary conditions
202  std :: vector< IntArray >r_locs;
203  std :: vector< IntArray >c_locs;
204 
205  for ( auto &gbc : domain->giveBcs() ) {
206  ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() );
207  if ( bc != NULL ) {
208  bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s);
209  for ( std :: size_t k = 0; k < r_locs.size(); k++ ) {
210  IntArray &krloc = r_locs [ k ];
211  IntArray &kcloc = c_locs [ k ];
212  for ( int ii : krloc ) {
213  if ( ii ) {
214  for ( int jj : kcloc ) {
215  if ( jj ) {
216  columns [ jj - 1 ].insert(ii - 1);
217  }
218  }
219  }
220  }
221  }
222  }
223  }
224 
225  for ( int i = 0; i < neq; i++ ) {
226  this->nz_ += columns [ i ].size();
227  }
228 
229  rowind_.resize(nz_);
230  colptr_.resize(neq + 1);
231  indx = 0;
232 
233  for ( int j = 0; j < neq; j++ ) { // column loop
234  colptr_(j) = indx;
235  for ( int row: columns [ j ] ) { // row loop
236  rowind_(indx++) = row;
237  }
238  }
239 
240  colptr_(neq) = indx;
241 
242  // allocate value array
243  val_.resize(nz_);
244  val_.zero();
245 
246  OOFEM_LOG_DEBUG("CompCol info: neq is %d, nwk is %d\n", neq, nz_);
247 
248  dim_ [ 0 ] = dim_ [ 1 ] = nColumns = nRows = neq;
249 
250  // increment version
251  this->version++;
252 
253  return true;
254 }
255 
256 
257 int CompCol :: assemble(const IntArray &loc, const FloatMatrix &mat)
258 {
259  int dim = mat.giveNumberOfRows();
260 
261 # ifdef DEBUG
262  if ( dim != loc.giveSize() ) {
263  OOFEM_ERROR("dimension of 'k' and 'loc' mismatch");
264  }
265 # endif
266 
267  for ( int j = 0; j < dim; j++ ) {
268  int jj = loc[j];
269  if ( jj ) {
270  int cstart = colptr_[jj - 1];
271  int t = cstart;
272  int last_ii = this->nRows + 1; // Ensures that t is set correctly the first time.
273  for ( int i = 0; i < dim; i++ ) {
274  int ii = loc[i];
275  if ( ii ) {
276  // Some heuristics that speed up most cases ( benifits are large for incremental sub-blocks, e.g. locs = [123, 124, 125, 245, 246, 247] ):
277  if ( ii < last_ii )
278  t = cstart;
279  else if ( ii > last_ii )
280  t++;
281  for ( ; rowind_[t] < ii - 1; t++ ) {
282 # ifdef DEBUG
283  if ( t >= colptr_[jj] )
284  OOFEM_ERROR("Couldn't find row %d in the sparse structure", ii);
285 # endif
286  }
287  val_[t] += mat(i, j);
288  last_ii = ii;
289  }
290  }
291  }
292  }
293 
294  // increment version
295  this->version++;
296 
297  return 1;
298 }
299 
300 int CompCol :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat)
301 {
302  int dim1, dim2;
303 
304  dim1 = mat.giveNumberOfRows();
305  dim2 = mat.giveNumberOfColumns();
306 
307  for ( int j = 0; j < dim2; j++ ) {
308  int jj = cloc[j];
309  if ( jj ) {
310  int cstart = colptr_[jj - 1];
311  int t = cstart;
312  int last_ii = this->nRows + 1; // Ensures that t is set correctly the first time.
313  for ( int i = 0; i < dim1; i++ ) {
314  int ii = rloc[i];
315  if ( ii ) {
316  // Some heuristics that speed up most cases ( benifits are large for incremental sub-blocks, e.g. locs = [123, 124, 125, 245, 246, 247] ):
317  if ( ii < last_ii )
318  t = cstart;
319  else if ( ii > last_ii )
320  t++;
321  for ( ; rowind_[t] < ii - 1; t++ ) {
322 # ifdef DEBUG
323  if ( t >= colptr_[jj] )
324  OOFEM_ERROR("Couldn't find row %d in the sparse structure", ii);
325 # endif
326  }
327  val_[t] += mat(i, j);
328  last_ii = ii;
329  }
330  }
331  }
332  }
333 
334  // increment version
335  this->version++;
336 
337  return 1;
338 }
339 
341 {
342  val_.zero();
343 
344  // increment version
345  this->version++;
346 }
347 
348 
350 { }
351 
353 { }
354 
355 /*********************/
356 /* Array access */
357 /*********************/
358 
359 double &CompCol :: at(int i, int j)
360 {
361  // increment version
362  this->version++;
363 
364  for ( int t = colptr_(j - 1); t < colptr_(j); t++ ) {
365  if ( rowind_(t) == i - 1 ) {
366  return val_(t);
367  }
368  }
369 
370  OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j);
371  return val_(0); // return to suppress compiler warning message
372 }
373 
374 
375 double CompCol :: at(int i, int j) const
376 {
377  for ( int t = colptr_(j - 1); t < colptr_(j); t++ ) {
378  if ( rowind_(t) == i - 1 ) {
379  return val_(t);
380  }
381  }
382 
383  if ( i <= dim_ [ 0 ] && j <= dim_ [ 1 ] ) {
384  return 0.0;
385  } else {
386  OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j);
387  return ( 0 ); // return to suppress compiler warning message
388  }
389 }
390 
391 double CompCol :: operator() (int i, int j) const
392 {
393  for ( int t = colptr_(j); t < colptr_(j + 1); t++ ) {
394  if ( rowind_(t) == i ) {
395  return val_(t);
396  }
397  }
398 
399  if ( i < dim_ [ 0 ] && j < dim_ [ 1 ] ) {
400  return 0.0;
401  } else {
402  OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j);
403  return ( 0 ); // return to suppress compiler warning message
404  }
405 }
406 
407 double &CompCol :: operator() (int i, int j)
408 {
409  // increment version
410  this->version++;
411 
412  for ( int t = colptr_(j); t < colptr_(j + 1); t++ ) {
413  if ( rowind_(t) == i ) {
414  return val_(t);
415  }
416  }
417 
418  OOFEM_ERROR("Array element (%d,%d) not in sparse structure -- cannot assign", i, j);
419  return val_(0); // return to suppress compiler warning message
420 }
421 
422 void CompCol :: timesT(const FloatArray &x, FloatArray &answer) const
423 {
424  int M = dim_ [ 0 ];
425  int N = dim_ [ 1 ];
426 
427  // Check for compatible dimensions:
428  if ( x.giveSize() != M ) {
429  OOFEM_ERROR("Error in CompCol -- incompatible dimensions");
430  }
431 
432  answer.resize(N);
433  answer.zero();
434 
435  for ( int i = 0; i < N; i++ ) {
436  double r = 0.0;
437  for ( int t = colptr_(i); t < colptr_(i + 1); t++ ) {
438  r += val_(t) * x( rowind_(t) );
439  }
440 
441  answer(i) = r;
442  }
443 }
444 } // 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
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
virtual int assemble(const IntArray &loc, const FloatMatrix &mat)
Assembles sparse matrix from contribution of local elements.
Definition: compcol.C:257
SparseMtrx * GiveCopy() const
Returns a newly allocated copy of receiver.
Definition: compcol.C:139
virtual void timesT(const FloatArray &x, FloatArray &answer) const
Evaluates .
Definition: compcol.C:422
Compressed column.
#define S(p)
Definition: mdm.C:481
virtual void toFloatMatrix(FloatMatrix &answer) const
Converts receiving sparse matrix to a dense float matrix.
Definition: compcol.C:349
double operator()(int i, int j) const
implements 0-based access
Definition: compcol.C:391
#define OOFEM_LOG_DEBUG(...)
Definition: logger.h:128
Class implementing an array of integers.
Definition: intarray.h:61
virtual double & at(int i, int j)
Returns coefficient at position (i,j).
Definition: compcol.C:359
int nRows
Number of rows.
Definition: sparsemtrx.h:67
std::vector< std::unique_ptr< GeneralBoundaryCondition > > & giveBcs()
Definition: domain.h:322
virtual void zero()
Zeroes the receiver.
Definition: compcol.C:340
#define OOFEM_ERROR(...)
Definition: error.h:61
REGISTER_SparseMtrx(CompCol, SMT_CompCol)
Abstract base class allowing to control the way, how equations are assigned to individual DOFs...
int dim(int i) const
Definition: compcol.h:141
#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
IntArray rowind_
Definition: compcol.h:89
SparseMtrxVersionType version
Allows to track if receiver changes.
Definition: sparsemtrx.h:80
virtual int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &s)
Builds internal structure of receiver.
Definition: compcol.C:175
Class representing vector of real numbers.
Definition: floatarray.h:82
virtual void times(const FloatArray &x, FloatArray &answer) const
Evaluates .
Definition: compcol.C:146
CompCol()
Constructor.
Definition: compcol.C:86
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
virtual void printYourself() const
Prints receiver to stdout. Works only for relatively small matrices.
Definition: compcol.C:352
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
CompCol & operator=(const CompCol &C)
Assignment operator.
Definition: compcol.C:120
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.
Domain * giveDomain(int n)
Service for accessing particular problem domain.
Definition: engngm.C:1720
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
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:27 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011