19#ifndef OPM_WELLMATRIXMERGER_HEADER_INCLUDED
20#define OPM_WELLMATRIXMERGER_HEADER_INCLUDED
23#include <opm/grid/utility/SparseTable.hpp>
56 return !(*
this == other);
86 return !(*
this == other);
95 pattern.
rows = matrix.N();
96 pattern.
cols = matrix.M();
98 if constexpr (
requires { matrix.nonzeroes(); }) {
103 for (std::size_t rowIdx = 0; rowIdx < matrix.N(); ++rowIdx) {
104 for (
auto colIt = matrix[rowIdx].begin(); colIt != matrix[rowIdx].end(); ++colIt) {
116 if (matrix.N() != pattern.
rows || matrix.M() != pattern.
cols) {
127 std::size_t entryOffset = 0;
128 for (std::size_t rowIdx = 0; rowIdx < matrix.N(); ++rowIdx) {
129 if (pattern.
rowOffsets[rowIdx] != entryOffset) {
133 for (
auto colIt = matrix[rowIdx].begin(); colIt != matrix[rowIdx].end(); ++colIt) {
135 ||
static_cast<std::size_t
>(pattern.
columnIndices[entryOffset]) != colIt.index())
142 if (pattern.
rowOffsets[rowIdx + 1] != entryOffset) {
162template<
typename Scalar>
171 const std::vector<BMatrix>& bMatrices,
172 const std::vector<CMatrix>& cMatrices,
173 const std::vector<DMatrix>& dMatrices,
175 : numResDofs_(nResDofs)
176 , bMatrices_(bMatrices)
177 , cMatrices_(cMatrices)
178 , dMatrices_(dMatrices)
179 , wellCells_(wellCells)
181 assert(inputsAreValid());
186 const auto numWells = bMatrices_.size();
188 ||
static_cast<std::size_t
>(cachedStructure.
wellCells.size()) != numWells
189 || cachedStructure.
bPatterns.size() != numWells
190 || cachedStructure.
cPatterns.size() != numWells
191 || cachedStructure.
dPatterns.size() != numWells)
196 std::size_t totalWellDofs = 0;
197 for (std::size_t well = 0; well < numWells; ++well) {
198 totalWellDofs += dMatrices_[well].N();
200 const auto& cachedRow = cachedStructure.
wellCells[well];
201 const auto& currentRow = wellCells_[well];
202 if (!std::ranges::equal(cachedRow.begin(), cachedRow.end(), currentRow.begin(), currentRow.end())
220 structure.
bPatterns.reserve(bMatrices_.size());
221 structure.
cPatterns.reserve(cMatrices_.size());
222 structure.
dPatterns.reserve(dMatrices_.size());
224 for (std::size_t well = 0; well < bMatrices_.size(); ++well) {
238 mergeBMatrix(mergedB);
239 mergeCMatrix(mergedC);
240 mergeDMatrix(mergedD);
247 fillBValues(mergedB);
248 fillCValues(mergedC);
249 fillDValues(mergedD);
253 bool inputsAreValid()
const
255 const auto numWells = bMatrices_.size();
257 if (cMatrices_.size() != numWells) {
261 if (dMatrices_.size() != numWells) {
265 if (
static_cast<std::size_t
>(wellCells_.size()) != numWells) {
269 for (std::size_t well = 0; well < numWells; ++well) {
270 const auto& B = bMatrices_[well];
271 const auto& C = cMatrices_[well];
272 const auto& D = dMatrices_[well];
273 const auto& cells = wellCells_[well];
275 if (cells.size() != B.M()) {
279 if (cells.size() != C.N()) {
283 if (B.N() != C.M()) {
287 if (B.N() != D.N()) {
291 if (C.M() != D.M()) {
295 if (D.N() != D.M()) {
303 template<
class Matrix>
304 static void initializeEmptyMatrix(Matrix& matrix, std::size_t rows, std::size_t cols)
306 matrix.setSize(rows, cols);
307 matrix.setBuildMode(Matrix::random);
308 for (std::size_t row = 0; row < rows; ++row) {
309 matrix.setrowsize(row, 0);
311 matrix.endrowsizes();
315 template<
class MatrixVectorT,
class DimensionFn>
316 static std::size_t sumMatrixDimension(
const MatrixVectorT& matrices, DimensionFn&& dimension)
318 std::size_t total = 0;
319 for (
const auto& matrix : matrices) {
320 total += dimension(matrix);
326 static std::size_t countRowEntries(
const Row& row)
328 return static_cast<std::size_t
>(std::distance(row.begin(), row.end()));
331 template<
class Row,
class Matrix,
class ColumnMapper>
332 static void assignRowValues(
const Row& row,
333 Matrix& mergedMatrix,
334 std::size_t mergedRow,
335 ColumnMapper&& mapColumn)
337 for (
auto colIt = row.begin(); colIt != row.end(); ++colIt) {
338 mergedMatrix[mergedRow][mapColumn(colIt.index())] = *colIt;
342 void fillBValues(
BMatrix& mergedMatrix)
const
344 std::size_t rowOffset = 0;
345 for (std::size_t well = 0; well < bMatrices_.size(); ++well) {
346 const auto& matrix = bMatrices_[well];
347 const auto& cells = wellCells_[well];
348 for (std::size_t row = 0; row < matrix.N(); ++row) {
349 assignRowValues(matrix[row], mergedMatrix, rowOffset + row,
350 [&cells](
auto localColumn) {
351 assert(cells[localColumn] >= 0);
352 return static_cast<std::size_t
>(cells[localColumn]);
355 rowOffset += matrix.N();
359 void fillCValues(
CMatrix& mergedMatrix)
const
361 std::size_t colOffset = 0;
362 for (std::size_t well = 0; well < cMatrices_.size(); ++well) {
363 const auto& matrix = cMatrices_[well];
364 const auto& cells = wellCells_[well];
365 for (std::size_t row = 0; row < matrix.N(); ++row) {
366 assert(cells[row] >= 0);
367 const auto cell =
static_cast<std::size_t
>(cells[row]);
368 assignRowValues(matrix[row], mergedMatrix, cell,
369 [colOffset](
auto localColumn) {
return colOffset + localColumn; });
371 colOffset += matrix.M();
375 void fillDValues(
DMatrix& mergedMatrix)
const
377 std::size_t rowOffset = 0;
378 for (
const auto& matrix : dMatrices_) {
379 for (std::size_t row = 0; row < matrix.N(); ++row) {
380 assignRowValues(matrix[row], mergedMatrix, rowOffset + row,
381 [rowOffset](
auto localColumn) {
return rowOffset + localColumn; });
383 rowOffset += matrix.N();
387 void mergeBMatrix(
BMatrix& mergedMatrix)
const
389 if (bMatrices_.empty()) {
390 initializeEmptyMatrix(mergedMatrix, 0, numResDofs_);
394 const auto totalRows = sumMatrixDimension(bMatrices_, [](
const auto& matrix) {
return matrix.N(); });
396 mergedMatrix.setSize(totalRows, numResDofs_);
397 mergedMatrix.setBuildMode(BMatrix::random);
399 std::size_t rowOffset = 0;
400 for (
const auto& matrix : bMatrices_) {
401 for (std::size_t row = 0; row < matrix.N(); ++row) {
402 mergedMatrix.setrowsize(rowOffset + row, countRowEntries(matrix[row]));
404 rowOffset += matrix.N();
406 mergedMatrix.endrowsizes();
409 for (std::size_t well = 0; well < bMatrices_.size(); ++well) {
410 const auto& matrix = bMatrices_[well];
411 const auto& cells = wellCells_[well];
412 for (std::size_t row = 0; row < matrix.N(); ++row) {
413 for (
auto colIt = matrix[row].begin(); colIt != matrix[row].end(); ++colIt) {
414 assert(cells[colIt.index()] >= 0);
415 mergedMatrix.addindex(rowOffset + row,
416 static_cast<std::size_t
>(cells[colIt.index()]));
419 rowOffset += matrix.N();
421 mergedMatrix.endindices();
423 fillBValues(mergedMatrix);
426 void mergeCMatrix(
CMatrix& mergedMatrix)
const
428 if (cMatrices_.empty()) {
429 initializeEmptyMatrix(mergedMatrix, numResDofs_, 0);
433 const auto totalCols = sumMatrixDimension(cMatrices_, [](
const auto& matrix) {
return matrix.M(); });
435 mergedMatrix.setSize(numResDofs_, totalCols);
436 mergedMatrix.setBuildMode(CMatrix::random);
438 std::vector<std::size_t> rowSizes(numResDofs_, 0);
439 for (std::size_t well = 0; well < cMatrices_.size(); ++well) {
440 const auto& matrix = cMatrices_[well];
441 const auto& cells = wellCells_[well];
442 for (std::size_t rowIdx = 0; rowIdx < matrix.N(); ++rowIdx) {
443 assert(cells[rowIdx] >= 0);
444 rowSizes[
static_cast<std::size_t
>(cells[rowIdx])] += countRowEntries(matrix[rowIdx]);
447 for (std::size_t row = 0; row < numResDofs_; ++row) {
448 mergedMatrix.setrowsize(row, rowSizes[row]);
450 mergedMatrix.endrowsizes();
452 std::size_t colOffset = 0;
453 for (std::size_t well = 0; well < cMatrices_.size(); ++well) {
454 const auto& matrix = cMatrices_[well];
455 const auto& cells = wellCells_[well];
456 for (std::size_t rowIdx = 0; rowIdx < matrix.N(); ++rowIdx) {
457 assert(cells[rowIdx] >= 0);
458 const auto cell =
static_cast<std::size_t
>(cells[rowIdx]);
459 for (
auto colIt = matrix[rowIdx].begin(); colIt != matrix[rowIdx].end(); ++colIt) {
460 mergedMatrix.addindex(cell, colOffset + colIt.index());
463 colOffset += matrix.M();
465 mergedMatrix.endindices();
467 fillCValues(mergedMatrix);
470 void mergeDMatrix(
DMatrix& mergedMatrix)
const
472 if (dMatrices_.empty()) {
473 initializeEmptyMatrix(mergedMatrix, 0, 0);
477 const auto totalSize = sumMatrixDimension(dMatrices_, [](
const auto& matrix) {
return matrix.N(); });
479 mergedMatrix.setSize(totalSize, totalSize);
480 mergedMatrix.setBuildMode(DMatrix::random);
482 std::size_t rowOffset = 0;
483 for (
const auto& matrix : dMatrices_) {
484 for (std::size_t rowIdx = 0; rowIdx < matrix.N(); ++rowIdx) {
485 mergedMatrix.setrowsize(rowOffset + rowIdx, countRowEntries(matrix[rowIdx]));
487 rowOffset += matrix.N();
489 mergedMatrix.endrowsizes();
492 for (
const auto& matrix : dMatrices_) {
493 for (std::size_t rowIdx = 0; rowIdx < matrix.N(); ++rowIdx) {
494 for (
auto colIt = matrix[rowIdx].begin(); colIt != matrix[rowIdx].end(); ++colIt) {
495 mergedMatrix.addindex(rowOffset + rowIdx, rowOffset + colIt.index());
498 rowOffset += matrix.N();
500 mergedMatrix.endindices();
502 fillDValues(mergedMatrix);
505 std::size_t numResDofs_;
506 const std::vector<BMatrix>& bMatrices_;
507 const std::vector<CMatrix>& cMatrices_;
508 const std::vector<DMatrix>& dMatrices_;
Definition: WellMatrixMerger.hpp:164
WellMatrixStructure buildStructure() const
Definition: WellMatrixMerger.hpp:214
bool hasSameStructure(const WellMatrixStructure &cachedStructure) const
Definition: WellMatrixMerger.hpp:184
WRMatrix< Scalar > BMatrix
Definition: WellMatrixMerger.hpp:166
void updateValues(BMatrix &mergedB, CMatrix &mergedC, DMatrix &mergedD) const
Definition: WellMatrixMerger.hpp:243
RWMatrix< Scalar > CMatrix
Definition: WellMatrixMerger.hpp:167
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)
Definition: WellMatrixMerger.hpp:170
WWMatrix< Scalar > DMatrix
Definition: WellMatrixMerger.hpp:168
void buildMatrices(BMatrix &mergedB, CMatrix &mergedC, DMatrix &mergedD) const
Definition: WellMatrixMerger.hpp:234
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
bool hasSameMatrixSparsity(const Matrix &matrix, const MatrixSparsityPattern &pattern)
Definition: WellMatrixMerger.hpp:113
MatrixSparsityPattern captureMatrixSparsity(const Matrix &matrix)
Definition: WellMatrixMerger.hpp:92
Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, numWellDofs, numResDofs > > WRMatrix
Definition: SystemTypes.hpp:50
Definition: WellMatrixMerger.hpp:40
std::vector< int > columnIndices
Definition: WellMatrixMerger.hpp:44
bool operator!=(const MatrixSparsityPattern &other) const
Definition: WellMatrixMerger.hpp:54
std::size_t rows
Definition: WellMatrixMerger.hpp:41
bool operator==(const MatrixSparsityPattern &other) const
Definition: WellMatrixMerger.hpp:46
std::vector< std::size_t > rowOffsets
Definition: WellMatrixMerger.hpp:43
std::size_t cols
Definition: WellMatrixMerger.hpp:42
Definition: WellMatrixMerger.hpp:66
bool operator==(const WellMatrixStructure &other) const
Definition: WellMatrixMerger.hpp:74
bool operator!=(const WellMatrixStructure &other) const
Definition: WellMatrixMerger.hpp:84
std::vector< MatrixSparsityPattern > cPatterns
Definition: WellMatrixMerger.hpp:71
std::size_t numResDofs
Definition: WellMatrixMerger.hpp:67
Opm::SparseTable< int > wellCells
Definition: WellMatrixMerger.hpp:69
std::vector< MatrixSparsityPattern > dPatterns
Definition: WellMatrixMerger.hpp:72
std::vector< MatrixSparsityPattern > bPatterns
Definition: WellMatrixMerger.hpp:70
std::size_t totalWellBlocks
Definition: WellMatrixMerger.hpp:68