libmesh解析
本工作只是尝试解析原libmesh的代码,供学习使用
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 
dense_matrix_impl.h
浏览该文件的文档.
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 #ifndef LIBMESH_DENSE_MATRIX_IMPL_H
20 #define LIBMESH_DENSE_MATRIX_IMPL_H
21 
22 // C++ Includes
23 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
24 #include <cmath> // for sqrt
25 
26 // Local Includes
27 #include "libmesh/dense_matrix.h"
28 #include "libmesh/dense_vector.h"
29 #include "libmesh/int_range.h"
30 #include "libmesh/libmesh.h"
31 
32 #ifdef LIBMESH_HAVE_METAPHYSICL
33 #include "metaphysicl/dualnumber_decl.h"
34 #endif
35 
36 namespace libMesh
37 {
38 
39 
40 
41 // ------------------------------------------------------------
42 // Dense Matrix 成员函数
43 
50 template<typename T>
52 {
53  if (this->use_blas_lapack)
54  this->_multiply_blas(M2, LEFT_MULTIPLY);
55  else
56  {
57  // M3 是 *this 调整大小之前的副本
58  DenseMatrix<T> M3(*this);
59 
60  // 调整 *this 的大小以适应结果
61  this->resize(M2.m(), M3.n());
62 
63  // 在基类中调用乘法函数
64  this->multiply(*this, M2, M3);
65  }
66 }
67 
74 template<typename T>
75 template<typename T2>
77 {
78  // M3 是 *this 调整大小之前的副本
79  DenseMatrix<T> M3(*this);
80 
81  // 调整 *this 的大小以适应结果
82  this->resize(M2.m(), M3.n());
83 
84  // 在基类中调用乘法函数
85  this->multiply(*this, M2, M3);
86 }
87 
95 template<typename T>
97 {
98  if (this->use_blas_lapack)
99  this->_multiply_blas(A, LEFT_MULTIPLY_TRANSPOSE);
100  else
101  this->_left_multiply_transpose(A);
102 }
103 
109 template<typename T>
110 template<typename T2>
112 {
113  this->_left_multiply_transpose(A);
114 }
115 
123 template<typename T>
124 template<typename T2>
126 {
127  // 检查是否正在执行 (A^T)*A
128  if (this == &A)
129  {
130  // 复制 *this 的副本
131  DenseMatrix<T> B(*this);
132 
133  // 简单但低效的方式
134  // 返回 this->left_multiply_transpose(B);
135 
136  // 更有效,但代码更多的方式
137  // 如果 A 是 mxn,则结果将是大小为 n x n 的方阵。
138  const unsigned int n_rows = A.m();
139  const unsigned int n_cols = A.n();
140 
141  // 调整 *this 的大小并将所有条目清零。
142  this->resize(n_cols, n_cols);
143 
144  // 计算下三角部分
145  for (unsigned int i = 0; i < n_cols; ++i)
146  for (unsigned int j = 0; j <= i; ++j)
147  for (unsigned int k = 0; k < n_rows; ++k) // 内积在 n_rows 上
148  (*this)(i, j) += B(k, i) * B(k, j);
149 
150  // 将下三角部分复制到上三角部分
151  for (unsigned int i = 0; i < n_cols; ++i)
152  for (unsigned int j = i + 1; j < n_cols; ++j)
153  (*this)(i, j) = (*this)(j, i);
154  }
155  else
156  {
157  DenseMatrix<T> B(*this);
158 
159  this->resize(A.n(), B.n());
160 
161  libmesh_assert_equal_to(A.m(), B.m());
162  libmesh_assert_equal_to(this->m(), A.n());
163  libmesh_assert_equal_to(this->n(), B.n());
164 
165  const unsigned int m_s = A.n();
166  const unsigned int p_s = A.m();
167  const unsigned int n_s = this->n();
168 
169  // 以这种方式执行是因为
170  // 很大的机会(至少对于约束矩阵而言)
171  // A.transpose(i,k) = 0。
172  for (unsigned int i = 0; i < m_s; i++)
173  for (unsigned int k = 0; k < p_s; k++)
174  if (A.transpose(i, k) != 0.)
175  for (unsigned int j = 0; j < n_s; j++)
176  (*this)(i, j) += A.transpose(i, k) * B(k, j);
177  }
178 }
179 
187 template<typename T>
189 {
190  if (this->use_blas_lapack)
191  this->_multiply_blas(M3, RIGHT_MULTIPLY);
192  else
193  {
194  // M2 是 *this 调整大小之前的副本
195  DenseMatrix<T> M2(*this);
196 
197  // 调整 *this 的大小以适应结果
198  this->resize(M2.m(), M3.n());
199 
200  this->multiply(*this, M2, M3);
201  }
202 }
203 
211 template<typename T>
212 template<typename T2>
214 {
215  // M2 是 *this 调整大小之前的副本
216  DenseMatrix<T> M2(*this);
217 
218  // 调整 *this 的大小以适应结果
219  this->resize(M2.m(), M3.n());
220 
221  this->multiply(*this, M2, M3);
222 }
223 
231 template<typename T>
233 {
234  if (this->use_blas_lapack)
235  this->_multiply_blas(B, RIGHT_MULTIPLY_TRANSPOSE);
236  else
237  this->_right_multiply_transpose(B);
238 }
239 
245 template<typename T>
246 template<typename T2>
248 {
249  this->_right_multiply_transpose(B);
250 }
251 
259 template<typename T>
260 template<typename T2>
262 {
263  // 检查是否正在执行 B*(B^T)
264  if (this == &B)
265  {
266  // 复制 *this 的副本
267  DenseMatrix<T> A(*this);
268 
269  // 简单但低效的方式
270  // 返回 this->right_multiply_transpose(A);
271 
272  // 更有效,但代码更多的方式
273  // 如果 B 是 mxn,则结果将是大小为 m x m 的方阵。
274  const unsigned int n_rows = B.m();
275  const unsigned int n_cols = B.n();
276 
277  // 调整 *this 的大小并将所有条目清零。
278  this->resize(n_rows, n_rows);
279 
280  // 计算下三角部分
281  for (unsigned int i = 0; i < n_rows; ++i)
282  for (unsigned int j = 0; j <= i; ++j)
283  for (unsigned int k = 0; k < n_cols; ++k) // 内积在 n_cols 上
284  (*this)(i, j) += A(i, k) * A(j, k);
285 
286  // 将下三角部分复制到上三角部分
287  for (unsigned int i = 0; i < n_rows; ++i)
288  for (unsigned int j = i + 1; j < n_rows; ++j)
289  (*this)(i, j) = (*this)(j, i);
290  }
291  else
292  {
293  DenseMatrix<T> A(*this);
294 
295  this->resize(A.m(), B.m());
296 
297  libmesh_assert_equal_to(A.n(), B.n());
298  libmesh_assert_equal_to(this->m(), A.m());
299  libmesh_assert_equal_to(this->n(), B.m());
300 
301  const unsigned int m_s = A.m();
302  const unsigned int p_s = A.n();
303  const unsigned int n_s = this->n();
304 
305  // 以这种方式执行是因为
306  // 很多情况下(至少对于约束矩阵而言)B.transpose(k,j) = 0
307  for (unsigned int j = 0; j < n_s; j++)
308  for (unsigned int k = 0; k < p_s; k++)
309  if (B.transpose(k, j) != 0.)
310  for (unsigned int i = 0; i < m_s; i++)
311  (*this)(i, j) += A(i, k) * B.transpose(k, j);
312  }
313 }
314 
315 
325 template<typename T>
327 {
328  // 确保输入大小兼容
329  libmesh_assert_equal_to(this->n(), arg.size());
330 
331  // 调整并清除 dest
332  // 注意:DenseVector::resize() 也会将向量清零
333  dest.resize(this->m());
334 
335  // 如果矩阵为空,直接返回
336  if (this->m() == 0 || this->n() == 0)
337  return;
338 
339  if (this->use_blas_lapack)
340  this->_matvec_blas(1., 0., dest, arg);
341  else
342  {
343  const unsigned int n_rows = this->m();
344  const unsigned int n_cols = this->n();
345 
346  for (unsigned int i = 0; i < n_rows; i++)
347  for (unsigned int j = 0; j < n_cols; j++)
348  dest(i) += (*this)(i, j) * arg(j);
349  }
350 }
351 
358 template<typename T>
359 template<typename T2>
360 void DenseMatrix<T>::vector_mult(DenseVector<typename CompareTypes<T, T2>::supertype> & dest,
361  const DenseVector<T2> & arg) const
362 {
363  // 确保输入大小兼容
364  libmesh_assert_equal_to(this->n(), arg.size());
365 
366  // 调整并清除 dest
367  // 注意:DenseVector::resize() 也会将向量清零
368  dest.resize(this->m());
369 
370  // 如果矩阵为空,直接返回
371  if (this->m() == 0 || this->n() == 0)
372  return;
373 
374  const unsigned int n_rows = this->m();
375  const unsigned int n_cols = this->n();
376 
377  for (unsigned int i = 0; i < n_rows; i++)
378  for (unsigned int j = 0; j < n_cols; j++)
379  dest(i) += (*this)(i, j) * arg(j);
380 }
381 
391 template<typename T>
393  const DenseVector<T> & arg) const
394 {
395  // 确保输入大小兼容
396  libmesh_assert_equal_to(this->m(), arg.size());
397 
398  // 调整并清除 dest
399  // 注意:DenseVector::resize() 也会将向量清零
400  dest.resize(this->n());
401 
402  // 如果矩阵为空,直接返回
403  if (this->m() == 0)
404  return;
405 
406  if (this->use_blas_lapack)
407  {
408  this->_matvec_blas(1., 0., dest, arg, /*trans=*/true);
409  }
410  else
411  {
412  const unsigned int n_rows = this->m();
413  const unsigned int n_cols = this->n();
414 
415  // WORKS
416  // for (unsigned int j=0; j<n_cols; j++)
417  // for (unsigned int i=0; i<n_rows; i++)
418  // dest(j) += (*this)(i,j)*arg(i);
419 
420  // ALSO WORKS, (i,j) just swapped
421  for (unsigned int i = 0; i < n_cols; i++)
422  for (unsigned int j = 0; j < n_rows; j++)
423  dest(i) += (*this)(j, i) * arg(j);
424  }
425 }
426 
433 template<typename T>
434 template<typename T2>
435 void DenseMatrix<T>::vector_mult_transpose(DenseVector<typename CompareTypes<T, T2>::supertype> & dest,
436  const DenseVector<T2> & arg) const
437 {
438  // 确保输入大小兼容
439  libmesh_assert_equal_to(this->m(), arg.size());
440 
441  // 调整并清除 dest
442  // 注意:DenseVector::resize() 也会将向量清零
443  dest.resize(this->n());
444 
445  // 如果矩阵为空,直接返回
446  if (this->m() == 0)
447  return;
448 
449  const unsigned int n_rows = this->m();
450  const unsigned int n_cols = this->n();
451 
452  // WORKS
453  // for (unsigned int j=0; j<n_cols; j++)
454  // for (unsigned int i=0; i<n_rows; i++)
455  // dest(j) += (*this)(i,j)*arg(i);
456 
457  // ALSO WORKS, (i,j) just swapped
458  for (unsigned int i = 0; i < n_cols; i++)
459  for (unsigned int j = 0; j < n_rows; j++)
460  dest(i) += (*this)(j, i) * arg(j);
461 }
462 
472 template<typename T>
474  const T factor,
475  const DenseVector<T> & arg) const
476 {
477  // 如果矩阵为空,直接返回
478  if (this->m() == 0)
479  {
480  dest.resize(0);
481  return;
482  }
483 
484  if (this->use_blas_lapack)
485  this->_matvec_blas(factor, 1., dest, arg);
486  else
487  {
488  DenseVector<T> temp(arg.size());
489  this->vector_mult(temp, arg);
490  dest.add(factor, temp);
491  }
492 }
493 
503 template<typename T>
504 template<typename T2, typename T3>
505 void DenseMatrix<T>::vector_mult_add(DenseVector<typename CompareTypes<T, typename CompareTypes<T2, T3>::supertype>::supertype> & dest,
506  const T2 factor,
507  const DenseVector<T3> & arg) const
508 {
509  // 如果矩阵为空,直接返回
510  if (this->m() == 0)
511  {
512  dest.resize(0);
513  return;
514  }
515 
517  this->vector_mult(temp, arg);
518  dest.add(factor, temp);
519 }
520 
528 template<typename T>
530  unsigned int sub_n,
531  DenseMatrix<T> & dest) const
532 {
533  libmesh_assert((sub_m <= this->m()) && (sub_n <= this->n()));
534 
535  dest.resize(sub_m, sub_n);
536  for (unsigned int i = 0; i < sub_m; i++)
537  for (unsigned int j = 0; j < sub_n; j++)
538  dest(i, j) = (*this)(i, j);
539 }
540 
547 template<typename T>
549  const DenseVector<T> & b)
550 {
551  const unsigned int m = a.size();
552  const unsigned int n = b.size();
553 
554  this->resize(m, n);
555  for (unsigned int i = 0; i < m; ++i)
556  for (unsigned int j = 0; j < n; ++j)
557  (*this)(i, j) = a(i) * libmesh_conj(b(j));
558 }
559 
566 template<typename T>
567 void DenseMatrix<T>::get_principal_submatrix(unsigned int sub_m, DenseMatrix<T> & dest) const
568 {
569  get_principal_submatrix(sub_m, sub_m, dest);
570 }
571 
577 template<typename T>
579 {
580  dest.resize(this->n(), this->m());
581 
582  for (auto i : make_range(dest.m()))
583  for (auto j : make_range(dest.n()))
584  dest(i, j) = (*this)(j, i);
585 }
586 
606 template<typename T>
608 {
609  // 确保矩阵是方阵
610  libmesh_assert_equal_to(this->m(), this->n());
611 
612  switch (this->_decomposition_type)
613  {
614  case NONE:
615  {
616  if (this->use_blas_lapack)
617  this->_lu_decompose_lapack();
618  else
619  this->_lu_decompose();
620  break;
621  }
622 
623  case LU_BLAS_LAPACK:
624  {
625  // 已经分解,只需调用 back_substitute。
626  if (this->use_blas_lapack)
627  break;
628  }
629  libmesh_fallthrough();
630 
631  case LU:
632  {
633  // 已经分解,只需调用 back_substitute。
634  if (!(this->use_blas_lapack))
635  break;
636  }
637  libmesh_fallthrough();
638 
639  default:
640  libmesh_error_msg("Error! This matrix already has a different decomposition...");
641  }
642 
643  if (this->use_blas_lapack)
644  this->_lu_back_substitute_lapack(b, x);
645  else
646  this->_lu_back_substitute(b, x);
647 }
648 
655 template<typename T>
657 {
658  const unsigned int n_cols = this->n();
659 
660  libmesh_assert_equal_to(this->m(), n_cols);
661  libmesh_assert_equal_to(this->m(), b.size());
662 
663  x.resize(n_cols);
664 
665  // 方便引用 *this
666  const DenseMatrix<T> & A = *this;
667 
668  // 临时向量存储。使用这个向量而不是修改 RHS。
669  DenseVector<T> z = b;
670 
671  // 下三角 "从上到下" 解法步骤,考虑了主元素
672  for (unsigned int i = 0; i < n_cols; ++i)
673  {
674  // 交换
675  if (_pivots[i] != static_cast<pivot_index_t>(i))
676  std::swap(z(i), z(_pivots[i]));
677 
678  x(i) = z(i);
679 
680  for (unsigned int j = 0; j < i; ++j)
681  x(i) -= A(i, j) * x(j);
682 
683  x(i) /= A(i, i);
684  }
685 
686  // 上三角 "从下到上" 解法步骤
687  const unsigned int last_row = n_cols - 1;
688 
689  for (int i = last_row; i >= 0; --i)
690  {
691  for (int j = i + 1; j < static_cast<int>(n_cols); ++j)
692  x(i) -= A(i, j) * x(j);
693  }
694 }
695 
699 template<typename T>
701 {
702  // 如果调用了此函数,则矩阵不应该有任何先前的分解。
703  libmesh_assert_equal_to(this->_decomposition_type, NONE);
704 
705  // 获取矩阵大小并确保其是方阵
706  const unsigned int n_rows = this->m();
707 
708  // 方便引用 *this
709  DenseMatrix<T> & A = *this;
710 
711  _pivots.resize(n_rows);
712 
713  for (unsigned int i = 0; i < n_rows; ++i)
714  {
715  // 通过向下搜索第 i 列找到主元素所在的行
716  _pivots[i] = i;
717 
718  // std::abs(complex) 必须返回一个实数!
719  auto the_max = std::abs(A(i, i));
720  for (unsigned int j = i + 1; j < n_rows; ++j)
721  {
722  auto candidate_max = std::abs(A(j, i));
723  if (the_max < candidate_max)
724  {
725  the_max = candidate_max;
726  _pivots[i] = j;
727  }
728  }
729 
730  // 如果最大值在不同的行中找到,则交换行
731  // 这里交换整个行,在高斯消元中,只交换 A(i,j) 和 A(p(i),j) 的子行,对于 j>i
732  if (_pivots[i] != static_cast<pivot_index_t>(i))
733  {
734  for (unsigned int j = 0; j < n_rows; ++j)
735  std::swap(A(i, j), A(_pivots[i], j));
736  }
737 
738  // 如果找到的最大绝对值条目为零,则矩阵是奇异的
739  libmesh_error_msg_if(A(i, i) == libMesh::zero, "Matrix A is singular!");
740 
741  // 将第 i 行的上三角条目缩放为对角线条目
742  // 注意:不要缩放对角线条目本身!
743  const T diag_inv = 1. / A(i, i);
744  for (unsigned int j = i + 1; j < n_rows; ++j)
745  A(i, j) *= diag_inv;
746 
747  // 通过减去(对角线已缩放的)第 i 行的上三角部分,更新剩余子矩阵 A[i+1:m][i+1:m]
748  // 通过每行的第 i 列条目进行缩放。在行操作方面,这是:
749  // 对于每个 r > i
750  // SubRow(r) = SubRow(r) - A(r,i)*SubRow(i)
751  //
752  // 如果我们也缩放了第 i 列,就像在高斯消元中一样,这将“零”第 i 列的条目。
753  for (unsigned int row = i + 1; row < n_rows; ++row)
754  for (unsigned int col = i + 1; col < n_rows; ++col)
755  A(row, col) -= A(row, i) * A(i, col);
756  } // end i 循环
757 
758  // 设置 LU 分解标志
759  this->_decomposition_type = LU;
760 }
761 
767 template<typename T>
769 {
770  // 使用 LAPACK svd 实现
771  _svd_lapack(sigma);
772 }
773 
781 template<typename T>
784  DenseMatrix<Number> & VT)
785 {
786  // 使用 LAPACK svd 实现
787  _svd_lapack(sigma, U, VT);
788 }
789 
790 
791 
802 template <typename T>
803 template <typename T2>
805 {
806  // 检查是否已进行先前的分解
807  switch (this->_decomposition_type)
808  {
809  case NONE:
810  {
811  this->_cholesky_decompose();
812  break;
813  }
814 
815  case CHOLESKY:
816  {
817  // 已经分解,只需调用 back_substitute。
818  break;
819  }
820 
821  default:
822  libmesh_error_msg("Error! This matrix already has a different decomposition...");
823  }
824 
825  // 执行回代
826  this->_cholesky_back_substitute(b, x);
827 }
828 
834 template <typename T>
836 {
837  // 如果调用了此函数,则矩阵不应该有任何先前的分解。
838  libmesh_assert_equal_to(this->_decomposition_type, NONE);
839 
840  // 为了确保是方阵,检查行和列的数量是否相同
841  const unsigned int n_rows = this->m();
842  const unsigned int n_cols = this->n();
843 
844  // 仅为了确保是方阵
845  libmesh_assert_equal_to(n_rows, n_cols);
846 
847  // 方便引用 *this
848  DenseMatrix<T> &A = *this;
849 
850  for (unsigned int i = 0; i < n_rows; ++i)
851  {
852  for (unsigned int j = i; j < n_cols; ++j)
853  {
854  for (unsigned int k = 0; k < i; ++k)
855  A(i, j) -= A(i, k) * A(j, k);
856 
857  if (i == j)
858  {
859 #ifndef LIBMESH_USE_COMPLEX_NUMBERS
860  libmesh_error_msg_if(A(i, j) <= 0.0,
861  "Error! Can only use Cholesky decomposition with symmetric positive definite matrices.");
862 #endif
863 
864  A(i, i) = std::sqrt(A(i, j));
865  }
866  else
867  A(j, i) = A(i, j) / A(i, i);
868  }
869  }
870 
871  // 设置 CHOLESKY 分解标志
872  this->_decomposition_type = CHOLESKY;
873 }
874 
875 
883 template <typename T>
884 template <typename T2>
886  DenseVector<T2> &x) const
887 {
888  // 确保矩阵是方阵
889  libmesh_assert_equal_to(this->m(), this->n());
890 
891  // 行和列的数量的简写。
892  const unsigned int n_rows = this->m();
893  const unsigned int n_cols = this->n();
894 
895  // 方便引用 *this
896  const DenseMatrix<T> &A = *this;
897 
898  // 计算 Ax = b 的解。
899  x.resize(n_rows);
900 
901  // 解 Ly=b
902  for (unsigned int i = 0; i < n_cols; ++i)
903  {
904  T2 temp = b(i);
905 
906  for (unsigned int k = 0; k < i; ++k)
907  temp -= A(i, k) * x(k);
908 
909  x(i) = temp / A(i, i);
910  }
911 
912  // 解 L^T x = y
913  for (unsigned int i = 0; i < n_cols; ++i)
914  {
915  const unsigned int ib = (n_cols - 1) - i;
916 
917  for (unsigned int k = (ib + 1); k < n_cols; ++k)
918  x(ib) -= A(k, ib) * x(k);
919 
920  x(ib) /= A(ib, ib);
921  }
922 }
923 
924 
925 
926 
927 
928 
929 
930 
931 // This routine is commented out since it is not really a memory
932 // efficient implementation. Also, you don't *need* the inverse
933 // for anything, instead just use lu_solve to solve Ax=b.
934 // template<typename T>
935 // void DenseMatrix<T>::inverse ()
936 // {
937 // // First LU decompose the matrix
938 // // Note that the lu_decompose routine will check to see if the
939 // // matrix is square so we don't worry about it.
940 // if (!this->_lu_decomposed)
941 // this->_lu_decompose();
942 
943 // // A unit vector which will be used as a rhs
944 // // to pick off a single value each time.
945 // DenseVector<T> e;
946 // e.resize(this->m());
947 
948 // // An empty vector which will be used to hold the solution
949 // // to the back substitutions.
950 // DenseVector<T> x;
951 // x.resize(this->m());
952 
953 // // An empty dense matrix to store the resulting inverse
954 // // temporarily until we can overwrite A.
955 // DenseMatrix<T> inv;
956 // inv.resize(this->m(), this->n());
957 
958 // // Resize the passed in matrix to hold the inverse
959 // inv.resize(this->m(), this->n());
960 
961 // for (unsigned int j=0; j<this->n(); ++j)
962 // {
963 // e.zero();
964 // e(j) = 1.;
965 // this->_lu_back_substitute(e, x, false);
966 // for (unsigned int i=0; i<this->n(); ++i)
967 // inv(i,j) = x(i);
968 // }
969 
970 // // Now overwrite all the entries
971 // *this = inv;
972 // }
973 
974 
975 } // namespace libMesh
976 
977 #endif // LIBMESH_DENSE_MATRIX_IMPL_H
void _lu_back_substitute(const DenseVector< T > &b, DenseVector< T > &x) const
通过回代步骤解方程Ax=b。此函数是私有的,因为它仅在lu_solve(...)函数的实现部分中被调用。
boostcopy::enable_if_c< ScalarTraits< T2 >::value, void >::type add(const T2 factor, const DenseVector< T3 > &vec)
将 factor 乘以 vec 添加到该向量。这应该仅在 T += T2 * T3 是有效的 C++ 且 T2 是标量的情况下起作用。 返回类型是 void。
Definition: dense_vector.h:485
unsigned int n() const
返回矩阵的列维度。
T libmesh_conj(T a)
virtual void left_multiply(const DenseMatrixBase< T > &M2) overridefinal
左乘以矩阵 M2。
void vector_mult_transpose(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this)^T * arg。
void resize(const unsigned int n)
调整向量的大小。将所有元素设置为0。
Definition: dense_vector.h:404
void _cholesky_back_substitute(const DenseVector< T2 > &b, DenseVector< T2 > &x) const
根据矩阵A的Cholesky分解解方程Ax=b,得到未知值x和rhs b。
void get_transpose(DenseMatrix< T > &dest) const
将转置矩阵存储在 dest 中。
ADRealEigenVector< T, D, asd > sqrt(const ADRealEigenVector< T, D, asd > &)
计算自动微分实数向量的平方根。
Definition: type_vector.h:88
const Number zero
.
Definition: libmesh.h:248
void outer_product(const DenseVector< T > &a, const DenseVector< T > &b)
计算两个向量的外积并将结果存储在 (*this) 中。
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
计算自动微分实数向量的绝对值。
Definition: type_vector.h:112
unsigned int m() const
返回矩阵的行维度。
void svd(DenseVector< Real > &sigma)
计算矩阵的奇异值分解(SVD)。 在退出时,sigma包含所有奇异值(按降序排列)。
void _lu_decompose()
形成矩阵的LU分解。此函数是私有的,因为它仅在lu_solve(...)函数的实现部分中被调用。
void vector_mult_add(DenseVector< T > &dest, const T factor, const DenseVector< T > &arg) const
执行缩放矩阵-向量乘法,结果存储在 dest 中。 dest += factor * (*this) * arg.
T transpose(const unsigned int i, const unsigned int j) const
返回转置矩阵的 (i, j) 元素。
void get_principal_submatrix(unsigned int sub_m, unsigned int sub_n, DenseMatrix< T > &dest) const
将 sub_m x sub_n 的主子矩阵放入 dest 中。
virtual void right_multiply(const DenseMatrixBase< T > &M2) overridefinal
右乘以矩阵 M2。
void _cholesky_decompose()
将对称正定矩阵分解为两个下三角矩阵的乘积,即A = LL^T。
void right_multiply_transpose(const DenseMatrix< T > &A)
用矩阵 A 的转置右乘。
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
解方程组 给定输入向量 b。
void left_multiply_transpose(const DenseMatrix< T > &A)
用矩阵 A 的转置左乘。
void _left_multiply_transpose(const DenseMatrix< T2 > &A)
由矩阵 A 的转置左乘,该矩阵可能包含不同的数值类型。
void resize(const unsigned int new_m, const unsigned int new_n)
调整矩阵的大小,并调用 zero() 方法。
void cholesky_solve(const DenseVector< T2 > &b, DenseVector< T2 > &x)
对于对称正定矩阵(SPD),进行Cholesky分解。 分解为 A = L L^T,比标准LU分解大约快两倍。 因此,如果事先知道矩阵是SPD,则可以使用此方法。如果矩阵不是SPD,则会生成错误。 Ch...
定义用于有限元计算的稠密向量类。该类基本上是为了补充 DenseMatrix 类而设计的。 它相对于 std::vector 具有额外的功能,使其在有限元中特别有用,特别是对于方程组。 所有重写的虚拟函...
Definition: dof_map.h:64
void _right_multiply_transpose(const DenseMatrix< T2 > &A)
由矩阵 A 的转置右乘,该矩阵可能包含不同的数值类型。
为有限元类型的计算定义了一个抽象的稠密矩阵基类。例如 DenseSubMatrices 可以从这个类派生出来。
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
执行矩阵-向量乘法,dest := (*this) * arg。
定义用于有限元类型计算的密集矩阵。 用于在求和成全局矩阵之前存储单元刚度矩阵。所有被覆盖的虚函数都记录在dense_matrix_base.h中。
Definition: dof_map.h:65
virtual unsigned int size() const overridefinal
Definition: dense_vector.h:111