19 #ifndef OPM_WELLMATRIXMERGER_HEADER_INCLUDED 20 #define OPM_WELLMATRIXMERGER_HEADER_INCLUDED 22 #include <opm/simulators/linalg/system/SystemTypes.hpp> 23 #include <opm/grid/utility/SparseTable.hpp> 43 std::vector<std::size_t> rowOffsets;
44 std::vector<int> columnIndices;
48 return rows == other.rows
50 && rowOffsets == other.rowOffsets
51 && columnIndices == other.columnIndices;
56 return !(*
this == other);
67 std::size_t numResDofs = 0;
68 std::size_t totalWellBlocks = 0;
70 std::vector<MatrixSparsityPattern> bPatterns;
71 std::vector<MatrixSparsityPattern> cPatterns;
72 std::vector<MatrixSparsityPattern> dPatterns;
76 return numResDofs == other.numResDofs
77 && totalWellBlocks == other.totalWellBlocks
78 && wellCells == other.wellCells
79 && bPatterns == other.bPatterns
80 && cPatterns == other.cPatterns
81 && dPatterns == other.dPatterns;
86 return !(*
this == other);
90 template<
class Matrix>
92 captureMatrixSparsity(
const Matrix& matrix)
95 pattern.rows = matrix.N();
96 pattern.cols = matrix.M();
97 pattern.rowOffsets.reserve(matrix.N() + 1);
98 if constexpr (requires { matrix.nonzeroes(); }) {
99 pattern.columnIndices.reserve(matrix.nonzeroes());
101 pattern.rowOffsets.push_back(0);
103 for (std::size_t rowIdx = 0; rowIdx < matrix.N(); ++rowIdx) {
104 for (
auto colIt = matrix[rowIdx].begin(); colIt != matrix[rowIdx].end(); ++colIt) {
105 pattern.columnIndices.push_back(colIt.index());
107 pattern.rowOffsets.push_back(pattern.columnIndices.size());
113 template<
class Matrix>
bool hasSameMatrixSparsity(
const Matrix& matrix,
114 const MatrixSparsityPattern& pattern)
116 if (matrix.N() != pattern.rows || matrix.M() != pattern.cols) {
120 if (pattern.rowOffsets.size() != pattern.rows + 1
121 || pattern.rowOffsets.empty()
122 || pattern.rowOffsets.front() != 0)
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) {
134 if (entryOffset >= pattern.columnIndices.size()
135 ||
static_cast<std::size_t
>(pattern.columnIndices[entryOffset]) != colIt.index())
142 if (pattern.rowOffsets[rowIdx + 1] != entryOffset) {
147 return entryOffset == pattern.columnIndices.size();
162 template<
typename Scalar>
166 using BMatrix = WRMatrix<Scalar>;
167 using CMatrix = RWMatrix<Scalar>;
168 using DMatrix = WWMatrix<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();
187 if (cachedStructure.numResDofs != numResDofs_
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())
203 || !hasSameMatrixSparsity(bMatrices_[well], cachedStructure.bPatterns[well])
204 || !hasSameMatrixSparsity(cMatrices_[well], cachedStructure.cPatterns[well])
205 || !hasSameMatrixSparsity(dMatrices_[well], cachedStructure.dPatterns[well]))
211 return cachedStructure.totalWellBlocks == totalWellDofs;
217 structure.numResDofs = numResDofs_;
218 structure.totalWellBlocks = 0;
219 structure.wellCells = wellCells_;
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) {
225 structure.bPatterns.push_back(captureMatrixSparsity(bMatrices_[well]));
226 structure.cPatterns.push_back(captureMatrixSparsity(cMatrices_[well]));
227 structure.dPatterns.push_back(captureMatrixSparsity(dMatrices_[well]));
228 structure.totalWellBlocks += dMatrices_[well].N();
234 void buildMatrices(BMatrix& mergedB,
236 DMatrix& mergedD)
const 238 mergeBMatrix(mergedB);
239 mergeCMatrix(mergedC);
240 mergeDMatrix(mergedD);
243 void updateValues(BMatrix& mergedB,
245 DMatrix& mergedD)
const 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_;
514 #endif // OPM_WELLMATRIXMERGER_HEADER_INCLUDED
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
Definition: blackoilbioeffectsmodules.hh:45
Definition: WellMatrixMerger.hpp:39
Definition: WellMatrixMerger.hpp:163
Definition: WellMatrixMerger.hpp:65