Example codes
and tutorials
The (Not-so) Quick Guide
List of tutorials/demo codes
Single-Physics Problems
Poisson
Adaptivity illustrated for Poisson
Advection-Diffusion
Unsteady heat equation
Linear wave equation
The Young-Laplace equation
Navier-Stokes
Free-surface Navier-Stokes
Axisymmetric Navier-Stokes
Solid mechanics
Beam structures
Shell structures
Multi-physics Problems
Fluid-structure interaction
Boussinesq convection
Steady thermoelasticity
Methods-based example codes and tutorials
Mesh generation
Linear solvers and preconditioners
Visualisation of the results
Parallel processing
How to write a new element
How to write a new refineable element
Default nonlinear solvers -- the sequence of action functions
...
Documentation
FE theory and top-down discussion of the data structure
The (Not-so) Quick Guide
Comprehensive bottom-up discussion of the data structure
List of available structured and unstructured meshes
Linear solvers and preconditioners
Visualisation of the results
Parallel processing
Coding conventions and C++ style
Creating documentation
Optimisation - robustness vs. "raw speed"
Linear vs. nonlinear problems
Storing shape functions
Changing the default "full" integration scheme
Disabling the ALE formulation of unsteady equations
C vs. C++ output
Different sparse assembly techniques and the STL memory pool
Publications
Publications
Talks
Journal publications
Theses
Picture show
Download
Copyright
Download/installation instructions
Download page
FAQ & Contact
FAQ
Change log
Bugs and other known problems
Completeness of the library & our "To-Do List"
Contact the developers
Get involved

 


Beta release!

Please note that the library has not been "officially" released. While we continue to work on the documentation, these web pages are likely to contain broken links and documents in draft form. Please send an email to

oomph-lib AT maths DOT man DOT ac DOT uk

if you wish to be informed of the library's "official" release.

Download/installation instructions

The latest version of the library is 0.90.


The download/install process, step by step

  1. Download the distribution
  2. Unpack the distribution
  3. Install the distribution
    1. Option 1: Standard installation
    2. Option 2: Customised installation
  4. Finding your way through the distribution
  5. External (third-party) libraries
    1. External (third-party) libraries that are distributed with oomph-lib
      1. Specifying an existing, local copy of the blas library
      2. Specifying an existing, local copy of the lapack library
    2. External (third-party) libraries that are not distributed with oomph-lib
      1. Hypre
      2. Trilinos
  6. How to write your own code and link it against oomph-lib's library/libraries
    1. Writing/linking your own driver codes under autotools control
      1. Adding your own driver codes
      2. Adding new libraries and linking against them from driver codes
    2. Writing/linking user code without autotools


Download the distribution

Depending on the amount of diskspace available on your machine you can download the full library or various partial distributions from the oomph-lib download page. Note that you can also get hold of the very latest (possibly unstable) developers' version of the library from our subversion-based repository. The procedure for checking out from the repository is explained in another tutorial.


Unpack the distribution

Unpack the distribution:

gunzip oomph-lib-0.90.tar.gz
tar xvf oomph-lib-0.90.tar

The entire distribution will now be contained in the sub-directory oomph-lib-0.90.


Install the distribution

Option 1: Standard installation

Change into the oomph-lib directory and run the autogen.sh build script:

cd oomph-lib-0.90
./autogen.sh

The build script will ask a few questions, e.g. to verify that the default build directory ( oomph-lib-0.90/build ) is appropriate -- if you want to install the library elsewhere, you may specify an alternative directory. The script then proceeds with the standard configure; make; make install; make check; sequence. The build script uses the shell script configure to determine the appropriate compile/link options for your machine and disables certain (optional) parts of the build process if the required tools are not found. For instance, the documentation will only be generated if a sufficiently recent version of doxygen can be found on your system.

The self-test (initiated by make check ) will compile and run (at least) all demo codes and verify their output. This is an optional (and time consuming) step, therefore the user is given the option to terminate the build process at this point.

By default, autogen.sh will build the library and the demo codes with certain default settings (using the gcc compilers with full optimisation, no debugging, no PARANOIA, and fully installed header files rather than symbolic links -- these are appropriate if you wish to install the library once-and-for-all and do not anticipate any changes to their sources; the section Option 2: Customised installation provides more details on the various options). autogen.sh will display the configure options and ask for confirmation that they are appropriate. If you are unsure if they are, simply answer "y" -- the default will be fine...

New feature: Parallel make

oomph-lib's build script, autogen.sh now allows for parallel compilation. This can lead to considerable speedups on multicore processors that are now widely available. To build oomph-lib in parallel, using up four threads run autogen.sh as follows

./autogen.sh --jobs=4 

or (if you are re-building)

./autogen.sh --jobs=4 --rebuild


If you're an experience linux/unix user, you may prefer to control the build/install process manually, using the standard configure; make; make install; make check; sequence. In this case, the library will be compiled with GNU's default compiler options ("-O2 -g") and the libraries and include files will be installed in /usr/local/ unless you specify a different directory with the --prefix argument to the configure command. Here's an example of a manual installation

Option 2: Customised installation

The build script allows you to customise the build/install options. For instance, you may wish to specify another compiler, change the optimisation level, allow for debugging or range checking, etc. In this case, reply "n" when prompted to confirm the configure options. You are then given a list of previously used options which are stored in various files in the sub-directory config/configure_options/. (The default settings are in default; the currently used ones are in current -- when you run autogen.sh for the first time, the two will be identical.) You may either overwrite the defaults on a command line -- your chosen options will then be stored in config/configure_options/current -- or you may select one of the existing option files. It's a good idea to add your own option files to those that already exist.

What options are there? You can get a complete list by typing

./configure --help
in oomph-lib's top level directory. Here are some options that we use frequently:

Suppressing the build of the documentation:

Building the online documentation locally is time consuming and requires a significant amount of disk space. Since the documentation is also available from the oomph-lib homepage you may wish to suppress this step. To achieve this, specify the configure option
--enable-suppress-doc

Replace library headers by symbolic links to the sources

During the build process oomph-lib's various libraries are installed in the subdirectory build/lib (or in whatever other directory you may have specified when asked to confirm their location) and the associated header files are copied to build/include. This is a sensible default for libraries that are only installed once and then never again tinkered with. Here the situation is slightly different: If you ever decide to add your own "user libraries" to oomph-lib (and you are encouraged to do so!), their header files will also be copied to build/include. If during code development, any of your header files contain syntax errors, the compiler will complain about the syntax errors in the copied file in build/include rather than the one in your source directory. This will encourage you to edit the copied file rather than the original -- clearly a recipe for disaster! To avoid it we provide the configure option
 --enable-symbolic-links-for-headers
In this mode, the copies of the header files in build/include are replaced by symbolic links to the actual sources in src or user_src.

PARANOIA

oomph-lib provides an extensive range of optional run-time self-tests. The self-tests issue diagnostic error messages if any inconsistencies are detected at run-time and then terminate the code execution (semi-)gracefully by throwing an exception which (if not caught) aborts. This allows backtracking of the call sequence in a debugger during code development. Obviously, the self-tests introduce a slight run-time overhead and are therefore only performed if the C++ code is compiled with a special compiler flag, PARANOID. For gcc (and most other compilers we know) this is done by passing the flag -DPARANOID to the C++ compiler. This is achieved by adding
CXXFLAGS="-DPARANOID"
to the configure options. As discussed, during code development, this is most useful if debugging is also enabled, so the combination
CXXFLAGS="-g -DPARANOID"
is common.

Range checking

Most of the containers used in oomph-lib allow for optional (and very costly!) range checking which is enabled by specifying the C++ compiler flag RANGE_CHECKING. You are advised to recompile the code (yes, all of it!) if (and only if) you encounter some mysterious segmentation fault. Again, this is most useful if used together with debugging,
CXXFLAGS="-g -DRANGE_CHECKING"
(Without the -g flag you will only find out that an illegal index has been specified, not where this happened...)


Finding your way through the distribution

The oomph-lib distribution has several main sub-directories:

The src directory

The src sub-directory contains the source code for the various sub-libraries that make up oomph-lib. The most important one is the generic library which is built from the sources in the sub-directory src/generic. This library defines the fundamental oomph-lib objects (nodes, elements, meshes, timesteppers, linear and nonlinear solvers, mesh-adaptation routines, etc.)

The other libraries (poisson, navier-stokes,...) define elements for the solution of specific systems of PDEs. Not all of these will be required for all applications and you can reduce the overall build time by excluding certain sub-libraries from the build process. For instance, if you specify the configure option --enable-suppress-poisson, the Poisson equation library (and the associated demo problems; see below) will not be built.

Finally, the src/meshes subdirectory contains several fully functional Meshes (and, where appropriate, the associated Domains) that are used in the demo codes. All Meshes in this directory are templated by the type of element they contain. Since the element type can only be specified in the driver codes, the meshes cannot be compiled into libraries -- the sources are always included as header-like files. Our list of example codes contains an example that explains this in more detail.

The external_src directory

The external_src directory contains "frozen" versions of various external libraries (e.g. SuperLU). Inclusion of these libraries into the distribution facilitates the overall build process: You only have to download and install a single distribution. This is much easier than finding out (typically halfway through the install process), that library A depends on library B which invariably turns out to depend on library C, etc.) Often the sources in the external_src subdirectories are sub-sets of the full libraries. For instance, we only include the double precision sources for SuperLU as neither the complex nor the single-precision versions are required within oomph-lib.

If you have local (possibly optimised) versions of any of these libraries installed on your machine, you can, of course, link against those instead. Simply replace oomph-lib's own version (prefixed by "oomph" -- so oomph-lib's copy of the SuperLU library is called oomph_superlu) from the definition of the EXTERNAL_LIBS variable in the file /config/configure.ac_scripts/start with your own, then run autogen. sh --rebuild. If you don't have autotools installed on your machine, perform the replacement directly in the file configure.ac in the oomph-lib home directory. For the blas and lapack libraries, we provide a more sophisticated procedure for specifying local versions of the libraries; see the discussion in External (third-party) libraries that are distributed with oomph-lib for details.

The external_distributions directory

oomph-lib provides interfaces to various third-party libraries whose sources are too big to be included in the oomph-lib distribution. If you wish to use these we expect you to install them yourself. To facilite this task, we provide the option to let the oomph-lib build machinery perform the installation for you. If you place a copy of the tar file into the appropriate sub-directory in external_distributions, oomph-lib will build and install the library for you; see External (third-party) libraries that are not distributed with oomph-lib for details. (Note that oomph-lib is fully functional without these libraries -- if the libraries are not available the build process ignores any oomph-lib code that depends on them.)

The demo_drivers directory

The demo_drivers directory contains a large number of demo codes. They are arranged in sub-directories, based on the type of the problem that is being solved. For instance, the demo_drivers/poisson subdirectory contains a number of demo problems involving the Poisson equation.

All sub-directories in demo_drivers contain shell scripts that validate the output from the demo codes by comparing the computed results against the reference results stored in the validata sub-directories. The comparison is peformed with the python script bin/fpdiff.py which tolerates slight differences due to the unavaidable variations in roundoff error on different platforms and/or at different optimisation levels. The validation scripts can either be executed individually in each sub-directory or for all sub-directories by issuing the command make check.

If the self-test is run at the top-level, a summary of the self-tests is stored in self_test/analyse_self_tests/validation.log

The doc directory

The structure of the doc directory (approximately) mirrors that of demo_drivers and contains the source code for the doxygen - based detailed explanation of the demo codes. If configure locates a sufficiently up-to-date version of doxygen on your system, the entire oomph-lib documentation will be built locally and can be navigated from the homepage in doc/html/index.html -- a copy of the oomph-lib homepage.

The user_src and user_drivers directories

The configure script and the associated Makefiles that build and install the oomph-lib libraries and demo codes are generated by autoconf and automake. If these powerful tools are installed on your machine, you can incude your own libraries and driver codes into the fully-automated oomph-lib build process. Store your code in suitably named sub-directories in user_src and user_drivers and update config/configure. ac_scripts/user_src. dir_list and config/configure. ac_scripts/user_drivers. dir_list, to ensure that the sub-directories get included into the build process. See How to write your own code and link it against oomph-lib's library/libraries for more details.


External (third-party) libraries

oomph-lib provides interfaces to a number of third-party libraries. Those libraries that are essential for oomph-lib are distributed with the library to ensure that the user does not have to install these separately. We also provide interfaces to a number of third-party libraries that are not distributed with oomph-lib, typically because they are too big and/or take (too?) long to build. oomph-lib will only build the interfaces to these libraries if they are available and their location is specified during the configuration stage (or if the appropriate tar file is dropped into the required directory in which case oomph-lib's build process will build and install the library for you).

External (third-party) libraries that are distributed with oomph-lib

oomph-lib provides local copies of the following third-party libraries: By default oomph-lib automatically builds and links against these.

Specifying an existing, local copy of the blas library

If a local, possibly optimised version of the blas library already exists on your machine you can force oomph-lib to link against it and avoid the compilation of oomph-lib's own copy.

If your local copy of the blas library is located at

/home/mheil/local/lib/blas/blas.a
say, you can link against it by specifying the configure option
--with-blas=/home/mheil/local/lib/blas/blas.a

Specifying an existing, local copy of the lapack library

If a local, possibly optimised version of the lapack library already exists on your machine you can force oomph-lib to link against it and avoid the compilation of oomph-lib's own copy.

For instance, if your local copy of the lapack library is located at

/home/mheil/local/lib/lapack/lapack.a
you can link against it by specifying the configure option
--with-lapack=/home/mheil/local/lib/lapack/lapack.a

External (third-party) libraries that are not distributed with oomph-lib

Hypre

oomph-lib provides wrappers to the powerful solvers and preconditioners from the Scalable Linear Solvers Project. The wrappers are only built if Hypre is avaibable on your machine. If your local copy of the Hypre library installed in
/home/mheil/local/hypre
i.e. if this directory contains Hypre's lib and include directories:
biowulf:~ 10:44:22$ ll /home/mheil/local/hypre
total 8
drwxr-xr-x    2 mheil    users        4096 Nov  3  2007 include
drwxr-xr-x    2 mheil    users        4096 Nov  3  2007 lib
you can get oomph-lib to link against it (and to compile oomph-lib's wrappers to Hypre's solvers and preconditioners) by specifying the configure option
--with-hypre=/home/mheil/local/hypre

Note: oomph-lib works with version 2.0.0 of the library. If this version of Hypre is not available on your machine download the tar file

http://www.maths.man.ac.uk/~mheil/oomph-lib_actual_tar_files/hypre-2.0.0.tar.gz

You can either build the library yourself or get oomph-lib to build it for you. To do this simply place a copy of the tar file into the directory

external_distributions/hypre
and (re-)run autogen.sh. The installation procedure will detect the tar file, unpack it, and install the library in
external_distributions/hypre/hypre_default_installation
Unless you explicitly specified a library location using the --with-hypre flag, oomph-lib will then link against this newly created version of the library. However, we strongly recommend moving the newly created library to another place (outside the oomph-lib distribution) to preserve it for future use. Once this is done you simply specify the (new) location of the library with the --with-hypre flag, as discussed above. (Also make sure to delete the tar file from external_distributions/hypre, otherwise the library will be re-built again.) Note that make clean will delete the unpacked Hypre sources but not the tar file and the library itself.

Trilinos

oomph-lib provides wrappers to the powerful solvers and preconditioners from the Trilinos Project. The wrappers are only built if Trilinos is avaibable on your machine. If your local copy of the Trilinos library installed in
/home/mheil/local/trilinos
i.e. if this directory contains Trilinos's lib and include directories:
biowulf:~ 10:44:31$ ll /home/mheil/local/trilinos
total 24
drwxr-xr-x    2 mheil    users        4096 Dec 20 15:34 bin
drwxr-xr-x    2 mheil    users       16384 Dec 20 15:35 include
drwxr-xr-x    2 mheil    users        4096 Dec 20 15:35 lib
you can get oomph-lib to link against it (and to compile oomph-lib's wrappers to Trilnos's solvers and preconditioners) by specifying the configure option
--with-trilinos=/home/mheil/local/trilinos

Note: oomph-lib works with version 9.0.2 of the library. If this version of Trilinos is not available on your machine download the tar file

http://www.maths.man.ac.uk/~mheil/oomph-lib_actual_tar_files/trilinos-9.0.2.tar.gz

You can either build the library yourself or get oomph-lib to build it for you. To do this simply place a copy of the tar file into the directory

external_distributions/trilinos
and (re-)run autogen.sh. The installation procedure will detect the tar file, unpack it, and install the library in
external_distributions/trilinos/trilinos_default_installation
Unless you explicitly specified a library location using the --with-trilinos flag, oomph-lib will then link against this newly created version of the library. However, we strongly recommend moving the newly created library to another place (outside the oomph-lib distribution) to preserve it for future use. Once this is done you simply specify the (new) location of the library with the --with-trilinos flag, as discussed above. (Also make sure to delete the tar file from external_distributions/trilinos, otherwise the library will be re-built again.) Note that make clean will delete the unpacked Trilinos sources but not the tar file and the library itself.

WARNING:

The compilation of Trilinos takes very long!

We strongly recommend installing oomph-lib without it in the first instance.


How to write your own code and link it against oomph-lib's library/libraries

If you followed the instructions so far, you will be able to install oomph-lib and run the demo codes that are provided in the demo_drivers directory. Great! Now on to the next step: How do you write your own codes and link them against oomph-lib? There are two options, depending on whether you have (or are willing to install) the gnu autotools autoconf, automake and libtool on your machine.

Writing/linking your own driver codes under autotools control

Adding your own driver codes

Let's start with the straightforward case: You want to use oomph-lib to solve one of your own problems. To do this within oomph-lib's autotools framework, you will have to create a new directory in user_drivers, register this directory to ensure that it gets included in the overall build process, and, of course, write your driver code. To facilitate these steps, the user_drivers directory already contains a sample directory joe_cool for which all these steps have been performed. If you don't object to the directory name (or if your name is Joe Cool) you can simply work in that directory. If not, we suggest the following sequence of steps:
  1. Go to the user_drivers directory and create a new directory, e.g.
    cd user_drivers
    mkdir josephine_cool
    


  2. Add the entry user_drivers/josephine_cool to the file config/configure. ac_scripts/user_drivers.dir_list

  3. Copy the Makefile.am and the driver code joes_poisson_code.cc from user_drivers/joe_cool to user_drivers/josephine_cool.

  4. Return to oomph-lib's top-level directory and re-run autogen.sh with the --rebuild flag:
    ./autogen.sh --rebuild
    

    Note: There is no need to wipe any libraries that you might already have installed previously. In fact, you can terminate the (re-)build process as soon as
    [...]
    
    config.status: executing depfiles commands
    
    
    done running ./configure
    
    
    Running make
    
    [...]
    
    appears on the screen. This would be followed by the (in your case) needless re-generation of the existing libraries from the already compiled sources.

  5. You may now return to your own directory in user_drivers and make your own driver code:
    cd user_drivers/josephine_cool
    make
    
    This will create the required executable.

  6. Unfortunately, the driver code (copied from Joe Cool's directory!) is unlikely to be the one you want but you can now rename it, edit it, or add further driver codes to your directory. In general we suggest that you have a look at the list of example codes and try to identify a problem that is similar to the one you want to solve. The associated driver code will be a good starting point for your own. Note that whenever you add new driver codes or rename existing ones you will have to update the local Makefile.am, though it is not necessary to re-run autogen.sh. The sample Makefile.am copied from Joe Cool's directory is well annotated and gives clear instructions how to adapt its contents:

    # Name of executables: The prefix "noinst" means the executables don't
    # have to be installed anywhere.
    noinst_PROGRAMS= joes_poisson_code
    
    #---------------------------------------------------------------------------
    
    # Local sources that Joe's Poisson code depends on:
    joes_poisson_code_SOURCES = joes_poisson_code.cc
    
    # Required libraries: Only the "generic" and "poisson" libraries, 
    # which are accessible via the general library directory which 
    # we specify with -L. The generic sources also require the "external" libraries
    # that are shipped with oomph-lib. The Fortran libraries, $(FLIBS), get 
    # included just in case we decide to use a solver that involves Fortran 
    # sources. 
    # NOTE: The order in which libraries are specified is important! 
    #       The most specific ones (that might involve references to other
    #       libraries) need to be listed first, the more basic ones 
    #       later. In this example we have (from right to left, i.e. from
    #       general to specific):
    #       -- The fortran libraries: They  are compiler specific and
    #          obviously can't depend on any code that we (or others)
    #          have written. $(FLIBS) is a variable that automake will translate
    #          to the actual fortran libraries.
    #       -- The external (third party) libraries: They cannot depend on 
    #          any of our code. The variable $(EXTERNAL_LIBS) is defined
    #          in the machine-generated file configure.ac in oomph-lib's 
    #          home directory. 
    #       -- Oomph-lib's generic library contains oomph-lib's fundamental 
    #          objects which do not depend on any specific system of PDEs 
    #          or element types.
    #       -- Finally, oomph-lib's poisson library contains oomph-lib's 
    #          Poisson elements which refer to objects from the generic
    #          library. 
    joes_poisson_code_LDADD = -L@libdir@ -lpoisson -lgeneric $(EXTERNAL_LIBS) $(FLIBS)
    
    #---------------------------------------------------------------------------
    
    
    # Include path for library headers: All library headers live in 
    # the include directory which we specify with -I
    # Automake will replace the variable @includedir@ with the actual
    # include directory.
    INCLUDES = -I@includedir@  
    


    Note the following points:

Adding new libraries and linking against them from driver codes

The above instructions should be sufficient to get you started. You can create multiple sub-directories for different projects (just remember to register the directories, otherwise they will not get included in the build process) and each sub-directory may, of course, contain multiple files, separated into header and source files. automake will ensure that only those files that have been changed will be recompiled when you issue the make command. However, at some point you may wish to package some of your sources into your own library and maybe even offer it for permanent inclusion into oomph-lib. For this purpose the oomph-lib distribution provides the sub-directory user_src which closely mirrors that of the src and external_src directories discussed earlier. During the build process, each sub-directory in user_src is compiled into its own library and installed in the standard location.

The steps required to include your own library into the oomph-lib build process are very similar to those required to add additional user drivers. As before, the user_src directory already contains a sample directory jack_cool, to faciliate the procedure. We therefore suggest the following sequence of steps:

  1. Go to the user_src directory and create a new directory, e.g.
    cd user_src
    mkdir jacqueline_cool
    


  2. Add the entry user_src/jacqueline_cool to the file config/configure. ac_scripts/user_src.dir_list

  3. Copy the Makefile.am and the codes hello_world.cc and hello_world.h from user_src/jack_cool to user_src/jacqueline_cool.

  4. Return to the top-level oomph-lib directory and re-run autogen.sh with the --rebuild flag:
    ./autogen.sh --rebuild
    

    Note: There is no need to wipe any libraries that you might already have installed previously. In fact, you can terminate the (re-)build process as soon as
    [...]
    
    config.status: executing depfiles commands
    
    
    done running ./configure
    
    
    Running make
    
    [...]
    
    appears on the screen. This would be followed by the (in your case) needless re-generation of the existing libraries from the already compiled sources.

  5. You may now return to your own directory in user_src and make and install our own library
    cd user_src/jacqueline_cool
    make
    make install
    
    This will create the library and install it in build/lib

    The Makefile.am for libraries is slightly more complicated (though reasonably well documented) so -- for now -- we'll just list it here and hope that the changes required to include additional sources are obvious. If you really can't figure it out, send us an email and prompt us to complete this bit of the documentation....

    # A few file definitions
    #-----------------------
    
    # Define the sources
    sources =  \
    hello_world.cc
    
    # Define the headers
    headers =  \
    hello_world.h
    
    # Define name of library
    libname = jack_cool
    
    # Combine headers and sources
    headers_and_sources = $(headers) $(sources)
    
    # Define the library that gets placed in lib directory
    #-----------------------------------------------------
    lib_LTLIBRARIES = libjack_cool.la
    
    # Sources that the library depends on: 
    #-------------------------------------
    libjack_cool_la_SOURCES = $(headers_and_sources)
    
    # The library's include headers:
    #-------------------------------
    # Headers that are to be included in the $(includedir) directory:
    # This is the combined header which contains "#include<...>" commands
    # for the real headers in the subdirectory below $(includedir)
    include_HEADERS = $(libname).h 
    
    #Here's the subdirectory where the actual header files are placed
    library_includedir=$(includedir)/jack_cool
    
    #These are the header files that are to be placed in subdirectory
    library_include_HEADERS=$(headers) 
    
    
    # Required libraries -- [assuming that we want to link against stuff in generic
    #-------------------     add other oomph-lib libraries if you need them....]
    # Include path for library headers -- need to refer to include files
    # in their respective source directories as they will not have been 
    # installed yet! 
    INCLUDES = -I$(top_builddir)/src/generic
    
    
    # Combined header file
    #---------------------
    # Rule for building combined header (dummy target never gets made so
    # the combined header is remade every time)
    $(libname).h: dummy_$(libname).h
    
    dummy_$(libname).h:  $(headers)
            echo  $(libname) $(headers) > all_$(libname).aux
            $(AWK) -f $(top_builddir)/bin/headers.awk < \
                   all_$(libname).aux > $(libname).h
            rm all_$(libname).aux
    
    
    # Extra hook for install: Optionally replace headers by symbolic links
    #---------------------------------------------------------------------
    if SYMBOLIC_LINKS_FOR_HEADERS
    install-data-hook: 
            (cd $(library_includedir) && rm -f $(headers) )
            (echo "$(headers)" > include_files.list )
            ($(top_builddir)/bin/change_headers_to_links.sh `pwd`)
            ($(LN_S) `cat include_files.list.aux` $(library_includedir) )
            (rm -r include_files.list.aux include_files.list ) 
    else
    install-data-hook: 
    endif
    
    
    # Tidy up
    #--------
    clean-local:
            rm -f $(libname).h
    
    
    

Note that the directory user_drivers/jack_cool contains an example of a user driver code (jacks_own_code .cc) that uses a user library.

Writing/linking user code without autotools

Linking directly against oomph-lib's (sub-)libraries is slightly complicated by cross-compilation issues arising from the fact that the oomph-lib distribution includes a few C and Fortran sources. When linking is done (by the C++ compiler) one usually has to explicity specify a few compiler-specific Fortran libraries. The beauty of the autools approach described above is that these libraries (and any other flags that need to be passed to the compiler/linker) are determined and specified automatically. Doing this manually is no fun! Have a look at Mike Gerdts's excellent document "How gcc really works" for details.

The good news is that oomph-lib's installation procedure automatically generates a sample Makefile that contains all the relevant information. Once the installation is complete, the sample makefile is located at

demo_drivers/linking/makefile.sample
Here is the version that was generated one of our machines:

###############################################################
# Automatically-generated sample makefile to illustrate how to  
# link against oomph-lib from outside the automake/autoconf
# framework. Do not edit this -- make a copy first
# 
# When customising this makefile, you should only have to change
# 
# - the variable OOMPH-LIB_LIBS:
#         Add any additional oomph-lib sub-libraries that 
#         you may wish to use in your code. 
# 
# - the specific dependencies for your driver code: 
#         Include any additional local dependencies such as 
#         your own header files etc.
# 
###############################################################
 
 
# Installation-specific information -- don't change any of this! 
#-------------------------------------------------------------- 
 
# Flags for C pre-processor 
AM_CPPFLAGS=-DHAVE_CONFIG_H -I. -I../..  -DOOMPH_HAS_MPI -I/home/mheil/version_for_release/build/include
 
# Library include directory: This is where all the header files live
OOMPH-LIB_INCLUDE_DIR=/home/mheil/version_for_release/build/include
 
# Library directory: This is where all of oomph-lib's sub-libraries live
OOMPH-LIB_LIB_DIR=/home/mheil/version_for_release/build/lib
 
# These are the external (3rd party) libraries that are distributed
# with oomph-lib and that we always link against
OOMPH-LIB_EXTERNAL_LIBS=-loomph_hsl -loomph_superlu_3.0 -loomph_metis_4.0 -loomph_arpack -loomph_superlu_dist_2.0 /home/mheil/local/lib/lapack/lapack.a /home/mheil/local/lib/blas/blas.a
 
# This specifies where libraries built from third party 
# distributions can be found
EXTERNAL_DIST_LIBRARIES=
 
# This is additional machine-specific linking information that 
# allows mixed-language compilation/linking
FLIBS=-L/usr/lib/lam/lib -L/usr/lib/gcc/i486-linux-gnu/4.3.3 -L/usr/lib/gcc/i486-linux-gnu/4.3.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/i486-linux-gnu/4.3.3/../../.. -llammpio -llamf77mpi -lmpi -llam -lutil -ldl -lgfortranbegin -lgfortran -lm -lpthread
 
# Flags required for the use of shared libraries 
SHARED_LIBRARY_FLAGS=-Wl,--rpath -Wl,/home/mheil/version_for_release/build/lib
 
#Mac OSX: Replace the above line with the following
#SHARED_LIBRARY_FLAGS= --rpath=/home/mheil/version_for_release/build/lib
# Problem-specific information -- edit this for your driver code 
 
#---------------------------------------------------------------
# These are the specific oomph-lib sub-libraries that we have to link against
# for this driver code -- edit this according to your requirements
# but remember that the order of the libraries matters: List the
# the more specific ones before the more general ones!
OOMPH-LIB_LIBS=-lpoisson -lgeneric
 
# Dependencies for this driver code and compile instructions: 
# Which local source (usually *.cc or *.h) files does the
# driver code depend on?
my_demo_code.o: demo_code.cc
         mpic++ $(AM_CPPFLAGS) -c demo_code.cc -o my_demo_code.o \
               -I$(OOMPH-LIB_INCLUDE_DIR)  
 
# Linking instructions: Just declare the target (i.e. the name of the executable)
# and the dependencies (i.e. the object files created above). The rest 
# should not have to be changed. 
my_demo_code: my_demo_code.o
         mpic++ $(SHARED_LIBRARY_FLAGS) $< -o $@ \
               -L$(OOMPH-LIB_LIB_DIR) $(EXTERNAL_DIST_LIBRARIES) $(OOMPH-LIB_LIBS) \
                $(OOMPH-LIB_EXTERNAL_LIBS) $(FLIBS)

The version that is generated during the build process on your machine provides template for your own customised makefiles. When modifying the sample to different driver codes, you should not (have to) edit any of the "installation specific" variables. Simply specify the oomph-lib (sub-)libraries that you wish to link against in the OOMPH_LIB-LIBS variable (in the example shown above, we are linking against the generic and poisson libraries), and specify the dependencies for your own driver code, following the usual Makefile syntax. The executable may then be created by the usual

make -f makefile.sample my_demo_code

Note/Disclaimer: The sample Makefile generated during oomph-lib's installation should work for most (if not all) linux machines, though it may require slight tweaks for Darwin (the BSD-derived UNIX core of Apple's OSX operating system). Problems are most likely to arise from the SHARED_LIBRARY_FLAGS variable. As mentioned in the comment in the sample Makefile, on such machines the fragment -Wl,--rpath -Wl, should be deleted from the SHARED_LIBRARY_FLAGS variable.



PDF file

A pdf version of this document is available.
Generated on Mon Aug 10 11:23:12 2009 by  doxygen 1.4.7