diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 4814cffd3..93814ef3c 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -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 diff --git a/opm/output/eclipse/AggregateUDQData.hpp b/opm/output/eclipse/AggregateUDQData.hpp new file mode 100644 index 000000000..60ccdd048 --- /dev/null +++ b/opm/output/eclipse/AggregateUDQData.hpp @@ -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 . +*/ + +#ifndef OPM_AGGREGATE_UDQ_DATA_HPP +#define OPM_AGGREGATE_UDQ_DATA_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace Opm { + class Schedule; + class UDQInput; + class UDQActive; +} // Opm + +namespace Opm { namespace RestartIO { namespace Helpers { + +class igphData { +public: + const std::vector ig_phase(const Opm::Schedule& sched, const std::size_t simStep, const std::vector& inteHead); +}; + + +class AggregateUDQData +{ +public: + explicit AggregateUDQData(const std::vector& udqDims); + + void captureDeclaredUDQData(const Opm::Schedule& sched, + const std::size_t simStep, + const std::vector& ih); + + const std::vector& getIUDQ() const + { + return this->iUDQ_.data(); + } + + const std::vector& getIUAD() const + { + return this->iUAD_.data(); + } + + const std::vector>& getZUDN() const + { + return this->zUDN_.data(); + } + + const std::vector>& getZUDL() const + { + return this->zUDL_.data(); + } + + const std::vector& getIGPH() const + { + return this->iGPH_.data(); + } + + const std::vector& getIUAP() const + { + return this->iUAP_.data(); + } +#if 0 + const std::vector& getDUDW() const + { + return this->dUDW_.data(); + } + + const std::vector& getDUDF() const + { + return this->dUDF_.data(); + } +#endif + + +private: + /// Aggregate 'IUDQ' array (Integer) for all UDQ data (3 integers pr UDQ) + WindowedArray iUDQ_; + + /// Aggregate 'IUAD' array (Integer) for all UDQ data (5 integers pr UDQ that is used for various well and group controls) + WindowedArray iUAD_; + + + /// Aggregate 'ZUDN' array (Character) for all UDQ data. (2 * 8 chars pr UDQ -> UNIT keyword) + WindowedArray> zUDN_; + + /// Aggregate 'ZUDL' array (Character) for all UDQ data. (16 * 8 chars pr UDQ DEFINE "Data for operation - Msth Expression) + WindowedArray> zUDL_; + + /// Aggregate 'IGPH' array (Integer) for all UDQ data (3 - zeroes - as of current understanding) + WindowedArray iGPH_; + + /// Aggregate 'IUAP' array (ICharArrayNullTermnteger) for all UDQ data (1 integer pr UDQ constraint used) + WindowedArray iUAP_; +#if 0 + /// Aggregate 'DUDW' array (Double Precision) for all UDQ data. (Dimension = max no wells * noOfUDQ's) + WindowedArray dUDW_; + + /// Aggregate 'DUDF' array (Double Precision) for all UDQ data. (Dimension = Number of FU - UDQ's, with value equal to the actual constraint) + WindowedArray dUDF_; +#endif + + +}; + +}}} // Opm::RestartIO::Helpers + +#endif //OPM_AGGREGATE_WELL_DATA_HPP diff --git a/opm/output/eclipse/DoubHEAD.hpp b/opm/output/eclipse/DoubHEAD.hpp index c4348a12f..50c211bb4 100755 --- a/opm/output/eclipse/DoubHEAD.hpp +++ b/opm/output/eclipse/DoubHEAD.hpp @@ -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 start; std::chrono::duration 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& data() const { diff --git a/opm/output/eclipse/InteHEAD.hpp b/opm/output/eclipse/InteHEAD.hpp index 74fa1f23b..392886020 100755 --- a/opm/output/eclipse/InteHEAD.hpp +++ b/opm/output/eclipse/InteHEAD.hpp @@ -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& data() const { diff --git a/opm/output/eclipse/VectorItems/doubhead.hpp b/opm/output/eclipse/VectorItems/doubhead.hpp index 36a70b8d2..7e76a8513 100644 --- a/opm/output/eclipse/VectorItems/doubhead.hpp +++ b/opm/output/eclipse/VectorItems/doubhead.hpp @@ -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 diff --git a/opm/output/eclipse/VectorItems/intehead.hpp b/opm/output/eclipse/VectorItems/intehead.hpp index 1d0075ae1..525f181c8 100644 --- a/opm/output/eclipse/VectorItems/intehead.hpp +++ b/opm/output/eclipse/VectorItems/intehead.hpp @@ -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 diff --git a/opm/output/eclipse/WriteRestartHelpers.hpp b/opm/output/eclipse/WriteRestartHelpers.hpp index df921b451..3ffbad994 100755 --- a/opm/output/eclipse/WriteRestartHelpers.hpp +++ b/opm/output/eclipse/WriteRestartHelpers.hpp @@ -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 createLogiHead(const EclipseState& es); + std::vector + createUdqDims(const Schedule& sched, + const std::size_t lookup_step, + const std::vector& inteHead); + }}} // Opm::RestartIO::Helpers diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp index 9dbdbee41..ea0973803 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp @@ -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 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>> vfpinj_tables; DynamicState> wtest_config; DynamicState> wlist_manager; - DynamicState> udq_config; + DynamicState> udq_config; + DynamicState> udq_active; DynamicState 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 group, size_t reportStep); + bool checkGroups(const ParseContext& parseContext, ErrorGuard& errors); + void updateUDQActive( std::size_t timeStep, std::shared_ptr 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, diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp new file mode 100644 index 000000000..9d1d4e336 --- /dev/null +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.hpp @@ -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 . +*/ + + +#ifndef UDQ_USAGE_HPP +#define UDQ_USAGE_HPP + +#include +#include +#include +#include + +#include + +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& get_iuad() const; + std::vector 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 input_data; + std::vector mutable output_data; + std::unordered_map udq_keys; + std::unordered_map wg_keys; +}; + +} + +#endif diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp new file mode 100644 index 000000000..438769dbd --- /dev/null +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp @@ -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 . +*/ + + +#ifndef UDQINPUT_HPP_ +#define UDQINPUT_HPP_ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +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& selector, double value); + void add_define(const std::string& quantity, const std::vector& expression); + + std::vector definitions() const; + std::vector definitions(UDQVarType var_type) const; + std::vector 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 assignments() const; + std::vector 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 m_definitions; + std::unordered_map m_assignments; + std::unordered_map units; + + OrderedMap input_index; + std::map type_count; + }; +} + + + +#endif diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp index d4cb7ecc4..ef4c6a987 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp @@ -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); + } } diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp index 04e3de147..83db5a3f2 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.hpp @@ -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 -#include -#include +#include -#include -#include #include -#include -#include -#include - 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 definitions() const; - std::vector 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> input_definitions() const; - - std::vector assignments() const; - std::vector 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 m_definitions; - std::unordered_map m_assignments; - std::unordered_map 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> input_index; - }; + template + const T& get() const; + + template + 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; +}; } diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.hpp index a94516813..756768fb5 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.hpp @@ -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; diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well/Well2.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well/Well2.hpp index 1f1db6d22..8415e80f3 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well/Well2.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well/Well2.hpp @@ -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; diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp index c2205b058..cc6817f3c 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp @@ -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& ); diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp index 48c2d0fe3..52b031ccc 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp @@ -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 ); diff --git a/src/opm/output/eclipse/AggregateUDQData.cpp b/src/opm/output/eclipse/AggregateUDQData.cpp new file mode 100644 index 000000000..41e503699 --- /dev/null +++ b/src/opm/output/eclipse/AggregateUDQData.cpp @@ -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 . +*/ + +#include +#include +#include + +#include +#include +//#include +#include + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// ##################################################################### +// Class Opm::RestartIO::Helpers::AggregateGroupData +// --------------------------------------------------------------------- + + +namespace { + + // maximum number of groups + std::size_t ngmaxz(const std::vector& inteHead) + { + return inteHead[20]; + } + + + namespace iUdq { + + Opm::RestartIO::Helpers::WindowedArray + allocate(const std::vector& udqDims) + { + using WV = Opm::RestartIO::Helpers::WindowedArray; + return WV { + WV::NumWindows{ static_cast(udqDims[0]) }, + WV::WindowSize{ static_cast(udqDims[1]) } + }; + } + + template + void staticContrib(const Opm::UDQInput& udq_input, IUDQArray& iUdq) + { + if (udq_input.is()) { + 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 + allocate(const std::vector& udqDims) + { + using WV = Opm::RestartIO::Helpers::WindowedArray; + return WV { + WV::NumWindows{ static_cast(udqDims[2]) }, + WV::WindowSize{ static_cast(udqDims[3]) } + }; + } + + template + 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& udqDims) + { + using WV = Opm::RestartIO::Helpers::WindowedArray< + Opm::EclIO::PaddedOutputString<8> + >; + + return WV { + WV::NumWindows{ static_cast(udqDims[0]) }, + WV::WindowSize{ static_cast(udqDims[4]) } + }; + } + + template + 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& udqDims) + { + using WV = Opm::RestartIO::Helpers::WindowedArray< + Opm::EclIO::PaddedOutputString<8> + >; + + return WV { + WV::NumWindows{ static_cast(udqDims[0]) }, + WV::WindowSize{ static_cast(udqDims[5]) } + }; + } + + template + 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()) { + const auto& udq_define = input.get(); + const std::string& z_data = udq_define.input_string(); + int n_sstr = z_data.size()/l_sstr; + if (static_cast(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 + allocate(const std::vector& udqDims) + { + using WV = Opm::RestartIO::Helpers::WindowedArray; + return WV { + WV::NumWindows{ static_cast(udqDims[6]) }, + WV::WindowSize{ static_cast(1) } + }; + } + + template + void staticContrib(const int inj_phase, + IGPHArray& iGph) + { + iGph[0] = inj_phase; + } + } // iGph + + namespace iUap { + + Opm::RestartIO::Helpers::WindowedArray + allocate(const std::vector& udqDims) + { + using WV = Opm::RestartIO::Helpers::WindowedArray; + return WV { + WV::NumWindows{ static_cast(udqDims[7]) }, + WV::WindowSize{ static_cast(1) } + }; + } + + template + void staticContrib(const int wg_no, + IUAPArray& iUap) + { + iUap[0] = wg_no+1; + } + } // iUap + +} + +// ===================================================================== + + +template < typename T> +std::pair findInVector(const std::vector & vecOfElements, const T & element) +{ + std::pair 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 Opm::RestartIO::Helpers::igphData::ig_phase(const Opm::Schedule& sched, + const std::size_t simStep, + const std::vector& inteHead + ) +{ + std::vector 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 iuap_data(const Opm::Schedule& sched, + const std::size_t simStep, + const std::vector& iuap) +{ + //construct the current list of well or group sequence numbers to output the IUAP array + std::vector 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(ctrl) << std::endl; + throw std::invalid_argument("UDQ - variable: " + iuap[ind].udq ); + } + + } + + return wg_no; +} + + + +Opm::RestartIO::Helpers::AggregateUDQData:: +AggregateUDQData(const std::vector& 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& 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); + } + +} + diff --git a/src/opm/output/eclipse/CreateDoubHead.cpp b/src/opm/output/eclipse/CreateDoubHead.cpp index 165dcd4f7..0b1001d7e 100755 --- a/src/opm/output/eclipse/CreateDoubHead.cpp +++ b/src/opm/output/eclipse/CreateDoubHead.cpp @@ -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) { diff --git a/src/opm/output/eclipse/CreateInteHead.cpp b/src/opm/output/eclipse/CreateInteHead.cpp index ee1158062..1138d309b 100755 --- a/src/opm/output/eclipse/CreateInteHead.cpp +++ b/src/opm/output/eclipse/CreateInteHead.cpp @@ -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(); diff --git a/src/opm/output/eclipse/CreateUdqDims.cpp b/src/opm/output/eclipse/CreateUdqDims.cpp new file mode 100755 index 000000000..e64397a9a --- /dev/null +++ b/src/opm/output/eclipse/CreateUdqDims.cpp @@ -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 . +*/ + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +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& inteHead) +{ + std::size_t no_entries = inteHead[20]; + return no_entries; +} +} // Anonymous + +// ##################################################################### +// Public Interface (createUdqDims()) Below Separator +// --------------------------------------------------------------------- + +std::vector +Opm::RestartIO::Helpers:: +createUdqDims(const Schedule& sched, + const std::size_t simStep, + const std::vector& inteHead) +{ + const auto& udqCfg = sched.getUDQConfig(simStep); + const auto& udqActive = sched.udqActive(simStep); + std::vector 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; +} diff --git a/src/opm/output/eclipse/DoubHEAD.cpp b/src/opm/output/eclipse/DoubHEAD.cpp index b8e2ccb1c..4b65201f7 100755 --- a/src/opm/output/eclipse/DoubHEAD.cpp +++ b/src/opm/output/eclipse/DoubHEAD.cpp @@ -298,9 +298,9 @@ enum Index : std::vector::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; +} diff --git a/src/opm/output/eclipse/InteHEAD.cpp b/src/opm/output/eclipse/InteHEAD.cpp index 5c2cba8dd..aa2bdb7e2 100644 --- a/src/opm/output/eclipse/InteHEAD.cpp +++ b/src/opm/output/eclipse/InteHEAD.cpp @@ -19,420 +19,419 @@ namespace VI = ::Opm::RestartIO::Helpers::VectorItems; enum index : std::vector::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) diff --git a/src/opm/output/eclipse/RestartIO.cpp b/src/opm/output/eclipse/RestartIO.cpp index b3fa229cd..8320684ad 100644 --- a/src/opm/output/eclipse/RestartIO.cpp +++ b/src/opm/output/eclipse/RestartIO.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -259,6 +260,28 @@ namespace { rstFile.write("RSEG", MSWData.getRSeg()); } + void writeUDQ(int sim_step, + const Schedule& schedule, + const std::vector& 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 (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& 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); diff --git a/src/opm/output/eclipse/Summary.cpp b/src/opm/output/eclipse/Summary.cpp index 5e6a3f31b..8b951c735 100644 --- a/src/opm/output/eclipse/Summary.cpp +++ b/src/opm/output/eclipse/Summary.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include #include @@ -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 wells; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index 0fa5f9f96..12a46dbb2 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -48,7 +48,8 @@ #include #include -#include +#include +#include #include #include #include @@ -117,7 +118,8 @@ namespace { m_runspec( runspec ), wtest_config(this->m_timeMap, std::make_shared() ), wlist_manager( this->m_timeMap, std::make_shared()), - udq_config(this->m_timeMap, std::make_shared(deck)), + udq_config(this->m_timeMap, std::make_shared(deck)), + udq_active(this->m_timeMap, std::make_shared()), 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(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(this->udqActive(currentStep)); + if (properties->updateUDQActive(this->getUDQConfig(currentStep), *udq)) + this->updateUDQActive(currentStep, udq); } } } @@ -900,6 +905,10 @@ namespace { } } } + + auto udq = std::make_shared(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 new_udq = std::make_shared(current); + std::shared_ptr new_udq = std::make_shared(current); for (const auto& record : keyword) new_udq->add_record(record); @@ -1478,7 +1487,6 @@ namespace { auto water_target = record.getItem("WATER_TARGET").get(0); auto liquid_target = record.getItem("LIQUID_TARGET").get(0); auto resv_target = record.getItem("RESERVOIR_FLUID_TARGET").getSIDouble(0); - { auto group_ptr = std::make_shared(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 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; } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.cpp new file mode 100644 index 000000000..fd21b8548 --- /dev/null +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQActive.cpp @@ -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 . +*/ + +#include +#include +#include +#include +#include + +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(control)); +} + +std::string UDQActive::wg_hash(const std::string& wgname, UDAControl control) { + return wgname + std::to_string(static_cast(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() && 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()) { + // Alternative 2 + iter = this->input_data.erase(iter); + this->output_data.clear(); + return 1; + } else { + const std::string& udq = uda.get(); + 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()) { + const std::string& udq = uda.get(); + 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::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::get_iuap() const { + std::vector 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; +} + + +} + diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp new file mode 100644 index 000000000..3729477fd --- /dev/null +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.cpp @@ -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 . + */ + +#include + +#include +#include +#include +#include + +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& 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& 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(0)); + const auto& quantity = record.getItem("QUANTITY").get(0); + const auto& data = record.getItem("DATA").getData(); + + 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 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 UDQConfig::definitions() const { + std::vector 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 UDQConfig::definitions(UDQVarType var_type) const { + std::vector 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 UDQConfig::input() const { + std::vector 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 UDQConfig::assignments() const { + std::vector 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 UDQConfig::assignments(UDQVarType var_type) const { + std::vector 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; + } +} diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.cpp index 4516cedfe..b6162ee47 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include @@ -268,6 +268,53 @@ std::string typeName(UDQVarType var_type) { } } +UDAKeyword keyword(UDAControl control) { + const std::map 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 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"); +} } } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.cpp index e50681ccd..4a5dc0788 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQInput.cpp @@ -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 . - */ +*/ -#include -#include +#include +#include #include -#include 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(0)); - const auto& quantity = record.getItem("QUANTITY").get(0); - const auto& data = record.getItem("DATA").getData(); - - 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 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 UDQInput::definitions() const { - std::vector 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 UDQInput::definitions(UDQVarType var_type) const { - std::vector 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> UDQInput::input_definitions() const { - std::vector> 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 UDQInput::assignments() const { - std::vector 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 UDQInput::assignments(UDQVarType var_type) const { - std::vector 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() const { + if (this->assign) + return true; + return false; +} + + +template<> +bool UDQInput::is() const { + if (this->define) + return true; + return false; +} + +template<> +const UDQAssign& UDQInput::get() const { + if (this->assign) + return *this->assign; + + throw std::runtime_error("Invalid get"); +} + + +template<> +const UDQDefine& UDQInput::get() const { + if (this->define) + return *this->define; + + throw std::runtime_error("Invalid get"); +} + + + + +} + + diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.cpp index 4a88ce349..b58bb9422 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQParams.cpp @@ -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; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well2.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well2.cpp index 8e8b1375e..8238563f6 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well2.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well2.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -780,6 +781,4 @@ double Well2::temperature() const { throw std::runtime_error("Can not ask for temperature in a producer"); } - } - diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.cpp index 3ac7f95b4..0413bd690 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #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); + } + } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp index 13c05b4d5..86bc3f96e 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -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 diff --git a/src/opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.cpp b/src/opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.cpp index a5bcdbdfb..7d39a6773 100644 --- a/src/opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.cpp +++ b/src/opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.cpp @@ -34,8 +34,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/tests/UDQ_TEST_WCONPROD_IUAD-2.DATA b/tests/UDQ_TEST_WCONPROD_IUAD-2.DATA new file mode 100644 index 000000000..cc97d4752 --- /dev/null +++ b/tests/UDQ_TEST_WCONPROD_IUAD-2.DATA @@ -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 diff --git a/tests/parser/UDQTests.cpp b/tests/parser/UDQTests.cpp index 318114f12..a40ca463d 100644 --- a/tests/parser/UDQTests.cpp +++ b/tests/parser/UDQTests.cpp @@ -26,12 +26,13 @@ Copyright 2018 Statoil ASA. #include #include #include -#include +#include #include #include #include #include #include +#include #include 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() ); + BOOST_CHECK( input[1].is() ); + BOOST_CHECK( input[2].is() ); + BOOST_CHECK( input[3].is() ); + BOOST_CHECK( input[4].is() ); + BOOST_CHECK( input[5].is() ); + BOOST_CHECK( input[6].is() ); + 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().keyword(), "WUWCT"); + BOOST_CHECK_EQUAL( input[4].get().keyword(), "FUOPR"); + BOOST_CHECK_EQUAL( input[6].get().keyword(), "FUOPRX"); + BOOST_CHECK( udq.has_keyword("FUXXX") ); + const auto wubhp1 = udq["WUBHP1"]; + BOOST_CHECK( wubhp1.is() ); } @@ -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()); + BOOST_CHECK_EQUAL( input[0].keyword(), "WUBHP1"); + + const auto fuopr = udq["FUOPR"]; + BOOST_CHECK( fuopr.is() ); + const auto& def2 = fuopr.get(); + 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(), {}, 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); + } +} diff --git a/tests/parser/WellTests.cpp b/tests/parser/WellTests.cpp index 464585f5a..012735cbc 100644 --- a/tests/parser/WellTests.cpp +++ b/tests/parser/WellTests.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -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; } diff --git a/tests/parser/data/integration_tests/udq.data b/tests/parser/data/integration_tests/udq.data new file mode 100644 index 000000000..e7365e95c --- /dev/null +++ b/tests/parser/data/integration_tests/udq.data @@ -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 / +/ +)"; \ No newline at end of file diff --git a/tests/parser/data/integration_tests/udq2.data b/tests/parser/data/integration_tests/udq2.data new file mode 100644 index 000000000..b1a5207b5 --- /dev/null +++ b/tests/parser/data/integration_tests/udq2.data @@ -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' / +/ + + + +)"; \ No newline at end of file diff --git a/tests/test_AggregateUDQData.cpp b/tests/test_AggregateUDQData.cpp new file mode 100644 index 000000000..8bd85d43a --- /dev/null +++ b/tests/test_AggregateUDQData.cpp @@ -0,0 +1,354 @@ +#define BOOST_TEST_MODULE UDQ_Data + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +//#include +//#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +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 (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()