MFEM  v3.4
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
densemat.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 #ifndef MFEM_DENSEMAT
13 #define MFEM_DENSEMAT
14 
15 #include "../config/config.hpp"
16 #include "../general/globals.hpp"
17 #include "matrix.hpp"
18 
19 namespace mfem
20 {
21 
22 /// Data type dense matrix using column-major storage
23 class DenseMatrix : public Matrix
24 {
25  friend class DenseTensor;
26  friend class DenseMatrixInverse;
27 
28 private:
29  double *data;
30  int capacity; // zero or negative capacity means we do not own the data.
31 
32  void Eigensystem(Vector &ev, DenseMatrix *evect = NULL);
33 
34  // Auxiliary method used in FNorm2() and FNorm()
35  void FNorm(double &scale_factor, double &scaled_fnorm2) const;
36 
37 public:
38  /** Default constructor for DenseMatrix.
39  Sets data = NULL and height = width = 0. */
40  DenseMatrix();
41 
42  /// Copy constructor
43  DenseMatrix(const DenseMatrix &);
44 
45  /// Creates square matrix of size s.
46  explicit DenseMatrix(int s);
47 
48  /// Creates rectangular matrix of size m x n.
49  DenseMatrix(int m, int n);
50 
51  /// Creates rectangular matrix equal to the transpose of mat.
52  DenseMatrix(const DenseMatrix &mat, char ch);
53 
54  /** Construct a DenseMatrix using existing data array. The DenseMatrix does
55  not assume ownership of the data array, i.e. it will not delete the
56  array. */
57  DenseMatrix(double *d, int h, int w) : Matrix(h, w)
58  { data = d; capacity = -h*w; }
59 
60  /// Change the data array and the size of the DenseMatrix.
61  /** The DenseMatrix does not assume ownership of the data array, i.e. it will
62  not delete the data array @a d. This method should not be used with
63  DenseMatrix that owns its current data array. */
64  void UseExternalData(double *d, int h, int w)
65  { data = d; height = h; width = w; capacity = -h*w; }
66 
67  /// Change the data array and the size of the DenseMatrix.
68  /** The DenseMatrix does not assume ownership of the data array, i.e. it will
69  not delete the new array @a d. This method will delete the current data
70  array, if owned. */
71  void Reset(double *d, int h, int w)
72  { if (OwnsData()) { delete [] data; } UseExternalData(d, h, w); }
73 
74  /** Clear the data array and the dimensions of the DenseMatrix. This method
75  should not be used with DenseMatrix that owns its current data array. */
76  void ClearExternalData() { data = NULL; height = width = 0; capacity = 0; }
77 
78  /// Delete the matrix data array (if owned) and reset the matrix state.
79  void Clear()
80  { if (OwnsData()) { delete [] data; } ClearExternalData(); }
81 
82  /// For backward compatibility define Size to be synonym of Width()
83  int Size() const { return Width(); }
84 
85  /// Change the size of the DenseMatrix to s x s.
86  void SetSize(int s) { SetSize(s, s); }
87 
88  /// Change the size of the DenseMatrix to h x w.
89  void SetSize(int h, int w);
90 
91  /// Returns the matrix data array.
92  inline double *Data() const { return data; }
93  /// Returns the matrix data array.
94  inline double *GetData() const { return data; }
95 
96  inline bool OwnsData() const { return (capacity > 0); }
97 
98  /// Returns reference to a_{ij}.
99  inline double &operator()(int i, int j);
100 
101  /// Returns constant reference to a_{ij}.
102  inline const double &operator()(int i, int j) const;
103 
104  /// Matrix inner product: tr(A^t B)
105  double operator*(const DenseMatrix &m) const;
106 
107  /// Trace of a square matrix
108  double Trace() const;
109 
110  /// Returns reference to a_{ij}.
111  virtual double &Elem(int i, int j);
112 
113  /// Returns constant reference to a_{ij}.
114  virtual const double &Elem(int i, int j) const;
115 
116  /// Matrix vector multiplication.
117  void Mult(const double *x, double *y) const;
118 
119  /// Matrix vector multiplication.
120  virtual void Mult(const Vector &x, Vector &y) const;
121 
122  /// Multiply a vector with the transpose matrix.
123  void MultTranspose(const double *x, double *y) const;
124 
125  /// Multiply a vector with the transpose matrix.
126  virtual void MultTranspose(const Vector &x, Vector &y) const;
127 
128  /// y += A.x
129  void AddMult(const Vector &x, Vector &y) const;
130 
131  /// y += A^t x
132  void AddMultTranspose(const Vector &x, Vector &y) const;
133 
134  /// y += a * A.x
135  void AddMult_a(double a, const Vector &x, Vector &y) const;
136 
137  /// y += a * A^t x
138  void AddMultTranspose_a(double a, const Vector &x, Vector &y) const;
139 
140  /// Compute y^t A x
141  double InnerProduct(const double *x, const double *y) const;
142 
143  /// LeftScaling this = diag(s) * this
144  void LeftScaling(const Vector & s);
145  /// InvLeftScaling this = diag(1./s) * this
146  void InvLeftScaling(const Vector & s);
147  /// RightScaling: this = this * diag(s);
148  void RightScaling(const Vector & s);
149  /// InvRightScaling: this = this * diag(1./s);
150  void InvRightScaling(const Vector & s);
151  /// SymmetricScaling this = diag(sqrt(s)) * this * diag(sqrt(s))
152  void SymmetricScaling(const Vector & s);
153  /// InvSymmetricScaling this = diag(sqrt(1./s)) * this * diag(sqrt(1./s))
154  void InvSymmetricScaling(const Vector & s);
155 
156  /// Compute y^t A x
157  double InnerProduct(const Vector &x, const Vector &y) const
158  { return InnerProduct((const double *)x, (const double *)y); }
159 
160  /// Returns a pointer to the inverse matrix.
161  virtual MatrixInverse *Inverse() const;
162 
163  /// Replaces the current matrix with its inverse
164  void Invert();
165 
166  /// Replaces the current matrix with its square root inverse
167  void SquareRootInverse();
168 
169  /// Calculates the determinant of the matrix
170  /// (optimized for 2x2, 3x3, and 4x4 matrices)
171  double Det() const;
172 
173  double Weight() const;
174 
175  /** @brief Set the matrix to alpha * A, assuming that A has the same
176  dimensions as the matrix and uses column-major layout. */
177  void Set(double alpha, const double *A);
178  /// Set the matrix to alpha * A.
179  void Set(double alpha, const DenseMatrix &A)
180  {
181  SetSize(A.Height(), A.Width());
182  Set(alpha, A.GetData());
183  }
184 
185  /// Adds the matrix A multiplied by the number c to the matrix
186  void Add(const double c, const DenseMatrix &A);
187 
188  /// Sets the matrix elements equal to constant c
189  DenseMatrix &operator=(double c);
190 
191  /// Copy the matrix entries from the given array
192  DenseMatrix &operator=(const double *d);
193 
194  /// Sets the matrix size and elements equal to those of m
195  DenseMatrix &operator=(const DenseMatrix &m);
196 
197  DenseMatrix &operator+=(const double *m);
199 
201 
202  DenseMatrix &operator*=(double c);
203 
204  /// (*this) = -(*this)
205  void Neg();
206 
207  /// Take the 2-norm of the columns of A and store in v
208  void Norm2(double *v) const;
209 
210  /// Compute the norm ||A|| = max_{ij} |A_{ij}|
211  double MaxMaxNorm() const;
212 
213  /// Compute the Frobenius norm of the matrix
214  double FNorm() const { double s, n2; FNorm(s, n2); return s*sqrt(n2); }
215 
216  /// Compute the square of the Frobenius norm of the matrix
217  double FNorm2() const { double s, n2; FNorm(s, n2); return s*s*n2; }
218 
219  void Eigenvalues(Vector &ev)
220  { Eigensystem(ev); }
221 
222  void Eigenvalues(Vector &ev, DenseMatrix &evect)
223  { Eigensystem(ev, &evect); }
224 
225  void Eigensystem(Vector &ev, DenseMatrix &evect)
226  { Eigensystem(ev, &evect); }
227 
228  void SingularValues(Vector &sv) const;
229  int Rank(double tol) const;
230 
231  /// Return the i-th singular value (decreasing order) of NxN matrix, N=1,2,3.
232  double CalcSingularvalue(const int i) const;
233 
234  /** Return the eigenvalues (in increasing order) and eigenvectors of a
235  2x2 or 3x3 symmetric matrix. */
236  void CalcEigenvalues(double *lambda, double *vec) const;
237 
238  void GetRow(int r, Vector &row) const;
239  void GetColumn(int c, Vector &col) const;
240  double *GetColumn(int col) { return data + col*height; }
241  const double *GetColumn(int col) const { return data + col*height; }
242 
243  void GetColumnReference(int c, Vector &col)
244  { col.SetDataAndSize(data + c * height, height); }
245 
246  void SetRow(int r, const Vector &row);
247  void SetCol(int c, const Vector &col);
248 
249  /// Set all entries of a row to the specified value.
250  void SetRow(int row, double value);
251  /// Set all entries of a column to the specified value.
252  void SetCol(int col, double value);
253 
254  /// Returns the diagonal of the matrix
255  void GetDiag(Vector &d) const;
256  /// Returns the l1 norm of the rows of the matrix v_i = sum_j |a_ij|
257  void Getl1Diag(Vector &l) const;
258  /// Compute the row sums of the DenseMatrix
259  void GetRowSums(Vector &l) const;
260 
261  /// Creates n x n diagonal matrix with diagonal elements c
262  void Diag(double c, int n);
263  /// Creates n x n diagonal matrix with diagonal given by diag
264  void Diag(double *diag, int n);
265 
266  /// (*this) = (*this)^t
267  void Transpose();
268  /// (*this) = A^t
269  void Transpose(const DenseMatrix &A);
270  /// (*this) = 1/2 ((*this) + (*this)^t)
271  void Symmetrize();
272 
273  void Lump();
274 
275  /** Given a DShape matrix (from a scalar FE), stored in *this, returns the
276  CurlShape matrix. If *this is a N by D matrix, then curl is a D*N by
277  D*(D-1)/2 matrix. The size of curl must be set outside. The dimension D
278  can be either 2 or 3. */
279  void GradToCurl(DenseMatrix &curl);
280  /** Given a DShape matrix (from a scalar FE), stored in *this,
281  returns the DivShape vector. If *this is a N by dim matrix,
282  then div is a dim*N vector. The size of div must be set
283  outside. */
284  void GradToDiv(Vector &div);
285 
286  /// Copy rows row1 through row2 from A to *this
287  void CopyRows(const DenseMatrix &A, int row1, int row2);
288  /// Copy columns col1 through col2 from A to *this
289  void CopyCols(const DenseMatrix &A, int col1, int col2);
290  /// Copy the m x n submatrix of A at row/col offsets Aro/Aco to *this
291  void CopyMN(const DenseMatrix &A, int m, int n, int Aro, int Aco);
292  /// Copy matrix A to the location in *this at row_offset, col_offset
293  void CopyMN(const DenseMatrix &A, int row_offset, int col_offset);
294  /// Copy matrix A^t to the location in *this at row_offset, col_offset
295  void CopyMNt(const DenseMatrix &A, int row_offset, int col_offset);
296  /** Copy the m x n submatrix of A at row/col offsets Aro/Aco to *this at
297  row_offset, col_offset */
298  void CopyMN(const DenseMatrix &A, int m, int n, int Aro, int Aco,
299  int row_offset, int col_offset);
300  /// Copy c on the diagonal of size n to *this at row_offset, col_offset
301  void CopyMNDiag(double c, int n, int row_offset, int col_offset);
302  /// Copy diag on the diagonal of size n to *this at row_offset, col_offset
303  void CopyMNDiag(double *diag, int n, int row_offset, int col_offset);
304  /// Copy All rows and columns except m and n from A
305  void CopyExceptMN(const DenseMatrix &A, int m, int n);
306 
307  /// Perform (ro+i,co+j)+=A(i,j) for 0<=i<A.Height, 0<=j<A.Width
308  void AddMatrix(DenseMatrix &A, int ro, int co);
309  /// Perform (ro+i,co+j)+=a*A(i,j) for 0<=i<A.Height, 0<=j<A.Width
310  void AddMatrix(double a, DenseMatrix &A, int ro, int co);
311 
312  /// Add the matrix 'data' to the Vector 'v' at the given 'offset'
313  void AddToVector(int offset, Vector &v) const;
314  /// Get the matrix 'data' from the Vector 'v' at the given 'offset'
315  void GetFromVector(int offset, const Vector &v);
316  /** If (dofs[i] < 0 and dofs[j] >= 0) or (dofs[i] >= 0 and dofs[j] < 0)
317  then (*this)(i,j) = -(*this)(i,j). */
318  void AdjustDofDirection(Array<int> &dofs);
319 
320  /// Replace small entries, abs(a_ij) <= eps, with zero.
321  void Threshold(double eps);
322 
323  /** Count the number of entries in the matrix for which isfinite
324  is false, i.e. the entry is a NaN or +/-Inf. */
325  int CheckFinite() const { return mfem::CheckFinite(data, height*width); }
326 
327  /// Prints matrix to stream out.
328  virtual void Print(std::ostream &out = mfem::out, int width_ = 4) const;
329  virtual void PrintMatlab(std::ostream &out = mfem::out) const;
330  /// Prints the transpose matrix to stream out.
331  virtual void PrintT(std::ostream &out = mfem::out, int width_ = 4) const;
332 
333  /// Invert and print the numerical conditioning of the inversion.
334  void TestInversion();
335 
336  long MemoryUsage() const { return std::abs(capacity) * sizeof(double); }
337 
338  /// Destroys dense matrix.
339  virtual ~DenseMatrix();
340 };
341 
342 /// C = A + alpha*B
343 void Add(const DenseMatrix &A, const DenseMatrix &B,
344  double alpha, DenseMatrix &C);
345 
346 /// C = alpha*A + beta*B
347 void Add(double alpha, const double *A,
348  double beta, const double *B, DenseMatrix &C);
349 
350 /// C = alpha*A + beta*B
351 void Add(double alpha, const DenseMatrix &A,
352  double beta, const DenseMatrix &B, DenseMatrix &C);
353 
354 /// Matrix matrix multiplication. A = B * C.
355 void Mult(const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a);
356 
357 /// Matrix matrix multiplication. A += B * C.
358 void AddMult(const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a);
359 
360 /** Calculate the adjugate of a matrix (for NxN matrices, N=1,2,3) or the matrix
361  adj(A^t.A).A^t for rectangular matrices (2x1, 3x1, or 3x2). This operation
362  is well defined even when the matrix is not full rank. */
363 void CalcAdjugate(const DenseMatrix &a, DenseMatrix &adja);
364 
365 /// Calculate the transposed adjugate of a matrix (for NxN matrices, N=1,2,3)
366 void CalcAdjugateTranspose(const DenseMatrix &a, DenseMatrix &adjat);
367 
368 /** Calculate the inverse of a matrix (for NxN matrices, N=1,2,3) or the
369  left inverse (A^t.A)^{-1}.A^t (for 2x1, 3x1, or 3x2 matrices) */
370 void CalcInverse(const DenseMatrix &a, DenseMatrix &inva);
371 
372 /// Calculate the inverse transpose of a matrix (for NxN matrices, N=1,2,3)
373 void CalcInverseTranspose(const DenseMatrix &a, DenseMatrix &inva);
374 
375 /** For a given Nx(N-1) (N=2,3) matrix J, compute a vector n such that
376  n_k = (-1)^{k+1} det(J_k), k=1,..,N, where J_k is the matrix J with the
377  k-th row removed. Note: J^t.n = 0, det([n|J])=|n|^2=det(J^t.J). */
378 void CalcOrtho(const DenseMatrix &J, Vector &n);
379 
380 /// Calculate the matrix A.At
381 void MultAAt(const DenseMatrix &a, DenseMatrix &aat);
382 
383 /// ADAt = A D A^t, where D is diagonal
384 void MultADAt(const DenseMatrix &A, const Vector &D, DenseMatrix &ADAt);
385 
386 /// ADAt += A D A^t, where D is diagonal
387 void AddMultADAt(const DenseMatrix &A, const Vector &D, DenseMatrix &ADAt);
388 
389 /// Multiply a matrix A with the transpose of a matrix B: A*Bt
390 void MultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt);
391 
392 /// ADBt = A D B^t, where D is diagonal
393 void MultADBt(const DenseMatrix &A, const Vector &D,
394  const DenseMatrix &B, DenseMatrix &ADBt);
395 
396 /// ABt += A * B^t
397 void AddMultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt);
398 
399 /// ADBt = A D B^t, where D is diagonal
400 void AddMultADBt(const DenseMatrix &A, const Vector &D,
401  const DenseMatrix &B, DenseMatrix &ADBt);
402 
403 /// ABt += a * A * B^t
404 void AddMult_a_ABt(double a, const DenseMatrix &A, const DenseMatrix &B,
405  DenseMatrix &ABt);
406 
407 /// Multiply the transpose of a matrix A with a matrix B: At*B
408 void MultAtB(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &AtB);
409 
410 /// AAt += a * A * A^t
411 void AddMult_a_AAt(double a, const DenseMatrix &A, DenseMatrix &AAt);
412 
413 /// AAt = a * A * A^t
414 void Mult_a_AAt(double a, const DenseMatrix &A, DenseMatrix &AAt);
415 
416 /// Make a matrix from a vector V.Vt
417 void MultVVt(const Vector &v, DenseMatrix &vvt);
418 
419 void MultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt);
420 
421 /// VWt += v w^t
422 void AddMultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt);
423 
424 /// VVt += v v^t
425 void AddMultVVt(const Vector &v, DenseMatrix &VWt);
426 
427 /// VWt += a * v w^t
428 void AddMult_a_VWt(const double a, const Vector &v, const Vector &w,
429  DenseMatrix &VWt);
430 
431 /// VVt += a * v v^t
432 void AddMult_a_VVt(const double a, const Vector &v, DenseMatrix &VVt);
433 
434 
435 /** Class that can compute LU factorization of external data and perform various
436  operations with the factored data. */
438 {
439 public:
440  double *data;
441  int *ipiv;
442 #ifdef MFEM_USE_LAPACK
443  static const int ipiv_base = 1;
444 #else
445  static const int ipiv_base = 0;
446 #endif
447 
448  /** With this constructor, the (public) data and ipiv members should be set
449  explicitly before calling class methods. */
450  LUFactors() { }
451 
452  LUFactors(double *data_, int *ipiv_) : data(data_), ipiv(ipiv_) { }
453 
454  /** Factorize the current data of size (m x m) overwriting it with the LU
455  factors. The factorization is such that L.U = P.A, where A is the
456  original matrix and P is a permutation matrix represented by ipiv. */
457  void Factor(int m);
458 
459  /** Assuming L.U = P.A factored data of size (m x m), compute |A|
460  from the diagonal values of U and the permutation information. */
461  double Det(int m) const;
462 
463  /** Assuming L.U = P.A factored data of size (m x m), compute X <- A X,
464  for a matrix X of size (m x n). */
465  void Mult(int m, int n, double *X) const;
466 
467  /** Assuming L.U = P.A factored data of size (m x m), compute
468  X <- L^{-1} P X, for a matrix X of size (m x n). */
469  void LSolve(int m, int n, double *X) const;
470 
471  /** Assuming L.U = P.A factored data of size (m x m), compute
472  X <- U^{-1} X, for a matrix X of size (m x n). */
473  void USolve(int m, int n, double *X) const;
474 
475  /** Assuming L.U = P.A factored data of size (m x m), compute X <- A^{-1} X,
476  for a matrix X of size (m x n). */
477  void Solve(int m, int n, double *X) const;
478 
479  /// Assuming L.U = P.A factored data of size (m x m), compute X <- A^{-1}.
480  void GetInverseMatrix(int m, double *X) const;
481 
482  /** Given an (n x m) matrix A21, compute X2 <- X2 - A21 X1, for matrices X1,
483  and X2 of size (m x r) and (n x r), respectively. */
484  static void SubMult(int m, int n, int r, const double *A21,
485  const double *X1, double *X2);
486 
487  /** Assuming P.A = L.U factored data of size (m x m), compute the 2x2 block
488  decomposition:
489  | P 0 | | A A12 | = | L 0 | | U U12 |
490  | 0 I | | A21 A22 | | L21 I | | 0 S22 |
491  where A12, A21, and A22 are matrices of size (m x n), (n x m), and
492  (n x n), respectively. The blocks are overwritten as follows:
493  A12 <- U12 = L^{-1} P A12
494  A21 <- L21 = A21 U^{-1}
495  A22 <- S22 = A22 - L21 U12.
496  The block S22 is the Schur complement. */
497  void BlockFactor(int m, int n, double *A12, double *A21, double *A22) const;
498 
499  /** Given BlockFactor()'d data, perform the forward block solve for the
500  linear system:
501  | A A12 | | X1 | = | B1 |
502  | A21 A22 | | X2 | | B2 |
503  written in the factored form:
504  | L 0 | | U U12 | | X1 | = | P 0 | | B1 |
505  | L21 I | | 0 S22 | | X2 | | 0 I | | B2 |.
506  The resulting blocks Y1, Y2 solve the system:
507  | L 0 | | Y1 | = | P 0 | | B1 |
508  | L21 I | | Y2 | | 0 I | | B2 |
509  The blocks are overwritten as follows:
510  B1 <- Y1 = L^{-1} P B1
511  B2 <- Y2 = B2 - L21 Y1 = B2 - A21 A^{-1} B1
512  The blocks B1/Y1 and B2/Y2 are of size (m x r) and (n x r), respectively.
513  The Schur complement system is given by: S22 X2 = Y2. */
514  void BlockForwSolve(int m, int n, int r, const double *L21,
515  double *B1, double *B2) const;
516 
517  /** Given BlockFactor()'d data, perform the backward block solve in
518  | U U12 | | X1 | = | Y1 |
519  | 0 S22 | | X2 | | Y2 |.
520  The input is the solution block X2 and the block Y1 resulting from
521  BlockForwSolve(). The result block X1 overwrites input block Y1:
522  Y1 <- X1 = U^{-1} (Y1 - U12 X2). */
523  void BlockBackSolve(int m, int n, int r, const double *U12,
524  const double *X2, double *Y1) const;
525 };
526 
527 
528 /** Data type for inverse of square dense matrix.
529  Stores LU factors */
531 {
532 private:
533  const DenseMatrix *a;
534  LUFactors lu;
535 
536 public:
537  /// Default constructor.
538  DenseMatrixInverse() : a(NULL), lu(NULL, NULL) { }
539 
540  /** Creates square dense matrix. Computes factorization of mat
541  and stores LU factors. */
542  DenseMatrixInverse(const DenseMatrix &mat);
543 
544  /// Same as above but does not factorize the matrix.
545  DenseMatrixInverse(const DenseMatrix *mat);
546 
547  /// Get the size of the inverse matrix
548  int Size() const { return Width(); }
549 
550  /// Factor the current DenseMatrix, *a
551  void Factor();
552 
553  /// Factor a new DenseMatrix of the same size
554  void Factor(const DenseMatrix &mat);
555 
556  virtual void SetOperator(const Operator &op);
557 
558  /// Matrix vector multiplication with the inverse of dense matrix.
559  virtual void Mult(const Vector &x, Vector &y) const;
560 
561  /// Multiply the inverse matrix by another matrix: X = A^{-1} B.
562  void Mult(const DenseMatrix &B, DenseMatrix &X) const;
563 
564  /// Compute and return the inverse matrix in Ainv.
565  void GetInverseMatrix(DenseMatrix &Ainv) const
566  {
567  Ainv.SetSize(width);
568  lu.GetInverseMatrix(width, Ainv.Data());
569  }
570 
571  /// Compute the determinant of the original DenseMatrix using the LU factors.
572  double Det() const { return lu.Det(width); }
573 
574  /// Print the numerical conditioning of the inversion: ||A^{-1} A - I||.
575  void TestInversion();
576 
577  /// Destroys dense inverse matrix.
578  virtual ~DenseMatrixInverse();
579 };
580 
581 
583 {
584  DenseMatrix &mat;
585  Vector EVal;
586  DenseMatrix EVect;
587  Vector ev;
588  int n;
589 
590 #ifdef MFEM_USE_LAPACK
591  double *work;
592  char jobz, uplo;
593  int lwork, info;
594 #endif
595 
596 public:
597 
600  void Eval();
601  Vector &Eigenvalues() { return EVal; }
602  DenseMatrix &Eigenvectors() { return EVect; }
603  double Eigenvalue(int i) { return EVal(i); }
604  const Vector &Eigenvector(int i)
605  {
606  ev.SetData(EVect.Data() + i * EVect.Height());
607  return ev;
608  }
610 };
611 
612 
614 {
615  Vector sv;
616  int m, n;
617 
618 #ifdef MFEM_USE_LAPACK
619  double *work;
620  char jobu, jobvt;
621  int lwork, info;
622 #endif
623 
624  void Init();
625 public:
626 
628  DenseMatrixSVD(int h, int w);
629  void Eval(DenseMatrix &M);
630  Vector &Singularvalues() { return sv; }
631  double Singularvalue(int i) { return sv(i); }
632  ~DenseMatrixSVD();
633 };
634 
635 class Table;
636 
637 /// Rank 3 tensor (array of matrices)
639 {
640 private:
641  DenseMatrix Mk;
642  double *tdata;
643  int nk;
644  bool own_data;
645 
646 public:
648  {
649  nk = 0;
650  tdata = NULL;
651  own_data = true;
652  }
653 
654  DenseTensor(int i, int j, int k)
655  : Mk(NULL, i, j)
656  {
657  nk = k;
658  tdata = new double[i*j*k];
659  own_data = true;
660  }
661 
662  /// Copy constructor: deep copy
663  DenseTensor(const DenseTensor& other)
664  : Mk(NULL, other.Mk.height, other.Mk.width), nk(other.nk), own_data(true)
665  {
666  const int size = Mk.Height()*Mk.Width()*nk;
667  if (size > 0)
668  {
669  tdata = new double[size];
670  std::memcpy(tdata, other.tdata, sizeof(double) * size);
671  }
672  else
673  {
674  tdata = NULL;
675  }
676  }
677 
678  int SizeI() const { return Mk.Height(); }
679  int SizeJ() const { return Mk.Width(); }
680  int SizeK() const { return nk; }
681 
682  void SetSize(int i, int j, int k)
683  {
684  if (own_data) { delete [] tdata; }
685  Mk.UseExternalData(NULL, i, j);
686  nk = k;
687  tdata = new double[i*j*k];
688  own_data = true;
689  }
690 
691  void UseExternalData(double *ext_data, int i, int j, int k)
692  {
693  if (own_data) { delete [] tdata; }
694  Mk.UseExternalData(NULL, i, j);
695  nk = k;
696  tdata = ext_data;
697  own_data = false;
698  }
699 
700  /// Sets the tensor elements equal to constant c
701  DenseTensor &operator=(double c);
702 
703  DenseMatrix &operator()(int k) { Mk.data = GetData(k); return Mk; }
704  const DenseMatrix &operator()(int k) const
705  { return const_cast<DenseTensor&>(*this)(k); }
706 
707  double &operator()(int i, int j, int k)
708  { return tdata[i+SizeI()*(j+SizeJ()*k)]; }
709  const double &operator()(int i, int j, int k) const
710  { return tdata[i+SizeI()*(j+SizeJ()*k)]; }
711 
712  double *GetData(int k) { return tdata+k*Mk.Height()*Mk.Width(); }
713 
714  double *Data() { return tdata; }
715 
716  /** Matrix-vector product from unassembled element matrices, assuming both
717  'x' and 'y' use the same elem_dof table. */
718  void AddMult(const Table &elem_dof, const Vector &x, Vector &y) const;
719 
720  void Clear()
721  { UseExternalData(NULL, 0, 0, 0); }
722 
723  long MemoryUsage() const { return nk*Mk.MemoryUsage(); }
724 
726  {
727  if (own_data) { delete [] tdata; }
728  }
729 };
730 
731 
732 // Inline methods
733 
734 inline double &DenseMatrix::operator()(int i, int j)
735 {
736  MFEM_ASSERT(data && i >= 0 && i < height && j >= 0 && j < width, "");
737  return data[i+j*height];
738 }
739 
740 inline const double &DenseMatrix::operator()(int i, int j) const
741 {
742  MFEM_ASSERT(data && i >= 0 && i < height && j >= 0 && j < width, "");
743  return data[i+j*height];
744 }
745 
746 } // namespace mfem
747 
748 #endif
int Size() const
For backward compatibility define Size to be synonym of Width()
Definition: densemat.hpp:83
void Symmetrize()
(*this) = 1/2 ((*this) + (*this)^t)
Definition: densemat.cpp:2434
void MultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
Multiply a matrix A with the transpose of a matrix B: A*Bt.
Definition: densemat.cpp:3356
DenseMatrix & operator-=(const DenseMatrix &m)
Definition: densemat.cpp:612
void SymmetricScaling(const Vector &s)
SymmetricScaling this = diag(sqrt(s)) * this * diag(sqrt(s))
Definition: densemat.cpp:385
void SquareRootInverse()
Replaces the current matrix with its square root inverse.
Definition: densemat.cpp:752
int CheckFinite(const double *v, const int n)
Definition: vector.hpp:304
void AddMultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt)
VWt += v w^t.
Definition: densemat.cpp:3758
DenseMatrix & operator*=(double c)
Definition: densemat.cpp:623
void GetDiag(Vector &d) const
Returns the diagonal of the matrix.
Definition: densemat.cpp:2326
void UseExternalData(double *ext_data, int i, int j, int k)
Definition: densemat.hpp:691
DenseTensor & operator=(double c)
Sets the tensor elements equal to constant c.
Definition: densemat.cpp:4409
void MultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt)
Definition: densemat.cpp:3736
void InvRightScaling(const Vector &s)
InvRightScaling: this = this * diag(1./s);.
Definition: densemat.cpp:370
const DenseMatrix & operator()(int k) const
Definition: densemat.hpp:704
void Eigenvalues(Vector &ev)
Definition: densemat.hpp:219
void SingularValues(Vector &sv) const
Definition: densemat.cpp:1092
DenseMatrix & operator()(int k)
Definition: densemat.hpp:703
double Det() const
Definition: densemat.cpp:460
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition: table.cpp:478
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition: operator.hpp:42
int SizeK() const
Definition: densemat.hpp:680
long MemoryUsage() const
Definition: densemat.hpp:723
void BlockFactor(int m, int n, double *A12, double *A21, double *A22) const
Definition: densemat.cpp:4095
void BlockBackSolve(int m, int n, int r, const double *U12, const double *X2, double *Y1) const
Definition: densemat.cpp:4131
double InnerProduct(const double *x, const double *y) const
Compute y^t A x.
Definition: densemat.cpp:315
void CalcAdjugate(const DenseMatrix &a, DenseMatrix &adja)
Definition: densemat.cpp:3042
void AddMult(const Table &elem_dof, const Vector &x, Vector &y) const
Definition: densemat.cpp:4356
void TestInversion()
Invert and print the numerical conditioning of the inversion.
Definition: densemat.cpp:2918
Data type dense matrix using column-major storage.
Definition: densemat.hpp:23
void CopyRows(const DenseMatrix &A, int row1, int row2)
Copy rows row1 through row2 from A to *this.
Definition: densemat.cpp:2545
double Det(int m) const
Definition: densemat.cpp:3902
void SetSize(int i, int j, int k)
Definition: densemat.hpp:682
void Eval(DenseMatrix &M)
Definition: densemat.cpp:4325
Abstract data type for matrix inverse.
Definition: matrix.hpp:66
void AddMult_a_ABt(double a, const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
ABt += a * A * B^t.
Definition: densemat.cpp:3572
void GetInverseMatrix(DenseMatrix &Ainv) const
Compute and return the inverse matrix in Ainv.
Definition: densemat.hpp:565
void Factor(int m)
Definition: densemat.cpp:3850
void Factor()
Factor the current DenseMatrix, *a.
Definition: densemat.cpp:4160
void GetInverseMatrix(int m, double *X) const
Assuming L.U = P.A factored data of size (m x m), compute X &lt;- A^{-1}.
Definition: densemat.cpp:4013
double * GetData() const
Returns the matrix data array.
Definition: densemat.hpp:94
void CalcOrtho(const DenseMatrix &J, Vector &n)
Definition: densemat.cpp:3272
DenseMatrix & operator=(double c)
Sets the matrix elements equal to constant c.
Definition: densemat.cpp:562
void Set(double alpha, const double *A)
Set the matrix to alpha * A, assuming that A has the same dimensions as the matrix and uses column-ma...
Definition: densemat.cpp:544
void Mult_a_AAt(double a, const DenseMatrix &A, DenseMatrix &AAt)
AAt = a * A * A^t.
Definition: densemat.cpp:3713
static void SubMult(int m, int n, int r, const double *A21, const double *X1, double *X2)
Definition: densemat.cpp:4078
const Vector & Eigenvector(int i)
Definition: densemat.hpp:604
virtual void Print(std::ostream &out=mfem::out, int width_=4) const
Prints matrix to stream out.
Definition: densemat.cpp:2847
virtual void Mult(const Vector &x, Vector &y) const
Matrix vector multiplication with the inverse of dense matrix.
Definition: densemat.cpp:4193
const double & operator()(int i, int j, int k) const
Definition: densemat.hpp:709
void Set(double alpha, const DenseMatrix &A)
Set the matrix to alpha * A.
Definition: densemat.hpp:179
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
Definition: densemat.cpp:2942
double & operator()(int i, int j)
Returns reference to a_{ij}.
Definition: densemat.hpp:734
double Weight() const
Definition: densemat.cpp:517
void USolve(int m, int n, double *X) const
Definition: densemat.cpp:3980
double FNorm() const
Compute the Frobenius norm of the matrix.
Definition: densemat.hpp:214
void MultTranspose(const double *x, double *y) const
Multiply a vector with the transpose matrix.
Definition: densemat.cpp:219
void CalcAdjugateTranspose(const DenseMatrix &a, DenseMatrix &adjat)
Calculate the transposed adjugate of a matrix (for NxN matrices, N=1,2,3)
Definition: densemat.cpp:3114
double & operator()(int i, int j, int k)
Definition: densemat.hpp:707
void AddMult(const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a)
Matrix matrix multiplication. A += B * C.
Definition: densemat.cpp:3010
double operator*(const DenseMatrix &m) const
Matrix inner product: tr(A^t B)
Definition: densemat.cpp:204
double Singularvalue(int i)
Definition: densemat.hpp:631
void Reset(double *d, int h, int w)
Change the data array and the size of the DenseMatrix.
Definition: densemat.hpp:71
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition: operator.hpp:36
void Add(const double c, const DenseMatrix &A)
Adds the matrix A multiplied by the number c to the matrix.
Definition: densemat.cpp:553
void AddMult_a_VWt(const double a, const Vector &v, const Vector &w, DenseMatrix &VWt)
VWt += a * v w^t.
Definition: densemat.cpp:3803
void InvSymmetricScaling(const Vector &s)
InvSymmetricScaling this = diag(sqrt(1./s)) * this * diag(sqrt(1./s))
Definition: densemat.cpp:411
void GetRow(int r, Vector &row) const
Definition: densemat.cpp:2296
void BlockForwSolve(int m, int n, int r, const double *L21, double *B1, double *B2) const
Definition: densemat.cpp:4122
DenseMatrixSVD(DenseMatrix &M)
Definition: densemat.cpp:4291
Abstract data type matrix.
Definition: matrix.hpp:27
const double * GetColumn(int col) const
Definition: densemat.hpp:241
void Norm2(double *v) const
Take the 2-norm of the columns of A and store in v.
Definition: densemat.cpp:797
void MultADBt(const DenseMatrix &A, const Vector &D, const DenseMatrix &B, DenseMatrix &ADBt)
ADBt = A D B^t, where D is diagonal.
Definition: densemat.cpp:3439
void Invert()
Replaces the current matrix with its inverse.
Definition: densemat.cpp:642
virtual ~DenseMatrixInverse()
Destroys dense inverse matrix.
Definition: densemat.cpp:4216
void LSolve(int m, int n, double *X) const
Definition: densemat.cpp:3955
void LeftScaling(const Vector &s)
LeftScaling this = diag(s) * this.
Definition: densemat.cpp:333
double Det() const
Compute the determinant of the original DenseMatrix using the LU factors.
Definition: densemat.hpp:572
void AddMultVVt(const Vector &v, DenseMatrix &VVt)
VVt += v v^t.
Definition: densemat.cpp:3779
void CopyMNDiag(double c, int n, int row_offset, int col_offset)
Copy c on the diagonal of size n to *this at row_offset, col_offset.
Definition: densemat.cpp:2635
double * GetData(int k)
Definition: densemat.hpp:712
void AddMult_a_VVt(const double a, const Vector &v, DenseMatrix &VVt)
VVt += a * v v^t.
Definition: densemat.cpp:3825
void Neg()
(*this) = -(*this)
Definition: densemat.cpp:633
virtual void SetOperator(const Operator &op)
Set/update the solver for the given operator.
Definition: densemat.cpp:4186
void Solve(int m, int n, double *X) const
Definition: densemat.cpp:3999
void SetRow(int r, const Vector &row)
Definition: densemat.cpp:2817
void Getl1Diag(Vector &l) const
Returns the l1 norm of the rows of the matrix v_i = sum_j |a_ij|.
Definition: densemat.cpp:2340
void AddToVector(int offset, Vector &v) const
Add the matrix &#39;data&#39; to the Vector &#39;v&#39; at the given &#39;offset&#39;.
Definition: densemat.cpp:2752
void SetData(double *d)
Definition: vector.hpp:94
long MemoryUsage() const
Definition: densemat.hpp:336
DenseMatrix & Eigenvectors()
Definition: densemat.hpp:602
void GetColumn(int c, Vector &col) const
Definition: densemat.cpp:2312
void AddMult(const Vector &x, Vector &y) const
y += A.x
Definition: densemat.cpp:242
void Threshold(double eps)
Replace small entries, abs(a_ij) &lt;= eps, with zero.
Definition: densemat.cpp:2833
int SizeI() const
Definition: densemat.hpp:678
void CalcInverse(const DenseMatrix &a, DenseMatrix &inva)
Definition: densemat.cpp:3150
void TestInversion()
Print the numerical conditioning of the inversion: ||A^{-1} A - I||.
Definition: densemat.cpp:4205
double MaxMaxNorm() const
Compute the norm ||A|| = max_{ij} |A_{ij}|.
Definition: densemat.cpp:810
double * Data() const
Returns the matrix data array.
Definition: densemat.hpp:92
void Transpose()
(*this) = (*this)^t
Definition: densemat.cpp:2401
void MultVVt(const Vector &v, DenseMatrix &vvt)
Make a matrix from a vector V.Vt.
Definition: densemat.cpp:3727
double Trace() const
Trace of a square matrix.
Definition: densemat.cpp:436
void AddMultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
ABt += A * B^t.
Definition: densemat.cpp:3479
DenseTensor(int i, int j, int k)
Definition: densemat.hpp:654
void ClearExternalData()
Definition: densemat.hpp:76
int CheckFinite() const
Definition: densemat.hpp:325
void MultAAt(const DenseMatrix &a, DenseMatrix &aat)
Calculate the matrix A.At.
Definition: densemat.cpp:3298
void GetColumnReference(int c, Vector &col)
Definition: densemat.hpp:243
void AddMatrix(DenseMatrix &A, int ro, int co)
Perform (ro+i,co+j)+=A(i,j) for 0&lt;=i&lt;A.Height, 0&lt;=j&lt;A.Width.
Definition: densemat.cpp:2692
DenseMatrix(double *d, int h, int w)
Definition: densemat.hpp:57
void Clear()
Delete the matrix data array (if owned) and reset the matrix state.
Definition: densemat.hpp:79
void CalcInverseTranspose(const DenseMatrix &a, DenseMatrix &inva)
Calculate the inverse transpose of a matrix (for NxN matrices, N=1,2,3)
Definition: densemat.cpp:3233
void SetDataAndSize(double *d, int s)
Set the Vector data and size.
Definition: vector.hpp:101
void MultADAt(const DenseMatrix &A, const Vector &D, DenseMatrix &ADAt)
ADAt = A D A^t, where D is diagonal.
Definition: densemat.cpp:3340
int height
Dimension of the output / number of rows in the matrix.
Definition: operator.hpp:24
virtual void PrintT(std::ostream &out=mfem::out, int width_=4) const
Prints the transpose matrix to stream out.
Definition: densemat.cpp:2892
void CopyCols(const DenseMatrix &A, int col1, int col2)
Copy columns col1 through col2 from A to *this.
Definition: densemat.cpp:2556
int SizeJ() const
Definition: densemat.hpp:679
virtual MatrixInverse * Inverse() const
Returns a pointer to the inverse matrix.
Definition: densemat.cpp:455
double * GetColumn(int col)
Definition: densemat.hpp:240
bool OwnsData() const
Definition: densemat.hpp:96
void AddMultADBt(const DenseMatrix &A, const Vector &D, const DenseMatrix &B, DenseMatrix &ADBt)
ADBt = A D B^t, where D is diagonal.
Definition: densemat.cpp:3536
virtual ~DenseMatrix()
Destroys dense matrix.
Definition: densemat.cpp:2932
void CopyMNt(const DenseMatrix &A, int row_offset, int col_offset)
Copy matrix A^t to the location in *this at row_offset, col_offset.
Definition: densemat.cpp:2592
void AddMultTranspose(const Vector &x, Vector &y) const
y += A^t x
Definition: densemat.cpp:260
void CopyExceptMN(const DenseMatrix &A, int m, int n)
Copy All rows and columns except m and n from A.
Definition: densemat.cpp:2666
void Diag(double c, int n)
Creates n x n diagonal matrix with diagonal elements c.
Definition: densemat.cpp:2371
void Mult(int m, int n, double *X) const
Definition: densemat.cpp:3919
static const int ipiv_base
Definition: densemat.hpp:443
void GradToCurl(DenseMatrix &curl)
Definition: densemat.cpp:2465
DenseMatrixInverse()
Default constructor.
Definition: densemat.hpp:538
double CalcSingularvalue(const int i) const
Return the i-th singular value (decreasing order) of NxN matrix, N=1,2,3.
Definition: densemat.cpp:1758
void GetRowSums(Vector &l) const
Compute the row sums of the DenseMatrix.
Definition: densemat.cpp:2357
void CalcEigenvalues(double *lambda, double *vec) const
Definition: densemat.cpp:2056
void Eigenvalues(Vector &ev, DenseMatrix &evect)
Definition: densemat.hpp:222
DenseMatrixEigensystem(DenseMatrix &m)
Definition: densemat.cpp:4223
int Rank(double tol) const
Definition: densemat.cpp:1131
const double alpha
Definition: ex15.cpp:337
LUFactors(double *data_, int *ipiv_)
Definition: densemat.hpp:452
void AddMult_a(double a, const Vector &x, Vector &y) const
y += a * A.x
Definition: densemat.cpp:278
void RightScaling(const Vector &s)
RightScaling: this = this * diag(s);.
Definition: densemat.cpp:355
DenseTensor(const DenseTensor &other)
Copy constructor: deep copy.
Definition: densemat.hpp:663
void MultAtB(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &AtB)
Multiply the transpose of a matrix A with a matrix B: At*B.
Definition: densemat.cpp:3631
Vector data type.
Definition: vector.hpp:48
void Mult(const double *x, double *y) const
Matrix vector multiplication.
Definition: densemat.cpp:168
void AddMultTranspose_a(double a, const Vector &x, Vector &y) const
y += a * A^t x
Definition: densemat.cpp:296
void AddMultADAt(const DenseMatrix &A, const Vector &D, DenseMatrix &ADAt)
ADAt += A D A^t, where D is diagonal.
Definition: densemat.cpp:3312
void GetFromVector(int offset, const Vector &v)
Get the matrix &#39;data&#39; from the Vector &#39;v&#39; at the given &#39;offset&#39;.
Definition: densemat.cpp:2763
void CopyMN(const DenseMatrix &A, int m, int n, int Aro, int Aco)
Copy the m x n submatrix of A at row/col offsets Aro/Aco to *this.
Definition: densemat.cpp:2567
double * Data()
Definition: densemat.hpp:714
void InvLeftScaling(const Vector &s)
InvLeftScaling this = diag(1./s) * this.
Definition: densemat.cpp:344
void UseExternalData(double *d, int h, int w)
Change the data array and the size of the DenseMatrix.
Definition: densemat.hpp:64
void SetCol(int c, const Vector &col)
Definition: densemat.cpp:2825
void Eigensystem(Vector &ev, DenseMatrix &evect)
Definition: densemat.hpp:225
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition: densemat.hpp:86
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:64
Abstract operator.
Definition: operator.hpp:21
int Size() const
Get the size of the inverse matrix.
Definition: densemat.hpp:548
Vector & Singularvalues()
Definition: densemat.hpp:630
Rank 3 tensor (array of matrices)
Definition: densemat.hpp:638
double InnerProduct(const Vector &x, const Vector &y) const
Compute y^t A x.
Definition: densemat.hpp:157
double FNorm2() const
Compute the square of the Frobenius norm of the matrix.
Definition: densemat.hpp:217
virtual double & Elem(int i, int j)
Returns reference to a_{ij}.
Definition: densemat.cpp:158
void AdjustDofDirection(Array< int > &dofs)
Definition: densemat.cpp:2774
void GradToDiv(Vector &div)
Definition: densemat.cpp:2524
void AddMult_a_AAt(double a, const DenseMatrix &A, DenseMatrix &AAt)
AAt += a * A * A^t.
Definition: densemat.cpp:3688
int width
Dimension of the input / number of columns in the matrix.
Definition: operator.hpp:25
virtual void PrintMatlab(std::ostream &out=mfem::out) const
Definition: densemat.cpp:2873
double * data
Definition: densemat.hpp:440
DenseMatrix & operator+=(const double *m)
Definition: densemat.cpp:595