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