My Project
WellInterfaceGeneric.hpp
1/*
2 Copyright 2017 SINTEF Digital, Mathematics and Cybernetics.
3 Copyright 2017 Statoil ASA.
4 Copyright 2017 IRIS
5 Copyright 2019 Norce
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
24#ifndef OPM_WELLINTERFACE_GENERIC_HEADER_INCLUDED
25#define OPM_WELLINTERFACE_GENERIC_HEADER_INCLUDED
26
27#include <opm/input/eclipse/Schedule/Well/Well.hpp>
28
29#include <map>
30#include <optional>
31#include <string>
32#include <vector>
33
34namespace Opm
35{
36
37class DeferredLogger;
38class GuideRate;
39class ParallelWellInfo;
40struct PerforationData;
41struct PhaseUsage;
42class SummaryState;
43class VFPProperties;
44class WellTestState;
45class WellState;
46class SingleWellState;
47class GroupState;
48class Group;
49class Schedule;
50
52public:
53
54 static constexpr bool extraBhpAtThpLimitProdOutput = false;
55
56 WellInterfaceGeneric(const Well& well,
57 const ParallelWellInfo& parallel_well_info,
58 const int time_step,
59 const int pvtRegionIdx,
60 const int num_components,
61 const int num_phases,
62 const int index_of_well,
63 const std::vector<PerforationData>& perf_data);
64
66 const std::vector<PerforationData>& perforationData() const;
67
69 const std::string& name() const;
70
72 bool isInjector() const;
73
75 bool isProducer() const;
76
78 const std::vector<int>& cells() const { return well_cells_; }
79
81 int indexOfWell() const;
82
83 void adaptRatesForVFP(std::vector<double>& rates) const;
84
85 const Well& wellEcl() const;
86 const PhaseUsage& phaseUsage() const;
87
89 bool underPredictionMode() const;
90
91 // whether the well is operable
92 bool isOperableAndSolvable() const;
93 bool useVfpExplicit () const;
94 bool thpLimitViolatedButNotSwitched() const;
95
96 void initCompletions();
97 void closeCompletions(const WellTestState& wellTestState);
98
99 void setVFPProperties(const VFPProperties* vfp_properties_arg);
100 void setGuideRate(const GuideRate* guide_rate_arg);
101 void setWellEfficiencyFactor(const double efficiency_factor);
102 void setRepRadiusPerfLength();
103 void setWsolvent(const double wsolvent);
104 void setDynamicThpLimit(const double thp_limit);
105 std::optional<double> getDynamicThpLimit() const;
106 void updatePerforatedCell(std::vector<bool>& is_cell_perforated);
107
109 bool wellHasTHPConstraints(const SummaryState& summaryState) const;
110
111 void stopWell() {
112 this->wellStatus_ = Well::Status::STOP;
113 }
114
115 void openWell() {
116 this->wellStatus_ = Well::Status::OPEN;
117 }
118
119 bool wellIsStopped() const {
120 return this->wellStatus_ == Well::Status::STOP;
121 }
122
123 int currentStep() const {
124 return this->current_step_;
125 }
126
127 int pvtRegionIdx() const {
128 return pvtRegionIdx_;
129 }
130
131 const GuideRate* guideRate() const {
132 return guide_rate_;
133 }
134
135 int numComponents() const {
136 return num_components_;
137 }
138
139 int numPhases() const {
140 return number_of_phases_;
141 }
142
143 int numPerfs() const {
144 return number_of_perforations_;
145 }
146
147 double refDepth() const {
148 return ref_depth_;
149 }
150
151 double gravity() const {
152 return gravity_;
153 }
154
155 const VFPProperties* vfpProperties() const {
156 return vfp_properties_;
157 }
158
159 const ParallelWellInfo& parallelWellInfo() const {
160 return parallel_well_info_;
161 }
162
163 const std::vector<double>& perfDepth() const {
164 return perf_depth_;
165 }
166
167 std::vector<double>& perfDepth() {
168 return perf_depth_;
169 }
170
171 const std::vector<double>& wellIndex() const {
172 return well_index_;
173 }
174
175 double getTHPConstraint(const SummaryState& summaryState) const;
176 double getALQ(const WellState& well_state) const;
177 double wsolvent() const;
178 double rsRvInj() const;
179
180 // whether a well is specified with a non-zero and valid VFP table number
181 bool isVFPActive(DeferredLogger& deferred_logger) const;
182
183 void reportWellSwitching(const SingleWellState& ws, DeferredLogger& deferred_logger) const;
184
185 bool changedToOpenThisStep() const {
186 return this->changed_to_open_this_step_;
187 }
188 std::optional<double> computeBhpAtThpLimitProdCommon(const std::function<std::vector<double>(const double)>& frates,
189 const SummaryState& summary_state,
190 const double maxPerfPress,
191 const double rho,
192 const double alq_value,
193 DeferredLogger& deferred_logger
194 ) const;
195
196
197
198protected:
199 bool getAllowCrossFlow() const;
200 double mostStrictBhpFromBhpLimits(const SummaryState& summaryState) const;
201 void updateWellTestStatePhysical(const double simulation_time,
202 const bool write_message_to_opmlog,
203 WellTestState& well_test_state,
204 DeferredLogger& deferred_logger) const;
205
206 std::optional<double> bhpMax(const std::function<double(const double)>& fflo,
207 const double bhp_limit,
208 const double maxPerfPress,
209 const double vfp_flo_front,
210 DeferredLogger& deferred_logger) const;
211
212 std::optional<double> computeBhpAtThpLimitCommon(
213 const std::function<std::vector<double>(const double)>& frates,
214 const std::function<double(const std::vector<double>)>& fbhp,
215 const std::array<double, 2>& range,
216 DeferredLogger& deferred_logger) const;
217
218
219 bool bruteForceBracket(const std::function<double(const double)>& eq,
220 const std::array<double, 2>& range,
221 double& low, double& high,
222 DeferredLogger& deferred_logger) const;
223
224 bool bisectBracket(const std::function<double(const double)>& eq,
225 const std::array<double, 2>& range,
226 double& low, double& high,
227 std::optional<double>& approximate_solution,
228 DeferredLogger& deferred_logger) const;
229
230
231 // definition of the struct OperabilityStatus
233 bool isOperableAndSolvable() const {
234 if (!operable_under_only_bhp_limit || !solvable || has_negative_potentials) {
235 return false;
236 } else {
237 return ( (isOperableUnderBHPLimit() || isOperableUnderTHPLimit()) );
238 }
239 }
240
241 bool isOperableUnderBHPLimit() const {
242 return operable_under_only_bhp_limit && obey_thp_limit_under_bhp_limit;
243 }
244
245 bool isOperableUnderTHPLimit() const {
246 return can_obtain_bhp_with_thp_limit && obey_bhp_limit_with_thp_limit;
247 }
248
249 void resetOperability() {
250 operable_under_only_bhp_limit = true;
251 obey_thp_limit_under_bhp_limit = true;
252 can_obtain_bhp_with_thp_limit = true;
253 obey_bhp_limit_with_thp_limit = true;
254 }
255
256 // whether the well can be operated under bhp limit
257 // without considering other limits.
258 // if it is false, then the well is not operable for sure.
259 bool operable_under_only_bhp_limit = true;
260 // if the well can be operated under bhp limit, will it obey(not violate)
261 // the thp limit when operated under bhp limit
262 bool obey_thp_limit_under_bhp_limit = true;
263 // whether the well operate under the thp limit only
264 bool can_obtain_bhp_with_thp_limit = true;
265 // whether the well obey bhp limit when operated under thp limit
266 bool obey_bhp_limit_with_thp_limit = true;
267 // the well is solveable
268 bool solvable = true;
269 // the well have non positive potentials
270 bool has_negative_potentials = false;
271 //thp limit violated but not switched
272 mutable bool thp_limit_violated_but_not_switched = false;
273
274 bool use_vfpexplicit = false;
275 };
276
277 OperabilityStatus operability_status_;
278
279 Well well_ecl_;
280
281 const ParallelWellInfo& parallel_well_info_;
282 const int current_step_;
283
284 // The pvt region of the well. We assume
285 // We assume a well to not penetrate more than one pvt region.
286 const int pvtRegionIdx_;
287
288 const int num_components_;
289
290 // number of phases
291 int number_of_phases_;
292
293 // the index of well in Wells struct
294 int index_of_well_;
295
296 const std::vector<PerforationData>* perf_data_;
297
298 // the vectors used to describe the inflow performance relationship (IPR)
299 // Q = IPR_A - BHP * IPR_B
300 // TODO: it minght need to go to WellInterface, let us implement it in StandardWell first
301 // it is only updated and used for producers for now
302 mutable std::vector<double> ipr_a_;
303 mutable std::vector<double> ipr_b_;
304
305 // cell index for each well perforation
306 std::vector<int> well_cells_;
307
308 // well index for each perforation
309 std::vector<double> well_index_;
310
311 // number of the perforations for this well
312 int number_of_perforations_;
313
314 // depth for each perforation
315 std::vector<double> perf_depth_;
316
317 // representative radius of the perforations, used in shear calculation
318 std::vector<double> perf_rep_radius_;
319
320 // length of the perforations, use in shear calculation
321 std::vector<double> perf_length_;
322
323 // well bore diameter
324 std::vector<double> bore_diameters_;
325
326 /*
327 * completions_ contains the mapping from completion id to connection indices
328 * {
329 * 2 : [ConnectionIndex, ConnectionIndex],
330 * 1 : [ConnectionIndex, ConnectionIndex, ConnectionIndex],
331 * 5 : [ConnectionIndex],
332 * 7 : [ConnectionIndex]
333 * ...
334 * }
335 * The integer IDs correspond to the COMPLETION id given by the COMPLUMP keyword.
336 * When there is no COMPLUMP keyword used, a default completion number will be assigned
337 * based on the order of the declaration of the connections.
338 * Since the connections not OPEN is not included in the Wells, so they will not be considered
339 * in this mapping relation.
340 */
341 std::map<int, std::vector<int>> completions_;
342
343 // reference depth for the BHP
344 double ref_depth_;
345
346 // saturation table nubmer for each well perforation
347 std::vector<int> saturation_table_number_;
348
349 Well::Status wellStatus_;
350
351 const PhaseUsage* phase_usage_;
352
353 double gravity_;
354 double wsolvent_;
355 std::optional<double> dynamic_thp_limit_;
356
357 double well_efficiency_factor_;
358 const VFPProperties* vfp_properties_;
359 const GuideRate* guide_rate_;
360
361 std::vector< std::string> well_control_log_;
362
363 bool changed_to_open_this_step_ = true;
364};
365
366}
367
368#endif // OPM_WELLINTERFACE_HEADER_INCLUDED
Class encapsulating some information about parallel wells.
Definition: ParallelWellInfo.hpp:243
A thin wrapper class that holds one VFPProdProperties and one VFPInjProperties object.
Definition: VFPProperties.hpp:39
Definition: WellInterfaceGeneric.hpp:51
bool wellHasTHPConstraints(const SummaryState &summaryState) const
Returns true if the well has one or more THP limits/constraints.
Definition: WellInterfaceGeneric.cpp:181
const std::vector< int > & cells() const
Well cells.
Definition: WellInterfaceGeneric.hpp:78
int indexOfWell() const
Index of well in the wells struct and wellState.
Definition: WellInterfaceGeneric.cpp:149
const std::string & name() const
Well name.
Definition: WellInterfaceGeneric.cpp:134
bool underPredictionMode() const
Returns true if the well is currently in prediction mode (i.e. not history mode).
Definition: WellInterfaceGeneric.cpp:236
bool isProducer() const
True if the well is a producer.
Definition: WellInterfaceGeneric.cpp:144
bool isInjector() const
True if the well is an injector.
Definition: WellInterfaceGeneric.cpp:139
const std::vector< PerforationData > & perforationData() const
Get the perforations of the well.
Definition: WellInterfaceGeneric.cpp:129
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: BlackoilPhases.hpp:27
Definition: BlackoilPhases.hpp:46
Definition: WellInterfaceGeneric.hpp:232