libMesh
trilinos_epetra_matrix.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 // C++ includes
20 #include "libmesh/libmesh_config.h"
21 
22 #ifdef LIBMESH_TRILINOS_HAVE_EPETRA
23 
24 // Local includes
25 #include "libmesh/trilinos_epetra_matrix.h"
26 #include "libmesh/trilinos_epetra_vector.h"
27 #include "libmesh/dof_map.h"
28 #include "libmesh/dense_matrix.h"
29 #include "libmesh/parallel.h"
30 #include "libmesh/sparsity_pattern.h"
31 #include "libmesh/int_range.h"
32 
33 namespace libMesh
34 {
35 
36 
37 
38 //-----------------------------------------------------------------------
39 //EpetraMatrix members
40 
41 template <typename T>
43 {
44  // clear data, start over
45  this->clear ();
46 
47  // big trouble if this fails!
48  libmesh_assert(this->_dof_map);
49 
50  const numeric_index_type n_rows = cast_int<numeric_index_type>
51  (sparsity_pattern.size());
52 
53  const numeric_index_type m = this->_dof_map->n_dofs();
54  const numeric_index_type n = m;
55  const numeric_index_type n_l = this->_dof_map->n_dofs_on_processor(this->processor_id());
56  const numeric_index_type m_l = n_l;
57 
58  // error checking
59 #ifndef NDEBUG
60  {
61  libmesh_assert_equal_to (n, m);
62  libmesh_assert_equal_to (n_l, m_l);
63 
65  summed_m_l = m_l,
66  summed_n_l = n_l;
67 
68  this->comm().sum (summed_m_l);
69  this->comm().sum (summed_n_l);
70 
71  libmesh_assert_equal_to (m, summed_m_l);
72  libmesh_assert_equal_to (n, summed_n_l);
73  }
74 #endif
75 
76  // build a map defining the data distribution
77  _map = new Epetra_Map (static_cast<int>(m),
78  m_l,
79  0,
80  Epetra_MpiComm (this->comm().get()));
81 
82  libmesh_assert_equal_to (static_cast<numeric_index_type>(_map->NumGlobalPoints()), m);
83  libmesh_assert_equal_to (static_cast<numeric_index_type>(_map->MaxAllGID()+1), m);
84 
85  const std::vector<numeric_index_type> & n_nz = this->_dof_map->get_n_nz();
86  const std::vector<numeric_index_type> & n_oz = this->_dof_map->get_n_oz();
87 
88  // Make sure the sparsity pattern isn't empty
89  libmesh_assert_equal_to (n_nz.size(), n_l);
90  libmesh_assert_equal_to (n_oz.size(), n_l);
91 
92  // Epetra wants the total number of nonzeros, both local and remote.
93  std::vector<int> n_nz_tot; n_nz_tot.reserve(n_nz.size());
94 
95  for (auto i : index_range(n_nz))
96  n_nz_tot.push_back(std::min(n_nz[i] + n_oz[i], n));
97 
98  if (m==0)
99  return;
100 
101  _graph = new Epetra_CrsGraph(Copy, *_map, n_nz_tot.data());
102 
103  // Tell the matrix about its structure. Initialize it
104  // to zero.
105  for (numeric_index_type i=0; i<n_rows; i++)
106  _graph->InsertGlobalIndices(_graph->GRID(i),
107  cast_int<numeric_index_type>(sparsity_pattern[i].size()),
108  const_cast<int *>(reinterpret_cast<const int *>(sparsity_pattern[i].data())));
109 
110  _graph->FillComplete();
111 
112  //Initialize the matrix
113  libmesh_assert (!this->initialized());
114  this->init ();
115  libmesh_assert (this->initialized());
116 }
117 
118 
119 
120 template <typename T>
122  const numeric_index_type n,
123  const numeric_index_type m_l,
124  const numeric_index_type libmesh_dbg_var(n_l),
125  const numeric_index_type nnz,
126  const numeric_index_type noz,
127  const numeric_index_type /* blocksize */)
128 {
129  if ((m==0) || (n==0))
130  return;
131 
132  {
133  // Clear initialized matrices
134  if (this->initialized())
135  this->clear();
136 
137  libmesh_assert (!this->_mat);
138  libmesh_assert (!this->_map);
139 
140  this->_is_initialized = true;
141  }
142 
143  // error checking
144 #ifndef NDEBUG
145  {
146  libmesh_assert_equal_to (n, m);
147  libmesh_assert_equal_to (n_l, m_l);
148 
150  summed_m_l = m_l,
151  summed_n_l = n_l;
152 
153  this->comm().sum (summed_m_l);
154  this->comm().sum (summed_n_l);
155 
156  libmesh_assert_equal_to (m, summed_m_l);
157  libmesh_assert_equal_to (n, summed_n_l);
158  }
159 #endif
160 
161  // build a map defining the data distribution
162  _map = new Epetra_Map (static_cast<int>(m),
163  m_l,
164  0,
165  Epetra_MpiComm (this->comm().get()));
166 
167  libmesh_assert_equal_to (static_cast<numeric_index_type>(_map->NumGlobalPoints()), m);
168  libmesh_assert_equal_to (static_cast<numeric_index_type>(_map->MaxAllGID()+1), m);
169 
170  _mat = new Epetra_FECrsMatrix (Copy, *_map, nnz + noz);
171 }
172 
173 
174 
175 
176 template <typename T>
178 {
179  libmesh_assert(this->_dof_map);
180 
181  {
182  // Clear initialized matrices
183  if (this->initialized())
184  this->clear();
185 
186  this->_is_initialized = true;
187  }
188 
189 
190  _mat = new Epetra_FECrsMatrix (Copy, *_graph);
191 }
192 
193 
194 
195 template <typename T>
197 {
198  libmesh_assert (this->initialized());
199 
200  _mat->Scale(0.0);
201 }
202 
203 
204 
205 template <typename T>
207 {
208  // delete _mat;
209  // delete _map;
210 
211  this->_is_initialized = false;
212 
213  libmesh_assert (!this->initialized());
214 }
215 
216 
217 
218 template <typename T>
220 {
221  libmesh_assert (this->initialized());
222 
223  libmesh_assert(_mat);
224 
225  return static_cast<Real>(_mat->NormOne());
226 }
227 
228 
229 
230 template <typename T>
232 {
233  libmesh_assert (this->initialized());
234 
235 
236  libmesh_assert(_mat);
237 
238  return static_cast<Real>(_mat->NormInf());
239 }
240 
241 
242 
243 template <typename T>
245  const std::vector<numeric_index_type> & rows,
246  const std::vector<numeric_index_type> & cols)
247 {
248  libmesh_assert (this->initialized());
249 
250  const numeric_index_type m = dm.m();
251  const numeric_index_type n = dm.n();
252 
253  libmesh_assert_equal_to (rows.size(), m);
254  libmesh_assert_equal_to (cols.size(), n);
255 
256  _mat->SumIntoGlobalValues(m, numeric_trilinos_cast(rows.data()),
257  n, numeric_trilinos_cast(cols.data()),
258  dm.get_values().data());
259 }
260 
261 
262 
263 
264 
265 
266 template <typename T>
268 {
269  // Convert vector to EpetraVector.
270  EpetraVector<T> * epetra_dest = cast_ptr<EpetraVector<T> *>(&dest);
271 
272  // Call Epetra function.
273  _mat->ExtractDiagonalCopy(*(epetra_dest->vec()));
274 }
275 
276 
277 
278 template <typename T>
280 {
281  // Make sure the SparseMatrix passed in is really a EpetraMatrix
282  EpetraMatrix<T> & epetra_dest = cast_ref<EpetraMatrix<T> &>(dest);
283 
284  // We currently only support calling get_transpose() with ourself
285  // as the destination. Previously, this called the default copy
286  // constructor which was not safe because this class manually
287  // manages memory.
288  if (&epetra_dest != this)
289  libmesh_not_implemented();
290 
291  epetra_dest._use_transpose = !epetra_dest._use_transpose;
292  epetra_dest._mat->SetUseTranspose(epetra_dest._use_transpose);
293 }
294 
295 
296 
297 template <typename T>
298 EpetraMatrix<T>::EpetraMatrix(const Parallel::Communicator & comm) :
299  SparseMatrix<T>(comm),
300  _destroy_mat_on_exit(true),
301  _use_transpose(false)
302 {}
303 
304 
305 
306 
307 template <typename T>
308 EpetraMatrix<T>::EpetraMatrix(Epetra_FECrsMatrix * m,
309  const Parallel::Communicator & comm) :
310  SparseMatrix<T>(comm),
311  _destroy_mat_on_exit(false),
312  _use_transpose(false) // dumb guess is the best we can do...
313 {
314  this->_mat = m;
315  this->_is_initialized = true;
316 }
317 
318 
319 
320 
321 template <typename T>
323 {
324  this->clear();
325 }
326 
327 
328 
329 template <typename T>
331 {
332  libmesh_assert(_mat);
333 
334  _mat->GlobalAssemble();
335 }
336 
337 
338 
339 template <typename T>
341 {
342  libmesh_assert (this->initialized());
343 
344  return static_cast<numeric_index_type>(_mat->NumGlobalRows());
345 }
346 
347 
348 
349 template <typename T>
351 {
352  libmesh_assert (this->initialized());
353 
354  return static_cast<numeric_index_type>(_mat->NumGlobalCols());
355 }
356 
357 
358 
359 template <typename T>
361 {
362  libmesh_assert (this->initialized());
363  libmesh_assert(_map);
364 
365  return static_cast<numeric_index_type>(_map->MinMyGID());
366 }
367 
368 
369 
370 template <typename T>
372 {
373  libmesh_assert (this->initialized());
374  libmesh_assert(_map);
375 
376  return static_cast<numeric_index_type>(_map->MaxMyGID())+1;
377 }
378 
379 
380 
381 template <typename T>
383  const numeric_index_type j,
384  const T value)
385 {
386  libmesh_assert (this->initialized());
387 
388  int
389  epetra_i = static_cast<int>(i),
390  epetra_j = static_cast<int>(j);
391 
392  T epetra_value = value;
393 
394  if (_mat->Filled())
395  _mat->ReplaceGlobalValues (epetra_i, 1, &epetra_value, &epetra_j);
396  else
397  _mat->InsertGlobalValues (epetra_i, 1, &epetra_value, &epetra_j);
398 }
399 
400 
401 
402 template <typename T>
404  const numeric_index_type j,
405  const T value)
406 {
407  libmesh_assert (this->initialized());
408 
409  int
410  epetra_i = static_cast<int>(i),
411  epetra_j = static_cast<int>(j);
412 
413  T epetra_value = value;
414 
415  _mat->SumIntoGlobalValues (epetra_i, 1, &epetra_value, &epetra_j);
416 }
417 
418 
419 
420 template <typename T>
422  const std::vector<numeric_index_type> & dof_indices)
423 {
424  this->add_matrix (dm, dof_indices, dof_indices);
425 }
426 
427 
428 
429 template <typename T>
430 void EpetraMatrix<T>::add (const T a_in, const SparseMatrix<T> & X_in)
431 {
432 #ifdef LIBMESH_TRILINOS_HAVE_EPETRAEXT
433  libmesh_assert (this->initialized());
434 
435  // sanity check. but this cannot avoid
436  // crash due to incompatible sparsity structure...
437  libmesh_assert_equal_to (this->m(), X_in.m());
438  libmesh_assert_equal_to (this->n(), X_in.n());
439 
440  const EpetraMatrix<T> * X =
441  cast_ptr<const EpetraMatrix<T> *> (&X_in);
442 
443  EpetraExt::MatrixMatrix::Add (*X->_mat, false, a_in, *_mat, 1.);
444 #else
445  libmesh_error_msg("ERROR: EpetraExt is required for EpetraMatrix::add()!");
446 #endif
447 }
448 
449 
450 
451 
452 template <typename T>
454  const numeric_index_type j) const
455 {
456  libmesh_assert (this->initialized());
457  libmesh_assert(this->_mat);
458  libmesh_assert (this->_mat->MyGlobalRow(static_cast<int>(i)));
459  libmesh_assert_greater_equal (i, this->row_start());
460  libmesh_assert_less (i, this->row_stop());
461 
462 
463  int row_length;
464  int * row_indices;
465  double * values;
466 
467  _mat->ExtractMyRowView (i-this->row_start(),
468  row_length,
469  values,
470  row_indices);
471 
472  //libMesh::out << "row_length=" << row_length << std::endl;
473 
474  int * index = std::lower_bound (row_indices, row_indices+row_length, j);
475 
476  libmesh_assert_less (*index, row_length);
477  libmesh_assert_equal_to (static_cast<numeric_index_type>(row_indices[*index]), j);
478 
479  //libMesh::out << "val=" << values[*index] << std::endl;
480 
481  return values[*index];
482 }
483 
484 
485 
486 
487 template <typename T>
489 {
490  libmesh_assert (this->initialized());
491  libmesh_assert(this->_mat);
492 
493  return this->_mat->Filled();
494 }
495 
496 
497 template <typename T>
499 {
500  std::swap(_mat, m._mat);
501  std::swap(_destroy_mat_on_exit, m._destroy_mat_on_exit);
502 }
503 
504 
505 
506 
507 
508 template <typename T>
509 void EpetraMatrix<T>::print_personal(std::ostream & os) const
510 {
511  libmesh_assert (this->initialized());
512  libmesh_assert(_mat);
513 
514  os << *_mat;
515 }
516 
517 
518 
519 //------------------------------------------------------------------
520 // Explicit instantiations
521 template class EpetraMatrix<Number>;
522 
523 } // namespace libMesh
524 
525 
526 #endif // LIBMESH_TRILINOS_HAVE_EPETRA
libMesh::EpetraMatrix::init
virtual void init() override
Initialize this matrix using the sparsity structure computed by dof_map.
Definition: trilinos_epetra_matrix.C:177
libMesh::EpetraMatrix::_mat
Epetra_FECrsMatrix * _mat
Actual Epetra datatype to hold matrix entries.
Definition: trilinos_epetra_matrix.h:202
libMesh::index_range
IntRange< std::size_t > index_range(const std::vector< T > &vec)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:106
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::EpetraMatrix::set
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value) override
Set the element (i,j) to value.
Definition: trilinos_epetra_matrix.C:382
libMesh::DenseMatrix
Defines a dense matrix for use in Finite Element-type computations.
Definition: dof_map.h:73
libMesh::DenseMatrixBase::n
unsigned int n() const
Definition: dense_matrix_base.h:109
libMesh::DenseMatrix::get_values
std::vector< T > & get_values()
Definition: dense_matrix.h:371
libMesh::EpetraMatrix::~EpetraMatrix
virtual ~EpetraMatrix()
Definition: trilinos_epetra_matrix.C:322
libMesh::EpetraMatrix::row_stop
virtual numeric_index_type row_stop() const override
Definition: trilinos_epetra_matrix.C:371
libMesh::EpetraMatrix::linfty_norm
virtual Real linfty_norm() const override
Definition: trilinos_epetra_matrix.C:231
libMesh::EpetraMatrix::get_transpose
virtual void get_transpose(SparseMatrix< T > &dest) const override
Copies the transpose of the matrix into dest, which may be *this.
Definition: trilinos_epetra_matrix.C:279
libMesh::SparseMatrix
Generic sparse matrix.
Definition: vector_fe_ex5.C:45
libMesh::NumericVector
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
Definition: vector_fe_ex5.C:43
libMesh::DenseMatrixBase::m
unsigned int m() const
Definition: dense_matrix_base.h:104
libMesh::EpetraVector
This class provides a nice interface to the Trilinos Epetra_Vector object.
Definition: trilinos_epetra_vector.h:63
libMesh::TriangleWrapper::init
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::EpetraMatrix::close
virtual void close() override
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
Definition: trilinos_epetra_matrix.C:330
libMesh::EpetraMatrix::EpetraMatrix
EpetraMatrix(const Parallel::Communicator &comm)
Constructor; initializes the matrix to be empty, without any structure, i.e.
Definition: trilinos_epetra_matrix.C:298
libMesh::EpetraMatrix
This class provides a nice interface to the Epetra data structures for parallel, sparse matrices.
Definition: trilinos_epetra_matrix.h:63
libMesh::EpetraVector::vec
Epetra_Vector * vec()
Definition: trilinos_epetra_vector.h:264
libMesh::EpetraMatrix::_use_transpose
bool _use_transpose
Epetra has no GetUseTranspose so we need to keep track of whether we're transposed manually.
Definition: trilinos_epetra_matrix.h:224
libMesh::EpetraMatrix::row_start
virtual numeric_index_type row_start() const override
Definition: trilinos_epetra_matrix.C:360
libMesh::EpetraMatrix::m
virtual numeric_index_type m() const override
Definition: trilinos_epetra_matrix.C:340
libMesh::EpetraMatrix::closed
virtual bool closed() const override
Definition: trilinos_epetra_matrix.C:488
libMesh::SparseMatrix::m
virtual numeric_index_type m() const =0
libMesh::numeric_index_type
dof_id_type numeric_index_type
Definition: id_types.h:99
libMesh::initialized
bool initialized()
Checks that library initialization has been done.
Definition: libmesh.C:265
libMesh::EpetraMatrix::zero
virtual void zero() override
Set all entries to 0.
Definition: trilinos_epetra_matrix.C:196
libMesh::EpetraMatrix::update_sparsity_pattern
virtual void update_sparsity_pattern(const SparsityPattern::Graph &) override
Updates the matrix sparsity pattern.
Definition: trilinos_epetra_matrix.C:42
swap
void swap(Iterator &lhs, Iterator &rhs)
swap, used to implement op=
Definition: variant_filter_iterator.h:478
libMesh::ReferenceElem::get
const Elem & get(const ElemType type_in)
Definition: reference_elem.C:237
libMesh::libMeshPrivateData::_is_initialized
bool _is_initialized
Flag that tells if init() has been called.
Definition: libmesh.C:246
value
static const bool value
Definition: xdr_io.C:56
libMesh::EpetraMatrix::n
virtual numeric_index_type n() const override
Definition: trilinos_epetra_matrix.C:350
libMesh::numeric_trilinos_cast
int * numeric_trilinos_cast(const numeric_index_type *p)
Definition: trilinos_epetra_vector.h:836
libMesh::EpetraMatrix::add
virtual void add(const numeric_index_type i, const numeric_index_type j, const T value) override
Add value to the element (i,j).
Definition: trilinos_epetra_matrix.C:403
libMesh::EpetraMatrix::clear
virtual void clear() override
Restores the SparseMatrix<T> to a pristine state.
Definition: trilinos_epetra_matrix.C:206
libMesh::EpetraMatrix::add_matrix
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols) override
Add the full matrix dm to the SparseMatrix.
Definition: trilinos_epetra_matrix.C:244
libMesh::EpetraMatrix::get_diagonal
virtual void get_diagonal(NumericVector< T > &dest) const override
Copies the diagonal part of the matrix into dest.
Definition: trilinos_epetra_matrix.C:267
libMesh::EpetraMatrix::swap
void swap(EpetraMatrix< T > &)
Swaps the internal data pointers, no actual values are swapped.
Definition: trilinos_epetra_matrix.C:498
data
IterBase * data
Ideally this private member data should have protected access.
Definition: variant_filter_iterator.h:337
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::EpetraMatrix::print_personal
virtual void print_personal(std::ostream &os=libMesh::out) const override
Print the contents of the matrix to the screen in a package-personalized style, if available.
Definition: trilinos_epetra_matrix.C:509
libMesh::EpetraMatrix::l1_norm
virtual Real l1_norm() const override
Definition: trilinos_epetra_matrix.C:219
libMesh::SparsityPattern::Graph
Definition: sparsity_pattern.h:52
libMesh::EpetraMatrix::_destroy_mat_on_exit
bool _destroy_mat_on_exit
This boolean value should only be set to false for the constructor which takes an Epetra_FECrsMatrix ...
Definition: trilinos_epetra_matrix.h:218
libMesh::SparseMatrix::_is_initialized
bool _is_initialized
Flag indicating whether or not the matrix has been initialized.
Definition: sparse_matrix.h:448
libMesh::SparseMatrix::n
virtual numeric_index_type n() const =0
libMesh::EpetraMatrix::operator()
virtual T operator()(const numeric_index_type i, const numeric_index_type j) const override
Definition: trilinos_epetra_matrix.C:453