opm-simulators
SingleCompWellState_impl.hpp
1 /*
2  Copyright 2024, SINTEF Digital
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 namespace Opm {
21 
22 template <class Scalar>
23 CompConnectionData<Scalar>::
24 CompConnectionData(std::size_t num_connection,
25  std::size_t num_phases,
26  std::size_t num_components)
27  : pressure(num_connection)
28  , surface_phase_rates(num_connection * num_phases)
29  , reservoir_phase_rates(num_connection * num_phases)
30  , total_molar_fractions(num_connection * num_components)
31  , transmissibility_factor(num_connection)
32  , satnum_id(num_connection)
33  , ecl_index(num_connection)
34 {
35 }
36 
37 
38 template <class Scalar>
39 CompConnectionData<Scalar>::
40 CompConnectionData(const std::vector<PerforationData<Scalar>>& connections,
41  const std::size_t num_phases,
42  const CompositionalConfig& comp_config)
43  : CompConnectionData(connections.size(), num_phases, comp_config.numComps())
44 {
45  for (std::size_t con = 0; con < connections.size(); ++con) {
46  this->transmissibility_factor[con] = connections[con].connection_transmissibility_factor;
47  this->satnum_id[con] = connections[con].satnum_id;
48  this->ecl_index[con] = connections[con].cell_index;
49  }
50 }
51 
52 template <typename FluidSystem>
53 SingleCompWellState<FluidSystem>::
54 SingleCompWellState(const std::string& well_name,
55  const CompositionalConfig& comp_config,
56  const Scalar temperature_arg,
57  const std::vector<PerforationData<Scalar>>& connections,
58  bool is_producer)
59  : name(well_name)
60  , producer(is_producer)
61  , temperature(temperature_arg)
62  , surface_phase_rates(FluidSystem::numPhases)
63  , phase_fractions(FluidSystem::numPhases)
64  , reservoir_phase_rates(FluidSystem::numPhases)
65  , total_molar_fractions(comp_config.numComps())
66  , connection_data(connections, FluidSystem::numPhases, comp_config)
67 {
68 }
69 
70 template <typename FluidSystem>
71 void SingleCompWellState<FluidSystem>::
72 update_injector_targets(const Well& well,
73  const SummaryState& st)
74 {
75  const auto& inj_controls = well.injectionControls(st);
76  const auto& injection_properties = well.getInjectionProperties();
77  const auto& inj_composition = injection_properties.gasInjComposition();
78 #ifndef NDEBUG
79  assert(this->total_molar_fractions.size() == inj_composition.size());
80  const bool cmode_is_undefined = (inj_controls.cmode == Well::InjectorCMode::CMODE_UNDEFINED);
81  assert(!cmode_is_undefined && "control types should be specified");
82  const auto injection_type = injection_properties.injectorType;
83  const bool is_gas_injecting = (injection_type == InjectorType::GAS);
84  assert(is_gas_injecting && "Only gas injection is supported for now");
85 #endif
86  this->bhp = inj_controls.bhp_limit;
87  this->injection_cmode = inj_controls.cmode;
88  // TODO: this might not be correct when crossing flow is involved
89  this->total_molar_fractions = inj_composition;
90 
91  // we initialize all open wells with a rate to avoid singularities
92  Scalar inj_surf_rate = 10.0 * Opm::unit::cubic(Opm::unit::meter) / Opm::unit::day;
93  if (inj_controls.cmode == Well::InjectorCMode::RATE) {
94  inj_surf_rate = inj_controls.surface_rate;
95  }
96 
97  switch (inj_controls.injector_type) {
98  case InjectorType::WATER:
99  assert(FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx));
100  this->surface_phase_rates[FluidSystem::waterPhaseIdx] = inj_surf_rate;
101  break;
102  case InjectorType::GAS:
103  assert(FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx));
104  this->surface_phase_rates[FluidSystem::gasPhaseIdx] = inj_surf_rate;
105  break;
106  case InjectorType::OIL:
107  assert(FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx));
108  this->surface_phase_rates[FluidSystem::oilPhaseIdx] = inj_surf_rate;
109  break;
110  case InjectorType::MULTI:
111  // Not currently handled, keep zero init.
112  break;
113  }
114 }
115 
116 template <typename FluidSystem>
117 void SingleCompWellState<FluidSystem>::
118 update_producer_targets(const Well& well,
119  const std::vector<std::vector<Scalar>>& cell_mole_fractions,
120  const SummaryState& st)
121 {
122  const auto& prod_controls = well.productionControls(st);
123 #ifndef NDEBUG
124  const auto cmode_is_undefined = (prod_controls.cmode == Well::ProducerCMode::CMODE_UNDEFINED);
125  assert(!cmode_is_undefined && "control types should be specified");
126 #endif
127 
128  this->total_molar_fractions = cell_mole_fractions[this->connection_data.ecl_index[0]];
129 
130  this->bhp = prod_controls.bhp_limit;
131  this->production_cmode = prod_controls.cmode;
132 
133  // we give a set of rates for BHP-controlled wells for initialization
134  const Scalar production_rate = -1000.0 * Opm::unit::cubic(Opm::unit::meter) / Opm::unit::day;
135  if (prod_controls.cmode == Well::ProducerCMode::BHP) {
136  if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
137  this->surface_phase_rates[FluidSystem::oilPhaseIdx] = production_rate;
138  }
139  if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
140  this->surface_phase_rates[FluidSystem::waterPhaseIdx] = production_rate;
141  }
142  if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
143  this->surface_phase_rates[FluidSystem::gasPhaseIdx] = 100. * production_rate;
144  }
145  }
146 }
147 
148 template <typename FluidSystem>
149 void SingleCompWellState<FluidSystem>::
150 copyRuntimeStateFrom(const SingleCompWellState& other)
151 {
152  // Keep the freshly initialized schedule-derived status, controls, and
153  // injector targets from base_init(); only reuse the dynamic state.
154  bhp = other.bhp;
155  surface_phase_rates = other.surface_phase_rates;
156  phase_fractions = other.phase_fractions;
157  reservoir_phase_rates = other.reservoir_phase_rates;
158  if (producer) {
159  total_molar_fractions = other.total_molar_fractions;
160  phase_molar_fractions = other.phase_molar_fractions;
161  }
162 }
163 
164 template <typename FluidSystem>
165 typename SingleCompWellState<FluidSystem>::Scalar
166 SingleCompWellState<FluidSystem>::
167 get_total_surface_rate() const
168 {
169  return std::accumulate(surface_phase_rates.begin(), surface_phase_rates.end(), Scalar(0));
170 }
171 
172 
173 } // namespace Opm
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
Definition: blackoilbioeffectsmodules.hh:45