Overview
--------
The ERT application has evolved into a quite complex beast. Originally
the actual EnKF algorithm was located very deep down in the code, and
changes to the EnKF algorithm required detailed knowledge about the
enkf_node objects, the datatype for measurements and observations,
serialisation and so on. Quite complex and fragile stuff.

To facilitate easier development and testing of new update schemes the
core EnKF update step has been factored out as analysis modules, which
are called from the enkf_main scope. The update functions in the
module get ordinary matrices as input, and do not need to know
anything about the internals of the ERT application.

The modules can either be built in, or you can compile your own module
as a shared library and load it runtime. Apart from the initial
loading internal modules and external modules are treated 100%
identically.


How modules work
----------------
The modules are instances of the object type analysis_module_type, and
the enkf_main layer interacts with the module through the
analyis_module instance. The most important part of the
analysis_module type is a list of function pointers to functions which
"actually do the work". In addition to some functions for setting
internal module variables the most core functions are:

   init_update()
   initX()
   updateA()
   complete_update()

Of these functions a module should have ONLY ONE of initX() and
updateA(); the initX() function will initialize an X matrix which is
then subsequently used to update the ensemble matrix A. Alternatively
the updateA() function should will directly manipulate the A matrix.

The init_update() and complete_update() functions are optional, they
can be used to avoid repeated initialization calculations. These
functions interact quite closely with the scheme used for local
analysis; so you should understand that in detail before deciding
whether it is worthwile to implement init_update() and
complete_update() functions.


Loading modules
---------------

The loading of modules is based on the dlopen() function to open a
shared a library and map it into the adress space of the current
process, and then the dlsym() function to locate a symbol table which
is a list of function pointers. The only difference between internal
and external modules is in the arguments passed to the dlopen() and
dlsym() function calls:

   Loading internal modules
   ------------------------
   Internal modules means modules which have been compiled into the
   libanalyis library, i.e. they are already part of the ERT
   executable, however before we have "loaded" these modules we have
   no way to access them. The current executable is loaded by
   passing NULL as argument to dlopen().

   When dlopen() has succeded we must use dlsym() to get a handle to
   the symbol table. The symbol table is essentially a global
   variable in the ERT adress space, and must have a unique name for
   each module.


   Loading external modules
   ------------------------
   External modules are ordinary shared libraries. To load an external
   module the name of the shared library must be given to the dlopen()
   function, normal rules for runtime loading of dynamic libraries
   apply - i.e. the shared library must be in a location where the
   dynamic linker can find it. The name of module should be a
   filename, including the .so extension.  undo

   When dlopen() has succeded we must use dlsym() to get a handle to
   the symbol table; when the module loading is hidden behind a
   dlopen() call we have essentially created a module namespace, and
   the symbol tables from the different modules can have the same
   name. For convenience we assume that the symbol table is given by
   the name defined by the symbol EXTERNAL_MODULE_TABLE in
   analysis_module.h.

In practice all of is handled by the functions:

  analysis_module_type * analysis_module_alloc_internal( );
  analysis_module_type * analysis_module_alloc_external( );

symbol_table
------------

Interacting with modules
------------------------
The modules can implement four different functions to set a scalar
value. The four functions have signature:

   bool set_int (void * module_data, const char * var_name , int value)
   bool set_double( void * module_data , const char * var_name , double value)
   bool set_bool( void * module_data , const char * var_name , bool value )
   bool set_string( void * module_data , const char * var_name , const char * value )

Common for all these functions is:

  1. It is not necessary to implement these functions; if you know
     that the module has no internal integer variables which should be
     user-modifiable you can just set the set_int function pointer to
     NULL.

  2. If the module recognizes the variable name and actually sets an
     internal variable it should return true, otherwise return false.

  3. The set_xxx() functions are called from the wrapper function
     analysis_module_set_var(); when calling the wrapper function the
     value variable is a string which we try to convert to int, double
     and bool respectively and then cascade through the functions in
     the order listed above. This involves two things:

       a) A module has an internal variable namespace which is shared
          among all variable types.

       b) If the string value argument is incorrectly formatted,
          i.e. an integer is passed as "12x" the correct low level
          function will not be called.

The method to get information out from the module is much more
limited. Each module should contain an internal variable:

    long option_flags;

And when instantiating the module data you should initialize the
option_flags variable by adding together the relevant option flags
from analysis_module.h. The enkf_main_UPDATE() method which invokes
the module functions will inspect the option_flags to see which
variables to pass to the module, and which module functions to invoke,
so this must be correct.

Example
-------
The module/file std_enkf.c is commented quite heavily to serve as an
example.

---------------------------------------------------------------------

With the analysis modules we have essentially got a three layer
design:

 1. The ert core layer which creates/loads a list of analysis_module
    instances.

 2. analysis_module instances are a thing layer which:

    a) Hold on to specific analysis implementations like e.g. the
       std_enkf implementation on one side.

    b) Present a uniform module interface to the ert layer on the
       'other side'.

 3. Specific analysis module implementations like the std_enkf.


In fine ASCII art:
                                                                                                           .
                                                                              +----------------------+     .     +---------------------------+
                                                                              |    Analysis module   |     .     |  Implementation std_enkf  |
                                                                              +----------------------+     .     +---------------------------+
                                                                              |                      |  /------> |   std_enkf_alloc()        |
                                                      ----------------------> |                      | /   .     |   std_enkf_free()         |
                                                     /                        |         X            |o--------> |   std_enkf_get_options()  |
                                                    /                         |                      | \   .     |   std_enkf_initX()        |
    +------------------------------------------+   /                          |                      |  \------> |   std_enkf_set_int()      |
    | The ert core layer; in particular        |  /                           |                      |     .     |   std_enkf_set_double()   |
    | the following functions:                 | /                            +----------------------+     .     +---------------------------+
    | - analysis_config_load_external_module() |o                                                          .
    | - analysis_config_load_internal_module() | \                            +----------------------+     .     +---------------------------+
    | - enkf_main_module_update()              |  \                           |    Analysis module   |     .     |  Implementation sqrt_enkf |
    +------------------------------------------+   \                          +----------------------+     .     +---------------------------+
                                                    \                         |                      |  /------> |  sqrt_enkf_alloc()        |
                                                     \                        |                      | /   .     |  sqrt_enkf_free()         |
                                                      \---------------------> |                      |o--------> |  sqrt_enkf_get_options()  |
                                                       \                      |          X           | \   .     |  sqrt_enkf_initX()        |
                                                        \                     |                      |  \------> |  sqrt_enkf_set_int()      |
                                                         \                    |                      |     .     |  sqrt_enkf_set_double()   |
                                                          \                   +----------------------+     .     +---------------------------+
                                                           \                                               .
                             In the ert core layer the      \                 +----------------------+     .     +---------------------------+
                             different analysis module       \                |    Analysis module   |     .     |  Implementation cv_enkf   |
                             instances are collected in       \               +----------------------+     .     +---------------------------+
                             a hash table, and all function    \              |                      |  /------> |    cv_enkf_alloc()        |
                             invocations go through the         \             |                      | /   .     |    cv_enkf_free()         |
                             functions in the analysis_module    -----------> |                      |o--------> |    cv_enkf_get_options()  |
                             layer.                                           |          X           | \   .     |    cv_enkf_initX()        |
                                                                              |                      |  \------> |    cv_enkf_set_int()      |
                                                                              |                      |     .     |    cv_enkf_set_double()   |
                                                                              +----------------------+     .     +---------------------------+
                                                                                                           .
                                                                                                           .
                                                                                                           .
                                                                                                           .
                                                                                                           .
                                                                                                   The links between the analysis
                                                                                                   modules and the std_enkf, sqrt_enkf
                                                                                                   and cv_enkf implementations are
                                                                                                   in terms of function pointers. These
                                                                                                   links are established runtime, and
                                                                                                   the vertical dotted line represents
                                                                                                   an opaque wall which ert core layer
                                                                                                   can not see through. 
