diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index e27f718d..3bf606de 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -177,7 +177,8 @@ list (APPEND TEST_SOURCE_FILES list (APPEND TEST_DATA_FILES tests/extratestdata.xml tests/testdata.xml - tests/testFluid.DATA + tests/liveoil.DATA + tests/wetgas.DATA tests/testBlackoilState1.DATA tests/testBlackoilState2.DATA tests/wells_manager_data.data diff --git a/cmake/Modules/FindSuperLU.cmake b/cmake/Modules/FindSuperLU.cmake index 41b88602..e8616989 100644 --- a/cmake/Modules/FindSuperLU.cmake +++ b/cmake/Modules/FindSuperLU.cmake @@ -54,7 +54,7 @@ endif() # print message if there was still no blas found! if(NOT BLAS_FOUND AND NOT SUPERLU_BLAS_LIBRARY) - message("BLAS not found but required for SuperLU") + message(STATUS "BLAS not found but required for SuperLU") return() endif() list(APPEND CMAKE_REQUIRED_LIBRARIES "${SUPERLU_BLAS_LIBRARY}") @@ -69,7 +69,7 @@ if (NOT SUPERLU_INCLUDE_DIR) ) endif() if(NOT SUPERLU_INCLUDE_DIR) - message("Directory with the SuperLU include files not found") + message(STATUS "Directory with the SuperLU include files not found") return() endif() list(APPEND CMAKE_REQUIRED_INCLUDES "${SUPERLU_INCLUDE_DIR}") @@ -84,7 +84,7 @@ if (NOT SUPERLU_LIBRARY) ) endif() if(NOT SUPERLU_LIBRARY) - message("Directory with the SuperLU library not found") + message(STATUS "Directory with the SuperLU library not found") return() endif() list(APPEND CMAKE_REQUIRED_LIBRARIES "${SUPERLU_LIBRARY}") diff --git a/cmake/Modules/Finddune-common.cmake b/cmake/Modules/Finddune-common.cmake index 19717b40..564aef54 100644 --- a/cmake/Modules/Finddune-common.cmake +++ b/cmake/Modules/Finddune-common.cmake @@ -50,6 +50,7 @@ int main (void) { HAVE_ARRAY; HAVE_BOOST_MAKE_SHARED_HPP; HAVE_BOOST_SHARED_PTR_HPP; + HAVE_DUNE_BOOST; HAVE_GMP; HAVE_MAKE_SHARED; HAVE_MPI; diff --git a/cmake/Modules/Finddune-istl.cmake b/cmake/Modules/Finddune-istl.cmake index 8c50d3d5..60f2201b 100644 --- a/cmake/Modules/Finddune-istl.cmake +++ b/cmake/Modules/Finddune-istl.cmake @@ -49,6 +49,7 @@ int main (void) { HAVE_MPI; HAVE_PARMETIS; HAVE_SUPERLU; + HAVE_UMFPACK; SUPERLU_MIN_VERSION_4_3; SUPERLU_POST_2005_VERSION ") diff --git a/cmake/Modules/OpmAliases.cmake b/cmake/Modules/OpmAliases.cmake new file mode 100644 index 00000000..392749b9 --- /dev/null +++ b/cmake/Modules/OpmAliases.cmake @@ -0,0 +1,26 @@ +# - Alias probed variables for compatibility with DUNE buildsystem +# +# DUNE build system sets some variables which have different names +# in the CMake modules we are using; this module set those variable +# so they can be exported to config.h visible to DUNE headers + +function (set_aliases) + # hardcoded list of "dune-var opm-var" pairs, where the components + # are separated by space + set (aliases + "HAVE_UMFPACK HAVE_SUITESPARSE_UMFPACK_H" + "HAVE_DUNE_BOOST HAVE_BOOST" + ) + foreach (alias IN LISTS aliases) + # convert entry "X Y" into a list "X;Y", then pick apart + string (REGEX REPLACE "\ +" ";" tuple "${alias}") + list (GET tuple 0 var) + list (GET tuple 1 name) + + # write this alias to cache + set (${var} ${${name}} PARENT_SCOPE) + endforeach (alias) +endfunction (set_aliases) + +# always call this when the module is imported +set_aliases () diff --git a/cmake/Modules/OpmFind.cmake b/cmake/Modules/OpmFind.cmake index 2d9ecead..58501ba9 100644 --- a/cmake/Modules/OpmFind.cmake +++ b/cmake/Modules/OpmFind.cmake @@ -137,16 +137,22 @@ macro (find_and_append_package_to prefix name) # using config mode is better than using module (aka. find) mode # because then the package has already done all its probes and # stored them in the config file for us - if (NOT (${name}_FOUND OR ${NAME}_FOUND)) + if (NOT DEFINED ${name}_FOUND AND NOT DEFINED ${NAME}_FOUND) if (${name}_DIR) message (STATUS "Finding package ${name} using config mode") find_package (${name} ${ARGN} NO_MODULE PATHS ${${name}_DIR} NO_DEFAULT_PATH) - else (${name}_DIR) + else () message (STATUS "Finding package ${name} using module mode") find_package (${name} ${ARGN}) - endif (${name}_DIR) - endif (NOT (${name}_FOUND OR ${NAME}_FOUND)) - endif (CMAKE_DISABLE_FIND_PACKAGE_${name}) + endif () + endif () + if (NOT DEFINED ${name}_FOUND) + set (${name}_FOUND "${${NAME}_FOUND}") + endif () + if (NOT DEFINED ${NAME}_FOUND) + set (${NAME}_FOUND "${${name}_FOUND}") + endif () + endif () # the variable "NAME" may be replaced during find_package (as this is # now a macro, and not a function anymore), so we must reinitialize diff --git a/cmake/Modules/OpmLibMain.cmake b/cmake/Modules/OpmLibMain.cmake index 535cd5ff..7aef0322 100644 --- a/cmake/Modules/OpmLibMain.cmake +++ b/cmake/Modules/OpmLibMain.cmake @@ -89,6 +89,9 @@ endif (COMMAND prereqs_hook) include (OpmFind) find_and_append_package_list_to (${project} ${${project}_DEPS}) +# set aliases to probed variables +include (OpmAliases) + # remove the dependency on the testing framework from the main library; # it is not possible to query for Boost twice with different components. list (REMOVE_ITEM "${project}_LIBRARIES" "${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}") diff --git a/cmake/Modules/OpmPackage.cmake b/cmake/Modules/OpmPackage.cmake index 538fc4f3..3819ce74 100644 --- a/cmake/Modules/OpmPackage.cmake +++ b/cmake/Modules/OpmPackage.cmake @@ -344,11 +344,11 @@ macro (find_opm_package module deps header lib defs prog conf) if ((NOT (${module}_INCLUDE_DIR ${_and_lib_var} AND HAVE_${MODULE})) AND (_${module}_required OR NOT _${module}_quiet)) if (DEFINED ${module}_DIR) - message ("${module}_DIR = ${${module}_DIR}") + message (STATUS "${module}_DIR = ${${module}_DIR}") elseif (DEFINED ${module}_ROOT) - message ("${module}_ROOT = ${${module}_ROOT}") + message (STATUS "${module}_ROOT = ${${module}_ROOT}") elseif (DEFINED ${MODULE}_ROOT) - message ("${MODULE}_ROOT = ${${MODULE}_ROOT}") + message (STATUS "${MODULE}_ROOT = ${${MODULE}_ROOT}") endif (DEFINED ${module}_DIR) endif ((NOT (${module}_INCLUDE_DIR ${_and_lib_var} AND HAVE_${MODULE})) AND (_${module}_required OR NOT _${module}_quiet)) diff --git a/cmake/OPM-CMake.md b/cmake/OPM-CMake.md index 18a69e3d..c1f015d5 100644 --- a/cmake/OPM-CMake.md +++ b/cmake/OPM-CMake.md @@ -423,6 +423,12 @@ Wrapper script which emulates an autotools front-end, making the build system usable with dunecontrol. There is one in the project root directory which just forwards everything to the main script in `cmake/Scripts`. + + OpmAliases + +Copy variables which are probed by our find modules to the names which +are expected by DUNE. + OpmCompile diff --git a/opm/core/io/eclipse/EclipseGridParser.cpp b/opm/core/io/eclipse/EclipseGridParser.cpp index c33d6fd7..f0106cc3 100644 --- a/opm/core/io/eclipse/EclipseGridParser.cpp +++ b/opm/core/io/eclipse/EclipseGridParser.cpp @@ -97,6 +97,7 @@ namespace EclipseKeywords string("SHEARMOD"), string("POISSONMOD"), string("PWAVEMOD"), string("MULTPV"), string("PRESSURE"), string("SGAS"), string("SWAT"), string("SOIL"), string("RS"), + string("RV"), string("DXV"), string("DYV"), string("DZV"), string("DEPTHZ"), string("TOPS"), string("MAPAXES"), string("SWCR"), string("SWL"), string("SWU"), @@ -570,6 +571,8 @@ void EclipseGridParser::convertToSI() unit = units_.pressure; } else if (key == "RS") { unit = units_.gasvol_s / units_.liqvol_s; + } else if (key == "RV") { + unit = units_.liqvol_s / units_.gasvol_s; } else if (key == "MAPAXES") { OPM_MESSAGE("Not applying units to MAPAXES yet!"); unit = 1.0; diff --git a/opm/core/props/pvt/SinglePvtConstCompr.hpp b/opm/core/props/pvt/SinglePvtConstCompr.hpp index db73fc88..e97a7242 100644 --- a/opm/core/props/pvt/SinglePvtConstCompr.hpp +++ b/opm/core/props/pvt/SinglePvtConstCompr.hpp @@ -224,14 +224,24 @@ namespace Opm } - virtual void rbub(const int n, + virtual void rsSat(const int n, const double* /*p*/, - double* output_rbub, - double* output_drbubdp) const + double* output_rsSat, + double* output_drsSatdp) const { - std::fill(output_rbub, output_rbub + n, 0.0); - std::fill(output_drbubdp, output_drbubdp + n, 0.0); + std::fill(output_rsSat, output_rsSat + n, 0.0); + std::fill(output_drsSatdp, output_drsSatdp + n, 0.0); + } + + virtual void rvSat(const int n, + const double* /*p*/, + double* output_rvSat, + double* output_drvSatdp) const + + { + std::fill(output_rvSat, output_rvSat + n, 0.0); + std::fill(output_drvSatdp, output_drvSatdp + n, 0.0); } virtual void R(const int n, diff --git a/opm/core/props/pvt/SinglePvtDead.cpp b/opm/core/props/pvt/SinglePvtDead.cpp index 664c38f2..2db23dbe 100644 --- a/opm/core/props/pvt/SinglePvtDead.cpp +++ b/opm/core/props/pvt/SinglePvtDead.cpp @@ -176,13 +176,22 @@ namespace Opm } - void SinglePvtDead::rbub(const int n, + void SinglePvtDead::rsSat(const int n, const double* /*p*/, - double* output_rbub, - double* output_drbubdp) const + double* output_rsSat, + double* output_drsSatdp) const { - std::fill(output_rbub, output_rbub + n, 0.0); - std::fill(output_drbubdp, output_drbubdp + n, 0.0); + std::fill(output_rsSat, output_rsSat + n, 0.0); + std::fill(output_drsSatdp, output_drsSatdp + n, 0.0); + } + + void SinglePvtDead::rvSat(const int n, + const double* /*p*/, + double* output_rvSat, + double* output_drvSatdp) const + { + std::fill(output_rvSat, output_rvSat + n, 0.0); + std::fill(output_drvSatdp, output_drvSatdp + n, 0.0); } void SinglePvtDead::R(const int n, diff --git a/opm/core/props/pvt/SinglePvtDead.hpp b/opm/core/props/pvt/SinglePvtDead.hpp index 8b36c5fc..2c40a951 100644 --- a/opm/core/props/pvt/SinglePvtDead.hpp +++ b/opm/core/props/pvt/SinglePvtDead.hpp @@ -49,7 +49,7 @@ namespace Opm double* output_mu) const; /// Viscosity and its derivatives as a function of p and r. - /// The fluid is considered saturated if r >= rbub(p). + /// The fluid is considered saturated if r >= rsSat(p). virtual void mu(const int n, const double* p, const double* r, @@ -81,7 +81,7 @@ namespace Opm double* output_dBdp) const; /// The inverse of the formation volume factor b = 1 / B, and its derivatives as a function of p and r. - /// The fluid is considered saturated if r >= rbub(p). + /// The fluid is considered saturated if r >= rsSat(p). virtual void b(const int n, const double* p, const double* r, @@ -100,11 +100,17 @@ namespace Opm double* output_dbdr) const; - /// Gas resolution and its derivatives at bublepoint as a function of p. - virtual void rbub(const int n, + /// Solution gas/oil ratio and its derivatives at saturated conditions as a function of p. + virtual void rsSat(const int n, const double* p, - double* output_rbub, - double* output_drbubdp) const; + double* output_rsSat, + double* output_drsSatdp) const; + + /// Vapor oil/gas ratio and its derivatives at saturated conditions as a function of p. + virtual void rvSat(const int n, + const double* p, + double* output_rvSat, + double* output_drvSatdp) const; /// Solution factor as a function of p and z. virtual void R(const int n, diff --git a/opm/core/props/pvt/SinglePvtDeadSpline.cpp b/opm/core/props/pvt/SinglePvtDeadSpline.cpp index 5db3521d..a0873e0b 100644 --- a/opm/core/props/pvt/SinglePvtDeadSpline.cpp +++ b/opm/core/props/pvt/SinglePvtDeadSpline.cpp @@ -178,13 +178,22 @@ namespace Opm } - void SinglePvtDeadSpline::rbub(const int n, + void SinglePvtDeadSpline::rsSat(const int n, const double* /*p*/, - double* output_rbub, - double* output_drbubdp) const + double* output_rsSat, + double* output_drsSatdp) const { - std::fill(output_rbub, output_rbub + n, 0.0); - std::fill(output_drbubdp, output_drbubdp + n, 0.0); + std::fill(output_rsSat, output_rsSat + n, 0.0); + std::fill(output_drsSatdp, output_drsSatdp + n, 0.0); + } + + void SinglePvtDeadSpline::rvSat(const int n, + const double* /*p*/, + double* output_rvSat, + double* output_drvSatdp) const + { + std::fill(output_rvSat, output_rvSat + n, 0.0); + std::fill(output_drvSatdp, output_drvSatdp + n, 0.0); } void SinglePvtDeadSpline::R(const int n, diff --git a/opm/core/props/pvt/SinglePvtDeadSpline.hpp b/opm/core/props/pvt/SinglePvtDeadSpline.hpp index b6af388d..337c8a80 100644 --- a/opm/core/props/pvt/SinglePvtDeadSpline.hpp +++ b/opm/core/props/pvt/SinglePvtDeadSpline.hpp @@ -50,7 +50,7 @@ namespace Opm double* output_mu) const; /// Viscosity and its derivatives as a function of p and r. - /// The fluid is considered saturated if r >= rbub(p). + /// The fluid is considered saturated if r >= rsSat(p). virtual void mu(const int n, const double* p, const double* r, @@ -82,7 +82,7 @@ namespace Opm double* output_dBdp) const; /// The inverse of the formation volume factor b = 1 / B, and its derivatives as a function of p and r. - /// The fluid is considered saturated if r >= rbub(p). + /// The fluid is considered saturated if r >= rsSat(p). virtual void b(const int n, const double* p, const double* r, @@ -100,11 +100,17 @@ namespace Opm double* output_dbdp, double* output_dbdr) const; - /// Gas resolution and its derivatives at bublepoint as a function of p. - virtual void rbub(const int n, + /// Solution gas/oil ratio and its derivatives at saturated conditions as a function of p. + virtual void rsSat(const int n, const double* p, - double* output_rbub, - double* output_drbubdp) const; + double* output_rsSat, + double* output_drsSatdp) const; + + /// Vapor oil/gas ratio and its derivatives at saturated conditions as a function of p. + virtual void rvSat(const int n, + const double* p, + double* output_rvSat, + double* output_drvSatdp) const; /// Solution factor as a function of p and z. virtual void R(const int n, diff --git a/opm/core/props/pvt/SinglePvtInterface.hpp b/opm/core/props/pvt/SinglePvtInterface.hpp index 1deddb5e..83d3febb 100644 --- a/opm/core/props/pvt/SinglePvtInterface.hpp +++ b/opm/core/props/pvt/SinglePvtInterface.hpp @@ -56,7 +56,7 @@ namespace Opm double* output_mu) const = 0; /// Viscosity as a function of p and r. - /// The fluid is considered saturated if r >= rbub(p). + /// The fluid is considered saturated if r >= rsSat(p). virtual void mu(const int n, const double* p, const double* r, @@ -88,7 +88,7 @@ namespace Opm double* output_dBdp) const = 0; /// The inverse of the volume factor b = 1 / B as a function of p and r. - /// The fluid is considered saturated if r >= rbub(p). + /// The fluid is considered saturated if r >= rsSat(p). virtual void b(const int n, const double* p, const double* r, @@ -106,11 +106,17 @@ namespace Opm double* output_dbdp, double* output_dpdr) const = 0; - /// Gas resolution at bublepoint as a function of pressure - virtual void rbub(const int n, + /// Solution gas/oil ratio and its derivatives at saturated conditions as a function of p. + virtual void rsSat(const int n, const double* p, - double* output_rbub, - double* output_drbubdp) const = 0; + double* output_rsSat, + double* output_drsSatdp) const = 0; + + /// Vapor oil/gas ratio and its derivatives at saturated conditions as a function of p. + virtual void rvSat(const int n, + const double* p, + double* output_rvSat, + double* output_drvSatdp) const = 0; /// Solution factor as a function of p and z. diff --git a/opm/core/props/pvt/SinglePvtLiveGas.cpp b/opm/core/props/pvt/SinglePvtLiveGas.cpp index 2852237d..639ee3ac 100644 --- a/opm/core/props/pvt/SinglePvtLiveGas.cpp +++ b/opm/core/props/pvt/SinglePvtLiveGas.cpp @@ -61,7 +61,7 @@ namespace Opm for (int i=0; i= 2); + assert(undersat_gas_tables_[is+1][0].size() >= 2); + double val1 = + linearInterpolationDerivative(undersat_gas_tables_[is][0], + undersat_gas_tables_[is][item], + r); + double val2 = + linearInterpolationDerivative(undersat_gas_tables_[is+1][0], + undersat_gas_tables_[is+1][item], + r); + + double val = val1 + w * (val2 - val1); + return val; + + } + } else { + if (isSat) { // Saturated case + return linearInterpolation(saturated_gas_table_[0], + saturated_gas_table_[item], + press); + } else { // Undersaturated case + int is = tableIndex(saturated_gas_table_[0], press); + // Extrapolate from first table section + if (is == 0 && press < saturated_gas_table_[0][0]) { + return linearInterpolation(undersat_gas_tables_[0][0], + undersat_gas_tables_[0][item], + r); + } + + // Extrapolate from last table section + //int ltp = saturated_gas_table_[0].size() - 1; + //if (is+1 == ltp && press > saturated_gas_table_[0][ltp]) { + // return linearInterpolation(undersat_gas_tables_[ltp][0], + // undersat_gas_tables_[ltp][item], + // r); + //} + + // Interpolate between table sections + double w = (press - saturated_gas_table_[0][is]) / + (saturated_gas_table_[0][is+1] - + saturated_gas_table_[0][is]); + if (undersat_gas_tables_[is][0].size() < 2) { + double val = saturated_gas_table_[item][is] + + w*(saturated_gas_table_[item][is+1] - + saturated_gas_table_[item][is]); + return val; + } + double val1 = + linearInterpolation(undersat_gas_tables_[is][0], + undersat_gas_tables_[is][item], + r); + double val2 = + linearInterpolation(undersat_gas_tables_[is+1][0], + undersat_gas_tables_[is+1][item], + r); + double val = val1 + w*(val2 - val1); + return val; + } + } + } + + + } // namespace Opm diff --git a/opm/core/props/pvt/SinglePvtLiveGas.hpp b/opm/core/props/pvt/SinglePvtLiveGas.hpp index faa22254..de595393 100644 --- a/opm/core/props/pvt/SinglePvtLiveGas.hpp +++ b/opm/core/props/pvt/SinglePvtLiveGas.hpp @@ -47,7 +47,7 @@ namespace Opm double* output_mu) const; /// Viscosity and its derivatives as a function of p and r. - /// The fluid is considered saturated if r >= rbub(p). + /// The fluid is considered saturated if r >= rsSat(p). virtual void mu(const int n, const double* p, const double* r, @@ -79,7 +79,7 @@ namespace Opm double* output_dBdp) const; /// The inverse of the formation volume factor b = 1 / B, and its derivatives as a function of p and r. - /// The fluid is considered saturated if r >= rbub(p). + /// The fluid is considered saturated if r >= rsSat(p). virtual void b(const int n, const double* p, const double* r, @@ -99,11 +99,17 @@ namespace Opm - /// Gas resolution and its derivatives at bublepoint as a function of p. - virtual void rbub(const int n, + /// Solution gas/oil ratio and its derivatives at saturated conditions as a function of p. + virtual void rsSat(const int n, const double* p, - double* output_rbub, - double* output_drbubdp) const; + double* output_rsSat, + double* output_drsSatdp) const; + + /// Vapor oil/gas ratio and its derivatives at saturated conditions as a function of p. + virtual void rvSat(const int n, + const double* p, + double* output_rvSat, + double* output_drvSatdp) const; /// Solution factor as a function of p and z. virtual void R(const int n, @@ -129,6 +135,11 @@ namespace Opm const double* surfvol, const int item, const bool deriv = false) const; + double miscible_gas(const double press, + const double r, + const PhasePresence& cond, + const int item, + const int deriv = 0) const; // PVT properties of wet gas (with vaporised oil) std::vector > saturated_gas_table_; std::vector > > undersat_gas_tables_; diff --git a/opm/core/props/pvt/SinglePvtLiveOil.cpp b/opm/core/props/pvt/SinglePvtLiveOil.cpp index def278e1..d18252ee 100644 --- a/opm/core/props/pvt/SinglePvtLiveOil.cpp +++ b/opm/core/props/pvt/SinglePvtLiveOil.cpp @@ -225,21 +225,30 @@ namespace Opm } } - void SinglePvtLiveOil::rbub(const int n, + void SinglePvtLiveOil::rsSat(const int n, const double* p, - double* output_rbub, - double* output_drbubdp) const + double* output_rsSat, + double* output_drsSatdp) const { for (int i = 0; i < n; ++i) { - output_rbub[i] = linearInterpolation(saturated_oil_table_[0], + output_rsSat[i] = linearInterpolation(saturated_oil_table_[0], saturated_oil_table_[3],p[i]); - output_drbubdp[i] = linearInterpolationDerivative(saturated_oil_table_[0], + output_drsSatdp[i] = linearInterpolationDerivative(saturated_oil_table_[0], saturated_oil_table_[3],p[i]); } } + void SinglePvtLiveOil::rvSat(const int n, + const double* /*p*/, + double* output_rvSat, + double* output_drvSatdp) const + { + std::fill(output_rvSat, output_rvSat + n, 0.0); + std::fill(output_drvSatdp, output_drvSatdp + n, 0.0); + } + /// Solution factor as a function of p and z. void SinglePvtLiveOil::R(const int n, const double* p, diff --git a/opm/core/props/pvt/SinglePvtLiveOil.hpp b/opm/core/props/pvt/SinglePvtLiveOil.hpp index 4bfa9a76..d0e5fb70 100644 --- a/opm/core/props/pvt/SinglePvtLiveOil.hpp +++ b/opm/core/props/pvt/SinglePvtLiveOil.hpp @@ -48,7 +48,7 @@ namespace Opm double* output_mu) const; /// Viscosity and its derivatives as a function of p and r. - /// The fluid is considered saturated if r >= rbub(p). + /// The fluid is considered saturated if r >= rsSat(p). virtual void mu(const int n, const double* p, const double* r, @@ -80,7 +80,7 @@ namespace Opm double* output_dBdp) const; /// The inverse of the formation volume factor b = 1 / B, and its derivatives as a function of p and r. - /// The fluid is considered saturated if r >= rbub(p). + /// The fluid is considered saturated if r >= rsSat(p). virtual void b(const int n, const double* p, const double* r, @@ -98,11 +98,17 @@ namespace Opm double* output_dbdp, double* output_dbdr) const; - /// Gas resolution and its derivatives at bublepoint as a function of p. - virtual void rbub(const int n, + /// Solution gas/oil ratio and its derivatives at saturated conditions as a function of p. + virtual void rsSat(const int n, const double* p, - double* output_rbub, - double* output_drbubdp) const; + double* output_rsSat, + double* output_drsSatdp) const; + + /// Vapor oil/gas ratio and its derivatives at saturated conditions as a function of p. + virtual void rvSat(const int n, + const double* p, + double* output_rvSat, + double* output_drvSatdp) const; /// Solution factor as a function of p and z. virtual void R(const int n, diff --git a/opm/core/simulator/BlackoilState.cpp b/opm/core/simulator/BlackoilState.cpp index c8c3afa8..0b864a17 100644 --- a/opm/core/simulator/BlackoilState.cpp +++ b/opm/core/simulator/BlackoilState.cpp @@ -7,6 +7,7 @@ void BlackoilState::init(const UnstructuredGrid& g, int num_phases) { SimulatorState::init(g, num_phases); gor_.resize(g.number_of_cells, 0.) ; + rv_.resize(g.number_of_cells,0.); // surfvol_ intentionally empty, left to initBlackoilSurfvol } diff --git a/opm/core/simulator/BlackoilState.hpp b/opm/core/simulator/BlackoilState.hpp index 5cf8156e..c6fb7779 100644 --- a/opm/core/simulator/BlackoilState.hpp +++ b/opm/core/simulator/BlackoilState.hpp @@ -47,13 +47,16 @@ namespace Opm std::vector& surfacevol () { return surfvol_; } std::vector& gasoilratio () { return gor_ ; } + std::vector& rv () {return rv_ ; } const std::vector& surfacevol () const { return surfvol_; } const std::vector& gasoilratio () const { return gor_ ; } + const std::vector& rv () const {return rv_ ; } private: std::vector surfvol_; std::vector gor_ ; + std::vector rv_ ; }; } // namespace Opm diff --git a/opm/core/simulator/initState_impl.hpp b/opm/core/simulator/initState_impl.hpp index 13d7728b..12dbe7b5 100644 --- a/opm/core/simulator/initState_impl.hpp +++ b/opm/core/simulator/initState_impl.hpp @@ -609,26 +609,26 @@ namespace Opm } } /// Initialize surface volume from pressure and saturation by z = As. - /// Here the gas/oil ratio is used to compute an intial z for the - /// computation of A. + /// Here the solution gas/oil ratio or vapor oil/gas ratio is used to + /// compute an intial z for the computation of A. template - void initBlackoilSurfvolUsingRS(const UnstructuredGrid& grid, + void initBlackoilSurfvolUsingRSorRV(const UnstructuredGrid& grid, const Props& props, State& state) { if (props.numPhases() != 3) { OPM_THROW(std::runtime_error, "initBlackoilSurfvol() is only supported in three-phase simulations."); } - const std::vector& rs = state.gasoilratio(); + const std::vector& rv = state.rv(); //make input for computation of the A matrix state.surfacevol() = state.saturation(); - //const PhaseUsage pu = phaseUsageFromDeck(deck); const PhaseUsage pu = props.phaseUsage(); const int np = props.numPhases(); const int nc = grid.number_of_cells; + std::vector allA_a(nc*np*np); std::vector allA_l(nc*np*np); std::vector allA_v(nc*np*np); @@ -641,6 +641,17 @@ namespace Opm allcells[c] = c; } + std::vector capPressures(nc*np); + props.capPress(nc,&state.saturation()[0],&allcells[0],&capPressures[0],NULL); + + std::vector Pw(nc); + std::vector Pg(nc); + + for (int c = 0; c < nc; ++c){ + Pw[c] = state.pressure()[c] + capPressures[c*np + BlackoilPhases::Aqua]; + Pg[c] = state.pressure()[c] + capPressures[c*np + BlackoilPhases::Vapour]; + } + double z_tmp; @@ -687,7 +698,7 @@ namespace Opm if(state.saturation()[np*c + p] > 0) z_tmp = 1e10; else - z_tmp = rs[c]; + z_tmp = rv[c]; } else if(p == BlackoilPhases::Vapour) z_tmp = 1; @@ -717,7 +728,9 @@ namespace Opm z[2] += A_v[2 + np*col]*s[col]; } + double ztmp = z[2]; z[2] += z[1]*rs[c]; + z[1] += ztmp*rv[c]; } } @@ -739,10 +752,21 @@ namespace Opm int c_deck = (grid.global_cell == NULL) ? c : grid.global_cell[c]; state.gasoilratio()[c] = rs_deck[c_deck]; } - initBlackoilSurfvolUsingRS(grid, props, state); + initBlackoilSurfvolUsingRSorRV(grid, props, state); computeSaturation(props,state); - } else { - OPM_THROW(std::runtime_error, "Temporarily, we require the RS field."); + } else if (deck.hasField("RV")){ + const std::vector& rv_deck = deck.getFloatingPointValue("RV"); + const int num_cells = grid.number_of_cells; + for (int c = 0; c < num_cells; ++c) { + int c_deck = (grid.global_cell == NULL) ? c : grid.global_cell[c]; + state.rv()[c] = rv_deck[c_deck]; + } + initBlackoilSurfvolUsingRSorRV(grid, props, state); + computeSaturation(props,state); + } + + else { + OPM_THROW(std::runtime_error, "Temporarily, we require the RS or the RV field."); } } diff --git a/tests/liveoil.DATA b/tests/liveoil.DATA new file mode 100644 index 00000000..c6a04b40 --- /dev/null +++ b/tests/liveoil.DATA @@ -0,0 +1,36 @@ +OIL +GAS +WATER + +FIELD + +PVTO +-- Rs Pbub Bo Vo + .0 14.7 1.0000 1.20 / + .165 400. 1.0120 1.17 / + .335 800. 1.0255 1.14 / + .500 1200. 1.0380 1.11 / + .665 1600. 1.0510 1.08 / + .828 2000. 1.0630 1.06 / + .985 2400. 1.0750 1.03 / + 1.130 2800. 1.0870 1.00 / + 1.270 3200. 1.0985 .98 / + 1.390 3600. 1.1100 .95 / + 1.500 4000. 1.1200 .94 + 5000. 1.1189 .94 / + / + +PVDG +-- Pg Bg Vg + 14.7 178.08 .0125 + 400. 5.4777 .0130 + 800. 2.7392 .0135 + 1200. 1.8198 .0140 + 1600. 1.3648 .0145 + 2000. 1.0957 .0150 + 2400. 0.9099 .0155 + 2800. 0.7799 .0160 + 3200. 0.6871 .0165 + 3600. 0.6035 .0170 + 4000. 0.5432 .0175 / + diff --git a/tests/test_blackoilfluid.cpp b/tests/test_blackoilfluid.cpp index 9816284a..a1491f13 100644 --- a/tests/test_blackoilfluid.cpp +++ b/tests/test_blackoilfluid.cpp @@ -28,24 +28,18 @@ using namespace Opm; using namespace std; -BOOST_AUTO_TEST_CASE(test_blackoilfluid) -{ + +std::vector > getProps(const EclipseGridParser deck,PhaseUsage phase_usage_){ - // read eclipse deck - const string filename = "testFluid.DATA"; - cout << "Reading deck: " << filename << endl; - const EclipseGridParser deck (filename); - - // setup pvt interface - std::vector > props_; - PhaseUsage phase_usage_ = phaseUsageFromDeck(deck); enum PhaseIndex { Aqua = 0, Liquid = 1, Vapour = 2 }; int samples = 0; + std::vector > props_; // Set the properties. props_.resize(phase_usage_.num_phases); + // Water PVT if (phase_usage_.phase_used[Aqua]) { if (deck.hasField("PVTW")) { @@ -55,6 +49,7 @@ BOOST_AUTO_TEST_CASE(test_blackoilfluid) props_[phase_usage_.phase_pos[Aqua]].reset(new SinglePvtConstCompr(0.5*Opm::prefix::centi*Opm::unit::Poise)); } } + // Oil PVT if (phase_usage_.phase_used[Liquid]) { if (deck.hasField("PVDO")) { @@ -87,6 +82,146 @@ BOOST_AUTO_TEST_CASE(test_blackoilfluid) } } + return props_; +} + +void testmu(const double reltol, int n, int np, std::vector p, std::vector r,std::vector z, + std::vector > props_, std::vector condition) +{ + std::vector mu(n); + std::vector dmudp(n); + std::vector dmudr(n); + std::vector mu_new(n); + double dmudp_diff; + double dmudr_diff; + double dmudp_diff_u; + double dmudr_diff_u; + + // test mu + for (int phase = 0; phase < np; ++phase) { + props_[phase]->mu(n, &p[0], &r[0], &condition[0], &mu_new[0], &dmudp[0], &dmudr[0]); + props_[phase]->mu(n, &p[0], &z[0], &mu[0]); + dmudp_diff = (mu_new[1]-mu_new[0])/(p[1]-p[0]); + dmudr_diff = (mu_new[2]-mu_new[0])/(r[2]-r[0]); + dmudp_diff_u = (mu_new[4]-mu_new[3])/(p[4]-p[3]); + dmudr_diff_u = (mu_new[5]-mu_new[3])/(r[5]-r[3]); + + for (int i = 0; i < n; ++i){ + BOOST_CHECK_CLOSE(mu_new[i],mu[i],reltol); + } + + // saturated case + BOOST_CHECK_CLOSE(dmudp_diff,dmudp[0],reltol); + BOOST_CHECK_CLOSE(dmudr_diff,dmudr[0],reltol); + + // unsaturated case + BOOST_CHECK_CLOSE(dmudp_diff_u,dmudp[3],reltol); + BOOST_CHECK_CLOSE(dmudr_diff_u,dmudr[3],reltol); + + } +} + +void testb(const double reltol, int n, int np, std::vector p, std::vector r,std::vector z, + std::vector > props_, std::vector condition) +{ + // test b + std::vector b(n); + std::vector B(n); + std::vector invB(n); + std::vector dinvBdp(n); + std::vector dBdp(n); + std::vector dbdr(n); + std::vector dbdp(n); + double dbdp_diff; + double dbdr_diff; + double dbdp_diff_u; + double dbdr_diff_u; + + for (int phase = 0; phase < np; ++phase) { + props_[phase]->b(n, &p[0], &r[0], &condition[0], &b[0], &dbdp[0], &dbdr[0]); + props_[phase]->dBdp(n, &p[0], &z[0], &B[0], &dBdp[0]); + dbdp_diff = (b[1]-b[0])/(p[1]-p[0]); + dbdr_diff = (b[2]-b[0])/(r[2]-r[0]); + dbdp_diff_u = (b[4]-b[3])/(p[4]-p[3]); + dbdr_diff_u = (b[5]-b[3])/(r[5]-r[3]); + for (int i = 0; i < n; ++i){ + invB[i] = 1/B[i]; + dinvBdp[i] = -1/pow(B[i],2) * dBdp[i]; + } + + for (int i = 0; i < n; ++i){ + BOOST_CHECK_CLOSE(invB[i],b[i] , reltol); + BOOST_CHECK_CLOSE(dinvBdp[i],dbdp[i] , reltol); + + } + // saturated case + BOOST_CHECK_CLOSE(dbdp_diff,dbdp[0], reltol); + BOOST_CHECK_CLOSE(dbdr_diff,dbdr[0], reltol); + + // unsaturated case + BOOST_CHECK_CLOSE(dbdp_diff_u,dbdp[3], reltol); + BOOST_CHECK_CLOSE(dbdr_diff_u,dbdr[3], reltol); + } +} + +void testrsSat(double reltol, int n, int np, std::vector p, std::vector > props_){ + // test bublepoint pressure + std::vector rs(n); + std::vector drsdp(n); + double drsdp_diff; + double drsdp_diff_u; + + for (int phase = 0; phase < np; ++phase) { + props_[phase] ->rsSat(n, &p[0], &rs[0], &drsdp[0]); + + drsdp_diff = (rs[1]-rs[0])/(p[1]-p[0]); + drsdp_diff_u = (rs[4]-rs[3])/(p[4]-p[3]); + + // saturated case + BOOST_CHECK_CLOSE(drsdp_diff,drsdp[0], reltol); + + // unsaturad case + BOOST_CHECK_CLOSE(drsdp_diff_u,drsdp[3], reltol); + + } +} + +void testrvSat(double reltol, int n, int np, std::vector p, std::vector > props_){ + // test rv saturated + std::vector rv(n); + std::vector drvdp(n); + double drvdp_diff; + double drvdp_diff_u; + + for (int phase = 0; phase < np; ++phase) { + props_[phase] ->rvSat(n, &p[0], &rv[0], &drvdp[0]); + + drvdp_diff = (rv[1]-rv[0])/(p[1]-p[0]); + drvdp_diff_u = (rv[4]-rv[3])/(p[4]-p[3]); + + // saturated case + BOOST_CHECK_CLOSE(drvdp_diff,drvdp[0], reltol); + + // unsaturad case + BOOST_CHECK_CLOSE(drvdp_diff_u,drvdp[3], reltol); + + } +} + +BOOST_AUTO_TEST_CASE(test_liveoil) +{ + + + // read eclipse deck + const string filename = "liveoil.DATA"; + cout << "Reading deck: " << filename << endl; + const EclipseGridParser deck (filename); + + // setup pvt interface + PhaseUsage phase_usage_ = phaseUsageFromDeck(deck); + std::vector > props_ = getProps(deck,phase_usage_); + + // setup a test case. We will check 6 [p,r] pairs and compare them to both the [p,z] interface and a finite difference // approximation of the derivatives. const int n = 6; @@ -97,25 +232,16 @@ BOOST_AUTO_TEST_CASE(test_blackoilfluid) std::vector p(n); std::vector r(n); - std::vector condition(n); + std::vector condition(n); std::vector z(n * np); - std::vector mu(n); - std::vector dmudp(n); - std::vector dmudr(n); - std::vector mu_new(n); - double dmudp_diff; - double dmudr_diff; - double dmudp_diff_u; - double dmudr_diff_u; - // Used for forward difference calculations - const double h_p = 100000; + const double h_p = 1e4; const double h_r = 1; // saturated - p[0] = 10000000; + p[0] = 1e7; p[1] = p[0] + h_p; p[2] = p[0]; @@ -144,90 +270,85 @@ BOOST_AUTO_TEST_CASE(test_blackoilfluid) } - // test mu - for (int phase = 1; phase < 2; ++phase) { - props_[phase]->mu(n, &p[0], &r[0], &condition[0], &mu_new[0], &dmudp[0], &dmudr[0]); - props_[phase]->mu(n, &p[0], &z[0], &mu[0]); - dmudp_diff = (mu_new[1]-mu_new[0])/h_p; - dmudr_diff = (mu_new[2]-mu_new[0])/h_r; - dmudp_diff_u = (mu_new[4]-mu_new[3])/h_p; - dmudr_diff_u = (mu_new[5]-mu_new[3])/h_r; - - for (int i = 0; i < n; ++i){ - BOOST_CHECK_CLOSE(mu_new[i],mu[i],reltol); - } - // saturated case - BOOST_CHECK_CLOSE(dmudp_diff,dmudp[0],reltol); - BOOST_CHECK_CLOSE(dmudr_diff,dmudr[0],reltol); - - // unsaturated case - BOOST_CHECK_CLOSE(dmudp_diff_u,dmudp[3] , reltol); - BOOST_CHECK_CLOSE(dmudr_diff_u,dmudr[3] , reltol); - - } - - // test b - std::vector b(n); - std::vector B(n); - std::vector invB(n); - std::vector dinvBdp(n); - std::vector dBdp(n); - std::vector dbdr(n); - std::vector dbdp(n); - double dbdp_diff; - double dbdr_diff; - double dbdp_diff_u; - double dbdr_diff_u; - - for (int phase = 1; phase < 2; ++phase) { - props_[phase]->b(n, &p[0], &r[0], &condition[0], &b[0], &dbdp[0], &dbdr[0]); - //props_[phase]->B(n, p, z, B); - props_[phase]->dBdp(n, &p[0], &z[0], &B[0], &dBdp[0]); - dbdp_diff = (b[1]-b[0])/h_p; - dbdr_diff = (b[2]-b[0])/h_r; - dbdp_diff_u = (b[4]-b[3])/h_p; - dbdr_diff_u = (b[5]-b[3])/h_r; - for (int i = 0; i < n; ++i){ - invB[i] = 1/B[i]; - dinvBdp[i] = -1/pow(B[i],2) * dBdp[i]; - } - - for (int i = 0; i < n; ++i){ - BOOST_CHECK_CLOSE(invB[i],b[i] , reltol); - BOOST_CHECK_CLOSE(dinvBdp[i],dbdp[i] , reltol); - - } - // saturated case - BOOST_CHECK_CLOSE(dbdp_diff,dbdp[0], reltol); - BOOST_CHECK_CLOSE(dbdr_diff,dbdr[0], reltol); - - // unsaturated case - BOOST_CHECK_CLOSE(dbdp_diff_u,dbdp[3], reltol); - BOOST_CHECK_CLOSE(dbdr_diff_u,dbdr[3], reltol); - } - - // test bublepoint pressure - std::vector rbub(n); - std::vector drbubdp(n); - double drbubdp_diff; - double drbubdp_diff_u; - - for (int phase = 1; phase < 2; ++phase) { - props_[phase] ->rbub(n, &p[0], &rbub[0], &drbubdp[0]); - - drbubdp_diff = (rbub[1]-rbub[0])/h_p; - drbubdp_diff_u = (rbub[4]-rbub[3])/h_p; - - // saturated case - BOOST_CHECK_CLOSE(drbubdp_diff,drbubdp[0], reltol); - - // unsaturad case - BOOST_CHECK_CLOSE(drbubdp_diff_u,drbubdp[3], reltol); - - } + testmu(reltol, n, np, p, r,z, props_, condition); + testb(reltol,n,np,p,r,z,props_,condition); + testrsSat(reltol,n,np,p,props_); + testrvSat(reltol,n,np,p,props_); } + +BOOST_AUTO_TEST_CASE(test_wetgas) +{ + + + // read eclipse deck + const string filename = "wetgas.DATA"; + cout << "Reading deck: " << filename << endl; + const EclipseGridParser deck (filename); + + // setup pvt interface + PhaseUsage phase_usage_ = phaseUsageFromDeck(deck); + std::vector > props_ = getProps(deck,phase_usage_); + + + // setup a test case. We will check 6 [p,r] pairs and compare them to both the [p,z] interface and a finite difference + // approximation of the derivatives. + const int n = 6; + const int np = phase_usage_.num_phases; + + // the tolerance for acceptable difference in values + const double reltol = 1e-9; + + std::vector p(n); + std::vector r(n); + std::vector condition(n); + std::vector z(n * np); + + + // Used for forward difference calculations + const double h_p = 1e4; + const double h_r = 1e-7; + + // saturated + p[0] = 1e7; + p[1] = p[0] + h_p; + p[2] = p[0]; + + r[0] = 5e-5; + r[1] = 5e-5; + r[2] = 5e-5 + h_r; + + condition[0].setFreeOil(); + condition[1].setFreeOil(); + condition[2].setFreeOil(); + + + // undersaturated + p[3] = p[0]; + p[4] = p[1]; + p[5] = p[2]; + + r[3] = 1e-5; + r[4] = 1e-5; + r[5] = 1e-5 +h_r; + + // Corresponing z factors, used to compare with the [p,z] interface + for (int i = 0; i < n; ++i) { + z[0+i*np] = 0; z[1+i*np] = r[i]; + z[2+i*np] = 1; + + } + + testmu(reltol, n, np, p, r,z, props_, condition); + + testb(reltol,n,np,p,r,z,props_,condition); + + testrsSat(reltol,n,np,p,props_); + + testrvSat(reltol,n,np,p,props_); + +} diff --git a/tests/wetgas.DATA b/tests/wetgas.DATA new file mode 100644 index 00000000..4fad316e --- /dev/null +++ b/tests/wetgas.DATA @@ -0,0 +1,71 @@ +WATER +OIL +GAS + +FIELD + +-- PVT PROPERTIES OF DRY GAS (NO VAPOURISED OIL) +-- FROM SPE3 Blackoil Kleppe +-- +-- 'Pressure' 'Oil FVF' 'Oil Visc' +PVDO + 1214.7000 1.0632 0.3668 + 1814.7000 1.0518 0.4241 + 2414.7000 1.0418 0.5018 + 3014.7000 1.0332 0.6068 + 3214.7000 1.0308 0.6461 + 3364.7000 1.0291 0.6753 + 3414.7000 1.0285 0.6852 + 3443.8831 1.0282 0.6912 +/ + +-- Wet Gas PVT Properties (Vapourised Oil) +-- Column Properties are: +-- 'Gas Pressure' 'Gas OGR' 'Gas FVF' 'Gas Visc' +-- Units: psia stb /Mscf rb /Mscf cp +PVTG + 1214.7000 0.0013130 2.2799 0.0149 + 0 2.2815 0.01488/ + 1814.7000 0.00353 1.4401 0.01791 + 0.001313 1.4429 0.01782 + 0 1.4445 0.01735 / + 2414.7000 0.01102 1.0438 0.02328 + 0.00353 1.0495 0.02267 + 0.001313 1.0512 0.0225 + 0 1.0522 0.02240 / + 3014.7000 0.0331 0.8456 0.0318 + 0.01102 0.8489 0.02924 + 0.00353 0.8500 0.02844 + 0.001313 0.8503 0.02820 + 0 0.8505 0.02807 / + 3214.7000 0.0454 0.8082 0.03539 + 0.0331 0.8080 0.03371 + 0.01102 0.8075 0.03113 + 0.00353 0.8073 0.03029 + 0.001313 0.8073 0.03004 + 0 0.8073 0.02989 / + 3364.7000 0.05670 0.7875 0.0384 + 0.04540 0.7860 0.03667 + 0.03310 0.7843 0.03515 + 0.01102 0.7814 0.03429 + 0.00353 0.7804 0.03162 + 0.001313 0.7801 0.03136 + 0 0.7799 0.03121 / + 3416.7575 0.0612 0.7816 0.03955 + 0.0567 0.7809 0.0386 + 0.0454 0.7789 0.03717 + 0.0331 0.7768 0.03564 + 0.01102 0.7731 0.03296 + 0.00353 0.7718 0.03207 + 0.001313 0.7714 0.03181 + 0 0.7712 0.03166 / + 3449.3322 0.0642 0.7783 0.0403 + 0.0612 0.7777 0.0395 + 0.0567 0.7769 0.03892 + 0.0454 0.7747 0.03748 + 0.0331 0.7723 0.03594 + 0.01102 0.7681 0.03325 + 0.00353 0.7666 0.03236 + 0.001313 0.7662 0.0321 + 0 0.7660 0.03194 / +/