OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
floatmatrix.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  * The original idea for this class comes from
36  * Dubois-Pelerin, Y.: "Object-Oriented Finite Elements: Programming concepts and Implementation",
37  * PhD Thesis, EPFL, Lausanne, 1992.
38  */
39 
40 #include "floatmatrix.h"
41 #include "floatarray.h"
42 #include "intarray.h"
43 #include "mathfem.h"
44 #include "error.h"
45 #include "datastream.h"
46 
47 #include <cstdio>
48 #include <cstdlib>
49 #include <cstring>
50 #include <ostream>
51 #include <iostream>
52 #include <fstream>
53 #include <iomanip>
54 #include <numeric>
55 #define RESIZE(nr, nc) \
56  { \
57  this->nRows = nr; this->nColumns = nc; \
58  int nsize = this->nRows * this->nColumns; \
59  if ( nsize < ( int ) this->values.size() ) { \
60  this->values.resize(nsize); \
61  } else if ( nsize > ( int ) this->values.size() ) { \
62  this->values.assign(nsize, 0.); \
63  } \
64  }
65 
66 #ifdef BOOST_PYTHON
67  #include <boost/python.hpp>
68  #include <boost/python/extract.hpp>
69 #endif
70 
71 // Some forward declarations for LAPACK. Remember to append the underscore to the function name.
72 #ifdef __LAPACK_MODULE
73 extern "C" {
75 extern void dgecon_(const char *norm, const int *n, const double *a, const int *lda,
76  const double *anorm, double *rcond, double *work, int *iwork, int *info, int norm_len);
78 extern int dgetrf_(const int *m, const int *n, double *a, const int *lda, int *lpiv, int *info);
80 extern int dgetri_(const int *n, double *a, const int *lda, int *ipiv, double *work, const int *lwork, int *info);
82 extern int dgesv_(const int *n, const int *nrhs, double *a, const int *lda, int *ipiv, const double *b, const int *ldb, int *info);
84 extern double dlange_(const char *norm, const int *m, const int *n, const double *a, const int *lda, double *work, int norm_len);
86 extern int dsyevx_(const char *jobz, const char *range, const char *uplo, const int *n, double *a, const int *lda,
87  const double *vl, const double *vu, const int *il, const int *iu,
88  const double *abstol, int *m, double *w, double *z, const int *ldz,
89  double *work, int *lwork, int *iwork, int *ifail, int *info,
90  int jobz_len, int range_len, int uplo_len);
92 extern void dgetrs_(const char *trans, const int *n, const int *nrhs, double *a, const int *lda, int *ipiv, const double *b, const int *ldb, int *info);
94 extern void dgemm_(const char *transa, const char *transb, const int *m, const int *n, const int *k, const double *alpha,
95  const double *a, const int *lda, const double *b, const int *ldb, const double *beta, double *c, const int *ldc,
96  int a_columns, int b_columns, int c_columns);
98 extern void dger_(const int *m, const int *n, const double *alpha, const double *x, const int *incx,
99  const double *y, const int *incy, double *a, const int *lda,
100  int x_len, int y_len, int a_columns);
102 extern void dsyr_(const char *uplo, const int *n, const double *alpha, const double *x, const int *incx,
103  double *a, const int *lda, int x_len, int a_columns);
105 extern void daxpy_(const int *n, const double *alpha, const double *x, const int *incx, double *y, const int *incy, int xsize, int ysize);
107 extern void dscal_(const int *n, const double *alpha, const double *x, const int *incx, int size);
108 }
109 #endif
110 
111 
112 namespace oofem {
113 FloatMatrix :: FloatMatrix(const FloatArray &vector, bool transpose)
114 //
115 // constructor : creates (vector->giveSize(),1) FloatMatrix
116 // if transpose = 1 creates (1,vector->giveSize()) FloatMatrix
117 //
118 {
119  if ( transpose ) {
120  nRows = 1; // column vector
121  nColumns = vector.giveSize();
122  } else {
123  nRows = vector.giveSize(); // row vector- default
124  nColumns = 1;
125  }
126 
127  values = vector.values;
128 }
129 
130 
131 FloatMatrix :: FloatMatrix(std :: initializer_list< std :: initializer_list< double > >mat)
132 {
133  RESIZE( mat.size(), mat.begin()->size() )
134  auto p = this->values.begin();
135  for ( auto col : mat ) {
136 #if DEBUG
137  if ( this->nRows != ( int ) col.size() ) {
138  OOFEM_ERROR("Initializer list has inconsistent column sizes.");
139  }
140 #endif
141  for ( auto x : col ) {
142  * p = x;
143  p++;
144  }
145  }
146 }
147 
148 
149 FloatMatrix &FloatMatrix :: operator = ( std :: initializer_list< std :: initializer_list< double > >mat )
150 {
151  RESIZE( ( int ) mat.begin()->size(), ( int ) mat.size() );
152  auto p = this->values.begin();
153  for ( auto col : mat ) {
154 #if DEBUG
155  if ( this->nRows != ( int ) col.size() ) {
156  OOFEM_ERROR("Initializer list has inconsistent column sizes.");
157  }
158 #endif
159  for ( auto x : col ) {
160  * p = x;
161  p++;
162  }
163  }
164 
165  return * this;
166 }
167 
168 
169 FloatMatrix &FloatMatrix :: operator = ( std :: initializer_list< FloatArray >mat )
170 {
171  RESIZE( mat.begin()->giveSize(), ( int ) mat.size() );
172  auto p = this->values.begin();
173  for ( auto col : mat ) {
174 #if DEBUG
175  if ( this->nRows != col.giveSize() ) {
176  OOFEM_ERROR("Initializer list has inconsistent column sizes.");
177  }
178 #endif
179  for ( auto x : col ) {
180  * p = x;
181  p++;
182  }
183  }
184 
185  return * this;
186 }
187 
188 
189 void FloatMatrix :: checkBounds(int i, int j) const
190 // Checks that the receiver includes a position (i,j).
191 {
192  if ( i <= 0 ) {
193  OOFEM_ERROR("matrix error on rows : %d < 0", i);
194  }
195  if ( j <= 0 ) {
196  OOFEM_ERROR("matrix error on columns : %d < 0", j);
197  }
198 
199  if ( i > nRows ) {
200  OOFEM_ERROR("matrix error on rows : %d > %d", i, nRows);
201  }
202 
203  if ( j > nColumns ) {
204  printf("APA \n");
205  OOFEM_ERROR("matrix error on columns : %d > %d", j, nColumns);
206  }
207 }
208 
210 {
211  for (double val : values) {
212  if ( !std::isfinite(val) ) {
213  return false;
214  }
215  }
216 
217  return true;
218 }
219 
220 #ifdef DEBUG
221 double &FloatMatrix :: at(int i, int j)
222 // Returns the coefficient (i,j) of the receiver. Safer but slower than
223 // the inline version of method 'at'.
224 {
225  this->checkBounds(i, j);
226  return values [ ( j - 1 ) * nRows + i - 1 ];
227 }
228 
229 double FloatMatrix :: at(int i, int j) const
230 // Returns the coefficient (i,j) of the receiver. Safer but slower than
231 // the inline version of method 'at'.
232 {
233  this->checkBounds(i, j);
234  return values [ ( j - 1 ) * nRows + i - 1 ];
235 }
236 
237 double &FloatMatrix :: operator() (int i, int j)
238 {
239  this->checkBounds(i + 1, j + 1);
240  return values [ j * nRows + i ];
241 }
242 
243 double FloatMatrix :: operator() (int i, int j) const
244 {
245  this->checkBounds(i + 1, j + 1);
246  return values [ j * nRows + i ];
247 }
248 #endif
249 
250 
251 void FloatMatrix :: assemble(const FloatMatrix &src, const IntArray &loc)
252 {
253  int ii, jj, size = src.giveNumberOfRows();
254 
255 #ifdef DEBUG
256  if ( size != loc.giveSize() ) {
257  OOFEM_ERROR("dimensions of 'src' and 'loc' mismatch");
258  }
259 
260  if ( !src.isSquare() ) {
261  OOFEM_ERROR("'src' is not sqaure matrix");
262  }
263 #endif
264 
265  for ( int i = 1; i <= size; i++ ) {
266  if ( ( ii = loc.at(i) ) ) {
267  for ( int j = 1; j <= size; j++ ) {
268  if ( ( jj = loc.at(j) ) ) {
269  this->at(ii, jj) += src.at(i, j);
270  }
271  }
272  }
273  }
274 }
275 
276 
277 void FloatMatrix :: assemble(const FloatMatrix &src, const IntArray &rowind, const IntArray &colind)
278 {
279  int ii, jj;
280  int nr = src.giveNumberOfRows();
281  int nc = src.giveNumberOfColumns();
282 
283 #ifdef DEBUG
284  if ( nr != rowind.giveSize() ) {
285  OOFEM_ERROR("row dimensions of 'src' and 'rowind' mismatch");
286  }
287 
288  if ( nc != colind.giveSize() ) {
289  OOFEM_ERROR("column dimensions of 'src' and 'colind' mismatch");
290  }
291 #endif
292 
293  for ( int i = 1; i <= nr; i++ ) {
294  if ( ( ii = rowind.at(i) ) ) {
295  for ( int j = 1; j <= nc; j++ ) {
296  if ( ( jj = colind.at(j) ) ) {
297  this->at(ii, jj) += src.at(i, j);
298  }
299  }
300  }
301  }
302 }
303 
304 
305 void FloatMatrix :: assemble(const FloatMatrix &src, const int *rowind, const int *colind)
306 {
307  int ii, jj;
308  int nr = src.giveNumberOfRows();
309  int nc = src.giveNumberOfColumns();
310 
311  for ( int i = 1; i <= nr; i++ ) {
312  if ( ( ii = rowind [ i - 1 ] ) ) {
313  for ( int j = 1; j <= nc; j++ ) {
314  if ( ( jj = colind [ j - 1 ] ) ) {
315  this->at(ii, jj) += src.at(i, j);
316  }
317  }
318  }
319  }
320 }
321 
322 
324 {
325  // receiver becomes a transposition of src
326  int nrows = src.giveNumberOfColumns(), ncols = src.giveNumberOfRows();
327  RESIZE(nrows, ncols);
328 
329  for ( int i = 1; i <= nrows; i++ ) {
330  for ( int j = 1; j <= ncols; j++ ) {
331  this->at(i, j) = src.at(j, i);
332  }
333  }
334 }
335 
336 
337 void FloatMatrix :: beProductOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix)
338 // Receiver = aMatrix * bMatrix
339 {
340 # ifdef DEBUG
341  if ( aMatrix.nColumns != bMatrix.nRows ) {
342  OOFEM_ERROR("error in product A*B : dimensions do not match");
343  }
344 # endif
345  RESIZE(aMatrix.nRows, bMatrix.nColumns);
346 # ifdef __LAPACK_MODULE
347  double alpha = 1., beta = 0.;
348  dgemm_("n", "n", & this->nRows, & this->nColumns, & aMatrix.nColumns,
349  & alpha, aMatrix.givePointer(), & aMatrix.nRows, bMatrix.givePointer(), & bMatrix.nRows,
350  & beta, this->givePointer(), & this->nRows,
351  aMatrix.nColumns, bMatrix.nColumns, this->nColumns);
352 # else
353  for ( int i = 1; i <= aMatrix.nRows; i++ ) {
354  for ( int j = 1; j <= bMatrix.nColumns; j++ ) {
355  double coeff = 0.;
356  for ( int k = 1; k <= aMatrix.nColumns; k++ ) {
357  coeff += aMatrix.at(i, k) * bMatrix.at(k, j);
358  }
359 
360  this->at(i, j) = coeff;
361  }
362  }
363 # endif
364 }
365 
366 
367 void FloatMatrix :: beTProductOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix)
368 // Receiver = aMatrix^T * bMatrix
369 {
370 # ifdef DEBUG
371  if ( aMatrix.nRows != bMatrix.nRows ) {
372  OOFEM_ERROR("error in product A*B : dimensions do not match");
373  }
374 # endif
375  RESIZE(aMatrix.nColumns, bMatrix.nColumns);
376 # ifdef __LAPACK_MODULE
377  double alpha = 1., beta = 0.;
378  dgemm_("t", "n", & this->nRows, & this->nColumns, & aMatrix.nRows,
379  & alpha, aMatrix.givePointer(), & aMatrix.nRows, bMatrix.givePointer(), & bMatrix.nRows,
380  & beta, this->givePointer(), & this->nRows,
381  aMatrix.nColumns, bMatrix.nColumns, this->nColumns);
382 # else
383  for ( int i = 1; i <= aMatrix.nColumns; i++ ) {
384  for ( int j = 1; j <= bMatrix.nColumns; j++ ) {
385  double coeff = 0.;
386  for ( int k = 1; k <= aMatrix.nRows; k++ ) {
387  coeff += aMatrix.at(k, i) * bMatrix.at(k, j);
388  }
389 
390  this->at(i, j) = coeff;
391  }
392  }
393 #endif
394 }
395 
396 
397 void FloatMatrix :: beProductTOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix)
398 // Receiver = aMatrix * bMatrix^T
399 {
400 # ifdef DEBUG
401  if ( aMatrix.nColumns != bMatrix.nColumns ) {
402  OOFEM_ERROR("error in product A*B : dimensions do not match");
403  }
404 # endif
405  RESIZE(aMatrix.nRows, bMatrix.nRows);
406 # ifdef __LAPACK_MODULE
407  double alpha = 1., beta = 0.;
408  dgemm_("n", "t", & this->nRows, & this->nColumns, & aMatrix.nColumns,
409  & alpha, aMatrix.givePointer(), & aMatrix.nRows, bMatrix.givePointer(), & bMatrix.nRows,
410  & beta, this->givePointer(), & this->nRows,
411  aMatrix.nColumns, bMatrix.nColumns, this->nColumns);
412 # else
413  for ( int i = 1; i <= aMatrix.nRows; i++ ) {
414  for ( int j = 1; j <= bMatrix.nRows; j++ ) {
415  double coeff = 0.;
416  for ( int k = 1; k <= aMatrix.nColumns; k++ ) {
417  coeff += aMatrix.at(i, k) * bMatrix.at(j, k);
418  }
419 
420  this->at(i, j) = coeff;
421  }
422  }
423 # endif
424 }
425 
426 
427 void FloatMatrix :: addProductOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix)
428 // Receiver = aMatrix * bMatrix
429 {
430 # ifdef DEBUG
431  if ( aMatrix.nColumns != bMatrix.nRows ) {
432  OOFEM_ERROR("error in product A*B : dimensions do not match");
433  }
434  if ( aMatrix.nRows != this->nRows || bMatrix.nColumns != this->nColumns ) {
435  OOFEM_ERROR("error in product receiver : dimensions do not match");
436  }
437 # endif
438 
439 # ifdef __LAPACK_MODULE
440  double alpha = 1., beta = 1.;
441  dgemm_("n", "n", & this->nRows, & this->nColumns, & aMatrix.nColumns,
442  & alpha, aMatrix.givePointer(), & aMatrix.nRows, bMatrix.givePointer(), & bMatrix.nRows,
443  & beta, this->givePointer(), & this->nRows,
444  aMatrix.nColumns, bMatrix.nColumns, this->nColumns);
445 # else
446  for ( int i = 1; i <= aMatrix.nRows; i++ ) {
447  for ( int j = 1; j <= bMatrix.nColumns; j++ ) {
448  double coeff = 0.;
449  for ( int k = 1; k <= aMatrix.nColumns; k++ ) {
450  coeff += aMatrix.at(i, k) * bMatrix.at(k, j);
451  }
452 
453  this->at(i, j) += coeff;
454  }
455  }
456 # endif
457 }
458 
459 void FloatMatrix :: addTProductOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix)
460 // Receiver += aMatrix^T * bMatrix
461 {
462 # ifdef DEBUG
463  if ( aMatrix.nRows != bMatrix.nRows ) {
464  OOFEM_ERROR("error in product A*B : dimensions do not match");
465  }
466  if ( aMatrix.nColumns != this->nColumns || bMatrix.nColumns != this->nRows ) {
467  OOFEM_ERROR("error in product receiver : dimensions do not match");
468  }
469 # endif
470 
471 # ifdef __LAPACK_MODULE
472  double alpha = 1., beta = 1.;
473  dgemm_("t", "n", & this->nRows, & this->nColumns, & aMatrix.nRows,
474  & alpha, aMatrix.givePointer(), & aMatrix.nRows, bMatrix.givePointer(), & bMatrix.nRows,
475  & beta, this->givePointer(), & this->nRows,
476  aMatrix.nColumns, bMatrix.nColumns, this->nColumns);
477 # else
478  for ( int i = 1; i <= aMatrix.nColumns; i++ ) {
479  for ( int j = 1; j <= bMatrix.nColumns; j++ ) {
480  double coeff = 0.;
481  for ( int k = 1; k <= aMatrix.nRows; k++ ) {
482  coeff += aMatrix.at(k, i) * bMatrix.at(k, j);
483  }
484 
485  this->at(i, j) += coeff;
486  }
487  }
488 # endif
489 }
490 
491 
493 // Receiver = vec1 * vec2^T
494 {
495  int n1 = vec1.giveSize();
496  int n2 = vec2.giveSize();
497  RESIZE(n1, n2);
498  for ( int j = 1; j <= n2; j++ ) {
499  for ( int i = 1; i <= n1; i++ ) {
500  this->at(i, j) = vec1.at(i) * vec2.at(j);
501  }
502  }
503 }
504 
505 void FloatMatrix :: beNMatrixOf(const FloatArray &n, int nsd)
506 {
507  this->resize(nsd, n.giveSize() * nsd);
508  for ( int i = 0; i < n.giveSize(); ++i ) {
509  for ( int j = 0; j < nsd; ++j ) {
510  ( * this )( j, i * nsd + j ) = n(i);
511  }
512  }
513 }
514 
516 { //normal should be at the first position, easier for interface material models
517  if ( normal.giveSize() == 1 ) {
518  this->resize(1, 1);
519  this->at(1, 1) = normal(0);
520  } else if ( normal.giveSize() == 2 ) {
521  this->resize(2, 2);
522  this->at(1, 1) = normal(0);
523  this->at(1, 2) = normal(1);
524 
525  this->at(2, 1) = normal(1);
526  this->at(2, 2) = -normal(0);
527 
528  } else if ( normal.giveSize() == 3 ) {
529  // Create a permutated vector of n, *always* length 1 and significantly different from n.
530  FloatArray b, t = {
531  normal(1), -normal(2), normal(0)
532  }; // binormal and tangent
533 
534  // Construct orthogonal vector
535  double npn = t.dotProduct(normal);
536  t.add(-npn, normal);
537  t.normalize();
538  b.beVectorProductOf(t, normal);
539 
540  this->resize(3, 3);
541  this->at(1, 1) = normal.at(1);
542  this->at(1, 2) = normal.at(2);
543  this->at(1, 3) = normal.at(3);
544 
545  this->at(2, 1) = b.at(1);
546  this->at(2, 2) = b.at(2);
547  this->at(2, 3) = b.at(3);
548 
549  this->at(3, 1) = t.at(1);
550  this->at(3, 2) = t.at(2);
551  this->at(3, 3) = t.at(3);
552  } else {
553  OOFEM_ERROR("Normal needs 1 to 3 components.");
554  }
555 }
556 
557 void FloatMatrix :: setSubMatrix(const FloatMatrix &src, int sr, int sc)
558 {
559  sr--;
560  sc--;
561 
562  int srcRows = src.giveNumberOfRows(), srcCols = src.giveNumberOfColumns();
563 #ifdef DEBUG
564  int nr = sr + srcRows;
565  int nc = sc + srcCols;
566 
567  if ( ( this->giveNumberOfRows() < nr ) || ( this->giveNumberOfColumns() < nc ) ) {
568  OOFEM_ERROR("Sub matrix doesn't fit inside allocated space.");
569  }
570 #endif
571 
572  // add sub-matrix
573  for ( int j = 0; j < srcCols; j++ ) {
574  for ( int i = 0; i < srcRows; i++ ) {
575  ( * this )( sr + i, sc + j ) = src(i, j);
576  }
577  }
578  //memcpy( &(*this)(sr + 0, sc + j), &src(0,j), srcRows * sizeof(int));
579 }
580 
581 
582 void FloatMatrix :: setTSubMatrix(const FloatMatrix &src, int sr, int sc)
583 {
584  sr--;
585  sc--;
586 
587  int srcRows = src.giveNumberOfRows(), srcCols = src.giveNumberOfColumns();
588 #ifdef DEBUG
589  int nr = sr + srcCols;
590  int nc = sc + srcRows;
591 
592  if ( ( this->giveNumberOfRows() < nr ) || ( this->giveNumberOfColumns() < nc ) ) {
593  OOFEM_ERROR("Sub matrix doesn't fit inside allocated space");
594  }
595 #endif
596 
597  // add sub-matrix
598  for ( int i = 0; i < srcCols; i++ ) {
599  for ( int j = 0; j < srcRows; j++ ) {
600  ( * this )( sr + i, sc + j ) = src(j, i);
601  }
602  }
603 }
604 
605 
606 
607 void FloatMatrix :: addSubVectorRow(const FloatArray &src, int sr, int sc)
608 {
609  sc--;
610 
611  int srcCols = src.giveSize();
612 
613  int nr = sr;
614  int nc = sc + srcCols;
615 
616  if ( ( this->giveNumberOfRows() < nr ) || ( this->giveNumberOfColumns() < nc ) ) {
617  this->resizeWithData( max(this->giveNumberOfRows(), nr), max(this->giveNumberOfColumns(), nc) );
618  }
619 
620  // add sub-matrix
621  for ( int j = 1; j <= srcCols; j++ ) {
622  this->at(sr, sc + j) += src.at(j);
623  }
624 }
625 
626 
627 void FloatMatrix :: addSubVectorCol(const FloatArray &src, int sr, int sc)
628 {
629  sr--;
630 
631  int srcRows = src.giveSize();
632 
633  int nr = sr + srcRows;
634  int nc = sc;
635 
636  if ( ( this->giveNumberOfRows() < nr ) || ( this->giveNumberOfColumns() < nc ) ) {
637  this->resizeWithData( max(this->giveNumberOfRows(), nr), max(this->giveNumberOfColumns(), nc) );
638  }
639 
640  // add sub-matrix
641  for ( int j = 1; j <= srcRows; j++ ) {
642  this->at(sr + j, sc) += src.at(j);
643  }
644 }
645 
646 
647 
648 void FloatMatrix :: setColumn(const FloatArray &src, int c)
649 {
650  int nr = src.giveSize();
651 #ifdef DEBUG
652  if ( this->giveNumberOfRows() != nr || c < 1 || c > this->giveNumberOfColumns() ) {
653  OOFEM_ERROR("Size mismatch");
654  }
655 #endif
656 
657  auto P = this->values.begin() + ( c - 1 ) * nr;
658  std :: copy(src.begin(), src.end(), P);
659 }
660 
661 
662 void FloatMatrix :: copyColumn(FloatArray &dest, int c) const
663 {
664  int nr = this->giveNumberOfRows();
665 #ifdef DEBUG
666  if ( c < 1 || c > this->giveNumberOfColumns() ) {
667  OOFEM_ERROR("Column outside range (%d)", c);
668  }
669 #endif
670 
671  dest.resize(nr);
672  auto P = this->values.begin() + ( c - 1 ) * nr;
673  std :: copy( P, P + nr, dest.begin() );
674 }
675 
676 
677 void FloatMatrix :: copySubVectorRow(const FloatArray &src, int sr, int sc)
678 {
679  sc--;
680 
681  int srcCols = src.giveSize();
682 
683  int nr = sr;
684  int nc = sc + srcCols;
685 
686  if ( ( this->giveNumberOfRows() < nr ) || ( this->giveNumberOfColumns() < nc ) ) {
687  this->resizeWithData( max(this->giveNumberOfRows(), nr), max(this->giveNumberOfColumns(), nc) );
688  }
689 
690  // add sub-matrix
691  for ( int j = 1; j <= srcCols; j++ ) {
692  this->at(sr, sc + j) = src.at(j);
693  }
694 }
695 
696 
697 
699 // Adds to the receiver the product a(transposed).b dV .
700 // The receiver size is adjusted, if necessary.
701 // This method assumes that both the receiver and the product above are
702 // symmetric matrices, and therefore computes only the upper half of the
703 // receiver ; the lower half is not modified. Other advantage : it does
704 // not compute the transposition of matrix a.
705 {
706  if ( !this->isNotEmpty() ) {
707  this->nRows = a.nColumns;
708  this->nColumns = b.nColumns;
709  this->values.assign(a.nColumns * b.nColumns, 0.);
710  }
711 
712 #ifdef __LAPACK_MODULE
713  double beta = 1.;
716  if ( this->nRows < 20 ) {
717  // Split the matrix into 2 columns, s1 + s2 = n ( = nRows = nColumns ).
718  int s1 = this->nRows / 2;
719  int s2 = this->nRows - s1;
720  // First column block, we only take the first s rows by only taking the first s columns in the matrix a.
721  dgemm_("t", "n", & s1, & s1, & a.nRows, & dV, a.givePointer(), & a.nRows, b.givePointer(), & b.nRows, & beta, this->givePointer(), & this->nRows, a.nColumns, b.nColumns, this->nColumns);
722  // Second column block starting a memory position c * nRows
723  dgemm_("t", "n", & this->nRows, & s2, & a.nRows, & dV, a.givePointer(), & a.nRows, & b.givePointer() [ s1 * b.nRows ], & b.nRows, & beta, & this->givePointer() [ s1 * this->nRows ], & this->nRows, a.nColumns, b.nColumns, this->nColumns);
724  } else {
725  // Get suitable blocksize. Around 10 rows should be suitable (slightly adjusted to minimize number of blocks):
726  // Smaller blocks than ~10 didn't show any performance gains in my benchmarks. / Mikael
727  int block = ( this->nRows - 1 ) / ( this->nRows / 10 ) + 1;
728  int start = 0;
729  int end = block;
730  while ( start < this->nRows ) {
731  int s = end - start;
732  dgemm_("t", "n", & end, & s, & a.nRows, & dV, a.givePointer(), & a.nRows, & b.givePointer() [ start * b.nRows ], & b.nRows, & beta, & this->givePointer() [ start * this->nRows ],
733  & this->nRows, a.nColumns, b.nColumns, this->nColumns);
734  start = end;
735  end += block;
736  if ( end > this->nRows ) {
737  end = this->nRows;
738  }
739  }
740  }
741 #else
742  for ( int i = 1; i <= nRows; i++ ) {
743  for ( int j = i; j <= nColumns; j++ ) {
744  double summ = 0.;
745  for ( int k = 1; k <= a.nRows; k++ ) {
746  summ += a.at(k, i) * b.at(k, j);
747  }
748 
749  this->at(i, j) += summ * dV;
750  }
751  }
752 #endif
753 }
754 
755 
757 {
758  if ( !this->isNotEmpty() ) {
759  this->nRows = a.giveSize();
760  this->nColumns = a.giveSize();
761  this->values.assign(this->nRows * this->nColumns, 0.);
762  }
763 #ifdef __LAPACK_MODULE
764  int inc = 1;
765  int sizeA = a.giveSize();
766  dsyr_("u", & sizeA, & dV, a.givePointer(), & inc,
767  this->givePointer(), & this->nRows,
768  sizeA, this->nColumns);
769 #else
770  for ( int i = 1; i <= nRows; i++ ) {
771  for ( int j = i; j <= nColumns; j++ ) {
772  this->at(i, j) += a.at(i) * a.at(j) * dV;
773  }
774  }
775 #endif
776 }
777 
778 
779 
780 void FloatMatrix :: plusProductUnsym(const FloatMatrix &a, const FloatMatrix &b, double dV)
781 // Adds to the receiver the product a(transposed).b dV .
782 // If the receiver has a null size, it is expanded.
783 // Advantage : does not compute the transposition of matrix a.
784 {
785  if ( !this->isNotEmpty() ) {
786  this->nRows = a.nColumns;
787  this->nColumns = b.nColumns;
788  this->values.assign(this->nRows * this->nColumns, 0.);
789  }
790 #ifdef __LAPACK_MODULE
791  double beta = 1.;
792  dgemm_("t", "n", & this->nRows, & this->nColumns, & a.nRows,
793  & dV, a.givePointer(), & a.nRows, b.givePointer(), & b.nRows,
794  & beta, this->givePointer(), & this->nRows,
795  a.nColumns, b.nColumns, this->nColumns);
796 #else
797  for ( int i = 1; i <= nRows; i++ ) {
798  for ( int j = 1; j <= nColumns; j++ ) {
799  double summ = 0.;
800  for ( int k = 1; k <= a.nRows; k++ ) {
801  summ += a.at(k, i) * b.at(k, j);
802  }
803 
804  this->at(i, j) += summ * dV;
805  }
806  }
807 #endif
808 }
809 
810 
811 void FloatMatrix :: plusDyadUnsym(const FloatArray &a, const FloatArray &b, double dV)
812 {
813  if ( !this->isNotEmpty() ) {
814  this->nRows = a.giveSize();
815  this->nColumns = b.giveSize();
816  this->values.assign(this->nRows * this->nColumns, 0.);
817  }
818 #ifdef __LAPACK_MODULE
819  int inc = 1;
820  int sizeA = a.giveSize();
821  int sizeB = b.giveSize();
822  dger_(& sizeA, & sizeB, & dV, a.givePointer(), & inc,
823  b.givePointer(), & inc, this->givePointer(), & this->nRows,
824  sizeA, sizeB, this->nColumns);
825 #else
826  for ( int i = 1; i <= nRows; i++ ) {
827  for ( int j = 1; j <= nColumns; j++ ) {
828  this->at(i, j) += a.at(i) * b.at(j) * dV;
829  }
830  }
831 #endif
832 }
833 
834 
836 // Receiver becomes inverse of given parameter src. If necessary, size is adjusted.
837 {
838  double det;
839 
840 # ifdef DEBUG
841  if ( !src.isSquare() ) {
842  OOFEM_ERROR("cannot inverse a %d by %d matrix", src.nRows, src.nColumns);
843  }
844 # endif
845 
846  RESIZE(src.nRows, src.nColumns);
847 
848  if ( nRows == 1 ) {
849  this->at(1, 1) = 1. / src.at(1, 1);
850  return;
851  } else if ( nRows == 2 ) {
852  det = src.at(1, 1) * src.at(2, 2) - src.at(1, 2) * src.at(2, 1);
853  this->at(1, 1) = src.at(2, 2) / det;
854  this->at(2, 1) = -src.at(2, 1) / det;
855  this->at(1, 2) = -src.at(1, 2) / det;
856  this->at(2, 2) = src.at(1, 1) / det;
857  return;
858  } else if ( nRows == 3 ) {
859  det = src.at(1, 1) * src.at(2, 2) * src.at(3, 3) + src.at(1, 2) * src.at(2, 3) * src.at(3, 1) +
860  src.at(1, 3) * src.at(2, 1) * src.at(3, 2) - src.at(1, 3) * src.at(2, 2) * src.at(3, 1) -
861  src.at(2, 3) * src.at(3, 2) * src.at(1, 1) - src.at(3, 3) * src.at(1, 2) * src.at(2, 1);
862 
863  this->at(1, 1) = ( src.at(2, 2) * src.at(3, 3) - src.at(2, 3) * src.at(3, 2) ) / det;
864  this->at(2, 1) = ( src.at(2, 3) * src.at(3, 1) - src.at(2, 1) * src.at(3, 3) ) / det;
865  this->at(3, 1) = ( src.at(2, 1) * src.at(3, 2) - src.at(2, 2) * src.at(3, 1) ) / det;
866  this->at(1, 2) = ( src.at(1, 3) * src.at(3, 2) - src.at(1, 2) * src.at(3, 3) ) / det;
867  this->at(2, 2) = ( src.at(1, 1) * src.at(3, 3) - src.at(1, 3) * src.at(3, 1) ) / det;
868  this->at(3, 2) = ( src.at(1, 2) * src.at(3, 1) - src.at(1, 1) * src.at(3, 2) ) / det;
869  this->at(1, 3) = ( src.at(1, 2) * src.at(2, 3) - src.at(1, 3) * src.at(2, 2) ) / det;
870  this->at(2, 3) = ( src.at(1, 3) * src.at(2, 1) - src.at(1, 1) * src.at(2, 3) ) / det;
871  this->at(3, 3) = ( src.at(1, 1) * src.at(2, 2) - src.at(1, 2) * src.at(2, 1) ) / det;
872 
873  //p[0]= (values[4]*values[8]-values[7]*values[5])/det ;
874  //p[1]= (values[7]*values[2]-values[1]*values[8])/det ;
875  //p[2]= (values[1]*values[5]-values[4]*values[2])/det ;
876  //p[3]= (values[6]*values[5]-values[3]*values[8])/det ;
877  //p[4]= (values[0]*values[8]-values[6]*values[2])/det ;
878  //p[5]= (values[3]*values[2]-values[0]*values[5])/det ;
879  //p[6]= (values[3]*values[7]-values[6]*values[4])/det ;
880  //p[7]= (values[6]*values[1]-values[0]*values[7])/det ;
881  //p[8]= (values[0]*values[4]-values[3]*values[1])/det ;
882  return;
883  } else {
884 #ifdef __LAPACK_MODULE
885  int n = this->nRows;
886  IntArray ipiv(n);
887  int lwork, info;
888  * this = src;
889 
890  // LU-factorization
891  dgetrf_(& n, & n, this->givePointer(), & n, ipiv.givePointer(), & info);
892  if ( info != 0 ) {
893  OOFEM_ERROR("dgetrf error %d", info);
894  }
895 
896  // Inverse
897  lwork = n * n;
898  FloatArray work(lwork);
899  dgetri_(& this->nRows, this->givePointer(), & this->nRows, ipiv.givePointer(), work.givePointer(), & lwork, & info);
900  if ( info > 0 ) {
901  OOFEM_ERROR("Singular at %d", info);
902  } else if ( info < 0 ) {
903  OOFEM_ERROR("Error on input %d", info);
904  }
905 #else
906  // size >3 ... gaussian elimination - slow but safe
907  //
908  double piv, linkomb;
909  FloatMatrix tmp = src;
910  // initialize answer to be unity matrix;
911  this->zero();
912  for ( int i = 1; i <= nRows; i++ ) {
913  this->at(i, i) = 1.0;
914  }
915 
916  // lower triangle elimination by columns
917  for ( int i = 1; i < nRows; i++ ) {
918  piv = tmp.at(i, i);
919  if ( fabs(piv) < 1.e-24 ) {
920  OOFEM_ERROR("pivot (%d,%d) to close to small (< 1.e-24)", i, i);
921  }
922 
923  for ( int j = i + 1; j <= nRows; j++ ) {
924  linkomb = tmp.at(j, i) / tmp.at(i, i);
925  for ( int k = i; k <= nRows; k++ ) {
926  tmp.at(j, k) -= tmp.at(i, k) * linkomb;
927  }
928 
929  for ( int k = 1; k <= nRows; k++ ) {
930  this->at(j, k) -= this->at(i, k) * linkomb;
931  }
932  }
933  }
934 
935  // upper triangle elimination by columns
936  for ( int i = nRows; i > 1; i-- ) {
937  piv = tmp.at(i, i);
938  for ( int j = i - 1; j > 0; j-- ) {
939  linkomb = tmp.at(j, i) / piv;
940  for ( int k = i; k > 0; k-- ) {
941  tmp.at(j, k) -= tmp.at(i, k) * linkomb;
942  }
943 
944  for ( int k = nRows; k > 0; k-- ) {
945  // tmp -> at(j,k)-= tmp ->at(i,k)*linkomb;
946  this->at(j, k) -= this->at(i, k) * linkomb;
947  }
948  }
949  }
950 
951  // diagonal scaling
952  for ( int i = 1; i <= nRows; i++ ) {
953  for ( int j = 1; j <= nRows; j++ ) {
954  this->at(i, j) /= tmp.at(i, i);
955  }
956  }
957 #endif
958  }
959 }
960 
961 
963  int topRow, int bottomRow, int topCol, int bottomCol)
964 /*
965  * modifies receiver to be submatrix of the src matrix
966  * size of receiver submatrix is determined from
967  * input parameters
968  */
969 {
970 #ifdef DEBUG
971  if ( ( topRow < 1 ) || ( bottomRow < 1 ) || ( topCol < 1 ) || ( bottomCol < 1 ) ) {
972  OOFEM_ERROR("subindexes size mismatch");
973  }
974 
975  if ( ( src.nRows < bottomRow ) || ( src.nColumns < bottomCol ) || ( ( bottomRow - topRow ) > src.nRows ) ||
976  ( ( bottomCol - topCol ) > src.nColumns ) ) {
977  OOFEM_ERROR("subindexes size mismatch");
978  }
979 #endif
980 
981 
982  int topRm1, topCm1;
983  topRm1 = topRow - 1;
984  topCm1 = topCol - 1;
985 
986  // allocate return value
987  this->resize(bottomRow - topRm1, bottomCol - topCm1);
988  for ( int i = topRow; i <= bottomRow; i++ ) {
989  for ( int j = topCol; j <= bottomCol; j++ ) {
990  this->at(i - topRm1, j - topCm1) = src.at(i, j);
991  }
992  }
993 }
994 
995 
996 
997 void
998 FloatMatrix :: beSubMatrixOf(const FloatMatrix &src, const IntArray &indxRow, const IntArray &indxCol)
999 /*
1000  * Modifies receiver to be a sub-matrix of the src matrix.
1001  * sub-matrix has size(indxRow) x size(indxCol) with values given as
1002  * this(i,j) = src( indxRow(i), indxCol(j) )
1003  */
1004 {
1005 # ifdef DEBUG
1006  if ( indxRow.maximum() > src.giveNumberOfRows() || indxCol.maximum() > src.giveNumberOfColumns() ||
1007  indxRow.minimum() < 1 || indxCol.minimum() < 1 ) {
1008  OOFEM_ERROR("index exceeds source dimensions");
1009  }
1010 # endif
1011 
1012  int szRow = indxRow.giveSize();
1013  int szCol = indxCol.giveSize();
1014  this->resize(szRow, szCol);
1015 
1016  for ( int i = 1; i <= szRow; i++ ) {
1017  for ( int j = 1; j <= szCol; j++ ) {
1018  this->at(i, j) = src.at( indxRow.at(i), indxCol.at(j) );
1019  }
1020  }
1021 }
1022 
1023 void FloatMatrix :: add(const FloatMatrix &aMatrix)
1024 // Adds aMatrix to the receiver. If the receiver has a null size,
1025 // adjusts its size to that of aMatrix. Returns the modified receiver.
1026 {
1027  if ( aMatrix.nRows == 0 || aMatrix.nColumns == 0 ) {
1028  return;
1029  }
1030 
1031  if ( !this->isNotEmpty() ) {
1032  this->operator = ( aMatrix );
1033  return;
1034  }
1035 # ifdef DEBUG
1036  if ( ( aMatrix.nRows != nRows || aMatrix.nColumns != nColumns ) && aMatrix.isNotEmpty() ) {
1037  OOFEM_ERROR("dimensions mismatch : (r1,c1)+(r2,c2) : (%d,%d)+(%d,%d)", nRows, nColumns, aMatrix.nRows, aMatrix.nColumns);
1038  }
1039 # endif
1040 
1041 #ifdef __LAPACK_MODULE
1042  int aSize = aMatrix.nRows * aMatrix.nColumns;
1043  int inc = 1;
1044  double s = 1.;
1045  daxpy_(& aSize, & s, aMatrix.givePointer(), & inc, this->givePointer(), & inc, aSize, aSize);
1046 #else
1047  for ( size_t i = 0; i < this->values.size(); i++ ) {
1048  this->values [ i ] += aMatrix.values [ i ];
1049  }
1050 #endif
1051 }
1052 
1053 
1054 void FloatMatrix :: add(double s, const FloatMatrix &aMatrix)
1055 // Adds aMatrix to the receiver. If the receiver has a null size,
1056 // adjusts its size to that of aMatrix. Returns the modified receiver.
1057 {
1058  if ( aMatrix.nRows == 0 || aMatrix.nColumns == 0 ) {
1059  return;
1060  }
1061 
1062  if ( !this->isNotEmpty() ) {
1063  this->operator = ( aMatrix );
1064  this->times(s);
1065  return;
1066  }
1067 # ifdef DEBUG
1068  if ( ( aMatrix.nRows != nRows || aMatrix.nColumns != nColumns ) && aMatrix.isNotEmpty() ) {
1069  OOFEM_ERROR("dimensions mismatch : (r1,c1)+(r2,c2) : (%d,%d)+(%d,%d)", nRows, nColumns, aMatrix.nRows, aMatrix.nColumns);
1070  }
1071 # endif
1072 
1073 #ifdef __LAPACK_MODULE
1074  int aSize = aMatrix.nRows * aMatrix.nColumns;
1075  int inc = 1;
1076  daxpy_(& aSize, & s, aMatrix.givePointer(), & inc, this->givePointer(), & inc, aSize, aSize);
1077 #else
1078  for ( size_t i = 0; i < this->values.size(); i++ ) {
1079  this->values [ i ] += s * aMatrix.values [ i ];
1080  }
1081 #endif
1082 }
1083 
1085 // Adds aMatrix to the receiver. If the receiver has a null size,
1086 // adjusts its size to that of aMatrix. Returns the modified receiver.
1087 {
1088  if ( !this->isNotEmpty() ) {
1089  this->operator = ( aMatrix );
1090  this->negated();
1091  return;
1092  }
1093 # ifdef DEBUG
1094  if ( ( aMatrix.nRows != nRows || aMatrix.nColumns != nColumns ) && aMatrix.isNotEmpty() ) {
1095  OOFEM_ERROR("dimensions mismatch : (r1,c1)-(r2,c2) : (%d,%d)-(%d,%d)", nRows, nColumns, aMatrix.nRows, aMatrix.nColumns);
1096  }
1097 # endif
1098 
1099 #ifdef __LAPACK_MODULE
1100  int aSize = aMatrix.nRows * aMatrix.nColumns;
1101  int inc = 1;
1102  double s = -1.;
1103  daxpy_(& aSize, & s, aMatrix.givePointer(), & inc, this->givePointer(), & inc, aSize, aSize);
1104 #else
1105  for ( size_t i = 0; i < this->values.size(); i++ ) {
1106  this->values [ i ] -= aMatrix.values [ i ];
1107  }
1108 #endif
1109 }
1110 
1111 
1112 bool FloatMatrix :: solveForRhs(const FloatArray &b, FloatArray &answer, bool transpose)
1113 // solves equation b = this * x
1114 {
1115 # ifdef DEBUG
1116  if ( !this->isSquare() ) {
1117  OOFEM_ERROR("cannot solve a %d by %d matrix", nRows, nColumns);
1118  }
1119 
1120  if ( nRows != b.giveSize() ) {
1121  OOFEM_ERROR("dimension mismatch");
1122  }
1123 # endif
1124 
1125 #ifdef __LAPACK_MODULE
1126  int info, nrhs = 1;
1127  IntArray ipiv(this->nRows);
1128  answer = b;
1129  //dgesv_( &this->nRows, &nrhs, this->givePointer(), &this->nRows, ipiv.givePointer(), answer.givePointer(), &this->nRows, &info );
1130  dgetrf_(& this->nRows, & this->nRows, this->givePointer(), & this->nRows, ipiv.givePointer(), & info);
1131  if ( info == 0 ) {
1132  dgetrs_(transpose ? "Transpose" : "No transpose", & this->nRows, & nrhs, this->givePointer(), & this->nRows, ipiv.givePointer(), answer.givePointer(), & this->nRows, & info);
1133  }
1134  if ( info != 0 ) {
1135  return false;
1136  }
1137 #else
1138  int pivRow;
1139  double piv, linkomb, help;
1140  FloatMatrix *mtrx, trans;
1141  if ( transpose ) {
1142  trans.beTranspositionOf(* this);
1143  mtrx = & trans;
1144  } else {
1145  mtrx = this;
1146  }
1147 
1148  answer = b;
1149 
1150  // initialize answer to be unity matrix;
1151  // lower triangle elimination by columns
1152  for ( int i = 1; i < nRows; i++ ) {
1153  // find the suitable row and pivot
1154  piv = fabs( mtrx->at(i, i) );
1155  pivRow = i;
1156  for ( int j = i + 1; j <= nRows; j++ ) {
1157  if ( fabs( mtrx->at(j, i) ) > piv ) {
1158  pivRow = j;
1159  piv = fabs( mtrx->at(j, i) );
1160  }
1161  }
1162 
1163  if ( piv < 1.e-20 ) {
1164  return false;
1165  }
1166 
1167  // exchange rows
1168  if ( pivRow != i ) {
1169  for ( int j = i; j <= nRows; j++ ) {
1170  help = mtrx->at(i, j);
1171  mtrx->at(i, j) = mtrx->at(pivRow, j);
1172  mtrx->at(pivRow, j) = help;
1173  }
1174  help = answer.at(i);
1175  answer.at(i) = answer.at(pivRow);
1176  answer.at(pivRow) = help;
1177  }
1178 
1179  for ( int j = i + 1; j <= nRows; j++ ) {
1180  linkomb = mtrx->at(j, i) / mtrx->at(i, i);
1181  for ( int k = i; k <= nRows; k++ ) {
1182  mtrx->at(j, k) -= mtrx->at(i, k) * linkomb;
1183  }
1184 
1185  answer.at(j) -= answer.at(i) * linkomb;
1186  }
1187  }
1188 
1189  // back substitution
1190  for ( int i = nRows; i >= 1; i-- ) {
1191  help = 0.;
1192  for ( int j = i + 1; j <= nRows; j++ ) {
1193  help += mtrx->at(i, j) * answer.at(j);
1194  }
1195 
1196  answer.at(i) = ( answer.at(i) - help ) / mtrx->at(i, i);
1197  }
1198 #endif
1199 
1200  return true;
1201 }
1202 
1203 
1204 void FloatMatrix :: solveForRhs(const FloatMatrix &b, FloatMatrix &answer, bool transpose)
1205 // solves equation b = this * x
1206 // returns x. this and b are kept untouched
1207 //
1208 // gaussian elimination - slow but safe
1209 //
1210 {
1211 # ifdef DEBUG
1212  if ( !this->isSquare() ) {
1213  OOFEM_ERROR("cannot solve a %d by %d matrix", nRows, nColumns);
1214  }
1215 
1216  if ( nRows != b.giveNumberOfRows() ) {
1217  OOFEM_ERROR("dimension mismatch");
1218  }
1219 # endif
1220 
1221 #ifdef __LAPACK_MODULE
1222  int info;
1223  IntArray ipiv(this->nRows);
1224  answer = b;
1225  dgetrf_(& this->nRows, & this->nRows, this->givePointer(), & this->nRows, ipiv.givePointer(), & info);
1226  if ( info == 0 ) {
1227  dgetrs_(transpose ? "t" : "n", & this->nRows, & answer.nColumns, this->givePointer(), & this->nRows, ipiv.givePointer(), answer.givePointer(), & this->nRows, & info);
1228  }
1229  if ( info != 0 ) {
1230  OOFEM_ERROR("error %d", info);
1231  }
1232 #else
1233  int pivRow, nPs;
1234  double piv, linkomb, help;
1235  FloatMatrix *mtrx, trans;
1236  if ( transpose ) {
1237  trans.beTranspositionOf(* this);
1238  mtrx = & trans;
1239  } else {
1240  mtrx = this;
1241  }
1242 
1243  nPs = b.giveNumberOfColumns();
1244  answer = b;
1245  // initialize answer to be unity matrix;
1246  // lower triangle elimination by columns
1247  for ( int i = 1; i < nRows; i++ ) {
1248  // find the suitable row and pivot
1249  piv = fabs( mtrx->at(i, i) );
1250  pivRow = i;
1251  for ( int j = i + 1; j <= nRows; j++ ) {
1252  if ( fabs( mtrx->at(j, i) ) > piv ) {
1253  pivRow = j;
1254  piv = fabs( mtrx->at(j, i) );
1255  }
1256  }
1257 
1258  if ( fabs(piv) < 1.e-20 ) {
1259  OOFEM_ERROR("pivot too small, cannot solve %d by %d matrix", nRows, nColumns);
1260  }
1261 
1262  // exchange rows
1263  if ( pivRow != i ) {
1264  for ( int j = i; j <= nRows; j++ ) {
1265  help = mtrx->at(i, j);
1266  mtrx->at(i, j) = mtrx->at(pivRow, j);
1267  mtrx->at(pivRow, j) = help;
1268  }
1269 
1270  for ( int j = 1; j <= nPs; j++ ) {
1271  help = answer.at(i, j);
1272  answer.at(i, j) = answer.at(pivRow, j);
1273  answer.at(pivRow, j) = help;
1274  }
1275  }
1276 
1277  if ( fabs(piv) < 1.e-20 ) {
1278  OOFEM_ERROR("cannot solve, zero pivot encountered");
1279  }
1280 
1281  for ( int j = i + 1; j <= nRows; j++ ) {
1282  linkomb = mtrx->at(j, i) / mtrx->at(i, i);
1283  for ( int k = i; k <= nRows; k++ ) {
1284  mtrx->at(j, k) -= mtrx->at(i, k) * linkomb;
1285  }
1286 
1287  for ( int k = 1; k <= nPs; k++ ) {
1288  answer.at(j, k) -= answer.at(i, k) * linkomb;
1289  }
1290  }
1291  }
1292 
1293  // back substitution
1294  for ( int i = nRows; i >= 1; i-- ) {
1295  for ( int k = 1; k <= nPs; k++ ) {
1296  help = 0.;
1297  for ( int j = i + 1; j <= nRows; j++ ) {
1298  help += mtrx->at(i, j) * answer.at(j, k);
1299  }
1300 
1301  answer.at(i, k) = ( answer.at(i, k) - help ) / mtrx->at(i, i);
1302  }
1303  }
1304 #endif
1305 }
1306 
1307 
1308 void FloatMatrix :: initFromVector(const FloatArray &vector, bool transposed)
1309 //
1310 // constructor : creates (vector->giveSize(),1) FloatMatrix
1311 // if transpose = 1 creates (1,vector->giveSize()) FloatMatrix
1312 //
1313 {
1314  if ( transposed ) {
1315  this->nRows = 1;
1316  this->nColumns = vector.giveSize();
1317  } else {
1318  this->nRows = vector.giveSize();
1319  this->nColumns = 1;
1320  }
1321 
1322  this->values = vector.values;
1323 }
1324 
1325 
1327 {
1328  std :: fill(this->values.begin(), this->values.end(), 0.);
1329 }
1330 
1331 
1333 {
1334 #ifdef DEBUG
1335  if ( !this->isSquare() ) {
1336  OOFEM_ERROR("cannot make unit matrix of %d by %d matrix", nRows, nColumns);
1337  }
1338 #endif
1339 
1340  this->zero();
1341  for ( int i = 1; i <= nRows; i++ ) {
1342  this->at(i, i) = 1.0;
1343  }
1344 }
1345 
1346 
1348 // this matrix is the product of the 6x6 deviatoric projection matrix ID
1349 // and the inverse scaling matrix Pinv
1350 {
1351  this->resize(6, 6);
1352  values [ 0 ] = values [ 7 ] = values [ 14 ] = 2. / 3.;
1353  values [ 1 ] = values [ 2 ] = values [ 6 ] = values [ 8 ] = values [ 12 ] = values [ 13 ] = -1. / 3.;
1354  values [ 21 ] = values [ 28 ] = values [ 35 ] = 0.5;
1355 }
1356 
1357 
1358 void FloatMatrix :: resize(int rows, int columns)
1359 //
1360 // resizes receiver, all data will be lost
1361 //
1362 {
1363  this->nRows = rows;
1364  this->nColumns = columns;
1365  this->values.assign(rows * columns, 0.);
1366 }
1367 
1368 
1369 void FloatMatrix :: resizeWithData(int rows, int columns)
1370 //
1371 // resizes receiver, all data kept
1372 //
1373 {
1374  // Check of resize if necessary at all.
1375  if ( rows == this->nRows && columns == this->nColumns ) {
1376  return;
1377  }
1378 
1379  FloatMatrix old( std :: move(* this) );
1380 
1381  this->nRows = rows;
1382  this->nColumns = columns;
1383  this->values.resize(rows * columns);
1384 
1385  int ii = min( rows, old.giveNumberOfRows() );
1386  int jj = min( columns, old.giveNumberOfColumns() );
1387  // copy old values if possible
1388  for ( int i = 1; i <= ii; i++ ) {
1389  for ( int j = 1; j <= jj; j++ ) {
1390  this->at(i, j) = old.at(i, j);
1391  }
1392  }
1393 }
1394 
1395 
1396 void FloatMatrix :: hardResize(int rows, int columns)
1397 //
1398 // resizes receiver, all data will be lost
1399 //
1400 {
1401  this->nRows = rows;
1402  this->nColumns = columns;
1403  values.assign(rows * columns, 0.);
1404  this->values.shrink_to_fit();
1405 }
1406 
1407 
1409 // Returns the determinant of the receiver.
1410 {
1411 # ifdef DEBUG
1412  if ( !this->isSquare() ) {
1413  OOFEM_ERROR("cannot compute the determinant of a non-square %d by %d matrix", nRows, nColumns);
1414  }
1415 # endif
1416 
1417  if ( nRows == 1 ) {
1418  return values [ 0 ];
1419  } else if ( nRows == 2 ) {
1420  return ( values [ 0 ] * values [ 3 ] - values [ 1 ] * values [ 2 ] );
1421  } else if ( nRows == 3 ) {
1422  return ( values [ 0 ] * values [ 4 ] * values [ 8 ] + values [ 3 ] * values [ 7 ] * values [ 2 ] +
1423  values [ 6 ] * values [ 1 ] * values [ 5 ] - values [ 6 ] * values [ 4 ] * values [ 2 ] -
1424  values [ 7 ] * values [ 5 ] * values [ 0 ] - values [ 8 ] * values [ 3 ] * values [ 1 ] );
1425  } else {
1426  OOFEM_ERROR("sorry, cannot compute the determinant of a matrix larger than 3x3");
1427  }
1428 
1429  return 0.;
1430 }
1431 
1432 
1434 {
1435  int n = diag.giveSize();
1436  this->resize(n, n);
1437  for ( int i = 0; i < n; ++i ) {
1438  (*this)(i, i) = diag[i];
1439  }
1440 }
1441 
1442 
1444 {
1445 # ifdef DEBUG
1446  if ( !this->isSquare() ) {
1447  OOFEM_ERROR("cannot compute the trace of a non-square %d by %d matrix", nRows, nColumns);
1448  }
1449 # endif
1450  double answer = 0.;
1451  for ( int k = 0; k < nRows; k++ ) {
1452  answer += values [ k * ( nRows + 1 ) ];
1453  }
1454  return answer;
1455 }
1456 
1457 
1459 // Prints the receiver on screen.
1460 {
1461  printf("FloatMatrix with dimensions : %d %d\n",
1462  nRows, nColumns);
1463  if ( nRows <= 250 && nColumns <= 250 ) {
1464  for ( int i = 1; i <= nRows; ++i ) {
1465  for ( int j = 1; j <= nColumns && j <= 100; ++j ) {
1466  printf( "%10.3e ", this->at(i, j) );
1467  }
1468 
1469  printf("\n");
1470  }
1471  } else {
1472  printf(" large matrix : coefficients not printed \n");
1473  }
1474 }
1475 
1476 
1477 void FloatMatrix :: printYourselfToFile(const std::string filename, const bool showDimensions) const
1478 // Prints the receiver to file.
1479 {
1480  std :: ofstream matrixfile (filename);
1481  if (matrixfile.is_open()) {
1482  if (showDimensions)
1483  matrixfile << "FloatMatrix with dimensions : " << nRows << ", " << nColumns << "\n";
1484  matrixfile << std::scientific << std::right << std::setprecision(3);
1485  for ( int i = 1; i <= nRows; ++i ) {
1486  for ( int j = 1; j <= nColumns; ++j ) {
1487  matrixfile << std::setw(10) << this->at(i, j) << "\t";
1488  }
1489 
1490  matrixfile << "\n";
1491  }
1492  matrixfile.close();
1493  } else {
1494  OOFEM_ERROR("Failed to write to file");
1495  }
1496 }
1497 
1498 
1499 void FloatMatrix :: printYourself(const std::string &name) const
1500 // Prints the receiver on screen.
1501 {
1502  printf("%s (%d x %d): \n", name.c_str(), nRows, nColumns);
1503  if ( nRows <= 250 && nColumns <= 250 ) {
1504  for ( int i = 1; i <= nRows; ++i ) {
1505  for ( int j = 1; j <= nColumns && j <= 100; ++j ) {
1506  printf( "%10.3e ", this->at(i, j) );
1507  }
1508 
1509  printf("\n");
1510  }
1511  } else {
1512  for ( int i = 1; i <= nRows && i <= 20; ++i ) {
1513  for ( int j = 1; j <= nColumns && j <= 10; ++j ) {
1514  printf( "%10.3e ", this->at(i, j) );
1515  }
1516  if ( nColumns > 10 ) printf(" ...");
1517  printf("\n");
1518  }
1519  if ( nRows > 20 ) printf(" ...\n");
1520  }
1521 }
1522 
1523 
1524 void FloatMatrix :: pY() const
1525 // Prints the receiver on screen with higher accuracy than printYourself.
1526 {
1527  printf("[");
1528  for ( int i = 1; i <= nRows; ++i ) {
1529  for ( int j = 1; j <= nColumns; ++j ) {
1530  printf( "%20.15e", this->at(i, j) );
1531  if ( j < nColumns ) {
1532  printf(",");
1533  } else {
1534  printf(";");
1535  }
1536  }
1537  }
1538 
1539  printf("];\n");
1540 }
1541 
1542 
1543 void FloatMatrix :: writeCSV(const std :: string &name) const
1544 {
1545  FILE *file = fopen(name.c_str(), "w");
1546  for ( int i = 1; i <= nRows; ++i ) {
1547  for ( int j = 1; j <= nColumns; ++j ) {
1548  fprintf(file, "%10.3e, ", this->at(i, j) );
1549  }
1550 
1551  fprintf(file, "\n");
1552  }
1553  fclose(file);
1554 }
1555 
1556 
1557 void FloatMatrix :: rotatedWith(const FloatMatrix &r, char mode)
1558 // Returns the receiver 'a' rotated according the change-of-base matrix r.
1559 // The method performs the operation a = r^T . a . r . or the inverse
1560 {
1561  FloatMatrix rta;
1562 
1563  if ( mode == 'n' ) {
1564  rta.beTProductOf(r, * this); // r^T . a
1565  this->beProductOf(rta, r); // r^T . a . r
1566  } else if ( mode == 't' ) {
1567  rta.beProductOf(r, * this); // r . a
1568  this->beProductTOf(rta, r); // r . a . r^T
1569  } else {
1570  OOFEM_ERROR("unsupported mode");
1571  }
1572 }
1573 
1574 
1575 
1577 // Initializes the lower half of the receiver to the upper half.
1578 {
1579 # ifdef DEBUG
1580  if ( nRows != nColumns ) {
1581  OOFEM_ERROR("cannot symmetrize a non-square matrix");
1582  }
1583 
1584 # endif
1585 
1586  for ( int i = 2; i <= nRows; i++ ) {
1587  for ( int j = 1; j < i; j++ ) {
1588  this->at(i, j) = this->at(j, i);
1589  }
1590  }
1591 }
1592 
1593 
1594 void FloatMatrix :: times(double factor)
1595 // Multiplies every coefficient of the receiver by factor. Answers the
1596 // modified receiver.
1597 {
1598  for ( double &x : this->values ) {
1599  x *= factor;
1600  }
1601  // dscal_ seemed to be slower for typical usage of this function.
1602 }
1603 
1604 
1606 {
1607  for ( double &x : this->values ) {
1608  x = -x;
1609  }
1610 }
1611 
1612 
1614 {
1615  return sqrt( std :: inner_product(this->values.begin(), this->values.end(), this->values.begin(), 0.) );
1616 }
1617 
1618 double FloatMatrix :: computeNorm(char p) const
1619 {
1620 # ifdef __LAPACK_MODULE
1621  FloatArray work( this->giveNumberOfRows() );
1622  int lda = max(this->nRows, 1);
1623  double norm = dlange_(& p, & this->nRows, & this->nColumns, this->givePointer(), & lda, work.givePointer(), 1);
1624  return norm;
1625 
1626 # else
1627  if ( p == '1' ) { // Maximum absolute column sum.
1628  double col_sum, max_col = 0.0;
1629  for ( int j = 1; j <= this->nColumns; j++ ) {
1630  col_sum = 0.0;
1631  for ( int i = 1; i <= this->nRows; i++ ) {
1632  col_sum += fabs( this->at(i, j) );
1633  }
1634  if ( col_sum > max_col ) {
1635  max_col = col_sum;
1636  }
1637  }
1638  return max_col;
1639  }
1641  /*else if (p == '2') {
1642  * double lambda_max;
1643  * FloatMatrix AtA;
1644  * FloatArray eigs;
1645  * AtA.beTProductOf(*this,this);
1646  * Ata.eigenValues(eigs, 1);
1647  * return sqrt(eigs(0));
1648  * } */else {
1649  OOFEM_ERROR("p == %d not implemented.\n", p);
1650  return 0.0;
1651  }
1652 # endif
1653 }
1654 
1655 
1656 
1658 {
1659  // Revrites the vector on matrix form (symmetrized matrix used if size is 6),
1660  // order: 11, 22, 33, 23, 13, 12
1661  // order: 11, 22, 33, 23, 13, 12, 32, 31, 21
1662 # ifdef DEBUG
1663  if ( aArray.giveSize() != 6 && aArray.giveSize() != 9 ) {
1664  OOFEM_ERROR("matrix dimension is not 3x3");
1665  }
1666 # endif
1667  this->resize(3, 3);
1668  if ( aArray.giveSize() == 9 ) {
1669  this->at(1, 1) = aArray.at(1);
1670  this->at(2, 2) = aArray.at(2);
1671  this->at(3, 3) = aArray.at(3);
1672  this->at(2, 3) = aArray.at(4);
1673  this->at(1, 3) = aArray.at(5);
1674  this->at(1, 2) = aArray.at(6);
1675  this->at(3, 2) = aArray.at(7);
1676  this->at(3, 1) = aArray.at(8);
1677  this->at(2, 1) = aArray.at(9);
1678  } else if ( aArray.giveSize() == 6 ) {
1679  this->at(1, 1) = aArray.at(1);
1680  this->at(2, 2) = aArray.at(2);
1681  this->at(3, 3) = aArray.at(3);
1682  this->at(2, 3) = aArray.at(4);
1683  this->at(1, 3) = aArray.at(5);
1684  this->at(1, 2) = aArray.at(6);
1685  this->at(3, 2) = aArray.at(4);
1686  this->at(3, 1) = aArray.at(5);
1687  this->at(2, 1) = aArray.at(6);
1688  }
1689 }
1690 
1692 {
1693  // Changes index order between abaqus <-> OOFEM
1694 //# ifdef DEBUG
1695 // if ( nRows != 6 || nColumns != 6 ) {
1696 // OOFEM_ERROR("matrix dimension is not 6x6");
1697 // }
1698 //# endif
1699 
1700  if ( nRows == 6 && nColumns == 6 ) {
1701  // This could probably be done more beautifully + efficiently.
1702 
1703  std :: swap( this->at(4, 1), this->at(6, 1) );
1704 
1705  std :: swap( this->at(4, 2), this->at(6, 2) );
1706 
1707  std :: swap( this->at(4, 3), this->at(6, 3) );
1708 
1709  std :: swap( this->at(1, 4), this->at(1, 6) );
1710  std :: swap( this->at(2, 4), this->at(2, 6) );
1711  std :: swap( this->at(3, 4), this->at(3, 6) );
1712  std :: swap( this->at(4, 4), this->at(6, 6) );
1713  std :: swap( this->at(5, 4), this->at(5, 6) );
1714  std :: swap( this->at(6, 4), this->at(4, 6) );
1715 
1716  std :: swap( this->at(4, 5), this->at(6, 5) );
1717  } else if ( nRows == 9 && nColumns == 9 ) {
1718  // OOFEM: 11, 22, 33, 23, 13, 12, 32, 31, 21
1719  // UMAT: 11, 22, 33, 12, 13, 23, 32, 21, 31
1720  const int abq2oo [ 9 ] = {
1721  1, 2, 3, 6, 5, 4, 7, 9, 8
1722  };
1723 
1724  FloatMatrix tmp(9, 9);
1725  for ( int i = 1; i <= 9; i++ ) {
1726  for ( int j = 1; j <= 9; j++ ) {
1727  tmp.at(i, j) = this->at(abq2oo [ i - 1 ], abq2oo [ j - 1 ]);
1728  }
1729  }
1730 
1731  * this = tmp;
1732  }
1733 }
1734 
1735 
1736 
1738 {
1739 # ifdef DEBUG
1740  if ( !this->isSquare() ) {
1741  OOFEM_ERROR("receiver must be square (is %d by %d)", this->nRows, this->nColumns);
1742  }
1743 # endif
1744  double anorm = this->computeNorm(p);
1745 
1746 # ifdef __LAPACK_MODULE
1747  int n = this->nRows;
1748  FloatArray work(4 *n);
1749  IntArray iwork(n);
1750  int info;
1751  double rcond;
1752 
1753  if ( n > 3 ) { // Only use this routine for larger matrices. (not sure if it's suitable for n = 3) // Mikael
1754  FloatMatrix a_cpy = * this;
1755  dgetrf_(& n, & n, a_cpy.givePointer(), & n, iwork.givePointer(), & info);
1756  if ( info < 0 ) {
1757  OOFEM_ERROR("dgetfr error %d\n", info);
1758  }
1759  dgecon_(& p, & ( this->nRows ), a_cpy.givePointer(), & this->nRows, & anorm, & rcond, work.givePointer(), iwork.givePointer(), & info, 1);
1760  if ( info < 0 ) {
1761  OOFEM_ERROR("dgecon error %d\n", info);
1762  }
1763  return rcond;
1764  }
1765 # endif
1766  if ( this->giveDeterminant() <= 1e-6 * anorm ) {
1767  return 0.0;
1768  }
1769  FloatMatrix inv;
1770  inv.beInverseOf(* this);
1771  return 1.0 / ( inv.computeNorm(p) * anorm );
1772 }
1773 
1775 {
1776  // Revrites the matrix on vector form (symmetrized matrix used), order: 11, 22, 33, 23, 13, 12
1777 # ifdef DEBUG
1778  if ( aArray.giveSize() != 6 && aArray.giveSize() != 9 ) {
1779  OOFEM_ERROR("matrix dimension is not 3x3");
1780  }
1781 # endif
1782  this->resize(3, 3);
1783  if ( aArray.giveSize() == 9 ) {
1784  this->at(1, 1) = aArray.at(1);
1785  this->at(2, 2) = aArray.at(2);
1786  this->at(3, 3) = aArray.at(3);
1787  this->at(2, 3) = aArray.at(4);
1788  this->at(1, 3) = aArray.at(5);
1789  this->at(1, 2) = aArray.at(6);
1790  this->at(3, 2) = aArray.at(7);
1791  this->at(3, 1) = aArray.at(8);
1792  this->at(2, 1) = aArray.at(9);
1793  } else if ( aArray.giveSize() == 6 ) {
1794  this->at(1, 1) = aArray.at(1);
1795  this->at(2, 2) = aArray.at(2);
1796  this->at(3, 3) = aArray.at(3);
1797  this->at(2, 3) = aArray.at(4);
1798  this->at(1, 3) = aArray.at(5);
1799  this->at(1, 2) = aArray.at(6);
1800  this->at(3, 2) = aArray.at(4);
1801  this->at(3, 1) = aArray.at(5);
1802  this->at(2, 1) = aArray.at(6);
1803  }
1804 }
1805 
1806 #if 0
1807 bool FloatMatrix :: computeEigenValuesSymmetric(FloatArray &lambda, FloatMatrix &v, int neigs) const
1808 {
1809  #ifdef __LAPACK_MODULE
1810  double abstol = 1.0;
1811  int lda, n, ldz, info, found, lwork;
1812  n = this->nRows;
1813  lda = n;
1814  ldz = n;
1815  FloatMatrix a;
1816  a = * this;
1817  if ( neigs == 0 ) {
1818  neigs = n;
1819  }
1820 
1821  lambda.resize(neigs);
1822  v.resize(n, neigs);
1823 
1824  IntArray ifail(n), iwork(5 * n);
1825  FloatArray work( ( n + 3 ) *n ); // maximum block size should be less than n (?)
1826  lwork = ( n + 3 ) * n;
1827  if ( neigs > 0 ) {
1828  int one = 1;
1829  dsyevx_("N", "I", "U",
1830  & n, a.givePointer(), & n,
1831  NULL, NULL, & one, & neigs,
1832  & abstol, & found, lambda.givePointer(), v.givePointer(), & ldz,
1833  work.givePointer(), & lwork, iwork.givePointer(), ifail.givePointer(), & info, 1, 1, 1);
1834  } else {
1835  dsyevx_("N", "A", "U",
1836  & n, a.givePointer(), & n,
1837  NULL, NULL, NULL, NULL,
1838  & abstol, & found, lambda.givePointer(), v.givePointer(), & ldz,
1839  work.givePointer(), & lwork, iwork.givePointer(), ifail.givePointer(), & info, 1, 1, 1);
1840  }
1841 
1842  return info == 0;
1843 
1844  #else
1845  OOFEM_ERROR("Requires LAPACK");
1846  return false;
1847 
1848  #endif
1849 }
1850 #endif
1851 
1853 // writes receiver's binary image into stream
1854 // use id to distinguish some instances
1855 // return value >0 success
1856 // =0 file i/o error
1857 {
1858  // write size
1859  if ( !stream.write(nRows) ) {
1860  return ( CIO_IOERR );
1861  }
1862 
1863  if ( !stream.write(nColumns) ) {
1864  return ( CIO_IOERR );
1865  }
1866 
1867  // write raw data
1868  if ( !stream.write(this->givePointer(), nRows * nColumns) ) {
1869  return ( CIO_IOERR );
1870  }
1871 
1872  // return result back
1873  return CIO_OK;
1874 }
1875 
1876 
1878 // reads receiver from stream
1879 // warning - overwrites existing data!
1880 // returns 0 if file i/o error
1881 // -1 if id of class id is not correct
1882 {
1883  // read size
1884  if ( !stream.read(nRows) ) {
1885  return ( CIO_IOERR );
1886  }
1887 
1888  if ( !stream.read(nColumns) ) {
1889  return ( CIO_IOERR );
1890  }
1891 
1892  this->values.resize(nRows * nColumns);
1893 
1894  // read raw data
1895  if ( !stream.read(this->givePointer(), nRows * nColumns) ) {
1896  return ( CIO_IOERR );
1897  }
1898 
1899  // return result back
1900  return CIO_OK;
1901 }
1902 
1903 
1904 int
1906 {
1907  return buff.givePackSizeOfInt(1) + buff.givePackSizeOfInt(1) +
1909 }
1910 
1911 
1913 {
1914  /*
1915  * Solves the eigenvalues and eigenvectors of real
1916  * symmetric matrix by jacobi method.
1917  * Written by bp. Inspired by ED WILSON jaco_ procedure.
1918  *
1919  * Parameters (input):
1920  * nf - number of significant figures
1921  *
1922  * Output params:
1923  * eval - eigen values (not sorted)
1924  * v - eigenvectors (stored columvise)
1925  */
1926 
1927 
1928  /* Local variables */
1929  double ssum, aa, co, si, tt, tol, sum, aij, aji;
1930  int ite, i, j, k, ih;
1931  int neq = this->giveNumberOfRows();
1932 
1933  double c_b2 = .10;
1934  //double c_b27 = .01;
1935 
1936  /* Function Body */
1937 #ifdef DEBUG
1938  if ( !isSquare() ) {
1939  OOFEM_ERROR("Not square matrix");
1940  }
1941  // check for symmetry
1942  for ( i = 1; i <= neq; i++ ) {
1943  for ( j = i + 1; j <= neq; j++ ) {
1944  //if ( this->at(i, j) != this->at(j, i) ) {
1945  if ( fabs( this->at(i, j) - this->at(j, i) ) > 1.0e-6 ) {
1946  OOFEM_ERROR("Not Symmetric matrix");
1947  }
1948  }
1949  }
1950 
1951 #endif
1952 
1953  eval.resize(neq);
1954  v.resize(neq, neq);
1955 
1956  for ( i = 1; i <= neq; i++ ) {
1957  eval.at(i) = this->at(i, i);
1958  }
1959 
1960  tol = pow(c_b2, nf);
1961  sum = 0.0;
1962  for ( i = 1; i <= neq; ++i ) {
1963  for ( j = 1; j <= neq; ++j ) {
1964  sum += fabs( this->at(i, j) );
1965  v.at(i, j) = 0.0;
1966  }
1967 
1968  v.at(i, i) = 1.0;
1969  }
1970 
1971  if ( sum <= 0.0 ) {
1972  return 0;
1973  }
1974 
1975 
1976  /* ---- REDUCE MATRIX TO DIAGONAL ---------------- */
1977  ite = 0;
1978  do {
1979  ssum = 0.0;
1980  for ( j = 2; j <= neq; ++j ) {
1981  ih = j - 1;
1982  for ( i = 1; i <= ih; ++i ) {
1983  if ( ( fabs( this->at(i, j) ) / sum ) > tol ) {
1984  ssum += fabs( this->at(i, j) );
1985  /* ---- CALCULATE ROTATION ANGLE ----------------- */
1986  aa = atan2( this->at(i, j) * 2.0, eval.at(i) - eval.at(j) ) / 2.0;
1987  si = sin(aa);
1988  co = cos(aa);
1989  /*
1990  * // ---- MODIFY "I" AND "J" COLUMNS OF "A" AND "V"
1991  * for (k = 1; k <= neq; ++k) {
1992  * tt = this->at(k, i);
1993  * this->at(k, i) = co * tt + si * this->at(k, j);
1994  * this->at(k, j) = -si * tt + co * this->at(k, j);
1995  * tt = v.at(k, i);
1996  * v.at(k, i) = co * tt + si * v.at(k, j);
1997  * // L500:
1998  * v.at(k, j) = -si * tt + co * v.at(k, j);
1999  * }
2000  * // ---- MODIFY DIAGONAL TERMS --------------------
2001  * this->at(i, i) = co * this->at(i, i) + si * this->at(j, i);
2002  * this->at(j, j) = -si * this->at(i, j) + co * this->at(j, j);
2003  * this->at(i, j) = 0.0;
2004  * // ---- MAKE "A" MATRIX SYMMETRICAL --------------
2005  * for (k = 1; k <= neq; ++k) {
2006  * this->at(i, k) = this->at(k, i);
2007  * this->at(j, k) = this->at(k, j);
2008  * // L600:
2009  * }
2010  */
2011  // ---- MODIFY "I" AND "J" COLUMNS OF "A" AND "V"
2012  for ( k = 1; k < i; ++k ) {
2013  tt = this->at(k, i);
2014  this->at(k, i) = co * tt + si *this->at(k, j);
2015  this->at(k, j) = -si * tt + co *this->at(k, j);
2016  tt = v.at(k, i);
2017  v.at(k, i) = co * tt + si *v.at(k, j);
2018  v.at(k, j) = -si * tt + co *v.at(k, j);
2019  }
2020 
2021  // diagonal term (i,i)
2022  tt = eval.at(i);
2023  eval.at(i) = co * tt + si *this->at(i, j);
2024  aij = -si * tt + co *this->at(i, j);
2025  tt = v.at(i, i);
2026  v.at(i, i) = co * tt + si *v.at(i, j);
2027  v.at(i, j) = -si * tt + co *v.at(i, j);
2028 
2029  for ( k = i + 1; k < j; ++k ) {
2030  tt = this->at(i, k);
2031  this->at(i, k) = co * tt + si *this->at(k, j);
2032  this->at(k, j) = -si * tt + co *this->at(k, j);
2033  tt = v.at(k, i);
2034  v.at(k, i) = co * tt + si *v.at(k, j);
2035  v.at(k, j) = -si * tt + co *v.at(k, j);
2036  }
2037 
2038  // diagonal term (j,j)
2039  tt = this->at(i, j);
2040  aji = co * tt + si *eval.at(j);
2041  eval.at(j) = -si * tt + co *eval.at(j);
2042 
2043  tt = v.at(j, i);
2044  v.at(j, i) = co * tt + si *v.at(j, j);
2045  v.at(j, j) = -si * tt + co *v.at(j, j);
2046  //
2047  for ( k = j + 1; k <= neq; ++k ) {
2048  tt = this->at(i, k);
2049  this->at(i, k) = co * tt + si *this->at(j, k);
2050  this->at(j, k) = -si * tt + co *this->at(j, k);
2051  tt = v.at(k, i);
2052  v.at(k, i) = co * tt + si *v.at(k, j);
2053  v.at(k, j) = -si * tt + co *v.at(k, j);
2054  }
2055 
2056  // ---- MODIFY DIAGONAL TERMS --------------------
2057  eval.at(i) = co * eval.at(i) + si * aji;
2058  eval.at(j) = -si * aij + co *eval.at(j);
2059  this->at(i, j) = 0.0;
2060  } else {
2061  /* ---- A(I,J) MADE ZERO BY ROTATION ------------- */
2062  ;
2063  }
2064  }
2065  }
2066 
2067  /* ---- CHECK FOR CONVERGENCE -------------------- */
2068  if ( ++ite > 50 ) {
2069  OOFEM_ERROR("too many iterations");
2070  }
2071  } while ( fabs(ssum) / sum > tol );
2072 
2073  // restore original matrix
2074  for ( i = 1; i <= neq; i++ ) {
2075  for ( j = i; j <= neq; j++ ) {
2076  this->at(i, j) = this->at(j, i);
2077  }
2078  }
2079 
2080  return 0;
2081 } /* jaco_ */
2082 
2083 
2084 #ifdef BOOST_PYTHON
2085 void
2086 FloatMatrix :: __setitem__(boost :: python :: api :: object t, double val)
2087 {
2088  this->at(boost :: python :: extract< int >(t [ 0 ]) + 1, boost :: python :: extract< int >(t [ 1 ]) + 1) = val;
2089 }
2090 
2091 double
2092 FloatMatrix :: __getitem__(boost :: python :: api :: object t)
2093 {
2094  return this->at(boost :: python :: extract< int >(t [ 0 ]) + 1, boost :: python :: extract< int >(t [ 1 ]) + 1);
2095 }
2096 #endif
2097 
2098 std :: ostream &operator << ( std :: ostream & out, const FloatMatrix & x )
2099 {
2100  out << x.nRows << " " << x.nColumns << " {";
2101  for ( int i = 0; i < x.nRows; ++i ) {
2102  for ( int j = 0; j < x.nColumns; ++j ) {
2103  out << " " << x(i, j);
2104  }
2105  out << ";";
2106  }
2107  out << "}";
2108  return out;
2109 }
2110 } // end namespace oofem
int nRows
Number of rows.
Definition: floatmatrix.h:98
double giveDeterminant() const
Returns the trace (sum of diagonal components) of the receiver.
Definition: floatmatrix.C:1408
double computeNorm(char p) const
Computes the operator norm of the receiver.
Definition: floatmatrix.C:1618
int giveNumberOfColumns() const
Returns number of columns of receiver.
Definition: floatmatrix.h:158
void initFromVector(const FloatArray &vector, bool transposed)
Assigns to receiver one column or one row matrix containing vector.
Definition: floatmatrix.C:1308
#define RESIZE(nr, nc)
Definition: floatmatrix.C:55
void bePinvID()
Sets receiver to the inverse of scaling matrix P multiplied by the deviatoric projector ID...
Definition: floatmatrix.C:1347
void addTProductOf(const FloatMatrix &a, const FloatMatrix &b)
Adds to the receiver product of .
Definition: floatmatrix.C:459
void beVectorProductOf(const FloatArray &v1, const FloatArray &v2)
Computes vector product (or cross product) of vectors given as parameters, , and stores the result in...
Definition: floatarray.C:415
void writeCSV(const std::string &name) const
Writes receiver as CSV (comma seperated values)
Definition: floatmatrix.C:1543
bool solveForRhs(const FloatArray &b, FloatArray &answer, bool transpose=false)
Solves the system of linear equations .
Definition: floatmatrix.C:1112
std::vector< double > values
Stored values.
Definition: floatarray.h:86
The purpose of DataStream abstract class is to allow to store/restore context to different streams...
Definition: datastream.h:54
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
int max(int i, int j)
Returns bigger value form two given decimals.
Definition: mathfem.h:71
void beSubMatrixOf(const FloatMatrix &src, int topRow, int bottomRow, int topCol, int bottomCol)
Assigns to the receiver the sub-matrix of another matrix.
Definition: floatmatrix.C:962
int minimum() const
Finds the minimum component in the array.
Definition: intarray.C:184
void pY() const
Higher accuracy than printYourself.
Definition: floatmatrix.C:1524
bool isFinite() const
Returns true if no element is NAN or infinite.
Definition: floatmatrix.C:209
void beDiagonal(const FloatArray &diag)
Modifies receiver to be a diagonal matrix with the components specified in diag.
Definition: floatmatrix.C:1433
bool isSquare() const
Returns nonzero if receiver is square matrix.
Definition: floatmatrix.h:160
General IO error.
void negated()
Changes sign of receiver values.
Definition: floatmatrix.C:1605
const int * givePointer() const
Breaks encapsulation.
Definition: intarray.h:336
const double * givePointer() const
Exposes the internal values of the matrix.
Definition: floatmatrix.h:558
void plusDyadUnsym(const FloatArray &a, const FloatArray &b, double dV)
Adds to the receiver the product .
Definition: floatmatrix.C:811
int givePackSize(DataStream &buff) const
Definition: floatmatrix.C:1905
void printYourselfToFile(const std::string filename, const bool showDimensions=true) const
Print matrix to file.
Definition: floatmatrix.C:1477
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
virtual int read(int *data, int count)=0
Reads count integer values into array pointed by data.
double computeReciprocalCondition(char p= '1') const
Computes the conditioning of the receiver.
Definition: floatmatrix.C:1737
contextIOResultType storeYourself(DataStream &stream) const
Definition: floatmatrix.C:1852
int nColumns
Number of columns.
Definition: floatmatrix.h:100
void setSubMatrix(const FloatMatrix &src, int sr, int sc)
Adds the given matrix as sub-matrix to receiver.
Definition: floatmatrix.C:557
void beMatrixForm(const FloatArray &aArray)
Definition: floatmatrix.C:1657
bool isNotEmpty() const
Tests for empty matrix.
Definition: floatmatrix.h:162
void plusProductUnsym(const FloatMatrix &a, const FloatMatrix &b, double dV)
Adds to the receiver the product .
Definition: floatmatrix.C:780
bool jaco_(FloatArray &eval, FloatMatrix &v, int nf)
Computes eigenvalues and eigenvectors of receiver (must be symmetric) The receiver is preserved...
Definition: floatmatrix.C:1912
FloatMatrix & operator=(std::initializer_list< std::initializer_list< double > >mat)
Assignment operator.
Definition: floatmatrix.C:149
void checkBounds(int i, int j) const
Checks size of receiver towards requested bounds.
Definition: floatmatrix.C:189
double dotProduct(const FloatArray &x) const
Computes the dot product (or inner product) of receiver and argument.
Definition: floatarray.C:463
#define OOFEM_ERROR(...)
Definition: error.h:61
double giveTrace() const
Returns the trace of the receiver.
Definition: floatmatrix.C:1443
void copySubVectorRow(const FloatArray &src, int sr, int sc)
Copy (set) given vector to receiver row sr, starting at column sc.
Definition: floatmatrix.C:677
void resizeWithData(int, int)
Checks size of receiver towards requested bounds.
Definition: floatmatrix.C:1369
void times(double f)
Multiplies receiver by factor f.
Definition: floatmatrix.C:1594
void rotatedWith(const FloatMatrix &r, char mode= 'n')
Returns the receiver &#39;a&#39; transformed using give transformation matrix r.
Definition: floatmatrix.C:1557
void addProductOf(const FloatMatrix &a, const FloatMatrix &b)
Adds to the receiver product of .
Definition: floatmatrix.C:427
int maximum() const
Finds the maximum component in the array.
Definition: intarray.C:195
void beLocalCoordSys(const FloatArray &normal)
Makes receiver the local coordinate for the given normal.
Definition: floatmatrix.C:515
void plusProductSymmUpper(const FloatMatrix &a, const FloatMatrix &b, double dV)
Adds to the receiver the product .
Definition: floatmatrix.C:698
double at(int i, int j) const
Coefficient access function.
Definition: floatmatrix.h:176
void beNMatrixOf(const FloatArray &n, int nsd)
Assigns the receiver to be a repeated diagonal matrix.
Definition: floatmatrix.C:505
void subtract(const FloatMatrix &a)
Subtracts matrix from the receiver.
Definition: floatmatrix.C:1084
contextIOResultType restoreYourself(DataStream &stream)
Definition: floatmatrix.C:1877
Class representing vector of real numbers.
Definition: floatarray.h:82
void plusDyadSymmUpper(const FloatArray &a, double dV)
Adds to the receiver the dyadic product .
Definition: floatmatrix.C:756
FloatMatrix()
Creates zero sized matrix.
Definition: floatmatrix.h:112
Implementation of matrix containing floating point numbers.
Definition: floatmatrix.h:94
double & operator()(int i, int j)
Coefficient access function.
Definition: floatmatrix.h:199
double computeFrobeniusNorm() const
Computes the Frobenius norm of the receiver.
Definition: floatmatrix.C:1613
virtual int givePackSizeOfDouble(int count)=0
void beMatrixFormOfStress(const FloatArray &aArray)
Reciever will be a 3x3 matrix formed from a vector with either 9 or 6 components. ...
Definition: floatmatrix.C:1774
void changeComponentOrder()
Swaps the indices in the 6x6 matrix such that it converts between OOFEM&#39;s and Abaqus&#39; way of writing ...
Definition: floatmatrix.C:1691
void addSubVectorCol(const FloatArray &src, int sr, int sc)
Adds given vector to receiver starting at given position.
Definition: floatmatrix.C:627
double norm(const FloatArray &x)
Definition: floatarray.C:985
void resize(int rows, int cols)
Checks size of receiver towards requested bounds.
Definition: floatmatrix.C:1358
void add(const FloatMatrix &a)
Adds matrix to the receiver.
Definition: floatmatrix.C:1023
void beDyadicProductOf(const FloatArray &vec1, const FloatArray &vec2)
Assigns to the receiver the dyadic product .
Definition: floatmatrix.C:492
void copyColumn(FloatArray &dest, int c) const
Fetches the values from the specified column.
Definition: floatmatrix.C:662
void beTProductOf(const FloatMatrix &a, const FloatMatrix &b)
Assigns to the receiver product of .
Definition: floatmatrix.C:367
void setColumn(const FloatArray &src, int c)
Sets the values of the matrix in specified column.
Definition: floatmatrix.C:648
void beTranspositionOf(const FloatMatrix &src)
Assigns to the receiver the transposition of parameter.
Definition: floatmatrix.C:323
const double * givePointer() const
Gives the pointer to the raw data, breaking encapsulation.
Definition: floatarray.h:469
void printYourself() const
Prints matrix to stdout. Useful for debugging.
Definition: floatmatrix.C:1458
std::vector< double >::iterator end()
Definition: floatarray.h:92
void beProductTOf(const FloatMatrix &a, const FloatMatrix &b)
Assigns to the receiver product of .
Definition: floatmatrix.C:397
void zero()
Zeroes all coefficient of receiver.
Definition: floatmatrix.C:1326
std::vector< double > values
Values of matrix stored column wise.
Definition: floatmatrix.h:102
int min(int i, int j)
Returns smaller value from two given decimals.
Definition: mathfem.h:59
void beUnitMatrix()
Sets receiver to unity matrix.
Definition: floatmatrix.C:1332
void hardResize(int r, int c)
Resizing that enforces reallocation of memory.
Definition: floatmatrix.C:1396
void setTSubMatrix(const FloatMatrix &src, int sr, int sc)
Adds the given matrix as sub-matrix to receiver.
Definition: floatmatrix.C:582
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
Assigns to the receiver product of .
Definition: floatmatrix.C:337
int giveSize() const
Definition: intarray.h:203
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.
void assemble(const FloatMatrix &src, const IntArray &loc)
Assembles the contribution using localization array into receiver.
Definition: floatmatrix.C:251
friend std::ostream & operator<<(std::ostream &out, const FloatMatrix &r)
Definition: floatmatrix.C:2098
void beInverseOf(const FloatMatrix &src)
Modifies receiver to become inverse of given parameter.
Definition: floatmatrix.C:835
double normalize()
Normalizes receiver.
Definition: floatarray.C:828
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition: floatmatrix.h:156
void addSubVectorRow(const FloatArray &src, int sr, int sc)
Adds given vector to receiver starting at given position.
Definition: floatmatrix.C:607
void symmetrized()
Initializes the lower half of the receiver according to the upper half.
Definition: floatmatrix.C:1576
void add(const FloatArray &src)
Adds array src to receiver.
Definition: floatarray.C:156
std::vector< double >::iterator begin()
Definition: floatarray.h:91
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631
virtual int givePackSizeOfInt(int count)=0

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:28 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011