1 //-----------------------------------------------------------------------bl-
2 //--------------------------------------------------------------------------
3 //
4 // QUESO - a library to support the Quantification of Uncertainty
5 // for Estimation, Simulation and Optimization
6 //
7 // Copyright (C) 2008-2017 The PECOS Development Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the Version 2.1 GNU Lesser General
11 // Public License as published by the Free Software Foundation.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc. 51 Franklin Street, Fifth Floor,
21 // Boston, MA 02110-1301 USA
22 //
23 //-----------------------------------------------------------------------el-
24
25 #include <queso/GslMatrix.h>
26 #include <queso/GslVector.h>
27 #include <queso/Defines.h>
28 #include <queso/FilePtr.h>
29 #include <gsl/gsl_linalg.h>
30 #include <gsl/gsl_eigen.h>
31 #include <sys/time.h>
32 #include <cmath>
33
34 namespace QUESO {
35
GslMatrix(const BaseEnvironment & env,const Map & map,unsigned int nCols)36 GslMatrix::GslMatrix( // can be a rectangular matrix
37 const BaseEnvironment& env,
38 const Map& map,
39 unsigned int nCols)
40 :
41 Matrix (env,map),
42 m_mat (gsl_matrix_calloc(map.NumGlobalElements(),nCols)),
43 m_LU (NULL),
44 m_chol(),
45 m_inverse (NULL),
46 m_svdColMap (NULL),
47 m_svdUmat (NULL),
48 m_svdSvec (NULL),
49 m_svdVmat (NULL),
50 m_svdVTmat (NULL),
51 m_determinant (-INFINITY),
52 m_lnDeterminant(-INFINITY),
53 m_permutation (NULL),
54 m_signum (0),
55 m_isSingular (false)
56 {
57 queso_require_msg(m_mat, "null matrix generated");
58 }
59
60 // Shaped constructor --------------------------------------------------
GslMatrix(const BaseEnvironment & env,const Map & map,double diagValue)61 GslMatrix::GslMatrix( // square matrix
62 const BaseEnvironment& env,
63 const Map& map,
64 double diagValue)
65 :
66 Matrix (env,map),
67 m_mat (gsl_matrix_calloc(map.NumGlobalElements(),map.NumGlobalElements())),
68 m_LU (NULL),
69 m_chol(),
70 m_inverse (NULL),
71 m_svdColMap (NULL),
72 m_svdUmat (NULL),
73 m_svdSvec (NULL),
74 m_svdVmat (NULL),
75 m_svdVTmat (NULL),
76 m_determinant (-INFINITY),
77 m_lnDeterminant(-INFINITY),
78 m_permutation (NULL),
79 m_signum (0),
80 m_isSingular (false)
81 {
82 queso_require_msg(m_mat, "null matrix generated");
83
84 for (unsigned int i = 0; i < m_mat->size1; ++i) {
85 (*this)(i,i) = diagValue;
86 }
87 }
88 // Shaped constructor --------------------------------------------------
GslMatrix(const GslVector & v,double diagValue)89 GslMatrix::GslMatrix( // square matrix
90 const GslVector& v,
91 double diagValue)
92 :
93 Matrix (v.env(),v.map()),
94 m_mat (gsl_matrix_calloc(v.sizeLocal(),v.sizeLocal())),
95 m_LU (NULL),
96 m_chol(),
97 m_inverse (NULL),
98 m_svdColMap (NULL),
99 m_svdUmat (NULL),
100 m_svdSvec (NULL),
101 m_svdVmat (NULL),
102 m_svdVTmat (NULL),
103 m_determinant (-INFINITY),
104 m_lnDeterminant(-INFINITY),
105 m_permutation (NULL),
106 m_signum (0),
107 m_isSingular (false)
108 {
109 queso_require_msg(m_mat, "null matrix generated");
110
111 for (unsigned int i = 0; i < m_mat->size1; ++i) {
112 (*this)(i,i) = diagValue;
113 }
114 }
115 // Shaped constructor --------------------------------------------------
GslMatrix(const GslVector & v)116 GslMatrix::GslMatrix(const GslVector& v) // square matrix
117 :
118 Matrix (v.env(),v.map()),
119 m_mat (gsl_matrix_calloc(v.sizeLocal(),v.sizeLocal())),
120 m_LU (NULL),
121 m_chol(),
122 m_inverse (NULL),
123 m_svdColMap (NULL),
124 m_svdUmat (NULL),
125 m_svdSvec (NULL),
126 m_svdVmat (NULL),
127 m_svdVTmat (NULL),
128 m_determinant (-INFINITY),
129 m_lnDeterminant(-INFINITY),
130 m_permutation (NULL),
131 m_signum (0),
132 m_isSingular (false)
133 {
134 queso_require_msg(m_mat, "null matrix generated");
135
136 unsigned int dim = v.sizeLocal();
137 for (unsigned int i = 0; i < dim; ++i) {
138 (*this)(i,i) = v[i];
139 }
140 }
141
142 // Shaped constructor --------------------------------------------------
GslMatrix(const GslMatrix & B)143 GslMatrix::GslMatrix(const GslMatrix& B) // can be a rectangular matrix
144 :
145 Matrix (B.env(),B.map()),
146 m_mat (gsl_matrix_calloc(B.numRowsLocal(),B.numCols())),
147 m_LU (NULL),
148 m_chol(),
149 m_inverse (NULL),
150 m_svdColMap (NULL),
151 m_svdUmat (NULL),
152 m_svdSvec (NULL),
153 m_svdVmat (NULL),
154 m_svdVTmat (NULL),
155 m_determinant (-INFINITY),
156 m_lnDeterminant(-INFINITY),
157 m_permutation (NULL),
158 m_signum (0),
159 m_isSingular (false)
160 {
161 queso_require_msg(m_mat, "null vector generated");
162 this->Matrix::base_copy(B);
163 this->copy(B);
164 }
165
166 // Destructor ----------------------------------------------------------
~GslMatrix()167 GslMatrix::~GslMatrix()
168 {
169 this->reset();
170 if (m_mat) gsl_matrix_free(m_mat);
171 }
172
173 // Set methods (operators) ---------------------------------------------
174 GslMatrix&
175 GslMatrix::operator=(const GslMatrix& obj)
176 {
177 this->reset();
178 this->copy(obj);
179 return *this;
180 }
181
182 GslMatrix&
183 GslMatrix::operator*=(double a)
184 {
185 this->reset();
186 int iRC;
187 iRC = gsl_matrix_scale(m_mat,a);
188 queso_require_msg(!(iRC), "scaling failed");
189 return *this;
190 }
191
192 GslMatrix&
193 GslMatrix::operator/=(double a)
194 {
195 this->reset();
196 *this *= (1./a);
197
198 return *this;
199 }
200
201 GslMatrix&
202 GslMatrix::operator+=(const GslMatrix& rhs)
203 {
204 this->reset();
205 int iRC;
206 iRC = gsl_matrix_add(m_mat,rhs.m_mat);
207 queso_require_msg(!(iRC), "failed");
208
209 return *this;
210 }
211
212 GslMatrix&
213 GslMatrix::operator-=(const GslMatrix& rhs)
214 {
215 this->reset();
216 int iRC;
217 iRC = gsl_matrix_sub(m_mat,rhs.m_mat);
218 queso_require_msg(!(iRC), "failed");
219
220 return *this;
221 }
222
223
224
225 void
copy(const GslMatrix & src)226 GslMatrix::copy(const GslMatrix& src)
227 {
228 // FIXME - should we be calling Matrix::base_copy here? - RHS
229 this->reset();
230 int iRC;
231 iRC = gsl_matrix_memcpy(this->m_mat, src.m_mat);
232 queso_require_msg(!(iRC), "failed");
233
234 return;
235 }
236
237 void
reset()238 GslMatrix::reset()
239 {
240 m_chol.reset();
241 if (m_LU) {
242 gsl_matrix_free(m_LU);
243 m_LU = NULL;
244 }
245 if (m_inverse) {
246 delete m_inverse;
247 m_inverse = NULL;
248 }
249 if (m_svdColMap) {
250 delete m_svdColMap;
251 m_svdColMap = NULL;
252 }
253 if (m_svdUmat) {
254 delete m_svdUmat;
255 m_svdUmat = NULL;
256 }
257 if (m_svdSvec) {
258 delete m_svdSvec;
259 m_svdSvec = NULL;
260 }
261 if (m_svdVmat) {
262 delete m_svdVmat;
263 m_svdVmat = NULL;
264 }
265 if (m_svdVTmat) {
266 delete m_svdVTmat;
267 m_svdVTmat = NULL;
268 }
269 m_determinant = -INFINITY;
270 m_lnDeterminant = -INFINITY;
271 if (m_permutation) {
272 gsl_permutation_free(m_permutation);
273 m_permutation = NULL;
274 }
275 m_signum = 0;
276 m_isSingular = false;
277
278 return;
279 }
280
281 unsigned int
numRowsLocal()282 GslMatrix::numRowsLocal() const
283 {
284 return m_mat->size1;
285 }
286
287 unsigned int
numRowsGlobal()288 GslMatrix::numRowsGlobal() const
289 {
290 return m_mat->size1;
291 }
292
293 unsigned int
numCols()294 GslMatrix::numCols() const
295 {
296 return m_mat->size2;
297 }
298
299 double
normFrob()300 GslMatrix::normFrob() const
301 {
302 double value = 0.;
303
304 unsigned int nRows = this->numRowsLocal();
305 unsigned int nCols = this->numCols();
306 double aux = 0.;
307 for (unsigned int i = 0; i < nRows; i++) {
308 for (unsigned int j = 0; j < nCols; j++) {
309 aux = (*this)(i,j);
310 value += aux*aux;
311 }
312 }
313
314 return sqrt(value);
315 }
316
317 double
normMax()318 GslMatrix::normMax() const
319 {
320 double value = 0.;
321
322 unsigned int nRows = this->numRowsLocal();
323 unsigned int nCols = this->numCols();
324 double aux = 0.;
325 for (unsigned int i = 0; i < nRows; i++) {
326 for (unsigned int j = 0; j < nCols; j++) {
327 aux = fabs((*this)(i,j));
328 if (aux > value) value = aux;
329 }
330 }
331
332 return value;
333 }
334
335 double
max()336 GslMatrix::max() const
337 {
338 double value = -INFINITY;
339
340 unsigned int nRows = this->numRowsLocal();
341 unsigned int nCols = this->numCols();
342 double aux = 0.;
343 for (unsigned int i = 0; i < nRows; i++) {
344 for (unsigned int j = 0; j < nCols; j++) {
345 aux = (*this)(i,j);
346 if (aux > value) value = aux;
347 }
348 }
349
350 return value;
351 }
352
353 void
cwSet(double value)354 GslMatrix::cwSet(double value)
355 {
356 unsigned int nRows = this->numRowsLocal();
357 unsigned int nCols = this->numCols();
358
359 for (unsigned int row = 0; row < nRows; ++row) {
360 for (unsigned int col = 0; col < nCols; ++col) {
361 *gsl_matrix_ptr(m_mat,row,col) = value;
362 }
363 }
364
365 return;
366 }
367
368 void
cwSet(unsigned int initialTargetRowId,unsigned int initialTargetColId,const GslMatrix & mat)369 GslMatrix::cwSet(
370 unsigned int initialTargetRowId,
371 unsigned int initialTargetColId,
372 const GslMatrix& mat)
373 {
374 queso_require_less_msg(initialTargetRowId, this->numRowsLocal(), "invalid initialTargetRowId");
375
376 queso_require_less_equal_msg((initialTargetRowId + mat.numRowsLocal()), this->numRowsLocal(), "invalid vec.numRowsLocal()");
377
378 queso_require_less_msg(initialTargetColId, this->numCols(), "invalid initialTargetColId");
379
380 queso_require_less_equal_msg((initialTargetColId + mat.numCols()), this->numCols(), "invalid vec.numCols()");
381
382 for (unsigned int i = 0; i < mat.numRowsLocal(); ++i) {
383 for (unsigned int j = 0; j < mat.numCols(); ++j) {
384 (*this)(initialTargetRowId+i,initialTargetColId+j) = mat(i,j);
385 }
386 }
387
388 return;
389 }
390
391 void
cwExtract(unsigned int initialTargetRowId,unsigned int initialTargetColId,GslMatrix & mat)392 GslMatrix::cwExtract(
393 unsigned int initialTargetRowId,
394 unsigned int initialTargetColId,
395 GslMatrix& mat) const
396 {
397 queso_require_less_msg(initialTargetRowId, this->numRowsLocal(), "invalid initialTargetRowId");
398
399 queso_require_less_equal_msg((initialTargetRowId + mat.numRowsLocal()), this->numRowsLocal(), "invalid vec.numRowsLocal()");
400
401 queso_require_less_msg(initialTargetColId, this->numCols(), "invalid initialTargetColId");
402
403 queso_require_less_equal_msg((initialTargetColId + mat.numCols()), this->numCols(), "invalid vec.numCols()");
404
405 for (unsigned int i = 0; i < mat.numRowsLocal(); ++i) {
406 for (unsigned int j = 0; j < mat.numCols(); ++j) {
407 mat(i,j) = (*this)(initialTargetRowId+i,initialTargetColId+j) ;
408 }
409 }
410
411 return;
412 }
413
414 int
chol()415 GslMatrix::chol()
416 {
417 int iRC;
418 //std::cout << "Calling gsl_linalg_cholesky_decomp()..." << std::endl;
419 gsl_error_handler_t* oldHandler;
420 oldHandler = gsl_set_error_handler_off();
421 iRC = gsl_linalg_cholesky_decomp(m_mat);
422 if (iRC != 0) {
423 std::cerr << "In GslMatrix::chol()"
424 << ": iRC = " << iRC
425 << ", gsl error message = " << gsl_strerror(iRC)
426 << std::endl;
427 std::cerr << "Here is the offending matrix: " << std::endl;
428 std::cerr << *this << std::endl;
429 }
430 gsl_set_error_handler(oldHandler);
431 //std::cout << "Returned from gsl_linalg_cholesky_decomp() with iRC = " << iRC << std::endl;
432 UQ_RC_MACRO(iRC, // Yes, *not* a fatal check on RC
433 m_env.worldRank(),
434 "GslMatrix::chol()",
435 "matrix is not positive definite",
436 UQ_MATRIX_IS_NOT_POS_DEFINITE_RC);
437
438 return iRC;
439 }
440
441 void
cholSolve(const GslVector & rhs,GslVector & sol)442 GslMatrix::cholSolve(const GslVector & rhs, GslVector & sol) const
443 {
444 queso_require_equal_to_msg(this->numCols(), rhs.sizeLocal(), "matrix and rhs have incompatible sizes");
445 queso_require_equal_to_msg(sol.sizeLocal(), rhs.sizeLocal(), "solution and rhs have incompatible sizes");
446
447 int iRC;
448 if (m_chol == NULL) {
449 gsl_error_handler_t * oldHandler;
450 oldHandler = gsl_set_error_handler_off();
451
452 // Returns NULL if the allocation failed
453 m_chol.reset(gsl_matrix_calloc(this->numRowsLocal(), this->numCols()),
454 gsl_matrix_free);
455 if (m_chol == NULL) {
456 gsl_set_error_handler(oldHandler);
457 queso_error_msg("gsl_matrix_calloc() failed");
458 }
459
460 iRC = gsl_matrix_memcpy(m_chol.get(), m_mat);
461 if (iRC != 0) {
462 gsl_set_error_handler(oldHandler);
463 queso_error_msg("gsl_matrix_memcpy() failed");
464 }
465
466 iRC = gsl_linalg_cholesky_decomp(m_chol.get());
467 if (iRC != 0) { // Clean up if the matrix isn't spd
468 gsl_set_error_handler(oldHandler);
469 queso_error_msg("gsl_linalg_chol_decomp() failed: " << gsl_strerror(iRC));
470 }
471 }
472
473 gsl_error_handler_t * oldHandler;
474 oldHandler = gsl_set_error_handler_off();
475
476 iRC = gsl_linalg_cholesky_solve(m_chol.get(), rhs.data(), sol.data());
477
478 gsl_set_error_handler(oldHandler);
479
480 queso_require_msg(!iRC, "gsl_linalg_cholesky_solve failed: " << gsl_strerror(iRC));
481 }
482
483 int
svd(GslMatrix & matU,GslVector & vecS,GslMatrix & matVt)484 GslMatrix::svd(GslMatrix& matU, GslVector& vecS, GslMatrix& matVt) const
485 {
486 unsigned int nRows = this->numRowsLocal();
487 unsigned int nCols = this->numCols();
488
489 queso_require_msg(!((matU.numRowsLocal() != nRows) || (matU.numCols() != nCols)), "invalid matU");
490
491 queso_require_equal_to_msg(vecS.sizeLocal(), nCols, "invalid vecS");
492
493 queso_require_msg(!((matVt.numRowsLocal() != nCols) || (matVt.numCols() != nCols)), "invalid matVt");
494
495 int iRC = internalSvd();
496
497 matU = *m_svdUmat;
498 vecS = *m_svdSvec;
499 matVt = *m_svdVTmat;
500
501 return iRC;
502 }
503
504 int
svdSolve(const GslVector & rhsVec,GslVector & solVec)505 GslMatrix::svdSolve(const GslVector& rhsVec, GslVector& solVec) const
506 {
507 unsigned int nRows = this->numRowsLocal();
508 unsigned int nCols = this->numCols();
509
510 queso_require_equal_to_msg(rhsVec.sizeLocal(), nRows, "invalid rhsVec");
511
512 queso_require_equal_to_msg(solVec.sizeLocal(), nCols, "invalid solVec");
513
514 int iRC = internalSvd();
515
516 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 5)) {
517 *m_env.subDisplayFile() << "In GslMatrix::svdSolve():"
518 << "\n this->numRowsLocal() = " << this->numRowsLocal()
519 << ", this->numCols() = " << this->numCols()
520 << "\n m_svdUmat->numRowsLocal() = " << m_svdUmat->numRowsLocal()
521 << ", m_svdUmat->numCols() = " << m_svdUmat->numCols()
522 << "\n m_svdVmat->numRowsLocal() = " << m_svdVmat->numRowsLocal()
523 << ", m_svdVmat->numCols() = " << m_svdVmat->numCols()
524 << "\n m_svdSvec->sizeLocal() = " << m_svdSvec->sizeLocal()
525 << "\n rhsVec.sizeLocal() = " << rhsVec.sizeLocal()
526 << "\n solVec.sizeLocal() = " << solVec.sizeLocal()
527 << std::endl;
528 }
529
530 if (iRC == 0) iRC = gsl_linalg_SV_solve(m_svdUmat->data(), m_svdVmat->data(), m_svdSvec->data(), rhsVec.data(), solVec.data());
531
532 return iRC;
533 }
534
535 int
svdSolve(const GslMatrix & rhsMat,GslMatrix & solMat)536 GslMatrix::svdSolve(const GslMatrix& rhsMat, GslMatrix& solMat) const
537 {
538 unsigned int nRows = this->numRowsLocal();
539 unsigned int nCols = this->numCols();
540
541 queso_require_equal_to_msg(rhsMat.numRowsLocal(), nRows, "invalid rhsMat");
542
543 queso_require_equal_to_msg(solMat.numRowsLocal(), nCols, "invalid solMat");
544
545 queso_require_equal_to_msg(rhsMat.numCols(), solMat.numCols(), "rhsMat and solMat are not compatible");
546
547 GslVector rhsVec(m_env,rhsMat.map());
548 GslVector solVec(m_env,solMat.map());
549 int iRC = 0;
550 for (unsigned int j = 0; j < rhsMat.numCols(); ++j) {
551 rhsVec = rhsMat.getColumn(j);
552 iRC = this->svdSolve(rhsVec, solVec);
553 if (iRC) break;
554 solMat.setColumn(j,solVec);
555 }
556
557 return iRC;
558 }
559
560 const GslMatrix&
svdMatU()561 GslMatrix::svdMatU() const
562 {
563 int iRC = 0;
564 iRC = internalSvd();
565 if (iRC) {}; // just to remove compiler warning
566
567 return *m_svdUmat;
568 }
569
570 const GslMatrix&
svdMatV()571 GslMatrix::svdMatV() const
572 {
573 int iRC = 0;
574 iRC = internalSvd();
575 if (iRC) {}; // just to remove compiler warning
576
577 return *m_svdVmat;
578 }
579
580 int
internalSvd()581 GslMatrix::internalSvd() const
582 {
583 int iRC = 0;
584
585 if (m_svdColMap == NULL) {
586 unsigned int nRows = this->numRowsLocal();
587 unsigned int nCols = this->numCols();
588 queso_require_greater_equal_msg(nRows, nCols, "GSL only supports cases where nRows >= nCols");
589
590 m_svdColMap = new Map(this->numCols(),0,this->map().Comm()); // see 'VectorSpace<.,.>::newMap()' in src/basic/src/GslVectorSpace.C
591 m_svdUmat = new GslMatrix(*this); // Yes, 'this'
592 m_svdSvec = new GslVector(m_env,*m_svdColMap);
593 m_svdVmat = new GslMatrix(*m_svdSvec);
594 m_svdVTmat = new GslMatrix(*m_svdSvec);
595
596 //std::cout << "In GslMatrix::internalSvd()"
597 // << ", calling gsl_linalg_SV_decomp_jacobi()..."
598 // << ": nRows = " << nRows
599 // << ", nCols = " << nCols
600 // << std::endl;
601 struct timeval timevalBegin;
602 gettimeofday(&timevalBegin, NULL);
603 gsl_error_handler_t* oldHandler;
604 oldHandler = gsl_set_error_handler_off();
605 #if 1
606 iRC = gsl_linalg_SV_decomp_jacobi(m_svdUmat->data(), m_svdVmat->data(), m_svdSvec->data());
607 #else
608 GslVector vecWork(*m_svdSvec );
609 iRC = gsl_linalg_SV_decomp(m_svdUmat->data(), m_svdVmat->data(), m_svdSvec->data(), vecWork.data());
610 #endif
611 if (iRC != 0) {
612 std::cerr << "In GslMatrix::internalSvd()"
613 << ": iRC = " << iRC
614 << ", gsl error message = " << gsl_strerror(iRC)
615 << std::endl;
616 }
617 gsl_set_error_handler(oldHandler);
618
619 struct timeval timevalNow;
620 gettimeofday(&timevalNow, NULL);
621 //std::cout << "In GslMatrix::internalSvd()"
622 // << ": returned from gsl_linalg_SV_decomp_jacobi() with iRC = " << iRC
623 // << " after " << timevalNow.tv_sec - timevalBegin.tv_sec
624 // << " seconds"
625 // << std::endl;
626 UQ_RC_MACRO(iRC, // Yes, *not* a fatal check on RC
627 m_env.worldRank(),
628 "GslMatrix::internalSvd()",
629 "matrix svd failed",
630 UQ_MATRIX_SVD_FAILED_RC);
631 *m_svdVTmat = m_svdVmat->transpose();
632 }
633
634 return iRC;
635 }
636
637
638
639 void
zeroLower(bool includeDiagonal)640 GslMatrix::zeroLower(bool includeDiagonal)
641 {
642 unsigned int nRows = this->numRowsLocal();
643 unsigned int nCols = this->numCols();
644
645 queso_require_equal_to_msg(nRows, nCols, "routine works only for square matrices");
646
647 this->reset();
648
649 if (includeDiagonal) {
650 for (unsigned int i = 0; i < nRows; i++) {
651 for (unsigned int j = 0; j <= i; j++) {
652 (*this)(i,j) = 0.;
653 }
654 }
655 }
656 else {
657 for (unsigned int i = 0; i < nRows; i++) {
658 for (unsigned int j = 0; j < i; j++) {
659 (*this)(i,j) = 0.;
660 }
661 }
662 }
663
664 return;
665 }
666
667 void
zeroUpper(bool includeDiagonal)668 GslMatrix::zeroUpper(bool includeDiagonal)
669 {
670 unsigned int nRows = this->numRowsLocal();
671 unsigned int nCols = this->numCols();
672
673 queso_require_equal_to_msg(nRows, nCols, "routine works only for square matrices");
674
675 this->reset();
676
677 if (includeDiagonal) {
678 for (unsigned int i = 0; i < nRows; i++) {
679 for (unsigned int j = i; j < nCols; j++) {
680 (*this)(i,j) = 0.;
681 }
682 }
683 }
684 else {
685 for (unsigned int i = 0; i < nRows; i++) {
686 for (unsigned int j = (i+1); j < nCols; j++) {
687 (*this)(i,j) = 0.;
688 }
689 }
690 }
691
692 return;
693 }
694
695 void
filterSmallValues(double thresholdValue)696 GslMatrix::filterSmallValues(double thresholdValue)
697 {
698 unsigned int nRows = this->numRowsLocal();
699 unsigned int nCols = this->numCols();
700 for (unsigned int i = 0; i < nRows; ++i) {
701 for (unsigned int j = 0; j < nCols; ++j) {
702 double aux = (*this)(i,j);
703 // If 'thresholdValue' is negative, no values will be filtered
704 if ((aux < 0. ) &&
705 (-thresholdValue < aux)) {
706 (*this)(i,j) = 0.;
707 }
708 if ((aux > 0. ) &&
709 (thresholdValue > aux)) {
710 (*this)(i,j) = 0.;
711 }
712 }
713 }
714
715 return;
716 }
717
718 void
filterLargeValues(double thresholdValue)719 GslMatrix::filterLargeValues(double thresholdValue)
720 {
721 unsigned int nRows = this->numRowsLocal();
722 unsigned int nCols = this->numCols();
723 for (unsigned int i = 0; i < nRows; ++i) {
724 for (unsigned int j = 0; j < nCols; ++j) {
725 double aux = (*this)(i,j);
726 // If 'thresholdValue' is negative, no values will be filtered
727 if ((aux < 0. ) &&
728 (-thresholdValue > aux)) {
729 (*this)(i,j) = 0.;
730 }
731 if ((aux > 0. ) &&
732 (thresholdValue < aux)) {
733 (*this)(i,j) = 0.;
734 }
735 }
736 }
737
738 return;
739 }
740
741 GslMatrix
transpose()742 GslMatrix::transpose() const
743 {
744 unsigned int nRows = this->numRowsGlobal();
745 unsigned int nCols = this->numCols();
746
747 const MpiComm & comm = this->map().Comm();
748 Map serial_map(nCols, 0, comm);
749
750 GslMatrix mat(m_env,serial_map,nRows);
751
752 for (unsigned int row = 0; row < nRows; ++row) {
753 for (unsigned int col = 0; col < nCols; ++col) {
754 mat(col,row) = (*this)(row,col);
755 }
756 }
757
758 return mat;
759 }
760
761 GslMatrix
inverse()762 GslMatrix::inverse() const
763 {
764 unsigned int nRows = this->numRowsLocal();
765 unsigned int nCols = this->numCols();
766
767 queso_require_equal_to_msg(nRows, nCols, "matrix is not square");
768
769 if (m_inverse == NULL) {
770 m_inverse = new GslMatrix(m_env,m_map,nCols);
771 GslVector unitVector(m_env,m_map);
772 unitVector.cwSet(0.);
773 GslVector multVector(m_env,m_map);
774 for (unsigned int j = 0; j < nCols; ++j) {
775 if (j > 0) unitVector[j-1] = 0.;
776 unitVector[j] = 1.;
777 this->invertMultiply(unitVector, multVector);
778 for (unsigned int i = 0; i < nRows; ++i) {
779 (*m_inverse)(i,j) = multVector[i];
780 }
781 }
782 }
783 if (m_env.checkingLevel() >= 1) {
784 *m_env.subDisplayFile() << "CHECKING In GslMatrix::inverse()"
785 << ": M.lnDet = " << this->lnDeterminant()
786 << ", M^{-1}.lnDet = " << m_inverse->lnDeterminant()
787 << std::endl;
788 }
789 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 5)) {
790 *m_env.subDisplayFile() << "In GslMatrix::inverse():"
791 << "\n M = " << *this
792 << "\n M^{-1} = " << *m_inverse
793 << "\n M*M^{-1} = " << (*this)*(*m_inverse)
794 << "\n M^{-1}*M = " << (*m_inverse)*(*this)
795 << std::endl;
796 }
797
798 return *m_inverse;
799 }
800
801 void
fillWithBlocksDiagonally(unsigned int initialTargetRowId,unsigned int initialTargetColId,const std::vector<const GslMatrix * > & matrices,bool checkForExactNumRowsMatching,bool checkForExactNumColsMatching)802 GslMatrix::fillWithBlocksDiagonally(
803 unsigned int initialTargetRowId,
804 unsigned int initialTargetColId,
805 const std::vector<const GslMatrix* >& matrices,
806 bool checkForExactNumRowsMatching,
807 bool checkForExactNumColsMatching)
808 {
809 unsigned int sumNumRowsLocals = 0;
810 unsigned int sumNumCols = 0;
811 for (unsigned int i = 0; i < matrices.size(); ++i) {
812 sumNumRowsLocals += matrices[i]->numRowsLocal();
813 sumNumCols += matrices[i]->numCols();
814 }
815 queso_require_greater_equal_msg(this->numRowsLocal(), (initialTargetRowId + sumNumRowsLocals), "too big number of rows");
816 if (checkForExactNumRowsMatching) queso_require_equal_to_msg(this->numRowsLocal(), (initialTargetRowId + sumNumRowsLocals), "inconsistent number of rows");
817 queso_require_greater_equal_msg(this->numCols(), (initialTargetColId + sumNumCols), "too big number of cols");
818 if (checkForExactNumColsMatching) queso_require_equal_to_msg(this->numCols(), (initialTargetColId + sumNumCols), "inconsistent number of cols");
819
820 unsigned int cumulativeRowId = 0;
821 unsigned int cumulativeColId = 0;
822 for (unsigned int i = 0; i < matrices.size(); ++i) {
823 unsigned int nRows = matrices[i]->numRowsLocal();
824 unsigned int nCols = matrices[i]->numCols();
825 for (unsigned int rowId = 0; rowId < nRows; ++rowId) {
826 for (unsigned int colId = 0; colId < nCols; ++colId) {
827 (*this)(initialTargetRowId + cumulativeRowId + rowId, initialTargetColId + cumulativeColId + colId) = (*(matrices[i]))(rowId,colId);
828 }
829 }
830 cumulativeRowId += nRows;
831 cumulativeColId += nCols;
832 }
833
834 return;
835 }
836
837 void
fillWithBlocksDiagonally(unsigned int initialTargetRowId,unsigned int initialTargetColId,const std::vector<GslMatrix * > & matrices,bool checkForExactNumRowsMatching,bool checkForExactNumColsMatching)838 GslMatrix::fillWithBlocksDiagonally(
839 unsigned int initialTargetRowId,
840 unsigned int initialTargetColId,
841 const std::vector<GslMatrix* >& matrices,
842 bool checkForExactNumRowsMatching,
843 bool checkForExactNumColsMatching)
844 {
845 unsigned int sumNumRowsLocals = 0;
846 unsigned int sumNumCols = 0;
847 for (unsigned int i = 0; i < matrices.size(); ++i) {
848 sumNumRowsLocals += matrices[i]->numRowsLocal();
849 sumNumCols += matrices[i]->numCols();
850 }
851 queso_require_greater_equal_msg(this->numRowsLocal(), (initialTargetRowId + sumNumRowsLocals), "too big number of rows");
852 if (checkForExactNumRowsMatching) queso_require_equal_to_msg(this->numRowsLocal(), (initialTargetRowId + sumNumRowsLocals), "inconsistent number of rows");
853 queso_require_greater_equal_msg(this->numCols(), (initialTargetColId + sumNumCols), "too big number of cols");
854 if (checkForExactNumColsMatching) queso_require_equal_to_msg(this->numCols(), (initialTargetColId + sumNumCols), "inconsistent number of cols");
855
856 unsigned int cumulativeRowId = 0;
857 unsigned int cumulativeColId = 0;
858 for (unsigned int i = 0; i < matrices.size(); ++i) {
859 unsigned int nRows = matrices[i]->numRowsLocal();
860 unsigned int nCols = matrices[i]->numCols();
861 for (unsigned int rowId = 0; rowId < nRows; ++rowId) {
862 for (unsigned int colId = 0; colId < nCols; ++colId) {
863 (*this)(initialTargetRowId + cumulativeRowId + rowId, initialTargetColId + cumulativeColId + colId) = (*(matrices[i]))(rowId,colId);
864 }
865 }
866 cumulativeRowId += nRows;
867 cumulativeColId += nCols;
868 }
869
870 return;
871 }
872
873 void
fillWithBlocksHorizontally(unsigned int initialTargetRowId,unsigned int initialTargetColId,const std::vector<const GslMatrix * > & matrices,bool checkForExactNumRowsMatching,bool checkForExactNumColsMatching)874 GslMatrix::fillWithBlocksHorizontally(
875 unsigned int initialTargetRowId,
876 unsigned int initialTargetColId,
877 const std::vector<const GslMatrix* >& matrices,
878 bool checkForExactNumRowsMatching,
879 bool checkForExactNumColsMatching)
880 {
881 unsigned int sumNumCols = 0;
882 for (unsigned int i = 0; i < matrices.size(); ++i) {
883 queso_require_greater_equal_msg(this->numRowsLocal(), (initialTargetRowId + matrices[i]->numRowsLocal()), "too big number of rows");
884 if (checkForExactNumRowsMatching) queso_require_equal_to_msg(this->numRowsLocal(), (initialTargetRowId + matrices[i]->numRowsLocal()), "inconsistent number of rows");
885 sumNumCols += matrices[i]->numCols();
886 }
887 queso_require_greater_equal_msg(this->numCols(), (initialTargetColId + sumNumCols), "too big number of cols");
888 if (checkForExactNumColsMatching) queso_require_equal_to_msg(this->numCols(), (initialTargetColId + sumNumCols), "inconsistent number of cols");
889
890 unsigned int cumulativeColId = 0;
891 for (unsigned int i = 0; i < matrices.size(); ++i) {
892 unsigned int nRows = matrices[i]->numRowsLocal();
893 unsigned int nCols = matrices[i]->numCols();
894 for (unsigned int rowId = 0; rowId < nRows; ++rowId) {
895 for (unsigned int colId = 0; colId < nCols; ++colId) {
896 (*this)(initialTargetRowId + rowId, initialTargetColId + cumulativeColId + colId) = (*(matrices[i]))(rowId,colId);
897 }
898 }
899 cumulativeColId += nCols;
900 }
901
902 return;
903 }
904
905 void
fillWithBlocksHorizontally(unsigned int initialTargetRowId,unsigned int initialTargetColId,const std::vector<GslMatrix * > & matrices,bool checkForExactNumRowsMatching,bool checkForExactNumColsMatching)906 GslMatrix::fillWithBlocksHorizontally(
907 unsigned int initialTargetRowId,
908 unsigned int initialTargetColId,
909 const std::vector<GslMatrix* >& matrices,
910 bool checkForExactNumRowsMatching,
911 bool checkForExactNumColsMatching)
912 {
913 unsigned int sumNumCols = 0;
914 for (unsigned int i = 0; i < matrices.size(); ++i) {
915 queso_require_greater_equal_msg(this->numRowsLocal(), (initialTargetRowId + matrices[i]->numRowsLocal()), "too big number of rows");
916 if (checkForExactNumRowsMatching) queso_require_equal_to_msg(this->numRowsLocal(), (initialTargetRowId + matrices[i]->numRowsLocal()), "inconsistent number of rows");
917 sumNumCols += matrices[i]->numCols();
918 }
919 queso_require_greater_equal_msg(this->numCols(), (initialTargetColId + sumNumCols), "too big number of cols");
920 if (checkForExactNumColsMatching) queso_require_equal_to_msg(this->numCols(), (initialTargetColId + sumNumCols), "inconsistent number of cols");
921
922 unsigned int cumulativeColId = 0;
923 for (unsigned int i = 0; i < matrices.size(); ++i) {
924 unsigned int nRows = matrices[i]->numRowsLocal();
925 unsigned int nCols = matrices[i]->numCols();
926 for (unsigned int rowId = 0; rowId < nRows; ++rowId) {
927 for (unsigned int colId = 0; colId < nCols; ++colId) {
928 (*this)(initialTargetRowId + rowId, initialTargetColId + cumulativeColId + colId) = (*(matrices[i]))(rowId,colId);
929 }
930 }
931 cumulativeColId += nCols;
932 }
933
934 return;
935 }
936
937 void
fillWithBlocksVertically(unsigned int initialTargetRowId,unsigned int initialTargetColId,const std::vector<const GslMatrix * > & matrices,bool checkForExactNumRowsMatching,bool checkForExactNumColsMatching)938 GslMatrix::fillWithBlocksVertically( // checar
939 unsigned int initialTargetRowId,
940 unsigned int initialTargetColId,
941 const std::vector<const GslMatrix* >& matrices,
942 bool checkForExactNumRowsMatching,
943 bool checkForExactNumColsMatching)
944 {
945 unsigned int sumNumRows = 0;
946 for (unsigned int i = 0; i < matrices.size(); ++i) {
947 queso_require_greater_equal_msg(this->numCols(), (initialTargetColId + matrices[i]->numCols()), "too big number of cols");
948 if (checkForExactNumColsMatching) queso_require_equal_to_msg(this->numCols(), (initialTargetColId + matrices[i]->numCols()), "inconsistent number of cols");
949 sumNumRows += matrices[i]->numRowsLocal();
950 }
951 queso_require_greater_equal_msg(this->numRowsLocal(), (initialTargetRowId + sumNumRows), "too big number of rows");
952 if (checkForExactNumRowsMatching) queso_require_equal_to_msg(this->numRowsLocal(), (initialTargetRowId + sumNumRows), "inconsistent number of rows");
953
954 unsigned int cumulativeRowId = 0;
955 for (unsigned int i = 0; i < matrices.size(); ++i) {
956 unsigned int nRows = matrices[i]->numRowsLocal();
957 unsigned int nCols = matrices[i]->numCols();
958 for (unsigned int rowId = 0; rowId < nRows; ++rowId) {
959 for (unsigned int colId = 0; colId < nCols; ++colId) {
960 (*this)(initialTargetRowId + cumulativeRowId + rowId, initialTargetColId + colId) = (*(matrices[i]))(rowId,colId);
961 }
962 }
963 cumulativeRowId += nRows;
964 }
965
966 return;
967 }
968
969 void
fillWithBlocksVertically(unsigned int initialTargetRowId,unsigned int initialTargetColId,const std::vector<GslMatrix * > & matrices,bool checkForExactNumRowsMatching,bool checkForExactNumColsMatching)970 GslMatrix::fillWithBlocksVertically( // checar
971 unsigned int initialTargetRowId,
972 unsigned int initialTargetColId,
973 const std::vector<GslMatrix* >& matrices,
974 bool checkForExactNumRowsMatching,
975 bool checkForExactNumColsMatching)
976 {
977 unsigned int sumNumRows = 0;
978 for (unsigned int i = 0; i < matrices.size(); ++i) {
979 queso_require_greater_equal_msg(this->numCols(), (initialTargetColId + matrices[i]->numCols()), "too big number of cols");
980 if (checkForExactNumColsMatching) queso_require_equal_to_msg(this->numCols(), (initialTargetColId + matrices[i]->numCols()), "inconsistent number of cols");
981 sumNumRows += matrices[i]->numRowsLocal();
982 }
983 queso_require_greater_equal_msg(this->numRowsLocal(), (initialTargetRowId + sumNumRows), "too big number of rows");
984 if (checkForExactNumRowsMatching) queso_require_equal_to_msg(this->numRowsLocal(), (initialTargetRowId + sumNumRows), "inconsistent number of rows");
985
986 unsigned int cumulativeRowId = 0;
987 for (unsigned int i = 0; i < matrices.size(); ++i) {
988 unsigned int nRows = matrices[i]->numRowsLocal();
989 unsigned int nCols = matrices[i]->numCols();
990 for (unsigned int rowId = 0; rowId < nRows; ++rowId) {
991 for (unsigned int colId = 0; colId < nCols; ++colId) {
992 (*this)(initialTargetRowId + cumulativeRowId + rowId, initialTargetColId + colId) = (*(matrices[i]))(rowId,colId);
993 }
994 }
995 cumulativeRowId += nRows;
996 }
997
998 return;
999 }
1000
1001 void
fillWithTensorProduct(unsigned int initialTargetRowId,unsigned int initialTargetColId,const GslMatrix & mat1,const GslMatrix & mat2,bool checkForExactNumRowsMatching,bool checkForExactNumColsMatching)1002 GslMatrix::fillWithTensorProduct(
1003 unsigned int initialTargetRowId,
1004 unsigned int initialTargetColId,
1005 const GslMatrix& mat1,
1006 const GslMatrix& mat2,
1007 bool checkForExactNumRowsMatching,
1008 bool checkForExactNumColsMatching)
1009 {
1010 queso_require_greater_equal_msg(this->numRowsLocal(), (initialTargetRowId + (mat1.numRowsLocal() * mat2.numRowsLocal())), "too big number of rows");
1011 if (checkForExactNumRowsMatching) queso_require_equal_to_msg(this->numRowsLocal(), (initialTargetRowId + (mat1.numRowsLocal() * mat2.numRowsLocal())), "inconsistent number of rows");
1012 queso_require_greater_equal_msg(this->numCols(), (initialTargetColId + (mat1.numCols() * mat2.numCols())), "too big number of columns");
1013 if (checkForExactNumColsMatching) queso_require_equal_to_msg(this->numCols(), (initialTargetColId + (mat1.numCols() * mat2.numCols())), "inconsistent number of columns");
1014
1015 for (unsigned int rowId1 = 0; rowId1 < mat1.numRowsLocal(); ++rowId1) {
1016 for (unsigned int colId1 = 0; colId1 < mat1.numCols(); ++colId1) {
1017 double multiplicativeFactor = mat1(rowId1,colId1);
1018 unsigned int targetRowId = rowId1 * mat2.numRowsLocal();
1019 unsigned int targetColId = colId1 * mat2.numCols();
1020 for (unsigned int rowId2 = 0; rowId2 < mat2.numRowsLocal(); ++rowId2) {
1021 for (unsigned int colId2 = 0; colId2 < mat2.numCols(); ++colId2) {
1022 (*this)(initialTargetRowId + targetRowId + rowId2, initialTargetColId + targetColId + colId2) = multiplicativeFactor * mat2(rowId2,colId2);
1023 }
1024 }
1025 }
1026 }
1027
1028 return;
1029 }
1030
1031 void
fillWithTensorProduct(unsigned int initialTargetRowId,unsigned int initialTargetColId,const GslMatrix & mat1,const GslVector & vec2,bool checkForExactNumRowsMatching,bool checkForExactNumColsMatching)1032 GslMatrix::fillWithTensorProduct(
1033 unsigned int initialTargetRowId,
1034 unsigned int initialTargetColId,
1035 const GslMatrix& mat1,
1036 const GslVector& vec2,
1037 bool checkForExactNumRowsMatching,
1038 bool checkForExactNumColsMatching)
1039 {
1040 queso_require_greater_equal_msg(this->numRowsLocal(), (initialTargetRowId + (mat1.numRowsLocal() * vec2.sizeLocal())), "too big number of rows");
1041 if (checkForExactNumRowsMatching) queso_require_equal_to_msg(this->numRowsLocal(), (initialTargetRowId + (mat1.numRowsLocal() * vec2.sizeLocal())), "inconsistent number of rows");
1042 queso_require_greater_equal_msg(this->numCols(), (initialTargetColId + (mat1.numCols() * 1)), "too big number of columns");
1043 if (checkForExactNumColsMatching) queso_require_equal_to_msg(this->numCols(), (initialTargetColId + (mat1.numCols() * 1)), "inconsistent number of columns");
1044
1045 for (unsigned int rowId1 = 0; rowId1 < mat1.numRowsLocal(); ++rowId1) {
1046 for (unsigned int colId1 = 0; colId1 < mat1.numCols(); ++colId1) {
1047 double multiplicativeFactor = mat1(rowId1,colId1);
1048 unsigned int targetRowId = rowId1 * vec2.sizeLocal();
1049 unsigned int targetColId = colId1 * 1;
1050 for (unsigned int rowId2 = 0; rowId2 < vec2.sizeLocal(); ++rowId2) {
1051 for (unsigned int colId2 = 0; colId2 < 1; ++colId2) {
1052 (*this)(initialTargetRowId + targetRowId + rowId2, initialTargetColId + targetColId + colId2) = multiplicativeFactor * vec2[rowId2];
1053 }
1054 }
1055 }
1056 }
1057
1058
1059 return;
1060 }
1061
1062 void
fillWithTranspose(unsigned int initialTargetRowId,unsigned int initialTargetColId,const GslMatrix & mat,bool checkForExactNumRowsMatching,bool checkForExactNumColsMatching)1063 GslMatrix::fillWithTranspose(
1064 unsigned int initialTargetRowId,
1065 unsigned int initialTargetColId,
1066 const GslMatrix& mat,
1067 bool checkForExactNumRowsMatching,
1068 bool checkForExactNumColsMatching)
1069 {
1070 unsigned int nRows = mat.numRowsLocal();
1071 unsigned int nCols = mat.numCols();
1072 queso_require_greater_equal_msg(this->numRowsLocal(), (initialTargetRowId + nCols), "too big number of rows");
1073 if (checkForExactNumRowsMatching) queso_require_equal_to_msg(this->numRowsLocal(), (initialTargetRowId + nCols), "inconsistent number of rows");
1074 queso_require_greater_equal_msg(this->numCols(), (initialTargetColId + nRows), "too big number of cols");
1075 if (checkForExactNumColsMatching) queso_require_equal_to_msg(this->numCols(), (initialTargetColId + nRows), "inconsistent number of cols");
1076
1077 for (unsigned int row = 0; row < nRows; ++row) {
1078 for (unsigned int col = 0; col < nCols; ++col) {
1079 (*this)(initialTargetRowId + col, initialTargetColId + row) = mat(row,col);
1080 }
1081 }
1082
1083 return;
1084 }
1085
1086 double
determinant()1087 GslMatrix::determinant() const
1088 {
1089 if (m_determinant == -INFINITY) {
1090 if (m_LU == NULL) {
1091 GslVector tmpB(m_env,m_map);
1092 GslVector tmpX(m_env,m_map);
1093 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1094 *m_env.subDisplayFile() << "In GslMatrix::determinant()"
1095 << ": before 'this->invertMultiply()'"
1096 << std::endl;
1097 }
1098 this->invertMultiply(tmpB,tmpX);
1099 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1100 *m_env.subDisplayFile() << "In GslMatrix::determinant()"
1101 << ": after 'this->invertMultiply()'"
1102 << std::endl;
1103 }
1104 }
1105 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1106 *m_env.subDisplayFile() << "In GslMatrix::determinant()"
1107 << ": before 'gsl_linalg_LU_det()'"
1108 << std::endl;
1109 }
1110 m_determinant = gsl_linalg_LU_det(m_LU,m_signum);
1111 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1112 *m_env.subDisplayFile() << "In GslMatrix::determinant()"
1113 << ": after 'gsl_linalg_LU_det()'"
1114 << std::endl;
1115 }
1116 m_lnDeterminant = gsl_linalg_LU_lndet(m_LU);
1117 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1118 *m_env.subDisplayFile() << "In GslMatrix::determinant()"
1119 << ": after 'gsl_linalg_LU_lndet()'"
1120 << std::endl;
1121 }
1122 }
1123
1124 return m_determinant;
1125 }
1126
1127 double
lnDeterminant()1128 GslMatrix::lnDeterminant() const
1129 {
1130 if (m_lnDeterminant == -INFINITY) {
1131 if (m_LU == NULL) {
1132 GslVector tmpB(m_env,m_map);
1133 GslVector tmpX(m_env,m_map);
1134 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1135 *m_env.subDisplayFile() << "In GslMatrix::lnDeterminant()"
1136 << ": before 'this->invertMultiply()'"
1137 << std::endl;
1138 }
1139 this->invertMultiply(tmpB,tmpX);
1140 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1141 *m_env.subDisplayFile() << "In GslMatrix::lnDeterminant()"
1142 << ": after 'this->invertMultiply()'"
1143 << std::endl;
1144 }
1145 }
1146 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1147 *m_env.subDisplayFile() << "In GslMatrix::lnDeterminant()"
1148 << ": before 'gsl_linalg_LU_det()'"
1149 << std::endl;
1150 }
1151 m_determinant = gsl_linalg_LU_det(m_LU,m_signum);
1152 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1153 *m_env.subDisplayFile() << "In GslMatrix::lnDeterminant()"
1154 << ": after 'gsl_linalg_LU_det()'"
1155 << std::endl;
1156 }
1157 m_lnDeterminant = gsl_linalg_LU_lndet(m_LU);
1158 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1159 *m_env.subDisplayFile() << "In GslMatrix::lnDeterminant()"
1160 << ": before 'gsl_linalg_LU_lndet()'"
1161 << std::endl;
1162 }
1163 }
1164
1165 return m_lnDeterminant;
1166 }
1167
1168 unsigned int
rank(double absoluteZeroThreshold,double relativeZeroThreshold)1169 GslMatrix::rank(double absoluteZeroThreshold, double relativeZeroThreshold) const
1170 {
1171 int iRC = 0;
1172 iRC = internalSvd();
1173 if (iRC) {}; // just to remove compiler warning
1174
1175 GslVector relativeVec(*m_svdSvec);
1176 if (relativeVec[0] > 0.) {
1177 relativeVec = (1./relativeVec[0])*relativeVec;
1178 }
1179
1180 unsigned int rankValue = 0;
1181 for (unsigned int i = 0; i < relativeVec.sizeLocal(); ++i) {
1182 if (( (*m_svdSvec)[i] >= absoluteZeroThreshold ) &&
1183 ( relativeVec [i] >= relativeZeroThreshold )) {
1184 rankValue += 1;
1185 }
1186 }
1187
1188 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 3)) {
1189 *m_env.subDisplayFile() << "In GslMatrix::rank()"
1190 << ": this->numRowsLocal() = " << this->numRowsLocal()
1191 << ", this->numCols() = " << this->numCols()
1192 << ", absoluteZeroThreshold = " << absoluteZeroThreshold
1193 << ", relativeZeroThreshold = " << relativeZeroThreshold
1194 << ", rankValue = " << rankValue
1195 << ", m_svdSvec = " << *m_svdSvec
1196 << ", relativeVec = " << relativeVec
1197 << std::endl;
1198 }
1199
1200 return rankValue;
1201 }
1202
1203 GslVector
multiply(const GslVector & x)1204 GslMatrix::multiply(
1205 const GslVector& x) const
1206 {
1207 queso_require_equal_to_msg(this->numCols(), x.sizeLocal(), "matrix and vector have incompatible sizes");
1208
1209 GslVector y(m_env,m_map);
1210 this->multiply(x,y);
1211
1212 return y;
1213 }
1214
1215 void
multiply(const GslVector & x,GslVector & y)1216 GslMatrix::multiply(
1217 const GslVector& x,
1218 GslVector& y) const
1219 {
1220 queso_require_equal_to_msg(this->numCols(), x.sizeLocal(), "matrix and x have incompatible sizes");
1221
1222 queso_require_equal_to_msg(this->numRowsLocal(), y.sizeLocal(), "matrix and y have incompatible sizes");
1223
1224 unsigned int sizeX = this->numCols();
1225 unsigned int sizeY = this->numRowsLocal();
1226 for (unsigned int i = 0; i < sizeY; ++i) {
1227 double value = 0.;
1228 for (unsigned int j = 0; j < sizeX; ++j) {
1229 value += (*this)(i,j)*x[j];
1230 }
1231 y[i] = value;
1232 }
1233
1234 return;
1235 }
1236
1237 GslMatrix
multiply(const GslMatrix & X)1238 GslMatrix::multiply(
1239 const GslMatrix & X) const
1240 {
1241 GslMatrix Y(m_env,m_map,X.numCols());
1242 this->multiply(X,Y);
1243
1244 return Y;
1245 }
1246
1247
1248
1249 void
multiply(const GslMatrix & X,GslMatrix & Y)1250 GslMatrix::multiply(
1251 const GslMatrix & X,
1252 GslMatrix & Y) const
1253 {
1254 queso_require_equal_to_msg(this->numCols(), X.numRowsGlobal(), "matrix and X have incompatible sizes");
1255 queso_require_equal_to_msg(this->numRowsGlobal(), Y.numRowsGlobal(), "matrix and Y have incompatible sizes");
1256 queso_require_equal_to_msg(X.numCols(), Y.numCols(), "X and Y have incompatible sizes");
1257
1258 const unsigned int m_s = this->numRowsGlobal();
1259 const unsigned int p_s = this->numCols();
1260 const unsigned int n_s = X.numCols();
1261
1262 for (unsigned int k=0; k<p_s; k++)
1263 for (unsigned int j=0; j<n_s; j++)
1264 if (X(k,j) != 0.)
1265 for (unsigned int i=0; i<m_s; i++)
1266 Y(i,j) += (*this)(i,k) * X(k,j);
1267 }
1268
1269
1270 GslVector
invertMultiply(const GslVector & b)1271 GslMatrix::invertMultiply(
1272 const GslVector& b) const
1273 {
1274 queso_require_equal_to_msg(this->numCols(), b.sizeLocal(), "matrix and rhs have incompatible sizes");
1275
1276 GslVector x(m_env,m_map);
1277 this->invertMultiply(b,x);
1278
1279 return x;
1280 }
1281
1282 void
invertMultiply(const GslVector & b,GslVector & x)1283 GslMatrix::invertMultiply(
1284 const GslVector& b,
1285 GslVector& x) const
1286 {
1287 queso_require_equal_to_msg(this->numCols(), b.sizeLocal(), "matrix and rhs have incompatible sizes");
1288
1289 queso_require_equal_to_msg(x.sizeLocal(), b.sizeLocal(), "solution and rhs have incompatible sizes");
1290
1291 int iRC;
1292 if (m_LU == NULL) {
1293 queso_require_msg(!(m_permutation), "m_permutation should be NULL");
1294
1295 m_LU = gsl_matrix_calloc(this->numRowsLocal(),this->numCols());
1296 queso_require_msg(m_LU, "gsl_matrix_calloc() failed");
1297
1298 iRC = gsl_matrix_memcpy(m_LU, m_mat);
1299 queso_require_msg(!(iRC), "gsl_matrix_memcpy() failed");
1300
1301 m_permutation = gsl_permutation_calloc(numCols());
1302 queso_require_msg(m_permutation, "gsl_permutation_calloc() failed");
1303
1304 if (m_inDebugMode) {
1305 std::cout << "In GslMatrix::invertMultiply()"
1306 << ": before LU decomposition, m_LU = ";
1307 gsl_matrix_fprintf(stdout, m_LU, "%f");
1308 std::cout << std::endl;
1309 }
1310
1311 gsl_error_handler_t* oldHandler;
1312 oldHandler = gsl_set_error_handler_off();
1313 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1314 *m_env.subDisplayFile() << "In GslMatrix::invertMultiply()"
1315 << ": before 'gsl_linalg_LU_decomp()'"
1316 << std::endl;
1317 }
1318 iRC = gsl_linalg_LU_decomp(m_LU,m_permutation,&m_signum);
1319 if (iRC != 0) {
1320 std::cerr << "In GslMatrix::invertMultiply()"
1321 << ", after gsl_linalg_LU_decomp()"
1322 << ": iRC = " << iRC
1323 << ", gsl error message = " << gsl_strerror(iRC)
1324 << std::endl;
1325 }
1326 gsl_set_error_handler(oldHandler);
1327 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1328 *m_env.subDisplayFile() << "In GslMatrix::invertMultiply()"
1329 << ": after 'gsl_linalg_LU_decomp()'"
1330 << ", IRC = " << iRC
1331 << std::endl;
1332 }
1333 queso_require_msg(!(iRC), "gsl_linalg_LU_decomp() failed");
1334
1335 if (m_inDebugMode) {
1336 std::cout << "In GslMatrix::invertMultiply()"
1337 << ": after LU decomposition, m_LU = ";
1338 gsl_matrix_fprintf(stdout, m_LU, "%f");
1339 std::cout << std::endl;
1340 }
1341 }
1342
1343 gsl_error_handler_t* oldHandler;
1344 oldHandler = gsl_set_error_handler_off();
1345 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1346 *m_env.subDisplayFile() << "In GslMatrix::invertMultiply()"
1347 << ": before 'gsl_linalg_LU_solve()'"
1348 << std::endl;
1349 }
1350 iRC = gsl_linalg_LU_solve(m_LU,m_permutation,b.data(),x.data());
1351 if (iRC != 0) {
1352 m_isSingular = true;
1353 std::cerr << "In GslMatrix::invertMultiply()"
1354 << ", after gsl_linalg_LU_solve()"
1355 << ": iRC = " << iRC
1356 << ", gsl error message = " << gsl_strerror(iRC)
1357 << std::endl;
1358 }
1359 gsl_set_error_handler(oldHandler);
1360 if ((m_env.subDisplayFile()) && (m_env.displayVerbosity() >= 99)) {
1361 *m_env.subDisplayFile() << "In GslMatrix::invertMultiply()"
1362 << ": after 'gsl_linalg_LU_solve()'"
1363 << ", IRC = " << iRC
1364 << std::endl;
1365 }
1366
1367
1368 // m_env.worldRank(),
1369 // "GslMatrix::invertMultiply()",
1370 // "gsl_linalg_LU_solve() failed");
1371
1372 if (m_inDebugMode) {
1373 GslVector tmpVec(b - (*this)*x);
1374 std::cout << "In GslMatrix::invertMultiply()"
1375 << ": ||b - Ax||_2 = " << tmpVec.norm2()
1376 << ": ||b - Ax||_2/||b||_2 = " << tmpVec.norm2()/b.norm2()
1377 << std::endl;
1378 }
1379
1380 return;
1381 }
1382
1383 GslMatrix
invertMultiply(const GslMatrix & B)1384 GslMatrix::invertMultiply(const GslMatrix& B) const
1385 {
1386 GslMatrix X(m_env,m_map,B.numCols());
1387 this->invertMultiply(B,X);
1388
1389 return X;
1390 }
1391
1392 void
invertMultiply(const GslMatrix & B,GslMatrix & X)1393 GslMatrix::invertMultiply(const GslMatrix& B, GslMatrix& X) const
1394 {
1395 // Sanity Checks
1396 queso_require_equal_to_msg(B.numRowsLocal(), X.numRowsLocal(),
1397 "Matrices B and X are incompatible");
1398 queso_require_equal_to_msg(B.numCols(), X.numCols(),
1399 "Matrices B and X are incompatible");
1400 queso_require_equal_to_msg(this->numRowsLocal(), X.numRowsLocal(),
1401 "This and X matrices are incompatible");
1402
1403 // Some local variables used within the loop.
1404 GslVector b(m_env, m_map);
1405 GslVector x(m_env, m_map);
1406
1407 for( unsigned int j = 0; j < B.numCols(); ++j )
1408 {
1409 b = B.getColumn( j );
1410
1411 //invertMultiply will only do the LU once and store it. So we don't
1412 //need to worry about it doing LU multiple times.
1413 x = this->invertMultiply( b );
1414
1415 X.setColumn( j, x );
1416 }
1417
1418 return;
1419 }
1420
1421 GslVector
invertMultiplyForceLU(const GslVector & b)1422 GslMatrix::invertMultiplyForceLU(
1423 const GslVector& b) const
1424 {
1425 queso_require_equal_to_msg(this->numCols(), b.sizeLocal(), "matrix and rhs have incompatible sizes");
1426
1427 GslVector x(m_env,m_map);
1428 this->invertMultiplyForceLU(b,x);
1429
1430 return x;
1431 }
1432
1433 void
invertMultiplyForceLU(const GslVector & b,GslVector & x)1434 GslMatrix::invertMultiplyForceLU(
1435 const GslVector& b,
1436 GslVector& x) const
1437 {
1438 queso_require_equal_to_msg(this->numCols(), b.sizeLocal(), "matrix and rhs have incompatible sizes");
1439
1440 queso_require_equal_to_msg(x.sizeLocal(), b.sizeLocal(), "solution and rhs have incompatible sizes");
1441
1442 int iRC;
1443
1444 if ( m_LU == NULL ) {
1445 queso_require_msg(!(m_permutation), "m_permutation should be NULL");
1446 m_LU = gsl_matrix_calloc(this->numRowsLocal(),this->numCols());
1447 }
1448 queso_require_msg(m_LU, "gsl_matrix_calloc() failed");
1449
1450 iRC = gsl_matrix_memcpy(m_LU, m_mat);
1451 queso_require_msg(!(iRC), "gsl_matrix_memcpy() failed");
1452
1453 if( m_permutation == NULL ) m_permutation = gsl_permutation_calloc(numCols());
1454 queso_require_msg(m_permutation, "gsl_permutation_calloc() failed");
1455
1456 iRC = gsl_linalg_LU_decomp(m_LU,m_permutation,&m_signum);
1457 queso_require_msg(!(iRC), "gsl_linalg_LU_decomp() failed");
1458
1459 iRC = gsl_linalg_LU_solve(m_LU,m_permutation,b.data(),x.data());
1460 if (iRC != 0) {
1461 m_isSingular = true;
1462 }
1463 queso_require_msg(!(iRC), "gsl_linalg_LU_solve() failed");
1464
1465 return;
1466 }
1467
1468 void
eigen(GslVector & eigenValues,GslMatrix * eigenVectors)1469 GslMatrix::eigen(GslVector& eigenValues, GslMatrix* eigenVectors) const
1470 {
1471 unsigned int n = eigenValues.sizeLocal();
1472
1473 queso_require_not_equal_to_msg(n, 0, "invalid input vector size");
1474
1475 if (eigenVectors) {
1476 queso_require_equal_to_msg(eigenValues.sizeLocal(), eigenVectors->numRowsLocal(), "different input vector sizes");
1477 }
1478
1479 if (eigenVectors == NULL) {
1480 gsl_eigen_symm_workspace* w = gsl_eigen_symm_alloc((size_t) n);
1481 gsl_eigen_symm(m_mat,eigenValues.data(),w);
1482 gsl_eigen_symm_free(w);
1483 }
1484 else {
1485 gsl_eigen_symmv_workspace* w = gsl_eigen_symmv_alloc((size_t) n);
1486 gsl_eigen_symmv(m_mat,eigenValues.data(),eigenVectors->m_mat,w);
1487 gsl_eigen_symmv_sort(eigenValues.data(),eigenVectors->m_mat,GSL_EIGEN_SORT_VAL_ASC);
1488 gsl_eigen_symmv_free(w);
1489 }
1490
1491 return;
1492 }
1493
1494 void
largestEigen(double & eigenValue,GslVector & eigenVector)1495 GslMatrix::largestEigen(double& eigenValue, GslVector& eigenVector) const
1496 {
1497
1498 // Sanity Checks
1499 unsigned int n = eigenVector.sizeLocal();
1500
1501 queso_require_not_equal_to_msg(n, 0, "invalid input vector size");
1502
1503 /* The following notation is used:
1504 z = vector used in iteration that ends up being the eigenvector corresponding to the
1505 largest eigenvalue
1506 w = vector used in iteration that we extract the largest eigenvalue from. */
1507
1508 // Some parameters associated with the algorithm
1509 // TODO: Do we want to add the ability to have these set by the user?
1510 const unsigned int max_num_iterations = 10000;
1511 const double tolerance = 1.0e-13;
1512
1513 // Create temporary working vectors.
1514 // TODO: We shouldn't have to use these - we ought to be able to work directly
1515 // TODO: with eigenValue and eigenVector. Optimize this once we have regression
1516 // TODO: tests.
1517 GslVector z(m_env, m_map, 1.0 ); // Needs to be initialized to 1.0
1518 GslVector w(m_env, m_map);
1519
1520 // Some variables we use inside the loop.
1521 int index;
1522 double residual;
1523 double lambda;
1524
1525 for( unsigned int k = 0; k < max_num_iterations; ++k )
1526 {
1527 w = (*this) * z;
1528
1529 // For this algorithm, it's crucial to get the maximum in
1530 // absolute value, but then to normalize by the actual value
1531 // and *not* the absolute value.
1532 index = (w.abs()).getMaxValueIndex();
1533
1534 lambda = w[index];
1535
1536 z = (1.0/lambda) * w;
1537
1538 // Here we use the norm of the residual as our convergence check:
1539 // norm( A*x - \lambda*x )
1540 residual = ( (*this)*z - lambda*z ).norm2();
1541
1542 if( residual < tolerance )
1543 {
1544 eigenValue = lambda;
1545
1546 // TODO: Do we want to normalize this so eigenVector.norm2() = 1?
1547 eigenVector = z;
1548 return;
1549 }
1550
1551 }
1552
1553 // If we reach this point, then we didn't converge. Print error message
1554 // to this effect.
1555 // TODO: We know we failed at this point - need a way to not need a test
1556 // TODO: Just specify the error.
1557 queso_require_less_msg(residual, tolerance, "Maximum num iterations exceeded");
1558
1559
1560 return;
1561 }
1562
1563 void
smallestEigen(double & eigenValue,GslVector & eigenVector)1564 GslMatrix::smallestEigen(double& eigenValue, GslVector& eigenVector) const
1565 {
1566 // Sanity Checks
1567 unsigned int n = eigenVector.sizeLocal();
1568
1569 queso_require_not_equal_to_msg(n, 0, "invalid input vector size");
1570
1571 /* The following notation is used:
1572 z = vector used in iteration that ends up being the eigenvector corresponding to the
1573 largest eigenvalue
1574 w = vector used in iteration that we extract the largest eigenvalue from. */
1575
1576 // Some parameters associated with the algorithm
1577 // TODO: Do we want to add the ability to have these set by the user?
1578 const unsigned int max_num_iterations = 1000;
1579 const double tolerance = 1.0e-13;
1580
1581 // Create temporary working vectors.
1582 // TODO: We shouldn't have to use these - we ought to be able to work directly
1583 // TODO: with eigenValue and eigenVector. Optimize this once we have regression
1584 // TODO: tests.
1585 GslVector z(m_env, m_map, 1.0 ); // Needs to be initialized to 1.0
1586 GslVector w(m_env, m_map);
1587
1588 // Some variables we use inside the loop.
1589 int index;
1590 double residual;
1591 double one_over_lambda;
1592 double lambda;
1593
1594 for( unsigned int k = 0; k < max_num_iterations; ++k )
1595 {
1596 w = (*this).invertMultiplyForceLU( z );
1597
1598 // For this algorithm, it's crucial to get the maximum in
1599 // absolute value, but then to normalize by the actual value
1600 // and *not* the absolute value.
1601 index = (w.abs()).getMaxValueIndex();
1602
1603 // Remember: Inverse power method solves for max 1/lambda ==> lambda smallest
1604 one_over_lambda = w[index];
1605
1606 lambda = 1.0/one_over_lambda;
1607
1608 z = lambda * w;
1609
1610 // Here we use the norm of the residual as our convergence check:
1611 // norm( A*x - \lambda*x )
1612 residual = ( (*this)*z - lambda*z ).norm2();
1613
1614 if( residual < tolerance )
1615 {
1616 eigenValue = lambda;
1617
1618 // TODO: Do we want to normalize this so eigenVector.norm2() = 1?
1619 eigenVector = z;
1620 return;
1621 }
1622
1623 }
1624
1625 // If we reach this point, then we didn't converge. Print error message
1626 // to this effect.
1627 // TODO: We know we failed at this point - need a way to not need a test
1628 // TODO: Just specify the error.
1629 queso_require_less_msg(residual, tolerance, "Maximum num iterations exceeded");
1630
1631 return;
1632 }
1633
1634 void
getColumn(unsigned int column_num,GslVector & column)1635 GslMatrix::getColumn(unsigned int column_num, GslVector& column) const
1636 {
1637 // Sanity checks
1638 queso_require_less_msg(column_num, this->numCols(), "Specified row number not within range");
1639
1640 queso_require_equal_to_msg(column.sizeLocal(), this->numRowsLocal(), "column vector not same size as this matrix");
1641
1642 // Temporary working vector
1643 gsl_vector* gsl_column = gsl_vector_alloc( column.sizeLocal() );
1644
1645 int error_code = gsl_matrix_get_col( gsl_column, m_mat, column_num );
1646 queso_require_equal_to_msg(error_code, 0, "gsl_matrix_get_col failed");
1647
1648 // Copy column from gsl matrix into our GslVector object
1649 for( unsigned int i = 0; i < column.sizeLocal(); ++i )
1650 {
1651 column[i] = gsl_vector_get( gsl_column, i );
1652 }
1653
1654 // Clean up gsl temporaries
1655 gsl_vector_free( gsl_column );
1656
1657 return;
1658 }
1659
1660 void
getRow(unsigned int row_num,GslVector & row)1661 GslMatrix::getRow(unsigned int row_num, GslVector& row) const
1662 {
1663 // Sanity checks
1664 queso_require_less_msg(row_num, this->numRowsLocal(), "Specified row number not within range");
1665
1666 queso_require_equal_to_msg(row.sizeLocal(), this->numCols(), "row vector not same size as this matrix");
1667
1668 // Temporary working vector
1669 gsl_vector* gsl_row = gsl_vector_alloc( row.sizeLocal() );
1670
1671 int error_code = gsl_matrix_get_row( gsl_row, m_mat, row_num );
1672 queso_require_equal_to_msg(error_code, 0, "gsl_matrix_get_row failed");
1673
1674 // Copy row from gsl matrix into our GslVector object
1675 for( unsigned int i = 0; i < row.sizeLocal(); ++i )
1676 {
1677 row[i] = gsl_vector_get( gsl_row, i );
1678 }
1679
1680 // Clean up gsl temporaries
1681 gsl_vector_free( gsl_row );
1682
1683 return;
1684 }
1685
1686 GslVector
getRow(unsigned int row_num)1687 GslMatrix::getRow(unsigned int row_num ) const
1688 {
1689 // We rely on the void getRow's to do sanity checks
1690 // So we don't do them here.
1691
1692 GslVector row(m_env, m_map);
1693
1694 this->getRow( row_num, row );
1695
1696 return row;
1697 }
1698
1699 GslVector
getColumn(unsigned int column_num)1700 GslMatrix::getColumn(unsigned int column_num ) const
1701 {
1702 // We rely on the void getRow's to do sanity checks
1703 // So we don't do them here.
1704
1705 GslVector column(m_env, m_map);
1706
1707 this->getColumn( column_num, column );
1708
1709 return column;
1710 }
1711
1712 void
setRow(unsigned int row_num,const GslVector & row)1713 GslMatrix::setRow(unsigned int row_num, const GslVector& row)
1714 {
1715 this->reset();
1716 // Sanity checks
1717 queso_require_less_msg(row_num, this->numRowsLocal(), "Specified row number not within range");
1718
1719 queso_require_equal_to_msg(row.sizeLocal(), this->numCols(), "row vector not same size as this matrix");
1720
1721 gsl_vector* gsl_row = row.data();
1722
1723 int error_code = gsl_matrix_set_row( m_mat, row_num, gsl_row );
1724 queso_require_equal_to_msg(error_code, 0, "gsl_matrix_set_row failed");
1725
1726 return;
1727 }
1728
1729 void
setColumn(unsigned int column_num,const GslVector & column)1730 GslMatrix::setColumn(unsigned int column_num, const GslVector& column)
1731 {
1732 this->reset();
1733 // Sanity checks
1734 queso_require_less_msg(column_num, this->numCols(), "Specified column number not within range");
1735
1736 queso_require_equal_to_msg(column.sizeLocal(), this->numRowsLocal(), "column vector not same size as this matrix");
1737
1738 gsl_vector* gsl_column = column.data();
1739
1740 int error_code = gsl_matrix_set_col( m_mat, column_num, gsl_column );
1741 queso_require_equal_to_msg(error_code, 0, "gsl_matrix_set_col failed");
1742
1743 return;
1744 }
1745
1746 void
mpiSum(const MpiComm & comm,GslMatrix & M_global)1747 GslMatrix::mpiSum( const MpiComm& comm, GslMatrix& M_global ) const
1748 {
1749 // Sanity Checks
1750 UQ_FATAL_RC_MACRO(((this->numRowsLocal() != M_global.numRowsLocal()) ||
1751 (this->numCols() != M_global.numCols() )),
1752 env().fullRank(),
1753 "GslMatrix::mpiSum()",
1754 "local and global matrices incompatible");
1755
1756 /* TODO: Probably a better way to handle this unpacking/packing of data */
1757 int size = M_global.numRowsLocal()*M_global.numCols();
1758 std::vector<double> local( size, 0.0 );
1759 std::vector<double> global( size, 0.0 );
1760
1761 int k;
1762 for( unsigned int i = 0; i < this->numRowsLocal(); i++ )
1763 {
1764 for( unsigned int j = 0; j < this->numCols(); j++ )
1765 {
1766 k = i + j*M_global.numCols();
1767
1768 local[k] = (*this)(i,j);
1769 }
1770 }
1771
1772 comm.Allreduce<double>(&local[0], &global[0], size, RawValue_MPI_SUM,
1773 "GslMatrix::mpiSum()",
1774 "failed MPI.Allreduce()");
1775
1776 for( unsigned int i = 0; i < this->numRowsLocal(); i++ )
1777 {
1778 for( unsigned int j = 0; j < this->numCols(); j++ )
1779 {
1780 k = i + j*M_global.numCols();
1781
1782 M_global(i,j) = global[k];
1783 }
1784 }
1785
1786 return;
1787 }
1788
1789 void
matlabLinearInterpExtrap(const GslVector & x1Vec,const GslMatrix & y1Mat,const GslVector & x2Vec)1790 GslMatrix::matlabLinearInterpExtrap(
1791 const GslVector& x1Vec,
1792 const GslMatrix& y1Mat,
1793 const GslVector& x2Vec)
1794 {
1795 queso_require_greater_msg(x1Vec.sizeLocal(), 1, "invalid 'x1' size");
1796
1797 queso_require_equal_to_msg(x1Vec.sizeLocal(), y1Mat.numRowsLocal(), "invalid 'x1' and 'y1' sizes");
1798
1799 queso_require_equal_to_msg(x2Vec.sizeLocal(), this->numRowsLocal(), "invalid 'x2' and 'this' sizes");
1800
1801 queso_require_equal_to_msg(y1Mat.numCols(), this->numCols(), "invalid 'y1' and 'this' sizes");
1802
1803 GslVector y1Vec(x1Vec);
1804 GslVector y2Vec(x2Vec);
1805 for (unsigned int colId = 0; colId < y1Mat.numCols(); ++colId) {
1806 y1Mat.getColumn(colId,y1Vec);
1807 y2Vec.matlabLinearInterpExtrap(x1Vec,y1Vec,x2Vec);
1808 this->setColumn(colId,y2Vec);
1809 }
1810
1811 return;
1812 }
1813
1814 gsl_matrix*
data()1815 GslMatrix::data()
1816 {
1817 return m_mat;
1818 }
1819
1820 void
print(std::ostream & os)1821 GslMatrix::print(std::ostream& os) const
1822 {
1823 unsigned int nRows = this->numRowsLocal();
1824 unsigned int nCols = this->numCols();
1825
1826 if (m_printHorizontally) {
1827 for (unsigned int i = 0; i < nRows; ++i) {
1828 for (unsigned int j = 0; j < nCols; ++j) {
1829 os << (*this)(i,j)
1830 << " ";
1831 }
1832 if (i != (nRows-1)) os << "; ";
1833 }
1834 //os << std::endl;
1835 }
1836 else {
1837 for (unsigned int i = 0; i < nRows; ++i) {
1838 for (unsigned int j = 0; j < nCols; ++j) {
1839 os << (*this)(i,j)
1840 << " ";
1841 }
1842 os << std::endl;
1843 }
1844 }
1845
1846 return;
1847 }
1848
1849 void
subWriteContents(const std::string & varNamePrefix,const std::string & fileName,const std::string & fileType,const std::set<unsigned int> & allowedSubEnvIds)1850 GslMatrix::subWriteContents(
1851 const std::string& varNamePrefix,
1852 const std::string& fileName,
1853 const std::string& fileType,
1854 const std::set<unsigned int>& allowedSubEnvIds) const
1855 {
1856 queso_require_greater_equal_msg(m_env.subRank(), 0, "unexpected subRank");
1857
1858 queso_require_less_equal_msg(this->numOfProcsForStorage(), 1, "implemented just for sequential vectors for now");
1859
1860 FilePtrSetStruct filePtrSet;
1861 if (m_env.openOutputFile(fileName,
1862 fileType, // "m or hdf"
1863 allowedSubEnvIds,
1864 false,
1865 filePtrSet)) {
1866 unsigned int nRows = this->numRowsLocal();
1867 unsigned int nCols = this->numCols();
1868 *filePtrSet.ofsVar << varNamePrefix << "_sub" << m_env.subIdString() << " = zeros(" << nRows
1869 << "," << nCols
1870 << ");"
1871 << std::endl;
1872 *filePtrSet.ofsVar << varNamePrefix << "_sub" << m_env.subIdString() << " = [";
1873
1874 for (unsigned int i = 0; i < nRows; ++i) {
1875 for (unsigned int j = 0; j < nCols; ++j) {
1876 *filePtrSet.ofsVar << (*this)(i,j)
1877 << " ";
1878 }
1879 *filePtrSet.ofsVar << "\n";
1880 }
1881 *filePtrSet.ofsVar << "];\n";
1882
1883 m_env.closeFile(filePtrSet,fileType);
1884 }
1885
1886 return;
1887 }
1888
1889 void
subReadContents(const std::string & fileName,const std::string & fileType,const std::set<unsigned int> & allowedSubEnvIds)1890 GslMatrix::subReadContents(
1891 const std::string& fileName,
1892 const std::string& fileType,
1893 const std::set<unsigned int>& allowedSubEnvIds)
1894 {
1895 queso_require_greater_equal_msg(m_env.subRank(), 0, "unexpected subRank");
1896
1897 queso_require_less_equal_msg(this->numOfProcsForStorage(), 1, "implemented just for sequential vectors for now");
1898
1899 FilePtrSetStruct filePtrSet;
1900 if (m_env.openInputFile(fileName,
1901 fileType, // "m or hdf"
1902 allowedSubEnvIds,
1903 filePtrSet)) {
1904
1905 // palms
1906 unsigned int nRowsLocal = this->numRowsLocal();
1907
1908 // In the logic below, the id of a line' begins with value 0 (zero)
1909 unsigned int idOfMyFirstLine = 1;
1910 unsigned int idOfMyLastLine = nRowsLocal;
1911 unsigned int nCols = this->numCols();
1912
1913 // Read number of matrix rows in the file by taking care of the first line,
1914 // which resembles something like 'variable_name = zeros(n_rows,n_cols);'
1915 std::string tmpString;
1916
1917 // Read 'variable name' string
1918 *filePtrSet.ifsVar >> tmpString;
1919 //std::cout << "Just read '" << tmpString << "'" << std::endl;
1920
1921 // Read '=' sign
1922 *filePtrSet.ifsVar >> tmpString;
1923 //std::cout << "Just read '" << tmpString << "'" << std::endl;
1924 queso_require_equal_to_msg(tmpString, std::string("="), std::string("string should be the '=' sign"));
1925
1926 // Read 'zeros(n_rows,n_cols)' string
1927 *filePtrSet.ifsVar >> tmpString;
1928 //std::cout << "Just read '" << tmpString << "'" << std::endl;
1929 unsigned int posInTmpString = 6;
1930
1931 // Isolate 'n_rows' in a string
1932 std::string nRowsString(tmpString.size()-posInTmpString+1, ' ');
1933 unsigned int posInRowsString = 0;
1934 do {
1935 queso_require_less_msg(posInTmpString, tmpString.size(), "symbol ',' not found in first line of file");
1936 nRowsString[posInRowsString++] = tmpString[posInTmpString++];
1937 } while (tmpString[posInTmpString] != ',');
1938 nRowsString[posInRowsString] = '\0';
1939
1940 // Isolate 'n_cols' in a string
1941 posInTmpString++; // Avoid reading ',' char
1942 std::string nColsString(tmpString.size()-posInTmpString+1, ' ');
1943 unsigned int posInColsString = 0;
1944 do {
1945 queso_require_less_msg(posInTmpString, tmpString.size(), "symbol ')' not found in first line of file");
1946 nColsString[posInColsString++] = tmpString[posInTmpString++];
1947 } while (tmpString[posInTmpString] != ')');
1948 nColsString[posInColsString] = '\0';
1949
1950 // Convert 'n_rows' and 'n_cols' strings to numbers
1951 unsigned int numRowsInFile = (unsigned int) strtod(nRowsString.c_str(),NULL);
1952 unsigned int numColsInFile = (unsigned int) strtod(nColsString.c_str(),NULL);
1953 if (m_env.subDisplayFile()) {
1954 *m_env.subDisplayFile() << "In GslMatrix::subReadContents()"
1955 << ": fullRank " << m_env.fullRank()
1956 << ", numRowsInFile = " << numRowsInFile
1957 << ", numColsInFile = " << numColsInFile
1958 << ", nRowsLocal = " << nRowsLocal
1959 << ", nCols = " << nCols
1960 << std::endl;
1961 }
1962
1963 // Check if [num of rows in file] == [requested matrix row size]
1964 queso_require_equal_to_msg(numRowsInFile, nRowsLocal, "size of vec in file is not big enough");
1965
1966 // Check if [num of cols in file] == [num cols in current matrix]
1967 queso_require_equal_to_msg(numColsInFile, nCols, "number of parameters of vec in file is different than number of parameters in this vec object");
1968
1969 // Code common to any core in a communicator
1970 unsigned int maxCharsPerLine = 64*nCols; // Up to about 60 characters to represent each parameter value
1971
1972 unsigned int lineId = 0;
1973 while (lineId < idOfMyFirstLine) {
1974 filePtrSet.ifsVar->ignore(maxCharsPerLine,'\n');
1975 lineId++;
1976 };
1977
1978 if (m_env.subDisplayFile()) {
1979 *m_env.subDisplayFile() << "In GslMatrix::subReadContents()"
1980 << ": beginning to read input actual data"
1981 << std::endl;
1982 }
1983
1984 // Take care of initial part of the first data line,
1985 // which resembles something like 'variable_name = [value1 value2 ...'
1986 // Read 'variable name' string
1987 *filePtrSet.ifsVar >> tmpString;
1988 //std::cout << "Core 0 just read '" << tmpString << "'" << std::endl;
1989
1990 // Read '=' sign
1991 *filePtrSet.ifsVar >> tmpString;
1992 //std::cout << "Core 0 just read '" << tmpString << "'" << std::endl;
1993 queso_require_equal_to_msg(tmpString, std::string("="), std::string("in core 0, string should be the '=' sign"));
1994
1995 // Take into account the ' [' portion
1996 std::streampos tmpPos = filePtrSet.ifsVar->tellg();
1997 filePtrSet.ifsVar->seekg(tmpPos+(std::streampos)2);
1998
1999 if (m_env.subDisplayFile()) {
2000 *m_env.subDisplayFile() << "In GslMatrix::subReadContents()"
2001 << ": beginning to read lines with numbers only"
2002 << ", lineId = " << lineId
2003 << ", idOfMyFirstLine = " << idOfMyFirstLine
2004 << ", idOfMyLastLine = " << idOfMyLastLine
2005 << std::endl;
2006 }
2007
2008 double tmpRead;
2009 while (lineId <= idOfMyLastLine) {
2010 for (unsigned int j = 0; j < nCols; ++j) {
2011 *filePtrSet.ifsVar >> tmpRead;
2012 (*this)(lineId-idOfMyFirstLine,j) = tmpRead;
2013 }
2014 lineId++;
2015 };
2016
2017 m_env.closeFile(filePtrSet,fileType);
2018 }
2019
2020 return;
2021 }
2022
2023 std::ostream&
2024 operator<<(std::ostream& os, const GslMatrix& obj)
2025 {
2026 obj.print(os);
2027
2028 return os;
2029 }
2030
2031 GslMatrix operator*(double a, const GslMatrix& mat)
2032 {
2033 GslMatrix answer(mat);
2034 answer *= a;
2035 return answer;
2036 }
2037
2038 GslVector operator*(const GslMatrix& mat, const GslVector& vec)
2039 {
2040 return mat.multiply(vec);
2041 }
2042
2043 GslMatrix operator*(const GslMatrix& m1, const GslMatrix& m2)
2044 {
2045 unsigned int m1Rows = m1.numRowsLocal();
2046 unsigned int m1Cols = m1.numCols();
2047 unsigned int m2Rows = m2.numRowsLocal();
2048 unsigned int m2Cols = m2.numCols();
2049
2050 queso_require_equal_to_msg(m1Cols, m2Rows, "different sizes m1Cols and m2Rows");
2051
2052 GslMatrix mat(m1.env(),m1.map(),m2Cols);
2053
2054 //std::cout << "In GslMatrix(mat * mat): m1Cols = " << m1Cols << std::endl;
2055
2056 unsigned int commonSize = m1Cols;
2057 for (unsigned int row1 = 0; row1 < m1Rows; ++row1) {
2058 for (unsigned int col2 = 0; col2 < m2Cols; ++col2) {
2059 double result = 0.;
2060 for (unsigned int k = 0; k < commonSize; ++k) {
2061 result += m1(row1,k)*m2(k,col2);
2062 }
2063 mat(row1,col2) = result;
2064 }
2065 //std::cout << "In GslMatrix(mat * mat): ended row " << row1 << std::endl;
2066 }
2067
2068 return mat;
2069 }
2070
2071 GslMatrix operator+(const GslMatrix& m1, const GslMatrix& m2)
2072 {
2073 GslMatrix answer(m1);
2074 answer += m2;
2075 return answer;
2076 }
2077
2078 GslMatrix operator-(const GslMatrix& m1, const GslMatrix& m2)
2079 {
2080 GslMatrix answer(m1);
2081 answer -= m2;
2082 return answer;
2083 }
2084
matrixProduct(const GslVector & v1,const GslVector & v2)2085 GslMatrix matrixProduct(const GslVector& v1, const GslVector& v2)
2086 {
2087 unsigned int nRows = v1.sizeLocal();
2088 unsigned int nCols = v2.sizeLocal();
2089 GslMatrix answer(v1.env(),v1.map(),nCols);
2090
2091 for (unsigned int i = 0; i < nRows; ++i) {
2092 double value1 = v1[i];
2093 for (unsigned int j = 0; j < nCols; ++j) {
2094 answer(i,j) = value1*v2[j];
2095 }
2096 }
2097
2098 return answer;
2099 }
2100
leftDiagScaling(const GslVector & vec,const GslMatrix & mat)2101 GslMatrix leftDiagScaling(const GslVector& vec, const GslMatrix& mat)
2102 {
2103 unsigned int vSize = vec.sizeLocal();
2104 unsigned int mRows = mat.numRowsLocal();
2105 unsigned int mCols = mat.numCols();
2106
2107 queso_require_equal_to_msg(vSize, mRows, "size of vector is different from the number of rows in matrix");
2108
2109 queso_require_equal_to_msg(mCols, mRows, "routine currently works for square matrices only");
2110
2111 GslMatrix answer(mat);
2112 for (unsigned int i = 0; i < mRows; ++i) {
2113 double vecValue = vec[i];
2114 for (unsigned int j = 0; j < mCols; ++j) {
2115 answer(i,j) *= vecValue;
2116 }
2117 }
2118
2119 return answer;
2120 }
2121
rightDiagScaling(const GslMatrix & mat,const GslVector & vec)2122 GslMatrix rightDiagScaling(const GslMatrix& mat, const GslVector& vec)
2123 {
2124 unsigned int vSize = vec.sizeLocal();
2125 unsigned int mRows = mat.numRowsLocal();
2126 unsigned int mCols = mat.numCols();
2127
2128 queso_require_equal_to_msg(vSize, mCols, "size of vector is different from the number of cols in matrix");
2129
2130 queso_require_equal_to_msg(mCols, mRows, "routine currently works for square matrices only");
2131
2132 GslMatrix answer(mat);
2133 for (unsigned int j = 0; j < mCols; ++j) {
2134 double vecValue = vec[j];
2135 for (unsigned int i = 0; i < mRows; ++i) {
2136 answer(i,j) *= vecValue;
2137 }
2138 }
2139
2140 return answer;
2141 }
2142
2143 } // End namespace QUESO
2144