opm-simulators
extractMatrix.hpp
1 /*
2  Copyright 2021 SINTEF Digital, Mathematics and Cybernetics.
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 #ifndef OPM_EXTRACT_MATRIX_HEADER_INCLUDED
21 #define OPM_EXTRACT_MATRIX_HEADER_INCLUDED
22 
23 #include <algorithm>
24 #include <cassert>
25 #include <cstddef>
26 #include <vector>
27 
28 namespace Opm
29 {
30 
31 namespace Details
32 {
33 
34  template <class Matrix>
35  void copySubMatrix(const Matrix& A, const std::vector<int>& indices, Matrix& B)
36  {
37  // Copy elements so that B_{i, j} = A_{indices[i], indices[j]}.
38  for (auto row = B.begin(); row != B.end(); ++row) {
39  for (auto col = row->begin(); col != row->end(); ++col) {
40  *col = A[indices[row.index()]][indices[col.index()]];
41  }
42  }
43  }
44 
45 
46  template <class Matrix>
47  Matrix extractMatrix(const Matrix& m, const std::vector<int>& indices)
48  {
49  assert(std::ranges::is_sorted(indices));
50 
51  // Set up reverse index map.
52  const std::size_t n = indices.size();
53  std::size_t newrow = 0;
54  enum { NotIncluded = -1 };
55  std::vector<int> index_map(m.N(), NotIncluded);
56  for (auto row = m.begin(); row != m.end(); ++row) {
57  const int row_index = row.index();
58  if (row_index == indices[newrow]) {
59  index_map[row_index] = newrow;
60  ++newrow;
61  if (newrow == n) {
62  break;
63  }
64  }
65  }
66  assert(newrow == n);
67 
68  // Count nonzeroes.
69  std::size_t nnz = 0;
70  for (auto row = m.begin(); row != m.end(); ++row) {
71  if (index_map[row.index()] != NotIncluded) {
72  for (auto col = row->begin(); col != row->end(); ++col) {
73  if (index_map[col.index()] != NotIncluded) {
74  ++nnz;
75  }
76  }
77  }
78  }
79 
80  // Create the matrix structure.
81  Matrix res(n, n, nnz, Matrix::row_wise);
82  auto from_row = m.begin();
83  for (auto row = res.createbegin(); row != res.createend(); ++row) {
84  // Move from_row to point to the row to be extracted.
85  while (static_cast<int>(from_row.index()) < indices[row.index()]) {
86  ++from_row;
87  }
88  assert(static_cast<int>(from_row.index()) == indices[row.index()]);
89  // Insert nonzeros for row.
90  for (auto from_col = from_row->begin(); from_col != from_row->end(); ++from_col) {
91  const int new_col = index_map[from_col.index()];
92  if (new_col != NotIncluded) {
93  row.insert(new_col);
94  }
95  }
96  }
97 
98  copySubMatrix(m, indices, res);
99  return res;
100  }
101 
102 
103  template <class Vector>
104  Vector extractVector(const Vector& x, const std::vector<int>& indices)
105  {
106  Vector res(indices.size());
107  for (std::size_t ii = 0; ii < indices.size(); ++ii) {
108  res[ii] = x[indices[ii]];
109  }
110  return res;
111  }
112 
113 
114  template <class Vector>
115  void setGlobal(const Vector& x, const std::vector<int>& indices, Vector& global_x)
116  {
117  for (std::size_t ii = 0; ii < indices.size(); ++ii) {
118  global_x[indices[ii]] = x[ii];
119  }
120  }
121 
122 
123 
124  template <class Matrix>
125  bool matrixEqual(const Matrix& m1, const Matrix& m2)
126  {
127  // Compare size and nonzeroes.
128  if (m1.N() != m2.N()) return false;
129  if (m1.M() != m2.M()) return false;
130  if (m1.nonzeroes() != m2.nonzeroes()) return false;
131 
132  auto row1 = m1.begin();
133  auto row2 = m2.begin();
134  for (; row1 != m1.end(); ++row1, ++row2) {
135  if (row2 == m2.end()) return false;
136  if (row1.index() != row2.index()) return false;
137  auto col1 = row1->begin();
138  auto col2 = row2->begin();
139  for (; col1 != row1->end(); ++col1, ++col2) {
140  if (col2 == row2->end()) return false;
141  if (col1.index() != col2.index()) return false;
142  if (*col1 != *col2) return false;
143  }
144  }
145  return true;
146  }
147 
148 
149 } // namespace Details
150 
151 
152 } // namespace Opm
153 
154 #endif // OPM_EXTRACT_MATRIX_HEADER_INCLUDED
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45