|
HermesCommon 1.0
|
00001 // This file is part of HermesCommon 00002 // 00003 // Copyright (c) 2009 hp-FEM group at the University of Nevada, Reno (UNR). 00004 // Email: hpfem-group@unr.edu, home page: http://hpfem.org/. 00005 // 00006 // Hermes2D is free software; you can redistribute it and/or modify 00007 // it under the terms of the GNU General Public License as published 00008 // by the Free Software Foundation; either version 2 of the License, 00009 // or (at your option) any later version. 00010 // 00011 // Hermes2D is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU General Public License 00017 // along with Hermes2D; if not, write to the Free Software 00018 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00022 #ifndef __HERMES_COMMON_MATRIX_H 00023 #define __HERMES_COMMON_MATRIX_H 00024 00025 #include "common.h" 00026 #include "vector.h" 00027 #include "exceptions.h" 00028 #include "mixins.h" 00029 00030 namespace Hermes 00031 { 00032 enum MatrixSolverType 00033 { 00034 SOLVER_UMFPACK = 0, 00035 SOLVER_PETSC, 00036 SOLVER_MUMPS, 00037 SOLVER_SUPERLU, 00038 SOLVER_AMESOS, 00039 SOLVER_AZTECOO 00040 }; 00041 00043 namespace Algebra 00044 { 00046 namespace DenseMatrixOperations 00047 { 00051 template<typename T> 00052 T **new_matrix(unsigned int m, unsigned int n = 0) 00053 { 00054 if(!n) n = m; 00055 T **vec = (T **) new char[sizeof(T *) * m + sizeof(T) * m * n]; 00056 memset(vec, 0, sizeof(T *) * m + sizeof(T) * m * n); 00057 T *row = (T *) (vec + m); 00058 for (unsigned int i = 0; i < m; i++, row += n) vec[i] = row; 00059 return vec; 00060 } 00061 00062 template<typename T> 00063 T **new_matrix_malloc(unsigned int m, unsigned int n = 0) 00064 { 00065 if(!n) n = m; 00066 T **vec = (T **) malloc(sizeof(T *) * m + sizeof(T) * m * n); 00067 memset(vec, 0, sizeof(T *) * m + sizeof(T) * m * n); 00068 T *row = (T *) (vec + m); 00069 for (unsigned int i = 0; i < m; i++, row += n) vec[i] = row; 00070 return vec; 00071 } 00072 00075 template<typename T> 00076 void copy_matrix(T** dest, T** src, unsigned int m, unsigned int n = 0) 00077 { 00078 if(n == 0) n = m; 00079 for(unsigned int i = 0; i < m; i++) 00080 { 00081 memcpy(dest[i], src[i], n*sizeof(T)); 00082 } 00083 } 00084 00091 template<typename T> 00092 void save_matrix_octave(const std::string& matrix_name, T** matrix, unsigned int m, unsigned int n = 0, const std::string& filename = std::string()) 00093 { 00094 if(n == 0) n = m; 00095 00096 //create filename 00097 std::string fname = filename; 00098 if(fname.empty()) 00099 fname = matrix_name + ".mat"; 00100 00101 //open file 00102 std::ofstream fout(fname.c_str()); 00103 if(!fout.is_open()) 00104 { 00105 throw Hermes::Exceptions::Exception("Unable to save a matrix to a file \"%s\"", fname.c_str()); 00106 return; 00107 } 00108 00109 //write header 00110 fout << std::string("# name: ") << matrix_name << std::endl; 00111 fout << std::string("# type: matrix") << std::endl; 00112 fout << std::string("# rows: ") << m << std::endl; 00113 fout << std::string("# columns: ") << n << std::endl; 00114 00115 //write contents 00116 for(unsigned int i = 0; i < m; i++) 00117 { 00118 for(unsigned int k = 0; k < n; k++) 00119 fout << ' ' << matrix[i][k]; 00120 fout << std::endl; 00121 } 00122 00123 //finish 00124 fout.close(); 00125 } 00126 00128 template<typename T> 00129 void save_sparse_matrix_octave(const std::string& matrix_name, const T* Ax, const int* Ap, const int* Ai, 00130 unsigned int m, const std::string& filename = std::string()) 00131 { 00132 // create filename 00133 std::string fname = filename; 00134 if(fname.empty()) 00135 fname = matrix_name + ".mat"; 00136 00137 // open file 00138 std::ofstream fout(fname.c_str()); 00139 if(!fout.is_open()) 00140 { 00141 throw Hermes::Exceptions::Exception("Unable to save a matrix to a file \"%s\"", fname.c_str()); 00142 return; 00143 } 00144 00145 // write header 00146 fout << std::string("# name: ") << matrix_name << std::endl; 00147 fout << std::string("# type: sparse matrix") << std::endl; 00148 fout << std::string("# nnz: ") << Ap[m] << std::endl; 00149 fout << std::string("# rows: ") << m << std::endl; 00150 fout << std::string("# columns: ") << m << std::endl; 00151 00152 // write contents 00153 for (int j = 0; j < m; j++) 00154 for (int i = Ap[j]; i < Ap[j + 1]; i++) 00155 fout << j + 1 << " " << Ai[i] + 1 << " " << Ax[i] << std::endl; 00156 00157 // finish 00158 fout.close(); 00159 } 00160 00163 template<typename T> 00164 void transpose(T **matrix, unsigned int m, unsigned int n) 00165 { 00166 unsigned int min = std::min(m, n); 00167 for (unsigned int i = 0; i < min; i++) 00168 for (unsigned int j = i + 1; j < min; j++) 00169 std::swap(matrix[i][j], matrix[j][i]); 00170 00171 if(m < n) 00172 for (unsigned int i = 0; i < m; i++) 00173 for (unsigned int j = m; j < n; j++) 00174 matrix[j][i] = matrix[i][j]; 00175 else if(n < m) 00176 for (unsigned int i = n; i < m; i++) 00177 for (unsigned int j = 0; j < n; j++) 00178 matrix[j][i] = matrix[i][j]; 00179 } 00180 00182 template<typename T> 00183 void chsgn(T **matrix, unsigned int m, unsigned int n) 00184 { 00185 for (unsigned int i = 0; i < m; i++) 00186 for (unsigned int j = 0; j < n; j++) 00187 matrix[i][j] = -matrix[i][j]; 00188 } 00189 00196 HERMES_API void ludcmp(double **a, int n, int *indx, double *d); 00197 00205 template<typename T> 00206 void lubksb(double **a, int n, int *indx, T *b) 00207 { 00208 int i, ip, j; 00209 T sum; 00210 00211 for (i = 0; i < n; i++) 00212 { 00213 ip = indx[i]; 00214 sum = b[ip]; 00215 b[ip] = b[i]; 00216 for (j = 0; j < i; j++) sum -= a[i][j]*b[j]; 00217 b[i] = sum; 00218 } 00219 for (i = n-1; i >= 0; i--) 00220 { 00221 sum = b[i]; 00222 for (j = i + 1; j < n; j++) sum -= a[i][j]*b[j]; 00223 b[i] = sum / a[i][i]; 00224 } 00225 } 00226 00231 HERMES_API void choldc(double **a, int n, double p[]); 00232 00240 template<typename T> 00241 void cholsl(double **a, int n, double p[], T b[], T x[]) 00242 { 00243 int i, k; 00244 T sum; 00245 00246 for (i = 0; i < n; i++) 00247 { 00248 sum = b[i]; 00249 k = i; 00250 while (--k >= 0) sum -= a[i][k] * x[k]; 00251 x[i] = sum / p[i]; 00252 } 00253 00254 for (i = n-1; i >= 0; i--) 00255 { 00256 sum = x[i]; 00257 k = i; 00258 while (++k < n) sum -= a[k][i] * x[k]; 00259 x[i] = sum / p[i]; 00260 } 00261 } 00262 } 00263 00265 enum EMatrixDumpFormat 00266 { 00267 DF_MATLAB_SPARSE, 00268 00269 00270 00271 00272 DF_PLAIN_ASCII, 00275 DF_HERMES_BIN, 00276 DF_MATRIX_MARKET 00277 }; 00278 00280 template<typename Scalar> 00281 class HERMES_API Matrix : public Hermes::Mixins::Loggable 00282 { 00283 public: 00286 unsigned int get_size() { return this->size;}; 00287 00290 Matrix(unsigned int size) { this->size = size;}; 00291 00292 virtual ~Matrix() {}; 00293 00294 Matrix() { this->size = 0;}; 00295 00297 virtual void alloc() = 0; 00298 00300 virtual void free() = 0; 00301 00306 virtual Scalar get(unsigned int m, unsigned int n) = 0; 00307 00309 virtual void zero() = 0; 00310 00312 virtual void add_to_diagonal(Scalar v) = 0; 00313 00319 virtual void add(unsigned int m, unsigned int n, Scalar v) = 0; 00320 00328 virtual void add(unsigned int m, unsigned int n, Scalar **mat, int *rows, int *cols) = 0; 00329 00335 virtual bool dump(FILE *file, const char *var_name, EMatrixDumpFormat fmt = DF_MATLAB_SPARSE, char* number_format = "%lf") = 0; 00336 00339 virtual unsigned int get_matrix_size() const = 0; 00340 00341 protected: 00342 00343 unsigned int size; 00344 }; 00345 00347 template<typename Scalar> 00348 class HERMES_API SparseMatrix : public Matrix<Scalar> { 00349 public: 00350 SparseMatrix(); 00353 SparseMatrix(unsigned int size); 00354 virtual ~SparseMatrix(); 00355 00359 virtual void prealloc(unsigned int n); 00360 00365 virtual void pre_add_ij(unsigned int row, unsigned int col); 00366 00368 virtual void finish() { } 00369 00370 virtual unsigned int get_size() { return this->size; } 00371 00374 virtual void add_sparse_matrix(SparseMatrix* mat) 00375 { 00376 throw Hermes::Exceptions::Exception("add_sparse_matrix() undefined."); 00377 }; 00378 00383 virtual void add_sparse_to_diagonal_blocks(int num_stages, SparseMatrix<Scalar>* mat) 00384 { 00385 throw Hermes::Exceptions::Exception("add_sparse_to_diagonal_blocks() undefined."); 00386 }; 00387 00392 virtual int get_num_row_entries(unsigned int row) { return -1; } 00393 00401 virtual void extract_row_copy(unsigned int row, unsigned int len, 00402 unsigned int &n_entries, double *vals, 00403 unsigned int *idxs) { } 00404 00409 virtual int get_num_col_entries(unsigned int col) { return -1; } 00410 00418 virtual void extract_col_copy(unsigned int col, unsigned int len, 00419 unsigned int &n_entries, double *vals, 00420 unsigned int *idxs) { } 00421 00423 virtual void multiply_with_vector(Scalar* vector_in, Scalar* vector_out) { 00424 throw Hermes::Exceptions::Exception("multiply_with_vector() undefined."); 00425 }; 00426 00428 virtual void multiply_with_Scalar(Scalar value) { 00429 throw Hermes::Exceptions::Exception("multiply_with_Scalar() undefined."); 00430 }; 00431 00433 virtual SparseMatrix* duplicate() { return (SparseMatrix*)NULL;}; 00434 00436 virtual double get_fill_in() const = 0; 00437 00438 unsigned row_storage:1; 00439 unsigned col_storage:1; 00440 00443 virtual unsigned int get_nnz() const { 00444 throw Hermes::Exceptions::Exception("get_nnz() undefined."); 00445 return 0; 00446 } 00447 00448 protected: 00450 static const int PAGE_SIZE = 62; 00451 00453 struct Page { 00455 int count; 00457 int idx[PAGE_SIZE]; 00459 Page *next; 00460 }; 00461 00463 Page **pages; 00464 00471 int sort_and_store_indices(Page *page, int *buffer, int *max); 00474 int get_num_indices(); 00475 00477 int mem_size; 00478 }; 00479 00481 template<typename Scalar> 00482 class HERMES_API Vector : public Hermes::Mixins::Loggable 00483 { 00484 public: 00485 virtual ~Vector() { } 00486 00490 virtual void alloc(unsigned int ndofs) = 0; 00492 virtual void free() = 0; 00494 virtual void finish() { } 00495 00499 virtual Scalar get(unsigned int idx) = 0; 00500 00503 virtual void extract(Scalar *v) const = 0; 00504 00506 virtual void zero() = 0; 00507 00509 virtual void change_sign() = 0; 00510 00515 virtual void set(unsigned int idx, Scalar y) = 0; 00516 00521 virtual void add(unsigned int idx, Scalar y) = 0; 00522 00524 virtual void add_vector(Vector<Scalar>* vec) = 0; 00526 virtual void add_vector(Scalar* vec) = 0; 00527 00533 virtual void add(unsigned int n, unsigned int *idx, Scalar *y) = 0; 00534 00536 unsigned int length() const {return this->size;} 00537 00543 virtual bool dump(FILE *file, const char *var_name, 00544 EMatrixDumpFormat fmt = DF_MATLAB_SPARSE, char* number_format = "%lf") = 0; 00545 00546 protected: 00548 unsigned int size; 00549 }; 00550 00553 template<typename Scalar> HERMES_API 00554 Vector<Scalar>* create_vector(); 00555 00558 template<typename Scalar> HERMES_API 00559 SparseMatrix<Scalar>* create_matrix(); 00560 } 00561 } 00562 #endif
1.7.4