Using the user-source keyword

Some of the programs of this package require user-provided source-code or library functions. This can, for instance, be a potential energy routine, a switching-function, etc. The keyword user-source in the RUN-SECTION of these programs allows importing user-provided source-code at run-time without altering the original source code. The keyword user-source is always used together with at least one other keyword (e.g., potential-routine or switch-function) which provides the name of an entity specified in the user-provided source-code. Typically this entity is a subroutine or some other callable object.

With user-source the path to (or the name of) a module containing user-provided routines is specified. The module must be importable into Python, i.e., it must either be a Python script (file extension .py), a compiled Python script (file extension .pyc) or a shared library (file extension .so). If the module is already in the systems $PYTHONPATH, the name of the module is sufficient.

The module must provide all user-defined routines required within the calling program. In many cases, those routines are written in Fortran or some other languages, probably not even by the user himself, but are provided by a third party. If the routine is written in Fortran we suggest using the f2py Fortran to Python interface generator available at the SciPy homepage. See below. Another possibility could be writing a wrapper routine which can be imported into Python. A further possibility is also to start a background process (e.g. using the Python built-in subprocess module) and communicating with it through named pipes.

The routines receive a double precision array with coordinates of all DOF in the same order as they are in the primitive basis section or the DVR file. They must return the potential value as double precision number. In fortran one therefore needs to use the function statement and not a subroutine.

Simple example of a user-provided source file (Python):

#!/usr/bin/env python
#
# my_pes.py

import numpy

def potential(Q):
    """
    My PES routine: harmonic oscillator.
    Q is a numpy array containing a coordinate vector.
    """

    return numpy.dot(Q,Q)/2

Using the f2py command

When using a potential routine from a third party which is written in fortran one may first need to write a small wrapper to adjust the interface to what the python program expects. Usually the PES routines come as subroutines with various parameters, one of which being the return value (the potential value). One must then write a wrapper like this into the routines source file:

double precision function mypeswrapper(Q)
   implicit none
   integer, parameter           :: ndof=6  ! problematic comment, see below
   double precision, intent(in) :: Q(ndof)
   double precision             :: v

   ! call to the original routine:
   call OriginalPesSubroutine(Q(1), Q(2),...,Q(ndof),v)
   mypeswrapper = v
end function

Compiling

Assume the original PES routine and the wrapper are stored in the file mypes.f90. Then use:
 f2py -c mypes.f90 -m mypes
This will produce the file mypes.so. In the RUN-SECTION one would then use with the example above:
RUN-SECTION
 user-source = mypes               # this is the name of the .so file
 potential-routine = mypeswrapper  # this is the name of the wrapper function
 ...
end-run-section

Hint: f2py sometimes fails with cryptic error messages. To resolve this start with removing all comments from the routines source code that are placed at the end of lines containing fortran statements like the ! problematic comment above. Often f2py gets mixed up between these comments and the preceding fortran statements. Lines only containing comments are usually not problematic.