diff --git a/opm/output/eclipse/AggregateGroupData.hpp b/opm/output/eclipse/AggregateGroupData.hpp index eb7f8bf42..932213b6b 100644 --- a/opm/output/eclipse/AggregateGroupData.hpp +++ b/opm/output/eclipse/AggregateGroupData.hpp @@ -23,7 +23,7 @@ #include #include - +#include #include #include #include @@ -32,7 +32,8 @@ namespace Opm { class Schedule; class SummaryState; -class Group; +//class Group; +class UnitSystem; } // Opm namespace Opm { namespace RestartIO { namespace Helpers { @@ -42,10 +43,11 @@ class AggregateGroupData public: explicit AggregateGroupData(const std::vector& inteHead); - void captureDeclaredGroupData(const Opm::Schedule& sched, - const std::size_t simStep, - const Opm::SummaryState& sumState, - const std::vector& inteHead); + void captureDeclaredGroupData(const Opm::Schedule& sched, + const Opm::UnitSystem& units, + const std::size_t simStep, + const Opm::SummaryState& sumState, + const std::vector& inteHead); const std::vector& getIGroup() const { @@ -104,6 +106,19 @@ public: {"GGPTH", 143}, {"GGITH", 144}, }; + + + using inj_cmode_enum = Opm::Group::InjectionCMode; + const std::map cmodeToNum = { + + {inj_cmode_enum::NONE, 0}, + {inj_cmode_enum::RATE, 1}, + {inj_cmode_enum::RESV, 2}, + {inj_cmode_enum::REIN, 3}, + {inj_cmode_enum::VREP, 4}, + {inj_cmode_enum::FLD, 0}, + {inj_cmode_enum::SALE, 0}, + }; const std::map fieldKeyToIndex = { {"FOPR", 0}, diff --git a/opm/output/eclipse/AggregateWellData.hpp b/opm/output/eclipse/AggregateWellData.hpp index fea039e7c..1f8a43c03 100644 --- a/opm/output/eclipse/AggregateWellData.hpp +++ b/opm/output/eclipse/AggregateWellData.hpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -39,6 +40,11 @@ namespace Opm { namespace data { }} // Opm::data namespace Opm { namespace RestartIO { namespace Helpers { + + struct ActionResStatus { + std::vector result; + std::vector name; + }; class AggregateWellData { diff --git a/opm/output/eclipse/DoubHEAD.hpp b/opm/output/eclipse/DoubHEAD.hpp index d9e72ee54..86b9adfd5 100755 --- a/opm/output/eclipse/DoubHEAD.hpp +++ b/opm/output/eclipse/DoubHEAD.hpp @@ -40,6 +40,17 @@ namespace Opm { namespace RestartIO { std::chrono::duration elapsed; }; + struct guideRate { + double A; + double B; + double C; + double D; + double E; + double F; + double delay; + double damping_fact; + }; + DoubHEAD(); ~DoubHEAD() = default; @@ -61,6 +72,7 @@ namespace Opm { namespace RestartIO { const double cnvT); DoubHEAD& udq_param(const UDQParams& udqPar); + DoubHEAD& guide_rate_param(const guideRate& guide_rp); const std::vector& data() const { diff --git a/opm/output/eclipse/InteHEAD.hpp b/opm/output/eclipse/InteHEAD.hpp index d824d6f99..5969615d9 100755 --- a/opm/output/eclipse/InteHEAD.hpp +++ b/opm/output/eclipse/InteHEAD.hpp @@ -93,7 +93,11 @@ namespace Opm { namespace RestartIO { struct UdqParam { int udqParam_1; - int no_udqs; + int no_wudqs; + int no_gudqs; + int no_fudqs; + int no_iuads; + int no_iuaps; }; struct ActionParam { @@ -102,6 +106,11 @@ namespace Opm { namespace RestartIO { int max_no_conditions_per_action; int max_no_characters_per_line; }; + + struct GuideRateNominatedPhase { + int nominated_phase; + }; + InteHEAD(); ~InteHEAD() = default; @@ -122,6 +131,7 @@ namespace Opm { namespace RestartIO { InteHEAD& params_NWELZ(const int niwelz, const int nswelz, const int nxwelz, const int nzwelz); InteHEAD& params_NCON(const int niconz, const int nsconz, const int nxconz); InteHEAD& params_GRPZ(const std::array& grpz); + InteHEAD& params_NGCTRL(const int gct); InteHEAD& params_NAAQZ(const int ncamax, const int niaaqz, const int nsaaqz, const int nxaaqz, const int nicaqz, const int nscaqz, const int nacaqz); InteHEAD& stepParam(const int tstep, const int report_step); InteHEAD& tuningParam(const TuningPar& tunpar); @@ -131,6 +141,8 @@ namespace Opm { namespace RestartIO { InteHEAD& ngroups(const Group& gr); InteHEAD& udqParam_1(const UdqParam& udqpar); InteHEAD& actionParam(const ActionParam& act_par); + InteHEAD& variousUDQ_ACTIONXParam(); + InteHEAD& nominatedPhaseGuideRate(GuideRateNominatedPhase nphase); const std::vector& data() const { diff --git a/opm/output/eclipse/VectorItems/connection.hpp b/opm/output/eclipse/VectorItems/connection.hpp index 22e1d480b..a7b155c4a 100644 --- a/opm/output/eclipse/VectorItems/connection.hpp +++ b/opm/output/eclipse/VectorItems/connection.hpp @@ -57,6 +57,7 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems item30 = 29, // Unknown item31 = 30, // Unknown + item41 = 40, // = 0 for connection factor not defined, = 1 for connection factor defined }; } // SConn diff --git a/opm/output/eclipse/VectorItems/doubhead.hpp b/opm/output/eclipse/VectorItems/doubhead.hpp index 7e76a8513..1905e158c 100644 --- a/opm/output/eclipse/VectorItems/doubhead.hpp +++ b/opm/output/eclipse/VectorItems/doubhead.hpp @@ -27,12 +27,20 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems // This is a subset of the items in src/opm/output/eclipse/DoubHEAD.cpp . // Promote items from that list to this in order to make them public. enum doubhead : std::vector::size_type { - 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) + TsInit = 1, // Maximum Length of Next Timestep + TsMaxz = 2, // Maximum Length of Timestep After Next + TsMinz = 3, // Minumum Length of All Timesteps + GRpar_a = 87, // Guiderate parameter A + GRpar_b = 88, // Guiderate parameter B + GRpar_c = 89, // Guiderate parameter C + GRpar_d = 90, // Guiderate parameter D + GRpar_e = 91, // Guiderate parameter E + GRpar_f = 92, // Guiderate parameter F + GRpar_int = 97, // Guiderate parameter delay interval + GRpar_damp = 144, // Guiderate parameter damping factor + 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/group.hpp b/opm/output/eclipse/VectorItems/group.hpp index 46853a081..2f9027b54 100644 --- a/opm/output/eclipse/VectorItems/group.hpp +++ b/opm/output/eclipse/VectorItems/group.hpp @@ -24,6 +24,30 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems { + + namespace SGroup { + enum prod_index : std::vector::size_type { + OilRateLimit = 6, // Group's oil production target/limit + WatRateLimit = 7, // Group's water production target/limit + GasRateLimit = 8, // Group's gas production target/limit + LiqRateLimit = 9, // Group's liquid production target/limit + }; + + enum inj_index : std::vector::size_type { + waterSurfRateLimit = 15, // Group's water surface volume injection rate target/limit + waterResRateLimit = 16, // Group's water reservoir volume injection rate target/limit + waterReinjectionLimit = 17, // Group's water reinjection fraction target/limit + waterVoidageLimit = 18, // Group's water voidage injection fraction target/limit + gasSurfRateLimit = 20, // Group's gas surface volume injection rate target/limit + gasResRateLimit = 21, // Group's gas reservoir volume injection rate target/limit + gasReinjectionLimit = 22, // Group's gas reinjection fraction target/limit + gasVoidageLimit = 23, // Group's gas voidage injection fraction target/limit + + }; + } // SGroup + + + namespace XGroup { enum index : std::vector::size_type { OilPrRate = 0, // Group's oil production rate diff --git a/opm/output/eclipse/VectorItems/intehead.hpp b/opm/output/eclipse/VectorItems/intehead.hpp index eed5e953c..458b8cb30 100644 --- a/opm/output/eclipse/VectorItems/intehead.hpp +++ b/opm/output/eclipse/VectorItems/intehead.hpp @@ -75,6 +75,10 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems NICAQZ = 45, // Number of data elements per aquifer connection in ICAQ array NSCAQZ = 46, // Number of data elements per aquifer connection in SCAQ array NACAQZ = 47, // Number of data elements per aquifer connection in ACAQ array + + NGCTRL = 51, // Index indicating if group control is used or not (1 - if group control, 0 if not) + + NGRNPH = 58, // Index indicating if group control is used or not (1 - if group control, 0 if not) DAY = 64, // Calendar day of report step (1..31) MONTH = 65, // Calendar month of report step (1..12) @@ -96,11 +100,14 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems NILBRZ = 180, // Number of entries per segment in ILBR array MAX_ACT_COND = 245, // Maximum number of conditions pr action - MAX_AN_AQUIFERS = 252, // Maximum number of analytic aquifers - NO_UDQS = 266, // No of UDQ data (parameters) - UDQPAR_1 = 267, // Integer seed value for the RAND + NO_FIELD_UDQS = 262, // No of Field UDQ data (parameters) / + NO_GROUP_UDQS = 263, // No of Group UDQ data (parameters) / + NO_WELL_UDQS = 266, // No of Well UDQ data (parameters) / + UDQPAR_1 = 267, // Integer seed value for the RAND / + NO_IUADS = 290, // No IUADs + NO_IUAPS = 291, // No IUAPs RSEED = 296, }; }}}} // Opm::RestartIO::Helpers::VectorItems diff --git a/opm/output/eclipse/VectorItems/msw.hpp b/opm/output/eclipse/VectorItems/msw.hpp index b205368c5..4037c6f39 100644 --- a/opm/output/eclipse/VectorItems/msw.hpp +++ b/opm/output/eclipse/VectorItems/msw.hpp @@ -39,6 +39,7 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems namespace Value { enum SegmentType : int { + REGULAR = -1, AICD = -8, SICD = -7, Valve = -5, diff --git a/opm/output/eclipse/VectorItems/well.hpp b/opm/output/eclipse/VectorItems/well.hpp index 1e3ec5dbb..9dc08c904 100644 --- a/opm/output/eclipse/VectorItems/well.hpp +++ b/opm/output/eclipse/VectorItems/well.hpp @@ -180,6 +180,7 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems namespace ZWell { enum index : std::vector::size_type { WellName = 0, // Well name + ActionX = 2, // ActionX name }; } // ZWell }}}} // Opm::RestartIO::Helpers::VectorItems diff --git a/opm/parser/eclipse/EclipseState/Schedule/Action/ActionResult.hpp b/opm/parser/eclipse/EclipseState/Schedule/Action/ActionResult.hpp index 1f60ef7b4..d8a568692 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Action/ActionResult.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Action/ActionResult.hpp @@ -95,11 +95,15 @@ public: explicit operator bool() const; std::vector wells() const; - bool has_well(const std::string& well); + + bool has_well(const std::string& well) const; + void add_well(const std::string& well); Result& operator|=(const Result& other); + Result& operator=(const Result& src); Result& operator&=(const Result& other); + private: void assign(bool value); bool result; diff --git a/opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp b/opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp index 17f3f6e00..02e2ea2c7 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Group/Group.hpp @@ -197,6 +197,7 @@ struct ProductionControls { InjectionControls injectionControls(const SummaryState& st) const; const GroupProductionProperties& productionProperties() const; const GroupInjectionProperties& injectionProperties() const; + const GroupType& getGroupType() const; ProductionCMode production_cmode() const; InjectionCMode injection_cmode() const; Phase injection_phase() const; diff --git a/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateModel.hpp b/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateModel.hpp index d615b132c..39a81b62a 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateModel.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateModel.hpp @@ -62,7 +62,13 @@ public: bool operator==(const GuideRateModel& other) const; bool operator!=(const GuideRateModel& other) const; Target target() const; - + double getA() const; + double getB() const; + double getC() const; + double getD() const; + double getE() const; + double getF() const; + static Target convert_target(Group::GuideRateTarget group_target); static Target convert_target(Well::GuideRateTarget well_target); static double pot(Target target, double oil_pot, double gas_pot, double wat_pot); diff --git a/src/opm/output/eclipse/AggregateActionxData.cpp b/src/opm/output/eclipse/AggregateActionxData.cpp index 4cc19f339..af5d38c26 100644 --- a/src/opm/output/eclipse/AggregateActionxData.cpp +++ b/src/opm/output/eclipse/AggregateActionxData.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -30,6 +31,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -42,7 +46,7 @@ #include // ##################################################################### -// Class Opm::RestartIO::Helpers::AggregateGroupData +// Class Opm::RestartIO::Helpers // --------------------------------------------------------------------- @@ -55,6 +59,25 @@ namespace { {"M", 11}, {"Y", 12}, }; + + /*const std::map lhsQuantityToItem_12 = { + {"F", 0}, + {"W", 0}, + {"G", 0}, + {"D", 0}, + {"M", 1}, + {"Y", 0}, + };*/ + + using cmp_enum = Opm::Action::Condition::Comparator; + const std::map cmpToIacn_12 = { + {cmp_enum::GREATER, 0}, + {cmp_enum::LESS, 1}, + {cmp_enum::GREATER_EQUAL, 0}, + {cmp_enum::LESS_EQUAL, 1}, + {cmp_enum::EQUAL, 1}, + {cmp_enum::INVALID, 0}, + }; const std::map monthToNo = { {"JAN", 1.}, @@ -72,35 +95,35 @@ namespace { }; - const std::map rhsQuantityToIndex = { - {"F", 1}, - {"W", 2}, - {"G", 3}, - }; - - using logic_enum = Opm::Action::Condition::Logical; - const std::map logicalToIndex_13 = { - {logic_enum::AND, 1}, - {logic_enum::OR, 2}, - {logic_enum::END, 0}, - }; - - const std::map logicalToIndex_17 = { - {logic_enum::AND, 1}, - {logic_enum::OR, 0}, - {logic_enum::END, 0}, - }; +const std::map rhsQuantityToIndex = { + {"F", 1}, + {"W", 2}, + {"G", 3}, +}; +using logic_enum = Opm::Action::Condition::Logical; +const std::map logicalToIndex_13 = { + {logic_enum::AND, 1}, + {logic_enum::OR, 2}, + {logic_enum::END, 0}, +}; - using cmp_enum = Opm::Action::Condition::Comparator; - const std::map cmpToIndex = { - {cmp_enum::GREATER, 1}, - {cmp_enum::LESS, 2}, - {cmp_enum::GREATER_EQUAL, 3}, - {cmp_enum::LESS_EQUAL, 4}, - {cmp_enum::EQUAL, 5}, - {cmp_enum::INVALID, 0}, - }; +const std::map logicalToIndex_17 = { + {logic_enum::AND, 1}, + {logic_enum::OR, 0}, + {logic_enum::END, 0}, +}; + + +using cmp_enum = Opm::Action::Condition::Comparator; +const std::map cmpToIndex = { + {cmp_enum::GREATER, 1}, + {cmp_enum::LESS, 2}, + {cmp_enum::GREATER_EQUAL, 3}, + {cmp_enum::LESS_EQUAL, 4}, + {cmp_enum::EQUAL, 5}, + {cmp_enum::INVALID, 0}, +}; namespace iACT { @@ -109,9 +132,12 @@ namespace { allocate(const std::vector& actDims) { using WV = Opm::RestartIO::Helpers::WindowedArray; + + int nwin = std::max(actDims[0], 1); + int nitPrWin = std::max(actDims[1], 1); return WV { - WV::NumWindows{ static_cast(actDims[0]) }, - WV::WindowSize{ static_cast(actDims[1]) } + WV::NumWindows{ static_cast(nwin) }, + WV::WindowSize{ static_cast(nitPrWin) } }; } @@ -122,8 +148,18 @@ namespace { iAct[0] = 0; //item [1]: The number of lines of schedule data including ENDACTIO iAct[1] = actx.keyword_strings().size(); - //item [2]: is unknown, (=1) - iAct[2] = 1; + //item [2]: is = 1 for condition and previous condition = AND, and combinations OR/AND + // is = 2 for all conditions and previous conditions = OR + // This is not implemented yet - only use 1 for all cases + const auto& actx_cond = actx.conditions(); + int i_temp = 2; + for (auto cond_it = actx_cond.begin(); cond_it < actx_cond.end(); cond_it++) { + const auto it_logic_17 = logicalToIndex_17.find(cond_it->logic); + if (it_logic_17 != logicalToIndex_17.end()) { + if (it_logic_17->first == logic_enum::AND) i_temp = 1; + } + } + iAct[2] = i_temp; //item [3]: is unknown, (=7) iAct[3] = 7; //item [4]: is unknown, (=0) @@ -146,9 +182,12 @@ namespace { allocate(const std::vector& actDims) { using WV = Opm::RestartIO::Helpers::WindowedArray; + + int nwin = std::max(actDims[0], 1); + int nitPrWin = std::max(actDims[2], 1); return WV { - WV::NumWindows{ static_cast(actDims[0]) }, - WV::WindowSize{ static_cast(actDims[2]) } + WV::NumWindows{ static_cast(nwin) }, + WV::WindowSize{ static_cast(nitPrWin) } }; } @@ -173,10 +212,12 @@ namespace { using WV = Opm::RestartIO::Helpers::WindowedArray< Opm::EclIO::PaddedOutputString<8> >; - + + int nwin = std::max(actDims[0], 1); + int nitPrWin = std::max(actDims[3], 1); return WV { - WV::NumWindows{ static_cast(actDims[0]) }, - WV::WindowSize{ static_cast(actDims[3]) } + WV::NumWindows{ static_cast(nwin) }, + WV::WindowSize{ static_cast(nitPrWin) } }; } @@ -198,10 +239,11 @@ namespace { using WV = Opm::RestartIO::Helpers::WindowedArray< Opm::EclIO::PaddedOutputString<8> >; - + int nwin = std::max(actDims[0], 1); + int nitPrWin = std::max(actDims[4], 1); return WV { - WV::NumWindows{ static_cast(actDims[0]) }, - WV::WindowSize{ static_cast(actDims[4]) } + WV::NumWindows{ static_cast(nwin) }, + WV::WindowSize{ static_cast(nitPrWin) } }; } @@ -243,9 +285,11 @@ namespace { Opm::EclIO::PaddedOutputString<8> >; + int nwin = std::max(actDims[0], 1); + int nitPrWin = std::max(actDims[5], 1); return WV { - WV::NumWindows{ static_cast(actDims[0]) }, - WV::WindowSize{ static_cast(actDims[5]) } + WV::NumWindows{ static_cast(nwin) }, + WV::WindowSize{ static_cast(nitPrWin) } }; } @@ -291,8 +335,6 @@ namespace { } } } // zAcn - -} namespace iACN { @@ -300,9 +342,12 @@ namespace { allocate(const std::vector& actDims) { using WV = Opm::RestartIO::Helpers::WindowedArray; + + int nwin = std::max(actDims[0], 1); + int nitPrWin = std::max(actDims[6], 1); return WV { - WV::NumWindows{ static_cast(actDims[0]) }, - WV::WindowSize{ static_cast(actDims[6]) } + WV::NumWindows{ static_cast(nwin) }, + WV::WindowSize{ static_cast(nitPrWin) } }; } @@ -352,13 +397,13 @@ namespace { iAcn[ind + 11] = it_rhsq->second; } - /*item[12] - index for lhs type - 1 - for MNTH - 0 - for all other types + /*item[12] - index for relational operator (<, =, > ) + 0 - for LHS quantity greater RHS quantity + 1 - for LHS quantity less than or equal to RHS quantity */ - std::string lhsQ = z_data.lhs.quantity; - if ( lhsQ == "MNTH") { - iAcn[ind + 12] = 1; + const auto it_lhs_it = cmpToIacn_12.find(z_data.cmp); + if (it_lhs_it != cmpToIacn_12.end()) { + iAcn[ind + 12] = it_lhs_it->second; } /*item [13] - relates to operator @@ -424,42 +469,62 @@ namespace { allocate(const std::vector& actDims) { using WV = Opm::RestartIO::Helpers::WindowedArray; + + int nwin = std::max(actDims[0], 1); + int nitPrWin = std::max(actDims[7], 1); return WV { - WV::NumWindows{ static_cast(actDims[0]) }, - WV::WindowSize{ static_cast(actDims[7]) } + WV::NumWindows{ static_cast(nwin) }, + WV::WindowSize{ static_cast(nitPrWin) } }; } + + Opm::Action::Result + act_res(const Opm::Schedule& sched, const Opm::SummaryState& smry, const std::size_t sim_step, std::vector::const_iterator act_x) { + Opm::Action::Result ar(false); + Opm::Action::Context context(smry); + auto sim_time = sched.simTime(sim_step); + if (act_x->ready(sim_time)) { + ar = act_x->eval(sim_time, context); + } + return {ar}; + } template - void staticContrib(const Opm::Action::ActionX& actx, - const Opm::SummaryState& st, - SACNArray& sAcn) + void staticContrib(std::vector::const_iterator actx_it, + const Opm::SummaryState& st, + const Opm::Schedule& sched, + const std::size_t simStep, + SACNArray& sAcn) { std::size_t ind = 0; int noEPZacn = 16; double undef_high_val = 1.0E+20; + const auto& wells = sched.getWells(simStep); + const auto ar = sACN::act_res(sched, st, simStep, actx_it); // write out the schedule Actionx conditions - const auto& actx_cond = actx.conditions(); + const auto& actx_cond = actx_it->conditions(); for (const auto& z_data : actx_cond) { // item [0 - 1] = 0 (unknown) sAcn[ind + 0] = 0.; sAcn[ind + 1] = 0.; - //item [2, 5, 7, 9]: value of condition 1 (zero if well, group or field variable + const std::string& lhsQtype = z_data.lhs.quantity.substr(0,1); const std::string& rhsQtype = z_data.rhs.quantity.substr(0,1); + + //item [2, 5, 7, 9]: value of condition 1 (zero if well, group or field variable const auto& it_rhsq = rhsQuantityToIndex.find(rhsQtype); if (it_rhsq == rhsQuantityToIndex.end()) { //come here if constant value condition double t_val = 0.; - if (rhsQtype == "M") { + if (lhsQtype == "M") { const auto& it_mnth = monthToNo.find(z_data.rhs.quantity); if (it_mnth != monthToNo.end()) { t_val = it_mnth->second; } else { std::cout << "Unknown Month: " << z_data.rhs.quantity << std::endl; - throw std::invalid_argument("Actionx: " + actx.name() + " Condition: " + z_data.lhs.quantity ); + throw std::invalid_argument("Actionx: " + actx_it->name() + " Condition: " + z_data.lhs.quantity ); } } else { @@ -470,39 +535,33 @@ namespace { sAcn[ind + 7] = sAcn[ind + 2]; sAcn[ind + 9] = sAcn[ind + 2]; } - //Treat well, group and field right hand side conditions + + + //Treat well, group and field right hand side conditions if (it_rhsq != rhsQuantityToIndex.end()) { //Well variable - if (it_rhsq->first == "W") { - sAcn[ind + 4] = st.get_well_var(z_data.rhs.args[0], z_data.rhs.quantity); + if ((it_rhsq->first == "W") && (st.has_well_var(z_data.rhs.args[0], z_data.rhs.quantity))) { sAcn[ind + 5] = st.get_well_var(z_data.rhs.args[0], z_data.rhs.quantity); - sAcn[ind + 6] = st.get_well_var(z_data.rhs.args[0], z_data.rhs.quantity); sAcn[ind + 7] = st.get_well_var(z_data.rhs.args[0], z_data.rhs.quantity); - sAcn[ind + 8] = st.get_well_var(z_data.rhs.args[0], z_data.rhs.quantity); sAcn[ind + 9] = st.get_well_var(z_data.rhs.args[0], z_data.rhs.quantity); } //group variable - if (it_rhsq->first == "G") { - sAcn[ind + 4] = st.get_group_var(z_data.rhs.args[0], z_data.rhs.quantity); + if ((it_rhsq->first == "G") && (st.has_group_var(z_data.rhs.args[0], z_data.rhs.quantity))) {; sAcn[ind + 5] = st.get_group_var(z_data.rhs.args[0], z_data.rhs.quantity); - sAcn[ind + 6] = st.get_group_var(z_data.rhs.args[0], z_data.rhs.quantity); sAcn[ind + 7] = st.get_group_var(z_data.rhs.args[0], z_data.rhs.quantity); - sAcn[ind + 8] = st.get_group_var(z_data.rhs.args[0], z_data.rhs.quantity); sAcn[ind + 9] = st.get_group_var(z_data.rhs.args[0], z_data.rhs.quantity); } //field variable - if (it_rhsq->first == "F") { - sAcn[ind + 4] = st.get(z_data.rhs.quantity); + if ((it_rhsq->first == "F") && (st.has(z_data.rhs.quantity))) { sAcn[ind + 5] = st.get(z_data.rhs.quantity); - sAcn[ind + 6] = st.get(z_data.rhs.quantity); sAcn[ind + 7] = st.get(z_data.rhs.quantity); - sAcn[ind + 8] = st.get(z_data.rhs.quantity); sAcn[ind + 9] = st.get(z_data.rhs.quantity); } } + + //treat cases with left hand side condition being: DAY, MNTH og YEAR variable - const std::string& lhsQtype = z_data.lhs.quantity.substr(0,1); const auto& it_lhsq = lhsQuantityToIndex.find(lhsQtype); if ((it_lhsq->first == "D") || (it_lhsq->first == "M") || (it_lhsq->first == "Y")) { sAcn[ind + 4] = undef_high_val; @@ -513,6 +572,41 @@ namespace { sAcn[ind + 9] = undef_high_val; } + //Treat well, group and field left hand side conditions + if (it_lhsq != lhsQuantityToIndex.end()) { + std::string wn = ""; + //Well variable + if (it_lhsq->first == "W") { + //find the well that violates action if relevant + for (const auto& well : wells) + { + if (ar.has_well(well.name())) { + //set well name + wn = well.name(); + break; + } + } + + if ((it_lhsq->first == "W") && (st.has_well_var(wn, z_data.lhs.quantity)) ) { + sAcn[ind + 4] = st.get_well_var(wn, z_data.lhs.quantity); + sAcn[ind + 6] = st.get_well_var(wn, z_data.lhs.quantity); + sAcn[ind + 8] = st.get_well_var(wn, z_data.lhs.quantity); + } + } + //group variable + if ((it_lhsq->first == "G") && (st.has_group_var(z_data.lhs.args[0], z_data.lhs.quantity))) { + sAcn[ind + 4] = st.get_group_var(z_data.lhs.args[0], z_data.lhs.quantity); + sAcn[ind + 6] = st.get_group_var(z_data.lhs.args[0], z_data.lhs.quantity); + sAcn[ind + 8] = st.get_group_var(z_data.lhs.args[0], z_data.lhs.quantity); + } + //field variable + if ((it_lhsq->first == "F") && (st.has(z_data.lhs.quantity))) { + sAcn[ind + 4] = st.get(z_data.lhs.quantity); + sAcn[ind + 6] = st.get(z_data.lhs.quantity); + sAcn[ind + 8] = st.get(z_data.lhs.quantity); + } + } + //increment index according to no of items pr condition ind += static_cast(noEPZacn); } @@ -520,7 +614,7 @@ namespace { } // sAcn - +} // ===================================================================== Opm::RestartIO::Helpers::AggregateActionxData:: @@ -543,7 +637,7 @@ captureDeclaredActionxData( const Opm::Schedule& sched, const std::vector& actDims, const std::size_t simStep) { - auto acts = sched.actions(simStep); + const auto acts = sched.actions(simStep); std::size_t act_ind = 0; for (auto actx_it = acts.begin(); actx_it < acts.end(); actx_it++) { { @@ -578,7 +672,7 @@ captureDeclaredActionxData( const Opm::Schedule& sched, { auto s_acn = this->sACN_[act_ind]; - sACN::staticContrib(*actx_it, st, s_acn); + sACN::staticContrib(actx_it, st, sched, simStep, s_acn); } act_ind +=1; diff --git a/src/opm/output/eclipse/AggregateConnectionData.cpp b/src/opm/output/eclipse/AggregateConnectionData.cpp index 3a5731e7e..5a39edc5c 100755 --- a/src/opm/output/eclipse/AggregateConnectionData.cpp +++ b/src/opm/output/eclipse/AggregateConnectionData.cpp @@ -191,6 +191,7 @@ namespace { sConn[Ix::item30] = -1.0e+20f; sConn[Ix::item31] = -1.0e+20f; + sConn[Ix::item41] = (conn.CF() > 0) ? 1 : 0; } } // SConn diff --git a/src/opm/output/eclipse/AggregateGroupData.cpp b/src/opm/output/eclipse/AggregateGroupData.cpp index 4b61a22d3..b3ab34b8f 100644 --- a/src/opm/output/eclipse/AggregateGroupData.cpp +++ b/src/opm/output/eclipse/AggregateGroupData.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -123,12 +124,14 @@ allocate(const std::vector& inteHead) } template -void staticContrib(const Opm::Schedule& sched, - const Opm::Group& group, - const int nwgmax, - const int ngmaxz, - const std::size_t simStep, - IGrpArray& iGrp) +void staticContrib(const Opm::Schedule& sched, + const Opm::Group& group, + const int nwgmax, + const int ngmaxz, + const std::size_t simStep, + const Opm::SummaryState& sumState, + const std::map cmodeToNum, + IGrpArray& iGrp) { if (group.wellgroup()) { int igrpCount = 0; @@ -151,6 +154,88 @@ void staticContrib(const Opm::Schedule& sched, //assign the number of child wells or child groups to // location nwgmax iGrp[nwgmax] = groupSize(group); + + /*IGRP[NWGMAX + 5] + = -1 group under higher group control + = 0 for NONE (no control) + = 1 group under rate control + */ + + if ((group.getGroupType() == Opm::Group::GroupType::NONE) || (group.getGroupType() == Opm::Group::GroupType::PRODUCTION) ) { + const auto& prod_cmode = group.production_cmode(); + std::cout << "IGRP[nwgmax + 5] group.name()" << group.name() << " prod_cmode " << static_cast(prod_cmode) << std::endl; + + if (prod_cmode == Opm::Group::ProductionCMode::FLD) { + iGrp[nwgmax + 5] = -1; + } + else if (prod_cmode == Opm::Group::ProductionCMode::NONE) { + iGrp[nwgmax + 5] = 0; + } + else { + iGrp[nwgmax + 5] = 1; + } + + // Set iGrp for [nwgmax + 7] + /* + = 0 for group with "FLD" or "NONE" + = 4 for "GRAT" FIELD + = -40000 for production group with "ORAT" + = -4000 for production group with "WRAT" + = -400 for production group with "GRAT" + = -40 for production group with "LRAT" + */ + + if ((prod_cmode == Opm::Group::ProductionCMode::NONE) || prod_cmode == Opm::Group::ProductionCMode::FLD) { + iGrp[nwgmax + 7] = 0; + } + else if ((prod_cmode == Opm::Group::ProductionCMode::ORAT)) { + iGrp[nwgmax + 7] = -40000; + } + else if ((prod_cmode == Opm::Group::ProductionCMode::WRAT)) { + iGrp[nwgmax + 7] = -4000; + } + else if ((prod_cmode == Opm::Group::ProductionCMode::GRAT)) { + iGrp[nwgmax + 7] = -400; + if (group.name() == "FIELD") { + iGrp[nwgmax + 7] = 4; + } + } + else if ((prod_cmode == Opm::Group::ProductionCMode::LRAT)) { + iGrp[nwgmax + 7] = -40; + } + } + //Set injection group status + //item[nwgmax + 16] - mode for operation for injection group + // 1 - RATE + // 2 - RESV + // 3 - REIN + // 4 - VREP + // 0 - ellers + + if (group.isInjectionGroup()) { + const auto& inj_cntl = group.injectionControls(sumState); + const auto& inj_mode = inj_cntl.cmode; + const auto& phs = inj_cntl.phase; + //Gas injection control + if (phs == Opm::Phase::WATER) { + const auto it = cmodeToNum.find(inj_mode); + if (it != cmodeToNum.end()) { + iGrp[nwgmax + 16] = it->second; + iGrp[nwgmax + 18] = iGrp[nwgmax + 16]; + iGrp[nwgmax + 19] = iGrp[nwgmax + 16]; + } + } + //Water injection control + else if (phs == Opm::Phase::GAS) { + const auto it = cmodeToNum.find(inj_mode); + if (it != cmodeToNum.end()) { + iGrp[nwgmax + 21] = it->second; + iGrp[nwgmax + 23] = iGrp[nwgmax + 21]; + iGrp[nwgmax + 24] = iGrp[nwgmax + 21]; + } + } + } + iGrp[nwgmax + 26] = groupType(group); //find group level ("FIELD" is level 0) and store the level in @@ -161,7 +246,7 @@ void staticContrib(const Opm::Schedule& sched, // if (group.name() != "FIELD") { - iGrp[nwgmax+ 5] = -1; + //iGrp[nwgmax+ 5] = -1; iGrp[nwgmax+12] = -1; iGrp[nwgmax+17] = -1; iGrp[nwgmax+22] = -1; @@ -192,6 +277,7 @@ void staticContrib(const Opm::Schedule& sched, else iGrp[nwgmax+28] = parent_group.insert_index(); } + } } // Igrp @@ -214,8 +300,15 @@ allocate(const std::vector& inteHead) } template -void staticContrib(SGrpArray& sGrp) +void staticContrib(const Opm::Group& group, + const Opm::SummaryState& sumState, + const Opm::UnitSystem& units, + SGrpArray& sGrp) { + using Isp = ::Opm::RestartIO::Helpers::VectorItems::SGroup::prod_index; + using Isi = ::Opm::RestartIO::Helpers::VectorItems::SGroup::inj_index; + using M = ::Opm::UnitSystem::measure; + const auto dflt = -1.0e+20f; const auto dflt_2 = -2.0e+20f; const auto infty = 1.0e+20f; @@ -256,6 +349,67 @@ void staticContrib(SGrpArray& sGrp) auto e = b + std::min(init.size(), sz); std::copy(b, e, std::begin(sGrp)); + + auto sgprop = [&units](const M u, const double x) -> float + { + return static_cast(units.from_si(u, x)); + }; + + if (group.isProductionGroup()) { + const auto& prod_cntl = group.productionControls(sumState); + + if (prod_cntl.oil_target > 0.) { + sGrp[Isp::OilRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.oil_target); + sGrp[37] = sGrp[Isp::OilRateLimit]; + sGrp[52] = sGrp[Isp::OilRateLimit]; // "ORAT" control + } + if (prod_cntl.water_target > 0.) { + sGrp[Isp::WatRateLimit > 0.] = sgprop(M::liquid_surface_rate, prod_cntl.water_target); + sGrp[38] = sGrp[Isp::WatRateLimit]; + sGrp[53] = sGrp[Isp::WatRateLimit]; //"WRAT" control + } + if (prod_cntl.gas_target > 0.) { + sGrp[Isp::GasRateLimit] = sgprop(M::gas_surface_rate, prod_cntl.gas_target); + sGrp[39] = sGrp[Isp::GasRateLimit]; + } + if (prod_cntl.liquid_target > 0.) { + sGrp[Isp::LiqRateLimit] = sgprop(M::liquid_surface_rate, prod_cntl.liquid_target); + sGrp[40] = sGrp[Isp::LiqRateLimit]; + } + } + + if (group.isInjectionGroup()) { + const auto& inj_cntl = group.injectionControls(sumState); + const auto& phs = inj_cntl.phase; + if (phs == Opm::Phase::GAS) { + if (inj_cntl.surface_max_rate > 0.) { + sGrp[Isi::gasSurfRateLimit] = sgprop(M::gas_surface_rate, inj_cntl.surface_max_rate); + } + if (inj_cntl.resv_max_rate > 0.) { + sGrp[Isi::gasResRateLimit > 0.] = sgprop(M::rate, inj_cntl.resv_max_rate); + } + if (inj_cntl.target_reinj_fraction > 0.) { + sGrp[Isi::gasReinjectionLimit] = inj_cntl.target_reinj_fraction; + } + if (inj_cntl.target_void_fraction > 0.) { + sGrp[Isi::gasVoidageLimit] = inj_cntl.target_void_fraction; + } + } + if (phs == Opm::Phase::WATER) { + if (inj_cntl.surface_max_rate > 0.) { + sGrp[Isi::waterSurfRateLimit] = sgprop(M::liquid_surface_rate, inj_cntl.surface_max_rate); + } + if (inj_cntl.resv_max_rate > 0.) { + sGrp[Isi::waterResRateLimit > 0.] = sgprop(M::rate, inj_cntl.resv_max_rate); + } + if (inj_cntl.target_reinj_fraction > 0.) { + sGrp[Isi::waterReinjectionLimit] = inj_cntl.target_reinj_fraction; + } + if (inj_cntl.target_void_fraction > 0.) { + sGrp[Isi::waterVoidageLimit] = inj_cntl.target_void_fraction; + } + } + } } } // SGrp @@ -355,6 +509,7 @@ AggregateGroupData(const std::vector& inteHead) void Opm::RestartIO::Helpers::AggregateGroupData:: captureDeclaredGroupData(const Opm::Schedule& sched, + const Opm::UnitSystem& units, const std::size_t simStep, const Opm::SummaryState& sumState, const std::vector& inteHead) @@ -367,21 +522,21 @@ captureDeclaredGroupData(const Opm::Schedule& sched, curGroups[ind] = std::addressof(group); } - groupLoop(curGroups, [&sched, simStep, this] + groupLoop(curGroups, [&sched, simStep, sumState, this] (const Group& group, const std::size_t groupID) -> void { auto ig = this->iGroup_[groupID]; IGrp::staticContrib(sched, group, this->nWGMax_, this->nGMaxz_, - simStep, ig); + simStep, sumState, this->cmodeToNum, ig); }); // Define Static Contributions to SGrp Array. groupLoop(curGroups, - [this](const Group& /* group */, const std::size_t groupID) -> void + [&sumState, &units, this](const Group& group , const std::size_t groupID) -> void { auto sw = this->sGroup_[groupID]; - SGrp::staticContrib(sw); + SGrp::staticContrib(group, sumState, units, sw); }); // Define Dynamic Contributions to XGrp Array. diff --git a/src/opm/output/eclipse/AggregateMSWData.cpp b/src/opm/output/eclipse/AggregateMSWData.cpp index 344021200..c6041170e 100644 --- a/src/opm/output/eclipse/AggregateMSWData.cpp +++ b/src/opm/output/eclipse/AggregateMSWData.cpp @@ -30,7 +30,7 @@ #include #include #include - +#include #include #include @@ -418,21 +418,24 @@ namespace { const std::size_t baseIndex, ISegArray& iSeg) { - namespace ISegValue = ::Opm::RestartIO::Helpers:: - VectorItems::ISeg::Value; + + using IsTyp = ::Opm::RestartIO::Helpers:: + VectorItems::ISeg::Value::SegmentType; + using IsStatus = ::Opm::RestartIO::Helpers:: + VectorItems::ISeg::Value::SICDStatus; using Ix = ::Opm::RestartIO::Helpers:: VectorItems::ISeg::index; const auto& sicd = segment.spiralICD(); - iSeg[baseIndex + Ix::SegmentType] = ISegValue::SegmentType::SICD; + iSeg[baseIndex + Ix::SegmentType] = IsTyp::SICD; iSeg[baseIndex + Ix::ICDScalingMode] = sicd->methodFlowScaling(); iSeg[baseIndex + Ix::ICDOpenShutFlag] = (sicd->status() == Opm::SpiralICD::Status::OPEN) - ? ISegValue::SICDStatus::Open - : ISegValue::SICDStatus::Shut; + ? IsStatus::Open + : IsStatus::Shut; } template @@ -467,6 +470,11 @@ namespace { const std::vector& inteHead, ISegArray& iSeg) { + using IsTyp = ::Opm::RestartIO::Helpers:: + VectorItems::ISeg::Value::SegmentType; + using Ix = ::Opm::RestartIO::Helpers:: + VectorItems::ISeg::index; + if (well.isMultiSegment()) { //loop over segment set and print out information const auto& welSegSet = well.getSegments(); @@ -474,6 +482,12 @@ namespace { const auto& noElmSeg = nisegz(inteHead); std::size_t segmentInd = 0; auto orderedSegmentNo = segmentOrder(welSegSet, segmentInd); + std::vector seg_reorder (welSegSet.size(),0); + for (int ind = 0; ind < welSegSet.size(); ind++ ){ + const auto s_no = welSegSet[orderedSegmentNo[ind]].segmentNumber(); + const auto s_ind = welSegSet.segmentNumberToIndex(s_no); + seg_reorder[s_ind] = ind+1; + } for (int ind = 0; ind < welSegSet.size(); ind++) { const auto& segment = welSegSet[ind]; @@ -487,11 +501,14 @@ namespace { iSeg[iS + 5] = sumNoInFlowBranches(welSegSet, ind); iSeg[iS + 6] = noConnectionsSegment(completionSet, welSegSet, ind); iSeg[iS + 7] = sumConnectionsSegment(completionSet, welSegSet, ind); - iSeg[iS + 8] = iSeg[iS+0]; + iSeg[iS + 8] = seg_reorder[ind]; if (! isRegular(segment)) { assignSegmentTypeCharacteristics(segment, iS, iSeg); } + else if (segment.segmentType() == Opm::Segment::SegmentType::REGULAR) { + iSeg[iS + Ix::SegmentType] = IsTyp::REGULAR; + } } } else { diff --git a/src/opm/output/eclipse/AggregateUDQData.cpp b/src/opm/output/eclipse/AggregateUDQData.cpp index f547dfffd..9f1053116 100644 --- a/src/opm/output/eclipse/AggregateUDQData.cpp +++ b/src/opm/output/eclipse/AggregateUDQData.cpp @@ -17,9 +17,12 @@ along with OPM. If not, see . */ +#include #include #include #include +#include +#include #include #include @@ -46,7 +49,7 @@ // Class Opm::RestartIO::Helpers::AggregateGroupData // --------------------------------------------------------------------- - +namespace VI = ::Opm::RestartIO::Helpers::VectorItems; namespace { // maximum number of groups @@ -56,12 +59,36 @@ namespace { } // maximum number of wells - /*std::size_t nwmaxz(const std::vector& inteHead) + std::size_t nwmaxz(const std::vector& inteHead) { return inteHead[163]; - }*/ + } + // Categorize function in terms of which token-types are used in formula + int define_type(const std::set tokens) { + int type = -4; + std::vector type_1 = { + Opm::UDQTokenType::elemental_func_sorta, + Opm::UDQTokenType::elemental_func_sortd, + Opm::UDQTokenType::elemental_func_undef, + Opm::UDQTokenType::scalar_func_sum, + Opm::UDQTokenType::scalar_func_avea, + Opm::UDQTokenType::scalar_func_aveg, + Opm::UDQTokenType::scalar_func_aveh, + Opm::UDQTokenType::scalar_func_max, + Opm::UDQTokenType::scalar_func_min, + Opm::UDQTokenType::binary_op_div + }; + + int num_type_1 = 0; + for (const auto& tok_type : type_1) { + num_type_1 += tokens.count(tok_type); + } + type = (num_type_1 > 0) ? -1 : -4; + return type; + } + namespace iUdq { @@ -80,8 +107,10 @@ namespace { void staticContrib(const Opm::UDQInput& udq_input, IUDQArray& iUdq) { if (udq_input.is()) { + const auto& udq_define = udq_input.get(); + const auto& tokens = udq_define.func_tokens(); iUdq[0] = 2; - iUdq[1] = -4; + iUdq[1] = define_type(tokens); } else { iUdq[0] = 0; iUdq[1] = -4; @@ -442,6 +471,8 @@ captureDeclaredUDQData(const Opm::Schedule& sched, const std::vector& inteHead) { const auto& udqCfg = sched.getUDQConfig(simStep); + const auto nudq = inteHead[VI::intehead::NO_WELL_UDQS] + inteHead[VI::intehead::NO_GROUP_UDQS] + inteHead[VI::intehead::NO_FIELD_UDQS]; + int cnt_udq = 0; for (const auto& udq_input : udqCfg.input()) { auto udq_index = udq_input.index.insert_index; { @@ -456,66 +487,119 @@ captureDeclaredUDQData(const Opm::Schedule& sched, auto z_udl = this->zUDL_[udq_index]; zUdl::staticContrib(udq_input, z_udl); } + cnt_udq += 1; } - + if (cnt_udq != nudq) { + std::stringstream str; + str << "Inconsistent total number of udqs: " << cnt_udq << " and sum of well, group and field udqs: " << nudq; + OpmLog::error(str.str()); + } + + auto udq_active = sched.udqActive(simStep); if (udq_active) { const auto& udq_records = udq_active.get_iuad(); + int cnt_iuad = 0; 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); + cnt_iuad += 1; + } + if (cnt_iuad != inteHead[VI::intehead::NO_IUADS]) { + std::stringstream str; + str << "Inconsistent number of iuad's: " << cnt_iuad << " number of iuad's from intehead " << inteHead[VI::intehead::NO_IUADS]; + OpmLog::error(str.str()); } const auto& iuap_records = udq_active.get_iuap(); + int cnt_iuap = 0; 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); + cnt_iuap += 1; + } + if (cnt_iuap != inteHead[VI::intehead::NO_IUAPS]) { + std::stringstream str; + str << "Inconsistent number of iuap's: " << cnt_iuap << " number of iuap's from intehead " << inteHead[VI::intehead::NO_IUAPS]; + OpmLog::error(str.str()); } + } - 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); + if (inteHead[VI::intehead::NO_GROUP_UDQS] > 0) { + Opm::RestartIO::Helpers::igphData igph_dat; + int cnt_igph = 0; + 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); + cnt_igph += 1; } -#if 0 + if (cnt_igph != inteHead[VI::intehead::NGMAXZ]) { + std::stringstream str; + str << "Inconsistent number of igph's: " << cnt_igph << " number of igph's from intehead " << inteHead[VI::intehead::NGMAXZ]; + OpmLog::error(str.str()); + } + } + std::size_t i_wudq = 0; const auto& wnames = sched.wellNames(simStep); const auto nwmax = nwmaxz(inteHead); + int cnt_dudw = 0; for (const auto& udq_input : udqCfg.input()) { if (udq_input.var_type() == UDQVarType::WELL_VAR) { const std::string& udq = udq_input.keyword(); auto i_dudw = this->dUDW_[i_wudq]; dUdw::staticContrib(st, wnames, udq, nwmax, i_dudw); i_wudq++; + cnt_dudw += 1; } } -#endif + if (cnt_dudw != inteHead[VI::intehead::NO_WELL_UDQS]) { + std::stringstream str; + str << "Inconsistent number of dudw's: " << cnt_dudw << " number of dudw's from intehead " << inteHead[VI::intehead::NO_WELL_UDQS]; + OpmLog::error(str.str()); + } + std::size_t i_gudq = 0; const auto curGroups = currentGroups(sched, simStep, inteHead); const auto ngmax = ngmaxz(inteHead); + int cnt_dudg = 0; for (const auto& udq_input : udqCfg.input()) { if (udq_input.var_type() == UDQVarType::GROUP_VAR) { const std::string& udq = udq_input.keyword(); auto i_dudg = this->dUDG_[i_gudq]; dUdg::staticContrib(st, curGroups, udq, ngmax, i_dudg); i_gudq++; + cnt_dudg += 1; } } + if (cnt_dudg != inteHead[VI::intehead::NO_GROUP_UDQS]) { + std::stringstream str; + str << "Inconsistent number of dudg's: " << cnt_dudg << " number of dudg's from intehead " << inteHead[VI::intehead::NO_GROUP_UDQS]; + OpmLog::error(str.str()); + } std::size_t i_fudq = 0; + int cnt_dudf = 0; for (const auto& udq_input : udqCfg.input()) { if (udq_input.var_type() == UDQVarType::FIELD_VAR) { const std::string& udq = udq_input.keyword(); auto i_dudf = this->dUDF_[i_fudq]; dUdf::staticContrib(st, udq, i_dudf); i_fudq++; + cnt_dudf += 1; } } + if (cnt_dudf != inteHead[VI::intehead::NO_FIELD_UDQS]) { + std::stringstream str; + str << "Inconsistent number of dudf's: " << cnt_dudf << " number of dudf's from intehead " << inteHead[VI::intehead::NO_FIELD_UDQS]; + OpmLog::error(str.str()); + } + } diff --git a/src/opm/output/eclipse/AggregateWellData.cpp b/src/opm/output/eclipse/AggregateWellData.cpp index cbb325afc..7acc47d71 100644 --- a/src/opm/output/eclipse/AggregateWellData.cpp +++ b/src/opm/output/eclipse/AggregateWellData.cpp @@ -31,6 +31,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -72,6 +77,9 @@ namespace { // Remove leading/trailing blanks. return s.substr(b, e - b + 1); } + + + template void wellLoop(const std::vector& wells, @@ -407,11 +415,11 @@ namespace { zero , zero , infty, infty, zero , dflt , // 12.. 17 ( 2) infty, infty, infty, infty, infty, zero , // 18.. 23 ( 3) one , zero , zero , zero , zero , zero , // 24.. 29 ( 4) - zero , one , zero , zero, zero , zero , // 30.. 35 ( 5) + zero , one , zero , infty, zero , zero , // 30.. 35 ( 5) zero , zero , zero , zero , zero , zero , // 36.. 41 ( 6) zero , zero , zero , zero , zero , zero , // 42.. 47 ( 7) zero , zero , zero , zero , zero , zero , // 48.. 53 ( 8) - zero, zero , zero , zero , zero , zero , // 54.. 59 ( 9) + infty, zero , zero , zero , zero , zero , // 54.. 59 ( 9) zero , zero , zero , zero , zero , zero , // 60.. 65 (10) zero , zero , zero , zero , zero , zero , // 66.. 71 (11) zero , zero , zero , zero , zero , zero , // 72.. 77 (12) @@ -460,28 +468,28 @@ namespace { const auto& pc = well.productionControls(smry); const auto& predMode = well.predictionMode(); - if ((pc.oil_rate != 0.0) || (!predMode)) { + if (pc.oil_rate != 0.0) { sWell[Ix::OilRateTarget] = swprop(M::liquid_surface_rate, pc.oil_rate); } - if ((pc.water_rate != 0.0) || (!predMode)) { + if (pc.water_rate != 0.0) { sWell[Ix::WatRateTarget] = swprop(M::liquid_surface_rate, pc.water_rate); } - if ((pc.gas_rate != 0.0) || (!predMode)) { + if (pc.gas_rate != 0.0) { sWell[Ix::GasRateTarget] = swprop(M::gas_surface_rate, pc.gas_rate); sWell[Ix::HistGasRateTarget] = sWell[Ix::GasRateTarget]; } - if (pc.liquid_rate != 0.0 || (!predMode)) { + if (pc.liquid_rate != 0.0) { // check if this works - may need to be rewritten sWell[Ix::LiqRateTarget] = swprop(M::liquid_surface_rate, pc.liquid_rate); sWell[Ix::HistLiqRateTarget] = sWell[Ix::LiqRateTarget]; } - else { + else if (!predMode) { sWell[Ix::LiqRateTarget] = swprop(M::liquid_surface_rate, pc.oil_rate + pc.water_rate); } @@ -761,12 +769,31 @@ namespace { }; } + Opm::RestartIO::Helpers::ActionResStatus + act_res_stat(const Opm::Schedule& sched, const Opm::SummaryState& smry, const std::size_t sim_step) { + std::vector act_res; + std::vector act_name; + const auto acts = sched.actions(sim_step); + Opm::Action::Context context(smry); + auto sim_time = sched.simTime(sim_step); + for (const auto& action : acts.pending(sim_time)) { + act_res.push_back(action->eval(sim_time, context)); + act_name.push_back(action->name()); + } + return {act_res, act_name}; + } + template - void staticContrib(const Opm::Well& well, ZWellArray& zWell) + void staticContrib(const Opm::Well& well, const Opm::RestartIO::Helpers::ActionResStatus& actResStat, ZWellArray& zWell) { using Ix = ::Opm::RestartIO::Helpers::VectorItems::ZWell::index; - zWell[Ix::WellName] = well.name(); + //loop over actions to assign action name for relevant wells + for (std::size_t ind = 0; ind < actResStat.result.size(); ind++) { + if (actResStat.result[ind].has_well(well.name())) { + zWell[Ix::ActionX] = actResStat.name[ind]; + } + } } } // ZWell } // Anonymous @@ -828,14 +855,16 @@ captureDeclaredWellData(const Schedule& sched, XWell::staticContrib(well, smry, units, xw); }); - // Static contributions to ZWEL array. - wellLoop(wells, - [this](const Well& well, const std::size_t wellID) -> void { - auto zw = this->zWell_[wellID]; - - ZWell::staticContrib(well, zw); - }); + const auto actResStat = ZWell::act_res_stat(sched, smry, sim_step); + // Static contributions to ZWEL array. + wellLoop(wells, + [&actResStat, this](const Well& well, const std::size_t wellID) -> void + { + auto zw = this->zWell_[wellID]; + ZWell::staticContrib(well, actResStat, zw); + }); + } } // --------------------------------------------------------------------- diff --git a/src/opm/output/eclipse/CreateDoubHead.cpp b/src/opm/output/eclipse/CreateDoubHead.cpp index 121ffb432..80f9eaf91 100755 --- a/src/opm/output/eclipse/CreateDoubHead.cpp +++ b/src/opm/output/eclipse/CreateDoubHead.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -67,6 +68,45 @@ namespace { return static_cast(Opm::Metric::Time); } + + + Opm::RestartIO::DoubHEAD::guideRate + computeGuideRate(const ::Opm::Schedule& sched, + const std::size_t lookup_step) + { + double a = 0.; + double b = 0.; + double c = 0.; + double d = 0.; + double e = 0.; + double f = 0.; + double delay = 0.; + double damping_fact = 0.; + + const auto& guideCFG = sched.guideRateConfig(lookup_step); + if (guideCFG.has_model()) { + const auto& guideRateModel = guideCFG.model(); + + a = guideRateModel.getA(); + b = guideRateModel.getB(); + c = guideRateModel.getC(); + d = guideRateModel.getD(); + e = guideRateModel.getE(); + f = guideRateModel.getF(); + delay = guideRateModel.update_delay(); + damping_fact = guideRateModel.damping_factor(); + } + return { + a, + b, + c, + d, + e, + f, + delay, + damping_fact + }; + } } // Anonymous // ##################################################################### @@ -82,14 +122,15 @@ createDoubHead(const EclipseState& es, const double nextTimeStep) { const auto& usys = es.getDeckUnitSystem(); - //const auto& rspec = es.runspec(); + 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(rspec.udqParams()) + .udq_param(rspec.udqParams()) + .guide_rate_param(computeGuideRate(sched, lookup_step)) ; if (nextTimeStep > 0.0) { diff --git a/src/opm/output/eclipse/CreateInteHead.cpp b/src/opm/output/eclipse/CreateInteHead.cpp index e81cc0929..d9cf1c18a 100755 --- a/src/opm/output/eclipse/CreateInteHead.cpp +++ b/src/opm/output/eclipse/CreateInteHead.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,17 @@ #include namespace { + + using nph_enum = Opm::GuideRateModel::Target; + const std::map nph_enumToECL = { + {nph_enum::NONE, 0}, + {nph_enum::OIL, 1}, + {nph_enum::GAS, 3}, + {nph_enum::LIQ, 4}, + {nph_enum::RES, 6}, + {nph_enum::COMB, 9}, + }; + int maxConnPerWell(const Opm::Schedule& sched, const std::size_t lookup_step) { @@ -71,6 +83,65 @@ namespace { // Number of non-FIELD groups. return ngmax - 1; } + + int GroupControl(const Opm::Schedule& sched, + const std::size_t lookup_step) + { + int gctrl = 0; + + for (const auto& group_name : sched.groupNames(lookup_step)) { + const auto& group = sched.getGroup(group_name, lookup_step); + if (group.isProductionGroup()) { + std::cout << "CrIH group.name()" << group.name() << " group.production_cmode() " << static_cast(group.production_cmode()) << std::endl; + gctrl = 1; + } + if (group.isInjectionGroup()) { + std::cout << "CrIH group.name()" << group.name() << " group.injection_cmode() " << static_cast(group.injection_cmode()) << std::endl; + gctrl = 2; + } + } + + // Index for group control + return gctrl; + } + + + int noWellUdqs(const Opm::Schedule& sched, + const std::size_t simStep) + { + const auto& udqCfg = sched.getUDQConfig(simStep); + std::size_t i_wudq = 0; + for (const auto& udq_input : udqCfg.input()) { + if (udq_input.var_type() == Opm::UDQVarType::WELL_VAR) { + i_wudq++; + } + } + return i_wudq; + } + + + int noGroupUdqs(const Opm::Schedule& sched, + const std::size_t simStep) + { + const auto& udqCfg = sched.getUDQConfig(simStep); + const auto& input = udqCfg.input(); + return std::count_if(input.begin(), input.end(), [](const Opm::UDQInput inp) { return (inp.var_type() == Opm::UDQVarType::GROUP_VAR); }); + + } + + int noFieldUdqs(const Opm::Schedule& sched, + const std::size_t simStep) + { + const auto& udqCfg = sched.getUDQConfig(simStep); + std::size_t i_fudq = 0; + for (const auto& udq_input : udqCfg.input()) { + if (udq_input.var_type() == Opm::UDQVarType::FIELD_VAR) { + i_fudq++; + } + } + return i_fudq; +} + Opm::RestartIO::InteHEAD::WellTableDim getWellTableDims(const int nwgmax, @@ -189,14 +260,22 @@ namespace { }; } - /*Opm::RestartIO::InteHEAD::UdqParam - getUdqParam(const ::Opm::Runspec& rspec, const ::Opm::UDQConfig& udqcfg ) + + Opm::RestartIO::InteHEAD::UdqParam + getUdqParam(const ::Opm::Runspec& rspec, const Opm::Schedule& sched, + const std::size_t simStep ) { const auto& udq_par = rspec.udqParams(); - const auto r_seed = udq_par.rand_seed(); - const auto no_udq = udqcfg.size(); - - return { r_seed, static_cast(no_udq)}; + const auto& udqActive = sched.udqActive(simStep); + const auto r_seed = udq_par.rand_seed(); + const auto no_wudq = noWellUdqs(sched, simStep); + const auto no_gudq = noGroupUdqs(sched, simStep); + const auto no_fudq = noFieldUdqs(sched, simStep); + const auto no_iuads = udqActive.IUAD_size(); + const auto no_iuaps = udqActive.IUAP_size(); + + return { r_seed, static_cast(no_wudq), static_cast(no_gudq), static_cast(no_fudq), + static_cast(no_iuads), static_cast(no_iuaps)}; } Opm::RestartIO::InteHEAD::ActionParam @@ -208,7 +287,7 @@ namespace { const auto max_characters_per_line = rspec.actdims().max_characters(); return { static_cast(no_act), max_lines_pr_action, static_cast(max_cond_per_action), static_cast(max_characters_per_line)}; - }*/ + } Opm::RestartIO::InteHEAD::WellSegDims getWellSegDims(const ::Opm::Runspec& rspec, @@ -262,6 +341,30 @@ namespace { static_cast(nplmix), }; } + + Opm::RestartIO::InteHEAD::GuideRateNominatedPhase + setGuideRateNominatedPhase(const ::Opm::Schedule& sched, + const std::size_t lookup_step) + { + int nom_phase = 0; + + const auto& guideCFG = sched.guideRateConfig(lookup_step); + if (guideCFG.has_model()) { + const auto& guideRateModel = guideCFG.model(); + + const auto& targPhase = guideRateModel.target(); + const auto& allow_incr = guideRateModel.allow_increase(); + + const auto it_nph = nph_enumToECL.find(targPhase); + if (it_nph != nph_enumToECL.end()) { + nom_phase = it_nph->second; + } + //nominated phase has negative sign for allow increment set to 'NO' + if (!allow_incr) nom_phase *= -1; + } + + return {nom_phase}; + } } // Anonymous // ##################################################################### @@ -279,8 +382,7 @@ createInteHead(const EclipseState& es, { const auto nwgmax = maxGroupSize(sched, lookup_step); const auto ngmax = numGroupsInField(sched, lookup_step); - //const auto& udqCfg = sched.getUDQConfig(lookup_step); - //const auto& acts = sched.actions(lookup_step); + const auto& acts = sched.actions(lookup_step); const auto& rspec = es.runspec(); const auto& tdim = es.getTableManager(); const auto& rdim = tdim.getRegdims(); @@ -297,7 +399,7 @@ createInteHead(const EclipseState& es, // across a range of reference cases, but are not guaranteed to be // universally valid. .params_NWELZ (155, 122, 130, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL - .params_NCON (25, 40, 58) // n{isx}conz: number of data elements per completion in ICON + .params_NCON (25, 41, 58) // n{isx}conz: number of data elements per completion in ICON .params_GRPZ (getNGRPZ(nwgmax, ngmax, rspec)) // ncamax: max number of analytical aquifer connections // n{isx}aaqz: number of data elements per aquifer in {ISX}AAQ @@ -308,9 +410,12 @@ createInteHead(const EclipseState& es, .wellSegDimensions (getWellSegDims(rspec, sched, lookup_step)) .regionDimensions (getRegDims(tdim, rdim)) .ngroups ({ ngmax }) - .variousParam (201702, 100) // Output should be compatible with Eclipse 100, 2017.02 version. - //.udqParam_1 (getUdqParam(rspec, udqCfg)) - //.actionParam (getActionParam(rspec, acts)) + .params_NGCTRL (GroupControl(sched,lookup_step)) + .variousParam (201802, 100) // Output should be compatible with Eclipse 100, 2017.02 version. + .udqParam_1 (getUdqParam(rspec, sched, lookup_step )) + .actionParam (getActionParam(rspec, acts)) + .variousUDQ_ACTIONXParam() + .nominatedPhaseGuideRate(setGuideRateNominatedPhase(sched,lookup_step)) ; return ih.data(); diff --git a/src/opm/output/eclipse/CreateUdqDims.cpp b/src/opm/output/eclipse/CreateUdqDims.cpp index 4b46fa566..3017e4eaf 100755 --- a/src/opm/output/eclipse/CreateUdqDims.cpp +++ b/src/opm/output/eclipse/CreateUdqDims.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -39,6 +40,8 @@ #include #include +namespace VI = ::Opm::RestartIO::Helpers::VectorItems; + namespace { @@ -68,56 +71,10 @@ std::size_t entriesPerZUDL() std::size_t noIGphs(const std::vector& inteHead) { - std::size_t no_entries = inteHead[20]; + std::size_t no_entries = (inteHead[VI::intehead::NO_GROUP_UDQS] > 0) ? inteHead[20] : 0; return no_entries; } -// maximum number of wells -std::size_t nwmaxz(const std::vector& inteHead) -{ - return inteHead[163]; -} - -// maximum number of groups -std::size_t ngmaxz(const std::vector& inteHead) -{ - return inteHead[20]; -} - -int noWellUdqs(const Opm::Schedule& sched, - const std::size_t simStep) -{ - const auto& udqCfg = sched.getUDQConfig(simStep); - std::size_t i_wudq = 0; - for (const auto& udq_input : udqCfg.input()) { - if (udq_input.var_type() == Opm::UDQVarType::WELL_VAR) { - i_wudq++; - } - } - return i_wudq; -} - -int noGroupUdqs(const Opm::Schedule& sched, - const std::size_t simStep) -{ - const auto& udqCfg = sched.getUDQConfig(simStep); - const auto& input = udqCfg.input(); - return std::count_if(input.begin(), input.end(), [](const Opm::UDQInput inp) { return (inp.var_type() == Opm::UDQVarType::GROUP_VAR); }); - -} - -int noFieldUdqs(const Opm::Schedule& sched, - const std::size_t simStep) -{ - const auto& udqCfg = sched.getUDQConfig(simStep); - std::size_t i_fudq = 0; - for (const auto& udq_input : udqCfg.input()) { - if (udq_input.var_type() == Opm::UDQVarType::FIELD_VAR) { - i_fudq++; - } - } - return i_fudq; -} } // Anonymous @@ -132,23 +89,22 @@ createUdqDims(const Schedule& sched, const std::vector& inteHead) { const auto& udqCfg = sched.getUDQConfig(lookup_step); - const auto& udqActive = sched.udqActive(lookup_step); std::vector udqDims; udqDims.resize(13,0); udqDims[ 0] = udqCfg.size(); udqDims[ 1] = entriesPerIUDQ(); - udqDims[ 2] = udqActive.IUAD_size(); + udqDims[ 2] = inteHead[VI::intehead::NO_IUADS]; udqDims[ 3] = entriesPerIUAD(); udqDims[ 4] = entriesPerZUDN(); udqDims[ 5] = entriesPerZUDL(); udqDims[ 6] = noIGphs(inteHead); - udqDims[ 7] = udqActive.IUAP_size(); - udqDims[ 8] = nwmaxz(inteHead); - udqDims[ 9] = noWellUdqs(sched, lookup_step); - udqDims[10] = ngmaxz(inteHead); - udqDims[11] = noGroupUdqs(sched, lookup_step); - udqDims[12] = noFieldUdqs(sched, lookup_step); + udqDims[ 7] = inteHead[VI::intehead::NO_IUAPS]; + udqDims[ 8] = inteHead[VI::intehead::NWMAXZ]; + udqDims[ 9] = inteHead[VI::intehead::NO_WELL_UDQS]; + udqDims[10] = inteHead[VI::intehead::NGMAXZ]; + udqDims[11] = inteHead[VI::intehead::NO_GROUP_UDQS]; + udqDims[12] = inteHead[VI::intehead::NO_FIELD_UDQS]; return udqDims; } diff --git a/src/opm/output/eclipse/DoubHEAD.cpp b/src/opm/output/eclipse/DoubHEAD.cpp index 931cac014..df39aafb3 100755 --- a/src/opm/output/eclipse/DoubHEAD.cpp +++ b/src/opm/output/eclipse/DoubHEAD.cpp @@ -146,19 +146,19 @@ enum Index : std::vector::size_type { DdpLim = 84, DdsLim = 85, dh_086 = 86, - dh_087 = 87, - dh_088 = 88, - dh_089 = 89, + grpar_a = VI::doubhead::GRpar_a, + grpar_b = VI::doubhead::GRpar_b, + grpar_c = VI::doubhead::GRpar_c, // 90..99 - dh_090 = 90, - dh_091 = 91, - dh_092 = 92, + grpar_d = VI::doubhead::GRpar_d, + grpar_e = VI::doubhead::GRpar_e, + grpar_f = VI::doubhead::GRpar_f, dh_093 = 93, dh_094 = 94, dh_095 = 95, dh_096 = 96, - dh_097 = 97, + grpar_int = VI::doubhead::GRpar_int, dh_098 = 98, ThrUPT = 99, @@ -215,7 +215,7 @@ enum Index : std::vector::size_type { dh_141 = 141, dh_142 = 142, dh_143 = 143, - dh_144 = 144, + grpar_dmp = VI::doubhead::GRpar_damp, dh_145 = 145, dh_146 = 146, dh_147 = 147, @@ -396,8 +396,8 @@ Opm::RestartIO::DoubHEAD::DoubHEAD() this->data_[Index::dh_069] = -1.0; this->data_[Index::dh_080] = 1.0e+20; this->data_[Index::dh_081] = 1.0e+20; - this->data_[Index::dh_091] = 0.0; - this->data_[Index::dh_092] = 0.0; + this->data_[grpar_e] = 0.0; + this->data_[grpar_f] = 0.0; this->data_[Index::dh_093] = 0.0; this->data_[Index::dh_096] = 0.0; this->data_[Index::dh_105] = 1.0; @@ -627,3 +627,18 @@ Opm::RestartIO::DoubHEAD::udq_param(const UDQParams& udqPar) return *this; } + +Opm::RestartIO::DoubHEAD& +Opm::RestartIO::DoubHEAD::guide_rate_param(const guideRate& guide_rp) +{ + this->data_[grpar_a] = guide_rp.A; + this->data_[grpar_b] = guide_rp.B; + this->data_[grpar_c] = guide_rp.C; + this->data_[grpar_d] = guide_rp.D; + this->data_[grpar_e] = guide_rp.E; + this->data_[grpar_f] = guide_rp.F; + this->data_[grpar_int] = guide_rp.delay; + this->data_[grpar_dmp] = guide_rp.damping_fact; + + return *this; +} diff --git a/src/opm/output/eclipse/InteHEAD.cpp b/src/opm/output/eclipse/InteHEAD.cpp index 747e74b33..bc0440c3a 100644 --- a/src/opm/output/eclipse/InteHEAD.cpp +++ b/src/opm/output/eclipse/InteHEAD.cpp @@ -52,7 +52,7 @@ enum index : std::vector::size_type { 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 + NSCONZ = VI::intehead::NSCONZ, // 41 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 @@ -70,14 +70,14 @@ enum index : std::vector::size_type { 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 + NGCONT = VI::intehead::NGCTRL, // 0 - no group control, 1 if GCONPROD, 2 if GCONINJE 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 + NGRNPHASE = VI::intehead::NGRNPH, // Parameter to determine the nominated phase for the guiderate ih_059 = 59 , // 0 0 ih_060 = 60 , // 0 0 ih_061 = 61 , // 0 0 @@ -281,11 +281,11 @@ enum index : std::vector::size_type { ih_259 = 259 , // 0 ih_260 = 260 , // 0 ih_261 = 261 , // 0 - ih_262 = 262 , // 0 - ih_263 = 263 , // 0 + NOFUDQS = VI::intehead::NO_FIELD_UDQS, // 0 + NOGUDQS = VI::intehead::NO_GROUP_UDQS, // 0 ih_264 = 264 , // 0 ih_265 = 265 , // 0 - NOUDQS = VI::intehead::NO_UDQS, // 0 + NOWUDQS = VI::intehead::NO_WELL_UDQS, // 0 UDQPAR_1 = VI::intehead::UDQPAR_1, // 0 ih_268 = 268 , // 0 ih_269 = 269 , // 0 @@ -309,8 +309,8 @@ enum index : std::vector::size_type { ih_287 = 287 , // 0 ih_288 = 288 , // 0 ih_289 = 289 , // 0 - ih_290 = 290 , // 0 - ih_291 = 291 , // 0 + NOIUADS = VI::intehead::NO_IUADS, // 0 + NOIUAPS = VI::intehead::NO_IUAPS, // 0 ih_292 = 292 , // 0 ih_293 = 293 , // 0 ih_294 = 294 , // 0 @@ -501,7 +501,7 @@ Opm::RestartIO::InteHEAD::wellTableDimensions(const WellTableDim& wtdim) this->data_[NGMAXZ] = wtdim.maxGroupInField + 1; - //this->data_[NWMAXZ] = wtdim.maxWellsInField; + this->data_[NWMAXZ] = wtdim.maxWellsInField; return *this; } @@ -571,6 +571,15 @@ params_GRPZ(const std::array& grpz) return *this; } +Opm::RestartIO::InteHEAD& +Opm::RestartIO::InteHEAD:: +params_NGCTRL(const int gct) +{ + this -> data_[NGCONT] = gct; + + return *this; +} + Opm::RestartIO::InteHEAD& Opm::RestartIO::InteHEAD:: params_NAAQZ(const int ncamax, @@ -682,9 +691,13 @@ Opm::RestartIO::InteHEAD& Opm::RestartIO::InteHEAD:: udqParam_1(const UdqParam& udq_par) { - this -> data_[UDQPAR_1] = - udq_par.udqParam_1; - this -> data_[R_SEED] = - udq_par.udqParam_1; - this -> data_[NOUDQS] = udq_par.no_udqs; + this -> data_[UDQPAR_1] = - udq_par.udqParam_1; + this -> data_[R_SEED] = - udq_par.udqParam_1; + this -> data_[NOWUDQS] = udq_par.no_wudqs; + this -> data_[NOGUDQS] = udq_par.no_gudqs; + this -> data_[NOFUDQS] = udq_par.no_fudqs; + this -> data_[NOIUADS] = udq_par.no_iuads; + this -> data_[NOIUAPS] = udq_par.no_iuaps; return *this; } @@ -702,6 +715,31 @@ actionParam(const ActionParam& act_par) return *this; } + +//InteHEAD parameters which meaning are currently not known, but which are needed for Eclipse restart runs with UDQ and ACTIONX data +Opm::RestartIO::InteHEAD& +Opm::RestartIO::InteHEAD:: +variousUDQ_ACTIONXParam() +{ + this -> data_[159] = 4; + this -> data_[160] = 5; + this -> data_[161] = 9; + this -> data_[246] = 26; + this -> data_[247] = 16; + this -> data_[248] = 13; + + return *this; +} + +Opm::RestartIO::InteHEAD& +Opm::RestartIO::InteHEAD:: +nominatedPhaseGuideRate(GuideRateNominatedPhase nphase) +{ + this -> data_[NGRNPHASE] = nphase.nominated_phase; + + return *this; +} + // ===================================================================== // Free functions (calendar/time utilities) // ===================================================================== diff --git a/src/opm/output/eclipse/RestartIO.cpp b/src/opm/output/eclipse/RestartIO.cpp index c3c95d2c4..d25b2c702 100644 --- a/src/opm/output/eclipse/RestartIO.cpp +++ b/src/opm/output/eclipse/RestartIO.cpp @@ -29,6 +29,8 @@ #include #include #include +#include + #include #include @@ -232,6 +234,7 @@ namespace { } void writeGroup(int sim_step, + const UnitSystem& units, const Schedule& schedule, const Opm::SummaryState& sumState, const std::vector& ih, @@ -242,7 +245,7 @@ namespace { auto groupData = Helpers::AggregateGroupData(ih); - groupData.captureDeclaredGroupData(schedule, simStep, sumState, ih); + groupData.captureDeclaredGroupData(schedule, units, simStep, sumState, ih); rstFile.write("IGRP", groupData.getIGroup()); rstFile.write("SGRP", groupData.getSGroup()); @@ -278,10 +281,6 @@ namespace { 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); @@ -302,6 +301,30 @@ namespace { } } + void writeActionx(int sim_step, + const EclipseState& es, + const Schedule& schedule, + const SummaryState& sum_state, + EclIO::OutputStream::Restart& rstFile) + { + // write ACTIONX - data to restart file + const std::size_t simStep = static_cast (sim_step); + + const auto actDims = Opm::RestartIO::Helpers::createActionxDims(es.runspec(), schedule, simStep); + auto actionxData = Opm::RestartIO::Helpers::AggregateActionxData(actDims); + actionxData.captureDeclaredActionxData(schedule, sum_state, actDims, simStep); + + if (actDims[0] >= 1) { + rstFile.write("IACT", actionxData.getIACT()); + rstFile.write("SACT", actionxData.getSACT()); + rstFile.write("ZACT", actionxData.getZACT()); + rstFile.write("ZLACT", actionxData.getZLACT()); + rstFile.write("ZACN", actionxData.getZACN()); + rstFile.write("IACN", actionxData.getIACN()); + rstFile.write("SACN", actionxData.getSACN()); + } + } + void writeWell(int sim_step, const bool ecl_compatible_rst, const Phases& phases, @@ -538,7 +561,7 @@ void save(EclIO::OutputStream::Restart& rstFile, writeHeader(sim_step, nextStepSize(value), seconds_elapsed, schedule, grid, es, rstFile); - writeGroup(sim_step, schedule, sumState, inteHD, rstFile); + writeGroup(sim_step, units, schedule, sumState, inteHD, rstFile); // Write well and MSW data only when applicable (i.e., when present) { @@ -563,6 +586,8 @@ void save(EclIO::OutputStream::Restart& rstFile, } } + writeActionx(sim_step, es, schedule, sumState, rstFile); + writeSolution(value, schedule, sumState, sim_step, ecl_compatible_rst, write_double, inteHD, rstFile); if (! ecl_compatible_rst) { diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionResult.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionResult.cpp index 202c6a2f4..0ba760609 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionResult.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionResult.cpp @@ -18,6 +18,7 @@ */ #include +#include #include @@ -43,11 +44,10 @@ Result::Result(bool result_arg, const WellSet& wells) : Result::Result(const Result& src) { this->result = src.result; - if (src.matching_wells) + if (src.matching_wells) this->matching_wells.reset( new WellSet(*src.matching_wells) ); } - Result::operator bool() const { return this->result; } @@ -59,7 +59,6 @@ std::vector Result::wells() const { return {}; } - Result& Result::operator|=(const Result& other) { this->result = this->result || other.result; @@ -84,6 +83,14 @@ Result& Result::operator&=(const Result& other) { return *this; } +Result& Result::operator=(const Result& src) +{ + this->result = src.result; + if (src.matching_wells) this->matching_wells.reset( new WellSet(*src.matching_wells) ); + + return *this; +} + void Result::assign(bool value) { this->result = value; } @@ -94,7 +101,7 @@ void Result::add_well(const std::string& well) { this->matching_wells->add(well); } -bool Result::has_well(const std::string& well) { +bool Result::has_well(const std::string& well) const { if (!this->matching_wells) return false; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Group/Group.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Group/Group.cpp index 01ff008d4..faf4484e0 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Group/Group.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Group/Group.cpp @@ -309,6 +309,9 @@ Phase Group::injection_phase() const { return this->injection_properties.phase; } +const Group::GroupType& Group::getGroupType() const { + return this-> group_type; +} bool Group::ProductionControls::has_control(Group::ProductionCMode control) const { return (this->production_controls & static_cast(control)) != 0; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateModel.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateModel.cpp index beb59cc2b..ad94b4a64 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateModel.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Group/GuideRateModel.cpp @@ -175,6 +175,30 @@ double GuideRateModel::damping_factor() const { return this->damping_factor_; } +double GuideRateModel::getA() const { + return this->A; +} + +double GuideRateModel::getB() const { + return this->B; +} + +double GuideRateModel::getC() const { + return this->C; +} + +double GuideRateModel::getD() const { + return this->D; +} + +double GuideRateModel::getE() const { + return this->E; +} + +double GuideRateModel::getF() const { + return this->F; +} + bool GuideRateModel::allow_increase() const { return this->allow_increase_; } diff --git a/tests/UDQ_ACTIONX_TEST1.DATA b/tests/UDQ_ACTIONX_TEST1.DATA index 8b5d2e1bf..8fafc22d0 100644 --- a/tests/UDQ_ACTIONX_TEST1.DATA +++ b/tests/UDQ_ACTIONX_TEST1.DATA @@ -415,7 +415,7 @@ ACTIONX ACT02 11 / FMWPR > 25 AND / WGPR 'OPL02' > GGPR 'LOWER' AND / -MNTH > MAY / +MNTH > NOV / / WELOPEN '?' 'SHUT' 0 0 0 2* / @@ -441,19 +441,12 @@ WELOPEN / ENDACTIO -WELOPEN - 'OPL01' 'OPEN' 5* / -/ -DATES - 1 'OCT' 2018 / -/ - --start files/actionxprod.tmpl ACTIONX ACT01 10 / FMWPR > 45 AND / WUPR3 'OP*' > 46 OR / -MNTH > JUN / +MNTH > OCT / / WELOPEN '?' SHUT 0 0 0 2* / @@ -466,6 +459,14 @@ WELOPEN / ENDACTIO +WELOPEN + 'OPL01' 'OPEN' 5* / +/ + +DATES + 1 'OCT' 2018 / +/ + WELOPEN 'WIL01' 'OPEN' 5* / diff --git a/tests/test_AggregateActionxData.cpp b/tests/test_AggregateActionxData.cpp index e61a30bbf..fc9e4f817 100644 --- a/tests/test_AggregateActionxData.cpp +++ b/tests/test_AggregateActionxData.cpp @@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE (Declared_Actionx_data) auto actionxData = Opm::RestartIO::Helpers::AggregateActionxData(actDims); actionxData.captureDeclaredActionxData(sched, st, actDims, rptStep); -#if 0 + /*rstFile.write("INTEHEAD", ih); rstFile.write("IUDQ", udqData.getIUDQ()); rstFile.write("IUAD", udqData.getIUAD()); rstFile.write("IGPH", udqData.getIGPH()); @@ -162,10 +162,8 @@ BOOST_AUTO_TEST_CASE (Declared_Actionx_data) rstFile.write("ZLACT", actionxData.getZLACT()); rstFile.write("ZACN", actionxData.getZACN()); rstFile.write("IACN", actionxData.getIACN()); - rstFile.write("SACN", actionxData.getSACN()); -#endif - -#if 0 + rstFile.write("SACN", actionxData.getSACN()); */ + { /* Check of InteHEAD and DoubHEAD data for UDQ variables @@ -201,8 +199,6 @@ BOOST_AUTO_TEST_CASE (Declared_Actionx_data) } -#endif - { /* IACT @@ -526,11 +522,11 @@ BOOST_AUTO_TEST_CASE (Declared_Actionx_data) BOOST_CHECK_EQUAL(sAcn[start + 1] , 0); BOOST_CHECK_EQUAL(sAcn[start + 2] , 17); BOOST_CHECK_EQUAL(sAcn[start + 3] , 0); - BOOST_CHECK_EQUAL(sAcn[start + 4] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 4] , 24); BOOST_CHECK_EQUAL(sAcn[start + 5] , 17); - BOOST_CHECK_EQUAL(sAcn[start + 6] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 6] , 24); BOOST_CHECK_EQUAL(sAcn[start + 7] , 17); - BOOST_CHECK_EQUAL(sAcn[start + 8] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 8] , 24); BOOST_CHECK_EQUAL(sAcn[start + 9] , 17); BOOST_CHECK_EQUAL(sAcn[start + 10] , 0); BOOST_CHECK_EQUAL(sAcn[start + 11] , 0); @@ -576,12 +572,7 @@ BOOST_AUTO_TEST_CASE (Declared_Actionx_data) BOOST_CHECK_EQUAL(sAcn[start + 15] , 0); } - - - -#if 0 - -#endif + } BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/test_AggregateActionxData_2.cpp b/tests/test_AggregateActionxData_2.cpp new file mode 100644 index 000000000..848032f59 --- /dev/null +++ b/tests/test_AggregateActionxData_2.cpp @@ -0,0 +1,564 @@ +#define BOOST_TEST_MODULE UDQ-ACTIONX_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::SummaryState sum_state_TEST1() + { + auto state = Opm::SummaryState{std::chrono::system_clock::now()}; + state.update_well_var("OPU01", "WWPR", 21.); + state.update_well_var("OPU02", "WWPR", 22.); + state.update_well_var("OPL01", "WWPR", 23.); + state.update_well_var("OPL02", "WWPR", 24.); + + state.update_well_var("OPU01", "WGPR", 230.); + state.update_well_var("OPU02", "WGPR", 231.); + state.update_well_var("OPL01", "WGPR", 232.); + state.update_well_var("OPL02", "WGPR", 233.); + + state.update_group_var("UPPER", "GWPR", 36.); + state.update_group_var("LOWER", "GWPR", 37.); + state.update_group_var("TEST", "GWPR", 73.); + + state.update_group_var("UPPER", "GGPR", 460.); + state.update_group_var("LOWER", "GGPR", 461.); + state.update_group_var("TEST", "GGPR", 821.); + + + state.update_group_var("TEST", "GMWPR", 4); + + state.update("FWPR", 73.); + + state.update("FMWPR", 4); + + + return state; +} + +//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_Actionx) + + + +// test constructed UDQ-Actionx restart data +BOOST_AUTO_TEST_CASE (Declared_Actionx_data) +{ + const auto simCase = SimulationCase{first_sim("UDQ_ACTIONX_TEST1.DATA")}; + + Opm::EclipseState es = simCase.es; + Opm::Runspec rspec = es.runspec(); + Opm::SummaryState st = sum_state_TEST1(); + Opm::Schedule sched = simCase.sched; + Opm::EclipseGrid grid = simCase.grid; + const auto& ioConfig = es.getIOConfig(); + //const auto& restart = es.cfg().restart(); + + + // Report Step 1: 2008-10-10 --> 2011-01-20 + const auto rptStep = std::size_t{1}; + std::string outputDir = "./"; + std::string baseName = "UDQ_ACTIONX_TEST1"; + 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, st, ih); + + const auto actDims = Opm::RestartIO::Helpers::createActionxDims(rspec, sched, rptStep); + auto actionxData = Opm::RestartIO::Helpers::AggregateActionxData(actDims); + actionxData.captureDeclaredActionxData(sched, st, actDims, rptStep); + + /*rstFile.write("INTEHEAD", 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()); + + rstFile.write("IACT", actionxData.getIACT()); + rstFile.write("SACT", actionxData.getSACT()); + rstFile.write("ZACT", actionxData.getZACT()); + rstFile.write("ZLACT", actionxData.getZLACT()); + rstFile.write("ZACN", actionxData.getZACN()); + rstFile.write("IACN", actionxData.getIACN()); + rstFile.write("SACN", actionxData.getSACN()); */ + + { + /* + Check of InteHEAD and DoubHEAD data for UDQ variables + + INTEHEAD + + Intehead[156] - The number of ACTIONS + Intehead[157] - The max number of lines of schedule data including ENDACTIO keyword for any ACTION + + ---------------------------------------------------------------------------------------------------------------------] + + */ + const auto rptStep_1 = std::size_t{0}; + const auto ih_1 = Opm::RestartIO::Helpers::createInteHead(es, grid, sched, + secs_elapsed, rptStep, rptStep_1); + + BOOST_CHECK_EQUAL(ih_1[156] , 2); + BOOST_CHECK_EQUAL(ih_1[157] , 7); + + + const auto rptStep_2 = std::size_t{1}; + const auto ih_2 = Opm::RestartIO::Helpers::createInteHead(es, grid, sched, + secs_elapsed, rptStep, rptStep_2); + BOOST_CHECK_EQUAL(ih_2[156] , 3); + BOOST_CHECK_EQUAL(ih_2[157] , 7); + + const auto rptStep_3 = std::size_t{2}; + const auto ih_3 = Opm::RestartIO::Helpers::createInteHead(es, grid, sched, + secs_elapsed, rptStep, rptStep_3); + + BOOST_CHECK_EQUAL(ih_3[156] , 3); + BOOST_CHECK_EQUAL(ih_3[157] , 10); + + } + + { + /* + IACT + --length is equal to 9*the number of ACTIONX keywords + //item [0]: is unknown, (=0) + //item [1]: The number of lines of schedule data including ENDACTIO + //item [2]: is unknown, (=1) + //item [3]: is unknown, (=7) + //item [4]: is unknown, (=0) + //item [5]: The number of times the action is triggered + //item [6]: is unknown, (=0) + //item [7]: is unknown, (=0) + //item [8]: The number of times the action is triggered + */ + + + const auto& iAct = actionxData.getIACT(); + + auto start = 0*actDims[1]; + BOOST_CHECK_EQUAL(iAct[start + 0] , 0); + BOOST_CHECK_EQUAL(iAct[start + 1] , 4); + BOOST_CHECK_EQUAL(iAct[start + 2] , 1); + BOOST_CHECK_EQUAL(iAct[start + 3] , 7); + BOOST_CHECK_EQUAL(iAct[start + 4] , 0); + BOOST_CHECK_EQUAL(iAct[start + 5] , 10); + BOOST_CHECK_EQUAL(iAct[start + 6] , 0); + BOOST_CHECK_EQUAL(iAct[start + 7] , 0); + BOOST_CHECK_EQUAL(iAct[start + 8] , 3); + + + start = 1*actDims[1]; + BOOST_CHECK_EQUAL(iAct[start + 0] , 0); + BOOST_CHECK_EQUAL(iAct[start + 1] , 7); + BOOST_CHECK_EQUAL(iAct[start + 2] , 1); + BOOST_CHECK_EQUAL(iAct[start + 3] , 7); + BOOST_CHECK_EQUAL(iAct[start + 4] , 0); + BOOST_CHECK_EQUAL(iAct[start + 5] , 11); + BOOST_CHECK_EQUAL(iAct[start + 6] , 0); + BOOST_CHECK_EQUAL(iAct[start + 7] , 0); + BOOST_CHECK_EQUAL(iAct[start + 8] , 3); + + start = 2*actDims[1]; + BOOST_CHECK_EQUAL(iAct[start + 0] , 0); + BOOST_CHECK_EQUAL(iAct[start + 1] , 4); + BOOST_CHECK_EQUAL(iAct[start + 2] , 1); + BOOST_CHECK_EQUAL(iAct[start + 3] , 7); + BOOST_CHECK_EQUAL(iAct[start + 4] , 0); + BOOST_CHECK_EQUAL(iAct[start + 5] , 13); + BOOST_CHECK_EQUAL(iAct[start + 6] , 0); + BOOST_CHECK_EQUAL(iAct[start + 7] , 0); + BOOST_CHECK_EQUAL(iAct[start + 8] , 3); + + } + + { + /* + ZACT + --length 4 times 8-chars pr ACTIONX keyword + + Name of action 4 times 8 chars (up to 8 chars for name) + + */ + + const auto& zAct = actionxData.getZACT(); + + auto start = 0*actDims[3]; + BOOST_CHECK_EQUAL(zAct[start + 0].c_str() , "ACT01 "); + + start = 1*actDims[3]; + BOOST_CHECK_EQUAL(zAct[start + 0].c_str() , "ACT02 "); + + start = 2*actDims[3]; + BOOST_CHECK_EQUAL(zAct[start + 0].c_str() , "ACT03 "); + + } + + { + /* + ZLACT + -- length = ACTDIMS_item3*(max-over-action of number of lines of data pr ACTION) + + */ + + const auto& zLact = actionxData.getZLACT(); + + //First action + auto start_a = 0*actDims[4]; + auto start = start_a + 0*actDims[8]; + BOOST_CHECK_EQUAL(zLact[start + 0].c_str() , "WELOPEN "); + + start = start_a + 1*actDims[8]; + BOOST_CHECK_EQUAL(zLact[start + 0].c_str() , " '?' '"); + BOOST_CHECK_EQUAL(zLact[start + 1].c_str() , "SHUT' 0 "); + BOOST_CHECK_EQUAL(zLact[start + 2].c_str() , "0 0 / "); + + start = start_a + 2*actDims[8]; + BOOST_CHECK_EQUAL(zLact[start + 0].c_str() , "/ "); + + start = start_a + 3*actDims[8]; + BOOST_CHECK_EQUAL(zLact[start + 0].c_str() , "ENDACTIO"); + + //Second action + start_a = 1*actDims[4]; + start = start_a + 0*actDims[8]; + BOOST_CHECK_EQUAL(zLact[start + 0].c_str() , "WELOPEN "); + + start = start_a + 1*actDims[8]; + BOOST_CHECK_EQUAL(zLact[start + 0].c_str() , " '?' '"); + BOOST_CHECK_EQUAL(zLact[start + 1].c_str() , "SHUT' 0 "); + BOOST_CHECK_EQUAL(zLact[start + 2].c_str() , "0 0 / "); + + start = start_a + 2*actDims[8]; + BOOST_CHECK_EQUAL(zLact[start + 0].c_str() , "/ "); + + start = start_a + 3*actDims[8]; + BOOST_CHECK_EQUAL(zLact[start + 0].c_str() , "WELOPEN "); + + start = start_a + 4*actDims[8]; + BOOST_CHECK_EQUAL(zLact[start + 0].c_str() , " 'OPL0"); + BOOST_CHECK_EQUAL(zLact[start + 1].c_str() , "1' 'OPEN"); + BOOST_CHECK_EQUAL(zLact[start + 2].c_str() , "' / "); + + start = start_a + 5*actDims[8]; + BOOST_CHECK_EQUAL(zLact[start + 0].c_str() , "/ "); + + + start = start_a + 6*actDims[8]; + BOOST_CHECK_EQUAL(zLact[start + 0].c_str() , "ENDACTIO"); + + + } + + { + /* + ZACN + //(Max number of conditions pr ACTIONX) * ((max no characters pr line = 104) / (8 - characters pr string)(104/8 = 13) + + */ + + const auto& zAcn = actionxData.getZACN(); + + //First action + auto start_a = 0*actDims[5]; + auto start = start_a + 0*13; + BOOST_CHECK_EQUAL(zAcn[start + 0].c_str() , "WWPR "); + BOOST_CHECK_EQUAL(zAcn[start + 1].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 2].c_str() , "> "); + BOOST_CHECK_EQUAL(zAcn[start + 3].c_str() , "OP* "); + + start = start_a + 1*13; + BOOST_CHECK_EQUAL(zAcn[start + 0].c_str() , "GMWPR "); + BOOST_CHECK_EQUAL(zAcn[start + 1].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 2].c_str() , "> "); + BOOST_CHECK_EQUAL(zAcn[start + 3].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 4].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 5].c_str() , "T* "); + + start = start_a + 2*13; + BOOST_CHECK_EQUAL(zAcn[start + 0].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 1].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 2].c_str() , "> "); + BOOST_CHECK_EQUAL(zAcn[start + 3].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 4].c_str() , " "); + + + + //Second action + start_a = 1*actDims[5]; + start = start_a + 0*13; + BOOST_CHECK_EQUAL(zAcn[start + 0].c_str() , "FMWPR "); + BOOST_CHECK_EQUAL(zAcn[start + 1].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 2].c_str() , "> "); + BOOST_CHECK_EQUAL(zAcn[start + 3].c_str() , " "); + + start = start_a + 1*13; + BOOST_CHECK_EQUAL(zAcn[start + 0].c_str() , "WGPR "); + BOOST_CHECK_EQUAL(zAcn[start + 1].c_str() , "GGPR "); + BOOST_CHECK_EQUAL(zAcn[start + 2].c_str() , "> "); + BOOST_CHECK_EQUAL(zAcn[start + 3].c_str() , "OPL02 "); + BOOST_CHECK_EQUAL(zAcn[start + 4].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 5].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 6].c_str() , "LOWER "); + + start = start_a + 2*13; + BOOST_CHECK_EQUAL(zAcn[start + 0].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 1].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 2].c_str() , "> "); + BOOST_CHECK_EQUAL(zAcn[start + 3].c_str() , " "); + BOOST_CHECK_EQUAL(zAcn[start + 4].c_str() , " "); + } + + { + /* + IACN + 26*Max number of conditions pr ACTIONX + + */ + + + const auto& iAcn = actionxData.getIACN(); + + auto start_a = 0*actDims[6]; + auto start = start_a + 0*26; + BOOST_CHECK_EQUAL(iAcn[start + 0] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 1] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 2] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 3] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 4] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 5] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 6] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 7] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 8] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 9] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 10] , 2); + BOOST_CHECK_EQUAL(iAcn[start + 11] , 8); + BOOST_CHECK_EQUAL(iAcn[start + 12] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 13] , 2); + BOOST_CHECK_EQUAL(iAcn[start + 14] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 15] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 16] , 1); + BOOST_CHECK_EQUAL(iAcn[start + 17] , 0); + + start = start_a + 1*26; + BOOST_CHECK_EQUAL(iAcn[start + 0] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 1] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 2] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 3] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 4] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 5] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 6] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 7] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 8] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 9] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 10] , 3); + BOOST_CHECK_EQUAL(iAcn[start + 11] , 8); + BOOST_CHECK_EQUAL(iAcn[start + 12] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 13] , 1); + BOOST_CHECK_EQUAL(iAcn[start + 14] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 15] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 16] , 1); + BOOST_CHECK_EQUAL(iAcn[start + 17] , 0); + + start_a = 1*actDims[6]; + start = start_a + 0*26; + BOOST_CHECK_EQUAL(iAcn[start + 0] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 1] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 2] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 3] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 4] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 5] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 6] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 7] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 8] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 9] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 10] , 1); + BOOST_CHECK_EQUAL(iAcn[start + 11] , 8); + BOOST_CHECK_EQUAL(iAcn[start + 12] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 13] , 1); + BOOST_CHECK_EQUAL(iAcn[start + 14] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 15] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 16] , 1); + BOOST_CHECK_EQUAL(iAcn[start + 17] , 0); + + start = start_a + 1*26; + BOOST_CHECK_EQUAL(iAcn[start + 0] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 1] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 2] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 3] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 4] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 5] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 6] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 7] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 8] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 9] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 10] , 2); + BOOST_CHECK_EQUAL(iAcn[start + 11] , 3); + BOOST_CHECK_EQUAL(iAcn[start + 12] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 13] , 1); + BOOST_CHECK_EQUAL(iAcn[start + 14] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 15] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 16] , 1); + BOOST_CHECK_EQUAL(iAcn[start + 17] , 0); + + start = start_a + 2*26; + BOOST_CHECK_EQUAL(iAcn[start + 0] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 1] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 2] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 3] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 4] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 5] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 6] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 7] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 8] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 9] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 10] , 11); + BOOST_CHECK_EQUAL(iAcn[start + 11] , 8); + BOOST_CHECK_EQUAL(iAcn[start + 12] , 1); + BOOST_CHECK_EQUAL(iAcn[start + 13] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 14] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 15] , 0); + BOOST_CHECK_EQUAL(iAcn[start + 16] , 1); + BOOST_CHECK_EQUAL(iAcn[start + 17] , 1); + + } + + + + { + /* + SACN + 26*Max number of conditions pr ACTIONX + + */ + + + const auto& sAcn = actionxData.getSACN(); + + auto start_a = 0*actDims[6]; + auto start = start_a + 0*16; + BOOST_CHECK_EQUAL(sAcn[start + 0] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 1] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 2] , 17); + BOOST_CHECK_EQUAL(sAcn[start + 3] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 4] , 24); + BOOST_CHECK_EQUAL(sAcn[start + 5] , 17); + BOOST_CHECK_EQUAL(sAcn[start + 6] , 24); + BOOST_CHECK_EQUAL(sAcn[start + 7] , 17); + BOOST_CHECK_EQUAL(sAcn[start + 8] , 24); + BOOST_CHECK_EQUAL(sAcn[start + 9] , 17); + BOOST_CHECK_EQUAL(sAcn[start + 10] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 11] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 12] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 13] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 14] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 15] , 0); + + start = start_a + 1*16; + BOOST_CHECK_EQUAL(sAcn[start + 0] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 1] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 2] , 14); + BOOST_CHECK_EQUAL(sAcn[start + 3] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 4] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 5] , 14); + BOOST_CHECK_EQUAL(sAcn[start + 6] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 7] , 14); + BOOST_CHECK_EQUAL(sAcn[start + 8] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 9] , 14); + BOOST_CHECK_EQUAL(sAcn[start + 10] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 11] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 12] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 13] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 14] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 15] , 0); + + start = start_a + 2*16; + BOOST_CHECK_EQUAL(sAcn[start + 0] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 1] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 2] , 3); + BOOST_CHECK_EQUAL(sAcn[start + 3] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 4] , 1.E+20); + BOOST_CHECK_EQUAL(sAcn[start + 5] , 1.E+20); + BOOST_CHECK_EQUAL(sAcn[start + 6] , 1.E+20); + BOOST_CHECK_EQUAL(sAcn[start + 7] , 1.E+20); + BOOST_CHECK_EQUAL(sAcn[start + 8] , 1.E+20); + BOOST_CHECK_EQUAL(sAcn[start + 9] , 1.E+20); + BOOST_CHECK_EQUAL(sAcn[start + 10] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 11] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 12] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 13] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 14] , 0); + BOOST_CHECK_EQUAL(sAcn[start + 15] , 0); + + } + +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/test_AggregateGroupData.cpp b/tests/test_AggregateGroupData.cpp index a7c214938..cc3262dac 100644 --- a/tests/test_AggregateGroupData.cpp +++ b/tests/test_AggregateGroupData.cpp @@ -498,10 +498,10 @@ BOOST_AUTO_TEST_CASE (Declared_Group_Data) BOOST_CHECK_EQUAL(ih.nwells, MockIH::Sz{4}); const auto smry = sim_state(); + const auto& units = simCase.es.getUnits(); auto agrpd = Opm::RestartIO::Helpers::AggregateGroupData{ih.value}; - agrpd.captureDeclaredGroupData(simCase.sched, - rptStep, smry, - ih.value); + agrpd.captureDeclaredGroupData(simCase.sched, units, rptStep, smry, + ih.value); // IGRP (PROD) { diff --git a/tests/test_AggregateUDQData.cpp b/tests/test_AggregateUDQData.cpp index 58d015a5f..5e9c26328 100644 --- a/tests/test_AggregateUDQData.cpp +++ b/tests/test_AggregateUDQData.cpp @@ -187,10 +187,10 @@ BOOST_AUTO_TEST_CASE (Declared_UDQ_data) */ - /*BOOST_CHECK_EQUAL(ih[267] , -1); + 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); */ + BOOST_CHECK_EQUAL(dh[214] , 1.0E-4); }