Summary: Calculate Independent Set of Vectors for Restart

This commit ensures that the following set of vectors are stored/updated in

    Summary::add_timestep()

for all active wells and well groups (including FIELD):

    - Production rates for Oil, Water, Gas, and Reservoir Volume
      (i.e., (O|W|G|V)PR).

    - Cumulative production totals for Oil, Water, Gas, and
      Reservoir Volume (i.e., (O|W|G|V)PT).

    - Injection rates for Water and Gas (i.e., (W|G)IR).

    - Cumulative injection totals for Water and Gas ((W|G)IT).

    - Producing Water Cut (WCT).

    - Producing Gas/Oil ratio (GOR).

We additionally capture the well bottom-hole pressure (WBHP) for all
wells that are active at the pertinent simulation step (sim_step).

Add an accessor function

    const SummaryState& Summary::get_restart_vectors() const

that returns the 'prev_state' which contains these summary vectors
and add a set of unit tests to exercise the new interface.
This commit is contained in:
Bård Skaflestad 2018-06-25 13:47:34 +02:00
parent a50c823873
commit c3a11a2fb5
3 changed files with 828 additions and 4 deletions

View File

@ -62,6 +62,8 @@ class Summary {
~Summary();
const SummaryState& get_restart_vectors() const;
private:
class keyword_handlers;

View File

@ -17,7 +17,12 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <exception>
#include <initializer_list>
#include <iterator>
#include <numeric>
#include <stdexcept>
#include <string>
#include <opm/common/OpmLog/OpmLog.hpp>
@ -39,6 +44,78 @@
#include <ert/ecl/ecl_smspec.h>
#include <ert/ecl/ecl_kw_magic.h>
namespace {
std::vector<std::string> requiredRestartVectors()
{
return {
"OPR", "WPR", "GPR", "VPR",
"OPT", "WPT", "GPT", "VPT",
"WIR", "GIR",
"WIT", "GIT",
"WCT", "GOR",
};
}
std::vector<std::pair<std::string, std::string>>
requiredRestartVectors(const ::Opm::Schedule& sched)
{
auto entities = std::vector<std::pair<std::string, std::string>>{};
const auto& vectors = requiredRestartVectors();
auto makeEntities = [&vectors, &entities]
(const char cat, const std::string& name)
{
for (const auto& vector : vectors) {
entities.emplace_back(cat + vector, name);
}
};
for (const auto* well : sched.getWells()) {
const auto& well_name = well->name();
makeEntities('W', well_name);
entities.emplace_back("WBHP", well_name);
}
for (const auto* grp : sched.getGroups()) {
const auto& grp_name = grp->name();
if (grp_name != "FIELD") {
makeEntities('G', grp_name);
}
}
makeEntities('F', "FIELD");
return entities;
}
std::string genKey(const std::string& vector,
const std::string& entity)
{
return (entity == "FIELD")
? vector
: vector + ':' + entity;
}
ERT::ert_unique_ptr<smspec_node_type, smspec_node_free>
makeRestartVectorSMSPEC(const std::string& vector,
const std::string& entity)
{
const auto var_type =
ecl_smspec_identify_var_type(vector.c_str());
const int dims[] = { 1, 1, 1 };
return ERT::ert_unique_ptr<smspec_node_type, smspec_node_free> {
smspec_node_alloc(var_type, entity.c_str(), vector.c_str(),
"UNIT", ":", dims, 0, 0, 0.0f)
};
}
} // namespace Anonymous
/*
* This class takes simulator state and parser-provided information and
* orchestrates ert to write simulation results as requested by the SUMMARY
@ -805,7 +882,10 @@ class Summary::keyword_handlers {
std::map< std::pair <std::string, int>, smspec_node_type* > region_nodes;
std::map< std::pair <std::string, int>, smspec_node_type* > block_nodes;
// Memory management for restart-related summary vectors
// that are not requested in SUMMARY section.
std::vector<ERT::ert_unique_ptr<smspec_node_type,
smspec_node_free>> rstvec_backing_store;
};
Summary::Summary( const EclipseState& st,
@ -957,6 +1037,36 @@ Summary::Summary( const EclipseState& st,
Opm::OpmLog::info("Keyword " + std::string(keyword) + " is unhandled");
}
// Guarantee existence of certain summary vectors (mostly rates and
// cumulative totals for wells, groups, and field) that are required
// for simulation restart.
{
auto& rvec = this->handlers->rstvec_backing_store;
auto& handlers = this->handlers->handlers;
for (const auto& vector : requiredRestartVectors(schedule)) {
const auto& kw = vector.first;
const auto& entity = vector.second;
const auto key = genKey(kw, entity);
if (ecl_sum_has_key(this->ecl_sum.get(), key.c_str())) {
// Vector already requested in SUMMARY section.
// Don't add a second evaluation of this.
continue;
}
auto func = funs.find(kw);
if (func == std::end(funs)) {
throw std::logic_error {
"Unable to find handler for '" + kw + "'"
};
}
rvec.push_back(makeRestartVectorSMSPEC(kw, entity));
handlers.emplace_back(rvec.back().get(), func->second);
}
}
for (const auto& pair : this->handlers->handlers) {
const auto * nodeptr = pair.first;
if (smspec_node_is_total(nodeptr))
@ -1109,8 +1219,13 @@ void Summary::add_timestep( int report_step,
}
}
for (const auto& pair: st)
ecl_sum_tstep_set_from_key(tstep, pair.first.c_str(), pair.second);
for (const auto& pair: st) {
const auto* key = pair.first.c_str();
if (ecl_sum_has_key(this->ecl_sum.get(), key)) {
ecl_sum_tstep_set_from_key(tstep, key, pair.second);
}
}
this->prev_state = st;
this->prev_time_elapsed = secs_elapsed;
@ -1122,5 +1237,9 @@ void Summary::write() {
Summary::~Summary() {}
const SummaryState& Summary::get_restart_vectors() const
{
return this->prev_state;
}
}
}} // namespace Opm::out

View File

@ -199,6 +199,7 @@ struct setup {
};
BOOST_AUTO_TEST_SUITE(Summary)
/*
* Tests works by reading the Deck, write the summary output, then immediately
@ -1232,3 +1233,705 @@ BOOST_AUTO_TEST_CASE(Test_SummaryState) {
BOOST_CHECK(st.has("WWCT:OP_2"));
BOOST_CHECK(!st.has("NO_SUCH_KEY"));
}
BOOST_AUTO_TEST_SUITE_END()
// ####################################################################
namespace {
Opm::SummaryState calculateRestartVectors(const setup& config)
{
::Opm::out::Summary smry {
config.es, config.config, config.grid,
config.schedule, "Ignore.This"
};
smry.add_timestep(0, 0*day, config.es, config.schedule, config.wells, {});
smry.add_timestep(1, 1*day, config.es, config.schedule, config.wells, {});
smry.add_timestep(2, 2*day, config.es, config.schedule, config.wells, {});
return smry.get_restart_vectors();
}
auto calculateRestartVectors()
-> decltype(calculateRestartVectors({"test.Restart"}))
{
return calculateRestartVectors({"test.Restart"});
}
auto calculateRestartVectorsEffFac()
-> decltype(calculateRestartVectors({"test.Restart.EffFac",
"SUMMARY_EFF_FAC.DATA"}))
{
return calculateRestartVectors({
"test.Restart.EffFac", "SUMMARY_EFF_FAC.DATA"
});
}
std::vector<std::string> restartVectors()
{
return {
"WPR", "OPR", "GPR", "VPR",
"WPT", "OPT", "GPT", "VPT",
"WIR", "GIR", "WIT", "GIT",
"GOR", "WCT",
};
}
std::vector<std::string> activeWells()
{
return { "W_1", "W_2", "W_3" };
}
std::vector<std::string> activeGroups()
{
return { "G_1", "G_2" };
}
std::vector<std::string> activeGroupsEffFac()
{
return { "G_1", "G", "G_2", "G_3", "G_4" };
}
}
// ====================================================================
BOOST_AUTO_TEST_SUITE(Restart)
BOOST_AUTO_TEST_CASE(Well_Vectors_Present)
{
const auto rstrt = calculateRestartVectors();
for (const auto& vector : restartVectors()) {
for (const auto& w : activeWells()) {
BOOST_CHECK( rstrt.has("W" + vector + ':' + w));
BOOST_CHECK(!rstrt.has("W" + vector));
}
}
for (const auto& w : activeWells()) {
BOOST_CHECK( rstrt.has("WBHP:" + w));
BOOST_CHECK(!rstrt.has("WBHP"));
}
}
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(Well_Vectors_Correct)
{
const auto rstrt = calculateRestartVectors();
// W_1 (Producer)
{
// Production rates
BOOST_CHECK_CLOSE(rstrt.get("WWPR:W_1"), 10.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WOPR:W_1"), 10.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGPR:W_1"), 10.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WVPR:W_1"), 10.6 + 10.7 + 10.8, 1.0e-10);
// Production cumulative totals
BOOST_CHECK_CLOSE(rstrt.get("WWPT:W_1"), 2 * 1.0 * 10.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WOPT:W_1"), 2 * 1.0 * 10.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGPT:W_1"), 2 * 1.0 * 10.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WVPT:W_1"), 2 * 1.0 * (10.6 + 10.7 + 10.8), 1.0e-10);
// Injection rates
BOOST_CHECK_CLOSE(rstrt.get("WWIR:W_1"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGIR:W_1"), 0.0, 1.0e-10);
// Injection totals
BOOST_CHECK_CLOSE(rstrt.get("WWIT:W_1"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGIT:W_1"), 0.0, 1.0e-10);
// BHP
BOOST_CHECK_CLOSE(rstrt.get("WBHP:W_1"), 0.1, 1.0e-10); // Bars
// Water cut
BOOST_CHECK_CLOSE(rstrt.get("WWCT:W_1"), 10.0 / (10.0 + 10.1), 1.0e-10);
// Producing gas/oil ratio
BOOST_CHECK_CLOSE(rstrt.get("WGOR:W_1"), 10.2 / 10.1, 1.0e-10);
}
// W_2 (Producer)
{
// Production rates
BOOST_CHECK_CLOSE(rstrt.get("WWPR:W_2"), 20.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WOPR:W_2"), 20.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGPR:W_2"), 20.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WVPR:W_2"), 20.6 + 20.7 + 20.8, 1.0e-10);
// Production cumulative totals
BOOST_CHECK_CLOSE(rstrt.get("WWPT:W_2"), 2 * 1.0 * 20.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WOPT:W_2"), 2 * 1.0 * 20.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGPT:W_2"), 2 * 1.0 * 20.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WVPT:W_2"), 2 * 1.0 * (20.6 + 20.7 + 20.8), 1.0e-10);
// Injection rates
BOOST_CHECK_CLOSE(rstrt.get("WWIR:W_2"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGIR:W_2"), 0.0, 1.0e-10);
// Injection totals
BOOST_CHECK_CLOSE(rstrt.get("WWIT:W_2"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGIT:W_2"), 0.0, 1.0e-10);
// BHP
BOOST_CHECK_CLOSE(rstrt.get("WBHP:W_2"), 1.1, 1.0e-10); // Bars
// Water cut
BOOST_CHECK_CLOSE(rstrt.get("WWCT:W_2"), 20.0 / (20.0 + 20.1), 1.0e-10);
// Producing gas/oil ratio
BOOST_CHECK_CLOSE(rstrt.get("WGOR:W_2"), 20.2 / 20.1, 1.0e-10);
}
// W_3 (Injector)
{
// Production rates
BOOST_CHECK_CLOSE(rstrt.get("WWPR:W_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WOPR:W_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGPR:W_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WVPR:W_3"), 0.0, 1.0e-10);
// Production cumulative totals
BOOST_CHECK_CLOSE(rstrt.get("WWPT:W_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WOPT:W_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGPT:W_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WVPT:W_3"), 0.0, 1.0e-10);
// Injection rates
BOOST_CHECK_CLOSE(rstrt.get("WWIR:W_3"), 30.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGIR:W_3"), 30.2, 1.0e-10);
// Injection totals
BOOST_CHECK_CLOSE(rstrt.get("WWIT:W_3"), 2 * 1.0 * 30.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGIT:W_3"), 2 * 1.0 * 30.2, 1.0e-10);
// BHP
BOOST_CHECK_CLOSE(rstrt.get("WBHP:W_3"), 2.1, 1.0e-10); // Bars
// Water cut
BOOST_CHECK_CLOSE(rstrt.get("WWCT:W_3"), 0.0, 1.0e-10);
// Producing gas/oil ratio
BOOST_CHECK_CLOSE(rstrt.get("WGOR:W_3"), 0.0, 1.0e-10);
}
}
// ====================================================================
BOOST_AUTO_TEST_CASE(Group_Vectors_Present)
{
const auto& rstrt = calculateRestartVectors();
for (const auto& vector : restartVectors()) {
for (const auto& g : activeGroups()) {
BOOST_CHECK( rstrt.has("G" + vector + ':' + g));
BOOST_CHECK(!rstrt.has("G" + vector));
}
}
}
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(Group_Vectors_Correct)
{
const auto rstrt = calculateRestartVectors();
// G_1 (Producer, W_1 + W_2)
{
// Production rates
BOOST_CHECK_CLOSE(rstrt.get("GWPR:G_1"), 10.0 + 20.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPR:G_1"), 10.1 + 20.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPR:G_1"), 10.2 + 20.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPR:G_1"),
(10.6 + 10.7 + 10.8) +
(20.6 + 20.7 + 20.8), 1.0e-10);
// Production cumulative totals
BOOST_CHECK_CLOSE(rstrt.get("GWPT:G_1"), 2 * 1.0 * (10.0 + 20.0), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPT:G_1"), 2 * 1.0 * (10.1 + 20.1), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPT:G_1"), 2 * 1.0 * (10.2 + 20.2), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPT:G_1"),
2 * 1.0 *
((10.6 + 10.7 + 10.8) +
(20.6 + 20.7 + 20.8)), 1.0e-10);
// Injection rates
BOOST_CHECK_CLOSE(rstrt.get("GWIR:G_1"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIR:G_1"), 0.0, 1.0e-10);
// Injection totals
BOOST_CHECK_CLOSE(rstrt.get("GWIT:G_1"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIT:G_1"), 0.0, 1.0e-10);
// Water cut
BOOST_CHECK_CLOSE(rstrt.get("GWCT:G_1"),
(10.0 + 20.0) / ((10.0 + 10.1) + (20.0 + 20.1)), 1.0e-10);
// Producing gas/oil ratio
BOOST_CHECK_CLOSE(rstrt.get("GGOR:G_1"),
(10.2 + 20.2) / (10.1 + 20.1), 1.0e-10);
}
// G_2 (Injector, W_3)
{
// Production rates
BOOST_CHECK_CLOSE(rstrt.get("GWPR:G_2"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPR:G_2"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPR:G_2"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPR:G_2"), 0.0, 1.0e-10);
// Production cumulative totals
BOOST_CHECK_CLOSE(rstrt.get("GWPT:G_2"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPT:G_2"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPT:G_2"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPT:G_2"), 0.0, 1.0e-10);
// Injection rates
BOOST_CHECK_CLOSE(rstrt.get("GWIR:G_2"), 30.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIR:G_2"), 30.2, 1.0e-10);
// Injection totals
BOOST_CHECK_CLOSE(rstrt.get("GWIT:G_2"), 2 * 1.0 * 30.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIT:G_2"), 2 * 1.0 * 30.2, 1.0e-10);
// Water cut
BOOST_CHECK_CLOSE(rstrt.get("GWCT:G_2"), 0.0, 1.0e-10);
// Producing gas/oil ratio
BOOST_CHECK_CLOSE(rstrt.get("GGOR:G_2"), 0.0, 1.0e-10);
}
}
// ====================================================================
BOOST_AUTO_TEST_CASE(Field_Vectors_Present)
{
const auto& rstrt = calculateRestartVectors();
for (const auto& vector : restartVectors()) {
BOOST_CHECK( rstrt.has("F" + vector));
BOOST_CHECK(!rstrt.has("F" + vector + ":FIELD"));
}
}
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(Field_Vectors_Correct)
{
const auto rstrt = calculateRestartVectors();
// Production rates (F = G_1 = W_1 + W_2)
BOOST_CHECK_CLOSE(rstrt.get("FWPR"), 10.0 + 20.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FOPR"), 10.1 + 20.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FGPR"), 10.2 + 20.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FVPR"),
(10.6 + 10.7 + 10.8) +
(20.6 + 20.7 + 20.8), 1.0e-10);
// Production cumulative totals (F = G_1 = W_1 + W_2)
BOOST_CHECK_CLOSE(rstrt.get("FWPT"), 2 * 1.0 * (10.0 + 20.0), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FOPT"), 2 * 1.0 * (10.1 + 20.1), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FGPT"), 2 * 1.0 * (10.2 + 20.2), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FVPT"),
2 * 1.0 *
((10.6 + 10.7 + 10.8) +
(20.6 + 20.7 + 20.8)), 1.0e-10);
// Injection rates (F = G_2 = W_3)
BOOST_CHECK_CLOSE(rstrt.get("FWIR"), 30.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FGIR"), 30.2, 1.0e-10);
// Injection totals (F = G_2 = W_3)
BOOST_CHECK_CLOSE(rstrt.get("FWIT"), 2 * 1.0 * 30.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FGIT"), 2 * 1.0 * 30.2, 1.0e-10);
// Water cut (F = G_1 = W_1 + W_2)
BOOST_CHECK_CLOSE(rstrt.get("FWCT"),
(10.0 + 20.0) / ((10.0 + 10.1) + (20.0 + 20.1)), 1.0e-10);
// Producing gas/oil ratio (F = G_1 = W_1 + W_2)
BOOST_CHECK_CLOSE(rstrt.get("FGOR"),
(10.2 + 20.2) / (10.1 + 20.1), 1.0e-10);
}
BOOST_AUTO_TEST_SUITE_END()
// ####################################################################
BOOST_AUTO_TEST_SUITE(Restart_EffFac)
BOOST_AUTO_TEST_CASE(Well_Vectors_Correct)
{
const auto rstrt = calculateRestartVectorsEffFac();
// W_1 (Producer, efficiency factor = 1--no difference)
{
// Production rates
BOOST_CHECK_CLOSE(rstrt.get("WWPR:W_1"), 10.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WOPR:W_1"), 10.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGPR:W_1"), 10.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WVPR:W_1"), 10.6 + 10.7 + 10.8, 1.0e-10);
// Production cumulative totals
BOOST_CHECK_CLOSE(rstrt.get("WWPT:W_1"), 2 * 1.0 * 10.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WOPT:W_1"), 2 * 1.0 * 10.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGPT:W_1"), 2 * 1.0 * 10.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WVPT:W_1"), 2 * 1.0 * (10.6 + 10.7 + 10.8), 1.0e-10);
// Injection rates
BOOST_CHECK_CLOSE(rstrt.get("WWIR:W_1"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGIR:W_1"), 0.0, 1.0e-10);
// Injection totals
BOOST_CHECK_CLOSE(rstrt.get("WWIT:W_1"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGIT:W_1"), 0.0, 1.0e-10);
// BHP
BOOST_CHECK_CLOSE(rstrt.get("WBHP:W_1"), 0.1, 1.0e-10); // Bars
// Water cut
BOOST_CHECK_CLOSE(rstrt.get("WWCT:W_1"), 10.0 / (10.0 + 10.1), 1.0e-10);
// Producing gas/oil ratio
BOOST_CHECK_CLOSE(rstrt.get("WGOR:W_1"), 10.2 / 10.1, 1.0e-10);
}
// W_2 (Producer, efficiency factor = 0.2)
{
const auto wefac = 0.2;
const auto gefac = 0.01;
// Production rates (unaffected by WEFAC)
BOOST_CHECK_CLOSE(rstrt.get("WWPR:W_2"), 20.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WOPR:W_2"), 20.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGPR:W_2"), 20.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WVPR:W_2"), (20.6 + 20.7 + 20.8), 1.0e-10);
// Production cumulative totals (affected by WEFAC and containing GEFAC)
BOOST_CHECK_CLOSE(rstrt.get("WWPT:W_2"), 2 * 1.0 * wefac * gefac * 20.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WOPT:W_2"), 2 * 1.0 * wefac * gefac * 20.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGPT:W_2"), 2 * 1.0 * wefac * gefac * 20.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WVPT:W_2"), 2 * 1.0 * wefac * gefac * (20.6 + 20.7 + 20.8), 1.0e-10);
// Injection rates
BOOST_CHECK_CLOSE(rstrt.get("WWIR:W_2"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGIR:W_2"), 0.0, 1.0e-10);
// Injection totals
BOOST_CHECK_CLOSE(rstrt.get("WWIT:W_2"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGIT:W_2"), 0.0, 1.0e-10);
// BHP
BOOST_CHECK_CLOSE(rstrt.get("WBHP:W_2"), 1.1, 1.0e-10); // Bars
// Water cut (unaffected by WEFAC)
BOOST_CHECK_CLOSE(rstrt.get("WWCT:W_2"), 20.0 / (20.0 + 20.1), 1.0e-10);
// Producing gas/oil ratio (unaffected by WEFAC)
BOOST_CHECK_CLOSE(rstrt.get("WGOR:W_2"), 20.2 / 20.1, 1.0e-10);
}
// W_3 (Injector, efficiency factor = 0.3)
{
const auto wefac = 0.3;
const auto gefac = 0.02; // G_3
// Production rates
BOOST_CHECK_CLOSE(rstrt.get("WWPR:W_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WOPR:W_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGPR:W_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WVPR:W_3"), 0.0, 1.0e-10);
// Production cumulative totals
BOOST_CHECK_CLOSE(rstrt.get("WWPT:W_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WOPT:W_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGPT:W_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WVPT:W_3"), 0.0, 1.0e-10);
// Injection rates (unaffected by WEFAC)
BOOST_CHECK_CLOSE(rstrt.get("WWIR:W_3"), 30.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGIR:W_3"), 30.2, 1.0e-10);
// Injection totals (affected by WEFAC and containing GEFAC)
// GEFAC(G_4) = 0.03 at sim_step = 1
// GEFAC(G_4) = 0.04 at sim_step = 2
BOOST_CHECK_CLOSE(rstrt.get("WWIT:W_3"),
30.0 * wefac * gefac *
((1.0 * 0.03) + (1.0 * 0.04)), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("WGIT:W_3"),
30.2 * wefac * gefac *
((1.0 * 0.03) + (1.0 * 0.04)), 1.0e-10);
// BHP
BOOST_CHECK_CLOSE(rstrt.get("WBHP:W_3"), 2.1, 1.0e-10); // Bars
// Water cut (zero for injectors)
BOOST_CHECK_CLOSE(rstrt.get("WWCT:W_3"), 0.0, 1.0e-10);
// Producing gas/oil ratio (zero for injectors)
BOOST_CHECK_CLOSE(rstrt.get("WGOR:W_3"), 0.0, 1.0e-10);
}
}
// ====================================================================
BOOST_AUTO_TEST_CASE(Group_Vectors_Present)
{
const auto& rstrt = calculateRestartVectorsEffFac();
for (const auto& vector : restartVectors()) {
for (const auto& g : activeGroupsEffFac()) {
BOOST_CHECK( rstrt.has("G" + vector + ':' + g));
BOOST_CHECK(!rstrt.has("G" + vector));
}
}
}
// --------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(Group_Vectors_Correct)
{
const auto rstrt = calculateRestartVectorsEffFac();
// G_1 (Producer, W_1, GEFAC = 1--no change)
{
// Production rates
BOOST_CHECK_CLOSE(rstrt.get("GWPR:G_1"), 10.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPR:G_1"), 10.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPR:G_1"), 10.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPR:G_1"), (10.6 + 10.7 + 10.8), 1.0e-10);
// Production cumulative totals
BOOST_CHECK_CLOSE(rstrt.get("GWPT:G_1"), 2 * 1.0 * 10.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPT:G_1"), 2 * 1.0 * 10.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPT:G_1"), 2 * 1.0 * 10.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPT:G_1"),
2 * 1.0 * (10.6 + 10.7 + 10.8), 1.0e-10);
// Injection rates
BOOST_CHECK_CLOSE(rstrt.get("GWIR:G_1"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIR:G_1"), 0.0, 1.0e-10);
// Injection totals
BOOST_CHECK_CLOSE(rstrt.get("GWIT:G_1"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIT:G_1"), 0.0, 1.0e-10);
// Water cut
BOOST_CHECK_CLOSE(rstrt.get("GWCT:G_1"),
10.0 / (10.0 + 10.1), 1.0e-10);
// Producing gas/oil ratio
BOOST_CHECK_CLOSE(rstrt.get("GGOR:G_1"),
10.2 / 10.1, 1.0e-10);
}
// G_2 (Producer, W_2, GEFAC = 0.01)
{
const auto wefac = 0.2;
const auto gefac = 0.01;
// Production rates (affected by WEFAC)
BOOST_CHECK_CLOSE(rstrt.get("GWPR:G_2"), wefac * 20.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPR:G_2"), wefac * 20.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPR:G_2"), wefac * 20.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPR:G_2"), wefac * (20.6 + 20.7 + 20.8), 1.0e-10);
// Production cumulative totals (affected by both WEFAC and GEFAC)
BOOST_CHECK_CLOSE(rstrt.get("GWPT:G_2"), 2 * 1.0 * gefac * wefac * 20.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPT:G_2"), 2 * 1.0 * gefac * wefac * 20.1, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPT:G_2"), 2 * 1.0 * gefac * wefac * 20.2, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPT:G_2"), 2 * 1.0 * gefac * wefac * (20.6 + 20.7 + 20.8), 1.0e-10);
// Injection rates
BOOST_CHECK_CLOSE(rstrt.get("GWIR:G_2"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIR:G_2"), 0.0, 1.0e-10);
// Injection totals
BOOST_CHECK_CLOSE(rstrt.get("GWIT:G_2"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIT:G_2"), 0.0, 1.0e-10);
// Water cut (unaffected by WEFAC or GEFAC since G_2 = W_2)
BOOST_CHECK_CLOSE(rstrt.get("GWCT:G_2"), 20.0 / (20.0 + 20.1), 1.0e-10);
// Producing gas/oil ratio (unaffected by WEFAC or GEFAC since G_2 = W_2)
BOOST_CHECK_CLOSE(rstrt.get("GGOR:G_2"), 20.2 / 20.1, 1.0e-10);
}
// G (Producer, G_1 + G_2)
{
const auto gwefac = 0.01 * 0.2;
BOOST_CHECK_CLOSE(rstrt.get("GWPR:G"), 10.0 + (gwefac * 20.0), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPR:G"), 10.1 + (gwefac * 20.1), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPR:G"), 10.2 + (gwefac * 20.2), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPR:G"),
(10.6 + 10.7 + 10.8) +
(gwefac * (20.6 + 20.7 + 20.8)), 1.0e-10);
// Production cumulative totals
BOOST_CHECK_CLOSE(rstrt.get("GWPT:G"),
2 * 1.0 * (10.0 + (gwefac * 20.0)), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPT:G"),
2 * 1.0 * (10.1 + (gwefac * 20.1)), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPT:G"),
2 * 1.0 * (10.2 + (gwefac * 20.2)), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPT:G"),
2 * 1.0 *
( (10.6 + 10.7 + 10.8) +
(gwefac * (20.6 + 20.7 + 20.8))), 1.0e-10);
// Injection rates
BOOST_CHECK_CLOSE(rstrt.get("GWIR:G"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIR:G"), 0.0, 1.0e-10);
// Injection totals
BOOST_CHECK_CLOSE(rstrt.get("GWIT:G"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIT:G"), 0.0, 1.0e-10);
// Water cut
BOOST_CHECK_CLOSE(rstrt.get("GWCT:G"),
(10.0 + (gwefac * 20.0)) /
(10.0 + 10.1 + (gwefac * (20.0 + 20.1))), 1.0e-10);
// Producing gas/oil ratio
BOOST_CHECK_CLOSE(rstrt.get("GGOR:G"),
(10.2 + (gwefac * 20.2)) /
(10.1 + (gwefac * 20.1)), 1.0e-10);
}
// G_3 (Injector, W_3)
{
const auto wefac = 0.3;
const auto gefac_3 = 0.02;
// Production rates
BOOST_CHECK_CLOSE(rstrt.get("GWPR:G_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPR:G_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPR:G_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPR:G_3"), 0.0, 1.0e-10);
// Production cumulative totals
BOOST_CHECK_CLOSE(rstrt.get("GWPT:G_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPT:G_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPT:G_3"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPT:G_3"), 0.0, 1.0e-10);
// Injection rates
BOOST_CHECK_CLOSE(rstrt.get("GWIR:G_3"), wefac * 30.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIR:G_3"), wefac * 30.2, 1.0e-10);
// Injection totals
BOOST_CHECK_CLOSE(rstrt.get("GWIT:G_3"),
30.0 * gefac_3 * wefac *
((1.0 * 0.03) + (1.0 * 0.04)), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIT:G_3"),
30.2 * gefac_3 * wefac *
((1.0 * 0.03) + (1.0 * 0.04)), 1.0e-10);
// Water cut (zero for injectors)
BOOST_CHECK_CLOSE(rstrt.get("GWCT:G_3"), 0.0, 1.0e-10);
// Producing gas/oil ratio (zero for injectors)
BOOST_CHECK_CLOSE(rstrt.get("GGOR:G_3"), 0.0, 1.0e-10);
}
// G_4 (Injector, G_3, GEFAC = 0.03 and 0.04)
{
// Production rates
BOOST_CHECK_CLOSE(rstrt.get("GWPR:G_4"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPR:G_4"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPR:G_4"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPR:G_4"), 0.0, 1.0e-10);
// Production cumulative totals
BOOST_CHECK_CLOSE(rstrt.get("GWPT:G_4"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GOPT:G_4"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGPT:G_4"), 0.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GVPT:G_4"), 0.0, 1.0e-10);
// Injection rates (at sim_step = 2)
BOOST_CHECK_CLOSE(rstrt.get("GWIR:G_4"), 0.02 * 0.3 * 30.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIR:G_4"), 0.02 * 0.3 * 30.2, 1.0e-10);
// Injection totals (GEFAC(G_4) = 0.03 at sim_step = 1,
// GEFAC(G_4) = 0.04 at sim_step = 2)
BOOST_CHECK_CLOSE(rstrt.get("GWIT:G_4"),
30.0 * 0.3 * 0.02 *
((0.03 * 1.0) + (0.04 * 1.0)), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("GGIT:G_4"),
30.2 * 0.3 * 0.02 *
((0.03 * 1.0) + (0.04 * 1.0)), 1.0e-10);
// Water cut
BOOST_CHECK_CLOSE(rstrt.get("GWCT:G_4"), 0.0, 1.0e-10);
// Producing gas/oil ratio
BOOST_CHECK_CLOSE(rstrt.get("GGOR:G_4"), 0.0, 1.0e-10);
}
}
// ====================================================================
BOOST_AUTO_TEST_CASE(Field_Vectors_Correct)
{
const auto rstrt = calculateRestartVectorsEffFac();
// Field = G + G_4
const auto efac_G = 0.01 * 0.2;
BOOST_CHECK_CLOSE(rstrt.get("FWPR"), 10.0 + (efac_G * 20.0), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FOPR"), 10.1 + (efac_G * 20.1), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FGPR"), 10.2 + (efac_G * 20.2), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FVPR"),
(10.6 + 10.7 + 10.8) +
(efac_G * (20.6 + 20.7 + 20.8)), 1.0e-10);
// Production cumulative totals
BOOST_CHECK_CLOSE(rstrt.get("FWPT"),
2 * 1.0 * (10.0 + (efac_G * 20.0)), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FOPT"),
2 * 1.0 * (10.1 + (efac_G * 20.1)), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FGPT"),
2 * 1.0 * (10.2 + (efac_G * 20.2)), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FVPT"),
2 * 1.0 *
( (10.6 + 10.7 + 10.8) +
(efac_G * (20.6 + 20.7 + 20.8))), 1.0e-10);
// Injection rates (at sim_step = 2, GEFAC(G_4) = 0.04)
BOOST_CHECK_CLOSE(rstrt.get("FWIR"), 0.02 * 0.04 * 0.3 * 30.0, 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FGIR"), 0.02 * 0.04 * 0.3 * 30.2, 1.0e-10);
// Injection totals (GEFAC(G_4) = 0.03 at sim_step = 1,
// GEFAC(G_4) = 0.04 at sim_step = 2)
BOOST_CHECK_CLOSE(rstrt.get("FWIT"),
30.0 * 0.3 * 0.02 *
((0.03 * 1.0) + (0.04 * 1.0)), 1.0e-10);
BOOST_CHECK_CLOSE(rstrt.get("FGIT"),
30.2 * 0.3 * 0.02 *
((0.03 * 1.0) + (0.04 * 1.0)), 1.0e-10);
// Water cut
BOOST_CHECK_CLOSE(rstrt.get("FWCT"),
(10.0 + (efac_G * 20.0)) /
(10.0 + 10.1 + (efac_G * (20.0 + 20.1))), 1.0e-10);
// Producing gas/oil ratio
BOOST_CHECK_CLOSE(rstrt.get("FGOR"),
(10.2 + (efac_G * 20.2)) /
(10.1 + (efac_G * 20.1)), 1.0e-10);
}
BOOST_AUTO_TEST_SUITE_END()