libMesh
Loading...
Searching...
No Matches
trilinos_epetra_matrix.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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
33namespace libMesh
34{
35
36
37
38//-----------------------------------------------------------------------
39//EpetraMatrix members
40
41template <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
120template <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
176template <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
195template <typename T>
197{
198 libmesh_assert (this->initialized());
199
200 _mat->Scale(0.0);
201}
202
203
204
205template <typename T>
206std::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
222template <typename T>
223std::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
235template <typename T>
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
248template <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
260template <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
273template <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
296template <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
308template <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
327template <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
359template <typename T>
361 SparseMatrix<T>(comm),
362 _destroy_mat_on_exit(true),
363 _use_transpose(false)
364{}
365
366
367
368
369template <typename T>
370EpetraMatrix<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
383template <typename T>
385{
386 this->clear();
387}
388
389
390
391template <typename T>
393{
394 libmesh_assert(_mat);
395
396 _mat->GlobalAssemble();
397}
398
399
400
401template <typename T>
403{
404 libmesh_assert (this->initialized());
405
406 return static_cast<numeric_index_type>(_mat->NumGlobalRows());
407}
408
409
410
411template <typename T>
413{
414 libmesh_assert (this->initialized());
415
416 return static_cast<numeric_index_type>(_mat->NumGlobalCols());
417}
418
419
420
421template <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
432template <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
443template <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
454template <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
465template <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
486template <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
504template <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
513template <typename T>
514void 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
536template <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
571template <typename T>
573{
574 libmesh_assert (this->initialized());
575 libmesh_assert(this->_mat);
576
577 return this->_mat->Filled();
578}
579
580
581template <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
592template <typename T>
593void 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
605template class LIBMESH_EXPORT EpetraMatrix<Number>;
606
607} // namespace libMesh
608
609
610#endif // LIBMESH_TRILINOS_HAVE_EPETRA
Defines a dense matrix for use in Finite Element-type computations.
std::vector< T > & get_values()
This class provides a nice interface to the Epetra data structures for parallel, sparse matrices.
virtual void close() override
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
virtual void update_sparsity_pattern(const SparsityPattern::Graph &) override
Updates the matrix sparsity pattern.
virtual numeric_index_type col_stop() const override
void swap(EpetraMatrix< T > &)
Swaps the internal data pointers, no actual values are swapped.
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value) override
Set the element (i,j) to value.
virtual std::unique_ptr< SparseMatrix< T > > zero_clone() const override
virtual T operator()(const numeric_index_type i, const numeric_index_type j) const override
virtual Real linfty_norm() const override
bool _use_transpose
Epetra has no GetUseTranspose so we need to keep track of whether we're transposed manually.
virtual numeric_index_type m() 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 zero() override
Set all entries to 0.
virtual bool closed() const override
Epetra_FECrsMatrix * _mat
Actual Epetra datatype to hold matrix entries.
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.
virtual void add(const numeric_index_type i, const numeric_index_type j, const T value) override
Add value to the element (i,j).
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 numeric_index_type row_start() const override
virtual void get_diagonal(NumericVector< T > &dest) const override
Copies the diagonal part of the matrix into dest.
virtual Real l1_norm() const override
virtual numeric_index_type col_start() const override
virtual numeric_index_type row_stop() const override
virtual numeric_index_type n() const override
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 std::unique_ptr< SparseMatrix< T > > clone() const override
EpetraMatrix(const Parallel::Communicator &comm)
Constructor; initializes the matrix to be empty, without any structure, i.e.
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 ...
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.
This class provides a nice interface to the Trilinos Epetra_Vector object.
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
Generic sparse matrix.
virtual numeric_index_type n() const =0
virtual numeric_index_type m() const =0
bool _is_initialized
Flag indicating whether or not the matrix has been initialized.
const Elem & get(const ElemType type_in)
The libMesh namespace provides an interface to certain functionality in the library.
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:153
ParallelType
Defines an enum for parallel data structure types.
libmesh_assert(ctx)
dof_id_type numeric_index_type
Definition id_types.h:99
bool initialized()
Checks that library initialization has been done.
Definition libmesh.C:324
int * numeric_trilinos_cast(const numeric_index_type *p)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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:176
static const bool value
Definition xdr_io.C:55