libmesh解析
本工作只是尝试解析原libmesh的代码,供学习使用
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 
trilinos_epetra_matrix.C
浏览该文件的文档.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2023 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->_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>
177 void EpetraMatrix<T>::init (const ParallelType)
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  // Work around an issue on older compilers. We are able to simply
218  // "return mat_copy;" on newer compilers
219  return std::unique_ptr<SparseMatrix<T>>(mat_copy.release());
220 }
221 
222 
223 
224 template <typename T>
225 std::unique_ptr<SparseMatrix<T>> EpetraMatrix<T>::clone () const
226 {
227  // We don't currently have a faster implementation than making a
228  // zero clone and then filling in the values.
229  auto mat_copy = this->zero_clone();
230  mat_copy->add(1., *this);
231 
232  // Work around an issue on older compilers. We are able to simply
233  // "return mat_copy;" on newer compilers
234  return std::unique_ptr<SparseMatrix<T>>(mat_copy.release());
235 }
236 
237 
238 
239 template <typename T>
240 void EpetraMatrix<T>::clear () noexcept
241 {
242  // FIXME: clear() doesn't actually free the memory managed by this
243  // class, so it probably leaks memory.
244  // delete _mat;
245  // delete _map;
246 
247  this->_is_initialized = false;
248 }
249 
250 
251 
252 template <typename T>
254 {
255  libmesh_assert (this->initialized());
256 
257  libmesh_assert(_mat);
258 
259  return static_cast<Real>(_mat->NormOne());
260 }
261 
262 
263 
264 template <typename T>
266 {
267  libmesh_assert (this->initialized());
268 
269 
270  libmesh_assert(_mat);
271 
272  return static_cast<Real>(_mat->NormInf());
273 }
274 
275 
276 
277 template <typename T>
279  const std::vector<numeric_index_type> & rows,
280  const std::vector<numeric_index_type> & cols)
281 {
282  libmesh_assert (this->initialized());
283 
284  const numeric_index_type m = dm.m();
285  const numeric_index_type n = dm.n();
286 
287  libmesh_assert_equal_to (rows.size(), m);
288  libmesh_assert_equal_to (cols.size(), n);
289 
290  _mat->SumIntoGlobalValues(m, numeric_trilinos_cast(rows.data()),
291  n, numeric_trilinos_cast(cols.data()),
292  dm.get_values().data());
293 }
294 
295 
296 
297 
298 
299 
300 template <typename T>
302 {
303  // Convert vector to EpetraVector.
304  EpetraVector<T> * epetra_dest = cast_ptr<EpetraVector<T> *>(&dest);
305 
306  // Call Epetra function.
307  _mat->ExtractDiagonalCopy(*(epetra_dest->vec()));
308 }
309 
310 
311 
312 template <typename T>
314 {
315  // Make sure the SparseMatrix passed in is really a EpetraMatrix
316  EpetraMatrix<T> & epetra_dest = cast_ref<EpetraMatrix<T> &>(dest);
317 
318  // We currently only support calling get_transpose() with ourself
319  // as the destination. Previously, this called the default copy
320  // constructor which was not safe because this class manually
321  // manages memory.
322  if (&epetra_dest != this)
323  libmesh_not_implemented();
324 
325  epetra_dest._use_transpose = !epetra_dest._use_transpose;
326  epetra_dest._mat->SetUseTranspose(epetra_dest._use_transpose);
327 }
328 
329 
330 
331 template <typename T>
332 EpetraMatrix<T>::EpetraMatrix(const Parallel::Communicator & comm) :
333  SparseMatrix<T>(comm),
334  _destroy_mat_on_exit(true),
335  _use_transpose(false)
336 {}
337 
338 
339 
340 
341 template <typename T>
342 EpetraMatrix<T>::EpetraMatrix(Epetra_FECrsMatrix * m,
343  const Parallel::Communicator & comm) :
344  SparseMatrix<T>(comm),
345  _destroy_mat_on_exit(false),
346  _use_transpose(false) // dumb guess is the best we can do...
347 {
348  this->_mat = m;
349  this->_is_initialized = true;
350 }
351 
352 
353 
354 
355 template <typename T>
357 {
358  this->clear();
359 }
360 
361 
362 
363 template <typename T>
365 {
366  libmesh_assert(_mat);
367 
368  _mat->GlobalAssemble();
369 }
370 
371 
372 
373 template <typename T>
375 {
376  libmesh_assert (this->initialized());
377 
378  return static_cast<numeric_index_type>(_mat->NumGlobalRows());
379 }
380 
381 
382 
383 template <typename T>
385 {
386  libmesh_assert (this->initialized());
387 
388  return static_cast<numeric_index_type>(_mat->NumGlobalCols());
389 }
390 
391 
392 
393 template <typename T>
395 {
396  libmesh_assert (this->initialized());
397  libmesh_assert(_map);
398 
399  return static_cast<numeric_index_type>(_map->MinMyGID());
400 }
401 
402 
403 
404 template <typename T>
406 {
407  libmesh_assert (this->initialized());
408  libmesh_assert(_map);
409 
410  return static_cast<numeric_index_type>(_map->MaxMyGID())+1;
411 }
412 
413 
414 
415 template <typename T>
417  const numeric_index_type j,
418  const T value)
419 {
420  libmesh_assert (this->initialized());
421 
422  int
423  epetra_i = static_cast<int>(i),
424  epetra_j = static_cast<int>(j);
425 
426  T epetra_value = value;
427 
428  if (_mat->Filled())
429  _mat->ReplaceGlobalValues (epetra_i, 1, &epetra_value, &epetra_j);
430  else
431  _mat->InsertGlobalValues (epetra_i, 1, &epetra_value, &epetra_j);
432 }
433 
434 
435 
436 template <typename T>
438  const numeric_index_type j,
439  const T value)
440 {
441  libmesh_assert (this->initialized());
442 
443  int
444  epetra_i = static_cast<int>(i),
445  epetra_j = static_cast<int>(j);
446 
447  T epetra_value = value;
448 
449  _mat->SumIntoGlobalValues (epetra_i, 1, &epetra_value, &epetra_j);
450 }
451 
452 
453 
454 template <typename T>
456  const std::vector<numeric_index_type> & dof_indices)
457 {
458  this->add_matrix (dm, dof_indices, dof_indices);
459 }
460 
461 
462 
463 template <typename T>
464 void EpetraMatrix<T>::add (const T a_in, const SparseMatrix<T> & X_in)
465 {
466 #ifdef LIBMESH_TRILINOS_HAVE_EPETRAEXT
467  libmesh_assert (this->initialized());
468 
469  // sanity check. but this cannot avoid
470  // crash due to incompatible sparsity structure...
471  libmesh_assert_equal_to (this->m(), X_in.m());
472  libmesh_assert_equal_to (this->n(), X_in.n());
473 
474  const EpetraMatrix<T> * X =
475  cast_ptr<const EpetraMatrix<T> *> (&X_in);
476 
477  EpetraExt::MatrixMatrix::Add (*X->_mat, false, a_in, *_mat, 1.);
478 #else
479  libmesh_error_msg("ERROR: EpetraExt is required for EpetraMatrix::add()!");
480 #endif
481 }
482 
483 
484 
485 
486 template <typename T>
488  const numeric_index_type j) const
489 {
490  libmesh_assert (this->initialized());
491  libmesh_assert(this->_mat);
492  libmesh_assert (this->_mat->MyGlobalRow(static_cast<int>(i)));
493  libmesh_assert_greater_equal (i, this->row_start());
494  libmesh_assert_less (i, this->row_stop());
495 
496 
497  int row_length;
498  int * row_indices;
499  double * values;
500 
501  _mat->ExtractMyRowView (i-this->row_start(),
502  row_length,
503  values,
504  row_indices);
505 
506  //libMesh::out << "row_length=" << row_length << std::endl;
507 
508  int * index = std::lower_bound (row_indices, row_indices+row_length, j);
509 
510  libmesh_assert_less (*index, row_length);
511  libmesh_assert_equal_to (static_cast<numeric_index_type>(row_indices[*index]), j);
512 
513  //libMesh::out << "val=" << values[*index] << std::endl;
514 
515  return values[*index];
516 }
517 
518 
519 
520 
521 template <typename T>
523 {
524  libmesh_assert (this->initialized());
525  libmesh_assert(this->_mat);
526 
527  return this->_mat->Filled();
528 }
529 
530 
531 template <typename T>
533 {
534  std::swap(_mat, m._mat);
535  std::swap(_destroy_mat_on_exit, m._destroy_mat_on_exit);
536 }
537 
538 
539 
540 
541 
542 template <typename T>
543 void EpetraMatrix<T>::print_personal(std::ostream & os) const
544 {
545  libmesh_assert (this->initialized());
546  libmesh_assert(_mat);
547 
548  os << *_mat;
549 }
550 
551 
552 
553 //------------------------------------------------------------------
554 // Explicit instantiations
555 template class LIBMESH_EXPORT EpetraMatrix<Number>;
556 
557 } // namespace libMesh
558 
559 
560 #endif // LIBMESH_TRILINOS_HAVE_EPETRA
此类提供了对Trilinos Epetra_Vector对象的友好接口。所有重写的虚拟函数在numeric_vector.h中都有文档。
virtual ~EpetraMatrix()
析构函数
virtual std::unique_ptr< SparseMatrix< T > > clone() const override
创建矩阵克隆。
virtual numeric_index_type row_stop() const override
获取本地行索引的结束位置。
unsigned int n() const
返回矩阵的列维度。
virtual void get_transpose(SparseMatrix< T > &dest) const override
获取矩阵的转置。
bool _destroy_mat_on_exit
在接口函数中是否销毁_mat。
virtual void update_sparsity_pattern(const SparsityPattern::Graph &graph) override
更新矩阵的稀疏性模式。这将告诉底层矩阵存储方案如何映射(i,j)元素。
提供了不同线性代数库的向量存储方案的统一接口。
Definition: dof_map.h:67
bool _use_transpose
手动跟踪是否手动进行了转置。
virtual std::unique_ptr< SparseMatrix< T > > zero_clone() const override
创建零克隆矩阵。
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
初始化矩阵。
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols) override
添加稀疏矩阵的元素值。
virtual numeric_index_type n() const override
获取全局列数。
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value) override
设置矩阵元素值。
这是一个通用的稀疏矩阵类。该类包含了必须在派生类中覆盖的纯虚拟成员。 使用一个公共的基类允许从不同的求解器包中以不同的格式统一访问稀疏矩阵。
Definition: dof_map.h:66
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:242
unsigned int m() const
返回矩阵的行维度。
bool _is_initialized
标志,指示矩阵是否已初始化。
virtual numeric_index_type m() const override
获取全局行数。
virtual numeric_index_type m() const =0
void swap(EpetraMatrix< T > &other)
交换内部数据指针,不交换实际值。
std::vector< T > & get_values()
返回对应于存储向量的引用的底层数据存储矢量。
Definition: dense_matrix.h:488
virtual numeric_index_type row_start() const override
获取本地行索引的起始位置。
virtual void close() override
关闭矩阵,使其无法再次修改。
virtual void print_personal(std::ostream &os=libMesh::out) const override
打印矩阵的个性化信息。
EpetraMatrix(const Parallel::Communicator &comm)
构造函数; 初始化矩阵为空,没有任何结构。矩阵不可用。仅用于成员类的矩阵。 所有其他矩阵应在所有必要信息都可用的数据流的某个点创建。
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual Real l1_norm() const override
获取矩阵的L1范数。
virtual Real linfty_norm() const override
获取矩阵的L∞范数。
virtual void get_diagonal(NumericVector< T > &dest) const override
获取矩阵的对角线元素。
virtual bool closed() const override
检查矩阵是否已关闭。
virtual void zero() override
将矩阵元素设置为零。
virtual void clear() noexceptoverride
清除矩阵。
bool initialized()
Checks that library initialization has been done.
Definition: libmesh.C:261
int * numeric_trilinos_cast(const numeric_index_type *p)
Epetra_FECrsMatrix * _mat
实际Epetra数据类型来保存矩阵条目。
virtual void add(const numeric_index_type i, const numeric_index_type j, const T value) override
添加矩阵元素值。
Epetra_Vector * vec()
返回原始的 Epetra_Vector 指针。
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
此类提供了对Epetra数据结构的并行、稀疏矩阵的友好接口。所有重写的虚拟函数在sparse_matrix.h中都有文档。
virtual T operator()(const numeric_index_type i, const numeric_index_type j) const override
获取矩阵元素值。
virtual numeric_index_type n() const =0