AquiferCarterTracy.hpp
Go to the documentation of this file.
1/*
2 Copyright 2017 TNO - Heat Transfer & Fluid Dynamics, Modelling & Optimization of the Subsurface
3 Copyright 2017 Statoil ASA.
4
5 This file is part of the Open Porous Media project (OPM).
6
7 OPM is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 OPM is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with OPM. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#ifndef OPM_AQUIFERCT_HEADER_INCLUDED
22#define OPM_AQUIFERCT_HEADER_INCLUDED
23
24#include <opm/common/utility/numeric/linearInterpolation.hpp>
25
26#include <opm/input/eclipse/EclipseState/Aquifer/AquiferCT.hpp>
27
28#include <opm/output/data/Aquifer.hpp>
29
31
32#include <cstddef>
33#include <stdexcept>
34#include <utility>
35#include <vector>
36
37namespace Opm
38{
39
40template <typename TypeTag>
42{
43public:
45
46 using typename Base::BlackoilIndices;
47 using typename Base::ElementContext;
48 using typename Base::Eval;
49 using typename Base::FluidState;
50 using typename Base::FluidSystem;
51 using typename Base::IntensiveQuantities;
52 using typename Base::RateVector;
53 using typename Base::Scalar;
54 using typename Base::Simulator;
55 using typename Base::ElementMapper;
56
57 AquiferCarterTracy(const std::vector<Aquancon::AquancCell>& connections,
58 const Simulator& simulator,
59 const AquiferCT::AQUCT_data& aquct_data)
60 : Base(aquct_data.aquiferID, connections, simulator)
61 , aquct_data_(aquct_data)
62 {}
63
65 {
66 AquiferCarterTracy result({}, simulator, {});
67
68 result.pressure_previous_ = {1.0, 2.0, 3.0};
69 result.pressure_current_ = {4.0, 5.0};
70 result.Qai_ = {{6.0}};
71 result.rhow_ = 7.0;
72 result.W_flux_ = 8.0;
73 result.fluxValue_ = 9.0;
74 result.dimensionless_time_ = 10.0;
75 result.dimensionless_pressure_ = 11.0;
76
77 return result;
78 }
79
80 void endTimeStep() override
81 {
82 for (const auto& q : this->Qai_) {
83 this->W_flux_ += q * this->simulator_.timeStepSize();
84 }
85 this->fluxValue_ = this->W_flux_.value();
86 const auto& comm = this->simulator_.vanguard().grid().comm();
87 comm.sum(&this->fluxValue_, 1);
88 }
89
90 data::AquiferData aquiferData() const override
91 {
92 data::AquiferData data;
93 data.aquiferID = this->aquiferID();
94 // TODO: not sure how to get this pressure value yet
95 data.pressure = this->pa0_;
96 data.fluxRate = 0.;
97 for (const auto& q : this->Qai_) {
98 data.fluxRate += q.value();
99 }
100 data.volume = this->W_flux_.value();
101 data.initPressure = this->pa0_;
102
103 auto* aquCT = data.typeData.template create<data::AquiferType::CarterTracy>();
104
105 aquCT->dimensionless_time = this->dimensionless_time_;
106 aquCT->dimensionless_pressure = this->dimensionless_pressure_;
107 aquCT->influxConstant = this->aquct_data_.influxConstant();
108
109 if (!this->co2store_or_h2store_()) {
110 aquCT->timeConstant = this->aquct_data_.timeConstant();
111 aquCT->waterDensity = this->aquct_data_.waterDensity();
112 aquCT->waterViscosity = this->aquct_data_.waterViscosity();
113 } else {
114 aquCT->waterDensity = this->rhow_;
115 aquCT->timeConstant = this->Tc_;
116 const auto x = this->aquct_data_.porosity * this->aquct_data_.total_compr * this->aquct_data_.inner_radius * this->aquct_data_.inner_radius;
117 aquCT->waterViscosity = this->Tc_ * this->aquct_data_.permeability / x;
118 }
119
120 return data;
121 }
122
123 template<class Serializer>
124 void serializeOp(Serializer& serializer)
125 {
126 serializer(static_cast<Base&>(*this));
127 serializer(fluxValue_);
128 serializer(dimensionless_time_);
129 serializer(dimensionless_pressure_);
130 }
131
132 bool operator==(const AquiferCarterTracy& rhs) const
133 {
134 return static_cast<const AquiferAnalytical<TypeTag>&>(*this) == rhs &&
135 this->fluxValue_ == rhs.fluxValue_ &&
138 }
139
140protected:
141 // Variables constants
142 AquiferCT::AQUCT_data aquct_data_;
143
144 Scalar beta_; // Influx constant
145 // TODO: it is possible it should be a AD variable
146 Scalar fluxValue_{0}; // value of flux
147
150
151 void assignRestartData(const data::AquiferData& xaq) override
152 {
153 this->fluxValue_ = xaq.volume;
154 this->rhow_ = this->aquct_data_.waterDensity();
155 }
156
157 std::pair<Scalar, Scalar>
159 {
160 // We use the opm-common numeric linear interpolator
162 linearInterpolation(this->aquct_data_.dimensionless_time,
163 this->aquct_data_.dimensionless_pressure,
164 this->dimensionless_time_);
165
166 const auto PItd =
167 linearInterpolation(this->aquct_data_.dimensionless_time,
168 this->aquct_data_.dimensionless_pressure,
169 td_plus_dt);
170
171 const auto PItdprime =
172 linearInterpolationDerivative(this->aquct_data_.dimensionless_time,
173 this->aquct_data_.dimensionless_pressure,
174 td_plus_dt);
175
176 return std::make_pair(PItd, PItdprime);
177 }
178
179 Scalar dpai(const int idx) const
180 {
181 const auto gdz =
182 this->gravity_() * (this->cell_depth_.at(idx) - this->aquiferDepth());
183
184 const auto dp = this->pa0_ + this->rhow_*gdz
185 - this->pressure_previous_.at(idx);
186
187 return dp;
188 }
189
190 // This function implements Eqs 5.8 and 5.9 of the EclipseTechnicalDescription
191 std::pair<Scalar, Scalar>
192 calculateEqnConstants(const int idx, const Simulator& simulator)
193 {
194 const Scalar td_plus_dt = (simulator.timeStepSize() + simulator.time()) / this->Tc_;
195 this->dimensionless_time_ = simulator.time() / this->Tc_;
196
197 const auto [PItd, PItdprime] = this->getInfluenceTableValues(td_plus_dt);
198
199 const auto denom = this->Tc_ * (PItd - this->dimensionless_time_*PItdprime);
200 const auto a = (this->beta_*dpai(idx) - this->fluxValue_*PItdprime) / denom;
201 const auto b = this->beta_ / denom;
202
203 return std::make_pair(a, b);
204 }
205
206 std::size_t pvtRegionIdx() const
207 {
208 return this->aquct_data_.pvttableID - 1;
209 }
210
211 // This function implements Eq 5.7 of the EclipseTechnicalDescription
212 void calculateInflowRate(int idx, const Simulator& simulator) override
213 {
214 const auto [a, b] = this->calculateEqnConstants(idx, simulator);
215
216 this->Qai_.at(idx) = this->alphai_.at(idx) *
217 (a - b*(this->pressure_current_.at(idx) - this->pressure_previous_.at(idx)));
218 }
219
221 {
222 this->Tc_ = this->co2store_or_h2store_()
223 ? this->timeConstantCO2Store()
224 : this->aquct_data_.timeConstant();
225
226 this->beta_ = this->aquct_data_.influxConstant();
227 }
228
230 {
231 if (this->solution_set_from_restart_) {
232 return;
233 }
234
235 if (! this->aquct_data_.initial_pressure.has_value()) {
236 this->aquct_data_.initial_pressure =
238
239 const auto& tables = this->simulator_.vanguard()
240 .eclState().getTableManager();
241
242 this->aquct_data_.finishInitialisation(tables);
243 }
244
245 this->pa0_ = this->aquct_data_.initial_pressure.value();
246 if (this->aquct_data_.initial_temperature.has_value()) {
247 this->Ta0_ = this->aquct_data_.initial_temperature.value();
248 }
249
250 this->rhow_ = this->co2store_or_h2store_()
251 ? this->waterDensityCO2Store()
252 : this->aquct_data_.waterDensity();
253 }
254
255 Scalar aquiferDepth() const override
256 {
257 return this->aquct_data_.datum_depth;
258 }
259
260private:
261 Scalar timeConstantCO2Store() const
262 {
263 const Scalar press = this->aquct_data_.initial_pressure.value();
264 const auto temp = this->reservoirTemperatureCO2Store();
265
266 auto waterViscosity = Scalar { 0 };
267 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
268 const auto rs = Scalar { 0 }; // no dissolved CO2
269 waterViscosity = FluidSystem::oilPvt()
270 .viscosity(pvtRegionIdx(), temp, press, rs);
271 }
272 else if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
273 const auto salt = Scalar { 0 };
274 const auto rsw = Scalar { 0 };
275 waterViscosity = FluidSystem::waterPvt()
276 .viscosity(pvtRegionIdx(), temp, press, rsw, salt);
277 }
278 else {
279 OPM_THROW(std::runtime_error, "water or oil phase is needed to run CO2Store.");
280 }
281
282 const auto x = this->aquct_data_.porosity * this->aquct_data_.total_compr
283 * this->aquct_data_.inner_radius * this->aquct_data_.inner_radius;
284
285 return waterViscosity * x / this->aquct_data_.permeability;
286 }
287
288 Scalar waterDensityCO2Store() const
289 {
290 const Scalar press = this->aquct_data_.initial_pressure.value();
291 const auto temp = this->reservoirTemperatureCO2Store();
292
293 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
294 const auto& pvt = FluidSystem::oilPvt();
295 const auto reg = this->pvtRegionIdx();
296
297 const auto rs = Scalar { 0 }; // no dissolved CO2
298 return pvt.inverseFormationVolumeFactor(reg, temp, press, rs)
299 * pvt.oilReferenceDensity(reg);
300 }
301 else if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
302 const auto& pvt = FluidSystem::waterPvt();
303 const auto reg = this->pvtRegionIdx();
304
305 const auto salinity = Scalar { 0 };
306 const auto rsw = Scalar { 0 };
307
308 return pvt.inverseFormationVolumeFactor(reg, temp, press, rsw, salinity)
309 * pvt.waterReferenceDensity(reg);
310 }
311 else {
312 OPM_THROW(std::runtime_error, "water or oil phase is needed to run CO2Store.");
313 }
314 }
315
316 Scalar reservoirTemperatureCO2Store() const
317 {
318 return this->aquct_data_.initial_temperature.has_value()
319 ? this->aquct_data_.initial_temperature.value()
320 : FluidSystem::reservoirTemperature();
321 }
322
323}; // class AquiferCarterTracy
324
325} // namespace Opm
326
327#endif
Definition: AquiferAnalytical.hpp:54
Scalar gravity_() const
Definition: AquiferAnalytical.hpp:241
Scalar Tc_
Definition: AquiferAnalytical.hpp:447
GetPropType< TypeTag, Properties::Simulator > Simulator
Definition: AquiferAnalytical.hpp:56
GetPropType< TypeTag, Properties::IntensiveQuantities > IntensiveQuantities
Definition: AquiferAnalytical.hpp:62
bool solution_set_from_restart_
Definition: AquiferAnalytical.hpp:457
GetPropType< TypeTag, Properties::ElementContext > ElementContext
Definition: AquiferAnalytical.hpp:58
GetPropType< TypeTag, Properties::RateVector > RateVector
Definition: AquiferAnalytical.hpp:61
std::vector< Scalar > alphai_
Definition: AquiferAnalytical.hpp:445
Scalar pa0_
Definition: AquiferAnalytical.hpp:448
DenseAd::Evaluation< Scalar, numEq > Eval
Definition: AquiferAnalytical.hpp:75
GetPropType< TypeTag, Properties::ElementMapper > ElementMapper
Definition: AquiferAnalytical.hpp:63
std::vector< Scalar > pressure_previous_
Definition: AquiferAnalytical.hpp:442
GetPropType< TypeTag, Properties::Scalar > Scalar
Definition: AquiferAnalytical.hpp:57
Eval W_flux_
Definition: AquiferAnalytical.hpp:455
std::vector< Eval > pressure_current_
Definition: AquiferAnalytical.hpp:443
std::optional< Scalar > Ta0_
Definition: AquiferAnalytical.hpp:449
std::vector< Scalar > cell_depth_
Definition: AquiferAnalytical.hpp:441
GetPropType< TypeTag, Properties::FluidSystem > FluidSystem
Definition: AquiferAnalytical.hpp:59
std::vector< Eval > Qai_
Definition: AquiferAnalytical.hpp:444
Scalar calculateReservoirEquilibrium()
Definition: AquiferAnalytical.hpp:392
BlackOilFluidState< Eval, FluidSystem, enableTemperature, enableEnergy, BlackoilIndices::gasEnabled, enableVapwat, enableBrine, enableSaltPrecipitation, has_disgas_in_water, BlackoilIndices::numPhases > FluidState
Definition: AquiferAnalytical.hpp:86
GetPropType< TypeTag, Properties::Indices > BlackoilIndices
Definition: AquiferAnalytical.hpp:60
Scalar rhow_
Definition: AquiferAnalytical.hpp:450
Definition: AquiferCarterTracy.hpp:42
AquiferCT::AQUCT_data aquct_data_
Definition: AquiferCarterTracy.hpp:142
std::pair< Scalar, Scalar > getInfluenceTableValues(const Scalar td_plus_dt)
Definition: AquiferCarterTracy.hpp:158
void assignRestartData(const data::AquiferData &xaq) override
Definition: AquiferCarterTracy.hpp:151
static AquiferCarterTracy serializationTestObject(const Simulator &simulator)
Definition: AquiferCarterTracy.hpp:64
void calculateInflowRate(int idx, const Simulator &simulator) override
Definition: AquiferCarterTracy.hpp:212
data::AquiferData aquiferData() const override
Definition: AquiferCarterTracy.hpp:90
bool operator==(const AquiferCarterTracy &rhs) const
Definition: AquiferCarterTracy.hpp:132
Scalar fluxValue_
Definition: AquiferCarterTracy.hpp:146
void endTimeStep() override
Definition: AquiferCarterTracy.hpp:80
void calculateAquiferCondition() override
Definition: AquiferCarterTracy.hpp:229
GetPropType< TypeTag, Properties::Scalar > Scalar
Definition: AquiferAnalytical.hpp:57
Scalar dimensionless_pressure_
Definition: AquiferCarterTracy.hpp:149
AquiferCarterTracy(const std::vector< Aquancon::AquancCell > &connections, const Simulator &simulator, const AquiferCT::AQUCT_data &aquct_data)
Definition: AquiferCarterTracy.hpp:57
std::pair< Scalar, Scalar > calculateEqnConstants(const int idx, const Simulator &simulator)
Definition: AquiferCarterTracy.hpp:192
void calculateAquiferConstants() override
Definition: AquiferCarterTracy.hpp:220
void serializeOp(Serializer &serializer)
Definition: AquiferCarterTracy.hpp:124
Scalar dimensionless_time_
Definition: AquiferCarterTracy.hpp:148
Scalar aquiferDepth() const override
Definition: AquiferCarterTracy.hpp:255
Scalar beta_
Definition: AquiferCarterTracy.hpp:144
Scalar dpai(const int idx) const
Definition: AquiferCarterTracy.hpp:179
std::size_t pvtRegionIdx() const
Definition: AquiferCarterTracy.hpp:206
const Simulator & simulator_
Definition: AquiferInterface.hpp:98
bool co2store_or_h2store_() const
Definition: AquiferInterface.hpp:82
int aquiferID() const
Definition: AquiferInterface.hpp:79
Definition: BlackoilPhases.hpp:27