libMesh
trilinos_epetra_matrix.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 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_local_dofs();
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->_sp->get_n_nz();
86  const std::vector<numeric_index_type> & n_oz = this->_sp->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>
206 std::unique_ptr<SparseMatrix<T>> EpetraMatrix<T>::zero_clone () const
207 {
208  // This function is marked as "not implemented" since it hasn't been
209  // tested, the code below might serve as a possible implementation.
210  libmesh_not_implemented();
211 
212  // Make empty copy with matching comm, initialize, and return.
213  auto mat_copy = std::make_unique<EpetraMatrix<T>>(this->comm());
214  mat_copy->init();
215  mat_copy->zero();
216 
217  return mat_copy;
218 }
219 
220 
221 
222 template <typename T>
223 std::unique_ptr<SparseMatrix<T>> EpetraMatrix<T>::clone () const
224 {
225  // We don't currently have a faster implementation than making a
226  // zero clone and then filling in the values.
227  auto mat_copy = this->zero_clone();
228  mat_copy->add(1., *this);
229 
230  return mat_copy;
231 }
232 
233 
234 
235 template <typename T>
236 void EpetraMatrix<T>::clear () noexcept
237 {
238  // FIXME: clear() doesn't actually free the memory managed by this
239  // class, so it probably leaks memory.
240  // delete _mat;
241  // delete _map;
242 
243  this->_is_initialized = false;
244 }
245 
246 
247 
248 template <typename T>
250 {
251  libmesh_assert (this->initialized());
252 
253  libmesh_assert(_mat);
254 
255  return static_cast<Real>(_mat->NormOne());
256 }
257 
258 
259 
260 template <typename T>
262 {
263  libmesh_assert (this->initialized());
264 
265 
266  libmesh_assert(_mat);
267 
268  return static_cast<Real>(_mat->NormInf());
269 }
270 
271 
272 
273 template <typename T>
275  const std::vector<numeric_index_type> & rows,
276  const std::vector<numeric_index_type> & cols)
277 {
278  libmesh_assert (this->initialized());
279 
280  const numeric_index_type m = dm.m();
281  const numeric_index_type n = dm.n();
282 
283  libmesh_assert_equal_to (rows.size(), m);
284  libmesh_assert_equal_to (cols.size(), n);
285 
286  _mat->SumIntoGlobalValues(m, numeric_trilinos_cast(rows.data()),
287  n, numeric_trilinos_cast(cols.data()),
288  dm.get_values().data());
289 }
290 
291 
292 
293 
294 
295 
296 template <typename T>
298 {
299  // Convert vector to EpetraVector.
300  EpetraVector<T> * epetra_dest = cast_ptr<EpetraVector<T> *>(&dest);
301 
302  // Call Epetra function.
303  _mat->ExtractDiagonalCopy(*(epetra_dest->vec()));
304 }
305 
306 
307 
308 template <typename T>
310 {
311  // Make sure the SparseMatrix passed in is really a EpetraMatrix
312  EpetraMatrix<T> & epetra_dest = cast_ref<EpetraMatrix<T> &>(dest);
313 
314  // We currently only support calling get_transpose() with ourself
315  // as the destination. Previously, this called the default copy
316  // constructor which was not safe because this class manually
317  // manages memory.
318  if (&epetra_dest != this)
319  libmesh_not_implemented();
320 
321  epetra_dest._use_transpose = !epetra_dest._use_transpose;
322  epetra_dest._mat->SetUseTranspose(epetra_dest._use_transpose);
323 }
324 
325 
326 
327 template <typename T>
329  std::vector<numeric_index_type> & indices,
330  std::vector<T> & values) const
331 {
332  libmesh_assert (this->initialized());
333  libmesh_assert(this->_mat);
334  libmesh_assert (this->_mat->MyGlobalRow(static_cast<int>(i)));
335  libmesh_assert_greater_equal (i, this->row_start());
336  libmesh_assert_less (i, this->row_stop());
337 
338  int row_length;
339  int * row_indices;
340  double * row_values;
341 
342  _mat->ExtractMyRowView (i-this->row_start(),
343  row_length,
344  row_values,
345  row_indices);
346 
347  indices.resize(row_length);
348  values.resize(row_length);
349 
350  for (auto i : make_range(row_length))
351  {
352  indices[i] = row_indices[i];
353  values[i] = row_values[i];
354  }
355 }
356 
357 
358 
359 template <typename T>
361  SparseMatrix<T>(comm),
362  _destroy_mat_on_exit(true),
363  _use_transpose(false)
364 {}
365 
366 
367 
368 
369 template <typename T>
370 EpetraMatrix<T>::EpetraMatrix(Epetra_FECrsMatrix * m,
371  const Parallel::Communicator & comm) :
372  SparseMatrix<T>(comm),
373  _destroy_mat_on_exit(false),
374  _use_transpose(false) // dumb guess is the best we can do...
375 {
376  this->_mat = m;
377  this->_is_initialized = true;
378 }
379 
380 
381 
382 
383 template <typename T>
385 {
386  this->clear();
387 }
388 
389 
390 
391 template <typename T>
393 {
394  libmesh_assert(_mat);
395 
396  _mat->GlobalAssemble();
397 }
398 
399 
400 
401 template <typename T>
403 {
404  libmesh_assert (this->initialized());
405 
406  return static_cast<numeric_index_type>(_mat->NumGlobalRows());
407 }
408 
409 
410 
411 template <typename T>
413 {
414  libmesh_assert (this->initialized());
415 
416  return static_cast<numeric_index_type>(_mat->NumGlobalCols());
417 }
418 
419 
420 
421 template <typename T>
423 {
424  libmesh_assert (this->initialized());
425  libmesh_assert(_map);
426 
427  return static_cast<numeric_index_type>(_map->MinMyGID());
428 }
429 
430 
431 
432 template <typename T>
434 {
435  libmesh_assert (this->initialized());
436  libmesh_assert(_map);
437 
438  return static_cast<numeric_index_type>(_map->MaxMyGID())+1;
439 }
440 
441 
442 
443 template <typename T>
445 {
446  libmesh_assert (this->initialized());
447  libmesh_assert(_map);
448 
449  return static_cast<numeric_index_type>(_map->MinMyGID());
450 }
451 
452 
453 
454 template <typename T>
456 {
457  libmesh_assert (this->initialized());
458  libmesh_assert(_map);
459 
460  return static_cast<numeric_index_type>(_map->MaxMyGID())+1;
461 }
462 
463 
464 
465 template <typename T>
467  const numeric_index_type j,
468  const T value)
469 {
470  libmesh_assert (this->initialized());
471 
472  int
473  epetra_i = static_cast<int>(i),
474  epetra_j = static_cast<int>(j);
475 
476  T epetra_value = value;
477 
478  if (_mat->Filled())
479  _mat->ReplaceGlobalValues (epetra_i, 1, &epetra_value, &epetra_j);
480  else
481  _mat->InsertGlobalValues (epetra_i, 1, &epetra_value, &epetra_j);
482 }
483 
484 
485 
486 template <typename T>
488  const numeric_index_type j,
489  const T value)
490 {
491  libmesh_assert (this->initialized());
492 
493  int
494  epetra_i = static_cast<int>(i),
495  epetra_j = static_cast<int>(j);
496 
497  T epetra_value = value;
498 
499  _mat->SumIntoGlobalValues (epetra_i, 1, &epetra_value, &epetra_j);
500 }
501 
502 
503 
504 template <typename T>
506  const std::vector<numeric_index_type> & dof_indices)
507 {
508  this->add_matrix (dm, dof_indices, dof_indices);
509 }
510 
511 
512 
513 template <typename T>
514 void EpetraMatrix<T>::add (const T a_in, const SparseMatrix<T> & X_in)
515 {
516 #ifdef LIBMESH_TRILINOS_HAVE_EPETRAEXT
517  libmesh_assert (this->initialized());
518 
519  // sanity check. but this cannot avoid
520  // crash due to incompatible sparsity structure...
521  libmesh_assert_equal_to (this->m(), X_in.m());
522  libmesh_assert_equal_to (this->n(), X_in.n());
523 
524  const EpetraMatrix<T> * X =
525  cast_ptr<const EpetraMatrix<T> *> (&X_in);
526 
527  EpetraExt::MatrixMatrix::Add (*X->_mat, false, a_in, *_mat, 1.);
528 #else
529  libmesh_error_msg("ERROR: EpetraExt is required for EpetraMatrix::add()!");
530 #endif
531 }
532 
533 
534 
535 
536 template <typename T>
538  const numeric_index_type j) const
539 {
540  libmesh_assert (this->initialized());
541  libmesh_assert(this->_mat);
542  libmesh_assert (this->_mat->MyGlobalRow(static_cast<int>(i)));
543  libmesh_assert_greater_equal (i, this->row_start());
544  libmesh_assert_less (i, this->row_stop());
545 
546 
547  int row_length;
548  int * row_indices;
549  double * values;
550 
551  _mat->ExtractMyRowView (i-this->row_start(),
552  row_length,
553  values,
554  row_indices);
555 
556  //libMesh::out << "row_length=" << row_length << std::endl;
557 
558  int * index = std::lower_bound (row_indices, row_indices+row_length, j);
559 
560  libmesh_assert_less (*index, row_length);
561  libmesh_assert_equal_to (static_cast<numeric_index_type>(row_indices[*index]), j);
562 
563  //libMesh::out << "val=" << values[*index] << std::endl;
564 
565  return values[*index];
566 }
567 
568 
569 
570 
571 template <typename T>
573 {
574  libmesh_assert (this->initialized());
575  libmesh_assert(this->_mat);
576 
577  return this->_mat->Filled();
578 }
579 
580 
581 template <typename T>
583 {
584  std::swap(_mat, m._mat);
585  std::swap(_destroy_mat_on_exit, m._destroy_mat_on_exit);
586 }
587 
588 
589 
590 
591 
592 template <typename T>
593 void EpetraMatrix<T>::print_personal(std::ostream & os) const
594 {
595  libmesh_assert (this->initialized());
596  libmesh_assert(_mat);
597 
598  os << *_mat;
599 }
600 
601 
602 
603 //------------------------------------------------------------------
604 // Explicit instantiations
605 template class LIBMESH_EXPORT EpetraMatrix<Number>;
606 
607 } // namespace libMesh
608 
609 
610 #endif // LIBMESH_TRILINOS_HAVE_EPETRA
This class provides a nice interface to the Trilinos Epetra_Vector object.
virtual std::unique_ptr< SparseMatrix< T > > clone() const override
virtual numeric_index_type row_stop() const override
virtual void get_transpose(SparseMatrix< T > &dest) const override
Copies the transpose of the matrix into dest, which may be *this.
virtual void clear() noexcept override
clear() is called from the destructor, so it should not throw.
bool _destroy_mat_on_exit
This boolean value should only be set to false for the constructor which takes an Epetra_FECrsMatrix ...
Provides a uniform interface to vector storage schemes for different linear algebra libraries...
Definition: vector_fe_ex5.C:44
bool _use_transpose
Epetra has no GetUseTranspose so we need to keep track of whether we&#39;re transposed manually...
unsigned int m() const
virtual std::unique_ptr< SparseMatrix< T > > zero_clone() const override
The libMesh namespace provides an interface to certain functionality in the library.
virtual void init(const numeric_index_type m, const numeric_index_type n, const numeric_index_type m_l, const numeric_index_type n_l, const numeric_index_type nnz=30, const numeric_index_type noz=10, const numeric_index_type blocksize=1) override
Initialize SparseMatrix with the specified sizes.
virtual numeric_index_type col_stop() const override
virtual void get_row(numeric_index_type i, std::vector< numeric_index_type > &indices, std::vector< T > &values) const override
Get a row from the 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.
virtual numeric_index_type n() const override
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value) override
Set the element (i,j) to value.
Generic sparse matrix.
Definition: vector_fe_ex5.C:46
virtual numeric_index_type col_start() const override
dof_id_type numeric_index_type
Definition: id_types.h:99
bool _is_initialized
Flag that tells if init() has been called.
Definition: libmesh.C:257
bool _is_initialized
Flag indicating whether or not the matrix has been initialized.
virtual numeric_index_type m() const override
virtual numeric_index_type m() const =0
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
libmesh_assert(ctx)
std::vector< T > & get_values()
Definition: dense_matrix.h:382
virtual numeric_index_type row_start() const override
virtual void close() override
Calls the SparseMatrix&#39;s internal assembly routines, ensuring that the values are consistent across p...
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...
EpetraMatrix(const Parallel::Communicator &comm)
Constructor; initializes the matrix to be empty, without any structure, i.e.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual Real l1_norm() const override
virtual Real linfty_norm() const override
virtual void get_diagonal(NumericVector< T > &dest) const override
Copies the diagonal part of the matrix into dest.
virtual bool closed() const override
virtual void zero() override
Set all entries to 0.
static const bool value
Definition: xdr_io.C:54
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:140
bool initialized()
Checks that library initialization has been done.
Definition: libmesh.C:276
int * numeric_trilinos_cast(const numeric_index_type *p)
Epetra_FECrsMatrix * _mat
Actual Epetra datatype to hold matrix entries.
virtual void add(const numeric_index_type i, const numeric_index_type j, const T value) override
Add value to the element (i,j).
unsigned int n() const
Defines a dense matrix for use in Finite Element-type computations.
Definition: dof_map.h:75
void swap(EpetraMatrix< T > &)
Swaps the internal data pointers, no actual values are swapped.
This class provides a nice interface to the Epetra data structures for parallel, sparse matrices...
virtual T operator()(const numeric_index_type i, const numeric_index_type j) const override
virtual void update_sparsity_pattern(const SparsityPattern::Graph &) override
Updates the matrix sparsity pattern.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:117
virtual numeric_index_type n() const =0
ParallelType
Defines an enum for parallel data structure types.