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,
64 const bool contract_d_diagonal) const = 0;
65 virtual void addWellPressureEquationsStruct(PressureMatrix& jacobian) const = 0;
66 virtual int getNumberOfExtraEquations() const = 0;
67};
68
69template <class WellModel, class X, class Y>
71{
72public:
74 using field_type = typename Base::field_type;
76 explicit WellModelAsLinearOperator(const WellModel& wm)
77 : wellMod_(wm)
78 {
79 }
80
85 void apply(const X& x, Y& y) const override
86 {
87 OPM_TIMEBLOCK(apply);
88 for (const auto& well : this->wellMod_) {
89 this->applySingleWell(x, y, well, well->cells());
90 }
91 }
92
94 void applyscaleadd(field_type alpha, const X& x, Y& y) const override
95 {
96 OPM_TIMEBLOCK(applyscaleadd);
97 if (this->wellMod_.empty()) {
98 return;
99 }
100
101 if (scaleAddRes_.size() != y.size()) {
102 scaleAddRes_.resize(y.size());
103 }
104
105 scaleAddRes_ = 0.0;
106 // scaleAddRes_ = - C D^-1 B x
108 // Ax = Ax + alpha * scaleAddRes_
109 y.axpy(alpha, scaleAddRes_);
110 }
111
117 Dune::SolverCategory::Category category() const override
118 {
119 return Dune::SolverCategory::sequential;
120 }
121
123 const X& weights,
124 const bool use_well_weights,
125 const bool contract_d_diagonal) const override
126 {
127 OPM_TIMEBLOCK(addWellPressureEquations);
128 wellMod_.addWellPressureEquations(jacobian, weights, use_well_weights, contract_d_diagonal);
129 }
130
131 void addWellPressureEquationsStruct(PressureMatrix& jacobian) const override
132 {
133 OPM_TIMEBLOCK(addWellPressureEquationsStruct);
134 wellMod_.addWellPressureEquationsStruct(jacobian);
135 }
136
137 int getNumberOfExtraEquations() const override
138 {
139 return wellMod_.numLocalWellsEnd();
140 }
141
142protected:
143 const WellModel& wellMod_;
144
145 template<class WellType, class ArrayType>
146 void applySingleWell(const X& x, Y& y,
147 const WellType& well,
148 const ArrayType& cells) const
149 {
150 // Well equations B and C uses only the perforated cells, so need to apply on local vectors
151 x_local_.resize(cells.size());
152 Ax_local_.resize(cells.size());
153
154 for (size_t i = 0; i < cells.size(); ++i) {
155 x_local_[i] = x[cells[i]];
156 Ax_local_[i] = y[cells[i]];
157 }
158
159 well->apply(x_local_, Ax_local_);
160
161 for (size_t i = 0; i < cells.size(); ++i) {
162 // only need to update Ax
163 y[cells[i]] = Ax_local_[i];
164 }
165
166 }
167
168 // These members are used to avoid reallocation.
169 // Their state is not relevant between function calls, so they can
170 // (and must) be mutable, as the functions using them are const.
171 mutable X x_local_{};
172 mutable Y Ax_local_{};
173 mutable Y scaleAddRes_{};
174};
175
176template <class WellModel, class X, class Y>
178{
179public:
181 using WBase::WBase; // inherit all constructors from the base class
184
185 void setDomainIndex(int index) { domainIndex_ = index; }
186
187 void apply(const X& x, Y& y) const override
188 {
189 OPM_TIMEBLOCK(apply);
190 std::size_t well_index = 0;
191 for (const auto& well : this->wellMod_) {
192 if (this->wellMod_.well_domain().at(well->name()) == domainIndex_) {
193 this->applySingleWell(x, y, well,
194 this->wellMod_.well_local_cells()[well_index]);
195 }
196 ++well_index;
197 }
198 }
199
201 const X& weights,
202 const bool use_well_weights,
203 const bool contract_d_diagonal) const override
204 {
205 OPM_TIMEBLOCK(addWellPressureEquations);
206 this->wellMod_.addWellPressureEquationsDomain(jacobian,
207 weights,
208 use_well_weights,
209 contract_d_diagonal,
210 domainIndex_);
211 }
212
213private:
214 int domainIndex_ = -1;
215};
216
227template<class M, class X, class Y>
228class WellModelMatrixAdapter : public Dune::AssembledLinearOperator<M,X,Y>
229{
230public:
231 using matrix_type = M;
232 using domain_type = X;
233 using range_type = Y;
234 using field_type = typename X::field_type;
235 using PressureMatrix = Dune::BCRSMatrix<MatrixBlock<field_type, 1, 1>>;
236
237 Dune::SolverCategory::Category category() const override
238 {
239 return Dune::SolverCategory::sequential;
240 }
241
244 const LinearOperatorExtra<X, Y>& wellOper)
245 : A_( A ), wellOper_( wellOper )
246 {}
247
248 void apply( const X& x, Y& y ) const override
249 {
250 OPM_TIMEBLOCK(apply);
251 A_.mv(x, y);
252
253 // add well model modification to y
254 wellOper_.apply(x, y);
255 }
256
257 // y += \alpha * A * x
258 void applyscaleadd (field_type alpha, const X& x, Y& y) const override
259 {
260 OPM_TIMEBLOCK(applyscaleadd);
261 A_.usmv(alpha, x, y);
262
263 // add scaled well model modification to y
264 wellOper_.applyscaleadd(alpha, x, y);
265 }
266
267 const matrix_type& getmat() const override { return A_; }
268
270
272 const X& weights,
273 const bool use_well_weights,
274 const bool contract_d_diagonal) const
275 {
276 OPM_TIMEBLOCK(addWellPressureEquations);
277 wellOper_.addWellPressureEquations(jacobian, weights, use_well_weights, contract_d_diagonal);
278 }
279
281 {
282 OPM_TIMEBLOCK(addWellPressureEquations);
283 wellOper_.addWellPressureEquationsStruct(jacobian);
284 }
285
287 {
288 return wellOper_.getNumberOfExtraEquations();
289 }
290
291protected:
294};
295
304template<class M, class X, class Y, bool overlapping >
305class WellModelGhostLastMatrixAdapter : public Dune::AssembledLinearOperator<M,X,Y>
306{
307public:
308 using matrix_type = M;
309 using domain_type = X;
310 using range_type = Y;
311 using field_type = typename X::field_type;
312 using PressureMatrix = Dune::BCRSMatrix<MatrixBlock<field_type, 1, 1>>;
313#if HAVE_MPI
314 using communication_type = Dune::OwnerOverlapCopyCommunication<int,int>;
315#else
316 using communication_type = Dune::Communication<int>;
317#endif
318
319 Dune::SolverCategory::Category category() const override
320 {
321 return overlapping ?
322 Dune::SolverCategory::overlapping : Dune::SolverCategory::sequential;
323 }
324
327 const LinearOperatorExtra<X, Y>& wellOper,
328 const std::size_t interiorSize )
329 : A_( A ), wellOper_( wellOper ), interiorSize_(interiorSize)
330 {}
331
332 void apply(const X& x, Y& y) const override
333 {
334 OPM_TIMEBLOCK(apply);
335 for (auto row = A_.begin(); row.index() < interiorSize_; ++row)
336 {
337 y[row.index()]=0;
338 auto endc = (*row).end();
339 for (auto col = (*row).begin(); col != endc; ++col)
340 (*col).umv(x[col.index()], y[row.index()]);
341 }
342
343 // add well model modification to y
344 wellOper_.apply(x, y);
345
347 }
348
349 // y += \alpha * A * x
350 void applyscaleadd (field_type alpha, const X& x, Y& y) const override
351 {
352 OPM_TIMEBLOCK(applyscaleadd);
353 for (auto row = A_.begin(); row.index() < interiorSize_; ++row)
354 {
355 auto endc = (*row).end();
356 for (auto col = (*row).begin(); col != endc; ++col)
357 (*col).usmv(alpha, x[col.index()], y[row.index()]);
358 }
359 // add scaled well model modification to y
360 wellOper_.applyscaleadd(alpha, x, y);
361
363 }
364
365 const matrix_type& getmat() const override { return A_; }
366
368
370 const X& weights,
371 const bool use_well_weights,
372 const bool contract_d_diagonal) const
373 {
374 OPM_TIMEBLOCK(addWellPressureEquations);
375 wellOper_.addWellPressureEquations(jacobian, weights, use_well_weights, contract_d_diagonal);
376 }
377
379 {
380 OPM_TIMEBLOCK(addWellPressureEquationsStruct);
381 wellOper_.addWellPressureEquationsStruct(jacobian);
382 }
383
385 {
386 return wellOper_.getNumberOfExtraEquations();
387 }
388
389protected:
390 void ghostLastProject(Y& y) const
391 {
392 std::size_t end = y.size();
393 for (std::size_t i = interiorSize_; i < end; ++i)
394 y[i] = 0;
395 }
396
399 std::size_t interiorSize_;
400};
401
410template<class M, class X, class Y, class C>
411class GhostLastMatrixAdapter : public Dune::AssembledLinearOperator<M,X,Y>
412{
413public:
414 typedef M matrix_type;
415 typedef X domain_type;
416 typedef Y range_type;
417 typedef typename X::field_type field_type;
418
419
421
422 Dune::SolverCategory::Category category() const override
423 {
424 return Dune::SolverCategory::overlapping;
425 }
426
429 const communication_type& comm)
430 : A_( Dune::stackobject_to_shared_ptr(A) ), comm_(comm)
431 {
432 interiorSize_ = setInteriorSize(comm_);
433 }
434
435 GhostLastMatrixAdapter (const std::shared_ptr<M> A,
436 const communication_type& comm)
437 : A_( A ), comm_(comm)
438 {
439 interiorSize_ = setInteriorSize(comm_);
440 }
441
442 void apply( const X& x, Y& y ) const override
443 {
444 for (auto row = A_->begin(); row.index() < interiorSize_; ++row)
445 {
446 y[row.index()]=0;
447 auto endc = (*row).end();
448 for (auto col = (*row).begin(); col != endc; ++col)
449 (*col).umv(x[col.index()], y[row.index()]);
450 }
451
452 ghostLastProject( y );
453 }
454
455 // y += \alpha * A * x
456 void applyscaleadd (field_type alpha, const X& x, Y& y) const override
457 {
458 for (auto row = A_->begin(); row.index() < interiorSize_; ++row)
459 {
460 auto endc = (*row).end();
461 for (auto col = (*row).begin(); col != endc; ++col)
462 (*col).usmv(alpha, x[col.index()], y[row.index()]);
463 }
464
465 ghostLastProject( y );
466 }
467
468 const matrix_type& getmat() const override { return *A_; }
469
470 size_t getInteriorSize() const { return interiorSize_;}
471
472private:
473 void ghostLastProject(Y& y) const
474 {
475 size_t end = y.size();
476 for (size_t i = interiorSize_; i < end; ++i)
477 y[i] = 0; //project to interiorsize, i.e. ignore ghost
478 }
479
480 size_t setInteriorSize(const communication_type& comm) const
481 {
482 auto indexSet = comm.indexSet();
483 if (indexSet.size() == 0)
484 return 0;
485
486 size_t is = 0;
487 // Loop over index set
488 for (auto idx = indexSet.begin(); idx!=indexSet.end(); ++idx) {
489 //Only take "owner" indices
490 if (idx->local().attribute()==1) {
491 //get local index
492 auto loc = idx->local().local();
493 // if loc is higher than "old interior size", update it
494 if (loc > is) {
495 is = loc;
496 }
497 }
498 }
499 return is + 1; //size is plus 1 since we start at 0, except when indexSet is empty
500 }
501 const std::shared_ptr<const matrix_type> A_ ;
502 const communication_type& comm_;
503 size_t interiorSize_;
504};
505
506} // namespace Opm
507
508namespace Dune {
509namespace Amg {
510
511template<class M, class X, class Y, class C>
512class ConstructionTraits<Opm::GhostLastMatrixAdapter<M,X,Y,C> >
513{
514public:
515 typedef ParallelOperatorArgs<M,C> Arguments;
516
517 static inline std::shared_ptr<Opm::GhostLastMatrixAdapter<M,X,Y,C>> construct(const Arguments& args)
518 {
519 return std::make_shared<Opm::GhostLastMatrixAdapter<M,X,Y,C>>
520 (args.matrix_, args.comm_);
521 }
522};
523
524} // end namespace Amg
525} // end namespace Dune
526
527#endif // OPM_WELLOPERATORS_HEADER_INCLUDED
static std::shared_ptr< Opm::GhostLastMatrixAdapter< M, X, Y, C > > construct(const Arguments &args)
Definition: WellOperators.hpp:517
ParallelOperatorArgs< M, C > Arguments
Definition: WellOperators.hpp:515
Definition: WellOperators.hpp:178
void addWellPressureEquations(PressureMatrix &jacobian, const X &weights, const bool use_well_weights, const bool contract_d_diagonal) const override
Definition: WellOperators.hpp:200
void setDomainIndex(int index)
Definition: WellOperators.hpp:185
void apply(const X &x, Y &y) const override
Definition: WellOperators.hpp:187
Dune linear operator that assumes ghost rows are ordered after interior rows. Avoids some computation...
Definition: WellOperators.hpp:412
C communication_type
Definition: WellOperators.hpp:420
M matrix_type
Definition: WellOperators.hpp:414
void applyscaleadd(field_type alpha, const X &x, Y &y) const override
Definition: WellOperators.hpp:456
Dune::SolverCategory::Category category() const override
Definition: WellOperators.hpp:422
const matrix_type & getmat() const override
Definition: WellOperators.hpp:468
X::field_type field_type
Definition: WellOperators.hpp:417
void apply(const X &x, Y &y) const override
Definition: WellOperators.hpp:442
X domain_type
Definition: WellOperators.hpp:415
GhostLastMatrixAdapter(const std::shared_ptr< M > A, const communication_type &comm)
Definition: WellOperators.hpp:435
GhostLastMatrixAdapter(const M &A, const communication_type &comm)
constructor: just store a reference to a matrix
Definition: WellOperators.hpp:428
Y range_type
Definition: WellOperators.hpp:416
size_t getInteriorSize() const
Definition: WellOperators.hpp:470
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 bool contract_d_diagonal) 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:71
typename Base::PressureMatrix PressureMatrix
Definition: WellOperators.hpp:75
const WellModel & wellMod_
Definition: WellOperators.hpp:143
Y Ax_local_
Definition: WellOperators.hpp:172
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:85
WellModelAsLinearOperator(const WellModel &wm)
Definition: WellOperators.hpp:76
X x_local_
Definition: WellOperators.hpp:171
typename Base::field_type field_type
Definition: WellOperators.hpp:74
void addWellPressureEquations(PressureMatrix &jacobian, const X &weights, const bool use_well_weights, const bool contract_d_diagonal) const override
Definition: WellOperators.hpp:122
void applySingleWell(const X &x, Y &y, const WellType &well, const ArrayType &cells) const
Definition: WellOperators.hpp:146
void applyscaleadd(field_type alpha, const X &x, Y &y) const override
apply operator to x, scale and add:
Definition: WellOperators.hpp:94
Dune::SolverCategory::Category category() const override
Definition: WellOperators.hpp:117
int getNumberOfExtraEquations() const override
Definition: WellOperators.hpp:137
void addWellPressureEquationsStruct(PressureMatrix &jacobian) const override
Definition: WellOperators.hpp:131
Y scaleAddRes_
Definition: WellOperators.hpp:173
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:306
const LinearOperatorExtra< X, Y > & getwellOper() const
Definition: WellOperators.hpp:367
void addWellPressureEquationsStruct(PressureMatrix &jacobian) const
Definition: WellOperators.hpp:378
typename X::field_type field_type
Definition: WellOperators.hpp:311
const matrix_type & A_
Definition: WellOperators.hpp:397
const matrix_type & getmat() const override
Definition: WellOperators.hpp:365
Dune::SolverCategory::Category category() const override
Definition: WellOperators.hpp:319
void apply(const X &x, Y &y) const override
Definition: WellOperators.hpp:332
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:326
Dune::OwnerOverlapCopyCommunication< int, int > communication_type
Definition: WellOperators.hpp:314
void addWellPressureEquations(PressureMatrix &jacobian, const X &weights, const bool use_well_weights, const bool contract_d_diagonal) const
Definition: WellOperators.hpp:369
Dune::BCRSMatrix< MatrixBlock< field_type, 1, 1 > > PressureMatrix
Definition: WellOperators.hpp:312
X domain_type
Definition: WellOperators.hpp:309
void applyscaleadd(field_type alpha, const X &x, Y &y) const override
Definition: WellOperators.hpp:350
int getNumberOfExtraEquations() const
Definition: WellOperators.hpp:384
Y range_type
Definition: WellOperators.hpp:310
std::size_t interiorSize_
Definition: WellOperators.hpp:399
const LinearOperatorExtra< X, Y > & wellOper_
Definition: WellOperators.hpp:398
M matrix_type
Definition: WellOperators.hpp:308
void ghostLastProject(Y &y) const
Definition: WellOperators.hpp:390
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:229
Y range_type
Definition: WellOperators.hpp:233
const matrix_type & A_
Definition: WellOperators.hpp:292
void addWellPressureEquationsStruct(PressureMatrix &jacobian) const
Definition: WellOperators.hpp:280
void addWellPressureEquations(PressureMatrix &jacobian, const X &weights, const bool use_well_weights, const bool contract_d_diagonal) const
Definition: WellOperators.hpp:271
int getNumberOfExtraEquations() const
Definition: WellOperators.hpp:286
void apply(const X &x, Y &y) const override
Definition: WellOperators.hpp:248
M matrix_type
Definition: WellOperators.hpp:231
const LinearOperatorExtra< X, Y > & getwellOper() const
Definition: WellOperators.hpp:269
typename X::field_type field_type
Definition: WellOperators.hpp:234
Dune::BCRSMatrix< MatrixBlock< field_type, 1, 1 > > PressureMatrix
Definition: WellOperators.hpp:235
const matrix_type & getmat() const override
Definition: WellOperators.hpp:267
WellModelMatrixAdapter(const M &A, const LinearOperatorExtra< X, Y > &wellOper)
constructor: just store a reference to a matrix
Definition: WellOperators.hpp:243
const LinearOperatorExtra< X, Y > & wellOper_
Definition: WellOperators.hpp:293
void applyscaleadd(field_type alpha, const X &x, Y &y) const override
Definition: WellOperators.hpp:258
X domain_type
Definition: WellOperators.hpp:232
Dune::SolverCategory::Category category() const override
Definition: WellOperators.hpp:237
Definition: fvbaseprimaryvariables.hh:161
Definition: blackoilbioeffectsmodules.hh:45