Using AMICI’s C++ interface

The various import functions in of the Python interface and Matlab interface translate models defined in different formats into C++ code. These generated model libraries, together with the AMICI base library can be used in any C++ application for model simulation and sensitivity analysis. This section will give a short overview over the generated files and provide a brief introduction of how this code can be included in other applications. Further details are available in the C++ API reference.

AMICI-generated C++ model files

After importing a model using either the Python interface or the Matlab interface, the specified output directory contains (among others) C++ code for the various model functions.

The content of a model source directory looks something like this (given MODEL_NAME=model_steadystate):

CMakeLists.txt
main.cpp
model_steadystate_deltaqB.cpp
model_steadystate_deltaqB.h
[... many more files model_steadystate_*.(cpp|h|md5|o) ]
wrapfunctions.cpp
wrapfunctions.h
model_steadystate.h

These files provide the implementation of a model-specific subclass of amici::Model. The CMakeLists.txt file can be used to build the model library using CMake. main.cpp contains a simple scaffold for running a model simulation from C++. See next section for more details on these files.

Running a model simulation

AMICI’s public API is mostly available through amici/amici.h. This is the only header file that needs to be included for basic usage. All functions there are declared within the amici namespace. Additionally, amici/hdf5.h and amici/serialization.h may be handy for specific use cases. The former provides some functions for reading and writing HDF5 files, latter for serialization (requires Boost). All model-specific functions are defined in the namespace model_$modelname.

The main function for running an AMICI simulation is amici::runAmiciSimulation(). This function requires

  • an instance of a amici::Model subclass as generated during model import. For the example model_steadystate the respective class is provided as Model_model_steadystate in model_steadystate.h in output directory for the given model.

  • a amici::Solver instance. This solver instance needs to match the requirements of the model and can be obtained from amici::AbstractModel::getSolver().

  • optionally an amici::ExpData instance, which contains any experimental data (e.g. measurements, noise model parameters or model inputs) to evaluate residuals or an objective function.

This function returns a amici::ReturnData object, which contains all simulation results.

For running simulations for multiple experimental conditions (multiple amici::ExpData instances), amici::runAmiciSimulations() provides an alternative entry point. If AMICI (and your application) have been compiled with OpenMP support (see installation guide), this allows for running those simulations in parallel.

A scaffold for a standalone simulation program is automatically generated during model import in main.cpp in the model output directory. This program shows how to use the above-mentioned classes, how to obtain the simulation results, and may provide a starting point for your own simulation code.

Working with multiple or anonymous models

AMICI model import generates a amici::Model subclass for the specific model, based on the name used during import. One the one hand, this allows you to use multiple models with different names within a single application. On the other hand, this requires you to know the name of the model, which can be inconvenient in some cases.

When working with a single model, the wrapfunctions.h file generated during model import can be used to avoid specifying model names explicitly. It defines a function amici::generic_model::getModel(), that returns an instance of the model class by a generic name.

Note

Including multiple wrapfunctions.h files from different models in a single application is not possible. When using multiple models, explicit names have to be used or the different model libraries need to be loaded dynamically at runtime.

Compiling and linking

To run AMICI simulations from within your C++ application, you need to compile and link the following libraries:

  • model library

  • AMICI base library

  • SUNDIALS libraries

  • SuiteSparse libraries

  • CBLAS-compatible BLAS

  • optionally HDF5 (C, HL, and CXX components) set CMake option ENABLE_HDF5 to OFF to build without HDF5-support

  • optionally OpenMP (for parallel simulation of multiple conditions, see amici::runAmiciSimulations())

  • optionally boost (only when using serialization of AMICI object)

The simplest and recommended way is using the provide CMake files which take care of all these dependencies.

Considering the simple case, that you want to simulate one specific model in your CMake-based C++ application, you can copy or move the generated model directory containing the CMakeLists.txt file to your application directory, add add_subdirectory(yourModelDirectory) to your project’s CMakeLists.txt file and build your project using CMake as usual.

Parameter estimation for AMICI models in high-performance computing environments

To perform parameter estimation for large or otherwise computationally demanding AMICI models from C++ in a high-performance computing environment, you may find the parPE library helpful. parPE allows for the private or shared memory parallel evaluation of a cost function requiring multiple simulations of the same model with different inputs. It provides interfaces to different optimizers, such as Ipopt.