ConvergenceReport.hpp
Go to the documentation of this file.
1/*
2 Copyright 2018 SINTEF Digital, Mathematics and Cybernetics.
3 Copyright 2018, 2024 Equinor.
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#ifndef OPM_CONVERGENCEREPORT_HEADER_INCLUDED
22#define OPM_CONVERGENCEREPORT_HEADER_INCLUDED
23
24#include <algorithm>
25#include <cassert>
26#include <numeric>
27#include <string>
28#include <utility>
29#include <vector>
30
31namespace Opm
32{
33
38 {
39 public:
40
41 // ----------- Types -----------
42
43 enum Status {
46 WellFailed = 1 << 1,
47 };
48 // More severe problems should have higher numbers
49 enum struct Severity {
50 None = 0,
51 Normal = 1,
52 ConvergenceMonitorFailure = 2,
53 TooLarge = 3,
54 NotANumber = 4,
55 };
56
57 struct PenaltyCard {
61
62 int total() const {
64 }
65
66 void reset()
67 {
68 nonConverged = 0;
69 distanceDecay = 0;
71 }
72
77 return *this;
78 }
79
80 template <typename Serializer>
81 void serializeOp(Serializer& serializer)
82 {
83 serializer(nonConverged);
84 serializer(distanceDecay);
85 serializer(largeWellResiduals);
86 }
87 };
88
89 using CnvPvSplit = std::pair<
90 std::vector<double>,
91 std::vector<int>>;
92
94 {
95 public:
96 enum struct Type { Invalid, MassBalance, Cnv, ConvergenceMonitorFailure };
97
98 // Default constructor needed for object serialisation. Don't
99 // use this for anything else.
100 ReservoirFailure() = default;
101
103 : type_(t), severity_(s), phase_(phase)
104 {}
105
106 Type type() const { return type_; }
107 Severity severity() const { return severity_; }
108 int phase() const { return phase_; }
109
110 template <typename Serializer>
111 void serializeOp(Serializer& serializer)
112 {
113 serializer(this->type_);
114 serializer(this->severity_);
115 serializer(this->phase_);
116 }
117
118 private:
119 // Note to maintainers: If you change this list of data members,
120 // then please update serializeOp() accordingly.
121 Type type_ { Type::Invalid };
122 Severity severity_ { Severity::None };
123 int phase_ { -1 };
124 };
125
127 {
128 public:
129 // Default constructor needed for object serialisation. Don't
130 // use this for anything else.
132
134 : type_(t), phase_(phase), value_(value), tolerance_(tolerance)
135 {}
136
137 ReservoirFailure::Type type() const { return type_; }
138 int phase() const { return phase_; }
139 double value() const { return value_; }
140 double tolerance() const { return tolerance_; }
141
142 template <typename Serializer>
143 void serializeOp(Serializer& serializer)
144 {
145 serializer(this->type_);
146 serializer(this->phase_);
147 serializer(this->value_);
148 serializer(this->tolerance_);
149 }
150
151 private:
152 // Note to maintainers: If you change this list of data members,
153 // then please update serializeOp() accordingly.
155 int phase_ { -1 };
156 double value_ { 0.0 };
157 double tolerance_ { 0.0 };
158 };
159
161 {
162 public:
163 enum struct Type {
164 Invalid,
165 MassBalance,
166 Pressure,
167 Energy,
168 ControlBHP,
169 ControlTHP,
170 ControlRate,
171 Unsolvable,
172 WrongFlowDirection,
173 };
174
175 // Default constructor needed for object serialisation. Don't
176 // use this for anything else.
177 WellFailure() = default;
178
179 WellFailure(Type t, Severity s, int phase, const std::string& well_name)
180 : type_(t), severity_(s), phase_(phase), well_name_(well_name)
181 {}
182
183 Type type() const { return type_; }
184 Severity severity() const { return severity_; }
185 int phase() const { return phase_; }
186 const std::string& wellName() const { return well_name_; }
187
188 template <typename Serializer>
189 void serializeOp(Serializer& serializer)
190 {
191 serializer(this->type_);
192 serializer(this->severity_);
193 serializer(this->phase_);
194 serializer(this->well_name_);
195 }
196
197 private:
198 // Note to maintainers: If you change this list of data members,
199 // then please update serializeOp() accordingly.
200 Type type_ { Type::Invalid };
201 Severity severity_ { Severity::None };
202 int phase_ { -1 };
203 std::string well_name_ {};
204 };
205
207 {
208 public:
209 // Default constructor needed for object serialisation. Don't
210 // use this for anything else.
212
213 WellConvergenceMetric(WellFailure::Type t, Severity s, int phase, double value, const std::string& well_name)
214 : type_(t), severity_(s), phase_(phase), value_(value), well_name_(well_name)
215 {}
216
217 WellFailure::Type type() const { return type_; }
218 Severity severity() const { return severity_; }
219 int phase() const { return phase_; }
220 double value() const { return value_; }
221 const std::string& wellName() const { return well_name_; }
222
223 template <typename Serializer>
224 void serializeOp(Serializer& serializer)
225 {
226 serializer(this->type_);
227 serializer(this->severity_);
228 serializer(this->phase_);
229 serializer(this->value_);
230 serializer(this->well_name_);
231 }
232
233 private:
234 // Note to maintainers: If you change this list of data members,
235 // then please update serializeOp() accordingly.
237 Severity severity_ { Severity::None };
238 int phase_ { -1 };
239 double value_ { 0.0 };
240 std::string well_name_ {};
241 };
242
243 // ----------- Mutating member functions -----------
244
246 : ConvergenceReport{0.0}
247 {}
248
249 explicit ConvergenceReport(const double reportTime)
250 : reportTime_{reportTime}
251 , status_{AllGood}
252 , res_failures_{}
253 , well_failures_{}
254 , wellGroupTargetsViolated_(false)
255 , network_needs_more_balancing_force_another_newton_iteration_(false)
256 {}
257
258 void clear()
259 {
260 status_ = AllGood;
261 res_failures_.clear();
262 well_failures_.clear();
263 wellGroupTargetsViolated_ = false;
264 network_needs_more_balancing_force_another_newton_iteration_ = false;
265 }
266
268 {
269 status_ = static_cast<Status>(status_ | ReservoirFailed);
270 res_failures_.push_back(rf);
271 }
272
274 {
275 status_ = static_cast<Status>(status_ | WellFailed);
276 well_failures_.push_back(wf);
277 }
278
279 template <typename... Args>
280 void setReservoirConvergenceMetric(Args&&... args)
281 {
282 this->res_convergence_.emplace_back(std::forward<Args>(args)...);
283 }
284
285 template <typename... Args>
286 void setWellConvergenceMetric(Args&&... args)
287 {
288 this->well_convergence_.emplace_back(std::forward<Args>(args)...);
289 }
290
291 void setWellGroupTargetsViolated(const bool wellGroupTargetsViolated)
292 {
293 wellGroupTargetsViolated_ = wellGroupTargetsViolated;
294 }
295
296 void setNetworkNotYetBalancedForceAnotherNewtonIteration(const bool network_needs_more_balancing_force_another_newton_iteration)
297 {
298 network_needs_more_balancing_force_another_newton_iteration_ = network_needs_more_balancing_force_another_newton_iteration;
299 }
300
302 const double eligiblePoreVolume)
303 {
304 this->cnvPvSplit_ = cnvPvSplit;
305 this->eligiblePoreVolume_ = eligiblePoreVolume;
306 }
307
309 {
310 reportTime_ = std::max(reportTime_, other.reportTime_);
311 status_ = static_cast<Status>(status_ | other.status_);
312 res_failures_.insert(res_failures_.end(), other.res_failures_.begin(), other.res_failures_.end());
313 well_failures_.insert(well_failures_.end(), other.well_failures_.begin(), other.well_failures_.end());
314 res_convergence_.insert(res_convergence_.end(), other.res_convergence_.begin(), other.res_convergence_.end());
315 well_convergence_.insert(well_convergence_.end(), other.well_convergence_.begin(), other.well_convergence_.end());
316 assert(reservoirFailed() != res_failures_.empty());
317 assert(wellFailed() != well_failures_.empty());
318 wellGroupTargetsViolated_ = (wellGroupTargetsViolated_ || other.wellGroupTargetsViolated_);
319 network_needs_more_balancing_force_another_newton_iteration_ = (network_needs_more_balancing_force_another_newton_iteration_
320 || other.network_needs_more_balancing_force_another_newton_iteration_);
321
322 // Note regarding the CNV pore-volume split: We depend on the
323 // fact that the quantities have already been aggregated across
324 // all MPI ranks--see the implementation of member function
325 // NonlinearSystemBlackOilReservoir::getReservoirConvergence() for details--and are
326 // therefore equal on all ranks. Consequently, we simply assign
327 // 'other's values here, if it is non-empty. Empty splits
328 // typically come from well contributions.
329 if (! other.cnvPvSplit_.first.empty()) {
330 this->cnvPvSplit_ = other.cnvPvSplit_;
331 this->eligiblePoreVolume_ = other.eligiblePoreVolume_;
332 }
333
334 return *this;
335 }
336
337 // ----------- Const member functions (queries) -----------
338
339 double reportTime() const
340 {
341 return reportTime_;
342 }
343
344 double eligiblePoreVolume() const
345 {
346 return this->eligiblePoreVolume_;
347 }
348
349 const CnvPvSplit& cnvPvSplit() const
350 {
351 return this->cnvPvSplit_;
352 }
353
354 bool converged() const
355 {
356 return (status_ == AllGood)
357 && !wellGroupTargetsViolated_
358 && !network_needs_more_balancing_force_another_newton_iteration_;
359 }
360
361 bool reservoirFailed() const
362 {
363 return status_ & ReservoirFailed;
364 }
365
366 bool wellFailed() const
367 {
368 return status_ & WellFailed;
369 }
370
371 const std::vector<ReservoirFailure>& reservoirFailures() const
372 {
373 return res_failures_;
374 }
375
376 const std::vector<ReservoirConvergenceMetric>& reservoirConvergence() const
377 {
378 return res_convergence_;
379 }
380
381 const std::vector<WellFailure>& wellFailures() const
382 {
383 return well_failures_;
384 }
385
386 const std::vector<WellConvergenceMetric>& wellConvergence() const
387 {
388 return well_convergence_;
389 }
390
392 {
393 return penaltyCard_;
394 }
395
397 {
398 penaltyCard_.nonConverged++;
399 }
400
402 {
403 penaltyCard_.distanceDecay++;
404 }
405
407 {
408 penaltyCard_.largeWellResiduals++;
409 }
410
412 {
413 // A function to get the worst of two severities.
414 auto smax = [](Severity s1, Severity s2) {
415 return s1 < s2 ? s2 : s1;
416 };
417 auto s = Severity::None;
418 for (const auto& f : res_failures_) {
419 s = smax(s, f.severity());
420 }
421 for (const auto& f : well_failures_) {
422 s = smax(s, f.severity());
423 }
424 return s;
425 }
426
427 template <typename Serializer>
428 void serializeOp(Serializer& serializer)
429 {
430 serializer(this->reportTime_);
431 serializer(this->status_);
432 serializer(this->res_failures_);
433 serializer(this->well_failures_);
434 serializer(this->res_convergence_);
435 serializer(this->well_convergence_);
436 serializer(this->wellGroupTargetsViolated_);
437 serializer(this->network_needs_more_balancing_force_another_newton_iteration_);
438 serializer(this->cnvPvSplit_);
439 serializer(this->eligiblePoreVolume_);
440 serializer(this->penaltyCard_);
441 }
442
443 private:
444 // ----------- Member variables -----------
445 // Note to maintainers: If you change this list of data members,
446 // then please update serializeOp() accordingly.
447 double reportTime_;
448 Status status_;
449 std::vector<ReservoirFailure> res_failures_;
450 std::vector<WellFailure> well_failures_;
451 std::vector<ReservoirConvergenceMetric> res_convergence_;
452 std::vector<WellConvergenceMetric> well_convergence_;
453 bool wellGroupTargetsViolated_;
454 bool network_needs_more_balancing_force_another_newton_iteration_;
455 CnvPvSplit cnvPvSplit_{};
456 double eligiblePoreVolume_{};
457 PenaltyCard penaltyCard_;
458 };
459
461 {
464 std::vector<ConvergenceReport> report;
465 };
466
468
470
472
474
476
477
478
479} // namespace Opm
480
481#endif // OPM_CONVERGENCEREPORT_HEADER_INCLUDED
Definition: ConvergenceReport.hpp:127
int phase() const
Definition: ConvergenceReport.hpp:138
double value() const
Definition: ConvergenceReport.hpp:139
ReservoirFailure::Type type() const
Definition: ConvergenceReport.hpp:137
void serializeOp(Serializer &serializer)
Definition: ConvergenceReport.hpp:143
double tolerance() const
Definition: ConvergenceReport.hpp:140
ReservoirConvergenceMetric(ReservoirFailure::Type t, int phase, double value, double tolerance)
Definition: ConvergenceReport.hpp:133
Definition: ConvergenceReport.hpp:94
int phase() const
Definition: ConvergenceReport.hpp:108
void serializeOp(Serializer &serializer)
Definition: ConvergenceReport.hpp:111
Type
Definition: ConvergenceReport.hpp:96
ReservoirFailure(Type t, Severity s, int phase)
Definition: ConvergenceReport.hpp:102
Type type() const
Definition: ConvergenceReport.hpp:106
Severity severity() const
Definition: ConvergenceReport.hpp:107
Definition: ConvergenceReport.hpp:207
WellConvergenceMetric(WellFailure::Type t, Severity s, int phase, double value, const std::string &well_name)
Definition: ConvergenceReport.hpp:213
int phase() const
Definition: ConvergenceReport.hpp:219
void serializeOp(Serializer &serializer)
Definition: ConvergenceReport.hpp:224
double value() const
Definition: ConvergenceReport.hpp:220
WellFailure::Type type() const
Definition: ConvergenceReport.hpp:217
const std::string & wellName() const
Definition: ConvergenceReport.hpp:221
Severity severity() const
Definition: ConvergenceReport.hpp:218
Definition: ConvergenceReport.hpp:161
const std::string & wellName() const
Definition: ConvergenceReport.hpp:186
Type
Definition: ConvergenceReport.hpp:163
int phase() const
Definition: ConvergenceReport.hpp:185
Severity severity() const
Definition: ConvergenceReport.hpp:184
WellFailure(Type t, Severity s, int phase, const std::string &well_name)
Definition: ConvergenceReport.hpp:179
Type type() const
Definition: ConvergenceReport.hpp:183
void serializeOp(Serializer &serializer)
Definition: ConvergenceReport.hpp:189
Definition: ConvergenceReport.hpp:38
ConvergenceReport()
Definition: ConvergenceReport.hpp:245
Severity severityOfWorstFailure() const
Definition: ConvergenceReport.hpp:411
const std::vector< ReservoirConvergenceMetric > & reservoirConvergence() const
Definition: ConvergenceReport.hpp:376
void addDistanceDecayPenalty()
Definition: ConvergenceReport.hpp:401
void setWellFailed(const WellFailure &wf)
Definition: ConvergenceReport.hpp:273
void setWellGroupTargetsViolated(const bool wellGroupTargetsViolated)
Definition: ConvergenceReport.hpp:291
bool reservoirFailed() const
Definition: ConvergenceReport.hpp:361
const PenaltyCard & getPenaltyCard() const
Definition: ConvergenceReport.hpp:391
const CnvPvSplit & cnvPvSplit() const
Definition: ConvergenceReport.hpp:349
const std::vector< WellConvergenceMetric > & wellConvergence() const
Definition: ConvergenceReport.hpp:386
void setReservoirConvergenceMetric(Args &&... args)
Definition: ConvergenceReport.hpp:280
Severity
Definition: ConvergenceReport.hpp:49
double reportTime() const
Definition: ConvergenceReport.hpp:339
void clear()
Definition: ConvergenceReport.hpp:258
ConvergenceReport(const double reportTime)
Definition: ConvergenceReport.hpp:249
void addNonConvergedPenalty()
Definition: ConvergenceReport.hpp:396
bool converged() const
Definition: ConvergenceReport.hpp:354
Status
Definition: ConvergenceReport.hpp:43
@ ReservoirFailed
Definition: ConvergenceReport.hpp:45
@ AllGood
Definition: ConvergenceReport.hpp:44
@ WellFailed
Definition: ConvergenceReport.hpp:46
const std::vector< ReservoirFailure > & reservoirFailures() const
Definition: ConvergenceReport.hpp:371
const std::vector< WellFailure > & wellFailures() const
Definition: ConvergenceReport.hpp:381
void addLargeWellResidualsPenalty()
Definition: ConvergenceReport.hpp:406
void setReservoirFailed(const ReservoirFailure &rf)
Definition: ConvergenceReport.hpp:267
ConvergenceReport & operator+=(const ConvergenceReport &other)
Definition: ConvergenceReport.hpp:308
void setNetworkNotYetBalancedForceAnotherNewtonIteration(const bool network_needs_more_balancing_force_another_newton_iteration)
Definition: ConvergenceReport.hpp:296
bool wellFailed() const
Definition: ConvergenceReport.hpp:366
void serializeOp(Serializer &serializer)
Definition: ConvergenceReport.hpp:428
void setCnvPoreVolSplit(const CnvPvSplit &cnvPvSplit, const double eligiblePoreVolume)
Definition: ConvergenceReport.hpp:301
std::pair< std::vector< double >, std::vector< int > > CnvPvSplit
Definition: ConvergenceReport.hpp:91
double eligiblePoreVolume() const
Definition: ConvergenceReport.hpp:344
void setWellConvergenceMetric(Args &&... args)
Definition: ConvergenceReport.hpp:286
Definition: blackoilbioeffectsmodules.hh:45
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
Definition: ConvergenceReport.hpp:57
void serializeOp(Serializer &serializer)
Definition: ConvergenceReport.hpp:81
int nonConverged
Definition: ConvergenceReport.hpp:58
int total() const
Definition: ConvergenceReport.hpp:62
int largeWellResiduals
Definition: ConvergenceReport.hpp:60
PenaltyCard & operator+=(const PenaltyCard &other)
Definition: ConvergenceReport.hpp:73
void reset()
Definition: ConvergenceReport.hpp:66
int distanceDecay
Definition: ConvergenceReport.hpp:59
Definition: ConvergenceReport.hpp:461
std::vector< ConvergenceReport > report
Definition: ConvergenceReport.hpp:464
int report_step
Definition: ConvergenceReport.hpp:462
int current_step
Definition: ConvergenceReport.hpp:463