WellMatrixMerger.hpp
Go to the documentation of this file.
1/*
2 Copyright Equinor ASA 2026
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#ifndef OPM_WELLMATRIXMERGER_HEADER_INCLUDED
20#define OPM_WELLMATRIXMERGER_HEADER_INCLUDED
21
23#include <opm/grid/utility/SparseTable.hpp>
24
25#include <cstddef>
26#include <vector>
27
28namespace Opm
29{
30
31// Exact sparsity signature for one assembled well matrix.
32//
33// Matrix dimensions alone are not sufficient for MSW wells: the D block
34// connectivity depends on the current segment topology, so we keep the full
35// per-row column pattern and compare that directly.
37{
38 std::size_t rows = 0;
39 std::size_t cols = 0;
40 std::vector<std::size_t> rowOffsets;
41 std::vector<int> columnIndices;
42
43 bool operator==(const MatrixSparsityPattern& other) const
44 {
45 return rows == other.rows
46 && cols == other.cols
47 && rowOffsets == other.rowOffsets
48 && columnIndices == other.columnIndices;
49 }
50
51 bool operator!=(const MatrixSparsityPattern& other) const
52 {
53 return !(*this == other);
54 }
55};
56
57// Structural cache key for the merged well part of the system matrix.
58// totalWellBlocks is the sum of all individual well D-matrix dimensions,
59// i.e., the total number of well degrees of freedom. It is stored here
60// so that the well-vector size and the structure-rebuild decision stay
61// in the same place.
63{
64 std::size_t numResDofs = 0;
65 std::size_t totalWellBlocks = 0; // Aggregated well DOFs (sum of D_i.N())
67 std::vector<MatrixSparsityPattern> bPatterns;
68 std::vector<MatrixSparsityPattern> cPatterns;
69 std::vector<MatrixSparsityPattern> dPatterns;
70
71 bool operator==(const WellMatrixStructure& other) const
72 {
73 return numResDofs == other.numResDofs
75 && wellCells == other.wellCells
76 && bPatterns == other.bPatterns
77 && cPatterns == other.cPatterns
78 && dPatterns == other.dPatterns;
79 }
80
81 bool operator!=(const WellMatrixStructure& other) const
82 {
83 return !(*this == other);
84 }
85};
86
87template<class Matrix>
88MatrixSparsityPattern
89captureMatrixSparsity(const Matrix& matrix)
90{
92 pattern.rows = matrix.N();
93 pattern.cols = matrix.M();
94 pattern.rowOffsets.reserve(matrix.N() + 1);
95 if constexpr (requires { matrix.nonzeroes(); }) {
96 pattern.columnIndices.reserve(matrix.nonzeroes());
97 }
98 pattern.rowOffsets.push_back(0);
99
100 for (std::size_t rowIdx = 0; rowIdx < matrix.N(); ++rowIdx) {
101 for (auto colIt = matrix[rowIdx].begin(); colIt != matrix[rowIdx].end(); ++colIt) {
102 pattern.columnIndices.push_back(colIt.index());
103 }
104 pattern.rowOffsets.push_back(pattern.columnIndices.size());
105 }
106
107 return pattern;
108}
109
110// WellMatrixMerger assembles the global coupled well part of
111//
112// [ A C ]
113// [ B D ]
114//
115// from the per-well blocks B_j, C_j and D_j. It preserves each well's local
116// sparsity pattern and only does two structural operations: concatenate the
117// well blocks and remap perforation-related rows/columns through the list of
118// perforated reservoir cells for each well.
119
120// Give each block a distinctive value pattern so it is easy to see where it
121// ended up after merging.
122template<typename Scalar>
124{
125public:
129
130 WellMatrixMerger(const std::size_t nResDofs,
131 const std::vector<BMatrix>& bMatrices,
132 const std::vector<CMatrix>& cMatrices,
133 const std::vector<DMatrix>& dMatrices,
134 const Opm::SparseTable<int>& wellCells);
135
136 bool hasSameStructure(const WellMatrixStructure& cachedStructure) const;
137
139
140 void buildMatrices(BMatrix& mergedB,
141 CMatrix& mergedC,
142 DMatrix& mergedD) const;
143
144 void updateValues(BMatrix& mergedB,
145 CMatrix& mergedC,
146 DMatrix& mergedD) const;
147
148private:
149 bool inputsAreValid() const;
150
151 void fillBValues(BMatrix& mergedMatrix) const;
152 void fillCValues(CMatrix& mergedMatrix) const;
153 void fillDValues(DMatrix& mergedMatrix) const;
154
155 void mergeBMatrix(BMatrix& mergedMatrix) const;
156 void mergeCMatrix(CMatrix& mergedMatrix) const;
157 void mergeDMatrix(DMatrix& mergedMatrix) const;
158
159 std::size_t numResDofs_;
160 const std::vector<BMatrix>& bMatrices_;
161 const std::vector<CMatrix>& cMatrices_;
162 const std::vector<DMatrix>& dMatrices_;
163 const Opm::SparseTable<int>& wellCells_;
164};
165
166} // namespace Opm
167
168#endif // OPM_WELLMATRIXMERGER_HEADER_INCLUDED
Definition: WellMatrixMerger.hpp:124
WellMatrixStructure buildStructure() const
bool hasSameStructure(const WellMatrixStructure &cachedStructure) const
WRMatrix< Scalar > BMatrix
Definition: WellMatrixMerger.hpp:126
void updateValues(BMatrix &mergedB, CMatrix &mergedC, DMatrix &mergedD) const
RWMatrix< Scalar > CMatrix
Definition: WellMatrixMerger.hpp:127
WellMatrixMerger(const std::size_t nResDofs, const std::vector< BMatrix > &bMatrices, const std::vector< CMatrix > &cMatrices, const std::vector< DMatrix > &dMatrices, const Opm::SparseTable< int > &wellCells)
WWMatrix< Scalar > DMatrix
Definition: WellMatrixMerger.hpp:128
void buildMatrices(BMatrix &mergedB, CMatrix &mergedC, DMatrix &mergedD) const
Definition: blackoilbioeffectsmodules.hh:45
Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, numWellDofs, numWellDofs > > WWMatrix
Definition: SystemTypes.hpp:52
Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, numResDofs, numWellDofs > > RWMatrix
Definition: SystemTypes.hpp:48
MatrixSparsityPattern captureMatrixSparsity(const Matrix &matrix)
Definition: WellMatrixMerger.hpp:89
Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, numWellDofs, numResDofs > > WRMatrix
Definition: SystemTypes.hpp:50
Definition: WellMatrixMerger.hpp:37
std::vector< int > columnIndices
Definition: WellMatrixMerger.hpp:41
bool operator!=(const MatrixSparsityPattern &other) const
Definition: WellMatrixMerger.hpp:51
std::size_t rows
Definition: WellMatrixMerger.hpp:38
bool operator==(const MatrixSparsityPattern &other) const
Definition: WellMatrixMerger.hpp:43
std::vector< std::size_t > rowOffsets
Definition: WellMatrixMerger.hpp:40
std::size_t cols
Definition: WellMatrixMerger.hpp:39
Definition: WellMatrixMerger.hpp:63
bool operator==(const WellMatrixStructure &other) const
Definition: WellMatrixMerger.hpp:71
bool operator!=(const WellMatrixStructure &other) const
Definition: WellMatrixMerger.hpp:81
std::vector< MatrixSparsityPattern > cPatterns
Definition: WellMatrixMerger.hpp:68
std::size_t numResDofs
Definition: WellMatrixMerger.hpp:64
Opm::SparseTable< int > wellCells
Definition: WellMatrixMerger.hpp:66
std::vector< MatrixSparsityPattern > dPatterns
Definition: WellMatrixMerger.hpp:69
std::vector< MatrixSparsityPattern > bPatterns
Definition: WellMatrixMerger.hpp:67
std::size_t totalWellBlocks
Definition: WellMatrixMerger.hpp:65