BlackoilWellModelNldd_impl.hpp
Go to the documentation of this file.
1/*
2 Copyright 2016 - 2019 SINTEF Digital, Mathematics & Cybernetics.
3 Copyright 2016 - 2018 Equinor ASA.
4 Copyright 2017 Dr. Blatt - HPC-Simulation-Software & Services
5 Copyright 2016 - 2018 Norce AS
6
7 This file is part of the Open Porous Media project (OPM).
8
9 OPM is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 OPM is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with OPM. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#ifndef OPM_BLACKOILWELLMODEL_NLDD_IMPL_HEADER_INCLUDED
24#define OPM_BLACKOILWELLMODEL_NLDD_IMPL_HEADER_INCLUDED
25
26// Improve IDE experience
27#ifndef OPM_BLACKOILWELLMODEL_NLDD_HEADER_INCLUDED
28#include <config.h>
30#endif
31
32#include <algorithm>
33
34namespace Opm {
35
36template<typename TypeTag>
37void
39assemble(const int /*iterationIdx*/,
40 const double dt,
41 const Domain& domain)
42{
43 OPM_TIMEBLOCK(assemble);
44 // We assume that calculateExplicitQuantities() and
45 // prepareTimeStep() have been called already for the entire
46 // well model, so we do not need to do it here (when
47 // iterationIdx is 0).
48
49 // Use do_mpi_gather=false to avoid MPI collective operations in domain solves.
50 auto loggerGuard = wellModel_.groupStateHelper().pushLogger(/*do_mpi_gather=*/false);
51
52 this->updateWellControls(domain);
53 this->assembleWellEq(dt, domain);
54
55 // Update cellRates_ with current contributions from wells in this domain for reservoir linearization
56 wellModel_.updateCellRatesForDomain(domain.index, this->well_domain());
57}
58
59template<typename TypeTag>
60void
62assembleWellEq(const double dt,
63 const Domain& domain)
64{
65 OPM_TIMEBLOCK(assembleWellEq);
66 for (const auto& well : wellModel_.localNonshutWells()) {
67 if (this->well_domain().at(well->name()) == domain.index) {
68 well->assembleWellEq(wellModel_.simulator(),
69 dt,
70 wellModel_.groupStateHelper(),
71 wellModel_.wellState());
72 }
73 }
74}
75
76template<typename TypeTag>
77void
80 const BVector& /*weights*/,
81 const bool /*use_well_weights*/,
82 const int /*domainIndex*/) const
83{
84 throw std::logic_error("CPRW is not yet implemented for NLDD subdomains");
85 // To fix this function, rdofs should be the size of the domain, and the nw should be the number of wells in the domain
86 // int nw = this->numLocalWellsEnd(); // should number of wells in the domain
87 // int rdofs = local_num_cells_; // should be the size of the domain
88 // for ( int i = 0; i < nw; i++ ) {
89 // int wdof = rdofs + i;
90 // jacobian[wdof][wdof] = 1.0;// better scaling ?
91 // }
92
93 // for ( const auto& well : well_container_ ) {
94 // if (well_domain_.at(well->name()) == domainIndex) {
95 // weights should be the size of the domain
96 // well->addWellPressureEquations(jacobian, weights, pressureVarIndex, use_well_weights, this->wellState());
97 // }
98 // }
99}
100
101template<typename TypeTag>
102void
105 const int domainIdx)
106{
107 // Note: no point in trying to do a parallel gathering
108 // try/catch here, as this function is not called in
109 // parallel but for each individual domain of each rank.
110 // Use do_mpi_gather=false to avoid MPI collective operations.
111 auto loggerGuard = wellModel_.groupStateHelper().pushLogger(/*do_mpi_gather=*/false);
112 for (const auto& well : wellModel_.localNonshutWells()) {
113 if (this->well_domain().at(well->name()) == domainIdx) {
114 const auto& cells = well->cells();
115 x_local_.resize(cells.size());
116
117 for (size_t i = 0; i < cells.size(); ++i) {
118 x_local_[i] = x[cells[i]];
119 }
120 well->recoverWellSolutionAndUpdateWellState(wellModel_.simulator(),
121 x_local_,
122 wellModel_.groupStateHelper(),
123 wellModel_.wellState());
124 }
125 }
126}
127
128template<typename TypeTag>
131getWellConvergence(const Domain& domain,
132 const std::vector<Scalar>& B_avg,
133 DeferredLogger& local_deferredLogger) const
134{
135 const int iterationIdx = wellModel_.simulator().model().newtonMethod().numIterations();
136 const bool relax_tolerance = iterationIdx > wellModel_.numStrictIterations();
137
138 ConvergenceReport report;
139 {
140 // Use do_mpi_gather=false to avoid MPI collective operations in domain solves.
141 auto loggerGuard = wellModel_.groupStateHelper().pushLogger(/*do_mpi_gather=*/false);
142
143 for (const auto& well : wellModel_.localNonshutWells()) {
144 if ((this->well_domain().at(well->name()) == domain.index)) {
145 if (well->isOperableAndSolvable() || well->wellIsStopped()) {
146 report += well->getWellConvergence(wellModel_.groupStateHelper(),
147 B_avg,
148 relax_tolerance);
149 } else {
150 ConvergenceReport xreport;
151 using CR = ConvergenceReport;
152 xreport.setWellFailed({CR::WellFailure::Type::Unsolvable,
153 CR::Severity::Normal, -1, well->name()});
154 report += xreport;
155 }
156 }
157 }
158 } // loggerGuard goes out of scope here, before the OpmLog::debug() calls below
159
160 // Log debug messages for NaN or too large residuals.
161 if (wellModel_.terminalOutput()) {
162 for (const auto& f : report.wellFailures()) {
163 if (f.severity() == ConvergenceReport::Severity::NotANumber) {
164 local_deferredLogger.debug("NaN residual found with phase " +
165 std::to_string(f.phase()) +
166 " for well " + f.wellName());
167 } else if (f.severity() == ConvergenceReport::Severity::TooLarge) {
168 local_deferredLogger.debug("Too large residual found with phase " +
169 std::to_string(f.phase()) +
170 " for well " + f.wellName());
171 }
172 }
173 }
174 return report;
175}
176
177template<typename TypeTag>
178void
180updateWellControls(const Domain& domain)
181{
182 OPM_TIMEBLOCK(updateWellControls);
183 if (!wellModel_.wellsActive()) {
184 return;
185 }
186
187 // TODO: decide on and implement an approach to handling of
188 // group controls, network and similar for domain solves.
189
190 // Check only individual well constraints and communicate.
191 for (const auto& well : wellModel_.localNonshutWells()) {
192 if (this->well_domain().at(well->name()) == domain.index) {
194 well->updateWellControl(wellModel_.simulator(),
195 mode,
196 wellModel_.groupStateHelper(),
197 wellModel_.wellState());
198 }
199 }
200}
201
202template <typename TypeTag>
203void
205setupDomains(const std::vector<Domain>& domains)
206{
207 std::vector<const SubDomainIndices*> genDomains;
208 std::transform(domains.begin(), domains.end(),
209 std::back_inserter(genDomains),
210 [](const auto& domain)
211 { return static_cast<const SubDomainIndices*>(&domain); });
212 this->calcDomains(genDomains);
213}
214
215} // namespace Opm
216
217#endif
Class for handling the blackoil well model in a NLDD solver.
Definition: BlackoilWellModelNldd.hpp:80
ConvergenceReport getWellConvergence(const Domain &domain, const std::vector< Scalar > &B_avg, DeferredLogger &local_deferredLogger) const
Definition: BlackoilWellModelNldd_impl.hpp:131
void assemble(const int iterationIdx, const double dt, const Domain &domain)
Definition: BlackoilWellModelNldd_impl.hpp:39
void recoverWellSolutionAndUpdateWellState(const BVector &x, const int domainIdx)
Definition: BlackoilWellModelNldd_impl.hpp:104
typename BlackoilWellModel< TypeTag >::BVector BVector
Definition: BlackoilWellModelNldd.hpp:86
void setupDomains(const std::vector< Domain > &domains)
Definition: BlackoilWellModelNldd_impl.hpp:205
typename BlackoilWellModel< TypeTag >::PressureMatrix PressureMatrix
Definition: BlackoilWellModelNldd.hpp:85
void addWellPressureEquations(PressureMatrix &jacobian, const BVector &weights, const bool use_well_weights, const int domainIndex) const
Definition: BlackoilWellModelNldd_impl.hpp:79
void updateWellControls(const Domain &domain)
Definition: BlackoilWellModelNldd_impl.hpp:180
Definition: ConvergenceReport.hpp:38
void setWellFailed(const WellFailure &wf)
Definition: ConvergenceReport.hpp:272
const std::vector< WellFailure > & wellFailures() const
Definition: ConvergenceReport.hpp:380
Definition: DeferredLogger.hpp:57
void debug(const std::string &tag, const std::string &message)
Definition: WellInterface.hpp:77
bool updateWellControl(const Simulator &simulator, const IndividualOrGroup iog, const GroupStateHelperType &groupStateHelper, WellStateType &well_state)
Definition: WellInterface_impl.hpp:189
Definition: blackoilbioeffectsmodules.hh:43
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
int index
Definition: SubDomain.hpp:64
Definition: SubDomain.hpp:85