Merge pull request #2746 from bska/restart-active-group-constraints

Restore Groups' Active Constraints on Restart
This commit is contained in:
Atgeirr Flø Rasmussen 2020-09-03 10:35:55 +02:00 committed by GitHub
commit 4f7421d64d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 250 additions and 7 deletions

View File

@ -206,9 +206,30 @@ std::size_t packSize(const std::array<T,N>& data, Dune::MPIHelper::MPICommunicat
HANDLE_AS_POD(data::Connection) HANDLE_AS_POD(data::Connection)
HANDLE_AS_POD(data::CurrentControl) HANDLE_AS_POD(data::CurrentControl)
HANDLE_AS_POD(data::GroupConstraints)
HANDLE_AS_POD(data::Rates) HANDLE_AS_POD(data::Rates)
HANDLE_AS_POD(data::Segment) HANDLE_AS_POD(data::Segment)
std::size_t packSize(const data::GuideRateValue&, Dune::MPIHelper::MPICommunicator comm)
{
const auto nItem = static_cast<std::size_t>(data::GuideRateValue::Item::NumItems);
return packSize(std::array<int , nItem>{}, comm)
+ packSize(std::array<double, nItem>{}, comm);
}
std::size_t packSize(const data::GroupGuideRates& data, Dune::MPIHelper::MPICommunicator comm)
{
return packSize(data.production, comm)
+ packSize(data.injection, comm);
}
std::size_t packSize(const data::GroupData& data, Dune::MPIHelper::MPICommunicator comm)
{
return packSize(data.currentControl, comm)
+ packSize(data.guideRates, comm);
}
std::size_t packSize(const data::Well& data, Dune::MPIHelper::MPICommunicator comm) std::size_t packSize(const data::Well& data, Dune::MPIHelper::MPICommunicator comm)
{ {
std::size_t size = packSize(data.rates, comm); std::size_t size = packSize(data.rates, comm);
@ -218,6 +239,7 @@ std::size_t packSize(const data::Well& data, Dune::MPIHelper::MPICommunicator co
size += packSize(data.connections, comm); size += packSize(data.connections, comm);
size += packSize(data.segments, comm); size += packSize(data.segments, comm);
size += packSize(data.current_control, comm); size += packSize(data.current_control, comm);
size += packSize(data.guide_rates, comm);
return size; return size;
} }
@ -238,6 +260,13 @@ std::size_t packSize(const data::Solution& data, Dune::MPIHelper::MPICommunicato
return packSize(static_cast<const std::map< std::string, data::CellData>&>(data), comm); return packSize(static_cast<const std::map< std::string, data::CellData>&>(data), comm);
} }
std::size_t packSize(const data::GroupValues& data, Dune::MPIHelper::MPICommunicator comm)
{
// Needs explicit conversion to a supported base type holding the data
// to prevent throwing.
return packSize(static_cast<const std::map<std::string, data::GroupData>&>(data), comm);
}
std::size_t packSize(const data::WellRates& data, Dune::MPIHelper::MPICommunicator comm) std::size_t packSize(const data::WellRates& data, Dune::MPIHelper::MPICommunicator comm)
{ {
// Needs explicit conversion to a supported base type holding the data // Needs explicit conversion to a supported base type holding the data
@ -247,7 +276,10 @@ std::size_t packSize(const data::WellRates& data, Dune::MPIHelper::MPICommunicat
std::size_t packSize(const RestartValue& data, Dune::MPIHelper::MPICommunicator comm) std::size_t packSize(const RestartValue& data, Dune::MPIHelper::MPICommunicator comm)
{ {
return packSize(data.solution, comm) + packSize(data.wells, comm) + packSize(data.extra, comm); return packSize(data.solution, comm)
+ packSize(data.wells, comm)
+ packSize(data.groups, comm)
+ packSize(data.extra, comm);
} }
////// pack routines ////// pack routines
@ -436,6 +468,42 @@ void pack(const std::unordered_map<T1,T2,H,P,A>& data, std::vector<char>& buffer
} }
} }
void pack(const data::GuideRateValue& data, std::vector<char>& buffer, int& position,
Dune::MPIHelper::MPICommunicator comm)
{
using Item = data::GuideRateValue::Item;
const auto nItem = static_cast<std::size_t>(Item::NumItems);
auto has = std::array<int , nItem>{}; has.fill(0);
auto val = std::array<double, nItem>{}; val.fill(0.0);
for (auto itemID = 0*nItem; itemID < nItem; ++itemID) {
const auto item = static_cast<Item>(itemID);
if (data.has(item)) {
has[itemID] = 1;
val[itemID] = data.get(item);
}
}
pack(has, buffer, position, comm);
pack(val, buffer, position, comm);
}
void pack(const data::GroupGuideRates& data, std::vector<char>& buffer, int& position,
Dune::MPIHelper::MPICommunicator comm)
{
pack(data.production, buffer, position, comm);
pack(data.injection, buffer, position, comm);
}
void pack(const data::GroupData& data, std::vector<char>& buffer, int& position,
Dune::MPIHelper::MPICommunicator comm)
{
pack(data.currentControl, buffer, position, comm);
pack(data.guideRates, buffer, position, comm);
}
void pack(const data::Well& data, std::vector<char>& buffer, int& position, void pack(const data::Well& data, std::vector<char>& buffer, int& position,
Dune::MPIHelper::MPICommunicator comm) Dune::MPIHelper::MPICommunicator comm)
{ {
@ -447,6 +515,7 @@ void pack(const data::Well& data, std::vector<char>& buffer, int& position,
pack(data.connections, buffer, position, comm); pack(data.connections, buffer, position, comm);
pack(data.segments, buffer, position, comm); pack(data.segments, buffer, position, comm);
pack(data.current_control, buffer, position, comm); pack(data.current_control, buffer, position, comm);
pack(data.guide_rates, buffer, position, comm);
} }
void pack(const RestartKey& data, std::vector<char>& buffer, int& position, void pack(const RestartKey& data, std::vector<char>& buffer, int& position,
@ -483,11 +552,21 @@ void pack(const data::WellRates& data, std::vector<char>& buffer, int& position,
buffer, position, comm); buffer, position, comm);
} }
void pack(const data::GroupValues& data, std::vector<char>& buffer, int& position,
Dune::MPIHelper::MPICommunicator comm)
{
// Needs explicit conversion to a supported base type holding the data
// to prevent throwing.
pack(static_cast<const std::map< std::string, data::GroupData>&>(data),
buffer, position, comm);
}
void pack(const RestartValue& data, std::vector<char>& buffer, int& position, void pack(const RestartValue& data, std::vector<char>& buffer, int& position,
Dune::MPIHelper::MPICommunicator comm) Dune::MPIHelper::MPICommunicator comm)
{ {
pack(data.solution, buffer, position, comm); pack(data.solution, buffer, position, comm);
pack(data.wells, buffer, position, comm); pack(data.wells, buffer, position, comm);
pack(data.groups, buffer, position, comm);
pack(data.extra, buffer, position, comm); pack(data.extra, buffer, position, comm);
} }
@ -707,6 +786,40 @@ void unpack(data::Well& data, std::vector<char>& buffer, int& position,
unpack(data.connections, buffer, position, comm); unpack(data.connections, buffer, position, comm);
unpack(data.segments, buffer, position, comm); unpack(data.segments, buffer, position, comm);
unpack(data.current_control, buffer, position, comm); unpack(data.current_control, buffer, position, comm);
unpack(data.guide_rates, buffer, position, comm);
}
void unpack(data::GuideRateValue& data, std::vector<char>& buffer, int& position,
Dune::MPIHelper::MPICommunicator comm)
{
using Item = data::GuideRateValue::Item;
const auto nItem = static_cast<std::size_t>(Item::NumItems);
auto has = std::array<int , nItem>{};
auto val = std::array<double, nItem>{};
unpack(has, buffer, position, comm);
unpack(val, buffer, position, comm);
for (auto itemID = 0*nItem; itemID < nItem; ++itemID) {
if (has[itemID] != 0) {
data.set(static_cast<Item>(itemID), val[itemID]);
}
}
}
void unpack(data::GroupGuideRates& data, std::vector<char>& buffer, int& position,
Dune::MPIHelper::MPICommunicator comm)
{
unpack(data.production, buffer, position, comm);
unpack(data.injection, buffer, position, comm);
}
void unpack(data::GroupData& data, std::vector<char>& buffer, int& position,
Dune::MPIHelper::MPICommunicator comm)
{
unpack(data.currentControl, buffer, position, comm);
unpack(data.guideRates, buffer, position, comm);
} }
void unpack(RestartKey& data, std::vector<char>& buffer, int& position, void unpack(RestartKey& data, std::vector<char>& buffer, int& position,
@ -743,11 +856,21 @@ void unpack(data::WellRates& data, std::vector<char>& buffer, int& position,
buffer, position, comm); buffer, position, comm);
} }
void unpack(data::GroupValues& data, std::vector<char>& buffer, int& position,
Dune::MPIHelper::MPICommunicator comm)
{
// Needs explicit conversion to a supported base type holding the data
// to prevent throwing.
unpack(static_cast<std::map< std::string, data::GroupData>&>(data),
buffer, position, comm);
}
void unpack(RestartValue& data, std::vector<char>& buffer, int& position, void unpack(RestartValue& data, std::vector<char>& buffer, int& position,
Dune::MPIHelper::MPICommunicator comm) Dune::MPIHelper::MPICommunicator comm)
{ {
unpack(data.solution, buffer, position, comm); unpack(data.solution, buffer, position, comm);
unpack(data.wells, buffer, position, comm); unpack(data.wells, buffer, position, comm);
unpack(data.groups, buffer, position, comm);
unpack(data.extra, buffer, position, comm); unpack(data.extra, buffer, position, comm);
} }

View File

@ -306,6 +306,11 @@ ADD_PACK_PROTOTYPES(data::CurrentControl)
ADD_PACK_PROTOTYPES(data::Rates) ADD_PACK_PROTOTYPES(data::Rates)
ADD_PACK_PROTOTYPES(data::Segment) ADD_PACK_PROTOTYPES(data::Segment)
ADD_PACK_PROTOTYPES(data::Solution) ADD_PACK_PROTOTYPES(data::Solution)
ADD_PACK_PROTOTYPES(data::GuideRateValue)
ADD_PACK_PROTOTYPES(data::GroupConstraints)
ADD_PACK_PROTOTYPES(data::GroupGuideRates)
ADD_PACK_PROTOTYPES(data::GroupData)
ADD_PACK_PROTOTYPES(data::GroupValues)
ADD_PACK_PROTOTYPES(data::Well) ADD_PACK_PROTOTYPES(data::Well)
ADD_PACK_PROTOTYPES(data::WellRates) ADD_PACK_PROTOTYPES(data::WellRates)
ADD_PACK_PROTOTYPES(RestartKey) ADD_PACK_PROTOTYPES(RestartKey)

View File

@ -414,6 +414,7 @@ namespace Opm {
// convert well data from opm-common to well state from opm-core // convert well data from opm-common to well state from opm-core
void wellsToState( const data::Wells& wells, void wellsToState( const data::Wells& wells,
const data::GroupValues& groupValues,
const PhaseUsage& phases, const PhaseUsage& phases,
const bool handle_ms_well, const bool handle_ms_well,
WellStateFullyImplicitBlackoil& state ) const; WellStateFullyImplicitBlackoil& state ) const;

View File

@ -547,7 +547,7 @@ namespace Opm {
const size_t numCells = Opm::UgGridHelpers::numCells(grid()); const size_t numCells = Opm::UgGridHelpers::numCells(grid());
const bool handle_ms_well = (param_.use_multisegment_well_ && anyMSWellOpenLocal()); const bool handle_ms_well = (param_.use_multisegment_well_ && anyMSWellOpenLocal());
well_state_.resize(wells_ecl_, schedule(), handle_ms_well, numCells, phaseUsage, well_perf_data_, summaryState, globalNumWells); // Resize for restart step well_state_.resize(wells_ecl_, schedule(), handle_ms_well, numCells, phaseUsage, well_perf_data_, summaryState, globalNumWells); // Resize for restart step
wellsToState(restartValues.wells, phaseUsage, handle_ms_well, well_state_); wellsToState(restartValues.wells, restartValues.groups, phaseUsage, handle_ms_well, well_state_);
} }
previous_well_state_ = well_state_; previous_well_state_ = well_state_;
@ -1599,10 +1599,13 @@ namespace Opm {
void void
BlackoilWellModel<TypeTag>:: BlackoilWellModel<TypeTag>::
wellsToState( const data::Wells& wells, wellsToState( const data::Wells& wells,
const data::GroupValues& groupValues,
const PhaseUsage& phases, const PhaseUsage& phases,
const bool handle_ms_well, const bool handle_ms_well,
WellStateFullyImplicitBlackoil& state) const WellStateFullyImplicitBlackoil& state) const
{ {
using GPMode = Group::ProductionCMode;
using GIMode = Group::InjectionCMode;
using rt = data::Rates::opt; using rt = data::Rates::opt;
const auto np = phases.num_phases; const auto np = phases.num_phases;
@ -1692,6 +1695,24 @@ namespace Opm {
} }
} }
} }
for (const auto& [group, value] : groupValues) {
const auto cpc = value.currentControl.currentProdConstraint;
const auto cgi = value.currentControl.currentGasInjectionConstraint;
const auto cwi = value.currentControl.currentWaterInjectionConstraint;
if (cpc != GPMode::NONE) {
state.setCurrentProductionGroupControl(group, cpc);
}
if (cgi != GIMode::NONE) {
state.setCurrentInjectionGroupControl(Phase::GAS, group, cgi);
}
if (cwi != GIMode::NONE) {
state.setCurrentInjectionGroupControl(Phase::WATER, group, cwi);
}
}
} }

View File

@ -24,6 +24,9 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <tuple>
#include <utility>
#include <opm/common/OpmLog/Location.hpp> #include <opm/common/OpmLog/Location.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp> #include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/Deck/DeckItem.hpp> #include <opm/parser/eclipse/Deck/DeckItem.hpp>
@ -187,6 +190,15 @@ Opm::data::CurrentControl getCurrentControl()
return curr; return curr;
} }
Opm::data::GuideRateValue getWellGuideRate()
{
using Item = Opm::data::GuideRateValue::Item;
return Opm::data::GuideRateValue{}.set(Item::Oil , 1.23)
.set(Item::Gas , 2.34)
.set(Item::Water, 3.45)
.set(Item::ResV , 4.56);
}
Opm::data::Well getWell() Opm::data::Well getWell()
{ {
@ -199,10 +211,44 @@ Opm::data::Well getWell()
well1.connections.push_back(getConnection()); well1.connections.push_back(getConnection());
well1.segments.insert({0, getSegment()}); well1.segments.insert({0, getSegment()});
well1.current_control = getCurrentControl(); well1.current_control = getCurrentControl();
well1.guide_rates = getWellGuideRate();
return well1; return well1;
} }
Opm::data::GroupGuideRates getGroupGuideRates()
{
using Item = Opm::data::GuideRateValue::Item;
auto gr = Opm::data::GroupGuideRates{};
gr.production.set(Item::Oil , 999.888)
.set(Item::Gas , 8888.777)
.set(Item::ResV, 12345.678);
gr.injection.set(Item::Gas , 9876.543)
.set(Item::Water, 2345.987);
return gr;
}
Opm::data::GroupConstraints getGroupConstraints()
{
using PMode = ::Opm::Group::ProductionCMode;
using IMode = ::Opm::Group::InjectionCMode;
return Opm::data::GroupConstraints{}
.set(PMode::ORAT, // Production
IMode::VREP, // Gas Injection
IMode::NONE); // Water Injection
}
Opm::data::GroupData getGroupData()
{
return Opm::data::GroupData {
getGroupConstraints(),
getGroupGuideRates()
};
}
} }
@ -256,6 +302,23 @@ BOOST_AUTO_TEST_CASE(Rates)
DO_CHECKS(data::Rates) DO_CHECKS(data::Rates)
} }
BOOST_AUTO_TEST_CASE(dataGuideRateValue)
{
using Item = Opm::data::GuideRateValue::Item;
const auto val1 = Opm::data::GuideRateValue{}
.set(Item::Oil , 999.888)
.set(Item::Gas , 8888.777)
.set(Item::ResV, 12345.678);
const auto val2 = PackUnpack(val1);
BOOST_CHECK_MESSAGE(! std::get<0>(val2).has(Item::Water),
"Water Must Not Appear From "
"Serializing GuideRateValues");
DO_CHECKS(data::GuideRateValue)
}
BOOST_AUTO_TEST_CASE(dataConnection) BOOST_AUTO_TEST_CASE(dataConnection)
{ {
@ -297,6 +360,29 @@ BOOST_AUTO_TEST_CASE(WellRates)
DO_CHECKS(data::WellRates) DO_CHECKS(data::WellRates)
} }
BOOST_AUTO_TEST_CASE(dataGroupConstraints)
{
const auto val1 = getGroupConstraints();
const auto val2 = PackUnpack(val1);
DO_CHECKS(data::GroupConstraints)
}
BOOST_AUTO_TEST_CASE(dataGroupGuideRates)
{
const auto val1 = getGroupData().guideRates;
const auto val2 = PackUnpack(val1);
DO_CHECKS(data::GroupGuideRates)
}
BOOST_AUTO_TEST_CASE(dataGroupData)
{
const auto val1 = getGroupData();
const auto val2 = PackUnpack(val1);
DO_CHECKS(data::GroupData)
}
BOOST_AUTO_TEST_CASE(CellData) BOOST_AUTO_TEST_CASE(CellData)
{ {
@ -319,11 +405,18 @@ BOOST_AUTO_TEST_CASE(RestartKey)
BOOST_AUTO_TEST_CASE(RestartValue) BOOST_AUTO_TEST_CASE(RestartValue)
{ {
Opm::data::WellRates wells1; auto wells1 = Opm::data::WellRates {{
Opm::data::GroupValues groups1; { "test_well", getWell() },
wells1.insert({"test_well", getWell()}); }};
Opm::RestartValue val1(getSolution(), wells1, groups1); auto groups1 = Opm::data::GroupValues {{
auto val2 = PackUnpack(val1); { "test_group1", getGroupData() },
}};
const auto val1 = Opm::RestartValue {
getSolution(), std::move(wells1), std::move(groups1)
};
const auto val2 = PackUnpack(val1);
DO_CHECKS(RestartValue) DO_CHECKS(RestartValue)
} }