HermesCommon  2.0
epetra.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 "config.h"
23 #include <vector>
24 #ifdef HAVE_EPETRA
25 #include "epetra.h"
26 #include "callstack.h"
27 
28 namespace Hermes
29 {
30  namespace Algebra
31  {
33  static Epetra_SerialComm seq_comm;
34 
35  template<typename Scalar>
36  EpetraMatrix<Scalar>::EpetraMatrix()
37  {
38  this->mat = NULL;
39  this->mat_im = NULL;
40  this->grph = NULL;
41  this->std_map = NULL;
42  this->owner = true;
43 
44  this->row_storage = true;
45  this->col_storage = false;
46  }
47 
48  template<typename Scalar>
49  EpetraMatrix<Scalar>::EpetraMatrix(Epetra_RowMatrix &op)
50  {
51  this->mat = dynamic_cast<Epetra_CrsMatrix *>(&op);
52  assert(mat != NULL);
53  this->grph = (Epetra_CrsGraph *) &this->mat->Graph();
54  this->std_map = (Epetra_BlockMap *) &this->grph->Map();
55  this->owner = false;
56 
57  this->row_storage = true;
58  this->col_storage = false;
59  }
60 
61  template<typename Scalar>
62  EpetraMatrix<Scalar>::~EpetraMatrix()
63  {
64  free();
65  }
66 
67  template<typename Scalar>
68  void EpetraMatrix<Scalar>::prealloc(unsigned int n)
69  {
70  this->size = n;
71  // alloc trilinos structs
72  std_map = new Epetra_Map(n, 0, seq_comm);
73  grph = new Epetra_CrsGraph(Copy, *std_map, 0);
74  }
75 
76  template<typename Scalar>
77  void EpetraMatrix<Scalar>::pre_add_ij(unsigned int row, unsigned int col)
78  {
79  int col_to_pass = col;
80  grph->InsertGlobalIndices(row, 1, &col_to_pass);
81  }
82 
83  template<>
84  void EpetraMatrix<double>::finish()
85  {
86  mat->FillComplete();
87  }
88 
89  template<>
90  void EpetraMatrix<std::complex<double> >::finish()
91  {
92  mat->FillComplete();
93  mat_im->FillComplete();
94  }
95 
96  template<>
97  void EpetraMatrix<double>::alloc()
98  {
99  grph->FillComplete();
100  // create the matrix
101  mat = new Epetra_CrsMatrix(Copy, *grph);
102  }
103 
104  template<>
105  void EpetraMatrix<std::complex<double> >::alloc()
106  {
107  grph->FillComplete();
108  // create the matrix
109  mat = new Epetra_CrsMatrix(Copy, *grph);
110  mat_im = new Epetra_CrsMatrix(Copy, *grph);
111  }
112 
113  template<>
114  void EpetraMatrix<double>::free()
115  {
116  if(owner)
117  {
118  delete mat; mat = NULL;
119  delete grph; grph = NULL;
120  delete std_map; std_map = NULL;
121  }
122  }
123 
124  template<>
125  void EpetraMatrix<std::complex<double> >::free()
126  {
127  if(owner)
128  {
129  delete mat; mat = NULL;
130  delete mat_im; mat_im = NULL;
131  delete grph; grph = NULL;
132  delete std_map; std_map = NULL;
133  }
134  }
135 
136  template<typename Scalar>
137  Scalar EpetraMatrix<Scalar>::get(unsigned int m, unsigned int n)
138  {
139  int n_entries = mat->NumGlobalEntries(m);
140  Hermes::vector<double> vals(n_entries);
141  Hermes::vector<int> idxs(n_entries);
142  mat->ExtractGlobalRowCopy(m, n_entries, n_entries, &vals[0], &idxs[0]);
143  for (int i = 0; i < n_entries; i++)
144  if(idxs[i] == (int)n)
145  return vals[i];
146  return 0.0;
147  }
148 
149  template<typename Scalar>
150  int EpetraMatrix<Scalar>::get_num_row_entries(unsigned int row)
151  {
152  return mat->NumGlobalEntries(row);
153  }
154 
155  template<typename Scalar>
156  void EpetraMatrix<Scalar>::extract_row_copy(unsigned int row, unsigned int len, unsigned int &n_entries, double *vals, unsigned int *idxs)
157  {
158  int* idxs_to_pass = new int[len];
159  for(unsigned int i = 0; i < len; i++)
160  idxs_to_pass[i] = idxs[i];
161  int n_entries_to_pass = n_entries;
162  mat->ExtractGlobalRowCopy(row, len, n_entries_to_pass, vals, idxs_to_pass);
163  delete [] idxs_to_pass;
164  }
165 
166  template<>
167  void EpetraMatrix<double>::zero()
168  {
169  mat->PutScalar(0.0);
170  }
171 
172  template<>
173  void EpetraMatrix<std::complex<double> >::zero()
174  {
175  mat->PutScalar(0.0);
176  mat_im->PutScalar(0.0);
177  }
178 
179  template<>
180  void EpetraMatrix<double>::add(unsigned int m, unsigned int n, double v)
181  {
182  if(v != 0.0)
183  { // ignore zero values
184  int n_to_pass = n;
185  int ierr = mat->SumIntoGlobalValues(m, 1, &v, &n_to_pass);
186  if(ierr != 0) throw Hermes::Exceptions::Exception("Failed to insert into Epetra matrix");
187  }
188  }
189 
190  template<>
191  void EpetraMatrix<std::complex<double> >::add(unsigned int m, unsigned int n, std::complex<double> v)
192  {
193  if(v != 0.0)
194  { // ignore zero values
195  double v_r = std::real<double>(v);
196  int n_to_pass = n;
197  int ierr = mat->SumIntoGlobalValues(m, 1, &v_r, &n_to_pass);
198  if(ierr != 0) throw Hermes::Exceptions::Exception("Failed to insert into Epetra matrix");
199  assert(ierr == 0);
200  double v_i = std::imag<double>(v);
201  ierr = mat_im->SumIntoGlobalValues(m, 1, &v_i, &n_to_pass);
202  assert(ierr == 0);
203  }
204  }
205 
207  template<typename Scalar>
208  void EpetraMatrix<Scalar>::add_to_diagonal(Scalar v)
209  {
210  for (unsigned int i = 0; i < this->size; i++)
211  {
212  add(i, i, v);
213  }
214  };
215 
216  template<typename Scalar>
217  void EpetraMatrix<Scalar>::add_to_diagonal_blocks(int num_stages, EpetraMatrix<Scalar>* mat_block)
218  {
219  int ndof = mat_block->get_size();
220  if(this->get_size() != (unsigned int) num_stages * ndof)
221  throw Hermes::Exceptions::Exception("Incompatible matrix sizes in CSCMatrix<Scalar>::add_to_diagonal_blocks()");
222 
223  for (int i = 0; i < num_stages; i++)
224  {
225  this->add_as_block(ndof*i, ndof*i, mat_block);
226  }
227  }
228 
229  template<typename Scalar>
230  void EpetraMatrix<Scalar>::add_sparse_to_diagonal_blocks(int num_stages, SparseMatrix<Scalar>* mat)
231  {
232  add_to_diagonal_blocks(num_stages, dynamic_cast<EpetraMatrix<Scalar>*>(mat));
233  }
234 
235  template<typename Scalar>
236  void EpetraMatrix<Scalar>::add_as_block(unsigned int i, unsigned int j, EpetraMatrix<Scalar>* mat)
237  {
238  if((this->get_size() < i + mat->get_size() )||(this->get_size() < j + mat->get_size() ))
239  throw Hermes::Exceptions::Exception("Incompatible matrix sizes in Epetra<Scalar>::add_as_block()");
240  unsigned int block_size = mat->get_size();
241  for (unsigned int r = 0; r<block_size; r++)
242  {
243  for (unsigned int c = 0; c<block_size; c++)
244  {
245  this->add(i + r, j + c, mat->get(r, c));
246  }
247  }
248  }
249 
250  template<typename Scalar>
251  void EpetraMatrix<Scalar>::multiply_with_vector(Scalar* vector_in, Scalar* vector_out)
252  {
253  for (unsigned int i = 0; i<this->size; i++) //probably can be optimized by use native vectors
254  {
255  vector_out[i] = 0;
256  for (unsigned int j = 0; j<this->size; j++)
257  {
258  vector_out[i] +=vector_in[j]*get(i, j);
259  }
260  }
261  }
262 
263  template<typename Scalar>
264  void EpetraMatrix<Scalar>::add(unsigned int m, unsigned int n, Scalar **mat, int *rows, int *cols)
265  {
266  for (unsigned int i = 0; i < m; i++) // rows
267  for (unsigned int j = 0; j < n; j++) // cols
268  if(rows[i] >= 0 && cols[j] >= 0) // not Dir. dofs.
269  add(rows[i], cols[j], mat[i][j]);
270  }
271 
272  template<typename Scalar>
273  bool EpetraMatrix<Scalar>::dump(FILE *file, const char *var_name, EMatrixDumpFormat fmt, char* number_format)
274  {
275  return false;
276  }
277 
278  template<typename Scalar>
279  unsigned int EpetraMatrix<Scalar>::get_matrix_size() const
280  {
281  return this->size;
282  }
283 
284  template<typename Scalar>
285  double EpetraMatrix<Scalar>::get_fill_in() const
286  {
287  return mat->NumGlobalNonzeros() / ((double)this->size*this->size);
288  }
289 
290  template<typename Scalar>
291  unsigned int EpetraMatrix<Scalar>::get_nnz() const
292  {
293  return mat->NumGlobalNonzeros();
294  }
295 
296  template<typename Scalar>
297  EpetraVector<Scalar>::EpetraVector()
298  {
299  this->std_map = NULL;
300  this->vec = NULL;
301  this->vec_im = NULL;
302  this->size = 0;
303  this->owner = true;
304  }
305 
306  template<typename Scalar>
307  EpetraVector<Scalar>::EpetraVector(const Epetra_Vector &v)
308  {
309  this->vec = (Epetra_Vector *) &v;
310  this->vec_im = NULL;
311  this->std_map = (Epetra_BlockMap *) &v.Map();
312  this->size = v.MyLength();
313  this->owner = false;
314  }
315 
316  template<typename Scalar>
317  EpetraVector<Scalar>::~EpetraVector()
318  {
319  if(owner) free();
320  }
321 
322  template<typename Scalar>
323  void EpetraVector<Scalar>::alloc(unsigned int n)
324  {
325  free();
326  this->size = n;
327  std_map = new Epetra_Map(this->size, 0, seq_comm);
328  vec = new Epetra_Vector(*std_map);
329  vec_im = new Epetra_Vector(*std_map);
330  zero();
331  }
332 
333  template<typename Scalar>
334  void EpetraVector<Scalar>::zero()
335  {
336  for (unsigned int i = 0; i < this->size; i++) (*vec)[i] = 0.0;
337  if(vec_im)
338  for (unsigned int i = 0; i < this->size; i++) (*vec_im)[i] = 0.0;
339  }
340 
341  template<typename Scalar>
342  void EpetraVector<Scalar>::change_sign()
343  {
344  for (unsigned int i = 0; i < this->size; i++) (*vec)[i] *= -1.;
345  for (unsigned int i = 0; i < this->size; i++) (*vec_im)[i] *= -1.;
346  }
347 
348  template<typename Scalar>
349  void EpetraVector<Scalar>::free()
350  {
351  if(this->owner)
352  {
353  delete std_map; std_map = NULL;
354  delete vec; vec = NULL;
355  delete vec_im; vec_im = NULL;
356  this->size = 0;
357  }
358  }
359 
360  template<>
361  void EpetraVector<double>::set(unsigned int idx, double y)
362  {
363  (*vec)[idx] = y;
364  }
365 
366  template<>
367  void EpetraVector<std::complex<double> >::set(unsigned int idx, std::complex<double> y)
368  {
369  (*vec)[idx] = std::real(y);
370  (*vec_im)[idx] = std::imag(y);
371  }
372 
373  template<>
374  void EpetraVector<double>::add(unsigned int idx, double y)
375  {
376  (*vec)[idx] += y;
377  }
378 
379  template<>
380  void EpetraVector<std::complex<double> >::add(unsigned int idx, std::complex<double> y)
381  {
382  (*vec)[idx] += std::real(y);
383  (*vec_im)[idx] += std::imag(y);
384  }
385 
386  template<typename Scalar>
387  void EpetraVector<Scalar>::add(unsigned int n, unsigned int *idx, Scalar *y)
388  {
389  for (unsigned int i = 0; i < n; i++)
390  add(idx[i], y[i]);
391  }
392 
393  template<typename Scalar>
394  Scalar EpetraVector<Scalar>::get(unsigned int idx)
395  {
396  return (*vec)[idx];
397  }
398 
399  template<typename Scalar>
400  void EpetraVector<Scalar>::extract(Scalar *v) const
401  {
402  vec->ExtractCopy((double *)v);
403  }
404 
405  template<typename Scalar>
406  void EpetraVector<Scalar>::add_vector(Vector<Scalar>* vec)
407  {
408  assert(this->length() == vec->length());
409  for (unsigned int i = 0; i < this->length(); i++) this->add(i, vec->get(i));
410  }
411 
412  template<typename Scalar>
413  void EpetraVector<Scalar>::add_vector(Scalar* vec)
414  {
415  for (unsigned int i = 0; i < this->length(); i++) this->add(i, vec[i]);
416  }
417 
418  template<typename Scalar>
419  bool EpetraVector<Scalar>::dump(FILE *file, const char *var_name, EMatrixDumpFormat fmt, char* number_format)
420  {
421  return false;
422  }
423 
424  template class HERMES_API EpetraMatrix<double>;
425  template class HERMES_API EpetraMatrix<std::complex<double> >;
426  template class HERMES_API EpetraVector<double>;
427  template class HERMES_API EpetraVector<std::complex<double> >;
428  }
429 }
430 #endif