diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake
index 9fb202e48..2e6a59963 100644
--- a/CMakeLists_files.cmake
+++ b/CMakeLists_files.cmake
@@ -312,6 +312,7 @@ if(ENABLE_ECL_INPUT)
list(APPEND TEST_SOURCE_FILES
tests/rst_test.cpp
tests/test_ERsm.cpp
+ tests/test_GuideRate.cpp
tests/parser/ACTIONX.cpp
tests/parser/ADDREGTests.cpp
tests/parser/AquiferTests.cpp
diff --git a/tests/test_GuideRate.cpp b/tests/test_GuideRate.cpp
new file mode 100644
index 000000000..8e522589a
--- /dev/null
+++ b/tests/test_GuideRate.cpp
@@ -0,0 +1,524 @@
+/*
+ Copyright (c) 2020 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 .
+*/
+
+#define BOOST_TEST_MODULE test_GuideRate
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+
+#include
+
+namespace {
+ struct Setup
+ {
+ explicit Setup(const std::string& input)
+ : Setup { Opm::Parser{}.parseString(input) }
+ {}
+
+ explicit Setup(const Opm::Deck& deck)
+ : es { deck }
+ , sched { deck, es, std::make_shared() }
+ , gr { sched }
+ {}
+
+ Opm::EclipseState es;
+ Opm::Schedule sched;
+ Opm::GuideRate gr;
+ };
+
+ Setup case_10x10x10_model4(const double damping_factor = 0.5)
+ {
+ const auto prolog = std::string { R"(RUNSPEC
+START
+ 4 'AUG' 2020 /
+
+TITLE
+ Check GUIDERAT Formula Implementation
+
+DIMENS
+ 10 10 10 /
+
+OIL
+GAS
+WATER
+DISGAS
+VAPOIL
+
+METRIC
+
+TABDIMS
+/
+
+WELLDIMS
+3 10 2 2 /
+
+GRID
+
+DXV
+ 10*100 /
+
+DYV
+ 10*100 /
+
+DZV
+ 10*5 /
+
+DEPTHZ
+ 121*2000 /
+
+PERMX
+ 1000*100 /
+
+COPY
+ PERMX PERMY /
+ PERMX PERMZ /
+/
+
+MULTIPLY
+ PERMZ 0.1 /
+/
+
+PORO
+ 1000*0.3 /
+
+SOLUTION
+
+PRESSURE
+ 1000*320 /
+SOIL
+ 1000*0.85 /
+SWAT
+ 1000*0.12 /
+SGAS
+ 1000*0.03 /
+RS
+ 1000*226.0 /
+RV
+ 1000*0.0 /
+
+SCHEDULE
+
+WELSPECS
+ P1 P 10 7 2002.5 OIL /
+ P2 P 7 10 2002.5 OIL /
+ I1 I 2 2 2002.5 GAS /
+/
+
+COMPDAT
+ P1 2* 1 10 OPEN 1* 1* 0.5 /
+ P2 2* 1 10 OPEN 1* 1* 0.5 /
+ I1 2* 1 10 OPEN 1* 1* 0.5 /
+/
+)" };
+
+ const auto guiderat = std::string { R"(
+-- GR_{oil} = WOPP / (0.5 + (WWPP / WOPP))
+-- with a user-specified damping/time-delay factor (default 0.5).
+GUIDERAT
+--1 2 3 4 5 6 7 8 9 10
+ 1.0 OIL 1.0 0.5 1.0 1.0 1* 1* YES )" } + std::to_string(damping_factor) + " /\n";
+
+ const auto epilog = std::string { R"(
+WCONPROD
+ P* OPEN GRUP 150 100 15E+3 250 1* 50 25 /
+/
+
+WCONINJE
+ I1 GAS OPEN RATE 20.0E+3 1* 500 350 /
+/
+
+GCONPROD
+ P 'ORAT' 200.0 150.0 100.0E+3 1* 1* YES 1* FORM /
+/
+
+DATES
+ 5 'AUG' 2020 /
+ 10 'AUG' 2020 /
+ 20 'AUG' 2020 /
+ 1 'SEP' 2020 /
+ 1 'OCT' 2020 /
+ 1 'NOV' 2020 /
+ 1 'DEC' 2020 /
+ 1 'JAN' 2021 /
+/
+
+END
+)" };
+
+ return Setup { prolog + guiderat + epilog };
+}
+} // Namespace anonymous
+
+// ======================================================================
+
+BOOST_AUTO_TEST_SUITE(GuideRate_Calculations)
+
+BOOST_AUTO_TEST_CASE(P1_First)
+{
+ auto cse = case_10x10x10_model4();
+
+ const auto wopp = 1.0;
+ const auto wgpp = 5.0;
+ const auto wwpp = 0.1;
+ const auto stm = 0.0;
+ const auto rpt = size_t{1};
+
+ cse.gr.compute("P1", rpt, stm, wopp, wgpp, wwpp);
+
+ const auto orat = 2.0;
+ const auto grat = 4.0; // == 2 * orat
+ const auto wrat = 1.0; // == orat / 2
+
+ const auto expect_gr_oil = 1.0 / (0.5 + 0.1/1.0); // wopp / (0.5 + wwpp/wopp)
+
+ // GR_{oil}
+ {
+ const auto grval = cse.gr.get("P1", Opm::Well::GuideRateTarget::OIL, { orat, grat, wrat });
+
+ BOOST_CHECK_CLOSE(grval, expect_gr_oil, 1.0e-5);
+ }
+
+ // GR_{gas}
+ {
+ const auto grval = cse.gr.get("P1", Opm::Well::GuideRateTarget::GAS, { orat, grat, wrat });
+
+ const auto expect = (grat / orat) * expect_gr_oil;
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+
+ // GR_{water}
+ {
+ const auto grval = cse.gr.get("P1", Opm::Well::GuideRateTarget::WAT, { orat, grat, wrat });
+
+ const auto expect = (wrat / orat) * expect_gr_oil;
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(P2_Second)
+{
+ auto cse = case_10x10x10_model4();
+
+ {
+ const auto wopp = 1.0;
+ const auto wgpp = 5.0;
+ const auto wwpp = 0.1;
+ const auto stm = 0.0;
+ const auto rpt = size_t{1};
+
+ cse.gr.compute("P2", rpt, stm, wopp, wgpp, wwpp);
+ }
+
+ {
+ const auto wopp = 10.0;
+ const auto wgpp = 50.0;
+ const auto wwpp = 1.0;
+ const auto stm = 10.0*Opm::unit::second; // Before recalculation delay
+ const auto rpt = size_t{1};
+
+ cse.gr.compute("P2", rpt, stm, wopp, wgpp, wwpp);
+ }
+
+ const auto orat = 2.0;
+ const auto grat = 4.0; // == 2 * orat
+ const auto wrat = 1.0; // == orat / 2
+
+ const auto expect_gr_oil_1 = 1.0 / (0.5 + 0.1/1.0); // wopp_1 / (0.5 + wwpp_1/wopp_1)
+
+ // GR_{oil}
+ {
+ const auto grval = cse.gr.get("P2", Opm::Well::GuideRateTarget::OIL, { orat, grat, wrat });
+
+ BOOST_CHECK_CLOSE(grval, expect_gr_oil_1, 1.0e-5);
+ }
+
+ // GR_{gas}
+ {
+ const auto grval = cse.gr.get("P2", Opm::Well::GuideRateTarget::GAS, { orat, grat, wrat });
+
+ const auto expect = (grat / orat) * expect_gr_oil_1;
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+
+ // GR_{water}
+ {
+ const auto grval = cse.gr.get("P2", Opm::Well::GuideRateTarget::WAT, { orat, grat, wrat });
+
+ const auto expect = (wrat / orat) * expect_gr_oil_1;
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+
+ {
+ const auto wopp = 10.0;
+ const auto wgpp = 50.0;
+ const auto wwpp = 1.0;
+ const auto stm = 10.0*Opm::unit::day; // After recalculation delay
+ const auto rpt = size_t{3};
+
+ cse.gr.compute("P2", rpt, stm, wopp, wgpp, wwpp);
+ }
+
+ const auto expect_gr_oil_2 = 10.0 / (0.5 + 1.0/10.0); // wopp_2 / (0.5 + wwpp_2/wopp_2)
+
+ // GR_{oil}
+ {
+ const auto grval = cse.gr.get("P2", Opm::Well::GuideRateTarget::OIL, { orat, grat, wrat });
+
+ const auto expect = 0.5*expect_gr_oil_2 + 0.5*expect_gr_oil_1;
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+
+ // GR_{gas}
+ {
+ const auto grval = cse.gr.get("P2", Opm::Well::GuideRateTarget::GAS, { orat, grat, wrat });
+
+ const auto expect = (grat / orat) * (0.5*expect_gr_oil_2 + 0.5*expect_gr_oil_1);
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+
+ // GR_{water}
+ {
+ const auto grval = cse.gr.get("P2", Opm::Well::GuideRateTarget::WAT, { orat, grat, wrat });
+
+ const auto expect = (wrat / orat) * (0.5*expect_gr_oil_2 + 0.5*expect_gr_oil_1);
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(P_Third)
+{
+ auto cse = case_10x10x10_model4();
+
+ {
+ const auto wopp = 1.0;
+ const auto wgpp = 5.0;
+ const auto wwpp = 0.1;
+ const auto stm = 0.0;
+ const auto rpt = size_t{1};
+
+ cse.gr.compute("P", rpt, stm, wopp, wgpp, wwpp);
+ }
+
+ {
+ const auto wopp = 10.0;
+ const auto wgpp = 50.0;
+ const auto wwpp = 1.0;
+ const auto stm = 10.0*Opm::unit::day;
+ const auto rpt = size_t{3};
+
+ cse.gr.compute("P", rpt, stm, wopp, wgpp, wwpp);
+ }
+
+ {
+ const auto wopp = 20.0;
+ const auto wgpp = 100.0;
+ const auto wwpp = 10.0;
+ const auto stm = 20.0*Opm::unit::day;
+ const auto rpt = size_t{4};
+
+ cse.gr.compute("P", rpt, stm, wopp, wgpp, wwpp);
+ }
+
+ const auto expect_gr_oil_1 = 1.0 / (0.5 + 0.1/ 1.0); // wopp_1 / (0.5 + wwpp_1/wopp_1)
+ const auto expect_gr_oil_2 = 10.0 / (0.5 + 1.0/10.0); // wopp_2 / (0.5 + wwpp_2/wopp_2)
+ const auto expect_gr_oil_3 = 20.0 / (0.5 + 10.0/20.0); // wopp_3 / (0.5 + wwpp_3/wopp_3)
+
+ const auto orat = 2.0;
+ const auto grat = 4.0; // == 2 * orat
+ const auto wrat = 1.0; // == orat / 2
+
+ // GR_{oil}
+ {
+ const auto grval = cse.gr.get("P", Opm::Well::GuideRateTarget::OIL, { orat, grat, wrat });
+
+ const auto expect = 0.5*expect_gr_oil_3 + 0.5*0.5*expect_gr_oil_2 + 0.5*0.5*expect_gr_oil_1;
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+
+ // GR_{gas}
+ {
+ const auto grval = cse.gr.get("P", Opm::Well::GuideRateTarget::GAS, { orat, grat, wrat });
+
+ const auto expect = (grat / orat) * (0.5*expect_gr_oil_3 + 0.5*0.5*expect_gr_oil_2 + 0.5*0.5*expect_gr_oil_1);
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+
+ // GR_{water}
+ {
+ const auto grval = cse.gr.get("P", Opm::Well::GuideRateTarget::WAT, { orat, grat, wrat });
+
+ const auto expect = (wrat / orat) * (0.5*expect_gr_oil_3 + 0.5*0.5*expect_gr_oil_2 + 0.5*0.5*expect_gr_oil_1);
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(P_Third_df01)
+{
+ auto cse = case_10x10x10_model4(0.1);
+
+ {
+ const auto wopp = 1.0;
+ const auto wgpp = 5.0;
+ const auto wwpp = 0.1;
+ const auto stm = 0.0;
+ const auto rpt = size_t{1};
+
+ cse.gr.compute("P", rpt, stm, wopp, wgpp, wwpp);
+ }
+
+ {
+ const auto wopp = 10.0;
+ const auto wgpp = 50.0;
+ const auto wwpp = 1.0;
+ const auto stm = 10.0*Opm::unit::day;
+ const auto rpt = size_t{3};
+
+ cse.gr.compute("P", rpt, stm, wopp, wgpp, wwpp);
+ }
+
+ {
+ const auto wopp = 20.0;
+ const auto wgpp = 100.0;
+ const auto wwpp = 10.0;
+ const auto stm = 20.0*Opm::unit::day;
+ const auto rpt = size_t{4};
+
+ cse.gr.compute("P", rpt, stm, wopp, wgpp, wwpp);
+ }
+
+ const auto expect_gr_oil_1 = 1.0 / (0.5 + 0.1/ 1.0); // wopp_1 / (0.5 + wwpp_1/wopp_1)
+ const auto expect_gr_oil_2 = 10.0 / (0.5 + 1.0/10.0); // wopp_2 / (0.5 + wwpp_2/wopp_2)
+ const auto expect_gr_oil_3 = 20.0 / (0.5 + 10.0/20.0); // wopp_3 / (0.5 + wwpp_3/wopp_3)
+
+ const auto orat = 2.0;
+ const auto grat = 4.0; // == 2 * orat
+ const auto wrat = 1.0; // == orat / 2
+
+ // GR_{oil}
+ {
+ const auto grval = cse.gr.get("P", Opm::Well::GuideRateTarget::OIL, { orat, grat, wrat });
+
+ const auto expect = 0.1*expect_gr_oil_3 + 0.1*0.9*expect_gr_oil_2 + 0.9*0.9*expect_gr_oil_1;
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+
+ // GR_{gas}
+ {
+ const auto grval = cse.gr.get("P", Opm::Well::GuideRateTarget::GAS, { orat, grat, wrat });
+
+ const auto expect = (grat / orat) * (0.1*expect_gr_oil_3 + 0.1*0.9*expect_gr_oil_2 + 0.9*0.9*expect_gr_oil_1);
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+
+ // GR_{water}
+ {
+ const auto grval = cse.gr.get("P", Opm::Well::GuideRateTarget::WAT, { orat, grat, wrat });
+
+ const auto expect = (wrat / orat) * (0.1*expect_gr_oil_3 + 0.1*0.9*expect_gr_oil_2 + 0.9*0.9*expect_gr_oil_1);
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(P_Third_df09)
+{
+ auto cse = case_10x10x10_model4(0.9);
+
+ {
+ const auto wopp = 1.0;
+ const auto wgpp = 5.0;
+ const auto wwpp = 0.1;
+ const auto stm = 0.0;
+ const auto rpt = size_t{1};
+
+ cse.gr.compute("P", rpt, stm, wopp, wgpp, wwpp);
+ }
+
+ {
+ const auto wopp = 10.0;
+ const auto wgpp = 50.0;
+ const auto wwpp = 1.0;
+ const auto stm = 10.0*Opm::unit::day;
+ const auto rpt = size_t{3};
+
+ cse.gr.compute("P", rpt, stm, wopp, wgpp, wwpp);
+ }
+
+ {
+ const auto wopp = 20.0;
+ const auto wgpp = 100.0;
+ const auto wwpp = 10.0;
+ const auto stm = 20.0*Opm::unit::day;
+ const auto rpt = size_t{4};
+
+ cse.gr.compute("P", rpt, stm, wopp, wgpp, wwpp);
+ }
+
+ const auto expect_gr_oil_1 = 1.0 / (0.5 + 0.1/ 1.0); // wopp_1 / (0.5 + wwpp_1/wopp_1)
+ const auto expect_gr_oil_2 = 10.0 / (0.5 + 1.0/10.0); // wopp_2 / (0.5 + wwpp_2/wopp_2)
+ const auto expect_gr_oil_3 = 20.0 / (0.5 + 10.0/20.0); // wopp_3 / (0.5 + wwpp_3/wopp_3)
+
+ const auto orat = 2.0;
+ const auto grat = 4.0; // == 2 * orat
+ const auto wrat = 1.0; // == orat / 2
+
+ // GR_{oil}
+ {
+ const auto grval = cse.gr.get("P", Opm::Well::GuideRateTarget::OIL, { orat, grat, wrat });
+
+ const auto expect = 0.9*expect_gr_oil_3 + 0.9*0.1*expect_gr_oil_2 + 0.1*0.1*expect_gr_oil_1;
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+
+ // GR_{gas}
+ {
+ const auto grval = cse.gr.get("P", Opm::Well::GuideRateTarget::GAS, { orat, grat, wrat });
+
+ const auto expect = (grat / orat) * (0.9*expect_gr_oil_3 + 0.9*0.1*expect_gr_oil_2 + 0.1*0.1*expect_gr_oil_1);
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+
+ // GR_{water}
+ {
+ const auto grval = cse.gr.get("P", Opm::Well::GuideRateTarget::WAT, { orat, grat, wrat });
+
+ const auto expect = (wrat / orat) * (0.9*expect_gr_oil_3 + 0.9*0.1*expect_gr_oil_2 + 0.1*0.1*expect_gr_oil_1);
+ BOOST_CHECK_CLOSE(grval, expect, 1.0e-5);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END() // GuideRate_Calculations