WellOperators.hpp
Go to the documentation of this file.
1/*
2 Copyright 2016 IRIS AS
3 Copyright 2019, 2020 Equinor ASA
4 Copyright 2020 SINTEF
5
6 This file is part of the Open Porous Media project (OPM).
7
8 OPM is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 OPM is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with OPM. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#ifndef OPM_WELLOPERATORS_HEADER_INCLUDED
23#define OPM_WELLOPERATORS_HEADER_INCLUDED
24
25#include <dune/common/parallel/communication.hh>
26#include <dune/istl/operators.hh>
27#include <dune/istl/bcrsmatrix.hh>
28
29#include <opm/common/TimingMacros.hpp>
30
32#include <dune/common/shared_ptr.hh>
33#include <dune/istl/paamg/smoother.hh>
34
35#include <cstddef>
36
37namespace Opm {
38
39//=====================================================================
40// Implementation for ISTL-matrix based operators
41// Note: the classes WellModelMatrixAdapter and
42// WellModelGhostLastMatrixAdapter were moved from ISTLSolver.hpp
43// and subsequently modified.
44//=====================================================================
45
55template <class X, class Y>
56class LinearOperatorExtra : public Dune::LinearOperator<X, Y>
57{
58public:
59 using field_type = typename X::field_type;
60 using PressureMatrix = Dune::BCRSMatrix<MatrixBlock<field_type, 1, 1>>;
62 const X& weights,
63 const bool use_well_weights) const = 0;
64 virtual void addWellPressureEquationsStruct(PressureMatrix& jacobian) const = 0;
65 virtual int getNumberOfExtraEquations() const = 0;
66};
67
68template <class WellModel, class X, class Y>
70{
71public:
73 using field_type = typename Base::field_type;
75 explicit WellModelAsLinearOperator(const WellModel& wm)
76 : wellMod_(wm)
77 {
78 }
79
84 void apply(const X& x, Y& y) const override
85 {
86 OPM_TIMEBLOCK(apply);
87 for (const auto& well : this->wellMod_) {
88 this->applySingleWell(x, y, well, well->cells());
89 }
90 }
91
93 void applyscaleadd(field_type alpha, const X& x, Y& y) const override
94 {
95 OPM_TIMEBLOCK(applyscaleadd);
96 if (this->wellMod_.empty()) {
97 return;
98 }
99
100 if (scaleAddRes_.size() != y.size()) {
101 scaleAddRes_.resize(y.size());
102 }
103
104 scaleAddRes_ = 0.0;
105 // scaleAddRes_ = - C D^-1 B x
107 // Ax = Ax + alpha * scaleAddRes_
108 y.axpy(alpha, scaleAddRes_);
109 }
110
116 Dune::SolverCategory::Category category() const override
117 {
118 return Dune::SolverCategory::sequential;
119 }
120
122 const X& weights,
123 const bool use_well_weights) const override
124 {
125 OPM_TIMEBLOCK(addWellPressureEquations);
126 wellMod_.addWellPressureEquations(jacobian, weights, use_well_weights);
127 }
128
129 void addWellPressureEquationsStruct(PressureMatrix& jacobian) const override
130 {
131 OPM_TIMEBLOCK(addWellPressureEquationsStruct);
132 wellMod_.addWellPressureEquationsStruct(jacobian);
133 }
134
135 int getNumberOfExtraEquations() const override
136 {
137 return wellMod_.numLocalWellsEnd();
138 }
139
140protected:
141 const WellModel& wellMod_;
142
143 template<class WellType, class ArrayType>
144 void applySingleWell(const X& x, Y& y,
145 const WellType& well,
146 const ArrayType& cells) const
147 {
148 // Well equations B and C uses only the perforated cells, so need to apply on local vectors
149 x_local_.resize(cells.size());
150 Ax_local_.resize(cells.size());
151
152 for (size_t i = 0; i < cells.size(); ++i) {
153 x_local_[i] = x[cells[i]];
154 Ax_local_[i] = y[cells[i]];
155 }
156
157 well->apply(x_local_, Ax_local_);
158
159 for (size_t i = 0; i < cells.size(); ++i) {
160 // only need to update Ax
161 y[cells[i]] = Ax_local_[i];
162 }
163
164 }
165
166 // These members are used to avoid reallocation.
167 // Their state is not relevant between function calls, so they can
168 // (and must) be mutable, as the functions using them are const.
169 mutable X x_local_{};
170 mutable Y Ax_local_{};
171 mutable Y scaleAddRes_{};
172};
173
174template <class WellModel, class X, class Y>
176{
177public:
179 using WBase::WBase; // inherit all constructors from the base class
182
183 void setDomainIndex(int index) { domainIndex_ = index; }
184
185 void apply(const X& x, Y& y) const override
186 {
187 OPM_TIMEBLOCK(apply);
188 std::size_t well_index = 0;
189 for (const auto& well : this->wellMod_) {
190 if (this->wellMod_.well_domain().at(well->name()) == domainIndex_) {
191 this->applySingleWell(x, y, well,
192 this->wellMod_.well_local_cells()[well_index]);
193 }
194 ++well_index;
195 }
196 }
197
199 const X& weights,
200 const bool use_well_weights) const override
201 {
202 OPM_TIMEBLOCK(addWellPressureEquations);
203 this->wellMod_.addWellPressureEquationsDomain(jacobian,
204 weights,
205 use_well_weights,
206 domainIndex_);
207 }
208
209private:
210 int domainIndex_ = -1;
211};
212
223template<class M, class X, class Y>
224class WellModelMatrixAdapter : public Dune::AssembledLinearOperator<M,X,Y>
225{
226public:
227 using matrix_type = M;
228 using domain_type = X;
229 using range_type = Y;
230 using field_type = typename X::field_type;
231 using PressureMatrix = Dune::BCRSMatrix<MatrixBlock<field_type, 1, 1>>;
232
233 Dune::SolverCategory::Category category() const override
234 {
235 return Dune::SolverCategory::sequential;
236 }
237
240 const LinearOperatorExtra<X, Y>& wellOper)
241 : A_( A ), wellOper_( wellOper )
242 {}
243
244 void apply( const X& x, Y& y ) const override
245 {
246 OPM_TIMEBLOCK(apply);
247 A_.mv(x, y);
248
249 // add well model modification to y
250 wellOper_.apply(x, y);
251 }
252
253 // y += \alpha * A * x
254 void applyscaleadd (field_type alpha, const X& x, Y& y) const override
255 {
256 OPM_TIMEBLOCK(applyscaleadd);
257 A_.usmv(alpha, x, y);
258
259 // add scaled well model modification to y
260 wellOper_.applyscaleadd(alpha, x, y);
261 }
262
263 const matrix_type& getmat() const override { return A_; }
264
266
268 const X& weights,
269 const bool use_well_weights) const
270 {
271 OPM_TIMEBLOCK(addWellPressureEquations);
272 wellOper_.addWellPressureEquations(jacobian, weights, use_well_weights);
273 }
274
276 {
277 OPM_TIMEBLOCK(addWellPressureEquations);
278 wellOper_.addWellPressureEquationsStruct(jacobian);
279 }
280
282 {
283 return wellOper_.getNumberOfExtraEquations();
284 }
285
286protected:
289};
290
299template<class M, class X, class Y, bool overlapping >
300class WellModelGhostLastMatrixAdapter : public Dune::AssembledLinearOperator<M,X,Y>
301{
302public:
303 using matrix_type = M;
304 using domain_type = X;
305 using range_type = Y;
306 using field_type = typename X::field_type;
307 using PressureMatrix = Dune::BCRSMatrix<MatrixBlock<field_type, 1, 1>>;
308#if HAVE_MPI
309 using communication_type = Dune::OwnerOverlapCopyCommunication<int,int>;
310#else
311 using communication_type = Dune::Communication<int>;
312#endif
313
314 Dune::SolverCategory::Category category() const override
315 {
316 return overlapping ?
317 Dune::SolverCategory::overlapping : Dune::SolverCategory::sequential;
318 }
319
322 const LinearOperatorExtra<X, Y>& wellOper,
323 const std::size_t interiorSize )
324 : A_( A ), wellOper_( wellOper ), interiorSize_(interiorSize)
325 {}
326
327 void apply(const X& x, Y& y) const override
328 {
329 OPM_TIMEBLOCK(apply);
330 for (auto row = A_.begin(); row.index() < interiorSize_; ++row)
331 {
332 y[row.index()]=0;
333 auto endc = (*row).end();
334 for (auto col = (*row).begin(); col != endc; ++col)
335 (*col).umv(x[col.index()], y[row.index()]);
336 }
337
338 // add well model modification to y
339 wellOper_.apply(x, y);
340
342 }
343
344 // y += \alpha * A * x
345 void applyscaleadd (field_type alpha, const X& x, Y& y) const override
346 {
347 OPM_TIMEBLOCK(applyscaleadd);
348 for (auto row = A_.begin(); row.index() < interiorSize_; ++row)
349 {
350 auto endc = (*row).end();
351 for (auto col = (*row).begin(); col != endc; ++col)
352 (*col).usmv(alpha, x[col.index()], y[row.index()]);
353 }
354 // add scaled well model modification to y
355 wellOper_.applyscaleadd(alpha, x, y);
356
358 }
359
360 const matrix_type& getmat() const override { return A_; }
361
363
365 const X& weights,
366 const bool use_well_weights) const
367 {
368 OPM_TIMEBLOCK(addWellPressureEquations);
369 wellOper_.addWellPressureEquations(jacobian, weights, use_well_weights);
370 }
371
373 {
374 OPM_TIMEBLOCK(addWellPressureEquationsStruct);
375 wellOper_.addWellPressureEquationsStruct(jacobian);
376 }
377
379 {
380 return wellOper_.getNumberOfExtraEquations();
381 }
382
383protected:
384 void ghostLastProject(Y& y) const
385 {
386 std::size_t end = y.size();
387 for (std::size_t i = interiorSize_; i < end; ++i)
388 y[i] = 0;
389 }
390
393 std::size_t interiorSize_;
394};
395
404template<class M, class X, class Y, class C>
405class GhostLastMatrixAdapter : public Dune::AssembledLinearOperator<M,X,Y>
406{
407public:
408 typedef M matrix_type;
409 typedef X domain_type;
410 typedef Y range_type;
411 typedef typename X::field_type field_type;
412
413
415
416 Dune::SolverCategory::Category category() const override
417 {
418 return Dune::SolverCategory::overlapping;
419 }
420
423 const communication_type& comm)
424 : A_( Dune::stackobject_to_shared_ptr(A) ), comm_(comm)
425 {
426 interiorSize_ = setInteriorSize(comm_);
427 }
428
429 GhostLastMatrixAdapter (const std::shared_ptr<M> A,
430 const communication_type& comm)
431 : A_( A ), comm_(comm)
432 {
433 interiorSize_ = setInteriorSize(comm_);
434 }
435
436 void apply( const X& x, Y& y ) const override
437 {
438 for (auto row = A_->begin(); row.index() < interiorSize_; ++row)
439 {
440 y[row.index()]=0;
441 auto endc = (*row).end();
442 for (auto col = (*row).begin(); col != endc; ++col)
443 (*col).umv(x[col.index()], y[row.index()]);
444 }
445
446 ghostLastProject( y );
447 }
448
449 // y += \alpha * A * x
450 void applyscaleadd (field_type alpha, const X& x, Y& y) const override
451 {
452 for (auto row = A_->begin(); row.index() < interiorSize_; ++row)
453 {
454 auto endc = (*row).end();
455 for (auto col = (*row).begin(); col != endc; ++col)
456 (*col).usmv(alpha, x[col.index()], y[row.index()]);
457 }
458
459 ghostLastProject( y );
460 }
461
462 const matrix_type& getmat() const override { return *A_; }
463
464 size_t getInteriorSize() const { return interiorSize_;}
465
466private:
467 void ghostLastProject(Y& y) const
468 {
469 size_t end = y.size();
470 for (size_t i = interiorSize_; i < end; ++i)
471 y[i] = 0; //project to interiorsize, i.e. ignore ghost
472 }
473
474 size_t setInteriorSize(const communication_type& comm) const
475 {
476 auto indexSet = comm.indexSet();
477 if (indexSet.size() == 0)
478 return 0;
479
480 size_t is = 0;
481 // Loop over index set
482 for (auto idx = indexSet.begin(); idx!=indexSet.end(); ++idx) {
483 //Only take "owner" indices
484 if (idx->local().attribute()==1) {
485 //get local index
486 auto loc = idx->local().local();
487 // if loc is higher than "old interior size", update it
488 if (loc > is) {
489 is = loc;
490 }
491 }
492 }
493 return is + 1; //size is plus 1 since we start at 0, except when indexSet is empty
494 }
495 const std::shared_ptr<const matrix_type> A_ ;
496 const communication_type& comm_;
497 size_t interiorSize_;
498};
499
500} // namespace Opm
501
502namespace Dune {
503namespace Amg {
504
505template<class M, class X, class Y, class C>
506class ConstructionTraits<Opm::GhostLastMatrixAdapter<M,X,Y,C> >
507{
508public:
509 typedef ParallelOperatorArgs<M,C> Arguments;
510
511 static inline std::shared_ptr<Opm::GhostLastMatrixAdapter<M,X,Y,C>> construct(const Arguments& args)
512 {
513 return std::make_shared<Opm::GhostLastMatrixAdapter<M,X,Y,C>>
514 (args.matrix_, args.comm_);
515 }
516};
517
518} // end namespace Amg
519} // end namespace Dune
520
521#endif // OPM_WELLOPERATORS_HEADER_INCLUDED
static std::shared_ptr< Opm::GhostLastMatrixAdapter< M, X, Y, C > > construct(const Arguments &args)
Definition: WellOperators.hpp:511
ParallelOperatorArgs< M, C > Arguments
Definition: WellOperators.hpp:509
Definition: WellOperators.hpp:176
void addWellPressureEquations(PressureMatrix &jacobian, const X &weights, const bool use_well_weights) const override
Definition: WellOperators.hpp:198
void setDomainIndex(int index)
Definition: WellOperators.hpp:183
void apply(const X &x, Y &y) const override
Definition: WellOperators.hpp:185
Dune linear operator that assumes ghost rows are ordered after interior rows. Avoids some computation...
Definition: WellOperators.hpp:406
C communication_type
Definition: WellOperators.hpp:414
M matrix_type
Definition: WellOperators.hpp:408
void applyscaleadd(field_type alpha, const X &x, Y &y) const override
Definition: WellOperators.hpp:450
Dune::SolverCategory::Category category() const override
Definition: WellOperators.hpp:416
const matrix_type & getmat() const override
Definition: WellOperators.hpp:462
X::field_type field_type
Definition: WellOperators.hpp:411
void apply(const X &x, Y &y) const override
Definition: WellOperators.hpp:436
X domain_type
Definition: WellOperators.hpp:409
GhostLastMatrixAdapter(const std::shared_ptr< M > A, const communication_type &comm)
Definition: WellOperators.hpp:429
GhostLastMatrixAdapter(const M &A, const communication_type &comm)
constructor: just store a reference to a matrix
Definition: WellOperators.hpp:422
Y range_type
Definition: WellOperators.hpp:410
size_t getInteriorSize() const
Definition: WellOperators.hpp:464
Definition: WellOperators.hpp:57
virtual void addWellPressureEquationsStruct(PressureMatrix &jacobian) const =0
virtual void addWellPressureEquations(PressureMatrix &jacobian, const X &weights, const bool use_well_weights) const =0
Dune::BCRSMatrix< MatrixBlock< field_type, 1, 1 > > PressureMatrix
Definition: WellOperators.hpp:60
typename X::field_type field_type
Definition: WellOperators.hpp:59
virtual int getNumberOfExtraEquations() const =0
Definition: WellOperators.hpp:70
typename Base::PressureMatrix PressureMatrix
Definition: WellOperators.hpp:74
const WellModel & wellMod_
Definition: WellOperators.hpp:141
Y Ax_local_
Definition: WellOperators.hpp:170
void apply(const X &x, Y &y) const override
apply operator to x: The input vector is consistent and the output must also be consistent on the in...
Definition: WellOperators.hpp:84
WellModelAsLinearOperator(const WellModel &wm)
Definition: WellOperators.hpp:75
X x_local_
Definition: WellOperators.hpp:169
typename Base::field_type field_type
Definition: WellOperators.hpp:73
void addWellPressureEquations(PressureMatrix &jacobian, const X &weights, const bool use_well_weights) const override
Definition: WellOperators.hpp:121
void applySingleWell(const X &x, Y &y, const WellType &well, const ArrayType &cells) const
Definition: WellOperators.hpp:144
void applyscaleadd(field_type alpha, const X &x, Y &y) const override
apply operator to x, scale and add:
Definition: WellOperators.hpp:93
Dune::SolverCategory::Category category() const override
Definition: WellOperators.hpp:116
int getNumberOfExtraEquations() const override
Definition: WellOperators.hpp:135
void addWellPressureEquationsStruct(PressureMatrix &jacobian) const override
Definition: WellOperators.hpp:129
Y scaleAddRes_
Definition: WellOperators.hpp:171
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:301
const LinearOperatorExtra< X, Y > & getwellOper() const
Definition: WellOperators.hpp:362
void addWellPressureEquationsStruct(PressureMatrix &jacobian) const
Definition: WellOperators.hpp:372
typename X::field_type field_type
Definition: WellOperators.hpp:306
void addWellPressureEquations(PressureMatrix &jacobian, const X &weights, const bool use_well_weights) const
Definition: WellOperators.hpp:364
const matrix_type & A_
Definition: WellOperators.hpp:391
const matrix_type & getmat() const override
Definition: WellOperators.hpp:360
Dune::SolverCategory::Category category() const override
Definition: WellOperators.hpp:314
void apply(const X &x, Y &y) const override
Definition: WellOperators.hpp:327
WellModelGhostLastMatrixAdapter(const M &A, const LinearOperatorExtra< X, Y > &wellOper, const std::size_t interiorSize)
constructor: just store a reference to a matrix
Definition: WellOperators.hpp:321
Dune::OwnerOverlapCopyCommunication< int, int > communication_type
Definition: WellOperators.hpp:309
Dune::BCRSMatrix< MatrixBlock< field_type, 1, 1 > > PressureMatrix
Definition: WellOperators.hpp:307
X domain_type
Definition: WellOperators.hpp:304
void applyscaleadd(field_type alpha, const X &x, Y &y) const override
Definition: WellOperators.hpp:345
int getNumberOfExtraEquations() const
Definition: WellOperators.hpp:378
Y range_type
Definition: WellOperators.hpp:305
std::size_t interiorSize_
Definition: WellOperators.hpp:393
const LinearOperatorExtra< X, Y > & wellOper_
Definition: WellOperators.hpp:392
M matrix_type
Definition: WellOperators.hpp:303
void ghostLastProject(Y &y) const
Definition: WellOperators.hpp:384
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:225
Y range_type
Definition: WellOperators.hpp:229
const matrix_type & A_
Definition: WellOperators.hpp:287
void addWellPressureEquationsStruct(PressureMatrix &jacobian) const
Definition: WellOperators.hpp:275
int getNumberOfExtraEquations() const
Definition: WellOperators.hpp:281
void apply(const X &x, Y &y) const override
Definition: WellOperators.hpp:244
void addWellPressureEquations(PressureMatrix &jacobian, const X &weights, const bool use_well_weights) const
Definition: WellOperators.hpp:267
M matrix_type
Definition: WellOperators.hpp:227
const LinearOperatorExtra< X, Y > & getwellOper() const
Definition: WellOperators.hpp:265
typename X::field_type field_type
Definition: WellOperators.hpp:230
Dune::BCRSMatrix< MatrixBlock< field_type, 1, 1 > > PressureMatrix
Definition: WellOperators.hpp:231
const matrix_type & getmat() const override
Definition: WellOperators.hpp:263
WellModelMatrixAdapter(const M &A, const LinearOperatorExtra< X, Y > &wellOper)
constructor: just store a reference to a matrix
Definition: WellOperators.hpp:239
const LinearOperatorExtra< X, Y > & wellOper_
Definition: WellOperators.hpp:288
void applyscaleadd(field_type alpha, const X &x, Y &y) const override
Definition: WellOperators.hpp:254
X domain_type
Definition: WellOperators.hpp:228
Dune::SolverCategory::Category category() const override
Definition: WellOperators.hpp:233
Definition: fvbaseprimaryvariables.hh:161
Definition: blackoilbioeffectsmodules.hh:45