Merge pull request #1107 from bska/decouple-libecl-final

Decouple OPM Flow From Libecl
This commit is contained in:
Bård Skaflestad
2019-10-16 21:44:53 -05:00
committed by GitHub
23 changed files with 401 additions and 616 deletions

View File

@@ -225,14 +225,11 @@ if (OPM_ENABLE_PYTHON)
set(PYTHON_INSTALL_PREFIX "lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/${PYTHON_PACKAGE_PATH}" CACHE STRING "Subdirectory to install Python modules in")
make_directory(${CMAKE_BINARY_DIR}/python)
get_target_property(_ecl_include_dirs ecl INTERFACE_INCLUDE_DIRECTORIES)
get_target_property(_opmcommon_include_dirs opmcommon INCLUDE_DIRECTORIES)
list(APPEND _opmcommon_include_dirs ${_ecl_include_dirs})
string(REPLACE ";" ":" _setup_include_dirs "${_opmcommon_include_dirs}")
get_target_property(_ecl_lib ecl LOCATION)
get_filename_component(_ecl_lib_dir ${_ecl_lib} DIRECTORY)
set(_opmcommon_lib_dirs ${_ecl_lib_dir} ${CMAKE_BINARY_DIR}/lib ${CMAKE_PREFIX_PATH}/lib)
set(_opmcommon_lib_dirs ${CMAKE_BINARY_DIR}/lib ${CMAKE_PREFIX_PATH}/lib)
string(REPLACE ";" ":" _setup_lib_dirs "${_opmcommon_lib_dirs}")
add_custom_command(OUTPUT python/python/opm/libopmcommon_python.so

View File

@@ -35,6 +35,7 @@ list (APPEND MAIN_SOURCE_FILES
src/opm/common/utility/parameters/ParameterGroup.cpp
src/opm/common/utility/parameters/ParameterTools.cpp
src/opm/common/utility/numeric/calculateCellVol.cpp
src/opm/common/utility/TimeService.cpp
)
if(ENABLE_ECL_INPUT)
list(APPEND MAIN_SOURCE_FILES
@@ -451,6 +452,7 @@ list( APPEND PUBLIC_HEADER_FILES
opm/common/utility/parameters/ParameterStrings.hpp
opm/common/utility/parameters/ParameterTools.hpp
opm/common/utility/numeric/calculateCellVol.hpp
opm/common/utility/TimeService.hpp
)
if(ENABLE_ECL_INPUT)
list(APPEND PUBLIC_HEADER_FILES

View File

@@ -1,5 +1,5 @@
# Libs to link tests against
set(TEST_LIBS opmcommon ecl Boost::unit_test_framework)
set(TEST_LIBS opmcommon Boost::unit_test_framework)
set(EXTRA_TESTS)
# Generated source, needs to be here

View File

@@ -32,7 +32,7 @@ if(NOT cjson_FOUND)
endif()
add_executable(genkw ${genkw_SOURCES})
target_link_libraries(genkw ecl Boost::regex Boost::filesystem Boost::system)
target_link_libraries(genkw Boost::regex Boost::filesystem Boost::system)
# Generate keyword list
include(src/opm/parser/eclipse/share/keywords/keyword_list.cmake)

View File

@@ -1,287 +0,0 @@
# - Find the Ensemble-based Reservoir Tool (ERT)
#
# Set the cache variable ERT_ROOT to the install location of the ERT
# libraries and header files.
#
# If found, it sets these variables:
#
# ERT_INCLUDE_DIRS Header file directories
# ERT_LIBRARIES Archives and shared objects
# ERT_CONFIG_VARS Definitions that goes in config.h
# ERT_LINKER_FLAGS Options that must be passed to linker
#
# It will also add to CMAKE_C_FLAGS and CMAKE_CXX_FLAGS if necessary to
# link with the ERT libraries.
# variables to pass on to other packages
if (FIND_QUIETLY)
set (ERT_QUIET "QUIET")
else (FIND_QUIETLY)
set (ERT_QUIET "")
endif (FIND_QUIETLY)
# if a directory has been specified by the user, then don't go look
# in the system directories as well
if (ERT_ROOT)
set (_no_default_path "NO_DEFAULT_PATH")
else (ERT_ROOT)
set (_no_default_path "")
endif (ERT_ROOT)
# ERT doesn't have any config-mode file, so we need to specify the root
# directory in its own variable
find_path (ERT_ECL_INCLUDE_DIR
NAMES "ert/ecl/ecl_util.h"
HINTS "${ERT_ROOT}"
PATHS "${PROJECT_SOURCE_DIR}/../libecl" "${PROJECT_SOURCE_DIR}/../ert"
PATH_SUFFIXES "libecl/include/" "include"
DOC "Path to ERT Eclipse library header files"
${_no_default_path}
)
find_path (ERT_ECL_WELL_INCLUDE_DIR
NAMES "ert/ecl_well/well_const.h"
HINTS "${ERT_ROOT}"
PATHS "${PROJECT_SOURCE_DIR}/../libecl" "${PROJECT_SOURCE_DIR}/../ert"
PATH_SUFFIXES "libecl_well/include/" "include"
DOC "Path to ERT Eclipse library header files"
${_no_default_path}
)
find_path (ERT_ECLXX_INCLUDE_DIR
NAMES "ert/ecl/EclKW.hpp"
HINTS "${ERT_ROOT}"
PATHS "${PROJECT_SOURCE_DIR}/../libecl" "${PROJECT_SOURCE_DIR}/../ert"
PATH_SUFFIXES "libeclxx/include/" "include"
DOC "Path to ERT Eclipse C++ library header files"
${_no_default_path}
)
find_path (ERT_UTIL_INCLUDE_DIR
NAMES "ert/util/stringlist.h"
HINTS "${ERT_ROOT}"
PATHS "${PROJECT_SOURCE_DIR}/../libecl" "${PROJECT_SOURCE_DIR}/../ert"
PATH_SUFFIXES "libert_util/include/" "include"
DOC "Path to ERT Eclipse library header files"
${_no_default_path}
)
find_path (ERT_UTILXX_INCLUDE_DIR
NAMES "ert/util/ert_unique_ptr.hpp"
HINTS "${ERT_ROOT}"
PATHS "${PROJECT_SOURCE_DIR}/../libecl" "${PROJECT_SOURCE_DIR}/../ert"
PATH_SUFFIXES "libert_utilxx/include/" "include"
DOC "Path to ERT Eclipse C++ library header files"
${_no_default_path}
)
find_path (ERT_GEN_INCLUDE_DIR
NAMES "ert/util/int_vector.h"
HINTS "${ERT_ROOT}"
PATHS "${PROJECT_SOURCE_DIR}/../libecl" "${PROJECT_SOURCE_DIR}/../ert"
PATH_SUFFIXES "libert_util/include"
"include" "build/libert_util/include" "build/libert_util/include"
DOC "Path to ERT generated library header files"
${_no_default_path}
)
# need all of these libraries
if (CMAKE_SIZEOF_VOID_P)
math (EXPR _BITS "8 * ${CMAKE_SIZEOF_VOID_P}")
endif (CMAKE_SIZEOF_VOID_P)
find_library (ERT_LIBRARY_ECL
NAMES "ecl"
HINTS "${ERT_ROOT}"
PATHS "${PROJECT_BINARY_DIR}/../libecl"
"${PROJECT_SOURCE_DIR}/../libecl/build"
"${PROJECT_BINARY_DIR}/../libecl-build"
"${PROJECT_BINARY_DIR}/../ert"
"${PROJECT_SOURCE_DIR}/../ert/build"
"${PROJECT_BINARY_DIR}/../ert-build"
PATH_SUFFIXES "lib" "lib/Release" "lib/Debug" "lib${_BITS}" "lib/${CMAKE_LIBRARY_ARCHITECTURE}"
DOC "Path to ERT Eclipse library archive/shared object files"
${_no_default_path}
)
find_library (ERT_LIBRARY_ECLXX
NAMES "eclxx"
HINTS "${ERT_ROOT}"
PATHS "${PROJECT_BINARY_DIR}/../libecl"
"${PROJECT_SOURCE_DIR}/../libecl/build"
"${PROJECT_BINARY_DIR}/../libecl-build"
"${PROJECT_BINARY_DIR}/../ert"
"${PROJECT_SOURCE_DIR}/../ert/build"
"${PROJECT_BINARY_DIR}/../ert-build"
PATH_SUFFIXES "lib" "lib/Release" "lib/Debug" "lib${_BITS}" "lib/${CMAKE_LIBRARY_ARCHITECTURE}"
DOC "Path to ERT Eclipse C++ library archive/shared object files"
${_no_default_path}
)
find_library (ERT_LIBRARY_ECL_WELL
NAMES "ecl_well"
HINTS "${ERT_ROOT}"
PATHS "${PROJECT_BINARY_DIR}/../libecl"
"${PROJECT_SOURCE_DIR}/../libecl/build"
"${PROJECT_BINARY_DIR}/../libecl-build"
"${PROJECT_BINARY_DIR}/../ert"
"${PROJECT_SOURCE_DIR}/../ert/build"
"${PROJECT_BINARY_DIR}/../ert-build"
PATH_SUFFIXES "lib" "lib/Release" "lib/Debug" "lib${_BITS}" "lib/${CMAKE_LIBRARY_ARCHITECTURE}"
DOC "Path to ERT Eclipse library archive/shared object files"
${_no_default_path}
)
find_library (ERT_LIBRARY_GEOMETRY
NAMES "ert_geometry"
HINTS "${ERT_ROOT}"
PATHS "${PROJECT_BINARY_DIR}/../libecl"
"${PROJECT_SOURCE_DIR}/../libecl/build"
"${PROJECT_BINARY_DIR}/../libecl-build"
"${PROJECT_BINARY_DIR}/../ert"
"${PROJECT_SOURCE_DIR}/../ert/build"
"${PROJECT_BINARY_DIR}/../ert-build"
PATH_SUFFIXES "lib" "lib/Release" "lib/Debug" "lib${_BITS}" "lib/${CMAKE_LIBRARY_ARCHITECTURE}"
DOC "Path to ERT Geometry library archive/shared object files"
${_no_default_path}
)
find_library (ERT_LIBRARY_UTIL
NAMES "ert_util"
HINTS "${ERT_ROOT}"
PATHS "${PROJECT_BINARY_DIR}/../libecl"
"${PROJECT_SOURCE_DIR}/../libecl/build"
"${PROJECT_BINARY_DIR}/../libecl-build"
"${PROJECT_BINARY_DIR}/../ert"
"${PROJECT_SOURCE_DIR}/../ert/build"
"${PROJECT_BINARY_DIR}/../ert-build"
PATH_SUFFIXES "lib" "lib/Release" "lib/Debug" "lib${_BITS}" "lib/${CMAKE_LIBRARY_ARCHITECTURE}"
DOC "Path to ERT Utilities library archive/shared object files"
${_no_default_path}
)
find_library (ERT_LIBRARY_UTILXX
NAMES "ert_utilxx"
HINTS "${ERT_ROOT}"
PATHS "${PROJECT_BINARY_DIR}/../libecl"
"${PROJECT_SOURCE_DIR}/../libecl/build"
"${PROJECT_BINARY_DIR}/../libecl-build"
"${PROJECT_BINARY_DIR}/../ert"
"${PROJECT_SOURCE_DIR}/../ert/build"
"${PROJECT_BINARY_DIR}/../ert-build"
PATH_SUFFIXES "lib" "lib/Release" "lib/Debug" "lib${_BITS}" "lib/${CMAKE_LIBRARY_ARCHITECTURE}"
DOC "Path to ERT Utilities library archive/shared object files"
${_no_default_path}
)
# the "library" found here is actually a list of several files
list (APPEND ERT_INCLUDE_DIR
${ERT_ECL_INCLUDE_DIR}
${ERT_ECL_WELL_INCLUDE_DIR}
${ERT_ECLXX_INCLUDE_DIR}
${ERT_UTIL_INCLUDE_DIR}
${ERT_UTILXX_INCLUDE_DIR}
${ERT_GEN_INCLUDE_DIR}
)
list (APPEND ERT_LIBRARY
${ERT_LIBRARY_ECL}
${ERT_LIBRARY_ECLXX}
${ERT_LIBRARY_ECL_WELL}
${ERT_LIBRARY_GEOMETRY}
${ERT_LIBRARY_UTIL}
${ERT_LIBRARY_UTILXX}
)
list (APPEND ERT_LIBRARIES ${ERT_LIBRARY})
list (APPEND ERT_INCLUDE_DIRS ${ERT_INCLUDE_DIR})
# if we didn't find any files, then don't proceed through the entire dependency list
include (FindPackageHandleStandardArgs)
if (ERT_INCLUDE_DIR MATCHES "-NOTFOUND" OR ERT_LIBRARIES MATCHES "-NOTFOUND")
find_package_handle_standard_args (ERT
DEFAULT_MSG
ERT_INCLUDE_DIR ERT_LIBRARY
)
# clear the cache so the find probe is attempted again if files becomes
# available (only upon a unsuccessful *compile* should we disable further
# probing)
set (HAVE_ERT)
unset (HAVE_ERT CACHE)
return ()
endif (ERT_INCLUDE_DIR MATCHES "-NOTFOUND" OR ERT_LIBRARIES MATCHES "-NOTFOUND")
# dependencies
# parallel programming
include (UseOpenMP)
find_openmp (ERT)
# compression library
find_package (ZLIB ${ERT_QUIET})
if (ZLIB_FOUND)
list (APPEND ERT_INCLUDE_DIRS ${ZLIB_INCLUDE_DIRS})
list (APPEND ERT_LIBRARIES ${ZLIB_LIBRARIES})
endif (ZLIB_FOUND)
# numerics
find_package (BLAS ${ERT_QUIET})
if (BLAS_FOUND)
list (APPEND ERT_INCLUDE_DIRS ${BLAS_INCLUDE_DIRS})
list (APPEND ERT_LIBRARIES ${BLAS_LIBRARIES})
list (APPEND ERT_LINKER_FLAGS ${BLAS_LINKER_FLAGS})
endif (BLAS_FOUND)
find_package (LAPACK ${ERT_QUIET})
if (LAPACK_FOUND)
list (APPEND ERT_INCLUDE_DIRS ${LAPACK_INCLUDE_DIRS})
list (APPEND ERT_LIBRARIES ${LAPACK_LIBRARIES})
list (APPEND ERT_LINKER_FLAGS ${LAPACK_LINKER_FLAGS})
endif (LAPACK_FOUND)
# math library (should exist on all unices; automatically linked on Windows)
if (UNIX)
find_library (MATH_LIBRARY
NAMES "m"
)
list (APPEND ERT_LIBRARIES ${MATH_LIBRARY})
endif (UNIX)
# if shared libraries are disabled on linux, explcitly linking to the
# pthreads library is required by ERT
find_package(Threads ${ERT_QUIET})
if (CMAKE_THREAD_LIBS_INIT)
list (APPEND ERT_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
endif()
# Platform specific library where dlopen with friends lives
list (APPEND ERT_LIBRARIES ${CMAKE_DL_LIBS})
# since OpenMP often implies pthreads, we need to tidy up
# (last instance of library must be left standing, thus reversing that
# list before removing duplicates)
include (Duplicates)
remove_dup_deps (ERT)
# see if we can compile a minimum example
# CMake logical test doesn't handle lists (sic)
if (NOT (ERT_INCLUDE_DIR MATCHES "-NOTFOUND" OR ERT_LIBRARIES MATCHES "-NOTFOUND"))
include (CMakePushCheckState)
include (CheckCSourceCompiles)
cmake_push_check_state ()
set (CMAKE_REQUIRED_INCLUDES ${ERT_INCLUDE_DIR})
set (CMAKE_REQUIRED_LIBRARIES ${ERT_LIBRARIES})
check_cxx_source_compiles (
"#include <ert/ecl/ecl_grid.h>
int main ( ) {
ecl_grid_type * grid = ecl_grid_alloc_rectangular( 10,10,10,1,1,1, NULL);
ecl_grid_free( grid );
return 0;
}" HAVE_ERT)
cmake_pop_check_state ()
else (NOT (ERT_INCLUDE_DIR MATCHES "-NOTFOUND" OR ERT_LIBRARIES MATCHES "-NOTFOUND"))
# clear the cache so the find probe is attempted again if files becomes
# available (only upon a unsuccessful *compile* should we disable further
# probing)
set (HAVE_ERT)
unset (HAVE_ERT CACHE)
endif (NOT (ERT_INCLUDE_DIR MATCHES "-NOTFOUND" OR ERT_LIBRARIES MATCHES "-NOTFOUND"))
# if the test program didn't compile, but was required to do so, bail
# out now and display an error; otherwise limp on
find_package_handle_standard_args (ERT
DEFAULT_MSG
ERT_INCLUDE_DIR ERT_LIBRARY HAVE_ERT
)

View File

@@ -1,53 +0,0 @@
# - Find the Python wrappers for Ensemble-based Reservoir Tool (ERT)
#
# Set the cache variable ERT_PYTHON_PATH to the install location of
# the root ert package.
find_package(PythonInterp)
if(PYTHONINTERP_FOUND)
# We try to find the ert Python distribution. This is done by running
# Python code which tries to 'import ert' and prints out the path to
# the module if the import succeeds.
#
# The normal Python import machinery is employed, so if you have
# installed ert python in a default location, or alternatively set the
# PYTHONPATH variable the ert Python distribution will eventually be
# found there, independently of the alternatives which are tested with
# the ${PATH_LIST} variable.
if (EXISTS "/etc/debian_version")
set( PYTHON_PACKAGE_PATH "dist-packages")
else()
set( PYTHON_PACKAGE_PATH "site-packages")
endif()
set(PYTHON_INSTALL_PREFIX "lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/${PYTHON_PACKAGE_PATH}" CACHE STRING "Subdirectory to install Python modules in")
set(PATH_LIST)
if (ERT_ROOT)
list(APPEND PATH_LIST ${ERT_ROOT})
endif()
list(APPEND PATH_LIST ${CMAKE_PREFIX_PATH})
# Add various popular sibling alternatives.
list(APPEND PATH_LIST "${PROJECT_SOURCE_DIR}/../ert/build"
"${PROJECT_BINARY_DIR}/../ert-build")
foreach( PATH ${PATH_LIST})
set( python_code "import sys; sys.path.insert(0 , '${PATH}/${PYTHON_INSTALL_PREFIX}'); import os.path; import inspect; import ert; print os.path.dirname(os.path.dirname(inspect.getfile(ert))); from ert.ecl import EclSum")
execute_process( COMMAND ${PYTHON_EXECUTABLE} -c "${python_code}"
RESULT_VARIABLE import_result
OUTPUT_VARIABLE stdout_output
ERROR_VARIABLE stderr_output
OUTPUT_STRIP_TRAILING_WHITESPACE )
if (${import_result} EQUAL 0)
set( ERT_PYTHON_PATH ${stdout_output} CACHE PATH "Python path for ERT Python" )
break()
endif()
endforeach()
endif()
find_package_handle_standard_args("ERTPython" DEFAULT_MSG ERT_PYTHON_PATH)

View File

@@ -152,22 +152,7 @@ macro (find_and_append_package_to prefix name)
if ( (NOT DEFINED ${name}_FOUND AND NOT DEFINED ${NAME}_FOUND )
OR _search_components GREATER -1)
string(REGEX MATCH "(dune|opm)-.*" _is_opm ${name})
if(${name} STREQUAL "ecl")
# Give us a chance to find ecl installed to CMAKE_INSTALL_PREFIX.
# We need to deactivate the package registry for this.
create_module_dir_var(ecl)
set(ARGN_NO_REQUIRED ${ARGN})
if(ARGN)
list(REMOVE_ITEM ARGN_NO_REQUIRED "REQUIRED")
endif()
find_package (${name} ${ARGN_NO_REQUIRED} NO_CMAKE_SYSTEM_PACKAGE_REGISTRY NO_CMAKE_PACKAGE_REGISTRY)
if(TARGET ecl)
# Need to grab from target to enable transitional depends
#get_target_property(ecl_INCLUDE_DIRS ecl INTERFACE_INCLUDE_DIRECTORIES)
set(ecl_LIBRARIES ecl)
set(HAVE_ERT 1)
endif()
elseif(_${name}_exempted LESS 0 AND NOT _is_opm)
if(_${name}_exempted LESS 0 AND NOT _is_opm)
find_package (${name} ${ARGN})
elseif(_${name}_exempted GREATER -1)
find_package (${name} ${ARGN})

View File

@@ -9,12 +9,7 @@ macro(create_module_dir_var module)
get_filename_component(_parent_dir_name ${_parent_full_dir} NAME)
#Try if <module-name>/<build-dir> is used
get_filename_component(_modules_dir ${_parent_full_dir} DIRECTORY)
if ("${module}" STREQUAL "ecl")
#use clone directory libecl
set(_clone_dir "libecl")
else()
set(_clone_dir "${module}")
endif()
set(_clone_dir "${module}")
if(IS_DIRECTORY ${_modules_dir}/${_clone_dir}/${_leaf_dir_name})
set(${module}_DIR ${_modules_dir}/${_clone_dir}/${_leaf_dir_name})
else()

2
debian/control vendored
View File

@@ -5,7 +5,7 @@ Build-Depends: build-essential, debhelper (>= 9),
pkg-config, cmake, git, libtool, doxygen,
texlive-latex-extra, texlive-latex-recommended,
ghostscript, libboost-system-dev, libboost-test-dev,
libecl-dev, libboost-regex-dev, libboost-filesystem-dev,
libboost-regex-dev, libboost-filesystem-dev,
zlib1g-dev
Standards-Version: 3.9.2
Section: libs

View File

@@ -5,7 +5,6 @@ declare -A configurations
declare -A EXTRA_MODULE_FLAGS
EXTRA_MODULE_FLAGS[opm-simulators]="-DBUILD_EBOS_EXTENSIONS=ON -DBUILD_EBOS_DEBUG_EXTENSIONS=ON -DBUILD_FLOW_VARIANTS=ON"
EXTRA_MODULE_FLAGS[opm-common]="-DOPM_ENABLE_PYTHON=ON -DOPM_ENABLE_EMBEDDED_PYTHON=ON -DOPM_INSTALL_PYTHON=ON"
EXTRA_MODULE_FLAGS[libecl]="-DCMAKE_POSITION_INDEPENDENT_CODE=1"
# Parse revisions from trigger comment and setup arrays
# Depends on: 'upstreams', upstreamRev',
@@ -13,7 +12,6 @@ EXTRA_MODULE_FLAGS[libecl]="-DCMAKE_POSITION_INDEPENDENT_CODE=1"
# 'ghprbCommentBody',
# 'CONFIGURATIONS', 'TOOLCHAINS'
function parseRevisions {
# Set default for libecl to be last known good commit.
for upstream in ${upstreams[*]}
do
if grep -qi "$upstream=" <<< $ghprbCommentBody
@@ -148,12 +146,7 @@ function clone_module {
mkdir -p $WORKSPACE/deps/$1
cd $WORKSPACE/deps/$1
git init .
if [ "$1" == "libecl" ]
then
git remote add origin https://github.com/equinor/$1
else
git remote add origin https://github.com/OPM/$1
fi
git remote add origin https://github.com/OPM/$1
git fetch --depth 1 origin $2:branch_to_build
git checkout branch_to_build
git log HEAD -1 | cat

View File

@@ -6,11 +6,9 @@ source `dirname $0`/build-opm-module.sh
mkdir deps
ln -sf $WORKSPACE deps/opm-common
# No upstreams
declare -a upstreams
upstreams=(libecl)
declare -A upstreamRev
upstreamRev[libecl]=master
# Downstreams and revisions
declare -a downstreams

View File

@@ -15,7 +15,6 @@ set (opm-common_DEPS
if(ENABLE_ECL_INPUT)
list(APPEND opm-common_DEPS
"ecl REQUIRED"
# various runtime library enhancements
"Boost 1.44.0
COMPONENTS system filesystem unit_test_framework regex REQUIRED")

View File

@@ -0,0 +1,68 @@
/*
Copyright 2019 Equinor ASA.
This file is part of the Open Porous Media Project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_TIMESERVICE_HEADER_INCLUDED
#define OPM_TIMESERVICE_HEADER_INCLUDED
#include <ctime>
namespace Opm {
class TimeStampUTC
{
public:
struct YMD {
int year{0};
int month{0};
int day{0};
};
TimeStampUTC() = default;
explicit TimeStampUTC(const std::time_t tp);
explicit TimeStampUTC(const YMD& ymd);
TimeStampUTC& operator=(const std::time_t tp);
TimeStampUTC& hour(const int h);
TimeStampUTC& minutes(const int m);
TimeStampUTC& seconds(const int s);
TimeStampUTC& microseconds(const int us);
int year() const { return this->ymd_.year; }
int month() const { return this->ymd_.month; }
int day() const { return this->ymd_.day; }
int hour() const { return this->hour_; }
int minutes() const { return this->minutes_; }
int seconds() const { return this->seconds_; }
int microseconds() const { return this->usec_; }
private:
YMD ymd_{};
int hour_{0};
int minutes_{0};
int seconds_{0};
int usec_{0};
};
std::time_t asTimeT(const TimeStampUTC& tp);
} // namespace Opm
#endif // OPM_TIMESERVICE_HEADER_INCLUDED

View File

@@ -25,6 +25,8 @@
#include <ctime>
#include <map>
#include <stddef.h>
namespace Opm {
class Deck;

View File

@@ -47,7 +47,7 @@ ext_modules = [
'cxx/well.cpp',
'cxx/export.cpp'
],
libraries=['opmcommon', 'boost_filesystem', 'boost_regex', 'ecl', 'z'],
libraries=['opmcommon', 'boost_filesystem', 'boost_regex'],
language='c++',
undef_macros=["NDEBUG"],
include_dirs=["pybind11/include"]

View File

@@ -12,7 +12,7 @@ License: GPL-3.0
Group: Development/Libraries/C and C++
Url: http://www.opm-project.org/
Source0: https://github.com/OPM/%{name}/archive/release/%{version}/%{tag}.tar.gz#/%{name}-%{version}.tar.gz
BuildRequires: git doxygen bc devtoolset-6-toolchain ecl-devel openmpi-devel mpich-devel zlib-devel
BuildRequires: git doxygen bc devtoolset-6-toolchain openmpi-devel mpich-devel
%{?el6:BuildRequires: cmake3 boost148-devel}
%{!?el6:BuildRequires: cmake boost-devel}
BuildRoot: %{_tmppath}/%{name}-%{version}-build

View File

@@ -0,0 +1,119 @@
/*
Copyright 2019 Equinor ASA.
This file is part of the Open Porous Media Project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <opm/common/utility/TimeService.hpp>
#include <chrono>
#include <ctime>
#include <utility>
namespace {
std::time_t advance(const std::time_t tp, const double sec)
{
using namespace std::chrono;
using TP = time_point<system_clock>;
using DoubSec = duration<double, seconds::period>;
const auto t = system_clock::from_time_t(tp) +
duration_cast<TP::duration>(DoubSec(sec));
return system_clock::to_time_t(t);
}
std::time_t makeUTCTime(std::tm timePoint)
{
const auto ltime = std::mktime(&timePoint);
auto tmval = *std::gmtime(&ltime); // Mutable.
// offset = ltime - tmval
// == #seconds by which 'ltime' is AHEAD of tmval.
const auto offset =
std::difftime(ltime, std::mktime(&tmval));
// Advance 'ltime' by 'offset' so that std::gmtime(return value) will
// have the same broken-down elements as 'tp'.
return advance(ltime, offset);
}
}
Opm::TimeStampUTC::TimeStampUTC(const std::time_t tp)
{
auto t = tp;
const auto tm = *std::gmtime(&t);
this->ymd_ = YMD { tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday };
this->hour(tm.tm_hour).minutes(tm.tm_min).seconds(tm.tm_sec);
}
Opm::TimeStampUTC& Opm::TimeStampUTC::operator=(const std::time_t tp)
{
auto t = tp;
const auto tm = *std::gmtime(&t);
this->ymd_ = YMD { tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday };
this->hour(tm.tm_hour).minutes(tm.tm_min).seconds(tm.tm_sec);
return *this;
}
Opm::TimeStampUTC::TimeStampUTC(const YMD& ymd)
: ymd_{ std::move(ymd) }
{}
Opm::TimeStampUTC& Opm::TimeStampUTC::hour(const int h)
{
this->hour_ = h;
return *this;
}
Opm::TimeStampUTC& Opm::TimeStampUTC::minutes(const int m)
{
this->minutes_ = m;
return *this;
}
Opm::TimeStampUTC& Opm::TimeStampUTC::seconds(const int s)
{
this->seconds_ = s;
return *this;
}
Opm::TimeStampUTC& Opm::TimeStampUTC::microseconds(const int us)
{
this->usec_ = us;
return *this;
}
std::time_t Opm::asTimeT(const TimeStampUTC& tp)
{
auto timePoint = std::tm{};
timePoint.tm_year = tp.year() - 1900;
timePoint.tm_mon = tp.month() - 1;
timePoint.tm_mday = tp.day();
timePoint.tm_hour = tp.hour();
timePoint.tm_min = tp.minutes();
timePoint.tm_sec = tp.seconds();
return makeUTCTime(timePoint);
}

View File

@@ -18,8 +18,9 @@
*/
#include <ctime>
#include <stddef.h>
#include <ert/util/util.h>
#include <opm/common/utility/TimeService.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
@@ -27,7 +28,6 @@
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/TimeMap.hpp>
namespace Opm {
namespace {
@@ -119,9 +119,14 @@ namespace {
const std::time_t lastTime = m_timeList.back();
const size_t step = m_timeList.size();
if (newTime > lastTime) {
int new_day, new_month, new_year, last_day, last_month, last_year;
util_set_date_values_utc(newTime, &new_day, &new_month, &new_year);
util_set_date_values_utc(lastTime, &last_day, &last_month, &last_year);
const auto nw = TimeStampUTC{ newTime };
const auto last = TimeStampUTC{ lastTime };
const auto new_month = nw .month();
const auto last_month = last.month();
const auto new_year = nw .year();
const auto last_year = last.year();
if (new_month != last_month)
m_first_timestep_months.push_back(step);
@@ -305,16 +310,18 @@ namespace {
}
std::time_t TimeMap::mkdatetime(int in_year, int in_month, int in_day, int hour, int minute, int second) {
std::time_t t = util_make_datetime_utc(second, minute, hour, in_day, in_month, in_year);
const auto tp = TimeStampUTC{ TimeStampUTC::YMD { in_year, in_month, in_day } }
.hour(hour).minutes(minute).seconds(second);
std::time_t t = asTimeT(tp);
{
/*
The underlying mktime( ) function will happily wrap
around dates like January 33, this function will check
that no such wrap-around has taken place.
*/
int out_year, out_day, out_month;
util_set_date_values_utc( t, &out_day , &out_month, &out_year);
if ((in_day != out_day) || (in_month != out_month) || (in_year != out_year))
const auto check = TimeStampUTC{ t };
if ((in_day != check.day()) || (in_month != check.month()) || (in_year != check.year()))
throw std::invalid_argument("Invalid input arguments for date.");
}
return t;

View File

@@ -16,14 +16,14 @@
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include <stdexcept>
#include <algorithm>
#include <opm/parser/eclipse/EclipseState/Tables/ColumnSchema.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/TableColumn.hpp>
#include <ert/util/ssize_t.h>
namespace Opm {
TableColumn::TableColumn(const ColumnSchema& schema) :
@@ -271,33 +271,37 @@ namespace Opm {
for (size_t rowIdx = 0; rowIdx < size(); ++rowIdx) {
if (defaultApplied( rowIdx )) {
// find first row which was not defaulted before the current one
ssize_t rowBeforeIdx = rowIdx;
int rowBeforeIdx = static_cast<int>(rowIdx);
for (; rowBeforeIdx >= 0; -- rowBeforeIdx)
if (!defaultApplied(rowBeforeIdx))
break;
// find first row which was not defaulted after the current one
ssize_t rowAfterIdx = rowIdx;
for (; rowAfterIdx < static_cast<ssize_t>(size()); ++ rowAfterIdx)
int rowAfterIdx = static_cast<int>(rowIdx);
for (; rowAfterIdx < static_cast<int>(size()); ++ rowAfterIdx)
if (!defaultApplied(rowAfterIdx))
break;
// switch to extrapolation by a constant at the fringes
if (rowBeforeIdx < 0 && rowAfterIdx >= static_cast<ssize_t>(size()))
if (rowBeforeIdx < 0 && rowAfterIdx >= static_cast<int>(size()))
throw std::invalid_argument("Column " + m_schema.name() + " can't be fully defaulted");
else if (rowBeforeIdx < 0)
rowBeforeIdx = rowAfterIdx;
else if (rowAfterIdx >= static_cast<ssize_t>(size()))
else if (rowAfterIdx >= static_cast<int>(size()))
rowAfterIdx = rowBeforeIdx;
{
const size_t before = static_cast<size_t>(rowBeforeIdx);
const size_t after = static_cast<size_t>(rowAfterIdx);
// linear interpolation
double alpha = 0.0;
if (rowBeforeIdx != rowAfterIdx)
alpha = (argColumn[rowIdx] - argColumn[rowBeforeIdx]) / (argColumn[rowAfterIdx] - argColumn[rowBeforeIdx]);
alpha = (argColumn[rowIdx] - argColumn[before])
/ (argColumn[after] - argColumn[before]);
double value = m_values[rowBeforeIdx]*(1-alpha) + m_values[rowAfterIdx]*alpha;
double value = m_values[before]*(1-alpha) + m_values[after]*alpha;
updateValue( rowIdx , value );
}

View File

@@ -26,7 +26,7 @@
#include <boost/test/unit_test.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <ert/util/util.hpp>
#include <opm/common/utility/TimeService.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
@@ -1163,18 +1163,15 @@ BOOST_AUTO_TEST_CASE(createDeckWithWPIMULT) {
BOOST_CHECK_EQUAL(cs4.get( i ).wellPi(), 1.0);
BOOST_CHECK_THROW(schedule.simTime(10000), std::invalid_argument);
auto sim_time1 = schedule.simTime(1);
int day, month,year;
util_set_date_values_utc(sim_time1, &day, &month, &year);
BOOST_CHECK_EQUAL(day, 10);
BOOST_CHECK_EQUAL(month, 10);
BOOST_CHECK_EQUAL(year, 2008);
auto sim_time1 = TimeStampUTC{ schedule.simTime(1) };
BOOST_CHECK_EQUAL(sim_time1.day(), 10);
BOOST_CHECK_EQUAL(sim_time1.month(), 10);
BOOST_CHECK_EQUAL(sim_time1.year(), 2008);
sim_time1 = schedule.simTime(3);
util_set_date_values_utc(sim_time1, &day, &month, &year);
BOOST_CHECK_EQUAL(day, 20);
BOOST_CHECK_EQUAL(month, 1);
BOOST_CHECK_EQUAL(year, 2011);
BOOST_CHECK_EQUAL(sim_time1.day(), 20);
BOOST_CHECK_EQUAL(sim_time1.month(), 1);
BOOST_CHECK_EQUAL(sim_time1.year(), 2011);
}
BOOST_AUTO_TEST_CASE(WELSPECS_WGNAME_SPACE) {
@@ -1385,7 +1382,7 @@ BOOST_AUTO_TEST_CASE(createDeckWithDRSDTthenDRVDT) {
"0.100\n"
"/\n"
"DATES -- 3\n"
" 10 OKT 20010 / \n"
" 10 OKT 2010 / \n"
"/\n"
"VAPPARS\n"
"2 0.100\n"

View File

@@ -25,7 +25,7 @@
#include <boost/test/unit_test.hpp>
#include <opm/common/utility/TimeService.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/TimeMap.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
@@ -35,7 +35,6 @@
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
#include <opm/parser/eclipse/Parser/Parser.hpp>
#include <ert/util/util.h>
const std::time_t startDateJan1st2010 = Opm::TimeMap::mkdate(2010, 1, 1);
@@ -346,14 +345,11 @@ BOOST_AUTO_TEST_CASE(initTimestepsLongStep) {
0 1 jan 1983 START
1 14 dec 2052*/
const std::time_t tEnd = tmap.getEndTime();
const auto tEnd = Opm::TimeStampUTC { tmap.getEndTime() };
int year, day, month;
util_set_date_values_utc(tEnd, &day, &month, &year);
BOOST_CHECK_EQUAL(year, 2052);
BOOST_CHECK_EQUAL(month, 12);
BOOST_CHECK_EQUAL(day, 14);
BOOST_CHECK_EQUAL(tEnd.year(), 2052);
BOOST_CHECK_EQUAL(tEnd.month(), 12);
BOOST_CHECK_EQUAL(tEnd.day(), 14);
}
@@ -375,14 +371,11 @@ BOOST_AUTO_TEST_CASE(TimestepsLabUnit) {
0 1 jan 1983 START
1 11 jan 1983*/
const std::time_t tEnd = tmap.getEndTime();
const auto tEnd = Opm::TimeStampUTC { tmap.getEndTime() };
int year, day, month;
util_set_date_values_utc(tEnd, &day, &month, &year);
BOOST_CHECK_EQUAL(year, 1983);
BOOST_CHECK_EQUAL(month, 1);
BOOST_CHECK_EQUAL(day, 11);
BOOST_CHECK_EQUAL(tEnd.year(), 1983);
BOOST_CHECK_EQUAL(tEnd.month(), 1);
BOOST_CHECK_EQUAL(tEnd.day(), 11);
}
@@ -405,73 +398,58 @@ BOOST_AUTO_TEST_CASE(initTimestepsDistantDates) {
1 1 jan 2040
2 1 jan 2050*/
const std::time_t t1 = tmap.getStartTime(1);
const std::time_t t2 = tmap.getEndTime();
const auto t1 = Opm::TimeStampUTC { tmap.getStartTime(1) };
const auto t2 = Opm::TimeStampUTC { tmap.getEndTime() };
int year, day, month;
BOOST_CHECK_EQUAL(t1.year(), 2040);
BOOST_CHECK_EQUAL(t1.month(), 1);
BOOST_CHECK_EQUAL(t1.day(), 1);
util_set_date_values_utc(t1, &day, &month, &year);
BOOST_CHECK_EQUAL(year, 2040);
BOOST_CHECK_EQUAL(month, 1);
BOOST_CHECK_EQUAL(day, 1);
util_set_date_values_utc(t2, &day, &month, &year);
BOOST_CHECK_EQUAL(year, 2050);
BOOST_CHECK_EQUAL(month, 1);
BOOST_CHECK_EQUAL(day, 1);
BOOST_CHECK_EQUAL(t2.year(), 2050);
BOOST_CHECK_EQUAL(t2.month(), 1);
BOOST_CHECK_EQUAL(t2.day(), 1);
}
BOOST_AUTO_TEST_CASE(mkdate) {
BOOST_CHECK_THROW( Opm::TimeMap::mkdate( 2010 , 0 , 0 ) , std::invalid_argument);
std::time_t t0 = Opm::TimeMap::mkdate( 2010 , 1, 1);
std::time_t t1 = Opm::TimeMap::forward( t0 , 24*3600);
auto t0 = Opm::TimeStampUTC { Opm::TimeMap::mkdate( 2010 , 1, 1) };
auto t1 = Opm::TimeStampUTC { Opm::TimeMap::forward( asTimeT(t0) , 24*3600) };
int year, day, month;
BOOST_CHECK_EQUAL( t1.year() , 2010 );
BOOST_CHECK_EQUAL( t1.month() , 1 );
BOOST_CHECK_EQUAL( t1.day() , 2 );
util_set_date_values_utc( t1, &day , &month, &year);
BOOST_CHECK_EQUAL( year , 2010 );
BOOST_CHECK_EQUAL( month , 1 );
BOOST_CHECK_EQUAL( day , 2 );
t1 = Opm::TimeMap::forward( asTimeT(t1) , -24*3600);
BOOST_CHECK_EQUAL( t1.year() , 2010 );
BOOST_CHECK_EQUAL( t1.month() , 1 );
BOOST_CHECK_EQUAL( t1.day() , 1 );
t1 = Opm::TimeMap::forward( t1 , -24*3600);
util_set_date_values_utc( t1, &day , &month, &year);
BOOST_CHECK_EQUAL( year , 2010 );
BOOST_CHECK_EQUAL( month , 1 );
BOOST_CHECK_EQUAL( day , 1 );
t1 = Opm::TimeMap::forward( t0 , 23, 55 , 300);
util_set_date_values_utc( t1, &day , &month, &year);
BOOST_CHECK_EQUAL( year , 2010 );
BOOST_CHECK_EQUAL( month , 1 );
BOOST_CHECK_EQUAL( day , 2 );
t1 = Opm::TimeMap::forward( asTimeT(t0) , 23, 55 , 300);
BOOST_CHECK_EQUAL( t1.year() , 2010 );
BOOST_CHECK_EQUAL( t1.month() , 1 );
BOOST_CHECK_EQUAL( t1.day() , 2 );
}
BOOST_AUTO_TEST_CASE(mkdatetime) {
BOOST_CHECK_THROW(Opm::TimeMap::mkdatetime(2010, 0, 0, 0, 0, 0), std::invalid_argument);
std::time_t t0 = Opm::TimeMap::mkdatetime(2010, 1, 1, 0, 0, 0);
std::time_t t1 = Opm::TimeMap::forward(t0, 24 * 3600);
auto t0 = Opm::TimeStampUTC { Opm::TimeMap::mkdatetime(2010, 1, 1, 0, 0, 0) };
auto t1 = Opm::TimeStampUTC { Opm::TimeMap::forward(asTimeT(t0), 24 * 3600) };
int year, day, month;
BOOST_CHECK_EQUAL(t1.year(), 2010);
BOOST_CHECK_EQUAL(t1.month(), 1);
BOOST_CHECK_EQUAL(t1.day(), 2);
util_set_date_values_utc(t1, &day, &month, &year);
BOOST_CHECK_EQUAL(year, 2010);
BOOST_CHECK_EQUAL(month, 1);
BOOST_CHECK_EQUAL(day, 2);
t1 = Opm::TimeMap::forward(asTimeT(t1), -24 * 3600);
BOOST_CHECK_EQUAL(t1.year(), 2010);
BOOST_CHECK_EQUAL(t1.month(), 1);
BOOST_CHECK_EQUAL(t1.day(), 1);
t1 = Opm::TimeMap::forward(t1, -24 * 3600);
util_set_date_values_utc(t1, &day, &month, &year);
BOOST_CHECK_EQUAL(year, 2010);
BOOST_CHECK_EQUAL(month, 1);
BOOST_CHECK_EQUAL(day, 1);
t1 = Opm::TimeMap::forward(t0, 23, 55, 300);
util_set_date_values_utc(t1, &day, &month, &year);
BOOST_CHECK_EQUAL(year, 2010);
BOOST_CHECK_EQUAL(month, 1);
BOOST_CHECK_EQUAL(day, 2);
t1 = Opm::TimeMap::forward(asTimeT(t0), 23, 55, 300);
BOOST_CHECK_EQUAL(t1.year(), 2010);
BOOST_CHECK_EQUAL(t1.month(), 1);
BOOST_CHECK_EQUAL(t1.day(), 2);
}
Opm::DeckRecord createDeckRecord(int day, const std::string &month, int year, const std::string &time) {

View File

@@ -35,24 +35,43 @@
#include <opm/parser/eclipse/Units/Units.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
// ERT stuff
#include <ert/util/ert_unique_ptr.hpp>
#include <ert/util/test_work_area.h>
#include <opm/io/eclipse/EclFile.hpp>
#include <opm/io/eclipse/EGrid.hpp>
#include <opm/io/eclipse/ERst.hpp>
#include <ert/ecl/ecl_kw.h>
#include <ert/ecl/ecl_grid.h>
#include <ert/ecl/ecl_endian_flip.h>
#include <ert/ecl/ecl_file.h>
#include <ert/ecl/ecl_util.h>
#include <opm/common/utility/TimeService.hpp>
#include <ert/ecl_well/well_info.h>
#include <memory>
#include <algorithm>
#include <map>
#include <numeric>
#include <string>
#include <tuple>
#include <vector>
#include <time.h>
#include <tests/WorkArea.cpp>
using namespace Opm;
namespace {
bool keywordExists(const std::vector<EclIO::EclFile::EclEntry>& knownVec,
const std::string& arrayname)
{
return std::any_of(knownVec.begin(), knownVec.end(),
[&arrayname](const EclIO::EclFile::EclEntry& entry) -> bool
{
return std::get<0>(entry) == arrayname;
});
}
template <typename T>
T sum(const std::vector<T>& array)
{
return std::accumulate(array.begin(), array.end(), T(0));
}
data::Solution createBlackoilState( int timeStepIdx, int numCells ) {
std::vector< double > pressure( numCells );
@@ -84,21 +103,11 @@ data::Solution createBlackoilState( int timeStepIdx, int numCells ) {
return solution;
}
template< typename T >
std::vector< T > getErtData( ecl_kw_type *eclKeyword ) {
size_t kwSize = ecl_kw_get_size(eclKeyword);
T* ertData = static_cast< T* >(ecl_kw_iget_ptr(eclKeyword, 0));
return { ertData, ertData + kwSize };
}
template< typename T, typename U >
void compareErtData(const std::vector< T > &src,
const std::vector< U > &dst,
double tolerance ) {
BOOST_CHECK_EQUAL(src.size(), dst.size());
if (src.size() != dst.size())
return;
BOOST_REQUIRE_EQUAL(src.size(), dst.size());
for (size_t i = 0; i < src.size(); ++i)
BOOST_CHECK_CLOSE(src[i], dst[i], tolerance);
@@ -111,139 +120,118 @@ void compareErtData(const std::vector<int> &src, const std::vector<int> &dst)
}
void checkEgridFile( const EclipseGrid& eclGrid ) {
// use ERT directly to inspect the EGRID file produced by EclipseIO
auto egridFile = fortio_open_reader("FOO.EGRID", /*isFormated=*/0, ECL_ENDIAN_FLIP);
auto egridFile = EclIO::EGrid("FOO.EGRID");
const auto numCells = eclGrid.getNX() * eclGrid.getNY() * eclGrid.getNZ();
while( auto* eclKeyword = ecl_kw_fread_alloc( egridFile ) ) {
std::string keywordName(ecl_kw_get_header(eclKeyword));
if (keywordName == "COORD") {
std::vector< double > sourceData;
sourceData = eclGrid.getCOORD();
auto resultData = getErtData< float >( eclKeyword );
compareErtData(sourceData, resultData, 1e-6);
}
else if (keywordName == "ZCORN") {
std::vector< double > sourceData;
sourceData = eclGrid.getZCORN();
auto resultData = getErtData< float >( eclKeyword );
compareErtData(sourceData, resultData, /*percentTolerance=*/1e-6);
}
else if (keywordName == "ACTNUM") {
std::vector< int > sourceData( numCells );
sourceData = eclGrid.getACTNUM();
auto resultData = getErtData< int >( eclKeyword );
if( sourceData.empty() )
sourceData.assign( numCells, 1 );
compareErtData( sourceData, resultData );
}
ecl_kw_free(eclKeyword);
{
const auto& coord = egridFile.get<float>("COORD");
const auto& expect = eclGrid.getCOORD();
compareErtData(expect, coord, 1e-6);
}
fortio_fclose(egridFile);
{
const auto& zcorn = egridFile.get<float>("ZCORN");
const auto& expect = eclGrid.getZCORN();
compareErtData(expect, zcorn, 1e-6);
}
if (egridFile.hasKey("ACTNUM")) {
const auto& actnum = egridFile.get<int>("ACTNUM");
auto expect = eclGrid.getACTNUM();
if (expect.empty())
expect.assign(numCells, 1);
compareErtData(expect, actnum);
}
}
void loadWells( const char* grid_file , const char* restart_file ) {
ecl_grid_type * grid = ecl_grid_alloc( grid_file );
well_info_type * well_info = well_info_alloc( grid );
well_info_load_rstfile( well_info , restart_file, true);
well_info_free( well_info );
ecl_grid_free( grid );
}
void checkInitFile( const Deck& deck, const data::Solution& simProps) {
// use ERT directly to inspect the INIT file produced by EclipseIO
ERT::ert_unique_ptr<ecl_file_type , ecl_file_close> initFile(ecl_file_open( "FOO.INIT" , 0 ));
EclIO::EclFile initFile { "FOO.INIT" };
for (int k=0; k < ecl_file_get_size( initFile.get() ); k++) {
ecl_kw_type * eclKeyword = ecl_file_iget_kw( initFile.get( ) , k );
std::string keywordName(ecl_kw_get_header(eclKeyword));
if (initFile.hasKey("PORO")) {
const auto& poro = initFile.get<float>("PORO");
const auto& expect = deck.getKeyword("PORO").getSIDoubleData();
if (keywordName == "PORO") {
const auto &sourceData = deck.getKeyword("PORO").getSIDoubleData();
auto resultData = getErtData< float >( eclKeyword );
compareErtData(sourceData, resultData, 1e-4);
compareErtData(expect, poro, 1e-4);
}
if (initFile.hasKey("PERMX")) {
const auto& expect = deck.getKeyword("PERMX").getSIDoubleData();
auto permx = initFile.get<float>("PERMX");
for (auto& kx : permx) {
kx *= 9.869233e-16;
}
if (keywordName == "PERMX") {
const auto& sourceData = deck.getKeyword("PERMX").getSIDoubleData();
auto resultData = getErtData< float >( eclKeyword );
// convert the data from ERT from Field to SI units (mD to m^2)
for (size_t i = 0; i < resultData.size(); ++i) {
resultData[i] *= 9.869233e-16;
}
compareErtData(sourceData, resultData, 1e-4);
}
compareErtData(expect, permx, 1e-4);
}
/*
These keyword should always be in the INIT file, irrespective of
whether they appear in the inut deck or not.
*/
BOOST_CHECK( ecl_file_has_kw( initFile.get() , "NTG" ));
BOOST_CHECK( ecl_file_has_kw( initFile.get() , "FIPNUM" ));
BOOST_CHECK( ecl_file_has_kw( initFile.get() , "SATNUM" ));
BOOST_CHECK_MESSAGE( initFile.hasKey("NTG"), R"(INIT file must have "NTG" array)" );
BOOST_CHECK_MESSAGE( initFile.hasKey("FIPNUM"), R"(INIT file must have "FIPNUM" array)");
BOOST_CHECK_MESSAGE( initFile.hasKey("SATNUM"), R"(INIT file must have "SATNUM" array)");
for (const auto& prop : simProps) {
BOOST_CHECK( ecl_file_has_kw( initFile.get() , prop.first.c_str()) );
BOOST_CHECK_MESSAGE( initFile.hasKey(prop.first), R"(INIT file must have ")" + prop.first + R"(" array)" );
}
}
void checkRestartFile( int timeStepIdx ) {
EclIO::ERst rstFile{ "FOO.UNRST" };
for (int i = 1; i <= timeStepIdx; ++i) {
if (! rstFile.hasReportStepNumber(i))
continue;
auto sol = createBlackoilState( i, 3 * 3 * 3 );
// use ERT directly to inspect the restart file produced by EclipseIO
auto rstFile = fortio_open_reader("FOO.UNRST", /*isFormated=*/0, ECL_ENDIAN_FLIP);
rstFile.loadReportStepNumber(i);
int curSeqnum = -1;
while( auto* eclKeyword = ecl_kw_fread_alloc(rstFile) ) {
std::string keywordName(ecl_kw_get_header(eclKeyword));
const auto& knownVec = rstFile.listOfRstArrays(i);
if (keywordName == "SEQNUM") {
curSeqnum = *static_cast<int*>(ecl_kw_iget_ptr(eclKeyword, 0));
}
if (curSeqnum != i)
continue;
if (keywordExists(knownVec, "PRESSURE")) {
const auto& press = rstFile.getRst<float>("PRESSURE", i);
for( auto& x : sol.data("PRESSURE") )
x /= Metric::Pressure;
if (keywordName == "PRESSURE") {
const auto resultData = getErtData< float >( eclKeyword );
for( auto& x : sol.data("PRESSURE") )
x /= Metric::Pressure;
compareErtData( sol.data("PRESSURE"), resultData, 1e-4 );
}
if (keywordName == "SWAT") {
const auto resultData = getErtData< float >( eclKeyword );
compareErtData(sol.data("SWAT"), resultData, 1e-4);
}
if (keywordName == "SGAS") {
const auto resultData = getErtData< float >( eclKeyword );
compareErtData( sol.data("SGAS"), resultData, 1e-4 );
}
if (keywordName == "KRO")
BOOST_CHECK_EQUAL( 1.0 * i * ecl_kw_get_size( eclKeyword ) , ecl_kw_element_sum_float( eclKeyword ));
if (keywordName == "KRG")
BOOST_CHECK_EQUAL( 10.0 * i * ecl_kw_get_size( eclKeyword ) , ecl_kw_element_sum_float( eclKeyword ));
compareErtData( sol.data("PRESSURE"), press, 1e-4 );
}
fortio_fclose(rstFile);
if (keywordExists(knownVec, "SWAT")) {
const auto& swat = rstFile.getRst<float>("SWAT", i);
compareErtData( sol.data("SWAT"), swat, 1e-4 );
}
if (keywordExists(knownVec, "SGAS")) {
const auto& sgas = rstFile.getRst<float>("SGAS", i);
compareErtData( sol.data("SGAS"), sgas, 1e-4 );
}
if (keywordExists(knownVec, "KRO")) {
const auto& kro = rstFile.getRst<float>("KRO", i);
BOOST_CHECK_CLOSE(1.0 * i * kro.size(), sum(kro), 1.0e-8);
}
if (keywordExists(knownVec, "KRG")) {
const auto& krg = rstFile.getRst<float>("KRG", i);
BOOST_CHECK_CLOSE(10.0 * i * krg.size(), sum(krg), 1.0e-8);
}
}
}
time_t ecl_util_make_date( const int day, const int month, const int year )
{
const auto ymd = Opm::TimeStampUTC::YMD{ year, month, day };
return static_cast<time_t>(asTimeT(Opm::TimeStampUTC{ymd}));
}
} // Anonymous namespace
BOOST_AUTO_TEST_CASE(EclipseIOIntegration) {
const char *deckString =
"RUNSPEC\n"
@@ -341,14 +329,12 @@ BOOST_AUTO_TEST_CASE(EclipseIOIntegration) {
checkInitFile( deck , eGridProps);
checkEgridFile( eclGrid );
loadWells( "FOO.EGRID", "FOO.UNRST" );
ecl_file_type * ecl_file = ecl_file_open("FOO.INIT", 0);
BOOST_CHECK( ecl_file_has_kw(ecl_file, "STR_V") );
ecl_kw_type * kw = ecl_file_iget_named_kw(ecl_file, "STR_V", 0);
BOOST_CHECK(67 == ecl_kw_iget_as_double(kw, 2));
BOOST_CHECK(89 == ecl_kw_iget_as_double(kw, 26));
EclIO::EclFile initFile("FOO.INIT");
BOOST_CHECK_MESSAGE( initFile.hasKey("STR_V"), R"(INIT file must have "STR_V" array)" );
const auto& kw = initFile.get<int>("STR_V");
BOOST_CHECK_EQUAL(67, kw[ 2]);
BOOST_CHECK_EQUAL(89, kw[26]);
std::ifstream file( "FOO.UNRST", std::ios::binary );
std::streampos file_size = 0;
@@ -370,7 +356,7 @@ BOOST_AUTO_TEST_CASE(EclipseIOIntegration) {
* * https://github.com/OPM/opm-output/pull/61
*/
test_work_area_type * work_area = test_work_area_alloc("test_ecl_writer");
WorkArea work_area("test_ecl_writer");
const auto file_size = write_and_check();
for( int i = 0; i < 3; ++i )
@@ -390,8 +376,4 @@ BOOST_AUTO_TEST_CASE(EclipseIOIntegration) {
* the file
*/
BOOST_CHECK_EQUAL( file_size, write_and_check( 3, 5 ) );
test_work_area_free(work_area);
}
BOOST_AUTO_TEST_CASE(OPM_XWEL) {
}

View File

@@ -44,8 +44,7 @@
#include <tuple>
// ERT stuff
#include <ert/ecl/ecl_util.h>
#include <opm/common/utility/TimeService.hpp>
#include <tests/WorkArea.cpp>
@@ -505,8 +504,8 @@ RestartValue first_sim(const EclipseState& es, EclipseIO& eclWriter, SummaryStat
const auto& grid = es.getInputGrid();
auto num_cells = grid.getNumActive( );
auto start_time = ecl_util_make_date( 1, 11, 1979 );
auto first_step = ecl_util_make_date( 1, 2, 2011 ); // Must be after 2011-01-20
auto start_time = TimeStampUTC( TimeStampUTC::YMD{ 1979, 11, 1 } );
auto first_step = TimeStampUTC( TimeStampUTC::YMD{ 2011, 2, 1 } ); // Must be after 2011-01-20
auto sol = mkSolution( num_cells );
auto wells = mkWells();
@@ -515,7 +514,7 @@ RestartValue first_sim(const EclipseState& es, EclipseIO& eclWriter, SummaryStat
eclWriter.writeTimeStep( st,
1,
false,
first_step - start_time,
asTimeT(first_step) - asTimeT(start_time),
restart_value,
write_double);