diff --git a/src/opm/output/eclipse/Tables.cpp b/src/opm/output/eclipse/Tables.cpp index 952a9dcaa..216da0cdb 100644 --- a/src/opm/output/eclipse/Tables.cpp +++ b/src/opm/output/eclipse/Tables.cpp @@ -30,6 +30,7 @@ #include // PVTW, PVCDO #include #include +#include #include #include #include @@ -1193,6 +1194,205 @@ namespace { namespace PVTFunc { }); } + /// Create linearised and padded 'TAB' vector entries of normalised + /// gas tables for all PVT function regions from PVTG (wet gas with + /// volatile/vaporised oil) keyword data. + /// + /// \param[in] numCompNodes Number of composition nodes (rows per + /// sub-table) to allocate in the output vector for each table. + /// Expected to be equal to the number of declared composition + /// nodes in the simulation run's TABDIMS keyword (NRPVT, Item + /// 6). + /// + /// \param[in] numPressNodes Number of pressure nodes (sub-tables) + /// to allocate in the output vector for each gas PVT table. + /// Expected to be equal to the number of declared pressure nodes + /// in the simulation run's TABDIMS keyword (NPPVT, Item 4). + /// + /// \param[in] units Active unit system. Needed to convert SI + /// convention vaporised oil composition values (Sm3/Sm3), + /// formation volume factors (Rm3/Sm3), and viscosity values + /// (Pa*s) to declared conventions of the run specification. + /// + /// \param[in] pvtg Collection of PVTG tables for all PVT regions. + /// + /// \return Linearised and padded 'TAB' vector values for output gas + /// PVT tables. A unit-converted copy of the input table \p pvtg + /// with added derivatives. + std::vector + fromPVTG(const std::size_t numCompNodes, + const std::size_t numPressNodes, + const Opm::UnitSystem& units, + const std::vector& pvtg) + { + // Columns [ Rv, 1/Bg, 1/(Bg*mu_g), derivatives ] + const auto numTab = pvtg.size(); + const auto numPrim = numPressNodes; + const auto numRows = numCompNodes; + const auto numDep = std::size_t{2}; // 1/Bg, 1/(Bg*mu_g) + + // PVTG fill value = -2.0e20 + const auto fillVal = -2.0e20; + + return createPropfuncTable(numTab, numPrim, numRows, numDep, fillVal, + [&units, &pvtg](const std::size_t tableID, + const std::size_t primID, + Opm::LinearisedOutputTable& linTable) + -> std::size_t + { + auto numActRows = std::size_t{0}; + + if (primID >= pvtg[tableID].size()) { + // Composition node outside current table's active set. + // No active rows in this subtable. + return numActRows; + } + + const auto& t = pvtg[tableID].getUnderSaturatedTable(primID); + + // Column 0: Rv + { + const auto uRv = ::Opm::UnitSystem::measure::oil_gas_ratio; + + const auto& Rv = t.getColumn(0); + + numActRows = Rv.size(); + + std::transform(std::begin(Rv), std::end(Rv), + linTable.column(tableID, primID, 0), + [&units](const double rv) -> double + { + return units.from_si(uRv, rv); + }); + } + + // Column 1: 1/Bg + { + const auto uRecipFVF = ::Opm::UnitSystem::measure:: + gas_inverse_formation_volume_factor; + + const auto& Bg = t.getColumn(1); + + std::transform(std::begin(Bg), std::end(Bg), + linTable.column(tableID, primID, 1), + [&units](const double B) -> double + { + return units.from_si(uRecipFVF, 1.0 / B); + }); + } + + // Column 2: 1/(Bg*mu_g) + { + const auto uRecipFVF = ::Opm::UnitSystem::measure:: + gas_inverse_formation_volume_factor; + + const auto uVisc = ::Opm::UnitSystem::measure::viscosity; + + const auto& Bg = t.getColumn(1); + const auto& mu_g = t.getColumn(2); + + std::transform(std::begin(Bg), std::end(Bg), + std::begin(mu_g), + linTable.column(tableID, primID, 2), + [&units](const double B, const double mu) -> double + { + return units.from_si(uRecipFVF, 1.0 / B) + / units.from_si(uVisc , mu); + }); + } + + // Inform createPropfuncTable() of number of active rows in + // this table. Needed to compute slopes of piecewise linear + // interpolants. + return numActRows; + }); + } + + /// Create linearised and padded 'TAB' vector entries of normalised + /// gas pressure nodes for all PVT function regions from PVTG (wet + /// gas with volatile/vaporised oil) keyword data. + /// + /// \param[in] numPressNodes Number of pressure nodes to allocate in + /// the output vector for each gas PVT table. Expected to be + /// equal to the number of declared pressure nodes in the + /// simulation run's TABDIMS keyword (NPPVT, Item 4). + /// + /// \param[in] units Active unit system. Needed to convert SI + /// convention pressure values (Pascal) to declared conventions + /// of the run specification. + /// + /// \param[in] pvtg Collection of PVTG tables for all PVT regions. + /// + /// \return Linearised and padded 'TAB' vector values for output gas + /// PVT tables. A unit-converted copy of the primary keys in + /// input table \p pvtg. + std::vector + pressureNodes(const std::size_t numPressNodes, + const Opm::UnitSystem& units, + const std::vector& pvtg) + { + // Columns [ Pg ] + const auto numTab = pvtg.size(); + + // One set of pressure nodes per table. + const auto numPrim = std::size_t{1}; + + const auto numRows = numPressNodes; + + // No dependent variables. + const auto numDep = std::size_t{0}; + + // Pressure node fill value = +2.0e20 + const auto fillVal = +2.0e20; + + return createPropfuncTable(numTab, numPrim, numRows, numDep, fillVal, + [&units, &pvtg](const std::size_t tableID, + const std::size_t primID, + Opm::LinearisedOutputTable& linTable) + -> std::size_t + { + const auto uPress = ::Opm::UnitSystem::measure::pressure; + + const auto& t = pvtg[tableID].getSaturatedTable(); + const auto& Pg = t.getColumn(0); + + const auto numActRows = Pg.size(); + + std::transform(std::begin(Pg), std::end(Pg), + linTable.column(tableID, primID, 0), + [&units](const double p) -> double + { + return units.from_si(uPress, p); + }); + + return numActRows; + }); + } + + /// Extract maximum effective composition nodes in PVTG table data + /// + /// \param[in] pvtg Collection of PVTG tables for all PVT regions. + /// + /// \return Maximum number of active rows across all sub-tables of \p + /// pvtg. + std::size_t maxNumCompNodes(const std::vector& pvtg) + { + auto max_nrpvt = std::size_t{0}; + + for (const auto& table : pvtg) { + const auto max_nrpvt_tab = + std::accumulate(table.begin(), table.end(), std::size_t{0}, + [](const std::size_t n, const Opm::SimpleTable& t) + { + return std::max(n, t.numRows()); + }); + + max_nrpvt = std::max(max_nrpvt, max_nrpvt_tab); + } + + return max_nrpvt; + } + /// Extract maximum effective pressure nodes in PVDG table data /// /// \param[in] pvdg Collection of PVDG tables for all PVT regions. @@ -1212,6 +1412,23 @@ namespace { namespace PVTFunc { return std::max(n, pvdg.getTable(table).numRows()); }); } + + /// Extract maximum effective pressure nodes in PVTG table data + /// + /// \param[in] pvtg Collection of PVTG tables for all PVT regions. + /// + /// \return Maximum number of active keys across all tables of \p + /// pvtg. + std::size_t maxNumPressNodes(const std::vector& pvtg) + { + if (pvtg.empty()) { return 0; } + + return std::accumulate(std::begin(pvtg), std::end(pvtg), std::size_t{0}, + [](const std::size_t n, const Opm::PvtgTable& t) -> std::size_t + { + return std::max(n, t.getSaturatedTable().numRows()); + }); + } } // Gas /// Functions to create linearised, padded, and normalised oil PVT @@ -2117,9 +2334,38 @@ namespace Opm { const auto numPressNodes = tabd.getNumPressureNodes(); + const auto hasPVTG = !tabMgr.getPvtgTables().empty(); const auto hasPVDG = tabMgr.hasTables("PVDG"); - if (hasPVDG) { + if (hasPVTG + hasPVDG != 1) { + // Inconsistent table specification. Maybe throw here? + return; + } + + if (hasPVTG) { + // Wet gas with vaporised/volatile oil. + const auto& pvtg = tabMgr.getPvtgTables(); + + const auto numCompNodes = + std::max(tabd.getNumRSNodes(), PVTFunc::Gas::maxNumCompNodes(pvtg)); + + const auto numPrimary = + std::max(numPressNodes, PVTFunc::Gas::maxNumPressNodes(pvtg)); + + const auto data = PVTFunc::Gas:: + fromPVTG(numCompNodes, numPrimary, this->units, pvtg); + + const auto pressData = PVTFunc::Gas:: + pressureNodes(numPrimary, this->units, pvtg); + + this->addData(TABDIMS_IBPVTG_OFFSET_ITEM, data); + this->addData(TABDIMS_JBPVTG_OFFSET_ITEM, pressData); + + this->m_tabdims[TABDIMS_NPPVTG_ITEM] = numPrimary; + this->m_tabdims[TABDIMS_NRPVTG_ITEM] = numCompNodes; + this->m_tabdims[TABDIMS_NTPVTG_ITEM] = pvtg.size(); + } + else { // Dry gas, pressure dependent compressibility. const auto& pvdg = tabMgr.getPvdgTables(); diff --git a/tests/test_Tables.cpp b/tests/test_Tables.cpp index 979e0c529..6349f3ae0 100644 --- a/tests/test_Tables.cpp +++ b/tests/test_Tables.cpp @@ -1656,6 +1656,697 @@ END } } +BOOST_AUTO_TEST_SUITE (Gas) + +BOOST_AUTO_TEST_CASE (PVDG_Regular) +{ + const auto rspec = std::string { R"(RUNSPEC +DIMENS + 10 10 10 / + +TITLE + Test PVDG Output + +GAS + +FIELD + +TABDIMS +-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT + 1* 2 1* 16 1* 1* +/ +)" }; + + const auto props = std::string { R"( +PVDG + 14.7 166.666 0.0080 + 264.7 12.093 0.0096 + 514.7 6.274 0.0112 +1014.7 3.197 0.0140 +2014.7 1.614 0.0189 +2514.7 1.294 0.0208 +3014.7 1.080 0.0228 +4014.7 0.811 0.0268 +5014.7 0.649 0.0309 +9014.7 0.386 0.0470 / + 400.0 5.900 0.0130 + 800.0 2.950 0.0135 +1200.0 1.960 0.0140 +1600.0 1.470 0.0145 +2000.0 1.180 0.0150 +2400.0 0.980 0.0155 +2800.0 0.840 0.0160 +3200.0 0.740 0.0165 +3600.0 0.650 0.0170 +4000.0 0.590 0.0175 +4400.0 0.540 0.0180 +4800.0 0.490 0.0185 +5200.0 0.450 0.0190 +5600.0 0.420 0.0195 / +)" }; + + const auto es = parse(rspec, props); + + auto tables = ::Opm::Tables(es.getUnits()); + tables.addPVTTables(es); + + const auto& tabdims = tables.tabdims(); + const auto& tab = tables.tab(); + + const auto ibpvtg = tabdims[ TABDIMS_IBPVTG_OFFSET_ITEM ] - 1; + const auto nppvtg = tabdims[ TABDIMS_NPPVTG_ITEM ]; + const auto ntpvtg = tabdims[ TABDIMS_NTPVTG_ITEM ]; + const auto ncol = 5; + + // Pg table defaulted + BOOST_CHECK_EQUAL(tabdims[TABDIMS_JBPVTG_OFFSET_ITEM], 1); + BOOST_CHECK_EQUAL(tabdims[TABDIMS_NRPVTG_ITEM], 1); + + BOOST_CHECK_EQUAL(nppvtg, 16); + BOOST_CHECK_EQUAL(ntpvtg, 2); + + const auto pvdg = std::vector { + &tab[ ibpvtg ] + 0, + &tab[ ibpvtg ] + ntpvtg*nppvtg*ncol + }; + + const auto expect_pvdg = makeTable(5, { + // Pg 1/Bg 1/(Bg*mu_g) d(1/Bg)/dPg d(1/(Bg*mu_g))/dPg + // + // Table 1 (10 pressure nodes) + 1.470000000000000e+01, 6.000024000096002e-03, 7.500030000120003e-01, 2.000000000000000e+20, 2.000000000000000e+20, + 2.647000000000000e+02, 8.269246671628215e-02, 8.613798616279391e+00, 3.067697708647446e-04, 3.145518246506956e-02, + 5.147000000000000e+02, 1.593879502709595e-01, 1.423106698847853e+01, 3.067819342187094e-04, 2.246907348879655e-02, + 1.014700000000000e+03, 3.127932436659369e-01, 2.234237454756692e+01, 3.068105867899547e-04, 1.622261511817678e-02, + 2.014700000000000e+03, 6.195786864931847e-01, 3.278194108429548e+01, 3.067854428272479e-04, 1.043956653672856e-02, + 2.514700000000000e+03, 7.727975270479135e-01, 3.715372726191892e+01, 3.064376811094576e-04, 8.743572355246868e-03, + 3.014700000000000e+03, 9.259259259259259e-01, 4.061078622482131e+01, 3.062567977560249e-04, 6.914117925804789e-03, + 4.014699999999999e+03, 1.233045622688040e+00, 4.600916502567312e+01, 3.071196967621139e-04, 5.398378800851812e-03, + 5.014700000000000e+03, 1.540832049306626e+00, 4.986511486429210e+01, 3.077864266185862e-04, 3.855949838618981e-03, + 9.014699999999999e+03, 2.590673575129534e+00, 5.512071436445817e+01, 2.624603814557271e-04, 1.313899875041518e-03, + 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, + 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, + 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, + 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, + 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, + 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, + + // =========================================================================================================================== + + // Table 2 (14 pressure nodes) + 4.000000000000000e+02, 1.694915254237289e-01, 1.303780964797914e+01, 2.000000000000000e+20, 2.000000000000000e+20, + 8.000000000000000e+02, 3.389830508474577e-01, 2.510985561833020e+01, 4.237288135593221e-04, 3.018011492587764e-02, + 1.200000000000000e+03, 5.102040816326532e-01, 3.644314868804666e+01, 4.280525769629887e-04, 2.833323267429114e-02, + 1.600000000000000e+03, 6.802721088435375e-01, 4.691531785127844e+01, 4.251700680272108e-04, 2.618042290807946e-02, + 2.000000000000000e+03, 8.474576271186441e-01, 5.649717514124294e+01, 4.179637956877669e-04, 2.395464322491127e-02, + 2.400000000000000e+03, 1.020408163265306e+00, 6.583278472679396e+01, 4.323763403666553e-04, 2.333902396387753e-02, + 2.800000000000000e+03, 1.190476190476191e+00, 7.440476190476191e+01, 4.251700680272113e-04, 2.142994294491990e-02, + 3.200000000000000e+03, 1.351351351351352e+00, 8.190008190008190e+01, 4.021879021879017e-04, 1.873829998829995e-02, + 3.600000000000000e+03, 1.538461538461539e+00, 9.049773755656106e+01, 4.677754677754675e-04, 2.149413914119791e-02, + 4.000000000000000e+03, 1.694915254237288e+00, 9.685230024213075e+01, 3.911342894393748e-04, 1.588640671392424e-02, + 4.400000000000000e+03, 1.851851851851852e+00, 1.028806584362140e+02, 3.923414940364085e-04, 1.507089548520804e-02, + 4.800000000000000e+03, 2.040816326530613e+00, 1.103143960286818e+02, 4.724111866969022e-04, 1.858434398116948e-02, + 5.199999999999999e+03, 2.222222222222222e+00, 1.169590643274854e+02, 4.535147392290250e-04, 1.661167074700910e-02, + 5.599999999999999e+03, 2.380952380952381e+00, 1.221001221001221e+02, 3.968253968253976e-04, 1.285264443159182e-02, + 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, + 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, + }); + + check_is_close(pvdg, expect_pvdg); +} + +BOOST_AUTO_TEST_CASE (PVDG_Exceed_Tabdims_Limits) +{ + // This checks that Flow's extended table allocation scheme does what + // it's supposed to do. Normally, one would announce the maximum sizes + // in the RUNSPEC keyword 'TABDIMS'. Note that the maximum sizes need + // to be big enough in order to run the case in ECLIPSE. Other than + // NTPVT, Flow does not really care about these declared maximum sizes. + + const auto rspec = std::string { R"(RUNSPEC +DIMENS + 10 10 10 / + +TITLE + Test PVDG Output + +GAS + +FIELD + +TABDIMS +-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT + 1* 2 1* 2 1* 1* +/ +)" }; + + const auto props = std::string { R"( +PVDG + 14.7 166.666 0.0080 + 264.7 12.093 0.0096 + 514.7 6.274 0.0112 +1014.7 3.197 0.0140 +2014.7 1.614 0.0189 +2514.7 1.294 0.0208 +3014.7 1.080 0.0228 +4014.7 0.811 0.0268 +5014.7 0.649 0.0309 +9014.7 0.386 0.0470 / + 400.0 5.900 0.0130 + 800.0 2.950 0.0135 +1200.0 1.960 0.0140 +1600.0 1.470 0.0145 +2000.0 1.180 0.0150 +2400.0 0.980 0.0155 +2800.0 0.840 0.0160 +3200.0 0.740 0.0165 +3600.0 0.650 0.0170 +4000.0 0.590 0.0175 +4400.0 0.540 0.0180 +4800.0 0.490 0.0185 +5200.0 0.450 0.0190 +5600.0 0.420 0.0195 / +)" }; + + const auto es = parse(rspec, props); + + auto tables = ::Opm::Tables(es.getUnits()); + tables.addPVTTables(es); + + const auto& tabdims = tables.tabdims(); + const auto& tab = tables.tab(); + + const auto ibpvtg = tabdims[ TABDIMS_IBPVTG_OFFSET_ITEM ] - 1; + const auto nppvtg = tabdims[ TABDIMS_NPPVTG_ITEM ]; + const auto ntpvtg = tabdims[ TABDIMS_NTPVTG_ITEM ]; + const auto ncol = 5; + + // Pg table defaulted + BOOST_CHECK_EQUAL(tabdims[TABDIMS_JBPVTG_OFFSET_ITEM], 1); + BOOST_CHECK_EQUAL(tabdims[TABDIMS_NRPVTG_ITEM], 1); + + BOOST_CHECK_EQUAL(nppvtg, 14); // Table 2 + BOOST_CHECK_EQUAL(ntpvtg, 2); + + const auto pvdg = std::vector { + &tab[ ibpvtg ] + 0, + &tab[ ibpvtg ] + ntpvtg*nppvtg*ncol + }; + + const auto expect_pvdg = makeTable(5, { + // Pg 1/Bg 1/(Bg*mu_g) d(1/Bg)/dPg d(1/(Bg*mu_g))/dPg + // + // Table 1 (10 pressure nodes) + 1.470000000000000e+01, 6.000024000096002e-03, 7.500030000120003e-01, 2.000000000000000e+20, 2.000000000000000e+20, + 2.647000000000000e+02, 8.269246671628215e-02, 8.613798616279391e+00, 3.067697708647446e-04, 3.145518246506956e-02, + 5.147000000000000e+02, 1.593879502709595e-01, 1.423106698847853e+01, 3.067819342187094e-04, 2.246907348879655e-02, + 1.014700000000000e+03, 3.127932436659369e-01, 2.234237454756692e+01, 3.068105867899547e-04, 1.622261511817678e-02, + 2.014700000000000e+03, 6.195786864931847e-01, 3.278194108429548e+01, 3.067854428272479e-04, 1.043956653672856e-02, + 2.514700000000000e+03, 7.727975270479135e-01, 3.715372726191892e+01, 3.064376811094576e-04, 8.743572355246868e-03, + 3.014700000000000e+03, 9.259259259259259e-01, 4.061078622482131e+01, 3.062567977560249e-04, 6.914117925804789e-03, + 4.014699999999999e+03, 1.233045622688040e+00, 4.600916502567312e+01, 3.071196967621139e-04, 5.398378800851812e-03, + 5.014700000000000e+03, 1.540832049306626e+00, 4.986511486429210e+01, 3.077864266185862e-04, 3.855949838618981e-03, + 9.014699999999999e+03, 2.590673575129534e+00, 5.512071436445817e+01, 2.624603814557271e-04, 1.313899875041518e-03, + 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, + 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, + 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, + 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, 2.000000000000000e+20, + + // =========================================================================================================================== + + // Table 2 (14 pressure nodes) + 4.000000000000000e+02, 1.694915254237289e-01, 1.303780964797914e+01, 2.000000000000000e+20, 2.000000000000000e+20, + 8.000000000000000e+02, 3.389830508474577e-01, 2.510985561833020e+01, 4.237288135593221e-04, 3.018011492587764e-02, + 1.200000000000000e+03, 5.102040816326532e-01, 3.644314868804666e+01, 4.280525769629887e-04, 2.833323267429114e-02, + 1.600000000000000e+03, 6.802721088435375e-01, 4.691531785127844e+01, 4.251700680272108e-04, 2.618042290807946e-02, + 2.000000000000000e+03, 8.474576271186441e-01, 5.649717514124294e+01, 4.179637956877669e-04, 2.395464322491127e-02, + 2.400000000000000e+03, 1.020408163265306e+00, 6.583278472679396e+01, 4.323763403666553e-04, 2.333902396387753e-02, + 2.800000000000000e+03, 1.190476190476191e+00, 7.440476190476191e+01, 4.251700680272113e-04, 2.142994294491990e-02, + 3.200000000000000e+03, 1.351351351351352e+00, 8.190008190008190e+01, 4.021879021879017e-04, 1.873829998829995e-02, + 3.600000000000000e+03, 1.538461538461539e+00, 9.049773755656106e+01, 4.677754677754675e-04, 2.149413914119791e-02, + 4.000000000000000e+03, 1.694915254237288e+00, 9.685230024213075e+01, 3.911342894393748e-04, 1.588640671392424e-02, + 4.400000000000000e+03, 1.851851851851852e+00, 1.028806584362140e+02, 3.923414940364085e-04, 1.507089548520804e-02, + 4.800000000000000e+03, 2.040816326530613e+00, 1.103143960286818e+02, 4.724111866969022e-04, 1.858434398116948e-02, + 5.199999999999999e+03, 2.222222222222222e+00, 1.169590643274854e+02, 4.535147392290250e-04, 1.661167074700910e-02, + 5.599999999999999e+03, 2.380952380952381e+00, 1.221001221001221e+02, 3.968253968253976e-04, 1.285264443159182e-02, + }); + + check_is_close(pvdg, expect_pvdg); +} + +BOOST_AUTO_TEST_CASE (PVTG_USat_Defaulted) +{ + const auto rspec = std::string { R"(RUNSPEC +DIMENS + 10 10 10 / + +TITLE + Test PVTG Output + +GAS + +METRIC + +TABDIMS +-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT + 1* 2 1* 7 1* 2 +/ +)" }; + + const auto props = std::string { R"( +PVTG +30 0.00014 0.0523 0.0234 + 0 0.0521 0.0238 / +90 0.00012 0.0132 0.0252 + 0 0.0131 0.0253 / +150 0.00015 0.00877 0.0281 + 0 0.00861 0.0275 / +210 0.00019 0.00554 0.0318 + 0 0.00555 0.0302 / +270 0.00029 0.00417 0.0355 + 0 0.00421 0.0330 / +330 0.00049 0.00357 0.0392 + 0 0.00361 0.0358 / +530 0.00060 0.00356 0.0393 + 0 0.00360 0.0359 / +/ +60 0.00014 0.0523 0.0234 / +120 0.00012 0.0132 0.0252 / +180 0.00015 0.00877 0.0281 / +240 0.00019 0.00554 0.0318 / +300 0.00029 0.00417 0.0355 / +360 0.00049 0.00357 0.0392 / +560 0.00060 0.00356 0.0393 + 0 0.00360 0.0359 / +/ +)" }; + + const auto es = parse(rspec, props); + + auto tables = ::Opm::Tables(es.getUnits()); + tables.addPVTTables(es); + + const auto& tabdims = tables.tabdims(); + const auto& tab = tables.tab(); + + const auto ibpvtg = tabdims[ TABDIMS_IBPVTG_OFFSET_ITEM ] - 1; + const auto jbpvtg = tabdims[ TABDIMS_JBPVTG_OFFSET_ITEM ] - 1; + const auto nppvtg = tabdims[ TABDIMS_NPPVTG_ITEM ]; + const auto nrpvtg = tabdims[ TABDIMS_NRPVTG_ITEM ]; + const auto ntpvtg = tabdims[ TABDIMS_NTPVTG_ITEM ]; + const auto ncol = 5; + + BOOST_CHECK_EQUAL(nppvtg, 7); + BOOST_CHECK_EQUAL(nrpvtg, 2); + BOOST_CHECK_EQUAL(ntpvtg, 2); + + const auto pvtg = std::vector { + &tab[ ibpvtg ] + 0, + &tab[ ibpvtg ] + ntpvtg*nppvtg*nrpvtg*ncol + }; + + const auto pg = std::vector { + &tab[ jbpvtg ] + 0, + &tab[ jbpvtg ] + ntpvtg*nppvtg + }; + + const auto expect_pvtg = makeTable(5, { + // Rv 1/Bg 1/(Bg*mu_g) d(1/Bg)/dRv d(1/(Bg*mu_g))/dRv + // + // Table 1 (Pg 1) + 1.400000000000000e-04, 1.912045889101339e+01, 8.171136278210848e+02, -2.000000000000000e+20, -2.000000000000000e+20, + 0, 1.919385796545106e+01, 8.064646203971031e+02, -5.242791031262176e+02, 7.606433874272674e+04, + + // Table 1 (Pg 2) ------------------------------------------------------------------------------------------------------------ + + 1.200000000000000e-04, 7.575757575757576e+01, 3.006253006253006e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 0, 7.633587786259541e+01, 3.017228374015629e+03, -4.819184208497044e+03, -9.146139802185188e+04, + + // Table 1 (Pg 3) ------------------------------------------------------------------------------------------------------------ + + 1.500000000000000e-04, 1.140250855188141e+02, 4.057832224868830e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 0, 1.161440185830430e+02, 4.223418857565199e+03, -1.412622042819227e+04, -1.103910884642458e+06, + + // Table 1 (Pg 4) ------------------------------------------------------------------------------------------------------------ + + 1.900000000000000e-04, 1.805054151624549e+02, 5.676270917058329e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 0, 1.801801801801802e+02, 5.966231131794045e+03, 1.711763064603725e+03, -1.526106393345871e+06, + + // Table 1 (Pg 5) ------------------------------------------------------------------------------------------------------------ + + 2.900000000000000e-04, 2.398081534772182e+02, 6.755159252879387e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 0, 2.375296912114014e+02, 7.197869430648528e+03, 7.856766433850982e+03, -1.526586819893588e+06, + + // Table 1 (Pg 6) ------------------------------------------------------------------------------------------------------------ + + 4.900000000000000e-04, 2.801120448179272e+02, 7.145715429028755e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 0, 2.770083102493075e+02, 7.737662297466691e+03, 6.334152180856531e+03, -1.208054833546807e+06, + + // Table 1 (Pg 7) ------------------------------------------------------------------------------------------------------------ + + 5.999999999999999e-04, 2.808988764044944e+02, 7.147554106984589e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 0, 2.777777777777778e+02, 7.737542556484059e+03, 5.201831044527695e+03, -9.833140824991158e+05, + + // ========================================================================================================================== + + // Table 2 (Pg 1) + 1.400000000000000e-04, 1.912045889101339e+01, 8.171136278210848e+02, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 2 (Pg 2) ------------------------------------------------------------------------------------------------------------ + + 1.200000000000000e-04, 7.575757575757576e+01, 3.006253006253006e+03, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 2 (Pg 3) ------------------------------------------------------------------------------------------------------------ + + 1.500000000000000e-04, 1.140250855188141e+02, 4.057832224868830e+03, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 2 (Pg 4) ------------------------------------------------------------------------------------------------------------ + + 1.900000000000000e-04, 1.805054151624549e+02, 5.676270917058329e+03, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 2 (Pg 5) ------------------------------------------------------------------------------------------------------------ + + 2.900000000000000e-04, 2.398081534772182e+02, 6.755159252879387e+03, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 2 (Pg 6) ------------------------------------------------------------------------------------------------------------ + + 4.900000000000000e-04, 2.801120448179272e+02, 7.145715429028755e+03, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 2 (Pg 7) ------------------------------------------------------------------------------------------------------------ + + 5.999999999999999e-04, 2.808988764044944e+02, 7.147554106984589e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 0, 2.777777777777778e+02, 7.737542556484059e+03, 5.201831044527695e+03, -9.833140824991158e+05, + }); + + const auto expect_pg = makeTable(1, { + // Table 1 + 30, 90, 150, 210, 270, 330, 530, + + // Table 2 + 60, 120, 180, 240, 300, 360, 560, + }); + + check_is_close(pvtg, expect_pvtg); + check_is_close(pg , expect_pg ); +} + +BOOST_AUTO_TEST_CASE (PVTG_USat_Full_Large_Tabdims) +{ + const auto rspec = std::string { R"(RUNSPEC +DIMENS + 10 10 10 / + +TITLE + Test PVTG Output + +GAS + +METRIC + +TABDIMS +-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT + 1* 1 1* 7 1* 5 +/ +)" }; + + const auto props = std::string { R"( +PVTG + 50.00 0.00000497 0.024958 0.01441 + 0.00000248 0.024958 0.01440 + 0.00000000 0.024958 0.01440 / + 70.00 0.00000521 0.017639 0.01491 + 0.00000261 0.017641 0.01490 + 0.00000000 0.017643 0.01490 / + 90.00 0.00000627 0.013608 0.01547 + 0.00000313 0.013611 0.01546 + 0.00000000 0.013615 0.01544 / +110.00 0.00000798 0.011072 0.01609 + 0.00000399 0.011076 0.01607 + 0.00000000 0.011081 0.01605 / +/ +)" }; + + const auto es = parse(rspec, props); + + auto tables = ::Opm::Tables(es.getUnits()); + tables.addPVTTables(es); + + const auto& tabdims = tables.tabdims(); + const auto& tab = tables.tab(); + + const auto ibpvtg = tabdims[ TABDIMS_IBPVTG_OFFSET_ITEM ] - 1; + const auto jbpvtg = tabdims[ TABDIMS_JBPVTG_OFFSET_ITEM ] - 1; + const auto nppvtg = tabdims[ TABDIMS_NPPVTG_ITEM ]; + const auto nrpvtg = tabdims[ TABDIMS_NRPVTG_ITEM ]; + const auto ntpvtg = tabdims[ TABDIMS_NTPVTG_ITEM ]; + const auto ncol = 5; + + BOOST_CHECK_EQUAL(nppvtg, 7); + BOOST_CHECK_EQUAL(nrpvtg, 5); + BOOST_CHECK_EQUAL(ntpvtg, 1); + + const auto pvtg = std::vector { + &tab[ ibpvtg ] + 0, + &tab[ ibpvtg ] + ntpvtg*nppvtg*nrpvtg*ncol + }; + + const auto pg = std::vector { + &tab[ jbpvtg ] + 0, + &tab[ jbpvtg ] + ntpvtg*nppvtg + }; + + const auto expect_pvtg = makeTable(5, { + // Rv 1/Bg 1/(Bg*mu_g) d(1/Bg)/dRv d(1/(Bg*mu_g))/dRv + // + // Table 1 (Pg 1) + 4.970000000000000e-06, 4.006731308598445e+01, 2.780521380012800e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 2.480000000000000e-06, 4.006731308598445e+01, 2.782452297637809e+03, 0, -7.754689257064208e+05, + 0, 4.006731308598445e+01, 2.782452297637809e+03, 0, 0, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 1 (Pg 2) ------------------------------------------------------------------------------------------------------------ + + 5.210000000000000e-06, 5.669255626736210e+01, 3.802317657100074e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 2.610000000000000e-06, 5.668612890425712e+01, 3.804438181493767e+03, 2.472062732683009e+03, -8.155863052665014e+05, + 0, 5.667970299835629e+01, 3.804006912641362e+03, 2.462032912196776e+03, 1.652371082011811e+05, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 1 (Pg 3) ------------------------------------------------------------------------------------------------------------ + + 6.270000000000000e-06, 7.348618459729570e+01, 4.750238176942192e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 3.130000000000000e-06, 7.346998751010213e+01, 4.752263098971676e+03, 5.158308023431543e+03, -6.448796272243677e+05, + 0, 7.344840249724568e+01, 4.757020887127311e+03, 6.896170241676778e+03, -1.520060113621228e+06, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 1 (Pg 4) ------------------------------------------------------------------------------------------------------------ + + 7.980000000000000e-06, 9.031791907514450e+01, 5.613295156938751e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 3.990000000000000e-06, 9.028530155290719e+01, 5.618251496758381e+03, 8.174817603337499e+03, -1.242190430985102e+06, + 0, 9.024456276509339e+01, 5.622714190971551e+03, 1.021022250972279e+04, -1.118469727611510e+06, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 1 (Pg 5) ------------------------------------------------------------------------------------------------------------ + + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 1 (Pg 6) ------------------------------------------------------------------------------------------------------------ + + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 1 (Pg 7) ------------------------------------------------------------------------------------------------------------ + + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + }); + + const auto expect_pg = makeTable(1, { + // Table 1 + 50.00, 70.00, 90.00, 110.00, 2.0e20, 2.0e20, 2.0e20, + }); + + check_is_close(pvtg, expect_pvtg); + check_is_close(pg , expect_pg ); +} + +BOOST_AUTO_TEST_CASE (PVTG_Exceed_Tabdims_Limits) +{ + // This checks that Flow's extended table allocation scheme does what + // it's supposed to do. Normally, one would announce the maximum sizes + // in the RUNSPEC keyword 'TABDIMS'. Note that the maximum sizes need + // to be big enough in order to run the case in ECLIPSE. Other than + // NTPVT, Flow does not really care about these declared maximum sizes. + + const auto rspec = std::string { R"(RUNSPEC +DIMENS + 10 10 10 / + +TITLE + Test PVTG Output + +GAS + +METRIC + +TABDIMS +-- NTSFUN NTPVT NSSFUN NPPVT NTFIP NRPVT + 1* 2 1* 1 1* 1 +/ +)" }; + + const auto props = std::string { R"( +PVTG + 50.00 0.00000497 0.024958 0.01441 + 0.00000248 0.024958 0.01440 + 0.00000000 0.024958 0.01440 / + 70.00 0.00000521 0.017639 0.01491 + 0.00000261 0.017641 0.01490 + 0.00000000 0.017643 0.01490 / + 90.00 0.00000627 0.013608 0.01547 + 0.00000313 0.013611 0.01546 + 0.00000000 0.013615 0.01544 / +110.00 0.00000798 0.011072 0.01609 + 0.00000399 0.011076 0.01607 + 0.00000000 0.011081 0.01605 / +130.00 0.00001041 0.009340 0.01677 + 0.00000520 0.009346 0.01674 + 0.00000000 0.009352 0.01671 / +/ + 50.00 0.00000497 0.024958 0.01441 + 0.00000248 0.024958 0.01440 + 0.00000000 0.024958 0.01440 / +/ +)" }; + + const auto es = parse(rspec, props); + + auto tables = ::Opm::Tables(es.getUnits()); + tables.addPVTTables(es); + + const auto& tabdims = tables.tabdims(); + const auto& tab = tables.tab(); + + const auto ibpvtg = tabdims[ TABDIMS_IBPVTG_OFFSET_ITEM ] - 1; + const auto jbpvtg = tabdims[ TABDIMS_JBPVTG_OFFSET_ITEM ] - 1; + const auto nppvtg = tabdims[ TABDIMS_NPPVTG_ITEM ]; + const auto nrpvtg = tabdims[ TABDIMS_NRPVTG_ITEM ]; + const auto ntpvtg = tabdims[ TABDIMS_NTPVTG_ITEM ]; + const auto ncol = 5; + + BOOST_CHECK_EQUAL(nppvtg, 5); // Table 1 + BOOST_CHECK_EQUAL(nrpvtg, 3); // Table 1, Pg 1 + BOOST_CHECK_EQUAL(ntpvtg, 2); // TABDIMS + + const auto pvtg = std::vector { + &tab[ ibpvtg ] + 0, + &tab[ ibpvtg ] + ntpvtg*nppvtg*nrpvtg*ncol + }; + + const auto pg = std::vector { + &tab[ jbpvtg ] + 0, + &tab[ jbpvtg ] + ntpvtg*nppvtg + }; + + const auto expect_pvtg = makeTable(5, { + // Rv 1/Bg 1/(Bg*mu_g) d(1/Bg)/dRv d(1/(Bg*mu_g))/dRv + // + // Table 1 (Pg 1) + 4.970000000000000e-06, 4.006731308598445e+01, 2.780521380012800e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 2.480000000000000e-06, 4.006731308598445e+01, 2.782452297637809e+03, 0, -7.754689257064208e+05, + 0, 4.006731308598445e+01, 2.782452297637809e+03, 0, 0, + + // Table 1 (Pg 2) ------------------------------------------------------------------------------------------------------------ + + 5.210000000000000e-06, 5.669255626736210e+01, 3.802317657100074e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 2.610000000000000e-06, 5.668612890425712e+01, 3.804438181493767e+03, 2.472062732683009e+03, -8.155863052665014e+05, + 0, 5.667970299835629e+01, 3.804006912641362e+03, 2.462032912196776e+03, 1.652371082011811e+05, + + // Table 1 (Pg 3) ------------------------------------------------------------------------------------------------------------ + + 6.270000000000000e-06, 7.348618459729570e+01, 4.750238176942192e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 3.130000000000000e-06, 7.346998751010213e+01, 4.752263098971676e+03, 5.158308023431543e+03, -6.448796272243677e+05, + 0, 7.344840249724568e+01, 4.757020887127311e+03, 6.896170241676778e+03, -1.520060113621228e+06, + + // Table 1 (Pg 4) ------------------------------------------------------------------------------------------------------------ + + 7.980000000000000e-06, 9.031791907514450e+01, 5.613295156938751e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 3.990000000000000e-06, 9.028530155290719e+01, 5.618251496758381e+03, 8.174817603337499e+03, -1.242190430985102e+06, + 0, 9.024456276509339e+01, 5.622714190971551e+03, 1.021022250972279e+04, -1.118469727611510e+06, + + // Table 1 (Pg 5) ------------------------------------------------------------------------------------------------------------ + + 1.041000000000000e-05, 1.070663811563169e+02, 6.384399591909179e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 5.200000000000000e-06, 1.069976460517869e+02, 6.391735128541628e+03, 1.319291833590461e+04, -1.407972482235984e+06, + 0, 1.069289991445680e+02, 6.399102282738958e+03, 1.320132831131706e+04, -1.416760422563444e+06, + + // ========================================================================================================================== + + // Table 2 (Pg 1) + 4.970000000000000e-06, 4.006731308598445e+01, 2.780521380012800e+03, -2.000000000000000e+20, -2.000000000000000e+20, + 2.480000000000000e-06, 4.006731308598445e+01, 2.782452297637809e+03, 0, -7.754689257064208e+05, + 0, 4.006731308598445e+01, 2.782452297637809e+03, 0, 0, + + // Table 2 (Pg 2) ------------------------------------------------------------------------------------------------------------ + + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 2 (Pg 3) ------------------------------------------------------------------------------------------------------------ + + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 2 (Pg 4) ------------------------------------------------------------------------------------------------------------ + + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + + // Table 2 (Pg 5) ------------------------------------------------------------------------------------------------------------ + + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, -2.000000000000000e+20, + }); + + const auto expect_pg = makeTable(1, { + // Table 1 + 50.00, 70.00, 90.00, 110.00, 130.0, + + // Table 2 + 50.00, 2.0e20, 2.0e20, 2.0e20, 2.0e20, + }); + + check_is_close(pvtg, expect_pvtg); + check_is_close(pg , expect_pg ); +} + +BOOST_AUTO_TEST_SUITE_END () + +// ===================================================================== + BOOST_AUTO_TEST_SUITE (Oil) BOOST_AUTO_TEST_CASE (PVCDO)