opm-simulators
Loading...
Searching...
No Matches
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#include <opm/simulators/flow/BlackoilModelParameters.hpp>
29#include <opm/simulators/wells/RuntimePerforation.hpp>
30
31#include <map>
32#include <optional>
33#include <string>
34#include <vector>
35
36namespace Opm
37{
38
39class DeferredLogger;
40class GuideRate;
41template<class Scalar> class ParallelWellInfo;
42template<class Scalar> struct PerforationData;
43class SummaryState;
44template<typename Scalar, typename IndexTraits> class VFPProperties;
45class WellTestState;
46template<typename Scalar, typename IndexTraits> class WellState;
47template<typename Scalar, typename IndexTraits> class SingleWellState;
48class Group;
49class Schedule;
50template<typename IndexTraits> class PhaseUsageInfo;
51
52template<typename Scalar, typename IndexTraits>
54public:
56
58
59 WellInterfaceGeneric(const Well& well,
61 const int time_step,
62 const ModelParameters& param,
63 const int pvtRegionIdx,
65 const int num_phases,
66 const int index_of_well,
68 const std::vector<PerforationData<Scalar>>& perf_data);
69
71 const std::vector<PerforationData<Scalar>>& perforationData() const;
72
74 const std::string& name() const;
75
77 bool isInjector() const;
78
80 bool isProducer() const;
81
83 const std::vector<int>& cells() const { return well_cells_; }
84
86 int indexOfWell() const;
87
88 void adaptRatesForVFP(std::vector<Scalar>& rates) const;
89
90 const Well& wellEcl() const;
91 Well& wellEcl();
92 const PhaseUsageInfo<IndexTraits>& phaseUsage() const;
93
95 bool underPredictionMode() const;
96
97 // whether the well is operable
98 bool isOperableAndSolvable() const;
99 bool useVfpExplicit () const;
100 bool thpLimitViolatedButNotSwitched() const;
101
102 void initCompletions();
103 void closeCompletions(const WellTestState& wellTestState);
104
105 void setVFPProperties(const VFPProperties<Scalar, IndexTraits>* vfp_properties_arg);
106 void setPrevSurfaceRates(WellStateType& well_state,
107 const WellStateType& prev_well_state) const;
108 void setGuideRate(const GuideRate* guide_rate_arg);
109 void setWellEfficiencyFactor(const Scalar efficiency_factor);
110 void setRepRadiusPerfLength();
111 void setWsolvent(const Scalar wsolvent);
112 void setDynamicThpLimit(const Scalar thp_limit);
113 std::optional<Scalar> getDynamicThpLimit() const;
114 void setDynamicThpLimit(const std::optional<Scalar> thp_limit);
115 void updatePerforatedCell(std::vector<bool>& is_cell_perforated);
116
118 bool wellHasTHPConstraints(const SummaryState& summaryState) const;
119
120 void stopWell() { this->wellStatus_ = Well::Status::STOP; }
121 void openWell() { this->wellStatus_ = Well::Status::OPEN; }
122 Well::Status wellStatus() { return this->wellStatus_;}
123
124 bool wellIsStopped() const { return this->wellStatus_ == Well::Status::STOP; }
125
126 int currentStep() const { return this->current_step_; }
127
128 int pvtRegionIdx() const { return pvtRegionIdx_; }
129
130 const GuideRate* guideRate() const { return guide_rate_; }
131
132 int numConservationQuantities() const { return num_conservation_quantities_; }
133
134 int numPhases() const { return number_of_phases_; }
135
136 int numLocalPerfs() const { return number_of_local_perforations_; }
137
138 Scalar refDepth() const { return ref_depth_; }
139
140 Scalar gravity() const { return gravity_; }
141
142 const VFPProperties<Scalar, IndexTraits>* vfpProperties() const { return vfp_properties_; }
143
144 const ParallelWellInfo<Scalar>& parallelWellInfo() const { return parallel_well_info_; }
145
146 const std::vector<Scalar>& perfDepth() const { return perf_depth_; }
147
148 std::vector<Scalar>& perfDepth() { return perf_depth_; }
149
150 const std::vector<Scalar>& wellIndex() const { return well_index_; }
151
152 const std::map<int,std::vector<int>>& getCompletions() const { return completions_; }
153
154 Scalar getTHPConstraint(const SummaryState& summaryState) const;
155 Scalar getALQ(const WellStateType& well_state) const;
156 Scalar wsolvent() const;
157 Scalar rsRvInj() const;
158
159 // at the beginning of the time step, we check what inj_multiplier from the previous running
160 void initInjMult(const std::vector<Scalar>& max_inj_mult);
161
162 // update the InjMult information at the end of the time step, so it can be used for later.
163 void updateInjMult(std::vector<Scalar>& inj_multipliers,
164 DeferredLogger& deferred_logger) const;
165
166 // Note:: for multisegment wells, bhp is actually segment pressure in practice based on observation
167 // it might change in the future
168 Scalar getInjMult(const int local_perf_index, const Scalar bhp, const Scalar perf_pres, DeferredLogger& dlogger) const;
169
170 // whether a well is specified with a non-zero and valid VFP table number
171 bool isVFPActive(DeferredLogger& deferred_logger) const;
172
173 void reportWellSwitching(const SingleWellState<Scalar, IndexTraits>& ws,
174 DeferredLogger& deferred_logger) const;
175
176 bool changedToOpenThisStep() const { return this->changed_to_open_this_step_; }
177
178 void updateWellTestState(const SingleWellState<Scalar, IndexTraits>& ws,
179 const double& simulationTime,
180 const bool& writeMessageToOPMLog,
181 const bool zero_group_target,
182 WellTestState& wellTestState,
183 DeferredLogger& deferred_logger) const;
184
185 bool isPressureControlled(const WellStateType& well_state) const;
186
187 Scalar wellEfficiencyFactor() const { return well_efficiency_factor_; }
188
190 void updateFilterCakeMultipliers(const std::vector<Scalar>& inj_fc_multiplier)
191 {
192 inj_fc_multiplier_ = inj_fc_multiplier;
193 }
194
195 void resetWellOperability();
196
197 virtual std::vector<Scalar> getPrimaryVars() const
198 {
199 return {};
200 }
201
202 virtual int setPrimaryVars(typename std::vector<Scalar>::const_iterator)
203 {
204 return 0;
205 }
206
207 virtual Scalar connectionDensity(const int globalConnIdx,
208 const int openConnIdx) const = 0;
209
210 void addPerforations(const std::vector<RuntimePerforation>& perfs);
211
212protected:
213 bool getAllowCrossFlow() const;
214
215 Scalar wmicrobes_() const;
216 Scalar wfoam_() const;
217 Scalar woxygen_() const;
218 Scalar wpolymer_() const;
219 Scalar wsalt_() const;
220 Scalar wurea_() const;
221
222 int polymerTable_() const;
223 int polymerInjTable_() const;
224 int polymerWaterTable_() const;
225
226 bool wellUnderZeroRateTargetIndividual(const SummaryState& summary_state,
227 const WellState<Scalar, IndexTraits>& well_state) const;
228
229 bool wellUnderGroupControl(const SingleWellState<Scalar, IndexTraits>& ws) const;
230
231 std::pair<bool,bool>
232 computeWellPotentials(std::vector<Scalar>& well_potentials,
233 const WellStateType& well_state);
234
235 void checkNegativeWellPotentials(std::vector<Scalar>& well_potentials,
236 const bool checkOperability,
237 DeferredLogger& deferred_logger);
238
239 // Remove all other controls than THP and BHP
240 void onlyKeepBHPandTHPcontrols(const SummaryState& summary_state,
241 WellStateType& well_state,
242 Well::InjectionControls& inj_controls,
243 Well::ProductionControls& prod_controls) const;
244
245 void resetDampening() {
246 std::fill(this->inj_multiplier_damp_factor_.begin(), this->inj_multiplier_damp_factor_.end(), 1.0);
247 }
248
249 // definition of the struct OperabilityStatus
251 {
252 bool isOperableAndSolvable() const
253 {
254 if (!operable_under_only_bhp_limit || !solvable || has_negative_potentials) {
255 return false;
256 } else {
257 return ( (isOperableUnderBHPLimit() || isOperableUnderTHPLimit()) );
258 }
259 }
260
261 bool isOperableUnderBHPLimit() const
262 {
263 return operable_under_only_bhp_limit && obey_thp_limit_under_bhp_limit;
264 }
265
266 bool isOperableUnderTHPLimit() const
267 {
268 return can_obtain_bhp_with_thp_limit && obey_bhp_limit_with_thp_limit;
269 }
270
271 void resetOperability()
272 {
273 operable_under_only_bhp_limit = true;
274 obey_thp_limit_under_bhp_limit = true;
275 can_obtain_bhp_with_thp_limit = true;
276 obey_bhp_limit_with_thp_limit = true;
277 }
278
279 // whether the well can be operated under bhp limit
280 // without considering other limits.
281 // if it is false, then the well is not operable for sure.
282 bool operable_under_only_bhp_limit = true;
283 // if the well can be operated under bhp limit, will it obey(not violate)
284 // the thp limit when operated under bhp limit
285 bool obey_thp_limit_under_bhp_limit = true;
286 // whether the well operate under the thp limit only
287 bool can_obtain_bhp_with_thp_limit = true;
288 // whether the well obey bhp limit when operated under thp limit
289 bool obey_bhp_limit_with_thp_limit = true;
290 // the well is solveable
291 bool solvable = true;
292 // the well have non positive potentials
293 bool has_negative_potentials = false;
294 //thp limit violated but not switched
295 mutable bool thp_limit_violated_but_not_switched = false;
296
297 bool use_vfpexplicit = false;
298 };
299
300 OperabilityStatus operability_status_;
301
302 Well well_ecl_;
303
304 const ParallelWellInfo<Scalar>& parallel_well_info_;
305 const int current_step_;
306 const ModelParameters& param_;
307
308 // The pvt region of the well. We assume
309 // We assume a well to not penetrate more than one pvt region.
310 const int pvtRegionIdx_;
311
312 const int num_conservation_quantities_;
313
314 // number of phases
315 int number_of_phases_;
316
317 // the index of well in Wells struct
318 int index_of_well_;
319
320 const PhaseUsageInfo<IndexTraits>& phase_usage_;
321
322 const std::vector<PerforationData<Scalar>>* perf_data_;
323
324 // the vectors used to describe the inflow performance relationship (IPR)
325 // Q = IPR_A - BHP * IPR_B
326 // TODO: it minght need to go to WellInterface, let us implement it in StandardWell first
327 // it is only updated and used for producers for now
328 mutable std::vector<Scalar> ipr_a_;
329 mutable std::vector<Scalar> ipr_b_;
330
331 // cell index for each well perforation
332 std::vector<int> well_cells_;
333
334 // well index for each perforation
335 std::vector<Scalar> well_index_;
336
337 // number of the perforations for this well on this process
338 int number_of_local_perforations_;
339
340 // depth for each perforation
341 std::vector<Scalar> perf_depth_;
342
343 // representative radius of the perforations, used in shear calculation
344 std::vector<Scalar> perf_rep_radius_;
345
346 // length of the perforations, use in shear calculation
347 std::vector<Scalar> perf_length_;
348
349 // well bore diameter
350 std::vector<Scalar> bore_diameters_;
351
352 /*
353 * completions_ contains the mapping from completion id to connection indices
354 * {
355 * 2 : [ConnectionIndex, ConnectionIndex],
356 * 1 : [ConnectionIndex, ConnectionIndex, ConnectionIndex],
357 * 5 : [ConnectionIndex],
358 * 7 : [ConnectionIndex]
359 * ...
360 * }
361 * The integer IDs correspond to the COMPLETION id given by the COMPLUMP keyword.
362 * When there is no COMPLUMP keyword used, a default completion number will be assigned
363 * based on the order of the declaration of the connections.
364 * Since the connections not OPEN is not included in the Wells, so they will not be considered
365 * in this mapping relation.
366 */
367 std::map<int, std::vector<int>> completions_;
368
369 // reference depth for the BHP
370 Scalar ref_depth_;
371
372 // saturation table nubmer for each well perforation
373 std::vector<int> saturation_table_number_;
374
375 Well::Status wellStatus_;
376
377 Scalar gravity_;
378 Scalar wsolvent_;
379 std::optional<Scalar> dynamic_thp_limit_;
380
381 // recording the multiplier calculate from the keyword WINJMULT during the time step
382 mutable std::vector<Scalar> inj_multiplier_;
383
384 // the injection multiplier from the previous running, it is mostly used for CIRR mode
385 // which intends to keep the fracturing open
386 std::vector<Scalar> prev_inj_multiplier_;
387
388 // WINJMULT multipliers for previous iteration (used for oscillation detection)
389 mutable std::vector<Scalar> inj_multiplier_previter_;
390 // WINJMULT dampening factors (used in case of oscillations)
391 mutable std::vector<Scalar> inj_multiplier_damp_factor_;
392
393 // the multiplier due to injection filtration cake
394 std::vector<Scalar> inj_fc_multiplier_;
395
396 Scalar well_efficiency_factor_;
397 const VFPProperties<Scalar, IndexTraits>* vfp_properties_;
398 const GuideRate* guide_rate_;
399
400 std::vector<std::string> well_control_log_;
401
402 bool changed_to_open_this_step_ = true;
403};
404
405}
406
407#endif // OPM_WELLINTERFACE_GENERIC_HEADER_INCLUDED
Class encapsulating some information about parallel wells.
Definition ParallelWellInfo.hpp:198
Definition GasLiftGroupInfo.hpp:37
A thin wrapper class that holds one VFPProdProperties and one VFPInjProperties object.
Definition VFPProperties.hpp:40
Definition WellInterfaceGeneric.hpp:53
bool underPredictionMode() const
Returns true if the well is currently in prediction mode (i.e. not history mode).
Definition WellInterfaceGeneric.cpp:372
void updateFilterCakeMultipliers(const std::vector< Scalar > &inj_fc_multiplier)
Update filter cake multipliers.
Definition WellInterfaceGeneric.hpp:190
bool isProducer() const
True if the well is a producer.
Definition WellInterfaceGeneric.cpp:180
bool isInjector() const
True if the well is an injector.
Definition WellInterfaceGeneric.cpp:174
int indexOfWell() const
Index of well in the wells struct and wellState.
Definition WellInterfaceGeneric.cpp:186
const std::vector< PerforationData< Scalar > > & perforationData() const
Get the perforations of the well.
Definition WellInterfaceGeneric.cpp:161
const std::vector< int > & cells() const
Well cells.
Definition WellInterfaceGeneric.hpp:83
const std::string & name() const
Well name.
Definition WellInterfaceGeneric.cpp:168
bool wellHasTHPConstraints(const SummaryState &summaryState) const
Returns true if the well has one or more THP limits/constraints.
Definition WellInterfaceGeneric.cpp:325
The state of a set of wells, tailored for use by the fully implicit blackoil simulator.
Definition WellState.hpp:66
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition blackoilbioeffectsmodules.hh:43
constexpr auto getPropValue()
get the value data member of a property
Definition propertysystem.hh:240
Solver parameters for the BlackoilModel.
Definition BlackoilModelParameters.hpp:180
Static data associated with a well perforation.
Definition PerforationData.hpp:30
Definition WellInterfaceGeneric.hpp:251