HermesCommon  2.0
matrix.h
Go to the documentation of this file.
1 // This file is part of HermesCommon
2 //
3 // Copyright (c) 2009 hp-FEM group at the University of Nevada, Reno (UNR).
4 // Email: hpfem-group@unr.edu, home page: http://hpfem.org/.
5 //
6 // Hermes2D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published
8 // by the Free Software Foundation; either version 2 of the License,
9 // or (at your option) any later version.
10 //
11 // Hermes2D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with Hermes2D; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #ifndef __HERMES_COMMON_MATRIX_H
23 #define __HERMES_COMMON_MATRIX_H
24 
25 #include "common.h"
26 #include "vector.h"
27 #include "exceptions.h"
28 #include "mixins.h"
29 
30 namespace Hermes
31 {
32  enum MatrixSolverType
33  {
34  SOLVER_UMFPACK = 0,
35  SOLVER_PETSC,
36  SOLVER_MUMPS,
37  SOLVER_SUPERLU,
38  SOLVER_AMESOS,
39  SOLVER_AZTECOO
40  };
41 
43  namespace Algebra
44  {
46  namespace DenseMatrixOperations
47  {
51  template<typename T>
52  T **new_matrix(unsigned int m, unsigned int n = 0)
53  {
54  if(!n) n = m;
55  T **vec = (T **) new char[sizeof(T *) * m + sizeof(T) * m * n];
56  memset(vec, 0, sizeof(T *) * m + sizeof(T) * m * n);
57  T *row = (T *) (vec + m);
58  for (unsigned int i = 0; i < m; i++, row += n) vec[i] = row;
59  return vec;
60  }
61 
62  template<typename T>
63  T **new_matrix_malloc(unsigned int m, unsigned int n = 0)
64  {
65  if(!n) n = m;
66  T **vec = (T **) malloc(sizeof(T *) * m + sizeof(T) * m * n);
67  memset(vec, 0, sizeof(T *) * m + sizeof(T) * m * n);
68  T *row = (T *) (vec + m);
69  for (unsigned int i = 0; i < m; i++, row += n) vec[i] = row;
70  return vec;
71  }
72 
75  template<typename T>
76  void copy_matrix(T** dest, T** src, unsigned int m, unsigned int n = 0)
77  {
78  if(n == 0) n = m;
79  for(unsigned int i = 0; i < m; i++)
80  {
81  memcpy(dest[i], src[i], n*sizeof(T));
82  }
83  }
84 
91  template<typename T>
92  void save_matrix_octave(const std::string& matrix_name, T** matrix, unsigned int m, unsigned int n = 0, const std::string& filename = std::string())
93  {
94  if(n == 0) n = m;
95 
96  //create filename
97  std::string fname = filename;
98  if(fname.empty())
99  fname = matrix_name + ".mat";
100 
101  //open file
102  std::ofstream fout(fname.c_str());
103  if(!fout.is_open())
104  {
105  throw Hermes::Exceptions::Exception("Unable to save a matrix to a file \"%s\"", fname.c_str());
106  return;
107  }
108 
109  //write header
110  fout << std::string("# name: ") << matrix_name << std::endl;
111  fout << std::string("# type: matrix") << std::endl;
112  fout << std::string("# rows: ") << m << std::endl;
113  fout << std::string("# columns: ") << n << std::endl;
114 
115  //write contents
116  for(unsigned int i = 0; i < m; i++)
117  {
118  for(unsigned int k = 0; k < n; k++)
119  fout << ' ' << matrix[i][k];
120  fout << std::endl;
121  }
122 
123  //finish
124  fout.close();
125  }
126 
128  template<typename T>
129  void save_sparse_matrix_octave(const std::string& matrix_name, const T* Ax, const int* Ap, const int* Ai,
130  unsigned int m, const std::string& filename = std::string())
131  {
132  // create filename
133  std::string fname = filename;
134  if(fname.empty())
135  fname = matrix_name + ".mat";
136 
137  // open file
138  std::ofstream fout(fname.c_str());
139  if(!fout.is_open())
140  {
141  throw Hermes::Exceptions::Exception("Unable to save a matrix to a file \"%s\"", fname.c_str());
142  return;
143  }
144 
145  // write header
146  fout << std::string("# name: ") << matrix_name << std::endl;
147  fout << std::string("# type: sparse matrix") << std::endl;
148  fout << std::string("# nnz: ") << Ap[m] << std::endl;
149  fout << std::string("# rows: ") << m << std::endl;
150  fout << std::string("# columns: ") << m << std::endl;
151 
152  // write contents
153  for (int j = 0; j < m; j++)
154  for (int i = Ap[j]; i < Ap[j + 1]; i++)
155  fout << j + 1 << " " << Ai[i] + 1 << " " << Ax[i] << std::endl;
156 
157  // finish
158  fout.close();
159  }
160 
163  template<typename T>
164  void transpose(T **matrix, unsigned int m, unsigned int n)
165  {
166  unsigned int min = std::min(m, n);
167  for (unsigned int i = 0; i < min; i++)
168  for (unsigned int j = i + 1; j < min; j++)
169  std::swap(matrix[i][j], matrix[j][i]);
170 
171  if(m < n)
172  for (unsigned int i = 0; i < m; i++)
173  for (unsigned int j = m; j < n; j++)
174  matrix[j][i] = matrix[i][j];
175  else if(n < m)
176  for (unsigned int i = n; i < m; i++)
177  for (unsigned int j = 0; j < n; j++)
178  matrix[j][i] = matrix[i][j];
179  }
180 
182  template<typename T>
183  void chsgn(T **matrix, unsigned int m, unsigned int n)
184  {
185  for (unsigned int i = 0; i < m; i++)
186  for (unsigned int j = 0; j < n; j++)
187  matrix[i][j] = -matrix[i][j];
188  }
189 
196  HERMES_API void ludcmp(double **a, int n, int *indx, double *d);
197 
205  template<typename T>
206  void lubksb(double **a, int n, int *indx, T *b)
207  {
208  int i, ip, j;
209  T sum;
210 
211  for (i = 0; i < n; i++)
212  {
213  ip = indx[i];
214  sum = b[ip];
215  b[ip] = b[i];
216  for (j = 0; j < i; j++) sum -= a[i][j]*b[j];
217  b[i] = sum;
218  }
219  for (i = n-1; i >= 0; i--)
220  {
221  sum = b[i];
222  for (j = i + 1; j < n; j++) sum -= a[i][j]*b[j];
223  b[i] = sum / a[i][i];
224  }
225  }
226 
231  HERMES_API void choldc(double **a, int n, double p[]);
232 
240  template<typename T>
241  void cholsl(double **a, int n, double p[], T b[], T x[])
242  {
243  int i, k;
244  T sum;
245 
246  for (i = 0; i < n; i++)
247  {
248  sum = b[i];
249  k = i;
250  while (--k >= 0) sum -= a[i][k] * x[k];
251  x[i] = sum / p[i];
252  }
253 
254  for (i = n-1; i >= 0; i--)
255  {
256  sum = x[i];
257  k = i;
258  while (++k < n) sum -= a[k][i] * x[k];
259  x[i] = sum / p[i];
260  }
261  }
262  }
263 
266  {
268 
269 
270 
271 
277  };
278 
280  template<typename Scalar>
281  class HERMES_API Matrix : public Hermes::Mixins::Loggable
282  {
283  public:
286  unsigned int get_size() { return this->size;};
287 
290  Matrix(unsigned int size) { this->size = size;};
291 
292  virtual ~Matrix() {};
293 
294  Matrix() { this->size = 0;};
295 
297  virtual void alloc() = 0;
298 
300  virtual void free() = 0;
301 
306  virtual Scalar get(unsigned int m, unsigned int n) = 0;
307 
309  virtual void zero() = 0;
310 
312  virtual void add_to_diagonal(Scalar v) = 0;
313 
319  virtual void add(unsigned int m, unsigned int n, Scalar v) = 0;
320 
328  virtual void add(unsigned int m, unsigned int n, Scalar **mat, int *rows, int *cols) = 0;
329 
335  virtual bool dump(FILE *file, const char *var_name, EMatrixDumpFormat fmt = DF_MATLAB_SPARSE, char* number_format = "%lf") = 0;
336 
339  virtual unsigned int get_matrix_size() const = 0;
340 
341  protected:
342 
343  unsigned int size;
344  };
345 
347  template<typename Scalar>
348  class HERMES_API SparseMatrix : public Matrix<Scalar> {
349  public:
350  SparseMatrix();
353  SparseMatrix(unsigned int size);
354  virtual ~SparseMatrix();
355 
359  virtual void prealloc(unsigned int n);
360 
365  virtual void pre_add_ij(unsigned int row, unsigned int col);
366 
368  virtual void finish() { }
369 
370  virtual unsigned int get_size() { return this->size; }
371 
374  virtual void add_sparse_matrix(SparseMatrix* mat)
375  {
376  throw Hermes::Exceptions::Exception("add_sparse_matrix() undefined.");
377  };
378 
383  virtual void add_sparse_to_diagonal_blocks(int num_stages, SparseMatrix<Scalar>* mat)
384  {
385  throw Hermes::Exceptions::Exception("add_sparse_to_diagonal_blocks() undefined.");
386  };
387 
392  virtual int get_num_row_entries(unsigned int row) { return -1; }
393 
401  virtual void extract_row_copy(unsigned int row, unsigned int len,
402  unsigned int &n_entries, double *vals,
403  unsigned int *idxs) { }
404 
409  virtual int get_num_col_entries(unsigned int col) { return -1; }
410 
418  virtual void extract_col_copy(unsigned int col, unsigned int len,
419  unsigned int &n_entries, double *vals,
420  unsigned int *idxs) { }
421 
423  virtual void multiply_with_vector(Scalar* vector_in, Scalar* vector_out) {
424  throw Hermes::Exceptions::Exception("multiply_with_vector() undefined.");
425  };
426 
428  virtual void multiply_with_Scalar(Scalar value) {
429  throw Hermes::Exceptions::Exception("multiply_with_Scalar() undefined.");
430  };
431 
433  virtual SparseMatrix* duplicate() { return (SparseMatrix*)NULL;};
434 
436  virtual double get_fill_in() const = 0;
437 
438  unsigned row_storage:1;
439  unsigned col_storage:1;
440 
443  virtual unsigned int get_nnz() const {
444  throw Hermes::Exceptions::Exception("get_nnz() undefined.");
445  return 0;
446  }
447 
448  protected:
450  static const int PAGE_SIZE = 62;
451 
453  struct Page {
455  int count;
457  int idx[PAGE_SIZE];
460  };
461 
464 
471  int sort_and_store_indices(Page *page, int *buffer, int *max);
474  int get_num_indices();
475 
477  int mem_size;
478  };
479 
481  template<typename Scalar>
482  class HERMES_API Vector : public Hermes::Mixins::Loggable
483  {
484  public:
485  virtual ~Vector() { }
486 
490  virtual void alloc(unsigned int ndofs) = 0;
492  virtual void free() = 0;
494  virtual void finish() { }
495 
499  virtual Scalar get(unsigned int idx) = 0;
500 
503  virtual void extract(Scalar *v) const = 0;
504 
506  virtual void zero() = 0;
507 
509  virtual void change_sign() = 0;
510 
515  virtual void set(unsigned int idx, Scalar y) = 0;
516 
521  virtual void add(unsigned int idx, Scalar y) = 0;
522 
524  virtual void add_vector(Vector<Scalar>* vec) = 0;
526  virtual void add_vector(Scalar* vec) = 0;
527 
533  virtual void add(unsigned int n, unsigned int *idx, Scalar *y) = 0;
534 
536  unsigned int length() const {return this->size;}
537 
543  virtual bool dump(FILE *file, const char *var_name,
544  EMatrixDumpFormat fmt = DF_MATLAB_SPARSE, char* number_format = "%lf") = 0;
545 
546  protected:
548  unsigned int size;
549  };
550 
553  template<typename Scalar> HERMES_API
555 
558  template<typename Scalar> HERMES_API
560  }
561 }
562 #endif