From 245a3aa09e3c07f8800cfe99aa81f2911fb7ce6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Mon, 17 Aug 2020 23:37:49 +0200 Subject: [PATCH] GuideRate: Add Test Case for Revised get() Implementation --- CMakeLists_files.cmake | 1 + tests/test_GuideRate.cpp | 524 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 525 insertions(+) create mode 100644 tests/test_GuideRate.cpp 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