17#ifndef OPM_DILU_HEADER_INCLUDED
18#define OPM_DILU_HEADER_INCLUDED
20#include <opm/common/ErrorMacros.hpp>
21#include <opm/common/TimingMacros.hpp>
24#include <dune/common/fmatrix.hh>
25#include <dune/common/unused.hh>
26#include <dune/common/version.hh>
27#include <dune/istl/bcrsmatrix.hh>
51template <
class M,
class X,
class Y>
71 OPM_TIMEBLOCK(prec_construct);
74 use_multithreading = omp_get_max_threads() > 1;
77 if (use_multithreading) {
78 A_reordered_.emplace(A_.N(), A_.N(), A_.nonzeroes(), M::row_wise);
83 reordered_to_natural_ = std::vector<std::size_t>(A_.N());
84 natural_to_reorder_ = std::vector<std::size_t>(A_.N());
86 for (
const auto& level_set : level_sets_) {
87 for (
const auto j : level_set) {
88 reordered_to_natural_[globCnt] = j;
89 natural_to_reorder_[j] = globCnt++;
93 for (
auto dst_row_it = A_reordered_->createbegin(); dst_row_it != A_reordered_->createend(); ++dst_row_it) {
94 auto src_row = A_.begin() + reordered_to_natural_[dst_row_it.index()];
96 for (
auto elem = src_row->begin(); elem != src_row->end(); elem++) {
97 dst_row_it.insert(elem.index());
102 Dinv_.resize(A_.N());
112 OPM_TIMEBLOCK(prec_update);
113 if (use_multithreading) {
124 void pre(X& v, Y& d)
override
126 DUNE_UNUSED_PARAMETER(v);
127 DUNE_UNUSED_PARAMETER(d);
135 void apply(X& v,
const Y& d)
override
137 OPM_TIMEBLOCK(prec_apply);
138 if (use_multithreading) {
151 DUNE_UNUSED_PARAMETER(x);
160 virtual SolverCategory::Category
category()
const override
162 return SolverCategory::sequential;
174 std::optional<M> A_reordered_;
176 std::vector<typename M::block_type> Dinv_;
180 std::vector<std::size_t> reordered_to_natural_;
182 std::vector<std::size_t> natural_to_reorder_;
184 bool use_multithreading{
false};
188 for (std::size_t row = 0; row < A_.N(); ++row) {
189 Dinv_[row] = A_[row][row];
191 for (
auto row = A_.begin(); row != A_.end(); ++row) {
192 const auto row_i = row.index();
193 auto Dinv_temp = Dinv_[row_i];
194 for (
auto a_ij = row->begin(); a_ij.index() < row_i; ++a_ij) {
195 const auto col_j = a_ij.index();
196 const auto a_ji = A_[col_j].find(row_i);
198 if (a_ji != A_[col_j].end()) {
200 Dinv_temp -= (*a_ij) * Dune::FieldMatrix(Dinv_[col_j]) * (*a_ji);
204 Dinv_[row_i] = Dinv_temp;
208 void parallelUpdate()
211#pragma omp parallel for
213 for (std::size_t row = 0; row != A_.N(); ++row) {
214 Dinv_[natural_to_reorder_[row]] = A_[row][row];
218 for (
auto dst_row_it = A_reordered_->begin(); dst_row_it != A_reordered_->end(); ++dst_row_it) {
219 auto src_row = A_.begin() + reordered_to_natural_[dst_row_it.index()];
220 for (
auto elem = src_row->begin(); elem != src_row->end(); elem++) {
221 (*A_reordered_)[dst_row_it.index()][elem.index()] = *elem;
225 int level_start_idx = 0;
226 for (
int level = 0; level < level_sets_.size(); ++level) {
227 const int num_of_rows_in_level = level_sets_[level].size();
230#pragma omp parallel for
232 for (
int row_idx_in_level = 0; row_idx_in_level < num_of_rows_in_level; ++row_idx_in_level) {
233 auto row = A_reordered_->begin() + level_start_idx + row_idx_in_level;
234 const auto row_i = reordered_to_natural_[row.index()];
236 auto Dinv_temp = Dinv_[level_start_idx + row_idx_in_level];
237 for (
auto a_ij = row->begin(); a_ij.index() < row_i; ++a_ij) {
238 const auto col_j = natural_to_reorder_[a_ij.index()];
239 const auto a_ji = (*A_reordered_)[col_j].find(row_i);
240 if (a_ji != (*A_reordered_)[col_j].end()) {
242 Dinv_temp -= (*a_ij) * Dune::FieldMatrix(Dinv_[col_j]) * (*a_ji);
246 Dinv_[level_start_idx + row_idx_in_level] = Dinv_temp;
249 level_start_idx += num_of_rows_in_level;
253 void serialApply(X& v,
const Y& d)
262 using Xblock =
typename X::block_type;
263 using Yblock =
typename Y::block_type;
265 OPM_TIMEBLOCK(lower_solve);
266 auto endi = A_.end();
267 for (
auto row = A_.begin(); row != endi; ++row) {
268 const auto row_i = row.index();
269 Yblock rhs = d[row_i];
270 for (
auto a_ij = (*row).begin(); a_ij.index() < row_i; ++a_ij) {
273 const auto col_j = a_ij.index();
274 a_ij->mmv(v[col_j], rhs);
278 Dinv_[row_i].mv(rhs, v[row_i]);
283 OPM_TIMEBLOCK(upper_solve);
286 auto rindex = [](
auto it) {
return std::prev(it.base()).index(); };
287 auto rbegini = std::make_reverse_iterator(A_.begin());
288 for (
auto row = std::make_reverse_iterator(A_.end()); row != rbegini; ++row) {
289 const auto row_i = rindex(row);
292 for (
auto a_ij = std::make_reverse_iterator(row->end()); rindex(a_ij) > row_i; ++a_ij) {
295 const auto col_j = rindex(a_ij);
296 a_ij->umv(v[col_j], rhs);
301 Dinv_[row_i].mmv(rhs, v[row_i]);
306 void parallelApply(X& v,
const Y& d)
308 using Xblock =
typename X::block_type;
309 using Yblock =
typename Y::block_type;
311 OPM_TIMEBLOCK(lower_solve);
312 int level_start_idx = 0;
313 for (
int level = 0; level < level_sets_.size(); ++level) {
314 const int num_of_rows_in_level = level_sets_[level].size();
317#pragma omp parallel for
319 for (
int row_idx_in_level = 0; row_idx_in_level < num_of_rows_in_level; ++row_idx_in_level) {
320 auto row = A_reordered_->begin() + level_start_idx + row_idx_in_level;
321 const auto row_i = reordered_to_natural_[row.index()];
322 Yblock rhs = d[row_i];
323 for (
auto a_ij = (*row).begin(); a_ij.index() < row_i; ++a_ij) {
326 const auto col_j = a_ij.index();
327 a_ij->mmv(v[col_j], rhs);
331 Dinv_[level_start_idx + row_idx_in_level].mv(rhs, v[row_i]);
333 level_start_idx += num_of_rows_in_level;
338 int level_start_idx = A_.N();
340 for (
int level = level_sets_.size() - 1; level >= 0; --level) {
341 const int num_of_rows_in_level = level_sets_[level].size();
342 level_start_idx -= num_of_rows_in_level;
344#pragma omp parallel for
346 for (
int row_idx_in_level = num_of_rows_in_level - 1; row_idx_in_level >= 0; --row_idx_in_level) {
347 auto row = A_reordered_->begin() + level_start_idx + row_idx_in_level;
348 const auto row_i = reordered_to_natural_[row.index()];
350 auto rindex = [](
auto it) {
return std::prev(it.base()).index(); };
351 for (
auto a_ij = std::make_reverse_iterator((*row).end()); rindex(a_ij) > row_i; ++a_ij) {
353 const auto col_j = rindex(a_ij);
354 a_ij->umv(v[col_j], rhs);
359 Dinv_[level_start_idx + row_idx_in_level].mmv(rhs, v[row_i]);
The OpenMP thread parallelized DILU preconditioner.
Definition: DILU.hpp:53
void post(X &x) override
Clean up.
Definition: DILU.hpp:149
M matrix_type
The matrix type the preconditioner is for.
Definition: DILU.hpp:56
void apply(X &v, const Y &d) override
Apply the preconditioner.
Definition: DILU.hpp:135
X domain_type
The domain type of the preconditioner.
Definition: DILU.hpp:58
void pre(X &v, Y &d) override
Prepare the preconditioner.
Definition: DILU.hpp:124
MultithreadDILU(const M &A)
scalar type underlying the field_type
Definition: DILU.hpp:68
virtual SolverCategory::Category category() const override
Category of the preconditioner (see SolverCategory::Category)
Definition: DILU.hpp:160
Y range_type
The range type of the preconditioner.
Definition: DILU.hpp:60
void update() override
Update the preconditioner.
Definition: DILU.hpp:110
virtual bool hasPerfectUpdate() const override
Definition: DILU.hpp:165
std::vector< typename M::block_type > getDiagonal()
Definition: DILU.hpp:154
typename X::field_type field_type
The field type of the preconditioner.
Definition: DILU.hpp:62
Interface class adding the update() method to the preconditioner interface.
Definition: PreconditionerWithUpdate.hpp:34
Definition: fvbaseprimaryvariables.hh:161
Opm::SparseTable< std::size_t > getMatrixRowColoring(const M &matrix, ColoringType coloringType)
Given a matrix and dependecy type, returns a SparseTable grouping the rows by which can be executed i...
Definition: GraphColoring.hpp:248