#2661 Update ecllib from statoil master repo

This commit is contained in:
Bjørn Erik Jensen
2018-04-09 08:48:36 +02:00
parent e8d765a2a9
commit b72091bb94
306 changed files with 32640 additions and 1429 deletions

View File

@@ -15,6 +15,7 @@ dist: trusty
env:
global:
- ERT_SHOW_BACKTRACE=1
- LD_LIBRARY_PATH="$(pwd)/install/lib64"
matrix:
- PYTHON_VERSION=2.7 TEST_SUITE="-LE SLOW" # Run all tests not labeled as slow
- PYTHON_VERSION=2.7 TEST_SUITE="-L SLOW_1" # Run all tests labeled as SLOW in group 1
@@ -65,10 +66,12 @@ install:
- export CONDA_HOME="$HOME/miniconda"
- export PATH="$CONDA_HOME/bin:$PATH"
- hash -r
- pip install -r requirements.txt
- conda config --set always_yes yes --set changeps1 no
- conda update -q conda
- conda info -a # Useful for debugging any issues with conda
- conda install pylint numpy pandas
- wget https://raw.githubusercontent.com/Statoil/ert/master/travis/install_python_packages.py
- python install_python_packages.py
before_script:
- wget https://raw.githubusercontent.com/Statoil/ert/master/travis/build_total.py

View File

@@ -45,8 +45,8 @@ endif()
option( BUILD_TESTS "Should the tests be built" OFF)
option( BUILD_APPLICATIONS "Should we build small utility applications" OFF)
option( BUILD_ECL_SUMMARY "Build the commandline application ecl_summary" OFF)
option( BUILD_NEXUS "Build support for the Nexus simulator" ON)
option( BUILD_PYTHON "Run py_compile on the python wrappers" OFF)
option( ENABLE_PYTHON "Build and install the Python wrappers" OFF)
option( BUILD_SHARED_LIBS "Build shared libraries" ON )
option( ERT_USE_OPENMP "Use OpenMP" OFF )
option( RST_DOC "Build RST documentation" OFF)
@@ -54,7 +54,6 @@ option( ERT_BUILD_CXX "Build some CXX wrappers"
option( USE_RPATH "Don't strip RPATH from libraries and binaries" OFF)
option( INSTALL_ERT_LEGACY "Add ert legacy wrappers" OFF)
set(STATOIL_TESTDATA_ROOT "" CACHE PATH "Root to Statoil internal testdata")
if (EXISTS ${STATOIL_TESTDATA_ROOT})
set( LINK "${CMAKE_CURRENT_SOURCE_DIR}/test-data/Statoil" )
@@ -71,6 +70,11 @@ if (EXISTS ${STATOIL_TESTDATA_ROOT})
endif()
if (BUILD_PYTHON)
set(ENABLE_PYTHON ON)
message(WARNING "The option 'BUILD_PYTHON' is deprecated - use ENABLE_PYTHON.")
endif()
# output libs to some lib/ path for testing
set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin)
@@ -176,18 +180,6 @@ if(M_LIBRARY)
set(m m)
endif ()
find_package(BLAS)
if (BLAS_FOUND)
set(blas "${BLAS_LIBRARIES}")
endif ()
set(ERT_HAVE_LAPACK OFF)
find_package(LAPACK)
if (LAPACK_FOUND)
set(ERT_HAVE_LAPACK ON)
list(APPEND lapack ${LAPACK_LIBRARIES} ${LAPACK_LINKER_FLAGS})
endif()
find_package(ZLIB)
if (ZLIB_FOUND)
set(ERT_HAVE_ZLIB ON)
@@ -199,6 +191,11 @@ if (SHLWAPI_LIBRARY)
set(shlwapi ${SHLWAPI_LIBRARY})
endif ()
find_library(WS2_32_LIBRARY NAMES Ws2_32)
if (WS2_32_LIBRARY)
set(ws2_32 ${WS2_32_LIBRARY})
endif ()
#-----------------------------------------------------------------
# feature tests
@@ -207,6 +204,8 @@ include(CheckIncludeFile)
include(CheckSymbolExists)
include(CheckTypeSize)
check_function_exists( access HAVE_POSIX_ACCESS)
check_function_exists( _access HAVE_WINDOWS__ACCESS)
check_function_exists( chdir HAVE_POSIX_CHDIR )
check_function_exists( _chdir HAVE_WINDOWS_CHDIR )
check_function_exists( chmod HAVE_CHMOD )
@@ -235,7 +234,6 @@ check_function_exists( readlinkat ERT_HAVE_READLINKAT )
check_function_exists( realpath HAVE_REALPATH )
check_function_exists( regexec ERT_HAVE_REGEXP )
check_function_exists( round HAVE_ROUND )
check_function_exists( setenv HAVE_POSIX_SETENV )
check_function_exists( symlink ERT_HAVE_SYMLINK )
check_function_exists( timegm HAVE_TIMEGM )
check_function_exists( usleep HAVE__USLEEP )
@@ -287,10 +285,6 @@ if (ERT_WINDOWS)
endif()
endif()
find_program(PING_PATH NAMES ping)
if (PING_PATH)
set(ERT_HAVE_PING ON)
endif()
find_package(Git)
if(GIT_FOUND)
@@ -330,7 +324,7 @@ endif()
if (ERT_WINDOWS)
message(WARNING "Python is not supported on Windows")
set( BUILD_PYTHON OFF )
set( ENABLE_PYTHON OFF )
endif ()
if (ERT_LINUX)
@@ -339,15 +333,15 @@ endif()
add_subdirectory( lib )
add_subdirectory( applications )
add_subdirectory( bin )
if (BUILD_PYTHON)
if (ENABLE_PYTHON)
if (ERT_WINDOWS)
message(WARNING "Python is not supported on Windows")
set( BUILD_PYTHON OFF )
set( ENABLE_PYTHON OFF )
else()
# If finding the Python interpreter and required packages
# fails in the python/CMakeLists.txt file the BUILD_PYTHON
# fails in the python/CMakeLists.txt file the ENABLE_PYTHON
# will be set to OFF.
add_subdirectory( python )
@@ -357,15 +351,12 @@ if (BUILD_PYTHON)
endif()
endif()
if (BUILD_PYTHON)
if (ENABLE_PYTHON)
if (NOT ${BUILD_SHARED_LIBS})
message(FATAL_ERROR "The Python wrappers require shared libraries")
endif()
endif()
if (INSTALL_ERT)
install(EXPORT ecl-config DESTINATION share/cmake/ecl)
endif()
install(EXPORT ecl-config DESTINATION share/cmake/ecl)
export(TARGETS ecl FILE eclConfig.cmake)
export(PACKAGE ecl)

View File

@@ -10,6 +10,7 @@ if (BUILD_APPLICATIONS)
target_link_libraries(grdecl_grid ecl)
target_link_libraries(summary ecl)
list(APPEND apps make_grid grdecl_grid summary)
foreach (app ecl_pack

View File

@@ -1,30 +1,29 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'ecl_pack.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
Copyright (C) 2011 Statoil ASA, Norway.
The file 'ecl_pack.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <stdlib.h>
#include <ert/util/util.h>
#include <ert/util/stringlist.h>
#include <ert/util/msg.h>
#include <ert/ecl/ecl_file.h>
#include <ert/ecl/ecl_util.h>
#include <ert/ecl/ecl_endian_flip.h>
#include <ert/ecl/ecl_endian_flip.h>
#include <ert/ecl/ecl_type.h>
@@ -50,7 +49,7 @@ int main(int argc, char ** argv) {
}
util_alloc_file_components( argv[1] , &path , &ecl_base , NULL);
/**
Will pack to cwd, even though the source files might be
somewhere else. To unpack to the same directory as the source
@@ -59,7 +58,6 @@ int main(int argc, char ** argv) {
*/
{
msg_type * msg;
int i , report_step , prev_report_step;
char * target_file_name = ecl_util_alloc_filename( NULL , ecl_base , target_type , fmt_file , -1);
stringlist_type * filelist = stringlist_alloc_argv_copy( (const char **) &argv[1] , num_files );
@@ -69,16 +67,8 @@ int main(int argc, char ** argv) {
if (target_type == ECL_UNIFIED_RESTART_FILE) {
int dummy;
seqnum_kw = ecl_kw_alloc_new("SEQNUM" , 1 , ECL_INT , &dummy);
}
{
char * msg_format = util_alloc_sprintf("Packing %s <= " , target_file_name);
msg = msg_alloc( msg_format , false);
free( msg_format );
}
msg_show( msg );
stringlist_sort( filelist , ecl_util_fname_report_cmp);
prev_report_step = -1;
for (i=0; i < num_files; i++) {
@@ -87,11 +77,10 @@ int main(int argc, char ** argv) {
if (this_file_type == file_type) {
if (report_step == prev_report_step)
util_exit("Tried to write same report step twice: %s / %s \n",
stringlist_iget(filelist , i-1) ,
stringlist_iget(filelist , i-1) ,
stringlist_iget(filelist , i));
prev_report_step = report_step;
msg_update(msg , stringlist_iget( filelist , i));
{
ecl_file_type * src_file = ecl_file_open( stringlist_iget( filelist , i) , 0 );
if (target_type == ECL_UNIFIED_RESTART_FILE) {
@@ -104,7 +93,6 @@ int main(int argc, char ** argv) {
}
} /* Else skipping file of incorrect type. */
}
msg_free(msg , false);
fortio_fclose( target );
free(target_file_name);
stringlist_free( filelist );
@@ -114,4 +102,4 @@ int main(int argc, char ** argv) {
util_safe_free(path);
}
}

View File

@@ -1,25 +1,24 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'ecl_unpack.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
Copyright (C) 2011 Statoil ASA, Norway.
The file 'ecl_unpack.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <stdbool.h>
#include <ert/util/util.h>
#include <ert/util/msg.h>
#include <ert/ecl/ecl_file.h>
#include <ert/ecl/ecl_util.h>
@@ -36,9 +35,9 @@ void unpack_file(const char * filename) {
target_type = ECL_SUMMARY_FILE;
else if (file_type == ECL_UNIFIED_RESTART_FILE)
target_type = ECL_RESTART_FILE;
else
else
util_exit("Can only unpack unified ECLIPSE summary and restart files\n");
if (target_type == ECL_SUMMARY_FILE) {
printf("** Warning: when unpacking unified summary files it as ambigous - starting with 0001 -> \n");
}
@@ -48,23 +47,16 @@ void unpack_file(const char * filename) {
int offset;
int report_step = 0;
int block_index = 0;
char * path;
char * path;
char * base;
msg_type * msg;
util_alloc_file_components( filename , &path , &base , NULL);
{
char * label = util_alloc_sprintf("Unpacking %s => ", filename);
msg = msg_alloc( label , false);
free( label );
}
msg_show(msg);
if (target_type == ECL_SUMMARY_FILE)
if (target_type == ECL_SUMMARY_FILE)
size = ecl_file_get_num_named_kw( src_file , "SEQHDR" );
else
size = ecl_file_get_num_named_kw( src_file , "SEQNUM" );
while (true) {
ecl_file_view_type * active_view;
@@ -89,22 +81,20 @@ void unpack_file(const char * filename) {
files, just send in @path as first argument when creating the
target_file.
*/
{
char * target_file = ecl_util_alloc_filename( NULL , base , target_type , fmt_file , report_step);
fortio_type * fortio_target = fortio_open_writer( target_file , fmt_file , ECL_ENDIAN_FLIP );
msg_update(msg , target_file);
ecl_file_view_fwrite( active_view , fortio_target , offset);
fortio_fclose(fortio_target);
free(target_file);
}
block_index++;
}
}
ecl_file_close( src_file );
util_safe_free(path);
free(base);
msg_free(msg , true);
}
}

View File

@@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'kw_extract.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
Copyright (C) 2011 Statoil ASA, Norway.
The file 'kw_extract.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <stdlib.h>
@@ -23,7 +23,6 @@
#include <ert/util/set.h>
#include <ert/util/util.h>
#include <ert/util/hash.h>
#include <ert/util/msg.h>
#include <ert/ecl/ecl_kw.h>
#include <ert/ecl/fortio.h>
@@ -54,10 +53,10 @@ int main(int argc, char ** argv) {
fortio_type * fortio_target;
bool fmt_src , fmt_target;
set_type * kw_set = set_alloc( num_kw , kw_list );
if (!ecl_util_fmt_file(src_file, &fmt_src))
util_exit("Hmm - could not determine formatted/unformatted status for:%s \n",src_file);
fmt_target = fmt_src; /* Can in principle be different */
fortio_src = fortio_open_reader(src_file , fmt_src , ECL_ENDIAN_FLIP);
fortio_target = fortio_open_writer(target_file , fmt_target , ECL_ENDIAN_FLIP);
@@ -66,18 +65,18 @@ int main(int argc, char ** argv) {
ecl_kw_type * ecl_kw = ecl_kw_alloc_empty();
while (true) {
if (ecl_kw_fread_header( ecl_kw , fortio_src ) == ECL_KW_READ_OK) {
const char * header = ecl_kw_get_header( ecl_kw );
const char * header = ecl_kw_get_header( ecl_kw );
if (set_has_key( kw_set , header )) {
ecl_kw_fread_realloc_data(ecl_kw , fortio_src );
ecl_kw_fwrite( ecl_kw , fortio_target );
} else
ecl_kw_fskip_data( ecl_kw , fortio_src );
} else
} else
break; /* We have reached EOF */
}
ecl_kw_free( ecl_kw );
}
fortio_fclose(fortio_src);
fortio_fclose(fortio_target);
set_free( kw_set );

View File

@@ -6,7 +6,7 @@ build_script:
cd build
cmake .. -G"Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DERT_BUILD_CXX=OFF -DBUILD_PYTHON=OFF -DBUILD_APPLICATIONS=ON
cmake .. -G"Visual Studio 14 2015 Win64" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DERT_BUILD_CXX=OFF -DENABLE_PYTHON=OFF -DBUILD_APPLICATIONS=ON
msbuild /m /p:Configuration=Release /p:Platform="x64" ERT.sln

3
ThirdParty/Ert/bin/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,3 @@
if (ENABLE_PYTHON)
install(PROGRAMS summary_resample DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
endif()

27
ThirdParty/Ert/bin/summary_resample vendored Normal file
View File

@@ -0,0 +1,27 @@
#!/usr/bin/env python
import sys
import argparse
from ecl.summary import EclSum
from ecl.util.util import TimeVector, CTime
parser = argparse.ArgumentParser()
parser.add_argument("input_case", metavar="input_case", type=str)
parser.add_argument("output_case", metavar="output_case", type=str)
parser.add_argument("--num-timestep", type=int, default=50)
parser.add_argument("--refcase", metavar="refcase", type=str)
args = parser.parse_args()
input_case = EclSum(args.input_case)
if args.refcase:
refcase = EclSum(args.refcase)
report_only = False
time_points = refcase.alloc_time_vector( report_only )
else:
start_time = input_case.get_data_start_time()
end_time = input_case.get_end_time()
time_points = TimeVector.create_linear(CTime(start_time), CTime(end_time), args.num_timestep)
output_case = input_case.resample(args.output_case, time_points)
output_case.fwrite( )

View File

@@ -9,6 +9,6 @@ link_directories( @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ )
include_directories( @CMAKE_INSTALL_PREFIX@/include )
set( CMAKE_MODULE_PATH @CMAKE_INSTALL_PREFIX@/share/cmake/Modules ${CMAKE_MODULE_PATH})
if (@BUILD_PYTHON@)
if (@ENABLE_PYTHON@)
set(libecl_PYTHONPATH @CMAKE_INSTALL_PREFIX@/@PYTHON_INSTALL_PREFIX@ )
endif()
endif()

View File

@@ -5,6 +5,6 @@ set( CMAKE_MODULE_PATH @CMAKE_INSTALL_PREFIX@/share/cmake/Modules ${CMAKE_MODULE
link_directories( @CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ )
include_directories( @CMAKE_INSTALL_PREFIX@/include )
if (@BUILD_PYTHON@)
if (@ENABLE_PYTHON@)
set(libecl_PYTHONPATH @CMAKE_INSTALL_PREFIX@/@PYTHON_INSTALL_PREFIX@ )
endif()
endif()

View File

@@ -2,7 +2,7 @@ Source: ecl
Priority: extra
Maintainer: Arne Morten Kvarving <arne.morten.kvarving@sintef.no>
Build-Depends: debhelper (>= 8.0.0), cmake, liblapack-dev, libquadmath0,
iputils-ping, zlib1g-dev, git, python-dev, python-numpy
iputils-ping, zlib1g-dev, git, python-dev, python-numpy, python-cwrap
Standards-Version: 3.9.2
Section: libs
Homepage: http://ert.nr.no
@@ -26,6 +26,6 @@ Description: libecl Eclipse IO library
Package: python-ecl
Section: python
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, libert.ecl1, python-cwrap
Depends: ${shlibs:Depends}, ${misc:Depends}, libecl1, python-cwrap
Description: libecl Eclipse IO library - Python bindings
libecl is a package for reading and writing the result files from the Eclipse reservoir simulator.

View File

@@ -0,0 +1 @@
usr/lib/python2.7/*/cwrap/*

View File

@@ -13,4 +13,4 @@
dh $@
override_dh_auto_configure:
DESTDIR=$$(pwd)/debian/tmp dh_auto_configure -- -DBUILD_SHARED_LIBS=1 -DBUILD_ECL_SUMMARY=1 -DBUILD_PYTHON=1 -DCMAKE_BUILD_TYPE=Release
DESTDIR=$$(pwd)/debian/tmp dh_auto_configure -- -DBUILD_SHARED_LIBS=1 -DBUILD_ECL_SUMMARY=1 -DENABLE_PYTHON=1 -DCMAKE_BUILD_TYPE=Release

View File

@@ -17,7 +17,7 @@ if (SPHINX_FOUND)
configure_file(index.rst.in ${PROJECT_BINARY_DIR}/doc-src/index.rst)
configure_file(conf.py.in ${PROJECT_BINARY_DIR}/doc-src/conf.py)
if (BUILD_PYTHON)
if (ENABLE_PYTHON)
add_custom_target(api-doc ALL
COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/code" "${PROJECT_BINARY_DIR}/doc-src/code"
COMMAND sphinx-apidoc -e -o doc-src/API/python/ecl ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}

View File

@@ -851,9 +851,9 @@ ministep sequence, but there will never be holes in this range. It is
closely coupled to the simulator timestep and what the user of ECLIPSE
has chosen to store, so no further meaning should be attached to these
indices. Ultimately all lookups will be based on :code:`time_index`; in the C
code it is therefor often denoted :code:`internal_index`.
code it is therefore often denoted :code:`internal_index`.
ministep
ministep
,,,,,,,,,
Each simulator timestep corresponds to one ministep, but an arbitrary

View File

@@ -20,14 +20,13 @@ for c in classes:
for v in vars[c]:
4*b : The variable names
8*b : Skipped
4*b : Skipped
----> : This is the position of first timestep
while classname != STOP:
8*b : classname
8*b : skipped
f : timestep (will cast to int)
f : timestep (cast to int)
f : time
f : num_items (cast to int)
f : max_items (cast to int)
@@ -49,3 +48,4 @@ while classname != STOP:
8*b : skipped
72*b : skipped
var_in_class*f : The real data
8*b : skipped

View File

@@ -94,7 +94,7 @@ it. In the configuration file both GEN_DATA and GEN_PARAM can be used:
GEN_PARAM: For parameters which are not changed by the forward
model, i.e. like porosity and permeability.
GEN_DATA: Data which is changed by the forward model, and therefor
GEN_DATA: Data which is changed by the forward model, and therefore
must be loaded at the end of each timestep. The arch-typical
example of a GEN_DATA instance would be seismic data.
@@ -436,14 +436,14 @@ The block_fs driver is based on creating block_fs instances
(block_fs_type is implemented in libutil/src/block_fs.c). The block_fs
instances are binary files which are open through the duration of the
program, the block_fs system then has an api for reading and writing
(key,value) pairs to this file.
(key,value) pairs to this file.
The block_fs_driver/block_fs combination is quite complex, but it has
not had any hickups for about 1.5 years of extensive use in
Statoil. Observe that if you pull the plug on ERT you might loose some
of the data which has been stored with the block_fs driver, but partly
written and malformed data will be detected and discarded at the next
boot. You are therefor guaranteed (add as many quotes you like to the
boot. You are therefore guaranteed (add as many quotes you like to the
guarantee - but this has at least worked 100% up until now) that no
bogus data will be loaded after an unclean shutdown. When shut down
cleanly the block_fs will create an index file which can be used for
@@ -551,7 +551,7 @@ SConstruct files:
Unfortunately it has been a major pain in the ass to get SCons to
behave according to the requirements listed above; for the more
extensive installation procedures there are therefor simple Python
extensive installation procedures there are therefore simple Python
scripts "install.py" which should be invoked after the SCons build is
complete.

View File

@@ -1,20 +1,6 @@
project(libecl-ecl C CXX)
if (HAVE_PTHREAD)
# The block_fs filesystem is so heavily dependant on pthreads that it is
# not built if de not have pthreads.
list(APPEND opt_srcs util/thread_pool.c)
endif ()
if (LAPACK_FOUND)
list(APPEND opt_srcs util/matrix_lapack.c
util/matrix_blas.c
util/matrix_stat.c
util/regression.c
util/lars.c
util/stepwise.c
)
endif ()
if (HAVE_BACKTRACE)
list(APPEND opt_srcs util/util_abort_gnu.c)
@@ -71,13 +57,9 @@ if (ERT_BUILD_CXX)
ecl/FortIO.cpp
ecl/Smspec.cpp
ecl/EclFilename.cpp
nexus/nexus_plot.cpp
)
endif ()
if (BUILD_NEXUS)
list(APPEND opt_srcs nexus/nexus_plot.cpp)
endif ()
configure_file(build_config.h.in include/ert/util/build_config.h)
configure_file(ert_api_config.h.in include/ert/util/ert_api_config.h)
@@ -93,26 +75,18 @@ add_library(ecl util/rng.c
util/node_data.c
util/node_ctype.c
util/util.c
util/util_env.c
util/util_symlink.c
util/util_lfs.c
util/util_unlink.c
util/msg.c
util/arg_pack.c
util/path_fmt.c
util/menu.c
util/subst_func.c
util/vector.c
util/parser.c
util/stringlist.c
util/matrix.c
util/buffer.c
util/log.c
util/timer.c
util/time_interval.c
util/string_util.c
util/type_vector_functions.c
util/ui_return.c
util/ecl_version.c
util/struct_vector.c
util/perm_vector.c
@@ -182,9 +156,9 @@ target_link_libraries(ecl PUBLIC ${m}
${dl}
${pthread}
${blas}
${lapack}
${zlib}
${shlwapi}
${ws2_32}
)
target_include_directories(ecl
@@ -207,9 +181,6 @@ target_compile_definitions(ecl PRIVATE
target_compile_options(ecl PUBLIC ${pthreadarg})
if (PING_PATH)
target_compile_definitions(ecl PRIVATE -DPING_CMD=${PING_PATH})
endif()
if (ERT_USE_OPENMP)
target_compile_options(ecl PUBLIC ${OpenMP_C_FLAGS})
@@ -220,7 +191,7 @@ endif ()
set_target_properties(ecl PROPERTIES
VERSION ${ECL_VERSION_MAJOR}.${ECL_VERSION_MINOR}
SOVERSION ${ECL_VERSION_MAJOR})
if (INSTALL_ERT)
install(TARGETS ecl
EXPORT ecl-config
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
@@ -245,7 +216,6 @@ if (ERT_BUILD_CXX)
PATTERN *.hpp
)
endif ()
endif()
if (NOT BUILD_TESTS)
return ()
@@ -261,10 +231,7 @@ foreach (name ert_util_alloc_file_components
ert_util_chdir
ert_util_filename
ert_util_hash_test
ert_util_logh
ert_util_matrix
ert_util_parent_path
ert_util_PATH_test
ert_util_realpath
ert_util_relpath_test
ert_util_rng
@@ -277,9 +244,9 @@ foreach (name ert_util_alloc_file_components
ert_util_strstr_int_format
ert_util_time_interval
ert_util_type_vector_functions
ert_util_ui_return
ert_util_vector_test
ert_util_datetime
ert_util_normal_path
)
add_executable(${name} util/tests/${name}.c)
@@ -301,15 +268,6 @@ add_test(NAME ert_util_work_area
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/util/tests
)
find_library( VALGRIND NAMES valgr )
if (VALGRIND)
set(valgrind_cmd valgrind --error-exitcode=1 --tool=memcheck)
endif ()
add_executable(test_thread_pool util/tests/test_thread_pool.c)
target_link_libraries(test_thread_pool ecl)
add_test(NAME test_thread_pool COMMAND ${valgrind_cmd} test_thread_pool)
add_executable(ert_util_cwd_test util/tests/ert_util_cwd_test.c)
target_link_libraries(ert_util_cwd_test ecl)
add_test(NAME ert_util_cwd_test COMMAND ert_util_cwd_test ${CMAKE_CURRENT_BINARY_DIR})
@@ -329,15 +287,6 @@ target_link_libraries(ert_util_path_stack_test ecl)
add_test(NAME ert_util_path_stack_test COMMAND ert_util_path_stack_test
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
if (LAPACK_FOUND)
add_executable(ert_util_matrix_lapack util/tests/ert_util_matrix_lapack.c)
target_link_libraries(ert_util_matrix_lapack ecl)
add_test(NAME ert_util_matrix_lapack COMMAND ert_util_matrix_lapack)
add_executable(ert_util_matrix_stat util/tests/ert_util_matrix_stat.c)
target_link_libraries(ert_util_matrix_stat ecl)
add_test(NAME ert_util_matrix_stat COMMAND ert_util_matrix_stat)
endif()
if (HAVE_BACKTRACE)
add_executable(ert_util_abort_gnu_tests util/tests/ert_util_abort_gnu_tests.c)
@@ -372,6 +321,7 @@ endif()
foreach (name ecl_alloc_cpgrid
ecl_alloc_grid_dxv_dyv_dzv
ecl_fault_block_layer
ecl_util_path_access
ecl_grid_add_nnc
ecl_grid_copy
ecl_grid_create
@@ -389,11 +339,13 @@ foreach (name ecl_alloc_cpgrid
ecl_nnc_info_test
ecl_nnc_vector
ecl_rft_cell
ecl_sum_alloc_resampled_test
ecl_file_view
test_ecl_file_index
test_transactions
ecl_rst_file
ecl_sum_writer
ecl_util_filenames
ecl_util_make_date_no_shift
ecl_util_month_range
ecl_valid_basename
@@ -467,14 +419,6 @@ if (ERT_BUILD_CXX)
endforeach ()
endif ()
if (BUILD_NEXUS)
foreach (name nexus_plot_load nexus2ecl)
add_executable(${name} nexus/tests/${name}.cpp)
target_link_libraries(${name} ecl)
add_test(NAME ${name} COMMAND ${name} ${CMAKE_SOURCE_DIR})
endforeach ()
endif()
if (NOT STATOIL_TESTDATA_ROOT)
return ()
@@ -484,12 +428,6 @@ endif()
# ecl
#
if (PING_PATH)
add_executable(ert_util_ping util/tests/ert_util_ping.c)
target_link_libraries(ert_util_ping ecl)
add_test(NAME ert_util_ping COMMAND ert_util_ping)
endif ()
add_executable(ecl_coarse_test ecl/tests/ecl_coarse_test.c)
target_link_libraries(ecl_coarse_test ecl)

View File

@@ -24,7 +24,6 @@
#cmakedefine HAVE_WINDOWS_MKDIR
#cmakedefine HAVE_GETPWUID
#cmakedefine HAVE_FSYNC
#cmakedefine HAVE_POSIX_SETENV
#cmakedefine HAVE_CHMOD
#cmakedefine HAVE_MODE_T
#cmakedefine HAVE_CXX_SHARED_PTR
@@ -35,6 +34,8 @@
#cmakedefine HAVE_WINSOCK2_H
#cmakedefine HAVE_POSIX_ACCESS
#cmakedefine HAVE_WINDOWS__ACCESS
#cmakedefine HAVE_WINDOWS_GET_TEMP_PATH
#cmakedefine HAVE_WINDOWS_TZNAME

View File

@@ -17,6 +17,8 @@
*/
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <ert/util/util.h>
#include <ert/util/type_macros.h>

View File

@@ -411,7 +411,7 @@
properties and the fracture properties in a cell is implemented as a
nnc where the fracture cell has global index in the range [nx*ny*nz,
2*nz*ny*nz). In ert we we have not implemented this double covering
in the case of dual porosity models, and therefor NNC involving
in the case of dual porosity models so NNC involving
fracture cells are not considered.
*/
@@ -1011,7 +1011,7 @@ static double ecl_cell_max_y( const ecl_cell_type * cell ) {
have all four corner at the same arbitrary depth; these cells are
inactive and do not affect flow simulations - however the arbitrary
location of the cells warps visualisation of normal inactive cells
completely. We therefor try to invalidate such cells here. The
completely. We therefore try to invalidate such cells here. The
algorithm used is the same as used for RMS; however RMS will mark
the cells as inactive - whereas we mark already inactive cells as
invalid.
@@ -1326,7 +1326,7 @@ static double ecl_cell_get_signed_volume( ecl_cell_type * cell) {
* Note added: these volume calculations are used to calculate pore
* volumes in OPM, it turns out that opm is very sensitive to these
* volumes. Extracting the divison by 6.0 was actually enough to
* induce a regression test failure in flow, this has therefor been
* induce a regression test failure in flow, this has therefore been
* reverted.
*/
@@ -2793,7 +2793,7 @@ static void ecl_grid_init_nnc_cells( ecl_grid_type * grid1, ecl_grid_type * grid
The physical connection between the matrix and the fractures in
cell nr c is modelled as an nnc: cell[c] -> cell[c + nx*ny*nz]. In
the ert ecl library we only have cells in the range [0,nx*ny*nz),
and fracture is a property of a cell, we therefor do not include
and fracture is a property of a cell. We therefore do not include
nnc connections involving fracture cells (i.e. cell_index >=
nx*ny*nz).
*/
@@ -4751,6 +4751,17 @@ void ecl_grid_get_cell_corner_xyz1(const ecl_grid_type * grid , int global_index
}
void ecl_grid_export_cell_corners1(const ecl_grid_type * grid, int global_index, double *x, double *y, double *z) {
const ecl_cell_type * cell = ecl_grid_get_cell(grid, global_index);
for (int i=0; i<8; i++) {
const point_type point = cell->corner_list[i];
x[i] = point.x;
y[i] = point.y;
z[i] = point.z;
}
}
void ecl_grid_get_cell_corner_xyz3(const ecl_grid_type * grid , int i , int j , int k, int corner_nr , double * xpos , double * ypos , double * zpos ) {
const int global_index = ecl_grid_get_global_index__(grid , i , j , k );
ecl_grid_get_cell_corner_xyz1( grid , global_index , corner_nr , xpos , ypos , zpos);

View File

@@ -26,6 +26,7 @@
#include <ert/util/buffer.h>
#include <ert/util/int_vector.h>
#include <ert/ecl/ecl_kw_magic.h>
#include <ert/ecl/ecl_kw.h>
#include <ert/ecl/fortio.h>
#include <ert/ecl/ecl_endian_flip.h>
@@ -107,7 +108,7 @@ UTIL_IS_INSTANCE_FUNCTION(ecl_kw , ECL_KW_TYPE_ID )
3. The logical type involves converting back and forth between 'T'
and 'F' and internal logical representation. The format strings
are therefor for reading/writing a character.
are therefore for reading/writing a character.
*/
@@ -1289,7 +1290,7 @@ bool ecl_kw_fskip_data(ecl_kw_type *ecl_kw, fortio_type *fortio) {
/**
This function will skip the header part of an ecl_kw instance. The
function will read the file content at the current position, it is
therefor essential that the file pointer is positioned at the
therefore essential that the file pointer is positioned at the
beginning of a keyword when this function is called; otherwise it
will be complete crash and burn.
*/
@@ -1917,6 +1918,38 @@ ecl_kw_type * ecl_kw_alloc_scatter_copy( const ecl_kw_type * src_kw , int target
return new_kw;
}
ecl_kw_type * ecl_kw_alloc_global_copy(const ecl_kw_type * src, const ecl_kw_type * actnum) {
if (ecl_kw_get_type(actnum) != ECL_INT_TYPE)
return NULL;
const int global_size = ecl_kw_get_size(actnum);
ecl_kw_type * global_copy = ecl_kw_alloc( ecl_kw_get_header(src), global_size, src->data_type);
const int * mapping = ecl_kw_get_int_ptr(actnum);
const int src_size = ecl_kw_get_size(src);
int src_index = 0;
for (int global_index=0; global_index < global_size; global_index++) {
if (mapping[global_index]) {
/* We ran through and beyond the size of the src keyword. */
if (src_index >= src_size) {
ecl_kw_free(global_copy);
global_copy = NULL;
break;
}
const void * value_ptr = ecl_kw_iget_ptr(src, src_index);
ecl_kw_iset_static(global_copy, global_index, value_ptr);
src_index++;
}
}
/* Not all the src data was distributed. */
if (src_index < src_size) {
ecl_kw_free(global_copy);
global_copy = NULL;
}
return global_copy;
}
void ecl_kw_fread_double_param(const char * filename , bool fmt_file , double * double_data) {
@@ -2194,6 +2227,41 @@ void ecl_kw_inplace_add( ecl_kw_type * target_kw , const ecl_kw_type * add_kw) {
}
}
#define ECL_KW_TYPED_INPLACE_ADD_SQUARED( ctype ) \
static void ecl_kw_inplace_add_squared_ ## ctype( ecl_kw_type * target_kw , const ecl_kw_type * add_kw) { \
if (!ecl_kw_assert_binary_ ## ctype( target_kw , add_kw )) \
util_abort("%s: type/size mismatch\n",__func__); \
{ \
ctype * target_data = ecl_kw_get_data_ref( target_kw ); \
const ctype * add_data = ecl_kw_get_data_ref( add_kw ); \
int i; \
for (i=0; i < target_kw->size; i++) \
target_data[i] += add_data[i] * add_data[i]; \
} \
}
ECL_KW_TYPED_INPLACE_ADD_SQUARED( int )
ECL_KW_TYPED_INPLACE_ADD_SQUARED( double )
ECL_KW_TYPED_INPLACE_ADD_SQUARED( float )
#undef ECL_KW_TYPED_INPLACE_ADD
void ecl_kw_inplace_add_squared( ecl_kw_type * target_kw , const ecl_kw_type * add_kw) {
ecl_type_enum type = ecl_kw_get_type(target_kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_add_squared_float( target_kw , add_kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_add_squared_double( target_kw , add_kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_add_squared_int( target_kw , add_kw );
break;
default:
util_abort("%s: inplace add not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(target_kw) ));
}
}
@@ -2310,6 +2378,45 @@ void ecl_kw_inplace_abs( ecl_kw_type * kw ) {
/*****************************************************************/
static int sqrti(int x) {
return round( sqrt(x) );
}
#define ECL_KW_TYPED_INPLACE_SQRT( ctype, sqrt_func ) \
void ecl_kw_inplace_sqrt_ ## ctype( ecl_kw_type * kw ) { \
ctype * data = ecl_kw_get_data_ref( kw ); \
int i; \
for (i=0; i < kw->size; i++) \
data[i] = sqrt_func(data[i]); \
}
ECL_KW_TYPED_INPLACE_SQRT( double , sqrt )
ECL_KW_TYPED_INPLACE_SQRT( float , sqrtf )
ECL_KW_TYPED_INPLACE_SQRT( int, sqrti)
#undef ECL_KW_TYPED_INPLACE_SQRT
void ecl_kw_inplace_sqrt( ecl_kw_type * kw ) {
ecl_type_enum type = ecl_kw_get_type(kw);
switch (type) {
case(ECL_FLOAT_TYPE):
ecl_kw_inplace_sqrt_float( kw );
break;
case(ECL_DOUBLE_TYPE):
ecl_kw_inplace_sqrt_double( kw );
break;
case(ECL_INT_TYPE):
ecl_kw_inplace_sqrt_int( kw );
break;
default:
util_abort("%s: inplace sqrt not implemented for type:%s \n",__func__ , ecl_type_alloc_name( ecl_kw_get_data_type(kw) ));
}
}
/*****************************************************************/
#define ECL_KW_TYPED_INPLACE_MUL( ctype ) \
void ecl_kw_inplace_mul_ ## ctype( ecl_kw_type * target_kw , const ecl_kw_type * mul_kw) { \
@@ -2468,6 +2575,23 @@ void ecl_kw_inplace_div_indexed( ecl_kw_type * target_kw , const int_vector_type
}
bool ecl_kw_inplace_safe_div(ecl_kw_type * target_kw, const ecl_kw_type * divisor) {
if (ecl_kw_get_type(target_kw) != ECL_FLOAT_TYPE)
return false;
if (ecl_kw_get_type(divisor) != ECL_INT_TYPE)
return false;
float * target_data = ecl_kw_get_data_ref( target_kw );
const int* div_data = ecl_kw_get_data_ref( divisor );
for (int i=0; i < target_kw->size; i++) {
if (div_data[i] != 0)
target_data[i] /= div_data[i];
}
return true;
}

View File

@@ -128,3 +128,27 @@ void ecl_kw_fix_uninitialized(ecl_kw_type * ecl_kw , int nx , int ny , int nz, c
int_vector_free( undetermined1 );
int_vector_free( undetermined2 );
}
ecl_kw_type * ecl_kw_alloc_actnum(const ecl_kw_type * porv_kw, float porv_limit) {
if (!ecl_type_is_float( porv_kw->data_type))
return NULL;
if (!util_string_equal(PORV_KW, ecl_kw_get_header(porv_kw)))
return NULL;
const int size = ecl_kw_get_size(porv_kw);
ecl_kw_type * actnum_kw = ecl_kw_alloc(ACTNUM_KW, size, ECL_INT);
const float * porv_values = ecl_kw_get_float_ptr(porv_kw);
int * actnum_values = ecl_kw_get_int_ptr( actnum_kw);
for (int i=0; i < size; i++) {
if (porv_values[i] > porv_limit)
actnum_values[i] = 1;
else
actnum_values[i] = 0;
}
return actnum_kw;
}

View File

@@ -42,7 +42,7 @@
b) There is not type information; presented with a bunch of
formatted numbers it is in general impossible to determine
whether the underlying datatype should be integer, float or
double. Therefor all the file-reading routines here expect an
double. Therefore all the file-reading routines here expect an
ecl_data_type as input.
2. The files can have comment sections; even in the data block.
@@ -159,7 +159,7 @@ char * ecl_kw_grdecl_alloc_next_header( FILE * stream ) {
This function will search through a GRDECL file to look for the
'kw'; input variables and return vales are similar to
ecl_kw_fseek_kw(). Observe that the GRDECL files are extremely
weakly structured, it is therefor veeeery easy to fool this function
weakly structured, it is therefore veeeery easy to fool this function
with a malformed GRDECL file.
In particular the comparison is case sensitive; that is probably not

View File

@@ -415,7 +415,7 @@ void ecl_rft_file_update(const char * rft_file_name, ecl_rft_node_type ** nodes,
/**
The sorting here works directly on the internal node storage
rft_file->data; that might in principle ruin the indexing of
the ecl_file object - it is therefor absolutely essential
the ecl_file object - it is therefore absolutely essential
that this ecl_rft_file object does not live beyond this
function, and also that the ecl_rft_file api functions are
avoided for the rest of this function.

View File

@@ -75,7 +75,7 @@ struct ecl_rft_node_struct {
The implementation of cell types based on _either_ RFT data or PLT
data is based on a misunderstanding and is currently WRONG. One
section in an RFT file can contain RFT data, PLT data and SEGMENT
data. The @data_type string should therefor not be interpreted as a
data. The @data_type string should therefore not be interpreted as a
type string, but rather as a "bit mask":

View File

@@ -88,10 +88,7 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ
// The only derived quantity
rsthead->sim_time = rsthead_date( rsthead->day , rsthead->month , rsthead->year );
}
if (doubhead_kw)
rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX );
rsthead->sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX );
if (logihead_kw)
rsthead->dualp = ecl_kw_iget_bool( logihead_kw , LOGIHEAD_DUALP_INDEX);
@@ -112,15 +109,12 @@ ecl_rsthead_type * ecl_rsthead_alloc_from_kw( int report_step , const ecl_kw_typ
ecl_rsthead_type * ecl_rsthead_alloc( const ecl_file_view_type * rst_view, int report_step) {
const ecl_kw_type * intehead_kw = ecl_file_view_iget_named_kw( rst_view , INTEHEAD_KW , 0);
const ecl_kw_type * doubhead_kw = NULL;
const ecl_kw_type * doubhead_kw = ecl_file_view_iget_named_kw( rst_view , DOUBHEAD_KW , 0);
const ecl_kw_type * logihead_kw = NULL;
if (ecl_file_view_has_kw(rst_view, LOGIHEAD_KW))
logihead_kw = ecl_file_view_iget_named_kw( rst_view , LOGIHEAD_KW , 0);
if (ecl_file_view_has_kw(rst_view, DOUBHEAD_KW))
doubhead_kw = ecl_file_view_iget_named_kw(rst_view, DOUBHEAD_KW, 0);
if (ecl_file_view_has_kw( rst_view , SEQNUM_KW)) {
const ecl_kw_type * seqnum_kw = ecl_file_view_iget_named_kw( rst_view , SEQNUM_KW , 0);
report_step = ecl_kw_iget_int( seqnum_kw , 0);

View File

@@ -141,6 +141,8 @@ struct ecl_smspec_struct {
float_vector_type * params_default;
char * restart_case;
ert_ecl_unit_enum unit_system;
int restart_step;
};
@@ -246,7 +248,7 @@ static const char* smspec_required_keywords[] = {
/*****************************************************************/
static ecl_smspec_type * ecl_smspec_alloc_empty(bool write_mode , const char * key_join_string) {
ecl_smspec_type * ecl_smspec_alloc_empty(bool write_mode , const char * key_join_string) {
ecl_smspec_type *ecl_smspec;
ecl_smspec = util_malloc(sizeof *ecl_smspec );
UTIL_TYPE_ID_INIT(ecl_smspec , ECL_SMSPEC_ID);
@@ -272,8 +274,16 @@ static ecl_smspec_type * ecl_smspec_alloc_empty(bool write_mode , const char * k
ecl_smspec->locked = false;
ecl_smspec->time_seconds = -1;
/*
The unit system is given as an integer in the INTEHEAD keyword. The INTEHEAD
keyword is optional, and we have for a long time been completely oblivious
to the possibility of extracting unit system information from the SMSPEC file.
*/
ecl_smspec->unit_system = ECL_METRIC_UNITS;
ecl_smspec->index_map = int_vector_alloc(0,0);
ecl_smspec->restart_case = NULL;
ecl_smspec->restart_step = -1;
ecl_smspec->params_default = float_vector_alloc(0 , PARAMS_GLOBAL_DEFAULT);
ecl_smspec->write_mode = write_mode;
ecl_smspec->need_nums = false;
@@ -357,137 +367,140 @@ static ecl_data_type get_wgnames_type(const ecl_smspec_type * smspec) {
return max_len <= ECL_STRING8_LENGTH ? ECL_CHAR : ECL_STRING(max_len);
}
// DIMENS
// KEYWORDS
// WGNAMES
// NUMS - optional
// UNITS
// STARTDAT
static void ecl_smspec_fwrite_INTEHEAD(const ecl_smspec_type * smspec, fortio_type * fortio) {
ecl_kw_type * intehead = ecl_kw_alloc( INTEHEAD_KW, INTEHEAD_SMSPEC_SIZE, ECL_INT);
ecl_kw_iset_int(intehead, INTEHEAD_SMSPEC_UNIT_INDEX, smspec->unit_system);
/*
The simulator type is just hardcoded to ECLIPSE100.
*/
ecl_kw_iset_int(intehead, INTEHEAD_SMSPEC_IPROG_INDEX, INTEHEAD_ECLIPSE100_VALUE);
ecl_kw_fwrite(intehead, fortio);
ecl_kw_free(intehead);
}
static void ecl_smspec_fwrite_RESTART(const ecl_smspec_type * smspec, fortio_type * fortio) {
ecl_kw_type * restart_kw = ecl_kw_alloc( RESTART_KW , SUMMARY_RESTART_SIZE , ECL_CHAR );
for (int i=0; i < SUMMARY_RESTART_SIZE; i++)
ecl_kw_iset_string8( restart_kw , i , "");
if (smspec->restart_case != NULL) {
int restart_case_len = strlen(smspec->restart_case);
int offset = 0;
for (int i = 0; i < SUMMARY_RESTART_SIZE ; i++) {
if (offset < restart_case_len)
ecl_kw_iset_string8( restart_kw , i , &smspec->restart_case[ offset ]);
offset += ECL_STRING8_LENGTH;
}
}
ecl_kw_fwrite( restart_kw , fortio );
ecl_kw_free( restart_kw );
}
static void ecl_smspec_fwrite_DIMENS(const ecl_smspec_type * smspec, fortio_type * fortio) {
ecl_kw_type * dimens_kw = ecl_kw_alloc( DIMENS_KW , DIMENS_SIZE , ECL_INT );
int num_nodes = ecl_smspec_num_nodes( smspec );
ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_SIZE_INDEX , num_nodes );
ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_NX_INDEX , smspec->grid_dims[0] );
ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_NY_INDEX , smspec->grid_dims[1] );
ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_NZ_INDEX , smspec->grid_dims[2] );
ecl_kw_iset_int( dimens_kw , 4 , 0 ); // Do not know what this is for.
ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_RESTART_STEP_INDEX , smspec->restart_step );
ecl_kw_fwrite( dimens_kw , fortio );
ecl_kw_free( dimens_kw );
}
static void ecl_smspec_fwrite_STARTDAT(const ecl_smspec_type * smspec, fortio_type * fortio) {
ecl_kw_type * startdat_kw = ecl_kw_alloc( STARTDAT_KW , STARTDAT_SIZE , ECL_INT );
int day,month,year;
ecl_util_set_date_values( smspec->sim_start_time , &day, &month , &year);
ecl_kw_iset_int( startdat_kw , STARTDAT_DAY_INDEX , day );
ecl_kw_iset_int( startdat_kw , STARTDAT_MONTH_INDEX , month );
ecl_kw_iset_int( startdat_kw , STARTDAT_YEAR_INDEX , year );
ecl_kw_fwrite( startdat_kw , fortio );
ecl_kw_free( startdat_kw );
}
static void ecl_smspec_fortio_fwrite( const ecl_smspec_type * smspec , fortio_type * fortio) {
int num_nodes = ecl_smspec_num_nodes( smspec );
{
ecl_kw_type * restart_kw = ecl_kw_alloc( RESTART_KW , SUMMARY_RESTART_SIZE , ECL_CHAR );
for (int i=0; i < SUMMARY_RESTART_SIZE; i++)
ecl_kw_iset_string8( restart_kw , i , "");
ecl_smspec_fwrite_INTEHEAD(smspec, fortio);
ecl_smspec_fwrite_RESTART(smspec, fortio);
ecl_smspec_fwrite_DIMENS(smspec, fortio);
if (smspec->restart_case != NULL) {
int restart_case_len = strlen(smspec->restart_case);
int offset = 0;
for (int i = 0; i < SUMMARY_RESTART_SIZE ; i++) {
if (offset < restart_case_len)
ecl_kw_iset_string8( restart_kw , i , &smspec->restart_case[ offset ]);
offset += ECL_STRING8_LENGTH;
}
}
int num_nodes = ecl_smspec_num_nodes( smspec );
ecl_kw_type * keywords_kw = ecl_kw_alloc( KEYWORDS_KW , num_nodes , ECL_CHAR );
ecl_kw_type * units_kw = ecl_kw_alloc( UNITS_KW , num_nodes , ECL_CHAR );
ecl_kw_type * nums_kw = NULL;
ecl_kw_fwrite( restart_kw , fortio );
ecl_kw_free( restart_kw );
}
{
ecl_kw_type * dimens_kw = ecl_kw_alloc( DIMENS_KW , DIMENS_SIZE , ECL_INT );
ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_SIZE_INDEX , num_nodes );
ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_NX_INDEX , smspec->grid_dims[0] );
ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_NY_INDEX , smspec->grid_dims[1] );
ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_NZ_INDEX , smspec->grid_dims[2] );
// If the names_type is an ECL_STRING we expect this to be an INTERSECT
// summary, otherwise an ECLIPSE summary.
ecl_data_type names_type = get_wgnames_type(smspec);
ecl_kw_type * wgnames_kw = ecl_kw_alloc( ecl_type_is_char(names_type) ? WGNAMES_KW : NAMES_KW,
num_nodes,
names_type );
/* Do not know what these two last items are for. */
ecl_kw_iset_int( dimens_kw , 4 , 0 );
ecl_kw_iset_int( dimens_kw , 5 , -1 );
if (smspec->need_nums)
nums_kw = ecl_kw_alloc( NUMS_KW , num_nodes , ECL_INT);
ecl_kw_fwrite( dimens_kw , fortio );
ecl_kw_free( dimens_kw );
}
for (int i=0; i < ecl_smspec_num_nodes( smspec ); i++) {
const smspec_node_type * smspec_node = ecl_smspec_iget_node( smspec , i );
/*
It is possible to add variables with deferred initialisation
with the ecl_sum_add_blank_var() function. Before these
variables can be actually used for anything interesting they
must be initialized with the ecl_sum_init_var() function.
If a call to save the smspec file comes before all the
variable have been initialized things will potentially go
belly up. This is solved with the following uber-hack:
{
ecl_kw_type * keywords_kw = ecl_kw_alloc( KEYWORDS_KW , num_nodes , ECL_CHAR );
ecl_kw_type * units_kw = ecl_kw_alloc( UNITS_KW , num_nodes , ECL_CHAR );
ecl_kw_type * nums_kw = NULL;
o One of the well related keywords is chosen; in
particular 'WWCT' in this case.
// If the names_type is an ECL_STRING we expect this to be an INTERSECT
// summary, otherwise an ECLIPSE summary.
ecl_data_type names_type = get_wgnames_type(smspec);
ecl_kw_type * wgnames_kw = ecl_kw_alloc(
ecl_type_is_char(names_type) ? WGNAMES_KW : NAMES_KW,
num_nodes,
names_type
);
o The wgname value is set to DUMMY_WELL
if (smspec->need_nums)
nums_kw = ecl_kw_alloc( NUMS_KW , num_nodes , ECL_INT);
{
int i;
for (i=0; i < ecl_smspec_num_nodes( smspec ); i++) {
const smspec_node_type * smspec_node = ecl_smspec_iget_node( smspec , i );
/*
It is possible to add variables with deferred initialisation
with the ecl_sum_add_blank_var() function. Before these
variables can be actually used for anything interesting they
must be initialized with the ecl_sum_init_var() function.
If a call to save the smspec file comes before all the
variable have been initialized things will potentially go
belly up. This is solved with the following uber-hack:
o One of the well related keywords is chosen; in
particular 'WWCT' in this case.
o The wgname value is set to DUMMY_WELL
The use of DUMMY_WELL ensures that this field will be
ignored when/if this smspec file is read in at a later
stage.
*/
if (smspec_node_get_var_type( smspec_node ) == ECL_SMSPEC_INVALID_VAR) {
ecl_kw_iset_string8( keywords_kw , i , "WWCT" );
ecl_kw_iset_string8( units_kw , i , "????????");
ecl_kw_iset_string_ptr( wgnames_kw , i , DUMMY_WELL);
} else {
ecl_kw_iset_string8( keywords_kw , i , smspec_node_get_keyword( smspec_node ));
ecl_kw_iset_string8( units_kw , i , smspec_node_get_unit( smspec_node ));
{
const char * wgname = DUMMY_WELL;
if (smspec_node_get_wgname( smspec_node ))
wgname = smspec_node_get_wgname( smspec_node );
ecl_kw_iset_string_ptr( wgnames_kw , i , wgname);
}
}
if (nums_kw != NULL)
ecl_kw_iset_int( nums_kw , i , smspec_node_get_num( smspec_node ));
The use of DUMMY_WELL ensures that this field will be
ignored when/if this smspec file is read in at a later
stage.
*/
if (smspec_node_get_var_type( smspec_node ) == ECL_SMSPEC_INVALID_VAR) {
ecl_kw_iset_string8( keywords_kw , i , "WWCT" );
ecl_kw_iset_string8( units_kw , i , "????????");
ecl_kw_iset_string_ptr( wgnames_kw , i , DUMMY_WELL);
} else {
ecl_kw_iset_string8( keywords_kw , i , smspec_node_get_keyword( smspec_node ));
ecl_kw_iset_string8( units_kw , i , smspec_node_get_unit( smspec_node ));
{
const char * wgname = DUMMY_WELL;
if (smspec_node_get_wgname( smspec_node ))
wgname = smspec_node_get_wgname( smspec_node );
ecl_kw_iset_string_ptr( wgnames_kw , i , wgname);
}
}
ecl_kw_fwrite( keywords_kw , fortio );
ecl_kw_fwrite( wgnames_kw , fortio );
if (nums_kw != NULL)
ecl_kw_fwrite( nums_kw , fortio );
ecl_kw_fwrite( units_kw , fortio );
ecl_kw_free( keywords_kw );
ecl_kw_free( wgnames_kw );
ecl_kw_free( units_kw );
if (nums_kw != NULL)
ecl_kw_free( nums_kw );
ecl_kw_iset_int( nums_kw , i , smspec_node_get_num( smspec_node ));
}
ecl_kw_fwrite( keywords_kw , fortio );
ecl_kw_fwrite( wgnames_kw , fortio );
if (nums_kw != NULL)
ecl_kw_fwrite( nums_kw , fortio );
ecl_kw_fwrite( units_kw , fortio );
{
ecl_kw_type * startdat_kw = ecl_kw_alloc( STARTDAT_KW , STARTDAT_SIZE , ECL_INT );
int day,month,year;
ecl_util_set_date_values( smspec->sim_start_time , &day, &month , &year);
ecl_kw_free( keywords_kw );
ecl_kw_free( wgnames_kw );
ecl_kw_free( units_kw );
if (nums_kw != NULL)
ecl_kw_free( nums_kw );
ecl_kw_iset_int( startdat_kw , STARTDAT_DAY_INDEX , day );
ecl_kw_iset_int( startdat_kw , STARTDAT_MONTH_INDEX , month );
ecl_kw_iset_int( startdat_kw , STARTDAT_YEAR_INDEX , year );
ecl_kw_fwrite( startdat_kw , fortio );
ecl_kw_free( startdat_kw );
}
ecl_smspec_fwrite_STARTDAT(smspec, fortio);
}
@@ -501,14 +514,19 @@ void ecl_smspec_fwrite( const ecl_smspec_type * smspec , const char * ecl_case ,
free( filename );
}
ecl_smspec_type * ecl_smspec_alloc_writer( const char * key_join_string , const char * restart_case, time_t sim_start , bool time_in_days , int nx , int ny , int nz) {
ecl_smspec_type * ecl_smspec = ecl_smspec_alloc_empty( true , key_join_string );
if (restart_case != NULL) {
if (strlen(restart_case) <= (SUMMARY_RESTART_SIZE * ECL_STRING8_LENGTH))
ecl_smspec->restart_case = util_alloc_string_copy( restart_case );
else
return NULL;
static ecl_smspec_type * ecl_smspec_alloc_writer__( const char * key_join_string , const char * restart_case, int restart_step, time_t sim_start , bool time_in_days , int nx , int ny , int nz) {
ecl_smspec_type * ecl_smspec = ecl_smspec_alloc_empty( true , key_join_string );
/*
Only a total of 9 * 8 characters is set aside for the restart keyword, if
the supplied restart case is longer than that we silently ignore it.
*/
if (restart_case) {
if (strlen(restart_case) <= (SUMMARY_RESTART_SIZE * ECL_STRING8_LENGTH)) {
ecl_smspec->restart_case = util_alloc_string_copy( restart_case );
ecl_smspec->restart_step = restart_step;
}
}
ecl_smspec->grid_dims[0] = nx;
ecl_smspec->grid_dims[1] = ny;
@@ -547,6 +565,14 @@ ecl_smspec_type * ecl_smspec_alloc_writer( const char * key_join_string , const
return ecl_smspec;
}
ecl_smspec_type * ecl_smspec_alloc_restart_writer( const char * key_join_string , const char * restart_case, int restart_step, time_t sim_start , bool time_in_days , int nx , int ny , int nz) {
return ecl_smspec_alloc_writer__(key_join_string, restart_case, restart_step, sim_start, time_in_days, nx, ny, nz);
}
ecl_smspec_type * ecl_smspec_alloc_writer(const char * key_join_string, time_t sim_start, bool time_in_days, int nx, int ny , int nz) {
return ecl_smspec_alloc_writer__(key_join_string, NULL, 0, sim_start, time_in_days, nx, ny, nz);
}
UTIL_SAFE_CAST_FUNCTION( ecl_smspec , ECL_SMSPEC_ID )
@@ -1017,9 +1043,13 @@ static void ecl_smspec_load_restart( ecl_smspec_type * ecl_smspec , const ecl_fi
util_alloc_file_components( ecl_smspec->header_file , &path , NULL , NULL );
smspec_header = ecl_util_alloc_exfilename( path , restart_base , ECL_SUMMARY_HEADER_FILE , ecl_smspec->formatted , 0);
if (!util_same_file(smspec_header , ecl_smspec->header_file)) /* Restart from the current case is ignored. */ {
char * tmp_path = util_alloc_filename( path , restart_base , NULL );
ecl_smspec->restart_case = util_alloc_abs_path(tmp_path);
free( tmp_path );
if (util_is_abs_path(restart_base))
ecl_smspec->restart_case = util_alloc_string_copy( restart_base );
else {
char * tmp_path = util_alloc_filename( path , restart_base , NULL );
ecl_smspec->restart_case = util_alloc_abs_path(tmp_path);
free( tmp_path );
}
}
util_safe_free( path );
@@ -1147,6 +1177,16 @@ static bool ecl_smspec_fread_header(ecl_smspec_type * ecl_smspec, const char * h
if (ecl_file_has_kw(header , NUMS_KW))
nums = ecl_file_iget_named_kw(header , NUMS_KW , 0);
if (ecl_file_has_kw(header, INTEHEAD_KW)) {
const ecl_kw_type * intehead = ecl_file_iget_named_kw(header, INTEHEAD_KW, 0);
ecl_smspec->unit_system = ecl_kw_iget_int(intehead, INTEHEAD_SMSPEC_UNIT_INDEX);
/*
The second item in the INTEHEAD vector is an integer designating which
simulator has been used for the current simulation, that is currently
ignored.
*/
}
if (ecl_file_has_kw( header , LGRS_KW )) {/* The file has LGR information. */
lgrs = ecl_file_iget_named_kw( header , LGRS_KW , 0 );
numlx = ecl_file_iget_named_kw( header , NUMLX_KW , 0 );
@@ -1166,6 +1206,7 @@ static bool ecl_smspec_fread_header(ecl_smspec_type * ecl_smspec, const char * h
ecl_smspec->grid_dims[0] = ecl_kw_iget_int(dimens , DIMENS_SMSPEC_NX_INDEX );
ecl_smspec->grid_dims[1] = ecl_kw_iget_int(dimens , DIMENS_SMSPEC_NY_INDEX );
ecl_smspec->grid_dims[2] = ecl_kw_iget_int(dimens , DIMENS_SMSPEC_NZ_INDEX );
ecl_smspec->restart_step = ecl_kw_iget_int(dimens , DIMENS_SMSPEC_RESTART_STEP_INDEX);
ecl_smspec_set_params_size( ecl_smspec , ecl_kw_get_size(keywords));
ecl_util_get_file_type( header_file , &ecl_smspec->formatted , NULL );
@@ -1640,6 +1681,10 @@ const char * ecl_smspec_get_header_file( const ecl_smspec_type * ecl_smspec ) {
}
int ecl_smspec_get_restart_step(const ecl_smspec_type * ecl_smspec) {
return ecl_smspec->restart_step;
}
const char * ecl_smspec_get_restart_case( const ecl_smspec_type * ecl_smspec) {
return ecl_smspec->restart_case;
@@ -1884,3 +1929,7 @@ void ecl_smspec_sort( ecl_smspec_type * smspec ) {
}
}
ert_ecl_unit_enum ecl_smspec_get_unit_system(const ecl_smspec_type * smspec) {
return smspec->unit_system;
}

View File

@@ -35,6 +35,8 @@
#include <ert/ecl/ecl_util.h>
#include <ert/ecl/ecl_sum.h>
#include <ert/ecl/ecl_sum_data.h>
#include <ert/ecl/ecl_smspec.h>
#include <ert/ecl/ecl_sum_data.h>
#include <ert/ecl/smspec_node.h>
@@ -95,6 +97,7 @@ struct ecl_sum_struct {
UTIL_TYPE_ID_DECLARATION;
ecl_smspec_type * smspec; /* Internalized version of the SMSPEC file. */
ecl_sum_data_type * data; /* The data - can be NULL. */
ecl_sum_type * restart_case;
bool fmt_case;
@@ -149,6 +152,9 @@ void ecl_sum_set_case( ecl_sum_type * ecl_sum , const char * ecl_case) {
static ecl_sum_type * ecl_sum_alloc__( const char * input_arg , const char * key_join_string) {
if (!ecl_util_path_access(input_arg))
return NULL;
ecl_sum_type * ecl_sum = util_malloc( sizeof * ecl_sum );
UTIL_TYPE_ID_INIT( ecl_sum , ECL_SUM_ID );
@@ -162,6 +168,7 @@ static ecl_sum_type * ecl_sum_alloc__( const char * input_arg , const char * key
ecl_sum->smspec = NULL;
ecl_sum->data = NULL;
ecl_sum->restart_case = NULL;
return ecl_sum;
}
@@ -177,10 +184,10 @@ static bool ecl_sum_fread_data( ecl_sum_type * ecl_sum , const stringlist_type *
static void ecl_sum_fread_history( ecl_sum_type * ecl_sum ) {
ecl_sum_type * history = ecl_sum_fread_alloc_case__( ecl_smspec_get_restart_case( ecl_sum->smspec ) , ":" , true);
if (history) {
ecl_sum_data_add_case(ecl_sum->data , history->data );
ecl_sum_free( history );
ecl_sum_type * restart_case = ecl_sum_fread_alloc_case__( ecl_smspec_get_restart_case( ecl_sum->smspec ) , ":" , true);
if (restart_case) {
ecl_sum->restart_case = restart_case;
ecl_sum_data_add_case(ecl_sum->data , restart_case->data );
}
}
@@ -244,9 +251,11 @@ static bool ecl_sum_fread_case( ecl_sum_type * ecl_sum , bool include_restart) {
ecl_sum_type * ecl_sum_fread_alloc(const char *header_file , const stringlist_type *data_files , const char * key_join_string, bool include_restart) {
ecl_sum_type * ecl_sum = ecl_sum_alloc__( header_file , key_join_string );
if (!ecl_sum_fread( ecl_sum , header_file , data_files , include_restart)) {
ecl_sum_free( ecl_sum );
ecl_sum = NULL;
if (ecl_sum) {
if (!ecl_sum_fread( ecl_sum , header_file , data_files , include_restart)) {
ecl_sum_free( ecl_sum );
ecl_sum = NULL;
}
}
return ecl_sum;
}
@@ -274,6 +283,15 @@ smspec_node_type * ecl_sum_add_var( ecl_sum_type * ecl_sum , const char * keywor
return smspec_node;
}
smspec_node_type * ecl_sum_add_smspec_node(ecl_sum_type * ecl_sum, const smspec_node_type * node) {
return ecl_sum_add_var(ecl_sum,
smspec_node_get_keyword(node),
smspec_node_get_wgname(node),
smspec_node_get_num(node),
smspec_node_get_unit(node),
smspec_node_get_default(node));
}
smspec_node_type * ecl_sum_add_blank_var( ecl_sum_type * ecl_sum , float default_value) {
smspec_node_type * smspec_node = smspec_node_alloc_new( -1 , default_value );
@@ -299,23 +317,49 @@ ecl_sum_tstep_type * ecl_sum_add_tstep( ecl_sum_type * ecl_sum , int report_step
return ecl_sum_data_add_new_tstep( ecl_sum->data , report_step , sim_seconds );
}
static ecl_sum_type * ecl_sum_alloc_writer__( const char * ecl_case , const char * restart_case , int restart_step, bool fmt_output , bool unified , const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz) {
ecl_sum_type * ecl_sum_alloc_restart_writer( const char * ecl_case , const char * restart_case , bool fmt_output , bool unified , const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz) {
ecl_sum_type * ecl_sum = ecl_sum_alloc__( ecl_case , key_join_string );
ecl_sum_set_unified( ecl_sum , unified );
ecl_sum_set_fmt_case( ecl_sum , fmt_output );
if (ecl_sum) {
ecl_sum_set_unified( ecl_sum , unified );
ecl_sum_set_fmt_case( ecl_sum , fmt_output );
ecl_sum->smspec = ecl_smspec_alloc_writer( key_join_string , restart_case, sim_start , time_in_days , nx , ny , nz );
ecl_sum->data = ecl_sum_data_alloc_writer( ecl_sum->smspec );
if (restart_case)
ecl_sum->smspec = ecl_smspec_alloc_restart_writer( key_join_string , restart_case, restart_step, sim_start , time_in_days , nx , ny , nz );
else
ecl_sum->smspec = ecl_smspec_alloc_writer( key_join_string, sim_start, time_in_days, nx, ny, nz);
ecl_sum->data = ecl_sum_data_alloc_writer( ecl_sum->smspec );
}
return ecl_sum;
}
ecl_sum_type * ecl_sum_alloc_writer( const char * ecl_case , bool fmt_output , bool unified , const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz) {
return ecl_sum_alloc_restart_writer(ecl_case, NULL, fmt_output, unified, key_join_string, sim_start, time_in_days, nx, ny, nz);
ecl_sum_type * ecl_sum_alloc_restart_writer2( const char * ecl_case , const char * restart_case , int restart_step, bool fmt_output , bool unified , const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz) {
return ecl_sum_alloc_writer__(ecl_case, restart_case, restart_step, fmt_output, unified, key_join_string, sim_start, time_in_days, nx, ny, nz);
}
/*
This does not take in the restart_step argument is depcrecated. You should use the
ecl_sum_alloc_restart_writer2() function.
*/
ecl_sum_type * ecl_sum_alloc_restart_writer( const char * ecl_case , const char * restart_case, bool fmt_output , bool unified , const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz) {
int restart_step = 0;
return ecl_sum_alloc_writer__(ecl_case, restart_case, restart_step, fmt_output, unified, key_join_string, sim_start, time_in_days, nx, ny, nz);
}
ecl_sum_type * ecl_sum_alloc_writer( const char * ecl_case , bool fmt_output , bool unified , const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz) {
return ecl_sum_alloc_writer__(ecl_case, NULL, 0, fmt_output, unified, key_join_string, sim_start, time_in_days, nx, ny, nz);
}
void ecl_sum_fwrite( const ecl_sum_type * ecl_sum ) {
ecl_sum_fwrite_smspec( ecl_sum );
ecl_sum_data_fwrite( ecl_sum->data , ecl_sum->ecl_case , ecl_sum->fmt_case , ecl_sum->unified );
@@ -342,10 +386,13 @@ void ecl_sum_free_data( ecl_sum_type * ecl_sum ) {
void ecl_sum_free( ecl_sum_type * ecl_sum ) {
if (ecl_sum->data != NULL)
if (ecl_sum->restart_case)
ecl_sum_free(ecl_sum->restart_case);
if (ecl_sum->data)
ecl_sum_free_data( ecl_sum );
if (ecl_sum->smspec != NULL)
if (ecl_sum->smspec)
ecl_smspec_free( ecl_sum->smspec );
util_safe_free( ecl_sum->path );
@@ -390,7 +437,10 @@ void ecl_sum_free__(void * __ecl_sum) {
ecl_sum_type * ecl_sum_fread_alloc_case__(const char * input_file , const char * key_join_string , bool include_restart){
ecl_sum_type * ecl_sum = ecl_sum_alloc__(input_file , key_join_string);
ecl_sum_type * ecl_sum = ecl_sum_alloc__(input_file , key_join_string);
if (!ecl_sum)
return NULL;
if (ecl_sum_fread_case( ecl_sum , include_restart))
return ecl_sum;
else {
@@ -690,6 +740,67 @@ const char * ecl_sum_get_general_var_unit( const ecl_sum_type * ecl_sum , const
/*****************************************************************/
ecl_sum_type * ecl_sum_alloc_resample(const ecl_sum_type * ecl_sum, const char * ecl_case, const time_t_vector_type * times) {
time_t start_time = ecl_sum_get_data_start(ecl_sum);
if ( time_t_vector_get_first(times) < start_time )
return NULL;
if ( time_t_vector_get_last(times) > ecl_sum_get_end_time(ecl_sum) )
return NULL;
if ( !time_t_vector_is_sorted(times, false) )
return NULL;
const int * grid_dims = ecl_smspec_get_grid_dims(ecl_sum->smspec);
bool time_in_days = false;
const smspec_node_type * node = ecl_smspec_iget_node(ecl_sum->smspec, 0);
if ( util_string_equal(smspec_node_get_unit(node), "DAYS" ) )
time_in_days = true;
ecl_sum_type * ecl_sum_resampled = ecl_sum_alloc_writer( ecl_case , ecl_sum->fmt_case , ecl_sum->unified , ecl_sum->key_join_string , start_time , time_in_days , grid_dims[0] , grid_dims[1] , grid_dims[2] );
for (int i = 0; i < ecl_smspec_num_nodes(ecl_sum->smspec); i++) {
const smspec_node_type * node = ecl_smspec_iget_node(ecl_sum->smspec, i);
if (util_string_equal(smspec_node_get_gen_key1(node), "TIME"))
continue;
if (!smspec_node_is_valid(node))
continue;
ecl_sum_add_smspec_node( ecl_sum_resampled, node );
}
/*
The SMSPEC header structure has been completely initialized, it is time to
start filling it up with data.
*/
ecl_sum_vector_type * ecl_sum_vector = ecl_sum_vector_alloc(ecl_sum, true);
double_vector_type * data = double_vector_alloc( ecl_sum_vector_get_size(ecl_sum_vector) , 0);
for (int report_step = 0; report_step < time_t_vector_size(times); report_step++) {
time_t t = time_t_vector_iget(times, report_step);
/* Look up interpolated data in the original case. */
ecl_sum_get_interp_vector( ecl_sum, t, ecl_sum_vector, data);
/* Add timestep corresponding to the interpolated data in the resampled case. */
ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum_resampled , report_step , t - start_time);
for (int data_index = 0; data_index < ecl_sum_vector_get_size(ecl_sum_vector); data_index++) {
double value = double_vector_iget(data,data_index);
int params_index = data_index + 1; // The +1 shift is because the first element in the tstep is time value.
ecl_sum_tstep_iset(tstep, params_index, value);
}
}
double_vector_free( data );
ecl_sum_vector_free( ecl_sum_vector );
return ecl_sum_resampled;
}
double ecl_sum_iget( const ecl_sum_type * ecl_sum , int time_index , int param_index) {
return ecl_sum_data_iget(ecl_sum->data , time_index , param_index);
}
@@ -1053,6 +1164,14 @@ void ecl_sum_export_csv(const ecl_sum_type * ecl_sum , const char * filename ,
}
const ecl_sum_type * ecl_sum_get_restart_case(const ecl_sum_type * ecl_sum) {
return ecl_sum->restart_case;
}
int ecl_sum_get_restart_step(const ecl_sum_type * ecl_sum) {
return ecl_smspec_get_restart_step(ecl_sum->smspec);
}
const char * ecl_sum_get_case(const ecl_sum_type * ecl_sum) {
return ecl_sum->ecl_case;
@@ -1300,3 +1419,8 @@ time_t_vector_type * ecl_sum_alloc_time_solution( const ecl_sum_type * ecl_sum ,
}
return solution;
}
ert_ecl_unit_enum ecl_sum_get_unit_system(const ecl_sum_type * ecl_sum) {
return ecl_smspec_get_unit_system(ecl_sum->smspec);
}

View File

@@ -17,6 +17,7 @@
*/
#include <string.h>
#include <math.h>
#include <ert/util/util.h>
#include <ert/util/vector.h>
@@ -927,9 +928,15 @@ void ecl_sum_data_add_case(ecl_sum_data_type * self, const ecl_sum_data_type * o
ecl_sum_tstep_type * other_tstep = ecl_sum_data_iget_ministep( other , tstep_nr );
/*
The dataset 'self' is the authorative in the timeinterval where
it has data, so if 'other' also has data in the same time interval
that is discarded.
The dataset 'self' is the authorative in the timeinterval where it has
data, so if 'other' also has data in the same time interval that is
discarded. In most cases 'other' will represent a history case, and 'self'
is a prediction which has been restarted.
After implementing the time_interval_contains() based check it turned out
that the smspec structure also contains a restart_step integer value in
the DIMENS vector which could probably be used to achieve the same thing.
That field is currently not used.
*/
if (!time_interval_contains( self->sim_time , ecl_sum_tstep_get_sim_time( other_tstep ))) {
@@ -1180,12 +1187,10 @@ double ecl_sum_data_interp_get(const ecl_sum_data_type * data , int time_index1
}
static double ecl_sum_data_vector_iget(const ecl_sum_data_type * data, time_t sim_time, const ecl_sum_vector_type * keylist, int key_index,
static double ecl_sum_data_vector_iget(const ecl_sum_data_type * data, time_t sim_time, int params_index, bool is_rate,
int time_index1 , int time_index2 , double weight1 , double weight2 ) {
int params_index = ecl_sum_vector_iget_param_index(keylist, key_index);
double value = 0.0;
bool is_rate = ecl_sum_vector_iget_is_rate(keylist, key_index);
if (is_rate) {
int time_index = ecl_sum_data_get_index_from_sim_time(data, sim_time);
// uses step function since it is a rate
@@ -1205,15 +1210,35 @@ void ecl_sum_data_fwrite_interp_csv_line(const ecl_sum_data_type * data, time_t
ecl_sum_data_init_interp_from_sim_time(data, sim_time, &time_index1, &time_index2, &weight1, &weight2);
for (int i = 0; i < num_keywords; i++) {
double value = ecl_sum_data_vector_iget( data, sim_time, keylist , i , time_index1, time_index2, weight1, weight2);
if (ecl_sum_vector_iget_valid(keylist, i)) {
int params_index = ecl_sum_vector_iget_param_index(keylist, i);
bool is_rate = ecl_sum_vector_iget_is_rate(keylist, i);
double value = ecl_sum_data_vector_iget( data, sim_time, params_index , is_rate, time_index1, time_index2, weight1, weight2);
if (i == 0)
fprintf(fp, "%f", value);
else
fprintf(fp, ",%f", value);
if (i == 0)
fprintf(fp, "%f", value);
else
fprintf(fp, ",%f", value);
} else {
if (i == 0)
fputs("", fp);
else
fputs(",", fp);
}
}
}
/*
If the keylist contains invalid indices the corresponding element in the
results vector will *not* be updated; i.e. it is smart to initialize the
results vector with an invalid-value marker before calling this function:
double_vector_type * results = double_vector_alloc( ecl_sum_vector_get_size(keys), NAN);
ecl_sum_data_get_interp_vector( data, sim_time, keys, results);
*/
void ecl_sum_data_get_interp_vector( const ecl_sum_data_type * data , time_t sim_time, const ecl_sum_vector_type * keylist, double_vector_type * results){
int num_keywords = ecl_sum_vector_get_size(keylist);
double weight1, weight2;
@@ -1222,8 +1247,12 @@ void ecl_sum_data_get_interp_vector( const ecl_sum_data_type * data , time_t sim
ecl_sum_data_init_interp_from_sim_time(data, sim_time, &time_index1, &time_index2, &weight1, &weight2);
double_vector_reset( results );
for (int i = 0; i < num_keywords; i++) {
double value = ecl_sum_data_vector_iget( data, sim_time, keylist , i , time_index1, time_index2, weight1, weight2);
double_vector_iset( results, i , value );
if (ecl_sum_vector_iget_valid(keylist, i)) {
int params_index = ecl_sum_vector_iget_param_index(keylist, i);
bool is_rate = ecl_sum_vector_iget_is_rate(keylist, i);
double value = ecl_sum_data_vector_iget( data, sim_time, params_index, is_rate, time_index1, time_index2, weight1, weight2);
double_vector_iset( results, i , value );
}
}
}
@@ -1414,7 +1443,7 @@ void ecl_sum_data_init_time_vector( const ecl_sum_data_type * data , time_t_vect
}
} else {
int i;
for (i = 0; i < vector_get_size(data->data); i++) {
for (i = 1; i < vector_get_size(data->data); i++) {
const ecl_sum_tstep_type * ministep = ecl_sum_data_iget_ministep( data , i );
time_t_vector_append( time_vector , ecl_sum_tstep_get_sim_time( ministep ));
}

View File

@@ -42,39 +42,91 @@ void ecl_sum_vector_free( ecl_sum_vector_type * ecl_sum_vector ){
int_vector_free(ecl_sum_vector->node_index_list);
bool_vector_free(ecl_sum_vector->is_rate_list);
stringlist_free(ecl_sum_vector->key_list);
free(ecl_sum_vector);
}
UTIL_IS_INSTANCE_FUNCTION( ecl_sum_vector , ECL_SUM_VECTOR_TYPE_ID )
static void ecl_sum_vector_add_node(ecl_sum_vector_type * vector, const smspec_node_type * node, const char * key ) {
int params_index = smspec_node_get_params_index( node );
bool is_rate_key = smspec_node_is_rate( node);
ecl_sum_vector_type * ecl_sum_vector_alloc(const ecl_sum_type * ecl_sum){
int_vector_append(vector->node_index_list, params_index);
bool_vector_append(vector->is_rate_list, is_rate_key);
stringlist_append_copy( vector->key_list, key );
}
ecl_sum_vector_type * ecl_sum_vector_alloc(const ecl_sum_type * ecl_sum, bool add_keywords) {
ecl_sum_vector_type * ecl_sum_vector = util_malloc( sizeof * ecl_sum_vector );
UTIL_TYPE_ID_INIT( ecl_sum_vector , ECL_SUM_VECTOR_TYPE_ID);
ecl_sum_vector->ecl_sum = ecl_sum;
ecl_sum_vector->node_index_list = int_vector_alloc(0,0);
ecl_sum_vector->is_rate_list = bool_vector_alloc(0,false);
ecl_sum_vector->key_list = stringlist_alloc_new( );
if (add_keywords) {
const ecl_smspec_type * smspec = ecl_sum_get_smspec(ecl_sum);
for (int i=0; i < ecl_smspec_num_nodes(smspec); i++) {
const smspec_node_type * node = ecl_smspec_iget_node( smspec , i );
if (!smspec_node_is_valid(node))
continue;
const char * key = smspec_node_get_gen_key1(node);
/*
The TIME keyword is special case handled to not be included; that is
to match the same special casing in the key matching function.
*/
if (!util_string_equal(key, "TIME"))
ecl_sum_vector_add_node( ecl_sum_vector, node, key);
}
}
return ecl_sum_vector;
}
static void ecl_sum_vector_add_invalid_key(ecl_sum_vector_type * vector, const char * key) {
int_vector_append(vector->node_index_list, -1);
bool_vector_append(vector->is_rate_list, false);
stringlist_append_copy(vector->key_list, key);
}
/*
This function will allocate a keyword vector for the keys in the @ecl_sum
argument passed in, it will contain all the same keys as in the input argument
@src_vector. If the @src_vector contains keys which are not present in
@ecl_sum an entry marked as *invalid* will be added. The whole point about
this function is to ensure that calls to:
ecl_sum_fwrite_interp_csv_line( )
will result in nicely aligned output even if the different summary cases do
not have the exact same keys.
*/
ecl_sum_vector_type * ecl_sum_vector_alloc_layout_copy(const ecl_sum_vector_type * src_vector, const ecl_sum_type * ecl_sum) {
ecl_sum_vector_type * new_vector = ecl_sum_vector_alloc(ecl_sum, false);
for (int i=0; i < stringlist_get_size(src_vector->key_list); i++) {
const char * key = stringlist_iget(src_vector->key_list, i);
if (ecl_sum_has_general_var(ecl_sum, key))
ecl_sum_vector_add_key(new_vector, key);
else
ecl_sum_vector_add_invalid_key(new_vector, key);
}
return new_vector;
}
bool ecl_sum_vector_add_key( ecl_sum_vector_type * ecl_sum_vector, const char * key){
if (ecl_sum_has_general_var( ecl_sum_vector->ecl_sum , key)) {
const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum_vector->ecl_sum , key );
int params_index = smspec_node_get_params_index( node );
bool is_rate_key = smspec_node_is_rate( node);
int_vector_append(ecl_sum_vector->node_index_list, params_index);
bool_vector_append(ecl_sum_vector->is_rate_list, is_rate_key);
stringlist_append_copy( ecl_sum_vector->key_list, key );
ecl_sum_vector_add_node(ecl_sum_vector, node, key);
return true;
} else
return false;
}
void ecl_sum_vector_add_keys( ecl_sum_vector_type * ecl_sum_vector, const char * pattern){
stringlist_type * keylist = ecl_sum_alloc_matching_general_var_list(ecl_sum_vector->ecl_sum , pattern);
@@ -83,12 +135,7 @@ void ecl_sum_vector_add_keys( ecl_sum_vector_type * ecl_sum_vector, const char *
for(i = 0; i < num_keywords ;i++){
const char * key = stringlist_iget(keylist, i);
const smspec_node_type * node = ecl_sum_get_general_var_node( ecl_sum_vector->ecl_sum , key );
int params_index = smspec_node_get_params_index( node );
bool is_rate_key = smspec_node_is_rate( node);
int_vector_append(ecl_sum_vector->node_index_list, params_index);
bool_vector_append(ecl_sum_vector->is_rate_list, is_rate_key);
stringlist_append_copy( ecl_sum_vector->key_list, key );
ecl_sum_vector_add_node(ecl_sum_vector, node, key);
}
stringlist_free(keylist);
}
@@ -101,6 +148,10 @@ bool ecl_sum_vector_iget_is_rate(const ecl_sum_vector_type * ecl_sum_vector, int
return bool_vector_iget(ecl_sum_vector->is_rate_list, index);
}
bool ecl_sum_vector_iget_valid(const ecl_sum_vector_type * ecl_sum_vector, int index) {
return (int_vector_iget(ecl_sum_vector->node_index_list, index) >= 0);
}
int ecl_sum_vector_iget_param_index(const ecl_sum_vector_type * ecl_sum_vector, int index){
return int_vector_iget(ecl_sum_vector->node_index_list, index);
}

View File

@@ -55,22 +55,6 @@
#define ECL_INIT_UFMT_PATTERN "INIT"
#define ECL_RFT_UFMT_PATTERN "RFT"
#ifdef ERT_WINDOWS
/*
The filename matching function on windows onyl recognizes the '*'
and '?' wildcard characters.
*/
#define ECL_RESTART_FMT_PATTERN "F????"
#define ECL_SUMMARY_FMT_PATTERN "A????"
#define ECL_RESTART_UFMT_PATTERN "X????"
#define ECL_SUMMARY_UFMT_PATTERN "S????"
#else
#define ECL_RESTART_FMT_PATTERN "F[0-9][0-9][0-9][0-9]"
#define ECL_SUMMARY_FMT_PATTERN "A[0-9][0-9][0-9][0-9]"
#define ECL_RESTART_UFMT_PATTERN "X[0-9][0-9][0-9][0-9]"
#define ECL_SUMMARY_UFMT_PATTERN "S[0-9][0-9][0-9][0-9]"
#endif
@@ -122,37 +106,15 @@ char * ecl_util_alloc_base_guess(const char * path) {
int ecl_util_filename_report_nr(const char *filename) {
char *ext = strrchr(filename , '.');
if (ext == NULL)
return -1;
if (ext[1] == 'X' || ext[1] == 'F' || ext[1] == 'S' || ext[1] == 'A')
return atoi(&ext[2]);
return -1;
int report_nr = -1;
ecl_util_get_file_type(filename, NULL, &report_nr);
return report_nr;
}
/*
bool ecl_util_numeric_extension(const char * extension) {
const char digit_ascii_min = 48;
const char digit_ascii_max = 57;
bool valid = true;
int pos = 1;
while (valid && pos <= 5) {
char c = extension[pos];
valid = (valid & (c >= digit_ascii_min && c <= digit_ascii_max));
if (!valid)
break;
}
return valid;
}
*/
/*
We accept mixed lowercase/uppercase Eclipse file extensions even if Eclipse itself does not accept them.
@@ -252,39 +214,26 @@ ecl_file_enum ecl_util_inspect_extension(const char * ext , bool *_fmt_file, int
to the fundamental type, it is also determined whether the file is
formatted or not, and in the case of summary/restart files, which
report number this corresponds to.
*/
ecl_file_enum ecl_util_get_file_type(const char * filename, bool *_fmt_file, int * _report_nr) {
ecl_file_enum ecl_util_get_file_type(const char * filename, bool *fmt_file, int * report_nr) {
char *ext = strrchr(filename , '.');
if (ext != NULL) {
ext++;
return ecl_util_inspect_extension( ext , _fmt_file , _report_nr);
} else
if (ext == NULL)
return ECL_OTHER_FILE;
return ecl_util_inspect_extension( &ext[1] , fmt_file , report_nr);
}
static const char * ecl_util_get_file_pattern( ecl_file_enum file_type , bool fmt_file ) {
if (fmt_file) {
switch( file_type ) {
case( ECL_OTHER_FILE ):
return ECL_OTHER_FILE_FMT_PATTERN; /* '*' */
break;
case( ECL_RESTART_FILE ):
return ECL_RESTART_FMT_PATTERN;
break;
case( ECL_UNIFIED_RESTART_FILE ):
return ECL_UNIFIED_RESTART_FMT_PATTERN;
break;
case( ECL_SUMMARY_FILE ):
return ECL_SUMMARY_FMT_PATTERN;
break;
case( ECL_UNIFIED_SUMMARY_FILE ):
return ECL_UNIFIED_SUMMARY_FMT_PATTERN;
break;
@@ -312,15 +261,9 @@ static const char * ecl_util_get_file_pattern( ecl_file_enum file_type , bool fm
case( ECL_OTHER_FILE ):
return ECL_OTHER_FILE_UFMT_PATTERN; /* '*' */
break;
case( ECL_RESTART_FILE ):
return ECL_RESTART_UFMT_PATTERN;
break;
case( ECL_UNIFIED_RESTART_FILE ):
return ECL_UNIFIED_RESTART_UFMT_PATTERN;
break;
case( ECL_SUMMARY_FILE ):
return ECL_SUMMARY_UFMT_PATTERN;
break;
case( ECL_UNIFIED_SUMMARY_FILE ):
return ECL_UNIFIED_SUMMARY_UFMT_PATTERN;
break;
@@ -392,6 +335,28 @@ const char * ecl_util_file_type_name( ecl_file_enum file_type ) {
return NULL;
}
static bool valid_base(const char * input_base, bool * upper_case) {
bool upper = false;
bool lower = false;
const char * base = strrchr(input_base, UTIL_PATH_SEP_CHAR);
if (base == NULL)
base = input_base;
for (int i=0; i < strlen(base); i++) {
char c = base[i];
if (isupper(c))
upper = true;
if (islower(c))
lower = true;
}
if (upper_case)
*upper_case = upper;
return !(lower && upper);
}
@@ -408,6 +373,11 @@ const char * ecl_util_file_type_name( ecl_file_enum file_type ) {
*/
static char * ecl_util_alloc_filename_static(const char * path, const char * base , ecl_file_enum file_type , bool fmt_file, int report_nr, bool must_exist) {
bool upper_case;
if (!valid_base(base, &upper_case))
return NULL;
char * filename;
char * ext;
switch (file_type) {
@@ -484,6 +454,11 @@ static char * ecl_util_alloc_filename_static(const char * path, const char * bas
ext = NULL;
}
if (!upper_case) {
for (int i=0; i < strlen(ext); i++)
ext[i] = tolower(ext[i]);
}
filename = util_alloc_filename(path , base , ext);
free(ext);
@@ -570,24 +545,134 @@ int ecl_util_fname_report_cmp(const void *f1, const void *f2) {
starts.
*/
static bool numeric_extension_predicate(const char * filename, const char * base, const char leading_char) {
if (strncmp(filename, base, strlen(base)) != 0)
return false;
const char * ext_start = strrchr(filename, '.');
if (!ext_start)
return false;
if (strlen(ext_start) != 6)
return false;
if (ext_start[1] != leading_char)
return false;
for (int i=0; i < 4; i++)
if (!isdigit(ext_start[i+2]))
return false;
return true;
}
static bool summary_UPPERCASE_ASCII(const char * filename, const void * base) {
return numeric_extension_predicate(filename, base, 'A');
}
static bool summary_UPPERCASE_BINARY(const char * filename, const void * base) {
return numeric_extension_predicate(filename, base, 'S');
}
static bool summary_lowercase_ASCII(const char * filename, const void * base) {
return numeric_extension_predicate(filename, base, 'a');
}
static bool summary_lowercase_BINARY(const char * filename, const void * base) {
return numeric_extension_predicate(filename, base, 's');
}
static bool restart_UPPERCASE_ASCII(const char * filename, const void * base) {
return numeric_extension_predicate(filename, base, 'F');
}
static bool restart_UPPERCASE_BINARY(const char * filename, const void * base) {
return numeric_extension_predicate(filename, base, 'X');
}
static bool restart_lowercase_ASCII(const char * filename, const void * base) {
return numeric_extension_predicate(filename, base, 'f');
}
static bool restart_lowercase_BINARY(const char * filename, const void * base) {
return numeric_extension_predicate(filename, base, 'x');
}
static int ecl_util_select_predicate_filelist(const char * path, const char * base, ecl_file_enum file_type, bool fmt_file, bool upper_case, stringlist_type * filelist) {
file_pred_ftype * predicate = NULL;
char * full_path = NULL;
char * pure_base = NULL;
{
char * tmp = util_alloc_filename(path, base, NULL);
util_alloc_file_components(tmp, &full_path, &pure_base, NULL);
free(tmp);
}
if (file_type == ECL_SUMMARY_FILE) {
if (fmt_file) {
if (upper_case)
predicate = summary_UPPERCASE_ASCII;
else
predicate = summary_lowercase_ASCII;
} else {
if (upper_case)
predicate = summary_UPPERCASE_BINARY;
else
predicate = summary_lowercase_BINARY;
}
} else if (file_type == ECL_RESTART_FILE) {
if (fmt_file) {
if (upper_case)
predicate = restart_UPPERCASE_ASCII;
else
predicate = restart_lowercase_ASCII;
} else {
if (upper_case)
predicate = restart_UPPERCASE_BINARY;
else
predicate = restart_lowercase_BINARY;
}
} else
util_abort("%s: internal error - method called with wrong file type: %d\n", __func__, file_type);
stringlist_select_files(filelist, full_path, predicate, pure_base);
stringlist_sort( filelist , ecl_util_fname_report_cmp );
free(pure_base);
free(full_path);
return stringlist_get_size(filelist);
}
int ecl_util_select_filelist( const char * path , const char * base , ecl_file_enum file_type , bool fmt_file , stringlist_type * filelist) {
char * file_pattern;
char * base_pattern;
const char * extension = ecl_util_get_file_pattern( file_type , fmt_file );
if (base == NULL)
base_pattern = util_alloc_string_copy( "*" );
else
base_pattern = util_alloc_string_copy( base );
bool valid_case = true;
bool upper_case = true;
stringlist_clear(filelist);
file_pattern = util_alloc_filename( NULL , base_pattern , extension );
stringlist_select_matching_files( filelist , path , file_pattern );
if ((file_type == ECL_SUMMARY_FILE) || (file_type == ECL_RESTART_FILE))
stringlist_sort( filelist , ecl_util_fname_report_cmp );
if (base)
valid_case = valid_base(base, &upper_case);
free( base_pattern );
free( file_pattern );
if (valid_case) {
if (file_type == ECL_SUMMARY_FILE || file_type == ECL_RESTART_FILE)
return ecl_util_select_predicate_filelist(path, base, file_type, fmt_file, upper_case, filelist);
char * ext_pattern = util_alloc_string_copy(ecl_util_get_file_pattern( file_type , fmt_file ));
char * file_pattern;
if (!upper_case) {
for (int i=0; i < strlen(ext_pattern); i++)
ext_pattern[i] = tolower(ext_pattern[i]);
}
if (base)
file_pattern = util_alloc_filename(NULL , base, ext_pattern);
else
file_pattern = util_alloc_filename(NULL, "*", ext_pattern);
stringlist_select_matching_files( filelist , path , file_pattern );
free( file_pattern );
free( ext_pattern );
}
return stringlist_get_size( filelist );
}
@@ -1274,29 +1359,7 @@ ert_ecl_unit_enum ecl_util_get_unit_set(const char * data_file) {
bool ecl_util_valid_basename( const char * basename ) {
char * eclbasename = util_split_alloc_filename(basename);
int upper_count = 0;
int lower_count = 0;
int index;
for (index = 0; index < strlen( eclbasename ); index++) {
int c = eclbasename[index];
if (isalpha(c)) {
if (isupper(c))
upper_count++;
else
lower_count++;
}
}
free(eclbasename);
if ((lower_count * upper_count) != 0)
return false;
else
return true;
return valid_base(basename, NULL);
}
@@ -1437,3 +1500,59 @@ void ecl_util_set_date_values(time_t t , int * mday , int * month , int * year)
}
#ifdef ERT_HAVE_UNISTD
#include <unistd.h>
#endif
/*
This is a small function which tries to give a sensible answer to the
question: Do I have read access to this eclipse simulation? The ecl_case
argument can either be a directory or the full path to a file, the filename
need not exists. The approach is as follows:
1. If @ecl_case corresponds to an existing filesystem entry - just return
access(ecl_case, R_OK).
2. If @ecl_case corresponds to a non-existing entry:
a) If there is a directory part - return access(dir, R_OK).
b) No directory part - return access(cwd, R_OK);
For the case 2b) the situation is that we test for read access to CWD,
that could in principle be denied - but that is a highly contrived
situation and we just return true.
ecl_util_access_path("PATH") -> access("PATH", R_OK);
ecl_util_access_path("PATH/FILE_EXISTS") -> access("PATH/FILE_EXISTS", R_OK);
ecl_util_access_path("PATH/FILE_DOES_NOT_EXIST") -> access("PATH", R_OK);
ecl_util_access_path("PATH_DOES_NOT_EXIST") -> true
*/
bool ecl_util_path_access(const char * ecl_case) {
if (util_access(ecl_case, R_OK))
return true;
if (util_access(ecl_case, F_OK))
return false;
/* Check if the input argument corresponds to an existing directory and one
additional element, in that case we do an access check on the directory part. */
{
bool path_access;
char * dir_name;
const char * path_sep = strrchr(ecl_case, UTIL_PATH_SEP_CHAR);
if (!path_sep)
/* We are trying to access CWD - we return true without actually checking
access. */
return true;
dir_name = util_alloc_substring_copy(ecl_case, 0, path_sep - ecl_case);
path_access = util_access(dir_name, R_OK);
free(dir_name);
return path_access;
}
return false;
}

View File

@@ -34,7 +34,7 @@
The fault_block object is implemented as a separate object type in
the fault_block.c file; however the fault blocks should be closely
linked to the layer object in the fault_block_layer structure - it
is therefor not possible/legal to create a fault block instance by
is therefore not possible/legal to create a fault block instance by
itself. To support that encapsulation the fault_block.c file is included
here, and the functions:

View File

@@ -197,7 +197,7 @@ char * smspec_alloc_completion_num_key( const char * join_string , const char *
To support ECLIPSE behaviour where new wells/groups can be created
during the simulation it must be possible to create a smspec node
with an initially unknown well/group name; all gen_key formats which
use the wgname value must therefor accept a NULL value for wgname.
use the wgname value must therefore accept a NULL value for wgname.
*/
static char * smspec_alloc_wgname_key( const char * join_string , const char * keyword , const char * wgname) {

View File

@@ -1,19 +1,19 @@
/*
Copyright (C) 2014 Statoil ASA, Norway.
The file 'ecl_grid_corner.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
Copyright (C) 2014 Statoil ASA, Norway.
The file 'ecl_grid_corner.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <stdlib.h>
#include <stdbool.h>
@@ -40,7 +40,10 @@ void test_invalid( ecl_grid_type * grid) {
void test_OK( const ecl_grid_type * grid) {
double x,y,z;
double x8[8];
double y8[8];
double z8[8];
ecl_grid_get_corner_xyz( grid , 0,0,0,&x,&y,&z);
test_assert_double_equal( x,0 );
test_assert_double_equal( y,0 );
@@ -55,6 +58,14 @@ void test_OK( const ecl_grid_type * grid) {
test_assert_double_equal( x,10 );
test_assert_double_equal( y,10 );
test_assert_double_equal( z,10 );
ecl_grid_export_cell_corners1(grid, 456, x8, y8, z8);
for (int i=0; i < 8; i++) {
ecl_grid_get_cell_corner_xyz1(grid, 456, i, &x,&y,&z);
test_assert_double_equal(x,x8[i]);
test_assert_double_equal(y,y8[i]);
test_assert_double_equal(z,z8[i]);
}
}
@@ -65,7 +76,7 @@ int main( int argc , char ** argv) {
test_invalid( grid );
test_OK(grid);
ecl_grid_free( grid );
exit(0);
}

View File

@@ -1,25 +1,23 @@
/*
Copyright (C) 2013 Statoil ASA, Norway.
The file 'ecl_win64.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
Copyright (C) 2013 Statoil ASA, Norway.
The file 'ecl_win64.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <stdlib.h>
#include <stdbool.h>
#include <ert/util/rng.h>
#include <ert/ecl/ecl_kw.h>
#include <ert/ecl/ecl_file.h>
#include <ert/ecl/ecl_endian_flip.h>
@@ -32,11 +30,10 @@ int main( int argc , char ** argv) {
int num_kw = 1000; // Total file size should roughly exceed 2GB
int kw_size = 600000;
ecl_kw_type * kw = ecl_kw_alloc("KW" , kw_size , ECL_INT );
rng_type * rng = rng_alloc( MZRAN , INIT_DEFAULT );
int i;
offset_type file_size;
for (i=0; i < kw_size; i++)
ecl_kw_iset_int( kw , i , rng_get_int( rng , 912732 ));
for (i=0; i < kw_size; i++)
ecl_kw_iset_int( kw , i , i);
{
fortio_type * fortio = fortio_open_writer( "LARGE_FILE.UNRST" , false , ECL_ENDIAN_FLIP);
@@ -73,7 +70,7 @@ int main( int argc , char ** argv) {
fortio_fclose( fortio );
printf("Seek OK \n");
}
printf("Doing ecl_file_open(..)\n");
{
@@ -87,6 +84,6 @@ int main( int argc , char ** argv) {
}
remove( "LARGE_FILE.UNRST" );
exit(0);
}

View File

@@ -20,7 +20,7 @@
#include <stdbool.h>
#include <ert/util/test_util.h>
#include <ert/ecl/ecl_sum.h>
#include <ert/ecl/ecl_smspec.h>
void test_sort( ecl_smspec_type * smspec )
@@ -39,6 +39,18 @@ void test_sort( ecl_smspec_type * smspec )
}
void test_copy(const ecl_smspec_type * smspec1) {
ecl_sum_type * ecl_sum2 = ecl_sum_alloc_writer("CASE", false, true, ":", 0, true, 100, 100, 100);
ecl_smspec_type * smspec2 = ecl_sum_get_smspec(ecl_sum2);
for (int i=0; i < ecl_smspec_num_nodes(smspec1); i++) {
const smspec_node_type * node = ecl_smspec_iget_node(smspec1, i);
ecl_sum_add_smspec_node(ecl_sum2, node);
}
test_assert_true( ecl_smspec_equal(smspec1, smspec2));
ecl_sum_free(ecl_sum2);
}
int main(int argc, char ** argv) {
const char * case1 = argv[1];
const char * case2 = argv[2];

View File

@@ -0,0 +1,98 @@
#include <ert/util/test_util.h>
#include <ert/ecl/ecl_sum.h>
#include <ert/ecl/smspec_node.h>
ecl_sum_type * test_alloc_ecl_sum() {
time_t start_time = util_make_date_utc( 1,1,2010 );
ecl_sum_type * ecl_sum = ecl_sum_alloc_writer( "/tmp/CASE" , false , true , ":" , start_time , true , 10 , 10 , 10 );
double sim_seconds = 0;
int num_dates = 4;
double ministep_length = 86400; // seconds in a day
smspec_node_type * node1 = ecl_sum_add_var( ecl_sum , "FOPT" , NULL , 0 , "Barrels" , 99.0 );
smspec_node_type * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 567 , "BARS" , 0.0 );
smspec_node_type * node3 = ecl_sum_add_var( ecl_sum , "WWCT" , "OP-1" , 0 , "(1)" , 0.0 );
for (int report_step = 0; report_step < num_dates; report_step++) {
{
ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum , report_step + 1 , sim_seconds );
ecl_sum_tstep_set_from_node( tstep , node1 , report_step*2.0 );
ecl_sum_tstep_set_from_node( tstep , node2 , report_step*4.0 + 2.0 );
ecl_sum_tstep_set_from_node( tstep , node3 , report_step*6.0 + 4.0 );
}
sim_seconds += ministep_length * 3;
}
return ecl_sum;
}
void test_correct_time_vector() {
ecl_sum_type * ecl_sum = test_alloc_ecl_sum();
time_t_vector_type * t = time_t_vector_alloc( 0 , 0 );
time_t_vector_append(t, util_make_date_utc( 2,1,2010 ));
time_t_vector_append(t, util_make_date_utc( 4,1,2010 ));
time_t_vector_append(t, util_make_date_utc( 6,1,2010 ));
time_t_vector_append(t, util_make_date_utc( 8,1,2010 ));
ecl_sum_type * ecl_sum_resampled = ecl_sum_alloc_resample(ecl_sum, "kk", t);
test_assert_int_equal( ecl_sum_get_report_time(ecl_sum_resampled, 2) , util_make_date_utc( 6,1,2010 ));
const ecl_smspec_type * smspec_resampled = ecl_sum_get_smspec(ecl_sum_resampled);
const smspec_node_type * node1 = ecl_smspec_iget_node(smspec_resampled, 1);
const smspec_node_type * node2 = ecl_smspec_iget_node(smspec_resampled, 2);
const smspec_node_type * node3 = ecl_smspec_iget_node(smspec_resampled, 3);
test_assert_string_equal( "BPR" , smspec_node_get_keyword(node2) );
test_assert_string_equal( "BARS" , smspec_node_get_unit(node2) );
test_assert_double_equal(3.33333, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 6,1,2010 ), node1) );
test_assert_double_equal(3.33333, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 2,1,2010 ), node2) );
test_assert_double_equal(10.0000, ecl_sum_get_from_sim_time( ecl_sum_resampled, util_make_date_utc( 4,1,2010 ), node3) );
ecl_sum_free(ecl_sum_resampled);
time_t_vector_free(t);
ecl_sum_free(ecl_sum);
}
void test_time_before() {
ecl_sum_type * ecl_sum = test_alloc_ecl_sum();
time_t_vector_type * t = time_t_vector_alloc( 0 , 0 );
time_t_vector_append(t, util_make_date_utc( 1,1,2009 ));
test_assert_NULL( ecl_sum_alloc_resample(ecl_sum, "kk", t) );
time_t_vector_free(t);
ecl_sum_free(ecl_sum);
}
void test_time_after() {
ecl_sum_type * ecl_sum = test_alloc_ecl_sum();
time_t_vector_type * t = time_t_vector_alloc( 0 , 0 );
time_t_vector_append(t, util_make_date_utc( 1,1,2010 ));
time_t_vector_append(t, util_make_date_utc( 11,1,2010 ));
test_assert_NULL( ecl_sum_alloc_resample(ecl_sum, "kk", t) );
time_t_vector_free(t);
ecl_sum_free(ecl_sum);
}
void test_not_sorted() {
ecl_sum_type * ecl_sum = test_alloc_ecl_sum();
time_t_vector_type * t = time_t_vector_alloc( 0 , 0 );
time_t_vector_append(t, util_make_date_utc( 1,1,2010 ));
time_t_vector_append(t, util_make_date_utc( 3,1,2010 ));
time_t_vector_append(t, util_make_date_utc( 2,1,2010 ));
test_assert_NULL( ecl_sum_alloc_resample( ecl_sum, "kk", t) );
time_t_vector_free(t);
ecl_sum_free(ecl_sum);
}
int main() {
test_correct_time_vector();
test_time_before();
test_time_after();
test_not_sorted();
return 0;
}

View File

@@ -63,7 +63,7 @@ void test_is_oil_producer( const ecl_sum_type * ecl_sum) {
int main( int argc , char ** argv) {
const char * case1 = argv[1];
ecl_sum_type * ecl_sum1 = ecl_sum_fread_alloc_case( case1 , ":");
test_assert_true( ecl_sum_is_instance( ecl_sum1 ));

View File

@@ -61,7 +61,7 @@ double write_summary( const char * name , time_t start_time , int nx , int ny ,
int write_restart_summary(const char * name, const char * restart_name , int start_report_step, double sim_seconds, time_t start_time , int nx , int ny , int nz , int num_dates, int num_ministep, double ministep_length) {
ecl_sum_type * ecl_sum = ecl_sum_alloc_restart_writer( name , restart_name, false , true , ":" , start_time , true , nx , ny , nz );
smspec_node_type * node1 = ecl_sum_add_var( ecl_sum , "FOPT" , NULL , 0 , "Barrels" , 99.0 );
smspec_node_type * node2 = ecl_sum_add_var( ecl_sum , "BPR" , NULL , 567 , "BARS" , 0.0 );
@@ -70,8 +70,6 @@ int write_restart_summary(const char * name, const char * restart_name , int sta
int num_report_steps = start_report_step + num_dates;
for (int report_step = start_report_step; report_step < num_report_steps; report_step++) {
for (int step = 0; step < num_ministep; step++) {
{
ecl_sum_tstep_type * tstep = ecl_sum_add_tstep( ecl_sum , report_step + 1 , sim_seconds );
ecl_sum_tstep_set_from_node( tstep , node1 , sim_seconds);
@@ -147,7 +145,7 @@ void test_ecl_sum_alloc_restart_writer() {
int num_ministep = 10;
double ministep_length = 36000; // Seconds
int sim_seconds = write_summary( name1 , start_time , nx , ny , nz , num_dates , num_ministep , ministep_length);
int sim_seconds = write_summary( name1 , start_time , nx , ny , nz , num_dates , num_ministep , ministep_length);
sim_seconds = write_restart_summary( name2 , name1 , num_dates, sim_seconds, start_time , nx , ny , nz , num_dates , num_ministep , ministep_length);
ecl_sum_type * case1 = ecl_sum_fread_alloc_case( name1 , ":" );
@@ -157,20 +155,20 @@ void test_ecl_sum_alloc_restart_writer() {
test_assert_true( ecl_sum_has_key( case2 , "FOPT" ));
ecl_file_type * restart_file = ecl_file_open( "CASE2.SMSPEC" , 0 );
ecl_file_view_type * view_file = ecl_file_get_global_view( restart_file );
ecl_file_view_type * view_file = ecl_file_get_global_view( restart_file );
test_assert_true( ecl_file_view_has_kw(view_file, RESTART_KW));
ecl_kw_type * kw = ecl_file_view_iget_kw(view_file, 0);
test_assert_int_equal(8, ecl_kw_get_size(kw));
test_assert_string_equal( "CASE1 ", ecl_kw_iget_ptr( kw , 0 ) );
test_assert_string_equal( " ", ecl_kw_iget_ptr( kw , 1 ) );
ecl_kw_type * restart_kw = ecl_file_view_iget_named_kw(view_file, "RESTART", 0);
test_assert_int_equal(8, ecl_kw_get_size(restart_kw));
test_assert_string_equal( "CASE1 ", ecl_kw_iget_ptr( restart_kw , 0 ) );
test_assert_string_equal( " ", ecl_kw_iget_ptr( restart_kw , 1 ) );
for (int time_index=0; time_index < ecl_sum_get_data_length( case1 ); time_index++)
for (int time_index=0; time_index < ecl_sum_get_data_length( case1 ); time_index++)
test_assert_double_equal( ecl_sum_get_general_var( case1 , time_index , "FOPT"), ecl_sum_get_general_var( case2 , time_index , "FOPT"));
ecl_sum_free(case2);
ecl_sum_free(case1);
ecl_file_close(restart_file);
}
test_work_area_free( work_area );
}
@@ -186,27 +184,35 @@ void test_long_restart_names() {
const char * name = "THE_CASE";
test_work_area_type * work_area = test_work_area_alloc("sum_write_restart_long_name");
{
int restart_step = 77;
time_t start_time = util_make_date_utc( 1,1,2010 );
ecl_sum_type * ecl_sum = ecl_sum_alloc_restart_writer( name , restart_case , false , true , ":" , start_time , true , 3, 3, 3);
ecl_sum_type * ecl_sum = ecl_sum_alloc_restart_writer2( name , restart_case , restart_step, false , true , ":" , start_time , true , 3, 3, 3);
ecl_sum_fwrite( ecl_sum );
ecl_sum_free(ecl_sum);
ecl_file_type * smspec_file = ecl_file_open( "THE_CASE.SMSPEC" , 0 );
ecl_file_view_type * view_file = ecl_file_get_global_view( smspec_file );
ecl_file_view_type * view_file = ecl_file_get_global_view( smspec_file );
test_assert_true( ecl_file_view_has_kw(view_file, RESTART_KW));
ecl_kw_type * kw = ecl_file_view_iget_kw(view_file, 0);
test_assert_int_equal(8, ecl_kw_get_size(kw));
ecl_kw_type * restart_kw = ecl_file_view_iget_named_kw(view_file, "RESTART", 0);
test_assert_int_equal(8, ecl_kw_get_size(restart_kw));
for (int n = 0; n < 8; n++) {
char s[9]; sprintf(s, "WWWWGGG%d", n);
test_assert_string_equal(s, ecl_kw_iget_char_ptr(kw, n) );
test_assert_string_equal(s, ecl_kw_iget_char_ptr(restart_kw, n) );
}
ecl_file_close( smspec_file);
{
ecl_smspec_type * smspec = ecl_smspec_alloc_restart_writer( ":" , "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ", 10, start_time, true, 3, 3 ,3);
/*
Restart case is too long - it is ignored.
*/
test_assert_NULL( ecl_smspec_get_restart_case( smspec));
ecl_smspec_free( smspec);
}
test_assert_NULL( ecl_smspec_alloc_writer( ":" , "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ", start_time, true, 3, 3 ,3) );
}
test_work_area_free( work_area );
}
int main( int argc , char ** argv) {

View File

@@ -0,0 +1,120 @@
/*
Copyright (C) 2018 Statoil ASA, Norway.
The file 'ecl_util_filenames.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <stdlib.h>
#include <stdbool.h>
#include <ert/util/test_work_area.h>
#include <ert/util/test_util.h>
#include <ert/util/time_t_vector.h>
#include <ert/util/util.h>
#include <ert/ecl/ecl_util.h>
void test_filename_report_nr() {
test_assert_int_equal(78, ecl_util_filename_report_nr("Path/with/mixedCASE/case.x0078"));
test_assert_int_equal(78, ecl_util_filename_report_nr("Case.X0078"));
test_assert_int_equal(ECL_EGRID_FILE, ecl_util_get_file_type("path/WITH/xase/MyGrid.EGrid", NULL, NULL));
}
void test_filename_case() {
test_assert_NULL( ecl_util_alloc_filename(NULL, "mixedBase", ECL_EGRID_FILE, false, -1));
test_assert_string_equal( ecl_util_alloc_filename(NULL, "UPPER", ECL_EGRID_FILE, false, -1), "UPPER.EGRID");
test_assert_string_equal( ecl_util_alloc_filename(NULL , "lower", ECL_EGRID_FILE, false, -1), "lower.egrid");
}
void test_file_list() {
test_work_area_type * work_area = test_work_area_alloc("RESTART_FILES");
stringlist_type * s = stringlist_alloc_new();
for (int i = 0; i < 10; i += 2) {
char * fname = ecl_util_alloc_filename(NULL, "case", ECL_RESTART_FILE, true, i);
FILE * stream = util_fopen(fname, "w");
fclose(stream);
free( fname);
}
for (int i = 0; i < 10; i += 2) {
char * fname = util_alloc_sprintf("Case.F%04d", i);
FILE * stream = util_fopen(fname, "w");
fclose(stream);
free( fname);
}
ecl_util_select_filelist(NULL , "case" , ECL_RESTART_FILE, true, s);
test_assert_int_equal( stringlist_get_size(s), 5);
for (int i = 0; i < 5; i++) {
char * fname = ecl_util_alloc_filename(NULL, "case", ECL_RESTART_FILE, true, 2*i);
test_assert_string_equal( fname, stringlist_iget(s,i));
free( fname);
}
ecl_util_select_filelist(NULL , "Case" , ECL_RESTART_FILE, true, s);
test_assert_int_equal( stringlist_get_size(s), 0);
util_make_path("path");
for (int i=0; i < 10; i++) {
char * summary_file1 = ecl_util_alloc_filename("path", "CASE1", ECL_SUMMARY_FILE, false, i );
char * summary_file2 = ecl_util_alloc_filename("path", "CASE2", ECL_SUMMARY_FILE, true, i);
char * restart_file1 = ecl_util_alloc_filename("path", "CASE1", ECL_RESTART_FILE, false, i);
FILE * f1 = fopen(summary_file1, "w");
fclose(f1);
FILE * f2 = fopen(summary_file2, "w");
fclose(f2);
FILE * f3 = fopen(restart_file1, "w");
fclose(f3);
free(summary_file1);
free(summary_file2);
free(restart_file1);
}
printf("-----------------------------------------------------------------\n");
ecl_util_select_filelist(NULL, "path/CASE1", ECL_SUMMARY_FILE, false, s);
test_assert_int_equal(stringlist_get_size(s), 10);
ecl_util_select_filelist(NULL, "path/CASE1", ECL_SUMMARY_FILE, true, s);
test_assert_int_equal(stringlist_get_size(s), 0);
ecl_util_select_filelist(NULL, "path/CASE2", ECL_SUMMARY_FILE, true, s);
test_assert_int_equal(stringlist_get_size(s), 10);
ecl_util_select_filelist("path", "CASE1", ECL_SUMMARY_FILE, false, s);
test_assert_int_equal(stringlist_get_size(s), 10);
ecl_util_select_filelist("path", "CASE1", ECL_SUMMARY_FILE, true, s);
test_assert_int_equal(stringlist_get_size(s), 0);
ecl_util_select_filelist("path", "CASE2", ECL_SUMMARY_FILE, true, s);
test_assert_int_equal(stringlist_get_size(s), 10);
stringlist_free(s);
test_work_area_free(work_area);
}
int main(int argc , char ** argv) {
test_filename_report_nr();
test_filename_case();
test_file_list();
}

View File

@@ -0,0 +1,53 @@
/*
Copyright (C) 2018 Statoil ASA, Norway.
The file 'ecl_util_path_access.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <ert/util/util.h>
#include <ert/util/test_work_area.h>
#include <ert/util/test_util.h>
#include <ert/ecl/ecl_util.h>
void test_relative_access() {
test_work_area_type * work_area = test_work_area_alloc("access");
test_assert_false( ecl_util_path_access("No/directory/does/not/exist"));
util_make_path("path");
test_assert_true( ecl_util_path_access("path"));
test_assert_true( ecl_util_path_access("path/FILE_DOES_NOT_EXIST"));
{
FILE * f = util_fopen("path/file", "w");
fprintf(f,"Hello\n");
fclose(f);
}
test_assert_true( ecl_util_path_access("path/file"));
chmod("path/file", 0);
test_assert_false( ecl_util_path_access("path/file"));
test_assert_true( ecl_util_path_access("ECLIPSE_CASE"));
test_work_area_free( work_area );
}
int main(int argc, char ** argv) {
test_relative_access();
}

View File

@@ -62,8 +62,12 @@ int main(int argc , char ** argv) {
test_assert_true( well_segment_is_instance( well_branch_collection_iget_start_segment( branches , 0 )));
test_assert_true( well_segment_is_instance( well_branch_collection_get_start_segment( branches , 78 )));
test_assert_true( well_branch_collection_has_branch( branches , 78 ));
well_segment_free( segment2 );
well_segment_free( segment1 );
}
free( rseg_data );
well_branch_collection_free( branches );
exit(0);

View File

@@ -77,6 +77,8 @@ int main(int argc , char ** argv) {
test_assert_true( well_conn_equal( conn , conn2 ));
test_assert_false( well_conn_equal( conn , conn3 ));
test_assert_double_equal( CF , well_conn_get_connection_factor( conn ));
well_conn_free( conn3 );
well_conn_free( conn2 );
well_conn_free( conn );
}
@@ -107,6 +109,7 @@ int main(int argc , char ** argv) {
well_conn_dir_enum dir = well_conn_dirX;
well_conn_type * conn = well_conn_alloc_fracture(i,j,k,CF,dir,open);
test_assert_not_NULL( conn );
well_conn_free( conn );
}
{

View File

@@ -72,6 +72,7 @@ int main(int argc , char ** argv) {
test_assert_true( well_segment_nearest_wellhead( ws ));
test_assert_false( well_segment_main_stem( ws ));
well_segment_free( ws );
}
@@ -81,6 +82,7 @@ int main(int argc , char ** argv) {
well_segment_type * ws = well_segment_alloc(89 , outlet_segment_id , branch_nr, rseg_data);
test_assert_false( well_segment_active( ws ));
well_segment_free( ws );
}
{
@@ -96,6 +98,7 @@ int main(int argc , char ** argv) {
well_segment_link_strict( ws , outlet ); // This relinks - not very logical; refcount gets wrong.
well_segment_free( ws );
well_segment_free( outlet );
}
{
@@ -109,6 +112,7 @@ int main(int argc , char ** argv) {
test_assert_int_equal( well_segment_get_link_count( outlet ) , 0 );
well_segment_free( ws );
well_segment_free( outlet );
}
free( rseg_data );
exit(0);

View File

@@ -55,6 +55,10 @@ int main(int argc , char ** argv) {
test_assert_true( well_conn_collection_is_instance( well_segment_get_connections( ws , ECL_GRID_GLOBAL_GRID)));
test_assert_true( well_conn_collection_is_instance( well_segment_get_global_connections( ws)));
test_assert_NULL( well_segment_get_connections( ws , "doesNotExist"));
well_conn_free( conn1 );
well_conn_free( conn2 );
well_segment_free( ws );
}
free( rseg_data );
exit(0);

View File

@@ -1,4 +1,3 @@
#cmakedefine ERT_HAVE_LAPACK
#cmakedefine ERT_HAVE_ZLIB
#cmakedefine ERT_HAVE_ISFINITE
#cmakedefine ERT_HAVE_GETOPT

View File

@@ -107,7 +107,7 @@ inline const char* EclKW_ref< const char* >::at( size_t i ) const {
/*
The current implementation of "string" storage in the underlying C
ecl_kw structure does not lend itself to easily implement
operator[]. We have therefor explicitly deleted it here.
operator[]. We have therefore explicitly deleted it here.
*/
template<>

View File

@@ -254,6 +254,7 @@ extern "C" {
void ecl_grid_reset_actnum( ecl_grid_type * grid , const int * actnum );
void ecl_grid_compressed_kw_copy( const ecl_grid_type * grid , ecl_kw_type * target_kw , const ecl_kw_type * src_kw);
void ecl_grid_global_kw_copy( const ecl_grid_type * grid , ecl_kw_type * target_kw , const ecl_kw_type * src_kw);
void ecl_grid_export_cell_corners1(const ecl_grid_type * grid, int global_index, double *x, double *y, double *z);
UTIL_IS_INSTANCE_HEADER( ecl_grid );
UTIL_SAFE_CAST_HEADER( ecl_grid );

View File

@@ -174,6 +174,7 @@ extern "C" {
ecl_kw_type * ecl_kw_alloc_scatter_copy( const ecl_kw_type * src_kw , int target_size , const int * mapping, void * def_value);
void ecl_kw_inplace_add_squared(ecl_kw_type * target_kw, const ecl_kw_type * add_kw);
void ecl_kw_inplace_add( ecl_kw_type * target_kw , const ecl_kw_type * add_kw);
void ecl_kw_inplace_sub( ecl_kw_type * target_kw , const ecl_kw_type * sub_kw);
void ecl_kw_inplace_div( ecl_kw_type * target_kw , const ecl_kw_type * div_kw);

View File

@@ -303,7 +303,9 @@ values (2e20) are denoted with '*'.
#define INTEHEAD_TIMESTEP_INDEX 67
#define INTEHEAD_REPORT_STEP 68
#define INTEHEAD_IPROG_INDEX 94
#define INTEHEAD_REPORT_INDEX 219 (report_steps-1)
// The value seems to be: report_step - 1; might be previous?
#define INTEHEAD_REPORT_INDEX 219
#define INTEHEAD_METRIC_VALUE 1
@@ -339,6 +341,7 @@ values (2e20) are denoted with '*'.
#define LOGIHEAD_REV_ENDPOINT_SCALING_INDEX 18
#define LOGIHEAD_ALT_ENDPOINT_SCALING_INDEX 19
#define LOGIHEAD_MISC_DISPLACEMENT_INDEX 35
#define LOGIHEAD_CONSTANT_OILCOMPR_INDEX (39-1) /* Constant oil compressibility (PVCDO)? */
#define LOGIHEAD_SCALE_WATER_PC_AT_MAX_SAT_INDEX 55
#define LOGIHEAD_SCALE_GAS_PC_AT_MAX_SAT_INDEX 56
@@ -450,12 +453,16 @@ values (2e20) are denoted with '*'.
keyword in the SMSPEC files. Observe that these magic indices
differ from the magic indices used to look up grid dimensions from
the DIMENS keyword in GRID files. */
#define DIMENS_SMSPEC_SIZE_INDEX 0
#define DIMENS_SMSPEC_NX_INDEX 1
#define DIMENS_SMSPEC_NY_INDEX 2
#define DIMENS_SMSPEC_NZ_INDEX 3
#define DIMENS_SMSPEC_SIZE_INDEX 0
#define DIMENS_SMSPEC_NX_INDEX 1
#define DIMENS_SMSPEC_NY_INDEX 2
#define DIMENS_SMSPEC_NZ_INDEX 3
#define DIMENS_SMSPEC_RESTART_STEP_INDEX 5
#define DIMENS_SIZE 6
#define DIMENS_SIZE 6 // Do not know what the two last items are?
#define INTEHEAD_SMSPEC_SIZE 2
#define INTEHEAD_SMSPEC_UNIT_INDEX 0
#define INTEHEAD_SMSPEC_IPROG_INDEX 1
/* Summary data files: */

View File

@@ -29,6 +29,7 @@ extern "C" {
#include <ert/util/float_vector.h>
#include <ert/util/stringlist.h>
#include <ert/ecl/ecl_util.h>
#include <ert/ecl/smspec_node.h>
typedef struct ecl_smspec_struct ecl_smspec_type;
@@ -54,7 +55,11 @@ typedef struct ecl_smspec_struct ecl_smspec_type;
bool ecl_smspec_needs_wgname( ecl_smspec_var_type var_type );
const char * ecl_smspec_get_var_type_name( ecl_smspec_var_type var_type );
ecl_smspec_var_type ecl_smspec_identify_var_type(const char * var);
ecl_smspec_type * ecl_smspec_alloc_writer( const char * key_join_string , const char * restart_case, time_t sim_start , bool time_in_days , int nx , int ny , int nz);
ecl_smspec_type * ecl_smspec_alloc_empty(bool write_mode , const char * key_join_string);
ecl_smspec_type * ecl_smspec_alloc_restart_writer( const char * key_join_string , const char * restart_case, int restart_step, time_t sim_start , bool time_in_days , int nx , int ny , int nz);
ecl_smspec_type * ecl_smspec_alloc_writer( const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz);
void ecl_smspec_fwrite( const ecl_smspec_type * smspec , const char * ecl_case , bool fmt_file );
ecl_smspec_type * ecl_smspec_fread_alloc(const char *header_file, const char * key_join_string , bool include_restart);
@@ -128,6 +133,7 @@ typedef struct ecl_smspec_struct ecl_smspec_type;
stringlist_type * ecl_smspec_alloc_group_list( const ecl_smspec_type * smspec , const char * pattern);
stringlist_type * ecl_smspec_alloc_well_var_list( const ecl_smspec_type * smspec );
const char * ecl_smspec_get_simulation_path(const ecl_smspec_type * ecl_smspec);
int ecl_smspec_get_restart_step(const ecl_smspec_type * ecl_smspec);
const char * ecl_smspec_get_restart_case( const ecl_smspec_type * ecl_smspec);
const char * ecl_smspec_get_join_string( const ecl_smspec_type * smspec);
const float_vector_type * ecl_smspec_get_params_default( const ecl_smspec_type * ecl_smspec );
@@ -144,6 +150,7 @@ typedef struct ecl_smspec_struct ecl_smspec_type;
bool ecl_smspec_equal( const ecl_smspec_type * self , const ecl_smspec_type * other);
void ecl_smspec_sort( ecl_smspec_type * smspec );
ert_ecl_unit_enum ecl_smspec_get_unit_system(const ecl_smspec_type * smspec);
#ifdef __cplusplus
}

View File

@@ -94,6 +94,7 @@ typedef struct ecl_sum_struct ecl_sum_type;
ecl_sum_type * ecl_sum_fread_alloc(const char * , const stringlist_type * data_files, const char * key_join_string, bool include_restart);
ecl_sum_type * ecl_sum_fread_alloc_case(const char * , const char * key_join_string);
ecl_sum_type * ecl_sum_fread_alloc_case__(const char * , const char * key_join_string , bool include_restart);
ecl_sum_type * ecl_sum_alloc_resample(const ecl_sum_type * ecl_sum, const char * ecl_case, const time_t_vector_type * times);
bool ecl_sum_case_exists( const char * input_file );
/* Accessor functions : */
@@ -170,6 +171,7 @@ typedef struct ecl_sum_struct ecl_sum_type;
const char * ecl_sum_get_base(const ecl_sum_type * ecl_sum );
const char * ecl_sum_get_path(const ecl_sum_type * ecl_sum );
const char * ecl_sum_get_abs_path(const ecl_sum_type * ecl_sum );
const ecl_sum_type * ecl_sum_get_restart_case(const ecl_sum_type * ecl_sum);
const char * ecl_sum_get_case(const ecl_sum_type * );
bool ecl_sum_same_case( const ecl_sum_type * ecl_sum , const char * input_file );
@@ -200,7 +202,18 @@ typedef struct ecl_sum_struct ecl_sum_type;
int ecl_sum_iget_report_end( const ecl_sum_type * ecl_sum , int report_step );
int ecl_sum_iget_report_start( const ecl_sum_type * ecl_sum , int report_step );
ecl_sum_type * ecl_sum_alloc_restart_writer2( const char * ecl_case,
const char * restart_case,
int restart_step,
bool fmt_output,
bool unified,
const char * key_join_string,
time_t sim_start,
bool time_in_days,
int nx,
int ny,
int nz);
ecl_sum_type * ecl_sum_alloc_restart_writer(const char * ecl_case ,
const char * restart_case ,
bool fmt_output ,
@@ -221,6 +234,7 @@ typedef struct ecl_sum_struct ecl_sum_type;
void ecl_sum_set_case( ecl_sum_type * ecl_sum , const char * ecl_case);
void ecl_sum_fwrite( const ecl_sum_type * ecl_sum );
void ecl_sum_fwrite_smspec( const ecl_sum_type * ecl_sum );
smspec_node_type * ecl_sum_add_smspec_node(ecl_sum_type * ecl_sum, const smspec_node_type * node);
smspec_node_type * ecl_sum_add_var(ecl_sum_type * ecl_sum ,
const char * keyword ,
const char * wgname ,

View File

@@ -30,14 +30,17 @@ extern "C" {
typedef struct ecl_sum_vector_struct ecl_sum_vector_type;
void ecl_sum_vector_free( ecl_sum_vector_type * keylist );
ecl_sum_vector_type * ecl_sum_vector_alloc(const ecl_sum_type * ecl_sum);
ecl_sum_vector_type * ecl_sum_vector_alloc(const ecl_sum_type * ecl_sum, bool add_keywords);
bool ecl_sum_vector_add_key( ecl_sum_vector_type * keylist, const char * key);
void ecl_sum_vector_add_keys( ecl_sum_vector_type * keylist, const char * pattern);
const char* ecl_sum_vector_iget_key(const ecl_sum_vector_type * ecl_sum_vector, int index);
bool ecl_sum_vector_iget_is_rate(const ecl_sum_vector_type * ecl_sum_vector, int index);
int ecl_sum_vector_iget_param_index(const ecl_sum_vector_type * ecl_sum_vector, int index);
int ecl_sum_vector_get_size(const ecl_sum_vector_type * ecl_sum_vector);
bool ecl_sum_vector_iget_valid(const ecl_sum_vector_type * ecl_sum_vector, int index);
UTIL_IS_INSTANCE_HEADER( ecl_sum_vector);

View File

@@ -96,7 +96,6 @@ typedef enum {
#define ECL_PHASE_ENUM_DEFS {.value = 1 , .name = "ECL_OIL_PHASE"}, {.value = 2 , .name = "ECL_GAS_PHASE"} , {.value = 4 , .name = "ECL_WATER_PHASE"}
#define ECL_PHASE_ENUM_SIZE 3
typedef enum {
ECL_METRIC_UNITS = 1,
ECL_FIELD_UNITS = 2,
@@ -118,8 +117,8 @@ bool ecl_util_unified_file(const char *filename);
const char * ecl_util_file_type_name( ecl_file_enum file_type );
char * ecl_util_alloc_base_guess(const char *);
int ecl_util_filename_report_nr(const char *);
ecl_file_enum ecl_util_get_file_type(const char * , bool * , int * );
ecl_file_enum ecl_util_inspect_extension(const char * ext , bool *_fmt_file, int * _report_nr);
ecl_file_enum ecl_util_get_file_type(const char * filename, bool * fmt_file, int * report_nr);
char * ecl_util_alloc_filename(const char * /* path */, const char * /* base */, ecl_file_enum , bool /* fmt_file */ , int /*report_nr*/);
char * ecl_util_alloc_exfilename(const char * /* path */, const char * /* base */, ecl_file_enum , bool /* fmt_file */ , int /*report_nr*/);
void ecl_util_memcpy_typed_data(void *, const void * , ecl_data_type , ecl_data_type , int );
@@ -145,7 +144,7 @@ int ecl_util_select_filelist( const char * path , const char * base
void ecl_util_append_month_range( time_t_vector_type * date_list , time_t start_date , time_t end_date , bool force_append_end);
void ecl_util_init_month_range( time_t_vector_type * date_list , time_t start_date , time_t end_date);
void ecl_util_set_date_values(time_t t , int * mday , int * month , int * year);
bool ecl_util_path_access(const char * ecl_case);
#ifdef __cplusplus
}
#endif

View File

@@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'hash.h' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
Copyright (C) 2011 Statoil ASA, Norway.
The file 'hash.h' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#ifndef ERT_HASH_H
@@ -35,10 +35,7 @@ typedef void (hash_apply_ftype) (void * );
UTIL_SAFE_CAST_HEADER(hash);
UTIL_SAFE_CAST_HEADER_CONST(hash);
void hash_lock (hash_type * );
void hash_unlock(hash_type * );
hash_type * hash_alloc(void);
hash_type * hash_alloc_unlocked(void);
void hash_iter_complete(hash_type * );
void hash_free(hash_type *);
void hash_free__(void *);
@@ -55,12 +52,12 @@ void hash_safe_del(hash_type * , const char * );
void hash_clear(hash_type *);
int hash_get_size(const hash_type *);
void hash_set_keylist(const hash_type * , char **);
char ** hash_alloc_keylist(hash_type *);
stringlist_type * hash_alloc_stringlist(hash_type * );
char ** hash_alloc_keylist(const hash_type *);
stringlist_type * hash_alloc_stringlist(const hash_type * );
char ** hash_alloc_sorted_keylist (hash_type *hash , int ( hash_get_cmp_value ) (const void *));
char ** hash_alloc_key_sorted_list(hash_type *hash, int (*cmp)(const void *, const void *));
bool hash_key_list_compare( hash_type * hash1, hash_type * hash2);
char ** hash_alloc_sorted_keylist (const hash_type *hash , int ( hash_get_cmp_value ) (const void *));
char ** hash_alloc_key_sorted_list(const hash_type *hash, int (*cmp)(const void *, const void *));
bool hash_key_list_compare(const hash_type * hash1, const hash_type * hash2);
void hash_insert_hash_owned_ref(hash_type *, const char * , const void *, free_ftype *);
void hash_resize(hash_type *hash, int new_size);

View File

@@ -4,12 +4,12 @@
- The ERT code makes use of stdbool in many places. The msvc C
compiler does not have a stdbool header, i.e. the #include <stdbool.h>
statements fail when compiling.
statements fail when compiling.
- When included in a C++ project the compiler already has a bool
defined; it is therefor important not to redefine this symbol if
defined; it is therefore important not to redefine this symbol if
we are compiling C++.
*/
#ifndef __cplusplus

View File

@@ -25,7 +25,6 @@
#include <ert/util/ert_api_config.h>
#include <ert/util/type_macros.h>
#include <ert/util/int_vector.h>
#include <ert/util/buffer.h>
#ifdef __cplusplus
extern "C" {
@@ -34,6 +33,9 @@ extern "C" {
typedef struct stringlist_struct stringlist_type;
typedef int ( string_cmp_ftype) (const void * , const void *);
typedef bool ( file_pred_ftype) (const char *, const void *);
int stringlist_select_files(stringlist_type * names, const char * path, file_pred_ftype * predicate, const void * pred_arg);
const char * stringlist_get_last( const stringlist_type * stringlist );
char * stringlist_pop( stringlist_type * stringlist);
@@ -103,8 +105,6 @@ typedef int ( string_cmp_ftype) (const void * , const void *);
char ** stringlist_alloc_char_ref(const stringlist_type * stringlist);
void stringlist_fread(stringlist_type * , FILE * );
void stringlist_fwrite(const stringlist_type * , FILE * );
void stringlist_buffer_fread( stringlist_type * s , buffer_type * buffer );
void stringlist_buffer_fwrite( const stringlist_type * s , buffer_type * buffer );
void stringlist_sort(stringlist_type * , string_cmp_ftype * string_cmp);
void stringlist_reverse( stringlist_type * s );
void stringlist_python_sort( stringlist_type * s , int cmp_flag);

View File

@@ -134,8 +134,6 @@ typedef enum {left_pad = 0,
bool util_sscanf_date_utc(const char * , time_t *);
bool util_sscanf_isodate(const char * , time_t *);
bool util_sscanf_percent(const char * string, double * value);
char * util_alloc_stdin_line(void);
char * util_realloc_stdin_line(char * );
bool util_is_executable(const char * );
bool util_entry_exists( const char * entry );
bool util_file_exists(const char *);
@@ -164,6 +162,7 @@ typedef enum {left_pad = 0,
bool util_copy_file(const char * , const char * );
char * util_alloc_cwd(void);
bool util_is_cwd( const char * path );
char * util_alloc_normal_path( const char * input_path );
char * util_alloc_realpath(const char * );
char * util_alloc_realpath__(const char * input_path);
bool util_string_match(const char * string , const char * pattern);
@@ -175,7 +174,6 @@ typedef enum {left_pad = 0,
void util_usleep( unsigned long micro_seconds );
void util_yield(void);
char * util_blocking_alloc_stdin_line(unsigned long );
int util_roundf( float x );
int util_round( double x );
@@ -213,7 +211,7 @@ typedef enum {left_pad = 0,
int util_count_file_lines(FILE * );
FILE * util_mkdir_fopen( const char * filename , const char * mode );
int util_fmove( FILE * stream , long offset , long shift);
FILE * util_fopen(const char * , const char *);
FILE * util_fopen(const char * , const char *);
FILE * util_fopen__(const char * filename , const char * mode);
void util_fclose( FILE * stream );
bool util_fopen_test(const char *, const char *);
@@ -238,14 +236,7 @@ typedef enum {left_pad = 0,
bool util_sscanf_int(const char * , int * );
const char * util_parse_int(const char * , int * , bool *);
const char * util_skip_sep(const char * , const char * , bool *);
int util_scanf_int_with_limits(const char * , int , int , int );
char * util_scanf_int_with_limits_return_char(const char * , int , int , int );
void util_printf_prompt(const char * , int , char , const char *);
int util_scanf_int(const char * , int);
char * util_scanf_int_return_char(const char * , int);
double util_scanf_double(const char * prompt , int prompt_len);
char * util_scanf_alloc_string(const char * );
bool util_sscanf_double(const char * , double * );
bool util_sscanf_double(const char * , double * );
//char * util_alloc_full_path(const char *, const char *);
char * util_alloc_filename(const char * , const char * , const char * );
char * util_realloc_filename(char * , const char * , const char * , const char * );
@@ -340,9 +331,6 @@ typedef enum {left_pad = 0,
double util_double_min(double , double );
void util_fskip_lines(FILE * , int);
bool util_same_file(const char * , const char * );
void util_read_path(const char * , int , bool , char * );
char * util_fscanf_alloc_filename(const char * , int , int);
void util_read_string(const char * , int , char * );
void util_fread (void *, size_t , size_t , FILE * , const char * );
void util_fwrite(const void *, size_t , size_t , FILE * , const char * );
time_t util_fread_time_t(FILE * stream);
@@ -382,17 +370,21 @@ typedef enum {left_pad = 0,
int util_fnmatch( const char * pattern , const char * string );
void util_time_utc( time_t * t , struct tm * ts );
char ** util_alloc_PATH_list(void);
char * util_alloc_PATH_executable(const char * executable );
char * util_isscanf_alloc_envvar( const char * string , int env_index );
void util_setenv( const char * variable , const char * value);
const char * util_interp_setenv( const char * variable , const char * value);
void util_unsetenv( const char * variable);
char * util_alloc_envvar( const char * value );
bool util_is_link(const char * ); // Will always return false on windows
int util_chdir(const char * path);
bool util_chdir_file( const char * filename );
#ifdef ERT_HAVE_UNISTD
#include <unistd.h>
bool util_access(const char * entry, mode_t mode);
#else
bool util_access(const char * entry, int mode);
#define F_OK 0
#define R_OK 4
#define W_OK 2
#define X_OK 1
#endif
#define UTIL_FWRITE_SCALAR(s,stream) { if (fwrite(&s , sizeof s , 1 , stream) != 1) util_abort("%s: write failed: %s\n",__func__ , strerror(errno)); }
#define UTIL_FREAD_SCALAR(s,stream) { \
@@ -495,9 +487,6 @@ const char * util_enum_iget( int index , int size , const util_enum_element_type
void util_abort__(const char * file , const char * function , int line , const char * fmt , ...);
void util_abort_signal(int );
void util_abort_append_version_info(const char * );
void util_abort_free_version_info(void);
void util_abort_set_executable( const char * argv0 );
@@ -521,9 +510,6 @@ void util_abort_set_executable( const char * argv0 );
#ifdef ERT_HAVE_SPAWN
pid_t util_spawn(const char *executable, int argc, const char **argv, const char *stdout_file, const char *stderr_file);
int util_spawn_blocking(const char *executable, int argc, const char **argv, const char *stdout_file, const char *stderr_file);
#ifdef ERT_HAVE_PING
bool util_ping( const char * hostname);
#endif
#endif

View File

@@ -30,12 +30,6 @@
#include <ert/util/util.h>
#include <ert/util/stringlist.h>
#ifdef HAVE_PTHREAD
#include <pthread.h>
typedef pthread_rwlock_t lock_type;
#else
typedef int lock_type;
#endif
#ifdef __cplusplus
extern "C" {
@@ -71,8 +65,6 @@ struct hash_struct {
double resize_fill;
hash_sll_type **table;
hashf_type *hashf;
lock_type rwlock;
};
@@ -83,54 +75,12 @@ typedef struct hash_sort_node {
} hash_sort_type;
/*****************************************************************/
/* locking */
/*****************************************************************/
#ifdef HAVE_PTHREAD
static void __hash_rdlock(hash_type * hash) {
int lock_error = pthread_rwlock_tryrdlock( &hash->rwlock );
if (lock_error != 0)
util_abort("%s: did not get hash->read_lock - fix locking in calling scope\n",__func__);
}
static void __hash_wrlock(hash_type * hash) {
int lock_error = pthread_rwlock_trywrlock( &hash->rwlock );
if (lock_error != 0)
util_abort("%s: did not get hash->write_lock - fix locking in calling scope\n",__func__);
}
static void __hash_unlock( hash_type * hash) {
pthread_rwlock_unlock( &hash->rwlock );
}
static void LOCK_DESTROY( lock_type * rwlock ) {
pthread_rwlock_destroy( rwlock );
}
static void LOCK_INIT( lock_type * rwlock ) {
pthread_rwlock_init( rwlock , NULL);
}
#else
static void __hash_rdlock(hash_type * hash) {}
static void __hash_wrlock(hash_type * hash) {}
static void __hash_unlock(hash_type * hash) {}
static void LOCK_DESTROY(lock_type * rwlock) {}
static void LOCK_INIT(lock_type * rwlock) {}
#endif
/*****************************************************************/
/* Low level access functions */
/*****************************************************************/
static void * __hash_get_node_unlocked(const hash_type *__hash , const char *key, bool abort_on_error) {
static void * __hash_get_node(const hash_type *__hash , const char *key, bool abort_on_error) {
hash_type * hash = (hash_type *) __hash; /* The net effect is no change - but .... ?? */
hash_node_type * node = NULL;
{
@@ -146,23 +96,6 @@ static void * __hash_get_node_unlocked(const hash_type *__hash , const char *key
}
/*
This function looks up a hash_node from the hash. This is the common
low-level function to get content from the hash. The function takes
read-lock which is held during execution.
Would strongly preferred that the hash_type * was const - but that is
difficult due to locking requirements.
*/
static void * __hash_get_node(const hash_type *hash_in , const char *key, bool abort_on_error) {
hash_node_type * node;
hash_type * hash = (hash_type *)hash_in;
__hash_rdlock( hash );
node = (hash_node_type*)__hash_get_node_unlocked(hash , key , abort_on_error);
__hash_unlock( hash );
return node;
}
static node_data_type * hash_get_node_data(const hash_type *hash , const char *key) {
@@ -215,46 +148,37 @@ void hash_resize(hash_type *hash, int new_size) {
/**
This is the low-level function for inserting a hash node. This
function takes a write-lock which is held during the execution of
the function.
This is the low-level function for inserting a hash node.
*/
static void __hash_insert_node(hash_type *hash , hash_node_type *node) {
__hash_wrlock( hash );
uint32_t table_index = hash_node_get_table_index(node);
{
uint32_t table_index = hash_node_get_table_index(node);
{
/*
If a node with the same key already exists in the table
it is removed.
*/
hash_node_type *existing_node = (hash_node_type*)__hash_get_node_unlocked(hash , hash_node_get_key(node) , false);
if (existing_node != NULL) {
hash_sll_del_node(hash->table[table_index] , existing_node);
hash->elements--;
}
/*
If a node with the same key already exists in the table
it is removed.
*/
hash_node_type *existing_node = (hash_node_type*)__hash_get_node(hash , hash_node_get_key(node) , false);
if (existing_node != NULL) {
hash_sll_del_node(hash->table[table_index] , existing_node);
hash->elements--;
}
hash_sll_add_node(hash->table[table_index] , node);
hash->elements++;
if ((1.0 * hash->elements / hash->size) > hash->resize_fill)
hash_resize(hash , hash->size * 2);
}
__hash_unlock( hash );
hash_sll_add_node(hash->table[table_index] , node);
hash->elements++;
if ((1.0 * hash->elements / hash->size) > hash->resize_fill)
hash_resize(hash , hash->size * 2);
}
/**
This function deletes a node from the hash_table. Observe that this
function does *NOT* do any locking - it is the repsonsibility of
the calling functions: hash_del() and hash_clear() to take the
necessary write lock.
This function deletes a node from the hash_table.
*/
static void hash_del_unlocked__(hash_type *hash , const char *key) {
static void hash_del__(hash_type *hash , const char *key) {
const uint32_t global_index = hash->hashf(key , strlen(key));
const uint32_t table_index = (global_index % hash->size);
hash_node_type *node = hash_sll_get(hash->table[table_index] , global_index , key);
@@ -297,40 +221,32 @@ static hash_node_type * hash_internal_iter_next(const hash_type *hash , const ha
This is the low level function which traverses a hash table and
allocates a char ** list of keys.
It takes a read-lock which is held during the execution of the
function. The locking guarantees that the list of keys is valid
when this function is exited, but the the hash table can be
subsequently updated.
If the hash table is empty NULL is returned.
*/
static char ** hash_alloc_keylist__(hash_type *hash , bool lock) {
static char ** hash_alloc_keylist__(const hash_type *hash) {
char **keylist;
if (lock) __hash_rdlock( hash );
{
if (hash->elements > 0) {
int i = 0;
hash_node_type *node = NULL;
keylist = (char**)calloc(hash->elements , sizeof *keylist);
{
uint32_t i = 0;
while (i < hash->size && hash_sll_empty(hash->table[i]))
i++;
if (i < hash->size)
node = hash_sll_get_head(hash->table[i]);
}
while (node != NULL) {
const char *key = hash_node_get_key(node);
keylist[i] = util_alloc_string_copy(key);
node = hash_internal_iter_next(hash , node);
if (hash->elements > 0) {
int i = 0;
hash_node_type *node = NULL;
keylist = (char**)calloc(hash->elements , sizeof *keylist);
{
uint32_t i = 0;
while (i < hash->size && hash_sll_empty(hash->table[i]))
i++;
}
} else keylist = NULL;
}
if (lock) __hash_unlock( hash );
if (i < hash->size)
node = hash_sll_get_head(hash->table[i]);
}
while (node != NULL) {
const char *key = hash_node_get_key(node);
keylist[i] = util_alloc_string_copy(key);
node = hash_internal_iter_next(hash , node);
i++;
}
} else
keylist = NULL;
return keylist;
}
@@ -420,9 +336,7 @@ double hash_get_double(const hash_type * hash , const char * key) {
/*****************************************************************/
void hash_del(hash_type *hash , const char *key) {
__hash_wrlock( hash );
hash_del_unlocked__(hash , key);
__hash_unlock( hash );
hash_del__(hash , key);
}
/**
@@ -431,28 +345,21 @@ void hash_del(hash_type *hash , const char *key) {
*/
void hash_safe_del(hash_type * hash , const char * key) {
__hash_wrlock( hash );
if (__hash_get_node_unlocked(hash , key , false))
hash_del_unlocked__(hash , key);
__hash_unlock( hash );
if (__hash_get_node(hash , key , false))
hash_del__(hash , key);
}
void hash_clear(hash_type *hash) {
__hash_wrlock( hash );
{
int old_size = hash_get_size(hash);
if (old_size > 0) {
char **keyList = hash_alloc_keylist__( hash , false);
int i;
for (i=0; i < old_size; i++) {
hash_del_unlocked__(hash , keyList[i]);
free(keyList[i]);
}
free(keyList);
int old_size = hash_get_size(hash);
if (old_size > 0) {
char **keyList = hash_alloc_keylist__( hash );
for (int i=0; i < old_size; i++) {
hash_del__(hash , keyList[i]);
free(keyList[i]);
}
free(keyList);
}
__hash_unlock( hash );
}
@@ -512,8 +419,6 @@ static hash_type * __hash_alloc(int size, double resize_fill , hashf_type *hashf
hash->table = hash_sll_alloc_table(hash->size);
hash->elements = 0;
hash->resize_fill = resize_fill;
LOCK_INIT( &hash->rwlock );
return hash;
}
@@ -522,11 +427,6 @@ hash_type * hash_alloc() {
return __hash_alloc(HASH_DEFAULT_SIZE , 0.50 , hash_index);
}
// Purely a helper in the process of removing the internal locking
// in the hash implementation.
hash_type * hash_alloc_unlocked() {
return __hash_alloc(HASH_DEFAULT_SIZE , 0.50 , hash_index);
}
UTIL_SAFE_CAST_FUNCTION( hash , HASH_TYPE_ID)
@@ -538,7 +438,6 @@ void hash_free(hash_type *hash) {
for (i=0; i < hash->size; i++)
hash_sll_free(hash->table[i]);
free(hash->table);
LOCK_DESTROY( &hash->rwlock );
free(hash);
}
@@ -548,13 +447,13 @@ void hash_free__(void * void_hash) {
}
char ** hash_alloc_keylist(hash_type *hash) {
return hash_alloc_keylist__(hash , true);
char ** hash_alloc_keylist(const hash_type *hash) {
return hash_alloc_keylist__(hash);
}
stringlist_type * hash_alloc_stringlist(hash_type * hash) {
stringlist_type * hash_alloc_stringlist(const hash_type * hash) {
stringlist_type * stringlist = stringlist_alloc_new();
char ** keylist = hash_alloc_keylist__(hash , true);
char ** keylist = hash_alloc_keylist__(hash);
int i;
for (i = 0; i < hash_get_size( hash ); i++)
stringlist_append_owned_ref( stringlist , keylist[i] );
@@ -684,7 +583,7 @@ static int hash_sortlist_cmp(const void *_p1 , const void *_p2) {
}
static char ** __hash_alloc_ordered_keylist(hash_type *hash , int ( hash_get_cmp_value) (const void * )) {
static char ** __hash_alloc_ordered_keylist(const hash_type *hash , int ( hash_get_cmp_value) (const void * )) {
int i;
char **sorted_keylist;
char **tmp_keylist = hash_alloc_keylist(hash);
@@ -705,7 +604,7 @@ static char ** __hash_alloc_ordered_keylist(hash_type *hash , int ( hash_get_cmp
}
char ** hash_alloc_sorted_keylist(hash_type *hash , int ( hash_get_cmp_value) (const void *)) {
char ** hash_alloc_sorted_keylist(const hash_type *hash , int ( hash_get_cmp_value) (const void *)) {
char ** key_list;
key_list = __hash_alloc_ordered_keylist(hash , hash_get_cmp_value);
@@ -722,7 +621,7 @@ static int key_cmp(const void *_s1 , const void *_s2) {
}
static char ** __hash_alloc_key_sorted_list(hash_type *hash, int (*cmp) (const void * , const void *)) {
static char ** __hash_alloc_key_sorted_list(const hash_type *hash, int (*cmp) (const void * , const void *)) {
char **keylist = hash_alloc_keylist(hash);
qsort(keylist , hash_get_size(hash) , sizeof *keylist , cmp);
@@ -731,7 +630,7 @@ static char ** __hash_alloc_key_sorted_list(hash_type *hash, int (*cmp) (const v
char ** hash_alloc_key_sorted_list(hash_type * hash, int (*cmp) (const void *, const void *))
char ** hash_alloc_key_sorted_list(const hash_type * hash, int (*cmp) (const void *, const void *))
{
char ** key_list;
@@ -742,7 +641,7 @@ char ** hash_alloc_key_sorted_list(hash_type * hash, int (*cmp) (const void *, c
bool hash_key_list_compare(hash_type * hash1, hash_type * hash2)
bool hash_key_list_compare(const hash_type * hash1, const hash_type * hash2)
{
bool has_equal_keylist;
int i,size1, size2;

View File

@@ -1,23 +1,24 @@
/*
Copyright (C) 2012 Statoil ASA, Norway.
The file 'path_stack.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
Copyright (C) 2012 Statoil ASA, Norway.
The file 'path_stack.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
@@ -47,22 +48,22 @@ struct path_stack_struct {
/**
This will create a new path_stack instance; it will push anything
on the current stack of paths.
on the current stack of paths.
*/
path_stack_type * path_stack_alloc() {
path_stack_type * path_stack = (path_stack_type*)util_malloc( sizeof * path_stack );
path_stack->stack = stringlist_alloc_new();
path_stack->storage = stringlist_alloc_new();
return path_stack;
path_stack->stack = stringlist_alloc_new();
path_stack->storage = stringlist_alloc_new();
return path_stack;
}
/*
/*
This will destroy the storage taken by the current path_stack
instance. This function will NOT pop any elements off the stack; so
if you have not manully clerad the stack with the right number of
path_stack_pop() calls, you will (probably) destroy the path stack
instance with an incorrect value of cwd.
instance with an incorrect value of cwd.
*/
void path_stack_free( path_stack_type * path_stack ) {
@@ -85,7 +86,7 @@ bool path_stack_push( path_stack_type * path_stack , const char * path ) {
if (path != NULL)
if (util_chdir( path ) != 0)
return false;
path_stack_push_cwd( path_stack );
return true;
}

View File

@@ -40,7 +40,7 @@ static UTIL_SAFE_CAST_FUNCTION( set , SET_TYPE_ID )
set_type * set_alloc(int size, const char ** keyList) {
set_type * set = (set_type*) malloc(sizeof * set);
UTIL_TYPE_ID_INIT( set , SET_TYPE_ID );
set->key_hash = hash_alloc_unlocked();
set->key_hash = hash_alloc();
{
int ikey;
for (ikey = 0; ikey < size; ikey++)

View File

@@ -17,6 +17,8 @@
*/
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <ert/util/util.h>
#include <ert/util/parser.h>

View File

@@ -21,6 +21,11 @@
#include <stdlib.h>
#include <ert/util/ert_api_config.h>
#ifdef ERT_HAVE_OPENDIR
#include <sys/types.h>
#include <dirent.h>
#endif
#ifdef ERT_HAVE_GLOB
#include <glob.h>
#else
@@ -30,8 +35,6 @@
#include <ert/util/util.h>
#include <ert/util/stringlist.h>
#include <ert/util/vector.h>
#include <ert/util/buffer.h>
#define STRINGLIST_TYPE_ID 671855
@@ -621,13 +624,6 @@ stringlist_type * stringlist_alloc_from_split( const char * input_string , const
/*****************************************************************/
void stringlist_buffer_fwrite( const stringlist_type * s , buffer_type * buffer ) {
int i;
int size = stringlist_get_size( s );
buffer_fwrite_int( buffer , size );
for (i=0; i < size; i++)
buffer_fwrite_string(buffer , stringlist_iget(s , i) );
}
void stringlist_fwrite(const stringlist_type * s, FILE * stream) {
@@ -652,13 +648,6 @@ void stringlist_fread(stringlist_type * s, FILE * stream) {
}
void stringlist_buffer_fread( stringlist_type * s , buffer_type * buffer ) {
int size = buffer_fread_int( buffer );
int i;
stringlist_clear(s);
for (i=0; i < size; i++)
stringlist_append_owned_ref( s , buffer_fread_alloc_string( buffer ));
}
@@ -772,6 +761,68 @@ int stringlist_select_matching_files(stringlist_type * names , const char * path
#endif
}
int stringlist_select_files(stringlist_type * names, const char * path, file_pred_ftype * predicate, const void * pred_arg) {
stringlist_clear(names);
char * path_arg = path ? util_alloc_string_copy(path) : util_alloc_cwd();
#ifdef ERT_HAVE_OPENDIR
DIR * dir = opendir(path_arg);
if (!dir) {
free(path_arg);
return 0;
}
while (true) {
struct dirent * entry = readdir(dir);
if (!entry)
break;
if (util_string_equal(entry->d_name, "."))
continue;
if (util_string_equal(entry->d_name, ".."))
continue;
if (predicate && !predicate(entry->d_name, pred_arg))
continue;
stringlist_append_owned_ref(names, util_alloc_filename(path, entry->d_name, NULL));
}
closedir(dir);
#else
WIN32_FIND_DATA file_data;
HANDLE file_handle;
char * pattern = util_alloc_filename( path_arg , "*", NULL );
file_handle = FindFirstFile( pattern , &file_data );
if (file_handle != INVALID_HANDLE_VALUE) {
do {
if (util_string_equal(file_data.cFileName, "."))
continue;
if (util_string_equal(file_data.cFileName, ".."))
continue;
if (predicate && !predicate(file_data.cFileName, pred_arg))
continue;
stringlist_append_owned_ref(names, util_alloc_filename(path, file_data.cFileName, NULL));
} while (FindNextFile( file_handle , &file_data) != 0);
FindClose( file_handle );
}
free( pattern );
#endif
free(path_arg);
return stringlist_get_size(names);
}
int stringlist_append_matching_elements(stringlist_type * target , const stringlist_type * src , const char * pattern) {
int ielm;
int match_count = 0;
@@ -790,12 +841,17 @@ int stringlist_append_matching_elements(stringlist_type * target , const stringl
return stringlist_append_matching_elements( target , src , pattern );
}
static int void_strcmp(const void* s1, const void *s2) {
return strcmp(s1,s2);
}
bool stringlist_unique(const stringlist_type * stringlist )
{
bool unique = true;
stringlist_type * cpy = stringlist_alloc_shallow_copy(stringlist);
stringlist_sort(cpy, strcmp);
stringlist_sort(cpy, void_strcmp);
for (int i = 0; i < stringlist_get_size(cpy) - 1; i++) {
const char* s1 = stringlist_iget(cpy, i);
const char* s2 = stringlist_iget(cpy, i+1);

View File

@@ -32,7 +32,6 @@
#include <ert/util/util.h>
#include <ert/util/test_work_area.h>
#include <ert/util/type_macros.h>
#include <ert/util/rng.h>
#include <ert/util/ert_api_config.h>
#ifdef ERT_HAVE_OPENDIR
@@ -173,18 +172,20 @@ UTIL_IS_INSTANCE_FUNCTION( test_work_area , TEST_WORK_AREA_TYPE_ID)
static test_work_area_type * test_work_area_alloc_with_prefix(const char * prefix , const char * test_name, bool change_dir) {
if (test_name) {
rng_type * rng = rng_alloc(MZRAN , INIT_DEV_URANDOM );
unsigned int random_int;
util_fread_dev_urandom( sizeof random_int, (char *) &random_int);
random_int = random_int % 100000000;
#ifdef ERT_HAVE_GETUID
uid_t uid = getuid();
struct passwd * pw = getpwuid( uid );
char * user_name = util_alloc_string_copy( pw->pw_name );
#else
char * user_name = util_alloc_sprintf("ert-test-%08d" , rng_get_int(rng , 100000000));
char * user_name = util_alloc_sprintf("ert-test-%08u" , random_int);
#endif
char * test_path = util_alloc_sprintf( TEST_PATH_FMT , user_name , test_name , rng_get_int( rng , 100000000 ));
char * test_path = util_alloc_sprintf( TEST_PATH_FMT , user_name , test_name , random_int);
test_work_area_type * work_area = test_work_area_alloc__( prefix , test_path, change_dir);
free( test_path );
rng_free( rng );
free( user_name );
return work_area;
} else

View File

@@ -1,19 +1,19 @@
/*
Copyright (C) 2012 Statoil ASA, Norway.
The file 'ert_util_PATH_test.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
Copyright (C) 2012 Statoil ASA, Norway.
The file 'ert_util_PATH_test.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <stdlib.h>
@@ -29,7 +29,7 @@ void test_dirname() {
const char * src_file1 = "/some/very/long/path/file.txt";
const char * src_file2 = "relative/path/file.txt";
const char * src_file3 = "file.txt";
char * path1 = util_split_alloc_dirname( src_file1 );
char * path2 = util_split_alloc_dirname( src_file2 );
char * path3 = util_split_alloc_dirname( src_file3 );
@@ -48,7 +48,7 @@ void test_filename() {
const char * src_file1 = "/some/very/long/path/file1.txt";
const char * src_file2 = "relative/path/file2";
const char * src_file3 = "/tmp";
char * file1 = util_split_alloc_filename( src_file1 );
char * file2 = util_split_alloc_filename( src_file2 );
char * file3 = util_split_alloc_filename( src_file3 );
@@ -61,13 +61,24 @@ void test_filename() {
}
void test_alloc_filename_empty_strings() {
const char * path = "";
const char * filename = "file";
const char * extension = "";
char * alloc_filename = util_alloc_filename( path, filename , extension);
test_assert_string_equal( alloc_filename , filename );
free( alloc_filename );
}
int main(int argc , char ** argv) {
test_dirname();
test_filename();
test_alloc_filename_empty_strings();
exit(0);
}

View File

@@ -0,0 +1,73 @@
/*
Copyright (C) 2017 Statoil ASA, Norway.
The file 'ert_util_normal_path.c' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <stdlib.h>
#include <stdbool.h>
#include <ert/util/test_util.h>
#include <ert/util/test_work_area.h>
#include <ert/util/util.h>
void test_path(const char * input_path, const char * expected_path) {
char * normal_path = util_alloc_normal_path( input_path );
test_assert_string_equal( normal_path , expected_path );
free( normal_path );
}
void test_relative() {
test_work_area_type * work_area = test_work_area_alloc("Work");
util_make_path("level0/level1/level2");
test_path( "level0/level1/../", "level0");
test_path( "level0", "level0");
test_path( "level0/././level1/../", "level0");
test_path( "level0/level1/../level1/level2/../", "level0/level1");
test_path( "level0/level1/../level1/level2/..", "level0/level1");
test_path( "level0/level1/../level1/level2/../file.txt", "level0/level1/file.txt");
test_path( "level0/level1/../level1a" , "level0/level1a");
test_path( "a/b/c/../c/../.." , "a");
test_path( "a/b/c/d/e/f" , "a/b/c/d/e/f");
util_chdir("level0/level1");
test_path("../../level0/level1/level2/../file.txt" , "file.txt");
test_path("../../level0/level1/level2/../" , "");
test_work_area_free( work_area );
}
void test_beyond_root() {
test_work_area_type * work_area = test_work_area_alloc("Work");
char * cwd = util_alloc_cwd( );
char * backref_cwd1 = util_alloc_sprintf("../../../../../../../../../../../%s" , cwd );
char * backref_cwd2 = util_alloc_sprintf("/../../../../../../../../../../../%s" , cwd );
test_path( backref_cwd1 , "" );
test_path( backref_cwd2 , cwd ); // The input is a semi-absolute path, and we compare with the absolute path cwd().
free( backref_cwd1 );
free( backref_cwd2 );
free( cwd );
test_work_area_free( work_area );
}
int main( int argc , char ** argv) {
test_relative( );
test_beyond_root( );
exit(0);
}

View File

@@ -64,7 +64,7 @@ int main(int argc , char ** argv) {
const char * root7 = "/tmp/root/path";
const char * path7 = "/tmp/root/path";
const char * true7 = NULL;
const char * true7 = "";
const char * root8 = "/tmp";
const char * path8 = "root/path";

View File

@@ -24,9 +24,7 @@
#include <ert/util/stringlist.h>
#include <ert/util/test_util.h>
#include <ert/util/util.h>
#include <ert/util/rng.h>
#include <ert/util/test_work_area.h>
#include <ert/util/thread_pool.h>
static const char * stdout_msg = "stdout_xxx";
@@ -150,7 +148,6 @@ void test_spawn_redirect() {
}
void test_spawn_redirect_threaded() {
rng_type * rng = rng_alloc( MZRAN , INIT_DEFAULT );
const int num = 128;
// Generate the scripts on disk first
@@ -158,7 +155,7 @@ void test_spawn_redirect_threaded() {
int * path_codes = (int *)util_calloc(num, sizeof *path_codes);
stringlist_type * script_fullpaths = stringlist_alloc_new();
for (int i=0; i < num; i++) {
path_codes[i] = rng_get_int( rng , 1000000);
path_codes[i] = rand() % 1000000;
char * path = util_alloc_sprintf("%06d" , path_codes[i]);
util_make_path( path );
@@ -180,22 +177,9 @@ void test_spawn_redirect_threaded() {
test_assert_true(check_script(script));
}
// Run the scripts in parallel
stringlist_type * script_paths = stringlist_alloc_new(); // free the paths after threads have completed
thread_pool_type * tp = thread_pool_alloc( 8 , true );
for(int i = 0; i < num; i++) {
char * path = util_alloc_sprintf("%06d" , path_codes[i]);
stringlist_append_owned_ref(script_paths, path);
thread_pool_add_job( tp , test_spawn_redirect__ , path );
}
thread_pool_join( tp );
thread_pool_free( tp );
stringlist_free(script_paths);
stringlist_free(script_fullpaths);
util_free(path_codes);
test_work_area_free( test_area );
rng_free( rng );
}

View File

@@ -17,9 +17,12 @@
*/
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ert/util/util.h>
#include <ert/util/test_util.h>
#include <ert/util/stringlist.h>
#include <ert/util/test_work_area.h>
void test_char() {
const char * S1 = "S1";
@@ -338,6 +341,54 @@ void test_matching() {
}
bool FILE_predicate(const char * name, const void * arg) {
return util_string_equal("FILE.txt", name);
}
bool not_FILE_predicate(const char * name, const void * arg) {
return !util_string_equal("FILE.txt", name);
}
void test_predicate_matching() {
test_work_area_type * work_area = test_work_area_alloc("predicate_test");
stringlist_type * s = stringlist_alloc_new();
stringlist_append_ref(s, "s");
stringlist_select_files(s, "does/not/exist", NULL, NULL);
test_assert_int_equal(stringlist_get_size(s), 0);
{
FILE * f = util_fopen("FILE.txt", "w");
fclose(f);
}
stringlist_select_files(s , test_work_area_get_cwd(work_area), NULL, NULL);
test_assert_int_equal(1, stringlist_get_size(s));
{
char * exp = util_alloc_abs_path("FILE.txt");
test_assert_string_equal( exp, stringlist_iget(s, 0));
free(exp);
}
stringlist_select_files(s , NULL, NULL, NULL);
test_assert_int_equal(1, stringlist_get_size(s));
test_assert_string_equal( "FILE.txt", stringlist_iget(s, 0));
stringlist_select_files(s , test_work_area_get_cwd(work_area), FILE_predicate, NULL);
test_assert_int_equal(1, stringlist_get_size(s));
{
char * exp = util_alloc_abs_path("FILE.txt");
test_assert_string_equal( exp, stringlist_iget(s, 0));
free(exp);
}
stringlist_select_files(s , test_work_area_get_cwd(work_area), not_FILE_predicate, NULL);
test_assert_int_equal(0, stringlist_get_size(s));
stringlist_free(s);
test_work_area_free(work_area);
}
void test_unique() {
stringlist_type * s = stringlist_alloc_new();
@@ -365,5 +416,6 @@ int main( int argc , char ** argv) {
test_split();
test_matching();
test_unique();
test_predicate_matching();
exit(0);
}

View File

@@ -343,6 +343,38 @@ void test_empty() {
int_vector_free( vec );
}
void test_equal_index() {
int_vector_type * v1 = int_vector_alloc(0,0);
int_vector_type * v2 = int_vector_alloc(0,0);
int_vector_type * v3 = int_vector_alloc(0,0);
for (int i=0; i < 5; i++) {
int_vector_iset(v1,i,i);
int_vector_iset(v2,i,i);
int_vector_iset(v3,i,i+1);
}
test_assert_int_equal( int_vector_first_equal(v1,v2,10), -2);
test_assert_int_equal( int_vector_first_not_equal(v1,v2,10), -2);
test_assert_int_equal( int_vector_first_equal(v1,v2,0), 0);
test_assert_int_equal( int_vector_first_not_equal(v1,v2,0), -1);
int_vector_iset(v1,0,77);
test_assert_int_equal( int_vector_first_equal(v1,v2,0), 1);
test_assert_int_equal( int_vector_first_not_equal(v1,v2,0),0);
test_assert_int_equal( int_vector_first_equal(v1,v3,0), -1);
test_assert_int_equal( int_vector_first_not_equal(v1,v1,0), -1);
int_vector_free(v1);
int_vector_free(v2);
int_vector_free(v3);
}
int main(int argc , char ** argv) {
int_vector_type * int_vector = int_vector_alloc( 0 , 99);
@@ -433,5 +465,6 @@ int main(int argc , char ** argv) {
test_resize();
test_empty();
test_insert_double();
test_equal_index();
exit(0);
}

View File

@@ -183,7 +183,7 @@ void util_endian_flip_vector(void *data, int element_size , int elements) {
variables will be by swapping two elements in one operation;
this is provided by the util_endian_convert32_64() function. In the case
of binary ECLIPSE files this case is quite common, and
therefor worth supporting as a special case.
therefore worth supporting as a special case.
*/
uint64_t *tmp64 = (uint64_t *) data;
@@ -680,56 +680,6 @@ char * util_fscanf_realloc_line(FILE *stream , bool *at_eof , char *line) {
/**
Reads characters from stdin until EOL/EOF is detected. A '\0' is
appended to the resulting string before it is returned. If the
function reads an immediate EOF/EOL, i.e. the user enters an empty
input string, NULL (and not "") is returned.
Observe that is this function does *not* cooperate very nicely with
fscanf() based input, because fscanf will leave a EOL character in
the input buffer, which will lead to immediate return from this
function. Hence if this function is called after a fscanf() based
function it is essential to preceede this function with one call to
getchar() to clear the EOL character.
*/
char * util_alloc_stdin_line(void) {
int input_size = 256;
char * input = (char*)util_calloc(input_size , sizeof * input );
int index = 0;
bool end = false;
int c;
do {
c = getchar();
if ((!EOL_CHAR(c)) && (c != EOF)) {
input[index] = c;
index++;
if (index == (input_size - 1)) { /* Reserve space for terminating \0 */
input_size *= 2;
input = (char*)util_realloc(input , input_size );
}
} else end = true;
} while (!end);
if (index == 0) {
free(input);
input = NULL;
} else {
input[index] = '\0';
input = (char*)util_realloc(input , strlen(input) + 1 );
}
return input;
}
char * util_realloc_stdin_line(char * p) {
util_safe_free(p);
return util_alloc_stdin_line();
}
/**
WIndows does not have the usleep() function, on the other hand
@@ -764,23 +714,6 @@ void util_yield() {
#endif
}
/**
This function will allocate and read a line from stdin. If there is
no input waiting on stdin (this typically only applies if stdin is
redirected from a file/PIPE), the function will sleep for 'usec'
microseconds and try again.
*/
char * util_blocking_alloc_stdin_line(unsigned long usec) {
char * line;
do {
line = util_alloc_stdin_line();
if (line == NULL)
util_usleep(usec);
} while (line == NULL);
return line;
}
static char * util_getcwd(char * buffer , int size) {
#ifdef HAVE_POSIX_GETCWD
return getcwd( buffer , size );
@@ -875,78 +808,67 @@ char * util_alloc_realpath__(const char * input_path) {
char * real_path = (char*)util_malloc( strlen(abs_path) + 2 );
real_path[0] = '\0';
{
bool * mask;
char ** path_list;
char ** path_stack;
int path_len;
util_path_split( abs_path , &path_len , &path_list );
mask = (bool*)util_malloc( path_len * sizeof * mask );
{
int i;
for (i=0; i < path_len; i++)
mask[i] = true;
}
path_stack = util_malloc( path_len * sizeof * path_stack );
for (int i=0; i < path_len; i++)
path_stack[i] = NULL;
{
int path_index = 1; // Path can not start with ..
int prev_index = 0;
while (true) {
if (path_index == path_len)
break;
int stack_size = 0;
if (strcmp(path_list[path_index] , BACKREF ) == 0) {
mask[path_index] = false;
mask[prev_index] = false;
prev_index--;
path_index++;
} else if (strcmp( path_list[path_index] , CURRENT) == 0) {
mask[path_index] = false;
path_index++;
} else {
path_index++;
prev_index++;
while (!mask[prev_index])
prev_index++;
for (int path_index=0; path_index < path_len; path_index++) {
const char * path_elm = path_list[path_index];
if (strcmp( path_elm , CURRENT) == 0)
continue;
/* Backref - pop from stack. */
if (strcmp(path_elm , BACKREF ) == 0) {
if (stack_size > 0) {
memmove(path_stack, &path_stack[1] , (stack_size - 1) * sizeof * path_stack);
stack_size--;
}
continue;
}
/* Normal path element - push onto stack. */
memmove(&path_stack[1], path_stack, stack_size * sizeof * path_stack);
path_stack[0] = path_elm;
stack_size++;
}
/* Build up the new string. */
{
int i;
bool first = true;
for (i=0; i < path_len; i++) {
if (mask[i]) {
const char * path_elm = path_list[i];
if (first) {
if (stack_size > 0) {
for (int pos = stack_size - 1; pos >= 0; pos--) {
const char * path_elm = path_stack[pos];
if (pos == (stack_size- 1)) {
#ifdef ERT_WINDOWS
// Windows:
// 1) If the path starts with X: - just do nothing
// 2) Else add \\ - for a UNC path.
if (path_elm[1] != ':') {
strcat(real_path, UTIL_PATH_SEP_STRING);
strcat(real_path, UTIL_PATH_SEP_STRING);
}
#else
// Posix: just start with a leading '/'
// Windows:
// 1) If the path starts with X: - just do nothing
// 2) Else add \\ - for a UNC path.
if (path_elm[1] != ':') {
strcat(real_path, UTIL_PATH_SEP_STRING);
#endif
strcat( real_path , path_elm);
} else {
strcat(real_path, UTIL_PATH_SEP_STRING);
strcat( real_path , path_elm);
}
first = false;
#else
// Posix: just start with a leading '/'
strcat(real_path, UTIL_PATH_SEP_STRING);
#endif
strcat( real_path , path_elm);
} else {
strcat(real_path, UTIL_PATH_SEP_STRING);
strcat(real_path , path_elm);
}
}
}
}
free(mask);
free( path_stack );
util_free_stringlist( path_list , path_len );
}
@@ -1085,10 +1007,7 @@ char * util_alloc_rel_path( const char * __root_path , const char * path) {
util_free_stringlist( path_list , path_length );
free( root_path );
if (strlen(rel_path) == 0) {
free(rel_path);
rel_path = NULL;
} return rel_path;
return rel_path;
} else {
/*
One or both the input arguments do not correspond to an
@@ -1099,72 +1018,19 @@ char * util_alloc_rel_path( const char * __root_path , const char * path) {
}
}
/**
This function will allocate a string copy of the env_index'th
occurence of an embedded environment variable from the input
string.
An environment variable is defined as follows:
1. It starts with '$'.
2. It ends with a characeter NOT in the set [a-Z,0-9,_].
The function will return environment variable number 'env_index'. If
no such environment variable can be found in the string the
function will return NULL.
Observe that the returned string will start with '$'. This is to
simplify subsequent calls to util_string_replace_XXX() functions,
however &ret_value[1] must be used in the subsequent getenv() call:
{
char * env_var = util_isscanf_alloc_envvar( s , 0 );
if (env_var != NULL) {
const char * env_value = getenv( &env_var[1] ); // Skip the leading '$'.
if (env_value != NULL)
util_string_replace_inplace( s , env_value );
else
fprintf(stderr,"** Warning: environment variable: \'%s\' is not defined \n", env_var);
free( env_var );
}
}
/*
This function will return a new string where all "../" and "./"
occurences have been normalized away. The function is based on pure
string scanning, and will not consider the filesystem at
all.
*/
char * util_isscanf_alloc_envvar( const char * string , int env_index ) {
int env_count = 0;
const char * offset = string;
const char * env_ptr;
do {
env_ptr = strchr( offset , '$' );
offset = &env_ptr[1];
env_count++;
} while ((env_count <= env_index) && (env_ptr != NULL));
char * util_alloc_normal_path( const char * input_path ) {
if (util_is_abs_path(input_path))
return util_alloc_realpath__( input_path );
if (env_ptr != NULL) {
/*
We found an environment variable we are interested in. Find the
end of this variable and return a copy.
*/
int length = 1;
bool cont = true;
do {
if ( !( isalnum(env_ptr[length]) || env_ptr[length] == '_' ))
cont = false;
else
length++;
if (length == strlen( env_ptr ))
cont = false;
} while (cont);
return util_alloc_substring_copy( env_ptr , 0 , length );
} else
return NULL; /* Could not find any env variable occurences. */
char * realpath = util_alloc_realpath__(input_path);
return util_alloc_rel_path( NULL , realpath );
}
@@ -1173,6 +1039,8 @@ char * util_isscanf_alloc_envvar( const char * string , int env_index ) {
void util_fskip_lines(FILE * stream , int lines) {
bool cont = true;
int line_nr = 0;
@@ -1994,8 +1862,10 @@ bool util_sscanf_bool(const char * buffer , bool * _value) {
bool util_fscanf_bool(FILE * stream , bool * value) {
char buffer[256];
fscanf(stream , "%s" , buffer);
return util_sscanf_bool( buffer , value );
if (fscanf(stream , "%s" , buffer) == 1)
return util_sscanf_bool( buffer , value );
return false;
}
@@ -2026,100 +1896,6 @@ bool util_fscanf_int(FILE * stream , int * value) {
}
/**
Prompt .........====>
<-------1------><-2->
The section marked with 1 above is the prompt length, i.e. the
input prompt is padded wth one blank, and then padded with
'fill_char' (in the case above that is '.') characters up to a
total length of prompt_len. Then the the termination string ("===>"
above) is added. Observe the following:
* A space is _always_ added after the prompt, before the fill char
comes, even if the prompt is too long in the first place.
* No space is added at the end of the termination string. If
you want a space, that should be included in the termination
string.
*/
void util_printf_prompt(const char * prompt , int prompt_len, char fill_char , const char * termination) {
int current_len = strlen(prompt) + 1;
printf("%s ",prompt); /* Observe that one ' ' is forced in here. */
while (current_len < prompt_len) {
fputc(fill_char , stdout);
current_len++;
}
printf("%s" , termination);
}
/**
This functions presents the user with a prompt, and reads an
integer - the integer value is returned. The functions returns
NULL on empty input.
*/
int util_scanf_int(const char * prompt , int prompt_len) {
char input[256];
int int_value;
bool OK;
do {
util_printf_prompt(prompt , prompt_len, '=', "=> ");
scanf("%s" , input);
OK = util_sscanf_int(input , &int_value);
} while (!OK);
getchar(); /* eating a \r left in the stdin input buffer. */
return int_value;
}
/**
This functions presents the user with a prompt, and reads an
integer - the integer value is returned. The functions will loop
indefinitely until a valid integer is entered.
*/
char * util_scanf_int_return_char(const char * prompt , int prompt_len) {
char input[256];
int int_value;
bool OK = false;
while(!OK){
util_printf_prompt(prompt , prompt_len, '=', "=> ");
fgets(input, prompt_len, stdin);
{
char *newline = strchr(input,'\n');
if(newline)
*newline = 0;
}
if(strlen(input) !=0){
OK = util_sscanf_int(input , &int_value);
}
else {
OK = true;
}
}
return util_alloc_string_copy(input);
}
double util_scanf_double(const char * prompt , int prompt_len) {
char input[256];
double double_value;
bool OK;
do {
util_printf_prompt(prompt , prompt_len, '=', "=> ");
scanf("%s" , input);
OK = util_sscanf_double(input , &double_value);
} while (!OK);
getchar(); /* eating a \r left in the stdin input buffer. */
return double_value;
}
@@ -2127,47 +1903,6 @@ double util_scanf_double(const char * prompt , int prompt_len) {
/**
The limits are inclusive.
*/
int util_scanf_int_with_limits(const char * prompt , int prompt_len , int min_value , int max_value) {
int value;
char * new_prompt = util_alloc_sprintf("%s [%d:%d]" , prompt , min_value , max_value);
do {
value = util_scanf_int(new_prompt , prompt_len);
} while (value < min_value || value > max_value);
free(new_prompt);
return value;
}
/**
The limits are inclusive, yet the function returns the input char and stops on empty string.
*/
char * util_scanf_int_with_limits_return_char(const char * prompt , int prompt_len , int min_value , int max_value) {
int value = min_value - 1;
char * value_char = NULL;
char * new_prompt = util_alloc_sprintf("%s [%d:%d]" , prompt , min_value , max_value);
while( value < min_value || value > max_value ){
value_char = util_scanf_int_return_char(new_prompt , prompt_len);
if (strlen(value_char) == 0)
value = min_value;
else
util_sscanf_int(value_char , &value);
}
free(new_prompt);
return value_char;
}
char * util_scanf_alloc_string(const char * prompt) {
char input[256];
printf("%s" , prompt);
scanf("%256s" , input);
return util_alloc_string_copy(input);
}
/**
This function counts the number of lines from the current position
@@ -2505,9 +2240,27 @@ int util_fmove( FILE * stream , long offset , long shift) {
}
/*
Windows *might* have both the symbols _access() and access(), but we prefer
the _access() symbol as that seems to be preferred by Windows. We therefor do
the #HAVE_WINDOWS__ACCESS check first.
*/
#ifdef HAVE_WINDOWS__ACCESS
bool util_access(const char * entry, int mode) {
return (_access(entry, mode) == 0);
}
#else
#ifdef HAVE_POSIX_ACCESS
bool util_access(const char * entry, mode_t mode) {
return (access(entry, mode) == 0);
}
#endif
#endif
/**
@@ -2527,20 +2280,8 @@ bool util_file_exists(const char *filename) {
*/
bool util_entry_exists( const char * entry ) {
stat_type stat_buffer;
int stat_return = util_stat(entry, &stat_buffer);
if (stat_return == 0)
return true;
else {
if (errno == ENOENT)
return false;
else {
util_abort("%s: error checking for entry:%s %d/%s \n",__func__ , entry , errno , strerror(errno));
return false;
}
}
return util_access(entry, F_OK);
}
/*****************************************************************/
@@ -2896,11 +2637,7 @@ bool util_ftruncate(FILE * stream , long size) {
*/
bool util_same_file(const char * file1 , const char * file2) {
#ifdef _WINDOWS
if (file1 == NULL || file2 == NULL) return false;
return stricmp(file1, file2) == 0;
#else
#ifdef ERT_HAVE_UNISTD
stat_type buffer1 , buffer2;
int stat1,stat2;
@@ -2914,6 +2651,17 @@ bool util_same_file(const char * file1 , const char * file2) {
return false;
} else
return false; // Files which do not exist are no equal!
#else
if (util_file_exists(file1) && util_file_exists(file2)) {
char * abs_path1 = util_alloc_abs_path(file1);
char * abs_path2 = util_alloc_abs_path(file2);
bool same_file = util_string_equal(abs_path1, abs_path2);
free(abs_path1);
free(abs_path2);
return same_file;
}
else
return false;
#endif
}
@@ -4718,67 +4466,6 @@ void util_free(void * ptr) {
static void util_display_prompt(const char * prompt , int prompt_len2) {
int i;
printf("%s" , prompt);
for (i=0; i < util_int_max(strlen(prompt) , prompt_len2) - strlen(prompt); i++)
fputc(' ' , stdout);
printf(": ");
}
void util_read_string(const char * prompt , int prompt_len , char * s) {
util_display_prompt(prompt , prompt_len);
fscanf(stdin , "%s" , s);
}
void util_read_path(const char * prompt , int prompt_len , bool must_exist , char * path) {
bool ok = false;
while (!ok) {
util_read_string(prompt , prompt_len , path);
if (must_exist)
ok = util_is_directory(path);
else
ok = true;
if (!ok)
fprintf(stderr,"Path: %s does not exist - try again.\n",path);
}
}
/*
exist_status == 0: Just read a string; do not check if it exist or not.
exist_status == 1: Must be existing file.
exist_status == 2: Must NOT exist as entry.
*/
char * util_fscanf_alloc_filename(const char * prompt , int prompt_len , int exist_status) {
char * filename = NULL;
while (filename == NULL) {
util_printf_prompt(prompt , prompt_len , '=' , "=> ");
filename = util_alloc_stdin_line();
if (filename != NULL) {
if (exist_status != 0) {
if (exist_status == 1) {
if (!util_file_exists(filename)) {
fprintf(stderr,"Sorry: %s does not exist. \n",filename);
free( filename );
filename = NULL;
}
} else if (exist_status == 2) {
if (util_entry_exists( filename )) {
fprintf(stderr,"Sorry: entry %s already exists. \n",filename);
free( filename );
filename = NULL;
}
}
}
}
}
return filename;
}
/*****************************************************************/
@@ -5088,39 +4775,6 @@ const char * util_enum_iget( int index , int size , const util_enum_element_type
}
static char * __abort_program_message = NULL; /* Can use util_abort_append_version_info() to fill this with
version info+++ wich will be printed when util_abort() is called. */
static char * __current_executable = NULL;
void util_abort_append_version_info(const char * msg) {
__abort_program_message = util_strcat_realloc( __abort_program_message , msg );
}
void util_abort_free_version_info() {
util_safe_free( __abort_program_message );
util_safe_free( __current_executable );
__current_executable = NULL;
__abort_program_message = NULL;
}
void util_abort_set_executable( const char * argv0 ) {
if (util_is_abs_path(argv0))
__current_executable = util_realloc_string_copy( __current_executable , argv0 );
else {
char * executable;
if (util_is_executable( argv0 ))
executable = util_alloc_realpath(argv0);
else
executable = util_alloc_PATH_executable( argv0 );
util_abort_set_executable( executable );
free( executable );
}
}
@@ -5352,24 +5006,23 @@ char * util_alloc_filename(const char * path , const char * basename , const cha
char * file;
int length = strlen(basename) + 1;
if (path != NULL)
if (path && strlen(path))
length += strlen(path) + 1;
if (extension != NULL)
if (extension && strlen(extension))
length += strlen(extension) + 1;
file = (char*)util_calloc(length , sizeof * file );
if (path == NULL) {
if (extension == NULL)
memcpy(file , basename , strlen(basename) + 1);
else
sprintf(file , "%s.%s" , basename , extension);
} else {
if (extension == NULL)
sprintf(file , "%s%c%s" , path , UTIL_PATH_SEP_CHAR , basename);
else
sprintf(file , "%s%c%s.%s" , path , UTIL_PATH_SEP_CHAR , basename , extension);
file = (char*) util_calloc(length , sizeof * file );
file[0] = '\0';
if (path && strlen(path)) {
strcat(file, path);
strcat(file, UTIL_PATH_SEP_STRING );
}
strcat(file, basename);
if (extension && strlen(extension)) {
strcat(file, ".");
strcat(file, extension);
}
return file;

View File

@@ -119,7 +119,7 @@ void util_endian_flip_vector(void *data, int element_size , int elements) {
variables will be by swapping two elements in one operation;
this is provided by the util_endian_convert32_64() function. In the case
of binary ECLIPSE files this case is quite common, and
therefor worth supporting as a special case.
therefore worth supporting as a special case.
*/
uint64_t *tmp64 = (uint64_t *) data;

View File

@@ -20,7 +20,7 @@
If the lock is aquired the function will return true, otherwise it
will return false. The lock is only active as long as the lockfile
is open, we therefor have to keep track of the relevant file
is open, we therefore have to keep track of the relevant file
descriptor; it is passed back to the calling scope through a
reference. Observe that if the locking fails we close the file
immediately, and return -1 in the file descriptor argument.

View File

@@ -19,7 +19,18 @@ extern char **environ;
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
static void __init_redirection(posix_spawn_file_actions_t * file_actions, const char *stdout_file, const char *stderr_file) {
static void spawn_init_attributes__(posix_spawnattr_t * attributes) {
posix_spawnattr_init(attributes);
short flags;
posix_spawnattr_getflags(attributes, &flags);
flags |= POSIX_SPAWN_SETPGROUP;
posix_spawnattr_setflags(attributes, flags);
posix_spawnattr_setpgroup( attributes, 0);
}
static void spawn_init_redirection__(posix_spawn_file_actions_t * file_actions, const char *stdout_file, const char *stderr_file) {
int status;
status = posix_spawn_file_actions_init(file_actions);
@@ -62,27 +73,28 @@ static pthread_mutex_t spawn_mutex = PTHREAD_MUTEX_INITIALIZER;
*/
pid_t util_spawn(const char *executable, int argc, const char **argv, const char *stdout_file, const char *stderr_file) {
pid_t pid;
char **__argv = (char**)util_malloc((argc + 2) * sizeof *__argv);
char **argv__ = (char**)util_malloc((argc + 2) * sizeof *argv__);
{
int iarg;
__argv[0] = (char *) executable;
argv__[0] = (char *) executable;
for (iarg = 0; iarg < argc; iarg++)
__argv[iarg + 1] = (char *) argv[iarg];
__argv[argc + 1] = NULL;
argv__[iarg + 1] = (char *) argv[iarg];
argv__[argc + 1] = NULL;
}
{
posix_spawnattr_t spawn_attr;
posix_spawn_file_actions_t file_actions;
__init_redirection(&file_actions , stdout_file , stderr_file);
spawn_init_redirection__(&file_actions , stdout_file , stderr_file);
spawn_init_attributes__(&spawn_attr);
pthread_mutex_lock( &spawn_mutex );
{
int spawn_status;
if (util_is_executable(executable)) { // the executable is in current directory or an absolute path
spawn_status = posix_spawn(&pid, executable, &file_actions, NULL, __argv, environ);
spawn_status = posix_spawn(&pid, executable, &file_actions, &spawn_attr, argv__, environ);
} else { // Try to find executable in path
spawn_status = posix_spawnp(&pid, executable, &file_actions, NULL, __argv, environ);
spawn_status = posix_spawnp(&pid, executable, &file_actions, &spawn_attr, argv__, environ);
}
if (spawn_status != 0)
@@ -90,9 +102,10 @@ pid_t util_spawn(const char *executable, int argc, const char **argv, const char
}
pthread_mutex_unlock( &spawn_mutex );
posix_spawn_file_actions_destroy(&file_actions);
posix_spawnattr_destroy(&spawn_attr);
}
free(__argv);
free(argv__);
return pid;
}
@@ -111,30 +124,6 @@ int util_spawn_blocking(const char *executable, int argc, const char **argv, con
/**
The ping program must(?) be setuid root, so implementing a simple
version based on sockets() proved to be nontrivial.
The PING_CMD is passed as -D from the build system.
*/
#ifdef ERT_HAVE_PING
#define xstr(s) #s
#define str(s) xstr(s)
bool util_ping(const char *hostname) {
int wait_status;
const char* args[ 4 ] = { "-c", "3", "-q", hostname };
wait_status = util_spawn_blocking(str(PING_CMD), 4, args, "/dev/null" , "/dev/null");
if (WIFEXITED( wait_status )) {
int ping_status = WEXITSTATUS( wait_status );
return ping_status == 0;
} else {
return false;
}
}
#endif

View File

@@ -93,7 +93,7 @@ Layout on disk when using util_fwrite_compressed:
Observe that the functions util_fwrite_compressed() and
util_fread_compressed must be used as a pair, the files can **N O T**
be interchanged with normal calls to gzip/gunzip. To avoid confusion
it is therefor strongly advised NOT to give the files a .gz extension.
it is therefore strongly advised NOT to give the files a .gz extension.
*/

View File

@@ -542,7 +542,7 @@ static int vector_cmp(const void * s1 , const void * s2) {
int (* user_cmp) (const void *, const void *)
i.e. the same as for qsort. The vector implementation considers
(fully) untyped data, it is therefor the users responsability to
(fully) untyped data, it is therefore the users responsability to
ensure that the comparison makes sense. For example:

View File

@@ -95,10 +95,11 @@
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <math.h>
#include <ert/util/type_macros.h>
#include <ert/util/util.h>
#include <ert/util/buffer.h>
#include <ert/util/@TYPE@_vector.h>
#ifdef __cplusplus
@@ -895,6 +896,26 @@ void @TYPE@_vector_init_range(@TYPE@_vector_type * vector , @TYPE@ value1 , @TYP
}
bool @TYPE@_vector_init_linear(@TYPE@_vector_type * vector , @TYPE@ start_value, @TYPE@ end_value, int num_values) {
if (num_values < 2)
return false;
@TYPE@_vector_reset( vector );
@TYPE@_vector_iset( vector, 0 , start_value);
{
double slope = (end_value - start_value) / (num_values - 1);
for (int i=1; i < num_values - 1; i++) {
@TYPE@ value = (@TYPE@) start_value + slope*i;
@TYPE@_vector_iset(vector, i, value);
}
}
@TYPE@_vector_iset( vector, num_values - 1, end_value);
return true;
}
void @TYPE@_vector_append_many(@TYPE@_vector_type * vector , const @TYPE@ * data , int length) {
@TYPE@_vector_set_many( vector , @TYPE@_vector_size( vector ) , data , length);
}
@@ -1450,31 +1471,6 @@ void @TYPE@_vector_fread( @TYPE@_vector_type * vector , FILE * stream ) {
void @TYPE@_vector_buffer_fwrite(const @TYPE@_vector_type * vector , buffer_type * buffer) {
buffer_fwrite_int( buffer , vector->size );
buffer_fwrite( buffer , &vector->default_value , sizeof vector->default_value , 1 );
buffer_fwrite( buffer , vector->data , sizeof * vector->data , vector->size );
}
void @TYPE@_vector_buffer_fread(@TYPE@_vector_type * vector , buffer_type * buffer) {
@TYPE@ default_value;
int size = buffer_fread_int( buffer );
buffer_fread( buffer , &default_value , sizeof default_value , 1 );
@TYPE@_vector_set_default( vector , default_value );
@TYPE@_vector_realloc_data__( vector , size );
buffer_fread( buffer , vector->data , sizeof * vector->data , size );
vector->size = size;
}
@TYPE@_vector_type * @TYPE@_vector_buffer_fread_alloc( buffer_type * buffer ) {
@TYPE@_vector_type * vector = @TYPE@_vector_alloc( 0 , 0);
@TYPE@_vector_buffer_fread( vector , buffer );
return vector;
}
/*****************************************************************/
@@ -1489,6 +1485,51 @@ bool @TYPE@_vector_equal(const @TYPE@_vector_type * vector1 , const @TYPE@_vecto
}
int @TYPE@_vector_first_equal(const @TYPE@_vector_type * vector1, const @TYPE@_vector_type * vector2, int offset) {
if (offset >= vector1->size)
return -2;
if (offset >= vector2->size)
return -2;
int index = offset;
while (vector1->data[index] != vector2->data[index]) {
index++;
if (index == vector1->size)
return -1;
if (index == vector2->size)
return -1;
}
return index;
}
int @TYPE@_vector_first_not_equal(const @TYPE@_vector_type * vector1, const @TYPE@_vector_type * vector2, int offset) {
if (offset >= vector1->size)
return -2;
if (offset >= vector2->size)
return -2;
int index = offset;
while (vector1->data[index] == vector2->data[index]) {
index++;
if (index == vector1->size)
return -1;
if (index == vector2->size)
return -1;
}
return index;
}
void @TYPE@_vector_apply(@TYPE@_vector_type * vector , @TYPE@_ftype * func) {
@TYPE@_vector_assert_writable( vector );

View File

@@ -1,37 +1,36 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'vector_template.h' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
Copyright (C) 2011 Statoil ASA, Norway.
The file 'vector_template.h' is part of ERT - Ensemble based Reservoir Tool.
ERT 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.
ERT 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 at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#ifndef ERT_@TYPE@_VECTOR_H
#define ERT_@TYPE@_VECTOR_H
#ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdbool.h>
#include <ert/util/buffer.h>
#include <ert/util/type_macros.h>
#include <ert/util/perm_vector.h>
typedef struct @TYPE@_vector_struct @TYPE@_vector_type;
typedef @TYPE@ (@TYPE@_ftype) (@TYPE@);
int @TYPE@_vector_lookup_bin( const @TYPE@_vector_type * limits , @TYPE@ value , int guess);
int @TYPE@_vector_lookup_bin__( const @TYPE@_vector_type * limits , @TYPE@ value , int guess);
void @TYPE@_vector_inplace_div( @TYPE@_vector_type * vector , const @TYPE@_vector_type * inv_factor);
@@ -71,10 +70,10 @@ typedef @TYPE@ (@TYPE@_ftype) (@TYPE@);
void @TYPE@_vector_insert( @TYPE@_vector_type * vector , int index , @TYPE@ value);
void @TYPE@_vector_append(@TYPE@_vector_type * , @TYPE@);
void @TYPE@_vector_free_container(@TYPE@_vector_type * vector);
void @TYPE@_vector_free(@TYPE@_vector_type *);
void @TYPE@_vector_free__(void *);
void @TYPE@_vector_free_data(@TYPE@_vector_type *);
void @TYPE@_vector_reset(@TYPE@_vector_type *);
void @TYPE@_vector_free(@TYPE@_vector_type *);
void @TYPE@_vector_free__(void *);
void @TYPE@_vector_free_data(@TYPE@_vector_type *);
void @TYPE@_vector_reset(@TYPE@_vector_type *);
void @TYPE@_vector_reset__(void * __vector);
int @TYPE@_vector_size(const @TYPE@_vector_type * );
void @TYPE@_vector_lshift(@TYPE@_vector_type * vector , int shift);
@@ -85,6 +84,7 @@ typedef @TYPE@ (@TYPE@_ftype) (@TYPE@);
@TYPE@ * @TYPE@_vector_get_ptr(const @TYPE@_vector_type * );
@TYPE@ * @TYPE@_vector_alloc_data_copy( const @TYPE@_vector_type * vector );
const @TYPE@ * @TYPE@_vector_get_const_ptr(const @TYPE@_vector_type * );
bool @TYPE@_vector_init_linear(@TYPE@_vector_type * vector , @TYPE@ start_value, @TYPE@ end_value, int num_values);
void @TYPE@_vector_init_range(@TYPE@_vector_type * vector , @TYPE@ value1 , @TYPE@ value2 , @TYPE@ delta);
void @TYPE@_vector_set_many(@TYPE@_vector_type * , int , const @TYPE@ * , int );
void @TYPE@_vector_set_all(@TYPE@_vector_type * vector , @TYPE@ value);
@@ -108,14 +108,13 @@ typedef @TYPE@ (@TYPE@_ftype) (@TYPE@);
perm_vector_type * @TYPE@_vector_alloc_rsort_perm(const @TYPE@_vector_type * vector);
void @TYPE@_vector_fprintf(const @TYPE@_vector_type * vector , FILE * stream , const char * name , const char * fmt);
void @TYPE@_vector_fwrite(const @TYPE@_vector_type * vector , FILE * stream);
void @TYPE@_vector_buffer_fread(@TYPE@_vector_type * vector , buffer_type * buffer);
@TYPE@_vector_type * @TYPE@_vector_fread_alloc( FILE * stream );
@TYPE@_vector_type * @TYPE@_vector_buffer_fread_alloc( buffer_type * buffer );
void @TYPE@_vector_buffer_fwrite(const @TYPE@_vector_type * vector , buffer_type * buffer);
void @TYPE@_vector_fread( @TYPE@_vector_type * vector , FILE * stream );
void @TYPE@_vector_fwrite_data( const @TYPE@_vector_type * vector , FILE * stream );
void @TYPE@_vector_fread_data( @TYPE@_vector_type * vector , int size, FILE * stream);
bool @TYPE@_vector_equal(const @TYPE@_vector_type * vector1 , const @TYPE@_vector_type * vector2);
int @TYPE@_vector_first_equal(const @TYPE@_vector_type * vector1, const @TYPE@_vector_type * vector2, int offset);
int @TYPE@_vector_first_not_equal(const @TYPE@_vector_type * vector1, const @TYPE@_vector_type * vector2, int offset);
void @TYPE@_vector_apply(@TYPE@_vector_type * vector , @TYPE@_ftype *func);
int @TYPE@_vector_count_equal( const @TYPE@_vector_type * vector , @TYPE@ cmp_value);
int @TYPE@_vector_element_size( const @TYPE@_vector_type * vector );
@@ -125,7 +124,7 @@ typedef @TYPE@ (@TYPE@_ftype) (@TYPE@);
UTIL_SAFE_CAST_HEADER( @TYPE@_vector );
UTIL_IS_INSTANCE_HEADER( @TYPE@_vector );
#ifdef __cplusplus
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -7,14 +7,27 @@ init_python( 2.7 )
find_python_package(numpy 1.7.1 ${PYTHON_INSTALL_PREFIX})
if (NOT DEFINED PY_numpy)
message(WARNING "numpy module not found - Python wrappers not enabled")
set( BUILD_PYTHON OFF PARENT_SCOPE )
message(WARNING "numpy module not found - Python wrappers not enabled. Install with: \"pip install numpy\"")
set( ENABLE_PYTHON OFF PARENT_SCOPE )
return()
endif()
find_python_package(cwrap 1 ${PYTHON_INSTALL_PREFIX})
if (NOT DEFINED PY_cwrap)
message(WARNING "cwrap module not found Python wrappers not enabled. Install with: \"pip install cwrap\"")
set( ENABLE_PYTHON OFF PARENT_SCOPE )
return()
endif()
configure_file(test_env.py.in ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/test_env.py )
add_subdirectory( ecl )
if (INSTALL_ERT_LEGACY)
add_subdirectory( ert )
endif()
if (BUILD_TESTS)
add_subdirectory( tests )
endif()
add_subdirectory( python )

View File

@@ -134,7 +134,7 @@ def update_path():
if __name__ == '__main__':
update_path( )
from ecl.test import ErtTestRunner
from ecl.util.test import ErtTestRunner
for test_class in sys.argv[1:]:
tests = ErtTestRunner.getTestsFromTestClass(test_class)

View File

@@ -165,16 +165,16 @@ like:
typedef struct {
.....
.....
} abs_type;
} abs_type;
and "methods" like:
abs_type * abs_type_alloc( ) { }
void abs_type_free( abs_type * at ) {}
int abs_type_get_an_int( const abs_type * at) {}
void abs_type_free( abs_type * at ) {}
int abs_type_get_an_int( const abs_type * at) {}
void abs_type_set_an_int( abs_type * at , int value) {}
it has therefor been relatively easy to map this onto Python classes
it has therefore been relatively easy to map this onto Python classes
and give a pythonic feel to the whole thing. As a ground rule each C
file implements one struct; this struct is wrapped in a Python module
with the same name and a Python class with CamelCaps naming:

View File

@@ -0,0 +1,18 @@
set(PYTHON_SOURCES
__init__.py
ecl_type.py
ecl_util.py
)
add_python_package("python.ecl" ${PYTHON_INSTALL_PREFIX}/ecl "${PYTHON_SOURCES}" True)
add_subdirectory(eclfile)
add_subdirectory(grid)
add_subdirectory(rft)
add_subdirectory(gravimetry)
add_subdirectory(summary)
add_subdirectory(util)
add_subdirectory(well)
configure_file(ecl_lib_info_build.py.in ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/ecl/__ecl_lib_info.py )
configure_file(ecl_lib_info_install.py.in ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/ecl_lib_info_install.py )
install(FILES ${PROJECT_BINARY_DIR}/${PYTHON_INSTALL_PREFIX}/ecl_lib_info_install.py DESTINATION ${PYTHON_INSTALL_PREFIX}/ecl RENAME __ecl_lib_info.py)

140
ThirdParty/Ert/python/ecl/__init__.py vendored Normal file
View File

@@ -0,0 +1,140 @@
# Copyright (C) 2011 Statoil ASA, Norway.
#
# The file '__init__.py' is part of ERT - Ensemble based Reservoir Tool.
#
# ERT 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.
#
# ERT 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 at <http://www.gnu.org/licenses/gpl.html>
# for more details.
"""
ert - Ensemble Reservoir Tool - a package for reservoir modeling.
The ert package itself has no code, but contains several subpackages:
ecl.ecl: Package for working with ECLIPSE files. The far most mature
package in ert.
ecl.util:
The ert package is based on wrapping the libriaries from the ERT C
code with ctypes; an essential part of ctypes approach is to load the
shared libraries with the ctypes.CDLL() function. The ctypes.CDLL()
function uses the standard methods of the operating system,
i.e. standard locations configured with ld.so.conf and the environment
variable LD_LIBRARY_PATH.
To avoid conflict with other application using the ert libraries the
Python code should be able to locate the shared libraries without
(necessarily) using the LD_LIBRARY_PATH variable. The default
behaviour is to try to load from the library ../../lib64, but by using
the enviornment variable ERT_LIBRARY_PATH you can alter how ert looks
for shared libraries.
1. By default the code will try to load the shared libraries from
'../../lib64' relative to the location of this file.
2. Depending on the value of ERT_LIBRARY_PATH two different
behaviours can be imposed:
Existing path: the package will look in the path pointed to
by ERT_LIBRARY_PATH for shared libraries.
Arbitrary value: the package will use standard load order for
the operating system.
If the fixed path, given by the default ../../lib64 or ERT_LIBRARY_PATH
alternative fails, the loader will try the default load behaviour
before giving up completely.
"""
import os.path
import sys
import warnings
warnings.simplefilter('always', DeprecationWarning) # see #1437
from cwrap import load as cwrapload
from cwrap import Prototype
try:
import ert_site_init
except ImportError:
pass
required_version_hex = 0x02070000
ecl_lib_path = None
ert_so_version = ""
__version__ = "0.0.0"
# 1. Try to load the __ecl_lib_info module; this module has been
# configured by cmake during the build configuration process. The
# module should contain the variable lib_path pointing to the
# directory with shared object files.
try:
from .__ecl_lib_info import EclLibInfo
ecl_lib_path = EclLibInfo.lib_path
ert_so_version = EclLibInfo.so_version
__version__ = EclLibInfo.__version__
except ImportError:
pass
except AttributeError:
pass
# 2. Using the environment variable ERT_LIBRARY_PATH it is possible to
# override the default algorithms. If the ERT_LIBRARY_PATH is set
# to a non existing directory a warning will go to stderr and the
# setting will be ignored.
env_lib_path = os.getenv("ERT_LIBRARY_PATH")
if env_lib_path:
if os.path.isdir( env_lib_path ):
ert_lib_path = os.getenv("ERT_LIBRARY_PATH")
else:
sys.stderr.write("Warning: Environment variable ERT_LIBRARY_PATH points to nonexisting directory:%s - ignored" % env_lib_path)
# Check that the final ert_lib_path setting corresponds to an existing
# directory.
if ecl_lib_path:
if not os.path.isabs(ecl_lib_path):
ecl_lib_path = os.path.abspath(os.path.join(os.path.dirname(__file__), ecl_lib_path))
if not os.path.isdir( ecl_lib_path ):
ecl_lib_path = None
if sys.hexversion < required_version_hex:
raise Exception("ERT Python requires Python 2.7.")
def load(name):
return cwrapload(name, path=ecl_lib_path, so_version=ert_so_version)
class EclPrototype(Prototype):
lib = load("libecl")
def __init__(self, prototype, bind=True):
super(EclPrototype, self).__init__(EclPrototype.lib, prototype, bind=bind)
from .ecl_type import EclTypeEnum, EclDataType
from .ecl_util import EclFileEnum, EclFileFlagEnum, EclPhaseEnum, EclUnitTypeEnum , EclUtil
from .util.util import EclVersion
from .util.util import updateAbortSignals
updateAbortSignals( )
def root():
"""
Will print the filesystem root of the current ert package.
"""
return os.path.abspath( os.path.join( os.path.dirname( __file__ ) , "../"))

View File

@@ -0,0 +1,9 @@
class EclLibInfo(object):
lib_path = "${LIBRARY_OUTPUT_PATH}"
so_version = "${ECL_BINARY_POSTFIX}"
__version__ = "${ECL_VERSION_MAJOR}.${ECL_VERSION_MINOR}.${ECL_VERSION_MICRO}"
def __init__(self):
pass

View File

@@ -0,0 +1,9 @@
class EclLibInfo(object):
lib_path = "../../../../${CMAKE_INSTALL_LIBDIR}"
so_version = "${ECL_BINARY_POSTFIX}"
__version__ = "${ECL_VERSION_MAJOR}.${ECL_VERSION_MINOR}.${ECL_VERSION_MICRO}"
def __init__(self):
pass

184
ThirdParty/Ert/python/ecl/ecl_type.py vendored Normal file
View File

@@ -0,0 +1,184 @@
# Copyright (C) 2017 Statoil ASA, Norway.
#
# The file 'ecl_type.py' is part of ERT - Ensemble based Reservoir Tool.
#
# ERT 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.
#
# ERT 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 at <http://www.gnu.org/licenses/gpl.html>
# for more details.
from cwrap import BaseCClass, BaseCEnum
from ecl import EclPrototype
class EclTypeEnum(BaseCEnum):
TYPE_NAME="ecl_type_enum"
ECL_CHAR_TYPE = None
ECL_FLOAT_TYPE = None
ECL_DOUBLE_TYPE = None
ECL_INT_TYPE = None
ECL_BOOL_TYPE = None
ECL_MESS_TYPE = None
ECL_STRING_TYPE = None
EclTypeEnum.addEnum("ECL_CHAR_TYPE", 0)
EclTypeEnum.addEnum("ECL_FLOAT_TYPE", 1)
EclTypeEnum.addEnum("ECL_DOUBLE_TYPE", 2)
EclTypeEnum.addEnum("ECL_INT_TYPE", 3)
EclTypeEnum.addEnum("ECL_BOOL_TYPE", 4)
EclTypeEnum.addEnum("ECL_MESS_TYPE", 5)
EclTypeEnum.addEnum("ECL_STRING_TYPE", 7)
#-----------------------------------------------------------------
class EclDataType(BaseCClass):
TYPE_NAME = "ecl_data_type"
_alloc = EclPrototype("void* ecl_type_alloc_python(ecl_type_enum, size_t)", bind=False)
_alloc_from_type = EclPrototype("void* ecl_type_alloc_from_type_python(ecl_type_enum)", bind=False)
_alloc_from_name = EclPrototype("void* ecl_type_alloc_from_name_python(char*)", bind=False)
_free = EclPrototype("void ecl_type_free_python(ecl_data_type)")
_get_type = EclPrototype("ecl_type_enum ecl_type_get_type_python(ecl_data_type)")
_get_element_size = EclPrototype("size_t ecl_type_get_sizeof_ctype_fortio_python(ecl_data_type)")
_is_int = EclPrototype("bool ecl_type_is_int_python(ecl_data_type)")
_is_char = EclPrototype("bool ecl_type_is_char_python(ecl_data_type)")
_is_float = EclPrototype("bool ecl_type_is_float_python(ecl_data_type)")
_is_double = EclPrototype("bool ecl_type_is_double_python(ecl_data_type)")
_is_mess = EclPrototype("bool ecl_type_is_mess_python(ecl_data_type)")
_is_bool = EclPrototype("bool ecl_type_is_bool_python(ecl_data_type)")
_is_string = EclPrototype("bool ecl_type_is_string_python(ecl_data_type)")
_get_name = EclPrototype("char* ecl_type_alloc_name_python(ecl_data_type)")
_is_numeric = EclPrototype("bool ecl_type_is_numeric_python(ecl_data_type)")
_is_equal = EclPrototype("bool ecl_type_is_equal_python(ecl_data_type, ecl_data_type)")
def __init__(self, type_enum=None, element_size=None, type_name=None):
self._assert_valid_arguments(type_enum, element_size, type_name)
if type_name:
c_ptr = self._alloc_from_name(type_name)
elif element_size is None:
c_ptr = self._alloc_from_type(type_enum)
else:
c_ptr = self._alloc(type_enum, element_size)
super(EclDataType, self).__init__(c_ptr)
def _assert_valid_arguments(self, type_enum, element_size, type_name):
if type_name is not None:
if type_enum is not None or element_size is not None:
err_msg = ("Type name given (%s). Expected both " +
"type_enum and element_size to be None")
raise ValueError(err_msg % type_name)
elif type_enum is None:
raise ValueError("Both type_enum and type_name is None!")
elif type_enum == EclTypeEnum.ECL_STRING_TYPE:
if element_size is None:
raise ValueError("When creating an ECL_STRING one must " +
"provide an element size!")
if not (0 <= element_size <= 999):
raise ValueError("Expected element_size to be in the range " +
"[0, 999], was: %d" % element_size)
@property
def type(self):
return self._get_type()
@property
def element_size(self):
return self._get_element_size()
@property
def type_name(self):
return self._get_name()
def free(self):
self._free()
def is_int(self):
return self._is_int()
def is_char(self):
return self._is_char()
def is_float(self):
return self._is_float()
def is_double(self):
return self._is_double()
def is_mess(self):
return self._is_mess()
def is_bool(self):
return self._is_bool()
def is_string(self):
return self._is_string()
def is_numeric(self):
return self._is_numeric()
def is_equal(self, other):
return self._is_equal(other)
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.is_equal(other)
return False
def __ne__(self, other):
return not self.__eq__(other)
def __hash__(self):
return hash((self.type, self. element_size))
@classmethod
def create_from_type_name(cls, name):
return EclDataType(type_name=name)
# Enables one to fetch a type as EclDataType.ECL_XXXX
class classproperty(object):
def __init__(self, fget):
self.fget = fget
def __get__(self, owner_self, owner_cls):
return self.fget(owner_cls)
@classproperty
def ECL_INT(cls):
return EclDataType(EclTypeEnum.ECL_INT_TYPE)
@classproperty
def ECL_FLOAT(cls):
return EclDataType(EclTypeEnum.ECL_FLOAT_TYPE)
@classproperty
def ECL_DOUBLE(cls):
return EclDataType(EclTypeEnum.ECL_DOUBLE_TYPE)
@classproperty
def ECL_BOOL(cls):
return EclDataType(EclTypeEnum.ECL_BOOL_TYPE)
@classproperty
def ECL_MESS(cls):
return EclDataType(EclTypeEnum.ECL_MESS_TYPE)
@classproperty
def ECL_CHAR(cls):
return EclDataType(EclTypeEnum.ECL_CHAR_TYPE)
@classmethod
def ECL_STRING(cls, elem_size):
return EclDataType(EclTypeEnum.ECL_STRING_TYPE, elem_size)

166
ThirdParty/Ert/python/ecl/ecl_util.py vendored Normal file
View File

@@ -0,0 +1,166 @@
# Copyright (C) 2011 Statoil ASA, Norway.
#
# The file 'ecl_util.py' is part of ERT - Ensemble based Reservoir Tool.
#
# ERT 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.
#
# ERT 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 at <http://www.gnu.org/licenses/gpl.html>
# for more details.
"""
Constants from the header ecl_util.h - some stateless functions.
This module does not contain any class definitions; it mostly consists
of enum definitions/values from ecl_util.h; the enum values are
extracted from the shared library in a semi-automagic manner using the
BaseCEnum class from cwrap.
In addition to the enum definitions there are a few stateless
functions from ecl_util.c which are not bound to any class type.
"""
import ctypes
from cwrap import BaseCEnum
from ecl.util.util import monkey_the_camel
from ecl import EclPrototype
class EclFileEnum(BaseCEnum):
TYPE_NAME = "ecl_file_enum"
ECL_OTHER_FILE = None
ECL_RESTART_FILE = None
ECL_UNIFIED_RESTART_FILE = None
ECL_SUMMARY_FILE = None
ECL_UNIFIED_SUMMARY_FILE = None
ECL_GRID_FILE = None
ECL_EGRID_FILE = None
ECL_INIT_FILE = None
ECL_RFT_FILE = None
ECL_DATA_FILE = None
EclFileEnum.addEnum("ECL_OTHER_FILE", 0)
EclFileEnum.addEnum("ECL_RESTART_FILE", 1)
EclFileEnum.addEnum("ECL_UNIFIED_RESTART_FILE", 2)
EclFileEnum.addEnum("ECL_SUMMARY_FILE", 4)
EclFileEnum.addEnum("ECL_UNIFIED_SUMMARY_FILE", 8)
EclFileEnum.addEnum("ECL_SUMMARY_HEADER_FILE", 16)
EclFileEnum.addEnum("ECL_GRID_FILE", 32)
EclFileEnum.addEnum("ECL_EGRID_FILE", 64)
EclFileEnum.addEnum("ECL_INIT_FILE", 128)
EclFileEnum.addEnum("ECL_RFT_FILE", 256)
EclFileEnum.addEnum("ECL_DATA_FILE", 512)
#-----------------------------------------------------------------
class EclPhaseEnum(BaseCEnum):
TYPE_NAME="ecl_phase_enum"
ECL_OIL_PHASE = None
ECL_GAS_PHASE = None
ECL_WATER_PHASE = None
EclPhaseEnum.addEnum("ECL_OIL_PHASE", 1)
EclPhaseEnum.addEnum("ECL_GAS_PHASE", 2)
EclPhaseEnum.addEnum("ECL_WATER_PHASE", 4)
#-----------------------------------------------------------------
class EclUnitTypeEnum(BaseCEnum):
TYPE_NAME = "ecl_unit_enum"
ECL_METRIC_UNITS = None
ECL_FIELD_UNITS = None
ECL_LAB_UNITS = None
ECL_PVT_M_UNITS = None
EclUnitTypeEnum.addEnum("ECL_METRIC_UNITS", 1)
EclUnitTypeEnum.addEnum("ECL_FIELD_UNITS", 2)
EclUnitTypeEnum.addEnum("ECL_LAB_UNITS", 3)
EclUnitTypeEnum.addEnum("ECL_PVT_M_UNITS", 4)
#-----------------------------------------------------------------
class EclFileFlagEnum(BaseCEnum):
TYPE_NAME="ecl_file_flag_enum"
ECL_FILE_CLOSE_STREAM = None
ECL_FILE_WRITABLE = None
EclFileFlagEnum.addEnum("ECL_FILE_CLOSE_STREAM", 1)
EclFileFlagEnum.addEnum("ECL_FILE_WRITABLE", 2)
#-----------------------------------------------------------------
class EclUtil(object):
_get_num_cpu = EclPrototype("int ecl_util_get_num_cpu(char*)", bind = False)
_get_file_type = EclPrototype("ecl_file_enum ecl_util_get_file_type(char*, bool*, int*)", bind = False)
_get_start_date = EclPrototype("time_t ecl_util_get_start_date(char*)", bind = False)
_get_report_step = EclPrototype("int ecl_util_filename_report_nr(char*)", bind = False)
@staticmethod
def get_num_cpu(datafile):
"""
Parse ECLIPSE datafile and determine how many CPUs are needed.
Will look for the "PARALLELL" keyword, and then read off the
number of CPUs required. Will return one if no PARALLELL keyword
is found.
"""
return EclUtil._get_num_cpu(datafile)
@staticmethod
def get_file_type(filename):
"""
Will inspect an ECLIPSE filename and return an integer type flag.
"""
file_type, fmt, step = EclUtil.inspectExtension(filename)
return file_type
@staticmethod
def get_start_date(datafile):
return EclUtil._get_start_date(datafile).datetime()
@staticmethod
def inspect_extension(filename):
"""Will inspect an ECLIPSE filename and return a tuple consisting of
file type (EclFileEnum), a bool for formatted or not, and an
integer for the step number.
"""
fmt_file = ctypes.c_bool()
report_step = ctypes.c_int(-1)
file_type = EclUtil._get_file_type(filename, ctypes.byref(fmt_file), ctypes.byref(report_step))
if report_step.value == -1:
step = None
else:
step = report_step.value
return (file_type, fmt_file.value, step)
@staticmethod
def report_step(filename):
report_step = EclUtil._get_report_step(filename)
if report_step < 0:
raise ValueError("Could not infer report step from: %s" % filename)
return report_step
get_num_cpu = EclUtil.get_num_cpu
get_file_type = EclUtil.get_file_type
get_start_date = EclUtil.get_start_date
monkey_the_camel(EclUtil, 'inspectExtension', EclUtil.inspect_extension, staticmethod)
monkey_the_camel(EclUtil, 'reportStep', EclUtil.report_step, staticmethod)

View File

@@ -0,0 +1,14 @@
set(PYTHON_SOURCES
__init__.py
ecl_3d_file.py
ecl_file.py
ecl_file_view.py
ecl_init_file.py
ecl_restart_file.py
ecl_kw.py
fortio.py
ecl_3dkw.py
)
add_python_package("python.ecl.eclfile" ${PYTHON_INSTALL_PREFIX}/ecl/eclfile "${PYTHON_SOURCES}" True)

View File

@@ -0,0 +1,45 @@
# Copyright (C) 2018 Statoil ASA, Norway.
#
# This file is part of ERT - Ensemble based Reservoir Tool.
#
# ERT 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.
#
# ERT 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 at <http://www.gnu.org/licenses/gpl.html>
# for more details.
"""
The eclfile package contains several classes for working directly with ECLIPSE
files.
fortio/FortIO: This is functionality to read and write binary
fortran files.
ecl_kw/EclKW: This class holds one ECLIPSE keyword, like SWAT, in
restart format.
ecl_type/EclDataType: This class is used to represent the data type
of the elements in EclKW.
ecl_file/EclFile: This class is used to load an ECLIPSE file in
restart format, alternatively only parts of the file can be
loaded. Internally it consists of a collection of EclKW
instances.
"""
import ecl.util.util
from .fortio import FortIO, openFortIO
from .ecl_kw import EclKW
from .ecl_file_view import EclFileView
from .ecl_file import EclFile , openEclFile
from .ecl_3dkw import Ecl3DKW
from .ecl_3d_file import Ecl3DFile
from .ecl_init_file import EclInitFile
from .ecl_restart_file import EclRestartFile

View File

@@ -0,0 +1,41 @@
# Copyright (C) 2015 Statoil ASA, Norway.
#
# This file is part of ERT - Ensemble based Reservoir Tool.
#
# ERT 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.
#
# ERT 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 at <http://www.gnu.org/licenses/gpl.html>
# for more details.
from ecl.eclfile import EclFile, Ecl3DKW
class Ecl3DFile(EclFile):
def __init__(self, grid, filename, flags=0):
self.grid = grid
super(Ecl3DFile, self).__init__(filename, flags)
def __getitem__(self, index):
return_arg = super(Ecl3DFile, self).__getitem__(index)
if isinstance(return_arg,list):
kw_list = return_arg
else:
kw_list = [return_arg]
# Go through all the keywords and try inplace promotion to Ecl3DKW
for kw in kw_list:
try:
Ecl3DKW.castFromKW(kw, self.grid)
except ValueError:
pass
return return_arg

View File

@@ -0,0 +1,239 @@
# Copyright (C) 2015 Statoil ASA, Norway.
#
# The file 'ecl_3dkw.py' is part of ERT - Ensemble based Reservoir Tool.
#
# ERT 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.
#
# ERT 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 at <http://www.gnu.org/licenses/gpl.html>
# for more details.
from __future__ import (absolute_import, division,
print_function, unicode_literals)
from ecl.util.util import monkey_the_camel
from .ecl_kw import EclKW
class Ecl3DKW(EclKW):
"""
Class for working with Eclipse keywords defined over a grid
The Ecl3DKW class is derived from the EclKW class, and most of the
methods are implemented in the EclKW base class. The purpose of
the Ecl3DKW class is to simplify working with 3D properties like
PORO or SATNUM.
The Ecl3DKW class has an attached EclGrid which is used to support
[i,j,k] indexing, and a defined default value which is used when
reading an inactive value. The Ecl3DKW keyword instances are
returned from the EclInitFile and EclRestartFile classes, in
addition you can excplicitly \"cast\" a EclKW keyword to Ecl3DKW
with the Ecl3DKW.castFromKW() classmethod.
Usage example:
from ecl.ecl import EclInitFile,EclGrid
grid = EclGrid("ECLIPSE.EGRID")
file = EclInitFile(grid , "ECLIPSE.INIT")
permx_kw = file["PORO"][0]
porv_kw = file["PORV"][0]
permx_kw.setDefault( -1 )
for k in range(grid.getNZ()):
for j in range(grid.getNY()):
for i in range(grid.getNX()):
print('"(%d,%d,%d) Permx:%g Porv:%g"' % (i,j,k,permx_kw[i,j,k] , porv_kw[i,j,k]))
In the example we open an ECLIPSE INIT file and extract the PERMX
and PORV properties, and then iterate over all the cells in the
grid.
In the INIT file the PORV keyword is stored with all cells,
whereas the PERMX keyword typically only has the active cells
stored, this active/inactive gymnastics is handled
transparently. With the call:
permx_kw.setDefault( -1 )
we say that we want the value -1 for all inactive cells in the
PERMX property.
"""
def __init__(self, kw , grid , value_type , default_value = 0 , global_active = False):
if global_active:
size = grid.getGlobalSize()
else:
size = grid.getNumActive( )
super(Ecl3DKW , self).__init__( kw , size , value_type)
self.grid = grid
self.global_active = global_active
self.setDefault( default_value )
@classmethod
def create(cls , kw , grid , value_type , default_value = 0 , global_active = False):
new_kw = Ecl3DKW(kw , grid , value_type , default_value , global_active)
return new_kw
@classmethod
def read_grdecl( cls , grid , fileH , kw , strict = True , ecl_type = None):
"""
Will load an Ecl3DKW instance from a grdecl formatted filehandle.
See the base class EclKW.read_grdecl() for more documentation.
"""
kw = super(Ecl3DKW , cls).read_grdecl( fileH , kw , strict , ecl_type)
Ecl3DKW.castFromKW(kw , grid)
return kw
def __getitem__(self , index):
"""Will return item [g] or [i,j,k].
The __getitem__() methods supports both scalar indexing like
[g] and tuples [i,j,k]. If the input argument is given as a
[i,j,k] tuple it is converted to an active index before the
final lookup.
If the [i,j,k] input corresponds to an inactive cell in a
keyword with only nactive elements the default value will be
returned. By default the default value will be 0, but another
value can be assigned with the setDefault() method.
"""
if isinstance(index , tuple):
global_index = self.grid.get_global_index( ijk = index )
if self.global_active:
index = global_index
else:
if not self.grid.active( global_index = global_index):
return self.getDefault()
else:
index = self.grid.get_active_index( ijk = index )
return super(Ecl3DKW , self).__getitem__( index )
def __setitem__(self , index , value):
"""Set the value of at index [g] or [i,j,k].
The __setitem__() methods supports both scalar indexing like
[g] and tuples [i,j,k]. If the input argument is given as a
[i,j,k] tuple it is converted to an active index before the
final assignment.
If you try to assign an inactive cell in a keyword with only
nactive elements a ValueError() exception will be raised.
"""
if isinstance(index , tuple):
global_index = self.grid.get_global_index( ijk = index )
if self.global_active:
index = global_index
else:
if not self.grid.active( global_index = global_index):
raise ValueError("Tried to assign value to inactive cell: (%d,%d,%d)" % index)
else:
index = self.grid.get_active_index( ijk = index )
return super(Ecl3DKW , self).__setitem__( index , value )
@classmethod
def cast_from_kw(cls, kw, grid, default_value=0):
"""Will convert a normal EclKW to a Ecl3DKW.
The method will convert a normal EclKW instance to Ecl3DKw
instance with an attached grid and a default value.
The method will check that size of the keyword is compatible
with the grid dimensions, i.e. the keyword must have either
nactive or nx*ny*nz elements. If the size of the keyword is
not compatible with the grid dimensions a ValueError exception
is raised.
Example:
1. Load the poro keyword from a grdecl formatted file.
2. Convert the keyword to a 3D keyword.
from ecl.ecl import EclGrid,EclKW,Ecl3DKW
grid = EclGrid("ECLIPSE.EGRID")
poro = EclKW.read_grdecl(open("poro.grdecl") , "PORO")
Ecl3DKW.castFromKW( poro , grid )
print('Porosity in cell (10,11,12):%g' % poro[10,11,12])
"""
if len(kw) == grid.getGlobalSize():
kw.global_active = True
elif len(kw) == grid.getNumActive():
kw.global_active = False
else:
raise ValueError("Size mismatch - must have size matching global/active size of grid")
kw.__class__ = cls
kw.default_value = default_value
kw.grid = grid
if len(kw) == grid.getGlobalSize():
kw.global_active = True
else:
kw.global_active = False
kw.setDefault( default_value )
return kw
def compressed_copy(self):
"""Will return a EclKW copy with nactive elements.
The returned copy will be of type EclKW; i.e. no default
interpolation and only linear access in the [] operator. The
main purpose of this is to facilitate iteration over the
active index, and for writing binary files.
"""
return self.grid.compressedKWCopy( self )
def global_copy(self):
"""Will return a EclKW copy with nx*ny*nz elements.
The returned copy will be of type EclKW; i.e. no default
interpolation and only linear access in the [] operator. The
main purpose of this is to facilitate iteration over the
global index, and for writing binary files.
"""
return self.grid.globalKWCopy( self , self.getDefault() )
def dims(self):
return (self.grid.getNX() , self.grid.getNY() , self.grid.getNZ())
def set_default(self, default_value):
self.default_value = default_value
def get_default(self):
return self.default_value
monkey_the_camel(Ecl3DKW, 'castFromKW', Ecl3DKW.cast_from_kw, classmethod)
monkey_the_camel(Ecl3DKW, 'compressedCopy', Ecl3DKW.compressed_copy)
monkey_the_camel(Ecl3DKW, 'globalCopy', Ecl3DKW.global_copy)
monkey_the_camel(Ecl3DKW, 'setDefault', Ecl3DKW.set_default)
monkey_the_camel(Ecl3DKW, 'getDefault', Ecl3DKW.get_default)

View File

@@ -0,0 +1,721 @@
# Copyright (C) 2011 Statoil ASA, Norway.
#
# The file 'ecl_file.py' is part of ERT - Ensemble based Reservoir Tool.
#
# ERT 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.
#
# ERT 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 at <http://www.gnu.org/licenses/gpl.html>
# for more details.
"""
The ecl_file module contains functionality to load a an ECLIPSE file
in 'restart format'. Files of 'restart format' include restart files,
init files, grid files, summary files and RFT files.
The ecl_file implementation is agnostic[1] to the content and
structure of the file; more specialized classes like EclSum and
EclGrid use the EclFile functionality for low level file loading.
The typical usage involves loading a complete file, and then
subsequently querying for various keywords. In the example below we
load a restart file, and ask for the SWAT keyword:
file = EclFile( "ECLIPSE.X0067" )
swat_kw = file.iget_named_kw( "SWAT" , 0 )
The ecl_file module is a thin wrapper around the ecl_file.c
implementation from the libecl library.
[1]: In particular for restart files, which do not have a special
RestartFile class, there is some specialized functionality.
"""
import re
import types
import datetime
import ctypes
from cwrap import BaseCClass
from ecl import EclPrototype
from ecl.util.util import CTime
from ecl.util.util import monkey_the_camel
from ecl import EclFileEnum
from ecl.eclfile import EclKW, EclFileView
class EclFile(BaseCClass):
TYPE_NAME = "ecl_file"
_open = EclPrototype("void* ecl_file_open( char* , int )" , bind = False)
_get_file_type = EclPrototype("ecl_file_enum ecl_util_get_file_type( char* , bool* , int*)" , bind = False)
_writable = EclPrototype("bool ecl_file_writable( ecl_file )")
_save_kw = EclPrototype("void ecl_file_save_kw( ecl_file , ecl_kw )")
_close = EclPrototype("void ecl_file_close( ecl_file )")
_iget_restart_time = EclPrototype("time_t ecl_file_iget_restart_sim_date( ecl_file , int )")
_iget_restart_days = EclPrototype("double ecl_file_iget_restart_sim_days( ecl_file , int )")
_get_restart_index = EclPrototype("int ecl_file_get_restart_index( ecl_file , time_t)")
_get_src_file = EclPrototype("char* ecl_file_get_src_file( ecl_file )")
_replace_kw = EclPrototype("void ecl_file_replace_kw( ecl_file , ecl_kw , ecl_kw , bool)")
_fwrite = EclPrototype("void ecl_file_fwrite_fortio( ecl_file , fortio , int)")
_has_report_step = EclPrototype("bool ecl_file_has_report_step( ecl_file , int)")
_has_sim_time = EclPrototype("bool ecl_file_has_sim_time( ecl_file , time_t )")
_get_global_view = EclPrototype("ecl_file_view_ref ecl_file_get_global_view( ecl_file )")
_write_index = EclPrototype("bool ecl_file_write_index( ecl_file , char*)")
_fast_open = EclPrototype("void* ecl_file_fast_open( char* , char* , int )" , bind=False)
@staticmethod
def get_filetype(filename):
fmt_file = ctypes.c_bool()
report_step = ctypes.c_int()
file_type = EclFile._get_file_type( filename , ctypes.byref( fmt_file ) , ctypes.byref(report_step))
if file_type in [EclFileEnum.ECL_RESTART_FILE , EclFileEnum.ECL_SUMMARY_FILE]:
report_step = report_step.value
else:
report_step = None
if file_type in [EclFileEnum.ECL_OTHER_FILE , EclFileEnum.ECL_DATA_FILE]:
fmt_file = None
else:
fmt_file = fmt_file.value
return (file_type , report_step , fmt_file )
@classmethod
def restart_block( cls , filename , dtime = None , report_step = None):
raise NotImplementedError("The restart_block implementation has been removed - open file normally and use EclFileView.")
@classmethod
def contains_report_step( cls , filename , report_step ):
"""
Will check if the @filename contains @report_step.
This classmethod works by opening the file @filename and
searching through linearly to see if an ecl_kw with value
corresponding to @report_step can be found. Since this is a
classmethod it is invoked like this:
import ecl.ecl.ecl as ecl
....
if ecl.EclFile.contains_report_step("ECLIPSE.UNRST" , 20):
print "OK - file contains report step 20"
else:
print "File does not contain report step 20"
If you have already loaded the file into an EclFile instance
you should use the has_report_step() method instead.
"""
obj = EclFile( filename )
return obj.has_report_step( report_step )
@classmethod
def contains_sim_time( cls , filename , dtime ):
"""
Will check if the @filename contains simulation at @dtime.
This classmethod works by opening the file @filename and
searching through linearly to see if a result block at the
time corresponding to @dtime can be found. Since this is a
classmethod it is invoked like this:
import ecl.ecl.ecl as ecl
....
if ecl.EclFile.contains_sim_time("ECLIPSE.UNRST" , datetime.datetime( 2007 , 10 , 10) ):
print "OK - file contains 10th of October 2007"
else:
print "File does not contain 10th of October 2007"
If you have already loaded the file into an EclFile instance
you should use the has_sim_time() method instead.
"""
obj = EclFile( filename )
return obj.has_sim_time( dtime )
@property
def report_list(self):
report_steps = []
try:
seqnum_list = self["SEQNUM"]
for s in seqnum_list:
report_steps.append( s[0] )
except KeyError:
# OK - we did not have seqnum; that might be because this
# a non-unified restart file; or because this is not a
# restart file at all.
fname = self.getFilename( )
matchObj = re.search("\.[XF](\d{4})$" , fname)
if matchObj:
report_steps.append( int(matchObj.group(1)) )
else:
raise TypeError('Tried get list of report steps from file "%s" - which is not a restart file' % fname)
return report_steps
@classmethod
def file_report_list( cls , filename ):
"""
Will identify the available report_steps from @filename.
"""
file = EclFile( filename )
return file.report_list
def __repr__(self):
fn = self.getFilename()
wr = ', read/write' if self._writable() else ''
return self._create_repr('"%s"%s' % (fn,wr))
def __init__( self , filename , flags = 0 , index_filename = None):
"""
Loads the complete file @filename.
Will create a new EclFile instance with the content of file
@filename. The file @filename must be in 'restart format' -
otherwise it will be crash and burn.
The optional argument flags can be an or'ed combination of the
flags:
ecl.ECL_FILE_WRITABLE : It is possible to update the
content of the keywords in the file.
ecl.ECL_FILE_CLOSE_STREAM : The underlying FILE * is closed
when not used; to save number of open file descriptors
in cases where a high number of EclFile instances are
open concurrently.
When the file has been loaded the EclFile instance can be used
to query for and get reference to the EclKW instances
constituting the file, like e.g. SWAT from a restart file or
FIPNUM from an INIT file.
"""
if index_filename is None:
c_ptr = self._open( filename , flags )
else:
c_ptr = self._fast_open(filename, index_filename, flags)
if c_ptr is None:
raise IOError('Failed to open file "%s"' % filename)
else:
super(EclFile , self).__init__(c_ptr)
self.global_view = self._get_global_view( )
self.global_view.setParent( self )
def save_kw( self , kw ):
"""
Will write the @kw back to file.
This function should typically be used in situations like this:
1. Create an EclFile instance around an ECLIPSE output file.
2. Extract a keyword of interest and modify it.
3. Call this method to save the modifications to disk.
There are several restrictions to the use of this function:
1. The EclFile instance must have been created with the
optional read_only flag set to False.
2. You can only modify the content of the keyword; if you
try to modify the header in any way (i.e. size, datatype
or name) the function will fail.
3. The keyword you are trying to save must be exactly the
keyword you got from this EclFile instance, otherwise the
function will fail.
"""
if self._writable( ):
self._save_kw( kw )
else:
raise IOError('save_kw: the file "%s" has been opened read only.' % self.getFilename( ))
def __len__(self):
return len(self.global_view)
def close(self):
if self:
self._close( )
self._invalidateCPointer( )
def free(self):
self.close()
def block_view(self, kw, kw_index):
if not kw in self:
raise KeyError('No such keyword "%s".' % kw)
ls = self.global_view.numKeywords(kw)
idx = kw_index
if idx < 0:
idx += ls
if 0 <= idx < ls:
return self.global_view.blockView(kw, idx)
raise IndexError('Index out of range, must be in [0, %d), was %d.' % (ls, kw_index))
def block_view2(self, start_kw, stop_kw, start_index):
return self.global_view.blockView2( start_kw , stop_kw, start_index )
def restart_view(self, seqnum_index=None, report_step=None, sim_time=None, sim_days=None):
return self.global_view.restartView( seqnum_index, report_step , sim_time, sim_days )
def select_block(self, kw, kw_index):
raise NotImplementedError("The select_block implementation has been removed - use EclFileView")
def select_global( self ):
raise NotImplementedError("The select_global implementation has been removed - use EclFileView")
def select_restart_section( self, index = None , report_step = None , sim_time = None):
raise NotImplementedError("The select_restart_section implementation has been removed - use EclFileView")
"""
Will select a restart section as the active section.
You must specify a report step with the @report_step argument,
a true time with the @sim_time argument or a plain index to
select restart block. If none of arguments are given exception
TypeError will be raised. If present the @sim_time argument
should be a datetime instance.
If the restart section you ask for can not be found the method
will raise a ValueError exeception. To protect against this
you can query first with the has_report_step(),
has_sim_time() or num_report_steps() methods.
This method should be used when you have already loaded the
complete file; if you only want to load a section from the
file you can use the classmethod restart_block().
The method will return 'self' which can be used to aid
readability.
"""
def select_last_restart( self ):
raise NotImplementedError("The select_restart_section implementation has been removed - use EclFileView")
"""
Will select the last SEQNUM block in restart file.
Works by searching for the last SEQNUM keyword; the SEQNUM
Keywords are only present in unified restart files. If this
is a non-unified restart file (or not a restart file at all),
the method will do nothing and return False.
"""
def __getitem__(self , index):
"""
Implements [] operator; index can be integer or key.
Will look up EclKW instances from the current EclFile
instance. The @index argument can either be an integer, in
which case the method will return EclKW number @index, or
alternatively a keyword string, in which case the method will
return a list of EclKW instances with that keyword:
restart_file = ecl_file.EclFile("ECLIPSE.UNRST")
kw9 = restart_file[9]
swat_list = restart_file["SWAT"]
The keyword based lookup can be combined with an extra [] to
get EclKW instance nr:
swat9 = restart_file["SWAT"][9]
Will return the 10'th SWAT keyword from the restart file. The
following example will iterate over all the SWAT keywords in a
restart file:
restart_file = ecl_file.EclFile("ECLIPSE.UNRST")
for swat in restart_file["SWAT"]:
....
"""
if isinstance(index, int):
ls = len(self)
idx = index
if idx < 0:
idx += ls
if 0 <= idx < ls:
return self.global_view[idx]
else:
raise IndexError('Index must be in [0, %d), was: %d.' % (ls, index))
return self.global_view[index]
def iget_kw( self , index , copy = False):
"""
Will return EclKW instance nr @index.
In the files loaded with the EclFile implementation the
ECLIPSE keywords come sequentially in a long series, an INIT
file might have the following keywords:
INTEHEAD
LOGIHEAD
DOUBHEAD
PORV
DX
DY
DZ
PERMX
PERMY
PERMZ
MULTX
MULTY
.....
The iget_kw() method will give you a EclKW reference to
keyword nr @index. This functionality is also available
through the index operator []:
file = EclFile( "ECLIPSE.INIT" )
permx = file.iget_kw( 7 )
permz = file[ 9 ]
Observe that the returned EclKW instance is only a reference
to the data owned by the EclFile instance.
The method iget_named_kw() which lets you specify the name of
the keyword you are interested in is in general more useful
than this method.
"""
kw = self[index]
if copy:
return EclKW.copy( kw )
else:
return kw
def iget_named_kw( self , kw_name , index , copy = False):
return self.global_view.iget_named_kw( kw_name , index )
def restart_get_kw( self , kw_name , dtime , copy = False):
"""Will return EclKW @kw_name from restart file at time @dtime.
This function assumes that the current EclFile instance
represents a restart file. It will then look for keyword
@kw_name exactly at the time @dtime; @dtime is a datetime
instance:
file = EclFile( "ECLIPSE.UNRST" )
swat2010 = file.restart_get_kw( "SWAT" , datetime.datetime( 2000 , 1 , 1 ))
By default the returned kw instance is a reference to the
ecl_kw still contained in the EclFile instance; i.e. the kw
will become a dangling reference if the EclFile instance goes
out of scope. If the optional argument @copy is True the
returned kw will be a true copy.
If the file does not have the keyword at the specified time
the function will raise IndexError(); if the file does not
have the keyword at all - KeyError will be raised.
"""
index = self._get_restart_index( CTime( dtime ) )
if index >= 0:
if self.num_named_kw(kw_name) > index:
kw = self.iget_named_kw( kw_name , index )
if copy:
return EclKW.copy( kw )
else:
return kw
else:
if self.has_kw(kw_name):
raise IndexError('Does not have keyword "%s" at time:%s.' % (kw_name , dtime))
else:
raise KeyError('Keyword "%s" not recognized.' % kw_name)
else:
raise IndexError('Does not have keyword "%s" at time:%s.' % (kw_name , dtime))
def replace_kw( self , old_kw , new_kw):
"""
Will replace @old_kw with @new_kw in current EclFile instance.
This method can be used to replace one of the EclKW instances
in the current EclFile. The @old_kw reference must be to the
actual EclKW instance in the current EclFile instance (the
final comparison is based on C pointer equality!), i.e. it
must be a reference (not a copy) from one of the ??get_kw??
methods of the EclFile class. In the example below we replace
the SWAT keyword from a restart file:
swat = file.iget_named_kw( "SWAT" , 0 )
new_swat = swat * 0.25
file.replace_kw( swat , new_swat )
The C-level ecl_file_type structure takes full ownership of
all installed ecl_kw instances; mixing the garbage collector
into it means that this is quite low level - and potentially
dangerous!
"""
# We ensure that this scope owns the new_kw instance; the
# new_kw will be handed over to the ecl_file instance, and we
# can not give away something we do not alreeady own.
if not new_kw.data_owner:
new_kw = EclKW.copy( new_kw )
# The ecl_file instance will take responsability for freeing
# this ecl_kw instance.
new_kw.data_owner = False
self._replace_kw( old_kw , new_kw , False )
@property
def size(self):
"""
The number of keywords in the current EclFile object.
"""
return len(self)
@property
def unique_size( self ):
"""
The number of unique keyword (names) in the current EclFile object.
"""
return self.global_view.uniqueSize( )
def keys(self):
"""
Will return a list of unique kw names - like keys() on a dict.
"""
header_dict = {}
for index in range(len(self)):
kw = self[index]
header_dict[ kw.getName() ] = True
return header_dict.keys()
@property
def headers(self):
"""
Will return a list of the headers of all the keywords.
"""
header_list = []
for index in range(self.size):
kw = self[index]
header_list.append( kw.header )
return header_list
@property
def report_steps( self ):
"""
Will return a list of all report steps.
The method works by iterating through the whole restart file
looking for 'SEQNUM' keywords; if the current EclFile instance
is not a restart file it will not contain any 'SEQNUM'
keywords and the method will simply return an empty list.
"""
steps = []
seqnum_list = self["SEQNUM"]
for kw in self["SEQNUM"]:
steps.append( kw[0] )
return steps
@property
def report_dates( self ):
"""
Will return a list of the dates for all report steps.
The method works by iterating through the whole restart file
looking for 'SEQNUM/INTEHEAD' keywords; the method can
probably be tricked by other file types also containing an
INTEHEAD keyword.
"""
if self.has_kw('SEQNUM'):
dates = []
for index in range( self.num_named_kw( 'SEQNUM' )):
dates.append( self.iget_restart_sim_time( index ))
return dates
elif 'INTEHEAD' in self:
# This is a uber-hack; should export the ecl_rsthead
# object as ctypes structure.
intehead = self["INTEHEAD"][0]
year = intehead[66]
month = intehead[65]
day = intehead[64]
date = datetime.datetime( year , month , day )
return [ date ]
return None
@property
def dates( self ):
"""
Will return a list of the dates for all report steps.
"""
return self.report_dates
def num_named_kw( self , kw):
"""
The number of keywords with name == @kw in the current EclFile object.
"""
return self.global_view.numKeywords( kw )
def has_kw( self , kw , num = 0):
"""
Check if current EclFile instance has a keyword @kw.
If the optional argument @num is given it will check if the
EclFile has at least @num occurences of @kw.
"""
return self.num_named_kw( kw ) > num
def __contains__(self , kw):
"""
Check if the current file contains keyword @kw.
"""
return self.has_kw( kw )
def has_report_step( self , report_step ):
"""
Checks if the current EclFile has report step @report_step.
If the EclFile in question is not a restart file, you will
just get False. If you want to check if the file contains the
actual report_step before loading the file, you should use the
classmethod contains_report_step() instead.
"""
return self._has_report_step( report_step )
def num_report_steps( self ):
"""
Returns the total number of report steps in the restart file.
Works by counting the number of 'SEQNUM' instances, and will
happily return 0 for a non-restart file. Observe that the
report_steps present in a unified restart file are in general
not consecutive, i.e. the last report step will typically be
much higher than the return value from this function.
"""
return len( self["SEQNUM"] )
def has_sim_time( self , dtime ):
"""
Checks if the current EclFile has data for time @dtime.
The implementation goes through all the INTEHEAD headers in
the EclFile, i.e. it can be fooled (and probably crash and
burn) if the EclFile instance in question is has INTEHEAD
keyword(s), but is still not a restart file. The @dtime
argument should be a normal python datetime instance.
"""
return self._has_sim_time( CTime(dtime) )
def iget_restart_sim_time( self , index ):
"""
Will locate restart block nr @index and return the true time
as a datetime instance.
"""
ct = CTime(self._iget_restart_time( index ))
return ct.datetime()
def iget_restart_sim_days( self , index ):
"""
Will locate restart block nr @index and return the number of days
(in METRIC at least ...) since the simulation started.
"""
return self._iget_restart_days( index )
def get_filename(self):
"""
Name of the file currently loaded.
"""
fn = self._get_src_file()
return str(fn) if fn else ''
def fwrite( self , fortio ):
"""
Will write current EclFile instance to fortio stream.
ECLIPSE is written in Fortran; and a "special" handle for
Fortran IO must be used when reading and writing these files.
This method will write the current EclFile instance to a
FortIO stream already opened for writing:
import ecl.ecl.ecl as ecl
...
fortio = ecl.FortIO( "FILE.XX" )
file.fwrite( fortio )
fortio.close()
"""
self._fwrite( fortio , 0 )
def write_index(self, index_file_name):
if not self._write_index(index_file_name):
raise IOError("Failed to write index file:%s" % index_file_name)
class EclFileContextManager(object):
def __init__(self , ecl_file):
self.__ecl_file = ecl_file
def __enter__(self):
return self.__ecl_file
def __exit__(self, exc_type, exc_val, exc_tb):
self.__ecl_file.close()
return False
def openEclFile( file_name , flags = 0):
print('The function openEclFile is deprecated, use open_ecl_file.')
return open_ecl_file(file_name, flags)
def open_ecl_file(file_name, flags=0):
return EclFileContextManager(EclFile(file_name, flags))
monkey_the_camel(EclFile, 'getFileType', EclFile.get_filetype, staticmethod)
monkey_the_camel(EclFile, 'blockView', EclFile.block_view)
monkey_the_camel(EclFile, 'blockView2', EclFile.block_view2)
monkey_the_camel(EclFile, 'restartView', EclFile.restart_view)
monkey_the_camel(EclFile, 'getFilename', EclFile.get_filename)

View File

@@ -0,0 +1,200 @@
# Copyright (C) 2017 Statoil ASA, Norway.
#
# This file is part of ERT - Ensemble based Reservoir Tool.
#
# ERT 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.
#
# ERT 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 at <http://www.gnu.org/licenses/gpl.html>
# for more details.
from __future__ import absolute_import, division, print_function, unicode_literals
from six import string_types
from cwrap import BaseCClass
from ecl.util.util import monkey_the_camel
from ecl.util.util import CTime
from ecl import EclPrototype
class EclFileView(BaseCClass):
TYPE_NAME = "ecl_file_view"
_iget_kw = EclPrototype("ecl_kw_ref ecl_file_view_iget_kw( ecl_file_view , int)")
_iget_named_kw = EclPrototype("ecl_kw_ref ecl_file_view_iget_named_kw( ecl_file_view , char* , int)")
_get_size = EclPrototype("int ecl_file_view_get_size( ecl_file_view )")
_get_num_named_kw = EclPrototype("int ecl_file_view_get_num_named_kw( ecl_file_view , char* )")
_get_unique_size = EclPrototype("int ecl_file_view_get_num_distinct_kw( ecl_file_view )")
_create_block_view = EclPrototype("ecl_file_view_ref ecl_file_view_add_blockview( ecl_file_view , char*, int )")
_create_block_view2 = EclPrototype("ecl_file_view_ref ecl_file_view_add_blockview2( ecl_file_view , char*, char*, int )")
_restart_view = EclPrototype("ecl_file_view_ref ecl_file_view_add_restart_view( ecl_file_view , int, int, time_t, double )")
def __init__(self):
raise NotImplementedError("Can not instantiate directly")
def __iget(self, index):
return self._iget_kw(index).setParent(parent=self)
def __repr__(self):
return 'EclFileView(size=%d) %s' % (len(self), self._ad_str())
def iget_named_kw(self, kw_name, index):
if not kw_name in self:
raise KeyError("No such keyword: %s" % kw_name)
if index >= self.numKeywords(kw_name):
raise IndexError("Too large index: %d" % index)
return self._iget_named_kw(kw_name, index).setParent(parent=self)
def __getitem__(self, index):
"""
Implements [] operator; index can be integer or key.
Will look up EclKW instances from the current EclFile
instance. The @index argument can either be an integer, in
which case the method will return EclKW number @index, or
alternatively a keyword string, in which case the method will
return a list of EclKW instances with that keyword:
restart_file = ecl_file.EclFile("ECLIPSE.UNRST")
kw9 = restart_file[9]
swat_list = restart_file["SWAT"]
The keyword based lookup can be combined with an extra [] to
get EclKW instance nr:
swat9 = restart_file["SWAT"][9]
Will return the 10'th SWAT keyword from the restart file. The
following example will iterate over all the SWAT keywords in a
restart file:
restart_file = ecl_file.EclFile("ECLIPSE.UNRST")
for swat in restart_file["SWAT"]:
....
"""
if isinstance(index, int):
ls = len(self)
idx = index
if idx < 0:
idx += ls
if 0 <= idx < ls:
return self.__iget(idx)
else:
raise IndexError('Index must be in [0, %d), was: %d.' % (ls, index))
if isinstance(index, slice):
indices = index.indices(len(self))
kw_list = []
for i in range(*indices):
kw_list.append(self[i])
return kw_list
else:
if isinstance(index, bytes):
index = index.decode('ascii')
if isinstance(index, string_types):
if index in self:
kw_index = index
kw_list = []
for index in range(self.numKeywords(kw_index)):
kw_list.append( self.iget_named_kw(kw_index, index))
return kw_list
else:
raise KeyError("Unrecognized keyword:\'%s\'" % index)
else:
raise TypeError("Index must be integer or string (keyword)")
def __len__(self):
return self._get_size()
def __contains__(self, kw):
if self.numKeywords(kw) > 0:
return True
else:
return False
def num_keywords(self, kw):
return self._get_num_named_kw(kw)
def unique_size(self):
return self._get_unique_size()
def block_view2(self, start_kw, stop_kw, start_index):
idx = start_index
if start_kw:
if not start_kw in self:
raise KeyError("The keyword:%s is not in file" % start_kw)
ls = self.numKeywords(start_kw)
if idx < 0:
idx += ls
if not (0 <= idx < ls):
raise IndexError('Index must be in [0, %d), was: %d.' % (ls, start_index))
if stop_kw:
if not stop_kw in self:
raise KeyError("The keyword:%s is not in file" % stop_kw)
view = self._create_block_view2(start_kw, stop_kw, idx)
view.setParent(parent=self)
return view
def block_view(self, kw, kw_index):
num = self.numKeywords(kw)
if num == 0:
raise KeyError("Unknown keyword: %s" % kw)
idx = kw_index
if idx < 0:
idx += num
if not (0 <= idx < num):
raise IndexError('Index must be in [0, %d), was: %d.' % (num, kw_index))
view = self._create_block_view(kw, kw_index)
view.setParent(parent=self)
return view
def restart_view(self, seqnum_index=None, report_step=None, sim_time=None, sim_days=None):
if report_step is None:
report_step = -1
if sim_time is None:
sim_time = -1
if sim_days is None:
sim_days = -1
if seqnum_index is None:
seqnum_index = -1
view = self._restart_view(seqnum_index, report_step, CTime(sim_time), sim_days)
if view is None:
raise ValueError("No such restart block could be identiefied")
view.setParent(parent=self)
return view
monkey_the_camel(EclFileView, 'numKeywords', EclFileView.num_keywords)
monkey_the_camel(EclFileView, 'uniqueSize', EclFileView.unique_size)
monkey_the_camel(EclFileView, 'blockView2', EclFileView.block_view2)
monkey_the_camel(EclFileView, 'blockView', EclFileView.block_view)
monkey_the_camel(EclFileView, 'restartView', EclFileView.restart_view)

View File

@@ -0,0 +1,30 @@
# Copyright (C) 2015 Statoil ASA, Norway.
#
# The file 'ecl_init_file.py' is part of ERT - Ensemble based Reservoir Tool.
#
# ERT 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.
#
# ERT 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 at <http://www.gnu.org/licenses/gpl.html>
# for more details.
from ecl import EclFileEnum
from ecl.eclfile import EclFile, Ecl3DFile
class EclInitFile(Ecl3DFile):
def __init__(self, grid, filename, flags=0):
file_type, report_step, fmt_file = EclFile.getFileType(filename)
if file_type == EclFileEnum.ECL_INIT_FILE:
super(EclInitFile, self).__init__(grid, filename, flags)
else:
err = 'The input filename "%s" does not correspond to a restart file.'
err += ' Please follow the Eclipse naming conventions.'
raise ValueError(err % filename)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,159 @@
# Copyright (C) 2015 Statoil ASA, Norway.
#
# The file 'ecl_restart_file.py' is part of ERT - Ensemble based Reservoir Tool.
#
# ERT 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.
#
# ERT 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 at <http://www.gnu.org/licenses/gpl.html>
# for more details.
from cwrap import BaseCClass
from ecl import EclPrototype
from ecl.util.util import monkey_the_camel
from ecl.util.util import CTime
from ecl import EclFileEnum
from ecl.eclfile import EclFile, Ecl3DFile, Ecl3DKW
class EclRestartHead(BaseCClass):
TYPE_NAME = "ecl_rsthead"
_alloc = EclPrototype("void* ecl_rsthead_alloc(ecl_file_view , int )", bind = False)
_alloc_from_kw = EclPrototype("void* ecl_rsthead_alloc_from_kw(int , ecl_kw , ecl_kw , ecl_kw )", bind = False)
_free = EclPrototype("void ecl_rsthead_free(ecl_rsthead)")
_get_report_step = EclPrototype("int ecl_rsthead_get_report_step(ecl_rsthead)")
_get_sim_time = EclPrototype("time_t ecl_rsthead_get_sim_time(ecl_rsthead)")
_get_sim_days = EclPrototype("double ecl_rsthead_get_sim_days(ecl_rsthead)")
_get_nxconz = EclPrototype("int ecl_rsthead_get_nxconz(ecl_rsthead)")
_get_ncwmax = EclPrototype("int ecl_rsthead_get_ncwmax(ecl_rsthead)")
def __init__(self , kw_arg = None , rst_view = None):
if kw_arg is None and rst_view is None:
raise ValueError('Cannot construct EclRestartHead without one of kw_arg and rst_view, both were None!')
if not kw_arg is None:
report_step , intehead_kw , doubhead_kw , logihead_kw = kw_arg
c_ptr = self._alloc_from_kw( report_step , intehead_kw , doubhead_kw , logihead_kw )
else:
c_ptr = self._alloc( rst_view , -1 )
super(EclRestartHead, self).__init__(c_ptr)
def free(self):
self._free( )
def get_report_step(self):
return self._get_report_step( )
def get_sim_date(self):
ct = CTime( self._get_sim_time( ) )
return ct.datetime( )
def get_sim_days(self):
return self._get_sim_days( )
def well_details(self):
return {"NXCONZ" : self._get_nxconz(),
"NCWMAX" : self._get_ncwmax()}
class EclRestartFile(Ecl3DFile):
def __init__(self , grid , filename , flags = 0):
"""Will open an Eclipse restart file.
The EclRestartFile class will open an eclipse restart file, in
unified or non unified format. The constructor will infer the
file type based on the filename, and will raise a ValueError
exception if the file type is not ECL_RESTART_FILE or
ECL_UNIFIED_RESTART_FILE.
The EclRestartFile will use a grid reference to create Ecl3DKw
instances for all the keyword elements which have either
'nactive' or 'nx*ny*nz' elements.
"""
file_type , report_step , fmt_file = EclFile.getFileType( filename )
if not file_type in [EclFileEnum.ECL_RESTART_FILE, EclFileEnum.ECL_UNIFIED_RESTART_FILE]:
raise ValueError('The input filename "%s" does not correspond to a restart file. Please follow the Eclipse naming conventions'
% filename)
super(EclRestartFile , self).__init__( grid, filename , flags)
self.rst_headers = None
if file_type == EclFileEnum.ECL_RESTART_FILE:
self.is_unified = False
self.report_step = report_step
else:
self.is_unified = True
def unified(self):
"""
Will return True if the file we have opened is unified.
"""
return self.is_unified
def assert_headers(self):
if self.rst_headers is None:
self.rst_headers = []
if self.unified():
for index in range(self.num_named_kw("SEQNUM")):
self.rst_headers.append( EclRestartHead( rst_view = self.restartView( seqnum_index = index )))
else:
intehead_kw = self["INTEHEAD"][0]
doubhead_kw = self["DOUBHEAD"][0]
if "LOGIHEAD" in self:
logihead_kw = self["LOGIHEAD"][0]
else:
logihead_kw = None
self.rst_headers.append( EclRestartHead( kw_arg = (self.report_step , intehead_kw , doubhead_kw , logihead_kw) ))
def time_list(self):
"""Will return a list of report_step, simulation time and days.
The return value will be a list tuples. For a unified restart
file with the three report steps {10,15,20} it can look like:
[ (10, datetime.datetime( 2010 , 1 , 1 , 0 , 0 , 0 ) , 100.0),
(15, datetime.datetime( 2010 , 3 , 1 , 0 , 0 , 0 ) , 160.0),
(20, datetime.datetime( 2010 , 5 , 1 , 0 , 0 , 0 ) , 220.0) ]
For a non-unified restart file the list will have only one element.
"""
self.assertHeaders()
time_list = []
for header in self.rst_headers:
time_list.append( (header.getReportStep() , header.getSimDate( ) , header.getSimDays( )) )
return time_list
def headers(self):
self.assertHeaders()
return self.rst_headers
def get_header(self, index):
self.assertHeaders()
return self.rst_headers[index]
monkey_the_camel(EclRestartHead, 'getReportStep', EclRestartHead.get_report_step)
monkey_the_camel(EclRestartHead, 'getSimDate', EclRestartHead.get_sim_date)
monkey_the_camel(EclRestartHead, 'getSimDays', EclRestartHead.get_sim_days)
monkey_the_camel(EclRestartFile, 'assertHeaders', EclRestartFile.assert_headers)
monkey_the_camel(EclRestartFile, 'timeList', EclRestartFile.time_list)

View File

@@ -0,0 +1,211 @@
# Copyright (C) 2011 Statoil ASA, Norway.
#
# The file 'fortio.py' is part of ERT - Ensemble based Reservoir Tool.
#
# ERT 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.
#
# ERT 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 at <http://www.gnu.org/licenses/gpl.html>
# for more details.
"""
Module to support transparent binary IO of Fortran created files.
Fortran is a a funny language; when writing binary blobs of data to
file the Fortran runtime will silently add a header and footer around
the date. The Fortran code:
integer array(100)
write(unit) array
it actually writes a head and tail in addition to the actual
data. The header and tail is a 4 byte integer, which value is the
number of bytes in the immediately following record. I.e. what is
actually found on disk after the Fortran code above is:
| 400 | array ...... | 400 |
The fortio.c file implements the fortio_type C structure which can be
used to read and write these structures transparently. The current
python module is a minimal wrapping of this datastructure; mainly to
support passing of FortIO handles to the underlying C functions. A
more extensive wrapping of the fortio implementation would be easy.
"""
import ctypes
import os
from cwrap import BaseCClass
from ecl.util.util import monkey_the_camel
from ecl import EclPrototype
class FortIO(BaseCClass):
TYPE_NAME = "fortio"
READ_MODE = 1
WRITE_MODE = 2
READ_AND_WRITE_MODE = 3
APPEND_MODE = 4
_open_reader = EclPrototype("void* fortio_open_reader(char*, bool, bool)", bind=False)
_open_writer = EclPrototype("void* fortio_open_writer(char*, bool, bool)", bind=False)
_open_readwrite = EclPrototype("void* fortio_open_readwrite(char*, bool, bool)", bind=False)
_open_append = EclPrototype("void* fortio_open_append(char*, bool, bool)", bind=False)
_guess_fortran = EclPrototype("bool fortio_looks_like_fortran_file(char*, bool)", bind=False)
_write_record = EclPrototype("void fortio_fwrite_record(fortio, char*, int)")
_get_position = EclPrototype("long fortio_ftell(fortio)")
_seek = EclPrototype("void fortio_fseek(fortio, long, int)")
_close = EclPrototype("bool fortio_fclose(fortio)")
_truncate = EclPrototype("bool fortio_ftruncate(fortio, long)")
_filename = EclPrototype("char* fortio_filename_ref(fortio)")
def __init__(self, file_name, mode=READ_MODE, fmt_file=False, endian_flip_header=True):
"""Will open a new FortIO handle to @file_name - default for reading.
The newly created FortIO handle will open the underlying FILE*
for reading, but if you pass the flag mode=FortIO.WRITE_MODE
the file will be opened for writing.
Observe that the flag @endian_flip_header will only affect the
interpretation of the block size markers in the file, endian
flipping of the actual data blocks must be handled at a higher
level.
When you are finished working with the FortIO instance you can
manually close it with the close() method, alternatively that
will happen automagically when it goes out of scope.
Small example script opening a restart file, and then writing
all the pressure keywords to another file:
import sys
from ecl.ecl import FortIO, EclFile
rst_file = EclFile(sys.argv[1])
fortio = FortIO("PRESSURE", mode=FortIO.WRITE_MODE)
for kw in rst_file:
if kw.name() == "PRESSURE":
kw.write(fortio)
fortio.close()
See the documentation of openFortIO() for an alternative
method based on a context manager and the with statement.
"""
read_modes = (FortIO.READ_MODE, FortIO.APPEND_MODE, FortIO.READ_AND_WRITE_MODE)
if mode in read_modes and not os.path.exists(file_name):
raise IOError('No such file "%s".' % file_name)
if mode == FortIO.READ_MODE:
c_pointer = self._open_reader(file_name, fmt_file, endian_flip_header)
elif mode == FortIO.WRITE_MODE:
c_pointer = self._open_writer(file_name, fmt_file, endian_flip_header)
elif mode == FortIO.READ_AND_WRITE_MODE:
c_pointer = self._open_readwrite(file_name, fmt_file, endian_flip_header)
elif mode == FortIO.APPEND_MODE:
c_pointer = self._open_append(file_name, fmt_file, endian_flip_header)
else:
raise UserWarning("Unknown mode: %d" % mode)
self.__mode = mode
if not c_pointer:
raise IOError('Failed to open FortIO file "%s".' % file_name)
super(FortIO, self).__init__(c_pointer)
def close(self):
if self:
self._close()
self._invalidateCPointer()
def get_position(self):
""" @rtype: long """
return self._get_position()
def truncate(self, size=None):
"""Will truncate the file to new size.
If the method is called without a size argument the stream
will be truncated to the current position.
"""
if size is None:
size = self.getPosition()
if not self._truncate(size):
raise IOError("Truncate of fortran filehandle:%s failed" % self.filename())
def filename(self):
return self._filename()
def seek(self, position, whence=0):
# SEEK_SET = 0
# SEEK_CUR = 1
# SEEK_END = 2
self._seek(position, whence)
@classmethod
def is_fortran_file(cls, filename, endian_flip=True):
"""@rtype: bool
@type filename: str
Will use heuristics to try to guess if @filename is a binary
file written in fortran style. ASCII files will return false,
even if they are structured as ECLIPSE keywords.
"""
return cls._guess_fortran(filename, endian_flip)
def free(self):
self.close()
class FortIOContextManager(object):
def __init__(self, fortio):
self.__fortio = fortio
def __enter__(self):
return self.__fortio
def __exit__(self, exc_type, exc_val, exc_tb):
self.__fortio.close()
return exc_type is not None
def openFortIO(file_name, mode=FortIO.READ_MODE, fmt_file=False, endian_flip_header=True):
"""Will create FortIO based context manager for use with with.
The with: statement and context managers is a good alternative in
the situation where you need to ensure resource cleanup.
import sys
from ecl.ecl import FortIO, EclFile
rst_file = EclFile(sys.argv[1])
with openFortIO("PRESSURE", mode=FortIO.WRITE_MODE) as fortio:
for kw in rst_file:
if kw.name() == "PRESSURE":
kw.write(fortio)
"""
return FortIOContextManager(FortIO(file_name, mode=mode, fmt_file=fmt_file,
endian_flip_header=endian_flip_header))
monkey_the_camel(FortIO, 'getPosition', FortIO.get_position)
monkey_the_camel(FortIO, 'isFortranFile', FortIO.is_fortran_file, classmethod)

View File

@@ -0,0 +1,9 @@
set(PYTHON_SOURCES
__init__.py
ecl_grav.py
ecl_grav_calc.py
ecl_subsidence.py
)
add_python_package("python.ecl.gravimetry" ${PYTHON_INSTALL_PREFIX}/ecl/gravimetry "${PYTHON_SOURCES}" True)

Some files were not shown because too many files have changed in this diff Show More