Merge pull request #928 from jalvestad/udqrst-pull909

Output of UDQ properties to Eclipse compatible restart file
This commit is contained in:
Joakim Hove
2019-08-13 19:33:50 +02:00
committed by GitHub
40 changed files with 4008 additions and 701 deletions

View File

@@ -136,13 +136,15 @@ if(ENABLE_ECL_INPUT)
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParser.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQSet.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQAssign.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQContext.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQFunction.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQFunctionTable.cpp
src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.cpp
src/opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.cpp
src/opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.cpp
src/opm/parser/eclipse/Parser/ErrorGuard.cpp
@@ -178,10 +180,12 @@ if(ENABLE_ECL_OUTPUT)
src/opm/output/eclipse/AggregateConnectionData.cpp
src/opm/output/eclipse/AggregateGroupData.cpp
src/opm/output/eclipse/AggregateMSWData.cpp
src/opm/output/eclipse/AggregateUDQData.cpp
src/opm/output/eclipse/AggregateWellData.cpp
src/opm/output/eclipse/CreateDoubHead.cpp
src/opm/output/eclipse/CreateInteHead.cpp
src/opm/output/eclipse/CreateLogiHead.cpp
src/opm/output/eclipse/CreateUdqDims.cpp
src/opm/output/eclipse/DoubHEAD.cpp
src/opm/output/eclipse/EclipseGridInspector.cpp
src/opm/output/eclipse/EclipseIO.cpp
@@ -284,6 +288,7 @@ if(ENABLE_ECL_OUTPUT)
tests/test_AggregateGroupData.cpp
tests/test_AggregateMSWData.cpp
tests/test_AggregateConnectionData.cpp
#tests/test_AggregateUDQData.cpp
tests/test_ArrayDimChecker.cpp
tests/test_EclipseIO.cpp
tests/test_DoubHEAD.cpp
@@ -324,6 +329,7 @@ if(ENABLE_ECL_OUTPUT)
tests/SPE1CASE1A.SMSPEC
tests/SPE9_CP_PACKED.DATA
tests/SOFR_TEST.DATA
tests/UDQ_TEST_WCONPROD_IUAD-2.DATA
)
endif()
@@ -564,10 +570,11 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQAssign.hpp
opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp
opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQContext.hpp
opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp
opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp
opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp
opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.hpp
opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp
opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp
opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQSet.hpp
opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQFunction.hpp
opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQFunctionTable.hpp
@@ -608,6 +615,7 @@ if(ENABLE_ECL_OUTPUT)
opm/output/eclipse/AggregateGroupData.hpp
opm/output/eclipse/AggregateConnectionData.hpp
opm/output/eclipse/AggregateMSWData.hpp
opm/output/eclipse/AggregateUDQData.hpp
opm/output/eclipse/AggregateWellData.hpp
opm/output/eclipse/DoubHEAD.hpp
opm/output/eclipse/EclipseGridInspector.hpp

View File

@@ -0,0 +1,137 @@
/*
Copyright (c) 2018 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_AGGREGATE_UDQ_DATA_HPP
#define OPM_AGGREGATE_UDQ_DATA_HPP
#include <opm/output/eclipse/WindowedArray.hpp>
#include <opm/io/eclipse/PaddedOutputString.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQAssign.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQFunctionTable.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <cstddef>
#include <string>
#include <vector>
#include <map>
namespace Opm {
class Schedule;
class UDQInput;
class UDQActive;
} // Opm
namespace Opm { namespace RestartIO { namespace Helpers {
class igphData {
public:
const std::vector<int> ig_phase(const Opm::Schedule& sched, const std::size_t simStep, const std::vector<int>& inteHead);
};
class AggregateUDQData
{
public:
explicit AggregateUDQData(const std::vector<int>& udqDims);
void captureDeclaredUDQData(const Opm::Schedule& sched,
const std::size_t simStep,
const std::vector<int>& ih);
const std::vector<int>& getIUDQ() const
{
return this->iUDQ_.data();
}
const std::vector<int>& getIUAD() const
{
return this->iUAD_.data();
}
const std::vector<EclIO::PaddedOutputString<8>>& getZUDN() const
{
return this->zUDN_.data();
}
const std::vector<EclIO::PaddedOutputString<8>>& getZUDL() const
{
return this->zUDL_.data();
}
const std::vector<int>& getIGPH() const
{
return this->iGPH_.data();
}
const std::vector<int>& getIUAP() const
{
return this->iUAP_.data();
}
#if 0
const std::vector<double>& getDUDW() const
{
return this->dUDW_.data();
}
const std::vector<double>& getDUDF() const
{
return this->dUDF_.data();
}
#endif
private:
/// Aggregate 'IUDQ' array (Integer) for all UDQ data (3 integers pr UDQ)
WindowedArray<int> iUDQ_;
/// Aggregate 'IUAD' array (Integer) for all UDQ data (5 integers pr UDQ that is used for various well and group controls)
WindowedArray<int> iUAD_;
/// Aggregate 'ZUDN' array (Character) for all UDQ data. (2 * 8 chars pr UDQ -> UNIT keyword)
WindowedArray<EclIO::PaddedOutputString<8>> zUDN_;
/// Aggregate 'ZUDL' array (Character) for all UDQ data. (16 * 8 chars pr UDQ DEFINE "Data for operation - Msth Expression)
WindowedArray<EclIO::PaddedOutputString<8>> zUDL_;
/// Aggregate 'IGPH' array (Integer) for all UDQ data (3 - zeroes - as of current understanding)
WindowedArray<int> iGPH_;
/// Aggregate 'IUAP' array (ICharArrayNullTermnteger) for all UDQ data (1 integer pr UDQ constraint used)
WindowedArray<int> iUAP_;
#if 0
/// Aggregate 'DUDW' array (Double Precision) for all UDQ data. (Dimension = max no wells * noOfUDQ's)
WindowedArray<double> dUDW_;
/// Aggregate 'DUDF' array (Double Precision) for all UDQ data. (Dimension = Number of FU - UDQ's, with value equal to the actual constraint)
WindowedArray<double> dUDF_;
#endif
};
}}} // Opm::RestartIO::Helpers
#endif //OPM_AGGREGATE_WELL_DATA_HPP

View File

@@ -27,6 +27,7 @@
namespace Opm {
class Tuning;
class Schedule;
class UDQParams;
}
namespace Opm { namespace RestartIO {
@@ -38,7 +39,7 @@ namespace Opm { namespace RestartIO {
std::chrono::time_point<std::chrono::system_clock> start;
std::chrono::duration<double, std::chrono::seconds::period> elapsed;
};
DoubHEAD();
~DoubHEAD() = default;
@@ -58,6 +59,8 @@ namespace Opm { namespace RestartIO {
DoubHEAD& drsdt(const Schedule& sched,
const std::size_t lookup_step,
const double cnvT);
DoubHEAD& udq_param(const UDQParams& udqPar);
const std::vector<double>& data() const
{

View File

@@ -89,6 +89,10 @@ namespace Opm { namespace RestartIO {
struct Group {
int ngroups;
};
struct UdqParam {
int udqParam_1;
};
InteHEAD();
~InteHEAD() = default;
@@ -117,6 +121,7 @@ namespace Opm { namespace RestartIO {
InteHEAD& wellSegDimensions(const WellSegDims& wsdim);
InteHEAD& regionDimensions(const RegDims& rdim);
InteHEAD& ngroups(const Group& gr);
InteHEAD& udqParam_1(const UdqParam& udqpar);
const std::vector<int>& data() const
{

View File

@@ -30,6 +30,9 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
TsInit = 1, // Maximum Length of Next Timestep
TsMaxz = 2, // Maximum Length of Timestep After Next
TsMinz = 3, // Minumum Length of All Timesteps
UdqPar_2 = 212, // UDQPARAM item number 2 (Permitted range (+/-) of user-defined quantities)
UdqPar_3 = 213, // UDQPARAM item number 3 (Value given to undefined elements when outputting data)
UdqPar_4 = 214, // UDQPARAM item number 4 (fractional equality tolerance used in ==, <= etc. functions)
};
}}}} // Opm::RestartIO::Helpers::VectorItems

View File

@@ -84,6 +84,8 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
NISEGZ = 178, // Number of entries per segment in ISEG array
NRSEGZ = 179, // Number of entries per segment in RSEG array
NILBRZ = 180, // Number of entries per segment in ILBR array
UDQPAR_1 = 267, // Integer seed value for the RAND /
};
}}}} // Opm::RestartIO::Helpers::VectorItems

View File

@@ -36,6 +36,7 @@ namespace Opm {
class Schedule;
class Well;
class UnitSystem;
class UDQActive;
} // Opm
@@ -63,6 +64,11 @@ namespace Opm { namespace RestartIO { namespace Helpers {
std::vector<bool>
createLogiHead(const EclipseState& es);
std::vector<int>
createUdqDims(const Schedule& sched,
const std::size_t lookup_step,
const std::vector<int>& inteHead);
}}} // Opm::RestartIO::Helpers

View File

@@ -101,7 +101,8 @@ namespace Opm
class UnitSystem;
class ErrorGuard;
class WListManager;
class UDQInput;
class UDQConfig;
class UDQActive;
class Schedule {
public:
@@ -177,9 +178,10 @@ namespace Opm
std::vector<Well2> getChildWells2(const std::string& group_name, size_t timeStep, GroupWellQueryMode query_mode) const;
const OilVaporizationProperties& getOilVaporizationProperties(size_t timestep) const;
const UDQActive& udqActive(size_t timeStep) const;
const WellTestConfig& wtestConfig(size_t timestep) const;
const WListManager& getWListManager(size_t timeStep) const;
const UDQInput& getUDQConfig(size_t timeStep) const;
const UDQConfig& getUDQConfig(size_t timeStep) const;
const Action::Actions& actions() const;
void evalAction(const SummaryState& summary_state, size_t timeStep);
@@ -226,7 +228,8 @@ namespace Opm
std::map<int, DynamicState<std::shared_ptr<VFPInjTable>>> vfpinj_tables;
DynamicState<std::shared_ptr<WellTestConfig>> wtest_config;
DynamicState<std::shared_ptr<WListManager>> wlist_manager;
DynamicState<std::shared_ptr<UDQInput>> udq_config;
DynamicState<std::shared_ptr<UDQConfig>> udq_config;
DynamicState<std::shared_ptr<UDQActive>> udq_active;
DynamicState<WellProducer::ControlModeEnum> global_whistctl_mode;
RFTConfig rft_config;
@@ -236,6 +239,8 @@ namespace Opm
GTNode groupTree(const std::string& root_node, std::size_t report_step, const GTNode * parent) const;
void updateGroup(std::shared_ptr<Group2> group, size_t reportStep);
bool checkGroups(const ParseContext& parseContext, ErrorGuard& errors);
void updateUDQActive( std::size_t timeStep, std::shared_ptr<UDQActive> udq );
bool updateWellStatus( const std::string& well, size_t reportStep , WellCommon::StatusEnum status);
void addWellToGroup( const std::string& group_name, const std::string& well_name , size_t timeStep);
void iterateScheduleSection(const ParseContext& parseContext , ErrorGuard& errors, const SCHEDULESection& , const EclipseGrid& grid,

View File

@@ -0,0 +1,113 @@
/*
Copyright 2019 Equinor 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 UDQ_USAGE_HPP
#define UDQ_USAGE_HPP
#include <cstdlib>
#include <string>
#include <vector>
#include <unordered_map>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
namespace Opm {
class UDAValue;
class UDQConfig;
class UDQActive {
public:
class Record{
public:
Record(const std::string& udq_arg, std::size_t input_index_arg, std::size_t use_index_arg, const std::string& wgname_arg, UDAControl control_arg) :
udq(udq_arg),
input_index(input_index_arg),
use_index(use_index_arg),
wgname(wgname_arg),
control(control_arg),
uad_code(UDQ::uadCode(control_arg)),
use_count(1)
{}
bool operator==(const Record& other) const {
if ((this->udq == other.udq) &&
(this->input_index == other.input_index) &&
(this->use_index == other.use_index) &&
(this->wgname == other.wgname) &&
(this->control == other.control) &&
(this->uad_code == other.uad_code) &&
(this->use_count == other.use_count))
return true;
return false;
}
bool operator!=(const Record& other) const {
return !(*this == other);
}
std::string udq;
std::size_t input_index;
std::size_t use_index = 0;
std::string wgname;
UDAControl control;
int uad_code;
std::size_t use_count;
};
class InputRecord {
public:
InputRecord(std::size_t input_index_arg, const std::string& udq_arg, const std::string& wgname_arg, UDAControl control_arg) :
input_index(input_index_arg),
udq(udq_arg),
wgname(wgname_arg),
control(control_arg)
{}
std::size_t input_index;
std::string udq;
std::string wgname;
UDAControl control;
int uad_code;
};
int update(const UDQConfig& udq_config, const UDAValue& uda, const std::string& wgname, UDAControl control);
std::size_t IUAD_size() const;
std::size_t IUAP_size() const;
explicit operator bool() const;
Record operator[](std::size_t index) const;
const std::vector<Record>& get_iuad() const;
std::vector<InputRecord> get_iuap() const;
private:
std::string udq_hash(const std::string& udq, UDAControl control);
std::string wg_hash(const std::string& wgname, UDAControl control);
int add(const UDQConfig& udq_config, const std::string& udq, const std::string& wgname, UDAControl control);
int update_input(const UDQConfig& udq_config, const UDAValue& uda, const std::string& wgname, UDAControl control);
int drop(const std::string& wgname, UDAControl control);
std::vector<InputRecord> input_data;
std::vector<Record> mutable output_data;
std::unordered_map<std::string, std::size_t> udq_keys;
std::unordered_map<std::string, std::size_t> wg_keys;
};
}
#endif

View File

@@ -0,0 +1,97 @@
/*
Copyright 2018 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 UDQINPUT_HPP_
#define UDQINPUT_HPP_
#include <string>
#include <unordered_map>
#include <map>
#include <unordered_set>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQAssign.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQFunctionTable.hpp>
#include <opm/parser/eclipse/EclipseState/Util/OrderedMap.hpp>
namespace Opm {
class DeckRecord;
class Deck;
class UDQConfig {
public:
explicit UDQConfig(const Deck& deck);
explicit UDQConfig(const UDQParams& params);
const std::string& unit(const std::string& key) const;
bool has_unit(const std::string& keyword) const;
bool has_keyword(const std::string& keyword) const;
void add_record(const DeckRecord& record);
void add_unit(const std::string& keyword, const std::string& unit);
void add_assign(const std::string& quantity, const std::vector<std::string>& selector, double value);
void add_define(const std::string& quantity, const std::vector<std::string>& expression);
std::vector<UDQDefine> definitions() const;
std::vector<UDQDefine> definitions(UDQVarType var_type) const;
std::vector<UDQInput> input() const;
// The size() method will return the number of active DEFINE and ASSIGN
// statements; this will correspond to the length of the vector returned
// from input().
size_t size() const;
const UDQInput operator[](const std::string& keyword) const;
std::vector<UDQAssign> assignments() const;
std::vector<UDQAssign> assignments(UDQVarType var_type) const;
const UDQParams& params() const;
const UDQFunctionTable& function_table() const;
private:
void add_node(const std::string& quantity, UDQAction action);
UDQParams udq_params;
UDQFunctionTable udqft;
/*
The choices of datastructures are strongly motivated by the
constraints imposed by the Eclipse formatted restart files; for
writing restart files it is essential to keep meticolous control over
the ordering of the keywords. In this class the ordering is mainly
maintained by the input_index map which keeps track of the insert
order of each keyword, and whether the keyword is currently DEFINE'ed
or ASSIGN'ed.
*/
std::unordered_map<std::string, UDQDefine> m_definitions;
std::unordered_map<std::string, UDQAssign> m_assignments;
std::unordered_map<std::string, std::string> units;
OrderedMap<std::string, UDQIndex> input_index;
std::map<UDQVarType, std::size_t> type_count;
};
}
#endif

View File

@@ -100,7 +100,6 @@ enum class UDQAction {
UPDATE
};
enum class UDAControl {
WCONPROD_ORAT,
WCONPROD_GRAT,
@@ -122,6 +121,15 @@ enum class UDAControl {
};
enum class UDAKeyword {
WCONPROD,
WCONINJE,
GCONINJE,
GCONPROD
};
namespace UDQ {
bool compatibleTypes(UDQVarType lhs, UDQVarType rhs);
@@ -135,6 +143,9 @@ namespace UDQ {
bool cmpFunc(UDQTokenType token_type);
std::string typeName(UDQVarType var_type);
UDAKeyword keyword(UDAControl control);
int uadCode(UDAControl control);
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Statoil ASA.
Copyright 2019 Equinor ASA.
This file is part of the Open Porous Media project (OPM).
@@ -18,90 +18,58 @@
*/
#ifndef UDQINPUT_HPP_
#define UDQINPUT_HPP_
#ifndef UDQINPUT__HPP_
#define UDQINPUT__HPP_
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <memory>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQAssign.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQFunctionTable.hpp>
#include <opm/parser/eclipse/EclipseState/Util/OrderedMap.hpp>
namespace Opm {
class DeckRecord;
class Deck;
class UDQAssign;
class UDQDefine;
class UDQInput {
public:
explicit UDQInput(const Deck& deck);
const std::string& unit(const std::string& key) const;
bool has_unit(const std::string& keyword) const;
bool has_keyword(const std::string& keyword) const;
void add_record(const DeckRecord& record);
void assign_unit(const std::string& keyword, const std::string& unit);
class UDQIndex {
public:
UDQIndex() = default;
std::vector<UDQDefine> definitions() const;
std::vector<UDQDefine> definitions(UDQVarType var_type) const;
/*
The input_definitions() function is written to supply the information
needed when writing the restart file. The return value is a list of
pairs, where the first element in the pair is the index in the deck
for a particular UDQ keyword, and then the corresponding keyword.
Assume a deck keyword which looks like this:
UDQ
ASSIGN WUX 10 /
UNITS WUX 'BARSA' /
DEFINE WUPR SUM(WOPR) * 0.75 /
DEFINE FUCK MAX(WOPR) * 1.25 /
ASSIGN FUX 100 /
DEFINE BUPR ?? /
/
Then the return value from input_definitions() will be:
{{1, UDQDefine("WUPR")},
{2, UDQDefine("FUCK")},
{4, UDQDefine("BUPR")}
UDQIndex(std::size_t insert_index_arg, std::size_t typed_insert_index_arg, UDQAction action_arg) :
insert_index(insert_index_arg),
typed_insert_index(typed_insert_index_arg),
action(action_arg)
{
}
Where the the numerical index is the index in a fictious vector
consisting of only the ASSIGN and DEFINE keywords, in input order.
*/
std::vector<std::pair<size_t, UDQDefine>> input_definitions() const;
std::vector<UDQAssign> assignments() const;
std::vector<UDQAssign> assignments(UDQVarType var_type) const;
const UDQParams& params() const;
const UDQFunctionTable& function_table() const;
private:
UDQParams udq_params;
UDQFunctionTable udqft;
std::size_t insert_index;
std::size_t typed_insert_index;
UDQAction action;
};
/*
The choices of datastructures are strongly motivated by the
constraints imposed by the Eclipse formatted restart files; for
writing restart files it is essential to keep meticolous control over
the ordering of the keywords. In this class the ordering is mainly
maintained by the input_index map which keeps track of the insert
order of each keyword, and whether the keyword is currently DEFINE'ed
or ASSIGN'ed.
*/
std::unordered_map<std::string, UDQDefine> m_definitions;
std::unordered_map<std::string, UDQAssign> m_assignments;
std::unordered_map<std::string, std::string> units;
class UDQInput{
public:
UDQInput(const UDQIndex& index, const UDQDefine& udq_define, const std::string& unit);
UDQInput(const UDQIndex& index, const UDQAssign& udq_assign, const std::string& unit);
OrderedMap<std::string, std::pair<size_t, UDQAction>> input_index;
};
template<typename T>
const T& get() const;
template<typename T>
bool is() const;
const std::string& keyword() const;
UDQVarType var_type() const;
const std::string& unit() const;
const UDQIndex index;
private:
const UDQDefine * define;
const UDQAssign * assign;
const std::string m_keyword;
UDQVarType m_var_type;
const std::string m_unit;
};
}

View File

@@ -31,7 +31,7 @@ namespace Opm {
public:
explicit UDQParams(const Deck& deck);
UDQParams();
int rand_seed() const noexcept;
void reseedRNG(int seed);
double range() const noexcept;
double undefinedValue() const noexcept;

View File

@@ -44,6 +44,7 @@ class EclipseGrid;
class DeckKeyword;
struct WellInjectionProperties;
class WellProductionProperties;
class UDQActive;
struct WellGuideRate {
bool available;
@@ -162,7 +163,6 @@ public:
void switchToProducer();
ProductionControls productionControls(const SummaryState& st) const;
InjectionControls injectionControls(const SummaryState& st) const;
int vfp_table_number() const;
double alq_value() const;
double temperature() const;

View File

@@ -31,6 +31,8 @@ namespace Opm {
class DeckRecord;
class UnitSystem;
class SummaryState;
class UDQActive;
class UDQConfig;
struct WellInjectionProperties {
std::string name;
@@ -75,6 +77,7 @@ namespace Opm {
void setBHPLimit(const double limit);
InjectionControls controls(const UnitSystem& unit_system, const SummaryState& st, double udq_default) const;
bool updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const;
};
std::ostream& operator<<( std::ostream&, const WellInjectionProperties& );

View File

@@ -32,6 +32,7 @@ namespace Opm {
class DeckRecord;
class SummaryState;
class UDQActive;
class WellProductionProperties {
public:
@@ -75,13 +76,13 @@ namespace Opm {
// this is used to check whether the specified control mode is an effective history matching production mode
static bool effectiveHistoryProductionControl(const WellProducer::ControlModeEnum cmode);
void handleWCONPROD( const DeckRecord& record);
void handleWCONPROD( const std::string& well, const DeckRecord& record);
void handleWCONHIST( const DeckRecord& record);
void handleWELTARG(WellTarget::ControlModeEnum cmode, double newValue, double siFactorG, double siFactorL, double siFactorP);
void resetDefaultBHPLimit();
void clearControls();
ProductionControls controls(const SummaryState& st, double udq_default) const;
bool updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const;
private:
int m_productionControls = 0;
void init_rates( const DeckRecord& record );

View File

@@ -0,0 +1,360 @@
/*
Copyright 2018 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 <opm/output/eclipse/AggregateUDQData.hpp>
#include <opm/output/eclipse/AggregateGroupData.hpp>
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
//#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQAssign.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQFunctionTable.hpp>
#include <algorithm>
#include <cstddef>
#include <cstring>
#include <string>
#include <iostream>
// #####################################################################
// Class Opm::RestartIO::Helpers::AggregateGroupData
// ---------------------------------------------------------------------
namespace {
// maximum number of groups
std::size_t ngmaxz(const std::vector<int>& inteHead)
{
return inteHead[20];
}
namespace iUdq {
Opm::RestartIO::Helpers::WindowedArray<int>
allocate(const std::vector<int>& udqDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<int>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(udqDims[0]) },
WV::WindowSize{ static_cast<std::size_t>(udqDims[1]) }
};
}
template <class IUDQArray>
void staticContrib(const Opm::UDQInput& udq_input, IUDQArray& iUdq)
{
if (udq_input.is<Opm::UDQDefine>()) {
iUdq[0] = 2;
iUdq[1] = -4;
} else {
iUdq[0] = 0;
iUdq[1] = -4;
}
iUdq[2] = udq_input.index.typed_insert_index;
}
} // iUdq
namespace iUad {
Opm::RestartIO::Helpers::WindowedArray<int>
allocate(const std::vector<int>& udqDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<int>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(udqDims[2]) },
WV::WindowSize{ static_cast<std::size_t>(udqDims[3]) }
};
}
template <class IUADArray>
void staticContrib(const Opm::UDQActive::Record& udq_record, IUADArray& iUad)
{
iUad[0] = udq_record.uad_code;
iUad[1] = udq_record.input_index + 1;
// entry 3 - unknown meaning - value = 1
iUad[2] = 1;
iUad[3] = udq_record.use_count;
iUad[4] = udq_record.use_index + 1;
}
} // iUad
namespace zUdn {
Opm::RestartIO::Helpers::WindowedArray<
Opm::EclIO::PaddedOutputString<8>
>
allocate(const std::vector<int>& udqDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<
Opm::EclIO::PaddedOutputString<8>
>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(udqDims[0]) },
WV::WindowSize{ static_cast<std::size_t>(udqDims[4]) }
};
}
template <class zUdnArray>
void staticContrib(const Opm::UDQInput& udq_input, zUdnArray& zUdn)
{
// entry 1 is udq keyword
zUdn[0] = udq_input.keyword();
zUdn[1] = udq_input.unit();
}
} // zUdn
namespace zUdl {
Opm::RestartIO::Helpers::WindowedArray<
Opm::EclIO::PaddedOutputString<8>
>
allocate(const std::vector<int>& udqDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<
Opm::EclIO::PaddedOutputString<8>
>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(udqDims[0]) },
WV::WindowSize{ static_cast<std::size_t>(udqDims[5]) }
};
}
template <class zUdlArray>
void staticContrib(const Opm::UDQInput& input, zUdlArray& zUdl)
{
int l_sstr = 8;
int max_l_str = 128;
// write out the input formula if key is a DEFINE udq
if (input.is<Opm::UDQDefine>()) {
const auto& udq_define = input.get<Opm::UDQDefine>();
const std::string& z_data = udq_define.input_string();
int n_sstr = z_data.size()/l_sstr;
if (static_cast<int>(z_data.size()) > max_l_str) {
std::cout << "Too long input data string (max 128 characters): " << z_data << std::endl;
throw std::invalid_argument("UDQ - variable: " + udq_define.keyword());
}
else {
for (int i = 0; i < n_sstr; i++) {
zUdl[i] = z_data.substr(i*l_sstr, l_sstr);
}
//add remainder of last non-zero string
if ((z_data.size() % l_sstr) > 0)
zUdl[n_sstr] = z_data.substr(n_sstr*l_sstr);
}
}
}
} // zUdl
namespace iGph {
Opm::RestartIO::Helpers::WindowedArray<int>
allocate(const std::vector<int>& udqDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<int>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(udqDims[6]) },
WV::WindowSize{ static_cast<std::size_t>(1) }
};
}
template <class IGPHArray>
void staticContrib(const int inj_phase,
IGPHArray& iGph)
{
iGph[0] = inj_phase;
}
} // iGph
namespace iUap {
Opm::RestartIO::Helpers::WindowedArray<int>
allocate(const std::vector<int>& udqDims)
{
using WV = Opm::RestartIO::Helpers::WindowedArray<int>;
return WV {
WV::NumWindows{ static_cast<std::size_t>(udqDims[7]) },
WV::WindowSize{ static_cast<std::size_t>(1) }
};
}
template <class IUAPArray>
void staticContrib(const int wg_no,
IUAPArray& iUap)
{
iUap[0] = wg_no+1;
}
} // iUap
}
// =====================================================================
template < typename T>
std::pair<bool, int > findInVector(const std::vector<T> & vecOfElements, const T & element)
{
std::pair<bool, int > result;
// Find given element in vector
auto it = std::find(vecOfElements.begin(), vecOfElements.end(), element);
if (it != vecOfElements.end())
{
result.second = std::distance(vecOfElements.begin(), it);
result.first = true;
}
else
{
result.first = false;
result.second = -1;
}
return result;
}
const std::vector<int> Opm::RestartIO::Helpers::igphData::ig_phase(const Opm::Schedule& sched,
const std::size_t simStep,
const std::vector<int>& inteHead
)
{
std::vector<int> inj_phase(ngmaxz(inteHead), 0);
for (const auto& gname : sched.groupNames(simStep)) {
const auto& group = sched.getGroup2(gname, simStep);
if (group.isInjectionGroup()) {
//auto phase = group.getInjectionPhase();
auto phase = Opm::Phase::OIL;
if ( phase == Opm::Phase::OIL ) inj_phase[group.insert_index()] = 1;
if ( phase == Opm::Phase::WATER ) inj_phase[group.insert_index()] = 2;
if ( phase == Opm::Phase::GAS ) inj_phase[group.insert_index()] = 3;
}
}
return inj_phase;
}
const std::vector<int> iuap_data(const Opm::Schedule& sched,
const std::size_t simStep,
const std::vector<Opm::UDQActive::InputRecord>& iuap)
{
//construct the current list of well or group sequence numbers to output the IUAP array
std::vector<int> wg_no;
Opm::UDAKeyword wg_key;
for (std::size_t ind = 0; ind < iuap.size(); ind++) {
auto& ctrl = iuap[ind].control;
wg_key = Opm::UDQ::keyword(ctrl);
if ((wg_key == Opm::UDAKeyword::WCONPROD) || (wg_key == Opm::UDAKeyword::WCONINJE)) {
const auto& well = sched.getWell2(iuap[ind].wgname, simStep);
wg_no.push_back(well.seqIndex());
}
else if ((wg_key == Opm::UDAKeyword::GCONPROD) || (wg_key == Opm::UDAKeyword::GCONINJE)) {
const auto& group = sched.getGroup2(iuap[ind].wgname, simStep);
wg_no.push_back(group.insert_index());
}
else {
std::cout << "Invalid Control keyword: " << static_cast<int>(ctrl) << std::endl;
throw std::invalid_argument("UDQ - variable: " + iuap[ind].udq );
}
}
return wg_no;
}
Opm::RestartIO::Helpers::AggregateUDQData::
AggregateUDQData(const std::vector<int>& udqDims)
: iUDQ_ (iUdq::allocate(udqDims)),
iUAD_ (iUad::allocate(udqDims)),
zUDN_ (zUdn::allocate(udqDims)),
zUDL_ (zUdl::allocate(udqDims)),
iGPH_ (iGph::allocate(udqDims)),
iUAP_ (iUap::allocate(udqDims))
{}
// ---------------------------------------------------------------------
void
Opm::RestartIO::Helpers::AggregateUDQData::
captureDeclaredUDQData(const Opm::Schedule& sched,
const std::size_t simStep,
const std::vector<int>& inteHead)
{
auto udqCfg = sched.getUDQConfig(simStep);
for (const auto& udq_input : udqCfg.input()) {
auto udq_index = udq_input.index.insert_index;
{
auto i_udq = this->iUDQ_[udq_index];
iUdq::staticContrib(udq_input, i_udq);
}
{
auto z_udn = this->zUDN_[udq_index];
zUdn::staticContrib(udq_input, z_udn);
}
{
auto z_udl = this->zUDL_[udq_index];
zUdl::staticContrib(udq_input, z_udl);
}
}
auto udq_active = sched.udqActive(simStep);
if (udq_active) {
const auto& udq_records = udq_active.get_iuad();
for (std::size_t index = 0; index < udq_records.size(); index++) {
const auto& record = udq_records[index];
auto i_uad = this->iUAD_[index];
iUad::staticContrib(record, i_uad);
}
const auto& iuap_records = udq_active.get_iuap();
const auto iuap_vect = iuap_data(sched, simStep,iuap_records);
for (std::size_t index = 0; index < iuap_vect.size(); index++) {
const auto& wg_no = iuap_vect[index];
auto i_uap = this->iUAP_[index];
iUap::staticContrib(wg_no, i_uap);
}
}
Opm::RestartIO::Helpers::igphData igph_dat;
auto igph = igph_dat.ig_phase(sched, simStep, inteHead);
for (std::size_t index = 0; index < igph.size(); index++) {
auto i_igph = this->iGPH_[index];
iGph::staticContrib(igph[index], i_igph);
}
}

View File

@@ -82,12 +82,14 @@ createDoubHead(const EclipseState& es,
const double nextTimeStep)
{
const auto& usys = es.getDeckUnitSystem();
//const auto& rspec = es.runspec();
const auto tconv = getTimeConv(usys);
auto dh = DoubHEAD{}
.tuningParameters(sched.getTuning(), lookup_step, tconv)
.timeStamp (computeTimeStamp(sched, simTime))
.drsdt (sched, lookup_step, tconv)
//.udq_param(getUDQParam(rspec))
;
if (nextTimeStep > 0.0) {

View File

@@ -182,7 +182,18 @@ namespace {
mxwpit,
};
}
/*
Opm::RestartIO::InteHEAD::UdqParam
getRandSeedPar(const ::Opm::Runspec& rspec)
{
const auto& udq_par = rspec.udqParams();
const auto r_seed = udq_par.rand_seed();
return { r_seed};
}
*/
Opm::RestartIO::InteHEAD::WellSegDims
getWellSegDims(const ::Opm::Runspec& rspec,
const ::Opm::Schedule& sched,
@@ -280,6 +291,7 @@ createInteHead(const EclipseState& es,
.regionDimensions (getRegDims(tdim, rdim))
.ngroups ({ ngmax })
.variousParam (201702, 100) // Output should be compatible with Eclipse 100, 2017.02 version.
//.udqParam_1 (getRandSeedPar(rspec))
;
return ih.data();

View File

@@ -0,0 +1,98 @@
/*
Copyright (c) 2018 Equinor ASA
Copyright (c) 2018 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 <opm/output/eclipse/AggregateUDQData.hpp>
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
#include <opm/output/eclipse/InteHEAD.hpp>
#include <opm/output/eclipse/DoubHEAD.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
#include <opm/parser/eclipse/Units/Units.hpp>
#include <chrono>
#include <cstddef>
#include <vector>
namespace {
std::size_t entriesPerIUDQ()
{
std::size_t no_entries = 3;
return no_entries;
}
std::size_t entriesPerIUAD()
{
std::size_t no_entries = 5;
return no_entries;
}
std::size_t entriesPerZUDN()
{
std::size_t no_entries = 2;
return no_entries;
}
std::size_t entriesPerZUDL()
{
std::size_t no_entries = 16;
return no_entries;
}
std::size_t entriesPerIGph(const std::vector<int>& inteHead)
{
std::size_t no_entries = inteHead[20];
return no_entries;
}
} // Anonymous
// #####################################################################
// Public Interface (createUdqDims()) Below Separator
// ---------------------------------------------------------------------
std::vector<int>
Opm::RestartIO::Helpers::
createUdqDims(const Schedule& sched,
const std::size_t simStep,
const std::vector<int>& inteHead)
{
const auto& udqCfg = sched.getUDQConfig(simStep);
const auto& udqActive = sched.udqActive(simStep);
std::vector<int> udqDims(8);
udqDims[0] = udqCfg.size();
udqDims[1] = entriesPerIUDQ();
udqDims[2] = udqActive.IUAD_size();
udqDims[3] = entriesPerIUAD();
udqDims[4] = entriesPerZUDN();
udqDims[5] = entriesPerZUDL();
udqDims[6] = entriesPerIGph(inteHead);
udqDims[7] = udqActive.IUAP_size();
return udqDims;
}

View File

@@ -298,9 +298,9 @@ enum Index : std::vector<double>::size_type {
// 210..219
dh_210 = 210,
dh_211 = 211,
dh_212 = 212,
dh_213 = 213,
dh_214 = 214,
UdqPar_2= VI::doubhead::UdqPar_2,
UdqPar_3= VI::doubhead::UdqPar_3,
UdqPar_4= VI::doubhead::UdqPar_4,
dh_215 = 215,
dh_216 = 216,
dh_217 = 217,
@@ -487,7 +487,14 @@ Opm::RestartIO::DoubHEAD::DoubHEAD()
this->data_[Index::dh_210] = 0.0;
this->data_[Index::dh_211] = 0.0;
this->data_[Index::dh_214] = 1.0e-4;
/*
UdqPar_2 and UdqPar_3 correspond to indices 212 og 213 respectively, they
were not set at all in the original code, therefor temporarily commented
out here to avoid effect of UDQ.
*/
//this->data_[UdqPar_2] = 1.0E+20;
//this->data_[UdqPar_3] = 0.0;
this->data_[UdqPar_4] = 1.0e-4;
this->data_[Index::dh_215] = -2.0e+20;
this->data_[Index::dh_217] = 0.0;
this->data_[Index::dh_218] = 0.0;
@@ -616,3 +623,13 @@ Opm::RestartIO::DoubHEAD::drsdt(const Schedule& sched,
return *this;
}
Opm::RestartIO::DoubHEAD&
Opm::RestartIO::DoubHEAD::udq_param(const UDQParams& udqPar)
{
this->data_[UdqPar_2] = udqPar.range();
this->data_[UdqPar_3] = udqPar.undefinedValue();
this->data_[UdqPar_4] = udqPar.cmpEpsilon();
return *this;
}

View File

@@ -19,420 +19,419 @@
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
enum index : std::vector<int>::size_type {
ISNUM = VI::intehead::ISNUM , // 0 0 An encoded integer corresponding to the time the file was created. For files not originating from ECLIPSE, this value may be set to zero.
VERSION = VI::intehead::VERSION , // 0 0
UNIT = VI::intehead::UNIT , // (1,2,3) 1 units type: 1 - METRIC, 2 - FIELD, 3 - LAB
ih_003 = 3 , // 0 0
ih_004 = 4 , // 0 0
ih_005 = 5 , // 0 0
ih_006 = 6 , // 0 0
ih_007 = 7 , // 0 0
NX = VI::intehead::NX , // NX 137 Grid x-direction dimension, NX
NY = VI::intehead::NY , // NY 236 Grid x-direction dimension, NY
NZ = VI::intehead::NZ , // NZ 58 Grid x-direction dimension, NZ
NACTIV = VI::intehead::NACTIV , // NACTIV? 89022 NACTIV = number of active cells
ih_012 = 12 , // 0 0
ih_013 = 13 , // 0 0
PHASE = VI::intehead::PHASE , // IPHS 7 IPHS = phase indicator: 1 - oil, 2 - water, 3 - oil/water, 4 - gas, 5 oil/gas, 6 - gas/water, 7 - oil/water/gas (ECLIPSE output only)
ih_015 = 15 , // 0 0
NWELLS = VI::intehead::NWELLS , // NWELLS 39 NWELL = number of wells
NCWMAX = VI::intehead::NCWMAX , // NCWMAX 108 Weldims item2 NCWMAX = maximum number of completions per well
NGRP = 18 , // NGRP? 0 Number of actual groups
NWGMAX = VI::intehead::NWGMAX , // NWGMAX 0 maximum of weldims item3 or item4 NWGMAX = maximum number of wells in any well group
NGMAXZ = VI::intehead::NGMAXZ , // NGMAXZ 0 weldims item3 + 1 NGMAXZ = maximum number of groups in field
ih_021 = 21 , // 0 0
ih_022 = 22 , // 0 0
ih_023 = 23 , // 0 0
NIWELZ = VI::intehead::NIWELZ , // NIWELZ 155 155 NIWELZ = no of data elements per well in IWEL array (default 97 for ECLIPSE, 94 for ECLIPSE 300)
NSWELZ = VI::intehead::NSWELZ , // NSWELZ 122 122 NSWELZ = number of daelements per well in SWEL array
NXWELZ = VI::intehead::NXWELZ , // NXWELZ 130 130 NXWELZ = number of delements per well in XWEL array
NZWELZ = VI::intehead::NZWELZ , // NZWEL 3 3 NZWEL = no of 8-character words per well in ZWEL array (= 3)
ih_028 = 28 , // 0 0
ih_029 = 29 , // 0 0
ih_030 = 30 , // 0 0
ih_031 = 31 , // 0 0
NICONZ = VI::intehead::NICONZ , // 25 15 25 NICON = no of data elements per completion in ICON array (default 19)
NSCONZ = VI::intehead::NSCONZ , // 40 0 NSCONZ = number of data elements per completion in SCON array
NXCONZ = VI::intehead::NXCONZ , // 58 0 58 NXCONZ = number of data elements per completion in XCON array
ih_035 = 35 , // 0 0
NIGRPZ = VI::intehead::NIGRPZ , // 97+intehead_array[19] 0 97 + intehead[19] NIGRPZ = no of data elements per group in IGRP array
NSGRPZ = VI::intehead::NSGRPZ , // 112 0 112 NSGRPZ = number of data elements per group in SGRP array
NXGRPZ = VI::intehead::NXGRPZ , // 180 0 180 NXGRPZ = number of data elements per group in XGRP array
NZGRPZ = VI::intehead::NZGRPZ , // 5 0 NZGRPZ = number of data elements per group in ZGRP array
ih_040 = 40 , // 0 0
NCAMAX = VI::intehead::NCAMAX , // 1 0 NCAMAX = maximum number of analytic aquifer connections
NIAAQZ = VI::intehead::NIAAQZ , // 18 0 NIAAQZ = number of data elements per aquifer in IAAQ array
NSAAQZ = VI::intehead::NSAAQZ , // 24 0 NSAAQZ = number of data elements per aquifer in SAAQ array
NXAAQZ = VI::intehead::NXAAQZ , // 10 0 NXAAQZ = number of data elements per aquifer in XAAQ array
NICAQZ = VI::intehead::NICAQZ , // 7 0 NSCAQZ= number of data elements per aquifer connection in SCAQ array
NSCAQZ = VI::intehead::NSCAQZ , // 2 0
NACAQZ = VI::intehead::NACAQZ , // 4 0
ih_048 = 48 , // 0 0
ih_049 = 49 , // 1 // has been determined by testing
ih_050 = 50 , // 1 // has been determined by testing
ih_051 = 51 , // 0 0
ih_052 = 52 , // 0 0
ih_053 = 53 , // 0 0
ih_054 = 54 , // 0 0
ih_055 = 55 , // 0 0
ih_056 = 56 , // 0 0
ih_057 = 57 , // 0 0
ih_058 = 58 , // 0 0
ih_059 = 59 , // 0 0
ih_060 = 60 , // 0 0
ih_061 = 61 , // 0 0
ih_062 = 62 , // 0 0
ih_063 = 63 , // 0 0
DAY = 64 , // IDAY 2 IDAY = calendar day at this report time
MONTH = 65 , // IMON 6 IMON = calendar month at this report time
YEAR = 66 , // IYEAR 2016 IYEAR = calendar year at this report time
NUM_SOLVER_STEPS = 67 , // The number of solver steps the simulator has performed so far.
REPORT_STEP = 68 , // The sequence/report number for for this restart file.
ih_069 = 69 , // 0 0
ih_070 = 70 , // 0 0
ih_071 = 71 , // 0 0
ih_072 = 72 , // 0 0
ih_073 = 73 , // 0 0
ih_074 = 74 , // 0 0
ih_075 = 75 , // 0 0
ih_076 = 76 , // 0 0 2
ih_077 = 77 , // 0 0
ih_078 = 78 , // 0 0
ih_079 = 79 , // 0 0
NEWTMX = 80 , // 0 0 Tuning,Record3,Item1
NEWTMN = 81 , // 0 0 Tuning,Record3,Item2
LITMAX = 82 , // 0 0 Tuning,Record3,Item3
LITMIN = 83 , // 0 0 Tuning,Record3,Item4
ih_084 = 84 , // 0 0 Tuning,Record3,Item5
ih_085 = 85 , // 0 0 Tuning,Record3,Item6
MXWSIT = 86 , // 0 0
MXWPIT = 87 , // 0 0
ih_088 = 88 , // 0 0
NTFIP = 89 , // 0 0 REGDIMS item1, or TABDIMS item 5
ih_090 = 90 , // 0 0
ih_091 = 91 , // 0 0
ih_092 = 92 , // 0 0
ih_093 = 93 , // 0 0
IPROG = 94 , // 0 100 IPROG = simulation program identifier: 100 - ECLIPSE 100, 300 - ECLIPSE 300, 500 - ECLIPSE 300 (thermal option), negative - Other simulator
INITSIZE = 95 , // 0 0
ih_096 = 96 , // 0 0
ih_097 = 97 , // 0 0
ih_098 = 98 , // 0 0
NMFIPR = 99 , // 0 0 REGDIMS item2
ih_100 = 100 , // 0 0
ih_101 = 101 , // 0 0 1
ih_102 = 102 , // 0 0
ih_103 = 103 , // 0 0 1
ih_104 = 104 , // 0 0
ih_105 = 105 , // 0 0
ih_106 = 106 , // 0 0
ih_107 = 107 , // 0 0
ih_108 = 108 , // 0 0
ih_109 = 109 , // 0 0
ih_110 = 110 , // 0 0
ih_111 = 111 , // 0 0
ih_112 = 112 , // 0 0
ih_113 = 113 , // 0 0
ih_114 = 114 , // 0 0
ih_115 = 115 , // 0 0
ih_116 = 116 , // 0 0
ih_117 = 117 , // 0 0
ih_118 = 118 , // 0 0
ih_119 = 119 , // 0 0
ih_120 = 120 , // 0 0
ih_121 = 121 , // 0 0
ih_122 = 122 , // 0 0
ih_123 = 123 , // 0 0
ih_124 = 124 , // 0 0
ih_125 = 125 , // 0 0
ih_126 = 126 , // 0 0
ih_127 = 127 , // 0 0
ih_128 = 128 , // 0 0
ih_129 = 129 , // 0 0
ih_130 = 130 , // 0 0
NODMAX = 131 , // 0 0 NODMAX = maximum number of nodes in extended network option
NBRMAX = 132 , // 0 0 NBRMAX = maximum number of branches in extended network option
NIBRAN = 133 , // 0 0 NIBRAN = number of entries per branch in the IBRAN array
NRBRAN = 134 , // 0 0 NRBRAN = number of tries per branch in the RBRAN array
NINODE = 135 , // 0 0 NINODE = number of entries per node in the INODE array
NRNODE = 136 , // 0 0 NRNODE = number of entries per node in the RNODE array
NZNODE = 137 , // 0 0 NZNODE = number of entries per node in the ZNODE array
NINOBR = 138 , // 0 0 NINOBR = size of the INOBR array
ih_139 = 139 , // 0 0
ih_140 = 140 , // 0 0
ih_141 = 141 , // 0 0
ih_142 = 142 , // 0 0
ih_143 = 143 , // 0 0
ih_144 = 144 , // 0 0
ih_145 = 145 , // 0 0
ih_146 = 146 , // 0 0
ih_147 = 147 , // 0 0
ih_148 = 148 , // 0 0
ih_149 = 149 , // 0 0
ih_150 = 150 , // 0 0
ih_151 = 151 , // 0 0
ih_152 = 152 , // 0 0
ih_153 = 153 , // 0 0
ih_154 = 154 , // 0 0
ih_155 = 155 , // 0 0
ih_156 = 156 , // 0 0
ih_157 = 157 , // 0 0
ih_158 = 158 , // 0 0
ih_159 = 159 , // 0 0
ih_160 = 160 , // 0 0
ih_161 = 161 , // 0 0
NGCAUS = 162 , // 0 0 NGCAUS = maximum number of aquifer connections actually used.
ih_163 = 163 , // 0 0
ih_164 = 164 , // 0 0
ih_165 = 165 , // 0 0
ih_166 = 166 , // 0 0
ih_167 = 167 , // 0 0
ih_168 = 168 , // 0 0
ih_169 = 169 , // 0 0
ih_170 = 170 , // 0 0
ih_171 = 171 , // 0 0
ih_172 = 172 , // 0 0
ih_173 = 173 , // 0 0
NSEGWL = VI::intehead::NSEGWL , // 0 0 number of mswm wells defined with WELSEG
NSWLMX = VI::intehead::NSWLMX , // NSWLMX 0 Item 1 in WSEGDIMS keyword (runspec section) NSWLMX = maximum number of segmented wells
NSEGMX = VI::intehead::NSEGMX , // NSEGMX 0 Item 2 in WSEGDIMS keyword (runspec section) NSEGMX = maximum number of segments per well
NLBRMX = VI::intehead::NLBRMX , // NLBRMX 0 Item 3 in WSEGDIMS keyword (runspec section) NLBRMX = maximum number of lateral branches per well
NISEGZ = VI::intehead::NISEGZ , // 22 0 22 NISEGZ = number of entries per segment in ISEG array
NRSEGZ = VI::intehead::NRSEGZ , // 146 0 140 NRSEGZ = number of entries per segment in RSEG array
NILBRZ = VI::intehead::NILBRZ , // 10 10 NILBRZ = number of entries per segment in ILBR array
RSTSIZE = 181 , // 0
ih_182 = 182 , // 0
ih_183 = 183 , // 0
ih_184 = 184 , // 0
ih_185 = 185 , // 0
ih_186 = 186 , // 0
ih_187 = 187 , // 0
ih_188 = 188 , // 0
ih_189 = 189 , // 0
ih_190 = 190 , // 0
ih_191 = 191 , // 0
ih_192 = 192 , // 0
ih_193 = 193 , // 0
ih_194 = 194 , // 0
ih_195 = 195 , // 0
ih_196 = 196 , // 0
ih_197 = 197 , // 0
ih_198 = 198 , // 0
ih_199 = 199 , // 0
ih_200 = 200 , // 0
ih_201 = 201 , // 0
ih_202 = 202 , // 0
ih_203 = 203 , // 0
ih_204 = 204 , // 0
ih_205 = 205 , // 0
IHOURZ = 206 , // IHOURZ IHOURZ = current simulation time HH:MM:SS number of hours (HH) (0-23).
IMINTS = 207 , // IMINTS IMINTS = current simulation time HH:MM:SS - number of minutes (MM) (0-59).
ih_208 = 208 , // 0
ih_209 = 209 , // 0
ih_210 = 210 , // 0
ih_211 = 211 , // 0
ih_212 = 212 , // 0
ih_213 = 213 , // 0
ih_214 = 214 , // 0
ih_215 = 215 , // 0
ih_216 = 216 , // 0
ih_217 = 217 , // 0
ih_218 = 218 , // 0
ih_219 = 219 , // 0
ih_220 = 220 , // 0
ih_221 = 221 , // 0
ih_222 = 222 , // 0
NIIAQN = 223 , // 0 NIIAQN = number of lines of integer AQUNUM data.
NIRAQN = 224 , // 0 NIRAQN = number of lines of real AQUNUM data.
ih_225 = 225 , // 0
NUMAQN = 226 , // 0 NUMAQN = number of lines of AQUNUM data entered.
ih_227 = 227 , // 0
ih_228 = 228 , // 0
ih_229 = 229 , // 0
ih_230 = 230 , // 0
ih_231 = 231 , // 0
ih_232 = 232 , // 0
ih_233 = 233 , // 0
NICOTZ = 234 , // 0 NICOTZ = number of entries in the ICOT array
NXCOTZ = 235 , // 0 NXCOTZ = number of entries in the XCOT array
NIWETZ = 236 , // 0 NIWETZ = number of entries in the IWET array
NXWETZ = 237 , // 0 NXWETZ = number of entries in the XWET array
NIGRTZ = 238 , // 0 NIGRTZ = number of entries in the IGRT array
NXGRTZ = 239 , // 0 NXGRTZ = number of entries in the XGRT array
NSTRA2 = 240 , // 0 NSTRA2 = number of tracers + 2
ih_241 = 241 , // 0
ih_242 = 242 , // 0
ih_243 = 243 , // 0
ih_244 = 244 , // 0
ih_245 = 245 , // 0
ih_246 = 246 , // 0
ih_247 = 247 , // 0
ih_248 = 248 , // 0
ih_249 = 249 , // 0
ih_250 = 250 , // 0
ih_251 = 251 , // 0
MAAQID = 252 , // 0 MAAQID = maximum number of analytic aquifers
ih_253 = 253 , // 0
ih_254 = 254 , // 0
ih_255 = 255 , // 0
ih_256 = 256 , // 0
ih_257 = 257 , // 0
ih_258 = 258 , // 0
ih_259 = 259 , // 0
ih_260 = 260 , // 0
ih_261 = 261 , // 0
ih_262 = 262 , // 0
ih_263 = 263 , // 0
ih_264 = 264 , // 0
ih_265 = 265 , // 0
ih_266 = 266 , // 0
ih_267 = 267 , // 0
ih_268 = 268 , // 0
ih_269 = 269 , // 0
ih_270 = 270 , // 0
NCRDMX = 271 , // 0 NCRDMX = maximum number of chord segment links per well
ih_272 = 272 , // 0
ih_273 = 273 , // 0
ih_274 = 274 , // 0
ih_275 = 275 , // 0
ih_276 = 276 , // 0
ih_277 = 277 , // 0
ih_278 = 278 , // 0
ih_279 = 279 , // 0
ih_280 = 280 , // 0
ih_281 = 281 , // 0
ih_282 = 282 , // 0
ih_283 = 283 , // 0
ih_284 = 284 , // 0
ih_285 = 285 , // 0
ih_286 = 286 , // 0
ih_287 = 287 , // 0
ih_288 = 288 , // 0
ih_289 = 289 , // 0
ih_290 = 290 , // 0
ih_291 = 291 , // 0
ih_292 = 292 , // 0
ih_293 = 293 , // 0
ih_294 = 294 , // 0
ih_295 = 295 , // 0
ih_296 = 296 , // 0
ih_297 = 297 , // 0
ih_298 = 298 , // 0
ih_299 = 299 , // 0
ih_300 = 300 , // 0
ih_301 = 301 , // 0
ih_302 = 302 , // 0
ih_303 = 303 , // 0
ih_304 = 304 , // 0
ih_305 = 305 , // 0
ih_306 = 306 , // 0
ih_307 = 307 , // 0
ih_308 = 308 , // 0
ih_309 = 309 , // 0
ih_310 = 310 , // 0
ih_311 = 311 , // 0
ih_312 = 312 , // 0
ih_313 = 313 , // 0
ih_314 = 314 , // 0
ih_315 = 315 , // 0
ih_316 = 316 , // 0
ih_317 = 317 , // 0
ih_318 = 318 , // 0
ih_319 = 319 , // 0
ih_320 = 320 , // 0
ih_321 = 321 , // 0
ih_322 = 322 , // 0
ih_323 = 323 , // 0
ih_324 = 324 , // 0
ih_325 = 325 , // 0
ih_326 = 326 , // 0
ih_327 = 327 , // 0
ih_328 = 328 , // 0
ih_329 = 329 , // 0
ih_330 = 330 , // 0
ih_331 = 331 , // 0
ih_332 = 332 , // 0
ih_333 = 333 , // 0
ih_334 = 334 , // 0
ih_335 = 335 , // 0
ih_336 = 336 , // 0
ih_337 = 337 , // 0
ih_338 = 338 , // 0
ih_339 = 339 , // 0
ih_340 = 340 , // 0
ih_341 = 341 , // 0
ih_342 = 342 , // 0
ih_343 = 343 , // 0
ih_344 = 344 , // 0
ih_345 = 345 , // 0
ih_346 = 346 , // 0
ih_347 = 347 , // 0
ih_348 = 348 , // 0
ih_349 = 349 , // 0
ih_350 = 350 , // 0
ih_351 = 351 , // 0
ih_352 = 352 , // 0
ih_353 = 353 , // 0
ih_354 = 354 , // 0
ih_355 = 355 , // 0
ih_356 = 356 , // 0
ih_357 = 357 , // 0
ih_358 = 358 , // 0
ih_359 = 359 , // 0
ih_360 = 360 , // 0
ih_361 = 361 , // 0
ih_362 = 362 , // 0
ih_363 = 363 , // 0
ih_364 = 364 , // 0
ih_365 = 365 , // 0
ih_366 = 366 , // 0
ih_367 = 367 , // 0
ih_368 = 368 , // 0
ih_369 = 369 , // 0
ih_370 = 370 , // 0
ih_371 = 371 , // 0
ih_372 = 372 , // 0
ih_373 = 373 , // 0
ih_374 = 374 , // 0
ih_375 = 375 , // 0
ih_376 = 376 , // 0
ih_377 = 377 , // 0
ih_378 = 378 , // 0
ih_379 = 379 , // 0
ih_380 = 380 , // 0
ih_381 = 381 , // 0
ih_382 = 382 , // 0
ih_383 = 383 , // 0
ih_384 = 384 , // 0
ih_385 = 385 , // 0
ih_386 = 386 , // 0
ih_387 = 387 , // 0
ih_388 = 388 , // 0
ih_389 = 389 , // 0
ih_390 = 390 , // 0
ih_391 = 391 , // 0
ih_392 = 392 , // 0
ih_393 = 393 , // 0
ih_394 = 394 , // 0
ih_395 = 395 , // 0
ih_396 = 396 , // 0
ih_397 = 397 , // 0
ih_398 = 398 , // 0
ih_399 = 399 , // 0
ih_400 = 400 , // 0
ih_401 = 401 , // 0
ih_402 = 402 , // 0
ih_403 = 403 , // 0
ih_404 = 404 , // 0
ih_405 = 405 , // 0
ih_406 = 406 , // 0
ih_407 = 407 , // 0
ih_408 = 408 , // 0
ih_409 = 409 , // 0
ISECND = 410 , // 0 ISECND = current simulation time HH:MM:SS - number of seconds (SS), reported in microseconds (0-59,999,999)
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
ISNUM = VI::intehead::ISNUM, // 0 0 An encoded integer corresponding to the time the file was created. For files not originating from ECLIPSE, this value may be set to zero.
VERSION = VI::intehead::VERSION, // 0 0
UNIT = VI::intehead::UNIT, // (1,2,3) 1 units type: 1 - METRIC, 2 - FIELD, 3 - LAB
ih_003 = 3 , // 0 0
ih_004 = 4 , // 0 0
ih_005 = 5 , // 0 0
ih_006 = 6 , // 0 0
ih_007 = 7 , // 0 0
NX = VI::intehead::NX, // NX 137 Grid x-direction dimension, NX
NY = VI::intehead::NY, // NY 236 Grid x-direction dimension, NY
NZ = VI::intehead::NZ, // NZ 58 Grid x-direction dimension, NZ
NACTIV = VI::intehead::NACTIV, // NACTIV? 89022 NACTIV = number of active cells
ih_012 = 12 , // 0 0
ih_013 = 13 , // 0 0
PHASE = VI::intehead::PHASE, // IPHS 7 IPHS = phase indicator: 1 - oil, 2 - water, 3 - oil/water, 4 - gas, 5 oil/gas, 6 - gas/water, 7 - oil/water/gas (ECLIPSE output only)
ih_015 = 15 , // 0 0
NWELLS = VI::intehead::NWELLS, // NWELLS 39 NWELL = number of wells
NCWMAX = VI::intehead::NCWMAX, // NCWMAX 108 Weldims item2 NCWMAX = maximum number of completions per well
NGRP = 18 , // NGRP? 0 Number of actual groups
NWGMAX = VI::intehead::NWGMAX, // NWGMAX 0 maximum of weldims item3 or item4 NWGMAX = maximum number of wells in any well group
NGMAXZ = VI::intehead::NGMAXZ, // NGMAXZ 0 weldims item3 + 1 NGMAXZ = maximum number of groups in field
ih_021 = 21 , // 0 0
ih_022 = 22 , // 0 0
ih_023 = 23 , // 0 0
NIWELZ = VI::intehead::NIWELZ, // NIWELZ 155 155 NIWELZ = no of data elements per well in IWEL array (default 97 for ECLIPSE, 94 for ECLIPSE 300)
NSWELZ = VI::intehead::NSWELZ, // NSWELZ 122 122 NSWELZ = number of daelements per well in SWEL array
NXWELZ = VI::intehead::NXWELZ, // NXWELZ 130 130 NXWELZ = number of delements per well in XWEL array
NZWELZ = VI::intehead::NZWELZ, // NZWEL 3 3 NZWEL = no of 8-character words per well in ZWEL array (= 3)
ih_028 = 28 , // 0 0
ih_029 = 29 , // 0 0
ih_030 = 30 , // 0 0
ih_031 = 31 , // 0 0
NICONZ = VI::intehead::NICONZ, // 25 15 25 NICON = no of data elements per completion in ICON array (default 19)
NSCONZ = VI::intehead::NSCONZ, // 40 0 NSCONZ = number of data elements per completion in SCON array
NXCONZ = VI::intehead::NXCONZ, // 58 0 58 NXCONZ = number of data elements per completion in XCON array
ih_035 = 35 , // 0 0
NIGRPZ = VI::intehead::NIGRPZ, // 97+intehead_array[19] 0 97 + intehead[19] NIGRPZ = no of data elements per group in IGRP array
NSGRPZ = VI::intehead::NSGRPZ, // 112 0 112 NSGRPZ = number of data elements per group in SGRP array
NXGRPZ = VI::intehead::NXGRPZ, // 180 0 180 NXGRPZ = number of data elements per group in XGRP array
NZGRPZ = VI::intehead::NZGRPZ, // 5 0 NZGRPZ = number of data elements per group in ZGRP array
ih_040 = 40 , // 0 0
NCAMAX = VI::intehead::NCAMAX, // 1 0 NCAMAX = maximum number of analytic aquifer connections
NIAAQZ = VI::intehead::NIAAQZ, // 18 0 NIAAQZ = number of data elements per aquifer in IAAQ array
NSAAQZ = VI::intehead::NSAAQZ, // 24 0 NSAAQZ = number of data elements per aquifer in SAAQ array
NXAAQZ = VI::intehead::NXAAQZ, // 10 0 NXAAQZ = number of data elements per aquifer in XAAQ array
NICAQZ = VI::intehead::NICAQZ, // 7 0 NSCAQZ= number of data elements per aquifer connection in SCAQ array
NSCAQZ = VI::intehead::NSCAQZ, // 2 0
NACAQZ = VI::intehead::NACAQZ, // 4 0
ih_048 = 48 , // 0 0
ih_049 = 49 , // 1 // has been determined by testing
ih_050 = 50 , // 1 // has been determined by testing
ih_051 = 51 , // 0 0
ih_052 = 52 , // 0 0
ih_053 = 53 , // 0 0
ih_054 = 54 , // 0 0
ih_055 = 55 , // 0 0
ih_056 = 56 , // 0 0
ih_057 = 57 , // 0 0
ih_058 = 58 , // 0 0
ih_059 = 59 , // 0 0
ih_060 = 60 , // 0 0
ih_061 = 61 , // 0 0
ih_062 = 62 , // 0 0
ih_063 = 63 , // 0 0
DAY = 64 , // IDAY 2 IDAY = calendar day at this report time
MONTH = 65 , // IMON 6 IMON = calendar month at this report time
YEAR = 66 , // IYEAR 2016 IYEAR = calendar year at this report time
NUM_SOLVER_STEPS = 67 , // The number of solver steps the simulator has performed so far.
REPORT_STEP = 68 , // The sequence/report number for for this restart file.
ih_069 = 69 , // 0 0
ih_070 = 70 , // 0 0
ih_071 = 71 , // 0 0
ih_072 = 72 , // 0 0
ih_073 = 73 , // 0 0
ih_074 = 74 , // 0 0
ih_075 = 75 , // 0 0
ih_076 = 76 , // 0 0 2
ih_077 = 77 , // 0 0
ih_078 = 78 , // 0 0
ih_079 = 79 , // 0 0
NEWTMX = 80 , // 0 0 Tuning,Record3,Item1
NEWTMN = 81 , // 0 0 Tuning,Record3,Item2
LITMAX = 82 , // 0 0 Tuning,Record3,Item3
LITMIN = 83 , // 0 0 Tuning,Record3,Item4
ih_084 = 84 , // 0 0 Tuning,Record3,Item5
ih_085 = 85 , // 0 0 Tuning,Record3,Item6
MXWSIT = 86 , // 0 0
MXWPIT = 87 , // 0 0
ih_088 = 88 , // 0 0
NTFIP = 89 , // 0 0 REGDIMS item1, or TABDIMS item 5
ih_090 = 90 , // 0 0
ih_091 = 91 , // 0 0
ih_092 = 92 , // 0 0
ih_093 = 93 , // 0 0
IPROG = 94 , // 0 100 IPROG = simulation program identifier: 100 - ECLIPSE 100, 300 - ECLIPSE 300, 500 - ECLIPSE 300 (thermal option), negative - Other simulator
INITSIZE = 95 , // 0 0
ih_096 = 96 , // 0 0
ih_097 = 97 , // 0 0
ih_098 = 98 , // 0 0
NMFIPR = 99 , // 0 0 REGDIMS item2
ih_100 = 100 , // 0 0
ih_101 = 101 , // 0 0 1
ih_102 = 102 , // 0 0
ih_103 = 103 , // 0 0 1
ih_104 = 104 , // 0 0
ih_105 = 105 , // 0 0
ih_106 = 106 , // 0 0
ih_107 = 107 , // 0 0
ih_108 = 108 , // 0 0
ih_109 = 109 , // 0 0
ih_110 = 110 , // 0 0
ih_111 = 111 , // 0 0
ih_112 = 112 , // 0 0
ih_113 = 113 , // 0 0
ih_114 = 114 , // 0 0
ih_115 = 115 , // 0 0
ih_116 = 116 , // 0 0
ih_117 = 117 , // 0 0
ih_118 = 118 , // 0 0
ih_119 = 119 , // 0 0
ih_120 = 120 , // 0 0
ih_121 = 121 , // 0 0
ih_122 = 122 , // 0 0
ih_123 = 123 , // 0 0
ih_124 = 124 , // 0 0
ih_125 = 125 , // 0 0
ih_126 = 126 , // 0 0
ih_127 = 127 , // 0 0
ih_128 = 128 , // 0 0
ih_129 = 129 , // 0 0
ih_130 = 130 , // 0 0
NODMAX = 131 , // 0 0 NODMAX = maximum number of nodes in extended network option
NBRMAX = 132 , // 0 0 NBRMAX = maximum number of branches in extended network option
NIBRAN = 133 , // 0 0 NIBRAN = number of entries per branch in the IBRAN array
NRBRAN = 134 , // 0 0 NRBRAN = number of tries per branch in the RBRAN array
NINODE = 135 , // 0 0 NINODE = number of entries per node in the INODE array
NRNODE = 136 , // 0 0 NRNODE = number of entries per node in the RNODE array
NZNODE = 137 , // 0 0 NZNODE = number of entries per node in the ZNODE array
NINOBR = 138 , // 0 0 NINOBR = size of the INOBR array
ih_139 = 139 , // 0 0
ih_140 = 140 , // 0 0
ih_141 = 141 , // 0 0
ih_142 = 142 , // 0 0
ih_143 = 143 , // 0 0
ih_144 = 144 , // 0 0
ih_145 = 145 , // 0 0
ih_146 = 146 , // 0 0
ih_147 = 147 , // 0 0
ih_148 = 148 , // 0 0
ih_149 = 149 , // 0 0
ih_150 = 150 , // 0 0
ih_151 = 151 , // 0 0
ih_152 = 152 , // 0 0
ih_153 = 153 , // 0 0
ih_154 = 154 , // 0 0
ih_155 = 155 , // 0 0
ih_156 = 156 , // 0 0
ih_157 = 157 , // 0 0
ih_158 = 158 , // 0 0
ih_159 = 159 , // 0 0
ih_160 = 160 , // 0 0
ih_161 = 161 , // 0 0
NGCAUS = 162 , // 0 0 NGCAUS = maximum number of aquifer connections actually used.
ih_163 = 163 , // 0 0
ih_164 = 164 , // 0 0
ih_165 = 165 , // 0 0
ih_166 = 166 , // 0 0
ih_167 = 167 , // 0 0
ih_168 = 168 , // 0 0
ih_169 = 169 , // 0 0
ih_170 = 170 , // 0 0
ih_171 = 171 , // 0 0
ih_172 = 172 , // 0 0
ih_173 = 173 , // 0 0
NSEGWL = VI::intehead::NSEGWL, // 0 0 number of mswm wells defined with WELSEG
NSWLMX = VI::intehead::NSWLMX, // NSWLMX 0 Item 1 in WSEGDIMS keyword (runspec section) NSWLMX = maximum number of segmented wells
NSEGMX = VI::intehead::NSEGMX, // NSEGMX 0 Item 2 in WSEGDIMS keyword (runspec section) NSEGMX = maximum number of segments per well
NLBRMX = VI::intehead::NLBRMX, // NLBRMX 0 Item 3 in WSEGDIMS keyword (runspec section) NLBRMX = maximum number of lateral branches per well
NISEGZ = VI::intehead::NISEGZ, // 22 0 22 NISEGZ = number of entries per segment in ISEG array
NRSEGZ = VI::intehead::NRSEGZ, // 146 0 140 NRSEGZ = number of entries per segment in RSEG array
NILBRZ = VI::intehead::NILBRZ, // 10 10 NILBRZ = number of entries per segment in ILBR array
RSTSIZE = 181 , // 0
ih_182 = 182 , // 0
ih_183 = 183 , // 0
ih_184 = 184 , // 0
ih_185 = 185 , // 0
ih_186 = 186 , // 0
ih_187 = 187 , // 0
ih_188 = 188 , // 0
ih_189 = 189 , // 0
ih_190 = 190 , // 0
ih_191 = 191 , // 0
ih_192 = 192 , // 0
ih_193 = 193 , // 0
ih_194 = 194 , // 0
ih_195 = 195 , // 0
ih_196 = 196 , // 0
ih_197 = 197 , // 0
ih_198 = 198 , // 0
ih_199 = 199 , // 0
ih_200 = 200 , // 0
ih_201 = 201 , // 0
ih_202 = 202 , // 0
ih_203 = 203 , // 0
ih_204 = 204 , // 0
ih_205 = 205 , // 0
IHOURZ = 206 , // IHOURZ IHOURZ = current simulation time HH:MM:SS number of hours (HH) (0-23).
IMINTS = 207 , // IMINTS IMINTS = current simulation time HH:MM:SS - number of minutes (MM) (0-59).
ih_208 = 208 , // 0
ih_209 = 209 , // 0
ih_210 = 210 , // 0
ih_211 = 211 , // 0
ih_212 = 212 , // 0
ih_213 = 213 , // 0
ih_214 = 214 , // 0
ih_215 = 215 , // 0
ih_216 = 216 , // 0
ih_217 = 217 , // 0
ih_218 = 218 , // 0
ih_219 = 219 , // 0
ih_220 = 220 , // 0
ih_221 = 221 , // 0
ih_222 = 222 , // 0
NIIAQN = 223 , // 0 NIIAQN = number of lines of integer AQUNUM data.
NIRAQN = 224 , // 0 NIRAQN = number of lines of real AQUNUM data.
ih_225 = 225 , // 0
NUMAQN = 226 , // 0 NUMAQN = number of lines of AQUNUM data entered.
ih_227 = 227 , // 0
ih_228 = 228 , // 0
ih_229 = 229 , // 0
ih_230 = 230 , // 0
ih_231 = 231 , // 0
ih_232 = 232 , // 0
ih_233 = 233 , // 0
NICOTZ = 234 , // 0 NICOTZ = number of entries in the ICOT array
NXCOTZ = 235 , // 0 NXCOTZ = number of entries in the XCOT array
NIWETZ = 236 , // 0 NIWETZ = number of entries in the IWET array
NXWETZ = 237 , // 0 NXWETZ = number of entries in the XWET array
NIGRTZ = 238 , // 0 NIGRTZ = number of entries in the IGRT array
NXGRTZ = 239 , // 0 NXGRTZ = number of entries in the XGRT array
NSTRA2 = 240 , // 0 NSTRA2 = number of tracers + 2
ih_241 = 241 , // 0
ih_242 = 242 , // 0
ih_243 = 243 , // 0
ih_244 = 244 , // 0
ih_245 = 245 , // 0
ih_246 = 246 , // 0
ih_247 = 247 , // 0
ih_248 = 248 , // 0
ih_249 = 249 , // 0
ih_250 = 250 , // 0
ih_251 = 251 , // 0
MAAQID = 252 , // 0 MAAQID = maximum number of analytic aquifers
ih_253 = 253 , // 0
ih_254 = 254 , // 0
ih_255 = 255 , // 0
ih_256 = 256 , // 0
ih_257 = 257 , // 0
ih_258 = 258 , // 0
ih_259 = 259 , // 0
ih_260 = 260 , // 0
ih_261 = 261 , // 0
ih_262 = 262 , // 0
ih_263 = 263 , // 0
ih_264 = 264 , // 0
ih_265 = 265 , // 0
ih_266 = 266 , // 0
UDQPAR_1 = VI::intehead::UDQPAR_1, // 0
ih_268 = 268 , // 0
ih_269 = 269 , // 0
ih_270 = 270 , // 0
NCRDMX = 271 , // 0 NCRDMX = maximum number of chord segment links per well
ih_272 = 272 , // 0
ih_273 = 273 , // 0
ih_274 = 274 , // 0
ih_275 = 275 , // 0
ih_276 = 276 , // 0
ih_277 = 277 , // 0
ih_278 = 278 , // 0
ih_279 = 279 , // 0
ih_280 = 280 , // 0
ih_281 = 281 , // 0
ih_282 = 282 , // 0
ih_283 = 283 , // 0
ih_284 = 284 , // 0
ih_285 = 285 , // 0
ih_286 = 286 , // 0
ih_287 = 287 , // 0
ih_288 = 288 , // 0
ih_289 = 289 , // 0
ih_290 = 290 , // 0
ih_291 = 291 , // 0
ih_292 = 292 , // 0
ih_293 = 293 , // 0
ih_294 = 294 , // 0
ih_295 = 295 , // 0
ih_296 = 296 , // 0
ih_297 = 297 , // 0
ih_298 = 298 , // 0
ih_299 = 299 , // 0
ih_300 = 300 , // 0
ih_301 = 301 , // 0
ih_302 = 302 , // 0
ih_303 = 303 , // 0
ih_304 = 304 , // 0
ih_305 = 305 , // 0
ih_306 = 306 , // 0
ih_307 = 307 , // 0
ih_308 = 308 , // 0
ih_309 = 309 , // 0
ih_310 = 310 , // 0
ih_311 = 311 , // 0
ih_312 = 312 , // 0
ih_313 = 313 , // 0
ih_314 = 314 , // 0
ih_315 = 315 , // 0
ih_316 = 316 , // 0
ih_317 = 317 , // 0
ih_318 = 318 , // 0
ih_319 = 319 , // 0
ih_320 = 320 , // 0
ih_321 = 321 , // 0
ih_322 = 322 , // 0
ih_323 = 323 , // 0
ih_324 = 324 , // 0
ih_325 = 325 , // 0
ih_326 = 326 , // 0
ih_327 = 327 , // 0
ih_328 = 328 , // 0
ih_329 = 329 , // 0
ih_330 = 330 , // 0
ih_331 = 331 , // 0
ih_332 = 332 , // 0
ih_333 = 333 , // 0
ih_334 = 334 , // 0
ih_335 = 335 , // 0
ih_336 = 336 , // 0
ih_337 = 337 , // 0
ih_338 = 338 , // 0
ih_339 = 339 , // 0
ih_340 = 340 , // 0
ih_341 = 341 , // 0
ih_342 = 342 , // 0
ih_343 = 343 , // 0
ih_344 = 344 , // 0
ih_345 = 345 , // 0
ih_346 = 346 , // 0
ih_347 = 347 , // 0
ih_348 = 348 , // 0
ih_349 = 349 , // 0
ih_350 = 350 , // 0
ih_351 = 351 , // 0
ih_352 = 352 , // 0
ih_353 = 353 , // 0
ih_354 = 354 , // 0
ih_355 = 355 , // 0
ih_356 = 356 , // 0
ih_357 = 357 , // 0
ih_358 = 358 , // 0
ih_359 = 359 , // 0
ih_360 = 360 , // 0
ih_361 = 361 , // 0
ih_362 = 362 , // 0
ih_363 = 363 , // 0
ih_364 = 364 , // 0
ih_365 = 365 , // 0
ih_366 = 366 , // 0
ih_367 = 367 , // 0
ih_368 = 368 , // 0
ih_369 = 369 , // 0
ih_370 = 370 , // 0
ih_371 = 371 , // 0
ih_372 = 372 , // 0
ih_373 = 373 , // 0
ih_374 = 374 , // 0
ih_375 = 375 , // 0
ih_376 = 376 , // 0
ih_377 = 377 , // 0
ih_378 = 378 , // 0
ih_379 = 379 , // 0
ih_380 = 380 , // 0
ih_381 = 381 , // 0
ih_382 = 382 , // 0
ih_383 = 383 , // 0
ih_384 = 384 , // 0
ih_385 = 385 , // 0
ih_386 = 386 , // 0
ih_387 = 387 , // 0
ih_388 = 388 , // 0
ih_389 = 389 , // 0
ih_390 = 390 , // 0
ih_391 = 391 , // 0
ih_392 = 392 , // 0
ih_393 = 393 , // 0
ih_394 = 394 , // 0
ih_395 = 395 , // 0
ih_396 = 396 , // 0
ih_397 = 397 , // 0
ih_398 = 398 , // 0
ih_399 = 399 , // 0
ih_400 = 400 , // 0
ih_401 = 401 , // 0
ih_402 = 402 , // 0
ih_403 = 403 , // 0
ih_404 = 404 , // 0
ih_405 = 405 , // 0
ih_406 = 406 , // 0
ih_407 = 407 , // 0
ih_408 = 408 , // 0
ih_409 = 409 , // 0
ISECND = 410 , // 0 ISECND = current simulation time HH:MM:SS - number of seconds (SS), reported in microseconds (0-59,999,999)
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
INTEHEAD_NUMBER_OF_ITEMS // MUST be last element of enum.
};
@@ -677,6 +676,14 @@ ngroups(const Group& gr)
return *this;
}
Opm::RestartIO::InteHEAD&
Opm::RestartIO::InteHEAD::
udqParam_1(const UdqParam& udq_par)
{
this -> data_[UDQPAR_1] = - udq_par.udqParam_1;
return *this;
}
// =====================================================================
// Free functions (calendar/time utilities)

View File

@@ -28,6 +28,7 @@
#include <opm/output/eclipse/AggregateWellData.hpp>
#include <opm/output/eclipse/AggregateConnectionData.hpp>
#include <opm/output/eclipse/AggregateMSWData.hpp>
#include <opm/output/eclipse/AggregateUDQData.hpp>
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
#include <opm/io/eclipse/OutputStream.hpp>
@@ -259,6 +260,28 @@ namespace {
rstFile.write("RSEG", MSWData.getRSeg());
}
void writeUDQ(int sim_step,
const Schedule& schedule,
const std::vector<int>& ih,
EclIO::OutputStream::Restart& rstFile)
{
return;
//need to add test if UDQ-data exist and UDQ - active exist etc.
// do not write unless data exists and copy E100 logic.
// write UDQ - data to restart file
const std::size_t simStep = static_cast<size_t> (sim_step);
const auto udqDims = Helpers::createUdqDims(schedule, simStep, ih);
auto udqData = Helpers::AggregateUDQData(udqDims);
udqData.captureDeclaredUDQData(schedule, simStep, ih);
rstFile.write("IUDQ", udqData.getIUDQ());
rstFile.write("IUAD", udqData.getIUAD());
rstFile.write("ZUDN", udqData.getZUDN());
rstFile.write("ZUDL", udqData.getZUDL());
}
void writeWell(int sim_step,
const bool ecl_compatible_rst,
const Phases& phases,
@@ -368,8 +391,11 @@ namespace {
}
void writeSolution(const RestartValue& value,
const Schedule& schedule,
int report_step,
const bool ecl_compatible_rst,
const bool write_double_arg,
const std::vector<int>& inteHD,
EclIO::OutputStream::Restart& rstFile)
{
rstFile.message("STARTSOL");
@@ -396,6 +422,8 @@ namespace {
}
}
writeUDQ(report_step, schedule, inteHD, rstFile);
for (const auto& elm : value.extra) {
const std::string& key = elm.first.key;
if (extraInSolution(key)) {
@@ -489,8 +517,8 @@ void save(EclIO::OutputStream::Restart& rstFile,
value.wells, sumState, inteHD, rstFile);
}
}
writeSolution(value, ecl_compatible_rst, write_double, rstFile);
writeSolution(value, schedule, sim_step, ecl_compatible_rst, write_double, inteHD, rstFile);
if (! ecl_compatible_rst) {
writeExtraData(value.extra, rstFile);

View File

@@ -36,7 +36,7 @@
#include <opm/parser/eclipse/EclipseState/Grid/GridProperty.hpp>
#include <opm/parser/eclipse/EclipseState/IOConfig/IOConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQContext.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Group/Group2.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
@@ -1168,7 +1168,7 @@ bool is_udq(const std::string& keyword) {
void eval_udq(const Schedule& schedule, std::size_t sim_step, SummaryState& st)
{
const UDQInput& udq = schedule.getUDQConfig(sim_step);
const UDQConfig& udq = schedule.getUDQConfig(sim_step);
const auto& func_table = udq.function_table();
UDQContext context(udq.params(), func_table, st);
std::vector<std::string> wells;

View File

@@ -48,7 +48,8 @@
#include <opm/parser/eclipse/EclipseState/Schedule/OilVaporizationProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/TimeMap.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp>
@@ -117,7 +118,8 @@ namespace {
m_runspec( runspec ),
wtest_config(this->m_timeMap, std::make_shared<WellTestConfig>() ),
wlist_manager( this->m_timeMap, std::make_shared<WListManager>()),
udq_config(this->m_timeMap, std::make_shared<UDQInput>(deck)),
udq_config(this->m_timeMap, std::make_shared<UDQConfig>(deck)),
udq_active(this->m_timeMap, std::make_shared<UDQActive>()),
global_whistctl_mode(this->m_timeMap, WellProducer::CMODE_UNDEFINED),
rft_config(this->m_timeMap)
{
@@ -772,12 +774,11 @@ namespace {
bool switching_from_injector = !well2->isProducer();
auto properties = std::make_shared<WellProductionProperties>(well2->getProductionProperties());
bool update_well = switching_from_injector;
properties->clearControls();
if (well2->isAvailableForGroupControl())
properties->addProductionControl(WellProducer::GRUP);
properties->handleWCONPROD(record);
properties->handleWCONPROD(well_name, record);
if (switching_from_injector)
properties->resetDefaultBHPLimit();
@@ -796,6 +797,10 @@ namespace {
this->addWellEvent( well2->name(), ScheduleEvents::PRODUCTION_UPDATE, currentStep);
this->updateWell(well2, currentStep);
}
auto udq = std::make_shared<UDQActive>(this->udqActive(currentStep));
if (properties->updateUDQActive(this->getUDQConfig(currentStep), *udq))
this->updateUDQActive(currentStep, udq);
}
}
}
@@ -900,6 +905,10 @@ namespace {
}
}
}
auto udq = std::make_shared<UDQActive>(this->udqActive(currentStep));
if (injection->updateUDQActive(this->getUDQConfig(currentStep), *udq))
this->updateUDQActive(currentStep, udq);
}
}
}
@@ -1126,7 +1135,7 @@ namespace {
void Schedule::handleUDQ(const DeckKeyword& keyword, size_t currentStep) {
const auto& current = *this->udq_config.get(currentStep);
std::shared_ptr<UDQInput> new_udq = std::make_shared<UDQInput>(current);
std::shared_ptr<UDQConfig> new_udq = std::make_shared<UDQConfig>(current);
for (const auto& record : keyword)
new_udq->add_record(record);
@@ -1478,7 +1487,6 @@ namespace {
auto water_target = record.getItem("WATER_TARGET").get<UDAValue>(0);
auto liquid_target = record.getItem("LIQUID_TARGET").get<UDAValue>(0);
auto resv_target = record.getItem("RESERVOIR_FLUID_TARGET").getSIDouble(0);
{
auto group_ptr = std::make_shared<Group2>(this->getGroup2(group_name, currentStep));
Group2::GroupProductionProperties production;
@@ -2444,6 +2452,13 @@ void Schedule::handleGRUPTREE( const DeckKeyword& keyword, size_t currentStep, c
return tables;
}
const UDQActive& Schedule::udqActive(size_t timeStep) const {
return *this->udq_active[timeStep];
}
void Schedule::updateUDQActive( size_t timeStep, std::shared_ptr<UDQActive> udq ) {
this->udq_active.update(timeStep, udq);
}
const WellTestConfig& Schedule::wtestConfig(size_t timeStep) const {
const auto& ptr = this->wtest_config.get(timeStep);
@@ -2455,7 +2470,7 @@ void Schedule::handleGRUPTREE( const DeckKeyword& keyword, size_t currentStep, c
return *ptr;
}
const UDQInput& Schedule::getUDQConfig(size_t timeStep) const {
const UDQConfig& Schedule::getUDQConfig(size_t timeStep) const {
const auto& ptr = this->udq_config.get(timeStep);
return *ptr;
}

View File

@@ -0,0 +1,178 @@
/*
Copyright 2019 Equinor 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 <opm/parser/eclipse/Deck/UDAValue.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
#include <iostream>
namespace Opm {
std::size_t UDQActive::IUAD_size() const {
const auto& output = this->get_iuad();
return output.size();
}
std::size_t UDQActive::IUAP_size() const {
const auto& output = this->get_iuap();
return output.size();
}
UDQActive::operator bool() const {
return this->input_data.size() > 0;
}
std::string UDQActive::udq_hash(const std::string& udq, UDAControl control) {
return udq + std::to_string(static_cast<int64_t>(control));
}
std::string UDQActive::wg_hash(const std::string& wgname, UDAControl control) {
return wgname + std::to_string(static_cast<int64_t>(control));
}
/*
We go through the current list of input records and compare with the supplied
arguments (uda, wgnamem, control). There are six possible outcomes:
1. The uda variable is a double and no uda usage has been registered so far:
fast return.
2. The uda variable is a double, and the (wgname,control) combination is
found in the input data; this implies that uda has been used previously
for this particular (wgname, control) combination: We remove that record
from the input_data.
3. The uda variable is a string and we find that particular (udq, wgname,
control) combination in the input data: No changes
4. The uda variable is a string; but another udq was used for this (wgname,
control) combination: We erase the previous entry and add a new entry.
5. The uda ariable is a string and we do not find this (wgname, control)
combination in the previous records: We add a new record.
6. The uda variable is a double, and the (wgname, control) combination has
not been encountered before: return 0
*/
int UDQActive::update(const UDQConfig& udq_config, const UDAValue& uda, const std::string& wgname, UDAControl control) {
// Alternative 1
if (uda.is<double>() && this->input_data.empty())
return 0;
for (auto iter = this->input_data.begin(); iter != this->input_data.end(); ++iter) {
auto& record = *iter;
if ((record.wgname == wgname) && (record.control == control)) {
if (uda.is<double>()) {
// Alternative 2
iter = this->input_data.erase(iter);
this->output_data.clear();
return 1;
} else {
const std::string& udq = uda.get<std::string>();
if (record.udq == udq)
// Alternative 3
return 0;
else {
// Alternative 4
iter = this->input_data.erase(iter);
this->output_data.clear();
break;
}
}
}
}
// Alternative 4 & 5
if (uda.is<std::string>()) {
const std::string& udq = uda.get<std::string>();
const auto& udq_input = udq_config[udq];
auto udq_index = udq_input.index.insert_index;
this->input_data.emplace_back( udq_index, udq, wgname, control );
this->output_data.clear();
return 1;
}
// Alternative 6
return 0;
}
const std::vector<UDQActive::Record>& UDQActive::get_iuad() const {
if (this->output_data.empty()) {
for (const auto& input_record : this->input_data) {
const auto& udq = input_record.udq;
const auto& control = input_record.control;
bool found = false;
for (auto& output_record : this->output_data) {
if ((output_record.udq == udq) && (output_record.control == control)) {
output_record.use_count += 1;
found = true;
break;
}
}
if (!found)
this->output_data.emplace_back(input_record.udq, input_record.input_index, 0, input_record.wgname, input_record.control);
}
if (!output_data.empty()) {
for (std::size_t index = 1; index < output_data.size(); index++) {
const auto& prev_record = this->output_data[index - 1];
this->output_data[index].use_index = prev_record.use_index + prev_record.use_count;
}
}
}
return this->output_data;
}
std::vector<UDQActive::InputRecord> UDQActive::get_iuap() const {
std::vector<UDQActive::InputRecord> iuap_data;
auto input_rcpy = this->input_data;
while (!input_rcpy.empty()) {
//store next active control (new control)
auto inp_rec = input_rcpy.begin();
auto cur_rec = *inp_rec;
iuap_data.push_back(*inp_rec);
auto it = input_rcpy.erase(input_rcpy.begin());
//find and store active controls with same control and udq
//auto it = input_rcpy.begin();
while (it != input_rcpy.end()) {
if ((it->control == cur_rec.control) && (it->udq == cur_rec.udq)) {
iuap_data.push_back(*it);
it = input_rcpy.erase(it);
}
else {
it++;
}
}
}
return iuap_data;
}
UDQActive::Record UDQActive::operator[](std::size_t index) const {
const auto& output_record = this->get_iuad()[index];
return output_record;
}
}

View File

@@ -0,0 +1,260 @@
/*
Copyright 2018 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 <algorithm>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp>
namespace Opm {
namespace {
std::string strip_quotes(const std::string& s) {
if (s[0] == '\'')
return s.substr(1, s.size() - 2);
else
return s;
}
}
UDQConfig::UDQConfig(const UDQParams& params) :
udq_params(params),
udqft(this->udq_params)
{}
UDQConfig::UDQConfig(const Deck& deck) :
udq_params(deck),
udqft(this->udq_params)
{}
const UDQParams& UDQConfig::params() const {
return this->udq_params;
}
void UDQConfig::add_node( const std::string& quantity, UDQAction action) {
auto index_iter = this->input_index.find(quantity);
if (this->input_index.find(quantity) == this->input_index.end()) {
auto var_type = UDQ::varType(quantity);
auto insert_index = this->input_index.size();
this->type_count[var_type] += 1;
this->input_index[quantity] = UDQIndex(insert_index, this->type_count[var_type], action);
} else
index_iter->second.action = action;
}
void UDQConfig::add_assign(const std::string& quantity, const std::vector<std::string>& selector, double value) {
this->add_node(quantity, UDQAction::ASSIGN);
auto assignment = this->m_assignments.find(quantity);
if (assignment == this->m_assignments.end())
this->m_assignments.insert( std::make_pair(quantity, UDQAssign(quantity, selector, value )));
else
assignment->second.add_record(selector, value);
}
void UDQConfig::add_define(const std::string& quantity, const std::vector<std::string>& expression) {
this->add_node(quantity, UDQAction::DEFINE);
auto defined_iter = this->m_definitions.find( quantity );
if (defined_iter != this->m_definitions.end())
this->m_definitions.erase( defined_iter );
this->m_definitions.insert( std::make_pair(quantity, UDQDefine(this->udq_params, quantity, expression)));
}
void UDQConfig::add_unit(const std::string& keyword, const std::string& quoted_unit) {
const std::string unit = strip_quotes(quoted_unit);
const auto pair_ptr = this->units.find(keyword);
if (pair_ptr != this->units.end()) {
if (pair_ptr->second != unit)
throw std::invalid_argument("Illegal to change unit of UDQ keyword runtime");
return;
}
this->units[keyword] = unit;
}
void UDQConfig::add_record(const DeckRecord& record) {
auto action = UDQ::actionType(record.getItem("ACTION").get<std::string>(0));
const auto& quantity = record.getItem("QUANTITY").get<std::string>(0);
const auto& data = record.getItem("DATA").getData<std::string>();
if (action == UDQAction::UPDATE)
throw std::invalid_argument("The UDQ action UPDATE is not yet implemented in opm/flow");
if (action == UDQAction::UNITS)
this->add_unit( quantity, data[0] );
else {
if (action == UDQAction::ASSIGN) {
std::vector<std::string> selector(data.begin(), data.end() - 1);
double value = std::stod(data.back());
this->add_assign(quantity, selector, value);
} else if (action == UDQAction::DEFINE)
this->add_define(quantity, data);
else
throw std::runtime_error("Internal error - should not be here");
}
}
std::vector<UDQDefine> UDQConfig::definitions() const {
std::vector<UDQDefine> ret;
for (const auto& index_pair : this->input_index) {
if (index_pair.second.action == UDQAction::DEFINE) {
const std::string& key = index_pair.first;
ret.push_back(this->m_definitions.at(key));
}
}
return ret;
}
std::vector<UDQDefine> UDQConfig::definitions(UDQVarType var_type) const {
std::vector<UDQDefine> filtered_defines;
for (const auto& index_pair : this->input_index) {
if (index_pair.second.action == UDQAction::DEFINE) {
const std::string& key = index_pair.first;
const auto& udq_define = this->m_definitions.at(key);
if (udq_define.var_type() == var_type)
filtered_defines.push_back(udq_define);
}
}
return filtered_defines;
}
std::vector<UDQInput> UDQConfig::input() const {
std::vector<UDQInput> res;
for (const auto& index_pair : this->input_index) {
const UDQIndex& index = index_pair.second;
std::string u;
if (this->has_unit(index_pair.first))
u = this->unit(index_pair.first);
if (index.action == UDQAction::DEFINE) {
const std::string& key = index_pair.first;
res.push_back(UDQInput(index, this->m_definitions.at(key), u));
} else if (index_pair.second.action == UDQAction::ASSIGN) {
const std::string& key = index_pair.first;
res.push_back(UDQInput(index, this->m_assignments.at(key), u));
}
}
return res;
}
std::size_t UDQConfig::size() const {
std::size_t s = 0;
for (const auto& index_pair : this->input_index) {
if (index_pair.second.action == UDQAction::DEFINE)
s += 1;
else if (index_pair.second.action == UDQAction::ASSIGN)
s += 1;
}
return s;
}
std::vector<UDQAssign> UDQConfig::assignments() const {
std::vector<UDQAssign> ret;
for (const auto& index_pair : this->input_index) {
if (index_pair.second.action == UDQAction::ASSIGN) {
const std::string& key = index_pair.first;
ret.push_back(this->m_assignments.at(key));
}
}
return ret;
}
std::vector<UDQAssign> UDQConfig::assignments(UDQVarType var_type) const {
std::vector<UDQAssign> filtered_defines;
for (const auto& index_pair : this->input_index) {
if (index_pair.second.action == UDQAction::ASSIGN) {
const std::string& key = index_pair.first;
const auto& udq_define = this->m_assignments.at(key);
if (udq_define.var_type() == var_type)
filtered_defines.push_back(udq_define);
}
}
return filtered_defines;
}
const std::string& UDQConfig::unit(const std::string& key) const {
const auto pair_ptr = this->units.find(key);
if (pair_ptr == this->units.end())
throw std::invalid_argument("No such UDQ quantity: " + key);
return pair_ptr->second;
}
bool UDQConfig::has_unit(const std::string& keyword) const {
return (this->units.count(keyword) > 0);
}
bool UDQConfig::has_keyword(const std::string& keyword) const {
if (this->m_assignments.count(keyword) > 0)
return true;
if (this->m_definitions.count(keyword) > 0)
return true;
/*
That a keyword is mentioned with UNITS is enough to consider it
as a keyword which is present.
*/
if (this->units.count(keyword) > 0)
return true;
return false;
}
const UDQInput UDQConfig::operator[](const std::string& keyword) const {
const auto index_iter = this->input_index.find(keyword);
if (index_iter == this->input_index.end())
throw std::invalid_argument("Keyword: " + keyword + " not recognized as ASSIGN/DEFINE UDQ");
std::string u;
if (this->has_unit(keyword))
u = this->unit(keyword);
if (index_iter->second.action == UDQAction::ASSIGN)
return UDQInput(this->input_index.at(keyword), this->m_assignments.at(keyword), u);
if (index_iter->second.action == UDQAction::DEFINE)
return UDQInput(this->input_index.at(keyword), this->m_definitions.at(keyword), u);
throw std::logic_error("Internal error - should not be here");
}
const UDQFunctionTable& UDQConfig::function_table() const {
return this->udqft;
}
}

View File

@@ -19,7 +19,7 @@
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <set>
#include <stdexcept>
@@ -268,6 +268,53 @@ std::string typeName(UDQVarType var_type) {
}
}
UDAKeyword keyword(UDAControl control) {
const std::map<UDAControl, UDAKeyword> c2k = {{UDAControl::WCONPROD_ORAT, UDAKeyword::WCONPROD},
{UDAControl::WCONPROD_GRAT, UDAKeyword::WCONPROD},
{UDAControl::WCONPROD_WRAT, UDAKeyword::WCONPROD},
{UDAControl::WCONPROD_LRAT, UDAKeyword::WCONPROD},
{UDAControl::WCONPROD_RESV, UDAKeyword::WCONPROD},
{UDAControl::WCONPROD_BHP, UDAKeyword::WCONPROD},
{UDAControl::WCONPROD_THP, UDAKeyword::WCONPROD},
{UDAControl::WCONINJE_RATE, UDAKeyword::WCONINJE},
{UDAControl::WCONINJE_RESV, UDAKeyword::WCONINJE},
{UDAControl::WCONINJE_BHP, UDAKeyword::WCONINJE},
{UDAControl::WCONINJE_THP, UDAKeyword::WCONINJE},
{UDAControl::GCONPROD_OIL_TARGET, UDAKeyword::GCONPROD},
{UDAControl::GCONPROD_WATER_TARGET, UDAKeyword::GCONPROD},
{UDAControl::GCONPROD_GAS_TARGET, UDAKeyword::GCONPROD},
{UDAControl::GCONPROD_LIQUID_TARGET, UDAKeyword::GCONPROD}};
auto it = c2k.find(control);
if (it != c2k.end())
return it->second;
throw std::logic_error("Unrecognized enum type - internal error");
}
int uadCode(UDAControl control) {
const std::map<UDAControl, int> c2uad = {{UDAControl::WCONPROD_ORAT, 300004},
{UDAControl::WCONPROD_GRAT, 500004},
{UDAControl::WCONPROD_WRAT, 400004},
{UDAControl::WCONPROD_LRAT, 600004},
{UDAControl::WCONPROD_RESV, 999999},
{UDAControl::WCONPROD_BHP, 999999},
{UDAControl::WCONPROD_THP, 999999},
{UDAControl::WCONINJE_RATE, 400003},
{UDAControl::WCONINJE_RESV, 500003},
{UDAControl::WCONINJE_BHP, 999999},
{UDAControl::WCONINJE_THP, 999999},
{UDAControl::GCONPROD_OIL_TARGET, 200019},
{UDAControl::GCONPROD_WATER_TARGET, 300019},
{UDAControl::GCONPROD_GAS_TARGET, 400019},
{UDAControl::GCONPROD_LIQUID_TARGET, 500019}};
auto it = c2uad.find(control);
if (it != c2uad.end())
return it->second;
throw std::logic_error("Unrecognized enum type - internal error");
}
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2018 Statoil ASA.
Copyright 2019 Equinor ASA.
This file is part of the Open Porous Media project (OPM).
@@ -15,180 +15,78 @@
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#include <algorithm>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQAssign.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
namespace Opm {
namespace {
std::string strip_quotes(const std::string& s) {
if (s[0] == '\'')
return s.substr(1, s.size() - 2);
else
return s;
}
}
UDQInput::UDQInput(const Deck& deck) :
udq_params(deck),
udqft(this->udq_params)
{
}
const UDQParams& UDQInput::params() const {
return this->udq_params;
}
void UDQInput::add_record(const DeckRecord& record) {
auto action = UDQ::actionType(record.getItem("ACTION").get<std::string>(0));
const auto& quantity = record.getItem("QUANTITY").get<std::string>(0);
const auto& data = record.getItem("DATA").getData<std::string>();
if (action == UDQAction::UPDATE)
throw std::invalid_argument("The UDQ action UPDATE is not yet implemented in opm/flow");
if (action == UDQAction::UNITS)
this->assign_unit( quantity, data[0] );
else {
auto index_iter = this->input_index.find(quantity);
if (this->input_index.find(quantity) == this->input_index.end())
this->input_index[quantity] = std::make_pair(this->input_index.size(), action);
else
index_iter->second.second = action;
UDQInput::UDQInput(const UDQIndex& index_arg, const UDQDefine& udq_define, const std::string& unit_arg) :
index(index_arg),
define(std::addressof(udq_define)),
assign(nullptr),
m_keyword(udq_define.keyword()),
m_var_type(udq_define.var_type()),
m_unit(unit_arg)
{}
if (action == UDQAction::ASSIGN) {
std::vector<std::string> selector(data.begin(), data.end() - 1);
double value = std::stod(data.back());
auto assignment = this->m_assignments.find(quantity);
if (assignment == this->m_assignments.end())
this->m_assignments.insert( std::make_pair(quantity, UDQAssign(quantity, selector, value )));
else
assignment->second.add_record(selector, value);
} else if (action == UDQAction::DEFINE)
this->m_definitions.insert( std::make_pair(quantity, UDQDefine(this->udq_params, quantity, data)));
else
throw std::runtime_error("Internal error - should not be here");
}
}
UDQInput::UDQInput(const UDQIndex& index_arg, const UDQAssign& udq_assign, const std::string& unit_arg):
index(index_arg),
define(nullptr),
assign(std::addressof(udq_assign)),
m_keyword(udq_assign.keyword()),
m_var_type(udq_assign.var_type()),
m_unit(unit_arg)
{}
std::vector<UDQDefine> UDQInput::definitions() const {
std::vector<UDQDefine> ret;
for (const auto& index_pair : this->input_index) {
if (index_pair.second.second == UDQAction::DEFINE) {
const std::string& key = index_pair.first;
ret.push_back(this->m_definitions.at(key));
}
}
return ret;
}
std::vector<UDQDefine> UDQInput::definitions(UDQVarType var_type) const {
std::vector<UDQDefine> filtered_defines;
for (const auto& index_pair : this->input_index) {
if (index_pair.second.second == UDQAction::DEFINE) {
const std::string& key = index_pair.first;
const auto& udq_define = this->m_definitions.at(key);
if (udq_define.var_type() == var_type)
filtered_defines.push_back(udq_define);
}
}
return filtered_defines;
}
std::vector<std::pair<size_t, UDQDefine>> UDQInput::input_definitions() const {
std::vector<std::pair<size_t, UDQDefine>> res;
for (const auto& index_pair : this->input_index) {
if (index_pair.second.second == UDQAction::DEFINE) {
const std::string& key = index_pair.first;
res.emplace_back(index_pair.second.first, this->m_definitions.at(key));
}
}
return res;
}
std::vector<UDQAssign> UDQInput::assignments() const {
std::vector<UDQAssign> ret;
for (const auto& index_pair : this->input_index) {
if (index_pair.second.second == UDQAction::ASSIGN) {
const std::string& key = index_pair.first;
ret.push_back(this->m_assignments.at(key));
}
}
return ret;
}
std::vector<UDQAssign> UDQInput::assignments(UDQVarType var_type) const {
std::vector<UDQAssign> filtered_defines;
for (const auto& index_pair : this->input_index) {
if (index_pair.second.second == UDQAction::ASSIGN) {
const std::string& key = index_pair.first;
const auto& udq_define = this->m_assignments.at(key);
if (udq_define.var_type() == var_type)
filtered_defines.push_back(udq_define);
}
}
return filtered_defines;
}
const std::string& UDQInput::unit(const std::string& key) const {
const auto pair_ptr = this->units.find(key);
if (pair_ptr == this->units.end())
throw std::invalid_argument("No such UDQ quantity: " + key);
return pair_ptr->second;
}
void UDQInput::assign_unit(const std::string& keyword, const std::string& quoted_unit) {
const std::string unit = strip_quotes(quoted_unit);
const auto pair_ptr = this->units.find(keyword);
if (pair_ptr != this->units.end()) {
if (pair_ptr->second != unit)
throw std::invalid_argument("Illegal to change unit of UDQ keyword runtime");
return;
}
this->units[keyword] = unit;
}
bool UDQInput::has_unit(const std::string& keyword) const {
return (this->units.count(keyword) > 0);
}
bool UDQInput::has_keyword(const std::string& keyword) const {
if (this->m_assignments.count(keyword) > 0)
return true;
if (this->m_definitions.count(keyword) > 0)
return true;
/*
That a keyword is mentioned with UNITS is enough to consider it
as a keyword which is present.
*/
if (this->units.count(keyword) > 0)
return true;
return false;
}
const UDQFunctionTable& UDQInput::function_table() const {
return this->udqft;
}
const std::string& UDQInput::unit() const {
return this->m_unit;
}
const std::string& UDQInput::keyword() const {
return this->m_keyword;
}
template<>
bool UDQInput::is<UDQAssign>() const {
if (this->assign)
return true;
return false;
}
template<>
bool UDQInput::is<UDQDefine>() const {
if (this->define)
return true;
return false;
}
template<>
const UDQAssign& UDQInput::get<UDQAssign>() const {
if (this->assign)
return *this->assign;
throw std::runtime_error("Invalid get");
}
template<>
const UDQDefine& UDQInput::get<UDQDefine>() const {
if (this->define)
return *this->define;
throw std::runtime_error("Invalid get");
}
}

View File

@@ -88,6 +88,9 @@ namespace Opm {
this->m_true_rng.seed( seed );
}
int UDQParams::rand_seed() const noexcept {
return this->random_seed;
}
double UDQParams::range() const noexcept {
return this->value_range;

View File

@@ -22,6 +22,7 @@
#include <opm/parser/eclipse/Parser/ParserKeywords/W.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/updatingConnectionsWithSegments.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/Well2.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp>
@@ -780,6 +781,4 @@ double Well2::temperature() const {
throw std::runtime_error("Can not ask for temperature in a producer");
}
}

View File

@@ -25,6 +25,7 @@
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/Parser/ParserKeywords/S.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp>
#include "injection.hpp"
@@ -261,4 +262,16 @@ namespace Opm {
return controls;
}
bool WellInjectionProperties::updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const {
int update_count = 0;
update_count += active.update(udq_config, this->surfaceInjectionRate, this->name, UDAControl::WCONINJE_RATE);
update_count += active.update(udq_config, this->reservoirInjectionRate, this->name, UDAControl::WCONINJE_RESV);
update_count += active.update(udq_config, this->BHPLimit, this->name, UDAControl::WCONINJE_BHP);
update_count += active.update(udq_config, this->THPLimit, this->name, UDAControl::WCONINJE_THP);
return (update_count > 0);
}
}

View File

@@ -25,6 +25,7 @@
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
#include <opm/parser/eclipse/Units/Units.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp>
@@ -102,7 +103,7 @@ namespace Opm {
void WellProductionProperties::handleWCONPROD( const DeckRecord& record )
void WellProductionProperties::handleWCONPROD( const std::string& /* well */, const DeckRecord& record)
{
this->predictionMode = true;
@@ -297,5 +298,19 @@ namespace Opm {
return controls;
}
bool WellProductionProperties::updateUDQActive(const UDQConfig& udq_config, UDQActive& active) const {
int update_count = 0;
update_count += active.update(udq_config, this->OilRate, this->name, UDAControl::WCONPROD_ORAT);
update_count += active.update(udq_config, this->WaterRate, this->name, UDAControl::WCONPROD_WRAT);
update_count += active.update(udq_config, this->GasRate, this->name, UDAControl::WCONPROD_GRAT);
update_count += active.update(udq_config, this->LiquidRate, this->name, UDAControl::WCONPROD_LRAT);
update_count += active.update(udq_config, this->ResVRate, this->name, UDAControl::WCONPROD_RESV);
update_count += active.update(udq_config, this->BHPLimit, this->name, UDAControl::WCONPROD_BHP);
update_count += active.update(udq_config, this->THPLimit, this->name, UDAControl::WCONPROD_THP);
return (update_count > 0);
}
} // namespace Opm

View File

@@ -34,8 +34,8 @@
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/GridDims.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Group/Group2.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/TimeMap.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/Connection.hpp>

View File

@@ -0,0 +1,383 @@
RUNSPEC
TITLE
2 PRODUCERS AND INJECTORS, 2 WELL GROUPS AND ONE INTERMEDIATE GROUP LEVEL BELOW THE FIELD LEVEL
DIMENS
10 5 10 /
OIL
WATER
GAS
DISGAS
FIELD
TABDIMS
1 1 15 15 2 15 /
EQLDIMS
2 /
WELLDIMS
4 20 4 2 /
UNIFIN
UNIFOUT
FMTIN
FMTOUT
-- 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 /
START
1 'JAN' 2015 /
-- RPTRUNSP
GRID =========================================================
--NOGGF
BOX
1 10 1 5 1 1 /
TOPS
50*7000 /
BOX
1 10 1 5 1 10 /
DXV
10*100 /
DYV
5*100 /
DZV
2*20 100 7*20 /
EQUALS
-- 'DX' 100 /
-- 'DY' 100 /
'PERMX' 50 /
'PERMZ' 5 /
-- 'DZ' 20 /
'PORO' 0.2 /
-- 'TOPS' 7000 1 10 1 5 1 1 /
--'DZ' 100 1 10 1 5 3 3 /
'PORO' 0.0 1 10 1 5 3 3 /
/
COPY
PERMX PERMY /
/
RPTGRID
-- Report Levels for Grid Section Data
--
/
PROPS ==========================================================
-- WATER RELATIVE PERMEABILITY AND CAPILLARY PRESSURE ARE TABULATED AS
-- A FUNCTION OF WATER SATURATION.
--
-- SWAT KRW PCOW
SWFN
0.12 0 0
1.0 0.00001 0 /
-- SIMILARLY FOR GAS
--
-- SGAS KRG PCOG
SGFN
0 0 0
0.02 0 0
0.05 0.005 0
0.12 0.025 0
0.2 0.075 0
0.25 0.125 0
0.3 0.19 0
0.4 0.41 0
0.45 0.6 0
0.5 0.72 0
0.6 0.87 0
0.7 0.94 0
0.85 0.98 0
1.0 1.0 0
/
-- OIL RELATIVE PERMEABILITY IS TABULATED AGAINST OIL SATURATION
-- FOR OIL-WATER AND OIL-GAS-CONNATE WATER CASES
--
-- SOIL KROW KROG
SOF3
0 0 0
0.18 0 0
0.28 0.0001 0.0001
0.38 0.001 0.001
0.43 0.01 0.01
0.48 0.021 0.021
0.58 0.09 0.09
0.63 0.2 0.2
0.68 0.35 0.35
0.76 0.7 0.7
0.83 0.98 0.98
0.86 0.997 0.997
0.879 1 1
0.88 1 1 /
-- PVT PROPERTIES OF WATER
--
-- REF. PRES. REF. FVF COMPRESSIBILITY REF VISCOSITY VISCOSIBILITY
PVTW
4014.7 1.029 3.13D-6 0.31 0 /
-- ROCK COMPRESSIBILITY
--
-- REF. PRES COMPRESSIBILITY
ROCK
14.7 3.0D-6 /
-- SURFACE DENSITIES OF RESERVOIR FLUIDS
--
-- OIL WATER GAS
DENSITY
49.1 64.79 0.06054 /
-- PVT PROPERTIES OF DRY GAS (NO VAPOURISED OIL)
-- WE WOULD USE PVTG TO SPECIFY THE PROPERTIES OF WET GAS
--
-- PGAS BGAS VISGAS
PVDG
14.7 166.666 0.008
264.7 12.093 0.0096
514.7 6.274 0.0112
1014.7 3.197 0.014
2014.7 1.614 0.0189
2514.7 1.294 0.0208
3014.7 1.080 0.0228
4014.7 0.811 0.0268
5014.7 0.649 0.0309
9014.7 0.386 0.047 /
-- PVT PROPERTIES OF LIVE OIL (WITH DISSOLVED GAS)
-- WE WOULD USE PVDO TO SPECIFY THE PROPERTIES OF DEAD OIL
--
-- FOR EACH VALUE OF RS THE SATURATION PRESSURE, FVF AND VISCOSITY
-- ARE SPECIFIED. FOR RS=1.27 AND 1.618, THE FVF AND VISCOSITY OF
-- UNDERSATURATED OIL ARE DEFINED AS A FUNCTION OF PRESSURE. DATA
-- FOR UNDERSATURATED OIL MAY BE SUPPLIED FOR ANY RS, BUT MUST BE
-- SUPPLIED FOR THE HIGHEST RS (1.618).
--
-- RS POIL FVFO VISO
PVTO
0.001 14.7 1.062 1.04 /
0.0905 264.7 1.15 0.975 /
0.18 514.7 1.207 0.91 /
0.371 1014.7 1.295 0.83 /
0.636 2014.7 1.435 0.695 /
0.775 2514.7 1.5 0.641 /
0.93 3014.7 1.565 0.594 /
1.270 4014.7 1.695 0.51
5014.7 1.671 0.549
9014.7 1.579 0.74 /
1.618 5014.7 1.827 0.449
9014.7 1.726 0.605 /
/
RPTPROPS
-- PROPS Reporting Options
--
/
REGIONS ===========================================================
FIPNUM
100*1
400*2
/
EQLNUM
100*1
400*2
/
RPTREGS
/
SOLUTION ============================================================
EQUIL
7020.00 2700.00 7990.00 .00000 7020.00 .00000 0 0 5 /
7200.00 3700.00 7300.00 .00000 7000.00 .00000 1 0 5 /
RSVD 2 TABLES 3 NODES IN EACH FIELD 12:00 17 AUG 83
7000.0 1.0000
7990.0 1.0000
/
7000.0 1.0000
7400.0 1.0000
/
RPTRST
-- Restart File Output Control
--
'BASIC=2' 'FLOWS' 'POT' 'PRES' /
SUMMARY ===========================================================
FOPR
WOPR
/
FGPR
FWPR
FWIR
FWCT
FGOR
--RUNSUM
ALL
MSUMLINS
MSUMNEWT
SEPARATE
SCHEDULE ===========================================================
DEBUG
1 3 /
DRSDT
1.0E20 /
RPTSCHED
'PRES' 'SWAT' 'SGAS' 'RESTART=1' 'RS' 'WELLS=2' 'SUMMARY=2'
'CPU=2' 'WELSPECS' 'NEWTON=2' /
NOECHO
ECHO
GRUPTREE
'GRP1' 'FIELD' /
'WGRP1' 'GRP1' /
'WGRP2' 'GRP1' /
/
WELSPECS
'PROD1' 'WGRP1' 1 5 7030 'OIL' 0.0 'STD' 'STOP' /
'PROD2' 'WGRP2' 1 5 7030 'OIL' 0.0 'STD' 'STOP' /
'WINJ1' 'WGRP1' 10 1 7030 'WAT' 0.0 'STD' 'STOP' /
'WINJ2' 'WGRP2' 10 1 7030 'WAT' 0.0 'STD' 'STOP' /
/
COMPDAT
'PROD1' 1 5 2 2 3* 0.2 3* 'X' /
'PROD1' 2 5 2 2 3* 0.2 3* 'X' /
'PROD1' 3 5 2 2 3* 0.2 3* 'X' /
'PROD2' 4 5 2 2 3* 0.2 3* 'X' /
'PROD2' 5 5 2 2 3* 0.2 3* 'X' /
'WINJ1' 10 1 9 9 3* 0.2 3* 'X' /
'WINJ1' 9 1 9 9 3* 0.2 3* 'X' /
'WINJ1' 8 1 9 9 3* 0.2 3* 'X' /
'WINJ2' 7 1 9 9 3* 0.2 3* 'X' /
'WINJ2' 6 1 9 9 3* 0.2 3* 'X' /
/
UDQ
-- test
--oil & liquid capacities at GEFAC = 0.8995
DEFINE WUOPRL (WOPR PROD1 - 150) * 0.90 /
DEFINE WULPRL (WLPR PROD1 - 200) * 0.90 /
DEFINE WUOPRU (WOPR PROD2 - 250) * 0.80 /
DEFINE GUOPRU (GOPR WGRP2 - 449) * 0.77 /
DEFINE WULPRU (WLPR PROD2 - 300) * 0.80 /
ASSIGN WULPRL 400. /
DEFINE FULPR (FLPR - 543) * 0.65 /
DEFINE WUOPRL (WOPR PROD1 - 170) * 0.60 /
-- units
UNITS WUOPRL SM3/DAY /
UNITS WULPRL SM3/DAY /
UNITS GUOPRU SM3/DAY /
UNITS WUOPRU SM3/DAY /
UNITS WULPRU SM3/DAY /
UNITS FULPR SM3/DAY /
--
/
-- Well production rate targets/limits:
-- testing UDQs as production constrains
WCONPROD
-- name status ctrl qo qw qg ql qr bhp thp vfp alq
'PROD1' 'OPEN' 'GRUP' WUOPRU 1* 1* WULPRU 1* 60.0 / single wells
/
WCONPROD
-- name status ctrl qo qw qg ql qr bhp thp vfp alq
'PROD2' 'OPEN' 'GRUP' WUOPRU 1* 1* WULPRU 1* 60.0 / single wells
/
WCONINJE
'WINJ1' 'WAT' 'OPEN' 'BHP' 1* 1200 3500 1* /
'WINJ2' 'WAT' 'OPEN' 'BHP' 1* 800 3500 1* /
/
TUNING
/
/
/
TSTEP
4
/
END

View File

@@ -26,12 +26,13 @@ Copyright 2018 Statoil ASA.
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQSet.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQContext.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQAssign.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQFunction.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQFunctionTable.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
using namespace Opm;
@@ -1173,22 +1174,32 @@ UDQ
const auto& udq = schedule.getUDQConfig(0);
const auto& def_input = udq.input_definitions();
const auto& input = udq.input();
const auto& def = udq.definitions();
BOOST_CHECK_EQUAL(def_input.size(), 3);
for (std::size_t i = 0; i < def_input.size(); i++)
BOOST_CHECK_EQUAL(def[i].input_string(), def_input[i].second.input_string());
BOOST_CHECK_EQUAL(input.size(), 7);
BOOST_CHECK_EQUAL(udq.size(), 7);
BOOST_CHECK_EQUAL(def_input[0].first, 3);
BOOST_CHECK_EQUAL(def_input[1].first, 4);
BOOST_CHECK_EQUAL(def_input[2].first, 6);
BOOST_CHECK( input[0].is<UDQAssign>() );
BOOST_CHECK( input[1].is<UDQAssign>() );
BOOST_CHECK( input[2].is<UDQAssign>() );
BOOST_CHECK( input[3].is<UDQDefine>() );
BOOST_CHECK( input[4].is<UDQDefine>() );
BOOST_CHECK( input[5].is<UDQAssign>() );
BOOST_CHECK( input[6].is<UDQDefine>() );
BOOST_CHECK_EQUAL( input[4].unit(), "SM3/DAY" );
BOOST_CHECK_EQUAL(def[0].keyword(), "WUWCT");
BOOST_CHECK_EQUAL(def[1].keyword(), "FUOPR");
BOOST_CHECK_EQUAL(def[2].keyword(), "FUOPRX");
BOOST_CHECK_EQUAL( input[3].get<UDQDefine>().keyword(), "WUWCT");
BOOST_CHECK_EQUAL( input[4].get<UDQDefine>().keyword(), "FUOPR");
BOOST_CHECK_EQUAL( input[6].get<UDQDefine>().keyword(), "FUOPRX");
BOOST_CHECK( udq.has_keyword("FUXXX") );
const auto wubhp1 = udq["WUBHP1"];
BOOST_CHECK( wubhp1.is<UDQAssign>() );
}
@@ -1210,6 +1221,7 @@ UDQ
UDQ
DEFINE WUBHP1 SUM(WOPR) /
DEFINE FUOPR MAX(WOPR) /
/
)";
@@ -1217,14 +1229,221 @@ UDQ
const auto& udq = schedule.getUDQConfig(0);
const auto& def_input = udq.input_definitions();
const auto& input = udq.input();
const auto& def = udq.definitions();
BOOST_CHECK_EQUAL(def_input.size(), 3);
for (std::size_t i = 0; i < def_input.size(); i++)
BOOST_CHECK_EQUAL(def[i].input_string(), def_input[i].second.input_string());
BOOST_CHECK_EQUAL(input.size(), 5);
BOOST_CHECK_EQUAL(udq.size(), 5);
BOOST_CHECK_EQUAL(def_input[0].first, 0);
BOOST_CHECK_EQUAL(def_input[1].first, 3);
BOOST_CHECK_EQUAL(def_input[2].first, 4);
BOOST_CHECK( input[0].is<UDQDefine>());
BOOST_CHECK_EQUAL( input[0].keyword(), "WUBHP1");
const auto fuopr = udq["FUOPR"];
BOOST_CHECK( fuopr.is<UDQDefine>() );
const auto& def2 = fuopr.get<UDQDefine>();
BOOST_CHECK_EQUAL(def2.input_string(), "MAX(WOPR)");
}
BOOST_AUTO_TEST_CASE(UDQ_USAGE) {
UDQActive usage;
UDQParams params;
UDQConfig conf(params);
BOOST_CHECK_EQUAL( usage.IUAD_size(), 0 );
UDAValue uda1("WUX");
conf.add_assign(uda1.get<std::string>(), {}, 100);
usage.update(conf, uda1, "W1", UDAControl::WCONPROD_ORAT);
BOOST_CHECK_EQUAL( usage.IUAD_size(), 1 );
BOOST_CHECK_EQUAL( usage[0].use_count, 1);
usage.update(conf, uda1, "W1", UDAControl::WCONPROD_GRAT);
BOOST_CHECK_EQUAL( usage.IUAD_size(), 2 );
BOOST_CHECK_EQUAL( usage[1].use_count, 1);
const auto& rec = usage[0];
BOOST_CHECK_EQUAL(rec.wgname, "W1");
BOOST_CHECK_EQUAL(rec.udq, "WUX");
BOOST_CHECK(rec.control == UDAControl::WCONPROD_ORAT);
for (std::size_t index = 0; index < usage.IUAD_size(); index++) {
const auto& record = usage[index];
BOOST_CHECK_EQUAL(record.input_index, 0);
BOOST_CHECK_EQUAL(record.wgname, "W1");
if (index == 0)
BOOST_CHECK(record.control == UDAControl::WCONPROD_ORAT);
else
BOOST_CHECK(record.control == UDAControl::WCONPROD_GRAT);
index += 1;
}
}
BOOST_AUTO_TEST_CASE(IntegrationTest) {
#include "data/integration_tests/udq.data"
auto schedule = make_schedule(deck_string);
{
const auto& active = schedule.udqActive(1);
BOOST_CHECK_EQUAL(active.IUAD_size(), 4);
BOOST_CHECK(active[0].control == UDAControl::WCONPROD_ORAT);
BOOST_CHECK(active[1].control == UDAControl::WCONPROD_LRAT);
BOOST_CHECK(active[2].control == UDAControl::WCONPROD_ORAT);
BOOST_CHECK(active[3].control == UDAControl::WCONPROD_LRAT);
BOOST_CHECK(active[0].wgname == "OPL02");
BOOST_CHECK(active[1].wgname == "OPL02");
BOOST_CHECK(active[2].wgname == "OPU02");
BOOST_CHECK(active[3].wgname == "OPU02");
BOOST_CHECK(active[0].udq == "WUOPRL");
BOOST_CHECK(active[1].udq == "WULPRL");
BOOST_CHECK(active[2].udq == "WUOPRU");
BOOST_CHECK(active[3].udq == "WULPRU");
BOOST_CHECK(active[0].input_index == 0);
BOOST_CHECK(active[1].input_index == 1);
BOOST_CHECK(active[2].input_index == 2);
BOOST_CHECK(active[3].input_index == 3);
BOOST_CHECK(active[0].use_count == 1);
BOOST_CHECK(active[1].use_count == 1);
BOOST_CHECK(active[2].use_count == 1);
BOOST_CHECK(active[3].use_count == 1);
}
}
Schedule make_udq_schedule(const std::string& schedule_string) {
#include "data/integration_tests/udq2.data"
deck_string += schedule_string;
return make_schedule(deck_string);
}
BOOST_AUTO_TEST_CASE(IntegrationTest2) {
const std::string udq_string = R"(
UDQ
DEFINE WUOPRL (WOPR PROD1 - 150) * 0.90 /
DEFINE WULPRL (WLPR PROD1 - 200) * 0.90 /
DEFINE WUOPRU (WOPR PROD2 - 250) * 0.80 /
DEFINE WULPRU (WLPR PROD2 - 300) * 0.80 /
DEFINE WUOPRL (WOPR PROD1 - 170) * 0.60 /
DEFINE WUXO (WOPR PROD1 - 170) * 0.60 /
DEFINE WUXL (WOPR PROD1 - 170) * 0.60 /
-- units
UNITS WUOPRL SM3/DAY /
UNITS WULPRL SM3/DAY /
UNITS WUOPRU SM3/DAY /
UNITS WULPRU SM3/DAY /
/
WCONPROD
'PROD1' 'OPEN' 'GRUP' WUOPRU 1* 1* WULPRU 1* 60.0 / single wells
/
WCONPROD
'PROD2' 'OPEN' 'GRUP' WUOPRU 1* 1* WULPRU 1* 60.0 / single wells
/
WCONINJE
'WINJ1' 'WAT' 'OPEN' 'BHP' 1* 1200 3500 1* /
'WINJ2' 'WAT' 'OPEN' 'BHP' 1* 800 3500 1* /
/
TSTEP
5 /
WCONPROD
'PROD2' 'OPEN' 'GRUP' WUXO 1* 1* WUXL 1* 60.0 / single wells
/
TSTEP
5 /
WCONPROD
'PROD1' 'OPEN' 'GRUP' 100 1* 1* 100 1* 60.0 / single wells
/
)";
auto schedule = make_udq_schedule(udq_string);
// First timestep
{
const auto& udq_active = schedule.udqActive(0);
BOOST_CHECK(udq_active);
BOOST_CHECK_EQUAL(udq_active.IUAD_size(), 2);
const auto& record0 = udq_active[0];
BOOST_CHECK_EQUAL( record0.uad_code, 300004);
BOOST_CHECK_EQUAL( record0.input_index, 2);
BOOST_CHECK_EQUAL( record0.use_count, 2);
BOOST_CHECK_EQUAL( record0.use_index, 0);
const auto& record1 = udq_active[1];
BOOST_CHECK_EQUAL( record1.uad_code, 600004);
BOOST_CHECK_EQUAL( record1.input_index, 3);
BOOST_CHECK_EQUAL( record1.use_count, 2);
BOOST_CHECK_EQUAL( record1.use_index, 2);
}
{
// Second timestep
// - The WUOPRU and WULPRU udq are still used in the same manner for the PROD1 well.
// - The new UDQs WUXO and WUXL are now used for the PROD2 well.
const auto& udq_active = schedule.udqActive(1);
BOOST_CHECK(udq_active);
BOOST_CHECK_EQUAL(udq_active.IUAD_size(), 4);
const auto& record0 = udq_active[0];
BOOST_CHECK_EQUAL( record0.uad_code, 300004);
BOOST_CHECK_EQUAL( record0.input_index, 2);
BOOST_CHECK_EQUAL( record0.use_count, 1);
BOOST_CHECK_EQUAL( record0.use_index, 0);
const auto& record1 = udq_active[1];
BOOST_CHECK_EQUAL( record1.uad_code, 600004);
BOOST_CHECK_EQUAL( record1.input_index, 3);
BOOST_CHECK_EQUAL( record1.use_count, 1);
BOOST_CHECK_EQUAL( record1.use_index, 1);
const auto& record2 = udq_active[2];
BOOST_CHECK_EQUAL( record2.uad_code, 300004);
BOOST_CHECK_EQUAL( record2.input_index, 4);
BOOST_CHECK_EQUAL( record2.use_count, 1);
BOOST_CHECK_EQUAL( record2.use_index, 2);
const auto& record3 = udq_active[3];
BOOST_CHECK_EQUAL( record3.uad_code, 600004);
BOOST_CHECK_EQUAL( record3.input_index, 5);
BOOST_CHECK_EQUAL( record3.use_count, 1);
BOOST_CHECK_EQUAL( record3.use_index, 3);
}
{
// Third timestep
// - The new UDQs WUXO and WUXL are now used for the PROD2 well.
// - The PROD1 well does not use UDQ
const auto& udq_active = schedule.udqActive(2);
BOOST_CHECK(udq_active);
BOOST_CHECK_EQUAL(udq_active.IUAD_size(), 2);
const auto& record0 = udq_active[0];
BOOST_CHECK_EQUAL( record0.uad_code, 300004);
BOOST_CHECK_EQUAL( record0.input_index, 4);
BOOST_CHECK_EQUAL( record0.use_count, 1);
BOOST_CHECK_EQUAL( record0.use_index, 0);
const auto& record1 = udq_active[1];
BOOST_CHECK_EQUAL( record1.uad_code, 600004);
BOOST_CHECK_EQUAL( record1.input_index, 5);
BOOST_CHECK_EQUAL( record1.use_count, 1);
BOOST_CHECK_EQUAL( record1.use_index, 1);
}
}

View File

@@ -35,6 +35,7 @@
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/Connection.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellConnections.hpp>
@@ -545,7 +546,7 @@ namespace {
const auto& kwd = deck.getKeyword("WCONPROD");
const auto& record = kwd.getRecord(0);
Opm::WellProductionProperties pred("W");
pred.handleWCONPROD(record);
pred.handleWCONPROD("WELL", record);
return pred;
}

View File

@@ -0,0 +1,718 @@
const std::string deck_string = R"(
RUNSPEC
TITLE
'Generic' 'Reservoir'
NOECHO
DIMENS
3 5 4 /
START
22 'AUG' 2018 /
OIL
GAS
WATER
DISGAS
METRIC
TABDIMS
1 1 130 24 1 20 /
EQLDIMS
2 100 20 /
WELLDIMS
230 120 50 80 /
UNIFIN
UNIFOUT
UDQDIMS
50 25 0 50 50 0 0 50 0 20 /
UDADIMS
10 1* 10 /
GRID
NOECHO
INIT
GRIDFILE
0 1 /
MAPAXES
0 100 0 0 100 0 /
NOECHO
SPECGRID
3 5 4 1 'F' /
COORD
2000 2000 2000 1999.5638 2000 2039.9619 2199.8096 2000 2008.7239 2199.3735 2000 2048.6858 2399.6193 2000 2017.4478 2399.1831
2000 2057.4097 2599.4289 2000 2026.1716 2598.9927 2000 2066.1336 2000 2200 2000 1999.5638 2200 2039.9619 2199.8096 2200
2008.7239 2199.3735 2200 2048.6858 2399.6193 2200 2017.4478 2399.1831 2200 2057.4097 2599.4289 2200 2026.1716 2598.9927 2200 2066.1336
2000 2400 2000 1999.5638 2400 2039.9619 2199.8096 2400 2008.7239 2199.3735 2400 2048.6858 2399.6193 2400 2017.4478 2399.1831
2400 2057.4097 2599.4289 2400 2026.1716 2598.9927 2400 2066.1336 2000 2600 2000 1999.5638 2600 2039.9619 2199.8096 2600
2008.7239 2199.3735 2600 2048.6858 2399.6193 2600 2017.4478 2399.1831 2600 2057.4097 2599.4289 2600 2026.1716 2598.9927 2600 2066.1336
2000 2800 2000 1999.5638 2800 2039.9619 2199.8096 2800 2008.7239 2199.3735 2800 2048.6858 2399.6193 2800 2017.4478 2399.1831
2800 2057.4097 2599.4289 2800 2026.1716 2598.9927 2800 2066.1336 2000 3000 2000 1999.5638 3000 2039.9619 2199.8096 3000
2008.7239 2199.3735 3000 2048.6858 2399.6193 3000 2017.4478 2399.1831 3000 2057.4097 2599.4289 3000 2026.1716 2598.9927 3000 2066.1336 /
ZCORN
2000 2008.7239 2008.7239 2017.4478 2017.4478 2026.1716 2000 2008.7239 2008.7239 2017.4478 2017.4478 2026.1716 2000 2008.7239 2008.7239 2017.4478
2017.4478 2026.1716 2000 2008.7239 2008.7239 2017.4478 2017.4478 2026.1716 2000 2008.7239 2008.7239 2017.4478 2017.4478 2026.1716 2000 2008.7239
2008.7239 2017.4478 2017.4478 2026.1716 2000 2008.7239 2008.7239 2017.4478 2017.4478 2026.1716 2000 2008.7239 2008.7239 2017.4478 2017.4478 2026.1716
2000 2008.7239 2008.7239 2017.4478 2017.4478 2026.1716 2000 2008.7239 2008.7239 2017.4478 2017.4478 2026.1716 2009.9905 2018.7144 2018.7144 2027.4382
2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144
2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621
2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382
2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144
2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621
2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382
2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144 2018.7144 2027.4382 2027.4382 2036.1621 2009.9905 2018.7144
2018.7144 2027.4382 2027.4382 2036.1621 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526
2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287
2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048
2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526
2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287
2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048
2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526
2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2019.981 2028.7048 2028.7048 2037.4287 2037.4287 2046.1526 2029.9714 2038.6953 2038.6953 2047.4192
2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953
2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431
2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192
2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953
2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431
2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192
2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953 2038.6953 2047.4192 2047.4192 2056.1431 2029.9714 2038.6953
2038.6953 2047.4192 2047.4192 2056.1431 2039.9619 2048.6858 2048.6858 2057.4097 2057.4097 2066.1336 2039.9619 2048.6858 2048.6858 2057.4097 2057.4097 2066.1336
2039.9619 2048.6858 2048.6858 2057.4097 2057.4097 2066.1336 2039.9619 2048.6858 2048.6858 2057.4097 2057.4097 2066.1336 2039.9619 2048.6858 2048.6858 2057.4097
2057.4097 2066.1336 2039.9619 2048.6858 2048.6858 2057.4097 2057.4097 2066.1336 2039.9619 2048.6858 2048.6858 2057.4097 2057.4097 2066.1336 2039.9619 2048.6858
2048.6858 2057.4097 2057.4097 2066.1336 2039.9619 2048.6858 2048.6858 2057.4097 2057.4097 2066.1336 2039.9619 2048.6858 2048.6858 2057.4097 2057.4097 2066.1336 /
PORO
0.25 0.25 0.25 0.25 0.25 0.25 0.25 0.25 0.25 0.25 0.25 0.25 0.25 0.25 0.25 0.2
0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.23 0.23
0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.18 0.18 0.18
0.18 0.18 0.18 0.18 0.18 0.18 0.18 0.18 0.18 0.18 0.18 0.18 /
PERMX
500 500 500 500 500 500 500 500 500 500 500 500 500 500 500 100
100 100 100 100 100 100 100 100 100 100 100 100 100 100 1000 1000
1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 250 250 250
250 250 250 250 250 250 250 250 250 250 250 250 /
COPY
'PERMX' 'PERMY' /
'PERMX' 'PERMZ' /
/
MULTIPLY
'PERMZ' 0.1 /
/
MULTZ
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 /
EDIT
PROPS
SGOF
0 0 1 0 0.0183 0.001480314 0.8127534 0 0.0366 0.004696335 0.675857 0 0.0549 0.009371694 0.5622753 0
0.0732 0.01546379 0.4663578 0 0.0915 0.02298664 0.385133 0 0.1098 0.03197913 0.3164995 0 0.1281 0.04249268 0.2587408 0
0.1464 0.05458466 0.2103665 0 0.1647 0.06831379 0.1700565 0 0.183 0.08373629 0.1366388 0 0.2013 0.1009022 0.1090792 0
0.2196 0.1198516 0.08647139 0 0.2379 0.1406109 0.06802822 0 0.2562 0.1631885 0.05307051 0 0.2745 0.1875705 0.04101619 0
0.2928 0.2137163 0.03136912 0 0.3111 0.2415547 0.02370834 0 0.3294 0.2709792 0.01767817 0 0.3477 0.3018447 0.01297907 0
0.366 0.3339653 0.009359652 0 0.3843 0.3671116 0.006609586 0 0.4026 0.401011 0.00455345 0 0.4209 0.4353486 0.003045475 0
0.4392 0.4697695 0.001965044 0 0.4575 0.5038828 0.001212868 0 0.4758 0.5372664 0.0007077659 0 0.4941 0.5694721 0.000383946 0
0.5124 0.6000285 0.0001887263 0 0.5307 0.6284408 8.062741e-05 0 0.549 0.6541796 2.778023e-05 0 0.5673 0.676644 6.602397e-06 0
0.5856 0.6950468 7.048731e-07 0 0.61 0.71 0 0 0.6275 0.7825 0 0 0.645 0.855 0 0
0.6625 0.9275 0 0 0.68 1 0 0 /
SWOF
0.32 0 1 0 0.3365 3.00925e-08 0.9804566 0 0.353 7.541952e-07 0.9391194 0 0.3695 5.01876e-06 0.8832853 0
0.386 1.941502e-05 0.8178788 0 0.4025 5.581854e-05 0.7471578 0 0.419 0.0001330574 0.674704 0 0.4355 0.0002787865 0.60333 0
0.452 0.0005316304 0.535068 0 0.4685 0.0009436502 0.4712431 0 0.485 0.001583182 0.412597 0 0.5015 0.002538082 0.3594268 0
0.518 0.00391938 0.3117147 0 0.5345 0.005865308 0.2692366 0 0.551 0.008545575 0.2316458 0 0.5675 0.01216566 0.1985336 0
0.584 0.01697073 0.169471 0 0.6005 0.0232485 0.1440352 0 0.617 0.03133019 0.1218258 0 0.6335 0.04158825 0.1024735 0
0.65 0.05442925 0.08564409 0 0.6665 0.07028023 0.0710386 0 0.683 0.08956673 0.05839253 0 0.6995 0.1126816 0.0474734 0
0.716 0.1399451 0.03807806 0 0.7325 0.1715593 0.03002991 0 0.749 0.2075632 0.02317622 0 0.7655 0.2478002 0.01738581 0
0.782 0.2919105 0.01254709 0 0.7985 0.3393688 0.008566921 0 0.815 0.3895919 0.005370427 0 0.8315 0.4421811 0.002903191 0
0.848 0.4975608 0.001139647 0 0.87 0.59168 0 0 0.8885714 0.6500114 0 0 0.9071429 0.7083429 0 0
0.9257143 0.7666743 0 0 0.9442857 0.8250057 0 0 0.9628571 0.8833371 0 0 0.9814286 0.9416686 0 0
1 1 0 0 /
PVDG
20 0.061895 0.01299 40 0.030252 0.01383 60 0.019844 0.0145 80 0.014686 0.0152 100 0.011627 0.01596 120
0.009619 0.01682 140 0.008213 0.0178 160 0.007184 0.0189 197.66 0.00582 0.0216 231.13 0.005042 0.02477 261.31 0.004561
0.02844 288.87 0.004255 0.03272 314.34 0.004062 0.03783 338.2 0.003953 0.0441 360.83 0.003947 0.0521 382.58 0.003915 0.06273
403.6 0.003912 0.07723 423.77 0.003907 0.09631 /
PVTO
19.6 20 1.12324 0.96519 55 1.11698 1.03237 90 1.11127 1.10051 125 1.10602 1.16942 160 1.10119 1.2389
195 1.09672 1.30876 230 1.09256 1.37884 265 1.08868 1.44899 300 1.08504 1.51908 335 1.08164 1.58903 370
1.07843 1.65876 /
31.5 40 1.15981 0.85738 75 1.15288 0.91402 110 1.14657 0.97137 145 1.14079 1.02927 180 1.13546 1.08759
215 1.13053 1.14617 250 1.12595 1.20488 285 1.12168 1.2636 320 1.11768 1.32224 355 1.11394 1.38073 390
1.11042 1.43898 /
42.4 60 1.191 0.7868 95 1.184 0.8364 130 1.177 0.8866 165 1.171 0.9371 200 1.165 0.988
235 1.16 1.039 270 1.155 1.0902 305 1.15 1.1413 340 1.146 1.1922 375 1.142 1.2431 410
1.138 1.2936 /
53.4 80 1.222 0.7175 115 1.214 0.7608 150 1.206 0.8045 185 1.2 0.8485 220 1.194 0.8928
255 1.188 0.9371 290 1.183 0.9815 325 1.178 1.0258 360 1.173 1.07 395 1.169 1.1141 430
1.165 1.1579 /
64.6 100 1.252 0.6544 135 1.244 0.6923 170 1.236 0.7305 205 1.229 0.7689 240 1.222 0.8075
275 1.216 0.8461 310 1.211 0.8847 345 1.205 0.9233 380 1.2 0.9618 415 1.196 1 450
1.191 1.0381 /
76.3 120 1.284 0.5978 155 1.275 0.6312 190 1.266 0.6648 225 1.259 0.6985 260 1.252 0.7323
295 1.245 0.7661 330 1.239 0.7999 365 1.234 0.8337 400 1.229 0.8673 435 1.224 0.9007 470
1.219 0.934 /
88.5 140 1.316 0.5477 175 1.307 0.5749 210 1.298 0.602 245 1.29 0.629 280 1.282 0.6559
315 1.276 0.6827 350 1.269 0.7095 385 1.263 0.7362 420 1.258 0.7629 455 1.253 0.7895 490
1.248 0.8161 /
101.3 160 1.35 0.502 195 1.34 0.5227 230 1.331 0.5432 265 1.322 0.5635 300 1.314 0.5835
335 1.307 0.6034 370 1.3 0.6231 405 1.294 0.6426 440 1.288 0.662 475 1.283 0.6813 /
114.7 180 1.385 0.4636 215 1.375 0.482 250 1.365 0.5003 285 1.356 0.5183 320 1.347 0.5362
355 1.34 0.5538 390 1.333 0.5712 425 1.326 0.5885 460 1.32 0.6055 495 1.314 0.6222 /
128.9 200 1.422 0.429 235 1.411 0.4455 270 1.401 0.4618 305 1.391 0.4779 340 1.382 0.4938
375 1.374 0.5096 410 1.367 0.5252 445 1.36 0.5406 480 1.353 0.5558 /
143.8 220 1.461 0.3977 255 1.449 0.4125 290 1.438 0.4271 325 1.428 0.4415 360 1.419 0.4558
395 1.41 0.4699 430 1.402 0.4839 465 1.395 0.4977 /
159.5 240 1.502 0.3692 275 1.489 0.3825 310 1.478 0.3956 345 1.467 0.4086 380 1.458 0.4214
415 1.449 0.4341 450 1.44 0.4466 485 1.432 0.459 /
184 268.79 1.565 0.3324 303.79 1.551 0.3438 338.79 1.539 0.3551 373.79 1.528 0.3663 408.79 1.517 0.3774
443.79 1.508 0.3883 478.79 1.499 0.3991 /
226.3 306.18 1.679 0.2855 341.18 1.664 0.2949 376.18 1.65 0.3041 411.18 1.637 0.3132 446.18 1.625 0.3222
481.18 1.614 0.3311 /
268.6 339.93 1.792 0.2517 374.93 1.775 0.2597 409.93 1.76 0.2675 444.93 1.746 0.2751 479.93 1.732 0.2827 /
310.9 371.44 1.903 0.2265 406.44 1.885 0.2333 441.44 1.868 0.2401 476.44 1.853 0.2468 /
353.3 401.66 2.013 0.2071 436.66 1.993 0.2132 471.66 1.975 0.2192 /
/
PVTW
344.83 1.0292 4.002e-05 0.36 0 /
ROCK
383 4.12e-05 /
DENSITY
842.3 1001.1 0.9 /
REGIONS
EQLNUM
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 /
SOLUTION
EQUIL
2030 382.4 2030 0 500 0 1 1 0 /
2050 382.4 2050 0 500 0 1 1 0 /
RSVD
1500 180 4000 180 /
1500 180 4000 180 /
RPTRST
'BASIC=2' 'PBPD' /
SUMMARY
FOPR
FOPRH
FGPR
FGPRH
FWPR
FWPRH
FWIR
FWIP
FOIP
FGIP
FWCT
FWCTH
FGOR
FGORH
FPR
RPR
/
ROIP
/
ROIPL
/
ROIPG
/
RGIP
/
RGIPL
/
RGIPG
/
RGPR
/
RGPT
/
GWIR
/
GVIR
/
GOPR
/
GWPR
/
GLPR
/
GLPR
/
GVPR
/
WOPR
/
WOPRH
/
WGPR
/
WGPRH
/
WWPR
/
WWPRH
/
WOPT
/
WWPT
/
WGPT
/
WOPTH
/
WWPTH
/
WGPTH
/
WWCT
/
WWCTH
/
WGOR
/
WGORH
/
WWIR
/
WWIRH
/
WGIR
/
WGIRH
/
WWIT
/
WWITH
/
WGIT
/
WGITH
/
WBHP
/
WTHP
/
WPI
/
WVPR
/
WBP
/
WBP4
/
WBP9
/
WMCTL
/
WLPR
/
TCPU
TCPUDAY
FMWIN
FMWPR
GMWPR
'UPPER' 'LOWER' /
GMWIN
'UPPER' 'LOWER' /
WUOPRL
'OPL01' 'OPL02' 'OPU01' 'OPU02' /
WULPRL
'OPL01' 'OPL02' 'OPU01' 'OPU02' /
WUOPRU
'OPL01' 'OPL02' 'OPU01' 'OPU02' /
WULPRU
'OPL01' 'OPL02' 'OPU01' 'OPU02' /
SCHEDULE
GRUPTREE
'UPPER' 'TEST' /
'LOWER' 'TEST' /
/
WELSPECS
'OPU01' 'UPPER' 1 2 2002 'OIL' 0 'STD' 'SHUT' 'YES' 0 'SEG' /
'OPU02' 'UPPER' 1 4 2002 'OIL' 0 'STD' 'SHUT' 'YES' 0 'SEG' /
'OPL01' 'LOWER' 1 2 2025 'OIL' 0 'STD' 'SHUT' 'YES' 0 'SEG' /
'OPL02' 'LOWER' 1 4 2025 'OIL' 0 'STD' 'SHUT' 'YES' 0 'SEG' /
/
WELSPECS
'WIU01' 'UPPER' 3 3 2030 'WATER' 0 'STD' 'SHUT' 'YES' 0 'SEG' /
'WIL01' 'LOWER' 3 3 2050 'WATER' 0 'STD' 'SHUT' 'YES' 0 'SEG' /
/
COMPDAT
'OPU01' 1 2 1 1 'OPEN' 0 1* 0.241 1* 2.5 0 'Z' /
'OPU02' 1 4 1 1 'OPEN' 0 1* 0.241 1* 2.5 0 'Z' /
'OPL01' 1 2 3 3 'OPEN' 0 1* 0.241 1* 2.5 0 'Z' /
'OPL02' 1 4 3 3 'OPEN' 0 1* 0.241 1* 2.5 0 'Z' /
'WIU01' 3 3 2 2 'OPEN' 0 1* 0.241 1* 2.5 0 'Z' /
'WIL01' 3 3 4 4 'OPEN' 0 1* 0.241 1* 2.5 0 'Z' /
/
WCONPROD
'OPU*' 'SHUT' 'GRUP' 1500 2* 2500 1* 60 /
'OPL*' 'SHUT' 'GRUP' 1500 2* 2500 1* 60 /
/
WCONINJE
'WIU*' 'WATER' 'SHUT' 'GRUP' 10500 1* 400 /
'WIL*' 'WATER' 'SHUT' 'GRUP' 10500 1* 400 /
/
UDQ
-- test
--oil & liquid capacities at GEFAC = 0.8995
DEFINE WUOPRL (WOPR OPL01 - 150) * 0.90 /
DEFINE WULPRL (WLPR OPL01 - 200) * 0.90 /
DEFINE WUOPRU (WOPR OPU01 - 250) * 0.80 /
DEFINE WULPRU (WLPR OPU01 - 300) * 0.80 /
-- units
UNITS WUOPRL SM3/DAY /
UNITS WULPRL SM3/DAY /
UNITS WUOPRU SM3/DAY /
UNITS WULPRU SM3/DAY /
--
/
GCONPROD
'TEST' 'LRAT' 6000 2* 6000 'RATE' 'NO' /
'LOWER' 'FLD' 6000 2* 6000 'RATE' 'YES' 1* 'FORM' /
'UPPER' 'FLD' 3000 2* 6000 'RATE' 'YES' 1* 'FORM' /
/
GCONINJE
'LOWER' 'WATER' 'VREP' 3* 1.2 /
'UPPER' 'WATER' 'VREP' 3* 1.2 /
/
GUIDERAT
0 'OIL' 1 0.5 1 1 0 0 'YES' 0.5 /
WCONPROD
'OPL02' 'OPEN' 'GRUP' 'WUOPRL' 2* 'WULPRL' 1* 60 /
/
WCONPROD
'OPU02' 'OPEN' 'GRUP' 'WUOPRU' 2* 'WULPRU' 1* 60 /
/
DATES
1 'SEP' 2018 /
/
WELOPEN
'OPL01' 'OPEN' /
/
DATES
1 'OCT' 2018 /
/
WELOPEN
'WIL01' 'OPEN' /
/
DATES
1 'NOV' 2018 /
/
WCONPROD
'OPL02' 'OPEN' 'GRUP' 100 2* 200 1* 60 /
/
WELOPEN
'OPL02' 'OPEN' /
/
DATES
1 'DEC' 2018 /
/
WELOPEN
'OPU01' 'OPEN' /
/
DATES
1 'JAN' 2019 /
/
WELOPEN
'OPU02' 'OPEN' /
/
DATES
1 'FEB' 2019 /
/
WELOPEN
'WIU01' 'OPEN' /
/
DATES
1 'MAR' 2019 /
1 'APR' 2019 /
1 'MAY' 2019 /
1 'JUN' 2019 /
1 'JUL' 2019 /
1 'JAN' 2020 /
/
)";

View File

@@ -0,0 +1,318 @@
std::string deck_string = R"(
RUNSPEC
TITLE
2 PRODUCERS AND INJECTORS, 2 WELL GROUPS AND ONE INTERMEDIATE GROUP LEVEL BELOW THE FIELD LEVEL
DIMENS
10 5 10 /
OIL
WATER
GAS
DISGAS
FIELD
TABDIMS
1 1 15 15 2 15 /
EQLDIMS
2 /
WELLDIMS
4 20 4 2 /
UNIFIN
UNIFOUT
FMTIN
FMTOUT
-- 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 /
START
1 'JAN' 2015 /
-- RPTRUNSP
GRID =========================================================
--NOGGF
BOX
1 10 1 5 1 1 /
TOPS
50*7000 /
BOX
1 10 1 5 1 10 /
DXV
10*100 /
DYV
5*100 /
DZV
2*20 100 7*20 /
EQUALS
-- 'DX' 100 /
-- 'DY' 100 /
'PERMX' 50 /
'PERMZ' 5 /
-- 'DZ' 20 /
'PORO' 0.2 /
-- 'TOPS' 7000 1 10 1 5 1 1 /
--'DZ' 100 1 10 1 5 3 3 /
'PORO' 0.0 1 10 1 5 3 3 /
/
COPY
PERMX PERMY /
/
RPTGRID
-- Report Levels for Grid Section Data
--
/
PROPS ==========================================================
-- WATER RELATIVE PERMEABILITY AND CAPILLARY PRESSURE ARE TABULATED AS
-- A FUNCTION OF WATER SATURATION.
--
-- SWAT KRW PCOW
SWFN
0.12 0 0
1.0 0.00001 0 /
-- SIMILARLY FOR GAS
--
-- SGAS KRG PCOG
SGFN
0 0 0
0.02 0 0
0.05 0.005 0
0.12 0.025 0
0.2 0.075 0
0.25 0.125 0
0.3 0.19 0
0.4 0.41 0
0.45 0.6 0
0.5 0.72 0
0.6 0.87 0
0.7 0.94 0
0.85 0.98 0
1.0 1.0 0
/
-- OIL RELATIVE PERMEABILITY IS TABULATED AGAINST OIL SATURATION
-- FOR OIL-WATER AND OIL-GAS-CONNATE WATER CASES
--
-- SOIL KROW KROG
SOF3
0 0 0
0.18 0 0
0.28 0.0001 0.0001
0.38 0.001 0.001
0.43 0.01 0.01
0.48 0.021 0.021
0.58 0.09 0.09
0.63 0.2 0.2
0.68 0.35 0.35
0.76 0.7 0.7
0.83 0.98 0.98
0.86 0.997 0.997
0.879 1 1
0.88 1 1 /
-- PVT PROPERTIES OF WATER
--
-- REF. PRES. REF. FVF COMPRESSIBILITY REF VISCOSITY VISCOSIBILITY
PVTW
4014.7 1.029 3.13D-6 0.31 0 /
-- ROCK COMPRESSIBILITY
--
-- REF. PRES COMPRESSIBILITY
ROCK
14.7 3.0D-6 /
-- SURFACE DENSITIES OF RESERVOIR FLUIDS
--
-- OIL WATER GAS
DENSITY
49.1 64.79 0.06054 /
-- PVT PROPERTIES OF DRY GAS (NO VAPOURISED OIL)
-- WE WOULD USE PVTG TO SPECIFY THE PROPERTIES OF WET GAS
--
-- PGAS BGAS VISGAS
PVDG
14.7 166.666 0.008
264.7 12.093 0.0096
514.7 6.274 0.0112
1014.7 3.197 0.014
2014.7 1.614 0.0189
2514.7 1.294 0.0208
3014.7 1.080 0.0228
4014.7 0.811 0.0268
5014.7 0.649 0.0309
9014.7 0.386 0.047 /
-- PVT PROPERTIES OF LIVE OIL (WITH DISSOLVED GAS)
-- WE WOULD USE PVDO TO SPECIFY THE PROPERTIES OF DEAD OIL
--
-- FOR EACH VALUE OF RS THE SATURATION PRESSURE, FVF AND VISCOSITY
-- ARE SPECIFIED. FOR RS=1.27 AND 1.618, THE FVF AND VISCOSITY OF
-- UNDERSATURATED OIL ARE DEFINED AS A FUNCTION OF PRESSURE. DATA
-- FOR UNDERSATURATED OIL MAY BE SUPPLIED FOR ANY RS, BUT MUST BE
-- SUPPLIED FOR THE HIGHEST RS (1.618).
--
-- RS POIL FVFO VISO
PVTO
0.001 14.7 1.062 1.04 /
0.0905 264.7 1.15 0.975 /
0.18 514.7 1.207 0.91 /
0.371 1014.7 1.295 0.83 /
0.636 2014.7 1.435 0.695 /
0.775 2514.7 1.5 0.641 /
0.93 3014.7 1.565 0.594 /
1.270 4014.7 1.695 0.51
5014.7 1.671 0.549
9014.7 1.579 0.74 /
1.618 5014.7 1.827 0.449
9014.7 1.726 0.605 /
/
RPTPROPS
-- PROPS Reporting Options
--
/
REGIONS ===========================================================
FIPNUM
100*1
400*2
/
EQLNUM
100*1
400*2
/
RPTREGS
/
SOLUTION ============================================================
EQUIL
7020.00 2700.00 7990.00 .00000 7020.00 .00000 0 0 5 /
7200.00 3700.00 7300.00 .00000 7000.00 .00000 1 0 5 /
RSVD 2 TABLES 3 NODES IN EACH FIELD 12:00 17 AUG 83
7000.0 1.0000
7990.0 1.0000
/
7000.0 1.0000
7400.0 1.0000
/
RPTRST
-- Restart File Output Control
--
'BASIC=2' 'FLOWS' 'POT' 'PRES' /
SUMMARY ===========================================================
FOPR
WOPR
/
FGPR
FWPR
FWIR
FWCT
FGOR
--RUNSUM
ALL
MSUMLINS
MSUMNEWT
SEPARATE
SCHEDULE ===========================================================
GRUPTREE
'GRP1' 'FIELD' /
'WGRP1' 'GRP1' /
'WGRP2' 'GRP1' /
/
WELSPECS
'PROD1' 'WGRP1' 1 5 7030 'OIL' 0.0 'STD' 'STOP' /
'PROD2' 'WGRP2' 1 5 7030 'OIL' 0.0 'STD' 'STOP' /
'WINJ1' 'WGRP1' 10 1 7030 'WAT' 0.0 'STD' 'STOP' /
'WINJ2' 'WGRP2' 10 1 7030 'WAT' 0.0 'STD' 'STOP' /
/
COMPDAT
'PROD1' 1 5 2 2 3* 0.2 3* 'X' /
'PROD1' 2 5 2 2 3* 0.2 3* 'X' /
'PROD1' 3 5 2 2 3* 0.2 3* 'X' /
'PROD2' 4 5 2 2 3* 0.2 3* 'X' /
'PROD2' 5 5 2 2 3* 0.2 3* 'X' /
'WINJ1' 10 1 9 9 3* 0.2 3* 'X' /
'WINJ1' 9 1 9 9 3* 0.2 3* 'X' /
'WINJ1' 8 1 9 9 3* 0.2 3* 'X' /
'WINJ2' 7 1 9 9 3* 0.2 3* 'X' /
'WINJ2' 6 1 9 9 3* 0.2 3* 'X' /
/
)";

View File

@@ -0,0 +1,354 @@
#define BOOST_TEST_MODULE UDQ_Data
#include <boost/test/unit_test.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/Well2.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/output/eclipse/AggregateUDQData.hpp>
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
#include <opm/output/eclipse/InteHEAD.hpp>
#include <opm/output/eclipse/VectorItems/intehead.hpp>
#include <opm/output/eclipse/DoubHEAD.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.hpp>
//#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
//#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
#include <opm/parser/eclipse/Units/Units.hpp>
#include <opm/io/eclipse/OutputStream.hpp>
#include <stdexcept>
#include <utility>
#include <exception>
#include <iostream>
#include <string>
#include <vector>
namespace {
Opm::Deck first_sim(std::string fname) {
return Opm::Parser{}.parseFile(fname);
}
Opm::UDQActive udq_active() {
int update_count = 0;
// construct record data for udq_active
Opm::UDQParams params;
Opm::UDQConfig conf(params);
Opm::UDQActive udq_act;
Opm::UDAValue uda1("WUOPRL");
update_count += udq_act.update(conf, uda1, "PROD1", Opm::UDAControl::WCONPROD_ORAT);
Opm::UDAValue uda2("WULPRL");
update_count += udq_act.update(conf, uda2, "PROD1", Opm::UDAControl::WCONPROD_LRAT);
Opm::UDAValue uda3("WUOPRU");
update_count += udq_act.update(conf, uda3, "PROD2", Opm::UDAControl::WCONPROD_ORAT);
Opm::UDAValue uda4("WULPRU");
update_count += udq_act.update(conf, uda4, "PROD2", Opm::UDAControl::WCONPROD_LRAT);
for (std::size_t index=0; index < udq_act.IUAD_size(); index++)
{
const auto & record = udq_act[index];
auto ind = record.input_index;
auto udq_key = record.udq;
auto name = record.wgname;
auto ctrl_type = record.control;
}
return udq_act;
}
}
//int main(int argc, char* argv[])
struct SimulationCase
{
explicit SimulationCase(const Opm::Deck& deck)
: es { deck }
, grid { deck }
, sched{ deck, es }
{}
// Order requirement: 'es' must be declared/initialised before 'sched'.
Opm::EclipseState es;
Opm::EclipseGrid grid;
Opm::Schedule sched;
};
BOOST_AUTO_TEST_SUITE(Aggregate_UDQ)
// test constructed UDQ restart data
BOOST_AUTO_TEST_CASE (Declared_UDQ_data)
{
const auto simCase = SimulationCase{first_sim("UDQ_TEST_WCONPROD_IUAD-2.DATA")};
Opm::EclipseState es = simCase.es;
Opm::Schedule sched = simCase.sched;
Opm::EclipseGrid grid = simCase.grid;
const auto& ioConfig = es.getIOConfig();
const auto& restart = es.cfg().restart();
//Opm::UDQActive udq_act = udq_active();
// Report Step 1: 2008-10-10 --> 2011-01-20
const auto rptStep = std::size_t{1};
std::string outputDir = "./";
std::string baseName = "TEST_UDQRST";
Opm::EclIO::OutputStream::Restart rstFile {
Opm::EclIO::OutputStream::ResultSet { outputDir, baseName },
rptStep,
Opm::EclIO::OutputStream::Formatted { ioConfig.getFMTOUT() },
Opm::EclIO::OutputStream::Unified { ioConfig.getUNIFOUT() }
};
double secs_elapsed = 3.1536E07;
const auto ih = Opm::RestartIO::Helpers::createInteHead(es, grid, sched,
secs_elapsed, rptStep, rptStep);
//set dummy value for next_step_size
const double next_step_size= 0.1;
const auto dh = Opm::RestartIO::Helpers::createDoubHead(es, sched, rptStep,
secs_elapsed, next_step_size);
const auto udqDims = Opm::RestartIO::Helpers::createUdqDims(sched, rptStep, ih);
auto udqData = Opm::RestartIO::Helpers::AggregateUDQData(udqDims);
udqData.captureDeclaredUDQData(sched, rptStep, ih);
rstFile.write("IUDQ", udqData.getIUDQ());
rstFile.write("IUAD", udqData.getIUAD());
rstFile.write("IGPH", udqData.getIGPH());
rstFile.write("IUAP", udqData.getIUAP());
rstFile.write("ZUDN", udqData.getZUDN());
rstFile.write("ZUDL", udqData.getZUDL());
{
/*
Check of InteHEAD and DoubHEAD data for UDQ variables
INTEHEAD
UDQPARAM (1) = - InteHead [267 ]
---------------------------------------------------------------------------------------------------------------------
DOUBHEAD
UDQPARAM (2) = Doubhead [212]
UDQPARAM (3) = Doubhead [213]
UDQPARAM (4) = Doubhead [214]
*/
BOOST_CHECK_EQUAL(ih[267] , -1);
BOOST_CHECK_EQUAL(dh[212] , 1.0E+20);
BOOST_CHECK_EQUAL(dh[213] , 0.0);
BOOST_CHECK_EQUAL(dh[214] , 1.0E-4);
}
{
/*
IUDQ
3- integers pr UDQ (line/quantity)
Integer no 1 = type of UDQ ( 0 - ASSIGN, UPDATE-OFF
1-update+NEXT,
2 - DEFINE, 2- UPDATE-ON
3 - units)
Integer no 2 = -4 : used for ASSIGN - numerical value
-4 : used for DEFINE
-1 : used for DEFINE MIN() function, SUM() function, AVEA() function
-4 : used for DEFINE MAX() - function - also used for SUM() function - must check on (-1 - value)
1 : used for UPDATE quantity
Integer no 3 = sequence number of UDQ pr type (CU, FU, GU, RU, , SU, WU, AU or BU etc.)
(1 - based)
NOTE: UPDATE - does not define a new quantity, only updates an alredy defined quantity!
*/
const auto& iUdq = udqData.getIUDQ();
auto start = 0*udqDims[1];
BOOST_CHECK_EQUAL(iUdq[start + 0] , 2); // udq NO. 1 - ( 0 - ASSIGN, 2 - DEFINE)
BOOST_CHECK_EQUAL(iUdq[start + 1] , -4); // udq NO. 1 - (-4 - DEFINE / ASSIGN
BOOST_CHECK_EQUAL(iUdq[start + 2] , 1); // udq NO. 1 - (sequence number of UDQ pr type (CU, FU, GU, RU, , SU, WU, AU or BU etc.)
start = 1*udqDims[1];
BOOST_CHECK_EQUAL(iUdq[start + 0] , 0); // udq NO. 2 - ( 0 - ASSIGN, 2 - DEFINE)
BOOST_CHECK_EQUAL(iUdq[start + 1] , -4); // udq NO. 2 - (-4 - DEFINE / ASSIGN
BOOST_CHECK_EQUAL(iUdq[start + 2] , 2); // udq NO. 2 - (sequence number of UDQ pr type (CU, FU, GU, RU, , SU, WU, AU or BU etc.)
start = 2*udqDims[1];
BOOST_CHECK_EQUAL(iUdq[start + 0] , 2); // udq NO. 2 - ( 0 - ASSIGN, 2 - DEFINE)
BOOST_CHECK_EQUAL(iUdq[start + 1] , -4); // udq NO. 2 - (-4 - DEFINE / ASSIGN
BOOST_CHECK_EQUAL(iUdq[start + 2] , 3); // udq NO. 2 - (sequence number of UDQ pr type (CU, FU, GU, RU, , SU, WU, AU or BU etc.)
start = 3*udqDims[1];
BOOST_CHECK_EQUAL(iUdq[start + 0] , 2); // udq NO. 2 - ( 0 - ASSIGN, 2 - DEFINE)
BOOST_CHECK_EQUAL(iUdq[start + 1] , -4); // udq NO. 2 - (-4 - DEFINE / ASSIGN
BOOST_CHECK_EQUAL(iUdq[start + 2] , 1); // udq NO. 2 - (sequence number of UDQ pr type (CU, FU, GU, RU, , SU, WU, AU or BU etc.)
start = 4*udqDims[1];
BOOST_CHECK_EQUAL(iUdq[start + 0] , 2); // udq NO. 2 - ( 0 - ASSIGN, 2 - DEFINE)
BOOST_CHECK_EQUAL(iUdq[start + 1] , -4); // udq NO. 2 - (-4 - DEFINE / ASSIGN
BOOST_CHECK_EQUAL(iUdq[start + 2] , 4); // udq NO. 2 - (sequence number of UDQ pr type (CU, FU, GU, RU, , SU, WU, AU or BU etc.)
start = 5*udqDims[1];
BOOST_CHECK_EQUAL(iUdq[start + 0] , 2); // udq NO. 2 - ( 0 - ASSIGN, 2 - DEFINE)
BOOST_CHECK_EQUAL(iUdq[start + 1] , -4); // udq NO. 2 - (-4 - DEFINE / ASSIGN
BOOST_CHECK_EQUAL(iUdq[start + 2] , 1); // udq NO. 2 - (sequence number of UDQ pr type (CU, FU, GU, RU, , SU, WU, AU or BU etc.)
}
{
/*
IUAD:
Sequences of 5 items pr UDQ that is used for various well and group controls,
i.e. sorted on the various active controls, see list for item (1).This means that
one udq can occur several times, one for each control it is used for
Only the active controls are output - and the sequence is according to when
they are defined
dimension 5*no_of_udq-constraint-used in well and group controls
item (1) : = 200000 + 19 for GCONPROD and ORAT
300000 + 19 for GCONPROD and WRAT
400000 + 19 for GCONPROD and GRAT
500000 + 19 for GCONPROD and LRAT
300000 + 4 for WCONPROD + oil rate target or upper limit
400000 + 4 for WCONPROD + water rate target or upper limit
500000 + 4 for WCONPROD + gas rate target or upper limit
600000 + 4 for WCONPROD + liquid rate target or upper limit
? 300000 + 3 for WCONINJE + oil rate target or upper limit
400000 + 3 for WCONINJE + surface rate target or upper limit
500000 + 3 for WCONINJE + reservoir volume rate target or upper limit
1000000 + 27 for CECON + minimum oil rate
item (2) - sequence number of UDQ used (from input sequence) for the actual constraint/target
item (3) - do not know yet (value: 1)
item (4) - number of times the UDQ variable is used (e.g. for several different wells)
item (5) - the sequence number for the first use of the actual UDQ (index i+1) = 1+sum over <the first i udq's in use >(no_use_udq(i))
*/
const auto& iUad = udqData.getIUAD();
auto start = 0*udqDims[3];
BOOST_CHECK_EQUAL(iUad[start + 0] , 300004); // iuad NO. 1
BOOST_CHECK_EQUAL(iUad[start + 1] , 3); // iuad NO. 1
BOOST_CHECK_EQUAL(iUad[start + 2] , 1); // iuad NO. 1
BOOST_CHECK_EQUAL(iUad[start + 3] , 2); // iuad NO. 1
BOOST_CHECK_EQUAL(iUad[start + 4] , 1); // iuad NO. 1
start = 1*udqDims[3];
BOOST_CHECK_EQUAL(iUad[start + 0] , 600004); // iuad NO. 2
BOOST_CHECK_EQUAL(iUad[start + 1] , 5); // iuad NO. 2
BOOST_CHECK_EQUAL(iUad[start + 2] , 1); // iuad NO. 2
BOOST_CHECK_EQUAL(iUad[start + 3] , 2); // iuad NO. 2
BOOST_CHECK_EQUAL(iUad[start + 4] , 3); // iuad NO. 2
}
{
/*
ZUDN:
contains UDQ keyword data:
Pairs of:
quantity name (item2): e.g. 'WUOPRL ' and
units: e.g.: 'SM3/DAY '
Length is dependent on number of UDQ quantities = 2*no of UDQ's
*/
const auto& zUdn = udqData.getZUDN();
auto start = 0*udqDims[4];
BOOST_CHECK_EQUAL(zUdn[start + 0].c_str() , "WUOPRL "); // udq NO. 1
BOOST_CHECK_EQUAL(zUdn[start + 1].c_str() , "SM3/DAY "); // udq NO. 1
start = 1*udqDims[4];
BOOST_CHECK_EQUAL(zUdn[start + 0].c_str() , "WULPRL "); // udq NO. 2
BOOST_CHECK_EQUAL(zUdn[start + 1].c_str() , "SM3/DAY "); // udq NO. 2
start = 2*udqDims[4];
BOOST_CHECK_EQUAL(zUdn[start + 0].c_str() , "WUOPRU "); // udq NO. 3
BOOST_CHECK_EQUAL(zUdn[start + 1].c_str() , "SM3/DAY "); // udq NO. 3
start = 3*udqDims[4];
BOOST_CHECK_EQUAL(zUdn[start + 0].c_str() , "GUOPRU "); // udq NO. 4
BOOST_CHECK_EQUAL(zUdn[start + 1].c_str() , "SM3/DAY "); // udq NO. 4
start = 4*udqDims[4];
BOOST_CHECK_EQUAL(zUdn[start + 0].c_str() , "WULPRU "); // udq NO. 5
BOOST_CHECK_EQUAL(zUdn[start + 1].c_str() , "SM3/DAY "); // udq NO. 5
start = 5*udqDims[4];
BOOST_CHECK_EQUAL(zUdn[start + 0].c_str() , "FULPR "); // udq NO. 6
BOOST_CHECK_EQUAL(zUdn[start + 1].c_str() , "SM3/DAY "); // udq NO. 6
}
{
/*
ZUDL:
contains string that define the "Data for operation" for the defined quantity
e.g.
'(WOPR OP' 'L01 - 15' '0) * 0.9' '0 ' ' ' ' ' ' '
The appropriate data are split into strings of 8 characters each.
Length: No of UDQ's * 16
*/
const auto& zUdl = udqData.getZUDL();
auto start = 0*udqDims[5];
BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(WOPR PR"); // udq NO. 1
BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "OD1 - 17"); // udq NO. 1
BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , "0) * 0.6"); // udq NO. 1
BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , "0 "); // udq NO. 1
/*start = 1*udqDims[5];
BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(WLPR PR"); // udq NO. 1
BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "OD1 - 20"); // udq NO. 1
BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , "0) * 0.9"); // udq NO. 1
BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , "0 "); // udq NO. 1
*/
start = 3*udqDims[5];
BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(GOPR WG"); // udq NO. 1
BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "RP2 - 44"); // udq NO. 1
BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , "9) * 0.7"); // udq NO. 1
BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , "7 "); // udq NO. 1
start = 5*udqDims[5];
BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(FLPR - "); // udq NO. 1
BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "543) * 0"); // udq NO. 1
BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , ".65 "); // udq NO. 1
BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , " "); // udq NO. 1
}
}
BOOST_AUTO_TEST_SUITE_END()