Merge pull request #1592 from jalvestad/opm_data_Groups
Changes in opm-common for current Production/Injection Group Control parameters
This commit is contained in:
@@ -380,6 +380,7 @@ if(ENABLE_ECL_OUTPUT)
|
||||
tests/test_rst.cpp
|
||||
tests/test_Solution.cpp
|
||||
tests/test_Summary.cpp
|
||||
tests/test_Summary_Group.cpp
|
||||
tests/test_Tables.cpp
|
||||
tests/test_Wells.cpp
|
||||
tests/test_WindowedArray.cpp
|
||||
@@ -411,6 +412,7 @@ if(ENABLE_ECL_OUTPUT)
|
||||
tests/SOFR_TEST.DATA
|
||||
tests/UDQ_TEST_WCONPROD_IUAD-2.DATA
|
||||
tests/UDQ_ACTIONX_TEST1.DATA
|
||||
tests/UDQ_ACTIONX_TEST1_U.DATA
|
||||
tests/include_example_pvt.txt
|
||||
tests/include_example_summary.txt
|
||||
tests/include_sgof.txt
|
||||
@@ -727,6 +729,7 @@ if(ENABLE_ECL_OUTPUT)
|
||||
opm/output/data/Cells.hpp
|
||||
opm/output/data/Solution.hpp
|
||||
opm/output/data/Wells.hpp
|
||||
opm/output/data/Groups.hpp
|
||||
opm/output/eclipse/VectorItems/aquifer.hpp
|
||||
opm/output/eclipse/VectorItems/connection.hpp
|
||||
opm/output/eclipse/VectorItems/group.hpp
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <opm/output/eclipse/Summary.hpp>
|
||||
#include <opm/output/data/Solution.hpp>
|
||||
#include <opm/output/data/Wells.hpp>
|
||||
#include <opm/output/data/Groups.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Action/ActionContext.hpp>
|
||||
@@ -91,6 +92,8 @@ void msim::run_step(const Schedule& schedule, SummaryState& st, data::Solution&
|
||||
|
||||
this->simulate(schedule, st, sol, well_data, report_step, seconds_elapsed, time_step);
|
||||
|
||||
Opm::data::Group group_data;
|
||||
|
||||
seconds_elapsed += time_step;
|
||||
|
||||
io.summary().eval(st,
|
||||
@@ -99,6 +102,7 @@ void msim::run_step(const Schedule& schedule, SummaryState& st, data::Solution&
|
||||
this->state,
|
||||
schedule,
|
||||
well_data,
|
||||
group_data,
|
||||
{});
|
||||
|
||||
this->output(st,
|
||||
|
||||
121
opm/output/data/Groups.hpp
Normal file
121
opm/output/data/Groups.hpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
Copyright 2016 Statoil ASA.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_OUTPUT_GROUPS_HPP
|
||||
#define OPM_OUTPUT_GROUPS_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
namespace data {
|
||||
|
||||
struct currentGroupConstraints {
|
||||
Opm::Group::ProductionCMode currentProdConstraint;
|
||||
Opm::Group::InjectionCMode currentGasInjectionConstraint;
|
||||
Opm::Group::InjectionCMode currentWaterInjectionConstraint;
|
||||
|
||||
template <class MessageBufferType>
|
||||
void write(MessageBufferType& buffer) const;
|
||||
template <class MessageBufferType>
|
||||
void read(MessageBufferType& buffer);
|
||||
|
||||
inline currentGroupConstraints& set( Opm::Group::ProductionCMode cpc,
|
||||
Opm::Group::InjectionCMode cgic,
|
||||
Opm::Group::InjectionCMode cwic);
|
||||
|
||||
inline bool has();
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Group : public std::map<std::string, Opm::data::currentGroupConstraints> {
|
||||
public:
|
||||
|
||||
template <class MessageBufferType>
|
||||
void write(MessageBufferType& buffer) const {
|
||||
unsigned int size = this->size();
|
||||
buffer.write(size);
|
||||
for (const auto& witr : *this) {
|
||||
const std::string& name = witr.first;
|
||||
buffer.write(name);
|
||||
const auto& pi_constr = witr.second;
|
||||
pi_constr.write(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
template <class MessageBufferType>
|
||||
void read(MessageBufferType& buffer) {
|
||||
unsigned int size;
|
||||
buffer.read(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
std::string name;
|
||||
buffer.read(name);
|
||||
currentGroupConstraints cgc;
|
||||
cgc.read(buffer);
|
||||
this->emplace(name, cgc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* IMPLEMENTATIONS */
|
||||
|
||||
template <class MessageBufferType>
|
||||
void currentGroupConstraints::write(MessageBufferType& buffer) const {
|
||||
buffer.write(this->currentProdConstraint);
|
||||
buffer.write(this->currentGasInjectionConstraint);
|
||||
buffer.write(this->currentWaterInjectionConstraint);
|
||||
}
|
||||
|
||||
template <class MessageBufferType>
|
||||
void currentGroupConstraints::read(MessageBufferType& buffer) {
|
||||
buffer.read(this->currentProdConstraint);
|
||||
buffer.read(this->currentGasInjectionConstraint);
|
||||
buffer.read(this->currentWaterInjectionConstraint);
|
||||
}
|
||||
|
||||
|
||||
inline currentGroupConstraints& currentGroupConstraints::set( Opm::Group::ProductionCMode cpc,
|
||||
Opm::Group::InjectionCMode cgic,
|
||||
Opm::Group::InjectionCMode cwic) {
|
||||
this->currentGasInjectionConstraint = cgic;
|
||||
this->currentWaterInjectionConstraint = cwic;
|
||||
this->currentProdConstraint = cpc;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool currentGroupConstraints::has() {
|
||||
return ((&this->currentGasInjectionConstraint != nullptr) && (&this->currentGasInjectionConstraint != nullptr)
|
||||
&& (&this->currentProdConstraint != nullptr));
|
||||
}
|
||||
|
||||
|
||||
}} // Opm::data
|
||||
|
||||
#endif //OPM_OUTPUT_GROUPS_HPP
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef OPM_OUTPUT_SUMMARY_HPP
|
||||
#define OPM_OUTPUT_SUMMARY_HPP
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -36,6 +38,7 @@ namespace Opm {
|
||||
|
||||
namespace Opm { namespace data {
|
||||
class WellRates;
|
||||
class Group;
|
||||
}} // namespace Opm::data
|
||||
|
||||
namespace Opm { namespace out {
|
||||
@@ -62,12 +65,14 @@ public:
|
||||
const EclipseState& es,
|
||||
const Schedule& schedule,
|
||||
const data::WellRates& well_solution,
|
||||
const data::Group& group_solution,
|
||||
const GlobalProcessParameters& single_values,
|
||||
const RegionParameters& region_values = {},
|
||||
const BlockValues& block_values = {}) const;
|
||||
|
||||
void write() const;
|
||||
|
||||
|
||||
private:
|
||||
class SummaryImplementation;
|
||||
std::unique_ptr<SummaryImplementation> pImpl_;
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace Opm {
|
||||
};
|
||||
|
||||
enum class Type {
|
||||
Rate, Total, Ratio, Pressure, Count,
|
||||
Rate, Total, Ratio, Pressure, Count, Mode,
|
||||
Undefined,
|
||||
};
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <opm/io/eclipse/OutputStream.hpp>
|
||||
|
||||
#include <opm/output/data/Wells.hpp>
|
||||
#include <opm/output/data/Groups.hpp>
|
||||
#include <opm/output/eclipse/RegionCache.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
@@ -70,6 +71,31 @@ namespace {
|
||||
Opm::SummaryConfigNode::Type type;
|
||||
};
|
||||
|
||||
using p_cmode = Opm::Group::ProductionCMode;
|
||||
const std::map<p_cmode, int> pCModeToPCntlMode = {
|
||||
{p_cmode::NONE, 0},
|
||||
{p_cmode::ORAT, 1},
|
||||
{p_cmode::WRAT, 2},
|
||||
{p_cmode::GRAT, 3},
|
||||
{p_cmode::LRAT, 4},
|
||||
{p_cmode::CRAT, 9},
|
||||
{p_cmode::RESV, 5},
|
||||
{p_cmode::PRBL, 6},
|
||||
{p_cmode::FLD, 0}, // same as NONE
|
||||
|
||||
};
|
||||
|
||||
using i_cmode = Opm::Group::InjectionCMode;
|
||||
const std::map<i_cmode, int> iCModeToICntlMode = {
|
||||
{i_cmode::NONE, 0},
|
||||
{i_cmode::RATE, 1},
|
||||
{i_cmode::RESV, 2},
|
||||
{i_cmode::REIN, 3},
|
||||
{i_cmode::VREP, 4},
|
||||
{i_cmode::FLD, 0}, // same as NONE
|
||||
{i_cmode::SALE, 0}, // not used in E100
|
||||
};
|
||||
|
||||
std::vector<ParamCTorArgs> requiredRestartVectors()
|
||||
{
|
||||
using Type = ::Opm::SummaryConfigNode::Type;
|
||||
@@ -104,7 +130,7 @@ namespace {
|
||||
ParamCTorArgs{ "WIT" , Type::Total },
|
||||
ParamCTorArgs{ "GIT" , Type::Total },
|
||||
ParamCTorArgs{ "WITH", Type::Total },
|
||||
ParamCTorArgs{ "GITH", Type::Total },
|
||||
ParamCTorArgs{ "GITH", Type::Total }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -147,12 +173,37 @@ namespace {
|
||||
}
|
||||
|
||||
for (const auto& grp_name : sched.groupNames()) {
|
||||
if (grp_name != "FIELD")
|
||||
if (grp_name != "FIELD") {
|
||||
makeEntities('G', SN::Category::Group, grp_name);
|
||||
|
||||
entities.emplace_back("GMCTP", SN::Category::Group, ::Opm::Location());
|
||||
entities.back().namedEntity(grp_name)
|
||||
.parameterType(SN::Type::Mode);
|
||||
|
||||
entities.emplace_back("GMCTW", SN::Category::Group, ::Opm::Location());
|
||||
entities.back().namedEntity(grp_name)
|
||||
.parameterType(SN::Type::Mode);
|
||||
|
||||
entities.emplace_back("GMCTG", SN::Category::Group, ::Opm::Location());
|
||||
entities.back().namedEntity(grp_name)
|
||||
.parameterType(SN::Type::Mode);
|
||||
}
|
||||
}
|
||||
|
||||
makeEntities('F', SN::Category::Field, "FIELD");
|
||||
|
||||
entities.emplace_back("FMCTP", SN::Category::Field, ::Opm::Location());
|
||||
entities.back().namedEntity("FIELD")
|
||||
.parameterType(SN::Type::Mode);
|
||||
|
||||
entities.emplace_back("FMCTW", SN::Category::Field, ::Opm::Location());
|
||||
entities.back().namedEntity("FIELD")
|
||||
.parameterType(SN::Type::Mode);
|
||||
|
||||
entities.emplace_back("FMCTG", SN::Category::Field, ::Opm::Location());
|
||||
entities.back().namedEntity("FIELD")
|
||||
.parameterType(SN::Type::Mode);
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
@@ -310,6 +361,7 @@ struct quantity {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* All functions must have the same parameters, so they're gathered in a struct
|
||||
* and functions use whatever information they care about.
|
||||
@@ -319,11 +371,13 @@ struct quantity {
|
||||
*/
|
||||
struct fn_args {
|
||||
const std::vector<Opm::Well>& schedule_wells;
|
||||
const std::string group_name;
|
||||
double duration;
|
||||
const int sim_step;
|
||||
int num;
|
||||
const Opm::SummaryState& st;
|
||||
const Opm::data::Wells& wells;
|
||||
const Opm::data::Group& group;
|
||||
const Opm::out::RegionCache& regionCache;
|
||||
const Opm::EclipseGrid& grid;
|
||||
const std::vector< std::pair< std::string, double > > eff_factors;
|
||||
@@ -688,6 +742,70 @@ inline quantity potential_rate( const fn_args& args ) {
|
||||
return { sum, rate_unit< phase >() };
|
||||
}
|
||||
|
||||
template < bool isGroup, bool Producer, bool waterInjector, bool gasInjector>
|
||||
inline quantity group_control( const fn_args& args ) {
|
||||
|
||||
std::string g_name = "";
|
||||
if (isGroup) {
|
||||
const quantity zero = { static_cast<double>(0), Opm::UnitSystem::measure::identity};
|
||||
if( args.group_name.empty() ) return zero;
|
||||
|
||||
g_name = args.group_name;
|
||||
}
|
||||
else {
|
||||
g_name = "FIELD";
|
||||
}
|
||||
|
||||
int cntl_mode = 0;
|
||||
|
||||
// production control
|
||||
if (Producer) {
|
||||
const auto it_g = args.group.find(g_name);
|
||||
if (it_g != args.group.end()) {
|
||||
const auto& value = it_g->second.currentProdConstraint;
|
||||
auto it_c = pCModeToPCntlMode.find(value);
|
||||
if (it_c == pCModeToPCntlMode.end()) {
|
||||
std::stringstream str;
|
||||
str << "unknown control CMode: " << static_cast<int>(value);
|
||||
throw std::invalid_argument(str.str());
|
||||
}
|
||||
cntl_mode = it_c->second;
|
||||
}
|
||||
}
|
||||
// water injection control
|
||||
else if (waterInjector){
|
||||
const auto it_g = args.group.find(g_name);
|
||||
if (it_g != args.group.end()) {
|
||||
const auto& value = it_g->second.currentWaterInjectionConstraint;
|
||||
auto it_c = iCModeToICntlMode.find(value);
|
||||
if (it_c == iCModeToICntlMode.end()) {
|
||||
std::stringstream str;
|
||||
str << "unknown control CMode: " << static_cast<int>(value);
|
||||
throw std::invalid_argument(str.str());
|
||||
}
|
||||
cntl_mode = it_c->second;
|
||||
}
|
||||
}
|
||||
|
||||
// gas injection control
|
||||
else if (gasInjector){
|
||||
const auto it_g = args.group.find(g_name);
|
||||
if (it_g != args.group.end()) {
|
||||
const auto& value = it_g->second.currentGasInjectionConstraint;
|
||||
auto it_c = iCModeToICntlMode.find(value);
|
||||
if (it_c == iCModeToICntlMode.end()) {
|
||||
std::stringstream str;
|
||||
str << "unknown control CMode: " << static_cast<int>(value);
|
||||
throw std::invalid_argument(str.str());
|
||||
}
|
||||
cntl_mode = it_c->second;
|
||||
}
|
||||
}
|
||||
|
||||
return {static_cast<double>(cntl_mode), Opm::UnitSystem::measure::identity};
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A small DSL, really poor man's function composition, to avoid massive
|
||||
* repetition when declaring the handlers for each individual keyword. bin_op
|
||||
@@ -831,6 +949,11 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
{ "GOPI", potential_rate< rt::well_potential_oil , false, true>},
|
||||
{ "GGPI", potential_rate< rt::well_potential_gas , false, true>},
|
||||
|
||||
//Group control mode
|
||||
{ "GMCTP", group_control< true, true, false, false >},
|
||||
{ "GMCTW", group_control< true, false, true, false >},
|
||||
{ "GMCTG", group_control< true, false, false, true >},
|
||||
|
||||
{ "WWPRH", production_history< Opm::Phase::WATER > },
|
||||
{ "WOPRH", production_history< Opm::Phase::OIL > },
|
||||
{ "WGPRH", production_history< Opm::Phase::GAS > },
|
||||
@@ -1024,6 +1147,11 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
{ "FMWPR", flowing< producer > },
|
||||
{ "FVPRT", res_vol_production_target },
|
||||
|
||||
//Field control mode
|
||||
{ "FMCTP", group_control< false, true, false, false >},
|
||||
{ "FMCTW", group_control< false, false, true, false >},
|
||||
{ "FMCTG", group_control< false, false, false, true >},
|
||||
|
||||
/* Region properties */
|
||||
{ "ROIR" , region_rate< rt::oil, injector > },
|
||||
{ "RGIR" , region_rate< rt::gas, injector > },
|
||||
@@ -1358,6 +1486,7 @@ namespace Evaluator {
|
||||
struct SimulatorResults
|
||||
{
|
||||
const Opm::data::WellRates& wellSol;
|
||||
const Opm::data::Group& groupSol;
|
||||
const std::map<std::string, double>& single;
|
||||
const std::map<std::string, std::vector<double>>& region;
|
||||
const std::map<std::pair<std::string, int>, double>& block;
|
||||
@@ -1402,13 +1531,15 @@ namespace Evaluator {
|
||||
// wells apply at this sim_step. Nothing to do.
|
||||
return;
|
||||
|
||||
std::string group_name = this->node_.category() == Opm::SummaryConfigNode::Category::Group ? this->node_.namedEntity() : "";
|
||||
|
||||
EfficiencyFactor efac{};
|
||||
efac.setFactors(this->node_, input.sched, wells, sim_step);
|
||||
|
||||
const fn_args args {
|
||||
wells, stepSize, static_cast<int>(sim_step),
|
||||
wells, group_name, stepSize, static_cast<int>(sim_step),
|
||||
std::max(0, this->node_.number()),
|
||||
st, simRes.wellSol, input.reg, input.grid,
|
||||
st, simRes.wellSol, simRes.groupSol, input.reg, input.grid,
|
||||
std::move(efac.factors)
|
||||
};
|
||||
|
||||
@@ -1798,8 +1929,8 @@ namespace Evaluator {
|
||||
const auto reg = Opm::out::RegionCache{};
|
||||
|
||||
const fn_args args {
|
||||
{}, 0.0, 0, std::max(0, this->node_->number()),
|
||||
this->st_, {}, reg, this->grid_,
|
||||
{}, "", 0.0, 0, std::max(0, this->node_->number()),
|
||||
this->st_, {}, {}, reg, this->grid_,
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -2028,6 +2159,7 @@ public:
|
||||
const int sim_step,
|
||||
const double duration,
|
||||
const data::WellRates& well_solution,
|
||||
const data::Group& group_solution,
|
||||
const GlobalProcessParameters& single_values,
|
||||
const RegionParameters& region_values,
|
||||
const BlockValues& block_values,
|
||||
@@ -2129,6 +2261,7 @@ eval(const EclipseState& es,
|
||||
const int sim_step,
|
||||
const double duration,
|
||||
const data::WellRates& well_solution,
|
||||
const data::Group& group_solution,
|
||||
const GlobalProcessParameters& single_values,
|
||||
const RegionParameters& region_values,
|
||||
const BlockValues& block_values,
|
||||
@@ -2139,7 +2272,7 @@ eval(const EclipseState& es,
|
||||
};
|
||||
|
||||
const Evaluator::SimulatorResults simRes {
|
||||
well_solution, single_values, region_values, block_values
|
||||
well_solution, group_solution, single_values, region_values, block_values
|
||||
};
|
||||
|
||||
for (auto& evalPtr : this->outputParameters_.getEvaluators()) {
|
||||
@@ -2404,6 +2537,7 @@ void Summary::eval(SummaryState& st,
|
||||
const EclipseState& es,
|
||||
const Schedule& schedule,
|
||||
const data::WellRates& well_solution,
|
||||
const data::Group& group_solution,
|
||||
const GlobalProcessParameters& single_values,
|
||||
const RegionParameters& region_values,
|
||||
const BlockValues& block_values) const
|
||||
@@ -2419,7 +2553,7 @@ void Summary::eval(SummaryState& st,
|
||||
const auto sim_step = std::max( 0, report_step - 1 );
|
||||
|
||||
this->pImpl_->eval(es, schedule, sim_step, duration,
|
||||
well_solution, single_values,
|
||||
well_solution, group_solution, single_values,
|
||||
region_values, block_values, st);
|
||||
|
||||
eval_udq(schedule, sim_step, st);
|
||||
|
||||
526
tests/UDQ_ACTIONX_TEST1_U.DATA
Normal file
526
tests/UDQ_ACTIONX_TEST1_U.DATA
Normal file
@@ -0,0 +1,526 @@
|
||||
-- This reservoir simulation deck is made available under the Open Database
|
||||
-- License: http://opendatacommons.org/licenses/odbl/1.0/. Any rights in
|
||||
-- individual contents of the database are licensed under the Database Contents
|
||||
-- License: http://opendatacommons.org/licenses/dbcl/1.0/
|
||||
|
||||
-- Copyright (C) 2018 Equinor
|
||||
|
||||
-- This deck uses User defined quantities (UDQ) together with the ACTIONX
|
||||
-- keyword to shut well with highest water cut when number of wells on stream
|
||||
-- exceeds a defined number.
|
||||
|
||||
--------------------------------------------------------
|
||||
|
||||
|
||||
-- *****************************************************
|
||||
RUNSPEC
|
||||
-- *****************************************************
|
||||
|
||||
-- Simulation run title
|
||||
TITLE
|
||||
Generic Reservoir
|
||||
|
||||
NOECHO
|
||||
|
||||
--
|
||||
-- ----------------------------------------------------
|
||||
-- Simulation grid dimension (Imax, Jmax, Kmax)
|
||||
DIMENS
|
||||
3 5 4 /
|
||||
|
||||
--
|
||||
-- ----------------------------------------------------
|
||||
-- Simulation run start
|
||||
START
|
||||
22 'AUG' 2018 /
|
||||
|
||||
--
|
||||
-- ----------------------------------------------------
|
||||
--Activate "Data Check Only" option
|
||||
--NOSIM
|
||||
--
|
||||
--
|
||||
-- ----------------------------------------------------
|
||||
-- Fluid phases present
|
||||
OIL
|
||||
GAS
|
||||
WATER
|
||||
DISGAS
|
||||
|
||||
--
|
||||
-- ----------------------------------------------------
|
||||
-- Measurement unit used
|
||||
METRIC
|
||||
|
||||
--
|
||||
--
|
||||
--Table dimensions
|
||||
TABDIMS
|
||||
-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT
|
||||
1 1 130 24 1 20 /
|
||||
--
|
||||
-- ----------------------------------------------------
|
||||
-- Dimensions for equilibration tables
|
||||
EQLDIMS
|
||||
2 100 20 /
|
||||
--
|
||||
--
|
||||
-- ----------------------------------------------------
|
||||
--Dimension for well data
|
||||
WELLDIMS
|
||||
6 5 5 6 /
|
||||
|
||||
--Dimensions for ACTIONX data
|
||||
ACTDIMS
|
||||
4 20 80 4 /
|
||||
|
||||
--
|
||||
--
|
||||
--
|
||||
-- ----------------------------------------------------
|
||||
-- Input and output files format
|
||||
--FMTIN
|
||||
--FMTOUT
|
||||
UNIFIN
|
||||
UNIFOUT
|
||||
|
||||
|
||||
-- Dimensions for used defined quantity facility
|
||||
-- max functions permitted in a quantity definition
|
||||
-- max arguments permitted in a quantity definition
|
||||
-- max user defined connection quantities
|
||||
-- max user defined field quantities
|
||||
-- max user defined group quantities
|
||||
-- max user defined region quantities
|
||||
-- max user defined segment quantities
|
||||
-- max user defined well quantities
|
||||
-- max user defined aquifer quantities
|
||||
-- max user defined block quantities
|
||||
-- whether new randon number generator seed computed for restart runs
|
||||
UDQDIMS
|
||||
50 25 0 50 50 0 0 50 0 20 /
|
||||
|
||||
-- Dimensions for the user defined arguments facility
|
||||
-- number of keyword arguments in which UDQs replace numerical values
|
||||
-- ratained for back-compatibility
|
||||
-- total number of unique instances in which a UDQ is used in a keyword argument
|
||||
UDADIMS
|
||||
10 1* 10 /
|
||||
|
||||
|
||||
--PARALLEL
|
||||
-- 2 /
|
||||
|
||||
-- *************************************************************************
|
||||
-- In this section simulation grid and static reservoir parameters are given
|
||||
-- *************************************************************************
|
||||
|
||||
GRID
|
||||
|
||||
-- ****************************************************
|
||||
-------------------------------------------------------
|
||||
|
||||
--
|
||||
--Disable echoing of the input file
|
||||
NOECHO
|
||||
|
||||
--
|
||||
--Requests output of an INIT file
|
||||
INIT
|
||||
|
||||
--
|
||||
--Control output of the Grid geometry file
|
||||
GRIDFILE
|
||||
0 1 /
|
||||
|
||||
|
||||
--
|
||||
--Input of pre-processor map origin (X1, Y1, X2, Y2, X3, Y3)
|
||||
--X1 Y1 The X and Y coordinates of one point of the grid Y-axis relative to the map
|
||||
--X2 Y2 The X and Y coordinates of the grid origin relative to the map origin
|
||||
--X3 Y3 The X and Y coordinates of one point of the grid X-axis relative to the map
|
||||
MAPAXES
|
||||
0.0 100.0 0.0 0.0 100.0 0.0 /
|
||||
--
|
||||
--
|
||||
|
||||
NOECHO
|
||||
|
||||
--
|
||||
-- ----------------------------------------------------
|
||||
--Include simulation grid
|
||||
INCLUDE
|
||||
'include_grid_3x5x4.grdecl' /
|
||||
|
||||
|
||||
|
||||
PORO
|
||||
15*0.25
|
||||
15*0.20
|
||||
15*0.23
|
||||
15*0.18
|
||||
/
|
||||
|
||||
PERMX
|
||||
15*500
|
||||
15*100
|
||||
15*1000
|
||||
15*250
|
||||
/
|
||||
|
||||
-- ---------------------------------------------------
|
||||
-- Copy PERMX to PERMY & PERMZ
|
||||
COPY
|
||||
PERMX PERMY /
|
||||
PERMX PERMZ /
|
||||
/
|
||||
--
|
||||
-- ---------------------------------------------------
|
||||
-- Set Kv/Kh
|
||||
MULTIPLY
|
||||
PERMZ 0.1 /
|
||||
/
|
||||
|
||||
|
||||
MULTZ
|
||||
15*1.0
|
||||
15*0.0
|
||||
30*1.0
|
||||
/
|
||||
|
||||
-- ***************************************************
|
||||
-- In this section simulation grid parameters are edited
|
||||
-- ***************************************************
|
||||
|
||||
EDIT
|
||||
|
||||
-- ***************************************************
|
||||
|
||||
|
||||
|
||||
-- ***************************************************
|
||||
-- In this section fluid-rock properties and
|
||||
-- relative permabilities are given
|
||||
-- ***************************************************
|
||||
|
||||
PROPS
|
||||
|
||||
-- ***************************************************
|
||||
|
||||
INCLUDE
|
||||
'include_sgof.txt' /
|
||||
|
||||
|
||||
INCLUDE
|
||||
'include_swof.txt' /
|
||||
|
||||
-- ---------------------------------------------------
|
||||
|
||||
-- Include PVT data
|
||||
INCLUDE
|
||||
'include_example_pvt.txt' /
|
||||
|
||||
|
||||
|
||||
|
||||
-- ***********************************************************
|
||||
-- In this section simulation grid region parameters are given
|
||||
-- ***********************************************************
|
||||
|
||||
REGIONS
|
||||
|
||||
-- ***************************************************
|
||||
|
||||
EQLNUM
|
||||
30*1 30*2 /
|
||||
|
||||
--
|
||||
--
|
||||
-- ***************************************************
|
||||
-- In this section the initialization parameters and
|
||||
-- dynamic parameters are defined
|
||||
-- ***************************************************
|
||||
|
||||
SOLUTION
|
||||
|
||||
-- ***************************************************
|
||||
|
||||
|
||||
------------------------------------------------------
|
||||
--
|
||||
--Simulation model initialisation data
|
||||
--
|
||||
-- DATUM DATUM OWC OWC GOC GOC RSVD RVVD SOLN
|
||||
-- Depth Pres. Depth Pcow Depth Pcog Table Table Method
|
||||
EQUIL
|
||||
2030 382.4 2030 0.0 500 0.0 1 1 0 /
|
||||
2050 382.4 2050 0.0 500 0.0 1 1 0 /
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- ---------------------------------------------------
|
||||
-- Dissolved gas-oil ratio versus depth,
|
||||
|
||||
RSVD
|
||||
1500 180.0
|
||||
4000 180.0 /
|
||||
1500 180.0
|
||||
4000 180.0 /
|
||||
|
||||
|
||||
-- ---------------------------------------------------
|
||||
--Controls on output to the RESTART file
|
||||
--RPTRST
|
||||
-- ALLPROPS=2 BASIC=2 FIP /
|
||||
|
||||
|
||||
RPTRST
|
||||
'BASIC=2' 'PBPD' /
|
||||
|
||||
|
||||
--
|
||||
-- **************************************************************************************
|
||||
-- In this section simulation output data to be written to sumTESTy file are defined
|
||||
-- **************************************************************************************
|
||||
|
||||
SUMMARY
|
||||
|
||||
-- ***************************************************
|
||||
|
||||
|
||||
-- ---------------------------------------------------
|
||||
-- Summary data to be written to summary file
|
||||
--
|
||||
--
|
||||
-- **************************************************************************************
|
||||
-- In this section data required to describe history and prediction is given
|
||||
-- - well completions, well production/injection, well constraints
|
||||
-- - platform/production unit constraints, etc.
|
||||
-- **************************************************************************************
|
||||
|
||||
INCLUDE
|
||||
'include_example_summary.txt' /
|
||||
|
||||
|
||||
FMWIN
|
||||
|
||||
FMWPR
|
||||
|
||||
GMWPR
|
||||
'UPPER' 'LOWER' /
|
||||
|
||||
GMWIN
|
||||
'UPPER' 'LOWER' /
|
||||
|
||||
|
||||
WUPR1
|
||||
'OP*' /
|
||||
|
||||
WUPR3
|
||||
'OP*' /
|
||||
|
||||
FMCTP
|
||||
FMCTW
|
||||
FMCTG
|
||||
|
||||
GMCTP
|
||||
/
|
||||
GMCTW
|
||||
/
|
||||
GMCTG
|
||||
/
|
||||
|
||||
|
||||
SCHEDULE
|
||||
|
||||
GRUPTREE
|
||||
'UPPER' 'TEST' /
|
||||
'LOWER' 'TEST' /
|
||||
/
|
||||
|
||||
|
||||
-- ***************************************************
|
||||
|
||||
WELSPECS
|
||||
'OPU01' 'UPPER' 1 2 2002 'OIL' 0.00 'STD' 'SHUT' 'YES' 0 'SEG' /
|
||||
'OPU02' 'UPPER' 1 4 2002 'OIL' 0.00 'STD' 'SHUT' 'YES' 0 'SEG' /
|
||||
'OPL01' 'LOWER' 1 2 2025 'OIL' 0.00 'STD' 'SHUT' 'YES' 0 'SEG' /
|
||||
'OPL02' 'LOWER' 1 4 2025 'OIL' 0.00 'STD' 'SHUT' 'YES' 0 'SEG' /
|
||||
/
|
||||
|
||||
|
||||
WELSPECS
|
||||
'WIU01' 'UPPER' 3 3 2030 'WATER' 0.00 'STD' 'SHUT' 'YES' 0 'SEG' /
|
||||
'WIL01' 'LOWER' 3 3 2050 'WATER' 0.00 'STD' 'SHUT' 'YES' 0 'SEG' /
|
||||
/
|
||||
|
||||
|
||||
COMPDAT
|
||||
-- --------------------------------------------------------------------------------------------------
|
||||
'OPU01' 1 2 1 1 'OPEN' 0 1* 0.241 1* 2.50 0.0 'Z' 1* /
|
||||
'OPU02' 1 4 1 1 'OPEN' 0 1* 0.241 1* 2.50 0.0 'Z' 1* /
|
||||
'OPL01' 1 2 3 3 'OPEN' 0 1* 0.241 1* 2.50 0.0 'Z' 1* /
|
||||
'OPL02' 1 4 3 3 'OPEN' 0 1* 0.241 1* 2.50 0.0 'Z' 1* /
|
||||
'WIU01' 3 3 2 2 'OPEN' 0 1* 0.241 1* 2.50 0.0 'Z' 1* /
|
||||
'WIL01' 3 3 4 4 'OPEN' 0 1* 0.241 1* 2.50 0.0 'Z' 1* /
|
||||
/
|
||||
|
||||
|
||||
-- Well production rate targets/limits:
|
||||
WCONPROD
|
||||
-- name status ctrl qo qw qg ql qr bhp thp vfp alq
|
||||
'OPU*' 'SHUT' 'GRUP' 1500. 1* 1* 2500. 1* 60.0 / single wells
|
||||
'OPL*' 'SHUT' 'GRUP' 1500. 1* 1* 2500. 1* 60.0 / single wells
|
||||
/
|
||||
|
||||
WCONINJE
|
||||
-- name inj type status ctrl surface_qw res_qw BHPmax
|
||||
'WIU*' 'WATER' 'SHUT' 'GRUP' 10500. 1* 500. /
|
||||
'WIL*' 'WATER' 'SHUT' 'GRUP' 10500. 1* 500. /
|
||||
/
|
||||
|
||||
|
||||
UDQ
|
||||
-- WUPR3 sorts production wells from poorest (highest wct) to best. ACTIONX will shut #1 in this list
|
||||
DEFINE WUPR1 1/(0.01 + WWCT 'OP*') /
|
||||
DEFINE WUPR3 SORTA(WUPR1) /
|
||||
-- units ignored
|
||||
/
|
||||
|
||||
|
||||
|
||||
|
||||
--start files/gconprod0.tmpl
|
||||
GCONPROD
|
||||
'TEST' 'LRAT' 6000 1* 1* 6000 'RATE' 'NO' 9* /
|
||||
'LOWER' 'FLD' 6000 1* 1* 6000 'RATE' 'YES' 1* 'FORM' 7* /
|
||||
'UPPER' 'FLD' 3000 1* 1* 6000 'RATE' 'YES' 1* 'FORM' 7* /
|
||||
/
|
||||
|
||||
GCONINJE
|
||||
'LOWER' 'WATER' 'VREP' 3* 1.2 /
|
||||
'UPPER' 'WATER' 'VREP' 3* 2.0 /
|
||||
/
|
||||
|
||||
-- Well proportions
|
||||
GUIDERAT
|
||||
-- int phase A B C D E F incr. damp
|
||||
0 'OIL' 1 0.5 1 1 0 0 'YES' 0.5 / equal to 1/(0.5+WWCT)
|
||||
|
||||
|
||||
|
||||
--start files/actionxprod.tmpl
|
||||
ACTIONX
|
||||
ACT01 10 /
|
||||
WWPR 'OP*' > 17 OR /
|
||||
GMWPR 'T*' > 14 AND /
|
||||
DAY > 3 /
|
||||
/
|
||||
WELOPEN
|
||||
'?' SHUT 0 0 0 2* /
|
||||
/
|
||||
ENDACTIO
|
||||
|
||||
ACTIONX
|
||||
ACT02 11 /
|
||||
FMWPR > 25 AND /
|
||||
WGPR 'OPL02' > GGPR 'LOWER' AND /
|
||||
MNTH > NOV /
|
||||
/
|
||||
WELOPEN
|
||||
'?' 'SHUT' 0 0 0 2* /
|
||||
/
|
||||
WELOPEN
|
||||
'OPL01' 'OPEN' 5* /
|
||||
/
|
||||
ENDACTIO
|
||||
|
||||
|
||||
DATES
|
||||
1 'SEP' 2018 /
|
||||
/
|
||||
|
||||
ACTIONX
|
||||
ACT03 13 /
|
||||
WWPR 'OPU02' > WWPR 'OPU01' OR /
|
||||
GMWPR 'T*' > 39 AND /
|
||||
YEAR > 2019 /
|
||||
/
|
||||
WELOPEN
|
||||
'?' SHUT 0 0 0 2* /
|
||||
/
|
||||
ENDACTIO
|
||||
|
||||
--start files/actionxprod.tmpl
|
||||
ACTIONX
|
||||
ACT01 10 /
|
||||
FMWPR > 45 AND /
|
||||
WUPR3 'OP*' > 46 OR /
|
||||
MNTH > OCT /
|
||||
/
|
||||
WELOPEN
|
||||
'?' SHUT 0 0 0 2* /
|
||||
/
|
||||
WELOPEN
|
||||
'OPU02' 'OPEN' 5* /
|
||||
/
|
||||
WELOPEN
|
||||
'OPL02' 'OPEN' 5* /
|
||||
/
|
||||
ENDACTIO
|
||||
|
||||
WELOPEN
|
||||
'OPL01' 'OPEN' 5* /
|
||||
/
|
||||
|
||||
DATES
|
||||
1 'OCT' 2018 /
|
||||
/
|
||||
|
||||
|
||||
WELOPEN
|
||||
'WIL01' 'OPEN' 5* /
|
||||
/
|
||||
|
||||
DATES
|
||||
1 'NOV' 2018 /
|
||||
/
|
||||
END
|
||||
|
||||
WELOPEN
|
||||
'OPL02' 'OPEN' 5* /
|
||||
/
|
||||
|
||||
|
||||
|
||||
DATES
|
||||
1 'DEC' 2018 /
|
||||
/
|
||||
|
||||
|
||||
WELOPEN
|
||||
'OPU01' 'OPEN' 5* /
|
||||
/
|
||||
|
||||
DATES
|
||||
1 'MAY' 2019 /
|
||||
/
|
||||
|
||||
|
||||
WELOPEN
|
||||
'OPU02' 'OPEN' 5* /
|
||||
/
|
||||
|
||||
DATES
|
||||
1 'JUN' 2019 /
|
||||
/
|
||||
|
||||
|
||||
WELOPEN
|
||||
'WIU01' 'OPEN' 5* /
|
||||
/
|
||||
|
||||
DATES
|
||||
1 'JAN' 2021 /
|
||||
/
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <ctime>
|
||||
|
||||
#include <opm/output/data/Wells.hpp>
|
||||
#include <opm/output/data/Groups.hpp>
|
||||
#include <opm/output/eclipse/Summary.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
@@ -51,6 +52,8 @@
|
||||
|
||||
using namespace Opm;
|
||||
using rt = data::Rates::opt;
|
||||
using p_cmode = Opm::Group::ProductionCMode;
|
||||
using i_cmode = Opm::Group::InjectionCMode;
|
||||
|
||||
namespace {
|
||||
double sm3_pr_day()
|
||||
@@ -271,6 +274,27 @@ static data::Wells result_wells() {
|
||||
return wellrates;
|
||||
}
|
||||
|
||||
static data::Group result_groups() {
|
||||
|
||||
data::Group groups;
|
||||
data::currentGroupConstraints cgc_group;
|
||||
|
||||
cgc_group.set(p_cmode::NONE, i_cmode::VREP, i_cmode::RATE);
|
||||
groups.emplace("G_1", cgc_group);
|
||||
|
||||
cgc_group.set(p_cmode::ORAT, i_cmode::RESV, i_cmode::FLD);
|
||||
groups.emplace("G_2", cgc_group);
|
||||
|
||||
cgc_group.set(p_cmode::GRAT, i_cmode::REIN, i_cmode::VREP);
|
||||
groups.emplace("G_3", cgc_group);
|
||||
|
||||
cgc_group.set(p_cmode::NONE, i_cmode::NONE, i_cmode::NONE);
|
||||
groups.emplace("FIELD", cgc_group);
|
||||
|
||||
return groups;
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr< EclIO::ESmry > readsum( const std::string& base ) {
|
||||
return std::make_unique<EclIO::ESmry>(base);
|
||||
}
|
||||
@@ -349,6 +373,7 @@ struct setup {
|
||||
Schedule schedule;
|
||||
SummaryConfig config;
|
||||
data::Wells wells;
|
||||
data::Group groups;
|
||||
std::string name;
|
||||
WorkArea ta;
|
||||
|
||||
@@ -361,6 +386,7 @@ struct setup {
|
||||
schedule( deck, es),
|
||||
config( deck, schedule, es.getTableManager()),
|
||||
wells( result_wells() ),
|
||||
groups( result_groups() ),
|
||||
name( toupper(std::move(fname)) ),
|
||||
ta( "summary_test" )
|
||||
{}
|
||||
@@ -383,13 +409,13 @@ BOOST_AUTO_TEST_CASE(well_keywords) {
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule , cfg.name );
|
||||
writer.eval(st, 0, 0*day, cfg.es, cfg.schedule, cfg.wells, {});
|
||||
writer.eval(st, 0, 0*day, cfg.es, cfg.schedule, cfg.wells, cfg.groups, {});
|
||||
writer.add_timestep( st, 0);
|
||||
|
||||
writer.eval(st, 1, 1*day, cfg.es, cfg.schedule, cfg.wells, {});
|
||||
writer.eval(st, 1, 1*day, cfg.es, cfg.schedule, cfg.wells, cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
|
||||
writer.eval(st, 2, 2*day, cfg.es, cfg.schedule, cfg.wells, {});
|
||||
writer.eval(st, 2, 2*day, cfg.es, cfg.schedule, cfg.wells, cfg.groups, {});
|
||||
writer.add_timestep( st, 2);
|
||||
writer.write();
|
||||
|
||||
@@ -598,11 +624,11 @@ BOOST_AUTO_TEST_CASE(udq_keywords) {
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule , cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 0);
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 2);
|
||||
writer.write();
|
||||
|
||||
@@ -623,13 +649,13 @@ BOOST_AUTO_TEST_CASE(group_keywords) {
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 0);
|
||||
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 2);
|
||||
|
||||
writer.write();
|
||||
@@ -767,11 +793,11 @@ BOOST_AUTO_TEST_CASE(group_group) {
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 0);
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 2);
|
||||
writer.write();
|
||||
|
||||
@@ -823,11 +849,11 @@ BOOST_AUTO_TEST_CASE(completion_kewords) {
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 0);
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 2);
|
||||
writer.write();
|
||||
|
||||
@@ -885,11 +911,11 @@ BOOST_AUTO_TEST_CASE(field_keywords) {
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 0);
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 2);
|
||||
writer.write();
|
||||
|
||||
@@ -1015,11 +1041,11 @@ BOOST_AUTO_TEST_CASE(report_steps_time) {
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 1, 2 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 1, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 1, 5 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 1, 5 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 10 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 2, 10 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 2);
|
||||
writer.write();
|
||||
|
||||
@@ -1042,11 +1068,11 @@ BOOST_AUTO_TEST_CASE(skip_unknown_var) {
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 1, 2 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 1, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 1, 5 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 1, 5 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 10 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 2, 10 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 2);
|
||||
writer.write();
|
||||
|
||||
@@ -1153,11 +1179,11 @@ BOOST_AUTO_TEST_CASE(region_vars) {
|
||||
{
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 1, 2 * day, cfg.es, cfg.schedule, cfg.wells, {}, region_values);
|
||||
writer.eval( st, 1, 2 * day, cfg.es, cfg.schedule, cfg.wells, cfg.groups, {}, region_values);
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 1, 5 * day, cfg.es, cfg.schedule, cfg.wells, {}, region_values);
|
||||
writer.eval( st, 1, 5 * day, cfg.es, cfg.schedule, cfg.wells, cfg.groups, {}, region_values);
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 10 * day, cfg.es, cfg.schedule, cfg.wells, {}, region_values);
|
||||
writer.eval( st, 2, 10 * day, cfg.es, cfg.schedule, cfg.wells, cfg.groups, {}, region_values);
|
||||
writer.add_timestep( st, 2);
|
||||
writer.write();
|
||||
}
|
||||
@@ -1204,11 +1230,11 @@ BOOST_AUTO_TEST_CASE(region_production) {
|
||||
{
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 0);
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 2);
|
||||
writer.write();
|
||||
}
|
||||
@@ -1236,11 +1262,11 @@ BOOST_AUTO_TEST_CASE(region_injection) {
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 0);
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 2);
|
||||
writer.write();
|
||||
|
||||
@@ -1292,15 +1318,15 @@ BOOST_AUTO_TEST_CASE(BLOCK_VARIABLES) {
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , {},{}, block_values);
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {},{}, block_values);
|
||||
writer.add_timestep( st, 0);
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , {},{}, block_values);
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {},{}, block_values);
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , {},{}, block_values);
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {},{}, block_values);
|
||||
writer.add_timestep( st, 2);
|
||||
writer.eval( st, 3, 2 * day, cfg.es, cfg.schedule, cfg.wells , {},{}, block_values);
|
||||
writer.eval( st, 3, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {},{}, block_values);
|
||||
writer.add_timestep( st, 3);
|
||||
writer.eval( st, 4, 2 * day, cfg.es, cfg.schedule, cfg.wells , {},{}, block_values);
|
||||
writer.eval( st, 4, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {},{}, block_values);
|
||||
writer.add_timestep( st, 4);
|
||||
writer.write();
|
||||
|
||||
@@ -1389,11 +1415,11 @@ BOOST_AUTO_TEST_CASE(MISC) {
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule , cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 0);
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , {});
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, {});
|
||||
writer.add_timestep( st, 2);
|
||||
writer.write();
|
||||
|
||||
@@ -1409,19 +1435,19 @@ BOOST_AUTO_TEST_CASE(EXTRA) {
|
||||
{
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule , cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , { {"TCPU" , 0 }});
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, { {"TCPU" , 0 }});
|
||||
writer.add_timestep( st, 0);
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , { {"TCPU" , 1 }});
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, { {"TCPU" , 1 }});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , { {"TCPU" , 2}});
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, { {"TCPU" , 2}});
|
||||
writer.add_timestep( st, 2);
|
||||
|
||||
/* Add a not-recognized key; that is OK */
|
||||
BOOST_CHECK_NO_THROW( writer.eval( st, 3, 3 * day, cfg.es, cfg.schedule, cfg.wells , { {"MISSING" , 2 }}));
|
||||
BOOST_CHECK_NO_THROW( writer.eval( st, 3, 3 * day, cfg.es, cfg.schedule, cfg.wells , cfg.groups, { {"MISSING" , 2 }}));
|
||||
BOOST_CHECK_NO_THROW( writer.add_timestep( st, 3));
|
||||
|
||||
/* Override a NOT MISC variable - ignored. */
|
||||
writer.eval( st, 4, 4 * day, cfg.es, cfg.schedule, cfg.wells, {});
|
||||
writer.eval( st, 4, 4 * day, cfg.es, cfg.schedule, cfg.wells, cfg.groups, {});
|
||||
writer.add_timestep( st, 4);
|
||||
writer.write();
|
||||
}
|
||||
@@ -1513,11 +1539,11 @@ BOOST_AUTO_TEST_CASE(efficiency_factor) {
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells, {});
|
||||
writer.eval( st, 0, 0 * day, cfg.es, cfg.schedule, cfg.wells, cfg.groups, {});
|
||||
writer.add_timestep( st, 0);
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells, {});
|
||||
writer.eval( st, 1, 1 * day, cfg.es, cfg.schedule, cfg.wells, cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells, {});
|
||||
writer.eval( st, 2, 2 * day, cfg.es, cfg.schedule, cfg.wells, cfg.groups, {});
|
||||
writer.add_timestep( st, 2);
|
||||
writer.write();
|
||||
auto res = readsum( cfg.name );
|
||||
@@ -1650,11 +1676,11 @@ namespace {
|
||||
};
|
||||
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
smry.eval(st, 0, 0*day, config.es, config.schedule, config.wells, {});
|
||||
smry.eval(st, 0, 0*day, config.es, config.schedule, config.wells, config.groups, {});
|
||||
smry.add_timestep(st, 0);
|
||||
smry.eval(st, 1, 1*day, config.es, config.schedule, config.wells, {});
|
||||
smry.eval(st, 1, 1*day, config.es, config.schedule, config.wells, config.groups, {});
|
||||
smry.add_timestep(st, 1);
|
||||
smry.eval(st, 2, 2*day, config.es, config.schedule, config.wells, {});
|
||||
smry.eval(st, 2, 2*day, config.es, config.schedule, config.wells, config.groups, {});
|
||||
smry.add_timestep(st, 2);
|
||||
|
||||
return st;
|
||||
@@ -2646,11 +2672,11 @@ BOOST_AUTO_TEST_CASE(Write_Read)
|
||||
};
|
||||
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
writer.eval(st, 0, 0*day, config.es, config.schedule, config.wells, {});
|
||||
writer.eval(st, 0, 0*day, config.es, config.schedule, config.wells, config.groups, {});
|
||||
writer.add_timestep(st, 0);
|
||||
writer.eval(st, 1, 1*day, config.es, config.schedule, config.wells, {});
|
||||
writer.eval(st, 1, 1*day, config.es, config.schedule, config.wells, config.groups, {});
|
||||
writer.add_timestep(st, 1);
|
||||
writer.eval(st, 2, 2*day, config.es, config.schedule, config.wells, {});
|
||||
writer.eval(st, 2, 2*day, config.es, config.schedule, config.wells, config.groups, {});
|
||||
writer.add_timestep(st, 2);
|
||||
writer.write();
|
||||
|
||||
|
||||
276
tests/test_Summary_Group.cpp
Normal file
276
tests/test_Summary_Group.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
Copyright 2016 Statoil ASA.
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define BOOST_TEST_MODULE Wells
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
#include <cctype>
|
||||
#include <ctime>
|
||||
|
||||
#include <opm/output/data/Wells.hpp>
|
||||
#include <opm/output/data/Groups.hpp>
|
||||
#include <opm/output/eclipse/Summary.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Units/Units.hpp>
|
||||
|
||||
#include <opm/io/eclipse/ESmry.hpp>
|
||||
|
||||
#include <tests/WorkArea.cpp>
|
||||
|
||||
using namespace Opm;
|
||||
using rt = data::Rates::opt;
|
||||
|
||||
namespace {
|
||||
double sm3_pr_day()
|
||||
{
|
||||
return unit::cubic(unit::meter) / unit::day;
|
||||
}
|
||||
|
||||
std::string toupper(std::string input)
|
||||
{
|
||||
for (auto& c : input) {
|
||||
const auto uc = std::toupper(static_cast<unsigned char>(c));
|
||||
c = static_cast<std::string::value_type>(uc);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
bool ecl_sum_has_group_var( const EclIO::ESmry* smry,
|
||||
const std::string& groupname,
|
||||
const std::string& variable )
|
||||
{
|
||||
return smry->hasKey(variable + ':' + groupname);
|
||||
}
|
||||
|
||||
double ecl_sum_get_group_var( const EclIO::ESmry* smry,
|
||||
const int timeIdx,
|
||||
const std::string& groupname,
|
||||
const std::string& variable )
|
||||
{
|
||||
return smry->get(variable + ':' + groupname)[timeIdx];
|
||||
}
|
||||
|
||||
} // Anonymous
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
/* conversion factor for whenever 'day' is the unit of measure, whereas we
|
||||
* expect input in SI units (seconds)
|
||||
*/
|
||||
|
||||
std::unique_ptr< EclIO::ESmry > readsum( const std::string& base ) {
|
||||
return std::make_unique<EclIO::ESmry>(base);
|
||||
}
|
||||
|
||||
using p_cmode = Opm::Group::ProductionCMode;
|
||||
using i_cmode = Opm::Group::InjectionCMode;
|
||||
|
||||
static const int day = 24 * 60 * 60;
|
||||
|
||||
static data::Wells result_wells() {
|
||||
/* populate with the following pattern:
|
||||
*
|
||||
* Wells are named W_1, W_2 etc, i.e. wells are 1 indexed.
|
||||
*
|
||||
* rates on a well are populated with 10 * wellidx . type (where type is
|
||||
* 0-1-2 from owg)
|
||||
*
|
||||
* bhp is wellidx.1
|
||||
* bhp is wellidx.2
|
||||
*
|
||||
* completions are 100*wellidx . type
|
||||
*/
|
||||
|
||||
// conversion factor Pascal (simulator output) <-> barsa
|
||||
const double ps = 100000;
|
||||
|
||||
data::Rates rates1;
|
||||
rates1.set( rt::wat, -10.0 / day );
|
||||
rates1.set( rt::oil, -10.1 / day );
|
||||
rates1.set( rt::gas, -10.2 / day );
|
||||
rates1.set( rt::solvent, -10.3 / day );
|
||||
rates1.set( rt::dissolved_gas, -10.4 / day );
|
||||
rates1.set( rt::vaporized_oil, -10.5 / day );
|
||||
rates1.set( rt::reservoir_water, -10.6 / day );
|
||||
rates1.set( rt::reservoir_oil, -10.7 / day );
|
||||
rates1.set( rt::reservoir_gas, -10.8 / day );
|
||||
rates1.set( rt::productivity_index_water, -10.9 / day );
|
||||
rates1.set( rt::productivity_index_oil, -10.11 / day );
|
||||
rates1.set( rt::productivity_index_gas, -10.12 / day );
|
||||
rates1.set( rt::well_potential_water, -10.13 / day );
|
||||
rates1.set( rt::well_potential_oil, -10.14 / day );
|
||||
rates1.set( rt::well_potential_gas, -10.15 / day );
|
||||
|
||||
/* completion rates */
|
||||
data::Rates crates1;
|
||||
crates1.set( rt::wat, -100.0 / day );
|
||||
crates1.set( rt::oil, -100.1 / day );
|
||||
crates1.set( rt::gas, -100.2 / day );
|
||||
crates1.set( rt::solvent, -100.3 / day );
|
||||
crates1.set( rt::dissolved_gas, -100.4 / day );
|
||||
crates1.set( rt::vaporized_oil, -100.5 / day );
|
||||
crates1.set( rt::reservoir_water, -100.6 / day );
|
||||
crates1.set( rt::reservoir_oil, -100.7 / day );
|
||||
crates1.set( rt::reservoir_gas, -100.8 / day );
|
||||
|
||||
// Segment vectors
|
||||
auto segment = ::Opm::data::Segment{};
|
||||
segment.rates.set(rt::wat, 123.45*sm3_pr_day());
|
||||
segment.rates.set(rt::oil, 543.21*sm3_pr_day());
|
||||
segment.rates.set(rt::gas, 1729.496*sm3_pr_day());
|
||||
segment.pressure = 314.159*unit::barsa;
|
||||
segment.segNumber = 1;
|
||||
|
||||
/*
|
||||
The global index assigned to the completion must be manually
|
||||
syncronized with the global index in the COMPDAT keyword in the
|
||||
input deck.
|
||||
*/
|
||||
data::Connection well1_comp1 { 0 , crates1, 1.9 , 123.4, 314.15, 0.35, 0.25, 2.718e2};
|
||||
|
||||
/*
|
||||
The completions
|
||||
*/
|
||||
data::Well well1 {
|
||||
rates1, 0.1 * ps, 0.2 * ps, 0.3 * ps, 1,
|
||||
{ {well1_comp1} },
|
||||
{ { segment.segNumber, segment } },
|
||||
data::CurrentControl{}
|
||||
};
|
||||
well1.current_control.isProducer = false;
|
||||
well1.current_control.inj =::Opm::Well::InjectorCMode::BHP;
|
||||
|
||||
data::Wells wellrates;
|
||||
|
||||
wellrates["OPU01"] = well1;
|
||||
|
||||
return wellrates;
|
||||
|
||||
}
|
||||
|
||||
static data::Group result_groups() {
|
||||
data::Group groups;
|
||||
data::currentGroupConstraints cgc_group;
|
||||
|
||||
cgc_group.set(p_cmode::NONE, i_cmode::VREP, i_cmode::RATE);
|
||||
groups.emplace("TEST", cgc_group);
|
||||
|
||||
cgc_group.set(p_cmode::ORAT, i_cmode::RESV, i_cmode::REIN);
|
||||
groups.emplace("LOWER", cgc_group);
|
||||
|
||||
cgc_group.set(p_cmode::GRAT, i_cmode::REIN, i_cmode::VREP);
|
||||
groups.emplace("UPPER", cgc_group);
|
||||
|
||||
cgc_group.set(p_cmode::NONE, i_cmode::NONE, i_cmode::NONE);
|
||||
groups.emplace("FIELD", cgc_group);
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
|
||||
struct setup {
|
||||
Deck deck;
|
||||
EclipseState es;
|
||||
const EclipseGrid& grid;
|
||||
Schedule schedule;
|
||||
SummaryConfig config;
|
||||
data::Wells wells;
|
||||
data::Group groups;
|
||||
std::string name;
|
||||
WorkArea ta;
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
|
||||
setup(std::string fname, const std::string& path = "UDQ_ACTIONX_TEST1_U.DATA") :
|
||||
deck( Parser().parseFile( path) ),
|
||||
es( deck ),
|
||||
grid( es.getInputGrid() ),
|
||||
schedule( deck, es),
|
||||
config( deck, schedule, es.getTableManager()),
|
||||
wells( result_wells() ),
|
||||
groups( result_groups() ),
|
||||
name( toupper(std::move(fname)) ),
|
||||
ta( "test_summary_group_constraints" )
|
||||
{}
|
||||
};
|
||||
} // Anonymous namespace
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(Summary)
|
||||
/*
|
||||
* Tests works by reading the Deck, write the summary output, then immediately
|
||||
* read it again (with ERT), and compare the read values with the input.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(group_keywords) {
|
||||
setup cfg( "test_summary_group_constraints");
|
||||
|
||||
// Force to run in a directory, to make sure the basename with
|
||||
// leading path works.
|
||||
cfg.ta.makeSubDir( "PATH" );
|
||||
cfg.name = "PATH/CASE";
|
||||
|
||||
SummaryState st(std::chrono::system_clock::now());
|
||||
|
||||
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule , cfg.name );
|
||||
writer.eval(st, 0, 0*day, cfg.es, cfg.schedule, cfg.wells, cfg.groups, {});
|
||||
writer.add_timestep( st, 0);
|
||||
|
||||
writer.eval(st, 1, 1*day, cfg.es, cfg.schedule, cfg.wells, cfg.groups, {});
|
||||
writer.add_timestep( st, 1);
|
||||
|
||||
writer.write();
|
||||
|
||||
auto res = readsum( cfg.name );
|
||||
const auto* resp = res.get();
|
||||
|
||||
//BOOST_CHECK( ecl_sum_has_report_step( resp, 1 ) );
|
||||
BOOST_CHECK( ecl_sum_has_group_var( resp, "TEST", "GMCTP" ) );
|
||||
|
||||
|
||||
// Integer flag indicating current active group control
|
||||
BOOST_CHECK_EQUAL( static_cast<int>(ecl_sum_get_group_var( resp, 1, "TEST", "GMCTP" )), 0 );
|
||||
BOOST_CHECK_EQUAL( static_cast<int>(ecl_sum_get_group_var( resp, 1, "LOWER", "GMCTW" )), 3 );
|
||||
BOOST_CHECK_EQUAL( static_cast<int>(ecl_sum_get_group_var( resp, 1, "LOWER", "GMCTP" )), 1 );
|
||||
|
||||
BOOST_CHECK_EQUAL( static_cast<int>(ecl_sum_get_group_var( resp, 1, "UPPER", "GMCTP" )), 3 );
|
||||
BOOST_CHECK_EQUAL( static_cast<int>(ecl_sum_get_group_var( resp, 1, "UPPER", "GMCTW" )), 4 );
|
||||
BOOST_CHECK_EQUAL( static_cast<int>(ecl_sum_get_group_var( resp, 1, "UPPER", "GMCTG" )), 3 );
|
||||
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
Reference in New Issue
Block a user