(#613) Updated ERT

Updated ERT to 9eb4c76cb930450c35e6d44d479da1141e296c7a of the
release/2015.10 branch
This commit is contained in:
Magne Sjaastad 2015-10-30 09:43:10 +01:00
parent 1b419f3098
commit aabd5c6cf7
399 changed files with 9556 additions and 19926 deletions

View File

@ -22,4 +22,5 @@ devel/python/lib64
scratch.sparsebundle
*.iml
*.DS_Store
__ert_lib_path.py

38
ThirdParty/Ert/.travis.yml vendored Normal file
View File

@ -0,0 +1,38 @@
language: python
python:
- 2.7_with_system_site_packages
compiler:
- gcc
addons:
apt:
packages:
- liblapack-dev
- texlive-latex-base
- valgrind
- python-qt4
- python-qt4-gl
before_install:
- wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh
- chmod +x miniconda.sh
- ./miniconda.sh -b
- export PATH=/home/travis/miniconda/bin:$PATH
- conda update --yes conda
install:
- conda install --yes numpy scipy matplotlib pandas pyopengl sphinx
before_script:
- sudo apt-get install libplplot-dev
- sudo apt-get install python-tk
- mkdir build
- cd build
- echo "WORKFLOW_JOB_DIRECTORY ../devel/share/workflows/jobs/internal/config" > DEFAULT_SITE_CONFIG_FILE
- echo "WORKFLOW_JOB_DIRECTORY ../devel/share/workflows/jobs/internal-gui/config" >> DEFAULT_SITE_CONFIG_FILE
- echo "JOB_SCRIPT ../devel/share/bin/job_dispatch.py" >> DEFAULT_SITE_CONFIG_FILE
- cmake -DPYTHON_INSTALL_PREFIX=python -DBUILD_ERT=ON -DERT_BUILD_GUI=ON -DBUILD_ENS_PLOT=ON -DBUILD_TESTS=ON -DBUILD_APPLICATIONS=ON -DUSE_RUNPATH=ON -DBUILD_PYTHON=ON -DERT_USE_OPENMP=ON -DERT_DOC=ON -DSITE_CONFIG_FILE=DEFAULT_SITE_CONFIG_FILE ../devel
script: make && ctest --output-on-failure -LE StatoilData

View File

@ -22,7 +22,7 @@ option( BUILD_ENS_PLOT "Build small Eclipse plotting program - no" OFF)
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_PYTHON "Run py_compile on the python wrappers" OFF)
option( BUILD_PYTHON "Run py_compile on the python wrappers" ON)
option( BUILD_SHARED_LIBS "Build shared libraries" ON )
option( INSTALL_ERT "Should anything be installed when issuing make install?" ON)
option( ERT_BUILD_GUI "Should the pyQt based gui be compiled and installed" OFF )
@ -84,8 +84,8 @@ if (ERT_USE_OPENMP)
endif()
include(cmake/ert_check.cmake)
include(cmake/ert_find.cmake)
include(cmake/ert_check.cmake)
include(cmake/Modules/UseMultiArch.cmake)
include(cmake/ert_link.cmake)
@ -207,10 +207,14 @@ endif()
if (BUILD_PYTHON)
include(cmake/python.cmake2)
add_subdirectory( python )
if(ERT_DOC)
add_subdirectory( docs )
if (ERT_WINDOWS)
message(STATUS "Python is not supported on Windows")
else()
include(cmake/python.cmake2)
add_subdirectory( python )
if(ERT_DOC)
add_subdirectory( docs )
endif()
endif()
endif()

View File

@ -1,3 +1,5 @@
include(CheckSymbolExists)
check_function_exists( fseeko HAVE_FSEEKO )
if (HAVE_HFSEEKO)
add_definitions( -DHAVE_FSEEKO )
@ -110,6 +112,17 @@ if (HAVE__USLEEP)
add_definitions( -DHAVE__USLEEP )
endif()
check_symbol_exists(_tzname time.h HAVE_WINDOWS_TZNAME)
if (HAVE_WINDOWS_TZNAME)
add_definitions(-DHAVE_WINDOWS_TZNAME)
else()
check_symbol_exists(tzname time.h HAVE_TZNAME)
if (HAVE_TZNAME)
add_definitions(-DHAVE_TZNAME)
else()
message(FATAL_ERROR "Could not find tzname global variable")
endif()
endif()
check_function_exists(pthread_yield_np HAVE_YIELD_NP)
if (HAVE_YIELD_NP)
@ -122,6 +135,11 @@ if (HAVE_YIELD)
endif()
check_function_exists(pthread_timedjoin_np HAVE_TIMEDJOIN)
if (HAVE_TIMEDJOIN)
add_definitions(-DHAVE_TIMEDJOIN)
endif()
# Checking based on compiling. Some of the code generates warnings, so we just cut down to bare-bone compiler flags.
set( CMAKE_C_FLAGS_main ${CMAKE_C_FLAGS} )

View File

@ -2,7 +2,7 @@ set(NEED_LIBDL OFF)
find_library( DL_LIBRARY NAMES dl )
find_path( DLFUNC_HEADER dlfcn.h )
if (DL_LIBRARY AND DLFUNC_HEADER)
set(CMAKE_REQUIRED_LIBRARIES dl)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl)
check_function_exists( dladdr HAVE_DLADDR )
if (HAVE_DLADDR)
@ -30,6 +30,7 @@ if (PTHREAD_LIBRARY)
if (WITH_PTHREAD)
add_definitions( -DWITH_PTHREAD )
endif()
set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} pthread)
else()
set( WITH_PTHREAD FALSE )
message("pthread library not found - pthread support will not be included")
@ -85,3 +86,7 @@ endif()
if (ERT_WINDOWS)
find_library( SHLWAPI_LIBRARY NAMES Shlwapi )
endif()
if (UNIX)
set (CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} m)
endif(UNIX)

View File

@ -8,7 +8,11 @@ function(add_python_package target package_path source_files install_package)
foreach (file ${source_files} )
set( source_file ${CMAKE_CURRENT_SOURCE_DIR}/${file} )
set( build_file ${PROJECT_BINARY_DIR}/${package_path}/${file} )
set( install_file ${CMAKE_INSTALL_PREFIX}/${package_path}/${file} )
if("$ENV{DESTDIR}" STREQUAL "")
set( install_file ${CMAKE_INSTALL_PREFIX}/${package_path}/${file} )
else()
set( install_file $ENV{DESTDIR}/${CMAKE_INSTALL_PREFIX}/${package_path}/${file} )
endif()
add_custom_command(
OUTPUT ${build_file}

View File

@ -2,7 +2,7 @@ Source: ert.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
iputils-ping, zlib1g-dev, git, python-dev
Standards-Version: 3.9.2
Section: libs
Homepage: http://ert.nr.no
@ -24,3 +24,11 @@ Depends: ${shlibs:Depends}, ${misc:Depends}
Description: The Ensemble based Reservoir Tool
ERT - Ensemble based Reservoir Tool is a tool for managing en ensemble
of reservoir models.
Package: python-ert.ecl
Section: python
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, libert.ecl1
Description: The Ensemble based Reservoir Tool - Python bindings
ERT - Ensemble based Reservoir Tool is a tool for managing en ensemble
of reservoir models.

View File

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

View File

@ -0,0 +1,141 @@
.. toctree::
:maxdepth: 1
.. _prior_distributions:
Prior distributions avaliable in ERT
====================================
The :ref:`GEN_KW <gen_kw>` keyword is typically used in sensitivy
studies and as parameters which are updated with the Ensemble Smoother
in a model updating project. In your configuration file the
:ref:`GEN_KW <gen_kw>` keyword is configured as:
::
GEN_KW ID my_template.txt my_eclipse_include.txt my_priors.txt
The file ``my_priors.txt`` contains the names of the variables
you are considering, and specifies the distribution which should be
used for the initial sampling.
NORMAL
------
To set a normal (Gaussian) prior, use the keyword NORMAL. It takes two
arguments, a mean value and a standard deviation. Thus, the following
example will assign a normal prior with mean 0 and standard deviation
1 to the variable VAR1:
::
VAR1 NORMAL 0 1
LOGNORMAL
---------
A stochastic variable is log normally distributed if the logarithm of
the variable is normally distributed. In other words, if X is normally
distributed, then Y = exp(X) is log normally distributed.
A log normal prior is suited to model positive quanties with a heavy
tail (tendency to take large values). To set a log normal prior, use
the keyword LOGNORMAL. It takes two arguments, the mean and standard
deviation of the *logarithm* of the variable:
::
VAR2 LOGNORMAL 0
TRUNCATED_NORMAL
-----------------
This *TRUNCATED_NORMAL* distribution works as follows:
1. Draw random variable X ~ N(mu,std)
2. Clamp X to the interval [min, max]
This is **not** a proper truncated normal distribution; hence the
clamping to ``[min,max]` should be an exceptional event. To configure
this distribution for a situation with mean 1, standard deviation 0.25
and hard limits 0 and 10:
::
VAR3 TRUNCATED_NORMAL 1 0.25 0 10
UNIFORM
-------
A stochastic variable is uniformly distributed if has a constant
probability density on a closed interval. Thus, the uniform
distribution is completely characterized by it's minimum and maximum
value. To assign a uniform distribution to a variable, use the keyword
UNIFORM, which takes a minimum and a maximum value for a the
variable. Here is an example, which assigns a uniform distribution
between 0 and 1 to a variable ``VAR4``:
::
VAR4 UNIFORM 0 1
It can be shown that among all distributions bounded below by a and
above by b, the uniform distribution with parameters a and b has the
maximal entropy (contains the least information). Thus, the uniform
distribution should be your preferred prior distribution for robust
modeling of bounded variables.
LOGUNIF
-------
A stochastic variable is log uniformly distributed if it's logarithm
is uniformly distributed on the interval [a,b]. To assign a log
uniform distribution to a a variable, use the keyword LOGUNIF, which
takes a minimum and a maximum value for the output variable as
arguments. The example
::
VAR5 LOGUNIF 0.00001 1
will give values in the range [0.00001,1] - with considerably more
weight towards the lower limit. The log uniform distribution is useful
when modeling a bounded positive variable who has most of it's
probability weight towards one of the bounds.
CONST
-----
The keyword CONST is used to assign a Dirac distribution to a
variable, i.e. set it to a constant value. Here is an example of use:
::
CONST 1.0
Priors and transformations
==========================
The Ensemble Smoother method, which ERT uses for updating of
parameters, works with normally distributed variables. So internally
in ERT the interplay between ``GEN_KW`` variables and updates is as
follows:
1. ERT samples a random variable ``x ~ N(0,1)`` - before outputing
to the forward model this is *transformed* to ``y ~ F(Y)`` where
the the distribution ``F(Y)`` is the correct prior distribution.
2. When the prior simulations are complete ERT calculates misfits
between simulated and observed values and *updates* the
parameters; hence the variables ``x`` now represent samples from
a posterior distribution which is Normal with mean and standard
deviation *different from (0,1)*.
The transformation prescribed by ``F(y)`` still "works" - but it no
longer maps to a distribution in the same family as initially
specified by the prior. A consequence of this is that the update
process can *not* give you a posterior with updated parameters in the
same distribution family as the Prior.

View File

@ -10,3 +10,5 @@ Contents:
keywords/index
workflows/index
observations/index
distributions/index
localization/index

View File

@ -767,22 +767,32 @@ The keywords in this section are used to define a parametrization of the ECLIPSE
GEN_KW ID my_template.txt my_eclipse_include.txt my_priors.txt
Here ID is an (arbitrary) unique string, my_template.txt is the name of a template file, my_eclipse_include.txt is the name of the file which is made for each member based on my_template.txt and my_priors.txt is a file containing a list of parametrized keywords and a prior distribution for each. Note that you must manually edit the ECLIPSE data file so that my_eclipse_include.txt is included.
Here ID is an (arbitrary) unique string, my_template.txt is
the name of a template file, my_eclipse_include.txt is the
name of the file which is made for each member based on
my_template.txt and my_priors.txt is a file containing a list
of parametrized keywords and a prior distribution for
each. Note that you must manually edit the ECLIPSE data file
so that my_eclipse_include.txt is included.
Let us consider an example where the GEN_KW parameter type is used to estimate pore volume multipliers. We would then declare a GEN_KW instance in the main enkf configuration file:
Let us consider an example where the GEN_KW parameter type is
used to estimate pore volume multipliers. We would then
declare a GEN_KW instance in the main enkf configuration file:
::
GEN_KW PAR_MULTPV multpv_template.txt multpv.txt multpv_priors.txt
In the GRID or EDIT section of the ECLIPSE data file, we would insert the following include statement:
In the GRID or EDIT section of the ECLIPSE data file, we would
insert the following include statement:
::
INCLUDE
'multpv.txt' /
The template file multpv_template.txt would contain some parametrized ECLIPSE statements:
The template file multpv_template.txt would contain some
parametrized ECLIPSE statements:
::
@ -798,24 +808,37 @@ The keywords in this section are used to define a parametrization of the ECLIPSE
300*<MULTPV_BOX2> /
ENDBOX
Here, <MULTPV_BOX1> and <MULTPV_BOX2> will act as magic strings. Note that the '<' '>' must be present around the magic strings. In this case, the parameter configuration file multpv_priors.txt could look like this:
Here, <MULTPV_BOX1> and <MULTPV_BOX2> will act as magic
strings. Note that the '<' '>' must be present around the
magic strings. In this case, the parameter configuration file
multpv_priors.txt could look like this:
::
MULTPV_BOX2 UNIFORM 0.98 1.03
MULTPV_BOX1 UNIFORM 0.85 1.00
In general, the first keyword on each line in the parameter configuration file defines a key, which when found in the template file enclosed in '<' and '>', is replaced with a value. The rest of the line defines a prior distribution for the key. See Prior distributions available in enkf for a list of available prior distributions.
In general, the first keyword on each line in the parameter
configuration file defines a key, which when found in the
template file enclosed in '<' and '>', is replaced with a
value. The rest of the line defines a prior distribution for
the key. See Prior distributions available in enkf for a list
of available prior distributions.
**Example: Using GEN_KW to estimate fault transmissibility multipliers**
Previously enkf supported a datatype MULTFLT for estimating fault transmissibility multipliers. This has now been depreceated, as the functionality can be easily achieved with the help of GEN_KW. In th enkf config file:
Previously enkf supported a datatype MULTFLT for estimating
fault transmissibility multipliers. This has now been
depreceated, as the functionality can be easily achieved with
the help of GEN_KW. In th enkf config file:
::
GEN_KW MY-FAULTS MULTFLT.tmpl MULTFLT.INC MULTFLT.txt
Here MY-FAULTS is the (arbitrary) key assigned to the fault multiplers, MULTFLT.tmpl is the template file, which can look like this:
Here MY-FAULTS is the (arbitrary) key assigned to the fault
multiplers, MULTFLT.tmpl is the template file, which can look
like this:
::
@ -824,22 +847,38 @@ The keywords in this section are used to define a parametrization of the ECLIPSE
'FAULT2' <FAULT2> /
/
and finally the initial distribution of the parameters FAULT1 and FAULT2 are defined in the file MULTFLT.txt:
and finally the initial distribution of the parameters FAULT1
and FAULT2 are defined in the file MULTFLT.txt:
::
FAULT1 LOGUNIF 0.00001 0.1
FAULT2 UNIFORM 0.00 1.0
The various prior distributions available for the ``GEN_KW``
keyword are here :ref:`prior distributions available in ERT <prior_distributions>`
Loading GEN_KW values from an external file
The default use of the GEN_KW keyword is to let the ERT application sample random values for the elements in the GEN_KW instance, but it is also possible to tell ERT to load a precreated set of data files, this can for instance be used as a component in a experimental design based workflow. When using external files to initialize the GEN_KW instances you supply an extra keyword INIT_FILE:/path/to/priors/files%d which tells where the prior files are:
The default use of the GEN_KW keyword is to let the ERT
application sample random values for the elements in the
GEN_KW instance, but it is also possible to tell ERT to load a
precreated set of data files, this can for instance be used as
a component in a experimental design based workflow. When
using external files to initialize the GEN_KW instances you
supply an extra keyword ``INIT_FILE:/path/to/priors/files%d``
which tells where the prior files are:
::
GEN_KW MY-FAULTS MULTFLT.tmpl MULTFLT.INC MULTFLT.txt INIT_FILES:priors/multflt/faults%d
In the example above you must prepare files priors/multflt/faults0, priors/multflt/faults1, ... priors/multflt/faultsn which ert will load when you initialize the case. The format of the GEN_KW input files can be of two varieties:
In the example above you must prepare files
priors/multflt/faults0, priors/multflt/faults1,
... priors/multflt/faultsn which ert will load when you
initialize the case. The format of the GEN_KW input files can
be of two varieties:
1. The files can be plain ASCII text files with a list of numbers:

View File

@ -0,0 +1,917 @@
Keywords for the local configuration file
=========================================
General overview
----------------
To create a configuration for localization you must "program" your own
configuration file, this file is then loaded from the ert/enkf proper
application. The 'commands' available in the local_config programming
language are listed below.
An alterative way to 'program' the local config commands is by writing a Python script, and invoking it from a workflow.
Not all the commands available from the local config programming are supported for Python scripting.
**Local config ERT script example:**
::
from ert.enkf import ErtScript
from ert.enkf import LocalConfig
class LocalConfigJob(ErtScript):
def run(self):
ert = self.ert()
local_config = ert.getLocalConfig()
# Add your local config commands here
dataset_multflt = local_config.createDataset("DATASET_MULTFLT")
...
# Write to file for debugging
local_config.writeLocalConfigFile("tmp/debug_local_config.txt")
List of keywords
----------------
=========================================================================================== =========================================================== ==============================================================================================================================================
Keyword name ERT script function Purpose
=========================================================================================== =========================================================== ==============================================================================================================================================
:ref:`CREATE_MINISTEP <create_ministep>` createMinistep Creates ministep
:ref:`CREATE_UPDATESTEP <create_updatestep>` createUpdatestep Creates updatestep
:ref:`CREATE_DATASET <create_dataset>` createDataset Creates dataset
:ref:`COPY_DATASET <copy_dataset>` copyDataset Deep copy of dataset
:ref:`CREATE_OBSSET <create_obsset>` createObsdata Creates observation set
:ref:`COPY_OBSSET <copy_obsset>` copyObsdata Deep copy of observation set
:ref:`ATTACH_MINISTEP <attach_ministep>` attachMinistep Attaches ministep to update step
:ref:`ATTACH_DATASET <attach_dataset>` attachDataset Attaches dataset to mini step
:ref:`ATTACH_OBSSET <attach_obsset>` attachObsset Attaches observation set to mini step
:ref:`ADD_DATA <add_data>` addNode Adds data node to dataset
:ref:`DEL_DATA <del_data>` del Deletes observation node from dataset
:ref:`ADD_OBS <add_obs>` addNodeAndRange Adds observation node to observation set
:ref:`DEL_OBS <del_obs>` del Deletes observation node from observation set
:ref:`DATASET_DEL_ALL_DATA <dataset_del_all_data>` clear Delete all the data keys from a dataset
:ref:`ACTIVE_LIST_ADD_DATA_INDEX <active_list_add_data_index>` addActiveIndex Adds data index to the list of active indices
:ref:`ACTIVE_LIST_ADD_OBS_INDEX <active_list_add_obs_index>` addActiveIndex Adds observation index to the list of active indices
:ref:`ACTIVE_LIST_ADD_MANY_DATA_INDEX <active_list_add_many_data_index>` addActiveIndex Adds several data indices to the list of active indices
:ref:`ACTIVE_LIST_ADD_MANY_OBS_INDEX <active_list_add_many_obs_index>` addActiveIndex Adds several observation indinces to the list of active indices
:ref:`INSTALL_DEFAULT_UPDATESTEP <install_default_updatestep>` Installs default update step
:ref:`ADD_FIELD <add_field>` addField Adds field node to dataset
:ref:`LOAD_FILE <load_file>` EclGrid, EclInitFile, Loads eclipse file in restart format
:ref:`CREATE_ECLREGION <create_eclregion>` EclRegion Creates a new region for use when defining active regions for fields
:ref:`ECLREGION_SELECT_ALL <eclregion_select_all>` select_active Selects or deselects cells in a region
:ref:`ECLREGION_SELECT_VALUE_EQUAL <eclregion_select_value_equal>` select_equal Selects or deselects cells in a region equal to given value
:ref:`ECLREGION_SELECT_VALUE_LESS <eclregion_select_value_less>` select_less Selects or deselects cells in a region equal less than a given value
:ref:`ECLREGION_SELECT_VALUE_MORE <eclregion_select_value_more>` select_more Selects or deselects cells in a region equal greater than a given value
:ref:`ECLREGION_SELECT_BOX <eclregion_select_box>` select_box Selects or deselects cells in a box
:ref:`ECLREGION_SELECT_SLICE <eclregion_select_slice>` select_islice, select_jslice, select_kslice Selects or deselects cells in a slice
:ref:`ECLREGION_SELECT_PLANE <eclregion_select_plane>` select_below_plane Selects or deselects cells in a half space defined by a plane
:ref:`ECLREGION_SELECT_IN_POLYGON <eclregion_select_in_polygon>` select_inside_polygon Selects or deselects cells in region inside polygon
:ref:`CREATE_POLYGON <create_polygon>` :ref:`Example <create_polygon>` Creates a geo-polygon based on coordinate list
:ref:`LOAD_POLYGON <load_polygon>` :ref:`Example <load_polygon>` Loads polygon in Irap RMS format from file
:ref:`LOAD_SURFACE <load_surface>` Loads surface in Irap RMS format from file
:ref:`CREATE_SURFACE_REGION <create_surface_region>` Creates region to select or deselect parts of a surface
:ref:`SURFACE_REGION_SELECT_IN_POLYGON <surface_region_select_in_polygon>` Creates region to select or deselect parts of a surface
:ref:`SURFACE_REGION_SELECT_LINE <surface_region_select_line>` Selects or deselects parts of a surface in half space define by a line
:ref:`ADD_DATA_SURFACE <add_data_surface>` Adds surface node to dataset with elements in a surface region
=========================================================================================== =========================================================== ==============================================================================================================================================
.. ###########################################################################################################
.. _create_updatestep:
.. topic:: CREATE_UPDATESTEP
| This function will create a new updatestep with the name 'NAME_OF_UPDATESTEP'. Observe that you must add (at least) one ministep to the updatestep, otherwise it will not be able to do anything.
*Example:*
::
-- Update step in time interval 0->1
CREATE_UPDATESTEP UPDATESTEP_0_1
*Example:*
::
update_step_0_1 = local_config.createUpdatestep("UPDATESTEP_0_1")
.. ###########################################################################################################
.. _create_ministep:
.. topic:: CREATE_MINISTEP
| This function will create a new ministep with the name 'NAME_OF_MINISTEP'. A given OBSSET can be attached to a given ministep.The ministep is then ready for adding data. Before the ministep can be used you must attach it to an updatestep with the ATTACH_MINISTEP command
*Example:*
::
-- Mini step 0 in update step 0->1
CREATE_MINISTEP MINISTEP_0_1_0
*Example:*
::
ministep_0_1_0 = local_config.createMinistep("MINISTEP_0_1_0")
.. ###########################################################################################################
.. _create_dataset:
.. topic:: CREATE_DATASET
| This function will create a new dataset, i.e. a collection of enkf_nodes which should be updated together. Before you can actually use a dataset you must attach it to a ministep with the ATTACH_DATASET command.
*Example:*
::
-- Create a DATASET_MULTFLT dataset
CREATE_DATASET DATASET_MULTFLT
*Example:*
::
dataset_multflt = local_config.createDataset("DATASET_MULTFLT")
.. ###########################################################################################################
.. _copy_dataset:
.. topic:: COPY_DATASET
| Will create a new local_obsset instance which is a copy of the 'SRC_OBSSET'; this is a deep copy where also the lowest level active_list instances are copied, and can then subsequently be updated independently of each other.
*Example:*
::
-- Deep copy DATASET_MULTFLT dataset
COPY_DATASET DATASET_MULTFLT COPY_DATASET_MULTFLT
.. ###########################################################################################################
.. _create_obsset:
.. topic:: CREATE_OBSSET
| This function will create an observation set, i.e. a collection of observation keys which will be used as the observations in one ministep. Before the obsset can be used it must be attached to a ministep with the ATTACH_OBSSET command.
*Example:*
::
-- Create a OBS_WELL obsset
CREATE_OBSSET OBS_WELL
*Example:*
::
obsset_obs_well = local_config.createObsdata("OBS_WELL")
.. ###########################################################################################################
.. _copy_obsset:
.. topic:: COPY_OBSSET
| Will create a new local_obsset instance which is a copy of the 'SRC_OBSSET'; this is a deep copy where also the lowest level active_list instances are copied, and can then subsequently be updated independently of each other.
*Example:*
::
-- Deep copy OBS_WELL observation set
COPY_OBSSET OBS_WELL COPY_OBS_WELL
.. ###########################################################################################################
.. _attach_ministep:
.. topic:: ATTACH_MINISTEP
| This function will attach the ministep 'NAME_OF_MINISTEP' to the updatestep 'NAME_OF_UPDATESTEP'; one ministep can be attached to many updatesteps.
*Example:*
::
-- Attach MINISTEP_0_1_0 to UPDATESTEP_0_1
ATTACH_MINISTEP UPDATESTEP_0_1 MINISTEP_0_1_0
*Example:*
::
update_step_0_1.attachMinistep(ministep_0_1_0)
.. ###########################################################################################################
.. _attach_dataset:
.. topic:: ATTACH_DATASET
| Will attach the dataset 'NAME_OF_DATASET' to the ministep given by 'NAME_OF_MINISTEP'.
*Example:*
::
-- Attach DATASET_MULTFLT to MINISTEP_0_1_0
ATTACH_MINISTEP MINISTEP_0_1_0 DATASET_MULTFLT
*Example:*
::
ministep_0_1_0.attachDataset(dataset_multflt)
.. ###########################################################################################################
.. _attach_obsset:
.. topic:: ATTACH_OBSSET
| Will attach the obsset 'NAME_OF_OBSSET' to the ministep given by 'NAME_OF_MINISTEP'.
*Example:*
::
-- Attach OBS_WELL to MINISTEP_0_1_0
ATTACH_MINISTEP MINISTEP_0_1_0 OBS_WELL
*Example:*
::
ministep_0_1_0.attachObsset(obsset_obs_well)
.. ###########################################################################################################
.. _add_data:
.. topic:: ADD_DATA
| This function will install 'KEY' as one enkf node which should be updated in this dataset. If you do not manipulate the KEY further with the ACTIVE_LIST_ADD_DATA_INDEX function the KEY will be added as 'ALL_ACTIVE', i.e. all elements will be updated.
*Example:*
::
-- Add data node to data set
ADD_DATA DATASET_MULTFLT MULTFLT
*Example:*
::
dataset_multflt.addNode("MULTFLT")
.. ###########################################################################################################
.. _del_data:
.. topic:: DEL_DATA
| This function will delete the data 'KEY' from the dataset 'NAME_OF_DATASET'.
*Example:*
::
-- Delete data node from data set
DEL_DATA DATASET_MULTFLT MULTFLT
*Example:*
::
del dataset_multflt["MULTFLT"]
.. ###########################################################################################################
.. _add_obs:
.. topic:: ADD_OBS
| This function will install the observation 'OBS_KEY' as an observation for this obsset - similarly to the ADD_DATA function.
*Example:*
::
-- Add data node to observation set
ADD_OBS OBS_WELL WOPR:OBS_WELL
*Example:*
::
-- The obsset has a time range
obsset_obs_well.addNodeAndRange("WOPR:OBS_WELL", 0, 1)
.. ###########################################################################################################
.. _del_obs:
.. topic:: DEL_OBS
| This function will delete the obs 'OBS_KEY' from the obsset 'NAME_OF_OBSSET'.
*Example:*
::
-- Delete data node from observation set
DEL_OBS OBS_WELL WOPR:OBS_WELL
*Example:*
::
del obsset_obs_well["WOPR:OBS_WELL"]
.. ###########################################################################################################
.. _dataset_del_all_data:
.. topic:: DATASET_DEL_ALL_DATA
| This function will delete all the data keys from the dataset 'NAME_OF_DATASET'.
*Example:*
::
-- Delete all data nodes from DATASET_MULTFLT
DATASET_DEL_ALL_DATA DATASET_MULTFLT
*Example:*
::
dataset_multflt.clear()
.. ###########################################################################################################
.. _active_list_add_data_index:
.. topic:: ACTIVE_LIST_ADD_DATA_INDEX
| This function will say that the data with name 'DATA_KEY' in dataset with name 'DATASTEP_NAME' should have the index 'INDEX' active.
*Example:*
::
-- Add index 0 from data MULTFLT to dataset DATASET_MULTFLT
ACTIVE_LIST_ADD_DATA_INDEX DATASET_MULTFLT MULTFLT 0
*Example:*
::
active_list = dataset_multflt.getActiveList("MULTFLT")
active_list.addActiveIndex(0);
.. ###########################################################################################################
.. _active_list_add_obs_index:
.. topic:: ACTIVE_LIST_ADD_OBS_INDEX
| This function will say that the observation with name 'OBS_KEY' in obsset with name 'OBSSET_NAME' should have the index 'INDEX' active.
*Example:*
::
-- Add index 0 from data WOPR:OBS_WELL to obsset OBS_WELL
ACTIVE_LIST_ADD_OBS_INDEX OBS_WELL WOPR:OBS_WELL 0
*Example:*
::
active_list = obsset_obs_well.getActiveList("WOPR:OBS_WELL")
active_list.addActiveIndex(0);
.. ###########################################################################################################
.. _active_list_add_many_data_index:
.. topic:: ACTIVE_LIST_ADD_MANY_DATA_INDEX
| This function is similar to ACTIVE_LIST_ADD_DATA_INDEX, but it will add many indices.
*Example:*
::
-- Add indices 0, 1 and 2 from data MULTFLT to dataset DATASET_MULTFLT
ACTIVE_LIST_ADD_MANY_DATA_INDEX DATASET_MULTFLT MULTFLT 0 1 2
.. ###########################################################################################################
.. _active_list_add_many_obs_index:
.. topic:: ACTIVE_LIST_ADD_MANY_OBS_INDEX
| This function is similar to ACTIVE_LIST_ADD_OBS_INDEX, but it will add many indices.
*Example:*
::
-- Add index 0, 1 and 2 from data WOPR:OBS_WELL to obsset OBS_WELL
ACTIVE_LIST_ADD_MANY_OBS_INDEX OBS_WELL WOPR:OBS_WELL 0 1 2
.. ###########################################################################################################
.. _install_default_updatestep:
.. topic:: INSTALL_DEFAULT_UPDATESTEP
| This function will install 'NAME_OF_UPDATESTEP' as the default updatestep which applies to all report steps where you have not explicitly set another updatestep with the INSTALL_UPDATESTEP function.
*Example:*
::
-- Install default update step
INSTALL_DEFAULT_UPDATESTEP ALL_ACTIVE
.. ###########################################################################################################
.. _add_field:
.. topic:: ADD_FIELD
| This function will install the node with name 'FIELD_NAME' in the dataset 'DATASET_NAME'. It will in addition select all the (currently) active cells in the region 'ECLREGION_NAME' as active for this field/ministep combination. The ADD_FIELD command is actually a shortcut of: ADD_DATA DATASET FIELD_NAME; followed by: ACTIVE_LIST_ADD_MANY_DATA_INDEX <All the indices from the region>
*Example:*
::
-- Add data node PORO to data set DATA_PORO activating indices in ECLREG_PORO
ADD_FIELD DATA_PORO PORO ECLREG_PORO
*Example:*
::
# Load Eclipse grid
ecl_grid = EclGrid("path/to/LOCAL.GRDECL")
with open("path/to/LOCAL.GRDECL","r") as fileH:
local_kw = Ecl3DKW.read_grdecl(ecl_grid, fileH, "LOCAL")
# Define Eclipse region
eclreg_poro = EclRegion(ecl_grid, False)
eclreg_poro.select_more(local_kw, 1)
# Create dataset and add field to dataset
data_poro = local_config.createDataset("DATA_PORO")
data_poro.addField("PORO", eclreg_poro)
.. ###########################################################################################################
.. _load_file:
.. topic:: LOAD_FILE
| This function will load an ECLIPSE file in restart format (i.e. restart file or INIT file), the keywords in this file can then subsequently be used in ECLREGION_SELECT_VALUE_XXX commands below. The 'KEY' argument is a string which will be used later when we refer to the content of this file
*Example:*
::
-- Load Eclipse init file
LOAD_FILE REFINIT path/to/FULLMODEL.INIT
*Example:*
::
# Load Eclipse grid and init file
ecl_grid = EclGrid("path/to/FULLMODEL.GRDECL")
refinit_file = EclInitFile(grid , "path/to/somefile.init")
.. ###########################################################################################################
.. _create_eclregion:
.. topic:: CREATE_ECLREGION
| This function will create a new region 'ECLREGION_NAME', which can subsequently be used when defining active regions for fields. The second argument, SELECT_ALL, is a boolean value. If this value is set to true the region will start with all cells selected, if set to false the region will start with no cells selected.
*Example:*
::
-- New Eclipse region with all cells inactive
CREATE_ECLREGION ECL_REGION FALSE
*Example:*
::
# Define Eclipse region
eclreg_poro = EclRegion(ecl_grid, False)
.. ###########################################################################################################
.. _eclregion_select_all:
.. topic:: ECLREGION_SELECT_ALL
| Will select all the cells in the region (or deselect if SELECT == FALSE).
*Example:*
::
-- Select cells in region
ECLREGION_SELECT_ALL ECL_REGION TRUE
*Example:*
::
eclreg_poro.select_active()
.. ###########################################################################################################
.. _eclregion_select_value_equal:
.. topic:: ECLREGION_SELECT_VALUE_EQUAL
| This function will compare an ecl_kw instance loaded from file with a user supplied value, and select (or deselect) all cells which match this value. It is assumed that the ECLIPSE keyword is an INTEGER keyword, for float comparisons use the ECLREGION_SELECT_VALUE_LESS and ECLREGION_SELECT_VALUE_MORE functions.
*Example:*
::
-- Select cells in region ECL_REGION equal to 0
ECLREGION_SELECT_VALUE_EQUAL ECL_REGION ECL_REGION:LOCAL 0 TRUE
*Example:*
::
# Load Eclipse grid
ecl_grid = EclGrid("path/to/LOCAL.GRDECL")
with open("path/to/LOCAL.GRDECL","r") as fileH:
local_kw = Ecl3DKW.read_grdecl(ecl_grid, fileH, "LOCAL", ecl_type= EclTypeEnum.ECL_INT_TYPE)
# Define Eclipse region
eclreg_poro = EclRegion(ecl_grid, False)
eclreg_poro.select_equal(local_kw, 1)
print 'GRID LOADED%s' % ecl_grid
print ecl_grid.getDims()
print local_kw.header
.. ###########################################################################################################
.. _eclregion_select_value_less:
.. topic:: ECLREGION_SELECT_VALUE_LESS
| This function will compare an ecl_kw instance loaded from disc with a numerical value, and select all cells which have numerical below the limiting value. The ecl_kw value should be a floating point value like e.g. PRESSURE or PORO. The arguments are just as for ECLREGION_SELECT_VALUE_EQUAL.
*Example:*
::
-- Select cells in region ECL_REGION less than 1
ECLREGION_SELECT_VALUE_LESS ECL_REGION ECL_REGION:LOCAL 1 TRUE
*Example:*
::
eclreg_poro.select_less(local_kw, 1)
.. ###########################################################################################################
.. _eclregion_select_value_more:
.. topic:: ECLREGION_SELECT_VALUE_MORE
| This function will compare an ecl_kw instance loaded from disc with a numerical value, and select all cells which have numerical above the limiting value. The ecl_kw value should be a floating point value like e.g. PRESSURE or PORO. The arguments are just as for ECLREGION_SELECT_VALUE_EQUAL.
*Example:*
::
-- Select cells in region ECL_REGION greater than 0
ECLREGION_SELECT_VALUE_MORE ECL_REGION ECL_REGION:LOCAL 0 TRUE
*Example:*
::
eclreg_poro.select_more(local_kw, 1)
.. ###########################################################################################################
.. _eclregion_select_box:
.. topic:: ECLREGION_SELECT_BOX
| This function will select (or deselect) all the cells in the box defined by the six coordinates i1 i2 j1 j2 k1 k2. The coordinates are inclusive, and the counting starts at 1.
*Example:*
::
-- Select cells in box [0,1] x [2,3] x [4,5]
ECLREGION_SELECT_BOX ECL_REGION 0 1 2 3 4 5 TRUE
*Example:*
::
eclreg_poro.select_box((0,2,4),(1,3,5))
.. ###########################################################################################################
.. _eclregion_select_slice:
.. topic:: ECLREGION_SELECT_SLICE
| This function will select a slice in the direction given by 'dir', which can 'x', 'y' or 'z'. Depending on the value of 'dir' the numbers n1 and n2 are interpreted as (i1 i2), (j1 j2) or (k1 k2) respectively. The numbers n1 and n2 are inclusice and the counting starts at 1. It is OK to use very high/low values to imply "the rest of the cells" in one direction.
*Example:*
::
-- Select layer from z=2 to z=3
ECLREGION_SELECT_SLICE ECL_REGION z 2 3 TRUE
*Example:*
::
eclreg_poro.select_kslice(2,3)
.. ###########################################################################################################
.. _eclregion_select_plane:
.. topic:: ECLREGION_SELECT_PLANE
| Will select all points which have positive (sign > 0) distance to the plane defined by normal vector n = (nx,ny,nz) and point p = (px,py,pz). If sign < 0 all cells with negative distance to plane will be selected.
*Example:*
::
-- Select half space defined by plane perpendicular to vector [1 1 1]
ECLREGION_SELECT_PLANE ECL_REGION 1 1 1 0 0 0 -1 TRUE
*Example:*
::
eclreg_poro.select_below_plane((1,1,1),(0,0,0))
.. ###########################################################################################################
.. _eclregion_select_in_polygon:
.. topic:: ECLREGION_SELECT_IN_POLYGON
| Well select all the points which are inside the polygon with name 'POLYGON_NAME'. The polygon should have been created with command CREATE_POLYGON or loaded with command 'LOAD_POLYGON' first.
*Example:*
::
-- Select region inside polygon in xy plane
ECLREGION_SELECT_IN_POLYGON POLYGON TRUE
*Example:*
::
polygon = [(0,0) , (0,1) , (1,0)]
eclreg_poro.select_inside_polygon(polygon)
.. ###########################################################################################################
.. _create_polygon:
.. topic:: CREATE_POLYGON
| Will create a geo_polygon instance based on the coordinate list: (x1,y1), (x2,y2), (x3,y3), ... The polygon should not be explicitly closed - i.e. you should in general have (x1,y1) != (xn,yn). The polygon will be stored under the name 'POLYGON_NAME' - which should later be used when referring to the polygon in region select operations.
*Example:*
::
-- Create polygon in xy plane
CREATE_POLYGON POLYGON 0 0 0 1 1 0 TRUE
*Example:*
::
polygon = [(0,0) , (0,1) , (1,0)]
.. ###########################################################################################################
.. _load_polygon:
.. topic:: LOAD_POLYGON
| Will load a polygon instance from the file 'FILENAME' - the file should be in irap RMS format. The polygon will be stored under the name 'POLYGON_NAME' which can then later be used to refer to the polygon for e.g. select operations.
*Example:*
::
-- Load polygon from RMS file
LOAD_POLYGON path/to/polygon.irap
*Example:*
::
polygon = []
with open("polygon.ply","r") as fileH:
for line in fileH.readlines():
tmp = line.split()
polygon.append( (float(tmp[0]) , float(tmp[1])))
.. ###########################################################################################################
.. _load_surface:
.. topic:: LOAD_SURFACE
| Will load an irap surface from file 'SURFACE_FILE'. The surface will be stored internally as 'SURFACE_NAME' - this function is mainly needed to have a base surface available for the CREATE_SURFACE_REGION command.
*Example:*
::
-- Load Irap RMS surface from file
LOAD_SURFACE path/to/surface.irap
.. ###########################################################################################################
.. _create_surface_region:
.. topic:: CREATE_SURFACE_REGION
| Will create a new surface region object which can be used to select and deselect parts of a surface. The region will be called 'REGION_NAME' and it will be based on the surface given by 'BASE_SURFACE'. 'PRESELECT' is a boolean 'TRUE' or 'FALSE' which determines whether the region is created with all points selected, or no points selected.
*Example:*
::
-- Create surface region in xy plane
CREATE_SURFACE_REGION SURF_REGION BASE_SURFACE TRUE
.. ###########################################################################################################
.. _surface_region_select_in_polygon:
.. topic:: SURFACE_REGION_SELECT_IN_POLYGON
| Well select all the points which are inside the polygon with name 'POLYGON_NAME'. The polygon should have been created with command CREATE_POLYGON or loaded with command 'LOAD_POLYGON' first.
*Example:*
::
-- Select surface region inside polygon
SURFACE_REGION_SELECT_IN_POLYGON SURF_REGION TRIANGLE TRUE
.. ###########################################################################################################
.. _surface_region_select_line:
.. topic:: SURFACE_REGION_SELECT_LINE
| Well select|deselect all the points which are above|below the line: (x1,y1) -> (x2,y2). If SIGN is positive the select will apply to all points with a positive (right hand system) distance to the line; if SIGN is negative the selector will apply to all points with a negative distance to the line.
*Example:*
::
-- Select surface region inside a half space defined by a line from [0,0] to [1,1]
SURFACE_REGION_SELECT_LINE SURF_REGION 0 0 1 1 -1 TRUE
.. ###########################################################################################################
.. _add_data_surface:
.. topic:: ADD_DATA_SURFACE
| Will add the node 'SURFACE_NAME' (not one of the loaded surfaces, but an enkf_node object) to the dataset 'DATASET_NAME'. Only the elements in the region 'REGION_NAME' will be added. Typically SURFACE_REGION_SELECT_xxxx has been used first to build a suitable region selection.
*Example:*
::
-- Add EnKF node object to dataset DATA_MULTFLT, with elements in SURF_REGION from BASE_SURFACE
ADD_DATA_SURFACE DATA_MULTFLT BASE_SURFACE SURF_REGION
.. ###########################################################################################################

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2012 Statoil ASA, Norway.
The file 'config_content_node.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 'config_content_node.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>
@ -30,7 +30,7 @@
#define CONFIG_CONTENT_NODE_ID 6752887
struct config_content_node_struct {
UTIL_TYPE_ID_DECLARATION;
const config_schema_item_type * schema;
const config_schema_item_type * schema;
stringlist_type * stringlist; /* The values which have been set. */
const config_path_elm_type * cwd;
stringlist_type * string_storage;
@ -59,7 +59,7 @@ void config_content_node_add_value(config_content_node_type * node , const char
void config_content_node_set(config_content_node_type * node , const stringlist_type * token_list) {
int argc = stringlist_get_size( token_list ) - 1;
for (int iarg=0; iarg < argc; iarg++)
for (int iarg=0; iarg < argc; iarg++)
config_content_node_add_value( node , stringlist_iget( token_list , iarg + 1));
}
@ -149,7 +149,7 @@ const char * config_content_node_iget_as_path(config_content_node_type * node ,
const char * config_value = config_content_node_iget(node , index);
char * path_value = config_path_elm_alloc_path( node->cwd , config_value );
config_content_node_push_string( node , path_value );
return path_value;
}
}
@ -161,7 +161,7 @@ const char * config_content_node_iget_as_abspath( config_content_node_type * nod
const char * config_value = config_content_node_iget(node , index);
char * path_value = config_path_elm_alloc_abspath( node->cwd , config_value );
config_content_node_push_string( node , path_value );
return path_value;
}
}
@ -173,7 +173,7 @@ const char * config_content_node_iget_as_relpath( config_content_node_type * nod
const char * config_value = config_content_node_iget(node , index);
char * path_value = config_path_elm_alloc_relpath( node->cwd , config_value );
config_content_node_push_string( node , path_value );
return path_value;
}
}
@ -216,13 +216,13 @@ const config_path_elm_type * config_content_node_get_path_elm( const config_cont
Which will be inserted in the opt_hash dictionary as : {"KEY1" :
"VALUE1" , ... } Elements which do not conform to this syntax are
ignored.
ignored.
*/
void config_content_node_init_opt_hash( const config_content_node_type * node , hash_type * opt_hash , int elm_offset) {
int i;
for (i = elm_offset; i < config_content_node_get_size( node ); i++)
for (i = elm_offset; i < config_content_node_get_size( node ); i++)
hash_add_option( opt_hash , config_content_node_iget( node , i ));
}

View File

@ -56,6 +56,10 @@ extern "C" {
void ecl_grid_get_cell_corner_xyz1(const ecl_grid_type * grid , int global_index , int corner_nr , double * xpos , double * ypos , double * zpos );
void ecl_grid_get_corner_xyz(const ecl_grid_type * grid , int i , int j , int k, double * xpos , double * ypos , double * zpos );
double ecl_grid_get_cell_dx1( const ecl_grid_type * grid , int global_index );
double ecl_grid_get_cell_dx3( const ecl_grid_type * grid , int i , int j , int k);
double ecl_grid_get_cell_dy1( const ecl_grid_type * grid , int global_index );
double ecl_grid_get_cell_dy3( const ecl_grid_type * grid , int i , int j , int k);
double ecl_grid_get_cell_thickness3( const ecl_grid_type * grid , int i , int j , int k);
double ecl_grid_get_cell_thickness1( const ecl_grid_type * grid , int global_index );
double ecl_grid_get_cdepth1(const ecl_grid_type * grid , int global_index);

View File

@ -52,7 +52,11 @@ typedef struct ecl_sum_tstep_struct ecl_sum_tstep_type;
void ecl_sum_tstep_fwrite( const ecl_sum_tstep_type * ministep , const int_vector_type * index_map , fortio_type * fortio);
void ecl_sum_tstep_iset( ecl_sum_tstep_type * tstep , int index , float value);
void ecl_sum_tstep_set_from_node( ecl_sum_tstep_type * tstep , const smspec_node_type * smspec_node , float value);
void ecl_sum_tstep_set_from_key( ecl_sum_tstep_type * tstep , const char * gen_key , float value);
double ecl_sum_tstep_get_from_key( const ecl_sum_tstep_type * tstep , const char * gen_key);
bool ecl_sum_tstep_has_key(const ecl_sum_tstep_type * tstep , const char * gen_key);
bool ecl_sum_tstep_sim_time_equal( const ecl_sum_tstep_type * tstep1 , const ecl_sum_tstep_type * tstep2 );
UTIL_SAFE_CAST_HEADER( ecl_sum_tstep );

View File

@ -42,20 +42,6 @@ typedef enum { ECL_OTHER_FILE = 0 ,
ECL_DATA_FILE = 512 } ecl_file_enum;
#define ECL_FILE_ENUM_DEFS {.value = 0 , .name="ECL_OTHER_FILE"}, \
{.value = 1 , .name="ECL_RESTART_FILE"}, \
{.value = 2 , .name="ECL_UNIFIED_RESTART_FILE"}, \
{.value = 4 , .name="ECL_SUMMARY_FILE"}, \
{.value = 8 , .name="ECL_UNIFIED_SUMMARY_FILE"}, \
{.value = 16 , .name="ECL_SUMMARY_HEADER_FILE"}, \
{.value = 32 , .name="ECL_GRID_FILE"}, \
{.value = 64 , .name="ECL_EGRID_FILE"}, \
{.value = 128 , .name="ECL_INIT_FILE"}, \
{.value = 256 , .name="ECL_RFT_FILE"}, \
{.value = 512 , .name="ECL_DATA_FILE"}
#define ECL_FILE_ENUM_SIZE 11
/*
This enum enumerates the four different ways summary and restart information

View File

@ -78,6 +78,7 @@ extern "C" {
void layer_update_active( layer_type * layer , const ecl_grid_type * grid , int k);
void layer_cells_equal( const layer_type * layer , int value , int_vector_type * i_list , int_vector_type * j_list);
int layer_count_equal( const layer_type * layer , int value );
UTIL_IS_INSTANCE_HEADER( layer );
UTIL_SAFE_CAST_HEADER( layer );

View File

@ -742,11 +742,6 @@ void ecl_file_fprintf_kw_list( const ecl_file_type * ecl_file , FILE * stream )
file_map_fprintf_kw_list( ecl_file->active_map , stream );
}
#ifdef HAVE_FORK
const char * ecl_file_enum_iget( int index , int * value) {
return util_enum_iget( index , ECL_FILE_ENUM_SIZE , (const util_enum_element_type []) { ECL_FILE_ENUM_DEFS } , value);
}
#endif
/*****************************************************************/

View File

@ -639,6 +639,7 @@ struct ecl_grid_struct {
but in cases with skewed cells this has proved
numerically challenging. */
bool is_metric;
int eclipse_version;
};
@ -1338,6 +1339,7 @@ static ecl_grid_type * ecl_grid_alloc_empty(ecl_grid_type * global_grid , int du
grid->parent_grid = NULL;
grid->children = hash_alloc();
grid->coarse_cells = vector_alloc_new();
grid->eclipse_version = 0;
return grid;
}
@ -2283,8 +2285,12 @@ static void ecl_grid_init_nnc_cells( ecl_grid_type * grid1, ecl_grid_type * grid
*/
static void ecl_grid_init_nnc(ecl_grid_type * main_grid, ecl_file_type * ecl_file) {
int num_nnchead_kw = ecl_file_get_num_named_kw( ecl_file , NNCHEAD_KW );
int i;
if(num_nnchead_kw > 0 && main_grid->eclipse_version == 2015){
return; //Eclipse 2015 has an error with nnc.
}
for (i = 0; i < num_nnchead_kw; i++) {
ecl_file_push_block(ecl_file); /* <---------------------------------------------------------------- */
ecl_file_select_block(ecl_file , NNCHEAD_KW , i);
@ -2366,11 +2372,15 @@ static ecl_grid_type * ecl_grid_alloc_EGRID__( ecl_grid_type * main_grid , const
ecl_kw_type * actnum_kw = NULL;
ecl_kw_type * mapaxes_kw = NULL;
int dualp_flag;
int eclipse_version;
if (grid_nr == 0) {
ecl_kw_type * filehead_kw = ecl_file_iget_named_kw( ecl_file , FILEHEAD_KW , grid_nr);
dualp_flag = ecl_kw_iget_int( filehead_kw , FILEHEAD_DUALP_INDEX );
} else
eclipse_version = ecl_kw_iget_int( filehead_kw, FILEHEAD_YEAR_INDEX);
} else{
dualp_flag = main_grid->dualp_flag;
eclipse_version = main_grid->eclipse_version;
}
/** If ACTNUM is not present - that is is interpreted as - all active. */
@ -2399,6 +2409,7 @@ static ecl_grid_type * ecl_grid_alloc_EGRID__( ecl_grid_type * main_grid , const
corsnum_kw );
if (ECL_GRID_MAINGRID_LGR_NR != grid_nr) ecl_grid_set_lgr_name_EGRID(ecl_grid , ecl_file , grid_nr);
ecl_grid->eclipse_version = eclipse_version;
return ecl_grid;
}
}
@ -4311,21 +4322,44 @@ double ecl_grid_get_cell_thickness3( const ecl_grid_type * grid , int i , int j
double ecl_grid_get_cell_dx1( const ecl_grid_type * grid , int global_index ) {
fprintf(stderr , "** WARNING: The ecl_grid_get_cell_dx1() function is only a stub returning -1.\n");
fprintf(stderr , " If you need a correct value for cell dx you must rebuild a new ert version.\n");
return -1;
}
double ecl_grid_get_cell_dx3( const ecl_grid_type * grid , int i , int j , int k) {
const int global_index = ecl_grid_get_global_index3(grid , i,j,k);
return ecl_grid_get_cell_dx1( grid , global_index );
}
double ecl_grid_get_cell_dy1( const ecl_grid_type * grid , int global_index ) {
fprintf(stderr , "** WARNING: The ecl_grid_get_cell_dy1() function is only a stub returning -1.\n");
fprintf(stderr , " If you need a correct value for cell dy you must update rebuild a new ert version.\n");
return -1;
}
double ecl_grid_get_cell_dy3( const ecl_grid_type * grid , int i , int j , int k) {
const int global_index = ecl_grid_get_global_index3(grid , i,j,k);
return ecl_grid_get_cell_dy1( grid , global_index );
}
const nnc_info_type * ecl_grid_get_cell_nnc_info1( const ecl_grid_type * grid , int global_index) {
const ecl_cell_type * cell = ecl_grid_get_cell( grid , global_index);
return cell->nnc_info;
}
const nnc_info_type * ecl_grid_get_cell_nnc_info3( const ecl_grid_type * grid , int i , int j , int k) {
const int global_index = ecl_grid_get_global_index3(grid , i,j,k);
return ecl_grid_get_cell_nnc_info1(grid, global_index);
}
/*****************************************************************/
/* Functions to query whether a cell is active or not. */

View File

@ -46,6 +46,7 @@ double ecl_rsthead_get_sim_days( const ecl_rsthead_type * header ) {
ecl_rsthead_type * ecl_rsthead_ialloc( const ecl_file_type * rst_file , int occurence) {
if (ecl_file_get_num_named_kw( rst_file , INTEHEAD_KW) > occurence) {
const ecl_kw_type * intehead_kw = ecl_file_iget_named_kw( rst_file , INTEHEAD_KW , occurence);
const ecl_kw_type * doubhead_kw = ecl_file_iget_named_kw( rst_file , DOUBHEAD_KW , occurence);
ecl_rsthead_type * rsthead = util_malloc( sizeof * rsthead );
@ -79,12 +80,7 @@ ecl_rsthead_type * ecl_rsthead_ialloc( const ecl_file_type * rst_file , int occu
// The only derived quantity
rsthead->sim_time = rsthead_date( rsthead->day , rsthead->month , rsthead->year );
}
if (ecl_file_get_num_named_kw(rst_file, DOUBHEAD_KW) > occurence) {
const ecl_kw_type * doubhead_kw = ecl_file_iget_named_kw( rst_file , DOUBHEAD_KW , occurence);
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 (ecl_file_get_num_named_kw(rst_file, LOGIHEAD_KW) > occurence) {
const ecl_kw_type * logihead_kw = ecl_file_iget_named_kw( rst_file , LOGIHEAD_KW , occurence);
rsthead->dualp = ecl_kw_iget_bool( logihead_kw , LOGIHEAD_DUALP_INDEX);

View File

@ -294,6 +294,16 @@ void ecl_sum_tstep_set_from_key( ecl_sum_tstep_type * tstep , const char * gen_k
ecl_sum_tstep_set_from_node( tstep , smspec_node , value);
}
double ecl_sum_tstep_get_from_key(const ecl_sum_tstep_type * tstep , const char * gen_key) {
const smspec_node_type * smspec_node = ecl_smspec_get_general_var_node( tstep->smspec , gen_key );
int data_index = smspec_node_get_params_index( smspec_node );
return ecl_sum_tstep_iget( tstep , data_index);
}
bool ecl_sum_tstep_has_key(const ecl_sum_tstep_type * tstep , const char * gen_key) {
return ecl_smspec_has_general_var(tstep->smspec, gen_key);
}
bool ecl_sum_tstep_sim_time_equal( const ecl_sum_tstep_type * tstep1 , const ecl_sum_tstep_type * tstep2 ) {
if (tstep1->sim_time == tstep2->sim_time)

View File

@ -1522,9 +1522,6 @@ time_t ecl_util_make_date(int mday , int month , int year) {
/* Small functions to support enum introspection. */
#ifdef HAVE_FORK
const char * ecl_util_file_enum_iget( int index, int * value) {
return util_enum_iget( index , ECL_FILE_ENUM_SIZE , (const util_enum_element_type []) { ECL_FILE_ENUM_DEFS }, value);
}
const char * ecl_util_phase_enum_iget( int index, int * value) {
return util_enum_iget( index , ECL_PHASE_ENUM_SIZE , (const util_enum_element_type []) { ECL_PHASE_ENUM_DEFS }, value);

View File

@ -772,6 +772,21 @@ void layer_cells_equal( const layer_type * layer , int value , int_vector_type *
}
int layer_count_equal( const layer_type * layer , int value ) {
int num_equal = 0;
int i,j;
for (j=0; j < layer->ny; j++) {
for (i=0; i < layer->nx; i++) {
cell_type * cell = layer_iget_cell( layer , i , j );
if (cell->cell_value == value)
num_equal++;
}
}
return num_equal;
}
void layer_update_active( layer_type * layer , const ecl_grid_type * grid , int k) {

View File

@ -114,6 +114,9 @@ add_executable( ecl_grid_simple ecl_grid_simple.c )
target_link_libraries( ecl_grid_simple ecl test_util )
add_test( ecl_grid_simple ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_simple ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Gurbat/ECLIPSE.EGRID )
add_test( ecl_grid_ecl2015_1 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_simple ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Eclipse2015_NNC_BUG/FF15_2015B2_LGRM_RDI15_HIST_RDIREAL1_NOSIM_GRID.EGRID )
add_test( ecl_grid_ecl2015_2 ${EXECUTABLE_OUTPUT_PATH}/ecl_grid_simple ${PROJECT_SOURCE_DIR}/test-data/Statoil/ECLIPSE/Eclipse2015_NNC_BUG/FF15_2015B2_LGRM_RDI15_HIST_RDIREAL1_20142.EGRID )
add_executable( ecl_grid_DEPTHZ ecl_grid_DEPTHZ.c )
target_link_libraries( ecl_grid_DEPTHZ ecl test_util )
@ -370,4 +373,6 @@ set_property( TEST ecl_grid_copy_statoil3 PROPERTY LABELS StatoilData )
set_property( TEST ecl_grid_copy_statoil4 PROPERTY LABELS StatoilData )
set_property( TEST ecl_layer_statoil PROPERTY LABELS StatoilData )
set_property( TEST ecl_grid_layer_contains1 PROPERTY LABELS StatoilData )
set_property( TEST ecl_grid_layer_contains2 PROPERTY LABELS StatoilData )
set_property( TEST ecl_grid_layer_contains2 PROPERTY LABELS StatoilData )
set_property( TEST ecl_grid_ecl2015_1 PROPERTY LABELS StatoilData )
set_property( TEST ecl_grid_ecl2015_2 PROPERTY LABELS StatoilData )

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'active_list.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 'active_list.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 __ACTIVE_LIST_H__
@ -29,7 +29,7 @@ extern "C" {
typedef struct active_list_struct active_list_type;
active_list_type * active_list_alloc( );
active_list_type * active_list_alloc( );
void active_list_reset(active_list_type * );
void active_list_add_index(active_list_type * , int);
void active_list_free( active_list_type *);
@ -41,10 +41,11 @@ typedef struct active_list_struct active_list_type;
active_mode_type active_list_get_mode(const active_list_type * );
void active_list_free__( void * arg );
active_list_type * active_list_alloc_copy( const active_list_type * src);
void active_list_fprintf( const active_list_type * active_list , bool obs , const char * key , FILE * stream );
void active_list_fprintf( const active_list_type * active_list , const char * dataset_key , const char * key , FILE * stream );
void active_list_summary_fprintf( const active_list_type * active_list , const char * dataset_key , const char * key , FILE * stream);
bool active_list_iget( const active_list_type * active_list , int index );
bool active_list_equal( const active_list_type * active_list1 , const active_list_type * active_list2);
void active_list_copy( active_list_type * target , const active_list_type * src);
void active_list_copy( active_list_type * target , const active_list_type * src);
UTIL_IS_INSTANCE_HEADER( active_list );

View File

@ -21,7 +21,7 @@ extern "C" {
char * custom_kw_config_get_result_file(const custom_kw_config_type * config);
char * custom_kw_config_get_output_file(const custom_kw_config_type * config);
bool custom_kw_config_parse_result_file(custom_kw_config_type * config, const char * result_file, stringlist_type * result);
void custom_kw_config_serialize(custom_kw_config_type * config, stringlist_type * config_set);
void custom_kw_config_serialize(const custom_kw_config_type * config, stringlist_type * config_set);
void custom_kw_config_deserialize(custom_kw_config_type * config, stringlist_type * config_set);
bool custom_kw_config_has_key(const custom_kw_config_type * config, const char * key);
bool custom_kw_config_key_is_double(const custom_kw_config_type * config, const char * key);

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'enkf_analysis.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 'enkf_analysis.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.
*/
@ -33,19 +33,21 @@ extern "C" {
void enkf_analysis_fprintf_obs_summary(const obs_data_type * obs_data ,
const meas_data_type * meas_data ,
const int_vector_type * step_list ,
void enkf_analysis_fprintf_obs_summary(const obs_data_type * obs_data ,
const meas_data_type * meas_data ,
const int_vector_type * step_list ,
const char * ministep_name ,
FILE * stream );
void enkf_analysis_deactivate_outliers(obs_data_type * obs_data ,
meas_data_type * meas_data ,
double std_cutoff ,
double alpha);
void enkf_analysis_deactivate_outliers(obs_data_type * obs_data ,
meas_data_type * meas_data ,
double std_cutoff ,
double alpha,
bool verbose);
void enkf_analysis_deactivate_std_zero(obs_data_type * obs_data ,
meas_data_type * meas_data);
meas_data_type * meas_data,
bool verbose);
#ifdef __cplusplus

View File

@ -254,7 +254,7 @@
#define DEFAULT_START_TAG "<"
#define DEFAULT_END_TAG ">"
#define DEFAULT_MANUAL_URL "http://ert.nr.no/wiki/index.php/User_Manual"
#define DEFAULT_MANUAL_URL "http://ert.nr.no/ert/index.php/User_Manual"
#define DEFAULT_BROWSER "firefox"
/*****************************************************************/

View File

@ -26,6 +26,7 @@ extern "C" {
#include <ert/util/hash.h>
#include <ert/util/stringlist.h>
#include <ert/util/int_vector.h>
#include <ert/util/type_macros.h>
#include <ert/sched/history.h>
@ -96,6 +97,8 @@ extern "C" {
double enkf_obs_scale_correlated_std(const enkf_obs_type * enkf_obs , enkf_fs_type * fs , const int_vector_type * ens_active_list , const local_obsdata_type * local_obsdata);
local_obsdata_type * enkf_obs_alloc_all_active_local_obs( const enkf_obs_type * enkf_obs , const char * key);
UTIL_IS_INSTANCE_HEADER( enkf_obs );
#ifdef __cplusplus
}
#endif

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'enkf_state.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 'enkf_state.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 __ENKF_STATE_H__
@ -32,7 +32,7 @@ extern "C" {
#include <ert/sched/sched_file.h>
#include <ert/ecl/fortio.h>
#include <ert/ecl/ecl_file.h>
@ -57,7 +57,7 @@ typedef struct enkf_state_struct enkf_state_type;
bool enkf_state_get_pre_clear_runpath( const enkf_state_type * enkf_state );
void enkf_state_set_pre_clear_runpath( enkf_state_type * enkf_state , bool pre_clear_runpath );
keep_runpath_type enkf_state_get_keep_runpath( const enkf_state_type * enkf_state );
void enkf_state_set_keep_runpath( enkf_state_type * enkf_state , keep_runpath_type keep_runpath);
keep_runpath_type member_config_get_keep_runpath(const member_config_type * member_config);
@ -77,24 +77,24 @@ typedef struct enkf_state_struct enkf_state_type;
void * enkf_state_run_eclipse__(void * );
void * enkf_state_start_forward_model__(void * );
void enkf_state_load_from_forward_model(enkf_state_type * enkf_state ,
run_arg_type * run_arg ,
int * result ,
bool interactive ,
void enkf_state_load_from_forward_model(enkf_state_type * enkf_state ,
run_arg_type * run_arg ,
int * result ,
bool interactive ,
stringlist_type * msg_list);
void enkf_state_forward_init(enkf_state_type * enkf_state ,
run_arg_type * run_arg ,
void enkf_state_forward_init(enkf_state_type * enkf_state ,
run_arg_type * run_arg ,
int * result );
void enkf_state_init_eclipse(enkf_state_type *enkf_state, const run_arg_type * run_arg );
enkf_state_type * enkf_state_alloc(int ,
rng_type * main_rng ,
enkf_fs_type * fs,
const char * casename ,
bool pre_clear_runpath,
keep_runpath_type ,
rng_type * main_rng ,
enkf_fs_type * fs,
const char * casename ,
bool pre_clear_runpath,
keep_runpath_type ,
model_config_type * ,
ensemble_config_type * ,
const site_config_type * ,

View File

@ -39,7 +39,7 @@ typedef enum {
CREATE_MINISTEP = 2, /* MINISTEP_NAME OBSSET_NAME -> local_config_alloc_ministep(); */
ATTACH_MINISTEP = 3, /* UPDATESTEP_NAME , MINISTEP_NAME -> local_updatestep_add_ministep(); */
CREATE_DATASET = 4, /* NAME */
ATTACH_DATASET = 5, /* DATASET_NAME MINISETP_NAME */
ATTACH_DATASET = 5, /* DATASET_NAME MINISTEP_NAME */
CREATE_OBSSET = 6, /* NAME */
ADD_DATA = 7, /* DATA_KEY -> local_ministep_add_node(); */
ADD_OBS = 8, /* OBS_KEY -> local_ministep_add_obs(); */
@ -47,8 +47,6 @@ typedef enum {
ACTIVE_LIST_ADD_DATA_INDEX = 10, /* DATA_KEY , ACTIVE_INDEX */
ACTIVE_LIST_ADD_MANY_OBS_INDEX = 11, /* OBS_KEY , NUM_INDEX , INDEX1, INDEX2, INDEX3,... */
ACTIVE_LIST_ADD_MANY_DATA_INDEX = 12, /* DATA_KEY , NUM_INDEX , INDEX1 , INDEX2 , INDEX3 ,... */
INSTALL_UPDATESTEP = 13, /* UPDATESTEP_NAME , STEP1 , STEP2 local_config_set_updatestep() */
INSTALL_DEFAULT_UPDATESTEP = 14, /* UPDATETSTEP_NAME local_config_set_default_updatestep() */
DEL_DATA = 16, /* DATASET KEY*/
DEL_OBS = 17, /* MINISTEP OBS_KEY */
DATASET_DEL_ALL_DATA = 18, /* DATASET */
@ -56,6 +54,7 @@ typedef enum {
ADD_FIELD = 20, /* MINISTEP FIELD_NAME REGION_NAME */
COPY_DATASET = 21, /* SRC_NAME TARGET_NAME */
COPY_OBSSET = 22, /* SRC_NAME TARGET_NAME */
ATTACH_OBSSET = 23, /* OBSSET_NAME MINISTEP_NAME */
/*****************************************************************/
CREATE_ECLREGION = 100, /* Name of region TRUE|FALSE*/
LOAD_FILE = 101, /* Key, filename */
@ -87,14 +86,13 @@ typedef enum {
#define CREATE_DATASET_STRING "CREATE_DATASET"
#define ATTACH_DATASET_STRING "ATTACH_DATASET"
#define CREATE_OBSSET_STRING "CREATE_OBSSET"
#define ATTACH_OBSSET_STRING "ATTACH_OBSSET"
#define ADD_DATA_STRING "ADD_DATA"
#define ADD_OBS_STRING "ADD_OBS"
#define ACTIVE_LIST_ADD_OBS_INDEX_STRING "ACTIVE_LIST_ADD_OBS_INDEX"
#define ACTIVE_LIST_ADD_DATA_INDEX_STRING "ACTIVE_LIST_ADD_DATA_INDEX"
#define ACTIVE_LIST_ADD_MANY_OBS_INDEX_STRING "ACTIVE_LIST_ADD_MANY_OBS_INDEX"
#define ACTIVE_LIST_ADD_MANY_DATA_INDEX_STRING "ACTIVE_LIST_ADD_MANY_DATA_INDEX"
#define INSTALL_UPDATESTEP_STRING "INSTALL_UPDATESTEP"
#define INSTALL_DEFAULT_UPDATESTEP_STRING "INSTALL_DEFAULT_UPDATESTEP"
#define DEL_DATA_STRING "DEL_DATA"
#define DEL_OBS_STRING "DEL_OBS"
#define ADD_FIELD_STRING "ADD_FIELD"
@ -124,13 +122,12 @@ typedef enum {
typedef struct local_config_struct local_config_type;
local_config_type * local_config_alloc( );
void local_config_clear( local_config_type * local_config );
void local_config_free( local_config_type * local_config );
local_updatestep_type * local_config_alloc_updatestep( local_config_type * local_config , const char * key );
local_ministep_type * local_config_alloc_ministep( local_config_type * local_config , const char * key , const char * obsset_name);
local_ministep_type * local_config_alloc_ministep( local_config_type * local_config , const char * key );
local_ministep_type * local_config_alloc_ministep_copy( local_config_type * local_config , const char * src_key , const char * new_key);
void local_config_set_default_updatestep( local_config_type * local_config , const char * default_key);
const local_updatestep_type * local_config_iget_updatestep( const local_config_type * local_config , int index);
local_updatestep_type * local_config_get_updatestep( const local_config_type * local_config , const char * key);
void local_config_set_default_updatestep( local_config_type * local_config , local_updatestep_type * update_step );
local_updatestep_type * local_config_get_updatestep( const local_config_type * local_config );
local_ministep_type * local_config_get_ministep( const local_config_type * local_config , const char * key);
void local_config_set_updatestep(local_config_type * local_config, int step1 , int step2 , const char * key);
void local_config_reload( local_config_type * local_config , const ecl_grid_type * ecl_grid , const ensemble_config_type * ensemble_config , const enkf_obs_type * enkf_obs ,
@ -140,9 +137,12 @@ const char * local_config_get_cmd_string( local_config_instruct
stringlist_type * local_config_get_config_files( const local_config_type * local_config );
void local_config_clear_config_files( local_config_type * local_config );
void local_config_add_config_file( local_config_type * local_config , const char * config_file );
void local_config_fprintf( const local_config_type * local_config , const char * config_file);
void local_config_fprintf_config( const local_config_type * local_config , FILE * stream);
void local_config_fprintf( const local_config_type * local_config , const char * config_file);
void local_config_summary_fprintf( const local_config_type * local_config , const char * config_file);
void local_config_fprintf_config( const local_config_type * local_config , FILE * stream);
local_obsdata_type * local_config_alloc_obsset( local_config_type * local_config , const char * obsset_name );
local_dataset_type * local_config_alloc_dataset( local_config_type * local_config , const char * key );
#ifdef __cplusplus
}
#endif

View File

@ -1,20 +1,20 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
Copyright (C) 2011 Statoil ASA, Norway.
The file 'local_dataset.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.
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 __LOCAL_DATASET_H__
@ -35,15 +35,16 @@ void local_dataset_del_node( local_dataset_type * dataset , cons
void local_dataset_clear( local_dataset_type * dataset);
const char * local_dataset_get_name( const local_dataset_type * dataset);
void local_dataset_fprintf( const local_dataset_type * dataset , FILE * stream);
void local_dataset_summary_fprintf( const local_dataset_type * dataset , FILE * stream);
active_list_type * local_dataset_get_node_active_list(const local_dataset_type * dataset , const char * node_key );
stringlist_type * local_dataset_alloc_keys( const local_dataset_type * dataset );
int local_dataset_get_size( const local_dataset_type * dataset );
void local_dataset_del_node( local_dataset_type * dataset , const char * node_key);
void local_dataset_clear( local_dataset_type * dataset);
bool local_dataset_has_key(const local_dataset_type * dataset, const char * key);
#ifdef __cplusplus
}
#endif
#endif
#endif

View File

@ -29,15 +29,18 @@ extern "C" {
#include <ert/enkf/active_list.h>
#include <ert/enkf/local_dataset.h>
#include <ert/enkf/local_obsdata.h>
#include <ert/enkf/local_obsdata_node.h>
typedef struct local_ministep_struct local_ministep_type;
local_ministep_type * local_ministep_alloc(const char * name , local_obsdata_type * observations);
local_ministep_type * local_ministep_alloc(const char * name);
void local_ministep_free(local_ministep_type * ministep);
void local_ministep_free__(void * arg);
void local_ministep_add_obs(local_ministep_type * ministep, const char * obs_key);
active_list_type * local_ministep_get_node_active_list(const local_ministep_type * ministep , const char * node_key );
hash_iter_type * local_ministep_alloc_dataset_iter( const local_ministep_type * ministep );
stringlist_type * local_ministep_alloc_data_keys( const local_ministep_type * ministep );
bool local_ministep_has_data_key(const local_ministep_type * ministep , const char * key);
local_ministep_type * local_ministep_alloc_copy( const local_ministep_type * src , const char * name);
void local_ministep_del_obs( local_ministep_type * ministep , const char * obs_key);
void local_ministep_del_node( local_ministep_type * ministep , const char * node_key);
@ -45,9 +48,14 @@ const char * local_ministep_get_name( const local_ministep_type * minis
void local_ministep_clear_nodes( local_ministep_type * ministep);
void local_ministep_clear_observations( local_ministep_type * ministep);
void local_ministep_fprintf( const local_ministep_type * ministep , FILE * stream );
void local_ministep_summary_fprintf( const local_ministep_type * ministep , FILE * stream);
void local_ministep_add_dataset( local_ministep_type * ministep , const local_dataset_type * dataset);
void local_ministep_add_obsdata( local_ministep_type * ministep , local_obsdata_type * obsdata);
void local_ministep_add_obsdata_node( local_ministep_type * ministep , local_obsdata_node_type * obsdatanode);
local_obsdata_type * local_ministep_get_obsdata(const local_ministep_type * ministep);
local_dataset_type * local_ministep_get_dataset( const local_ministep_type * ministep, const char * dataset_name);
bool local_ministep_has_dataset( const local_ministep_type * ministep, const char * dataset_name);
int local_ministep_get_num_dataset( const local_ministep_type * ministep );
UTIL_SAFE_CAST_HEADER(local_ministep);
UTIL_IS_INSTANCE_HEADER(local_ministep);

View File

@ -42,7 +42,9 @@ typedef struct local_obsdata_struct local_obsdata_type;
local_obsdata_node_type * local_obsdata_get( const local_obsdata_type * data , const char * key);
void local_obsdata_clear( local_obsdata_type * data );
void local_obsdata_del_node( local_obsdata_type * data , const char * key);
void local_obsdata_reset_tstep_list( local_obsdata_type * data , const int_vector_type * step_list);
void local_obsdata_reset_tstep_list( local_obsdata_type * data , const int_vector_type * step_list);
void local_obsdata_fprintf( const local_obsdata_type * obsdata , FILE * stream );
void local_obsdata_summary_fprintf( const local_obsdata_type * obsdata , FILE * stream);
UTIL_IS_INSTANCE_HEADER( local_obsdata );

View File

@ -37,6 +37,7 @@ int local_updatestep_get_num_ministep( const local_updateste
local_updatestep_type * local_updatestep_alloc_copy( const local_updatestep_type * src , const char * name );
void local_updatestep_fprintf( const local_updatestep_type * updatestep , FILE * stream);
const char * local_updatestep_get_name( const local_updatestep_type * updatestep );
bool local_updatestep_has_data_key( const local_updatestep_type * update_step , const char * key);
#ifdef __cplusplus
}

View File

@ -39,7 +39,7 @@ const char * obs_data_iget_keyword( const obs_data_type * obs_data , int index )
double obs_data_iget_value( const obs_data_type * obs_data , int index );
double obs_data_iget_std( const obs_data_type * obs_data , int index );
active_type obs_data_iget_active_mode( const obs_data_type * obs_data , int index );
void obs_block_deactivate( obs_block_type * obs_block , int iobs , const char * msg);
void obs_block_deactivate( obs_block_type * obs_block , int iobs , bool verbose , const char * msg);
int obs_block_get_size( const obs_block_type * obs_block );
void obs_block_iset( obs_block_type * obs_block , int iobs , double value , double std);
void obs_block_iset_missing( obs_block_type * obs_block , int iobs );
@ -68,8 +68,12 @@ void obs_data_scale_kernel(const obs_data_type * obs_data , matr
void obs_data_fprintf(const obs_data_type * , const meas_data_type * meas_data , FILE *);
void obs_data_iget_value_std(const obs_data_type * obs_data , int index , double * value , double * std);
int obs_data_get_active_size(const obs_data_type * obs_data );
int obs_data_get_total_size( const obs_data_type * obs_data );
int obs_data_get_num_blocks( const obs_data_type * obs_data );
const char * obs_block_get_key( const obs_block_type * obs_block) ;
double obs_data_iget_value( const obs_data_type * obs_data , int total_index );
double obs_data_iget_std( const obs_data_type * obs_data , int total_index );
#ifdef __cplusplus
}

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2014 Statoil ASA, Norway.
The file 'run_arg.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 'run_arg.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.
*/
#ifndef __RUN_ARG_H__
@ -29,22 +29,22 @@ extern "C" {
#include <ert/enkf/enkf_types.h>
#include <ert/enkf/enkf_fs.h>
typedef struct run_arg_struct run_arg_type;
UTIL_SAFE_CAST_HEADER( run_arg );
UTIL_IS_INSTANCE_HEADER( run_arg );
UTIL_IS_INSTANCE_HEADER( run_arg );
run_arg_type * run_arg_alloc_ENSEMBLE_EXPERIMENT(enkf_fs_type * fs , int iens , int iter , const char * runpath);
run_arg_type * run_arg_alloc_INIT_ONLY(enkf_fs_type * init_fs , int iens , int iter , const char * runpath);
run_arg_type * run_arg_alloc_SMOOTHER_RUN(enkf_fs_type * simulate_fs , enkf_fs_type * update_target_fs , int iens , int iter , const char * runpath);
run_arg_type * run_arg_alloc_ENKF_ASSIMILATION(enkf_fs_type * fs ,
int iens ,
run_arg_type * run_arg_alloc_ENKF_ASSIMILATION(enkf_fs_type * fs ,
int iens ,
state_enum init_state_parameter ,
state_enum init_state_dynamic ,
int step1 ,
int step1 ,
int step2 ,
const char * runpath);
@ -67,9 +67,9 @@ UTIL_IS_INSTANCE_HEADER( run_arg );
const char * run_arg_get_runpath( const run_arg_type * run_arg);
void run_arg_complete_run(run_arg_type * run_arg);
run_status_type run_arg_get_run_status( const run_arg_type * run_arg );
void run_arg_set_inactive( run_arg_type * run_arg );
int run_arg_get_queue_index( const run_arg_type * run_arg );
bool run_arg_is_submitted( const run_arg_type * run_arg );
bool run_arg_can_retry( const run_arg_type * run_arg );

View File

@ -209,6 +209,11 @@ if (USE_RUNPATH)
add_runpath( enkf )
endif()
add_custom_target(ert_share_symlinking ALL
COMMENT "Symlinking to the development share directory."
COMMAND ln -sf -t ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/share
)
#-----------------------------------------------------------------
if (INSTALL_ERT)
install(TARGETS enkf DESTINATION ${CMAKE_INSTALL_LIBDIR})

View File

@ -207,22 +207,32 @@ bool active_list_iget( const active_list_type * active_list , int index ) {
/*****************************************************************/
void active_list_fprintf( const active_list_type * active_list , bool obs , const char *key , FILE * stream ) {
void active_list_fprintf( const active_list_type * active_list , const char *dataset_key, const char *key , FILE * stream ) {
if (active_list->mode == PARTLY_ACTIVE) {
int i;
if (obs)
fprintf(stream , "%s %s %d\n" , local_config_get_cmd_string( ACTIVE_LIST_ADD_MANY_OBS_INDEX ) , key , int_vector_size( active_list->index_list ));
else
fprintf(stream , "%s %s %d\n" , local_config_get_cmd_string( ACTIVE_LIST_ADD_MANY_OBS_INDEX ) , key , int_vector_size( active_list->index_list ));
fprintf(stream , "%s %s %s " , local_config_get_cmd_string( ACTIVE_LIST_ADD_DATA_INDEX ) , dataset_key, key);
for (i = 0; i < int_vector_size( active_list->index_list ); i++) {
fprintf(stream , "%6d " , int_vector_iget( active_list->index_list , i));
fprintf(stream , " %6d " , int_vector_iget( active_list->index_list , i));
if ((i % 10) == 9)
fprintf(stream , "\n");
}
fprintf(stream , "\n");
} /* else: if mode == ALL_ACTIVE nothing is written */
}
void active_list_summary_fprintf( const active_list_type * active_list , const char *dataset_key, const char *key , FILE * stream) {
int number_of_active = int_vector_size( active_list->index_list );
if (active_list->mode == ALL_ACTIVE){
fprintf(stream , "NUMBER OF ACTIVE:%d,STATUS:%s,", number_of_active, "ALL_ACTIVE");
}
else if (active_list->mode == PARTLY_ACTIVE){
fprintf(stream , "NUMBER OF ACTIVE:%d,STATUS:%s,", number_of_active, "PARTLY_ACTIVE");
}
else
fprintf(stream , "NUMBER OF ACTIVE:%d,STATUS:%s,", number_of_active, "INACTIVE");
}
bool active_list_equal( const active_list_type * active_list1 , const active_list_type * active_list2) {

View File

@ -80,8 +80,9 @@ static void custom_kw_config_reset__(custom_kw_config_type * config) {
config->key_definition_file = NULL;
}
void custom_kw_config_serialize(custom_kw_config_type * config, stringlist_type * config_set) {
pthread_rwlock_rdlock(& config->rw_lock);
void custom_kw_config_serialize(const custom_kw_config_type * config, stringlist_type * config_set) {
pthread_rwlock_t * rw_lock = (pthread_rwlock_t *)& config->rw_lock;
pthread_rwlock_rdlock(rw_lock);
{
stringlist_clear(config_set);
@ -100,7 +101,7 @@ void custom_kw_config_serialize(custom_kw_config_type * config, stringlist_type
stringlist_free(configured_keys);
}
pthread_rwlock_unlock(& config->rw_lock);
pthread_rwlock_unlock(rw_lock);
}
void custom_kw_config_deserialize(custom_kw_config_type * config, stringlist_type * config_set) {

View File

@ -106,7 +106,7 @@ void enkf_analysis_fprintf_obs_summary(const obs_data_type * obs_data , const me
void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , meas_data_type * meas_data , double std_cutoff , double alpha) {
void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , meas_data_type * meas_data , double std_cutoff , double alpha, bool verbose) {
for (int block_nr =0; block_nr < obs_data_get_num_blocks( obs_data ); block_nr++) {
obs_block_type * obs_block = obs_data_iget_block( obs_data , block_nr);
meas_block_type * meas_block = meas_data_iget_block( meas_data , block_nr );
@ -121,7 +121,7 @@ void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , meas_data_type
De activated because the ensemble has to small
variation for this particular measurement.
*/
obs_block_deactivate( obs_block , iobs , "No ensemble variation");
obs_block_deactivate( obs_block , iobs , verbose , "No ensemble variation");
meas_block_deactivate( meas_block , iobs );
} else {
double ens_mean = meas_block_iget_ens_mean( meas_block , iobs );
@ -136,7 +136,7 @@ void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , meas_data_type
*/
if (fabs( innov ) > alpha * (ens_std + obs_std)) {
obs_block_deactivate(obs_block , iobs , "No overlap");
obs_block_deactivate(obs_block , iobs , verbose , "No overlap");
meas_block_deactivate(meas_block , iobs);
}
}
@ -146,7 +146,7 @@ void enkf_analysis_deactivate_outliers(obs_data_type * obs_data , meas_data_type
}
}
void enkf_analysis_deactivate_std_zero(obs_data_type * obs_data , meas_data_type * meas_data) {
void enkf_analysis_deactivate_std_zero(obs_data_type * obs_data , meas_data_type * meas_data , bool verbose) {
for (int block_nr =0; block_nr < obs_data_get_num_blocks( obs_data ); block_nr++) {
obs_block_type * obs_block = obs_data_iget_block( obs_data , block_nr);
@ -162,7 +162,7 @@ void enkf_analysis_deactivate_std_zero(obs_data_type * obs_data , meas_data_type
De activated because the ensemble has to small
variation for this particular measurement.
*/
obs_block_deactivate( obs_block , iobs , "No ensemble variation");
obs_block_deactivate( obs_block , iobs , verbose , "No ensemble variation");
meas_block_deactivate( meas_block , iobs );
}
}

View File

@ -330,30 +330,6 @@ qc_module_type * enkf_main_get_qc_module( const enkf_main_type * enkf_main ) {
}
/*
Adding inverse observation keys to the enkf_nodes; can be called
several times.
*/
void enkf_main_update_obs_keys( enkf_main_type * enkf_main ) {
/* First clear all existing observation keys. */
ensemble_config_clear_obs_keys( enkf_main->ensemble_config );
/* Add new observation keys. */
{
hash_type * map = enkf_obs_alloc_data_map(enkf_main->obs);
hash_iter_type * iter = hash_iter_alloc(map);
const char * obs_key = hash_iter_get_next_key(iter);
while (obs_key != NULL) {
const char * state_kw = hash_get(map , obs_key);
ensemble_config_add_obs_key(enkf_main->ensemble_config , state_kw , obs_key);
obs_key = hash_iter_get_next_key(iter);
}
hash_iter_free(iter);
hash_free(map);
}
}
void enkf_main_alloc_obs( enkf_main_type * enkf_main ) {
enkf_main->obs = enkf_obs_alloc( model_config_get_history(enkf_main->model_config),
@ -370,8 +346,7 @@ void enkf_main_load_obs( enkf_main_type * enkf_main , const char * obs_config_fi
if (enkf_obs_load(enkf_main->obs ,
obs_config_file ,
analysis_config_get_std_cutoff(enkf_main->analysis_config))) {
enkf_main_update_obs_keys(enkf_main);
enkf_main_update_local_updates(enkf_main );
enkf_main_update_local_updates( enkf_main );
} else
fprintf(stderr,"** Warning: failed to load observation data from: %s \n",obs_config_file);
}
@ -1067,7 +1042,7 @@ void enkf_main_init_PC( const enkf_main_type * enkf_main ,
double std_cutoff = analysis_config_get_std_cutoff( analysis_config );
double alpha = analysis_config_get_alpha( analysis_config );
enkf_analysis_deactivate_outliers( obs_data , meas_data , std_cutoff , alpha);
enkf_analysis_deactivate_outliers( obs_data , meas_data , std_cutoff , alpha, enkf_main->verbose);
}
{
@ -1181,8 +1156,7 @@ static void enkf_main_analysis_update( enkf_main_type * enkf_main ,
analysis_module_init_update( module , ens_mask , S , R , dObs , E , D );
{
hash_iter_type * dataset_iter = local_ministep_alloc_dataset_iter( ministep );
enkf_fs_type * src_fs = enkf_main_get_fs( enkf_main );
serialize_info_type * serialize_info = serialize_info_alloc( src_fs ,
serialize_info_type * serialize_info = serialize_info_alloc( target_fs, //src_fs - we have already copied the parameters from the src_fs to the target_fs
target_fs ,
iens_active_index,
target_step ,
@ -1268,6 +1242,7 @@ static void enkf_main_analysis_update( enkf_main_type * enkf_main ,
matrix_free( R );
matrix_free( dObs );
matrix_free( X );
matrix_free( A );
}
@ -1316,12 +1291,35 @@ bool enkf_main_UPDATE(enkf_main_type * enkf_main , const int_vector_type * step_
meas_data_type * meas_forecast = meas_data_alloc( ens_mask );
meas_data_type * meas_analyzed = meas_data_alloc( ens_mask );
local_config_type * local_config = enkf_main->local_config;
const local_updatestep_type * updatestep = local_config_iget_updatestep( local_config , current_step ); /* Only last step considered when forming local update */
const local_updatestep_type * updatestep = local_config_get_updatestep( local_config );
hash_type * use_count = hash_alloc();
const char * log_path = analysis_config_get_log_path( enkf_main->analysis_config );
FILE * log_stream;
/* Copy all the parameter nodes. */
if (target_fs != source_fs) {
stringlist_type * param_keys = ensemble_config_alloc_keylist_from_var_type(enkf_main->ensemble_config, PARAMETER );
for (int i=0; i < stringlist_get_size( param_keys ); i++) {
const char * key = stringlist_iget( param_keys , i );
if (local_updatestep_has_data_key(updatestep, key)) {
enkf_config_node_type * config_node = ensemble_config_get_node( enkf_main->ensemble_config , key );
enkf_node_type * data_node = enkf_node_alloc( config_node );
for (int j=0; j < int_vector_size( ens_active_list ); j++) {
node_id_type node_id = {.iens = int_vector_iget( ens_active_list , j ),
.state = FORECAST ,
.report_step = 0 };
enkf_node_load( data_node , source_fs , node_id );
enkf_node_store( data_node , target_fs , false , node_id );
}
enkf_node_free( data_node );
}
}
stringlist_free( param_keys );
}
if ((local_updatestep_get_num_ministep( updatestep ) > 1) &&
(analysis_config_get_module_option( analysis_config , ANALYSIS_ITERABLE))) {
util_exit("** ERROR: Can not combine iterable modules with multi step updates - sorry\n");
@ -1368,7 +1366,7 @@ bool enkf_main_UPDATE(enkf_main_type * enkf_main , const int_vector_type * step_
enkf_analysis_deactivate_outliers( obs_data , meas_forecast , std_cutoff , alpha);
enkf_analysis_deactivate_outliers( obs_data , meas_forecast , std_cutoff , alpha , enkf_main->verbose);
if (enkf_main->verbose)
enkf_analysis_fprintf_obs_summary( obs_data , meas_forecast , step_list , local_ministep_get_name( ministep ) , stdout );
@ -1407,8 +1405,30 @@ bool enkf_main_UPDATE(enkf_main_type * enkf_main , const int_vector_type * step_
if (target_state_map != source_state_map) {
state_map_set_from_inverted_mask( target_state_map , ens_mask , STATE_PARENT_FAILURE);
state_map_set_from_mask( target_state_map , ens_mask , STATE_INITIALIZED );
enkf_fs_fsync( target_fs );
}
enkf_fs_fsync( target_fs );
}
/* Copy all the nodes which have been updates */
if (target_fs != source_fs) {
stringlist_type * param_keys = ensemble_config_alloc_keylist_from_var_type(enkf_main->ensemble_config, PARAMETER );
for (int i=0; i < stringlist_get_size( param_keys ); i++) {
const char * key = stringlist_iget( param_keys , i );
if (!local_updatestep_has_data_key(updatestep, key)) {
enkf_config_node_type * config_node = ensemble_config_get_node( enkf_main->ensemble_config , key );
enkf_node_type * data_node = enkf_node_alloc( config_node );
for (int j=0; j < int_vector_size( ens_active_list ); j++) {
node_id_type node_id = {.iens = int_vector_iget( ens_active_list , j ),
.state = FORECAST ,
.report_step = 0 };
enkf_node_load( data_node , source_fs , node_id );
enkf_node_store( data_node , target_fs , false , node_id );
}
enkf_node_free( data_node );
}
}
stringlist_free( param_keys );
}
}
bool_vector_free( ens_mask );
int_vector_free( ens_active_list );
@ -1545,26 +1565,26 @@ void enkf_main_isubmit_job( enkf_main_type * enkf_main , run_arg_type * run_arg
if (run_arg_get_run_mode(run_arg) != INIT_ONLY) {
// The job_queue_node will take ownership of this arg_pack; and destroy it when
// the job_queue_node is discarded.
arg_pack_type * load_arg = arg_pack_alloc();
arg_pack_type * callback_arg = arg_pack_alloc();
/*
Prepare the job and submit it to the queue
*/
arg_pack_append_ptr( load_arg , enkf_state );
arg_pack_append_ptr( load_arg , run_arg );
arg_pack_append_ptr( callback_arg , enkf_state );
arg_pack_append_ptr( callback_arg , run_arg );
{
int queue_index = job_queue_add_job_mt( job_queue ,
job_script ,
enkf_state_complete_forward_modelOK__ ,
enkf_state_complete_forward_modelRETRY__ ,
enkf_state_complete_forward_modelEXIT__,
load_arg ,
ecl_config_get_num_cpu( ecl_config ),
run_path ,
member_config_get_jobname( member_config ) ,
1,
(const char *[1]) { run_path } );
int queue_index = job_queue_add_job( job_queue ,
job_script ,
enkf_state_complete_forward_modelOK__ ,
enkf_state_complete_forward_modelRETRY__ ,
enkf_state_complete_forward_modelEXIT__,
callback_arg ,
ecl_config_get_num_cpu( ecl_config ),
run_path ,
member_config_get_jobname( member_config ) ,
1,
(const char *[1]) { run_path } );
run_arg_set_queue_index( run_arg , queue_index );
run_arg_increase_submit_count( run_arg );
@ -1574,13 +1594,12 @@ void enkf_main_isubmit_job( enkf_main_type * enkf_main , run_arg_type * run_arg
static void * enkf_main_isubmit_job__( void * arg ) {
void * enkf_main_isubmit_job__( void * arg ) {
arg_pack_type * arg_pack = arg_pack_safe_cast( arg );
enkf_main_type * enkf_main = enkf_main_safe_cast( arg_pack_iget_ptr( arg_pack , 0 ));
run_arg_type * run_arg = run_arg_safe_cast( arg_pack_iget_ptr( arg_pack , 1));
enkf_main_isubmit_job( enkf_main , run_arg );
arg_pack_free( arg_pack );
return NULL;
}
@ -1588,21 +1607,21 @@ static void * enkf_main_isubmit_job__( void * arg ) {
void enkf_main_submit_jobs( enkf_main_type * enkf_main ,
const ert_run_context_type * run_context ) {
void enkf_main_submit_jobs__( enkf_main_type * enkf_main ,
const ert_run_context_type * run_context ,
thread_pool_type * submit_threads,
arg_pack_type ** arg_pack_list) {
runpath_list_type * runpath_list = qc_module_get_runpath_list( enkf_main->qc_module );
runpath_list_clear( runpath_list );
{
int iens;
const bool_vector_type * iactive = ert_run_context_get_iactive( run_context );
const int active_ens_size = util_int_min( bool_vector_size( iactive ) , enkf_main_get_ensemble_size( enkf_main ));
thread_pool_type * submit_threads = thread_pool_alloc( 4 , true );
for (iens = 0; iens < active_ens_size; iens++) {
if (bool_vector_iget(iactive , iens)) {
run_arg_type * run_arg = ert_run_context_iens_get_arg( run_context , iens);
arg_pack_type * arg_pack = arg_pack_alloc( ); // This is discarded by the enkf_main_isubmit_job__()
arg_pack_type * arg_pack = arg_pack_list[iens];
arg_pack_append_ptr( arg_pack , enkf_main );
arg_pack_append_ptr( arg_pack , run_arg);
@ -1610,20 +1629,38 @@ void enkf_main_submit_jobs( enkf_main_type * enkf_main ,
thread_pool_add_job(submit_threads , enkf_main_isubmit_job__ , arg_pack);
}
}
/*
After this join all directories/files for the simulations
have been set up correctly, and all the jobs have been added
to the job_queue manager.
*/
thread_pool_join(submit_threads);
thread_pool_free(submit_threads);
}
runpath_list_fprintf( runpath_list );
}
void enkf_main_submit_jobs( enkf_main_type * enkf_main ,
const ert_run_context_type * run_context) {
int ens_size = enkf_main_get_ensemble_size( enkf_main );
arg_pack_type ** arg_pack_list = util_malloc( ens_size * sizeof * arg_pack_list );
thread_pool_type * submit_threads = thread_pool_alloc( 4 , true );
int iens;
for (iens = 0; iens < ens_size; iens++)
arg_pack_list[iens] = arg_pack_alloc( );
enkf_main_submit_jobs__(enkf_main , run_context , submit_threads , arg_pack_list);
/*
After this join all directories/files for the simulations
have been set up correctly, and all the jobs have been added
to the job_queue manager.
*/
thread_pool_join(submit_threads);
thread_pool_free(submit_threads);
for (iens = 0; iens < ens_size; iens++)
arg_pack_free( arg_pack_list[iens] );
free( arg_pack_list );
}
/**
If all simulations have completed successfully the function will
@ -1693,11 +1730,12 @@ static bool enkf_main_run_step(enkf_main_type * enkf_main ,
{
job_queue_type * job_queue = site_config_get_job_queue(enkf_main->site_config);
job_queue_manager_type * queue_manager = job_queue_manager_alloc( job_queue );
bool restart_queue = true;
/* Start the queue */
if (ert_run_context_get_mode( run_context ) != INIT_ONLY) {
if (site_config_has_job_script( enkf_main->site_config ))
job_queue_manager_start_queue( queue_manager , job_size , verbose_queue );
job_queue_manager_start_queue( queue_manager , job_size , verbose_queue , restart_queue);
else
util_exit("No job script specified, can not start any jobs. Use the key JOB_SCRIPT in the config file\n");
}
@ -2165,76 +2203,69 @@ ert_run_context_type * enkf_main_alloc_ert_run_context_ENKF_ASSIMILATION( const
here...
*/
void enkf_main_create_all_active_config( const enkf_main_type * enkf_main ,
const char * local_config_file ) {
void enkf_main_create_all_active_config( const enkf_main_type * enkf_main) {
bool single_node_update = analysis_config_get_single_node_update( enkf_main->analysis_config );
bool update_results = analysis_config_get_update_results( enkf_main->analysis_config );
const char * update_step_name = "ALL_ACTIVE";
const char * ministep_name = "ALL_ACTIVE";
const char * obsset_name = "ALL_OBS";
const char * dataset_name = "ALL_DATA"; // <- This is is created for possible further use, even if
// single_node_update is true.
FILE * stream = util_fopen( local_config_file , "w");
fprintf(stream , "%-32s %s\n", local_config_get_cmd_string( CREATE_UPDATESTEP ) , update_step_name);
fprintf(stream , "%-32s %s \n", local_config_get_cmd_string( CREATE_OBSSET ) , obsset_name);
fprintf(stream , "%-32s %s %s \n", local_config_get_cmd_string( CREATE_MINISTEP ) , ministep_name , obsset_name);
fprintf(stream , "%-32s %s %s \n" , local_config_get_cmd_string( ATTACH_MINISTEP ), update_step_name , ministep_name);
fprintf(stream , "%-32s %s \n", local_config_get_cmd_string( CREATE_DATASET ) , dataset_name);
if (!single_node_update)
fprintf(stream , "%-32s %s %s \n", local_config_get_cmd_string( ATTACH_DATASET ) , ministep_name , dataset_name);
/* Adding all observation keys */
local_config_type * local_config = enkf_main->local_config;
local_config_clear( local_config );
{
hash_iter_type * obs_iter = enkf_obs_alloc_iter( enkf_main->obs );
while ( !hash_iter_is_complete(obs_iter) ) {
const char * obs_key = hash_iter_get_next_key( obs_iter );
fprintf(stream , "%-32s %s %s\n",local_config_get_cmd_string( ADD_OBS ) , obsset_name , obs_key);
}
hash_iter_free( obs_iter );
}
local_updatestep_type * default_step = local_config_get_updatestep(local_config);
local_ministep_type * ministep = local_config_alloc_ministep( local_config , "ALL_ACTIVE");
local_obsdata_type * obsdata = local_config_alloc_obsset(local_config, "ALL_OBS");
local_dataset_type * all_active_dataset = local_config_alloc_dataset(local_config, "ALL_DATA");
/* Adding all node which can be updated. */
{
stringlist_type * keylist = ensemble_config_alloc_keylist_from_var_type( enkf_main->ensemble_config , PARAMETER + DYNAMIC_STATE + DYNAMIC_RESULT);
int i;
for (i = 0; i < stringlist_get_size( keylist ); i++) {
const char * key = stringlist_iget( keylist , i);
const enkf_config_node_type * config_node = ensemble_config_get_node( enkf_main->ensemble_config , key );
enkf_var_type var_type = enkf_config_node_get_var_type( config_node );
bool add_node = true;
local_updatestep_add_ministep( default_step , ministep );
if ((var_type == DYNAMIC_RESULT) && (!update_results))
add_node = false;
/*
Make sure the funny GEN_KW instance masquerading as
SCHEDULE_PREDICTION_FILE is not added to the soup.
*/
if (util_string_equal(key , "PRED"))
add_node = false;
if (add_node) {
if (single_node_update) {
fprintf(stream , "%-32s %s \n" , local_config_get_cmd_string( CREATE_DATASET ) , key);
fprintf(stream , "%-32s %s %s \n" , local_config_get_cmd_string( ATTACH_DATASET ) , ministep_name , key);
fprintf(stream , "%-32s %s %s\n" , local_config_get_cmd_string( ADD_DATA ) , key , key);
}
fprintf(stream , "%-32s %s %s\n",local_config_get_cmd_string( ADD_DATA ) , dataset_name , key);
/* Adding all observation keys */
{
hash_iter_type * obs_iter = enkf_obs_alloc_iter( enkf_main->obs );
while ( !hash_iter_is_complete(obs_iter) ) {
const char * obs_key = hash_iter_get_next_key( obs_iter );
local_obsdata_node_type * obsdata_node = local_obsdata_node_alloc( obs_key );
local_obsdata_add_node(obsdata, obsdata_node );
}
local_ministep_add_obsdata(ministep, obsdata);
hash_iter_free( obs_iter );
}
stringlist_free( keylist);
}
/* Install the ALL_ACTIVE step as the default. */
fprintf(stream , "%-32s ALL_ACTIVE" , local_config_get_cmd_string( INSTALL_DEFAULT_UPDATESTEP ));
fclose( stream );
/* Adding all node which can be updated. */
{
stringlist_type * keylist = ensemble_config_alloc_keylist_from_var_type( enkf_main->ensemble_config , PARAMETER + DYNAMIC_STATE + DYNAMIC_RESULT);
int i;
for (i = 0; i < stringlist_get_size( keylist ); i++) {
const char * key = stringlist_iget( keylist , i);
const enkf_config_node_type * config_node = ensemble_config_get_node( enkf_main->ensemble_config , key );
enkf_var_type var_type = enkf_config_node_get_var_type( config_node );
bool add_node = true;
if ((var_type == DYNAMIC_RESULT) && (!update_results))
add_node = false;
/*
Make sure the funny GEN_KW instance masquerading as
SCHEDULE_PREDICTION_FILE is not added to the soup.
*/
if (util_string_equal(key , "PRED"))
add_node = false;
if (add_node) {
if (single_node_update) {
local_dataset_type * this_dataset = local_config_alloc_dataset(local_config, key);
local_dataset_add_node(this_dataset, key);
local_ministep_add_dataset(ministep, this_dataset);
}
local_dataset_add_node(all_active_dataset, key);
}
}
stringlist_free( keylist);
}
if (!single_node_update)
local_ministep_add_dataset(ministep, all_active_dataset);
}
}
@ -2777,23 +2808,7 @@ void enkf_main_update_local_updates( enkf_main_type * enkf_main) {
const enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main );
if (enkf_obs_have_obs( enkf_obs )) {
/* First create the default ALL_ACTIVE configuration. */
{
char * all_active_config_file = util_alloc_tmp_file("/tmp" , "enkf_local_config" , true);
enkf_main_create_all_active_config( enkf_main ,
all_active_config_file );
/**
This is where the local configuration files are actually parsed.
*/
local_config_reload( enkf_main->local_config ,
ecl_config_get_grid( enkf_main->ecl_config ),
enkf_main->ensemble_config ,
enkf_main->obs ,
all_active_config_file );
unlink( all_active_config_file );
free(all_active_config_file);
}
enkf_main_create_all_active_config( enkf_main );
}
}

View File

@ -256,11 +256,9 @@ void * enkf_main_scale_obs_std_JOB(void * self, const stringlist_type * args ) {
enkf_main_type * enkf_main = enkf_main_safe_cast( self );
double scale_factor;
util_sscanf_double(stringlist_iget(args, 0), &scale_factor);
if (enkf_main_have_obs(enkf_main)) {
enkf_obs_type * observations = enkf_main_get_obs(enkf_main);
enkf_obs_scale_std(observations, scale_factor);
if (util_sscanf_double(stringlist_iget(args, 0), &scale_factor)) {
analysis_config_type * analysis_config = enkf_main_get_analysis_config( enkf_main );
analysis_config_set_global_std_scaling( analysis_config , scale_factor );
}
return NULL;
}

View File

@ -186,8 +186,9 @@ static conf_class_type * enkf_obs_get_obs_conf_class();
//////////////////////////////////////////////////////////////////////////////////////
#define ENKF_OBS_TYPE_ID 637297
struct enkf_obs_struct {
UTIL_TYPE_ID_DECLARATION;
/** A hash of obs_vector_types indexed by user provided keys. */
vector_type * obs_vector;
hash_type * obs_hash;
@ -218,7 +219,7 @@ static int enkf_obs_get_last_restart( const enkf_obs_type * enkf_obs ) {
return time_map_get_size( enkf_obs->obs_time ) - 1;
}
UTIL_IS_INSTANCE_FUNCTION( enkf_obs , ENKF_OBS_TYPE_ID )
enkf_obs_type * enkf_obs_alloc( const history_type * history ,
time_map_type * external_time_map ,
@ -227,6 +228,7 @@ enkf_obs_type * enkf_obs_alloc( const history_type * history ,
ensemble_config_type * ensemble_config )
{
enkf_obs_type * enkf_obs = util_malloc(sizeof * enkf_obs);
UTIL_TYPE_ID_INIT( enkf_obs , ENKF_OBS_TYPE_ID );
enkf_obs->obs_hash = hash_alloc();
enkf_obs->obs_vector = vector_alloc_new();
enkf_obs->obs_time = time_map_alloc();
@ -356,7 +358,7 @@ static void enkf_obs_get_obs_and_measure_summary(const enkf_obs_type * enkf
if (obs_vector_iget_active( obs_vector , step ) && active_list_iget( active_list , 0 /* Index into the scalar summary observation */)) {
{
const summary_obs_type * summary_obs = obs_vector_iget_node( obs_vector , step );
double_vector_iset( obs_std , active_count , summary_obs_get_std( summary_obs ));
double_vector_iset( obs_std , active_count , summary_obs_get_std( summary_obs ) * summary_obs_get_std_scaling( summary_obs ));
double_vector_iset( obs_value , active_count , summary_obs_get_value( summary_obs ));
last_step = step;
}
@ -518,6 +520,34 @@ void enkf_obs_clear( enkf_obs_type * enkf_obs ) {
/*
Adding inverse observation keys to the enkf_nodes; can be called
several times.
*/
static void enkf_obs_update_keys( enkf_obs_type * enkf_obs ) {
/* First clear all existing observation keys. */
ensemble_config_clear_obs_keys( enkf_obs->ensemble_config );
/* Add new observation keys. */
{
hash_type * map = enkf_obs_alloc_data_map(enkf_obs);
hash_iter_type * iter = hash_iter_alloc(map);
const char * obs_key = hash_iter_get_next_key(iter);
while (obs_key != NULL) {
const char * state_kw = hash_get(map , obs_key);
ensemble_config_add_obs_key(enkf_obs->ensemble_config , state_kw , obs_key);
obs_key = hash_iter_get_next_key(iter);
}
hash_iter_free(iter);
hash_free(map);
}
}
/**
This function will load an observation configuration from the
observation file @config_file.
@ -531,7 +561,7 @@ void enkf_obs_clear( enkf_obs_type * enkf_obs ) {
bool enkf_obs_load(enkf_obs_type * enkf_obs ,
const char * config_file,
double std_cutoff) {
if (enkf_obs->valid) {
int last_report = enkf_obs_get_last_restart( enkf_obs );
conf_class_type * enkf_conf_class = enkf_obs_get_obs_conf_class();
@ -643,6 +673,7 @@ bool enkf_obs_load(enkf_obs_type * enkf_obs ,
conf_instance_free(enkf_conf );
conf_class_free( enkf_conf_class);
enkf_obs_update_keys( enkf_obs );
return true;
} else
return false;

File diff suppressed because it is too large Load Diff

View File

@ -60,11 +60,10 @@ ministep to the updatestep, otherwise it will not be able to do
anything.
CREATE_MINISTEP [NAME_OF_MINISTEP OBSSET_NAME]
CREATE_MINISTEP [NAME_OF_MINISTEP]
-----------------------------------------------
This function will create a new ministep with the name
'NAME_OF_MINISTEP'. The ministep will be based on the observation
set given by OBSSET_NAME (which must be created first).The ministep
'NAME_OF_MINISTEP'. A given OBSSET can be attached to a given ministep.The ministep
is then ready for adding data. Before the ministep can be used you
must attach it to an updatestep with the ATTACH_MINISTEP command
@ -147,7 +146,7 @@ This function will delete the obs 'OBS_KEY' from the obsset
DATASET_DEL_ALL_DATA [NAME_OF_DATASET]
--------------------------------------
This function will delete all the data keys from the dataset
'NAME_OF_MINISTEP'.
'NAME_OF_DATASET'.
OBSSET_DEL_ALL_OBS [NAME_OF_OBSSET]
@ -171,26 +170,13 @@ with name 'DATASTEP_NAME' should have the index 'INDEX' active.
ACTIVE_LIST_ADD_MANY_OBS_INDEX[OBSSET_NAME OBS_KEY N INDEX1 INDEX2 INDEX3 .. INDEXN]
----------------------------------------------------------------------------------------
This function is simular to ACTIVE_LIST_ADD_OBS_INDEX, but it will add many indices.
This function is similar to ACTIVE_LIST_ADD_OBS_INDEX, but it will add many indices.
ACTIVE_LIST_ADD_MANY_DATA_INDEX[DATA_NAME DATA_KEY N INDEX1 INDEX2 INDEX3 .. INDEXN]
------------------------------------------------------------------------------------------
This function is simular to ACTIVE_LIST_ADD_DATA_INDEX, but it will add many indices.
INSTALL_UPDATESTEP [NAME_OF_UPDATESTEP STEP1 STEP2]
----------------------------------------------------
This function will install the updatestep 'NAME_OF_UPDATESTEP' for the
report steps [STEP1,..,STEP2].
INSTALL_DEFAULT_UPDATESTEP [NAME_OF_UPDATESTEP]
-----------------------------------------------
This function will install 'NAME_OF_UPDATESTEP' as the default
updatestep which applies to all report streps where you have not
explicitly set another updatestep with the INSTALL_UPDATESTEP function.
This function is similar to ACTIVE_LIST_ADD_DATA_INDEX, but it will add many indices.
@ -522,7 +508,6 @@ core EnKF updating:
struct local_config_struct {
vector_type * updatestep; /* This is an indexed vector with (pointers to) local_reportsstep instances. */
local_updatestep_type * default_updatestep; /* A default report step returned if no particular report step has been installed for this time index. */
hash_type * updatestep_storage; /* These three hash tables are the 'holding area' for the local_updatestep, */
hash_type * ministep_storage; /* local_ministep instances. */
@ -532,13 +517,26 @@ struct local_config_struct {
};
static void local_config_clear( local_config_type * local_config ) {
/**
Instances of local_updatestep and local_ministep are allocated from
the local_config object, and then subsequently manipulated from the calling scope.
*/
static local_updatestep_type * local_config_alloc_updatestep( local_config_type * local_config , const char * key ) {
local_updatestep_type * updatestep = local_updatestep_alloc( key );
hash_insert_hash_owned_ref( local_config->updatestep_storage , key , updatestep , local_updatestep_free__);
return updatestep;
}
void local_config_clear( local_config_type * local_config ) {
local_config->default_updatestep = NULL;
hash_clear( local_config->updatestep_storage );
hash_clear( local_config->ministep_storage );
hash_clear( local_config->dataset_storage );
hash_clear( local_config->obsdata_storage );
vector_clear( local_config->updatestep );
local_config->default_updatestep = local_config_alloc_updatestep(local_config, "DEFAULT");
}
@ -552,7 +550,6 @@ local_config_type * local_config_alloc( ) {
local_config->ministep_storage = hash_alloc();
local_config->dataset_storage = hash_alloc();
local_config->obsdata_storage = hash_alloc();
local_config->updatestep = vector_alloc_new();
local_config->config_files = stringlist_alloc_new();
local_config_clear( local_config );
@ -561,7 +558,6 @@ local_config_type * local_config_alloc( ) {
void local_config_free(local_config_type * local_config) {
vector_free( local_config->updatestep );
hash_free( local_config->updatestep_storage );
hash_free( local_config->ministep_storage);
hash_free( local_config->dataset_storage);
@ -571,32 +567,12 @@ void local_config_free(local_config_type * local_config) {
/**
Actual report step must have been installed in the
updatestep_storage with local_config_alloc_updatestep() first.
*/
void local_config_set_default_updatestep( local_config_type * local_config , const char * default_key) {
local_updatestep_type * default_updatestep = local_config_get_updatestep( local_config , default_key );
local_config->default_updatestep = default_updatestep;
}
/**
Instances of local_updatestep and local_ministep are allocated from
the local_config object, and then subsequently manipulated from the calling scope.
*/
local_updatestep_type * local_config_alloc_updatestep( local_config_type * local_config , const char * key ) {
local_updatestep_type * updatestep = local_updatestep_alloc( key );
hash_insert_hash_owned_ref( local_config->updatestep_storage , key , updatestep , local_updatestep_free__);
return updatestep;
}
local_ministep_type * local_config_alloc_ministep( local_config_type * local_config , const char * key , const char * obsset_name) {
local_obsdata_type * obsdata = hash_get( local_config->obsdata_storage , obsset_name );
local_ministep_type * ministep = local_ministep_alloc( key , obsdata );
local_ministep_type * local_config_alloc_ministep( local_config_type * local_config , const char * key) {
local_ministep_type * ministep = local_ministep_alloc( key );
hash_insert_hash_owned_ref( local_config->ministep_storage , key , ministep , local_ministep_free__);
return ministep;
}
@ -608,7 +584,6 @@ local_obsdata_type * local_config_alloc_obsset( local_config_type * local_config
}
local_dataset_type * local_config_alloc_dataset( local_config_type * local_config , const char * key ) {
local_dataset_type * dataset = local_dataset_alloc( key );
hash_insert_hash_owned_ref( local_config->dataset_storage , key , dataset , local_dataset_free__);
@ -664,14 +639,8 @@ local_ministep_type * local_config_alloc_ministep_copy( local_config_type * loca
const local_updatestep_type * local_config_iget_updatestep( const local_config_type * local_config , int index) {
const local_updatestep_type * updatestep = vector_safe_iget_const( local_config->updatestep , index );
if (updatestep == NULL)
/*
No particular report step has been installed for this
time-index, revert to the default.
*/
updatestep = local_config->default_updatestep;
local_updatestep_type * local_config_get_updatestep( const local_config_type * local_config) {
local_updatestep_type * updatestep = local_config->default_updatestep;
if (updatestep == NULL)
util_exit("%s: fatal error. No report step information for step:%d - and no default \n",__func__ , index);
@ -680,27 +649,6 @@ const local_updatestep_type * local_config_iget_updatestep( const local_config_t
}
local_updatestep_type * local_config_get_updatestep( const local_config_type * local_config , const char * key) {
return hash_get( local_config->updatestep_storage , key );
}
/**
This will 'install' the updatestep instance identified with 'key'
for report steps [step1,step2]. Observe that the report step must
have been allocated with 'local_config_alloc_updatestep()' first.
*/
void local_config_set_updatestep(local_config_type * local_config, int step1 , int step2 , const char * key) {
local_updatestep_type * updatestep = hash_get( local_config->updatestep_storage , key );
int step;
for ( step = step1; step < step2 + 1; step++)
vector_safe_iset_ref(local_config->updatestep , step , updatestep );
}
/*******************************************************************/
/* Functions related to loading a local config instance from disk. */
@ -739,6 +687,9 @@ const char * local_config_get_cmd_string( local_config_instruction_type cmd ) {
case(CREATE_OBSSET):
return CREATE_OBSSET_STRING;
break;
case(ATTACH_OBSSET):
return ATTACH_OBSSET_STRING;
break;
case(ADD_DATA):
return ADD_DATA_STRING;
break;
@ -757,12 +708,6 @@ const char * local_config_get_cmd_string( local_config_instruction_type cmd ) {
case(ACTIVE_LIST_ADD_MANY_DATA_INDEX):
return ACTIVE_LIST_ADD_MANY_DATA_INDEX_STRING;
break;
case(INSTALL_UPDATESTEP):
return INSTALL_UPDATESTEP_STRING;
break;
case(INSTALL_DEFAULT_UPDATESTEP):
return INSTALL_DEFAULT_UPDATESTEP_STRING;
break;
case(DEL_DATA):
return DEL_DATA_STRING;
break;
@ -947,12 +892,11 @@ static void local_config_init_cmd_table( hash_type * cmd_table ) {
hash_insert_int(cmd_table , CREATE_OBSSET_STRING , CREATE_OBSSET);
hash_insert_int(cmd_table , ADD_DATA_STRING , ADD_DATA);
hash_insert_int(cmd_table , ADD_OBS_STRING , ADD_OBS );
hash_insert_int(cmd_table , ATTACH_OBSSET_STRING , ATTACH_OBSSET);
hash_insert_int(cmd_table , ACTIVE_LIST_ADD_OBS_INDEX_STRING , ACTIVE_LIST_ADD_OBS_INDEX);
hash_insert_int(cmd_table , ACTIVE_LIST_ADD_DATA_INDEX_STRING , ACTIVE_LIST_ADD_DATA_INDEX);
hash_insert_int(cmd_table , ACTIVE_LIST_ADD_MANY_OBS_INDEX_STRING , ACTIVE_LIST_ADD_MANY_OBS_INDEX);
hash_insert_int(cmd_table , ACTIVE_LIST_ADD_MANY_DATA_INDEX_STRING , ACTIVE_LIST_ADD_MANY_DATA_INDEX);
hash_insert_int(cmd_table , INSTALL_UPDATESTEP_STRING , INSTALL_UPDATESTEP);
hash_insert_int(cmd_table , INSTALL_DEFAULT_UPDATESTEP_STRING , INSTALL_DEFAULT_UPDATESTEP);
hash_insert_int(cmd_table , DEL_DATA_STRING , DEL_DATA);
hash_insert_int(cmd_table , DEL_OBS_STRING , DEL_OBS);
hash_insert_int(cmd_table , COPY_DATASET_STRING , COPY_DATASET);
@ -990,10 +934,8 @@ static void local_config_CREATE_UPDATESTEP( local_config_type * config , local_c
static void local_config_CREATE_MINISTEP( local_config_type * config , local_context_type * context , FILE * stream , bool binary) {
char * mini_name = read_alloc_string( stream , binary );
char * obs_name = read_alloc_string( stream , binary );
local_config_alloc_ministep( config , mini_name , obs_name );
local_config_alloc_ministep( config , mini_name );
free( mini_name );
free( obs_name );
}
@ -1009,7 +951,7 @@ static void local_config_ATTACH_MINISTEP( local_config_type * config , local_con
char * update_name = read_alloc_string( stream , binary );
char * mini_name = read_alloc_string( stream , binary );
{
local_updatestep_type * update = local_config_get_updatestep( config , update_name );
local_updatestep_type * update = local_config_get_updatestep( config );
local_ministep_type * ministep = local_config_get_ministep( config , mini_name );
local_updatestep_add_ministep( update , ministep );
}
@ -1054,6 +996,18 @@ static void local_config_ATTACH_DATASET( local_config_type * config , local_cont
free( dataset_name );
}
static void local_config_ATTACH_OBSSET( local_config_type * config , local_context_type * context , FILE * stream , bool binary) {
char * mini_name = read_alloc_string( stream , binary );
char * obsset_name = read_alloc_string( stream , binary );
{
local_ministep_type * ministep = local_config_get_ministep( config , mini_name );
local_obsdata_type * obsdata = hash_get( config->obsdata_storage , obsset_name );
local_ministep_add_obsdata(ministep, obsdata);
}
free( mini_name );
free( obsset_name );
}
static void local_config_ADD_DATA( local_config_type * config , local_context_type * context , FILE * stream , bool binary) {
char * dataset_name = read_alloc_string( stream , binary );
char * data_key = read_alloc_string( stream , binary );
@ -1158,23 +1112,7 @@ static void local_config_ACTIVE_LIST_ADD_MANY_DATA_INDEX( local_config_type * co
int_vector_free( int_vector );
}
static void local_config_INSTALL_UPDATESTEP( local_config_type * config , local_context_type * context , FILE * stream , bool binary) {
char * update_name = read_alloc_string( stream , binary );
{
int step1,step2;
step1 = read_int( stream , binary );
step2 = read_int( stream , binary );
local_config_set_updatestep( config , step1 , step2 , update_name );
}
free( update_name );
}
static void local_config_INSTALL_DEFAULT_UPDATESTEP( local_config_type * config , local_context_type * context , FILE * stream , bool binary) {
char * update_name = read_alloc_string( stream , binary );
local_config_set_default_updatestep( config , update_name );
free( update_name );
}
static void local_config_DEL_DATA( local_config_type * config , local_context_type * context , FILE * stream , bool binary) {
char * dataset_name = read_alloc_string( stream , binary );
@ -1606,6 +1544,9 @@ static void local_config_load_file( local_config_type * local_config ,
case(ATTACH_DATASET):
local_config_ATTACH_DATASET( local_config , context , stream , binary );
break;
case(ATTACH_OBSSET):
local_config_ATTACH_OBSSET( local_config , context , stream , binary );
break;
case(ADD_DATA):
local_config_ADD_DATA( local_config , context , stream , binary );
break;
@ -1624,12 +1565,6 @@ static void local_config_load_file( local_config_type * local_config ,
case(ACTIVE_LIST_ADD_MANY_DATA_INDEX):
local_config_ACTIVE_LIST_ADD_MANY_DATA_INDEX( local_config , context , stream , binary );
break;
case(INSTALL_UPDATESTEP):
local_config_INSTALL_UPDATESTEP( local_config , context , stream , binary );
break;
case(INSTALL_DEFAULT_UPDATESTEP):
local_config_INSTALL_DEFAULT_UPDATESTEP( local_config , context , stream , binary );
break;
case(DEL_DATA):
local_config_DEL_DATA( local_config , context , stream , binary );
break;
@ -1729,7 +1664,33 @@ void local_config_reload( local_config_type * local_config ,
void local_config_fprintf( const local_config_type * local_config , const char * config_file) {
FILE * stream = util_mkdir_fopen( config_file , "w");
/* Start with dumping all the ministep instances. */
/* Write DATASET. */
{
hash_iter_type * hash_iter = hash_iter_alloc( local_config->dataset_storage );
while (!hash_iter_is_complete( hash_iter )) {
const local_dataset_type * dataset = hash_iter_get_next_value( hash_iter );
local_dataset_fprintf( dataset , stream );
}
hash_iter_free( hash_iter );
}
/* Write OBSDATA. */
{
hash_iter_type * hash_iter = hash_iter_alloc( local_config->obsdata_storage );
while (!hash_iter_is_complete( hash_iter )) {
const local_obsdata_type * obsdata = hash_iter_get_next_value( hash_iter );
local_obsdata_fprintf( obsdata , stream );
}
hash_iter_free( hash_iter );
}
/* Write MINISTEP. */
{
hash_iter_type * hash_iter = hash_iter_alloc( local_config->ministep_storage );
@ -1742,37 +1703,36 @@ void local_config_fprintf( const local_config_type * local_config , const char *
}
/* Dumping all the reportstep instances as ATTACH_MINISTEP commands. */
/* Write UPDATESTEP */
if (local_config->default_updatestep)
local_updatestep_fprintf( local_config->default_updatestep , stream );
fclose( stream );
}
void local_config_summary_fprintf( const local_config_type * local_config , const char * config_file) {
FILE * stream = util_mkdir_fopen( config_file , "w");
const local_updatestep_type * updatestep = local_config_get_updatestep( local_config ); // There is only one update step, the default
{
hash_iter_type * hash_iter = hash_iter_alloc( local_config->updatestep_storage );
hash_iter_type * hash_iter = hash_iter_alloc( local_config->ministep_storage );
while (!hash_iter_is_complete( hash_iter )) {
const local_updatestep_type * updatestep = hash_iter_get_next_value( hash_iter );
local_updatestep_fprintf( updatestep , stream );
const local_ministep_type * ministep = hash_iter_get_next_value( hash_iter );
fprintf(stream , "UPDATE_STEP:%s,", local_updatestep_get_name(updatestep));
local_ministep_summary_fprintf( ministep , stream);
}
hash_iter_free( hash_iter );
}
/* Writing out the updatestep / time */
{
int i;
for (i=0; i < vector_get_size( local_config->updatestep ); i++) {
const local_updatestep_type * updatestep = vector_iget_const( local_config->updatestep , i );
if (updatestep != NULL)
fprintf(stream , "%s %s %d %d \n", local_config_get_cmd_string( INSTALL_UPDATESTEP ) , local_updatestep_get_name( updatestep ) , i , i );
}
}
/* Installing the default updatestep */
if (local_config->default_updatestep != NULL)
fprintf(stream , "%s %s\n", local_config_get_cmd_string( INSTALL_DEFAULT_UPDATESTEP ) , local_updatestep_get_name( local_config->default_updatestep ));
fclose( stream );
}
void local_config_fprintf_config( const local_config_type * local_config , FILE * stream) {
fprintf( stream , CONFIG_COMMENTLINE_FORMAT );
fprintf( stream , CONFIG_COMMENT_FORMAT , "Here comes the config files used for setting up local analysis.");

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'local_nodeset.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 'local_dataset.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.
*/
@ -25,7 +25,7 @@
#include <ert/enkf/enkf_macros.h>
#include <ert/enkf/local_ministep.h>
#include <ert/enkf/local_config.h>
#include <ert/enkf/local_config.h>
#include <ert/enkf/active_list.h>
#include <ert/enkf/local_dataset.h>
@ -93,6 +93,10 @@ void local_dataset_add_node(local_dataset_type * dataset, const char *node_key)
hash_insert_hash_owned_ref( dataset->nodes , node_key , active_list_alloc( ALL_ACTIVE ) , active_list_free__);
}
bool local_dataset_has_key(const local_dataset_type * dataset, const char * key) {
return hash_has_key( dataset->nodes , key );
}
void local_dataset_del_node( local_dataset_type * dataset , const char * node_key) {
hash_del( dataset->nodes , node_key );
@ -114,17 +118,33 @@ stringlist_type * local_dataset_alloc_keys( const local_dataset_type * dataset )
void local_dataset_fprintf( const local_dataset_type * dataset , FILE * stream) {
fprintf(stream , "\n%s %s\n", local_config_get_cmd_string( CREATE_DATASET ), local_dataset_get_name(dataset));
{
hash_iter_type * data_iter = hash_iter_alloc( dataset->nodes );
while (!hash_iter_is_complete( data_iter )) {
const char * data_key = hash_iter_get_next_key( data_iter );
active_list_type * active_list = hash_get( dataset->nodes , data_key );
fprintf(stream , "%s %s %s\n", local_config_get_cmd_string( ADD_DATA ) , dataset->name , data_key );
active_list_fprintf( active_list , false , data_key , stream );
active_list_fprintf( active_list , local_dataset_get_name(dataset) , data_key , stream );
}
hash_iter_free( data_iter );
}
}
void local_dataset_summary_fprintf( const local_dataset_type * dataset , FILE * stream) {
{
hash_iter_type * data_iter = hash_iter_alloc( dataset->nodes );
while (!hash_iter_is_complete( data_iter )) {
const char * data_key = hash_iter_get_next_key( data_iter );
fprintf(stream , "NAME OF DATA:%s,", data_key );
active_list_type * active_list = hash_get( dataset->nodes , data_key );
active_list_summary_fprintf( active_list , local_dataset_get_name(dataset) , data_key , stream);
}
hash_iter_free( data_iter );
}
}
int local_dataset_get_size( const local_dataset_type * dataset ) {

View File

@ -28,6 +28,7 @@
#include <ert/enkf/local_ministep.h>
#include <ert/enkf/local_dataset.h>
#include <ert/enkf/local_obsdata.h>
#include <ert/enkf/local_obsdata_node.h>
/**
This file implements a 'ministep' configuration for active /
@ -65,11 +66,18 @@ struct local_ministep_struct {
UTIL_SAFE_CAST_FUNCTION(local_ministep , LOCAL_MINISTEP_TYPE_ID)
UTIL_IS_INSTANCE_FUNCTION(local_ministep , LOCAL_MINISTEP_TYPE_ID)
local_ministep_type * local_ministep_alloc(const char * name , local_obsdata_type * observations) {
local_ministep_type * local_ministep_alloc(const char * name) {
local_ministep_type * ministep = util_malloc( sizeof * ministep );
ministep->name = util_alloc_string_copy( name );
ministep->observations = observations;
char* obsdata_name = "OBSDATA_";
char* result = malloc(strlen(obsdata_name)+strlen(name)+1);
strcpy(result, obsdata_name);
strcat(result, name);
ministep->observations = local_obsdata_alloc(result);
ministep->datasets = hash_alloc();
UTIL_TYPE_ID_INIT( ministep , LOCAL_MINISTEP_TYPE_ID);
@ -106,6 +114,7 @@ local_ministep_type * local_ministep_alloc_copy( const local_ministep_type * src
void local_ministep_free(local_ministep_type * ministep) {
free(ministep->name);
hash_free( ministep->datasets );
local_obsdata_free(ministep->observations);
free( ministep );
}
@ -135,7 +144,31 @@ void local_ministep_add_dataset( local_ministep_type * ministep , const local_da
hash_insert_ref( ministep->datasets , local_dataset_get_name( dataset ) , dataset );
}
void local_ministep_add_obsdata( local_ministep_type * ministep , local_obsdata_type * obsdata) {
if (ministep->observations == NULL)
ministep->observations = obsdata;
else { // Add nodes from input observations to existing observations
int iobs;
for (iobs = 0; iobs < local_obsdata_get_size( obsdata ); iobs++) {
local_obsdata_node_type * obs_node = local_obsdata_iget( obsdata , iobs );
local_obsdata_node_type * new_node = local_obsdata_node_alloc_copy(obs_node);
local_ministep_add_obsdata_node(ministep, new_node);
}
}
}
void local_ministep_add_obsdata_node( local_ministep_type * ministep , local_obsdata_node_type * obsdatanode) {
local_obsdata_type * obsdata = local_ministep_get_obsdata(ministep);
local_obsdata_add_node(obsdata, obsdatanode);
}
bool local_ministep_has_dataset( const local_ministep_type * ministep, const char * dataset_name) {
return hash_has_key( ministep->datasets, dataset_name );
}
int local_ministep_get_num_dataset( const local_ministep_type * ministep ) {
return hash_get_size( ministep->datasets );
}
local_dataset_type * local_ministep_get_dataset( const local_ministep_type * ministep, const char * dataset_name) {
return hash_get( ministep->datasets, dataset_name );
@ -145,29 +178,108 @@ local_obsdata_type * local_ministep_get_obsdata( const local_ministep_type * min
return ministep->observations;
}
const char * local_ministep_get_name( const local_ministep_type * ministep ) {
return ministep->name;
}
/*****************************************************************/
hash_iter_type * local_ministep_alloc_dataset_iter( const local_ministep_type * ministep ) {
return hash_iter_alloc( ministep->datasets );
}
/*****************************************************************/
void local_ministep_fprintf( const local_ministep_type * ministep , FILE * stream ) {
fprintf(stream , "%s %s %s\n", local_config_get_cmd_string( CREATE_MINISTEP ), ministep->name , local_obsdata_get_name( ministep->observations) );
/*
The keys referenced in the local_ministep_alloc_data_keys() and
local_ministep_has_data_key() are the underlying *enkf_node* keys -
not the keys used to index the local_datasets managed by this
local_ministep.
*/
stringlist_type * local_ministep_alloc_data_keys( const local_ministep_type * ministep ) {
stringlist_type * keys = stringlist_alloc_new();
{
hash_iter_type * dataset_iter = hash_iter_alloc( ministep->datasets );
while (!hash_iter_is_complete( dataset_iter )) {
const char * dataset_key = hash_iter_get_next_key( dataset_iter );
fprintf(stream , "%s %s %s\n", local_config_get_cmd_string( ATTACH_DATASET ) , ministep->name , dataset_key );
const local_dataset_type * dataset = hash_iter_get_next_value( dataset_iter );
stringlist_type * node_keys = local_dataset_alloc_keys( dataset );
for (int i=0; i < stringlist_get_size( node_keys ); i++) {
const char * data_key = stringlist_iget( node_keys , i );
if (!stringlist_contains(keys , data_key ))
stringlist_append_copy( keys , data_key );
}
stringlist_free( node_keys );
}
hash_iter_free( dataset_iter );
}
return keys;
}
bool local_ministep_has_data_key(const local_ministep_type * ministep , const char * key) {
bool has_key = false;
{
hash_iter_type * dataset_iter = hash_iter_alloc( ministep->datasets );
while (true) {
const local_dataset_type * dataset = hash_iter_get_next_value( dataset_iter );
if (dataset) {
if (local_dataset_has_key( dataset , key)) {
has_key = true;
break;
}
} else
break;
}
hash_iter_free( dataset_iter );
}
return has_key;
}
/*****************************************************************/
void local_ministep_fprintf( const local_ministep_type * ministep , FILE * stream ) {
fprintf(stream , "\n%s %s\n", local_config_get_cmd_string( CREATE_MINISTEP ), ministep->name);
{
/* Dumping all the DATASET instances. */
{
hash_iter_type * dataset_iter = hash_iter_alloc( ministep->datasets );
while (!hash_iter_is_complete( dataset_iter )) {
const local_dataset_type * dataset = hash_iter_get_next_value( dataset_iter );
fprintf(stream , "%s %s %s\n", local_config_get_cmd_string( ATTACH_DATASET ) , ministep->name , local_dataset_get_name( dataset ) );
}
hash_iter_free( dataset_iter );
}
/* Only one OBSDATA */
local_obsdata_type * obsdata = local_ministep_get_obsdata(ministep);
local_obsdata_fprintf( obsdata , stream );
fprintf(stream , "%s %s %s\n", local_config_get_cmd_string( ATTACH_OBSSET ) , ministep->name, local_obsdata_get_name(obsdata));
}
}
void local_ministep_summary_fprintf( const local_ministep_type * ministep , FILE * stream) {
fprintf(stream , "MINISTEP:%s,", ministep->name);
{
/* Dumping all the DATASET instances. */
{
hash_iter_type * dataset_iter = hash_iter_alloc( ministep->datasets );
while (!hash_iter_is_complete( dataset_iter )) {
const local_dataset_type * dataset = hash_iter_get_next_value( dataset_iter );
local_dataset_summary_fprintf(dataset, stream);
}
hash_iter_free( dataset_iter );
}
/* Only one OBSDATA */
local_obsdata_type * obsdata = local_ministep_get_obsdata(ministep);
local_obsdata_summary_fprintf( obsdata , stream);
fprintf(stream, "\n");
}
}

View File

@ -22,6 +22,7 @@
#include <ert/util/vector.h>
#include <ert/util/hash.h>
#include <ert/enkf/local_config.h>
#include <ert/enkf/local_obsdata.h>
@ -145,3 +146,29 @@ void local_obsdata_reset_tstep_list( local_obsdata_type * data , const int_vecto
local_obsdata_node_reset_tstep_list(node, step_list);
}
}
void local_obsdata_fprintf( const local_obsdata_type * obsdata , FILE * stream ) {
fprintf(stream , "\n%s %s\n", local_config_get_cmd_string( CREATE_OBSSET ) , local_obsdata_get_name(obsdata));
{
int i;
for (i=0; i < local_obsdata_get_size( obsdata ); i++ ) {
local_obsdata_node_type * node = local_obsdata_iget( obsdata , i );
const char * obs_key = local_obsdata_node_get_key(node);
fprintf(stream , "%s %s %s\n", local_config_get_cmd_string( ADD_OBS ) , local_obsdata_get_name(obsdata) , obs_key );
}
}
}
void local_obsdata_summary_fprintf( const local_obsdata_type * obsdata , FILE * stream) {
fprintf(stream , "LOCAL OBSDATA NAME:%s,LOCAL OBSDATA SIZE:%d,", local_obsdata_get_name(obsdata), local_obsdata_get_size(obsdata) );
int i;
for (i = 0; i < local_obsdata_get_size( obsdata ); i++ ) {
local_obsdata_node_type * node = local_obsdata_iget( obsdata , i );
const char * obs_key = local_obsdata_node_get_key(node);
fprintf(stream , "OBSERVATION:%s,", obs_key );
}
}

View File

@ -57,6 +57,16 @@ local_updatestep_type * local_updatestep_alloc( const char * name ) {
}
bool local_updatestep_has_data_key( const local_updatestep_type * update_step , const char * key) {
bool has_key = false;
for (int i = 0; i < vector_get_size( update_step->ministep ); i++) {
const local_ministep_type * ministep = vector_iget_const( update_step->ministep , i );
if (local_ministep_has_data_key(ministep, key))
has_key = true;
}
return has_key;
}
/**
Observe that use_count values are not copied.
*/
@ -110,7 +120,7 @@ const char * local_updatestep_get_name( const local_updatestep_type * updatestep
void local_updatestep_fprintf( const local_updatestep_type * updatestep , FILE * stream) {
fprintf(stream , "%s %s\n" , local_config_get_cmd_string( CREATE_UPDATESTEP ) , updatestep->name );
fprintf(stream , "\n%s %s\n" , local_config_get_cmd_string( CREATE_UPDATESTEP ) , updatestep->name );
{
int i;
for (i=0; i < vector_get_size( updatestep->ministep ); i++) {

View File

@ -139,12 +139,12 @@ static void obs_block_free__( void * arg ) {
}
void obs_block_deactivate( obs_block_type * obs_block , int iobs , const char * msg) {
void obs_block_deactivate( obs_block_type * obs_block , int iobs , bool verbose , const char * msg) {
if (obs_block->active_mode[ iobs ] == ACTIVE) {
printf("Deactivating: %s(%d) : %s \n",obs_block->obs_key , iobs , msg);
if (verbose)
printf("Deactivating: %s(%d) : %s \n",obs_block->obs_key , iobs , msg);
obs_block->active_mode[ iobs ] = DEACTIVATED;
obs_block->active_size--;
}
}
@ -692,3 +692,54 @@ int obs_data_get_active_size( const obs_data_type * obs_data ) {
int obs_data_get_num_blocks( const obs_data_type * obs_data ) {
return vector_get_size( obs_data->data );
}
int obs_data_get_total_size( const obs_data_type * obs_data ) {
int total_size = 0;
for (int block_nr = 0; block_nr < vector_get_size( obs_data->data ); block_nr++) {
const obs_block_type * obs_block = vector_iget_const( obs_data->data , block_nr );
total_size += obs_block->size;
}
return total_size;
}
static const obs_block_type * obs_data_lookup_block( const obs_data_type * obs_data, int total_index , int * block_offset) {
if (total_index < obs_data_get_total_size( obs_data )) {
const obs_block_type * obs_block;
int total_offset = 0;
int block_index = 0;
int block_size;
while (true) {
obs_block = vector_iget_const( obs_data->data , block_index );
block_size = obs_block->size;
if ((block_size + total_offset) > total_index)
break;
total_offset += block_size;
block_index++;
}
*block_offset = total_offset;
return obs_block;
} else {
util_abort("%s: could not lookup obs-block \n",__func__);
return NULL;
}
}
double obs_data_iget_value( const obs_data_type * obs_data , int total_index ) {
int total_offset;
const obs_block_type * obs_block = obs_data_lookup_block( obs_data , total_index , &total_offset );
return obs_block_iget_value( obs_block , total_index - total_offset );
}
double obs_data_iget_std( const obs_data_type * obs_data , int total_index ) {
int total_offset;
const obs_block_type * obs_block = obs_data_lookup_block( obs_data , total_index , &total_offset );
return obs_block_iget_std( obs_block , total_index - total_offset );
}

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2014 Statoil ASA, Norway.
The file 'run_arg.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 'run_arg.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.
*/
@ -27,18 +27,17 @@
#define RUN_ARG_TYPE_ID 66143287
#define INVALID_QUEUE_INDEX -99
struct run_arg_struct {
UTIL_TYPE_ID_DECLARATION;
int iens;
bool active; /* Is this state object active at all - used for instance in ensemble experiments where only some of the members are integrated. */
int init_step_parameters; /* The report step we initialize parameters from - will often be equal to step1, but can be different. */
state_enum init_state_parameter; /* Whether we should init from a forecast or an analyzed state - parameters. */
state_enum init_state_dynamic; /* Whether we should init from a forecast or an analyzed state - dynamic state variables. */
int max_internal_submit; /* How many times the enkf_state object should try to resubmit when the queueu has said everything is OK - but the load fails. */
int num_internal_submit;
int max_internal_submit; /* How many times the enkf_state object should try to resubmit when the queueu has said everything is OK - but the load fails. */
int num_internal_submit;
int load_start; /* When loading back results - start at this step. */
int step1; /* The forward model is integrated: step1 -> step2 */
int step2;
@ -46,7 +45,7 @@ struct run_arg_struct {
char * run_path; /* The currently used runpath - is realloced / freed for every step. */
run_mode_type run_mode; /* What type of run this is */
int queue_index; /* The job will in general have a different index in the queue than the iens number. */
enkf_fs_type * init_fs;
enkf_fs_type * result_fs;
enkf_fs_type * update_target_fs;
@ -55,28 +54,28 @@ struct run_arg_struct {
/* Return value - set by the called routine!! */
run_status_type run_status;
};
UTIL_SAFE_CAST_FUNCTION( run_arg , RUN_ARG_TYPE_ID )
UTIL_IS_INSTANCE_FUNCTION( run_arg , RUN_ARG_TYPE_ID )
static run_arg_type * run_arg_alloc(enkf_fs_type * init_fs ,
enkf_fs_type * result_fs ,
enkf_fs_type * update_target_fs ,
int iens ,
run_mode_type run_mode ,
int init_step_parameters ,
static run_arg_type * run_arg_alloc(enkf_fs_type * init_fs ,
enkf_fs_type * result_fs ,
enkf_fs_type * update_target_fs ,
int iens ,
run_mode_type run_mode ,
int init_step_parameters ,
state_enum init_state_parameter ,
state_enum init_state_dynamic ,
int step1 ,
int step1 ,
int step2 ,
int iter ,
const char * runpath) {
run_arg_type * run_arg = util_malloc(sizeof * run_arg );
UTIL_TYPE_ID_INIT(run_arg , RUN_ARG_TYPE_ID);
run_arg->init_fs = init_fs;
run_arg->result_fs = result_fs;
run_arg->update_target_fs = update_target_fs;
@ -91,24 +90,25 @@ static run_arg_type * run_arg_alloc(enkf_fs_type * init_fs ,
run_arg->iter = iter;
run_arg->run_path = util_alloc_abs_path( runpath );
run_arg->num_internal_submit = 0;
run_arg->queue_index = INVALID_QUEUE_INDEX;
if (step1 == 0)
run_arg->load_start = 1;
else
run_arg->load_start = step1;
return run_arg;
}
run_arg_type * run_arg_alloc_ENKF_ASSIMILATION(enkf_fs_type * fs ,
int iens ,
run_arg_type * run_arg_alloc_ENKF_ASSIMILATION(enkf_fs_type * fs ,
int iens ,
state_enum init_state_parameter ,
state_enum init_state_dynamic ,
int step1 ,
int step1 ,
int step2 ,
const char * runpath) {
return run_arg_alloc(fs,fs,fs,iens,ENKF_ASSIMILATION,step1 , init_state_parameter, init_state_dynamic , step1 , step2 , 0 , runpath);
}
@ -157,7 +157,10 @@ void run_arg_increase_submit_count( run_arg_type * run_arg ) {
void run_arg_set_queue_index( run_arg_type * run_arg , int queue_index) {
run_arg->queue_index = queue_index;
if (run_arg->queue_index == INVALID_QUEUE_INDEX)
run_arg->queue_index = queue_index;
else
util_abort("%s: attempt to reset run_arg->queue_index. These objects should not be recycled\n",__func__);
}
@ -222,13 +225,18 @@ int run_arg_get_parameter_init_step( const run_arg_type * run_arg ) {
void run_arg_set_inactive( run_arg_type * run_arg ) {
run_arg->active = false;
int run_arg_get_queue_index( const run_arg_type * run_arg ) {
if (run_arg->queue_index == INVALID_QUEUE_INDEX)
util_abort("%s: sorry internal error - asking for the queue_index in a not-initialized run_arg object.\n" , __func__);
return run_arg->queue_index;
}
int run_arg_get_queue_index( const run_arg_type * run_arg ) {
return run_arg->queue_index;
bool run_arg_is_submitted( const run_arg_type * run_arg ) {
if (run_arg->queue_index == INVALID_QUEUE_INDEX)
return false;
else
return true;
}

View File

@ -581,11 +581,6 @@ static void site_config_set_job_queue__(site_config_type * site_config, job_driv
site_config->driver_type_site = driver_type;
}
void site_config_set_job_queue(site_config_type * site_config, const char * queue_name) {
job_driver_type driver_type = job_queue_lookup_driver_name(queue_name);
site_config_set_job_queue__(site_config, driver_type);
}
bool site_config_queue_is_running(const site_config_type * site_config) {
return job_queue_is_running(site_config->job_queue);
}

View File

@ -75,7 +75,7 @@ void test_iget(ert_test_context_type * test_context) {
enkf_main_type * enkf_main = ert_test_context_get_main( test_context );
enkf_obs_type * enkf_obs = enkf_main_get_obs( enkf_main );
test_assert_int_equal( 31 , enkf_obs_get_size( enkf_obs ) );
test_assert_int_equal( 32 , enkf_obs_get_size( enkf_obs ) );
for (int iobs = 0; iobs < enkf_obs_get_size( enkf_obs ); iobs++) {
obs_vector_type * vec1 = enkf_obs_iget_vector( enkf_obs , iobs );
obs_vector_type * vec2 = enkf_obs_get_vector( enkf_obs , obs_vector_get_key( vec1 ));

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2014 Statoil ASA, Norway.
The file 'ert_run_context.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 'ert_run_context.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>
@ -26,6 +26,38 @@
#include <ert/enkf/run_arg.h>
#include <ert/enkf/enkf_fs.h>
void call_get_queue_index( void * arg ) {
run_arg_type * run_arg = run_arg_safe_cast( arg );
run_arg_get_queue_index( run_arg );
}
void call_set_queue_index( void * arg ) {
run_arg_type * run_arg = run_arg_safe_cast( arg );
run_arg_set_queue_index( run_arg , 88 );
}
void test_queue_index() {
test_work_area_type * test_area = test_work_area_alloc("run_arg/ENS");
{
enkf_fs_type * fs = enkf_fs_create_fs("sim" , BLOCK_FS_DRIVER_ID , NULL , true);
run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT(fs , 0 , 6 , "path");
test_assert_false( run_arg_is_submitted( run_arg ) );
test_assert_util_abort("run_arg_get_queue_index" , call_get_queue_index , run_arg );
run_arg_set_queue_index(run_arg, 78);
test_assert_true( run_arg_is_submitted( run_arg ) );
test_assert_int_equal( 78 , run_arg_get_queue_index( run_arg ));
test_assert_util_abort("run_arg_set_queue_index" , call_set_queue_index , run_arg );
run_arg_free( run_arg );
enkf_fs_decref( fs );
}
test_work_area_free( test_area );
}
void call_get_result_fs( void * arg ) {
run_arg_type * run_arg = run_arg_safe_cast( arg );
run_arg_get_result_fs( run_arg );
@ -51,7 +83,7 @@ void test_SMOOTHER_RUN( ) {
test_assert_ptr_equal( run_arg_get_result_fs( run_arg ) , sim_fs );
test_assert_ptr_equal( run_arg_get_update_target_fs( run_arg ) , target_fs );
run_arg_free( run_arg );
enkf_fs_decref( sim_fs );
enkf_fs_decref( target_fs );
}
@ -71,7 +103,7 @@ void test_INIT_ONLY( ) {
test_assert_util_abort( "run_arg_get_result_fs" , call_get_result_fs , run_arg );
test_assert_util_abort( "run_arg_get_update_target_fs" , call_get_update_target_fs , run_arg );
run_arg_free( run_arg );
enkf_fs_decref( init_fs );
}
test_work_area_free( test_area );
@ -82,10 +114,10 @@ void test_ENSEMBLE_EXPERIMENT( ) {
test_work_area_type * test_area = test_work_area_alloc("run_arg/ENS");
{
enkf_fs_type * fs = enkf_fs_create_fs("sim" , BLOCK_FS_DRIVER_ID , NULL , true);
run_arg_type * run_arg = run_arg_alloc_ENSEMBLE_EXPERIMENT(fs , 0 , 6 , "path");
test_assert_true( run_arg_is_instance( run_arg ));
test_assert_ptr_equal( run_arg_get_init_fs( run_arg ) , fs );
test_assert_ptr_equal( run_arg_get_result_fs( run_arg ) , fs );
test_assert_util_abort( "run_arg_get_update_target_fs" , call_get_update_target_fs , run_arg );
@ -102,6 +134,7 @@ void test_ENKF_ASSIMILATION( ) {
}
int main(int argc , char ** argv) {
test_queue_index();
test_SMOOTHER_RUN();
test_INIT_ONLY();
test_ENSEMBLE_EXPERIMENT();

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'arg_pack.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 'arg_pack.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 __ARG_PACK_H__
@ -42,12 +42,12 @@ typedef void * (arg_node_copyc_ftype) (const void *);
void arg_pack_lock(arg_pack_type *);
void arg_pack_fscanf(arg_pack_type * arg , FILE * stream, const char * filename);
void arg_pack_fprintf(const arg_pack_type * , FILE * );
void arg_pack_append_ptr(arg_pack_type * , void *);
void arg_pack_append_const_ptr(arg_pack_type * , const void *);
void arg_pack_append_owned_ptr(arg_pack_type * , void * , arg_node_free_ftype *);
void arg_pack_append_copy(arg_pack_type * , void * , arg_node_copyc_ftype * , arg_node_free_ftype *);
/*
void arg_pack_iset_copy(arg_pack_type * arg_pack , int index , void * ptr, arg_node_copyc_ftype * copyc , arg_node_free_ftype * freef);
void arg_pack_iset_ptr(arg_pack_type * arg_pack, int index , void * ptr);
@ -59,9 +59,9 @@ typedef void * (arg_node_copyc_ftype) (const void *);
node_ctype arg_pack_iget_ctype(const arg_pack_type * arg_pack ,int index);
int arg_pack_size( const arg_pack_type * arg_pack );
/*****************************************************************/
#define APPEND_TYPED_HEADER(type) void arg_pack_append_ ## type (arg_pack_type * , type);
#define IGET_TYPED_HEADER(type) type arg_pack_iget_ ## type( const arg_pack_type * , int );
#define ISET_TYPED_HEADER(type) void arg_pack_iset_ ## type( arg_pack_type * , int , type value);
@ -95,4 +95,4 @@ ISET_TYPED_HEADER(size_t)
}
#endif
#endif

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'buffer.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 'buffer.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 __BUFFER_H__
@ -28,6 +28,7 @@ extern "C" {
#include <string.h>
#include <time.h>
#include <ert/util/type_macros.h>
#include <ert/util/ssize_t.h>
@ -49,13 +50,10 @@ extern "C" {
size_t buffer_fread(buffer_type * buffer , void * target_ptr , size_t item_size , size_t items);
size_t buffer_safe_fwrite(buffer_type * buffer , const void * src_ptr , size_t item_size , size_t items);
size_t buffer_fwrite(buffer_type * buffer , const void * src_ptr , size_t item_size , size_t items);
const char * buffer_fread_string(buffer_type * buffer);
char * buffer_fread_alloc_string(buffer_type * buffer);
void buffer_fwrite_string(buffer_type * buffer , const char * string);
void buffer_summarize(const buffer_type * buffer , const char *);
void buffer_fwrite_char_ptr(buffer_type * buffer , const char * string_ptr );
void buffer_terminate_char_ptr( buffer_type * buffer );
void buffer_strcat(buffer_type * buffer , const char * string);
void buffer_fwrite_char(buffer_type * buffer , char value);
void buffer_fwrite_int(buffer_type * buffer , int value);
void buffer_fskip_bool(buffer_type * buffer);
@ -72,21 +70,22 @@ extern "C" {
size_t buffer_get_remaining_size(const buffer_type * buffer);
void * buffer_get_data(const buffer_type * buffer);
void * buffer_alloc_data_copy(const buffer_type * buffer);
void * buffer_iget_data(const buffer_type * buffer, size_t offset);
void buffer_stream_fwrite( const buffer_type * buffer , FILE * stream );
int buffer_fgetc( buffer_type * buffer );
void buffer_fseek(buffer_type * buffer , ssize_t offset , int whence);
void buffer_fskip(buffer_type * buffer, ssize_t offset);
void buffer_clear( buffer_type * buffer );
void buffer_fskip_int(buffer_type * buffer);
void buffer_fskip_time_t(buffer_type * buffer);
time_t buffer_fread_time_t(buffer_type * buffer);
void buffer_fwrite_time_t(buffer_type * buffer , time_t value);
void buffer_rewind(buffer_type * buffer );
double buffer_fread_double(buffer_type * buffer);
void buffer_fwrite_double(buffer_type * buffer , double value);
size_t buffer_stream_fwrite_n( const buffer_type * buffer , size_t offset , ssize_t write_size , FILE * stream );
void buffer_stream_fprintf( const buffer_type * buffer , FILE * stream );
void buffer_stream_fread( buffer_type * buffer , size_t byte_size , FILE * stream);
@ -97,6 +96,13 @@ extern "C" {
size_t buffer_fwrite_compressed(buffer_type * buffer, const void * ptr , size_t byte_size);
size_t buffer_fread_compressed(buffer_type * buffer , size_t compressed_size , void * target_ptr , size_t target_size);
#endif
#include "buffer_string.h"
UTIL_IS_INSTANCE_HEADER( buffer );
UTIL_SAFE_CAST_HEADER( buffer );
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,7 @@
/*
These functions are very deprecated and should not be used further.
*/
const char * buffer_fread_string(buffer_type * buffer);
char * buffer_fread_alloc_string(buffer_type * buffer);
void buffer_fwrite_string(buffer_type * buffer , const char * string);

View File

@ -49,7 +49,7 @@ bool hash_has_key(const hash_type *, const char *);
void * hash_pop( hash_type * hash , const char * key);
void * hash_safe_get( const hash_type * hash , const char * key );
void * hash_get(const hash_type *, const char *);
char * hash_get_string(hash_type * , const char *);
char * hash_get_string(const hash_type * , const char *);
void hash_del(hash_type *, const char *);
void hash_safe_del(hash_type * , const char * );
void hash_clear(hash_type *);
@ -75,11 +75,11 @@ hash_type * hash_alloc_from_options(const stringlist_type *);
bool hash_add_option( hash_type * hash, const char * key_value);
int hash_inc_counter(hash_type * hash , const char * counter_key);
int hash_get_counter(hash_type * hash , const char * key);
int hash_get_counter(const hash_type * hash , const char * key);
void hash_insert_int(hash_type * , const char * , int);
int hash_get_int(hash_type * , const char *);
int hash_get_int(const hash_type * , const char *);
void hash_insert_double(hash_type * , const char * , double);
double hash_get_double(hash_type * , const char *);
double hash_get_double(const hash_type * , const char *);
void hash_apply( hash_type * hash , hash_apply_ftype * func);
UTIL_IS_INSTANCE_HEADER(hash);

View File

@ -68,6 +68,7 @@ typedef enum {
unsigned int rng_forward( rng_type * rng );
double rng_get_double( rng_type * rng );
int rng_get_int( rng_type * rng , int max_value );
unsigned int rng_get_max_int(const rng_type * rng);
double rng_std_normal( rng_type * rng );
void rng_shuffle_int( rng_type * rng , int * data , size_t num_elements);

View File

@ -1,30 +1,31 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'subst_list.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 'subst_list.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 __SUBST_H__
#define __SUBST_H__
#ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdbool.h>
#include <ert/util/type_macros.h>
#include <ert/util/subst_func.h>
typedef struct subst_list_struct subst_list_type;
@ -43,7 +44,7 @@ extern "C" {
void subst_list_prepend_copy(subst_list_type * , const char * , const char * , const char * doc_string);
void subst_list_prepend_ref(subst_list_type * , const char * , const char * , const char * doc_string);
void subst_list_prepend_owned_ref(subst_list_type * , const char * , const char * , const char * doc_string);
bool subst_list_filter_file(const subst_list_type * , const char * , const char * );
bool subst_list_update_file(const subst_list_type * , const char * );
bool subst_list_update_string(const subst_list_type * , char ** );
@ -57,8 +58,9 @@ extern "C" {
bool subst_list_has_key( const subst_list_type * subst_list , const char * key);
char * subst_list_alloc_string_representation( const subst_list_type * subst_list );
int subst_list_add_from_string( subst_list_type * subst_list , const char * arg_string, bool append);
#ifdef __cplusplus
UTIL_IS_INSTANCE_HEADER( subst_list );
#ifdef __cplusplus
}
#endif
#endif

View File

@ -29,7 +29,7 @@ extern "C" {
void thread_pool_restart( thread_pool_type * tp );
void * thread_pool_iget_return_value( const thread_pool_type * pool , int queue_index );
int thread_pool_get_max_running( const thread_pool_type * pool );
bool thread_pool_try_join(thread_pool_type * pool, int timeout_seconds);
#ifdef __cplusplus
}
#endif

View File

@ -104,6 +104,7 @@ typedef enum {left_pad = 0,
//#define UTIL_CXX_MALLOC(var , num_elm) (typeof (var)) util_malloc( (num_elm) * sizeof var)
void util_bitmask_on(int * , int );
char * util_get_timezone();
time_t util_make_datetime(int , int , int , int , int , int );
void util_fprintf_datetime(time_t , FILE * );
void util_fprintf_date(time_t , FILE * );

View File

@ -67,6 +67,7 @@ set(header_files
type_vector_functions.h
ui_return.h
struct_vector.h
buffer_string.h
)
set( test_source test_util.c )

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'arg_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 'arg_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>
@ -61,14 +61,14 @@
void some_function(const char * arg1 , int arg2 , double arg3) {
.....
}
}
void some_function__(void * __arg_pack) {
arg_pack_type * arg_pack = arg_pack_safe_cast( __arg_pack );
const char * arg1 = arg_pack_iget_ptr( arg_pack , 0);
int arg2 = arg_pack_iget_int( arg_pack , 1);
double arg3 = arg_pack_iget_double(arg_pack , 2);
double arg3 = arg_pack_iget_double(arg_pack , 2);
some_function( arg1 , arg2 , arg3 );
}
@ -76,7 +76,7 @@
.....
arg_pack_type * arg_pack = arg_pack_alloc();
arg_pack_append_ptr(arg_pack , "ARG1");
arg_pack_append_ptr(arg_pack , "ARG1");
arg_pack_append_int(arg_pack , 1);
arg_pack_append_double(arg_pack , 3.14159265);
@ -84,7 +84,7 @@
*/
#define ARG_PACK_TYPE_ID 668268
@ -101,10 +101,10 @@ typedef struct {
struct arg_pack_struct {
UTIL_TYPE_ID_DECLARATION;
int size; /* The number of arguments appended to this arg_pack instance. */
int size; /* The number of arguments appended to this arg_pack instance. */
int alloc_size; /* The number of nodes allocated to this arg_pack - will in general be greater than size. */
bool locked; /* To insure against unwaranted modifictaions - you can explicitly lock the arg_pack instance. This only */
arg_node_type **nodes; /* Vector of nodes */
bool locked; /* To insure against unwaranted modifictaions - you can explicitly lock the arg_pack instance. This only */
arg_node_type **nodes; /* Vector of nodes */
};
@ -126,7 +126,7 @@ static void arg_node_realloc_buffer(arg_node_type * node , int new_size) {
static void __arg_node_assert_type(const arg_node_type * node , node_ctype arg_type) {
if (arg_type != node->ctype)
if (arg_type != node->ctype)
util_abort("%s: asked for type:\'%s\' inserted as:\'%s\' - aborting \n" , __func__ , node_ctype_name(arg_type) , node_ctype_name(node->ctype));
}
@ -182,7 +182,7 @@ static size_t arg_node_get_size_t( const arg_node_type * node) {
arg_pack, as that will delete the pointer you are using as well.
*/
static void * arg_node_get_ptr(const arg_node_type * node , bool get_ptr) {
if (get_ptr) {
if (node->ctype != CTYPE_VOID_POINTER)
@ -250,7 +250,7 @@ static void arg_node_set_size_t( arg_node_type * node , size_t value) {
static void arg_node_set_ptr(arg_node_type * node , const void * ptr , arg_node_copyc_ftype * copyc , arg_node_free_ftype * destructor) {
node->ctype = CTYPE_VOID_POINTER;
node->destructor = destructor;
node->copyc = copyc;
node->copyc = copyc;
if (copyc != NULL)
node->buffer = copyc( ptr );
else
@ -264,7 +264,7 @@ static void arg_node_set_ptr(arg_node_type * node , const void * ptr , arg_node_
static void arg_node_clear(arg_node_type * node) {
if (node->ctype == CTYPE_VOID_POINTER) {
if (node->destructor != NULL)
if (node->destructor != NULL)
node->destructor( node->buffer );
/* When you have cleared - must not reuse the thing. */
node->destructor = NULL;
@ -338,7 +338,7 @@ UTIL_SAFE_CAST_FUNCTION_CONST( arg_pack , ARG_PACK_TYPE_ID)
UTIL_IS_INSTANCE_FUNCTION(arg_pack , ARG_PACK_TYPE_ID)
static void __arg_pack_assert_index(const arg_pack_type * arg , int iarg) {
if (iarg < 0 || iarg >= arg->size)
if (iarg < 0 || iarg >= arg->size)
util_abort("%s: arg_pack() object filled with %d arguments - %d invalid argument number - aborting \n",__func__ , arg->size , iarg);
}
@ -369,11 +369,11 @@ static arg_node_type * arg_pack_iget_new_node( arg_pack_type * arg_pack , int in
arg_node_free( arg_pack->nodes[index] ); /* Free the existing current node. */
arg_pack->nodes[index] = arg_node_alloc_empty( ); /* Allocate a new fresh instance. */
}
if (arg_pack->size == arg_pack->alloc_size)
arg_pack_realloc_nodes(arg_pack , 1 + arg_pack->alloc_size * 2); /* We have to grow the vector of nodes. */
if (index == arg_pack->size)
if (index == arg_pack->size)
arg_pack->size++; /* We are asking for the first element beyond the current length of the vector, i.e. append. */
return arg_pack->nodes[index];
}
@ -414,7 +414,7 @@ arg_pack_type * arg_pack_alloc() {
void arg_pack_free(arg_pack_type * arg_pack) {
int i;
for (i=0; i < arg_pack->alloc_size; i++)
for (i=0; i < arg_pack->alloc_size; i++)
arg_node_free( arg_pack->nodes[i] );
free(arg_pack->nodes);
@ -430,7 +430,7 @@ void arg_pack_free__(void * __arg_pack) {
void arg_pack_clear(arg_pack_type * arg_pack) {
if (arg_pack->locked)
if (arg_pack->locked)
util_abort("%s: arg_pack has been locked - abortng \n",__func__);
{
int i;
@ -445,7 +445,7 @@ void arg_pack_clear(arg_pack_type * arg_pack) {
/* Access functions:
1. Append
2. iget
2. iget
3. iset (can NOT create holes in the vector)
******************************************************************/
@ -527,7 +527,7 @@ node_ctype arg_pack_iget_ctype(const arg_pack_type * arg_pack ,int index) {
void arg_pack_iset_copy(arg_pack_type * arg_pack , int index , const void * ptr, arg_node_copyc_ftype * copyc , arg_node_free_ftype * freef) {
arg_node_type * node = arg_pack_iget_new_node( arg_pack , index );
arg_node_type * node = arg_pack_iget_new_node( arg_pack , index );
arg_node_set_ptr(node , ptr , copyc , freef);
}
@ -577,7 +577,7 @@ void arg_pack_fscanf(arg_pack_type * arg , FILE * stream, const char * filename)
arg_node_type * node = arg->nodes[iarg];
fmt = util_strcat_realloc(fmt , arg_node_fmt(node));
}
switch(arg->size) {
case(0):
break;
@ -603,7 +603,7 @@ void arg_pack_fscanf(arg_pack_type * arg , FILE * stream, const char * filename)
arg0 = arg_pack_iget_adress(arg , 0);
arg1 = arg_pack_iget_adress(arg , 1);
arg2 = arg_pack_iget_adress(arg , 2);
scan_count = fscanf(stream , fmt , arg0 , arg1 , arg2);
break;
}
@ -614,7 +614,7 @@ void arg_pack_fscanf(arg_pack_type * arg , FILE * stream, const char * filename)
arg1 = arg_pack_iget_adress(arg , 1);
arg2 = arg_pack_iget_adress(arg , 2);
arg3 = arg_pack_iget_adress(arg , 3);
scan_count = fscanf(stream , fmt , arg0 , arg1 , arg2 , arg3);
break;
}
@ -635,11 +635,11 @@ void arg_pack_fscanf(arg_pack_type * arg , FILE * stream, const char * filename)
util_abort("%s: sorry %s not allocated for %d arguments from file %s\n",__func__ , __func__ , arg->size, filename);
}
if (scan_count != arg->size) {
util_abort("%s: wanted %d arguments - only found: %d in file %s \n", __func__ , arg->size , scan_count, filename);
}
free(fmt);
}

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'buffer.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 'buffer.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.
*/
@ -25,6 +25,7 @@
#include <ert/util/ssize_t.h>
#include <ert/util/util.h>
#include <ert/util/type_macros.h>
#include <ert/util/buffer.h>
@ -53,7 +54,7 @@
struct buffer_struct {
size_t __id;
UTIL_TYPE_ID_DECLARATION;
char * data; /* The actual storage. */
size_t alloc_size; /* The total byte size of the buffer. */
size_t content_size; /* The extent of initialized data in the buffer - i.e. the meaningful content in the buffer. */
@ -64,8 +65,8 @@ struct buffer_struct {
/*****************************************************************/
UTIL_IS_INSTANCE_FUNCTION( buffer , BUFFER_TYPE_ID )
UTIL_SAFE_CAST_FUNCTION( buffer , BUFFER_TYPE_ID )
/**
@ -99,7 +100,7 @@ static void buffer_resize__(buffer_type * buffer , size_t new_size, bool abort_o
static buffer_type * buffer_alloc_empty( ) {
buffer_type * buffer = util_malloc( sizeof * buffer );
buffer->__id = BUFFER_TYPE_ID;
UTIL_TYPE_ID_INIT( buffer , BUFFER_TYPE_ID );
buffer->data = NULL;
buffer->alloc_size = 0;
@ -128,11 +129,11 @@ void buffer_shrink_to_fit( buffer_type * buffer ) {
data. Observe that the buffer will 'steal' the input data pointer,
in the process the data pointer might very well be realloced()
leaving the original pointer invalid.
All the content of the input data pointer will be assumed to be
valid, i.e. the fields content_size and pos will be set to the
value @buffer_size.
When calling buffer_free() at a later stage the hijacked data will
also be freed.
*/
@ -144,7 +145,7 @@ buffer_type * buffer_alloc_private_wrapper(void * data , size_t buffer_size ) {
buffer->content_size = buffer_size;
buffer->pos = buffer_size;
buffer->alloc_size = buffer_size;
return buffer;
}
@ -193,7 +194,7 @@ void buffer_clear( buffer_type * buffer ) {
/*****************************************************************/
/**
/**
Observe that it is the functions with _safe_ in the name which
most closely mimicks the behaviour of fread(), and fwrite() -
these functions will *NOT* abort if the buffer is to small,
@ -212,19 +213,19 @@ static size_t buffer_fread__(buffer_type * buffer , void * target_ptr , size_t i
size_t remaining_items = remaining_size / item_size;
size_t read_items = util_size_t_min( items , remaining_items );
size_t read_bytes = read_items * item_size;
memcpy( target_ptr , &buffer->data[buffer->pos] , read_bytes );
buffer->pos += read_bytes;
if (read_items < items) {
/* The buffer was not large enough - what to do now???? */
if (abort_on_error)
if (abort_on_error)
util_abort("%s: tried to read beyond the length of the buffer: Wanted:%ld Size:%ld \n",__func__ , items , read_items);
else
else
/* OK we emulate fread() behaviour - setting errno to EOVERFLOW*/
errno = ENOMEM;//EOVERFLOW;
}
return read_items;
}
@ -253,7 +254,7 @@ static size_t buffer_fwrite__(buffer_type * buffer , const void * src_ptr , size
*/
remaining_size = buffer->alloc_size - buffer->pos;
}
{
size_t remaining_items = remaining_size / item_size;
@ -262,12 +263,12 @@ static size_t buffer_fwrite__(buffer_type * buffer , const void * src_ptr , size
memcpy( &buffer->data[buffer->pos] , src_ptr , write_bytes );
buffer->pos += write_bytes;
if (write_items < items) {
/* The buffer was not large enough - what to do now???? */
if (abort_on_error)
util_abort("%s: failed to write %d elements to the buffer \n",__func__ , items); /* This code is never executed - abort is in resize__(); */
else
else
/* OK we emulate fwrite() behaviour - setting errno to ENOMEM */
errno = ENOMEM;
}
@ -308,10 +309,10 @@ void buffer_fseek(buffer_type * buffer , ssize_t offset , int whence) {
new_pos = buffer->pos + offset;
else if (whence == SEEK_END)
new_pos = buffer->content_size + offset;
else
else
util_abort("%s: unrecognized whence indicator - aborting \n",__func__);
/**
/**
Observe that we can seek to the very end of the buffer. I.e. for
a buffer with content_size == 20 we can seek to position 20.
*/
@ -360,15 +361,26 @@ int buffer_fgetc( buffer_type * buffer ) {
}
/**
This function writes all the elements in the string __NOT__
including the terminating \0 character into the buffer. This should
not be confused with buffer_fwrite_string() function which both
prepends the string with an integer length specifier and also
includes the terminating \0.
This function writes all the elements in the string including the
terminating \0 character into the buffer. This should not be
confused with buffer_fwrite_string() function which in addition
prepends the string with an integer length.
*/
void buffer_fwrite_char_ptr(buffer_type * buffer , const char * string_ptr ) {
buffer_fwrite(buffer , string_ptr , sizeof * string_ptr , strlen( string_ptr ));
buffer_fwrite(buffer , string_ptr , sizeof * string_ptr , strlen( string_ptr ) + 1);
}
void buffer_strcat(buffer_type * buffer , const char * string) {
if (buffer->content_size == 0)
buffer_fwrite_char_ptr( buffer , string );
else {
if (buffer->data[ buffer->content_size - 1] == '\0') {
buffer_fseek( buffer , -1 , SEEK_END);
buffer_fwrite_char_ptr( buffer , string );
}
}
}
@ -377,7 +389,7 @@ void buffer_fwrite_char_ptr(buffer_type * buffer , const char * string_ptr ) {
of the buffer will be checked, and no new \0 will be added if the
buffer is already \0 terminated.
*/
void buffer_terminate_char_ptr( buffer_type * buffer ) {
static void buffer_terminate_char_ptr( buffer_type * buffer ) {
if (buffer->data[ buffer->content_size - 1] != '\0')
buffer_fwrite_char( buffer , '\0');
}
@ -448,57 +460,6 @@ void buffer_fwrite_double(buffer_type * buffer , double value) {
/**
Storing strings:
----------------
When storing a string (\0 terminated char pointer) what is actually
written to the buffer is
1. The length of the string - as returned from strlen().
2. The string content INCLUDING the terminating \0.
*/
/**
This function will return a pointer to the current position in the
buffer, and advance the buffer position forward until a \0
terminater is found. If \0 is not found the thing will abort().
Observe that the return value will point straight into the buffer,
this is highly volatile memory, and in general it will be safer to
use buffer_fread_alloc_string() to get a copy of the string.
*/
const char * buffer_fread_string(buffer_type * buffer) {
int string_length = buffer_fread_int( buffer );
char * string_ptr = &buffer->data[buffer->pos];
char c;
buffer_fskip( buffer , string_length );
c = buffer_fread_char( buffer );
if (c != '\0')
util_abort("%s: internal error - malformed string representation in buffer \n",__func__);
return string_ptr;
}
char * buffer_fread_alloc_string(buffer_type * buffer) {
return util_alloc_string_copy( buffer_fread_string( buffer ));
}
/**
Observe that this function writes a leading integer string length.
*/
void buffer_fwrite_string(buffer_type * buffer , const char * string) {
buffer_fwrite_int( buffer , strlen( string )); /* Writing the length of the string */
buffer_fwrite(buffer , string , 1 , strlen( string ) + 1); /* Writing the string content ** WITH ** the terminating \0 */
}
@ -528,22 +489,27 @@ size_t buffer_get_remaining_size(const buffer_type * buffer) {
return buffer->content_size - buffer->pos;
}
/**
/**
Returns a pointer to the internal storage of the buffer. Observe
that this storage is volatile, and the return value from this
function should not be kept around; alternatively you can use
buffer_alloc_data_copy().
*/
void * buffer_get_data(const buffer_type * buffer) {
void * buffer_get_data(const buffer_type * buffer) {
return buffer->data;
}
void * buffer_iget_data(const buffer_type * buffer, size_t offset) {
return &buffer->data[offset];
}
/**
Returns a copy of the initialized (i.e. buffer->content_size)
buffer content.
*/
void * buffer_alloc_data_copy(const buffer_type * buffer) {
void * buffer_alloc_data_copy(const buffer_type * buffer) {
return util_alloc_copy(buffer->data , buffer->content_size );
}
@ -571,11 +537,11 @@ void * buffer_alloc_data_copy(const buffer_type * buffer) {
-------------------------------------------------
| 0 | 1 | 2 | 3 | x | x | x | 4 | 5 | 6 | 7 | x |
-------------------------------------------------
If you are shifting beyound the end of the buffer, it will be
automatically resized.
buffer_memshift(buffer , 2 , -4)
--------------------------------
@ -583,7 +549,7 @@ void * buffer_alloc_data_copy(const buffer_type * buffer) {
| 4 | 5 | 6 | 7 | 8 | x | x | x | x | x | x | x |
-------------------------------------------------
When shifting to the left, content is lost (without warning/error)
when it is shifted beyond the start of the buffer.
@ -593,7 +559,7 @@ void * buffer_alloc_data_copy(const buffer_type * buffer) {
case it is set to the new end of the buffer.
*/
void buffer_memshift(buffer_type * buffer , size_t offset, ssize_t shift) {
void buffer_memshift(buffer_type * buffer , size_t offset, ssize_t shift) {
/* Do we need to grow the buffer? */
if (shift > 0) {
if (buffer->alloc_size <= (buffer->content_size + shift)) {
@ -601,7 +567,7 @@ void buffer_memshift(buffer_type * buffer , size_t offset, ssize_t shift) {
buffer_resize__(buffer , new_size , true );
}
}
{
size_t move_size;
if (shift < 0)
@ -611,7 +577,7 @@ void buffer_memshift(buffer_type * buffer , size_t offset, ssize_t shift) {
move_size = buffer->content_size - offset;
memmove( &buffer->data[offset + shift] , &buffer->data[offset] , move_size );
buffer->content_size += shift;
buffer->pos = util_size_t_min( buffer->pos , buffer->content_size);
buffer->pos = util_size_t_min( buffer->pos , buffer->content_size);
}
}
@ -625,7 +591,6 @@ void buffer_replace_data(buffer_type * buffer , size_t offset , size_t old_size
void buffer_replace_string( buffer_type * buffer , size_t offset , size_t old_size , const char * new_string) {
buffer_replace_data( buffer , offset , old_size , new_string , strlen(new_string));
}
@ -635,34 +600,28 @@ void buffer_replace_string( buffer_type * buffer , size_t offset , size_t old_si
the string @expr in @buffer. The search will start at the current
position in the buffer, if the string is found true is returned AND
the internal pos is updated to point at the match.
If the string is NOT found the function will return false, without
touching internal state.
*/
bool buffer_strstr( buffer_type * buffer , const char * expr ) {
/**
If this condition is satisfied the assumption that buffer->data
is a \0 terminated string certainly breaks down.
*/
if ((buffer->content_size == 0) || (buffer->pos == buffer->content_size))
return false;
bool match = false;
{
char * match = NULL;
match = strstr( &buffer->data[buffer->pos] , expr);
if (match != NULL)
buffer->pos = match - buffer->data;
return (match != NULL);
if (strlen(expr) > 0) {
char * match_ptr = strstr( &buffer->data[buffer->pos] , expr );
if (match_ptr) {
buffer->pos += match_ptr - &buffer->data[buffer->pos];
match = true;
}
}
return match;
}
bool buffer_strchr( buffer_type * buffer , int c) {
/**
/**
If this condition is satisfied the assumption that buffer->data
is a \0 terminated string certainly breaks down.
*/
@ -670,30 +629,37 @@ bool buffer_strchr( buffer_type * buffer , int c) {
return false;
{
char * match = NULL;
match = strchr( &buffer->data[buffer->pos] , c);
if (match != NULL)
buffer->pos = match - buffer->data;
return (match != NULL);
bool match = false;
size_t pos = buffer->pos;
while (true) {
if (buffer->data[pos] == c) {
match = true;
buffer->pos = pos;
break;
}
pos++;
if (pos == buffer->content_size)
break;
}
return match;
}
}
bool buffer_search_replace( buffer_type * buffer , const char * old_string , const char * new_string) {
const int shift = strlen( new_string ) - strlen( old_string );
bool match = buffer_strstr( buffer , old_string );
bool match = buffer_strstr( buffer , old_string );
if (match) {
size_t offset = buffer_get_offset( buffer ) + strlen( old_string );
const int shift = strlen( new_string ) - strlen( old_string );
if (shift != 0)
buffer_memshift( buffer , offset , shift );
/** Search continues at the end of the newly inserted string - i.e. no room for recursions. */
buffer_fwrite( buffer , new_string , strlen( new_string ) , sizeof * new_string );
buffer_fwrite( buffer , new_string , 1 , strlen(new_string));
buffer_terminate_char_ptr( buffer );
}
return match;
}
@ -723,14 +689,14 @@ void buffer_summarize(const buffer_type * buffer , const char * header) {
/**
This is the lowest level: 'read buffer content from file'
function. It will read 'byte_size' bytes from stream and fill the
buffer with the data.
buffer with the data.
When the function completes the buffer position is at the end of
the buffer, i.e. it is ready for more calls to buffer_stream_fread;
this is in contrast to the higher level functions
buffer_fread_alloc() / buffer_fread_realloc() which reposition the
buffer position to the beginning of the buffer.
Before reading from the buffer with e.g. buffer_fread_int() the
buffer must be repositioned with buffer_rewind().
*/
@ -758,8 +724,8 @@ void buffer_stream_fread( buffer_type * buffer , size_t byte_size , FILE * strea
void buffer_fread_realloc(buffer_type * buffer , const char * filename) {
size_t file_size = util_file_size( filename );
FILE * stream = util_fopen( filename , "r");
FILE * stream = util_fopen( filename , "r");
buffer_clear( buffer ); /* Setting: content_size = 0; pos = 0; */
buffer_stream_fread( buffer , file_size , stream );
buffer_rewind( buffer ); /* Setting: pos = 0; */
@ -779,7 +745,7 @@ buffer_type * buffer_fread_alloc(const char * filename) {
/**
Will write parts of the buffer to the stream. Will start at buffer
position @offset and write @write_size bytes.
o If @offset is invalid, i.e. less than zero or greater than
buffer->content_size the function will fail hard.
@ -787,7 +753,7 @@ buffer_type * buffer_fread_alloc(const char * filename) {
function will just write all the available data, but not complain
any more.
o @write_size == 0 that is interpreted as "write everything from offset".
o @write_size == 0 that is interpreted as "write everything from offset".
o @write_size < 0 is interpreted as : "Write everything except the
abs(@write_size) last bytes.
@ -802,15 +768,15 @@ size_t buffer_stream_fwrite_n( const buffer_type * buffer , size_t offset , ssiz
ssize_t len;
if (write_size > 0) /* Normal - write @write_size bytes from offset */
len = write_size;
else if (write_size == 0) /* Write everything from the offset */
len = write_size;
else if (write_size == 0) /* Write everything from the offset */
len = buffer->content_size - offset;
else /* @write_size < 0 - write everything excluding the last abs(write_size) bytes. */
len = buffer->content_size - offset - abs( write_size );
if (len < 0)
util_abort("%s: invalid length spesifier - tried to write %ld bytes \n",__func__ , len);
util_fwrite( &buffer->data[offset] , 1 , len , stream , __func__);
return len;
}
@ -829,7 +795,7 @@ void buffer_stream_fprintf( const buffer_type * buffer , FILE * stream ) {
/**
Dumps buffer content to a stream - without any metadata.
Dumps buffer content to a stream - without any metadata.
*/
void buffer_store(const buffer_type * buffer , const char * filename) {
FILE * stream = util_fopen(filename , "w");
@ -838,6 +804,8 @@ void buffer_store(const buffer_type * buffer , const char * filename) {
}
#include "buffer_string.c"
#ifdef WITH_ZLIB
#include "buffer_zlib.c"
#endif

View File

@ -0,0 +1,57 @@
/*
The functions buffer_fread_string() and buffer_fwrite_string()
should not be used; the embedded integer just creates chaos and
should the sole responsability of the calling scope.
*/
/**
Storing strings:
----------------
When storing a string (\0 terminated char pointer) what is actually
written to the buffer is
1. The length of the string - as returned from strlen().
2. The string content INCLUDING the terminating \0.
*/
/**
This function will return a pointer to the current position in the
buffer, and advance the buffer position forward until a \0
terminater is found. If \0 is not found the thing will abort().
Observe that the return value will point straight into the buffer,
this is highly volatile memory, and in general it will be safer to
use buffer_fread_alloc_string() to get a copy of the string.
*/
const char * buffer_fread_string(buffer_type * buffer) {
int string_length = buffer_fread_int( buffer );
char * string_ptr = &buffer->data[buffer->pos];
char c;
buffer_fskip( buffer , string_length );
c = buffer_fread_char( buffer );
if (c != '\0')
util_abort("%s: internal error - malformed string representation in buffer \n",__func__);
return string_ptr;
}
char * buffer_fread_alloc_string(buffer_type * buffer) {
return util_alloc_string_copy( buffer_fread_string( buffer ));
}
/**
Observe that this function writes a leading integer string length.
*/
void buffer_fwrite_string(buffer_type * buffer , const char * string) {
buffer_fwrite_int( buffer , strlen( string )); /* Writing the length of the string */
buffer_fwrite(buffer , string , 1 , strlen( string ) + 1); /* Writing the string content ** WITH ** the terminating \0 */
}

View File

@ -159,8 +159,9 @@ static void * __hash_get_node_unlocked(const hash_type *__hash , const char *key
difficult due to locking requirements.
*/
static void * __hash_get_node(hash_type *hash , const char *key, bool abort_on_error) {
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_get_node_unlocked(hash , key , abort_on_error);
__hash_unlock( hash );
@ -168,7 +169,7 @@ static void * __hash_get_node(hash_type *hash , const char *key, bool abort_on_e
}
static node_data_type * hash_get_node_data(hash_type *hash , const char *key) {
static node_data_type * hash_get_node_data(const hash_type *hash , const char *key) {
hash_node_type * node = __hash_get_node(hash , key , true);
return hash_node_get_data(node);
}
@ -356,7 +357,7 @@ void hash_insert_string(hash_type * hash , const char * key , const char * value
}
char * hash_get_string(hash_type * hash , const char * key) {
char * hash_get_string(const hash_type * hash , const char * key) {
node_data_type * node_data = hash_get_node_data(hash , key);
return node_data_get_string( node_data );
}
@ -369,7 +370,7 @@ void hash_insert_int(hash_type * hash , const char * key , int value) {
}
int hash_get_int(hash_type * hash , const char * key) {
int hash_get_int(const hash_type * hash , const char * key) {
node_data_type * node_data = hash_get_node_data(hash , key);
return node_data_get_int( node_data );
}
@ -400,7 +401,7 @@ int hash_inc_counter(hash_type * hash , const char * counter_key) {
Will return 0 if the key is not in the hash.
*/
int hash_get_counter(hash_type * hash , const char * key) {
int hash_get_counter(const hash_type * hash , const char * key) {
if (hash_has_key( hash , key ))
return hash_get_int( hash , key );
else
@ -414,7 +415,7 @@ void hash_insert_double(hash_type * hash , const char * key , double value) {
__hash_insert_node(hash , hash_node);
}
double hash_get_double(hash_type * hash , const char * key) {
double hash_get_double(const hash_type * hash , const char * key) {
node_data_type * node_data = hash_get_node_data(hash , key);
return node_data_get_double( node_data );
}

View File

@ -230,6 +230,15 @@ rng_alg_type rng_get_type( const rng_type * rng ) {
return rng->type;
}
unsigned int rng_get_max_int(const rng_type * rng) {
unsigned int MAX = -1;
if(rng->max_value < MAX) {
return rng->max_value;
} else {
return MAX;
}
}
/*****************************************************************/
void rng_shuffle( rng_type * rng , char * data , size_t element_size , size_t num_elements) {

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2013 Statoil ASA, Norway.
The file 'string_util.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 'string_util.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 <ctype.h>
@ -27,13 +27,13 @@
/*****************************************************************/
/*
/*
This functions parses an input string 'range_string' of the type:
"0,1,8, 10 - 20 , 15,17-21"
I.e. integers separated by "," and "-". The integer values are
parsed out.
parsed out.
*/
//#include <stringlist.h>
@ -47,11 +47,11 @@
// NULL );
// stringlist_type * tokens;
// tokens = tokenize_buffer( tokenizer , range_string , true);
//
//
// stringlist_free( tokens );
// tokenizer_free( tokenizer );
//}
//}
static bool valid_characters( const char * range_string ) {
@ -63,7 +63,7 @@ static bool valid_characters( const char * range_string ) {
char c = range_string[offset];
if (isspace(c) || isdigit(c) || c == ',' || c == '-')
offset++;
else
else
valid = false;
if (offset == strlen( range_string ) || !valid)
break;
@ -90,14 +90,14 @@ static int_vector_type * string_util_sscanf_alloc_active_list(const char * range
int item;
active_list = int_vector_alloc(0,0);
tokens = basic_parser_tokenize_buffer( parser , range_string , true);
for (item = 0; item < stringlist_get_size( tokens ); item++) {
const char * string_item = stringlist_iget( tokens , item );
char * pos_ptr = (char *) string_item;
int value1 , value2;
value1 = strtol( string_item , &pos_ptr , 10);
if (*pos_ptr == '\0')
if (*pos_ptr == '\0')
// The pos_ptr points to the end of the string, i.e. this was a single digit.
value2 = value1;
else {
@ -105,20 +105,20 @@ static int_vector_type * string_util_sscanf_alloc_active_list(const char * range
while (isspace(*pos_ptr) || *pos_ptr == '-')
pos_ptr++;
util_sscanf_int( pos_ptr , &value2);
}
}
{
int value;
for (value = value1; value <= value2; value++)
for (value = value1; value <= value2; value++)
int_vector_append( active_list , value );
}
}
stringlist_free( tokens );
basic_parser_free( parser );
}
return active_list;
}
@ -170,7 +170,7 @@ int_vector_type * string_util_alloc_active_list( const char * range_string ) {
/*
This is the only function which actually invokes the low level
string parsing in util_sscanf_alloc_active_list().
string parsing in util_sscanf_alloc_active_list().
*/
bool string_util_update_active_mask( const char * range_string , bool_vector_type * active_mask) {
@ -179,7 +179,7 @@ bool string_util_update_active_mask( const char * range_string , bool_vector_typ
if (sscanf_active) {
for (i=0; i < int_vector_size( sscanf_active ); i++)
bool_vector_iset( active_mask , int_vector_iget(sscanf_active , i) , true );
int_vector_free( sscanf_active );
return true;
} else
@ -223,6 +223,6 @@ bool string_util_init_value_list( const char * range_string , int_vector_type *
int_vector_type * string_util_alloc_value_list(const char * range_string) {
int_vector_type * value_list = int_vector_alloc(0,0);
string_util_init_value_list( range_string , value_list);
string_util_init_value_list( range_string , value_list);
return value_list;
}

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'stringlist.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 'stringlist.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 <string.h>
@ -38,7 +38,7 @@
This file implements a very thin wrapper around a list (vector) of
strings, and the total number of strings. It is mostly to avoid
sending both argc and argv.
Most of the functionality is implemented through vector.c and
stateless functions in util.c
*/
@ -63,7 +63,7 @@ static void stringlist_fprintf__(const stringlist_type * stringlist, const char
const char * s = stringlist_iget(stringlist , i);
fprintf(stream , "%s%s", s , sep);
}
fprintf(stream , "%s", stringlist_iget( stringlist , length - 1 ));
}
}
@ -140,7 +140,7 @@ static stringlist_type * stringlist_alloc_empty( bool alloc_vector ) {
stringlist->strings = vector_alloc_new();
else
stringlist->strings = NULL;
return stringlist;
}
@ -156,9 +156,9 @@ stringlist_type * stringlist_alloc_new() {
stringlist_type * stringlist_alloc_argv_copy(const char ** argv , int argc) {
int iarg;
stringlist_type * stringlist = stringlist_alloc_empty( true);
for (iarg = 0; iarg < argc; iarg++)
for (iarg = 0; iarg < argc; iarg++)
stringlist_append_copy( stringlist , argv[iarg]);
return stringlist;
}
@ -166,7 +166,7 @@ stringlist_type * stringlist_alloc_argv_copy(const char ** argv , int argc) {
stringlist_type * stringlist_alloc_argv_ref(const char ** argv , int argc) {
int iarg;
stringlist_type * stringlist = stringlist_alloc_empty( true );
for (iarg = 0; iarg < argc; iarg++)
for (iarg = 0; iarg < argc; iarg++)
stringlist_append_ref( stringlist , argv[iarg]);
return stringlist;
@ -176,19 +176,19 @@ stringlist_type * stringlist_alloc_argv_ref(const char ** argv , int argc) {
stringlist_type * stringlist_alloc_argv_owned_ref(const char ** argv , int argc) {
int iarg;
stringlist_type * stringlist = stringlist_alloc_empty( true );
for (iarg = 0; iarg < argc; iarg++)
for (iarg = 0; iarg < argc; iarg++)
stringlist_append_owned_ref( stringlist , argv[iarg]);
return stringlist;
}
/**
/**
Allocates a new stringlist instance where all the new string are
references to the string found in the existing stringlist
instance.
*/
instance.
*/
stringlist_type * stringlist_alloc_shallow_copy(const stringlist_type * src) {
stringlist_type * copy = stringlist_alloc_empty( false );
copy->strings = vector_alloc_copy( src->strings , false);
@ -223,7 +223,7 @@ stringlist_type * stringlist_alloc_shallow_copy_with_limits(const stringlist_typ
stringlist_type * stringlist_alloc_deep_copy_with_limits(const stringlist_type * src, int offset , int num_strings) {
stringlist_type * copy = stringlist_alloc_empty( true );
int i;
for (i = 0; i < num_strings; i++)
for (i = 0; i < num_strings; i++)
stringlist_append_copy( copy , stringlist_iget( src , i + offset));
return copy;
}
@ -256,7 +256,7 @@ void stringlist_append_stringlist_ref(stringlist_type * stringlist , const strin
/**
Insert a copy of a stringlist in some position.
Can probably be made more efficient.
*/
@ -302,7 +302,7 @@ void stringlist_deep_copy( stringlist_type * target , const stringlist_type * sr
/**
/**
Frees all the memory contained by the stringlist.
*/
void stringlist_clear(stringlist_type * stringlist) {
@ -352,11 +352,11 @@ const char * stringlist_back(const stringlist_type * stringlist) {
int stringlist_iget_as_int( const stringlist_type * stringlist , int index , bool * valid) {
const char * string_value = stringlist_iget( stringlist , index );
int value = -1;
if (valid != NULL)
*valid = false;
if (util_sscanf_int(string_value , &value))
if (util_sscanf_int(string_value , &value))
if (valid != NULL)
*valid = true;
@ -430,7 +430,7 @@ int stringlist_get_size(const stringlist_type * stringlist) {
/*
Return NULL if the list has zero entries.
Return NULL if the list has zero entries.
*/
static char ** stringlist_alloc_char__(const stringlist_type * stringlist, bool deep_copy) {
char ** strings = NULL;
@ -460,7 +460,7 @@ char ** stringlist_alloc_char_ref(const stringlist_type * stringlist) {
/**
/**
Scans the stringlist (linear scan) to see if it contains (at
least) one occurence of 's'. Will never return true if the input
string @s equals NULL, altough the stringlist itself can contain
@ -471,7 +471,7 @@ bool stringlist_contains(const stringlist_type * stringlist , const char * s) {
int size = stringlist_get_size( stringlist );
int index = 0;
bool contains = false;
while ((index < size) && (!contains)) {
const char * istring = stringlist_iget(stringlist , index);
if (istring != NULL)
@ -491,7 +491,7 @@ int_vector_type * stringlist_find(const stringlist_type * stringlist, const char
int_vector_type * indicies = int_vector_alloc(0, -1);
int size = stringlist_get_size( stringlist );
int index = 0;
while (index < size ) {
const char * istring = stringlist_iget(stringlist , index);
if (istring != NULL)
@ -562,25 +562,25 @@ char * stringlist_alloc_joined_substring( const stringlist_type * s , int start_
{
char * string = NULL;
int i;
/* Start with allocating a string long enough to hold all the substrings. */
{
int sep_length = strlen( sep );
int total_length = 0;
for (i=start_index; i < end_index; i++)
total_length += (strlen(stringlist_iget( s , i)) + sep_length);
total_length += (1 - sep_length);
string = util_malloc( total_length * sizeof * string );
string[0] = '\0';
}
for (i = start_index; i < end_index; i ++) {
strcat( string , stringlist_iget( s , i));
if (i < (end_index - 1))
strcat( string , sep );
}
return string;
}
}
@ -602,7 +602,7 @@ char * stringlist_alloc_joined_string(const stringlist_type * s , const char * s
in the list. The actual functionality is in the util_split_string()
function.
*/
stringlist_type * stringlist_alloc_from_split( const char * input_string , const char * sep ) {
@ -624,7 +624,7 @@ 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++)
for (i=0; i < size; i++)
buffer_fwrite_string(buffer , stringlist_iget(s , i) );
}
@ -633,11 +633,11 @@ void stringlist_fwrite(const stringlist_type * s, FILE * stream) {
int i;
int size = stringlist_get_size( s );
util_fwrite_int( size , stream);
for (i=0; i < size; i++)
for (i=0; i < size; i++)
util_fwrite_string(stringlist_iget(s , i) , stream);
}
/*
/*
When a stringlist is loaded from file the current content of the
stringlist is discarded; and the stringlist becomes the owner of
all the data read in.
@ -754,7 +754,7 @@ int stringlist_select_matching_files(stringlist_type * names , const char * path
WIN32_FIND_DATA file_data;
HANDLE file_handle;
char * pattern = util_alloc_filename( path , file_pattern , NULL );
stringlist_clear( names );
file_handle = FindFirstFile( pattern , &file_data );
if (file_handle != INVALID_HANDLE_VALUE) {
@ -765,7 +765,7 @@ int stringlist_select_matching_files(stringlist_type * names , const char * path
}
FindClose( file_handle );
free( pattern );
return stringlist_get_size( names );
}
#endif
@ -783,7 +783,7 @@ int stringlist_append_matching_elements(stringlist_type * target , const stringl
}
return match_count;
}
int stringlist_select_matching_elements(stringlist_type * target , const stringlist_type * src , const char * pattern) {
stringlist_clear( target );
return stringlist_append_matching_elements( target , src , pattern );

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'subst_list.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 'subst_list.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 <ctype.h>
@ -32,7 +32,7 @@
/**
This file implements a small support struct for search-replace
operations, along with wrapped calls to util_string_replace_inplace().
Substitutions can be carried out on files and string in memory (char *
with \0 termination); and the operations can be carried out inplace, or
in a filtering mode where a new file/string is created.
@ -46,16 +46,16 @@
* subst_list_insert_ref(subst_list , key , value);
* subst_list_insert_owned_ref(subst_list , key , value);
* subst_list_insert_copy(subst_list , key , value );
* subst_list_insert_copy(subst_list , key , value );
The difference between these functions is who is owning the memory
pointed to by the value pointer.
3. Do the actual search-replace operation on a file or memory buffer:
* subst_list_filter_file() : Does search-replace on a file.
* subst_list_update_string() : Does search-replace on a buffer.
4. Free the subst_list and go home.
Internally the (key,value) pairs used for substitutions are stored in a
@ -71,10 +71,10 @@
*/
typedef enum { SUBST_DEEP_COPY = 1,
typedef enum { SUBST_DEEP_COPY = 1,
SUBST_MANAGED_REF = 2,
SUBST_SHARED_REF = 3} subst_insert_type; /* Mode used in the subst_list_insert__() function */
#define SUBST_LIST_TYPE_ID 6614320
struct subst_list_struct {
@ -83,7 +83,7 @@ struct subst_list_struct {
vector_type * string_data; /* The string substitutions we should do. */
vector_type * func_data; /* The functions we support. */
const subst_func_pool_type * func_pool; /* NOT owned by the subst_list instance - can be NULL */
hash_type * map;
hash_type * map;
};
@ -96,16 +96,16 @@ typedef struct {
/*
/*
The subst_list type is implemented as a hash of subst_list_node
instances. This node type is not exported out of this file scope at
all.
*/
typedef struct {
typedef struct {
bool value_owner; /* Wether the memory pointed to by value should bee freed.*/
char * value;
char * key;
char * key;
char * doc_string; /* A doc_string of this substitution - only for documentation - can be NULL. */
} subst_list_string_type;
@ -120,7 +120,7 @@ static subst_list_string_type * subst_list_string_alloc(const char * key) {
subst_list_string_type * node = util_malloc(sizeof * node );
node->value_owner = false;
node->value = NULL;
node->doc_string = NULL;
node->doc_string = NULL;
node->key = util_alloc_string_copy( key );
return node;
}
@ -148,7 +148,7 @@ static void subst_list_string_free__(void * node) {
/**
input_value can be NULL.
input_value can be NULL.
*/
static void subst_list_string_set_value(subst_list_string_type * node, const char * input_value , const char * doc_string , subst_insert_type insert_mode) {
subst_list_string_free_content( node );
@ -158,15 +158,15 @@ static void subst_list_string_set_value(subst_list_string_type * node, const cha
value = util_alloc_string_copy(input_value);
else
value = (char *) input_value;
if (insert_mode == SUBST_SHARED_REF)
node->value_owner = false;
else
node->value_owner = true;
node->value = value;
}
if (doc_string != NULL)
node->doc_string = util_realloc_string_copy( node->doc_string , doc_string );
}
@ -176,7 +176,7 @@ static void subst_list_string_set_value(subst_list_string_type * node, const cha
When arriving at this function the main subst scope should already have verified that
the requested function is available in the function pool.
*/
static subst_list_func_type * subst_list_func_alloc( const char * func_name, subst_func_type * func) {
subst_list_func_type * subst_func = util_malloc( sizeof * subst_func );
subst_func->name = util_alloc_string_copy( func_name );
@ -231,14 +231,14 @@ static subst_list_string_type * subst_list_insert_new_node(subst_list_type * sub
vector_append_owned_ref( subst_list->string_data , new_node , subst_list_string_free__ );
else
vector_insert_owned_ref( subst_list->string_data , 0 , new_node , subst_list_string_free__ );
hash_insert_ref( subst_list->map , key , new_node );
return new_node;
}
/*****************************************************************/
static UTIL_IS_INSTANCE_FUNCTION( subst_list , SUBST_LIST_TYPE_ID )
UTIL_IS_INSTANCE_FUNCTION( subst_list , SUBST_LIST_TYPE_ID )
/**
@ -266,13 +266,13 @@ bool subst_list_has_key( const subst_list_type * subst_list , const char * key)
}
/*
/*
The input argument is currently only (void *), runtime it will be
checked whether it is of type subst_list_type, in which case it is
interpreted as a parent instance, if it is of type
subst_func_pool_type it is interpreted as a func_pool instance,
otherwise the function will fail hard.
If the the input argument is a subst_list parent, the func_pool of
the parent is used also for the newly allocated subst_list
instance.
@ -289,14 +289,14 @@ subst_list_type * subst_list_alloc(const void * input_arg) {
subst_list->func_data = vector_alloc_new();
if (input_arg != NULL) {
if (subst_list_is_instance( input_arg ))
if (subst_list_is_instance( input_arg ))
subst_list_set_parent( subst_list , input_arg );
else if (subst_func_pool_is_instance( input_arg ))
subst_list->func_pool = input_arg;
else
util_abort("%s: run_time cast failed - invalid type on input argument.\n",__func__);
}
return subst_list;
}
@ -315,10 +315,10 @@ subst_list_type * subst_list_alloc(const void * input_arg) {
*/
static void subst_list_insert__(subst_list_type * subst_list , const char * key , const char * value , const char * doc_string, bool append ,
static void subst_list_insert__(subst_list_type * subst_list , const char * key , const char * value , const char * doc_string, bool append ,
subst_insert_type insert_mode) {
subst_list_string_type * node = subst_list_get_string_node(subst_list , key);
if (node == NULL) /* Did not have the node. */
node = subst_list_insert_new_node(subst_list , key ,append);
subst_list_string_set_value(node , value , doc_string , insert_mode);
@ -346,7 +346,7 @@ static void subst_list_insert__(subst_list_type * subst_list , const char * key
to do whatever it wants with the value pointer.
*/
void subst_list_append_ref(subst_list_type * subst_list , const char * key , const char * value, const char * doc_string) {
subst_list_insert__(subst_list , key , value , doc_string , true , SUBST_SHARED_REF);
}
@ -381,7 +381,7 @@ void subst_list_prepend_copy(subst_list_type * subst_list , const char * key , c
*/
void subst_list_insert_func(subst_list_type * subst_list , const char * func_name , const char * local_func_name) {
if (subst_list->func_pool != NULL && subst_func_pool_has_func( subst_list->func_pool , func_name )) {
subst_list_func_type * subst_func = subst_list_func_alloc( local_func_name , subst_func_pool_get_func( subst_list->func_pool , func_name ));
vector_append_owned_ref( subst_list->func_data , subst_func , subst_list_func_free__ );
@ -407,10 +407,10 @@ void subst_list_free(subst_list_type * subst_list) {
/*
Below comes many different functions for doing the actual updating
the functions differ in the form of the input and output. At the
lowest level, is the function
lowest level, is the function
subst_list_uppdate_buffer()
which will update a buffer instance. This function again will call
two separate functions for pure string substitutions and for
function evaluation.
@ -486,19 +486,19 @@ static bool subst_list_eval_funcs____(const subst_list_type * subst_list , const
for (index = 0; index < vector_get_size( subst_list->func_data); index++) {
const subst_list_func_type * subst_func = vector_iget_const( subst_list->func_data , index );
const char * func_name = subst_func->name;
bool match;
buffer_rewind( buffer );
do {
size_t match_pos;
match = buffer_strstr( buffer , func_name );
match_pos = buffer_get_offset( buffer );
if (match) {
bool update = false;
char * arg_start = buffer_get_data( buffer );
arg_start += buffer_get_offset( buffer ) + strlen( func_name );
if (arg_start[0] == '(') { /* We require that an opening paren follows immediately behind the function name. */
char * arg_end = strchr( arg_start , ')');
if (arg_end != NULL) {
@ -506,8 +506,8 @@ static bool subst_list_eval_funcs____(const subst_list_type * subst_list , const
char * arg_content = util_alloc_substring_copy( arg_start, 1 , arg_end - arg_start - 1);
stringlist_type * arg_list = basic_parser_tokenize_buffer( parser , arg_content , true);
char * func_eval = subst_list_func_eval( subst_func , arg_list );
int old_len = strlen(func_name) + strlen( arg_content) + 2;
int old_len = strlen(func_name) + strlen( arg_content) + 2;
if (func_eval != NULL) {
buffer_memshift( buffer , match_pos + old_len , strlen( func_eval ) - old_len);
buffer_fwrite( buffer , func_eval , strlen( func_eval ) , sizeof * func_eval );
@ -515,17 +515,17 @@ static bool subst_list_eval_funcs____(const subst_list_type * subst_list , const
update = true;
global_match = true;
}
free( arg_content );
stringlist_free( arg_list );
}
}
if (!update)
}
}
if (!update)
buffer_fseek( buffer , match_pos + strlen( func_name ) , SEEK_SET);
}
} while (match);
}
if (subst_list->parent != NULL)
if (subst_list->parent != NULL)
global_match = (subst_list_eval_funcs____( subst_list->parent , parser , buffer ) || global_match);
return global_match;
}
@ -548,7 +548,7 @@ static bool subst_list_eval_funcs__(const subst_list_type * subst_list , buffer_
Inherited defintions
--------------------
In this situation we have defined a (key,value) substitution,
where the value depends on a value following afterwards:
@ -559,7 +559,7 @@ static bool subst_list_eval_funcs__(const subst_list_type * subst_list , buffer_
subsequently "<CASE>" is replaced with "Test4". A typical use
case here is that the common definition of "<PATH>" is in the
parent, and consequently parent should run first (i.e. top
down).
down).
However, in other cases the order of defintion might very well be
opposite, i.e. with "<CASE>" first and then things will blow up:
@ -569,8 +569,8 @@ static bool subst_list_eval_funcs__(const subst_list_type * subst_list , buffer_
and, the final <CASE> will not be resolved. I.e. there is no
obvious 'right' way to do it.
Overriding defaults
-------------------
@ -598,7 +598,7 @@ static bool subst_list_replace_strings( const subst_list_type * subst_list , buf
bool match = false;
if (subst_list->parent != NULL)
match = subst_list_replace_strings( subst_list->parent , buffer );
/* The actual string replace */
match = (subst_list_replace_strings__( subst_list , buffer ) || match);
return match;
@ -641,7 +641,7 @@ bool subst_list_filter_file(const subst_list_type * subst_list , const char * sr
buffer_type * buffer = buffer_fread_alloc( src_file );
buffer_fseek( buffer , 0 , SEEK_END ); /* Ensure that the buffer is a \0 terminated string. */
buffer_fwrite_char( buffer , '\0');
/*****************************************************************/
/* Backup file ?? */
if (util_same_file(src_file , target_file)) {
@ -649,19 +649,19 @@ bool subst_list_filter_file(const subst_list_type * subst_list , const char * sr
backup_file = util_alloc_tmp_file("/tmp" , backup_prefix , false);
free(backup_prefix);
}
/* Writing backup file */
if (backup_file != NULL) {
FILE * stream = util_fopen(backup_file , "w");
buffer_stream_fwrite_n( buffer , 0 , -1 , stream ); /* -1: Do not write the trailing \0. */
fclose(stream);
}
/* Doing the actual update */
match = subst_list_update_buffer(subst_list , buffer);
/* Writing updated file */
{
@ -669,7 +669,7 @@ bool subst_list_filter_file(const subst_list_type * subst_list , const char * sr
buffer_stream_fwrite_n( buffer , 0 , -1 , stream ); /* -1: Do not write the trailing \0. */
fclose(stream);
}
/* OK - all went hunka dory - unlink the backup file and leave the building. */
if (backup_file != NULL) {
remove( backup_file );
@ -697,7 +697,7 @@ bool subst_list_update_string(const subst_list_type * subst_list , char ** strin
bool match = subst_list_update_buffer(subst_list , buffer);
*string = buffer_get_data( buffer );
buffer_free_container( buffer );
return match;
}
@ -774,7 +774,7 @@ subst_list_type * subst_list_alloc_deep_copy(const subst_list_type * src) {
copy = subst_list_alloc( src->parent );
else
copy = subst_list_alloc( src->func_pool);
{
int index;
for (index = 0; index < vector_get_size( src->string_data ); index++) {
@ -787,7 +787,7 @@ subst_list_type * subst_list_alloc_deep_copy(const subst_list_type * src) {
subst_list_func_type * copy_node = subst_list_func_alloc( src_node->name , src_node->func );
vector_append_owned_ref( copy->func_data , copy_node , subst_list_func_free__ );
}
}
return copy;
}
@ -856,29 +856,28 @@ void subst_list_fprintf(const subst_list_type * subst_list , FILE * stream) {
KEY1=Value1, Key2=Value2, Key3=Value3. Will return NULL is there
are no elements in the subst_list.
*/
char * subst_list_alloc_string_representation( const subst_list_type * subst_list ) {
int size = subst_list_get_size( subst_list );
char * return_string = NULL;
if (size > 0) {
buffer_type * buffer = buffer_alloc( 512 );
int i;
for (i=0; i < size; i++) {
buffer_fwrite_char_ptr( buffer , subst_list_iget_key( subst_list , i));
buffer_fwrite_char(buffer , '=');
buffer_fwrite_char_ptr( buffer , subst_list_iget_value( subst_list , i));
if (i < (size - 1))
buffer_fwrite_char_ptr( buffer , ", ");
buffer_strcat(buffer , "=");
buffer_strcat( buffer , subst_list_iget_value( subst_list , i));
if (i < (size - 1))
buffer_strcat( buffer , ", ");
}
buffer_fwrite_char( buffer , '\0');
buffer_shrink_to_fit( buffer );
return_string = buffer_get_data( buffer );
buffer_free_container( buffer );
}
return return_string;
}
/** Will loose tagging .... */
int subst_list_add_from_string( subst_list_type * subst_list , const char * arg_string, bool append) {
@ -886,7 +885,7 @@ int subst_list_add_from_string( subst_list_type * subst_list , const char * arg_
if (arg_string != NULL) {
char ** key_value_list;
int num_arg, iarg;
util_split_string(arg_string , "," , &num_arg , &key_value_list);
for (iarg = 0; iarg < num_arg; iarg++) {
if (strchr(key_value_list[iarg] , '=') == NULL)
@ -902,27 +901,27 @@ int subst_list_add_from_string( subst_list_type * subst_list , const char * arg_
int arg_length , value_length;
while (isspace(*tmp)) /* Skipping initial space */
tmp++;
arg_length = strcspn(tmp , " =");
key = util_alloc_substring_copy(tmp , 0 , arg_length);
tmp += arg_length;
while ((*tmp == ' ') || (*tmp == '='))
tmp++;
value_length = strcspn(tmp , " ");
value = util_alloc_substring_copy( tmp , 0 , value_length);
/* Setting the argument */
if (append)
subst_list_append_copy( subst_list , key , value , NULL);
else
subst_list_prepend_copy( subst_list , key , value , NULL);
free(key);
free(value);
tmp += value_length;
/* Accept only trailing space - any other character indicates a failed parsing. */
while (*tmp != '\0') {
if (!isspace(*tmp))

View File

@ -119,15 +119,13 @@ static void loop_free( loop_type * loop ) {
static void replace_1var( buffer_type * var_expansion , int shift , int write_offset , int shift_offset , const char * value) {
buffer_memshift( var_expansion , shift_offset , shift );
buffer_fseek( var_expansion , write_offset , SEEK_SET );
buffer_fwrite_char_ptr( var_expansion , value );
buffer_fwrite( var_expansion , value , strlen(value) , 1);
}
static void loop_eval( const loop_type * loop , const char * body , buffer_type * var_expansion , int ivar) {
buffer_clear( var_expansion );
buffer_fwrite_char_ptr( var_expansion , body );
buffer_terminate_char_ptr( var_expansion );
{
const char * value = stringlist_iget( loop->items , ivar );
int value_length = strlen( value );
@ -235,13 +233,12 @@ static int template_eval_loop( const template_type * template , buffer_type * bu
for (ivar =0; ivar < stringlist_get_size( loop->items ); ivar++) {
loop_eval(loop , body , var_expansion , ivar );
buffer_fwrite_char_ptr( loop_expansion , buffer_get_data( var_expansion ));
buffer_strcat( loop_expansion , buffer_get_data( var_expansion ));
}
buffer_free( var_expansion );
util_safe_free( body );
}
buffer_terminate_char_ptr( loop_expansion );
{
int tag_length = loop->endtag_offset + loop->endtag_length - loop->opentag_offset;
int offset = loop->endtag_offset + loop->endtag_length;
@ -249,7 +246,7 @@ static int template_eval_loop( const template_type * template , buffer_type * bu
buffer_memshift( buffer , offset , shift );
buffer_fseek( buffer , loop->opentag_offset , SEEK_SET );
buffer_fwrite_char_ptr( buffer , buffer_get_data( loop_expansion ));
buffer_fwrite( buffer , buffer_get_data( loop_expansion ) , 1 , buffer_get_string_size( loop_expansion ));
global_offset = loop->opentag_offset + buffer_get_string_size( loop_expansion );
}

View File

@ -25,7 +25,9 @@
#include <signal.h>
#include <ert/util/util.h>
#include <ert/util/arg_pack.h>
#include <ert/util/test_util.h>
#include <ert/util/stringlist.h>
void test_error_exit( const char * fmt , ...) {
@ -317,3 +319,28 @@ void test_assert_util_abort(const char * function_name , void call_func (void *)
#endif
/*****************************************************************/
#ifdef WITH_PTHREAD
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void * thread_pool_test_func1( void * arg ) {
int * value = (int *) arg;
pthread_mutex_lock( &mutex );
value[0]++;
pthread_mutex_unlock( &mutex );
return NULL;
}
#endif
void * test_argpack_is_stringlist( void * arg ) {
arg_pack_type * arg_pack = arg_pack_safe_cast( arg );
void * arg0 = arg_pack_iget_ptr( arg_pack , 0 );
test_assert_true( stringlist_is_instance( arg0 ) );
return NULL;
}

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'thread_pool.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 'thread_pool.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 <ert/util/thread_pool.h>

View File

@ -20,11 +20,13 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <ert/util/thread_pool.h>
#include <ert/util/util.h>
#include <ert/util/type_macros.h>
/**
This file implements a small thread_pool object based on
@ -117,8 +119,9 @@ typedef struct {
#define THREAD_POOL_TYPE_ID 71443207
struct thread_pool_struct {
UTIL_TYPE_ID_DECLARATION;
thread_pool_arg_type * queue; /* The jobs to be executed are appended in this vector. */
int queue_index; /* The index of the next job to run. */
int queue_size; /* The number of jobs in the queue - including those which are complete. [Should be protected / atomic / ... ] */
@ -134,7 +137,7 @@ struct thread_pool_struct {
};
static UTIL_SAFE_CAST_FUNCTION( thread_pool , THREAD_POOL_TYPE_ID )
/**
@ -212,7 +215,7 @@ static void * thread_pool_start_job( void * arg ) {
*/
static void * thread_pool_main_loop( void * arg ) {
thread_pool_type * tp = (thread_pool_type *) arg;
thread_pool_type * tp = thread_pool_safe_cast( arg );
{
const int usleep_init = 1000; /* The sleep time when there are free slots available - but no jobs wanting to run. */
int internal_offset = 0; /* Keep track of the (index of) the last job slot fired off - minor time saving. */
@ -262,9 +265,8 @@ static void * thread_pool_main_loop( void * arg ) {
if (!slot_found) {
util_yield();
}
} else {
util_usleep(usleep_init); /* There are no jobs wanting to run. */
}
} else
util_usleep(usleep_init); /* There are no jobs wanting to run. */
/*****************************************************************/
/*
@ -349,6 +351,65 @@ void thread_pool_join(thread_pool_type * pool) {
}
}
/*
This will try to join the thread; if the manager thread has not
completed within @timeout_seconds the function will return false. If
the join fails the queue will be reset in a non-joining state and it
will be open for more jobs. Probably not in a 100% sane state.
*/
bool thread_pool_try_join(thread_pool_type * pool, int timeout_seconds) {
bool join_ok = true;
pool->join = true; /* Signals to the main thread that joining can start. */
if (pool->max_running > 0) {
struct timespec ts;
time_t timeout_time = time( NULL );
util_inplace_forward_seconds(&timeout_time , timeout_seconds );
ts.tv_sec = timeout_time;
ts.tv_nsec = 0;
#ifdef HAVE_TIMEDJOIN
{
int join_return = pthread_timedjoin_np( pool->dispatch_thread , NULL , &ts); /* Wait for the main thread to complete. */
if (join_return == 0)
pool->accepting_jobs = false;
else {
pool->join = false;
join_ok = false;
}
}
#else
while(true) {
if (pthread_kill(pool->dispatch_thread, 0) == 0){
util_yield();
} else {
pthread_join(pool->dispatch_thread, NULL);
pool->accepting_jobs = false;
break;
}
time_t now = time(NULL);
if(util_difftime_seconds(now, timeout_time) <= 0) {
join_ok = false;
break;
}
}
#endif
}
return join_ok;
}
/**
@ -360,6 +421,7 @@ void thread_pool_join(thread_pool_type * pool) {
thread_pool_type * thread_pool_alloc(int max_running , bool start_queue) {
thread_pool_type * pool = util_malloc( sizeof *pool );
UTIL_TYPE_ID_INIT( pool , THREAD_POOL_TYPE_ID );
pool->job_slots = util_calloc( max_running , sizeof * pool->job_slots );
pool->max_running = max_running;
pool->queue = NULL;

View File

@ -2637,6 +2637,7 @@ static int util_get_base_length(const char * file) {
int path_length = util_get_path_length(file);
const char * base_start;
const char * last_point;
long character_index;
if (path_length == strlen(file))
return 0;
@ -2646,7 +2647,9 @@ static int util_get_base_length(const char * file) {
base_start = &file[path_length + 1];
last_point = strrchr(base_start , '.');
if (last_point == NULL)
character_index = last_point - base_start;
if (last_point == NULL || character_index == 0)
return strlen(base_start);
else
return last_point - base_start;
@ -3243,6 +3246,15 @@ double util_difftime_seconds( time_t start_time , time_t end_time) {
*/
char * util_get_timezone() {
#if defined(HAVE_TZNAME)
return tzname[0];
#elif defined(HAVE_WINDOWS_TZNAME)
return _tzname[0];
#endif
}
time_t util_make_datetime(int sec, int min, int hour , int mday , int month , int year) {
struct tm ts;
ts.tm_sec = sec;
@ -3250,7 +3262,7 @@ time_t util_make_datetime(int sec, int min, int hour , int mday , int month , in
ts.tm_hour = hour;
ts.tm_mday = mday;
ts.tm_mon = month - 1;
ts.tm_year = year - 1900;
ts.tm_year = year - 1900;
ts.tm_isdst = -1; /* Negative value means mktime tries to determine automagically whether Daylight Saving Time is in effect. */
{
time_t t = mktime( &ts );
@ -4849,6 +4861,7 @@ void util_install_signals(void) {
Killing with SIGKILL (-9) will not give a backtrace.*/
signal(SIGABRT , util_abort_signal); /* Signal abort. */
signal(SIGILL , util_abort_signal); /* Signal illegal instruction. */
signal(SIGFPE , util_abort_signal); /* Floating point exception */
}

View File

@ -228,7 +228,6 @@ char * util_alloc_envvar( const char * value ) {
buffer_type * buffer = buffer_alloc( 1024 ); /* Start by filling up a buffer instance with
the current content of @value. */
buffer_fwrite_char_ptr( buffer , value );
buffer_fwrite_char( buffer , '\0' );
buffer_rewind( buffer );

View File

@ -10,6 +10,11 @@ set(PING_SERVERS "" CACHE STRING "List of servers for testing ping")
link_directories( ${ERT_BINARY_DIR}/libert_util/src )
add_executable( test_thread_pool test_thread_pool.c )
target_link_libraries( test_thread_pool ert_util test_util )
add_test( test_thread_pool valgrind --error-exitcode=1 --tool=memcheck ${EXECUTABLE_OUTPUT_PATH}/test_thread_pool )
add_executable( ert_util_type_vector_test ert_util_type_vector_test.c )
target_link_libraries( ert_util_type_vector_test ert_util test_util )
add_test( ert_util_type_vector_test ${EXECUTABLE_OUTPUT_PATH}/ert_util_type_vector_test )
@ -18,10 +23,19 @@ add_executable( ert_util_matrix ert_util_matrix.c )
target_link_libraries( ert_util_matrix ert_util test_util )
add_test( ert_util_matrix ${EXECUTABLE_OUTPUT_PATH}/ert_util_matrix )
add_executable( ert_util_subst_list ert_util_subst_list.c )
target_link_libraries( ert_util_subst_list ert_util test_util )
add_test( ert_util_subst_list ${EXECUTABLE_OUTPUT_PATH}/ert_util_subst_list )
add_executable( ert_util_matrix_stat ert_util_matrix_stat.c )
target_link_libraries( ert_util_matrix_stat ert_util test_util )
add_test( ert_util_matrix_stat ${EXECUTABLE_OUTPUT_PATH}/ert_util_matrix_stat )
add_executable( ert_util_buffer ert_util_buffer.c )
target_link_libraries( ert_util_buffer ert_util test_util )
add_test( ert_util_buffer ${EXECUTABLE_OUTPUT_PATH}/ert_util_buffer )
add_executable( ert_util_statistics ert_util_statistics.c )
target_link_libraries( ert_util_statistics ert_util test_util )
add_test( ert_util_statistics ${EXECUTABLE_OUTPUT_PATH}/ert_util_statistics )
@ -146,6 +160,10 @@ add_executable( ert_util_parent_path ert_util_parent_path.c )
target_link_libraries( ert_util_parent_path ert_util test_util )
add_test( ert_util_parent_path ${EXECUTABLE_OUTPUT_PATH}/ert_util_parent_path)
add_executable( ert_util_alloc_file_components ert_util_alloc_file_components.c )
target_link_libraries( ert_util_alloc_file_components ert_util test_util )
add_test( ert_util_alloc_file_components ${EXECUTABLE_OUTPUT_PATH}/ert_util_alloc_file_components)
add_executable( ert_util_work_area ert_util_work_area.c )
target_link_libraries( ert_util_work_area ert_util test_util )
add_test( NAME ert_util_work_area

View File

@ -0,0 +1,43 @@
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ert/util/util.h>
#include <ert/util/test_util.h>
bool checkPath(const char * path, const char * directory, const char * base_name, const char * extension) {
char * dir;
char * base;
char * ext;
util_alloc_file_components(path, &dir, &base, &ext);
bool success = true;
success = success && (util_string_equal(dir, directory) || dir == directory);
success = success && (util_string_equal(base, base_name) || base == base_name);
success = success && (util_string_equal(ext, extension) || ext == extension);
free(dir);
free(base);
free(ext);
return success;
}
int main(int argc , char ** argv) {
test_assert_true(checkPath("/dir/filename.ext", "/dir", "filename", "ext"));
test_assert_true(checkPath("/dir/subdir/filename.ext", "/dir/subdir", "filename", "ext"));
test_assert_true(checkPath("/dir/subdir/filename.name.ext", "/dir/subdir", "filename.name", "ext"));
test_assert_true(checkPath("/dir/subdir/filename", "/dir/subdir", "filename", NULL));
test_assert_true(checkPath("filename.ext", NULL, "filename", "ext"));
test_assert_true(checkPath("filename", NULL, "filename", NULL));
test_assert_true(checkPath(".filename", NULL, ".filename", NULL));
test_assert_true(checkPath(".filename.ext", NULL, ".filename", "ext"));
exit(0);
}

View File

@ -0,0 +1,144 @@
/*
Copyright (C) 2015 Statoil ASA, Norway.
The file 'ert_util_buffer.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/buffer.h>
void test_create() {
buffer_type * buffer = buffer_alloc( 1024 );
test_assert_true( buffer_is_instance( buffer ));
buffer_free( buffer );
}
void test_buffer_strchr() {
buffer_type * buffer = buffer_alloc( 1024 );
test_assert_false( buffer_strchr( buffer , 'A'));
buffer_fwrite_char_ptr(buffer , "XX AB AB AB");
test_assert_false( buffer_strchr( buffer , 'A'));
buffer_rewind( buffer );
test_assert_true( buffer_strchr( buffer , 'A')); buffer_fskip(buffer , 1);
test_assert_true( buffer_strchr( buffer , 'A')); buffer_fskip(buffer , 1);
test_assert_true( buffer_strchr( buffer , 'A')); buffer_fskip(buffer , 1);
test_assert_false( buffer_strchr( buffer , 'A'));
buffer_free( buffer );
}
void test_buffer_strstr() {
buffer_type * buffer = buffer_alloc( 1024 );
test_assert_false( buffer_strstr( buffer , "Hello World" ));
test_assert_false( buffer_strstr( buffer , "" ));
buffer_fwrite_char_ptr( buffer , "ABC");
test_assert_int_equal( buffer_get_size( buffer ), 4 );
test_assert_false( buffer_strstr( buffer , "ABC"));
buffer_rewind( buffer );
test_assert_true( buffer_strstr( buffer , "ABC"));
test_assert_int_equal( buffer_get_offset(buffer) , 0);
test_assert_string_equal( "ABC" , buffer_get_data(buffer));
{
size_t pos = buffer_get_offset( buffer );
test_assert_false( buffer_strstr( buffer , "ABCD" ));
test_assert_size_t_equal( pos , buffer_get_offset( buffer ));
}
buffer_rewind( buffer );
test_assert_true( buffer_strstr( buffer , "AB" ));
test_assert_true( buffer_strstr( buffer , "ABC" ));
test_assert_true( buffer_strstr( buffer , "BC" ));
test_assert_false( buffer_strstr( buffer , "ABC" ));
}
void test_buffer_search_replace1() {
buffer_type * buffer = buffer_alloc( 1024 );
test_assert_false( buffer_search_replace( buffer , "" , "XYZ"));
test_assert_false( buffer_search_replace( buffer , "XYZ" , "ABC"));
test_assert_false( buffer_search_replace( buffer , "XYZ" , ""));
buffer_fwrite_char_ptr(buffer , "ABC 123");
buffer_rewind(buffer);
test_assert_true( buffer_search_replace( buffer, "ABC" , "XYZ" ));
buffer_rewind( buffer );
test_assert_string_equal( "XYZ 123" , buffer_get_data( buffer ));
buffer_rewind( buffer );
test_assert_true( buffer_search_replace( buffer, "XYZ" , "A"));
buffer_rewind( buffer );
test_assert_string_equal( "A 123" , buffer_get_data( buffer ));
buffer_rewind( buffer );
test_assert_true( buffer_search_replace( buffer, "A", "XYZ"));
buffer_rewind( buffer );
test_assert_string_equal( "XYZ 123" , buffer_get_data( buffer ));
buffer_free( buffer );
}
void test_buffer_search_replace2() {
buffer_type * buffer = buffer_alloc( 1024 );
buffer_fwrite_char_ptr(buffer , "MAGIC_PRINT magic-list.txt <ERTCASE> __MAGIC__");
buffer_rewind( buffer );
test_assert_false( buffer_search_replace( buffer , "<CASE>" , "SUPERCase"));
test_assert_string_equal( "MAGIC_PRINT magic-list.txt <ERTCASE> __MAGIC__" , buffer_get_data( buffer));
buffer_rewind( buffer );
test_assert_true( buffer_search_replace( buffer , "<ERTCASE>" , "default"));
test_assert_string_equal( "MAGIC_PRINT magic-list.txt default __MAGIC__" , buffer_get_data( buffer));
buffer_free( buffer );
}
void test_char_ptr( ) {
buffer_type * buffer = buffer_alloc(1024);
buffer_fwrite_char_ptr( buffer , "Hello World");
test_assert_size_t_equal( buffer_get_size( buffer ) , 12 );
test_assert_int_equal( strlen( buffer_get_data( buffer )) , 11);
buffer_clear( buffer );
buffer_fwrite_char_ptr(buffer , "Hello" );
buffer_strcat( buffer , " " );
buffer_strcat( buffer , "World" );
test_assert_size_t_equal( buffer_get_size( buffer ) , 12 );
test_assert_int_equal( strlen( buffer_get_data( buffer )) , 11);
buffer_free( buffer );
}
int main( int argc , char ** argv) {
test_create();
test_char_ptr();
test_buffer_strchr();
test_buffer_strstr();
test_buffer_search_replace1();
test_buffer_search_replace2();
exit(0);
}

View File

@ -0,0 +1,97 @@
/*
Copyright (C) 2015 Statoil ASA, Norway.
The file 'ert_util_subst_list.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 <string.h>
#include <ert/util/test_work_area.h>
#include <ert/util/subst_list.h>
#include <ert/util/test_util.h>
void test_create() {
subst_list_type * subst_list = subst_list_alloc( NULL );
test_assert_true( subst_list_is_instance( subst_list ) );
subst_list_free( subst_list );
}
void test_filter_file1() {
subst_list_type * subst_list = subst_list_alloc( NULL );
test_work_area_type * work_area = test_work_area_alloc("subst_list/filter1");
{
FILE * stream = util_fopen("template" , "w");
fprintf(stream , "<KEY1>\n<KEY2>\n<KEY3>\n<KEY4>\n");
fclose(stream);
}
subst_list_append_copy( subst_list , "<KEY1>" , "Value1" , NULL);
subst_list_append_copy( subst_list , "<KEY2>" , "Value2" , NULL);
subst_list_append_copy( subst_list , "<KEY3>" , "Value3" , NULL);
subst_list_append_copy( subst_list , "<KEY4>" , "Value4" , NULL);
subst_list_filter_file( subst_list , "template" , "target");
{
FILE * stream = util_fopen("target" , "r");
char s1[128],s2[128],s3[128],s4[128];
test_assert_int_equal( 4 , fscanf( stream , "%s %s %s %s" , s1,s2,s3,s4));
fclose(stream);
test_assert_string_equal( s1 , "Value1");
test_assert_string_equal( s2 , "Value2");
test_assert_string_equal( s3 , "Value3");
test_assert_string_equal( s4 , "Value4");
}
test_work_area_free( work_area );
subst_list_free( subst_list );
}
void test_filter_file2() {
subst_list_type * subst_list = subst_list_alloc( NULL );
test_work_area_type * work_area = test_work_area_alloc("subst_list/filter2");
{
FILE * stream = util_fopen("template" , "w");
fprintf(stream , "MAGIC_PRINT magic-list.txt <ERTCASE> __MAGIC__");
fclose(stream);
}
subst_list_append_copy( subst_list , "<QC_PATH>" , "QC" , NULL);
subst_list_append_copy( subst_list , "__MAGIC__" , "MagicAllTheWayToWorkFlow" , NULL);
subst_list_append_copy( subst_list , "<CASE>" , "SUPERcase" , NULL);
subst_list_append_copy( subst_list , "<ERTCASE>" , "default" , NULL);
subst_list_filter_file( subst_list , "template" , "target");
{
char * target_string = util_fread_alloc_file_content( "target" , NULL );
test_assert_string_equal( target_string , "MAGIC_PRINT magic-list.txt default MagicAllTheWayToWorkFlow");
free( target_string );
}
test_work_area_free( work_area );
subst_list_free( subst_list );
}
int main(int argc , char ** argv) {
test_create();
test_filter_file1();
test_filter_file2();
}

View File

@ -0,0 +1,70 @@
/*
Copyright (C) 2015 Statoil ASA, Norway.
The file 'test_thread_pool.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 <pthread.h>
#include <ert/util/test_util.h>
#include <ert/util/thread_pool.h>
pthread_mutex_t lock;
void create_and_destroy() {
int run_size = 10;
thread_pool_type * tp = thread_pool_alloc( run_size , true );
thread_pool_join( tp );
thread_pool_free( tp );
}
void * inc(void * arg) {
int * int_arg = (int *) arg;
pthread_mutex_lock( &lock );
int_arg[0]++;
pthread_mutex_unlock( &lock );
return NULL;
}
void run() {
int run_size = 10;
int job_size = 1000;
int value = 0;
thread_pool_type * tp = thread_pool_alloc( run_size , true );
pthread_mutex_init(&lock , NULL);
for (int i=0; i < job_size; i++)
thread_pool_add_job( tp , inc , &value );
thread_pool_join( tp );
thread_pool_free( tp );
test_assert_int_equal( job_size , value );
pthread_mutex_destroy( &lock );
}
int main( int argc , char ** argv) {
create_and_destroy();
run();
}

View File

@ -0,0 +1,53 @@
/*
Copyright (C) 2015 Statoil ASA, Norway.
The file 'job_node.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 __JOB_LIST_H__
#define __JOB_LIST_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <ert/util/type_macros.h>
#include <ert/job_queue/queue_driver.h>
#include <ert/job_queue/job_node.h>
typedef struct job_list_struct job_list_type;
job_list_type * job_list_alloc();
void job_list_free( job_list_type * job_list );
int job_list_get_size( const job_list_type * job_list );
void job_list_add_job( job_list_type * job_list , job_queue_node_type * job_node );
job_queue_node_type * job_list_iget_job( const job_list_type * job_list , int queue_index);
void job_list_reset( job_list_type * job_list );
void job_list_get_wrlock( job_list_type * list);
void job_list_get_rdlock( job_list_type * list);
void job_list_reader_wait( job_list_type * list, int usleep_time1, int usleep_time2);
void job_list_unlock( job_list_type * list);
UTIL_SAFE_CAST_HEADER( job_list );
UTIL_IS_INSTANCE_HEADER( job_list );
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,115 @@
/*
Copyright (C) 2015 Statoil ASA, Norway.
The file 'job_node.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 __JOB_NODE_H__
#define __JOB_NODE_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <ert/util/type_macros.h>
#include <ert/job_queue/queue_driver.h>
#include <ert/job_queue/job_queue_status.h>
/**
This struct holds the job_queue information about one job. Observe
the following:
1. This struct is purely static - i.e. it is invisible outside of
this file-scope.
2. Typically the driver would like to store some additional
information, i.e. the PID of the running process for the local
driver; that is stored in a (driver specific) struct under the
field job_data.
3. If the driver detects that a job has failed it leaves an EXIT
file, the exit status is (currently) not reliably transferred
back to to the job_queue layer.
*/
typedef bool (job_callback_ftype) (void *);
typedef struct job_queue_node_struct job_queue_node_type;
bool job_queue_node_status_transition( job_queue_node_type * node , job_queue_status_type * status , job_status_type new_status);
submit_status_type job_queue_node_submit( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver);
void job_queue_node_free_error_info( job_queue_node_type * node );
void job_queue_node_fscanf_EXIT( job_queue_node_type * node );
void job_queue_node_clear_error_info(job_queue_node_type * node);
void job_queue_node_clear(job_queue_node_type * node);
void job_queue_node_free_data(job_queue_node_type * node);
job_queue_node_type * job_queue_node_alloc( const char * job_name ,
const char * run_path ,
const char * run_cmd ,
int argc ,
const char ** argv ,
int num_cpu ,
const char * ok_file,
const char * exit_file,
job_callback_ftype * done_callback,
job_callback_ftype * retry_callback,
job_callback_ftype * exit_callback,
void * callback_arg);
job_queue_node_type * job_queue_node_alloc_simple( const char * job_name ,
const char * run_path ,
const char * run_cmd ,
int argc ,
const char ** argv );
bool job_queue_node_kill( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver);
void job_queue_node_free(job_queue_node_type * node);
job_status_type job_queue_node_get_status(const job_queue_node_type * node);
void job_queue_node_free_driver_data( job_queue_node_type * node , queue_driver_type * driver);
void job_queue_node_restart( job_queue_node_type * node , job_queue_status_type * status);
bool job_queue_node_update_status( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver);
const char * job_queue_node_get_run_path( const job_queue_node_type * node);
const char * job_queue_node_get_name( const job_queue_node_type * node);
int job_queue_node_get_submit_attempt( const job_queue_node_type * node);
void job_queue_node_reset_submit_attempt( job_queue_node_type * node);
const char * job_queue_node_get_failed_job( const job_queue_node_type * node);
const char * job_queue_node_get_error_reason( const job_queue_node_type * node);
const char * job_queue_node_get_stderr_capture( const job_queue_node_type * node);
const char * job_queue_node_get_stderr_file( const job_queue_node_type * node);
time_t job_queue_node_get_sim_start( const job_queue_node_type * node );
time_t job_queue_node_get_sim_end( const job_queue_node_type * node );
time_t job_queue_node_get_submit_time( const job_queue_node_type * node );
const char * job_queue_node_get_ok_file( const job_queue_node_type * node);
const char * job_queue_node_get_exit_file( const job_queue_node_type * node);
bool job_queue_node_run_DONE_callback( job_queue_node_type * node );
bool job_queue_node_run_RETRY_callback( job_queue_node_type * node );
void job_queue_node_run_EXIT_callback( job_queue_node_type * node );
int job_queue_node_get_queue_index( const job_queue_node_type * node );
void job_queue_node_set_queue_index( job_queue_node_type * node , int queue_index);
UTIL_IS_INSTANCE_HEADER( job_queue_node );
UTIL_SAFE_CAST_HEADER( job_queue_node );
#ifdef __cplusplus
}
#endif
#endif

View File

@ -27,11 +27,11 @@ extern "C" {
#include <ert/util/path_fmt.h>
#include <ert/job_queue/queue_driver.h>
#include <ert/job_queue/job_node.h>
typedef bool (job_callback_ftype) (void *);
typedef struct job_queue_struct job_queue_type;
typedef struct job_queue_node_struct job_queue_node_type;
void job_queue_submit_complete( job_queue_type * queue );
job_driver_type job_queue_get_driver_type( const job_queue_type * queue );
@ -42,29 +42,17 @@ extern "C" {
job_queue_type * job_queue_alloc( int , const char * ok_file , const char * exit_file);
void job_queue_free(job_queue_type *);
int job_queue_add_job_mt(job_queue_type * ,
const char * run_cmd ,
job_callback_ftype * done_callback,
job_callback_ftype * retry_callback,
job_callback_ftype * exit_callback,
void * callback_arg ,
int num_cpu ,
const char * ,
const char * ,
int argc ,
const char ** argv );
int job_queue_add_job_st(job_queue_type * ,
const char * run_cmd ,
job_callback_ftype * done_callback,
job_callback_ftype * retry_callback,
job_callback_ftype * exit_callback,
void * callback_arg ,
int num_cpu ,
const char * ,
const char * ,
int argc ,
const char ** argv );
int job_queue_add_job(job_queue_type * ,
const char * run_cmd ,
job_callback_ftype * done_callback,
job_callback_ftype * retry_callback,
job_callback_ftype * exit_callback,
void * callback_arg ,
int num_cpu ,
const char * ,
const char * ,
int argc ,
const char ** argv );
void job_queue_reset(job_queue_type * queue);
void job_queue_run_jobs(job_queue_type * queue, int num_total_run, bool verbose);
@ -72,14 +60,12 @@ extern "C" {
void * job_queue_run_jobs__(void * );
void job_queue_start_manager_thread( job_queue_type * job_queue , pthread_t * queue_thread , int job_size , bool verbose);
job_status_type job_queue_iget_job_status(const job_queue_type * , int );
const char * job_queue_status_name( job_status_type status );
job_status_type job_queue_iget_job_status(job_queue_type * , int );
int job_queue_iget_status_summary( const job_queue_type * queue , job_status_type status);
time_t job_queue_iget_sim_start( job_queue_type * queue, int job_index);
time_t job_queue_iget_sim_end( job_queue_type * queue, int job_index);
time_t job_queue_iget_submit_time( job_queue_type * queue, int job_index);
job_driver_type job_queue_lookup_driver_name( const char * driver_name );
void job_queue_set_max_job_duration(job_queue_type * queue, int max_duration_seconds);
int job_queue_get_max_job_duration(const job_queue_type * queue);
@ -98,20 +84,25 @@ extern "C" {
void * job_queue_iget_job_data( job_queue_type * job_queue , int job_nr );
int job_queue_get_active_size( const job_queue_type * queue );
int job_queue_get_num_callback( const job_queue_type * queue);
int job_queue_get_num_running( const job_queue_type * queue);
int job_queue_get_num_pending( const job_queue_type * queue);
int job_queue_get_num_waiting( const job_queue_type * queue);
int job_queue_get_num_complete( const job_queue_type * queue);
int job_queue_get_num_failed( const job_queue_type * queue);
int job_queue_get_num_killed( const job_queue_type * queue);
const char * job_queue_iget_failed_job( const job_queue_type * queue , int job_index);
const char * job_queue_iget_error_reason( const job_queue_type * queue , int job_index);
const char * job_queue_iget_stderr_capture( const job_queue_type * queue , int job_index);
const char * job_queue_iget_stderr_file( const job_queue_type * queue , int job_index);
const char * job_queue_iget_run_path( const job_queue_type * queue , int job_index);
const char * job_queue_iget_failed_job( job_queue_type * queue , int job_index);
const char * job_queue_iget_error_reason( job_queue_type * queue , int job_index);
const char * job_queue_iget_stderr_capture( job_queue_type * queue , int job_index);
const char * job_queue_iget_stderr_file( job_queue_type * queue , int job_index);
const char * job_queue_iget_run_path( job_queue_type * queue , int job_index);
void job_queue_iset_external_restart(job_queue_type * queue , int job_index);
job_queue_node_type * job_queue_iget_job( job_queue_type * job_queue , int job_nr );
bool job_queue_has_driver(const job_queue_type * queue );
job_queue_node_type * job_queue_iget_node(job_queue_type * queue , int job_index);
int job_queue_get_max_running( const job_queue_type * queue );
UTIL_SAFE_CAST_HEADER( job_queue );
#ifdef __cplusplus
}

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'job_queue.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 'job_queue.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 __JOB_QUEUE_MANAGER_H__
@ -30,12 +30,19 @@ typedef struct job_queue_manager_struct job_queue_manager_type;
job_queue_manager_type * job_queue_manager_alloc( job_queue_type * job_queue );
void job_queue_manager_free( job_queue_manager_type * manager );
void job_queue_manager_start_queue( job_queue_manager_type * manager , int num_total_run , bool verbose);
void job_queue_manager_start_queue( job_queue_manager_type * manager , int num_total_run , bool verbose , bool reset_queue);
bool job_queue_manager_try_wait( job_queue_manager_type * manager , int timeout_seconds);
void job_queue_manager_wait( job_queue_manager_type * manager);
int job_queue_manager_get_num_running( const job_queue_manager_type * manager);
int job_queue_manager_get_num_complete( const job_queue_manager_type * manager);
int job_queue_manager_get_num_success( const job_queue_manager_type * manager);
int job_queue_manager_get_num_failed( const job_queue_manager_type * manager);
bool job_queue_manager_is_running( const job_queue_manager_type * manager);
bool job_queue_manager_job_success( const job_queue_manager_type * manager , int job_index);
bool job_queue_manager_job_complete( const job_queue_manager_type * manager , int job_index);
bool job_queue_manager_job_waiting( const job_queue_manager_type * manager , int job_index);
bool job_queue_manager_job_running( const job_queue_manager_type * manager , int job_index);
bool job_queue_manager_job_failed( const job_queue_manager_type * manager , int job_index);
UTIL_IS_INSTANCE_HEADER( job_queue_manager );

View File

@ -0,0 +1,46 @@
/*
Copyright (C) 2015 Statoil ASA, Norway.
The file 'job_status_test.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 __JOB_QUEUE_STATUS_H__
#define __JOB_QUEUE_STATUS_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <ert/util/type_macros.h>
#include <ert/job_queue/queue_driver.h>
typedef struct job_queue_status_struct job_queue_status_type;
job_queue_status_type * job_queue_status_alloc();
void job_queue_status_free( job_queue_status_type * status );
int job_queue_status_get_count( job_queue_status_type * status , job_status_type status_type);
void job_queue_status_clear( job_queue_status_type * status );
void job_queue_status_inc( job_queue_status_type * status_count , job_status_type status_type);
bool job_queue_status_transition( job_queue_status_type * status_count , job_status_type src_status , job_status_type target_status);
int job_queue_status_get_total_count( const job_queue_status_type * status );
const char * job_queue_status_name( job_status_type status );
UTIL_IS_INSTANCE_HEADER( job_queue_status );
UTIL_SAFE_CAST_HEADER( job_queue_status );
#ifdef __cplusplus
}
#endif
#endif

View File

@ -103,12 +103,10 @@ extern "C" {
*/
#define JOB_QUEUE_CAN_KILL (JOB_QUEUE_WAITING + JOB_QUEUE_RUNNING + JOB_QUEUE_PENDING + JOB_QUEUE_SUBMITTED + JOB_QUEUE_USER_EXIT)
#define JOB_QUEUE_WAITING_STATUS (JOB_QUEUE_WAITING + JOB_QUEUE_PENDING)
#define JOB_QUEUE_CAN_UPDATE_STATUS (JOB_QUEUE_RUNNING + JOB_QUEUE_PENDING + JOB_QUEUE_SUBMITTED)
#define JOB_QUEUE_COMPLETE_STATUS (JOB_QUEUE_USER_EXIT + JOB_QUEUE_SUCCESS + JOB_QUEUE_FAILED)
@ -147,6 +145,13 @@ extern "C" {
const char * queue_driver_type_enum_iget(int index, int * value);
const char * queue_driver_status_enum_iget(int index, int * value);
typedef enum {SUBMIT_OK = 0 ,
SUBMIT_JOB_FAIL = 1 , /* Typically no more attempts. */
SUBMIT_DRIVER_FAIL = 2 , /* The driver would not take the job - for whatever reason?? */
SUBMIT_QUEUE_CLOSED = 3 } /* The queue is currently not accepting more jobs - either (temporarilty)
because of pause or it is going down. */ submit_status_type;
#ifdef __cplusplus
}
#endif

View File

@ -1,7 +1,8 @@
#configure_file (${CMAKE_CURRENT_SOURCE_DIR}/CMake/include/libjob_queue_build_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/libjob_queue_build_config.h)
set(source_files forward_model.c queue_driver.c job_queue.c local_driver.c rsh_driver.c torque_driver.c ext_job.c ext_joblist.c workflow_job.c workflow.c workflow_joblist.c job_queue_manager.c)
set(header_files job_queue.h queue_driver.h local_driver.h rsh_driver.h torque_driver.h ext_job.h ext_joblist.h forward_model.h workflow_job.h workflow.h workflow_joblist.h job_queue_manager.h)
set(source_files job_queue_status.c forward_model.c queue_driver.c job_queue.c job_node.c job_list.c local_driver.c rsh_driver.c torque_driver.c ext_job.c ext_joblist.c workflow_job.c workflow.c workflow_joblist.c job_queue_manager.c)
set(header_files job_queue.h queue_driver.h local_driver.h job_node.h job_list.h rsh_driver.h torque_driver.h ext_job.h ext_joblist.h forward_model.h workflow_job.h workflow.h workflow_joblist.h job_queue_manager.h)
set_property(SOURCE rsh_driver.c PROPERTY COMPILE_FLAGS "-Wno-error")
list( APPEND source_files lsf_driver.c)

View File

@ -0,0 +1,151 @@
/*
Copyright (C) 2015 Statoil ASA, Norway.
The file 'job_list.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.
*/
#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <ert/util/msg.h>
#include <ert/util/util.h>
#include <ert/util/thread_pool.h>
#include <ert/util/arg_pack.h>
#include <ert/job_queue/job_node.h>
#include <ert/job_queue/job_list.h>
#define JOB_LIST_TYPE_ID 8154222
struct job_list_struct {
UTIL_TYPE_ID_DECLARATION;
int active_size;
int alloc_size;
job_queue_node_type ** jobs;
pthread_rwlock_t lock;
};
UTIL_IS_INSTANCE_FUNCTION( job_list , JOB_LIST_TYPE_ID )
UTIL_SAFE_CAST_FUNCTION( job_list , JOB_LIST_TYPE_ID )
job_list_type * job_list_alloc() {
job_list_type * job_list = util_malloc( sizeof * job_list );
UTIL_TYPE_ID_INIT( job_list , JOB_LIST_TYPE_ID );
job_list->active_size = 0;
job_list->alloc_size = 0;
job_list->jobs = NULL;
pthread_rwlock_init( &job_list->lock , NULL);
return job_list;
}
void job_list_reset( job_list_type * job_list ) {
int queue_index;
for (queue_index = 0; queue_index < job_list->active_size; queue_index++) {
job_queue_node_type * node = job_list_iget_job( job_list , queue_index );
job_queue_node_free( node );
job_list->jobs[queue_index] = NULL;
}
job_list->active_size = 0;
}
int job_list_get_size( const job_list_type * job_list ) {
return job_list->active_size;
}
/*
This takes ownership to the job node instance.
*/
#define QUEUE_DEBUG 1
void job_list_add_job( job_list_type * job_list , job_queue_node_type * job_node ) {
if (job_list->alloc_size == job_list->active_size) {
#ifdef QUEUE_DEBUG
int new_alloc_size = job_list->alloc_size + 1;
job_queue_node_type ** new_jobs = util_malloc( sizeof * new_jobs * new_alloc_size );
memcpy( new_jobs , job_list->jobs , sizeof * new_jobs * job_list->active_size );
free( job_list->jobs );
job_list->jobs = new_jobs;
#else
int new_alloc_size = util_int_max( 16 , job_list->alloc_size * 2);
job_list->jobs = util_realloc( job_list->jobs , sizeof * job_list->jobs * new_alloc_size );
#endif
job_list->alloc_size = new_alloc_size;
}
{
int queue_index = job_list_get_size( job_list );
job_queue_node_set_queue_index(job_node, queue_index );
job_list->jobs[queue_index] = job_node;
}
job_list->active_size++;
}
job_queue_node_type * job_list_iget_job( const job_list_type * job_list , int queue_index) {
if (queue_index >= 0 && queue_index < job_list->active_size)
return job_list->jobs[queue_index];
else {
util_abort("%s: invalid queue_index:%d Valid range: [0,%d) \n",__func__ , queue_index , queue_index);
return NULL;
}
}
void job_list_free( job_list_type * job_list ) {
if (job_list->alloc_size > 0) {
job_list_reset( job_list );
free( job_list->jobs );
}
free( job_list );
}
void job_list_get_wrlock( job_list_type * list) {
pthread_rwlock_wrlock( &list->lock );
}
void job_list_get_rdlock( job_list_type * list) {
pthread_rwlock_rdlock( &list->lock );
}
void job_list_unlock( job_list_type * list) {
pthread_rwlock_unlock( &list->lock );
}
void job_list_reader_wait( job_list_type * list, int usleep_time1, int usleep_time2) {
if (pthread_rwlock_tryrdlock( &list->lock ) == 0) {
// Seems to be no writers waiting - take a short sleep and return.
pthread_rwlock_unlock( &list->lock );
usleep( usleep_time1 );
} else
// A writer already has the lock - let more writers get access; sleep longer.
usleep( usleep_time2 );
}

View File

@ -0,0 +1,558 @@
/*
Copyright (C) 2015 Statoil ASA, Norway.
The file 'job_node.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.
*/
#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <ert/util/msg.h>
#include <ert/util/util.h>
#include <ert/util/thread_pool.h>
#include <ert/util/arg_pack.h>
#include <ert/util/type_macros.h>
#include <ert/job_queue/job_node.h>
#define JOB_QUEUE_NODE_TYPE_ID 3315299
#define INVALID_QUEUE_INDEX -999
struct job_queue_node_struct {
UTIL_TYPE_ID_DECLARATION;
int num_cpu; /* How many cpu's will this job need - the driver is free to ignore if not relevant. */
char *run_cmd; /* The path to the actual executable. */
char *exit_file; /* The queue will look for the occurence of this file to detect a failure. */
char *ok_file; /* The queue will look for this file to verify that the job was OK - can be NULL - in which case it is ignored. */
char *job_name; /* The name of the job. */
char *run_path; /* Where the job is run - absolute path. */
job_callback_ftype *done_callback;
job_callback_ftype *retry_callback; /* To determine if job can be retried */
job_callback_ftype *exit_callback; /* Callback to perform any cleanup */
void *callback_arg;
int argc; /* The number of commandline arguments to pass when starting the job. */
char **argv; /* The commandline arguments. */
int queue_index;
/*-----------------------------------------------------------------*/
char *failed_job; /* Name of the job (in the chain) which has failed. */
char *error_reason; /* The error message from the failed job. */
char *stderr_capture;
char *stderr_file; /* Name of the file containing stderr information. */
/*-----------------------------------------------------------------*/
int submit_attempt; /* Which attempt is this ... */
job_status_type job_status; /* The current status of the job. */
pthread_mutex_t data_mutex; /* Protecting the access to the job_data pointer. */
void *job_data; /* Driver specific data about this job - fully handled by the driver. */
time_t submit_time; /* When was the job added to job_queue - the FIRST TIME. */
time_t sim_start; /* When did the job change status -> RUNNING - the LAST TIME. */
time_t sim_end ; /* When did the job finish successfully */
};
void job_queue_node_free_error_info( job_queue_node_type * node ) {
util_safe_free(node->error_reason);
util_safe_free(node->stderr_capture);
util_safe_free(node->stderr_file);
util_safe_free(node->failed_job);
}
/*
When the job script has detected failure it will create a "EXIT"
file in the runpath directory; this function will inspect the EXIT
file and determine which job has failed, the reason the job script
has given to fail the job (typically missing TARGET_FILE) and
capture the stderr from the job.
The file is XML formatted:
------------------------------------------------
<error>
<time>HH:MM:SS</time>
<job> Name of job </job>
<reason> Reason why the job failed </reason>
<stderr>
Capture of stderr from the job, can typically be
a multiline string.
</stderr>
</error>
------------------------------------------------
This format is written by the dump_EXIT_file() function in the
job_dispatch.py script.
*/
/*
This extremely half-assed XML "parsing" should of course be kept a
secret...
*/
static char * __alloc_tag_content( const char * xml_buffer , const char * tag) {
char * open_tag = util_alloc_sprintf("<%s>" , tag);
char * close_tag = util_alloc_sprintf("</%s>" , tag);
char * start_ptr = strstr( xml_buffer , open_tag );
char * end_ptr = strstr( xml_buffer , close_tag );
char * tag_content = NULL;
if ((start_ptr != NULL) && (end_ptr != NULL)) {
int length;
start_ptr += strlen(open_tag);
length = end_ptr - start_ptr;
tag_content = util_alloc_substring_copy( start_ptr , 0 , length );
}
free( open_tag );
free( close_tag );
return tag_content;
}
/**
This code is meant to capture which of the jobs has failed; why it
has failed and the stderr stream of the failing job. Depending on
the failure circumstances the EXIT file might not be around.
*/
void job_queue_node_fscanf_EXIT( job_queue_node_type * node ) {
job_queue_node_free_error_info( node );
if (node->exit_file) {
if (util_file_exists( node->exit_file )) {
char * xml_buffer = util_fread_alloc_file_content( node->exit_file, NULL);
node->failed_job = __alloc_tag_content( xml_buffer , "job" );
node->error_reason = __alloc_tag_content( xml_buffer , "reason" );
node->stderr_capture = __alloc_tag_content( xml_buffer , "stderr");
node->stderr_file = __alloc_tag_content( xml_buffer , "stderr_file");
free( xml_buffer );
} else
node->failed_job = util_alloc_sprintf("EXIT file:%s not found - load failure?" , node->exit_file);
}
}
UTIL_IS_INSTANCE_FUNCTION( job_queue_node , JOB_QUEUE_NODE_TYPE_ID )
UTIL_SAFE_CAST_FUNCTION( job_queue_node , JOB_QUEUE_NODE_TYPE_ID )
int job_queue_node_get_queue_index( const job_queue_node_type * node ) {
if (node->queue_index == INVALID_QUEUE_INDEX)
util_abort("%s: internal error: asked for not-yet-initialized node->queue_index\n",__func__);
return node->queue_index;
}
void job_queue_node_set_queue_index( job_queue_node_type * node , int queue_index) {
if (node->queue_index == INVALID_QUEUE_INDEX)
node->queue_index = queue_index;
else
util_abort("%s: internal error: atteeempt to reset queue_index \n",__func__);
}
/*
The error information is retained even after the job has completed
completely, so that calling scope can ask for it - that is the
reason there are separate free() and clear functions for the error related fields.
*/
void job_queue_node_free_data(job_queue_node_type * node) {
util_safe_free( node->job_name );
util_safe_free( node->exit_file );
util_safe_free( node->ok_file );
util_safe_free( node->run_cmd );
util_free_stringlist( node->argv , node->argc );
if (node->job_data != NULL)
util_abort("%s: internal error - driver spesific job data has not been freed - will leak.\n",__func__);
}
void job_queue_node_free(job_queue_node_type * node) {
job_queue_node_free_data(node);
job_queue_node_free_error_info(node);
util_safe_free(node->run_path);
free(node);
}
job_status_type job_queue_node_get_status(const job_queue_node_type * node) {
return node->job_status;
}
/******************************************************************/
/*
These four functions all require that the caller has aquired the
data lock before entering.
*/
void job_queue_node_reset_submit_attempt( job_queue_node_type * node) {
node->submit_attempt = 0;
}
int job_queue_node_get_submit_attempt( const job_queue_node_type * node) {
return node->submit_attempt;
}
job_queue_node_type * job_queue_node_alloc_simple( const char * job_name ,
const char * run_path ,
const char * run_cmd ,
int argc ,
const char ** argv) {
return job_queue_node_alloc( job_name , run_path , run_cmd , argc , argv , 1, NULL , NULL, NULL, NULL, NULL, NULL);
}
job_queue_node_type * job_queue_node_alloc( const char * job_name ,
const char * run_path ,
const char * run_cmd ,
int argc ,
const char ** argv,
int num_cpu,
const char * ok_file,
const char * exit_file,
job_callback_ftype * done_callback,
job_callback_ftype * retry_callback,
job_callback_ftype * exit_callback,
void * callback_arg) {
if (util_is_directory( run_path )) {
job_queue_node_type * node = util_malloc(sizeof * node );
UTIL_TYPE_ID_INIT( node , JOB_QUEUE_NODE_TYPE_ID );
{
/* The data initialized in this block should *NEVER* change. */
node->job_name = util_alloc_string_copy( job_name );
if (util_is_abs_path(run_path))
node->run_path = util_alloc_string_copy( run_path );
else
node->run_path = util_alloc_realpath( run_path );
node->run_cmd = util_alloc_string_copy( run_cmd );
node->argc = argc;
node->argv = util_alloc_stringlist_copy( argv , argc );
node->num_cpu = num_cpu;
if (ok_file)
node->ok_file = util_alloc_filename(node->run_path , ok_file , NULL);
else
node->ok_file = NULL;
if (exit_file)
node->exit_file = util_alloc_filename(node->run_path , exit_file , NULL);
else
node->exit_file = NULL;
node->exit_callback = exit_callback;
node->retry_callback = retry_callback;
node->done_callback = done_callback;
node->callback_arg = callback_arg;
}
{
node->error_reason = NULL;
node->stderr_capture = NULL;
node->stderr_file = NULL;
node->failed_job = NULL;
}
{
node->job_status = JOB_QUEUE_NOT_ACTIVE;
node->queue_index = INVALID_QUEUE_INDEX;
node->submit_attempt = 0;
node->job_data = NULL; /* The allocation is run in single thread mode - we assume. */
node->sim_start = 0;
node->sim_end = 0;
node->submit_time = time( NULL );
}
pthread_mutex_init( &node->data_mutex , NULL );
return node;
} else
return NULL;
}
const char * job_queue_node_get_error_reason( const job_queue_node_type * node) {
return node->error_reason;
}
const char * job_queue_node_get_stderr_capture( const job_queue_node_type * node) {
return node->stderr_capture;
}
const char * job_queue_node_get_stderr_file( const job_queue_node_type * node) {
return node->stderr_file;
}
const char * job_queue_node_get_exit_file( const job_queue_node_type * node) {
return node->exit_file;
}
const char * job_queue_node_get_ok_file( const job_queue_node_type * node) {
return node->ok_file;
}
const char * job_queue_node_get_run_path( const job_queue_node_type * node) {
return node->run_path;
}
const char * job_queue_node_get_name( const job_queue_node_type * node) {
return node->job_name;
}
const char * job_queue_node_get_failed_job( const job_queue_node_type * node) {
return node->failed_job;
}
time_t job_queue_node_get_sim_start( const job_queue_node_type * node ) {
return node->sim_start;
}
time_t job_queue_node_get_sim_end( const job_queue_node_type * node ) {
return node->sim_end;
}
time_t job_queue_node_get_submit_time( const job_queue_node_type * node ) {
return node->submit_time;
}
bool job_queue_node_run_DONE_callback( job_queue_node_type * node ) {
bool OK = true;
if (node->done_callback)
OK = node->done_callback( node->callback_arg );
return OK;
}
bool job_queue_node_run_RETRY_callback( job_queue_node_type * node ) {
bool retry = false;
if (node->retry_callback)
retry = node->retry_callback( node->callback_arg );
return retry;
}
void job_queue_node_run_EXIT_callback( job_queue_node_type * node ) {
if (node->exit_callback)
node->exit_callback( node->callback_arg );
}
static void job_queue_node_set_status(job_queue_node_type * node , job_status_type new_status) {
if (new_status != node->job_status) {
node->job_status = new_status;
/*
We record sim start when the node is in state JOB_QUEUE_WAITING
to be sure that we do not miss the start time completely for
very fast jobs which are registered in the state
JOB_QUEUE_RUNNING.
*/
if (new_status == JOB_QUEUE_WAITING)
node->sim_start = time( NULL );
if (new_status == JOB_QUEUE_RUNNING)
node->sim_start = time( NULL );
if (new_status == JOB_QUEUE_SUCCESS)
node->sim_end = time( NULL );
if (new_status == JOB_QUEUE_FAILED)
job_queue_node_fscanf_EXIT( node );
}
}
submit_status_type job_queue_node_submit( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver) {
submit_status_type submit_status;
void * job_data = queue_driver_submit_job( driver,
node->run_cmd,
node->num_cpu,
node->run_path,
node->job_name,
node->argc,
(const char **) node->argv);
pthread_mutex_lock( &node->data_mutex );
{
if (job_data != NULL) {
job_status_type old_status = node->job_status;
job_status_type new_status = JOB_QUEUE_SUBMITTED;
node->job_data = job_data;
node->submit_attempt++;
/*
The status JOB_QUEUE_SUBMITTED is internal, and not
exported anywhere. The job_queue_update_status() will
update this to PENDING or RUNNING at the next call. The
important difference between SUBMITTED and WAITING is
that SUBMITTED have job_data != NULL and the
job_queue_node free function must be called on it.
*/
submit_status = SUBMIT_OK;
job_queue_node_set_status( node , new_status);
job_queue_status_transition(status, old_status, new_status);
} else
/*
In this case the status of the job itself will be
unmodified; i.e. it will still be WAITING, and a new attempt
to submit it will be performed in the next round.
*/
submit_status = SUBMIT_DRIVER_FAIL;
}
pthread_mutex_unlock( &node->data_mutex );
return submit_status;
}
bool job_queue_node_update_status( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver) {
bool status_change = false;
pthread_mutex_lock( &node->data_mutex );
{
if (node->job_data) {
job_status_type current_status = job_queue_node_get_status(node);
if (current_status & JOB_QUEUE_CAN_UPDATE_STATUS) {
job_status_type new_status = queue_driver_get_status( driver , node->job_data);
status_change = job_queue_status_transition(status , current_status , new_status);
job_queue_node_set_status(node,new_status);
}
}
}
pthread_mutex_unlock( &node->data_mutex );
return status_change;
}
bool job_queue_node_status_transition( job_queue_node_type * node , job_queue_status_type * status , job_status_type new_status) {
bool status_change;
pthread_mutex_lock( &node->data_mutex );
{
job_status_type old_status = job_queue_node_get_status( node );
status_change = job_queue_status_transition(status , old_status, new_status);
if (status_change)
job_queue_node_set_status( node , new_status );
}
pthread_mutex_unlock( &node->data_mutex );
return status_change;
}
bool job_queue_node_kill( job_queue_node_type * node , job_queue_status_type * status , queue_driver_type * driver) {
bool result = false;
pthread_mutex_lock( &node->data_mutex );
{
job_status_type current_status = job_queue_node_get_status( node );
if (current_status & JOB_QUEUE_CAN_KILL) {
/*
Jobs with status JOB_QUEUE_WAITING are killable - in the
sense that status should be set to JOB_QUEUE_USER_KILLED; but
they do not have any driver specific job_data, and the
driver->kill_job() function can NOT be called.
*/
if (current_status != JOB_QUEUE_WAITING) {
queue_driver_kill_job( driver , node->job_data );
if (node->job_data) {
queue_driver_free_job( driver , node->job_data );
node->job_data = NULL;
}
}
job_queue_status_transition(status, current_status, JOB_QUEUE_USER_KILLED);
job_queue_node_set_status( node , JOB_QUEUE_USER_KILLED);
result = true;
}
}
pthread_mutex_unlock( &node->data_mutex );
return result;
}
/*
This frees the storage allocated by the driver - the storage
allocated by the queue layer is retained.
In the case of jobs which are first marked as successfull by the
queue layer, and then subsequently set to status EXIT by the
DONE_callback this function will be called twice; i.e. we must
protect against a double free.
*/
void job_queue_node_free_driver_data( job_queue_node_type * node , queue_driver_type * driver) {
pthread_mutex_lock( &node->data_mutex );
{
if (node->job_data != NULL)
queue_driver_free_job( driver , node->job_data );
node->job_data = NULL;
}
pthread_mutex_unlock( &node->data_mutex );
}
void job_queue_node_restart( job_queue_node_type * node , job_queue_status_type * status) {
pthread_mutex_lock( &node->data_mutex );
{
job_status_type current_status = job_queue_node_get_status( node );
job_queue_status_transition(status, current_status, JOB_QUEUE_WAITING);
job_queue_node_set_status( node , JOB_QUEUE_WAITING);
job_queue_node_reset_submit_attempt(node);
}
pthread_mutex_unlock( &node->data_mutex );
}

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2014 Statoil ASA, Norway.
The file 'job_queue_manager.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 'job_queue_manager.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.
*/
#define _GNU_SOURCE /* Must define this to get access to pthread_rwlock_t */
@ -21,6 +21,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
@ -57,14 +58,52 @@ void job_queue_manager_free( job_queue_manager_type * manager) {
}
void job_queue_manager_start_queue( job_queue_manager_type * manager , int num_total_run , bool verbose) {
void job_queue_manager_start_queue( job_queue_manager_type * manager , int num_total_run , bool verbose , bool reset_queue) {
if (reset_queue)
job_queue_reset( manager->job_queue );
job_queue_start_manager_thread( manager->job_queue , &manager->queue_thread , num_total_run , verbose );
}
void job_queue_manager_wait( job_queue_manager_type * manager) {
pthread_join( manager->queue_thread , NULL );
pthread_join( manager->queue_thread , NULL );
}
bool job_queue_manager_try_wait( job_queue_manager_type * manager , int timeout_seconds) {
struct timespec ts;
time_t timeout_time = time( NULL );
util_inplace_forward_seconds(&timeout_time , timeout_seconds );
ts.tv_sec = timeout_time;
ts.tv_nsec = 0;
#ifdef HAVE_TIMEDJOIN
{
int join_return = pthread_timedjoin_np( manager->queue_thread , NULL , &ts); /* Wait for the main thread to complete. */
if (join_return == 0)
return true;
else
return false;
}
#else
while(true) {
if (pthread_kill(manager->queue_thread, 0) == 0){
util_yield();
} else {
return true;
}
time_t now = time(NULL);
if(util_difftime_seconds(now, timeout_time) <= 0) {
return false;
}
}
#endif
}
@ -78,10 +117,15 @@ int job_queue_manager_get_num_running( const job_queue_manager_type * manager) {
}
int job_queue_manager_get_num_complete( const job_queue_manager_type * manager) {
int job_queue_manager_get_num_success( const job_queue_manager_type * manager) {
return job_queue_get_num_complete( manager->job_queue );
}
int job_queue_manager_get_num_failed( const job_queue_manager_type * manager) {
return job_queue_get_num_failed( manager->job_queue );
}
bool job_queue_manager_job_complete( const job_queue_manager_type * manager , int job_index) {
job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index );
@ -90,3 +134,38 @@ bool job_queue_manager_job_complete( const job_queue_manager_type * manager , in
else
return false;
}
bool job_queue_manager_job_waiting( const job_queue_manager_type * manager , int job_index) {
job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index );
if (status & JOB_QUEUE_WAITING_STATUS)
return true;
else
return false;
}
bool job_queue_manager_job_running( const job_queue_manager_type * manager , int job_index) {
job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index );
if (status == JOB_QUEUE_RUNNING)
return true;
else
return false;
}
bool job_queue_manager_job_failed( const job_queue_manager_type * manager , int job_index) {
job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index );
if (status == JOB_QUEUE_FAILED)
return true;
else
return false;
}
bool job_queue_manager_job_success( const job_queue_manager_type * manager , int job_index) {
job_status_type status = job_queue_iget_job_status( manager->job_queue , job_index );
if (status == JOB_QUEUE_SUCCESS)
return true;
else
return false;
}

View File

@ -0,0 +1,161 @@
/*
Copyright (C) 2015 Statoil ASA, Norway.
The file 'job_status_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 <pthread.h>
#include <ert/util/type_macros.h>
#include <ert/util/util.h>
#include <ert/job_queue/queue_driver.h>
#include <ert/job_queue/job_queue_status.h>
#define JOB_QUEUE_STATUS_TYPE_ID 777620306
struct job_queue_status_struct {
UTIL_TYPE_ID_DECLARATION;
int status_list[JOB_QUEUE_MAX_STATE];
pthread_mutex_t update_mutex;
};
static const int status_index[] = { JOB_QUEUE_NOT_ACTIVE , // Initial, allocated job state, job not added - controlled by job_queue
JOB_QUEUE_WAITING , // The job is ready to be started - controlled by job_queue
JOB_QUEUE_SUBMITTED , // Job is submitted to driver - temporary state - controlled by job_queue
JOB_QUEUE_PENDING , // Job is pending, before actual execution - controlled by queue_driver
JOB_QUEUE_RUNNING , // Job is executing - controlled by queue_driver
JOB_QUEUE_DONE , // Job is done (sucessful or not), temporary state - controlled/returned by by queue_driver
JOB_QUEUE_EXIT , // Job is done, with exit status != 0, temporary state - controlled/returned by by queue_driver
JOB_QUEUE_USER_EXIT , // User / queue system has requested killing of job - controlled by job_queue / external scope
JOB_QUEUE_USER_KILLED, // Job has been killed, due to JOB_QUEUE_USER_EXIT, FINAL STATE - controlled by job_queue
JOB_QUEUE_SUCCESS , // All good, comes after JOB_QUEUE_DONE, with additional checks, FINAL STATE - controlled by job_queue
JOB_QUEUE_RUNNING_CALLBACK, // Temporary state, while running requested callbacks after an ended job - controlled by job_queue
JOB_QUEUE_FAILED }; // Job has failed, no more retries, FINAL STATE
static const char* status_name[] = { "JOB_QUEUE_NOT_ACTIVE" ,
"JOB_QUEUE_WAITING" ,
"JOB_QUEUE_SUBMITTED" ,
"JOB_QUEUE_PENDING" ,
"JOB_QUEUE_RUNNING" ,
"JOB_QUEUE_DONE" ,
"JOB_QUEUE_EXIT" ,
"JOB_QUEUE_USER_KILLED" ,
"JOB_QUEUE_USER_EXIT" ,
"JOB_QUEUE_SUCCESS" ,
"JOB_QUEUE_RUNNING_CALLBACK",
"JOB_QUEUE_FAILED" };
static int STATUS_INDEX( job_status_type status ) {
int index = 0;
while (true) {
if (status_index[index] == status)
return index;
index++;
if (index == JOB_QUEUE_MAX_STATE)
util_abort("%s: failed to get index from status:%d \n",__func__ , status);
}
}
UTIL_IS_INSTANCE_FUNCTION( job_queue_status , JOB_QUEUE_STATUS_TYPE_ID )
UTIL_SAFE_CAST_FUNCTION( job_queue_status , JOB_QUEUE_STATUS_TYPE_ID )
job_queue_status_type * job_queue_status_alloc() {
job_queue_status_type * status = util_malloc( sizeof * status );
UTIL_TYPE_ID_INIT( status , JOB_QUEUE_STATUS_TYPE_ID );
pthread_mutex_init( &status->update_mutex , NULL );
job_queue_status_clear( status );
return status;
}
void job_queue_status_free( job_queue_status_type * status ) {
free( status );
}
void job_queue_status_clear( job_queue_status_type * status ) {
int index;
for (index = 0; index < JOB_QUEUE_MAX_STATE; index++)
status->status_list[ index ] = 0;
}
int job_queue_status_get_count( job_queue_status_type * status_count , job_status_type status_type) {
int index = STATUS_INDEX( status_type );
int count;
count = status_count->status_list[index];
return count;
}
void job_queue_status_inc( job_queue_status_type * status_count , job_status_type status_type) {
int index = STATUS_INDEX( status_type );
pthread_mutex_lock( &status_count->update_mutex );
{
int count = status_count->status_list[index];
status_count->status_list[index] = count + 1;
}
pthread_mutex_unlock( &status_count->update_mutex );
}
static void job_queue_status_dec( job_queue_status_type * status_count , job_status_type status_type) {
int index = STATUS_INDEX( status_type );
pthread_mutex_lock( &status_count->update_mutex );
{
int count = status_count->status_list[index];
status_count->status_list[index] = count - 1;
}
pthread_mutex_unlock( &status_count->update_mutex );
}
/*
The important point is that each individual ++ and -- operation is
atomic, if the different status counts do not add upp perfectly at
all times that is ok.
*/
bool job_queue_status_transition( job_queue_status_type * status_count , job_status_type src_status , job_status_type target_status) {
if (src_status != target_status) {
job_queue_status_dec( status_count , src_status );
job_queue_status_inc( status_count , target_status );
return true;
} else
return false;
}
int job_queue_status_get_total_count( const job_queue_status_type * status ) {
int total_count = 0;
for (int index = 0; index < JOB_QUEUE_MAX_STATE; index++)
total_count += status->status_list[ index ];
return total_count;
}
const char * job_queue_status_name( job_status_type status ) {
int index = STATUS_INDEX( status );
return status_name[index];
}

View File

@ -21,6 +21,7 @@
#include <string.h>
#include <pthread.h>
#include <dlfcn.h>
#include <unistd.h>
#include <ert/util/util.h>
#include <ert/util/hash.h>
@ -348,12 +349,11 @@ static int lsf_driver_submit_internal_job( lsf_driver_type * driver ,
char * command;
{
buffer_type * command_buffer = buffer_alloc( 256 );
buffer_fwrite_char_ptr( command_buffer , submit_cmd );
buffer_strcat( command_buffer , submit_cmd );
for (int iarg = 0; iarg < argc; iarg++) {
buffer_fwrite_char( command_buffer , ' ');
buffer_fwrite_char_ptr( command_buffer , argv[ iarg ]);
buffer_strcat( command_buffer , " ");
buffer_strcat( command_buffer , argv[ iarg ]);
}
buffer_terminate_char_ptr( command_buffer );
command = buffer_get_data( command_buffer );
buffer_free_container( command_buffer );
}

View File

@ -341,7 +341,7 @@ void rsh_driver_free__(void * __driver) {
}
void rsh_driver_set_host_list( rsh_driver_type * rsh_driver , hash_type * rsh_host_list) {
void rsh_driver_set_host_list( rsh_driver_type * rsh_driver , const hash_type * rsh_host_list) {
rsh_driver_clear_host_list( rsh_driver );
if (rsh_host_list != NULL) {
hash_iter_type * hash_iter = hash_iter_alloc( rsh_host_list );
@ -429,7 +429,7 @@ bool rsh_driver_set_option( void * __driver , const char * option_key , const vo
rsh_driver_add_host_from_string( driver , value );
else if (strcmp(RSH_HOSTLIST , option_key) == 0) { /* Set full host list - value should be hash of integers. */
if (value != NULL) {
hash_type * hash_value = hash_safe_cast( value );
const hash_type * hash_value = hash_safe_cast_const( value );
rsh_driver_set_host_list( driver , hash_value );
}
} else if (strcmp( RSH_CLEAR_HOSTLIST , option_key) == 0)

View File

@ -1,17 +1,25 @@
add_executable( job_status_test job_status_test.c )
add_executable( job_loadOK job_loadOK.c )
add_executable( job_loadFail job_loadFail.c )
add_executable( job_node_test job_node_test.c )
add_executable( job_list_test job_list_test.c )
add_executable( create_file create_file.c )
add_executable( job_workflow_test job_workflow_test.c )
add_executable( job_lsf_parse_bsub_stdout job_lsf_parse_bsub_stdout.c )
add_executable( ext_joblist_test ext_joblist_test.c )
target_link_libraries( job_status_test job_queue test_util )
target_link_libraries( job_workflow_test job_queue test_util )
target_link_libraries( create_file job_queue test_util )
target_link_libraries( job_loadOK job_queue test_util )
target_link_libraries( job_loadFail job_queue test_util )
target_link_libraries( ext_joblist_test job_queue test_util )
target_link_libraries( job_lsf_parse_bsub_stdout job_queue test_util)
target_link_libraries( job_node_test job_queue test_util)
target_link_libraries( job_list_test job_queue test_util)
add_test( job_status_test ${EXECUTABLE_OUTPUT_PATH}/job_status_test)
add_test( job_lsf_parse_bsub_stdout ${EXECUTABLE_OUTPUT_PATH}/job_lsf_parse_bsub_stdout )
add_test( job_workflow_test ${EXECUTABLE_OUTPUT_PATH}/job_workflow_test ${EXECUTABLE_OUTPUT_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/data/internal_job)
@ -24,7 +32,8 @@ add_test( job_loadFail1 ${EXECUTABLE_OUTPUT_PATH}/job_loadFail ${CMAKE_CURRENT_S
add_test( job_loadFail2 ${EXECUTABLE_OUTPUT_PATH}/job_loadFail ${CMAKE_CURRENT_SOURCE_DIR}/data/externalFail)
add_test( job_loadFail3 ${EXECUTABLE_OUTPUT_PATH}/job_loadFail ${CMAKE_CURRENT_SOURCE_DIR}/data/internalFail ${CMAKE_CURRENT_SOURCE_DIR}/data/externalFail)
add_test( job_node_test ${EXECUTABLE_OUTPUT_PATH}/job_node_test)
add_test( job_list_test valgrind --leak-check=full --error-exitcode=1 ${EXECUTABLE_OUTPUT_PATH}/job_list_test)
add_test( ext_joblist_test ${EXECUTABLE_OUTPUT_PATH}/ext_joblist_test ${CMAKE_CURRENT_SOURCE_DIR}/data/jobs/util ${CMAKE_CURRENT_SOURCE_DIR})
add_executable( job_program_output job_program_output.c )
@ -34,6 +43,14 @@ add_executable( job_queue_test job_job_queue_test.c )
target_link_libraries( job_queue_test job_queue test_util )
add_test( job_queue_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_test ${EXECUTABLE_OUTPUT_PATH}/job_program_output )
add_executable( job_queue_stress_task job_queue_stress_task.c )
target_link_libraries( job_queue_stress_task ert_util )
add_executable( job_queue_stress_test job_queue_stress_test.c )
target_link_libraries( job_queue_stress_test job_queue test_util )
add_test( job_queue_stress_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_stress_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_stress_task )
add_executable( job_queue_driver_test job_queue_driver_test.c )
target_link_libraries( job_queue_driver_test job_queue test_util )
add_test( job_queue_driver_test ${EXECUTABLE_OUTPUT_PATH}/job_queue_driver_test )

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2013 Statoil ASA, Norway.
The file 'job_queue_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) 2013 Statoil ASA, Norway.
The file 'job_queue_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>
#include <stdbool.h>
@ -27,8 +27,9 @@
#include <ert/util/test_work_area.h>
#include <ert/job_queue/job_queue.h>
#include <ert/job_queue/job_queue_manager.h>
void submit_jobs_to_queue(job_queue_type * queue, test_work_area_type * work_area, char * executable_to_run, int number_of_jobs, int number_of_slowjobs, char* sleep_short, char* sleep_long, bool multithreaded) {
void submit_jobs_to_queue(job_queue_type * queue, test_work_area_type * work_area, char * executable_to_run, int number_of_jobs, int number_of_slowjobs, char* sleep_short, char* sleep_long) {
int submitted_slowjobs = 0;
for (int i = 0; i < number_of_jobs; i++) {
char * runpath = util_alloc_sprintf("%s/%s_%d", test_work_area_get_cwd(work_area), "job", i);
@ -40,43 +41,29 @@ void submit_jobs_to_queue(job_queue_type * queue, test_work_area_type * work_are
submitted_slowjobs++;
}
if (multithreaded) {
job_queue_add_job_mt(queue, executable_to_run, NULL, NULL, NULL, NULL, 1, runpath, "Testjob", 2, (const char *[2]) {
runpath, sleeptime
});
} else {
job_queue_add_job_st(queue, executable_to_run, NULL, NULL, NULL, NULL, 1, runpath, "Testjob", 2, (const char *[2]) {
runpath, sleeptime
});
}
job_queue_add_job(queue, executable_to_run, NULL, NULL, NULL, NULL, 1, runpath, "Testjob", 2, (const char *[2]) {runpath, sleeptime});
free(runpath);
}
test_assert_int_equal( number_of_jobs , job_queue_get_active_size(queue) );
}
void monitor_job_queue(job_queue_type * queue, int max_job_duration, time_t stop_time, int min_realizations) {
bool cont = true;
if (0 >= min_realizations)
cont = false;
while (cont) {
//Check if minimum number of realizations have run, and if so, kill the rest after a certain time
if ((job_queue_get_num_complete(queue) >= min_realizations)) {
job_queue_set_max_job_duration(queue, max_job_duration);
job_queue_set_job_stop_time(queue, stop_time);
cont = false;
}
if (cont) {
if (min_realizations > 0) {
while (true) {
util_usleep(100);
//Check if minimum number of realizations have run, and if so, kill the rest after a certain time
if ((job_queue_get_num_complete(queue) >= min_realizations)) {
job_queue_set_max_job_duration(queue, max_job_duration);
job_queue_set_job_stop_time(queue, stop_time);
break;
}
}
}
}
void run_jobs_with_time_limit_test(char * executable_to_run, int number_of_jobs, int number_of_slowjobs, char * sleep_short, char * sleep_long, int max_sleep) {
test_work_area_type * work_area = test_work_area_alloc("job_queue");
job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "ERROR");
@ -85,9 +72,9 @@ void run_jobs_with_time_limit_test(char * executable_to_run, int number_of_jobs,
job_queue_set_driver(queue, driver);
job_queue_set_max_job_duration(queue, max_sleep);
submit_jobs_to_queue(queue, work_area, executable_to_run, number_of_jobs, number_of_slowjobs, sleep_short, sleep_long, false);
submit_jobs_to_queue(queue, work_area, executable_to_run, number_of_jobs, number_of_slowjobs, sleep_short, sleep_long);
job_queue_run_jobs(queue, number_of_jobs, true);
job_queue_run_jobs(queue, number_of_jobs, false);
test_assert_int_equal(number_of_jobs - number_of_slowjobs, job_queue_get_num_complete(queue));
test_assert_int_equal(number_of_slowjobs, job_queue_get_num_killed(queue));
@ -104,48 +91,46 @@ void run_jobs_with_time_limit_test(char * executable_to_run, int number_of_jobs,
}
void run_and_monitor_jobs(char * executable_to_run, int max_job_duration, time_t stop_time, int min_realizations, int num_completed, int interval_between_jobs) {
int number_of_jobs = 10;
void run_and_monitor_jobs(char * executable_to_run,
int number_of_jobs ,
int max_job_duration,
time_t stop_time,
int min_realizations,
int min_completed,
int max_completed ,
int interval_between_jobs) {
test_work_area_type * work_area = test_work_area_alloc("job_queue");
job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "ERROR");
job_queue_manager_type * queue_manager = job_queue_manager_alloc( queue );
queue_driver_type * driver = queue_driver_alloc_local();
job_queue_set_driver(queue, driver);
arg_pack_type * arg_pack = arg_pack_alloc();
arg_pack_append_ptr(arg_pack, queue);
arg_pack_append_int(arg_pack, 0);
arg_pack_append_bool(arg_pack, true);
thread_pool_type * pool = thread_pool_alloc(1, true);
thread_pool_add_job(pool, job_queue_run_jobs__, arg_pack);
int job_run_time = 0;
for (int i = 0; i < number_of_jobs; i++) {
char * runpath = util_alloc_sprintf("%s/%s_%d", test_work_area_get_cwd(work_area), "job", i);
util_make_path(runpath);
char * sleeptime = util_alloc_sprintf("%d", job_run_time);
job_queue_add_job_mt(queue, executable_to_run, NULL, NULL, NULL, NULL, 1, runpath, "Testjob", 2, (const char *[2]) {
runpath, sleeptime
});
util_make_path(runpath);
job_queue_add_job(queue, executable_to_run, NULL, NULL, NULL, NULL, 1, runpath, "Testjob", 2, (const char *[2]) {runpath, sleeptime});
job_run_time += interval_between_jobs;
free(sleeptime);
free(runpath);
}
job_queue_submit_complete(queue);
job_queue_manager_start_queue(queue_manager,0,false,false);
monitor_job_queue( queue , max_job_duration , stop_time , min_realizations );
job_queue_manager_wait(queue_manager);
monitor_job_queue(queue, max_job_duration, stop_time, min_realizations);
printf("Completed: %d <= %d <= %d ?\n",min_completed , job_queue_get_num_complete(queue) , max_completed);
test_assert_true(job_queue_get_num_complete(queue) >= min_completed);
test_assert_true(job_queue_get_num_complete(queue) <= max_completed);
thread_pool_join(pool);
thread_pool_free(pool);
test_assert_int_equal(num_completed, job_queue_get_num_complete(queue));
test_assert_int_equal(number_of_jobs - num_completed, job_queue_get_num_killed(queue));
test_assert_int_equal(number_of_jobs - job_queue_get_num_complete( queue ) , job_queue_get_num_killed(queue));
test_assert_bool_equal(false, job_queue_get_open(queue));
job_queue_reset(queue);
test_assert_bool_equal(true, job_queue_get_open(queue));
@ -153,6 +138,7 @@ void run_and_monitor_jobs(char * executable_to_run, int max_job_duration, time_t
job_queue_free(queue);
queue_driver_free(driver);
job_queue_manager_free( queue_manager );
test_work_area_free(work_area);
}
@ -168,12 +154,12 @@ void run_jobs_time_limit_multithreaded(char * executable_to_run, int number_of_j
arg_pack_type * arg_pack = arg_pack_alloc();
arg_pack_append_ptr(arg_pack, queue);
arg_pack_append_int(arg_pack, 0);
arg_pack_append_bool(arg_pack, true);
arg_pack_append_bool(arg_pack, false);
thread_pool_type * pool = thread_pool_alloc(1, true);
thread_pool_add_job(pool, job_queue_run_jobs__, arg_pack);
submit_jobs_to_queue(queue, work_area, executable_to_run, number_of_jobs, number_of_slowjobs, sleep_short, sleep_long, true);
submit_jobs_to_queue(queue, work_area, executable_to_run, number_of_jobs, number_of_slowjobs, sleep_short, sleep_long);
job_queue_submit_complete(queue);
thread_pool_join(pool);
@ -191,8 +177,8 @@ void run_jobs_time_limit_multithreaded(char * executable_to_run, int number_of_j
test_work_area_free(work_area);
}
void JobQueueRunJobs_ReuseQueue_AllOk(char ** argv) {
printf("Running JobQueueRunJobs_ReuseQueue_AllOk\n");
void test1(char ** argv) {
printf("001: Running JobQueueRunJobs_ReuseQueue_AllOk\n");
int number_of_jobs = 20;
int number_of_queue_reuse = 10;
@ -204,9 +190,9 @@ void JobQueueRunJobs_ReuseQueue_AllOk(char ** argv) {
job_queue_set_driver(queue, driver);
for (int j = 0; j < number_of_queue_reuse; j++) {
submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, 0, "0", "0", false);
submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, 0, "0", "0");
job_queue_run_jobs(queue, number_of_jobs, true);
job_queue_run_jobs(queue, number_of_jobs, false);
test_assert_int_equal(number_of_jobs, job_queue_get_num_complete(queue));
test_assert_bool_equal(false, job_queue_get_open(queue));
@ -220,8 +206,8 @@ void JobQueueRunJobs_ReuseQueue_AllOk(char ** argv) {
}
void JobQueueRunJobs_ReuseQueueWithStopTime_AllOk(char ** argv) {
printf("Running JobQueueRunJobs_ReuseQueueWithStopTime_AllOk\n");
void test2(char ** argv) {
printf("002: Running JobQueueRunJobs_ReuseQueueWithStopTime_AllOk\n");
int number_of_jobs = 3;
int number_of_slow_jobs = 2;
@ -234,11 +220,11 @@ void JobQueueRunJobs_ReuseQueueWithStopTime_AllOk(char ** argv) {
job_queue_set_driver(queue, driver);
for (int j = 0; j < number_of_queue_reuse; j++) {
submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_slow_jobs, "1", "5", false);
submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_slow_jobs, "1", "5");
job_queue_run_jobs(queue, number_of_jobs, true);
time_t current_time = time(NULL);
job_queue_set_job_stop_time(queue, current_time);
job_queue_run_jobs(queue, number_of_jobs, false);
time_t current_time = time(NULL);
job_queue_set_job_stop_time(queue, current_time);
test_assert_int_equal(number_of_jobs, job_queue_get_num_complete(queue));
test_assert_bool_equal(false, job_queue_get_open(queue));
@ -253,25 +239,31 @@ void JobQueueRunJobs_ReuseQueueWithStopTime_AllOk(char ** argv) {
}
void JobQueueSetStopTime_StopTimeEarly_MinRealisationsAreRun(char ** argv) {
printf("Running JobQueueSetStopTime_StopTimeEarly_MinRealisationsAreRun\n");
void test3(char ** argv) {
printf("003: Running JobQueueSetStopTime_StopTimeEarly_MinRealisationsAreRun\n");
//Use stop_time to to stop jobs after min_realizations are finished
int number_of_jobs = 10;
int min_realizations = 5;
int num_expected_completed = 5;
int max_duration_time = 0;
int interval_between_jobs = 2;
time_t currenttime;
time(&currenttime);
time_t stoptime = currenttime;
run_and_monitor_jobs(argv[1], max_duration_time, stoptime, min_realizations, num_expected_completed, interval_between_jobs);
time_t stoptime = time( NULL );
run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, stoptime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs);
}
void JobQueueSetStopTime_StopTimeLate_AllRealisationsAreRun(char ** argv) {
printf("Running JobQueueSetStopTime_StopTimeLate_AllRealisationsAreRun\n");
void test4(char ** argv) {
printf("004: Running JobQueueSetMaxDuration_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds\n");
run_jobs_with_time_limit_test(argv[1], 100, 23, "1", "100", 5);
}
void test5(char ** argv) {
printf("005: Running JobQueueSetStopTime_StopTimeLate_AllRealisationsAreRun\n");
//Use stop_time to to stop jobs after min_realizations are finished
int number_of_jobs = 10;
int min_realizations = 5;
int num_expected_completed = 10;
int max_duration_time = 0;
@ -279,12 +271,13 @@ void JobQueueSetStopTime_StopTimeLate_AllRealisationsAreRun(char ** argv) {
time_t currenttime;
time(&currenttime);
time_t stoptime = currenttime + 15;
run_and_monitor_jobs(argv[1], max_duration_time, stoptime, min_realizations, num_expected_completed, interval_between_jobs);
run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, stoptime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs);
}
void JobQueueSetStopTimeAndMaxDuration_MaxDurationShort_StopTimeLate_MinRealisationsAreRun(char ** argv) {
printf("Running JobQueueSetStopTimeAndMaxDuration_MaxDurationShort_StopTimeLong_MinRealisationsAreRun\n");
void test6(char ** argv) {
printf("006: Running JobQueueSetStopTimeAndMaxDuration_MaxDurationShort_StopTimeLong_MinRealisationsAreRun\n");
int number_of_jobs = 10;
int min_realizations = 1;
int num_expected_completed = 1;
int max_duration_time = 1;
@ -292,13 +285,14 @@ void JobQueueSetStopTimeAndMaxDuration_MaxDurationShort_StopTimeLate_MinRealisat
time_t currenttime;
time(&currenttime);
time_t stoptime = currenttime + 10;
run_and_monitor_jobs(argv[1], max_duration_time, stoptime, min_realizations, num_expected_completed, interval_between_jobs);
run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, stoptime, min_realizations, num_expected_completed, number_of_jobs , interval_between_jobs);
}
void JobQueueSetStopTimeAndMaxDuration_MaxDurationLong_StopTimeEarly_MinRealisationsAreRun(char ** argv) {
printf("Running JobQueueSetStopTimeAndMaxDuration_MaxDurationLong_StopTimeEarly_MinRealisationsAreRun\n");
void test7(char ** argv) {
printf("007: Running JobQueueSetStopTimeAndMaxDuration_MaxDurationLong_StopTimeEarly_MinRealisationsAreRun\n");
int number_of_jobs = 10;
int min_realizations = 1;
int num_expected_completed = 1;
int max_duration_time = 10;
@ -306,101 +300,108 @@ void JobQueueSetStopTimeAndMaxDuration_MaxDurationLong_StopTimeEarly_MinRealisat
time_t currenttime;
time(&currenttime);
time_t stoptime = currenttime + 1;
run_and_monitor_jobs(argv[1], max_duration_time, stoptime, min_realizations, num_expected_completed, interval_between_jobs);
run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, stoptime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs);
}
void JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShort_OnlyMinRealizationsAreRun(char ** argv) {
printf("Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShort_OnlyMinRealizationsAreRun\n");
void test8(char ** argv) {
printf("008: Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShort_OnlyMinRealizationsAreRun\n");
// Must have one job completed, the rest are then killed due to the max_duration_time gets exceeded.
int number_of_jobs = 10;
int min_realizations = 1;
int num_expected_completed = 1;
int max_duration_time = 1;
int interval_between_jobs = 2;
time_t currenttime = 0;
run_and_monitor_jobs(argv[1], max_duration_time, currenttime, min_realizations, num_expected_completed, interval_between_jobs);
run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, currenttime, min_realizations, num_expected_completed, 3 , interval_between_jobs);
}
void JobQueueSetMaxDurationAfterMinRealizations_MaxDurationLooong_AllRealizationsAreRun(char ** argv) {
printf("Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationLooong_AllRealizationsAreRun\n");
void test9(char ** argv) {
printf("009: Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationLooong_AllRealizationsAreRun\n");
// Min realizations is 1, but the max running time exceeds the time used by any of the jobs, so all run to completion
int number_of_jobs = 10;
int min_realizations = 1;
int num_expected_completed = 10;
int max_duration_time = 12;
int interval_between_jobs = 1;
time_t currenttime = 0;
run_and_monitor_jobs(argv[1], max_duration_time, currenttime, min_realizations, num_expected_completed, interval_between_jobs);
run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, currenttime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs);
}
void JobQueueSetMaxDurationAfterMinRealizations_MaxDurationSemiLong_MoreThanMinRealizationsAreRun(char ** argv) {
printf("Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationSemiLong_MoreThanMinRealizationsAreRun\n");
// Min is 3, but max_duration_time allows for one more to be completed
void test10(char ** argv) {
printf("010: Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationSemiLong_MoreThanMinRealizationsAreRun\n");
int number_of_jobs = 10;
int min_realizations = 3;
int num_expected_completed = 4;
int max_duration_time = 7;
int interval_between_jobs = 2;
time_t currenttime = 0;
run_and_monitor_jobs(argv[1], max_duration_time, currenttime, min_realizations, num_expected_completed, interval_between_jobs);
run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, currenttime, min_realizations, min_realizations , number_of_jobs , interval_between_jobs);
}
void JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShortButMinRealizationsIsAll_AllRealizationsAreRun(char ** argv) {
printf("Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShortButMinRealizationsIsAll_AllRealizationsAreRun\n");
void test11(char ** argv) {
printf("011: Running JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShortButMinRealizationsIsAll_AllRealizationsAreRun\n");
// Min is 10, so all run to completion
int number_of_jobs = 10;
int min_realizations = 10;
int num_expected_completed = 10;
int max_duration_time = 1;
int interval_between_jobs = 0;
time_t currenttime = 0;
run_and_monitor_jobs(argv[1], max_duration_time, currenttime, min_realizations, num_expected_completed, interval_between_jobs);
run_and_monitor_jobs(argv[1], number_of_jobs , max_duration_time, currenttime, min_realizations, num_expected_completed, num_expected_completed , interval_between_jobs);
}
void JobQueueSetMaxDuration_DurationZero_AllRealisationsAreRun(char ** argv) {
printf("Running JobQueueSetMaxDuration_DurationZero_AllRealisationsAreRun\n");
void test12(char ** argv) {
printf("012: Running JobQueueSetMaxDuration_DurationZero_AllRealisationsAreRun\n");
run_jobs_with_time_limit_test(argv[1], 10, 0, "1", "100", 0); // 0 as limit means no limit*/
}
void JobQueueSetMaxDuration_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds(char ** argv) {
printf("Running JobQueueSetMaxDuration_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds\n");
run_jobs_with_time_limit_test(argv[1], 100, 23, "1", "100", 5);
}
void JobQueueSetMaxDurationRunJobsLoopInThread_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds(char ** argv) {
printf("Running JobQueueSetMaxDurationRunJobsLoopInThread_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds\n");
void test13(char ** argv) {
printf("013: Running JobQueueSetMaxDurationRunJobsLoopInThread_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds\n");
run_jobs_time_limit_multithreaded(argv[1], 100, 23, "1", "100", 5);
}
void JobQueueSetAutoStopTime_ThreeQuickJobs_AutoStopTimeKillsTheRest(char ** argv) {
printf("Running JobQueueSetAutoStopTime_ThreeQuickJobs_AutoStopTimeKillsTheRest\n");
void test14(char ** argv) {
printf("014: Running JobQueueSetAutoStopTime_ThreeQuickJobs_AutoStopTimeKillsTheRest\n");
int number_of_jobs = 10;
test_work_area_type * work_area = test_work_area_alloc("job_queue");
job_queue_type * queue = job_queue_alloc(number_of_jobs, "OK.status", "ERROR");
queue_driver_type * driver = queue_driver_alloc_local();
job_queue_manager_type * queue_manager = job_queue_manager_alloc( queue );
job_queue_set_driver(queue, driver);
arg_pack_type * arg_pack = arg_pack_alloc();
arg_pack_append_ptr(arg_pack, queue);
arg_pack_append_int(arg_pack, 0);
arg_pack_append_bool(arg_pack, true);
thread_pool_type * pool = thread_pool_alloc(1, true);
thread_pool_add_job(pool, job_queue_run_jobs__, arg_pack);
int number_of_slowjobs = 7;
int number_of_fastjobs = number_of_jobs - number_of_slowjobs;
char * sleep_short = "0";
char * sleep_long = "100";
submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_slowjobs, sleep_short, sleep_long, false);
util_usleep(1000000);
submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_slowjobs, sleep_short, sleep_long);
job_queue_submit_complete(queue);
job_queue_manager_start_queue( queue_manager , 10 , false , false);
/*
The jobs are distributed with some very fast, and some quite
long. Here we busy wait until all the fast ones have completed and
then we calculate a stop for the remaining jobs with the
job_queue_set_auto_job_stop_time() function.
*/
while (true) {
int num_complete = job_queue_get_num_complete(queue);
if (num_complete == number_of_fastjobs)
break;
util_usleep( 100000 );
}
job_queue_set_auto_job_stop_time(queue);
thread_pool_join(pool);
job_queue_manager_wait(queue_manager);
test_assert_int_equal(number_of_jobs - number_of_slowjobs, job_queue_get_num_complete(queue));
test_assert_int_equal(number_of_slowjobs, job_queue_get_num_killed(queue));
@ -411,14 +412,14 @@ void JobQueueSetAutoStopTime_ThreeQuickJobs_AutoStopTimeKillsTheRest(char ** arg
test_assert_int_equal(0, job_queue_get_num_complete(queue));
thread_pool_free(pool);
job_queue_manager_free( queue_manager );
job_queue_free(queue);
queue_driver_free(driver);
test_work_area_free(work_area);
}
void JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing(char ** argv) {
printf("Running JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing\n");
void test15(char ** argv) {
printf("015: Running JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing\n");
int number_of_jobs = 10;
@ -429,7 +430,7 @@ void JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing(char ** argv)
char * sleep_long = "100";
submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_jobs, "0", sleep_long, false);
submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, number_of_jobs, "0", sleep_long);
job_queue_set_auto_job_stop_time(queue);
@ -441,8 +442,8 @@ void JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing(char ** argv)
test_work_area_free(work_area);
}
void JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing(char ** argv) {
printf("Running JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing\n");
void test16(char ** argv) {
printf("016: Running JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing\n");
int number_of_jobs = 10;
test_work_area_type * work_area = test_work_area_alloc("job_queue");
@ -451,9 +452,9 @@ void JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing(char ** argv
queue_driver_type * driver = queue_driver_alloc_local();
job_queue_set_driver(queue, driver);
submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, 0, "0", "0", false);
submit_jobs_to_queue(queue, work_area, argv[1], number_of_jobs, 0, "0", "0");
job_queue_run_jobs(queue, number_of_jobs, true);
job_queue_run_jobs(queue, number_of_jobs, false);
test_assert_int_equal(number_of_jobs, job_queue_get_num_complete(queue));
test_assert_bool_equal(false, job_queue_get_open(queue));
@ -465,28 +466,26 @@ void JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing(char ** argv
test_work_area_free(work_area);
}
int main(int argc, char ** argv) {
JobQueueRunJobs_ReuseQueue_AllOk(argv);
JobQueueRunJobs_ReuseQueueWithStopTime_AllOk(argv);
JobQueueSetMaxDuration_DurationZero_AllRealisationsAreRun(argv);
JobQueueSetMaxDuration_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds(argv);
JobQueueSetMaxDurationRunJobsLoopInThread_Duration5Seconds_KillsAllJobsWithDurationMoreThan5Seconds(argv);
util_install_signals();
JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShort_OnlyMinRealizationsAreRun(argv);
JobQueueSetMaxDurationAfterMinRealizations_MaxDurationLooong_AllRealizationsAreRun(argv);
JobQueueSetMaxDurationAfterMinRealizations_MaxDurationSemiLong_MoreThanMinRealizationsAreRun(argv);
JobQueueSetMaxDurationAfterMinRealizations_MaxDurationShortButMinRealizationsIsAll_AllRealizationsAreRun(argv);
JobQueueSetStopTime_StopTimeEarly_MinRealisationsAreRun(argv);
JobQueueSetStopTime_StopTimeLate_AllRealisationsAreRun(argv);
JobQueueSetStopTimeAndMaxDuration_MaxDurationShort_StopTimeLate_MinRealisationsAreRun(argv);
JobQueueSetStopTimeAndMaxDuration_MaxDurationLong_StopTimeEarly_MinRealisationsAreRun(argv);
JobQueueSetAutoStopTime_ThreeQuickJobs_AutoStopTimeKillsTheRest(argv);
JobQueueSetAutoStopTime_NoJobsAreFinished_AutoStopDoesNothing(argv);
JobQueueSetAutoStopTime_AllJobsAreFinished_AutoStopDoesNothing(argv);
test1(argv);
test2(argv);
test3(argv);
test4(argv);
test5(argv);
test6(argv);
test7(argv);
test8(argv);
test9(argv);
test10(argv);
test11(argv);
test12(argv);
test13(argv);
test14(argv);
test15(argv);
test16(argv);
exit(0);
}

View File

@ -0,0 +1,77 @@
/*
Copyright (C) 2015 Statoil ASA, Norway.
The file 'job_node_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>
#include <stdbool.h>
#include <ert/util/test_util.h>
#include <ert/util/arg_pack.h>
#include <ert/job_queue/job_node.h>
#include <ert/job_queue/job_list.h>
void test_create() {
job_list_type * list = job_list_alloc();
test_assert_true( job_list_is_instance( list ));
test_assert_int_equal( 0 , job_list_get_size( list ));
job_list_free( list );
}
void call_add_job( void * arg ) {
arg_pack_type * arg_pack = arg_pack_safe_cast( arg );
job_list_type * job_list = arg_pack_iget_ptr( arg_pack , 0 );
job_queue_node_type * node = arg_pack_iget_ptr( arg_pack , 1 );
job_list_add_job( job_list , node );
}
void call_iget_job( void * arg ) {
job_list_type * job_list = job_list_safe_cast( arg );
job_list_iget_job( job_list , 10);
}
void test_add_job() {
job_list_type * list = job_list_alloc();
job_queue_node_type * node = job_queue_node_alloc_simple("name" , "/tmp" , "/bin/ls" , 0 , NULL);
job_list_add_job( list , node );
test_assert_int_equal( job_list_get_size( list ) , 1 );
test_assert_int_equal( job_queue_node_get_queue_index(node) , 0 );
test_assert_ptr_equal( node , job_list_iget_job(list , 0));
{
arg_pack_type * arg_pack = arg_pack_alloc( );
arg_pack_append_ptr( arg_pack , list );
arg_pack_append_ptr( arg_pack , node );
test_assert_util_abort("job_queue_node_set_queue_index", call_add_job, arg_pack );
arg_pack_free( arg_pack );
}
test_assert_util_abort("job_list_iget_job", call_iget_job, list);
job_list_reset( list );
test_assert_int_equal( 0 , job_list_get_size( list ));
job_list_free( list );
}
int main( int argc , char ** argv) {
util_install_signals();
test_create();
test_add_job();
}

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