libmesh解析
本工作只是尝试解析原libmesh的代码,供学习使用
全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 
eigen_sparse_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 
20 // Local includes
21 #include "libmesh/libmesh_config.h"
22 
23 #ifdef LIBMESH_HAVE_EIGEN
24 
25 #include "libmesh/eigen_sparse_vector.h"
26 #include "libmesh/eigen_sparse_matrix.h"
27 #include "libmesh/dense_matrix.h"
28 #include "libmesh/dof_map.h"
29 #include "libmesh/sparsity_pattern.h"
30 
31 // C++ Includes
32 #include <memory>
33 
34 
35 namespace libMesh
36 {
37 
38 
39 //-----------------------------------------------------------------------
40 // EigenSparseMatrix members
41 template <typename T>
43  const numeric_index_type n_in,
44  const numeric_index_type libmesh_dbg_var(m_l),
45  const numeric_index_type libmesh_dbg_var(n_l),
46  const numeric_index_type nnz,
47  const numeric_index_type,
48  const numeric_index_type)
49 {
50  // noz ignored... only used for multiple processors!
51  libmesh_assert_equal_to (m_in, m_l);
52  libmesh_assert_equal_to (n_in, n_l);
53  libmesh_assert_equal_to (m_in, n_in);
54  libmesh_assert_greater (nnz, 0);
55 
56  _mat.resize(m_in, n_in);
57  _mat.reserve(Eigen::Matrix<numeric_index_type, Eigen::Dynamic, 1>::Constant(m_in,nnz));
58 
59  this->_is_initialized = true;
60 }
61 
62 
63 
64 template <typename T>
65 void EigenSparseMatrix<T>::init (const ParallelType)
66 {
67  // Ignore calls on initialized objects
68  if (this->initialized())
69  return;
70 
71  // We need the DofMap for this!
72  libmesh_assert(this->_dof_map);
73 
74  // Clear initialized matrices
75  if (this->initialized())
76  this->clear();
77 
78  const numeric_index_type n_rows = this->_dof_map->n_dofs();
79  const numeric_index_type n_cols = n_rows;
80 
81 #ifndef NDEBUG
82  // The following variables are only used for assertions,
83  // so avoid declaring them when asserts are inactive.
84  const numeric_index_type n_l = this->_dof_map->n_dofs_on_processor(0);
85  const numeric_index_type m_l = n_l;
86 #endif
87 
88  // Laspack Matrices only work for uniprocessor cases
89  libmesh_assert_equal_to (n_rows, n_cols);
90  libmesh_assert_equal_to (m_l, n_rows);
91  libmesh_assert_equal_to (n_l, n_cols);
92 
93  const std::vector<numeric_index_type> & n_nz = this->_sp->get_n_nz();
94 
95 #ifndef NDEBUG
96  // The following variables are only used for assertions,
97  // so avoid declaring them when asserts are inactive.
98  const std::vector<numeric_index_type> & n_oz = this->_sp->get_n_oz();
99 #endif
100 
101  // Make sure the sparsity pattern isn't empty
102  libmesh_assert_equal_to (n_nz.size(), n_l);
103  libmesh_assert_equal_to (n_oz.size(), n_l);
104 
105  if (n_rows==0)
106  {
107  _mat.resize(0,0);
108  return;
109  }
110 
111  _mat.resize(n_rows,n_cols);
112  _mat.reserve(n_nz);
113 
114  this->_is_initialized = true;
115 
116  libmesh_assert_equal_to (n_rows, this->m());
117  libmesh_assert_equal_to (n_cols, this->n());
118 }
119 
120 
121 
122 template <typename T>
124  const std::vector<numeric_index_type> & rows,
125  const std::vector<numeric_index_type> & cols)
126 
127 {
128  libmesh_assert (this->initialized());
129  unsigned int n_rows = cast_int<unsigned int>(rows.size());
130  unsigned int n_cols = cast_int<unsigned int>(cols.size());
131  libmesh_assert_equal_to (dm.m(), n_rows);
132  libmesh_assert_equal_to (dm.n(), n_cols);
133 
134 
135  for (unsigned int i=0; i<n_rows; i++)
136  for (unsigned int j=0; j<n_cols; j++)
137  this->add(rows[i],cols[j],dm(i,j));
138 }
139 
140 
141 
142 template <typename T>
144 {
145  EigenSparseVector<T> & dest = cast_ref<EigenSparseVector<T> &>(dest_in);
146 
147  dest._vec = _mat.diagonal();
148 }
149 
150 
151 
152 template <typename T>
154 {
155  EigenSparseMatrix<T> & dest = cast_ref<EigenSparseMatrix<T> &>(dest_in);
156 
157  dest._mat = _mat.transpose();
158 }
159 
160 
161 
162 template <typename T>
163 EigenSparseMatrix<T>::EigenSparseMatrix (const Parallel::Communicator & comm_in) :
164  SparseMatrix<T>(comm_in),
165  _closed (false)
166 {
167 }
168 
169 
170 
171 template <typename T>
173 {
174  _mat.resize(0,0);
175 
176  _closed = false;
177  this->_is_initialized = false;
178 }
179 
180 
181 
182 template <typename T>
184 {
185  // This doesn't just zero, it clears the entire non-zero structure!
186  _mat.setZero();
187 
188  if (this->_sp)
189  {
190  // Re-reserve our non-zero structure
191  const std::vector<numeric_index_type> & n_nz = this->_sp->get_n_nz();
192  _mat.reserve(n_nz);
193  }
194 }
195 
196 
197 
198 template <typename T>
199 std::unique_ptr<SparseMatrix<T>> EigenSparseMatrix<T>::zero_clone () const
200 {
201  // TODO: If there is a more efficient way to make a zeroed-out copy
202  // of an EigenSM, we should call that instead.
203  auto ret = std::make_unique<EigenSparseMatrix<T>>(*this);
204  ret->zero();
205 
206  // Work around an issue on older compilers. We are able to simply
207  // "return ret;" on newer compilers
208  return std::unique_ptr<SparseMatrix<T>>(ret.release());
209 }
210 
211 
212 
213 template <typename T>
214 std::unique_ptr<SparseMatrix<T>> EigenSparseMatrix<T>::clone () const
215 {
216  return std::make_unique<EigenSparseMatrix<T>>(*this);
217 }
218 
219 
220 
221 template <typename T>
223 {
224  libmesh_assert (this->initialized());
225 
226  return cast_int<numeric_index_type>(_mat.rows());
227 }
228 
229 
230 
231 template <typename T>
233 {
234  libmesh_assert (this->initialized());
235 
236  return cast_int<numeric_index_type>(_mat.cols());
237 }
238 
239 
240 
241 template <typename T>
243 {
244  return 0;
245 }
246 
247 
248 
249 template <typename T>
251 {
252  return this->m();
253 }
254 
255 
256 
257 template <typename T>
259  const numeric_index_type j,
260  const T value)
261 {
262  libmesh_assert (this->initialized());
263  libmesh_assert_less (i, this->m());
264  libmesh_assert_less (j, this->n());
265 
266  _mat.coeffRef(i,j) = value;
267 }
268 
269 
270 
271 template <typename T>
273  const numeric_index_type j,
274  const T value)
275 {
276  libmesh_assert (this->initialized());
277  libmesh_assert_less (i, this->m());
278  libmesh_assert_less (j, this->n());
279 
280  _mat.coeffRef(i,j) += value;
281 }
282 
283 
284 
285 template <typename T>
287  const std::vector<numeric_index_type> & dof_indices)
288 {
289  this->add_matrix (dm, dof_indices, dof_indices);
290 }
291 
292 
293 
294 template <typename T>
295 void EigenSparseMatrix<T>::add (const T a_in, const SparseMatrix<T> & X_in)
296 {
297  libmesh_assert (this->initialized());
298  libmesh_assert_equal_to (this->m(), X_in.m());
299  libmesh_assert_equal_to (this->n(), X_in.n());
300 
301  const EigenSparseMatrix<T> & X =
302  cast_ref<const EigenSparseMatrix<T> &> (X_in);
303 
304  _mat += X._mat*a_in;
305 }
306 
307 
308 
309 
310 template <typename T>
312  const numeric_index_type j) const
313 {
314  libmesh_assert (this->initialized());
315  libmesh_assert_less (i, this->m());
316  libmesh_assert_less (j, this->n());
317 
318  return _mat.coeff(i,j);
319 }
320 
321 
322 
323 template <typename T>
325 {
326  // There does not seem to be a straightforward way to iterate over
327  // the columns of an EigenSparseMatrix. So we use some extra
328  // storage and keep track of the column sums while going over the
329  // row entries...
330  std::vector<Real> abs_col_sums(this->n());
331 
332  // For a row-major Eigen SparseMatrix like we're using, the
333  // InnerIterator iterates over the non-zero entries of rows.
334  for (auto row : make_range(this->m()))
335  {
336  EigenSM::InnerIterator it(_mat, row);
337  for (; it; ++it)
338  abs_col_sums[it.col()] += std::abs(it.value());
339  }
340 
341  return *(std::max_element(abs_col_sums.begin(), abs_col_sums.end()));
342 }
343 
344 
345 
346 template <typename T>
348 {
349  Real max_abs_row_sum = 0.;
350 
351  // For a row-major Eigen SparseMatrix like we're using, the
352  // InnerIterator iterates over the non-zero entries of rows.
353  for (auto row : make_range(this->m()))
354  {
355  Real current_abs_row_sum = 0.;
356  EigenSM::InnerIterator it(_mat, row);
357  for (; it; ++it)
358  current_abs_row_sum += std::abs(it.value());
359 
360  max_abs_row_sum = std::max(max_abs_row_sum, current_abs_row_sum);
361  }
362 
363  return max_abs_row_sum;
364 }
365 
366 
367 //------------------------------------------------------------------
368 // Explicit instantiations
369 template class LIBMESH_EXPORT EigenSparseMatrix<Number>;
370 
371 } // namespace libMesh
372 
373 
374 #endif // #ifdef LIBMESH_HAVE_EIGEN
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value) override
设置元素 (i,j) 为 value .
EigenSparseMatrix 类包装了来自 Eigen 库的稀疏矩阵对象。
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
使用指定的大小初始化 SparseMatrix。
virtual void add(const numeric_index_type i, const numeric_index_type j, const T value) override
将 value 添加到元素 (i,j) .
virtual numeric_index_type m() const override
unsigned int n() const
返回矩阵的列维度。
virtual numeric_index_type row_stop() const override
DataType _vec
Actual Eigen::SparseVector&lt;&gt; we are wrapping.
virtual std::unique_ptr< SparseMatrix< T > > clone() const override
提供了不同线性代数库的向量存储方案的统一接口。
Definition: dof_map.h:67
DataType _mat
实际的 Eigen::SparseMatrix&lt;&gt; 对象。
virtual void get_transpose(SparseMatrix< T > &dest) const override
将矩阵的转置复制到 dest 中,dest 可能是 *this。
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
计算自动微分实数向量的绝对值。
Definition: type_vector.h:112
这是一个通用的稀疏矩阵类。该类包含了必须在派生类中覆盖的纯虚拟成员。 使用一个公共的基类允许从不同的求解器包中以不同的格式统一访问稀疏矩阵。
Definition: dof_map.h:66
virtual void zero() override
将所有条目设置为 0。
virtual numeric_index_type n() const override
virtual void get_diagonal(NumericVector< T > &dest) const override
复制矩阵的对角线部分到 dest。
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
返回矩阵的行维度。
EigenSparseMatrix(const Parallel::Communicator &comm)
构造函数;初始化矩阵为空,没有任何结构,即矩阵无法使用。
virtual numeric_index_type m() const =0
virtual T operator()(const numeric_index_type i, const numeric_index_type j) const override
virtual numeric_index_type row_start() const override
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual Real linfty_norm() const override
获取矩阵的 -范数,即最大行和:
virtual void clear() override
恢复 SparseMatrix&lt;T&gt; 到原始状态。
bool initialized()
Checks that library initialization has been done.
Definition: libmesh.C:261
virtual std::unique_ptr< SparseMatrix< T > > zero_clone() const override
virtual Real l1_norm() const override
获取矩阵的 -范数,即最大列和:
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
This class provides a nice interface to the Eigen C++-based data structures for serial vectors...
virtual numeric_index_type n() const =0
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols) override
将完整矩阵 dm 添加到 SparseMatrix。这对于在装配时添加元素矩阵很有用。