• Keine Ergebnisse gefunden

5. Ordinary Differential Equations on GraphsGraphs

5.7. Wrapping Access to Numerical Libraries

Apache Commons Math into GroIMP, but also a wrapper to SUNDIALS is provided.

By default a Dormand-Prince 5(4) method with variable step size is used.

5.7. Wrapping Access to Numerical Libraries

Access to numerical integration algorithms is provided by a packagede.grogra.numeric in the pluginNumeric. The bottom part of the UML-Diagram in figure 5.7 presents the types exposed by the plugin. The upper part in the diagram builds on top of this in the RGG plugin and is described later on in section 5.8.2.

An interface Solver has been introduced to facilitate support for different numer-ical libraries, where the implementation FirstOrderIntegratorAdapter provides ac-cess to those solvers provided by Apache Commons Math, and the implementation CVodeAdapter respectively to CVODE.

A compromise is made between the user-interfaces of the libraries presented above. As a result, theSolverinterface allows to set monitor functions and tolerances. Additional options may be passed in aMapas well, but interpretation and availability of such options is up to the implementation of the actual integration method that is being used.

Monitor functions are provided, like for CVODE, all at once. This simplifies things if a special setup has to be performed before actually evaluating the g-functions, like having to copy the state into the graph (see section 5.8.2 below).

Actual integration is performed by calling the function integrate, to which initial conditions t0 and y0 are passed along with an implementation of the ODE interface for the rate functionf.

5.7.1. Wrapping Access to Apache Commons Math

In Apache Commons Math the interface FirstOrderDifferentialEquations is used to describe the rate function of the ODE, while the initial state is passed directly to the solver when its integrate method is called. Besides a function computeDerivatives to evalute the rate function, another function getDimension is used by the solver to query the size of the state vector, so that memory for internal data structures may be allocated.

Since in Java it is possible to obtain this information by retrieving the length of the array for the state vector, in the design of the wrapper interfaces it was decided to omit such a function like getDimension.

Another complication when wrapping Apache Commons Math is that monitor func-tions are assumed to be registered individually, rather than all at once. Since during integration it is not determined in which order monitor functions will be called, a caching strategy has been implemented that will ensure that the monitor will only be evaluted if time or state does not match to the cached values.

ODE

Figure 5.7.: Classes used in the ODE framework.

5.7. Wrapping Access to Numerical Libraries

5.7.2. Wrapping Access to CVODE

CVODE is a C library, and as such access to it requires to think about how to transfer execution from Java to native code. One way to achieve this is to use the Java Native Interface (JNI). Here, the developer has to implement a wrapper class (in our case one that implements the Solver interface) marking all functions as native for which execution is to be forwarded to a native context.

Then, a tool javah (part of the JDK) is used to generate a C header file for the wrapper class. Functions that have been marked as native will appear as global C functions in the generated header file, using special name mangling to uniquely identify them. The task of the developer then is to implement those functions using ordinary C code, to finally produce a shared library. This will be loaded and linked by the wrapper class at runtime.

While this sounds simple at a first glance, implementation of the wrapper can become quite challenging, especially if the native code calls back to Java (which is the case for monitor and rate functions).

Java Native Access (JNA)5 provides an alternative, where the wrapper can be imple-mented completely using just Java code. This simplifies development and also makes debugging much easier for the developer.

The classes in the packagede.grogra.numeric.cvode provide access to CVODE to the degree needed to implement the Solverinterface. There, the class CVODE contains wrappers for the functions in the library, and some constants that have been defined.

It is also responsible for loading the shared library. The class N Vector represents the analogously named structure for representation of an n-dimensional vector. It has been retrofitted with additional methods to more easily access the data stored in the vector.

The classes CVRhsFn and CVRootFn represent callbacks for rate and monitor functions as they are used by CVODE.CVodeAdapter in the packagede.grogra.numeric imple-ments theSolverinterface and resorts to those wrapper classes.

The native library itself must be created independently from the wrapper code. For CVODE, this can be done by downloading and then extracting the SUNDIALS source code to some directory. In a console the developer has to change to this directory and execute the common commands

./configure CFLAGS="-fPIC"

make

Theconfigurescript creates a suitableMakefilethat is used to compile SUNDIALS.

Setting the variable CFLAGSinstructsconfigure to generate position-independent code and is needed when a shared library ought to be created. Calling make will initiate the compilation process and produce object files. These must be linked to obtain a shared library file.

The command used to create the shared library with GCC for Linux is

gcc -shared -Wl,-soname=libcvode.so -o libcvode.so -static-libgcc *.o

5https://github.com/twall/jna, accessed 11 Januar 2012

The option -shared instructs GCC to produce a shared library. The -soname linker option will cause the name of the library to be stored in the file itself.

Naming of shared library files is platform dependent. For instance, under Windows the library would be namedcvode.dll instead of libcvode.so.