Merge pull request #3254 from bska/chase-aquifer-redefinition

Use Aquifer's Notion of Water Properties
This commit is contained in:
Bård Skaflestad 2021-06-22 20:39:42 +02:00 committed by GitHub
commit 801a34b88c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 72 deletions

View File

@ -84,6 +84,10 @@ public:
data.type = data::AquiferType::CarterTracy; data.type = data::AquiferType::CarterTracy;
data.aquCT = std::make_shared<data::CarterTracyData>(); data.aquCT = std::make_shared<data::CarterTracyData>();
data.aquCT->timeConstant = this->aquct_data_.timeConstant();
data.aquCT->influxConstant = this->aquct_data_.influxConstant();
data.aquCT->waterDensity = this->aquct_data_.waterDensity();
data.aquCT->waterViscosity = this->aquct_data_.waterViscosity();
data.aquCT->dimensionless_time = this->dimensionless_time_; data.aquCT->dimensionless_time = this->dimensionless_time_;
data.aquCT->dimensionless_pressure = this->dimensionless_pressure_; data.aquCT->dimensionless_pressure = this->dimensionless_pressure_;
@ -92,10 +96,10 @@ public:
protected: protected:
// Variables constants // Variables constants
const AquiferCT::AQUCT_data aquct_data_; AquiferCT::AQUCT_data aquct_data_;
Scalar beta_; // Influx constant Scalar beta_; // Influx constant
// TODO: it is possible it should be a AD variable // TODO: it is possible it should be a AD variable
Scalar mu_w_{1}; // water viscosity
Scalar fluxValue_{0}; // value of flux Scalar fluxValue_{0}; // value of flux
Scalar dimensionless_time_{0}; Scalar dimensionless_time_{0};
@ -112,26 +116,31 @@ protected:
{ {
// We use the opm-common numeric linear interpolator // We use the opm-common numeric linear interpolator
this->dimensionless_pressure_ = this->dimensionless_pressure_ =
linearInterpolation(this->aquct_data_.td, linearInterpolation(this->aquct_data_.dimensionless_time,
this->aquct_data_.pi, this->aquct_data_.dimensionless_pressure,
this->dimensionless_time_); this->dimensionless_time_);
const auto PItd = const auto PItd =
linearInterpolation(this->aquct_data_.td, linearInterpolation(this->aquct_data_.dimensionless_time,
this->aquct_data_.pi, td_plus_dt); this->aquct_data_.dimensionless_pressure,
td_plus_dt);
const auto PItdprime = const auto PItdprime =
linearInterpolationDerivative(this->aquct_data_.td, linearInterpolationDerivative(this->aquct_data_.dimensionless_time,
this->aquct_data_.pi, td_plus_dt); this->aquct_data_.dimensionless_pressure,
td_plus_dt);
return std::make_pair(PItd, PItdprime); return std::make_pair(PItd, PItdprime);
} }
Scalar dpai(const int idx) const Scalar dpai(const int idx) const
{ {
Scalar dp = this->pa0_ const auto gdz =
+ this->rhow_.at(idx).value() * this->gravity_() * (this->cell_depth_.at(idx) - this->aquiferDepth()) this->gravity_() * (this->cell_depth_.at(idx) - this->aquiferDepth());
const auto dp = this->pa0_ + this->rhow_*gdz
- this->pressure_previous_.at(idx); - this->pressure_previous_.at(idx);
return dp; return dp;
} }
@ -162,48 +171,29 @@ protected:
inline void calculateAquiferConstants() override inline void calculateAquiferConstants() override
{ {
// We calculate the influx constant this->Tc_ = this->aquct_data_.timeConstant();
beta_ = aquct_data_.c2 * aquct_data_.h * aquct_data_.theta * aquct_data_.phi_aq * aquct_data_.C_t this->beta_ = this->aquct_data_.influxConstant();
* aquct_data_.r_o * aquct_data_.r_o;
// We calculate the time constant
this->Tc_ = mu_w_ * aquct_data_.phi_aq * aquct_data_.C_t * aquct_data_.r_o * aquct_data_.r_o
/ (aquct_data_.k_a * aquct_data_.c1);
} }
inline void calculateAquiferCondition() override inline void calculateAquiferCondition() override
{ {
if (! this->aquct_data_.initial_pressure.has_value()) {
this->aquct_data_.initial_pressure =
this->calculateReservoirEquilibrium();
int pvttableIdx = aquct_data_.pvttableID - 1; const auto& tables = this->ebos_simulator_.vanguard()
this->rhow_.resize(this->size(), 0.); .eclState().getTableManager();
if (!aquct_data_.p0.first) {
this->pa0_ = this->calculateReservoirEquilibrium(); this->aquct_data_.finishInitialisation(tables);
} else {
this->pa0_ = aquct_data_.p0.second;
} }
// use the thermodynamic state of the first active cell as a this->pa0_ = this->aquct_data_.initial_pressure.value();
// reference. there might be better ways to do this... this->rhow_ = this->aquct_data_.waterDensity();
ElementContext elemCtx(this->ebos_simulator_);
auto elemIt = this->ebos_simulator_.gridView().template begin</*codim=*/0>();
elemCtx.updatePrimaryStencil(*elemIt);
elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
const auto& iq0 = elemCtx.intensiveQuantities(/*spaceIdx=*/0, /*timeIdx=*/0);
// Initialize a FluidState object first
FluidState fs_aquifer;
// We use the temperature of the first cell connected to the aquifer
// Here we copy the fluidstate of the first cell, so we do not accidentally mess up the reservoir fs
fs_aquifer.assign(iq0.fluidState());
Eval temperature_aq, pa0_mean, saltConcentration_aq;
temperature_aq = fs_aquifer.temperature(0);
saltConcentration_aq = fs_aquifer.saltConcentration();
pa0_mean = this->pa0_;
Eval mu_w_aquifer = FluidSystem::waterPvt().viscosity(pvttableIdx, temperature_aq, pa0_mean, saltConcentration_aq);
mu_w_ = mu_w_aquifer.value();
} }
virtual Scalar aquiferDepth() const override virtual Scalar aquiferDepth() const override
{ {
return aquct_data_.d0; return this->aquct_data_.datum_depth;
} }
}; // class AquiferCarterTracy }; // class AquiferCarterTracy
} // namespace Opm } // namespace Opm

View File

@ -85,14 +85,16 @@ public:
data.type = data::AquiferType::Fetkovich; data.type = data::AquiferType::Fetkovich;
data.aquFet = std::make_shared<data::FetkovichData>(); data.aquFet = std::make_shared<data::FetkovichData>();
data.aquFet->initVolume = this->aqufetp_data_.initial_watvolume;
data.aquFet->prodIndex = this->aqufetp_data_.prod_index;
data.aquFet->timeConstant = this->aqufetp_data_.timeConstant();
return data; return data;
} }
protected: protected:
// Aquifer Fetkovich Specific Variables // Aquifer Fetkovich Specific Variables
// TODO: using const reference here will cause segmentation fault, which is very strange Aquifetp::AQUFETP_data aqufetp_data_;
const Aquifetp::AQUFETP_data aqufetp_data_;
Scalar aquifer_pressure_; // aquifer Scalar aquifer_pressure_; // aquifer
void assignRestartData(const data::AquiferData& xaq) override void assignRestartData(const data::AquiferData& xaq) override
@ -109,52 +111,66 @@ protected:
inline Eval dpai(int idx) inline Eval dpai(int idx)
{ {
const Eval dp = aquifer_pressure_ - this->pressure_current_.at(idx) const auto gdz =
+ this->rhow_[idx] * this->gravity_() * (this->cell_depth_[idx] - this->aquiferDepth()); this->gravity_() * (this->cell_depth_[idx] - this->aquiferDepth());
return dp;
return this->aquifer_pressure_ + this->rhow_*gdz
- this->pressure_current_.at(idx);
} }
// This function implements Eq 5.12 of the EclipseTechnicalDescription // This function implements Eq 5.12 of the EclipseTechnicalDescription
inline Scalar aquiferPressure() inline Scalar aquiferPressure()
{ {
Scalar Flux = this->W_flux_.value(); Scalar Flux = this->W_flux_.value();
const auto& comm = this->ebos_simulator_.vanguard().grid().comm(); const auto& comm = this->ebos_simulator_.vanguard().grid().comm();
comm.sum(&Flux, 1); comm.sum(&Flux, 1);
Scalar pa_ = this->pa0_ - Flux / (aqufetp_data_.C_t * aqufetp_data_.V0);
return pa_; const auto denom =
this->aqufetp_data_.total_compr * this->aqufetp_data_.initial_watvolume;
return this->pa0_ - (Flux / denom);
} }
inline void calculateAquiferConstants() override inline void calculateAquiferConstants() override
{ {
this->Tc_ = (aqufetp_data_.C_t * aqufetp_data_.V0) / aqufetp_data_.J; this->Tc_ = this->aqufetp_data_.timeConstant();
} }
// This function implements Eq 5.14 of the EclipseTechnicalDescription // This function implements Eq 5.14 of the EclipseTechnicalDescription
inline void calculateInflowRate(int idx, const Simulator& simulator) override inline void calculateInflowRate(int idx, const Simulator& simulator) override
{ {
const Scalar td_Tc_ = simulator.timeStepSize() / this->Tc_; const Scalar td_Tc_ = simulator.timeStepSize() / this->Tc_;
const Scalar coef = (1 - exp(-td_Tc_)) / td_Tc_; const Scalar coef = (1 - exp(-td_Tc_)) / td_Tc_;
this->Qai_.at(idx) = this->alphai_[idx] * aqufetp_data_.J * dpai(idx) * coef;
this->Qai_.at(idx) = coef * this->alphai_[idx] *
this->aqufetp_data_.prod_index * dpai(idx);
} }
inline void calculateAquiferCondition() override inline void calculateAquiferCondition() override
{ {
this->rhow_.resize(this->size(), 0.);
if (this->solution_set_from_restart_) { if (this->solution_set_from_restart_) {
return; return;
} }
if (!aqufetp_data_.p0.first) { if (! this->aqufetp_data_.initial_pressure.has_value()) {
this->pa0_ = this->calculateReservoirEquilibrium(); this->aqufetp_data_.initial_pressure =
} else { this->calculateReservoirEquilibrium();
this->pa0_ = aqufetp_data_.p0.second;
const auto& tables = this->ebos_simulator_.vanguard()
.eclState().getTableManager();
this->aqufetp_data_.finishInitialisation(tables);
} }
aquifer_pressure_ = this->pa0_;
this->rhow_ = this->aqufetp_data_.waterDensity();
this->pa0_ = this->aqufetp_data_.initial_pressure.value();
this->aquifer_pressure_ = this->pa0_;
} }
virtual Scalar aquiferDepth() const override virtual Scalar aquiferDepth() const override
{ {
return aqufetp_data_.d0; return this->aqufetp_data_.datum_depth;
} }
}; // Class AquiferFetkovich }; // Class AquiferFetkovich
} // namespace Opm } // namespace Opm

View File

@ -146,7 +146,6 @@ public:
// This is the pressure at td + dt // This is the pressure at td + dt
this->updateCellPressure(this->pressure_current_, idx, intQuants); this->updateCellPressure(this->pressure_current_, idx, intQuants);
this->updateCellDensity(idx, intQuants);
this->calculateInflowRate(idx, context.simulator()); this->calculateInflowRate(idx, context.simulator());
rates[BlackoilIndices::conti0EqIdx + FluidSystem::waterCompIdx] rates[BlackoilIndices::conti0EqIdx + FluidSystem::waterCompIdx]
@ -197,13 +196,6 @@ protected:
pressure_water.at(idx) = fs.pressure(waterPhaseIdx).value(); pressure_water.at(idx) = fs.pressure(waterPhaseIdx).value();
} }
inline void updateCellDensity(const int idx, const IntensiveQuantities& intQuants)
{
const auto& fs = intQuants.fluidState();
rhow_.at(idx) = fs.density(waterPhaseIdx);
}
virtual void endTimeStep() = 0; virtual void endTimeStep() = 0;
const int aquiferID_{}; const int aquiferID_{};
@ -219,11 +211,11 @@ protected:
std::vector<Scalar> pressure_previous_; std::vector<Scalar> pressure_previous_;
std::vector<Eval> pressure_current_; std::vector<Eval> pressure_current_;
std::vector<Eval> Qai_; std::vector<Eval> Qai_;
std::vector<Eval> rhow_;
std::vector<Scalar> alphai_; std::vector<Scalar> alphai_;
Scalar Tc_{}; // Time constant Scalar Tc_{}; // Time constant
Scalar pa0_{}; // initial aquifer pressure Scalar pa0_{}; // initial aquifer pressure
Scalar rhow_{};
Eval W_flux_; Eval W_flux_;
@ -359,11 +351,13 @@ protected:
const auto& fs = iq0.fluidState(); const auto& fs = iq0.fluidState();
water_pressure_reservoir = fs.pressure(waterPhaseIdx).value(); water_pressure_reservoir = fs.pressure(waterPhaseIdx).value();
this->rhow_[idx] = fs.density(waterPhaseIdx); const auto water_density = fs.density(waterPhaseIdx);
pw_aquifer.push_back(
(water_pressure_reservoir const auto gdz =
- this->rhow_[idx].value() * this->gravity_() * (this->cell_depth_[idx] - this->aquiferDepth())) this->gravity_() * (this->cell_depth_[idx] - this->aquiferDepth());
* this->alphai_[idx]);
pw_aquifer.push_back(this->alphai_[idx] *
(water_pressure_reservoir - water_density.value()*gdz));
} }
// We take the average of the calculated equilibrium pressures. // We take the average of the calculated equilibrium pressures.