Load Constant Flux Aquifer Objects from Restart File

This commit adds logic and structures for bringing in constant flux
aquifer objects-keyword AQUFLUX-from the restart file and forming
the requisite dynamic objects in the Schedule.

In particular, the 'RstAquifer' gets a new bare-bones representation
of these aquifer types and we add new constant flux aquifer objects
to the pertinent 'ScheduleState' when these exist.  We also add this
aquifer type to 'data::Aquifers' in preparation of reinitialising
the simulator's aquifer container from the restart file.  In
particular, this needs the total produced volume from the aquifer so
far.
This commit is contained in:
Bård Skaflestad 2023-03-07 18:56:33 +01:00
parent f8f77ff081
commit 303889516f
7 changed files with 98 additions and 23 deletions

View File

@ -30,9 +30,9 @@ namespace Opm {
class DeckRecord;
}
namespace Opm::RestartIO {
class RstAquifer;
} // Opm::RestartIO
namespace Opm { namespace RestartIO {
class RstAquifer;
}} // Opm::RestartIO
namespace Opm {
struct SingleAquiferFlux

View File

@ -77,6 +77,12 @@ namespace Opm { namespace RestartIO {
double time_constant{};
};
struct ConstantFlux {
int aquiferID{};
double flow_rate{};
};
class Connections {
public:
struct Cell {
@ -120,6 +126,7 @@ namespace Opm { namespace RestartIO {
bool hasAnalyticAquifers() const;
const std::vector<CarterTracy>& carterTracy() const;
const std::vector<ConstantFlux>& constantFlux() const;
const std::vector<Fetkovich>& fetkovich() const;
const std::unordered_map<int, Connections>& connections() const;
@ -127,6 +134,7 @@ namespace Opm { namespace RestartIO {
class Implementation;
std::unique_ptr<Implementation> pImpl_;
};
}} // Opm::RestartIO
#endif // OPM_RESTART_AQUIFER_HPP

View File

@ -33,7 +33,7 @@ namespace Opm { namespace data {
enum class AquiferType
{
Fetkovich, CarterTracy, Numerical,
Fetkovich, CarterTracy, ConstantFlux, Numerical,
};
struct FetkovichData

View File

@ -116,7 +116,8 @@ namespace Opm {
}
void AquiferFlux::loadFromRestart(const RestartIO::RstAquifer&) {
// TODO: adding the restart functionality
// Constant flux aquifer objects loaded from restart file added to
// Schedule only.
}
AquiferFlux AquiferFlux::serializationTestObject() {

View File

@ -1745,7 +1745,10 @@ namespace {
}
}
void Schedule::load_rst(const RestartIO::RstState& rst_state, const TracerConfig& tracer_config, const ScheduleGrid& grid, const FieldPropsManager& fp)
void Schedule::load_rst(const RestartIO::RstState& rst_state,
const TracerConfig& tracer_config,
const ScheduleGrid& grid,
const FieldPropsManager& fp)
{
const auto report_step = rst_state.header.report_step - 1;
double udq_undefined = 0;
@ -1917,6 +1920,15 @@ namespace {
this->snapshots.back().network_balance.update(Network::Balance { rst_state.netbalan });
for (const auto& aquflux : rst_state.aquifers.constantFlux()) {
auto aqPos = this->snapshots.back().aqufluxs
.insert_or_assign(aquflux.aquiferID,
SingleAquiferFlux { aquflux.aquiferID });
aqPos.first->second.flux = aquflux.flow_rate;
aqPos.first->second.active = true;
}
if (!rst_state.wlists.empty())
this->snapshots.back().wlist_manager.update( WListManager(rst_state) );

View File

@ -385,6 +385,30 @@ load_carter_tracy(const int aquiferID,
// ---------------------------------------------------------------------
Opm::RestartIO::RstAquifer::ConstantFlux
load_constant_flux(const int aquiferID,
const AquiferVectors& aquifers,
const Opm::UnitSystem& usys)
{
auto aquifer = Opm::RestartIO::RstAquifer::ConstantFlux{};
using M = Opm::UnitSystem::measure;
using Ix = VI::SAnalyticAquifer::index;
const auto saaq = aquifers.saaq(aquiferID);
const auto q = usys.to_si(M::liquid_surface_rate, saaq[Ix::ConstFluxValue]);
aquifer.aquiferID = aquiferID + 1;
// Unit hack: *from_si()* here since we don't have an area unit.
aquifer.flow_rate = usys.from_si(M::length, usys.from_si(M::length, q));
return aquifer;
}
// ---------------------------------------------------------------------
Opm::RestartIO::RstAquifer::Fetkovich
load_fetkovich(const int aquiferID,
const AquiferVectors& aquifers,
@ -490,9 +514,10 @@ public:
bool hasAnalyticAquifers() const
{
return ! (this->connections_.empty() &&
this->carterTracy_.empty() &&
this->fetkovich_ .empty());
return ! (this->connections_ .empty() &&
this->carterTracy_ .empty() &&
this->constantFlux_.empty() &&
this->fetkovich_ .empty());
}
const std::vector<RstAquifer::CarterTracy>& carterTracy() const
@ -500,6 +525,11 @@ public:
return this->carterTracy_;
}
const std::vector<RstAquifer::ConstantFlux>& constantFlux() const
{
return this->constantFlux_;
}
const std::vector<RstAquifer::Fetkovich>& fetkovich() const
{
return this->fetkovich_;
@ -513,6 +543,7 @@ public:
private:
std::unordered_map<int, RstAquifer::Connections> connections_{};
std::vector<RstAquifer::CarterTracy> carterTracy_{};
std::vector<RstAquifer::ConstantFlux> constantFlux_{};
std::vector<RstAquifer::Fetkovich> fetkovich_{};
void loadAnalyticAquiferConnections(const AquiferVectors& vectors,
@ -530,6 +561,10 @@ private:
const AquiferVectors& aquifers,
const UnitSystem& usys);
void loadConstantFlux(const int aquiferID,
const AquiferVectors& aquifers,
const UnitSystem& usys);
void loadFetkovich(const int aquiferID,
const AquiferVectors& aquifers,
const UnitSystem& usys);
@ -559,7 +594,7 @@ loadAnalyticAquiferConnections(const AquiferVectors& aquifers,
const UnitSystem& usys)
{
const auto occurence = ConnectionOccurrence { aquifers.maxAquiferID(), *rstView };
const auto connections = ConnectionVectors { rstView->intehead(), std::move(rstView) };
const auto connections = ConnectionVectors { rstView->intehead(), rstView };
this->connections_ =
load_aquifer_connections(occurence, aquifers, connections,
@ -597,6 +632,10 @@ loadAnalyticAquifer(const int aquiferID,
this->loadCarterTracy(aquiferID, aquifers, usys);
return;
case VI::IAnalyticAquifer::Value::ModelType::ConstantFlux:
this->loadConstantFlux(aquiferID, aquifers, usys);
return;
case VI::IAnalyticAquifer::Value::ModelType::Fetkovich:
this->loadFetkovich(aquiferID, aquifers, usys);
return;
@ -617,6 +656,15 @@ loadCarterTracy(const int aquiferID,
this->carterTracy_.push_back(load_carter_tracy(aquiferID, aquifers, usys));
}
void
Opm::RestartIO::RstAquifer::Implementation::
loadConstantFlux(const int aquiferID,
const AquiferVectors& aquifers,
const UnitSystem& usys)
{
this->constantFlux_.push_back(load_constant_flux(aquiferID, aquifers, usys));
}
void
Opm::RestartIO::RstAquifer::Implementation::
loadFetkovich(const int aquiferID,
@ -631,11 +679,11 @@ loadFetkovich(const int aquiferID,
Opm::RestartIO::RstAquifer::RstAquifer(std::shared_ptr<EclIO::RestartFileView> rstView,
const EclipseGrid* grid,
const UnitSystem& usys)
: pImpl_{ new Implementation{ std::move(rstView), grid, usys } }
: pImpl_{ std::make_unique<Implementation>(std::move(rstView), grid, usys) }
{}
Opm::RestartIO::RstAquifer::RstAquifer(const RstAquifer& rhs)
: pImpl_{ new Implementation{ *rhs.pImpl_ } }
: pImpl_{ std::make_unique<Implementation>(*rhs.pImpl_) }
{}
Opm::RestartIO::RstAquifer::RstAquifer(RstAquifer&& rhs)
@ -645,7 +693,7 @@ Opm::RestartIO::RstAquifer::RstAquifer(RstAquifer&& rhs)
Opm::RestartIO::RstAquifer&
Opm::RestartIO::RstAquifer::operator=(const RstAquifer& rhs)
{
this->pImpl_.reset(new Implementation{ *rhs.pImpl_ });
this->pImpl_ = std::make_unique<Implementation>(*rhs.pImpl_);
return *this;
}
@ -656,8 +704,7 @@ Opm::RestartIO::RstAquifer::operator=(RstAquifer&& rhs)
return *this;
}
Opm::RestartIO::RstAquifer::~RstAquifer()
{}
Opm::RestartIO::RstAquifer::~RstAquifer() = default;
bool Opm::RestartIO::RstAquifer::hasAnalyticAquifers() const
{
@ -670,6 +717,12 @@ Opm::RestartIO::RstAquifer::carterTracy() const
return this->pImpl_->carterTracy();
}
const std::vector<Opm::RestartIO::RstAquifer::ConstantFlux>&
Opm::RestartIO::RstAquifer::constantFlux() const
{
return this->pImpl_->constantFlux();
}
const std::vector<Opm::RestartIO::RstAquifer::Fetkovich>&
Opm::RestartIO::RstAquifer::fetkovich() const
{

View File

@ -1316,19 +1316,20 @@ namespace {
Opm::data::AquiferType
determineAquiferType(const AquiferVectors::Window<int>& iaaq)
{
const auto t1 = iaaq[VI::IAnalyticAquifer::TypeRelated1];
using MType = Opm::RestartIO::Helpers::VectorItems::
IAnalyticAquifer::Value::ModelType;
if (t1 == 1) {
return Opm::data::AquiferType::CarterTracy;
}
using AType = Opm::data::AquiferType;
if (t1 == 0) {
return Opm::data::AquiferType::Fetkovich;
switch (iaaq[VI::IAnalyticAquifer::TypeRelated1]) {
case MType::Fetkovich: return AType::Fetkovich;
case MType::CarterTracy: return AType::CarterTracy;
case MType::ConstantFlux: return AType::ConstantFlux;
}
throw std::runtime_error {
"Unknown Aquifer Type:"
" T1 = " + std::to_string(t1)
"Unknown Aquifer Type: T1 = " +
std::to_string(iaaq[VI::IAnalyticAquifer::TypeRelated1])
};
}