opm-simulators
CompWellEquations_impl.hpp
1 /*
2  Copyright 2024, 2026, SINTEF Digital
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include <opm/simulators/linalg/matrixblock.hh>
21 
22 #include <cmath>
23 
24 namespace Opm {
25 
26 template <typename Scalar, int numWellEq, int numEq>
27 CompWellEquations<Scalar, numWellEq, numEq>::
28 CompWellEquations()
29 {
30  invDuneD_.setBuildMode(DiagMatWell::row_wise);
31 }
32 
33 
34 template <typename Scalar, int numWellEq, int numEq>
35 void
36 CompWellEquations<Scalar, numWellEq, numEq>::
37 init(const int num_conn, const std::vector<std::size_t>& cells)
38 {
39  duneB_.setBuildMode(OffDiagMatWell::row_wise);
40  duneC_.setBuildMode(OffDiagMatWell::row_wise),
41  duneD_.setBuildMode(DiagMatWell::row_wise);
42 
43  duneD_.setSize(1, 1, 1);
44  duneB_.setSize(1, num_conn, num_conn);
45  duneC_.setSize(1, num_conn, num_conn);
46 
47  auto endD = duneD_.createend();
48  for (auto row = duneD_.createbegin(); row != endD; ++row) {
49  // Add nonzeros for diagonal
50  row.insert(row.index());
51  }
52 
53  auto endB = duneB_.createend();
54  for (auto row = duneB_.createbegin(); row != endB; ++row) {
55  for (int con = 0 ; con < num_conn; ++con) {
56  row.insert(con);
57  }
58  }
59 
60  // make the C^T matrix
61  // TODO: let us see whether we should change the naming of DuneC_
62  auto endC = duneC_.createend();
63  for (auto row = duneC_.createbegin(); row != endC; ++row) {
64  for (int con = 0; con < num_conn; ++con) {
65  row.insert(con);
66  }
67  }
68 
69  resWell_.resize(1);
70 
71  Bx_.resize(duneB_.N());
72 
73  invDrw_.resize(duneD_.N());
74 
75  this->cells_ = cells;
76  // some others in the future
77 }
78 
79 template <typename Scalar, int numWellEq, int numEq>
80 void
81 CompWellEquations<Scalar, numWellEq, numEq>::
82 clear()
83 {
84  duneB_ = 0.0;
85  duneC_ = 0.0;
86  duneD_ = 0.0;
87  resWell_ = 0.0;
88 }
89 
90 template <typename Scalar, int numWellEq, int numEq>
91 void
92 CompWellEquations<Scalar, numWellEq, numEq>::
93 solve(BVectorWell& dx_well) const
94 {
95  invDuneD_.mv(resWell_, dx_well);
96 }
97 
98 template <typename Scalar, int numWellEq, int numEq>
99 void
100 CompWellEquations<Scalar, numWellEq, numEq>::
101 invert()
102 {
103  // On a singular well matrix, fall back to the identity to keep the Newton
104  // update finite. Singularity surfaces differently per block size (throw or
105  // silent inf/NaN), so guard against both below.
106  bool singular = false;
107  try {
108  invDuneD_ = duneD_; // Not strictly need if not cpr with well contributions is used
109  detail::invertMatrix(invDuneD_[0][0]);
110  } catch (const NumericalProblem&) {
111  singular = true;
112  } catch (const Dune::FMatrixError&) {
113  singular = true;
114  }
115 
116  // Catch the silent inf/NaN paths that do not throw.
117  for (std::size_t i = 0; !singular && i < invDuneD_[0][0].rows; ++i) {
118  for (std::size_t j = 0; !singular && j < invDuneD_[0][0].cols; ++j) {
119  if (!std::isfinite(invDuneD_[0][0][i][j])) {
120  singular = true;
121  }
122  }
123  }
124 
125  if (singular) {
126  invDuneD_[0][0] = 0.0;
127  for (std::size_t i = 0; i < invDuneD_[0][0].rows; ++i) {
128  invDuneD_[0][0][i][i] = 1.0;
129  }
130  }
131 }
132 
133 
134 template <typename Scalar, int numWellEq, int numEq>
135 void
136 CompWellEquations<Scalar, numWellEq, numEq>::
137 apply(BVector& r) const
138 {
139  assert(invDrw_.size() == invDuneD_.N());
140 
141  // invDrw_ = invDuneD_ * resWell_
142  invDuneD_.mv(resWell_, invDrw_);
143  // r = r - duneC_^T * invDrw_
144  duneC_.mmtv(invDrw_, r);
145 }
146 
147 template <typename Scalar, int numWellEq, int numEq>
148 void
149 CompWellEquations<Scalar, numWellEq, numEq>::
150 recoverSolutionWell(const BVector& x, BVectorWell& xw) const
151 {
152  BVectorWell resWell = resWell_;
153  // resWell = resWell - B * x
154  duneB_.mmv(x, resWell);
155  // xw = D^-1 * resWell
156  invDuneD_.mv(resWell, xw);
157 }
158 
159 } // end of namespace Opm
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
Definition: blackoilbioeffectsmodules.hh:45