OGS
EigenTools.cpp
Go to the documentation of this file.
1
10
11#include "EigenTools.h"
12
13#include <range/v3/view/zip.hpp>
14
15#include "EigenVector.h"
16
17namespace
18{
21 const std::vector<MathLib::EigenMatrix::IndexType>& row_ids)
22{
24
25 // A_eigen(k, j) = 0.
26 // set row to zero
27 for (auto row_id : row_ids)
28 {
29 for (SpMat::InnerIterator it(A_eigen, row_id); it; ++it)
30 {
31 if (it.col() != decltype(it.col())(row_id))
32 {
33 it.valueRef() = 0.0;
34 }
35 }
36 }
37}
38
42 const std::vector<MathLib::EigenMatrix::IndexType>& vec_knownX_id,
43 const std::vector<double>& vec_knownX_x)
44{
45 setRowsToZeroOffDiagonal(A_eigen, vec_knownX_id);
46
48 SpMat AT = A_eigen.transpose();
49
50 // Reserve space for at least one value (on the diagonal). For
51 // deactivated subdomains some rows and columns might end empty (in the
52 // A matrix) and so no space is reserved for the Dirichlet conditions in
53 // the transposed matrix. Then the coeffRef call will do costly
54 // reallocations.
55 AT.reserve(Eigen::VectorXi::Constant(A_eigen.rows(), 1));
56
57 for (std::size_t ix = 0; ix < vec_knownX_id.size(); ix++)
58 {
59 SpMat::Index const row_id = vec_knownX_id[ix];
60 auto const x = vec_knownX_x[ix];
61
62 // b_i -= A_eigen(i,k)*val, i!=k
63 // set column to zero, subtract from rhs
64 for (SpMat::InnerIterator it(AT, row_id); it; ++it)
65 {
66 if (it.col() == row_id)
67 {
68 continue;
69 }
70
71 b_eigen[it.col()] -= it.value() * x;
72 it.valueRef() = 0.0;
73 }
74
75 auto& c = AT.coeffRef(row_id, row_id);
76 if (c != 0.0)
77 {
78 b_eigen[row_id] = x * c;
79 }
80 else
81 {
82 b_eigen[row_id] = x;
83 c = 1.0;
84 }
85 }
86
87 A_eigen = AT.transpose();
88}
89
93 const std::vector<MathLib::EigenMatrix::IndexType>& vec_knownX_id,
94 const std::vector<double>& vec_knownX_x)
95{
96 INFO("partial Dirichlet BC application (rhs only).");
97
98 setRowsToZeroOffDiagonal(A_eigen, vec_knownX_id);
99
100 Eigen::VectorXd x_known{A_eigen.rows()};
101 x_known.setZero();
102
103 for (auto const& [row_id, x] :
104 ranges::views::zip(vec_knownX_id, vec_knownX_x))
105 {
106 x_known[row_id] = x;
107
108 // set rhs to Dirichlet value
109 auto const c = A_eigen.coeff(row_id, row_id);
110 if (c != 0)
111 {
112 b_eigen[row_id] = x * c;
113
114 // exclude diagonal (A_eigen(i,i)) from multiplication below
115 // (A_eigen * x_known)
116 A_eigen.coeffRef(row_id, row_id) = 0;
117 }
118 else
119 {
120 b_eigen[row_id] = x;
121 }
122 }
123
124 b_eigen -= A_eigen * x_known;
125}
126} // namespace
127
128namespace MathLib
129{
131 EigenMatrix& A, EigenVector& b, EigenVector& /*x*/,
132 const std::vector<EigenMatrix::IndexType>& vec_knownX_id,
133 const std::vector<double>& vec_knownX_x,
135{
136 using SpMat = EigenMatrix::RawMatrixType;
137 static_assert(SpMat::IsRowMajor, "matrix is assumed to be row major!");
138
139 auto& A_eigen = A.getRawMatrix();
140 auto& b_eigen = b.getRawVector();
141
143 switch (mode)
144 {
146 ::applyKnownSolutionComplete(A_eigen, b_eigen, vec_knownX_id,
147 vec_knownX_x);
148 return;
150 ::applyKnownSolutionIncomplete(A_eigen, b_eigen, vec_knownX_id,
151 vec_knownX_x);
152 return;
153 }
154
155 OGS_FATAL("Unhandled DirichletBCApplicationMode with integer value {}.",
156 std::to_underlying(mode));
157}
158
159} // namespace MathLib
#define OGS_FATAL(...)
Definition Error.h:26
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:36
Eigen::SparseMatrix< double, Eigen::RowMajor > RawMatrixType
Definition EigenMatrix.h:31
RawMatrixType & getRawMatrix()
Global vector based on Eigen vector.
Definition EigenVector.h:26
Eigen::VectorXd RawVectorType
Definition EigenVector.h:28
RawVectorType & getRawVector()
return a raw Eigen vector object
DirichletBCApplicationMode
Definition LinAlgEnums.h:42
@ COMPLETE_MATRIX_UPDATE
Both A and b fully updated.
Definition LinAlgEnums.h:43
@ FAST_INCOMPLETE_MATRIX_UPDATE
A partially updated, b fully updated.
Definition LinAlgEnums.h:44
void applyKnownSolution(EigenMatrix &A, EigenVector &b, EigenVector &, const std::vector< EigenMatrix::IndexType > &vec_knownX_id, const std::vector< double > &vec_knownX_x, DirichletBCApplicationMode const mode)
void setRowsToZeroOffDiagonal(MathLib::EigenMatrix::RawMatrixType &A_eigen, const std::vector< MathLib::EigenMatrix::IndexType > &row_ids)
void applyKnownSolutionIncomplete(MathLib::EigenMatrix::RawMatrixType &A_eigen, MathLib::EigenVector::RawVectorType &b_eigen, const std::vector< MathLib::EigenMatrix::IndexType > &vec_knownX_id, const std::vector< double > &vec_knownX_x)
void applyKnownSolutionComplete(MathLib::EigenMatrix::RawMatrixType &A_eigen, MathLib::EigenVector::RawVectorType &b_eigen, const std::vector< MathLib::EigenMatrix::IndexType > &vec_knownX_id, const std::vector< double > &vec_knownX_x)