diff --git a/.gitignore b/.gitignore
index 74fa1ca2..d124eee7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
*~
+.\#*
*.o
*.lo
*.la
@@ -28,15 +29,26 @@ ltmain.sh
m4/libtool.m4
m4/lt*.m4
missing
+tutorials/tutorial[1-4]
# Ignoring executables
*_test
examples/scaneclipsedeck
examples/spu_2p
examples/reorder-qfs
+examples/refine_wells
+examples/sim_2p_incomp_reorder
+examples/sim_wateroil
+examples/wells_example
tests/test_cfs_tpfa
tests/test_jacsys
tests/test_readvector
tests/test_sf2p
tests/bo_fluid_p_and_z_deps
tests/bo_fluid_pressuredeps
+tests/test_cartgrid
+tests/test_column_extract
+tests/test_lapack
+tests/test_read_vag
+tests/test_readpolymer
+tests/test_writeVtkData
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a6e3b690..eec84d9c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,8 +2,10 @@ cmake_minimum_required (VERSION 2.6)
project (opm-core)
enable_language(Fortran)
-
-
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
+SET(CMAKE_BUILD_TYPE "debug")
+SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG -pg -Wall -fopenmp -ggdb")
+SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -pg -Wall -fopenmp -ggdb")
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
@@ -16,94 +18,50 @@ include_directories(${PROJECT_SOURCE_DIR} ${Boost_INCLUDE_DIRS})
# The opmcore library
-add_library(opmcore
-opm/core/eclipse/EclipseGridInspector.cpp
-opm/core/eclipse/EclipseGridParser.cpp
-opm/core/fluid/blackoil/BlackoilPvtProperties.cpp
-opm/core/fluid/blackoil/SinglePvtDead.cpp
-opm/core/fluid/blackoil/SinglePvtLiveGas.cpp
-opm/core/fluid/blackoil/SinglePvtLiveOil.cpp
-opm/core/fluid/blackoil/SinglePvtInterface.cpp
-opm/core/fluid/BlackoilPropertiesBasic.cpp
-opm/core/fluid/BlackoilPropertiesFromDeck.cpp
-opm/core/fluid/IncompPropertiesBasic.cpp
-opm/core/fluid/IncompPropertiesFromDeck.cpp
-opm/core/fluid/PvtPropertiesBasic.cpp
-opm/core/fluid/PvtPropertiesIncompFromDeck.cpp
-opm/core/fluid/RockBasic.cpp
-opm/core/fluid/RockFromDeck.cpp
-opm/core/fluid/SaturationPropsBasic.cpp
-opm/core/fluid/SaturationPropsFromDeck.cpp
-opm/core/utility/MonotCubicInterpolator.cpp
-opm/core/utility/parameters/Parameter.cpp
-opm/core/utility/parameters/ParameterGroup.cpp
-opm/core/utility/parameters/ParameterTools.cpp
-opm/core/utility/parameters/ParameterXML.cpp
-opm/core/utility/parameters/tinyxml/tinystr.cpp
-opm/core/utility/parameters/tinyxml/tinyxml.cpp
-opm/core/utility/parameters/tinyxml/tinyxmlerror.cpp
-opm/core/utility/parameters/tinyxml/tinyxmlparser.cpp
-opm/core/utility/cart_grid.c
-opm/core/utility/cpgpreprocess/geometry.c
-opm/core/utility/cpgpreprocess/preprocess.c
-opm/core/utility/cpgpreprocess/readvector.cpp
-opm/core/utility/cpgpreprocess/cgridinterface.c
-opm/core/utility/cpgpreprocess/sparsetable.c
-opm/core/utility/cpgpreprocess/facetopology.c
-opm/core/utility/cpgpreprocess/uniquepoints.c
-opm/core/utility/StopWatch.cpp
-opm/core/utility/newwells.c
-opm/core/utility/writeVtkData.cpp
-opm/core/GridManager.cpp
-opm/core/linalg/sparse_sys.c
-opm/core/pressure/cfsh.c
-opm/core/pressure/flow_bc.c
-opm/core/pressure/well.c
-opm/core/pressure/fsh_common_impl.c
-opm/core/pressure/fsh.c
-opm/core/pressure/tpfa/ifs_tpfa.c
-opm/core/pressure/tpfa/compr_source.c
-opm/core/pressure/tpfa/cfs_tpfa.c
-opm/core/pressure/tpfa/compr_bc.c
-opm/core/pressure/tpfa/compr_quant.c
-opm/core/pressure/tpfa/compr_quant_general.c
-opm/core/pressure/tpfa/cfs_tpfa_residual.c
-opm/core/pressure/tpfa/trans_tpfa.c
-opm/core/pressure/msmfem/coarse_conn.c
-opm/core/pressure/msmfem/partition.c
-opm/core/pressure/msmfem/hash_set.c
-opm/core/pressure/msmfem/ifsh_ms.c
-opm/core/pressure/msmfem/dfs.c
-opm/core/pressure/msmfem/coarse_sys.c
-opm/core/pressure/ifsh.c
-opm/core/pressure/IncompTpfa.cpp
-opm/core/pressure/mimetic/mimetic.c
-opm/core/pressure/mimetic/hybsys_global.c
-opm/core/pressure/mimetic/hybsys.c
-opm/core/transport/spu_explicit.c
-opm/core/transport/spu_implicit.c
-opm/core/transport/transport_source.c
-opm/core/transport/reorder/TransportModelInterface.cpp
-opm/core/transport/reorder/TransportModelTwophase.cpp
-opm/core/transport/reorder/reordersequence.cpp
-opm/core/transport/reorder/nlsolvers.c
-opm/core/transport/reorder/tarjan.c
-opm/core/linalg/call_umfpack.c
-opm/core/pressure/IncompTpfa.cpp
-opm/core/linalg/LinearSolverInterface.cpp
-opm/core/linalg/LinearSolverIstl.cpp
-opm/core/linalg/LinearSolverUmfpack.cpp
-)
+FILE(GLOB_RECURSE C_FILES_CORE "opm/core/*.c")
+FILE(GLOB_RECURSE CPP_FILES_CORE "opm/core/*.cpp")
+FILE(GLOB_RECURSE REMOVE_FILES "processgrid.c")
+FILE(GLOB_RECURSE REMOVE_FILESMX "mx*.c")
+FILE(GLOB_RECURSE REMOVE_FILESAGMG "*AGMG.cpp" "*test*")
+list(REMOVE_ITEM C_FILES_CORE ${REMOVE_FILES} ${REMOVE_FILESMX} )
+list(REMOVE_ITEM CPP_FILES_CORE ${REMOVE_FILES} ${REMOVE_FILESAGMG})
+add_library(opmcore ${C_FILES_CORE} ${CPP_FILES_CORE} )
+
target_link_libraries(opmcore
${UMFPACK_LIBRARIES} ${LAPACK_LINKER_FLAGS} ${LAPACK_LIBRARIES} ${Boost_LIBRARIES}
-lcholmod -lcamd -lccolamd -lmetis -ldunecommon
)
+FILE(GLOB CPP_EXAMPLES "examples/*.cpp")
+FILE(GLOB CPP_tests "tests/*.cpp")
add_executable(spu_2p examples/spu_2p.cpp)
+add_executable(sim_2p_incomp_reorder examples/sim_2p_incomp_reorder.cpp)
+add_executable(sim_wateroil examples/sim_wateroil.cpp)
+
+add_executable(pvt_test tests/pvt_test.cpp)
+add_executable(relperm_test tests/relperm_test.cpp)
target_link_libraries(spu_2p
opmcore
)
+target_link_libraries(sim_2p_incomp_reorder
+ opmcore
+)
-set_target_properties(opmcore spu_2p PROPERTIES COMPILE_FLAGS -m64 LINKER_LANGUAGE CXX LINK_FLAGS -m64)
+target_link_libraries(sim_wateroil
+ opmcore
+)
+
+target_link_libraries(pvt_test
+ opmcore
+)
+target_link_libraries(relperm_test
+ opmcore
+)
+
+#set_target_properties(opmcore spu_2p PROPERTIES COMPILE_FLAGS -m64 LINKER_LANGUAGE CXX LINK_FLAGS -m64)
+#set_target_properties(opmcore sim_2p_incomp_reorder PROPERTIES COMPILE_FLAGS -m64 LINKER_LANGUAGE CXX LINK_FLAGS -m64)
+#set_target_properties(opmcore sim_wateroil PROPERTIES COMPILE_FLAGS -m64 LINKER_LANGUAGE CXX LINK_FLAGS -m64)
+#set_target_properties(opmcore pvt_test PROPERTIES COMPILE_FLAGS -m64 LINKER_LANGUAGE CXX LINK_FLAGS -m64)
+set_target_properties(opmcore relperm_test PROPERTIES COMPILE_FLAGS -m64 LINKER_LANGUAGE CXX LINK_FLAGS -m64)
diff --git a/FindUmfPack.cmake b/FindUmfPack.cmake
new file mode 100644
index 00000000..5fe5db16
--- /dev/null
+++ b/FindUmfPack.cmake
@@ -0,0 +1,56 @@
+if (UMFPACK_INCLUDES AND UMFPACK_LIBRARIES)
+ set(UMFPACK_FIND_QUIETLY TRUE)
+endif (UMFPACK_INCLUDES AND UMFPACK_LIBRARIES)
+
+find_package(BLAS)
+
+if(BLAS_FOUND)
+
+ find_path(UMFPACK_INCLUDES
+ NAMES
+ umfpack.h
+ PATHS
+ $ENV{UMFPACKDIR}
+ ${INCLUDE_INSTALL_DIR}
+ PATH_SUFFIXES
+ suitesparse
+ )
+
+ find_library(UMFPACK_LIBRARIES umfpack PATHS $ENV{UMFPACKDIR} ${LIB_INSTALL_DIR})
+
+ if(UMFPACK_LIBRARIES)
+
+ get_filename_component(UMFPACK_LIBDIR ${UMFPACK_LIBRARIES} PATH)
+
+ find_library(AMD_LIBRARY amd PATHS ${UMFPACK_LIBDIR} $ENV{UMFPACKDIR} ${LIB_INSTALL_DIR})
+ if (AMD_LIBRARY)
+ set(UMFPACK_LIBRARIES ${UMFPACK_LIBRARIES} ${AMD_LIBRARY})
+ #else (AMD_LIBRARY)
+ # set(UMFPACK_LIBRARIES FALSE)
+ endif (AMD_LIBRARY)
+
+ endif(UMFPACK_LIBRARIES)
+
+ if(UMFPACK_LIBRARIES)
+
+ find_library(COLAMD_LIBRARY colamd PATHS ${UMFPACK_LIBDIR} $ENV{UMFPACKDIR} ${LIB_INSTALL_DIR})
+ if (COLAMD_LIBRARY)
+ set(UMFPACK_LIBRARIES ${UMFPACK_LIBRARIES} ${COLAMD_LIBRARY})
+ #else (COLAMD_LIBRARY)
+ # set(UMFPACK_LIBRARIES FALSE)
+ endif (COLAMD_LIBRARY)
+
+ endif(UMFPACK_LIBRARIES)
+
+ if(UMFPACK_LIBRARIES)
+ set(UMFPACK_LIBRARIES ${UMFPACK_LIBRARIES} ${BLAS_LIBRARIES})
+ endif(UMFPACK_LIBRARIES)
+
+endif(BLAS_FOUND)
+
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(UMFPACK DEFAULT_MSG
+ UMFPACK_INCLUDES UMFPACK_LIBRARIES)
+
+mark_as_advanced(UMFPACK_INCLUDES UMFPACK_LIBRARIES AMD_LIBRARY COLAMD_LIBRARY)
\ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
index 115cd789..434f183f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,34 +6,39 @@ SUBDIRS = . tests examples tutorials
# ----------------------------------------------------------------------
# Declare products (i.e., the library)
-lib_LTLIBRARIES = libopmcore.la
+lib_LTLIBRARIES = lib/libopmcore.la
# ----------------------------------------------------------------------
# Build-time flags needed to build libopmcore.la
-AM_CPPFLAGS = \
-$(ERT_CPPFLAGS) \
-$(BOOST_CPPFLAGS)
+AM_CPPFLAGS = \
+$(ERT_CPPFLAGS) \
+$(OPM_BOOST_CPPFLAGS)
# ----------------------------------------------------------------------
# Link-time flags needed both to successfully link the library and to
# (transitively) convey inter-library dependency information.
-libopmcore_la_LDFLAGS = \
-$(ERT_LDFLAGS) \
-$(BOOST_LDFLAGS) \
-$(BOOST_FILESYSTEM_LIB) \
-$(BOOST_SYSTEM_LIB) \
-$(BOOST_DATE_TIME_LIB) \
+lib_libopmcore_la_LDFLAGS = \
+$(ERT_LDFLAGS) \
+$(OPM_BOOST_LDFLAGS) \
+$(BOOST_FILESYSTEM_LIB) \
+$(BOOST_SYSTEM_LIB) \
+$(BOOST_DATE_TIME_LIB) \
$(BOOST_UNIT_TEST_FRAMEWORK_LIB) \
-$(ERT_LIBS) $(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS)
+$(ERT_LIBS) \
+$(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS)
# ----------------------------------------------------------------------
# Library constituents. SOURCES followed by HEADERS.
#
# Please try to keep the list sorted.
-libopmcore_la_SOURCES = \
+# List of sources that should be built but not distributed. See AGMG
+# support below for additional details.
+nodist_lib_libopmcore_la_SOURCES =
+
+lib_libopmcore_la_SOURCES = \
opm/core/GridManager.cpp \
opm/core/eclipse/EclipseGridInspector.cpp \
opm/core/eclipse/EclipseGridParser.cpp \
@@ -48,8 +53,11 @@ opm/core/fluid/RockCompressibility.cpp \
opm/core/fluid/RockFromDeck.cpp \
opm/core/fluid/SaturationPropsBasic.cpp \
opm/core/fluid/SaturationPropsFromDeck.cpp \
+opm/core/fluid/SatFuncStone2.cpp \
+opm/core/fluid/SatFuncSimple.cpp \
opm/core/fluid/blackoil/BlackoilPvtProperties.cpp \
opm/core/fluid/blackoil/SinglePvtDead.cpp \
+opm/core/fluid/blackoil/SinglePvtDeadSpline.cpp \
opm/core/fluid/blackoil/SinglePvtInterface.cpp \
opm/core/fluid/blackoil/SinglePvtLiveGas.cpp \
opm/core/fluid/blackoil/SinglePvtLiveOil.cpp \
@@ -90,9 +98,10 @@ opm/core/pressure/tpfa/compr_source.c \
opm/core/pressure/tpfa/ifs_tpfa.c \
opm/core/pressure/tpfa/trans_tpfa.c \
opm/core/pressure/well.c \
+opm/core/simulator/SimulatorCompressibleTwophase.cpp \
+opm/core/simulator/SimulatorIncompTwophase.cpp \
opm/core/simulator/SimulatorReport.cpp \
opm/core/simulator/SimulatorTimer.cpp \
-opm/core/simulator/SimulatorTwophase.cpp \
opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp \
opm/core/transport/reorder/TransportModelInterface.cpp \
opm/core/transport/reorder/TransportModelTwophase.cpp \
@@ -142,13 +151,18 @@ opm/core/fluid/PvtPropertiesIncompFromDeck.hpp \
opm/core/fluid/RockBasic.hpp \
opm/core/fluid/RockCompressibility.hpp \
opm/core/fluid/RockFromDeck.hpp \
+opm/core/fluid/SatFuncStone2.hpp \
+opm/core/fluid/SatFuncSimple.hpp \
opm/core/fluid/SaturationPropsBasic.hpp \
opm/core/fluid/SaturationPropsFromDeck.hpp \
+opm/core/fluid/SaturationPropsFromDeck_impl.hpp \
+opm/core/fluid/SaturationPropsInterface.hpp \
opm/core/fluid/SimpleFluid2p.hpp \
opm/core/fluid/blackoil/BlackoilPhases.hpp \
opm/core/fluid/blackoil/BlackoilPvtProperties.hpp \
opm/core/fluid/blackoil/SinglePvtConstCompr.hpp \
opm/core/fluid/blackoil/SinglePvtDead.hpp \
+opm/core/fluid/blackoil/SinglePvtDeadSpline.hpp \
opm/core/fluid/blackoil/SinglePvtInterface.hpp \
opm/core/fluid/blackoil/SinglePvtLiveGas.hpp \
opm/core/fluid/blackoil/SinglePvtLiveOil.hpp \
@@ -193,9 +207,10 @@ opm/core/pressure/tpfa/compr_source.h \
opm/core/pressure/tpfa/ifs_tpfa.h \
opm/core/pressure/tpfa/trans_tpfa.h \
opm/core/simulator/BlackoilState.hpp \
+opm/core/simulator/SimulatorCompressibleTwophase.hpp \
opm/core/simulator/SimulatorReport.hpp \
+opm/core/simulator/SimulatorIncompTwophase.hpp \
opm/core/simulator/SimulatorTimer.hpp \
-opm/core/simulator/SimulatorTwophase.hpp \
opm/core/simulator/TwophaseState.hpp \
opm/core/simulator/WellState.hpp \
opm/core/transport/CSRMatrixBlockAssembler.hpp \
@@ -219,9 +234,11 @@ opm/core/transport/spu_implicit.h \
opm/core/transport/transport_source.h \
opm/core/utility/Average.hpp \
opm/core/utility/ColumnExtract.hpp \
+opm/core/utility/DataMap.hpp \
opm/core/utility/ErrorMacros.hpp \
opm/core/utility/Factory.hpp \
opm/core/utility/MonotCubicInterpolator.hpp \
+opm/core/utility/NonuniformTableLinear.hpp \
opm/core/utility/RootFinders.hpp \
opm/core/utility/SparseTable.hpp \
opm/core/utility/SparseVector.hpp \
@@ -246,7 +263,6 @@ opm/core/utility/parameters/ParameterXML.hpp \
opm/core/utility/parameters/tinyxml/tinystr.h \
opm/core/utility/parameters/tinyxml/tinyxml.h \
opm/core/utility/writeVtkData.hpp \
-opm/core/utility/DataMap.hpp \
opm/core/vag_format/vag.hpp \
opm/core/well.h \
opm/core/wells/InjectionSpecification.hpp \
@@ -259,7 +275,7 @@ opm/core/wells/WellsManager.hpp
# Optional library constituents.
if UMFPACK
-libopmcore_la_SOURCES += \
+lib_libopmcore_la_SOURCES += \
opm/core/linalg/call_umfpack.c \
opm/core/linalg/LinearSolverUmfpack.cpp
@@ -269,16 +285,16 @@ opm/core/linalg/LinearSolverUmfpack.hpp
endif
if HAVE_ERT
-libopmcore_la_SOURCES += \
+lib_libopmcore_la_SOURCES += \
opm/core/utility/writeECLData.cpp
-nobase_include_HEADERS += \
+nobase_include_HEADERS += \
opm/core/utility/writeECLData.hpp
endif
if DUNE_ISTL
-libopmcore_la_SOURCES += \
+lib_libopmcore_la_SOURCES += \
opm/core/linalg/LinearSolverIstl.cpp
nobase_include_HEADERS += \
@@ -287,14 +303,16 @@ endif
if BUILD_AGMG
-libopmcore_la_SOURCES += \
+nodist_lib_libopmcore_la_SOURCES += \
$(AGMG_SRCDIR)/dagmg.f90 \
-$(AGMG_SRCDIR)/dagmg_mumps.f90 \
+$(AGMG_SRCDIR)/dagmg_mumps.f90
+
+lib_libopmcore_la_SOURCES += \
opm/core/linalg/LinearSolverAGMG.cpp
nobase_include_HEADERS += \
opm/core/linalg/LinearSolverAGMG.hpp
-libopmcore_la_LDFLAGS += \
+lib_libopmcore_la_LDFLAGS += \
$(FCLIBS)
endif
diff --git a/README b/README
new file mode 100644
index 00000000..8c7c522f
--- /dev/null
+++ b/README
@@ -0,0 +1,125 @@
+Open Porous Media Core Library
+==============================
+
+These are release notes for opm-core.
+
+
+CONTENT
+-------
+
+opm-core is the core library within OPM and contains the following
+
+* Eclipse deck input and preprosessing
+* Fluid properties (basic PVT models and rock properties)
+* Grid handling (cornerpoint grids, unstructured grid interface)
+* Linear Algebra (interface to different linear solvers)
+* Pressure solvers (various discretization schemes, flow models)
+* Simulators (some basic examples of simulators based on sequential splitting schemes)
+* Transport solvers (various discretization schemes, flow models)
+* Utilities (input and output processing, unit conversion)
+* Wells (basic well handling)
+
+
+LICENSE
+-------
+
+The library is distributed under the GNU General Public License,
+version 3 or later (GPLv3+).
+
+
+PLATFORMS
+---------
+
+The opm-core module is designed to run on Linux platforms. It is also
+regularly run on Mac OS X. No efforts have been made to ensure that
+the code will compile and run on windows platforms.
+
+
+DEPENDENCIES FOR DEBIAN BASED DISTRIBUTIONS (Debian Squeeze/Ubuntu Precise)
+---------------------------------------------------------------------------
+
+# packages necessary for building
+sudo apt-get install -y build-essential gfortran pkg-config libtool \
+ automake autoconf
+
+# packages necessary for documentation
+sudo apt-get install -y doxygen ghostscript texlive-latex-recommended pgf
+
+# packages necessary for version control
+sudo apt-get install -y git-core git-svn subversion
+
+# libraries necessary for DUNE
+sudo apt-get install -y libboost-all-dev libsuperlu3-dev libsuitesparse-dev
+
+# libraries necessary for OPM
+sudo apt-get install -y libxml0-dev
+
+
+DEPENDENCIES FOR SUSE BASED DISTRIBUTIONS
+-----------------------------------------
+
+# libraries
+sudo zypper install blas libblas3 lapack liblapack3 libboost libxml2 umfpack
+
+# tools
+sudo zypper install gcc automake autoconf git doxygen
+
+
+RETRIEVING AND BUILDING DUNE PREREQUISITES
+------------------------------------------
+
+(only necessary if you want to use opm-core as a dune module)
+
+# trust DUNE certificate (sic)
+echo p | svn list https://svn.dune-project.org/svn/dune-common
+
+# checkout DUNE libraries
+for module in common istl geometry grid localfunctions; do
+ git svn clone -s \
+ https://svn.dune-project.org/svn/dune-$module/branches/release-2.2/ \
+ dune-$module
+done
+
+# building DUNE libraries
+for module in common istl geometry grid localfunctions; do
+ env CCACHE_DISABLE=1 dune-common/bin/dunecontrol --only=dune-$module \
+ --configure-opts="--enable-fieldvector-size-is-method" \
+ --make-opts="-j -l 0.8" autogen : configure : make
+done
+
+
+DOWNLOADING
+-----------
+
+For a read-only download:
+git clone git://github.com/OPM/opm-core.git
+
+If you want to contribute, fork OPM/opm-core on github.
+
+
+BUILDING
+--------
+
+(standalone opm-core:)
+
+ cd ../opm-core
+ autoreconf -i
+ ./configure
+ make
+ sudo make install
+
+(using opm-core as a dune module:)
+
+ # note: this is done from the parent directory of opm-core
+ env CCACHE_DISABLE=1 dune-common/bin/dunecontrol --only=opm-core \
+ --configure-opts="" --make-opts="-j -l 0.8" autogen : configure : make
+
+
+
+DOCUMENTATION
+-------------
+
+Efforts have been made to document the code with Doxygen.
+In order to build the documentation, enter the command
+$ doxygen
+in the topmost directory.
diff --git a/configure.ac b/configure.ac
index 140c6ff5..e603100a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -8,6 +8,10 @@ AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+# Needed for automake since version 1.12 because extra-portability
+# warnings were then added to -Wall. Ifdef makes it backwards compatible.
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([opm/core/grid.h])
AC_CONFIG_HEADERS([config.h])
@@ -28,60 +32,22 @@ m4_ifdef([LT_INIT],
AC_PROG_FC[]dnl
])[]dnl
-# Checks for libraries.
-
-# Bring in numerics support (standard library component)
-AC_SEARCH_LIBS([sqrt], [m])
-
-OPM_LAPACK
-
-AX_BOOST_BASE([1.37])
-AX_BOOST_SYSTEM
-AX_BOOST_DATE_TIME
-AX_BOOST_FILESYSTEM
-AX_BOOST_UNIT_TEST_FRAMEWORK
-
-AX_DUNE_ISTL
-OPM_AGMG
+OPM_CORE_CHECKS
OPM_DYNLINK_BOOST_TEST
-# Checks for header files.
-AC_CHECK_HEADERS([float.h limits.h stddef.h stdlib.h string.h])
-
-AC_CHECK_HEADERS([suitesparse/umfpack.h],
- [umfpack_header=yes],
- [umfpack_header=no])
-
-# Checks for typedefs, structures, and compiler characteristics.
-AC_HEADER_STDBOOL
-AC_TYPE_SIZE_T
-AC_CHECK_TYPES([ptrdiff_t])
-
-# Checks for library functions.
-AC_CHECK_FUNCS([floor memset memmove strchr strtol sqrt pow])
-AC_FUNC_STRTOD
-
-# Search for UMFPACK direct sparse solver.
-AC_SEARCH_LIBS([amd_free], [amd])
-AC_SEARCH_LIBS([camd_free], [camd])
-AC_SEARCH_LIBS([colamd_set_defaults], [colamd])
-AC_SEARCH_LIBS([ccolamd_set_defaults], [ccolamd])
-AC_SEARCH_LIBS([cholmod_l_start], [cholmod])
-AC_SEARCH_LIBS([umfpack_dl_solve], [umfpack],dnl
- [umfpack_lib=yes], [umfpack_lib=no])
-
-AM_CONDITIONAL([UMFPACK],
- [test "x$umfpack_header" != "xno" -a "x$umfpack_lib" != "xno"])
-
-m4_ifdef([AM_COND_IF],
-[AM_COND_IF([UMFPACK], [],
- [AC_MSG_NOTICE([Found no working installation of UMFPACK.
- UMFPACK support is disabled.])])
-])
-
ERT
+dnl Substitute Autoconf's abs_*dir variables into the Makefiles for the
+dnl benefit of external code that uses these variables to derive
+dnl locations (e.g., Dune's DUNE_CHECK_MODULES macro). Automakes prior
+dnl to version 1.10 do not automatically substitute these variables into
+dnl output files.
+AC_SUBST([abs_srcdir])
+AC_SUBST([abs_builddir])
+AC_SUBST([abs_top_srcdir])
+AC_SUBST([abs_top_builddir])
+
AC_CONFIG_FILES([
Makefile
tests/Makefile
diff --git a/dune.module b/dune.module
new file mode 100644
index 00000000..7deeedde
--- /dev/null
+++ b/dune.module
@@ -0,0 +1,7 @@
+#dune module information file#
+##############################
+
+#Name of the module
+Module: opm-core
+Version: 0.1
+Maintainer: atgeirr@sintef.no
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 5fafc37d..b9657dd0 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -1,15 +1,15 @@
# Build-time flags needed to form example programs
ERT_INCLUDE_PATH = $(ERT_ROOT)/include
-AM_CPPFLAGS = \
--I$(top_srcdir) \
-$(BOOST_CPPFLAGS) \
+AM_CPPFLAGS = \
+-I$(top_srcdir) \
+$(OPM_BOOST_CPPFLAGS) \
-I$(ERT_INCLUDE_PATH)
# All targets link to the library
-LDADD = \
-$(top_builddir)/libopmcore.la \
-$(BOOST_FILESYSTEM_LIB) \
+LDADD = \
+$(top_builddir)/lib/libopmcore.la \
+$(BOOST_FILESYSTEM_LIB) \
$(BOOST_SYSTEM_LIB)
# ----------------------------------------------------------------------
@@ -17,11 +17,12 @@ $(BOOST_SYSTEM_LIB)
#
# Please keep the list sorted.
-noinst_PROGRAMS = \
-refine_wells \
-scaneclipsedeck \
-sim_2p_incomp_reorder \
-sim_wateroil \
+noinst_PROGRAMS = \
+refine_wells \
+scaneclipsedeck \
+sim_2p_comp_reorder \
+sim_2p_incomp_reorder \
+sim_wateroil \
wells_example
# ----------------------------------------------------------------------
@@ -32,6 +33,7 @@ wells_example
# Please maintain sort order from "noinst_PROGRAMS".
refine_wells_SOURCES = refine_wells.cpp
+sim_2p_comp_reorder_SOURCES = sim_2p_comp_reorder.cpp
sim_2p_incomp_reorder_SOURCES = sim_2p_incomp_reorder.cpp
sim_wateroil_SOURCES = sim_wateroil.cpp
wells_example_SOURCES = wells_example.cpp
@@ -43,7 +45,7 @@ if UMFPACK
noinst_PROGRAMS += spu_2p
spu_2p_SOURCES = spu_2p.cpp
-spu_2p_LDADD = \
-$(LDADD) \
+spu_2p_LDADD = \
+$(LDADD) \
$(LAPACK_LIBS) $(BLAS_LIBS) $(LIBS)
endif
diff --git a/examples/sim_2p_comp_reorder.cpp b/examples/sim_2p_comp_reorder.cpp
new file mode 100644
index 00000000..cdc4a5a7
--- /dev/null
+++ b/examples/sim_2p_comp_reorder.cpp
@@ -0,0 +1,285 @@
+/*
+ Copyright 2012 SINTEF ICT, Applied Mathematics.
+
+ 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 .
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+
+namespace
+{
+ void warnIfUnusedParams(const Opm::parameter::ParameterGroup& param)
+ {
+ if (param.anyUnused()) {
+ std::cout << "-------------------- Unused parameters: --------------------\n";
+ param.displayUsage();
+ std::cout << "----------------------------------------------------------------" << std::endl;
+ }
+ }
+} // anon namespace
+
+
+
+// ----------------- Main program -----------------
+int
+main(int argc, char** argv)
+{
+ using namespace Opm;
+
+ std::cout << "\n================ Test program for weakly compressible two-phase flow ===============\n\n";
+ parameter::ParameterGroup param(argc, argv, false);
+ std::cout << "--------------- Reading parameters ---------------" << std::endl;
+
+ // If we have a "deck_filename", grid and props will be read from that.
+ bool use_deck = param.has("deck_filename");
+ boost::scoped_ptr deck;
+ boost::scoped_ptr grid;
+ boost::scoped_ptr props;
+ boost::scoped_ptr rock_comp;
+ BlackoilState state;
+ // bool check_well_controls = false;
+ // int max_well_control_iterations = 0;
+ double gravity[3] = { 0.0 };
+ if (use_deck) {
+ std::string deck_filename = param.get("deck_filename");
+ deck.reset(new EclipseGridParser(deck_filename));
+ // Grid init
+ grid.reset(new GridManager(*deck));
+ // Rock and fluid init
+ props.reset(new BlackoilPropertiesFromDeck(*deck, *grid->c_grid(), param));
+ // check_well_controls = param.getDefault("check_well_controls", false);
+ // max_well_control_iterations = param.getDefault("max_well_control_iterations", 10);
+ // Rock compressibility.
+ rock_comp.reset(new RockCompressibility(*deck));
+ // Gravity.
+ gravity[2] = deck->hasField("NOGRAV") ? 0.0 : unit::gravity;
+ // Init state variables (saturation and pressure).
+ if (param.has("init_saturation")) {
+ initStateBasic(*grid->c_grid(), *props, param, gravity[2], state);
+ } else {
+ initStateFromDeck(*grid->c_grid(), *props, *deck, gravity[2], state);
+ }
+ initBlackoilSurfvol(*grid->c_grid(), *props, state);
+ } else {
+ // Grid init.
+ const int nx = param.getDefault("nx", 100);
+ const int ny = param.getDefault("ny", 100);
+ const int nz = param.getDefault("nz", 1);
+ const double dx = param.getDefault("dx", 1.0);
+ const double dy = param.getDefault("dy", 1.0);
+ const double dz = param.getDefault("dz", 1.0);
+ grid.reset(new GridManager(nx, ny, nz, dx, dy, dz));
+ // Rock and fluid init.
+ props.reset(new BlackoilPropertiesBasic(param, grid->c_grid()->dimensions, grid->c_grid()->number_of_cells));
+ // Rock compressibility.
+ rock_comp.reset(new RockCompressibility(param));
+ // Gravity.
+ gravity[2] = param.getDefault("gravity", 0.0);
+ // Init state variables (saturation and pressure).
+ initStateBasic(*grid->c_grid(), *props, param, gravity[2], state);
+ initBlackoilSurfvol(*grid->c_grid(), *props, state);
+ }
+
+ bool use_gravity = (gravity[0] != 0.0 || gravity[1] != 0.0 || gravity[2] != 0.0);
+ const double *grav = use_gravity ? &gravity[0] : 0;
+
+ // Initialising src
+ int num_cells = grid->c_grid()->number_of_cells;
+ std::vector src(num_cells, 0.0);
+ if (use_deck) {
+ // Do nothing, wells will be the driving force, not source terms.
+ } else {
+ // Compute pore volumes, in order to enable specifying injection rate
+ // terms of total pore volume.
+ std::vector porevol;
+ if (rock_comp->isActive()) {
+ computePorevolume(*grid->c_grid(), props->porosity(), *rock_comp, state.pressure(), porevol);
+ } else {
+ computePorevolume(*grid->c_grid(), props->porosity(), porevol);
+ }
+ const double tot_porevol_init = std::accumulate(porevol.begin(), porevol.end(), 0.0);
+ const double default_injection = use_gravity ? 0.0 : 0.1;
+ const double flow_per_sec = param.getDefault("injected_porevolumes_per_day", default_injection)
+ *tot_porevol_init/unit::day;
+ src[0] = flow_per_sec;
+ src[num_cells - 1] = -flow_per_sec;
+ }
+
+ // Boundary conditions.
+ FlowBCManager bcs;
+ if (param.getDefault("use_pside", false)) {
+ int pside = param.get("pside");
+ double pside_pressure = param.get("pside_pressure");
+ bcs.pressureSide(*grid->c_grid(), FlowBCManager::Side(pside), pside_pressure);
+ }
+
+ // Linear solver.
+ LinearSolverFactory linsolver(param);
+
+ // Write parameters used for later reference.
+ bool output = param.getDefault("output", true);
+ std::ofstream epoch_os;
+ std::string output_dir;
+ if (output) {
+ output_dir =
+ param.getDefault("output_dir", std::string("output"));
+ boost::filesystem::path fpath(output_dir);
+ try {
+ create_directories(fpath);
+ }
+ catch (...) {
+ THROW("Creating directories failed: " << fpath);
+ }
+ std::string filename = output_dir + "/epoch_timing.param";
+ epoch_os.open(filename.c_str(), std::fstream::trunc | std::fstream::out);
+ // open file to clean it. The file is appended to in SimulatorTwophase
+ filename = output_dir + "/step_timing.param";
+ std::fstream step_os(filename.c_str(), std::fstream::trunc | std::fstream::out);
+ step_os.close();
+ param.writeParam(output_dir + "/simulation.param");
+ }
+
+
+ std::cout << "\n\n================ Starting main simulation loop ===============\n"
+ << " (number of epochs: "
+ << (use_deck ? deck->numberOfEpochs() : 1) << ")\n\n" << std::flush;
+
+ SimulatorReport rep;
+ if (!use_deck) {
+ // Simple simulation without a deck.
+ WellsManager wells; // no wells.
+ SimulatorCompressibleTwophase simulator(param,
+ *grid->c_grid(),
+ *props,
+ rock_comp->isActive() ? rock_comp.get() : 0,
+ wells,
+ src,
+ bcs.c_bcs(),
+ linsolver,
+ grav);
+ SimulatorTimer simtimer;
+ simtimer.init(param);
+ warnIfUnusedParams(param);
+ WellState well_state;
+ well_state.init(0, state);
+ rep = simulator.run(simtimer, state, well_state);
+ } else {
+ // With a deck, we may have more epochs etc.
+ WellState well_state;
+ int step = 0;
+ SimulatorTimer simtimer;
+ // Use timer for last epoch to obtain total time.
+ deck->setCurrentEpoch(deck->numberOfEpochs() - 1);
+ simtimer.init(*deck);
+ const double total_time = simtimer.totalTime();
+ for (int epoch = 0; epoch < deck->numberOfEpochs(); ++epoch) {
+ // Set epoch index.
+ deck->setCurrentEpoch(epoch);
+
+ // Update the timer.
+ if (deck->hasField("TSTEP")) {
+ simtimer.init(*deck);
+ } else {
+ if (epoch != 0) {
+ THROW("No TSTEP in deck for epoch " << epoch);
+ }
+ simtimer.init(param);
+ }
+ simtimer.setCurrentStepNum(step);
+ simtimer.setTotalTime(total_time);
+
+ // Report on start of epoch.
+ std::cout << "\n\n-------------- Starting epoch " << epoch << " --------------"
+ << "\n (number of steps: "
+ << simtimer.numSteps() - step << ")\n\n" << std::flush;
+
+ // Create new wells, well_state
+ WellsManager wells(*deck, *grid->c_grid(), props->permeability());
+ // @@@ HACK: we should really make a new well state and
+ // properly transfer old well state to it every epoch,
+ // since number of wells may change etc.
+ if (epoch == 0) {
+ well_state.init(wells.c_wells(), state);
+ }
+
+ // Create and run simulator.
+ SimulatorCompressibleTwophase simulator(param,
+ *grid->c_grid(),
+ *props,
+ rock_comp->isActive() ? rock_comp.get() : 0,
+ wells,
+ src,
+ bcs.c_bcs(),
+ linsolver,
+ grav);
+ if (epoch == 0) {
+ warnIfUnusedParams(param);
+ }
+ SimulatorReport epoch_rep = simulator.run(simtimer, state, well_state);
+ if (output) {
+ epoch_rep.reportParam(epoch_os);
+ }
+ // Update total timing report and remember step number.
+ rep += epoch_rep;
+ step = simtimer.currentStepNum();
+ }
+ }
+
+ std::cout << "\n\n================ End of simulation ===============\n\n";
+ rep.report(std::cout);
+
+ if (output) {
+ std::string filename = output_dir + "/walltime.param";
+ std::fstream tot_os(filename.c_str(),std::fstream::trunc | std::fstream::out);
+ rep.reportParam(tot_os);
+ }
+
+}
diff --git a/examples/sim_2p_incomp_reorder.cpp b/examples/sim_2p_incomp_reorder.cpp
index bc688b3f..0a7c3a71 100644
--- a/examples/sim_2p_incomp_reorder.cpp
+++ b/examples/sim_2p_incomp_reorder.cpp
@@ -43,9 +43,10 @@
#include
#include
-#include
+#include
#include
+#include
#include
#include
@@ -53,6 +54,18 @@
#include
+namespace
+{
+ void warnIfUnusedParams(const Opm::parameter::ParameterGroup& param)
+ {
+ if (param.anyUnused()) {
+ std::cout << "-------------------- Unused parameters: --------------------\n";
+ param.displayUsage();
+ std::cout << "----------------------------------------------------------------" << std::endl;
+ }
+ }
+} // anon namespace
+
// ----------------- Main program -----------------
@@ -81,9 +94,7 @@ main(int argc, char** argv)
// Grid init
grid.reset(new GridManager(*deck));
// Rock and fluid init
- const int* gc = grid->c_grid()->global_cell;
- std::vector global_cell(gc, gc + grid->c_grid()->number_of_cells);
- props.reset(new IncompPropertiesFromDeck(*deck, global_cell));
+ props.reset(new IncompPropertiesFromDeck(*deck, *grid->c_grid()));
// check_well_controls = param.getDefault("check_well_controls", false);
// max_well_control_iterations = param.getDefault("max_well_control_iterations", 10);
// Rock compressibility.
@@ -157,17 +168,28 @@ main(int argc, char** argv)
// Linear solver.
LinearSolverFactory linsolver(param);
- // Warn if any parameters are unused.
- // if (param.anyUnused()) {
- // std::cout << "-------------------- Unused parameters: --------------------\n";
- // param.displayUsage();
- // std::cout << "----------------------------------------------------------------" << std::endl;
- // }
-
// Write parameters used for later reference.
- // if (output) {
- // param.writeParam(output_dir + "/spu_2p.param");
- // }
+ bool output = param.getDefault("output", true);
+ std::ofstream epoch_os;
+ std::string output_dir;
+ if (output) {
+ output_dir =
+ param.getDefault("output_dir", std::string("output"));
+ boost::filesystem::path fpath(output_dir);
+ try {
+ create_directories(fpath);
+ }
+ catch (...) {
+ THROW("Creating directories failed: " << fpath);
+ }
+ std::string filename = output_dir + "/epoch_timing.param";
+ epoch_os.open(filename.c_str(), std::fstream::trunc | std::fstream::out);
+ // open file to clean it. The file is appended to in SimulatorTwophase
+ filename = output_dir + "/step_timing.param";
+ std::fstream step_os(filename.c_str(), std::fstream::trunc | std::fstream::out);
+ step_os.close();
+ param.writeParam(output_dir + "/simulation.param");
+ }
std::cout << "\n\n================ Starting main simulation loop ===============\n"
@@ -177,17 +199,19 @@ main(int argc, char** argv)
SimulatorReport rep;
if (!use_deck) {
// Simple simulation without a deck.
- SimulatorTwophase simulator(param,
- *grid->c_grid(),
- *props,
- rock_comp->isActive() ? rock_comp.get() : 0,
- 0, // wells
- src,
- bcs.c_bcs(),
- linsolver,
- grav);
+ WellsManager wells; // no wells.
+ SimulatorIncompTwophase simulator(param,
+ *grid->c_grid(),
+ *props,
+ rock_comp->isActive() ? rock_comp.get() : 0,
+ wells,
+ src,
+ bcs.c_bcs(),
+ linsolver,
+ grav);
SimulatorTimer simtimer;
simtimer.init(param);
+ warnIfUnusedParams(param);
WellState well_state;
well_state.init(0, state);
rep = simulator.run(simtimer, state, well_state);
@@ -221,7 +245,7 @@ main(int argc, char** argv)
<< "\n (number of steps: "
<< simtimer.numSteps() - step << ")\n\n" << std::flush;
- // Create new wells, well_satate
+ // Create new wells, well_state
WellsManager wells(*deck, *grid->c_grid(), props->permeability());
// @@@ HACK: we should really make a new well state and
// properly transfer old well state to it every epoch,
@@ -231,17 +255,22 @@ main(int argc, char** argv)
}
// Create and run simulator.
- SimulatorTwophase simulator(param,
- *grid->c_grid(),
- *props,
- rock_comp->isActive() ? rock_comp.get() : 0,
- wells.c_wells(),
- src,
- bcs.c_bcs(),
- linsolver,
- grav);
+ SimulatorIncompTwophase simulator(param,
+ *grid->c_grid(),
+ *props,
+ rock_comp->isActive() ? rock_comp.get() : 0,
+ wells,
+ src,
+ bcs.c_bcs(),
+ linsolver,
+ grav);
+ if (epoch == 0) {
+ warnIfUnusedParams(param);
+ }
SimulatorReport epoch_rep = simulator.run(simtimer, state, well_state);
-
+ if (output) {
+ epoch_rep.reportParam(epoch_os);
+ }
// Update total timing report and remember step number.
rep += epoch_rep;
step = simtimer.currentStepNum();
@@ -250,4 +279,11 @@ main(int argc, char** argv)
std::cout << "\n\n================ End of simulation ===============\n\n";
rep.report(std::cout);
+
+ if (output) {
+ std::string filename = output_dir + "/walltime.param";
+ std::fstream tot_os(filename.c_str(),std::fstream::trunc | std::fstream::out);
+ rep.reportParam(tot_os);
+ }
+
}
diff --git a/examples/sim_wateroil.cpp b/examples/sim_wateroil.cpp
index 1ffdd2b0..73374f00 100644
--- a/examples/sim_wateroil.cpp
+++ b/examples/sim_wateroil.cpp
@@ -68,8 +68,6 @@
#include
#include
-#define TRANSPORT_SOLVER_FIXED 1
-
template
static void outputState(const UnstructuredGrid& grid,
@@ -143,7 +141,6 @@ main(int argc, char** argv)
std::cout << "--------------- Reading parameters ---------------" << std::endl;
// Reading various control parameters.
- const bool use_reorder = param.getDefault("use_reorder", true);
const bool output = param.getDefault("output", true);
std::string output_dir;
int output_interval = 1;
@@ -178,9 +175,7 @@ main(int argc, char** argv)
// Grid init
grid.reset(new Opm::GridManager(deck));
// Rock and fluid init
- const int* gc = grid->c_grid()->global_cell;
- std::vector global_cell(gc, gc + grid->c_grid()->number_of_cells);
- props.reset(new Opm::BlackoilPropertiesFromDeck(deck, global_cell));
+ props.reset(new BlackoilPropertiesFromDeck(deck, *grid->c_grid(), param));
// Wells init.
wells.reset(new Opm::WellsManager(deck, *grid->c_grid(), props->permeability()));
check_well_controls = param.getDefault("check_well_controls", false);
@@ -233,28 +228,8 @@ main(int argc, char** argv)
}
}
bool use_segregation_split = false;
- bool use_column_solver = false;
- bool use_gauss_seidel_gravity = false;
- if (use_gravity && use_reorder) {
+ if (use_gravity) {
use_segregation_split = param.getDefault("use_segregation_split", use_segregation_split);
- if (use_segregation_split) {
- use_column_solver = param.getDefault("use_column_solver", use_column_solver);
- if (use_column_solver) {
- use_gauss_seidel_gravity = param.getDefault("use_gauss_seidel_gravity", use_gauss_seidel_gravity);
- }
- }
- }
-
- // Check that rock compressibility is not used with solvers that do not handle it.
- // int nl_pressure_maxiter = 0;
- // double nl_pressure_tolerance = 0.0;
- if (rock_comp->isActive()) {
- THROW("No rock compressibility in comp. pressure solver yet.");
- if (!use_reorder) {
- THROW("Cannot run implicit (non-reordering) transport solver with rock compressibility yet.");
- }
- // nl_pressure_maxiter = param.getDefault("nl_pressure_maxiter", 10);
- // nl_pressure_tolerance = param.getDefault("nl_pressure_tolerance", 1.0); // in Pascal
}
// Source-related variables init.
@@ -266,11 +241,11 @@ main(int argc, char** argv)
// Extra rock init.
std::vector porevol;
if (rock_comp->isActive()) {
- THROW("CompressibleTpfa solver does not handle this.");
computePorevolume(*grid->c_grid(), props->porosity(), *rock_comp, state.pressure(), porevol);
} else {
computePorevolume(*grid->c_grid(), props->porosity(), porevol);
}
+ std::vector initial_porevol = porevol;
double tot_porevol_init = std::accumulate(porevol.begin(), porevol.end(), 0.0);
@@ -297,21 +272,20 @@ main(int argc, char** argv)
const double nl_press_change_tol = param.getDefault("nl_press_change_tol", 10.0);
const int nl_press_maxiter = param.getDefault("nl_press_maxiter", 20);
const double *grav = use_gravity ? &gravity[0] : 0;
- Opm::CompressibleTpfa psolver(*grid->c_grid(), *props, linsolver,
+ Opm::CompressibleTpfa psolver(*grid->c_grid(), *props, rock_comp.get(), linsolver,
nl_press_res_tol, nl_press_change_tol, nl_press_maxiter,
grav, wells->c_wells());
// Reordering solver.
-#if TRANSPORT_SOLVER_FIXED
const double nl_tolerance = param.getDefault("nl_tolerance", 1e-9);
const int nl_maxiter = param.getDefault("nl_maxiter", 30);
Opm::TransportModelCompressibleTwophase reorder_model(*grid->c_grid(), *props, nl_tolerance, nl_maxiter);
- if (use_gauss_seidel_gravity) {
+ if (use_segregation_split) {
reorder_model.initGravity(grav);
}
-#endif // TRANSPORT_SOLVER_FIXED
+
// Column-based gravity segregation solver.
std::vector > columns;
- if (use_column_solver) {
+ if (use_segregation_split) {
Opm::extractColumn(*grid->c_grid(), columns);
}
@@ -414,24 +388,30 @@ main(int argc, char** argv)
Opm::computeTransportSource(*grid->c_grid(), src, state.faceflux(), 1.0,
wells->c_wells(), well_state.perfRates(), reorder_src);
+ // Compute new porevolumes after pressure solve, if necessary.
+ if (rock_comp->isActive()) {
+ initial_porevol = porevol;
+ computePorevolume(*grid->c_grid(), props->porosity(), *rock_comp, state.pressure(), porevol);
+ }
// Solve transport.
transport_timer.start();
-#if TRANSPORT_SOLVER_FIXED
double stepsize = simtimer.currentStepLength();
if (num_transport_substeps != 1) {
stepsize /= double(num_transport_substeps);
std::cout << "Making " << num_transport_substeps << " transport substeps." << std::endl;
}
for (int tr_substep = 0; tr_substep < num_transport_substeps; ++tr_substep) {
- reorder_model.solve(&state.faceflux()[0], &state.pressure()[0], &state.surfacevol()[0],
- &porevol[0], &reorder_src[0], stepsize, state.saturation());
+ // Note that for now we do not handle rock compressibility,
+ // although the transport solver should be able to.
+ reorder_model.solve(&state.faceflux()[0], &state.pressure()[0],
+ &porevol[0], &initial_porevol[0], &reorder_src[0], stepsize,
+ state.saturation(), state.surfacevol());
// Opm::computeInjectedProduced(*props, state.saturation(), reorder_src, stepsize, injected, produced);
if (use_segregation_split) {
- THROW("Segregation not implemented yet.");
- // reorder_model.solveGravity(columns, &porevol[0], stepsize, state.saturation());
+ reorder_model.solveGravity(columns, &state.pressure()[0], &initial_porevol[0],
+ stepsize, state.saturation(), state.surfacevol());
}
}
-#endif // TRANSPORT_SOLVER_FIXED
transport_timer.stop();
double tt = transport_timer.secsSinceStart();
std::cout << "Transport solver took: " << tt << " seconds." << std::endl;
diff --git a/examples/spu_2p.cpp b/examples/spu_2p.cpp
index ca05b424..755ef202 100644
--- a/examples/spu_2p.cpp
+++ b/examples/spu_2p.cpp
@@ -317,9 +317,7 @@ main(int argc, char** argv)
// Grid init
grid.reset(new Opm::GridManager(deck));
// Rock and fluid init
- const int* gc = grid->c_grid()->global_cell;
- std::vector global_cell(gc, gc + grid->c_grid()->number_of_cells);
- props.reset(new Opm::IncompPropertiesFromDeck(deck, global_cell));
+ props.reset(new Opm::IncompPropertiesFromDeck(deck, *grid->c_grid()));
// Wells init.
wells.reset(new Opm::WellsManager(deck, *grid->c_grid(), props->permeability()));
check_well_controls = param.getDefault("check_well_controls", false);
@@ -503,7 +501,7 @@ main(int argc, char** argv)
// Write parameters used for later reference.
if (output) {
- param.writeParam(output_dir + "/spu_2p.param");
+ param.writeParam(output_dir + "/simulation.param");
}
// Main simulation loop.
diff --git a/examples/wells_example.cpp b/examples/wells_example.cpp
index 9f7be7ec..1c523420 100644
--- a/examples/wells_example.cpp
+++ b/examples/wells_example.cpp
@@ -38,10 +38,8 @@ int main(int argc, char** argv)
// Finally handle the wells
WellsManager wells(parser, *grid.c_grid(), NULL);
- std::vector global_cells(grid.c_grid()->global_cell, grid.c_grid()->global_cell + grid.c_grid()->number_of_cells);
-
double gravity[3] = {0.0, 0.0, parameters.getDefault("gravity", 0.0)};
- IncompPropertiesFromDeck incomp_properties(parser, global_cells);
+ IncompPropertiesFromDeck incomp_properties(parser, *grid.c_grid());
RockCompressibility rock_comp(parser);
diff --git a/generate_doc_figures.py b/generate_doc_figures.py
index ae42709d..8d4931ee 100755
--- a/generate_doc_figures.py
+++ b/generate_doc_figures.py
@@ -1,6 +1,24 @@
+
+# This script generate the illustration pictures for the documentation.
+#
+# To run this script, you have to install paraview, see:
+#
+# http://www.paraview.org/paraview/resources/software.php
+#
+# Eventually, set up the paths (figure_path, tutorial_data_path, tutorial_path) according to your own installation.
+# (The default values should be ok.)
+#
+# Make sure that pvpython is in your path of executables.
+#
+# Run the following command at the root of the directory where
+# opm-core is installed (which also corresponds to the directory where
+# generate_doc_figures is located):
+#
+# pvpython generate_doc_figures.py
+#
+
from subprocess import call
from paraview.simple import *
-# from paraview import servermanager
from os import remove, mkdir, curdir
from os.path import join, isdir
@@ -13,7 +31,6 @@ collected_garbage_file = []
if not isdir(figure_path):
mkdir(figure_path)
-# connection = servermanager.Connect()
# tutorial 1
call(join(tutorial_path, "tutorial1"))
diff --git a/m4/agmg.m4 b/m4/agmg.m4
index 9e09157b..0a16e9b3 100644
--- a/m4/agmg.m4
+++ b/m4/agmg.m4
@@ -11,10 +11,14 @@ AC_DEFUN([OPM_AGMG],dnl
[AS_IF([test -f "$with_agmg/dagmg.f90"],dnl
[AC_SUBST([AGMG_SRCDIR], [$with_agmg])[]dnl
AC_DEFINE([HAVE_AGMG], [1],dnl
- [Define to `1' if Notay's AGMG solver is included])[]dnl
+ [Define to 1 if Notay's AGMG solver is included.])[]dnl
build_agmg="yes"],dnl
- [build_agmg="no"])],dnl
- [build_agmg="no"])[]dnl
+ [AC_DEFINE([HAVE_AGMG], [0],dnl
+ [Define to 0 if Notay's AGMG solver is unavailable.])[]dnl
+ build_agmg="no"])],dnl
+ [AC_DEFINE([HAVE_AGMG], [0],dnl
+ [Define to 0 if Notay's AGMG solver is unwanted.])[]dnl
+ build_agmg="no"])[]dnl
AS_IF([test x"$build_agmg" = x"yes"],dnl
[AC_PROG_FC_C_O[]dnl
diff --git a/m4/ax_boost_date_time.m4 b/m4/ax_boost_date_time.m4
index 959ab8ad..4e9d57ba 100644
--- a/m4/ax_boost_date_time.m4
+++ b/m4/ax_boost_date_time.m4
@@ -55,11 +55,11 @@ AC_DEFUN([AX_BOOST_DATE_TIME],
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
CPPFLAGS_SAVED="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $OPM_BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
- LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ LDFLAGS="$LDFLAGS $OPM_BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::Date_Time library is available,
@@ -74,7 +74,7 @@ AC_DEFUN([AX_BOOST_DATE_TIME],
])
if test "x$ax_cv_boost_date_time" = "xyes"; then
AC_DEFINE(HAVE_BOOST_DATE_TIME,,[define if the Boost::Date_Time library is available])
- BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+ BOOSTLIBDIR=`echo $OPM_BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
ax_lib="-lboost_date_time"
if test "x$ax_boost_user_date_time_lib" = "x"; then
diff --git a/m4/ax_boost_filesystem.m4 b/m4/ax_boost_filesystem.m4
index b230a191..2bb74e5a 100644
--- a/m4/ax_boost_filesystem.m4
+++ b/m4/ax_boost_filesystem.m4
@@ -56,11 +56,11 @@ AC_DEFUN([AX_BOOST_FILESYSTEM],
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
CPPFLAGS_SAVED="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $OPM_BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
- LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ LDFLAGS="$LDFLAGS $OPM_BOOST_LDFLAGS"
export LDFLAGS
LIBS_SAVED=$LIBS
@@ -79,7 +79,7 @@ AC_DEFUN([AX_BOOST_FILESYSTEM],
])
if test "x$ax_cv_boost_filesystem" = "xyes"; then
AC_DEFINE(HAVE_BOOST_FILESYSTEM,,[define if the Boost::Filesystem library is available])
- BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+ BOOSTLIBDIR=`echo $OPM_BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
ax_lib="-lboost_filesystem"
if test "x$ax_boost_user_filesystem_lib" = "x"; then
for libextension in `ls $BOOSTLIBDIR/libboost_filesystem*.so* $BOOSTLIBDIR/libboost_filesystem*.dylib* $BOOSTLIBDIR/libboost_filesystem*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_filesystem.*\)\.so.*$;\1;' -e 's;^lib\(boost_filesystem.*\)\.a*$;\1;' -e 's;^lib\(boost_filesystem.*\)\.dylib$;\1;'` ; do
diff --git a/m4/ax_boost_system.m4 b/m4/ax_boost_system.m4
index b97f3739..2d47ad45 100644
--- a/m4/ax_boost_system.m4
+++ b/m4/ax_boost_system.m4
@@ -57,11 +57,11 @@ AC_DEFUN([AX_BOOST_SYSTEM],
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_BUILD])
CPPFLAGS_SAVED="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $OPM_BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
- LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ LDFLAGS="$LDFLAGS $OPM_BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::System library is available,
@@ -76,10 +76,10 @@ AC_DEFUN([AX_BOOST_SYSTEM],
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_system" = "xyes"; then
- AC_SUBST(BOOST_CPPFLAGS)
+ AC_SUBST(OPM_BOOST_CPPFLAGS)
AC_DEFINE(HAVE_BOOST_SYSTEM,,[define if the Boost::System library is available])
- BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+ BOOSTLIBDIR=`echo $OPM_BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
ax_lib="-lboost_system"
LDFLAGS_SAVE=$LDFLAGS
diff --git a/m4/ax_boost_unit_test_framework.m4 b/m4/ax_boost_unit_test_framework.m4
index fa34c974..0cee8baa 100644
--- a/m4/ax_boost_unit_test_framework.m4
+++ b/m4/ax_boost_unit_test_framework.m4
@@ -54,11 +54,11 @@ AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK],
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
CPPFLAGS_SAVED="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $OPM_BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
- LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ LDFLAGS="$LDFLAGS $OPM_BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::Unit_Test_Framework library is available,
@@ -72,7 +72,7 @@ AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK],
])
if test "x$ax_cv_boost_unit_test_framework" = "xyes"; then
AC_DEFINE(HAVE_BOOST_UNIT_TEST_FRAMEWORK,,[define if the Boost::Unit_Test_Framework library is available])
- BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+ BOOSTLIBDIR=`echo $OPM_BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
ax_lib="-lboost_unit_test_framework"
if test "x$ax_boost_user_unit_test_framework_lib" = "x"; then
diff --git a/m4/ax_dune_istl.m4 b/m4/ax_dune_istl.m4
index 2f0fd55b..40fa9072 100644
--- a/m4/ax_dune_istl.m4
+++ b/m4/ax_dune_istl.m4
@@ -31,7 +31,9 @@ AC_DEFUN([AX_DUNE_ISTL],
"x$ax_cv_dune_common_available" = "xyes"],dnl
[AC_DEFINE([HAVE_DUNE_ISTL], [1],dnl
[Define to 1 if `dune-istl' is available])
- ])[]dnl
+ ],dnl
+ [AC_DEFINE([HAVE_DUNE_ISTL], [0],dnl
+ [Define to 0 if `dune-istl' is unavailable.])])[]dnl
AM_CONDITIONAL([DUNE_ISTL],
[test "x$ax_cv_dune_istl_available" = "xyes" -a \
diff --git a/m4/ax_boost_base.m4 b/m4/opm_boost_base.m4
similarity index 87%
rename from m4/ax_boost_base.m4
rename to m4/opm_boost_base.m4
index 54a2a1be..430f9abb 100644
--- a/m4/ax_boost_base.m4
+++ b/m4/opm_boost_base.m4
@@ -4,7 +4,7 @@
#
# SYNOPSIS
#
-# AX_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# OPM_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
#
# DESCRIPTION
#
@@ -17,11 +17,11 @@
#
# This macro calls:
#
-# AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)
+# AC_SUBST(OPM_BOOST_CPPFLAGS) / AC_SUBST(OPM_BOOST_LDFLAGS)
#
# And sets:
#
-# HAVE_BOOST
+# OPM_HAVE_BOOST
#
# LICENSE
#
@@ -35,7 +35,7 @@
#serial 20
-AC_DEFUN([AX_BOOST_BASE],
+AC_DEFUN([OPM_BOOST_BASE],
[
AC_ARG_WITH([boost],
[AS_HELP_STRING([--with-boost@<:@=ARG@:>@],
@@ -99,10 +99,10 @@ if test "x$want_boost" = "xyes"; then
dnl this location ist chosen if boost libraries are installed with the --layout=system option
dnl or if you install boost with RPM
if test "$ac_boost_path" != ""; then
- BOOST_CPPFLAGS="-I$ac_boost_path/include"
+ OPM_BOOST_CPPFLAGS="-I$ac_boost_path/include"
for ac_boost_path_tmp in $libsubdirs; do
if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then
- BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp"
+ OPM_BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp"
break
fi
done
@@ -112,8 +112,8 @@ if test "x$want_boost" = "xyes"; then
for libsubdir in $libsubdirs ; do
if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
done
- BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir"
- BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include"
+ OPM_BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir"
+ OPM_BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include"
break;
fi
done
@@ -122,15 +122,15 @@ if test "x$want_boost" = "xyes"; then
dnl overwrite ld flags if we have required special directory with
dnl --with-boost-libdir parameter
if test "$ac_boost_lib_path" != ""; then
- BOOST_LDFLAGS="-L$ac_boost_lib_path"
+ OPM_BOOST_LDFLAGS="-L$ac_boost_lib_path"
fi
CPPFLAGS_SAVED="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $OPM_BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
- LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ LDFLAGS="$LDFLAGS $OPM_BOOST_LDFLAGS"
export LDFLAGS
AC_REQUIRE([AC_PROG_CXX])
@@ -166,7 +166,7 @@ if test "x$want_boost" = "xyes"; then
_version=$_version_tmp
fi
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
- BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
+ OPM_BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
done
fi
else
@@ -185,12 +185,12 @@ if test "x$want_boost" = "xyes"; then
done
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
- BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
+ OPM_BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
if test "$ac_boost_lib_path" = ""; then
for libsubdir in $libsubdirs ; do
if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
done
- BOOST_LDFLAGS="-L$best_path/$libsubdir"
+ OPM_BOOST_LDFLAGS="-L$best_path/$libsubdir"
fi
fi
@@ -205,16 +205,16 @@ if test "x$want_boost" = "xyes"; then
V_CHECK=`expr $stage_version_shorten \>\= $_version`
if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then
AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT)
- BOOST_CPPFLAGS="-I$BOOST_ROOT"
- BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir"
+ OPM_BOOST_CPPFLAGS="-I$BOOST_ROOT"
+ OPM_BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir"
fi
fi
fi
fi
- CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $OPM_BOOST_CPPFLAGS"
export CPPFLAGS
- LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+ LDFLAGS="$LDFLAGS $OPM_BOOST_LDFLAGS"
export LDFLAGS
AC_LANG_PUSH(C++)
@@ -243,10 +243,12 @@ if test "x$want_boost" = "xyes"; then
fi
# execute ACTION-IF-NOT-FOUND (if present):
ifelse([$3], , :, [$3])
+ AC_DEFINE([OPM_HAVE_BOOST], [0],dnl
+ [Define to `0' if the Boost library is not available])
else
- AC_SUBST(BOOST_CPPFLAGS)
- AC_SUBST(BOOST_LDFLAGS)
- AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available])
+ AC_SUBST([OPM_BOOST_CPPFLAGS])
+ AC_SUBST([OPM_BOOST_LDFLAGS])
+ AC_DEFINE([OPM_HAVE_BOOST], [1], [define if the Boost library is available])
# execute ACTION-IF-FOUND (if present):
ifelse([$2], , :, [$2])
fi
diff --git a/m4/opm_core.m4 b/m4/opm_core.m4
new file mode 100644
index 00000000..efb75c13
--- /dev/null
+++ b/m4/opm_core.m4
@@ -0,0 +1,66 @@
+dnl -*- autoconf -*-
+ # Macros needed to find OPM-core and dependent libraries. They are called by
+# the macros in ${top_src_dir}/dependencies.m4, which is generated by
+# "dunecontrol autogen"
+AC_DEFUN([OPM_CORE_CHECKS],
+[
+
+# Checks for libraries.
+
+# Bring in numerics support (standard library component)
+AC_SEARCH_LIBS([sqrt], [m])
+
+OPM_LAPACK
+
+OPM_BOOST_BASE([1.37])
+AX_BOOST_SYSTEM
+AX_BOOST_DATE_TIME
+AX_BOOST_FILESYSTEM
+AX_BOOST_UNIT_TEST_FRAMEWORK
+
+AX_DUNE_ISTL
+OPM_AGMG
+
+# Checks for header files.
+AC_CHECK_HEADERS([float.h limits.h stddef.h stdlib.h string.h])
+
+AC_CHECK_HEADERS([suitesparse/umfpack.h],
+ [umfpack_header=yes],
+ [umfpack_header=no])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_STDBOOL
+AC_TYPE_SIZE_T
+AC_CHECK_TYPES([ptrdiff_t])
+
+# Checks for library functions.
+AC_CHECK_FUNCS([floor memset memmove strchr strtol sqrt pow])
+AC_FUNC_STRTOD
+
+# Search for UMFPACK direct sparse solver.
+AC_SEARCH_LIBS([amd_free], [amd])
+AC_SEARCH_LIBS([camd_free], [camd])
+AC_SEARCH_LIBS([colamd_set_defaults], [colamd])
+AC_SEARCH_LIBS([ccolamd_set_defaults], [ccolamd])
+AC_SEARCH_LIBS([cholmod_l_start], [cholmod])
+AC_SEARCH_LIBS([umfpack_dl_solve], [umfpack],dnl
+ [umfpack_lib=yes], [umfpack_lib=no])
+
+AM_CONDITIONAL([UMFPACK],
+ [test "x$umfpack_header" != "xno" -a "x$umfpack_lib" != "xno"])
+
+m4_ifdef([AM_COND_IF],
+[AM_COND_IF([UMFPACK], [],
+ [AC_MSG_NOTICE([Found no working installation of UMFPACK.
+ UMFPACK support is disabled.])])
+])
+
+])
+
+# Additional checks needed to find eWoms
+# This macro should be invoked by every module which depends on dumux, but
+# not by dumux itself
+AC_DEFUN([OPM_CORE_CHECK_MODULE],
+[
+ OPM_CORE_CHECK_MODULES([opm-core],[opm/core/grid.h],[create_grid_empty()])
+])
diff --git a/m4/opm_core_check_modules.m4 b/m4/opm_core_check_modules.m4
new file mode 100644
index 00000000..1f7cf878
--- /dev/null
+++ b/m4/opm_core_check_modules.m4
@@ -0,0 +1,281 @@
+dnl -*- autoconf -*-
+
+# OPM_CORE_CHECK_MODULES(NAME, HEADER, SYMBOL)
+#
+# THIS MACRO IS JUST A COPY OF DUNE_CHECK_MODULES WITH THE REQUIREMENT
+# THAT ALL HEADERS MUST RESIDE IN $MODULE_ROOT/dune REMOVED. REMOVE
+# THIS MACRO AS SOON AS DUNE DOES NOT ENFORCE THIS ANYMORE.
+#
+# Generic check for dune modules. This macro should not be used directly, but
+# in the modules m4/{module}.m4 in the {MODULE}_CHECK_MODULE macro. The
+# {MODULE}_CHECK_MODULE macro knows the parameters to call this
+# DUNE_CHECK_MODULES macro with, and it does not take any parameters itself,
+# so it may be used with AC_REQUIRE.
+#
+# NAME Name of the module, lowercase with dashes (like "dune-common"). The
+# value must be known when autoconf runs, so shell variables in the
+# value are not permissible.
+#
+# HEADER Header to check for. The check will really be for ,
+# so the header must reside within a directory called "dune".
+#
+# SYMBOL Symbol to check for in the module's library. If this argument is
+# empty or missing, it is assumed that the module does not provide a
+# library. The value must be known when autoconf runs, so shell
+# variables in the value are not permissible. This value is actually
+# handed to AC_TRY_LINK unchanged as the FUNCTION-BODY argument, so it
+# may contain more complex stuff than a simple symbol.
+#
+# The name of the library is assumed to be the same as the module name,
+# with any occurance of "-" removed. The path of the library is
+# obtained from pkgconfig for installed modules, or assumed to be the
+# directory "lib" within the modules root for non-installed modules.
+#
+# In the following, {module} is {NAME} with any "-" replaced by "_" and
+# {MODULE} is the uppercase version of {module}.
+#
+# configure options:
+# --with-{NAME}
+#
+# configure/shell variables:
+# {MODULE}_ROOT, {MODULE}_LIBDIR
+# HAVE_{MODULE} (1 or 0)
+# with_{module} ("yes" or "no")
+# DUNE_CPPFLAGS, DUNE_LDFLAGS, DUNE_LIBS (adds the modules values here,
+# substitution done by DUNE_CHECK_ALL)
+# ALL_PKG_CPPFLAGS, ALL_PKG_LDFLAGS, ALL_PKG_LIBS (adds the modules values
+# here, substitution done by DUNE_CHECK_ALL)
+# {MODULE}_VERSION
+# {MODULE}_VERSION_MAJOR
+# {MODULE}_VERSION_MINOR
+# {MODULE}_VERSION_REVISION
+#
+# configure substitutions/makefile variables:
+# {MODULE}_CPPFLAGS, {MODULE}_LDFLAGS, {MODULE}_LIBS
+# {MODULE}_ROOT
+# {MODULE}_LIBDIR (only if modules provides a library)
+#
+# preprocessor defines:
+# HAVE_{MODULE} (1 or undefined)
+# {MODULE}_VERSION
+# {MODULE}_VERSION_MAJOR
+# {MODULE}_VERSION_MINOR
+# {MODULE}_VERSION_REVISION
+#
+# automake conditionals:
+# HAVE_{MODULE}
+AC_DEFUN([OPM_CORE_CHECK_MODULES],[
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([AC_PROG_CXXCPP])
+ AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+ AC_REQUIRE([DUNE_DISABLE_LIBCHECK])
+ AC_REQUIRE([LT_OUTPUT])
+
+ # ____DUNE_CHECK_MODULES_____ ($1)
+
+ m4_pushdef([_dune_name], [$1])
+ m4_pushdef([_dune_module], [m4_translit(_dune_name, [-], [_])])
+ m4_pushdef([_dune_header], [$2])
+ m4_pushdef([_dune_ldpath], [lib])
+ m4_pushdef([_dune_lib], [m4_translit(_dune_name, [-], [])])
+ m4_pushdef([_dune_symbol], [$3])
+ m4_pushdef([_DUNE_MODULE], [m4_toupper(_dune_module)])
+
+ # switch tests to c++
+ AC_LANG_PUSH([C++])
+
+ # the usual option...
+ AC_ARG_WITH(_dune_name,
+ AS_HELP_STRING([--with-_dune_name=PATH],[_dune_module directory]))
+
+ # backup of flags
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ ac_save_LIBS="$LIBS"
+ ac_save_LDFLAGS="$LDFLAGS"
+ CPPFLAGS=""
+ LIBS=""
+
+ ##
+ ## Where is the module $1?
+ ##
+
+ AC_MSG_CHECKING([for $1 installation or source tree])
+
+ # is a directory set?
+ AS_IF([test -z "$with_[]_dune_module"],[
+ #
+ # search module $1 via pkg-config
+ #
+ with_[]_dune_module="global installation"
+ AS_IF([test -z "$PKG_CONFIG"],[
+ AC_MSG_RESULT([failed])
+ AC_MSG_NOTICE([could not search for module _dune_name])
+ AC_MSG_ERROR([pkg-config is required for using installed modules])
+ ])
+ AS_IF(AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]),[
+ _dune_cm_CPPFLAGS="`$PKG_CONFIG --cflags _dune_name`" 2>/dev/null
+ _DUNE_MODULE[]_ROOT="`$PKG_CONFIG --variable=prefix _dune_name`" 2>/dev/null
+ _DUNE_MODULE[]_VERSION="`$PKG_CONFIG --modversion _dune_name`" 2>/dev/null
+ _dune_cm_LDFLAGS=""
+ ifelse(_dune_symbol,,
+ [_DUNE_MODULE[]_LIBDIR=""
+ _dune_cm_LIBS=""],
+ [_DUNE_MODULE[]_LIBDIR=`$PKG_CONFIG --variable=libdir _dune_name 2>/dev/null`
+ _dune_cm_LIBS="-L$_DUNE_MODULE[]_LIBDIR -l[]_dune_lib"])
+ HAVE_[]_DUNE_MODULE=1
+ AC_MSG_RESULT([global installation in $_DUNE_MODULE[]_ROOT])
+ ],[
+ HAVE_[]_DUNE_MODULE=0
+ AC_MSG_RESULT([not found])
+ ])
+ ],[
+ #
+ # path for module $1 is specified via command line
+ #
+ AS_IF([test -d "$with_[]_dune_module"],[
+ # expand tilde / other stuff
+ _DUNE_MODULE[]_ROOT=`cd $with_[]_dune_module && pwd`
+
+ # expand search path (otherwise empty CPPFLAGS)
+ AS_IF([test -d "$_DUNE_MODULE[]_ROOT/include/dune"],[
+ # Dune was installed into directory given by with-dunecommon
+ _dune_cm_CPPFLAGS="-I$_DUNE_MODULE[]_ROOT/include"
+ _DUNE_MODULE[]_BUILDDIR=_DUNE_MODULE[]_ROOT
+ _DUNE_MODULE[]_VERSION="`PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$_DUNE_MODULE[]_ROOT/lib/pkgconfig $PKG_CONFIG --modversion _dune_name`" 2>/dev/null
+ ],[
+ _DUNE_MODULE[]_SRCDIR=$_DUNE_MODULE[]_ROOT
+ # extract src and build path from Makefile, if found
+ AS_IF([test -f $_DUNE_MODULE[]_ROOT/Makefile],[
+ _DUNE_MODULE[]_SRCDIR="`sed -ne '/^abs_top_srcdir = /{s/^abs_top_srcdir = //; p;}' $_DUNE_MODULE[]_ROOT/Makefile`"
+ ])
+ _dune_cm_CPPFLAGS="-I$_DUNE_MODULE[]_SRCDIR"
+ _DUNE_MODULE[]_VERSION="`grep Version $_DUNE_MODULE[]_SRCDIR/dune.module | sed -e 's/^Version: *//'`" 2>/dev/null
+ ])
+ _dune_cm_LDFLAGS=""
+ ifelse(_dune_symbol,,
+ [_DUNE_MODULE[]_LIBDIR=""
+ _dune_cm_LIBS=""],
+ [_DUNE_MODULE[]_LIBDIR="$_DUNE_MODULE[]_ROOT/lib"
+ _dune_cm_LIBS="-L$_DUNE_MODULE[]_LIBDIR -l[]_dune_lib"])
+ # set expanded module path
+ with_[]_dune_module="$_DUNE_MODULE[]_ROOT"
+ HAVE_[]_DUNE_MODULE=1
+ AC_MSG_RESULT([found in $_DUNE_MODULE[]_ROOT])
+ ],[
+ HAVE_[]_DUNE_MODULE=0
+ AC_MSG_RESULT([not found])
+ AC_MSG_ERROR([_dune_name-directory $with_[]_dune_module does not exist])
+ ])
+ ])
+
+ CPPFLAGS="$ac_save_CPPFLAGS $DUNE_CPPFLAGS $_dune_cm_CPPFLAGS"
+ ##
+ ## check for an arbitrary header
+ ##
+ AS_IF([test "$HAVE_[]_DUNE_MODULE" != "1"],[
+ AC_CHECK_HEADER([[]_dune_header],
+ [HAVE_[]_DUNE_MODULE=1], [HAVE_[]_DUNE_MODULE=0])
+ ])
+
+ AS_IF([test "$HAVE_[]_DUNE_MODULE" != "1"],[
+ AC_MSG_WARN([$_DUNE_MODULE[]_ROOT does not seem to contain a valid _dune_name (dune/[]_dune_header not found)])
+ ])
+
+ ##
+ ## check for lib (if lib name was provided)
+ ##
+ ifelse(_dune_symbol,,
+ AC_MSG_NOTICE([_dune_name does not provide libs]),
+
+ AS_IF([test "x$enable_dunelibcheck" = "xno"],[
+ AC_MSG_WARN([library check for _dune_name is disabled. DANGEROUS!])
+ ],[
+ AS_IF([test "x$HAVE_[]_DUNE_MODULE" = "x1"],[
+
+ # save current LDFLAGS
+ ac_save_CXX="$CXX"
+ HAVE_[]_DUNE_MODULE=0
+
+ # define LTCXXLINK like it will be defined in the Makefile
+ CXX="./libtool --tag=CXX --mode=link $ac_save_CXX"
+
+ # use module LDFLAGS
+ LDFLAGS="$ac_save_LDFLAGS $DUNE_LDFLAGS $_dune_cm_LDFLAGS"
+ LIBS="$_dune_cm_LIBS $DUNE_LIBS $LIBS"
+
+ AC_MSG_CHECKING([for lib[]_dune_lib])
+
+ AC_TRY_LINK(dnl
+ [#]include<_dune_header>,
+ _dune_symbol,
+ [
+ AC_MSG_RESULT([yes])
+ HAVE_[]_DUNE_MODULE=1
+ ],[
+ AC_MSG_RESULT([no])
+ HAVE_[]_DUNE_MODULE=0
+ AS_IF([test -n "$_DUNE_MODULE[]_ROOT"],[
+ AC_MSG_WARN([$with_[]_dune_module does not seem to contain a valid _dune_name (failed to link with lib[]_dune_lib[].la)])
+ ])
+ ]
+ )
+ ])
+
+ # reset variables
+ CXX="$ac_save_CXX"
+ ])
+ )
+
+ # did we succeed?
+ AS_IF([test "x$HAVE_[]_DUNE_MODULE" = "x1"],[
+ # add the module's own flags and libs to the modules and the global
+ # variables
+ DUNE_ADD_MODULE_DEPS(m4_defn([_dune_name]), m4_defn([_dune_name]),
+ [$_dune_cm_CPPFLAGS], [$_dune_cm_LDFLAGS], [$_dune_cm_LIBS])
+
+ # set variables for our modules
+ AC_SUBST(_DUNE_MODULE[]_CPPFLAGS, "$_DUNE_MODULE[]_CPPFLAGS")
+ AC_SUBST(_DUNE_MODULE[]_LDFLAGS, "$_DUNE_MODULE[]_LDFLAGS")
+ AC_SUBST(_DUNE_MODULE[]_LIBS, "$_DUNE_MODULE[]_LIBS")
+ AC_SUBST(_DUNE_MODULE[]_ROOT, "$_DUNE_MODULE[]_ROOT")
+ ifelse(m4_defn([_dune_symbol]),,
+ [],
+ [AC_SUBST(_DUNE_MODULE[]_LIBDIR)
+ ])
+ AC_DEFINE(HAVE_[]_DUNE_MODULE, 1, [Define to 1 if] _dune_name [was found])
+
+ DUNE_PARSE_MODULE_VERSION(_dune_name, $_DUNE_MODULE[]_VERSION)
+
+ # set DUNE_* variables
+ # This should actually be unneccesary, but I'm keeping it in here for now
+ # for backward compatibility
+ DUNE_LDFLAGS="$DUNE_LDFLAGS $_DUNE_MODULE[]_LDFLAGS"
+ DUNE_LIBS="$_DUNE_MODULE[]_LIBS $DUNE_LIBS"
+
+ with_[]_dune_module="yes"
+ ],[
+ with_[]_dune_module="no"
+ ])
+
+ AM_CONDITIONAL(HAVE_[]_DUNE_MODULE, test x$HAVE_[]_DUNE_MODULE = x1)
+
+ # reset previous flags
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LDFLAGS="$ac_save_LDFLAGS"
+ LIBS="$ac_save_LIBS"
+
+ # add this module to DUNE_SUMMARY
+ DUNE_MODULE_ADD_SUMMARY_ENTRY(_dune_name)
+
+ # remove local variables
+ m4_popdef([_dune_name])
+ m4_popdef([_dune_module])
+ m4_popdef([_dune_header])
+ m4_popdef([_dune_ldpath])
+ m4_popdef([_dune_lib])
+ m4_popdef([_dune_symbol])
+ m4_popdef([_DUNE_MODULE])
+
+ # restore previous language settings (leave C++)
+ AC_LANG_POP([C++])
+])
diff --git a/m4/opm_dynlink_boost_test.m4 b/m4/opm_dynlink_boost_test.m4
index 89c82908..7005b552 100644
--- a/m4/opm_dynlink_boost_test.m4
+++ b/m4/opm_dynlink_boost_test.m4
@@ -38,14 +38,14 @@ dnl -------------------------------------------------------------------
# system uses dynamic linking of Boost.Test .
AC_DEFUN([OPM_DYNLINK_BOOST_TEST],
[
-AC_REQUIRE([AX_BOOST_BASE])
+AC_REQUIRE([OPM_BOOST_BASE])
AC_REQUIRE([AX_BOOST_UNIT_TEST_FRAMEWORK])
-_opm_LIBS_SAVE="$LIBS"
-_opm_CPPFLAGS_SAVE="$CPPFLAGS"
+_opm_LIBS_SAVE="${LIBS}"
+_opm_CPPFLAGS_SAVE="${CPPFLAGS}"
-LIBS="${BOOST_LDFLAGS} ${BOOST_UNIT_TEST_FRAMEWORK_LIB} ${LIBS}"
-CPPFLAGS="${BOOST_CPPFLAGS} ${CPPFLAGS}"
+LIBS="${OPM_BOOST_LDFLAGS} ${BOOST_UNIT_TEST_FRAMEWORK_LIB} ${LIBS}"
+CPPFLAGS="${OPM_BOOST_CPPFLAGS} ${CPPFLAGS}"
AC_LANG_PUSH([C++])
@@ -66,12 +66,12 @@ AC_CACHE_CHECK([if the Boost.Test library can be linked dynamically],dnl
AC_LANG_POP([C++])
-LIBS="$_opm_LIBS_SAVE"
-CPPFLAGS="$_opm_CPPFLAGS_SAVE"
+LIBS="${_opm_LIBS_SAVE}"
+CPPFLAGS="${_opm_CPPFLAGS_SAVE}"
-AS_IF([test x"$opm_cv_boost_link_static" = x"yes" -o \
- x"$opm_cv_boost_link_dynamic" = x"yes"],
-[AS_IF([test x"$opm_cv_boost_link_dynamic" = x"yes"],
+AS_IF([test x"${opm_cv_boost_link_static}" = x"yes" -o \
+ x"${opm_cv_boost_link_dynamic}" = x"yes"],
+[AS_IF([test x"${opm_cv_boost_link_dynamic}" = x"yes"],
[AC_DEFINE([HAVE_DYNAMIC_BOOST_TEST], [1],
[Define to `1' if Boost.Test should use BOOST_TEST_DYN_LINK])]
[:])[]dnl
diff --git a/opm/core/GridManager.cpp b/opm/core/GridManager.cpp
index f84692ee..d286e504 100644
--- a/opm/core/GridManager.cpp
+++ b/opm/core/GridManager.cpp
@@ -22,6 +22,8 @@
#include
#include
#include
+#include
+#include
@@ -33,14 +35,26 @@ namespace Opm
/// Construct a 3d corner-point grid from a deck.
GridManager::GridManager(const Opm::EclipseGridParser& deck)
{
- // Collect in input struct for preprocessing.
- struct grdecl grdecl = deck.get_grdecl();
-
- // Process grid.
- ug_ = create_grid_cornerpoint(&grdecl, 0.0);
- if (!ug_) {
- THROW("Failed to construct grid.");
- }
+ // We accept two different ways to specify the grid.
+ // 1. Corner point format.
+ // Requires ZCORN, COORDS, DIMENS or SPECGRID, optionally
+ // ACTNUM, optionally MAPAXES.
+ // For this format, we will verify that DXV, DYV, DZV,
+ // DEPTHZ and TOPS are not present.
+ // 2. Tensor grid format.
+ // Requires DXV, DYV, DZV, optionally DEPTHZ or TOPS.
+ // For this format, we will verify that ZCORN, COORDS
+ // and ACTNUM are not present.
+ // Note that for TOPS, we only allow a uniform vector of values.
+
+ if (deck.hasField("ZCORN") && deck.hasField("COORD")) {
+ initFromDeckCornerpoint(deck);
+ } else if (deck.hasField("DXV") && deck.hasField("DYV") && deck.hasField("DZV")) {
+ initFromDeckTensorgrid(deck);
+ } else {
+ THROW("Could not initialize grid from deck. "
+ "Need either ZCORN + COORD or DXV + DYV + DZV keywords.");
+ }
}
@@ -102,5 +116,94 @@ namespace Opm
+ // Construct corner-point grid from deck.
+ void GridManager::initFromDeckCornerpoint(const Opm::EclipseGridParser& deck)
+ {
+ // Extract data from deck.
+ // Collect in input struct for preprocessing.
+ struct grdecl grdecl = deck.get_grdecl();
+
+ // Process grid.
+ ug_ = create_grid_cornerpoint(&grdecl, 0.0);
+ if (!ug_) {
+ THROW("Failed to construct grid.");
+ }
+ }
+
+
+ namespace
+ {
+ std::vector coordsFromDeltas(const std::vector& deltas)
+ {
+ std::vector coords(deltas.size() + 1);
+ coords[0] = 0.0;
+ std::partial_sum(deltas.begin(), deltas.end(), coords.begin() + 1);
+ return coords;
+ }
+ } // anonymous namespace
+
+
+ // Construct tensor grid from deck.
+ void GridManager::initFromDeckTensorgrid(const Opm::EclipseGridParser& deck)
+ {
+ // Extract logical cartesian size.
+ std::vector dims;
+ if (deck.hasField("DIMENS")) {
+ dims = deck.getIntegerValue("DIMENS");
+ } else if (deck.hasField("SPECGRID")) {
+ dims = deck.getSPECGRID().dimensions;
+ } else {
+ THROW("Deck must have either DIMENS or SPECGRID.");
+ }
+
+ // Extract coordinates (or offsets from top, in case of z).
+ const std::vector& dxv = deck.getFloatingPointValue("DXV");
+ const std::vector& dyv = deck.getFloatingPointValue("DYV");
+ const std::vector& dzv = deck.getFloatingPointValue("DZV");
+ std::vector x = coordsFromDeltas(dxv);
+ std::vector y = coordsFromDeltas(dyv);
+ std::vector z = coordsFromDeltas(dzv);
+
+ // Check that number of cells given are consistent with DIMENS/SPECGRID.
+ if (dims[0] != int(dxv.size())) {
+ THROW("Number of DXV data points do not match DIMENS or SPECGRID.");
+ }
+ if (dims[1] != int(dyv.size())) {
+ THROW("Number of DYV data points do not match DIMENS or SPECGRID.");
+ }
+ if (dims[2] != int(dzv.size())) {
+ THROW("Number of DZV data points do not match DIMENS or SPECGRID.");
+ }
+
+ // Extract top corner depths, if available.
+ const double* top_depths = 0;
+ std::vector top_depths_vec;
+ if (deck.hasField("DEPTHZ")) {
+ const std::vector& depthz = deck.getFloatingPointValue("DEPTHZ");
+ if (depthz.size() != x.size()*y.size()) {
+ THROW("Incorrect size of DEPTHZ: " << depthz.size());
+ }
+ top_depths = &depthz[0];
+ } else if (deck.hasField("TOPS")) {
+ // We only support constant values for TOPS.
+ // It is not 100% clear how we best can deal with
+ // varying TOPS (stair-stepping grid, or not).
+ const std::vector& tops = deck.getFloatingPointValue("TOPS");
+ if (std::count(tops.begin(), tops.end(), tops[0]) != int(tops.size())) {
+ THROW("We do not support nonuniform TOPS, please use ZCORN/COORDS instead.");
+ }
+ top_depths_vec.resize(x.size()*y.size(), tops[0]);
+ top_depths = &top_depths_vec[0];
+ }
+
+ // Construct grid.
+ ug_ = create_grid_tensor3d(dxv.size(), dyv.size(), dzv.size(),
+ &x[0], &y[0], &z[0], top_depths);
+ if (!ug_) {
+ THROW("Failed to construct grid.");
+ }
+ }
+
+
} // namespace Opm
diff --git a/opm/core/GridManager.hpp b/opm/core/GridManager.hpp
index 97dd84fd..26e335f2 100644
--- a/opm/core/GridManager.hpp
+++ b/opm/core/GridManager.hpp
@@ -33,39 +33,46 @@ namespace Opm
/// encapsulates creation and destruction of the grid.
/// The following grid types can be constructed:
/// - 3d corner-point grids (from deck input)
+ /// - 3d tensor grids (from deck input)
/// - 2d cartesian grids
/// - 3d cartesian grids
/// The resulting UnstructuredGrid is available through the c_grid() method.
class GridManager
{
public:
- /// Construct a 3d corner-point grid from a deck.
- GridManager(const Opm::EclipseGridParser& deck);
+ /// Construct a 3d corner-point grid or tensor grid from a deck.
+ GridManager(const Opm::EclipseGridParser& deck);
- /// Construct a 2d cartesian grid with cells of unit size.
- GridManager(int nx, int ny);
+ /// Construct a 2d cartesian grid with cells of unit size.
+ GridManager(int nx, int ny);
- /// Construct a 3d cartesian grid with cells of unit size.
- GridManager(int nx, int ny, int nz);
+ /// Construct a 3d cartesian grid with cells of unit size.
+ GridManager(int nx, int ny, int nz);
- /// Construct a 3d cartesian grid with cells of size [dx, dy, dz].
- GridManager(int nx, int ny, int nz,
- double dx, double dy, double dz);
+ /// Construct a 3d cartesian grid with cells of size [dx, dy, dz].
+ GridManager(int nx, int ny, int nz,
+ double dx, double dy, double dz);
- /// Destructor.
- ~GridManager();
+ /// Destructor.
+ ~GridManager();
- /// Access the managed UnstructuredGrid.
- /// The method is named similarly to c_str() in std::string,
- /// to make it clear that we are returning a C-compatible struct.
- const UnstructuredGrid* c_grid() const;
+ /// Access the managed UnstructuredGrid.
+ /// The method is named similarly to c_str() in std::string,
+ /// to make it clear that we are returning a C-compatible struct.
+ const UnstructuredGrid* c_grid() const;
private:
- // Disable copying and assignment.
- GridManager(const GridManager& other);
- GridManager& operator=(const GridManager& other);
- // The managed UnstructuredGrid.
- UnstructuredGrid* ug_;
+ // Disable copying and assignment.
+ GridManager(const GridManager& other);
+ GridManager& operator=(const GridManager& other);
+
+ // Construct corner-point grid from deck.
+ void initFromDeckCornerpoint(const Opm::EclipseGridParser& deck);
+ // Construct tensor grid from deck.
+ void initFromDeckTensorgrid(const Opm::EclipseGridParser& deck);
+
+ // The managed UnstructuredGrid.
+ UnstructuredGrid* ug_;
};
} // namespace Opm
diff --git a/opm/core/eclipse/EclipseGridParser.cpp b/opm/core/eclipse/EclipseGridParser.cpp
index d582a996..9b0352b2 100644
--- a/opm/core/eclipse/EclipseGridParser.cpp
+++ b/opm/core/eclipse/EclipseGridParser.cpp
@@ -96,7 +96,7 @@ namespace EclipseKeywords
string("MULTPV"), string("PRESSURE"), string("SGAS"),
string("SWAT"), string("SOIL"), string("RS"),
string("DXV"), string("DYV"), string("DZV"),
- string("DEPTHZ"), string("MAPAXES")
+ string("DEPTHZ"), string("TOPS"), string("MAPAXES")
};
const int num_floating_fields = sizeof(floating_fields) / sizeof(floating_fields[0]);
@@ -201,21 +201,7 @@ namespace {
return us;
}
- inline std::string readKeyword(std::istream& is)
- {
- std::string keyword_candidate;
- while (!is.eof()) {
- is >> keyword_candidate;
- if(keyword_candidate.find("--") == 0) {
- is >> ignoreLine; // This line is a comment
- } else {
- return upcase(keyword_candidate);
- }
- }
- return "CONTINUE"; // Last line in included file is a comment
- }
-
- inline bool readKeywordNew(std::istream& is, std::string& keyword)
+ inline bool readKeyword(std::istream& is, std::string& keyword)
{
char buf[9];
int i, j;
@@ -387,7 +373,7 @@ void EclipseGridParser::readImpl(istream& is)
std::string keyword;
while (is.good()) {
is >> ignoreWhitespace;
- bool ok = readKeywordNew(is, keyword);
+ bool ok = readKeyword(is, keyword);
if (ok) {
//#ifdef VERBOSE
cout << "Keyword found: " << keyword << endl;
@@ -549,9 +535,9 @@ void EclipseGridParser::convertToSI()
// Find the right unit.
double unit = 1e100;
bool do_convert = true;
- if (key == "COORD" || key == "ZCORN" ||
- key == "DXV" || key == "DYV" || key == "DZV" ||
- key == "DEPTHZ") {
+ if (key == "COORD" || key == "ZCORN" ||
+ key == "DXV" || key == "DYV" || key == "DZV" ||
+ key == "DEPTHZ" || key == "TOPS") {
unit = units_.length;
} else if (key == "PERMX" || key == "PERMY" || key == "PERMZ" ||
key == "PERMXX" || key == "PERMYY" || key == "PERMZZ" ||
diff --git a/opm/core/eclipse/EclipseGridParser.hpp b/opm/core/eclipse/EclipseGridParser.hpp
index 31195e77..98942375 100644
--- a/opm/core/eclipse/EclipseGridParser.hpp
+++ b/opm/core/eclipse/EclipseGridParser.hpp
@@ -136,47 +136,47 @@ public:
{ return dynamic_cast(*getSpecialValue(#keyword)); }
// Support for special fields.
- SPECIAL_FIELD(SPECGRID);
- SPECIAL_FIELD(FAULTS);
- SPECIAL_FIELD(MULTFLT);
- SPECIAL_FIELD(TITLE);
- SPECIAL_FIELD(START);
- SPECIAL_FIELD(DATES);
- SPECIAL_FIELD(DENSITY);
- SPECIAL_FIELD(PVDG);
- SPECIAL_FIELD(PVDO);
- SPECIAL_FIELD(PVTG);
- SPECIAL_FIELD(PVTO);
- SPECIAL_FIELD(PVTW);
- SPECIAL_FIELD(SGOF);
- SPECIAL_FIELD(SWOF);
- SPECIAL_FIELD(ROCK);
- SPECIAL_FIELD(ROCKTAB);
- SPECIAL_FIELD(WELSPECS);
- SPECIAL_FIELD(COMPDAT);
- SPECIAL_FIELD(WCONINJE);
- SPECIAL_FIELD(WCONPROD);
- SPECIAL_FIELD(WELTARG);
- SPECIAL_FIELD(WELOPEN);
- SPECIAL_FIELD(EQUIL);
- SPECIAL_FIELD(PVCDO);
- SPECIAL_FIELD(TSTEP);
- SPECIAL_FIELD(PLYVISC);
- SPECIAL_FIELD(PLYROCK);
- SPECIAL_FIELD(PLYADS);
- SPECIAL_FIELD(PLYMAX);
- SPECIAL_FIELD(TLMIXPAR);
- SPECIAL_FIELD(WPOLYMER);
- SPECIAL_FIELD(GRUPTREE);
- SPECIAL_FIELD(GCONINJE);
- SPECIAL_FIELD(GCONPROD);
- SPECIAL_FIELD(WGRUPCON);
+ SPECIAL_FIELD(SPECGRID)
+ SPECIAL_FIELD(FAULTS)
+ SPECIAL_FIELD(MULTFLT)
+ SPECIAL_FIELD(TITLE)
+ SPECIAL_FIELD(START)
+ SPECIAL_FIELD(DATES)
+ SPECIAL_FIELD(DENSITY)
+ SPECIAL_FIELD(PVDG)
+ SPECIAL_FIELD(PVDO)
+ SPECIAL_FIELD(PVTG)
+ SPECIAL_FIELD(PVTO)
+ SPECIAL_FIELD(PVTW)
+ SPECIAL_FIELD(SGOF)
+ SPECIAL_FIELD(SWOF)
+ SPECIAL_FIELD(ROCK)
+ SPECIAL_FIELD(ROCKTAB)
+ SPECIAL_FIELD(WELSPECS)
+ SPECIAL_FIELD(COMPDAT)
+ SPECIAL_FIELD(WCONINJE)
+ SPECIAL_FIELD(WCONPROD)
+ SPECIAL_FIELD(WELTARG)
+ SPECIAL_FIELD(WELOPEN)
+ SPECIAL_FIELD(EQUIL)
+ SPECIAL_FIELD(PVCDO)
+ SPECIAL_FIELD(TSTEP)
+ SPECIAL_FIELD(PLYVISC)
+ SPECIAL_FIELD(PLYROCK)
+ SPECIAL_FIELD(PLYADS)
+ SPECIAL_FIELD(PLYMAX)
+ SPECIAL_FIELD(TLMIXPAR)
+ SPECIAL_FIELD(WPOLYMER)
+ SPECIAL_FIELD(GRUPTREE)
+ SPECIAL_FIELD(GCONINJE)
+ SPECIAL_FIELD(GCONPROD)
+ SPECIAL_FIELD(WGRUPCON)
// The following fields only have a dummy implementation
// that allows us to ignore them.
- SPECIAL_FIELD(SWFN);
- SPECIAL_FIELD(SOF2);
- SPECIAL_FIELD(TUNING);
+ SPECIAL_FIELD(SWFN)
+ SPECIAL_FIELD(SOF2)
+ SPECIAL_FIELD(TUNING)
#undef SPECIAL_FIELD
diff --git a/opm/core/eclipse/SpecialEclipseFields.hpp b/opm/core/eclipse/SpecialEclipseFields.hpp
index 7e2fce9a..a8a1ba11 100644
--- a/opm/core/eclipse/SpecialEclipseFields.hpp
+++ b/opm/core/eclipse/SpecialEclipseFields.hpp
@@ -780,9 +780,11 @@ struct WelspecsLine
int fluids_in_place_reg_numb_; // Fluids in place region number
WelspecsLine() :
- datum_depth_BHP_(-1.0), drain_rad_(0.0), spec_inflow_("STD"),
- shut_in_("SHUT"), crossflow_("YES"), pressure_table_number_(0),
- density_calc_type_("SEG"), fluids_in_place_reg_numb_(0)
+ name_(), group_(), I_(-1), J_(-1),
+ datum_depth_BHP_(-1.0), pref_phase_(), drain_rad_(0.0),
+ spec_inflow_("STD"), shut_in_("SHUT"), crossflow_("YES"),
+ pressure_table_number_(0), density_calc_type_("SEG"),
+ fluids_in_place_reg_numb_(0)
{}
};
@@ -1360,8 +1362,8 @@ struct WgrupconLine
bool available_for_group_control_;
double guide_rate_;
std::string phase_;
- WgrupconLine() :
- available_for_group_control_(true)
+ WgrupconLine()
+ : well_(), available_for_group_control_(true), guide_rate_(-1.0), phase_()
{
}
};
@@ -1580,6 +1582,7 @@ struct WeltargLine
double new_value_; // New value of this quantity
WeltargLine()
+ : well_(), control_change_(), new_value_(-1.0)
{
}
};
@@ -1739,6 +1742,13 @@ struct EquilLine
// initial fluids in place calculation.
EquilLine()
{
+ datum_depth_ = datum_depth_pressure_ = 0.0;
+ water_oil_contact_depth_ = oil_water_cap_pressure_ = 0.0;
+ gas_oil_contact_depth_ = gas_oil_cap_pressure_ = 0.0;
+
+ live_oil_table_index_ = 0;
+ wet_gas_table_index_ = 0;
+ N_ = 0;
}
};
@@ -2128,7 +2138,8 @@ struct WpolymerLine
WpolymerLine()
{
- well_ = polymer_group_ = salt_group_ = "";
+ well_ = polymer_group_ = salt_group_ = "";
+ polymer_concentration_ = salt_concentration_ = 0.0;
}
};
diff --git a/opm/core/fluid/BlackoilPropertiesBasic.cpp b/opm/core/fluid/BlackoilPropertiesBasic.cpp
index be8211c1..2496d98e 100644
--- a/opm/core/fluid/BlackoilPropertiesBasic.cpp
+++ b/opm/core/fluid/BlackoilPropertiesBasic.cpp
@@ -26,20 +26,20 @@ namespace Opm
{
BlackoilPropertiesBasic::BlackoilPropertiesBasic(const parameter::ParameterGroup& param,
- const int dim,
- const int num_cells)
+ const int dim,
+ const int num_cells)
{
- double poro = param.getDefault("porosity", 1.0);
- using namespace Opm::unit;
- using namespace Opm::prefix;
- double perm = param.getDefault("permeability", 100.0)*milli*darcy;
+ double poro = param.getDefault("porosity", 1.0);
+ using namespace Opm::unit;
+ using namespace Opm::prefix;
+ double perm = param.getDefault("permeability", 100.0)*milli*darcy;
rock_.init(dim, num_cells, poro, perm);
- pvt_.init(param);
+ pvt_.init(param);
satprops_.init(param);
- if (pvt_.numPhases() != satprops_.numPhases()) {
- THROW("BlackoilPropertiesBasic::BlackoilPropertiesBasic() - Inconsistent number of phases in pvt data ("
- << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ").");
- }
+ if (pvt_.numPhases() != satprops_.numPhases()) {
+ THROW("BlackoilPropertiesBasic::BlackoilPropertiesBasic() - Inconsistent number of phases in pvt data ("
+ << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ").");
+ }
}
BlackoilPropertiesBasic::~BlackoilPropertiesBasic()
@@ -90,11 +90,11 @@ namespace Opm
/// \param[out] dmudp If non-null: array of nP viscosity derivative values,
/// array must be valid before calling.
void BlackoilPropertiesBasic::viscosity(const int n,
- const double* p,
- const double* z,
- const int* /*cells*/,
- double* mu,
- double* dmudp) const
+ const double* p,
+ const double* z,
+ const int* /*cells*/,
+ double* mu,
+ double* dmudp) const
{
if (dmudp) {
THROW("BlackoilPropertiesBasic::viscosity() -- derivatives of viscosity not yet implemented.");
@@ -114,16 +114,16 @@ namespace Opm
/// array must be valid before calling. The matrices are output
/// in Fortran order.
void BlackoilPropertiesBasic::matrix(const int n,
- const double* /*p*/,
- const double* /*z*/,
- const int* /*cells*/,
- double* A,
- double* dAdp) const
+ const double* /*p*/,
+ const double* /*z*/,
+ const int* /*cells*/,
+ double* A,
+ double* dAdp) const
{
- const int np = numPhases();
- ASSERT(np <= 2);
- double B[2]; // Must be enough since component classes do not handle more than 2.
- pvt_.B(1, 0, 0, B);
+ const int np = numPhases();
+ ASSERT(np <= 2);
+ double B[2]; // Must be enough since component classes do not handle more than 2.
+ pvt_.B(1, 0, 0, B);
// Compute A matrix
// #pragma omp parallel for
for (int i = 0; i < n; ++i) {
@@ -152,8 +152,8 @@ namespace Opm
/// of a call to the method matrix().
/// \param[out] rho Array of nP density values, array must be valid before calling.
void BlackoilPropertiesBasic::density(const int n,
- const double* A,
- double* rho) const
+ const double* A,
+ double* rho) const
{
const int np = numPhases();
const double* sdens = pvt_.surfaceDensities();
@@ -186,10 +186,10 @@ namespace Opm
/// m_{ij} = \frac{dkr_i}{ds^j},
/// and is output in Fortran order (m_00 m_10 m_20 m01 ...)
void BlackoilPropertiesBasic::relperm(const int n,
- const double* s,
- const int* /*cells*/,
- double* kr,
- double* dkrds) const
+ const double* s,
+ const int* /*cells*/,
+ double* kr,
+ double* dkrds) const
{
satprops_.relperm(n, s, kr, dkrds);
}
@@ -205,10 +205,10 @@ namespace Opm
/// m_{ij} = \frac{dpc_i}{ds^j},
/// and is output in Fortran order (m_00 m_10 m_20 m01 ...)
void BlackoilPropertiesBasic::capPress(const int n,
- const double* s,
- const int* /*cells*/,
- double* pc,
- double* dpcds) const
+ const double* s,
+ const int* /*cells*/,
+ double* pc,
+ double* dpcds) const
{
satprops_.capPress(n, s, pc, dpcds);
}
@@ -226,7 +226,7 @@ namespace Opm
double* smin,
double* smax) const
{
- satprops_.satRange(n, smin, smax);
+ satprops_.satRange(n, smin, smax);
}
diff --git a/opm/core/fluid/BlackoilPropertiesBasic.hpp b/opm/core/fluid/BlackoilPropertiesBasic.hpp
index d879036e..44a76013 100644
--- a/opm/core/fluid/BlackoilPropertiesBasic.hpp
+++ b/opm/core/fluid/BlackoilPropertiesBasic.hpp
@@ -35,16 +35,16 @@ namespace Opm
{
public:
/// Construct from parameters.
- /// The following parameters are accepted (defaults):
- /// num_phases (2) Must be 1 or 2.
- /// relperm_func ("Linear") Must be "Constant", "Linear" or "Quadratic".
- /// rho1 [rho2, rho3] (1.0e3) Density in kg/m^3
- /// mu1 [mu2, mu3] (1.0) Viscosity in cP
- /// porosity (1.0) Porosity
- /// permeability (100.0) Permeability in mD
+ /// The following parameters are accepted (defaults):
+ /// num_phases (2) Must be 1 or 2.
+ /// relperm_func ("Linear") Must be "Constant", "Linear" or "Quadratic".
+ /// rho1 [rho2, rho3] (1.0e3) Density in kg/m^3
+ /// mu1 [mu2, mu3] (1.0) Viscosity in cP
+ /// porosity (1.0) Porosity
+ /// permeability (100.0) Permeability in mD
BlackoilPropertiesBasic(const parameter::ParameterGroup& param,
- const int dim,
- const int num_cells);
+ const int dim,
+ const int num_cells);
/// Destructor.
virtual ~BlackoilPropertiesBasic();
@@ -151,7 +151,7 @@ namespace Opm
double* dpcds) const;
- /// Obtain the range of allowable saturation values.
+/// Obtain the range of allowable saturation values.
/// In cell cells[i], saturation of phase p is allowed to be
/// in the interval [smin[i*P + p], smax[i*P + p]].
/// \param[in] n Number of data points.
diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp
index 0eb23cb0..e2457f39 100644
--- a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp
+++ b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp
@@ -18,20 +18,69 @@
*/
#include
+#include
namespace Opm
{
BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck(const EclipseGridParser& deck,
- const std::vector& global_cell)
+ const UnstructuredGrid& grid)
{
- rock_.init(deck, global_cell);
- pvt_.init(deck);
- satprops_.init(deck, global_cell);
- if (pvt_.numPhases() != satprops_.numPhases()) {
- THROW("BlackoilPropertiesBasic::BlackoilPropertiesBasic() - Inconsistent number of phases in pvt data ("
- << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ").");
- }
+ rock_.init(deck, grid);
+ pvt_.init(deck, 200);
+ SaturationPropsFromDeck* ptr
+ = new SaturationPropsFromDeck();
+ satprops_.reset(ptr);
+ ptr->init(deck, grid, 200);
+
+ if (pvt_.numPhases() != satprops_->numPhases()) {
+ THROW("BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck() - Inconsistent number of phases in pvt data ("
+ << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_->numPhases() << ").");
+ }
+ }
+
+ BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck(const EclipseGridParser& deck,
+ const UnstructuredGrid& grid,
+ const parameter::ParameterGroup& param)
+ {
+ rock_.init(deck, grid);
+ const int pvt_samples = param.getDefault("pvt_tab_size", 200);
+ pvt_.init(deck, pvt_samples);
+
+ // Unfortunate lack of pointer smartness here...
+ const int sat_samples = param.getDefault("sat_tab_size", 200);
+ std::string threephase_model = param.getDefault("threephase_model", "simple");
+ bool use_stone2 = (threephase_model == "stone2");
+ if (sat_samples > 1) {
+ if (use_stone2) {
+ SaturationPropsFromDeck* ptr
+ = new SaturationPropsFromDeck();
+ satprops_.reset(ptr);
+ ptr->init(deck, grid, sat_samples);
+ } else {
+ SaturationPropsFromDeck* ptr
+ = new SaturationPropsFromDeck();
+ satprops_.reset(ptr);
+ ptr->init(deck, grid, sat_samples);
+ }
+ } else {
+ if (use_stone2) {
+ SaturationPropsFromDeck* ptr
+ = new SaturationPropsFromDeck();
+ satprops_.reset(ptr);
+ ptr->init(deck, grid, sat_samples);
+ } else {
+ SaturationPropsFromDeck* ptr
+ = new SaturationPropsFromDeck();
+ satprops_.reset(ptr);
+ ptr->init(deck, grid, sat_samples);
+ }
+ }
+
+ if (pvt_.numPhases() != satprops_->numPhases()) {
+ THROW("BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck() - Inconsistent number of phases in pvt data ("
+ << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_->numPhases() << ").");
+ }
}
BlackoilPropertiesFromDeck::~BlackoilPropertiesFromDeck()
@@ -235,7 +284,7 @@ namespace Opm
double* kr,
double* dkrds) const
{
- satprops_.relperm(n, s, cells, kr, dkrds);
+ satprops_->relperm(n, s, cells, kr, dkrds);
}
@@ -254,7 +303,7 @@ namespace Opm
double* pc,
double* dpcds) const
{
- satprops_.capPress(n, s, cells, pc, dpcds);
+ satprops_->capPress(n, s, cells, pc, dpcds);
}
@@ -270,7 +319,7 @@ namespace Opm
double* smin,
double* smax) const
{
- satprops_.satRange(n, cells, smin, smax);
+ satprops_->satRange(n, cells, smin, smax);
}
diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp
index 9c20b568..eb8b947b 100644
--- a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp
+++ b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp
@@ -26,6 +26,10 @@
#include
#include
#include
+#include
+#include
+
+struct UnstructuredGrid;
namespace Opm
{
@@ -35,12 +39,28 @@ namespace Opm
class BlackoilPropertiesFromDeck : public BlackoilPropertiesInterface
{
public:
- /// Construct from deck and cell mapping.
- /// \param deck eclipse input parser
- /// \param global_cell mapping from cell indices (typically from a processed grid)
+ /// Initialize from deck and grid.
+ /// \param[in] deck Deck input parser
+ /// \param[in] grid Grid to which property object applies, needed for the
+ /// mapping from cell indices (typically from a processed grid)
/// to logical cartesian indices consistent with the deck.
BlackoilPropertiesFromDeck(const EclipseGridParser& deck,
- const std::vector& global_cell);
+ const UnstructuredGrid& grid);
+
+ /// Initialize from deck, grid and parameters.
+ /// \param[in] deck Deck input parser
+ /// \param[in] grid Grid to which property object applies, needed for the
+ /// mapping from cell indices (typically from a processed grid)
+ /// to logical cartesian indices consistent with the deck.
+ /// \param[in] param Parameters. Accepted parameters include:
+ /// pvt_tab_size (200) number of uniform sample points for dead-oil pvt tables.
+ /// sat_tab_size (200) number of uniform sample points for saturation tables.
+ /// threephase_model("simple") three-phase relperm model (accepts "simple" and "stone2").
+ /// For both size parameters, a 0 or negative value indicates that no spline fitting is to
+ /// be done, and the input fluid data used directly for linear interpolation.
+ BlackoilPropertiesFromDeck(const EclipseGridParser& deck,
+ const UnstructuredGrid& grid,
+ const parameter::ParameterGroup& param);
/// Destructor.
virtual ~BlackoilPropertiesFromDeck();
@@ -147,9 +167,9 @@ namespace Opm
double* dpcds) const;
- /// Obtain the range of allowable saturation values.
- /// In cell cells[i], saturation of phase p is allowed to be
- /// in the interval [smin[i*P + p], smax[i*P + p]].
+ /// Obtain the range of allowable saturation values.
+ /// In cell cells[i], saturation of phase p is allowed to be
+ /// in the interval [smin[i*P + p], smax[i*P + p]].
/// \param[in] n Number of data points.
/// \param[in] cells Array of n cell indices.
/// \param[out] smin Array of nP minimum s values, array must be valid before calling.
@@ -162,7 +182,7 @@ namespace Opm
private:
RockFromDeck rock_;
BlackoilPvtProperties pvt_;
- SaturationPropsFromDeck satprops_;
+ boost::scoped_ptr satprops_;
mutable std::vector B_;
mutable std::vector dB_;
mutable std::vector R_;
diff --git a/opm/core/fluid/BlackoilPropertiesInterface.hpp b/opm/core/fluid/BlackoilPropertiesInterface.hpp
index dd8a857f..501c8a40 100644
--- a/opm/core/fluid/BlackoilPropertiesInterface.hpp
+++ b/opm/core/fluid/BlackoilPropertiesInterface.hpp
@@ -138,9 +138,9 @@ namespace Opm
double* dpcds) const = 0;
- /// Obtain the range of allowable saturation values.
- /// In cell cells[i], saturation of phase p is allowed to be
- /// in the interval [smin[i*P + p], smax[i*P + p]].
+ /// Obtain the range of allowable saturation values.
+ /// In cell cells[i], saturation of phase p is allowed to be
+ /// in the interval [smin[i*P + p], smax[i*P + p]].
/// \param[in] n Number of data points.
/// \param[in] cells Array of n cell indices.
/// \param[out] smin Array of nP minimum s values, array must be valid before calling.
diff --git a/opm/core/fluid/IncompPropertiesBasic.cpp b/opm/core/fluid/IncompPropertiesBasic.cpp
index 0ce3c88a..ab68017c 100644
--- a/opm/core/fluid/IncompPropertiesBasic.cpp
+++ b/opm/core/fluid/IncompPropertiesBasic.cpp
@@ -28,22 +28,22 @@ namespace Opm
{
IncompPropertiesBasic::IncompPropertiesBasic(const parameter::ParameterGroup& param,
- const int dim,
- const int num_cells)
+ const int dim,
+ const int num_cells)
{
- double poro = param.getDefault("porosity", 1.0);
- using namespace Opm::unit;
- using namespace Opm::prefix;
- double perm = param.getDefault("permeability", 100.0)*milli*darcy;
+ double poro = param.getDefault("porosity", 1.0);
+ using namespace Opm::unit;
+ using namespace Opm::prefix;
+ double perm = param.getDefault("permeability", 100.0)*milli*darcy;
rock_.init(dim, num_cells, poro, perm);
- pvt_.init(param);
+ pvt_.init(param);
satprops_.init(param);
- if (pvt_.numPhases() != satprops_.numPhases()) {
- THROW("IncompPropertiesBasic::IncompPropertiesBasic() - Inconsistent number of phases in pvt data ("
- << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ").");
- }
- viscosity_.resize(pvt_.numPhases());
- pvt_.mu(1, 0, 0, &viscosity_[0]);
+ if (pvt_.numPhases() != satprops_.numPhases()) {
+ THROW("IncompPropertiesBasic::IncompPropertiesBasic() - Inconsistent number of phases in pvt data ("
+ << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ").");
+ }
+ viscosity_.resize(pvt_.numPhases());
+ pvt_.mu(1, 0, 0, &viscosity_[0]);
}
IncompPropertiesBasic::IncompPropertiesBasic(const int num_phases,
@@ -56,14 +56,14 @@ namespace Opm
const int num_cells)
{
rock_.init(dim, num_cells, por, perm);
- pvt_.init(num_phases, rho, mu);
+ pvt_.init(num_phases, rho, mu);
satprops_.init(num_phases, relpermfunc);
- if (pvt_.numPhases() != satprops_.numPhases()) {
- THROW("IncompPropertiesBasic::IncompPropertiesBasic() - Inconsistent number of phases in pvt data ("
- << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ").");
- }
- viscosity_.resize(pvt_.numPhases());
- pvt_.mu(1, 0, 0, &viscosity_[0]);
+ if (pvt_.numPhases() != satprops_.numPhases()) {
+ THROW("IncompPropertiesBasic::IncompPropertiesBasic() - Inconsistent number of phases in pvt data ("
+ << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ").");
+ }
+ viscosity_.resize(pvt_.numPhases());
+ pvt_.mu(1, 0, 0, &viscosity_[0]);
}
IncompPropertiesBasic::~IncompPropertiesBasic()
@@ -109,7 +109,7 @@ namespace Opm
/// \return Array of P viscosity values.
const double* IncompPropertiesBasic::viscosity() const
{
- return &viscosity_[0];
+ return &viscosity_[0];
}
/// \return Array of P density values.
@@ -117,7 +117,7 @@ namespace Opm
{
// No difference between reservoir and surface densities
// modelled by this class.
- return pvt_.surfaceDensities();
+ return pvt_.surfaceDensities();
}
/// \return Array of P density values.
@@ -125,7 +125,7 @@ namespace Opm
{
// No difference between reservoir and surface densities
// modelled by this class.
- return pvt_.surfaceDensities();
+ return pvt_.surfaceDensities();
}
/// \param[in] n Number of data points.
@@ -138,10 +138,10 @@ namespace Opm
/// m_{ij} = \frac{dkr_i}{ds^j},
/// and is output in Fortran order (m_00 m_10 m_20 m_01 ...)
void IncompPropertiesBasic::relperm(const int n,
- const double* s,
- const int* /*cells*/,
- double* kr,
- double* dkrds) const
+ const double* s,
+ const int* /*cells*/,
+ double* kr,
+ double* dkrds) const
{
satprops_.relperm(n, s, kr, dkrds);
}
@@ -157,10 +157,10 @@ namespace Opm
/// m_{ij} = \frac{dpc_i}{ds^j},
/// and is output in Fortran order (m_00 m_10 m_20 m_01 ...)
void IncompPropertiesBasic::capPress(const int n,
- const double* s,
- const int* /*cells*/,
- double* pc,
- double* dpcds) const
+ const double* s,
+ const int* /*cells*/,
+ double* pc,
+ double* dpcds) const
{
satprops_.capPress(n, s, pc, dpcds);
}
@@ -174,11 +174,11 @@ namespace Opm
/// \param[out] smin Array of nP minimum s values, array must be valid before calling.
/// \param[out] smax Array of nP maximum s values, array must be valid before calling.
void IncompPropertiesBasic::satRange(const int n,
- const int* /*cells*/,
- double* smin,
- double* smax) const
+ const int* /*cells*/,
+ double* smin,
+ double* smax) const
{
- satprops_.satRange(n, smin, smax);
+ satprops_.satRange(n, smin, smax);
}
} // namespace Opm
diff --git a/opm/core/fluid/IncompPropertiesBasic.hpp b/opm/core/fluid/IncompPropertiesBasic.hpp
index b90b0876..72c39b1b 100644
--- a/opm/core/fluid/IncompPropertiesBasic.hpp
+++ b/opm/core/fluid/IncompPropertiesBasic.hpp
@@ -42,29 +42,29 @@ namespace Opm
{
public:
/// Construct from parameters.
- /// The following parameters are accepted (defaults):
- /// num_phases (2) Must be 1 or 2.
- /// relperm_func ("Linear") Must be "Constant", "Linear" or "Quadratic".
- /// rho1 [rho2, rho3] (1.0e3) Density in kg/m^3
- /// mu1 [mu2, mu3] (1.0) Viscosity in cP
- /// porosity (1.0) Porosity
- /// permeability (100.0) Permeability in mD
+ /// The following parameters are accepted (defaults):
+ /// num_phases (2) Must be 1 or 2.
+ /// relperm_func ("Linear") Must be "Constant", "Linear" or "Quadratic".
+ /// rho1 [rho2, rho3] (1.0e3) Density in kg/m^3
+ /// mu1 [mu2, mu3] (1.0) Viscosity in cP
+ /// porosity (1.0) Porosity
+ /// permeability (100.0) Permeability in mD
IncompPropertiesBasic(const parameter::ParameterGroup& param,
- const int dim,
- const int num_cells);
+ const int dim,
+ const int num_cells);
/// Construct from arguments a basic two phase fluid.
IncompPropertiesBasic(const int num_phases,
const SaturationPropsBasic::RelPermFunc& relpermfunc,
const std::vector& rho,
- const std::vector& mu,
+ const std::vector& mu,
const double porosity,
const double permeability,
const int dim,
- const int num_cells);
+ const int num_cells);
- /// Destructor.
+ /// Destructor.
virtual ~IncompPropertiesBasic();
// ---- Rock interface ----
@@ -132,9 +132,9 @@ namespace Opm
double* dpcds) const;
- /// Obtain the range of allowable saturation values.
- /// In cell cells[i], saturation of phase p is allowed to be
- /// in the interval [smin[i*P + p], smax[i*P + p]].
+ /// Obtain the range of allowable saturation values.
+ /// In cell cells[i], saturation of phase p is allowed to be
+ /// in the interval [smin[i*P + p], smax[i*P + p]].
/// \param[in] n Number of data points.
/// \param[in] cells Array of n cell indices.
/// \param[out] smin Array of nP minimum s values, array must be valid before calling.
@@ -145,9 +145,9 @@ namespace Opm
double* smax) const;
private:
RockBasic rock_;
- PvtPropertiesBasic pvt_;
+ PvtPropertiesBasic pvt_;
SaturationPropsBasic satprops_;
- std::vector viscosity_;
+ std::vector viscosity_;
};
diff --git a/opm/core/fluid/IncompPropertiesFromDeck.cpp b/opm/core/fluid/IncompPropertiesFromDeck.cpp
index e61e13c8..9aa69098 100644
--- a/opm/core/fluid/IncompPropertiesFromDeck.cpp
+++ b/opm/core/fluid/IncompPropertiesFromDeck.cpp
@@ -27,15 +27,15 @@ namespace Opm
{
IncompPropertiesFromDeck::IncompPropertiesFromDeck(const EclipseGridParser& deck,
- const std::vector& global_cell)
+ const UnstructuredGrid& grid)
{
- rock_.init(deck, global_cell);
- pvt_.init(deck);
- satprops_.init(deck, global_cell);
- if (pvt_.numPhases() != satprops_.numPhases()) {
- THROW("IncompPropertiesFromDeck::IncompPropertiesFromDeck() - Inconsistent number of phases in pvt data ("
- << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ").");
- }
+ rock_.init(deck, grid);
+ pvt_.init(deck);
+ satprops_.init(deck, grid, 200);
+ if (pvt_.numPhases() != satprops_.numPhases()) {
+ THROW("IncompPropertiesFromDeck::IncompPropertiesFromDeck() - Inconsistent number of phases in pvt data ("
+ << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ").");
+ }
}
IncompPropertiesFromDeck::~IncompPropertiesFromDeck()
@@ -81,19 +81,19 @@ namespace Opm
/// \return Array of P viscosity values.
const double* IncompPropertiesFromDeck::viscosity() const
{
- return pvt_.viscosity();
+ return pvt_.viscosity();
}
/// \return Array of P density values.
const double* IncompPropertiesFromDeck::density() const
{
- return pvt_.reservoirDensities();
+ return pvt_.reservoirDensities();
}
/// \return Array of P density values.
const double* IncompPropertiesFromDeck::surfaceDensity() const
{
- return pvt_.surfaceDensities();
+ return pvt_.surfaceDensities();
}
/// \param[in] n Number of data points.
@@ -106,10 +106,10 @@ namespace Opm
/// m_{ij} = \frac{dkr_i}{ds^j},
/// and is output in Fortran order (m_00 m_10 m_20 m_01 ...)
void IncompPropertiesFromDeck::relperm(const int n,
- const double* s,
- const int* cells,
- double* kr,
- double* dkrds) const
+ const double* s,
+ const int* cells,
+ double* kr,
+ double* dkrds) const
{
satprops_.relperm(n, s, cells, kr, dkrds);
}
@@ -125,10 +125,10 @@ namespace Opm
/// m_{ij} = \frac{dpc_i}{ds^j},
/// and is output in Fortran order (m_00 m_10 m_20 m_01 ...)
void IncompPropertiesFromDeck::capPress(const int n,
- const double* s,
- const int* cells,
- double* pc,
- double* dpcds) const
+ const double* s,
+ const int* cells,
+ double* pc,
+ double* dpcds) const
{
satprops_.capPress(n, s, cells, pc, dpcds);
}
@@ -142,11 +142,11 @@ namespace Opm
/// \param[out] smin Array of nP minimum s values, array must be valid before calling.
/// \param[out] smax Array of nP maximum s values, array must be valid before calling.
void IncompPropertiesFromDeck::satRange(const int n,
- const int* cells,
- double* smin,
- double* smax) const
+ const int* cells,
+ double* smin,
+ double* smax) const
{
- satprops_.satRange(n, cells, smin, smax);
+ satprops_.satRange(n, cells, smin, smax);
}
} // namespace Opm
diff --git a/opm/core/fluid/IncompPropertiesFromDeck.hpp b/opm/core/fluid/IncompPropertiesFromDeck.hpp
index d17dd1b7..6680eaa4 100644
--- a/opm/core/fluid/IncompPropertiesFromDeck.hpp
+++ b/opm/core/fluid/IncompPropertiesFromDeck.hpp
@@ -26,6 +26,8 @@
#include
#include
+struct UnstructuredGrid;
+
namespace Opm
{
@@ -43,14 +45,15 @@ namespace Opm
class IncompPropertiesFromDeck : public IncompPropertiesInterface
{
public:
- /// Construct from deck and cell mapping.
- /// \param deck eclipse input parser
- /// \param global_cell mapping from cell indices (typically from a processed grid)
+ /// Initialize from deck and grid.
+ /// \param deck Deck input parser
+ /// \param grid Grid to which property object applies, needed for the
+ /// mapping from cell indices (typically from a processed grid)
/// to logical cartesian indices consistent with the deck.
IncompPropertiesFromDeck(const EclipseGridParser& deck,
- const std::vector& global_cell);
+ const UnstructuredGrid& grid);
- /// Destructor.
+ /// Destructor.
virtual ~IncompPropertiesFromDeck();
// ---- Rock interface ----
@@ -118,9 +121,9 @@ namespace Opm
double* dpcds) const;
- /// Obtain the range of allowable saturation values.
- /// In cell cells[i], saturation of phase p is allowed to be
- /// in the interval [smin[i*P + p], smax[i*P + p]].
+ /// Obtain the range of allowable saturation values.
+ /// In cell cells[i], saturation of phase p is allowed to be
+ /// in the interval [smin[i*P + p], smax[i*P + p]].
/// \param[in] n Number of data points.
/// \param[in] cells Array of n cell indices.
/// \param[out] smin Array of nP minimum s values, array must be valid before calling.
@@ -131,8 +134,8 @@ namespace Opm
double* smax) const;
private:
RockFromDeck rock_;
- PvtPropertiesIncompFromDeck pvt_;
- SaturationPropsFromDeck satprops_;
+ PvtPropertiesIncompFromDeck pvt_;
+ SaturationPropsFromDeck satprops_;
};
diff --git a/opm/core/fluid/IncompPropertiesInterface.hpp b/opm/core/fluid/IncompPropertiesInterface.hpp
index a5025e8a..4f8bfb51 100644
--- a/opm/core/fluid/IncompPropertiesInterface.hpp
+++ b/opm/core/fluid/IncompPropertiesInterface.hpp
@@ -109,9 +109,9 @@ namespace Opm
double* pc,
double* dpcds) const = 0;
- /// Obtain the range of allowable saturation values.
- /// In cell cells[i], saturation of phase p is allowed to be
- /// in the interval [smin[i*P + p], smax[i*P + p]].
+ /// Obtain the range of allowable saturation values.
+ /// In cell cells[i], saturation of phase p is allowed to be
+ /// in the interval [smin[i*P + p], smax[i*P + p]].
/// \param[in] n Number of data points.
/// \param[in] cells Array of n cell indices.
/// \param[out] smin Array of nP minimum s values, array must be valid before calling.
diff --git a/opm/core/fluid/PvtPropertiesBasic.cpp b/opm/core/fluid/PvtPropertiesBasic.cpp
index 3d7d7bb2..5220502a 100644
--- a/opm/core/fluid/PvtPropertiesBasic.cpp
+++ b/opm/core/fluid/PvtPropertiesBasic.cpp
@@ -34,41 +34,41 @@ namespace Opm
void PvtPropertiesBasic::init(const parameter::ParameterGroup& param)
{
- int num_phases = param.getDefault("num_phases", 2);
- if (num_phases > 3 || num_phases < 1) {
- THROW("PvtPropertiesBasic::init() illegal num_phases: " << num_phases);
- }
- density_.resize(num_phases);
- viscosity_.resize(num_phases);
- // We currently do not allow the user to set B.
- formation_volume_factor_.clear();
- formation_volume_factor_.resize(num_phases, 1.0);
+ int num_phases = param.getDefault("num_phases", 2);
+ if (num_phases > 3 || num_phases < 1) {
+ THROW("PvtPropertiesBasic::init() illegal num_phases: " << num_phases);
+ }
+ density_.resize(num_phases);
+ viscosity_.resize(num_phases);
+ // We currently do not allow the user to set B.
+ formation_volume_factor_.clear();
+ formation_volume_factor_.resize(num_phases, 1.0);
- // Setting mu and rho from parameters
- using namespace Opm::prefix;
- using namespace Opm::unit;
- const double kgpm3 = kilogram/cubic(meter);
- const double cP = centi*Poise;
- std::string rname[3] = { "rho1", "rho2", "rho3" };
- double rdefault[3] = { 1.0e3, 1.0e3, 1.0e3 };
- std::string vname[3] = { "mu1", "mu2", "mu3" };
- double vdefault[3] = { 1.0, 1.0, 1.0 };
- for (int phase = 0; phase < num_phases; ++phase) {
- density_[phase] = kgpm3*param.getDefault(rname[phase], rdefault[phase]);
- viscosity_[phase] = cP*param.getDefault(vname[phase], vdefault[phase]);
- }
+ // Setting mu and rho from parameters
+ using namespace Opm::prefix;
+ using namespace Opm::unit;
+ const double kgpm3 = kilogram/cubic(meter);
+ const double cP = centi*Poise;
+ std::string rname[3] = { "rho1", "rho2", "rho3" };
+ double rdefault[3] = { 1.0e3, 1.0e3, 1.0e3 };
+ std::string vname[3] = { "mu1", "mu2", "mu3" };
+ double vdefault[3] = { 1.0, 1.0, 1.0 };
+ for (int phase = 0; phase < num_phases; ++phase) {
+ density_[phase] = kgpm3*param.getDefault(rname[phase], rdefault[phase]);
+ viscosity_[phase] = cP*param.getDefault(vname[phase], vdefault[phase]);
+ }
}
void PvtPropertiesBasic::init(const int num_phases,
const std::vector& rho,
const std::vector& visc)
{
- if (num_phases > 3 || num_phases < 1) {
- THROW("PvtPropertiesBasic::init() illegal num_phases: " << num_phases);
- }
- // We currently do not allow the user to set B.
- formation_volume_factor_.clear();
- formation_volume_factor_.resize(num_phases, 1.0);
+ if (num_phases > 3 || num_phases < 1) {
+ THROW("PvtPropertiesBasic::init() illegal num_phases: " << num_phases);
+ }
+ // We currently do not allow the user to set B.
+ formation_volume_factor_.clear();
+ formation_volume_factor_.resize(num_phases, 1.0);
density_ = rho;
viscosity_ = visc;
}
@@ -87,69 +87,69 @@ namespace Opm
void PvtPropertiesBasic::mu(const int n,
- const double* /*p*/,
- const double* /*z*/,
- double* output_mu) const
+ const double* /*p*/,
+ const double* /*z*/,
+ double* output_mu) const
{
- const int np = numPhases();
+ const int np = numPhases();
for (int phase = 0; phase < np; ++phase) {
// #pragma omp parallel for
for (int i = 0; i < n; ++i) {
output_mu[np*i + phase] = viscosity_[phase];
}
- }
+ }
}
void PvtPropertiesBasic::B(const int n,
- const double* /*p*/,
- const double* /*z*/,
- double* output_B) const
+ const double* /*p*/,
+ const double* /*z*/,
+ double* output_B) const
{
- const int np = numPhases();
+ const int np = numPhases();
for (int phase = 0; phase < np; ++phase) {
// #pragma omp parallel for
for (int i = 0; i < n; ++i) {
output_B[np*i + phase] = formation_volume_factor_[phase];
}
- }
+ }
}
void PvtPropertiesBasic::dBdp(const int n,
- const double* /*p*/,
- const double* /*z*/,
- double* output_B,
- double* output_dBdp) const
+ const double* /*p*/,
+ const double* /*z*/,
+ double* output_B,
+ double* output_dBdp) const
{
- const int np = numPhases();
+ const int np = numPhases();
for (int phase = 0; phase < np; ++phase) {
// #pragma omp parallel for
for (int i = 0; i < n; ++i) {
output_B[np*i + phase] = formation_volume_factor_[phase];
output_dBdp[np*i + phase] = 0.0;
}
- }
+ }
}
void PvtPropertiesBasic::R(const int n,
- const double* /*p*/,
- const double* /*z*/,
- double* output_R) const
+ const double* /*p*/,
+ const double* /*z*/,
+ double* output_R) const
{
- const int np = numPhases();
- std::fill(output_R, output_R + n*np, 0.0);
+ const int np = numPhases();
+ std::fill(output_R, output_R + n*np, 0.0);
}
void PvtPropertiesBasic::dRdp(const int n,
- const double* /*p*/,
- const double* /*z*/,
- double* output_R,
- double* output_dRdp) const
+ const double* /*p*/,
+ const double* /*z*/,
+ double* output_R,
+ double* output_dRdp) const
{
- const int np = numPhases();
- std::fill(output_R, output_R + n*np, 0.0);
- std::fill(output_dRdp, output_dRdp + n*np, 0.0);
+ const int np = numPhases();
+ std::fill(output_R, output_R + n*np, 0.0);
+ std::fill(output_dRdp, output_dRdp + n*np, 0.0);
}
} // namespace Opm
diff --git a/opm/core/fluid/PvtPropertiesBasic.hpp b/opm/core/fluid/PvtPropertiesBasic.hpp
index d1a3e9f3..3e30e807 100644
--- a/opm/core/fluid/PvtPropertiesBasic.hpp
+++ b/opm/core/fluid/PvtPropertiesBasic.hpp
@@ -38,11 +38,11 @@ namespace Opm
PvtPropertiesBasic();
/// Initialize from parameters.
- /// The following parameters are accepted (defaults):
- /// num_phases (2) Must be 1, 2 or 3.
- /// rho1 [rho2, rho3] (1.0e3) Density in kg/m^3
- /// mu1 [mu2, mu3] (1.0) Viscosity in cP
- void init(const parameter::ParameterGroup& param);
+ /// The following parameters are accepted (defaults):
+ /// num_phases (2) Must be 1, 2 or 3.
+ /// rho1 [rho2, rho3] (1.0e3) Density in kg/m^3
+ /// mu1 [mu2, mu3] (1.0) Viscosity in cP
+ void init(const parameter::ParameterGroup& param);
/// Initialize from arguments.
/// Basic multi phase fluid pvt properties.
@@ -55,7 +55,7 @@ namespace Opm
/// Densities of stock components at surface conditions.
/// \return Array of size numPhases().
- const double* surfaceDensities() const;
+ const double* surfaceDensities() const;
/// Viscosity as a function of p and z.
void mu(const int n,
@@ -90,9 +90,9 @@ namespace Opm
double* output_dRdp) const;
private:
- std::vector density_;
- std::vector viscosity_;
- std::vector formation_volume_factor_;
+ std::vector density_;
+ std::vector viscosity_;
+ std::vector formation_volume_factor_;
};
}
diff --git a/opm/core/fluid/PvtPropertiesIncompFromDeck.cpp b/opm/core/fluid/PvtPropertiesIncompFromDeck.cpp
index 62cc1b23..34a4ba00 100644
--- a/opm/core/fluid/PvtPropertiesIncompFromDeck.cpp
+++ b/opm/core/fluid/PvtPropertiesIncompFromDeck.cpp
@@ -38,54 +38,54 @@ namespace Opm
{
typedef std::vector > > table_t;
// If we need multiple regions, this class and the SinglePvt* classes must change.
- int region_number = 0;
+ int region_number = 0;
PhaseUsage phase_usage = phaseUsageFromDeck(deck);
- if (phase_usage.phase_used[PhaseUsage::Vapour] ||
- !phase_usage.phase_used[PhaseUsage::Aqua] ||
- !phase_usage.phase_used[PhaseUsage::Liquid]) {
- THROW("PvtPropertiesIncompFromDeck::init() -- must have gas and oil phases (only) in deck input.\n");
- }
+ if (phase_usage.phase_used[PhaseUsage::Vapour] ||
+ !phase_usage.phase_used[PhaseUsage::Aqua] ||
+ !phase_usage.phase_used[PhaseUsage::Liquid]) {
+ THROW("PvtPropertiesIncompFromDeck::init() -- must have gas and oil phases (only) in deck input.\n");
+ }
- // Surface densities. Accounting for different orders in eclipse and our code.
- if (deck.hasField("DENSITY")) {
- const std::vector& d = deck.getDENSITY().densities_[region_number];
- enum { ECL_oil = 0, ECL_water = 1, ECL_gas = 2 };
- surface_density_[phase_usage.phase_pos[PhaseUsage::Aqua]] = d[ECL_water];
- surface_density_[phase_usage.phase_pos[PhaseUsage::Liquid]] = d[ECL_oil];
- } else {
- THROW("Input is missing DENSITY\n");
- }
+ // Surface densities. Accounting for different orders in eclipse and our code.
+ if (deck.hasField("DENSITY")) {
+ const std::vector& d = deck.getDENSITY().densities_[region_number];
+ enum { ECL_oil = 0, ECL_water = 1, ECL_gas = 2 };
+ surface_density_[phase_usage.phase_pos[PhaseUsage::Aqua]] = d[ECL_water];
+ surface_density_[phase_usage.phase_pos[PhaseUsage::Liquid]] = d[ECL_oil];
+ } else {
+ THROW("Input is missing DENSITY\n");
+ }
// Make reservoir densities the same as surface densities initially.
// We will modify them with formation volume factors if found.
reservoir_density_ = surface_density_;
// Water viscosity.
- if (deck.hasField("PVTW")) {
- const std::vector& pvtw = deck.getPVTW().pvtw_[region_number];
- if (pvtw[2] != 0.0 || pvtw[4] != 0.0) {
- MESSAGE("Compressibility effects in PVTW are ignored.");
- }
+ if (deck.hasField("PVTW")) {
+ const std::vector& pvtw = deck.getPVTW().pvtw_[region_number];
+ if (pvtw[2] != 0.0 || pvtw[4] != 0.0) {
+ MESSAGE("Compressibility effects in PVTW are ignored.");
+ }
reservoir_density_[phase_usage.phase_pos[PhaseUsage::Aqua]] /= pvtw[1];
- viscosity_[phase_usage.phase_pos[PhaseUsage::Aqua]] = pvtw[3];
- } else {
- // Eclipse 100 default.
- // viscosity_[phase_usage.phase_pos[PhaseUsage::Aqua]] = 0.5*Opm::prefix::centi*Opm::unit::Poise;
- THROW("Input is missing PVTW\n");
- }
+ viscosity_[phase_usage.phase_pos[PhaseUsage::Aqua]] = pvtw[3];
+ } else {
+ // Eclipse 100 default.
+ // viscosity_[phase_usage.phase_pos[PhaseUsage::Aqua]] = 0.5*Opm::prefix::centi*Opm::unit::Poise;
+ THROW("Input is missing PVTW\n");
+ }
// Oil viscosity.
- if (deck.hasField("PVCDO")) {
- const std::vector& pvcdo = deck.getPVCDO().pvcdo_[region_number];
- if (pvcdo[2] != 0.0 || pvcdo[4] != 0.0) {
- MESSAGE("Compressibility effects in PVCDO are ignored.");
- }
+ if (deck.hasField("PVCDO")) {
+ const std::vector& pvcdo = deck.getPVCDO().pvcdo_[region_number];
+ if (pvcdo[2] != 0.0 || pvcdo[4] != 0.0) {
+ MESSAGE("Compressibility effects in PVCDO are ignored.");
+ }
reservoir_density_[phase_usage.phase_pos[PhaseUsage::Liquid]] /= pvcdo[1];
- viscosity_[phase_usage.phase_pos[PhaseUsage::Liquid]] = pvcdo[3];
- } else {
- THROW("Input is missing PVCDO\n");
- }
+ viscosity_[phase_usage.phase_pos[PhaseUsage::Liquid]] = pvcdo[3];
+ } else {
+ THROW("Input is missing PVCDO\n");
+ }
}
const double* PvtPropertiesIncompFromDeck::surfaceDensities() const
diff --git a/opm/core/fluid/PvtPropertiesIncompFromDeck.hpp b/opm/core/fluid/PvtPropertiesIncompFromDeck.hpp
index acbabaa4..01bbeed1 100644
--- a/opm/core/fluid/PvtPropertiesIncompFromDeck.hpp
+++ b/opm/core/fluid/PvtPropertiesIncompFromDeck.hpp
@@ -39,14 +39,14 @@ namespace Opm
PvtPropertiesIncompFromDeck();
/// Initialize from deck.
- void init(const EclipseGridParser& deck);
+ void init(const EclipseGridParser& deck);
/// Number of active phases.
int numPhases() const;
/// Densities of stock components at surface conditions.
/// \return Array of size numPhases().
- const double* surfaceDensities() const;
+ const double* surfaceDensities() const;
/// Densities of stock components at reservoir conditions.
/// Note: a reasonable question to ask is why there can be
@@ -58,15 +58,15 @@ namespace Opm
/// reporting and using data given in terms of surface values,
/// we need to handle this difference.
/// \return Array of size numPhases().
- const double* reservoirDensities() const;
+ const double* reservoirDensities() const;
/// Viscosities.
const double* viscosity() const;
private:
- std::tr1::array surface_density_;
- std::tr1::array reservoir_density_;
- std::tr1::array viscosity_;
+ std::tr1::array surface_density_;
+ std::tr1::array reservoir_density_;
+ std::tr1::array viscosity_;
};
}
diff --git a/opm/core/fluid/RockBasic.cpp b/opm/core/fluid/RockBasic.cpp
index a1423b76..b66cccce 100644
--- a/opm/core/fluid/RockBasic.cpp
+++ b/opm/core/fluid/RockBasic.cpp
@@ -25,29 +25,29 @@ namespace Opm
/// Default constructor.
RockBasic::RockBasic()
- : dimensions_(-1)
+ : dimensions_(-1)
{
}
/// Initialize with homogenous porosity and permeability.
void RockBasic::init(const int dimensions,
- const int num_cells,
- const double poro,
- const double perm)
+ const int num_cells,
+ const double poro,
+ const double perm)
{
- dimensions_ = dimensions;
- porosity_.clear();
- porosity_.resize(num_cells, poro);
- permeability_.clear();
- const int dsq = dimensions*dimensions;
- permeability_.resize(num_cells*dsq, 0.0);
+ dimensions_ = dimensions;
+ porosity_.clear();
+ porosity_.resize(num_cells, poro);
+ permeability_.clear();
+ const int dsq = dimensions*dimensions;
+ permeability_.resize(num_cells*dsq, 0.0);
// #pragma omp parallel for
- for (int i = 0; i < num_cells; ++i) {
- for (int d = 0; d < dimensions; ++d) {
- permeability_[dsq*i + dimensions*d + d] = perm;
- }
- }
+ for (int i = 0; i < num_cells; ++i) {
+ for (int d = 0; d < dimensions; ++d) {
+ permeability_[dsq*i + dimensions*d + d] = perm;
+ }
+ }
}
diff --git a/opm/core/fluid/RockBasic.hpp b/opm/core/fluid/RockBasic.hpp
index 96563780..2adc3ffd 100644
--- a/opm/core/fluid/RockBasic.hpp
+++ b/opm/core/fluid/RockBasic.hpp
@@ -35,9 +35,9 @@ namespace Opm
/// Initialize with homogenous porosity and permeability.
void init(const int dimensions,
- const int num_cells,
- const double poro,
- const double perm);
+ const int num_cells,
+ const double poro,
+ const double perm);
/// \return D, the number of spatial dimensions.
int numDimensions() const
@@ -66,7 +66,7 @@ namespace Opm
}
private:
- int dimensions_;
+ int dimensions_;
std::vector porosity_;
std::vector permeability_;
};
diff --git a/opm/core/fluid/RockCompressibility.cpp b/opm/core/fluid/RockCompressibility.cpp
index 17d86beb..af65d852 100644
--- a/opm/core/fluid/RockCompressibility.cpp
+++ b/opm/core/fluid/RockCompressibility.cpp
@@ -69,7 +69,8 @@ namespace Opm
const double cpnorm = rock_comp_*(pressure - pref_);
return (1.0 + cpnorm + 0.5*cpnorm*cpnorm);
} else {
- return Opm::linearInterpolation(p_, poromult_, pressure);
+ // return Opm::linearInterpolation(p_, poromult_, pressure);
+ return Opm::linearInterpolationExtrap(p_, poromult_, pressure);
}
}
@@ -78,8 +79,11 @@ namespace Opm
if (p_.empty()) {
return rock_comp_;
} else {
- const double poromult = Opm::linearInterpolation(p_, poromult_, pressure);
- const double dporomultdp = Opm::linearInterpolationDerivative(p_, poromult_, pressure);
+ //const double poromult = Opm::linearInterpolation(p_, poromult_, pressure);
+ //const double dporomultdp = Opm::linearInterpolationDerivative(p_, poromult_, pressure);
+ const double poromult = Opm::linearInterpolationExtrap(p_, poromult_, pressure);
+ const double dporomultdp = Opm::linearInterpolationDerivativeExtrap(p_, poromult_, pressure);
+
return dporomultdp/poromult;
}
}
diff --git a/opm/core/fluid/RockFromDeck.cpp b/opm/core/fluid/RockFromDeck.cpp
index 94777904..ec7db9a6 100644
--- a/opm/core/fluid/RockFromDeck.cpp
+++ b/opm/core/fluid/RockFromDeck.cpp
@@ -19,7 +19,7 @@
#include
-
+#include
#include
namespace Opm
@@ -36,8 +36,6 @@ namespace Opm
PermeabilityKind fillTensor(const EclipseGridParser& parser,
std::vector*>& tensor,
std::tr1::array& kmap);
-
- int numGlobalCells(const EclipseGridParser& parser);
} // anonymous namespace
@@ -53,28 +51,29 @@ namespace Opm
/// Initialize from deck and cell mapping.
/// \param deck Deck input parser
- /// \param global_cell mapping from cell indices (typically from a processed grid)
+ /// \param grid grid to which property object applies, needed for the
+ /// mapping from cell indices (typically from a processed grid)
/// to logical cartesian indices consistent with the deck.
void RockFromDeck::init(const EclipseGridParser& deck,
- const std::vector& global_cell)
+ const UnstructuredGrid& grid)
{
- assignPorosity(deck, global_cell);
- permfield_valid_.assign(global_cell.size(), false);
+ assignPorosity(deck, grid);
+ permfield_valid_.assign(grid.number_of_cells, false);
const double perm_threshold = 0.0; // Maybe turn into parameter?
- assignPermeability(deck, global_cell, perm_threshold);
+ assignPermeability(deck, grid, perm_threshold);
}
void RockFromDeck::assignPorosity(const EclipseGridParser& parser,
- const std::vector& global_cell)
+ const UnstructuredGrid& grid)
{
- porosity_.assign(global_cell.size(), 1.0);
-
+ porosity_.assign(grid.number_of_cells, 1.0);
+ const int* gc = grid.global_cell;
if (parser.hasField("PORO")) {
const std::vector& poro = parser.getFloatingPointValue("PORO");
-
for (int c = 0; c < int(porosity_.size()); ++c) {
- porosity_[c] = poro[global_cell[c]];
+ const int deck_pos = (gc == NULL) ? c : gc[c];
+ porosity_[c] = poro[deck_pos];
}
}
}
@@ -82,14 +81,16 @@ namespace Opm
void RockFromDeck::assignPermeability(const EclipseGridParser& parser,
- const std::vector& global_cell,
+ const UnstructuredGrid& grid,
double perm_threshold)
{
const int dim = 3;
- const int num_global_cells = numGlobalCells(parser);
+ const int num_global_cells = grid.cartdims[0]*grid.cartdims[1]*grid.cartdims[2];
+ const int nc = grid.number_of_cells;
+
ASSERT (num_global_cells > 0);
- permeability_.assign(dim * dim * global_cell.size(), 0.0);
+ permeability_.assign(dim * dim * nc, 0.0);
std::vector*> tensor;
tensor.reserve(10);
@@ -111,13 +112,13 @@ namespace Opm
// chosen) default value...
//
if (tensor.size() > 1) {
- const int nc = global_cell.size();
- int off = 0;
+ const int* gc = grid.global_cell;
+ int off = 0;
for (int c = 0; c < nc; ++c, off += dim*dim) {
// SharedPermTensor K(dim, dim, &permeability_[off]);
int kix = 0;
- const int glob = global_cell[c];
+ const int glob = (gc == NULL) ? c : gc[c];
for (int i = 0; i < dim; ++i) {
for (int j = 0; j < dim; ++j, ++kix) {
@@ -331,26 +332,6 @@ namespace Opm
return kind;
}
- int numGlobalCells(const EclipseGridParser& parser)
- {
- int ngc = -1;
-
- if (parser.hasField("DIMENS")) {
- const std::vector&
- dims = parser.getIntegerValue("DIMENS");
-
- ngc = dims[0] * dims[1] * dims[2];
- }
- else if (parser.hasField("SPECGRID")) {
- const SPECGRID& sgr = parser.getSPECGRID();
-
- ngc = sgr.dimensions[ 0 ];
- ngc *= sgr.dimensions[ 1 ];
- ngc *= sgr.dimensions[ 2 ];
- }
-
- return ngc;
- }
} // anonymous namespace
} // namespace Opm
diff --git a/opm/core/fluid/RockFromDeck.hpp b/opm/core/fluid/RockFromDeck.hpp
index abd9c14c..63e71a6e 100644
--- a/opm/core/fluid/RockFromDeck.hpp
+++ b/opm/core/fluid/RockFromDeck.hpp
@@ -24,6 +24,7 @@
#include
#include
+struct UnstructuredGrid;
namespace Opm
{
@@ -34,12 +35,13 @@ namespace Opm
/// Default constructor.
RockFromDeck();
- /// Initialize from deck and cell mapping.
+ /// Initialize from deck and grid.
/// \param deck Deck input parser
- /// \param global_cell mapping from cell indices (typically from a processed grid)
+ /// \param grid Grid to which property object applies, needed for the
+ /// mapping from cell indices (typically from a processed grid)
/// to logical cartesian indices consistent with the deck.
void init(const EclipseGridParser& deck,
- const std::vector& global_cell);
+ const UnstructuredGrid& grid);
/// \return D, the number of spatial dimensions. Always 3 for deck input.
int numDimensions() const
@@ -69,9 +71,9 @@ namespace Opm
private:
void assignPorosity(const EclipseGridParser& parser,
- const std::vector& global_cell);
+ const UnstructuredGrid& grid);
void assignPermeability(const EclipseGridParser& parser,
- const std::vector& global_cell,
+ const UnstructuredGrid& grid,
const double perm_threshold);
std::vector porosity_;
diff --git a/opm/core/fluid/SatFuncSimple.cpp b/opm/core/fluid/SatFuncSimple.cpp
new file mode 100644
index 00000000..7e226a4a
--- /dev/null
+++ b/opm/core/fluid/SatFuncSimple.cpp
@@ -0,0 +1,425 @@
+/*
+ Copyright 2012 SINTEF ICT, Applied Mathematics.
+
+ 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 .
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace Opm
+{
+
+
+
+
+ void SatFuncSimpleUniform::init(const EclipseGridParser& deck,
+ const int table_num,
+ const PhaseUsage phase_usg,
+ const int samples)
+ {
+ phase_usage = phase_usg;
+ double swco = 0.0;
+ double swmax = 1.0;
+ if (phase_usage.phase_used[Aqua]) {
+ const SWOF::table_t& swof_table = deck.getSWOF().swof_;
+ const std::vector& sw = swof_table[table_num][0];
+ const std::vector& krw = swof_table[table_num][1];
+ const std::vector& krow = swof_table[table_num][2];
+ const std::vector& pcow = swof_table[table_num][3];
+ buildUniformMonotoneTable(sw, krw, samples, krw_);
+ buildUniformMonotoneTable(sw, krow, samples, krow_);
+ buildUniformMonotoneTable(sw, pcow, samples, pcow_);
+ krocw_ = krow[0]; // At connate water -> ecl. SWOF
+ swco = sw[0];
+ smin_[phase_usage.phase_pos[Aqua]] = sw[0];
+ swmax = sw.back();
+ smax_[phase_usage.phase_pos[Aqua]] = sw.back();
+ }
+ if (phase_usage.phase_used[Vapour]) {
+ const SGOF::table_t& sgof_table = deck.getSGOF().sgof_;
+ const std::vector& sg = sgof_table[table_num][0];
+ const std::vector& krg = sgof_table[table_num][1];
+ const std::vector& krog = sgof_table[table_num][2];
+ const std::vector& pcog = sgof_table[table_num][3];
+ buildUniformMonotoneTable(sg, krg, samples, krg_);
+ buildUniformMonotoneTable(sg, krog, samples, krog_);
+ buildUniformMonotoneTable(sg, pcog, samples, pcog_);
+ smin_[phase_usage.phase_pos[Vapour]] = sg[0];
+ if (std::fabs(sg.back() + swco - 1.0) > 1e-3) {
+ THROW("Gas maximum saturation in SGOF table = " << sg.back() <<
+ ", should equal (1.0 - connate water sat) = " << (1.0 - swco));
+ }
+ smax_[phase_usage.phase_pos[Vapour]] = sg.back();
+ }
+ // These only consider water min/max sats. Consider gas sats?
+ smin_[phase_usage.phase_pos[Liquid]] = 1.0 - swmax;
+ smax_[phase_usage.phase_pos[Liquid]] = 1.0 - swco;
+ }
+
+
+ void SatFuncSimpleUniform::evalKr(const double* s, double* kr) const
+ {
+ if (phase_usage.num_phases == 3) {
+ // A simplified relative permeability model.
+ double sw = s[Aqua];
+ double sg = s[Vapour];
+ double krw = krw_(sw);
+ double krg = krg_(sg);
+ double krow = krow_(sw + sg); // = 1 - so
+ // double krog = krog_(sg); // = 1 - so - sw
+ // double krocw = krocw_;
+ kr[Aqua] = krw;
+ kr[Vapour] = krg;
+ kr[Liquid] = krow;
+ if (kr[Liquid] < 0.0) {
+ kr[Liquid] = 0.0;
+ }
+ return;
+ }
+ // We have a two-phase situation. We know that oil is active.
+ if (phase_usage.phase_used[Aqua]) {
+ int wpos = phase_usage.phase_pos[Aqua];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sw = s[wpos];
+ double krw = krw_(sw);
+ double krow = krow_(sw);
+ kr[wpos] = krw;
+ kr[opos] = krow;
+ } else {
+ ASSERT(phase_usage.phase_used[Vapour]);
+ int gpos = phase_usage.phase_pos[Vapour];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sg = s[gpos];
+ double krg = krg_(sg);
+ double krog = krog_(sg);
+ kr[gpos] = krg;
+ kr[opos] = krog;
+ }
+ }
+
+
+ void SatFuncSimpleUniform::evalKrDeriv(const double* s, double* kr, double* dkrds) const
+ {
+ const int np = phase_usage.num_phases;
+ std::fill(dkrds, dkrds + np*np, 0.0);
+
+ if (np == 3) {
+ // A simplified relative permeability model.
+ double sw = s[Aqua];
+ double sg = s[Vapour];
+ double krw = krw_(sw);
+ double dkrww = krw_.derivative(sw);
+ double krg = krg_(sg);
+ double dkrgg = krg_.derivative(sg);
+ double krow = krow_(sw + sg);
+ double dkrow = krow_.derivative(sw + sg);
+ // double krog = krog_(sg);
+ // double dkrog = krog_.derivative(sg);
+ // double krocw = krocw_;
+ kr[Aqua] = krw;
+ kr[Vapour] = krg;
+ kr[Liquid] = krow;
+ //krocw*((krow/krocw + krw)*(krog/krocw + krg) - krw - krg);
+ if (kr[Liquid] < 0.0) {
+ kr[Liquid] = 0.0;
+ }
+ dkrds[Aqua + Aqua*np] = dkrww;
+ dkrds[Vapour + Vapour*np] = dkrgg;
+ //dkrds[Liquid + Aqua*np] = dkrow;
+ dkrds[Liquid + Liquid*np] = -dkrow;
+ //krocw*((dkrow/krocw + dkrww)*(krog/krocw + krg) - dkrww);
+ dkrds[Liquid + Vapour*np] = 0.0;
+ //krocw*((krow/krocw + krw)*(dkrog/krocw + dkrgg) - dkrgg)
+ //+ krocw*((dkrow/krocw + krw)*(krog/krocw + krg) - dkrgg);
+ return;
+ }
+ // We have a two-phase situation. We know that oil is active.
+ if (phase_usage.phase_used[Aqua]) {
+ int wpos = phase_usage.phase_pos[Aqua];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sw = s[wpos];
+ double krw = krw_(sw);
+ double dkrww = krw_.derivative(sw);
+ double krow = krow_(sw);
+ double dkrow = krow_.derivative(sw);
+ kr[wpos] = krw;
+ kr[opos] = krow;
+ dkrds[wpos + wpos*np] = dkrww;
+ dkrds[opos + wpos*np] = dkrow; // Row opos, column wpos, fortran order.
+ } else {
+ ASSERT(phase_usage.phase_used[Vapour]);
+ int gpos = phase_usage.phase_pos[Vapour];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sg = s[gpos];
+ double krg = krg_(sg);
+ double dkrgg = krg_.derivative(sg);
+ double krog = krog_(sg);
+ double dkrog = krog_.derivative(sg);
+ kr[gpos] = krg;
+ kr[opos] = krog;
+ dkrds[gpos + gpos*np] = dkrgg;
+ dkrds[opos + gpos*np] = dkrog;
+ }
+
+ }
+
+
+ void SatFuncSimpleUniform::evalPc(const double* s, double* pc) const
+ {
+ pc[phase_usage.phase_pos[Liquid]] = 0.0;
+ if (phase_usage.phase_used[Aqua]) {
+ int pos = phase_usage.phase_pos[Aqua];
+ pc[pos] = pcow_(s[pos]);
+ }
+ if (phase_usage.phase_used[Vapour]) {
+ int pos = phase_usage.phase_pos[Vapour];
+ pc[pos] = pcog_(s[pos]);
+ }
+ }
+
+ void SatFuncSimpleUniform::evalPcDeriv(const double* s, double* pc, double* dpcds) const
+ {
+ // The problem of determining three-phase capillary pressures
+ // is very hard experimentally, usually one extends two-phase
+ // data (as for relative permeability).
+ // In our approach the derivative matrix is quite sparse, only
+ // the diagonal elements corresponding to non-oil phases are
+ // (potentially) nonzero.
+ const int np = phase_usage.num_phases;
+ std::fill(dpcds, dpcds + np*np, 0.0);
+ pc[phase_usage.phase_pos[Liquid]] = 0.0;
+ if (phase_usage.phase_used[Aqua]) {
+ int pos = phase_usage.phase_pos[Aqua];
+ pc[pos] = pcow_(s[pos]);
+ dpcds[np*pos + pos] = pcow_.derivative(s[pos]);
+ }
+ if (phase_usage.phase_used[Vapour]) {
+ int pos = phase_usage.phase_pos[Vapour];
+ pc[pos] = pcog_(s[pos]);
+ dpcds[np*pos + pos] = pcog_.derivative(s[pos]);
+ }
+ }
+
+
+
+
+
+ // ====== Methods for SatFuncSimpleNonuniform ======
+
+
+
+
+
+
+ void SatFuncSimpleNonuniform::init(const EclipseGridParser& deck,
+ const int table_num,
+ const PhaseUsage phase_usg,
+ const int /*samples*/)
+ {
+ phase_usage = phase_usg;
+ double swco = 0.0;
+ double swmax = 1.0;
+ if (phase_usage.phase_used[Aqua]) {
+ const SWOF::table_t& swof_table = deck.getSWOF().swof_;
+ const std::vector& sw = swof_table[table_num][0];
+ const std::vector& krw = swof_table[table_num][1];
+ const std::vector& krow = swof_table[table_num][2];
+ const std::vector& pcow = swof_table[table_num][3];
+ krw_ = NonuniformTableLinear(sw, krw);
+ krow_ = NonuniformTableLinear(sw, krow);
+ pcow_ = NonuniformTableLinear(sw, pcow);
+ krocw_ = krow[0]; // At connate water -> ecl. SWOF
+ swco = sw[0];
+ smin_[phase_usage.phase_pos[Aqua]] = sw[0];
+ swmax = sw.back();
+ smax_[phase_usage.phase_pos[Aqua]] = sw.back();
+ }
+ if (phase_usage.phase_used[Vapour]) {
+ const SGOF::table_t& sgof_table = deck.getSGOF().sgof_;
+ const std::vector& sg = sgof_table[table_num][0];
+ const std::vector& krg = sgof_table[table_num][1];
+ const std::vector& krog = sgof_table[table_num][2];
+ const std::vector& pcog = sgof_table[table_num][3];
+ krg_ = NonuniformTableLinear(sg, krg);
+ krog_ = NonuniformTableLinear(sg, krog);
+ pcog_ = NonuniformTableLinear(sg, pcog);
+ smin_[phase_usage.phase_pos[Vapour]] = sg[0];
+ if (std::fabs(sg.back() + swco - 1.0) > 1e-3) {
+ THROW("Gas maximum saturation in SGOF table = " << sg.back() <<
+ ", should equal (1.0 - connate water sat) = " << (1.0 - swco));
+ }
+ smax_[phase_usage.phase_pos[Vapour]] = sg.back();
+ }
+ // These only consider water min/max sats. Consider gas sats?
+ smin_[phase_usage.phase_pos[Liquid]] = 1.0 - swmax;
+ smax_[phase_usage.phase_pos[Liquid]] = 1.0 - swco;
+ }
+
+
+ void SatFuncSimpleNonuniform::evalKr(const double* s, double* kr) const
+ {
+ if (phase_usage.num_phases == 3) {
+ // A simplified relative permeability model.
+ double sw = s[Aqua];
+ double sg = s[Vapour];
+ double krw = krw_(sw);
+ double krg = krg_(sg);
+ double krow = krow_(sw + sg); // = 1 - so
+ // double krog = krog_(sg); // = 1 - so - sw
+ // double krocw = krocw_;
+ kr[Aqua] = krw;
+ kr[Vapour] = krg;
+ kr[Liquid] = krow;
+ if (kr[Liquid] < 0.0) {
+ kr[Liquid] = 0.0;
+ }
+ return;
+ }
+ // We have a two-phase situation. We know that oil is active.
+ if (phase_usage.phase_used[Aqua]) {
+ int wpos = phase_usage.phase_pos[Aqua];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sw = s[wpos];
+ double krw = krw_(sw);
+ double krow = krow_(sw);
+ kr[wpos] = krw;
+ kr[opos] = krow;
+ } else {
+ ASSERT(phase_usage.phase_used[Vapour]);
+ int gpos = phase_usage.phase_pos[Vapour];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sg = s[gpos];
+ double krg = krg_(sg);
+ double krog = krog_(sg);
+ kr[gpos] = krg;
+ kr[opos] = krog;
+ }
+ }
+
+
+ void SatFuncSimpleNonuniform::evalKrDeriv(const double* s, double* kr, double* dkrds) const
+ {
+ const int np = phase_usage.num_phases;
+ std::fill(dkrds, dkrds + np*np, 0.0);
+
+ if (np == 3) {
+ // A simplified relative permeability model.
+ double sw = s[Aqua];
+ double sg = s[Vapour];
+ double krw = krw_(sw);
+ double dkrww = krw_.derivative(sw);
+ double krg = krg_(sg);
+ double dkrgg = krg_.derivative(sg);
+ double krow = krow_(sw + sg);
+ double dkrow = krow_.derivative(sw + sg);
+ // double krog = krog_(sg);
+ // double dkrog = krog_.derivative(sg);
+ // double krocw = krocw_;
+ kr[Aqua] = krw;
+ kr[Vapour] = krg;
+ kr[Liquid] = krow;
+ //krocw*((krow/krocw + krw)*(krog/krocw + krg) - krw - krg);
+ if (kr[Liquid] < 0.0) {
+ kr[Liquid] = 0.0;
+ }
+ dkrds[Aqua + Aqua*np] = dkrww;
+ dkrds[Vapour + Vapour*np] = dkrgg;
+ //dkrds[Liquid + Aqua*np] = dkrow;
+ dkrds[Liquid + Liquid*np] = -dkrow;
+ //krocw*((dkrow/krocw + dkrww)*(krog/krocw + krg) - dkrww);
+ dkrds[Liquid + Vapour*np] = 0.0;
+ //krocw*((krow/krocw + krw)*(dkrog/krocw + dkrgg) - dkrgg)
+ //+ krocw*((dkrow/krocw + krw)*(krog/krocw + krg) - dkrgg);
+ return;
+ }
+ // We have a two-phase situation. We know that oil is active.
+ if (phase_usage.phase_used[Aqua]) {
+ int wpos = phase_usage.phase_pos[Aqua];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sw = s[wpos];
+ double krw = krw_(sw);
+ double dkrww = krw_.derivative(sw);
+ double krow = krow_(sw);
+ double dkrow = krow_.derivative(sw);
+ kr[wpos] = krw;
+ kr[opos] = krow;
+ dkrds[wpos + wpos*np] = dkrww;
+ dkrds[opos + wpos*np] = dkrow; // Row opos, column wpos, fortran order.
+ } else {
+ ASSERT(phase_usage.phase_used[Vapour]);
+ int gpos = phase_usage.phase_pos[Vapour];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sg = s[gpos];
+ double krg = krg_(sg);
+ double dkrgg = krg_.derivative(sg);
+ double krog = krog_(sg);
+ double dkrog = krog_.derivative(sg);
+ kr[gpos] = krg;
+ kr[opos] = krog;
+ dkrds[gpos + gpos*np] = dkrgg;
+ dkrds[opos + gpos*np] = dkrog;
+ }
+
+ }
+
+
+ void SatFuncSimpleNonuniform::evalPc(const double* s, double* pc) const
+ {
+ pc[phase_usage.phase_pos[Liquid]] = 0.0;
+ if (phase_usage.phase_used[Aqua]) {
+ int pos = phase_usage.phase_pos[Aqua];
+ pc[pos] = pcow_(s[pos]);
+ }
+ if (phase_usage.phase_used[Vapour]) {
+ int pos = phase_usage.phase_pos[Vapour];
+ pc[pos] = pcog_(s[pos]);
+ }
+ }
+
+ void SatFuncSimpleNonuniform::evalPcDeriv(const double* s, double* pc, double* dpcds) const
+ {
+ // The problem of determining three-phase capillary pressures
+ // is very hard experimentally, usually one extends two-phase
+ // data (as for relative permeability).
+ // In our approach the derivative matrix is quite sparse, only
+ // the diagonal elements corresponding to non-oil phases are
+ // (potentially) nonzero.
+ const int np = phase_usage.num_phases;
+ std::fill(dpcds, dpcds + np*np, 0.0);
+ pc[phase_usage.phase_pos[Liquid]] = 0.0;
+ if (phase_usage.phase_used[Aqua]) {
+ int pos = phase_usage.phase_pos[Aqua];
+ pc[pos] = pcow_(s[pos]);
+ dpcds[np*pos + pos] = pcow_.derivative(s[pos]);
+ }
+ if (phase_usage.phase_used[Vapour]) {
+ int pos = phase_usage.phase_pos[Vapour];
+ pc[pos] = pcog_(s[pos]);
+ dpcds[np*pos + pos] = pcog_.derivative(s[pos]);
+ }
+ }
+
+
+
+
+} // namespace Opm
diff --git a/opm/core/fluid/SatFuncSimple.hpp b/opm/core/fluid/SatFuncSimple.hpp
new file mode 100644
index 00000000..338a359e
--- /dev/null
+++ b/opm/core/fluid/SatFuncSimple.hpp
@@ -0,0 +1,80 @@
+/*
+ Copyright 2012 SINTEF ICT, Applied Mathematics.
+
+ 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 .
+*/
+#ifndef SATFUNCSIMPLE_HPP
+#define SATFUNCSIMPLE_HPP
+
+#include
+#include
+#include
+#include
+#include
+
+namespace Opm
+{
+ class SatFuncSimpleUniform : public BlackoilPhases
+ {
+ public:
+ void init(const EclipseGridParser& deck,
+ const int table_num,
+ const PhaseUsage phase_usg,
+ const int samples);
+ void evalKr(const double* s, double* kr) const;
+ void evalKrDeriv(const double* s, double* kr, double* dkrds) const;
+ void evalPc(const double* s, double* pc) const;
+ void evalPcDeriv(const double* s, double* pc, double* dpcds) const;
+ double smin_[PhaseUsage::MaxNumPhases];
+ double smax_[PhaseUsage::MaxNumPhases];
+ private:
+ PhaseUsage phase_usage; // A copy of the outer class' phase_usage_.
+ UniformTableLinear krw_;
+ UniformTableLinear krow_;
+ UniformTableLinear pcow_;
+ UniformTableLinear krg_;
+ UniformTableLinear krog_;
+ UniformTableLinear pcog_;
+ double krocw_; // = krow_(s_wc)
+ };
+
+
+ class SatFuncSimpleNonuniform : public BlackoilPhases
+ {
+ public:
+ void init(const EclipseGridParser& deck,
+ const int table_num,
+ const PhaseUsage phase_usg,
+ const int samples);
+ void evalKr(const double* s, double* kr) const;
+ void evalKrDeriv(const double* s, double* kr, double* dkrds) const;
+ void evalPc(const double* s, double* pc) const;
+ void evalPcDeriv(const double* s, double* pc, double* dpcds) const;
+ double smin_[PhaseUsage::MaxNumPhases];
+ double smax_[PhaseUsage::MaxNumPhases];
+ private:
+ PhaseUsage phase_usage; // A copy of the outer class' phase_usage_.
+ NonuniformTableLinear krw_;
+ NonuniformTableLinear krow_;
+ NonuniformTableLinear pcow_;
+ NonuniformTableLinear krg_;
+ NonuniformTableLinear krog_;
+ NonuniformTableLinear pcog_;
+ double krocw_; // = krow_(s_wc)
+ };
+
+} // namespace Opm
+#endif // SATFUNCSIMPLE_HPP
diff --git a/opm/core/fluid/SatFuncStone2.cpp b/opm/core/fluid/SatFuncStone2.cpp
new file mode 100644
index 00000000..062f8534
--- /dev/null
+++ b/opm/core/fluid/SatFuncStone2.cpp
@@ -0,0 +1,417 @@
+/*
+ Copyright 2012 SINTEF ICT, Applied Mathematics.
+
+ 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 .
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace Opm
+{
+
+
+
+
+ void SatFuncStone2Uniform::init(const EclipseGridParser& deck,
+ const int table_num,
+ const PhaseUsage phase_usg,
+ const int samples)
+ {
+ phase_usage = phase_usg;
+ double swco = 0.0;
+ double swmax = 1.0;
+ if (phase_usage.phase_used[Aqua]) {
+ const SWOF::table_t& swof_table = deck.getSWOF().swof_;
+ const std::vector& sw = swof_table[table_num][0];
+ const std::vector& krw = swof_table[table_num][1];
+ const std::vector& krow = swof_table[table_num][2];
+ const std::vector& pcow = swof_table[table_num][3];
+ buildUniformMonotoneTable(sw, krw, samples, krw_);
+ buildUniformMonotoneTable(sw, krow, samples, krow_);
+ buildUniformMonotoneTable(sw, pcow, samples, pcow_);
+ krocw_ = krow[0]; // At connate water -> ecl. SWOF
+ swco = sw[0];
+ smin_[phase_usage.phase_pos[Aqua]] = sw[0];
+ swmax = sw.back();
+ smax_[phase_usage.phase_pos[Aqua]] = sw.back();
+ }
+ if (phase_usage.phase_used[Vapour]) {
+ const SGOF::table_t& sgof_table = deck.getSGOF().sgof_;
+ const std::vector& sg = sgof_table[table_num][0];
+ const std::vector& krg = sgof_table[table_num][1];
+ const std::vector& krog = sgof_table[table_num][2];
+ const std::vector& pcog = sgof_table[table_num][3];
+ buildUniformMonotoneTable(sg, krg, samples, krg_);
+ buildUniformMonotoneTable(sg, krog, samples, krog_);
+ buildUniformMonotoneTable(sg, pcog, samples, pcog_);
+ smin_[phase_usage.phase_pos[Vapour]] = sg[0];
+ if (std::fabs(sg.back() + swco - 1.0) > 1e-3) {
+ THROW("Gas maximum saturation in SGOF table = " << sg.back() <<
+ ", should equal (1.0 - connate water sat) = " << (1.0 - swco));
+ }
+ smax_[phase_usage.phase_pos[Vapour]] = sg.back();
+ }
+ // These only consider water min/max sats. Consider gas sats?
+ smin_[phase_usage.phase_pos[Liquid]] = 1.0 - swmax;
+ smax_[phase_usage.phase_pos[Liquid]] = 1.0 - swco;
+ }
+
+
+ void SatFuncStone2Uniform::evalKr(const double* s, double* kr) const
+ {
+ if (phase_usage.num_phases == 3) {
+ // Stone-II relative permeability model.
+ double sw = s[Aqua];
+ double sg = s[Vapour];
+ double krw = krw_(sw);
+ double krg = krg_(sg);
+ double krow = krow_(sw + sg); // = 1 - so
+ double krog = krog_(sg); // = 1 - so - sw
+ double krocw = krocw_;
+ kr[Aqua] = krw;
+ kr[Vapour] = krg;
+ kr[Liquid] = krocw*((krow/krocw + krw)*(krog/krocw + krg) - krw - krg);
+ if (kr[Liquid] < 0.0) {
+ kr[Liquid] = 0.0;
+ }
+ return;
+ }
+ // We have a two-phase situation. We know that oil is active.
+ if (phase_usage.phase_used[Aqua]) {
+ int wpos = phase_usage.phase_pos[Aqua];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sw = s[wpos];
+ double krw = krw_(sw);
+ double krow = krow_(sw);
+ kr[wpos] = krw;
+ kr[opos] = krow;
+ } else {
+ ASSERT(phase_usage.phase_used[Vapour]);
+ int gpos = phase_usage.phase_pos[Vapour];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sg = s[gpos];
+ double krg = krg_(sg);
+ double krog = krog_(sg);
+ kr[gpos] = krg;
+ kr[opos] = krog;
+ }
+ }
+
+
+ void SatFuncStone2Uniform::evalKrDeriv(const double* s, double* kr, double* dkrds) const
+ {
+ const int np = phase_usage.num_phases;
+ std::fill(dkrds, dkrds + np*np, 0.0);
+
+ if (np == 3) {
+ // Stone-II relative permeability model.
+ double sw = s[Aqua];
+ double sg = s[Vapour];
+ double krw = krw_(sw);
+ double dkrww = krw_.derivative(sw);
+ double krg = krg_(sg);
+ double dkrgg = krg_.derivative(sg);
+ double krow = krow_(sw + sg);
+ double dkrow = krow_.derivative(sw + sg);
+ double krog = krog_(sg);
+ double dkrog = krog_.derivative(sg);
+ double krocw = krocw_;
+ kr[Aqua] = krw;
+ kr[Vapour] = krg;
+ kr[Liquid] = krocw*((krow/krocw + krw)*(krog/krocw + krg) - krw - krg);
+ if (kr[Liquid] < 0.0) {
+ kr[Liquid] = 0.0;
+ }
+ dkrds[Aqua + Aqua*np] = dkrww;
+ dkrds[Vapour + Vapour*np] = dkrgg;
+ dkrds[Liquid + Aqua*np] = krocw*((dkrow/krocw + dkrww)*(krog/krocw + krg) - dkrww);
+ dkrds[Liquid + Vapour*np] = krocw*((krow/krocw + krw)*(dkrog/krocw + dkrgg) - dkrgg)
+ + krocw*((dkrow/krocw + krw)*(krog/krocw + krg) - dkrgg);
+ return;
+ }
+ // We have a two-phase situation. We know that oil is active.
+ if (phase_usage.phase_used[Aqua]) {
+ int wpos = phase_usage.phase_pos[Aqua];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sw = s[wpos];
+ double krw = krw_(sw);
+ double dkrww = krw_.derivative(sw);
+ double krow = krow_(sw);
+ double dkrow = krow_.derivative(sw);
+ kr[wpos] = krw;
+ kr[opos] = krow;
+ dkrds[wpos + wpos*np] = dkrww;
+ dkrds[opos + wpos*np] = dkrow; // Row opos, column wpos, fortran order.
+ } else {
+ ASSERT(phase_usage.phase_used[Vapour]);
+ int gpos = phase_usage.phase_pos[Vapour];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sg = s[gpos];
+ double krg = krg_(sg);
+ double dkrgg = krg_.derivative(sg);
+ double krog = krog_(sg);
+ double dkrog = krog_.derivative(sg);
+ kr[gpos] = krg;
+ kr[opos] = krog;
+ dkrds[gpos + gpos*np] = dkrgg;
+ dkrds[opos + gpos*np] = dkrog;
+ }
+
+ }
+
+
+ void SatFuncStone2Uniform::evalPc(const double* s, double* pc) const
+ {
+ pc[phase_usage.phase_pos[Liquid]] = 0.0;
+ if (phase_usage.phase_used[Aqua]) {
+ int pos = phase_usage.phase_pos[Aqua];
+ pc[pos] = pcow_(s[pos]);
+ }
+ if (phase_usage.phase_used[Vapour]) {
+ int pos = phase_usage.phase_pos[Vapour];
+ pc[pos] = pcog_(s[pos]);
+ }
+ }
+
+ void SatFuncStone2Uniform::evalPcDeriv(const double* s, double* pc, double* dpcds) const
+ {
+ // The problem of determining three-phase capillary pressures
+ // is very hard experimentally, usually one extends two-phase
+ // data (as for relative permeability).
+ // In our approach the derivative matrix is quite sparse, only
+ // the diagonal elements corresponding to non-oil phases are
+ // (potentially) nonzero.
+ const int np = phase_usage.num_phases;
+ std::fill(dpcds, dpcds + np*np, 0.0);
+ pc[phase_usage.phase_pos[Liquid]] = 0.0;
+ if (phase_usage.phase_used[Aqua]) {
+ int pos = phase_usage.phase_pos[Aqua];
+ pc[pos] = pcow_(s[pos]);
+ dpcds[np*pos + pos] = pcow_.derivative(s[pos]);
+ }
+ if (phase_usage.phase_used[Vapour]) {
+ int pos = phase_usage.phase_pos[Vapour];
+ pc[pos] = pcog_(s[pos]);
+ dpcds[np*pos + pos] = pcog_.derivative(s[pos]);
+ }
+ }
+
+
+
+
+
+
+ // ====== Methods for SatFuncSimpleNonuniform ======
+
+
+
+
+ void SatFuncStone2Nonuniform::init(const EclipseGridParser& deck,
+ const int table_num,
+ const PhaseUsage phase_usg,
+ const int /*samples*/)
+ {
+ phase_usage = phase_usg;
+ double swco = 0.0;
+ double swmax = 1.0;
+ if (phase_usage.phase_used[Aqua]) {
+ const SWOF::table_t& swof_table = deck.getSWOF().swof_;
+ const std::vector& sw = swof_table[table_num][0];
+ const std::vector& krw = swof_table[table_num][1];
+ const std::vector& krow = swof_table[table_num][2];
+ const std::vector& pcow = swof_table[table_num][3];
+ krw_ = NonuniformTableLinear(sw, krw);
+ krow_ = NonuniformTableLinear(sw, krow);
+ pcow_ = NonuniformTableLinear(sw, pcow);
+ krocw_ = krow[0]; // At connate water -> ecl. SWOF
+ swco = sw[0];
+ smin_[phase_usage.phase_pos[Aqua]] = sw[0];
+ swmax = sw.back();
+ smax_[phase_usage.phase_pos[Aqua]] = sw.back();
+ }
+ if (phase_usage.phase_used[Vapour]) {
+ const SGOF::table_t& sgof_table = deck.getSGOF().sgof_;
+ const std::vector& sg = sgof_table[table_num][0];
+ const std::vector& krg = sgof_table[table_num][1];
+ const std::vector& krog = sgof_table[table_num][2];
+ const std::vector& pcog = sgof_table[table_num][3];
+ krg_ = NonuniformTableLinear(sg, krg);
+ krog_ = NonuniformTableLinear(sg, krog);
+ pcog_ = NonuniformTableLinear(sg, pcog);
+ smin_[phase_usage.phase_pos[Vapour]] = sg[0];
+ if (std::fabs(sg.back() + swco - 1.0) > 1e-3) {
+ THROW("Gas maximum saturation in SGOF table = " << sg.back() <<
+ ", should equal (1.0 - connate water sat) = " << (1.0 - swco));
+ }
+ smax_[phase_usage.phase_pos[Vapour]] = sg.back();
+ }
+ // These only consider water min/max sats. Consider gas sats?
+ smin_[phase_usage.phase_pos[Liquid]] = 1.0 - swmax;
+ smax_[phase_usage.phase_pos[Liquid]] = 1.0 - swco;
+ }
+
+
+ void SatFuncStone2Nonuniform::evalKr(const double* s, double* kr) const
+ {
+ if (phase_usage.num_phases == 3) {
+ // Stone-II relative permeability model.
+ double sw = s[Aqua];
+ double sg = s[Vapour];
+ double krw = krw_(sw);
+ double krg = krg_(sg);
+ double krow = krow_(sw + sg); // = 1 - so
+ double krog = krog_(sg); // = 1 - so - sw
+ double krocw = krocw_;
+ kr[Aqua] = krw;
+ kr[Vapour] = krg;
+ kr[Liquid] = krocw*((krow/krocw + krw)*(krog/krocw + krg) - krw - krg);
+ if (kr[Liquid] < 0.0) {
+ kr[Liquid] = 0.0;
+ }
+ return;
+ }
+ // We have a two-phase situation. We know that oil is active.
+ if (phase_usage.phase_used[Aqua]) {
+ int wpos = phase_usage.phase_pos[Aqua];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sw = s[wpos];
+ double krw = krw_(sw);
+ double krow = krow_(sw);
+ kr[wpos] = krw;
+ kr[opos] = krow;
+ } else {
+ ASSERT(phase_usage.phase_used[Vapour]);
+ int gpos = phase_usage.phase_pos[Vapour];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sg = s[gpos];
+ double krg = krg_(sg);
+ double krog = krog_(sg);
+ kr[gpos] = krg;
+ kr[opos] = krog;
+ }
+ }
+
+
+ void SatFuncStone2Nonuniform::evalKrDeriv(const double* s, double* kr, double* dkrds) const
+ {
+ const int np = phase_usage.num_phases;
+ std::fill(dkrds, dkrds + np*np, 0.0);
+
+ if (np == 3) {
+ // Stone-II relative permeability model.
+ double sw = s[Aqua];
+ double sg = s[Vapour];
+ double krw = krw_(sw);
+ double dkrww = krw_.derivative(sw);
+ double krg = krg_(sg);
+ double dkrgg = krg_.derivative(sg);
+ double krow = krow_(sw + sg);
+ double dkrow = krow_.derivative(sw + sg);
+ double krog = krog_(sg);
+ double dkrog = krog_.derivative(sg);
+ double krocw = krocw_;
+ kr[Aqua] = krw;
+ kr[Vapour] = krg;
+ kr[Liquid] = krocw*((krow/krocw + krw)*(krog/krocw + krg) - krw - krg);
+ if (kr[Liquid] < 0.0) {
+ kr[Liquid] = 0.0;
+ }
+ dkrds[Aqua + Aqua*np] = dkrww;
+ dkrds[Vapour + Vapour*np] = dkrgg;
+ dkrds[Liquid + Aqua*np] = krocw*((dkrow/krocw + dkrww)*(krog/krocw + krg) - dkrww);
+ dkrds[Liquid + Vapour*np] = krocw*((krow/krocw + krw)*(dkrog/krocw + dkrgg) - dkrgg)
+ + krocw*((dkrow/krocw + krw)*(krog/krocw + krg) - dkrgg);
+ return;
+ }
+ // We have a two-phase situation. We know that oil is active.
+ if (phase_usage.phase_used[Aqua]) {
+ int wpos = phase_usage.phase_pos[Aqua];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sw = s[wpos];
+ double krw = krw_(sw);
+ double dkrww = krw_.derivative(sw);
+ double krow = krow_(sw);
+ double dkrow = krow_.derivative(sw);
+ kr[wpos] = krw;
+ kr[opos] = krow;
+ dkrds[wpos + wpos*np] = dkrww;
+ dkrds[opos + wpos*np] = dkrow; // Row opos, column wpos, fortran order.
+ } else {
+ ASSERT(phase_usage.phase_used[Vapour]);
+ int gpos = phase_usage.phase_pos[Vapour];
+ int opos = phase_usage.phase_pos[Liquid];
+ double sg = s[gpos];
+ double krg = krg_(sg);
+ double dkrgg = krg_.derivative(sg);
+ double krog = krog_(sg);
+ double dkrog = krog_.derivative(sg);
+ kr[gpos] = krg;
+ kr[opos] = krog;
+ dkrds[gpos + gpos*np] = dkrgg;
+ dkrds[opos + gpos*np] = dkrog;
+ }
+
+ }
+
+
+ void SatFuncStone2Nonuniform::evalPc(const double* s, double* pc) const
+ {
+ pc[phase_usage.phase_pos[Liquid]] = 0.0;
+ if (phase_usage.phase_used[Aqua]) {
+ int pos = phase_usage.phase_pos[Aqua];
+ pc[pos] = pcow_(s[pos]);
+ }
+ if (phase_usage.phase_used[Vapour]) {
+ int pos = phase_usage.phase_pos[Vapour];
+ pc[pos] = pcog_(s[pos]);
+ }
+ }
+
+ void SatFuncStone2Nonuniform::evalPcDeriv(const double* s, double* pc, double* dpcds) const
+ {
+ // The problem of determining three-phase capillary pressures
+ // is very hard experimentally, usually one extends two-phase
+ // data (as for relative permeability).
+ // In our approach the derivative matrix is quite sparse, only
+ // the diagonal elements corresponding to non-oil phases are
+ // (potentially) nonzero.
+ const int np = phase_usage.num_phases;
+ std::fill(dpcds, dpcds + np*np, 0.0);
+ pc[phase_usage.phase_pos[Liquid]] = 0.0;
+ if (phase_usage.phase_used[Aqua]) {
+ int pos = phase_usage.phase_pos[Aqua];
+ pc[pos] = pcow_(s[pos]);
+ dpcds[np*pos + pos] = pcow_.derivative(s[pos]);
+ }
+ if (phase_usage.phase_used[Vapour]) {
+ int pos = phase_usage.phase_pos[Vapour];
+ pc[pos] = pcog_(s[pos]);
+ dpcds[np*pos + pos] = pcog_.derivative(s[pos]);
+ }
+ }
+
+
+
+
+
+} // namespace Opm
diff --git a/opm/core/fluid/SatFuncStone2.hpp b/opm/core/fluid/SatFuncStone2.hpp
new file mode 100644
index 00000000..532bf7ce
--- /dev/null
+++ b/opm/core/fluid/SatFuncStone2.hpp
@@ -0,0 +1,80 @@
+/*
+ Copyright 2012 SINTEF ICT, Applied Mathematics.
+
+ 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 .
+*/
+#ifndef SATFUNCSTONE2_HPP
+#define SATFUNCSTONE2_HPP
+
+#include
+#include
+#include
+#include
+#include
+
+namespace Opm
+{
+ class SatFuncStone2Uniform : public BlackoilPhases
+ {
+ public:
+ void init(const EclipseGridParser& deck,
+ const int table_num,
+ const PhaseUsage phase_usg,
+ const int samples);
+ void evalKr(const double* s, double* kr) const;
+ void evalKrDeriv(const double* s, double* kr, double* dkrds) const;
+ void evalPc(const double* s, double* pc) const;
+ void evalPcDeriv(const double* s, double* pc, double* dpcds) const;
+ double smin_[PhaseUsage::MaxNumPhases];
+ double smax_[PhaseUsage::MaxNumPhases];
+ private:
+ PhaseUsage phase_usage; // A copy of the outer class' phase_usage_.
+ UniformTableLinear krw_;
+ UniformTableLinear krow_;
+ UniformTableLinear pcow_;
+ UniformTableLinear krg_;
+ UniformTableLinear krog_;
+ UniformTableLinear pcog_;
+ double krocw_; // = krow_(s_wc)
+ };
+
+
+ class SatFuncStone2Nonuniform : public BlackoilPhases
+ {
+ public:
+ void init(const EclipseGridParser& deck,
+ const int table_num,
+ const PhaseUsage phase_usg,
+ const int samples);
+ void evalKr(const double* s, double* kr) const;
+ void evalKrDeriv(const double* s, double* kr, double* dkrds) const;
+ void evalPc(const double* s, double* pc) const;
+ void evalPcDeriv(const double* s, double* pc, double* dpcds) const;
+ double smin_[PhaseUsage::MaxNumPhases];
+ double smax_[PhaseUsage::MaxNumPhases];
+ private:
+ PhaseUsage phase_usage; // A copy of the outer class' phase_usage_.
+ NonuniformTableLinear krw_;
+ NonuniformTableLinear krow_;
+ NonuniformTableLinear pcow_;
+ NonuniformTableLinear krg_;
+ NonuniformTableLinear krog_;
+ NonuniformTableLinear pcog_;
+ double krocw_; // = krow_(s_wc)
+ };
+
+} // namespace Opm
+#endif // SATFUNCSTONE2_HPP
diff --git a/opm/core/fluid/SaturationPropsBasic.cpp b/opm/core/fluid/SaturationPropsBasic.cpp
index 4f20bd1b..10ddf23d 100644
--- a/opm/core/fluid/SaturationPropsBasic.cpp
+++ b/opm/core/fluid/SaturationPropsBasic.cpp
@@ -29,64 +29,64 @@ namespace Opm
namespace {
- struct KrFunConstant
- {
- double kr(double)
- {
- return 1.0;
- }
- double dkrds(double)
- {
- return 0.0;
- }
- };
+ struct KrFunConstant
+ {
+ double kr(double)
+ {
+ return 1.0;
+ }
+ double dkrds(double)
+ {
+ return 0.0;
+ }
+ };
- struct KrFunLinear
- {
- double kr(double s)
- {
- return s;
- }
- double dkrds(double)
- {
- return 1.0;
- }
- };
+ struct KrFunLinear
+ {
+ double kr(double s)
+ {
+ return s;
+ }
+ double dkrds(double)
+ {
+ return 1.0;
+ }
+ };
- struct KrFunQuadratic
- {
- double kr(double s)
- {
- return s*s;
- }
- double dkrds(double s)
- {
- return 2.0*s;
- }
- };
+ struct KrFunQuadratic
+ {
+ double kr(double s)
+ {
+ return s*s;
+ }
+ double dkrds(double s)
+ {
+ return 2.0*s;
+ }
+ };
- template
- static inline void evalAllKrDeriv(const int n, const int np,
- const double* s, double* kr, double* dkrds, Fun fun)
- {
- if (dkrds == 0) {
+ template
+ static inline void evalAllKrDeriv(const int n, const int np,
+ const double* s, double* kr, double* dkrds, Fun fun)
+ {
+ if (dkrds == 0) {
// #pragma omp parallel for
- for (int i = 0; i < n*np; ++i) {
- kr[i] = fun.kr(s[i]);
- }
- return;
- }
+ for (int i = 0; i < n*np; ++i) {
+ kr[i] = fun.kr(s[i]);
+ }
+ return;
+ }
// #pragma omp parallel for
- for (int i = 0; i < n; ++i) {
- std::fill(dkrds + i*np*np, dkrds + (i+1)*np*np, 0.0);
- for (int phase = 0; phase < np; ++phase) {
- kr[i*np + phase] = fun.kr(s[i*np + phase]);
- // Only diagonal elements in derivative.
- dkrds[i*np*np + phase*np + phase] = fun.dkrds(s[i*np + phase]);
- }
- }
- }
+ for (int i = 0; i < n; ++i) {
+ std::fill(dkrds + i*np*np, dkrds + (i+1)*np*np, 0.0);
+ for (int phase = 0; phase < np; ++phase) {
+ kr[i*np + phase] = fun.kr(s[i*np + phase]);
+ // Only diagonal elements in derivative.
+ dkrds[i*np*np + phase*np + phase] = fun.dkrds(s[i*np + phase]);
+ }
+ }
+ }
} // anon namespace
@@ -99,6 +99,7 @@ namespace Opm
/// Default constructor.
SaturationPropsBasic::SaturationPropsBasic()
+ : num_phases_(0), relperm_func_(Constant)
{
}
@@ -108,24 +109,25 @@ namespace Opm
/// Initialize from parameters.
void SaturationPropsBasic::init(const parameter::ParameterGroup& param)
{
- int num_phases = param.getDefault("num_phases", 2);
- if (num_phases > 2 || num_phases < 1) {
- THROW("SaturationPropsBasic::init() illegal num_phases: " << num_phases);
- }
+ int num_phases = param.getDefault("num_phases", 2);
+ if (num_phases > 2 || num_phases < 1) {
+ THROW("SaturationPropsBasic::init() illegal num_phases: " << num_phases);
+ }
num_phases_ = num_phases;
- std::string rpf = param.getDefault("relperm_func", std::string("Unset"));
- if (rpf == "Constant") {
- relperm_func_ = Constant;
- if(num_phases!=1){
- THROW("Constant relperm with more than one phase???");
- }
- } else if (rpf == "Linear") {
- relperm_func_ = Linear;
- } else if (rpf == "Quadratic") {
- relperm_func_ = Quadratic;
- } else {
- THROW("SaturationPropsBasic::init() illegal relperm_func: " << rpf);
- }
+ //std::string rpf = param.getDefault("relperm_func", std::string("Unset"));
+ std::string rpf = param.getDefault("relperm_func", std::string("Linear"));
+ if (rpf == "Constant") {
+ relperm_func_ = Constant;
+ if(num_phases!=1){
+ THROW("Constant relperm with more than one phase???");
+ }
+ } else if (rpf == "Linear") {
+ relperm_func_ = Linear;
+ } else if (rpf == "Quadratic") {
+ relperm_func_ = Quadratic;
+ } else {
+ THROW("SaturationPropsBasic::init() illegal relperm_func: " << rpf);
+ }
}
@@ -134,7 +136,7 @@ namespace Opm
/// \return P, the number of phases.
int SaturationPropsBasic::numPhases() const
{
- return num_phases_;
+ return num_phases_;
}
@@ -150,29 +152,29 @@ namespace Opm
/// m_{ij} = \frac{dkr_i}{ds^j},
/// and is output in Fortran order (m_00 m_10 m_20 m01 ...)
void SaturationPropsBasic::relperm(const int n,
- const double* s,
- double* kr,
- double* dkrds) const
+ const double* s,
+ double* kr,
+ double* dkrds) const
{
- switch (relperm_func_) {
- case Constant:
- {
- evalAllKrDeriv(n, num_phases_, s, kr, dkrds, KrFunConstant());
- break;
- }
- case Linear:
- {
- evalAllKrDeriv(n, num_phases_, s, kr, dkrds, KrFunLinear());
- break;
- }
- case Quadratic:
- {
- evalAllKrDeriv(n, num_phases_, s, kr, dkrds, KrFunQuadratic());
- break;
- }
- default:
- THROW("SaturationPropsBasic::relperm() unhandled relperm func type: " << relperm_func_);
- }
+ switch (relperm_func_) {
+ case Constant:
+ {
+ evalAllKrDeriv(n, num_phases_, s, kr, dkrds, KrFunConstant());
+ break;
+ }
+ case Linear:
+ {
+ evalAllKrDeriv(n, num_phases_, s, kr, dkrds, KrFunLinear());
+ break;
+ }
+ case Quadratic:
+ {
+ evalAllKrDeriv(n, num_phases_, s, kr, dkrds, KrFunQuadratic());
+ break;
+ }
+ default:
+ THROW("SaturationPropsBasic::relperm() unhandled relperm func type: " << relperm_func_);
+ }
}
@@ -188,13 +190,13 @@ namespace Opm
/// m_{ij} = \frac{dpc_i}{ds^j},
/// and is output in Fortran order (m_00 m_10 m_20 m01 ...)
void SaturationPropsBasic::capPress(const int n,
- const double* /*s*/,
- double* pc,
- double* dpcds) const
+ const double* /*s*/,
+ double* pc,
+ double* dpcds) const
{
- std::fill(pc, pc + num_phases_*n, 0.0);
+ std::fill(pc, pc + num_phases_*n, 0.0);
if (dpcds) {
- std::fill(dpcds, dpcds + num_phases_*num_phases_*n, 0.0);
+ std::fill(dpcds, dpcds + num_phases_*num_phases_*n, 0.0);
}
}
@@ -205,11 +207,11 @@ namespace Opm
/// \param[out] smin Array of nP minimum s values, array must be valid before calling.
/// \param[out] smax Array of nP maximum s values, array must be valid before calling.
void SaturationPropsBasic::satRange(const int n,
- double* smin,
- double* smax) const
+ double* smin,
+ double* smax) const
{
- std::fill(smin, smin + num_phases_*n, 0.0);
- std::fill(smax, smax + num_phases_*n, 1.0);
+ std::fill(smin, smin + num_phases_*n, 0.0);
+ std::fill(smax, smax + num_phases_*n, 1.0);
}
diff --git a/opm/core/fluid/SaturationPropsBasic.hpp b/opm/core/fluid/SaturationPropsBasic.hpp
index 789e0a35..2f90672d 100644
--- a/opm/core/fluid/SaturationPropsBasic.hpp
+++ b/opm/core/fluid/SaturationPropsBasic.hpp
@@ -40,16 +40,16 @@ namespace Opm
SaturationPropsBasic();
/// Initialize from parameters.
- /// The following parameters are accepted (defaults):
- /// num_phases (2) Must be 1 or 2.
- /// relperm_func ("Linear") Must be "Constant", "Linear" or "Quadratic".
+ /// The following parameters are accepted (defaults):
+ /// num_phases (2) Must be 1 or 2.
+ /// relperm_func ("Linear") Must be "Constant", "Linear" or "Quadratic".
void init(const parameter::ParameterGroup& param);
- enum RelPermFunc { Constant, Linear, Quadratic };
+ enum RelPermFunc { Constant, Linear, Quadratic };
/// Initialize from arguments a basic Saturation property.
void init(const int num_phases,
- const RelPermFunc& relperm_func)
+ const RelPermFunc& relperm_func)
{
num_phases_ = num_phases;
relperm_func_ = relperm_func;
@@ -86,18 +86,18 @@ namespace Opm
double* pc,
double* dpcds) const;
- /// Obtain the range of allowable saturation values.
+ /// Obtain the range of allowable saturation values.
/// \param[in] n Number of data points.
/// \param[out] smin Array of nP minimum s values, array must be valid before calling.
/// \param[out] smax Array of nP maximum s values, array must be valid before calling.
- void satRange(const int n,
- double* smin,
- double* smax) const;
+ void satRange(const int n,
+ double* smin,
+ double* smax) const;
private:
- int num_phases_;
- RelPermFunc relperm_func_;
+ int num_phases_;
+ RelPermFunc relperm_func_;
};
diff --git a/opm/core/fluid/SaturationPropsFromDeck.cpp b/opm/core/fluid/SaturationPropsFromDeck.cpp
index 89f81278..83c942c5 100644
--- a/opm/core/fluid/SaturationPropsFromDeck.cpp
+++ b/opm/core/fluid/SaturationPropsFromDeck.cpp
@@ -18,7 +18,7 @@
*/
#include
-#include
+#include
#include
#include
#include
@@ -26,368 +26,8 @@
namespace Opm
{
- /// Default constructor.
- SaturationPropsFromDeck::SaturationPropsFromDeck()
- {
- }
-
- /// Initialize from deck.
- void SaturationPropsFromDeck::init(const EclipseGridParser& deck,
- const std::vector& global_cell)
- {
- phase_usage_ = phaseUsageFromDeck(deck);
-
- // Extract input data.
- // Oil phase should be active.
- if (!phase_usage_.phase_used[Liquid]) {
- THROW("SaturationPropsFromDeck::init() -- oil phase must be active.");
- }
-
- // Obtain SATNUM, if it exists, and create cell_to_func_.
- // Otherwise, let the cell_to_func_ mapping be just empty.
- int satfuncs_expected = 1;
- if (deck.hasField("SATNUM")) {
- const std::vector& satnum = deck.getIntegerValue("SATNUM");
- satfuncs_expected = *std::max_element(satnum.begin(), satnum.end());
- int num_cells = global_cell.size();
- cell_to_func_.resize(num_cells);
- for (int cell = 0; cell < num_cells; ++cell) {
- cell_to_func_[cell] = satnum[global_cell[cell]] - 1;
- }
- }
-
- // Find number of tables, check for consistency.
- enum { Uninitialized = -1 };
- int num_tables = Uninitialized;
- if (phase_usage_.phase_used[Aqua]) {
- const SWOF::table_t& swof_table = deck.getSWOF().swof_;
- num_tables = swof_table.size();
- if (num_tables < satfuncs_expected) {
- THROW("Found " << num_tables << " SWOF tables, SATNUM specifies at least " << satfuncs_expected);
- }
- }
- if (phase_usage_.phase_used[Vapour]) {
- const SGOF::table_t& sgof_table = deck.getSGOF().sgof_;
- int num_sgof_tables = sgof_table.size();
- if (num_sgof_tables < satfuncs_expected) {
- THROW("Found " << num_tables << " SGOF tables, SATNUM specifies at least " << satfuncs_expected);
- }
- if (num_tables == Uninitialized) {
- num_tables = num_sgof_tables;
- } else if (num_tables != num_sgof_tables) {
- THROW("Inconsistent number of tables in SWOF and SGOF.");
- }
- }
-
- // Initialize tables.
- satfuncset_.resize(num_tables);
- for (int table = 0; table < num_tables; ++table) {
- satfuncset_[table].init(deck, table, phase_usage_);
- }
- }
-
-
-
-
- /// \return P, the number of phases.
- int SaturationPropsFromDeck::numPhases() const
- {
- return phase_usage_.num_phases;
- }
-
-
-
-
- /// Relative permeability.
- /// \param[in] n Number of data points.
- /// \param[in] s Array of nP saturation values.
- /// \param[in] cells Array of n cell indices to be associated with the s values.
- /// \param[out] kr Array of nP relperm values, array must be valid before calling.
- /// \param[out] dkrds If non-null: array of nP^2 relperm derivative values,
- /// array must be valid before calling.
- /// The P^2 derivative matrix is
- /// m_{ij} = \frac{dkr_i}{ds^j},
- /// and is output in Fortran order (m_00 m_10 m_20 m01 ...)
- void SaturationPropsFromDeck::relperm(const int n,
- const double* s,
- const int* cells,
- double* kr,
- double* dkrds) const
- {
- ASSERT (cells != 0);
-
- const int np = phase_usage_.num_phases;
- if (dkrds) {
-// #pragma omp parallel for
- for (int i = 0; i < n; ++i) {
- funcForCell(cells[i]).evalKrDeriv(s + np*i, kr + np*i, dkrds + np*np*i);
- }
- } else {
-// #pragma omp parallel for
- for (int i = 0; i < n; ++i) {
- funcForCell(cells[i]).evalKr(s + np*i, kr + np*i);
- }
- }
- }
-
-
-
-
- /// Capillary pressure.
- /// \param[in] n Number of data points.
- /// \param[in] s Array of nP saturation values.
- /// \param[in] cells Array of n cell indices to be associated with the s values.
- /// \param[out] pc Array of nP capillary pressure values, array must be valid before calling.
- /// \param[out] dpcds If non-null: array of nP^2 derivative values,
- /// array must be valid before calling.
- /// The P^2 derivative matrix is
- /// m_{ij} = \frac{dpc_i}{ds^j},
- /// and is output in Fortran order (m_00 m_10 m_20 m01 ...)
- void SaturationPropsFromDeck::capPress(const int n,
- const double* s,
- const int* cells,
- double* pc,
- double* dpcds) const
- {
- ASSERT (cells != 0);
-
- const int np = phase_usage_.num_phases;
- if (dpcds) {
-// #pragma omp parallel for
- for (int i = 0; i < n; ++i) {
- funcForCell(cells[i]).evalPcDeriv(s + np*i, pc + np*i, dpcds + np*np*i);
- }
- } else {
-// #pragma omp parallel for
- for (int i = 0; i < n; ++i) {
- funcForCell(cells[i]).evalPc(s + np*i, pc + np*i);
- }
- }
- }
-
-
-
-
- /// Obtain the range of allowable saturation values.
- /// \param[in] n Number of data points.
- /// \param[in] cells Array of n cell indices.
- /// \param[out] smin Array of nP minimum s values, array must be valid before calling.
- /// \param[out] smax Array of nP maximum s values, array must be valid before calling.
- void SaturationPropsFromDeck::satRange(const int n,
- const int* cells,
- double* smin,
- double* smax) const
- {
- ASSERT (cells != 0);
-
- const int np = phase_usage_.num_phases;
- for (int i = 0; i < n; ++i) {
- for (int p = 0; p < np; ++p) {
- smin[np*i + p] = funcForCell(cells[i]).smin_[p];
- smax[np*i + p] = funcForCell(cells[i]).smax_[p];
- }
- }
- }
-
-
- // Map the cell number to the correct function set.
- const SaturationPropsFromDeck::SatFuncSet&
- SaturationPropsFromDeck::funcForCell(const int cell) const
- {
- return cell_to_func_.empty() ? satfuncset_[0] : satfuncset_[cell_to_func_[cell]];
- }
-
-
-
- // ----------- Methods of SatFuncSet below -----------
-
-
- void SaturationPropsFromDeck::SatFuncSet::init(const EclipseGridParser& deck,
- const int table_num,
- const PhaseUsage phase_usg)
- {
- phase_usage = phase_usg;
- const int samples = 200;
- double swco = 0.0;
- double swmax = 1.0;
- if (phase_usage.phase_used[Aqua]) {
- const SWOF::table_t& swof_table = deck.getSWOF().swof_;
- const std::vector& sw = swof_table[table_num][0];
- const std::vector