MOOSE - Multiscale Object Oriented Simulation Environment
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
MatrixOps.cpp File Reference
#include <vector>
#include <math.h>
#include "doubleEq.h"
#include <iostream>
#include "MatrixOps.h"
+ Include dependency graph for MatrixOps.cpp:

Go to the source code of this file.

Functions

double doPartialPivot (Matrix *A, unsigned int row, unsigned int col, vector< unsigned int > *swaps)
 
MatrixmatAlloc (unsigned int n)
 
double matColNorm (Matrix *A)
 
MatrixmatEyeAdd (const Matrix *A, double k)
 
void matEyeAdd (Matrix *A, double k, unsigned int dummy)
 
void matInv (Matrix *A, vector< unsigned int > *swaps, Matrix *invA)
 
MatrixmatMatAdd (const Matrix *A, const Matrix *B, double alpha, double beta)
 
void matMatAdd (Matrix *A, Matrix *B, double alpha, double beta, unsigned int resIndex)
 
MatrixmatMatMul (Matrix *A, Matrix *B)
 
void matMatMul (Matrix *A, Matrix *B, unsigned int resIndex)
 
void matPermMul (Matrix *A, vector< unsigned int > *swaps)
 
void matPrint (Matrix *A)
 
MatrixmatScalShift (const Matrix *A, double mul, double add)
 
void matScalShift (Matrix *A, double mul, double add, unsigned int dummy)
 
double matTrace (Matrix *A)
 
MatrixmatTrans (Matrix *A)
 
VectormatVecMul (Matrix *A, Vector *v)
 
void triMatMul (Matrix *A, Matrix *B)
 
VectorvecAlloc (unsigned int n)
 
VectorvecMatMul (const Vector *v, Matrix *A)
 
void vecPrint (Vector *v)
 
VectorvecScalShift (const Vector *v, double scal, double shift)
 
void vecScalShift (Vector *v, double scal, double shift, unsigned int dummy)
 
VectorvecVecScalAdd (const Vector *v1, const Vector *v2, double alpha, double beta)
 
void vecVecScalAdd (Vector *v1, Vector *v2, double alpha, double beta, unsigned int dummy)
 

Function Documentation

double doPartialPivot ( Matrix A,
unsigned int  row,
unsigned int  col,
vector< unsigned int > *  swaps 
)

Definition at line 314 of file MatrixOps.cpp.

References doubleEq().

Referenced by matInv().

316 {
317  unsigned int n = A->size(), pivotRow = row;
318  double pivot = (*A)[row][col];
319 
320  for( unsigned i = row; i < n; ++i )
321  {
322  if( fabs( (*A)[i][col] ) > pivot )
323  {
324  pivotRow = i;
325  pivot = (*A)[i][col];
326  }
327  }
328 
329  //If pivot is non-zero, do the row swap.
330  if ( !doubleEq(pivot,0.0) && pivotRow != row )
331  {
332  Matrix::iterator pivotRowItr = (A->begin() + pivotRow);
333  Matrix::iterator currRowItr = (A->begin() + row);
334  swap( *pivotRowItr, *currRowItr );
335 
336  //The row numbers interchanged are stored as a 2-digit number and pushed
337  //into this vector. This information is later used in creating the
338  //permutation matrices.
339  swaps->push_back( 10 * pivotRow + row );
340  return pivot;
341  }
342  else if ( !doubleEq(pivot, 0.0) && pivotRow == row )
343  return (*A)[row][col]; //Choice of pivot is unchanged.
344  else
345  return 0; //Matrix is singular!
346 }
bool doubleEq(double x, double y)
Definition: doubleEq.cpp:16

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Matrix* matAlloc ( unsigned int  n)

Definition at line 480 of file MatrixOps.cpp.

Referenced by MarkovSolver::computePadeApproximant(), MarkovSolverBase::init(), matEyeAdd(), matInv(), matMatAdd(), matMatMul(), matScalShift(), and matTrans().

481 {
482  Matrix* A = new Matrix;
483 
484  A->resize( n );
485  for ( unsigned int i = 0; i < n; ++i )
486  (*A)[i].resize( n, 0.0 );
487 
488  return A;
489 }
vector< vector< double > > Matrix
Definition: MatrixOps.h:22

+ Here is the caller graph for this function:

double matColNorm ( Matrix A)

Definition at line 282 of file MatrixOps.cpp.

Referenced by MarkovSolver::computeMatrixExponential().

283 {
284  double norm = 0, colSum = 0;
285  unsigned int n = A->size();
286 
287  for( unsigned int i = 0; i < n; ++i )
288  {
289  colSum = 0;
290  for( unsigned int j = 0; j < n; ++j )
291  colSum += fabs( (*A)[j][i] );
292 
293  if ( colSum > norm )
294  norm = colSum;
295  }
296 
297  return norm;
298 }

+ Here is the caller graph for this function:

Matrix* matEyeAdd ( const Matrix A,
double  k 
)

Definition at line 147 of file MatrixOps.cpp.

References matAlloc().

Referenced by MarkovSolver::computeMatrixExponential(), and MarkovSolver::computePadeApproximant().

148 {
149  unsigned int n = A->size();
150  Matrix* B = matAlloc( n );
151 
152  for( unsigned int i = 0; i < n; ++i )
153  {
154  for( unsigned int j = 0; j < n; ++j )
155  {
156  if ( i == j )
157  (*B)[i][j] = (*A)[i][j] + k;
158  else
159  (*B)[i][j] = (*A)[i][j];
160  }
161  }
162 
163  return B;
164 }
vector< vector< double > > Matrix
Definition: MatrixOps.h:22
Matrix * matAlloc(unsigned int n)
Definition: MatrixOps.cpp:480

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void matEyeAdd ( Matrix A,
double  k,
unsigned int  dummy 
)

Definition at line 166 of file MatrixOps.cpp.

167 {
168  unsigned int n = A->size();
169  dummy = 0;
170 
171  for( unsigned int i = 0; i < n; ++i )
172  (*A)[i][i] += k;
173 }
static DestFinfo dummy("dummy","This Finfo is a dummy. If you are reading this you have used an invalid index", 0)
void matInv ( Matrix A,
vector< unsigned int > *  swaps,
Matrix invA 
)

Definition at line 348 of file MatrixOps.cpp.

References doPartialPivot(), doubleEq(), EPSILON, matAlloc(), matPermMul(), and triMatMul().

Referenced by MarkovSolver::computePadeApproximant().

349 {
350  Matrix *L, *invL;
351  unsigned int n = A->size(), i, j, diagPos;
352  double pivot, rowMultiplier1, rowMultiplier2;
353 
354  L = matAlloc( n );
355  invL = matAlloc( n );
356  *invA = *A;
357 
358  //The upper triangular portion is stored and inverted in invA
359 
360  //Creating a copy of the input matrix, as well as initializing the
361  //lower triangular matrix L.
362  for (i = 0; i < n; ++i)
363  (*L)[i][i] = 1;
364 
366  //Calculation of LU decomposition.
368  for ( unsigned int k = 0; k < n; ++k )
369  pivot = doPartialPivot( invA, k, k, swaps );
370 
371  diagPos = 0;
372  pivot = 0;
373  i = 1;
374  j = 0;
375  while( diagPos < n - 1 )
376  {
377  rowMultiplier1 = (*invA)[diagPos][j]; //Pivot element.
378  rowMultiplier2 = (*invA)[i][j];
379 
380  (*invA)[i][j] = 0;
381  for( unsigned int k = j + 1; k < n; ++k )
382  (*invA)[i][k] = ( (*invA)[i][k] * rowMultiplier1 -
383  (*invA)[diagPos][k] *rowMultiplier2 ) / rowMultiplier1;
384 
385 
386  (*L)[i][j] = rowMultiplier2 / rowMultiplier1;
387 
388  if ( i != n - 1 )
389  ++i;
390  else
391  {
392  ++j;
393  ++diagPos;
394  //In case of zero pivot, divide by a very small number whose value we
395  //know.
396  if ( doubleEq( (*invA)[diagPos][diagPos], 0.0 ) )
397  {
398  cerr << "Warning : Singularity detected. Proceeding with computation"
399  "anyway.\n";
400  (*invA)[diagPos][diagPos] = EPSILON;
401  }
402 
403  i = diagPos + 1;
404  }
405  }
406  //End of computation of L and U (which is stored in invA).
408 
410  //Obtaining the inverse of invA and L, which is obtained by solving the
411  //simple systems Ux = I and Lx= I.
413 
414  double sum = 0;
415 
416  //We serially solve for the equations Ux = e_n, Ux=e_{n-1} ..., Ux = e1.
417  //where, e_k is the k'th elementary basis vector.
418  for( int k = n - 1; k >= 0; --k )
419  {
420  for ( int l = k; l >= 0; --l )
421  {
422  sum = 0;
423 
424  if ( l != k )
425  {
426  for ( int m = k; m > l; --m )
427  sum += (*invA)[l][m] * (*invA)[m][k];
428  }
429 
430  if ( l == k )
431  (*invA)[l][k] = (1 - sum)/(*invA)[l][l];
432  else
433  (*invA)[l][k] = -sum/(*invA)[l][l];
434  }
435  }
436  //Similarly as above, we find the inverse of the lower triangular matrix by
437  //forward-substitution.
438 
439  *invL = *L;
440  double invTemp;
441 
442  //Always true when the diagonal elements are 1.
443  for( unsigned int k = 0; k < n - 1; ++k )
444  (*invL)[k+1][k] = -(*invL)[k+1][k];
445 
446  for( unsigned int k = 0; k <= n - 1; ++k )
447  {
448  for( unsigned int l = k + 2; l <= n - 1; ++l )
449  {
450  invTemp = 0;
451  for ( unsigned int m = k + 1; m <= n - 1; ++m )
452  invTemp -= (*invL)[m][k] * (*L)[l][m];
453 
454  (*invL)[l][k] = invTemp;
455  }
456  }
457 
458  //End of computation of invL and invU. Note that they have been computed in
459  //place, which means the original copies of L and U are now gone.
461 
463  //Constructing the inverse of the permutation matrix P.
464  //P is calculated only if there was any pivoting carried out.
465  //At this stage, L^(-1) has already been calculated.
466  //P^(-1) = P^T.
467  //Since we have computed PA = LU,
468  //the final inverse is given by U^(-1)*L^(-1)*P^(-1).
469  //If P was not calculated i.e. there were no exchanges, then the
470  //inverse is just U^(-1) * L^(-1).
472  triMatMul( invA, invL );
473  if ( !swaps->empty() )
474  matPermMul( invA, swaps );
475 
476  delete invL;
477  delete L;
478 }
void matPermMul(Matrix *A, vector< unsigned int > *swaps)
Definition: MatrixOps.cpp:88
bool doubleEq(double x, double y)
Definition: doubleEq.cpp:16
void triMatMul(Matrix *A, Matrix *B)
Definition: MatrixOps.cpp:67
double doPartialPivot(Matrix *A, unsigned int row, unsigned int col, vector< unsigned int > *swaps)
Definition: MatrixOps.cpp:314
vector< vector< double > > Matrix
Definition: MatrixOps.h:22
#define EPSILON
Definition: MatrixOps.h:28
Matrix * matAlloc(unsigned int n)
Definition: MatrixOps.cpp:480

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Matrix* matMatAdd ( const Matrix A,
const Matrix B,
double  alpha,
double  beta 
)

Definition at line 111 of file MatrixOps.cpp.

References matAlloc().

Referenced by MarkovSolver::computePadeApproximant().

112 {
113  unsigned int n = A->size();
114  Matrix *C = matAlloc( n );
115 
116  for( unsigned int i = 0; i < n; ++i )
117  {
118  for( unsigned int j = 0; j < n; ++j )
119  (*C)[i][j] = alpha * (*A)[i][j] + beta * (*B)[i][j];
120  }
121 
122  return C;
123 }
vector< vector< double > > Matrix
Definition: MatrixOps.h:22
Matrix * matAlloc(unsigned int n)
Definition: MatrixOps.cpp:480

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void matMatAdd ( Matrix A,
Matrix B,
double  alpha,
double  beta,
unsigned int  resIndex 
)

Definition at line 125 of file MatrixOps.cpp.

References FIRST, and SECOND.

127 {
128  Matrix *C;
129  unsigned int n = A->size();
130 
131  if ( resIndex == FIRST ) {
132  C = A;
133  } else if ( resIndex == SECOND ) {
134  C = B;
135  } else {
136  cerr << "matMatAdd : Invalid index supplied to store result.\n";
137  return;
138  }
139 
140  for( unsigned int i = 0; i < n; ++i )
141  {
142  for( unsigned int j = 0; j < n; ++j )
143  (*C)[i][j] = alpha * (*A)[i][j] + beta * (*B)[i][j];
144  }
145 }
#define SECOND
Definition: MatrixOps.h:31
vector< vector< double > > Matrix
Definition: MatrixOps.h:22
#define FIRST
Definition: MatrixOps.h:30
Matrix* matMatMul ( Matrix A,
Matrix B 
)

Definition at line 36 of file MatrixOps.cpp.

References matAlloc().

Referenced by MarkovSolver::computeMatrixExponential(), MarkovSolver::computePadeApproximant(), and matMatMul().

37 {
38  unsigned int n = A->size();
39  Matrix *C = matAlloc( n );
40 
41  for( unsigned int i = 0; i < n; ++i )
42  {
43  for( unsigned int j = 0; j < n; ++j )
44  {
45  for( unsigned int k = 0; k < n; ++k )
46  (*C)[i][j] += (*A)[i][k] * (*B)[k][j];
47  }
48  }
49 
50  return C;
51 }
vector< vector< double > > Matrix
Definition: MatrixOps.h:22
Matrix * matAlloc(unsigned int n)
Definition: MatrixOps.cpp:480

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void matMatMul ( Matrix A,
Matrix B,
unsigned int  resIndex 
)

Definition at line 53 of file MatrixOps.cpp.

References FIRST, matMatMul(), and SECOND.

54 {
55  Matrix *C;
56 
57  C = matMatMul( A, B );
58 
59  if ( resIndex == FIRST )
60  *A = *C;
61  else if ( resIndex == SECOND )
62  *B = *C;
63 
64  delete C;
65 }
#define SECOND
Definition: MatrixOps.h:31
Matrix * matMatMul(Matrix *A, Matrix *B)
Definition: MatrixOps.cpp:36
vector< vector< double > > Matrix
Definition: MatrixOps.h:22
#define FIRST
Definition: MatrixOps.h:30

+ Here is the call graph for this function:

void matPermMul ( Matrix A,
vector< unsigned int > *  swaps 
)

Definition at line 88 of file MatrixOps.cpp.

Referenced by matInv().

89 {
90  unsigned int i,j,n,index;
91  double temp;
92  n = A->size();
93 
94  while (!swaps->empty())
95  {
96  index = swaps->back();
97  swaps->pop_back();
98  i = index % 10;
99  j = (index / 10 ) % 10;
100 
101  //Swapping the columns.
102  for( unsigned int l = 0; l < n; ++l )
103  {
104  temp = (*A)[l][i];
105  (*A)[l][i] = (*A)[l][j];
106  (*A)[l][j] = temp;
107  }
108  }
109 }

+ Here is the caller graph for this function:

void matPrint ( Matrix A)

Definition at line 19 of file MatrixOps.cpp.

20 {
21  for( unsigned int i = 0; i < A->size(); ++i )
22  {
23  for( unsigned int j = 0; j < A->size(); ++j )
24  cout << (*A)[i][j] << " ";
25  cout << endl;
26  }
27 }
Matrix* matScalShift ( const Matrix A,
double  mul,
double  add 
)

Definition at line 175 of file MatrixOps.cpp.

References matAlloc().

Referenced by MarkovSolver::computeMatrixExponential(), and MarkovSolver::computePadeApproximant().

176 {
177  unsigned int n = A->size();
178  Matrix *C = matAlloc( n );
179 
180  for( unsigned int i = 0; i < n; ++i )
181  {
182  for( unsigned int j = 0; j < n; ++j )
183  (*C)[i][j] = (*A)[i][j] * mul + add;
184  }
185 
186  return C;
187 }
vector< vector< double > > Matrix
Definition: MatrixOps.h:22
Matrix * matAlloc(unsigned int n)
Definition: MatrixOps.cpp:480

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void matScalShift ( Matrix A,
double  mul,
double  add,
unsigned int  dummy 
)

Definition at line 189 of file MatrixOps.cpp.

190 {
191  unsigned int n = A->size();
192  dummy = 0;
193 
194  for( unsigned int i = 0; i < n; ++i )
195  {
196  for( unsigned int j = 0; j < n; ++j )
197  (*A)[i][j] = (*A)[i][j] * mul + add;
198  }
199 }
static DestFinfo dummy("dummy","This Finfo is a dummy. If you are reading this you have used an invalid index", 0)
double matTrace ( Matrix A)

Definition at line 271 of file MatrixOps.cpp.

References moose::trace.

Referenced by MarkovSolver::computeMatrixExponential().

272 {
273  unsigned int n = A->size();
274  double trace = 0;
275 
276  for ( unsigned int i = 0; i < n; ++i )
277  trace += (*A)[i][i];
278 
279  return trace;
280 }

+ Here is the caller graph for this function:

Matrix* matTrans ( Matrix A)

Definition at line 300 of file MatrixOps.cpp.

References matAlloc().

301 {
302  unsigned int n = A->size();
303  Matrix* At = matAlloc( n );
304 
305  for( unsigned int i = 0; i < n; ++i )
306  {
307  for( unsigned int j = 0; j < n; ++j )
308  (*At)[i][j] = (*A)[j][i];
309  }
310 
311  return At;
312 }
vector< vector< double > > Matrix
Definition: MatrixOps.h:22
Matrix * matAlloc(unsigned int n)
Definition: MatrixOps.cpp:480

+ Here is the call graph for this function:

Vector* matVecMul ( Matrix A,
Vector v 
)

Definition at line 235 of file MatrixOps.cpp.

References vecAlloc().

236 {
237  unsigned int n = A->size();
238  Vector* w = vecAlloc( n );
239 
240  for( unsigned int i = 0; i < n; ++i )
241  {
242  for( unsigned int j = 0; j < n; ++j )
243  (*w)[i] += (*A)[i][j] * (*v)[j];
244  }
245 
246  return w;
247 }
vector< double > Vector
Definition: MatrixOps.h:23
Vector * vecAlloc(unsigned int n)
Definition: MatrixOps.cpp:491

+ Here is the call graph for this function:

void triMatMul ( Matrix A,
Matrix B 
)

Definition at line 67 of file MatrixOps.cpp.

Referenced by matInv().

68 {
69  unsigned int n = A->size();
70  unsigned int k;
71  double temp;
72 
73  for ( unsigned int i = 0; i < n; ++i )
74  {
75  for ( unsigned int j = 0; j < n; ++j )
76  {
77  k = j >= i ? j : i;
78  temp = (*A)[i][j];
79 
80  for ( ; k < n; ++k )
81  (*A)[i][j] += (*A)[i][k] * (*B)[k][j];
82 
83  (*A)[i][j] -= temp;
84  }
85  }
86 }

+ Here is the caller graph for this function:

Vector* vecAlloc ( unsigned int  n)

Definition at line 491 of file MatrixOps.cpp.

Referenced by matVecMul(), vecMatMul(), vecScalShift(), and vecVecScalAdd().

492 {
493  Vector* vec = new Vector;
494 
495  vec->resize( n, 0.0 );
496 
497  return vec;
498 }
vector< double > Vector
Definition: MatrixOps.h:23

+ Here is the caller graph for this function:

Vector* vecMatMul ( const Vector v,
Matrix A 
)

Definition at line 201 of file MatrixOps.cpp.

References vecAlloc().

Referenced by MarkovSolverBase::bilinearInterpolate(), and MarkovSolverBase::linearInterpolate().

202 {
203  unsigned int n = A->size();
204  Vector* w = vecAlloc( n );
205 
206  for( unsigned int i = 0; i < n; ++i )
207  {
208  for( unsigned int j = 0; j < n; ++j )
209  (*w)[i] += (*v)[j] * (*A)[j][i];
210  }
211 
212  return w;
213 }
vector< double > Vector
Definition: MatrixOps.h:23
Vector * vecAlloc(unsigned int n)
Definition: MatrixOps.cpp:491

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void vecPrint ( Vector v)

Definition at line 29 of file MatrixOps.cpp.

30 {
31  for( unsigned int j = 0; j < v->size(); ++j )
32  cout << (*v)[j] << " ";
33  cout << endl;
34 }
Vector* vecScalShift ( const Vector v,
double  scal,
double  shift 
)

Definition at line 215 of file MatrixOps.cpp.

References vecAlloc().

216 {
217  unsigned int n = v->size();
218  Vector* w = vecAlloc( n );
219 
220  for ( unsigned int i = 0; i < n; ++i )
221  (*w)[i] = scal * (*v)[i] + shift;
222 
223  return w;
224 }
vector< double > Vector
Definition: MatrixOps.h:23
Vector * vecAlloc(unsigned int n)
Definition: MatrixOps.cpp:491

+ Here is the call graph for this function:

void vecScalShift ( Vector v,
double  scal,
double  shift,
unsigned int  dummy 
)

Definition at line 226 of file MatrixOps.cpp.

227 {
228  unsigned int n = v->size();
229  dummy = 0;
230 
231  for ( unsigned int i = 0; i < n; ++i )
232  (*v)[i] += scal * (*v)[i] + shift;
233 }
static DestFinfo dummy("dummy","This Finfo is a dummy. If you are reading this you have used an invalid index", 0)
Vector* vecVecScalAdd ( const Vector v1,
const Vector v2,
double  alpha,
double  beta 
)

Definition at line 249 of file MatrixOps.cpp.

References vecAlloc().

Referenced by MarkovSolverBase::bilinearInterpolate(), and MarkovSolverBase::linearInterpolate().

251 {
252  unsigned int n = v1->size();
253  Vector *w = vecAlloc( n );
254 
255  for ( unsigned int i = 0; i < n; ++i )
256  (*w)[i] = (*v1)[i] * alpha + (*v2)[i] * beta;
257 
258  return w;
259 }
vector< double > Vector
Definition: MatrixOps.h:23
Vector * vecAlloc(unsigned int n)
Definition: MatrixOps.cpp:491

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void vecVecScalAdd ( Vector v1,
Vector v2,
double  alpha,
double  beta,
unsigned int  dummy 
)

Definition at line 261 of file MatrixOps.cpp.

263 {
264  unsigned int n = v1->size();
265  dummy = 0;
266 
267  for ( unsigned int i = 0; i < n; ++i )
268  (*v1)[i] = (*v1)[i] * alpha + (*v2)[i] * beta;
269 }
static DestFinfo dummy("dummy","This Finfo is a dummy. If you are reading this you have used an invalid index", 0)