PressureBhpTransferPolicy.hpp
Go to the documentation of this file.
1/*
2 Copyright 2019 SINTEF Digital, Mathematics and Cybernetics.
3 Copyright 2019 Dr. Blatt - HPC-Simulation-Software & Services.
4
5 This file is part of the Open Porous Media project (OPM).
6
7 OPM is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 OPM is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with OPM. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#pragma once
22
23#include <opm/common/TimingMacros.hpp>
24
25#include <opm/simulators/linalg/matrixblock.hh>
28
29#include <dune/istl/paamg/pinfo.hh>
30
31#include <cstddef>
32
33namespace Opm
34{
35 template <class Communication>
37 std::shared_ptr<Communication>& commRW,
38 const int nw)
39 {
40 OPM_TIMEBLOCK(extendCommunicatorWithWells);
41 // used for extending the coarse communicator pattern
42 using IndexSet = typename Communication::ParallelIndexSet;
43 using LocalIndex = typename IndexSet::LocalIndex;
44 const IndexSet& indset = comm.indexSet();
45 IndexSet& indset_rw = commRW->indexSet();
46 const int max_nw = comm.communicator().max(nw);
47 const int rank = comm.communicator().rank();
48 int glo_max = 0;
49 std::size_t loc_max = 0;
50 indset_rw.beginResize();
51 for (auto ind = indset.begin(), indend = indset.end(); ind != indend; ++ind) {
52 indset_rw.add(ind->global(), LocalIndex(ind->local(), ind->local().attribute(), true));
53 const int glo = ind->global();
54 const std::size_t loc = ind->local().local();
55 glo_max = std::max(glo_max, glo);
56 loc_max = std::max(loc_max, loc);
57 }
58 const int global_max = comm.communicator().max(glo_max);
59 // used append the welldofs at the end
60 assert(loc_max + 1 == indset.size());
61 std::size_t local_ind = loc_max + 1;
62 for (int i = 0; i < nw; ++i) {
63 // need to set unique global number
64 const std::size_t v = global_max + max_nw * rank + i + 1;
65 // set to true to not have problems with higher levels if growing of domains is used
66 indset_rw.add(v, LocalIndex(local_ind, Dune::OwnerOverlapCopyAttributeSet::owner, true));
67 ++local_ind;
68 }
69 indset_rw.endResize();
70 assert(indset_rw.size() == indset.size() + nw);
71 // assume same communication pattern
72 commRW->remoteIndices().setNeighbours(comm.remoteIndices().getNeighbours());
73 commRW->remoteIndices().template rebuild<true>();
74 //commRW->clearInterfaces(); may need this for correct rebuild
75 }
76
77 namespace Details
78 {
79 using PressureMatrixType = Dune::BCRSMatrix<Opm::MatrixBlock<double, 1, 1>>;
80 using PressureVectorType = Dune::BlockVector<Dune::FieldVector<double, 1>>;
81 using SeqCoarseOperatorType = Dune::MatrixAdapter<PressureMatrixType, PressureVectorType, PressureVectorType>;
82 template <class Comm>
84 = Dune::OverlappingSchwarzOperator<PressureMatrixType, PressureVectorType, PressureVectorType, Comm>;
85 template <class Comm>
86 using CoarseOperatorType = std::conditional_t<std::is_same<Comm, Dune::Amg::SequentialInformation>::value,
89 } // namespace Details
90
91 template <class FineOperator, class Communication, bool transpose = false>
92 class PressureBhpTransferPolicy : public Dune::Amg::LevelTransferPolicyCpr<FineOperator, Details::CoarseOperatorType<Communication>>
93 {
94 public:
98 typedef typename FineOperator::domain_type FineVectorType;
99
100 public:
102 const FineVectorType& weights,
103 const Opm::PropertyTree& prm,
104 const std::size_t pressureIndex)
105 : communication_(&const_cast<Communication&>(comm))
106 , weights_(weights)
107 , prm_(prm)
108 , pressure_var_index_(pressureIndex)
109 {
110 }
111
112 virtual void createCoarseLevelSystem(const FineOperator& fineOperator) override
113 {
114 OPM_TIMEBLOCK(createCoarseLevelSystem);
115 using CoarseMatrix = typename CoarseOperator::matrix_type;
116 const auto& fineLevelMatrix = fineOperator.getmat();
117 const auto& nw = fineOperator.getNumberOfExtraEquations();
118 if (prm_.get<bool>("add_wells")) {
119 const std::size_t average_elements_per_row
120 = static_cast<std::size_t>(std::ceil(fineLevelMatrix.nonzeroes() / fineLevelMatrix.N()));
121 const double overflow_fraction = 1.2;
122 coarseLevelMatrix_.reset(new CoarseMatrix(fineLevelMatrix.N() + nw,
123 fineLevelMatrix.M() + nw,
124 average_elements_per_row,
125 overflow_fraction,
126 CoarseMatrix::implicit));
127 int rownum = 0;
128 for (const auto& row : fineLevelMatrix) {
129 for (auto col = row.begin(), cend = row.end(); col != cend; ++col) {
130 coarseLevelMatrix_->entry(rownum, col.index()) = 0.0;
131 }
132 ++rownum;
133 }
134 } else {
135 coarseLevelMatrix_.reset(
136 new CoarseMatrix(fineLevelMatrix.N(), fineLevelMatrix.M(), CoarseMatrix::row_wise));
137 auto createIter = coarseLevelMatrix_->createbegin();
138 for (const auto& row : fineLevelMatrix) {
139 for (auto col = row.begin(), cend = row.end(); col != cend; ++col) {
140 createIter.insert(col.index());
141 }
142 ++createIter;
143 }
144 }
145 if constexpr (std::is_same_v<Communication, Dune::Amg::SequentialInformation>) {
146 coarseLevelCommunication_ = std::make_shared<Communication>();
147 } else {
148 coarseLevelCommunication_ = std::make_shared<Communication>(
149 communication_->communicator(), communication_->category(), false);
150 }
151 if (prm_.get<bool>("add_wells")) {
152 fineOperator.addWellPressureEquationsStruct(*coarseLevelMatrix_);
153 coarseLevelMatrix_->compress(); // all elemenst should be set
154 if constexpr (!std::is_same_v<Communication, Dune::Amg::SequentialInformation>) {
155 extendCommunicatorWithWells(*communication_, coarseLevelCommunication_, nw);
156 }
157 }
158 calculateCoarseEntries(fineOperator);
159
160 this->lhs_.resize(this->coarseLevelMatrix_->M());
161 this->rhs_.resize(this->coarseLevelMatrix_->N());
162 using OperatorArgs = typename Dune::Amg::ConstructionTraits<CoarseOperator>::Arguments;
163 OperatorArgs oargs(coarseLevelMatrix_, *coarseLevelCommunication_);
164 this->operator_ = Dune::Amg::ConstructionTraits<CoarseOperator>::construct(oargs);
165 }
166
167 virtual void calculateCoarseEntries(const FineOperator& fineOperator) override
168 {
169 OPM_TIMEBLOCK(calculateCoarseEntries);
170 const auto& fineMatrix = fineOperator.getmat();
171 *coarseLevelMatrix_ = 0;
172 auto rowCoarse = coarseLevelMatrix_->begin();
173 for (auto row = fineMatrix.begin(), rowEnd = fineMatrix.end(); row != rowEnd; ++row, ++rowCoarse) {
174 assert(row.index() == rowCoarse.index());
175 auto entryCoarse = rowCoarse->begin();
176 for (auto entry = row->begin(), entryEnd = row->end(); entry != entryEnd; ++entry, ++entryCoarse) {
177 assert(entry.index() == entryCoarse.index());
178 double matrix_el = 0;
179 if (transpose) {
180 const auto& bw = weights_[entry.index()];
181 for (std::size_t i = 0; i < bw.size(); ++i) {
182 matrix_el += (*entry)[pressure_var_index_][i] * bw[i];
183 }
184 } else {
185 const auto& bw = weights_[row.index()];
186 for (std::size_t i = 0; i < bw.size(); ++i) {
187 matrix_el += (*entry)[i][pressure_var_index_] * bw[i];
188 }
189 }
190 (*entryCoarse) = matrix_el;
191 }
192 }
193 if (prm_.get<bool>("add_wells")) {
194 OPM_TIMEBLOCK(cprwAddWellEquation);
195 assert(transpose == false); // not implemented
196 bool use_well_weights = prm_.get<bool>("use_well_weights");
197 fineOperator.addWellPressureEquations(*coarseLevelMatrix_, weights_, use_well_weights);
198#ifndef NDEBUG
199 std::advance(rowCoarse, fineOperator.getNumberOfExtraEquations());
200 assert(rowCoarse == coarseLevelMatrix_->end());
201#endif
202
203 }
204 }
205
206 virtual void moveToCoarseLevel(const typename ParentType::FineRangeType& fine) override
207 {
208 OPM_TIMEBLOCK(moveToCoarseLevel);
209 //NB we iterate over fine assumming welldofs is at the end
210 // Set coarse vector to zero
211 this->rhs_ = 0;
212
213 auto end = fine.end(), begin = fine.begin();
214
215 for (auto block = begin; block != end; ++block) {
216 const auto& bw = weights_[block.index()];
217 double rhs_el = 0.0;
218 if (transpose) {
219 rhs_el = (*block)[pressure_var_index_];
220 } else {
221 for (std::size_t i = 0; i < block->size(); ++i) {
222 rhs_el += (*block)[i] * bw[i];
223 }
224 }
225 this->rhs_[block - begin] = rhs_el;
226 }
227
228 this->lhs_ = 0;
229 }
230
231 virtual void moveToFineLevel(typename ParentType::FineDomainType& fine) override
232 {
233 OPM_TIMEBLOCK(moveToFineLevel);
234 //NB we iterate over fine assumming welldofs is at the end
235 auto end = fine.end(), begin = fine.begin();
236
237 for (auto block = begin; block != end; ++block) {
238 if (transpose) {
239 const auto& bw = weights_[block.index()];
240 for (std::size_t i = 0; i < block->size(); ++i) {
241 (*block)[i] = this->lhs_[block - begin] * bw[i];
242 }
243 } else {
244 (*block)[pressure_var_index_] = this->lhs_[block - begin];
245 }
246 }
247 }
248
249 virtual PressureBhpTransferPolicy* clone() const override
250 {
251 return new PressureBhpTransferPolicy(*this);
252 }
253
255 {
256 return *coarseLevelCommunication_;
257 }
258
259private:
260 Communication* communication_;
261 const FineVectorType& weights_;
262 PropertyTree prm_;
263 const int pressure_var_index_;
264 std::shared_ptr<Communication> coarseLevelCommunication_;
265 std::shared_ptr<typename CoarseOperator::matrix_type> coarseLevelMatrix_;
266};
267
268} // namespace Opm
269
Abstract base class for transfer between levels and creation of the coarse level system.
Definition: twolevelmethodcpr.hh:44
FineOperatorType::range_type FineRangeType
The type of the range of the fine level operator.
Definition: twolevelmethodcpr.hh:54
CoarseDomainType lhs_
The coarse level lhs.
Definition: twolevelmethodcpr.hh:141
CoarseRangeType rhs_
The coarse level rhs.
Definition: twolevelmethodcpr.hh:139
FineOperatorType::domain_type FineDomainType
The type of the domain of the fine level operator.
Definition: twolevelmethodcpr.hh:58
std::shared_ptr< CoarseOperatorType > operator_
the coarse level linear operator.
Definition: twolevelmethodcpr.hh:143
Definition: PressureBhpTransferPolicy.hpp:93
Communication ParallelInformation
Definition: PressureBhpTransferPolicy.hpp:97
virtual void moveToFineLevel(typename ParentType::FineDomainType &fine) override
Updates the fine level linear system after the correction of the coarse levels system.
Definition: PressureBhpTransferPolicy.hpp:231
virtual void calculateCoarseEntries(const FineOperator &fineOperator) override
???.
Definition: PressureBhpTransferPolicy.hpp:167
Details::CoarseOperatorType< Communication > CoarseOperator
Definition: PressureBhpTransferPolicy.hpp:95
Dune::Amg::LevelTransferPolicyCpr< FineOperator, CoarseOperator > ParentType
Definition: PressureBhpTransferPolicy.hpp:96
virtual void moveToCoarseLevel(const typename ParentType::FineRangeType &fine) override
Definition: PressureBhpTransferPolicy.hpp:206
virtual PressureBhpTransferPolicy * clone() const override
Clone the current object.
Definition: PressureBhpTransferPolicy.hpp:249
PressureBhpTransferPolicy(const Communication &comm, const FineVectorType &weights, const Opm::PropertyTree &prm, const std::size_t pressureIndex)
Definition: PressureBhpTransferPolicy.hpp:101
FineOperator::domain_type FineVectorType
Definition: PressureBhpTransferPolicy.hpp:98
const Communication & getCoarseLevelCommunication() const
Definition: PressureBhpTransferPolicy.hpp:254
virtual void createCoarseLevelSystem(const FineOperator &fineOperator) override
Algebraically creates the coarse level system.
Definition: PressureBhpTransferPolicy.hpp:112
Definition: PropertyTree.hpp:37
T get(const std::string &key) const
std::conditional_t< std::is_same< Comm, Dune::Amg::SequentialInformation >::value, SeqCoarseOperatorType, ParCoarseOperatorType< Comm > > CoarseOperatorType
Definition: PressureBhpTransferPolicy.hpp:88
Dune::BlockVector< Dune::FieldVector< double, 1 > > PressureVectorType
Definition: PressureBhpTransferPolicy.hpp:80
Dune::MatrixAdapter< PressureMatrixType, PressureVectorType, PressureVectorType > SeqCoarseOperatorType
Definition: PressureBhpTransferPolicy.hpp:81
Dune::OverlappingSchwarzOperator< PressureMatrixType, PressureVectorType, PressureVectorType, Comm > ParCoarseOperatorType
Definition: PressureBhpTransferPolicy.hpp:84
Dune::BCRSMatrix< Opm::MatrixBlock< double, 1, 1 > > PressureMatrixType
Definition: PressureBhpTransferPolicy.hpp:79
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
Definition: BlackoilPhases.hpp:27
void extendCommunicatorWithWells(const Communication &comm, std::shared_ptr< Communication > &commRW, const int nw)
Definition: PressureBhpTransferPolicy.hpp:36
Algebraic twolevel methods.