HermesCommon  2.0
matrix.cpp
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 #include "common.h"
23 #include "matrix.h"
24 #include "callstack.h"
25 
26 #include "solvers/linear_matrix_solver.h"
27 #include "solvers/umfpack_solver.h"
28 #include "solvers/superlu_solver.h"
29 #include "solvers/amesos_solver.h"
30 #include "solvers/petsc_solver.h"
31 #include "solvers/mumps_solver.h"
33 #include "solvers/aztecoo_solver.h"
34 #include "qsort.h"
35 #include "api.h"
36 
37 void Hermes::Algebra::DenseMatrixOperations::ludcmp(double **a, int n, int *indx, double *d)
38 {
39  int i, imax = 0, j, k;
40  double big, dum, sum, temp;
41  double *vv = new double[n];
42 
43  *d = 1.0;
44  for (i = 0; i < n; i++)
45  {
46  big = 0.0;
47  for (j = 0; j < n; j++)
48  if((temp = fabs(a[i][j])) > big)
49  big = temp;
50  if(big == 0.0)
51  {
52  delete [] vv;
53  throw Exceptions::Exception("Singular matrix in routine LUDCMP!");
54  }
55  vv[i] = 1.0 / big;
56  }
57  for (j = 0; j < n; j++)
58  {
59  for (i = 0; i < j; i++)
60  {
61  sum = a[i][j];
62  for (k = 0; k < i; k++) sum -= a[i][k]*a[k][j];
63  a[i][j] = sum;
64  }
65  big = 0.0;
66  for (i = j; i < n; i++)
67  {
68  sum = a[i][j];
69  for (k = 0; k < j; k++) sum -= a[i][k]*a[k][j];
70  a[i][j] = sum;
71  if((dum = vv[i]*fabs(sum)) >= big)
72  {
73  big = dum;
74  imax = i;
75  }
76  }
77  if(j != imax)
78  {
79  for (k = 0; k < n; k++)
80  {
81  dum = a[imax][k];
82  a[imax][k] = a[j][k];
83  a[j][k] = dum;
84  }
85  *d = -(*d);
86  vv[imax] = vv[j];
87  }
88  indx[j] = imax;
89  if(a[j][j] == 0.0) a[j][j] = 1.0e-20;
90  if(j != n-1)
91  {
92  dum = 1.0 / (a[j][j]);
93  for (i = j + 1; i < n; i++) a[i][j] *= dum;
94  }
95  }
96  delete [] vv;
97 }
98 
99 void Hermes::Algebra::DenseMatrixOperations::choldc(double **a, int n, double p[])
100 {
101  int i, j, k;
102  for (i = 0; i < n; i++)
103  {
104  for (j = i; j < n; j++)
105  {
106  double sum = a[i][j];
107  k = i;
108  while (--k >= 0) sum -= a[i][k] * a[j][k];
109  if(i == j)
110  {
111  if(sum <= 0.0)
112  throw Exceptions::Exception("CHOLDC failed!");
113  else p[i] = sqrt(sum);
114  }
115  else a[j][i] = sum / p[i];
116  }
117  }
118 }
119 
120 template<typename Scalar>
122 {
123  this->size = 0;
124  pages = NULL;
125 
126  row_storage = false;
127  col_storage = false;
128 }
129 
130 template<typename Scalar>
132 {
133  this->size = size;
134  pages = NULL;
135 
136  row_storage = false;
137  col_storage = false;
138 }
139 
140 template<typename Scalar>
142 {
143  if(pages)
144  {
145  for (unsigned int i = 0; i < this->size; i++)
146  if(pages[i])
147  delete pages[i];
148  delete [] pages;
149  }
150 }
151 
152 template<typename Scalar>
154 {
155  this->size = n;
156 
157  pages = new Page *[n];
158  memset(pages, 0, n * sizeof(Page *));
159 }
160 
161 template<typename Scalar>
162 void Hermes::Algebra::SparseMatrix<Scalar>::pre_add_ij(unsigned int row, unsigned int col)
163 {
164  if(pages[col] == NULL || pages[col]->count >= PAGE_SIZE)
165  {
166  Page *new_page = new Page;
167  new_page->count = 0;
168  new_page->next = pages[col];
169  pages[col] = new_page;
170  }
171  pages[col]->idx[pages[col]->count++] = row;
172 }
173 
174 template<typename Scalar>
176 {
177  // gather all pages in the buffer, deleting them along the way
178  int *end = buffer;
179  while (page != NULL)
180  {
181  memcpy(end, page->idx, sizeof(int) * page->count);
182  end += page->count;
183  Page *tmp = page;
184  page = page->next;
185  delete tmp;
186  }
187 
188  // sort the indices and remove duplicities
189  qsort_int(buffer, end - buffer);
190  int *q = buffer;
191  for (int *p = buffer, last = -1; p < end; p++) if(*p != last) *q++= last = *p;
192 
193  return q - buffer;
194 }
195 
196 template<typename Scalar>
198 {
199  int total = 0;
200  for (unsigned int i = 0; i < this->size; i++)
201  for (Page *page = pages[i]; page != NULL; page = page->next)
202  total += page->count;
203 
204  return total;
205 }
206 
207 template<typename Scalar>
209 {
210  switch (Hermes::HermesCommonApi.get_integral_param_value(Hermes::matrixSolverType))
211  {
212  case Hermes::SOLVER_AMESOS:
213  {
214 #if defined HAVE_AMESOS && defined HAVE_EPETRA
215  return new EpetraMatrix<Scalar>;
216 #else
217  throw Hermes::Exceptions::Exception("Amesos not installed.");
218 #endif
219  break;
220  }
221  case Hermes::SOLVER_AZTECOO:
222  {
223 #if defined HAVE_AZTECOO && defined HAVE_EPETRA
224  return new EpetraMatrix<Scalar>;
225 #else
226  throw Hermes::Exceptions::Exception("AztecOO not installed.");
227 #endif
228  break;
229  }
230  case Hermes::SOLVER_MUMPS:
231  {
232 #ifdef WITH_MUMPS
233  return new MumpsMatrix<Scalar>;
234 #else
235  throw Hermes::Exceptions::Exception("MUMPS not installed.");
236 #endif
237  break;
238  }
239  case Hermes::SOLVER_PETSC:
240  {
241 #ifdef WITH_PETSC
242  return new PetscMatrix<Scalar>;
243 #else
244  throw Hermes::Exceptions::Exception("PETSc not installed.");
245 #endif
246  break;
247  }
248  case Hermes::SOLVER_UMFPACK:
249  {
250 #ifdef WITH_UMFPACK
251  return new UMFPackMatrix<Scalar>;
252 #else
253  throw Hermes::Exceptions::Exception("UMFPACK was not installed.");
254 #endif
255  break;
256  }
257  case Hermes::SOLVER_SUPERLU:
258  {
259 #ifdef WITH_SUPERLU
260  return new SuperLUMatrix<Scalar>;
261 #else
262  throw Hermes::Exceptions::Exception("SuperLU was not installed.");
263 #endif
264  break;
265  }
266  default:
267  throw Hermes::Exceptions::Exception("Unknown matrix solver requested in create_matrix().");
268  }
269  return NULL;
270 }
271 
272 template<typename Scalar>
274 {
275  switch (Hermes::HermesCommonApi.get_integral_param_value(Hermes::matrixSolverType))
276  {
277  case Hermes::SOLVER_AMESOS:
278  {
279 #if defined HAVE_AMESOS && defined HAVE_EPETRA
280  return new EpetraVector<Scalar>;
281 #else
282  throw Hermes::Exceptions::Exception("Amesos not installed.");
283 #endif
284  break;
285  }
286  case Hermes::SOLVER_AZTECOO:
287  {
288 #if defined HAVE_AZTECOO && defined HAVE_EPETRA
289  return new EpetraVector<Scalar>;
290 #else
291  throw Hermes::Exceptions::Exception("AztecOO not installed.");
292 #endif
293  break;
294  }
295  case Hermes::SOLVER_MUMPS:
296  {
297 #ifdef WITH_MUMPS
298  return new MumpsVector<Scalar>;
299 #else
300  throw Hermes::Exceptions::Exception("MUMPS was not installed.");
301 #endif
302  break;
303  }
304  case Hermes::SOLVER_PETSC:
305  {
306 #ifdef WITH_PETSC
307  return new PetscVector<Scalar>;
308 #else
309  throw Hermes::Exceptions::Exception("PETSc not installed.");
310 #endif
311  break;
312  }
313  case Hermes::SOLVER_UMFPACK:
314  {
315 #ifdef WITH_UMFPACK
316  return new UMFPackVector<Scalar>;
317 #else
318  throw Hermes::Exceptions::Exception("UMFPACK was not installed.");
319 #endif
320  break;
321  }
322  case Hermes::SOLVER_SUPERLU:
323  {
324 #ifdef WITH_SUPERLU
325  return new SuperLUVector<Scalar>;
326 #else
327  throw Hermes::Exceptions::Exception("SuperLU was not installed.");
328 #endif
329  break;
330  }
331  default:
332  throw Hermes::Exceptions::Exception("Unknown matrix solver requested in create_vector().");
333  }
334  return NULL;
335 }
336 
339 
340 template HERMES_API Vector<double>* Hermes::Algebra::create_vector();
342