Reference for interfacing MD codes with PLUMED


Plumed.h and Plumed.c contain the external plumed interface, which is used to integrate it with MD engines.

This interface is very general, and is expected not to change across plumed versions. Plumed.c also implements a dummy version of the interface, so as to allow a code to be fully linked even if the plumed library is not available yet. These files could be directly included in the official host MD distribution. In this manner, it will be sufficient to link the plumed library at link time (on all systems) or directly at runtime (on system where dynamic loading is enabled) to include plumed features.

Why is Plumed.c written in C and not C++? The reason is that the resulting Plumed.o needs to be linked with the host MD code immediately (whereas the rest of plumed could be linked a posteriori). Imagine the MD code is written in FORTRAN: when we link the Plumed.o file we would like not to need any C++ library linked. In this manner, we do not need to know which C++ compiler will be used to compile plumed. The C++ library is only linked to the "rest" of plumed, which actually use it. Anyway, Plumed.c is written in such a manner to allow its compilation also in C++ (C++ is a bit stricter than C; compatibility is checked when PlumedStatic.cpp, which basically includes Plumed.c, is compiled with the C++ compiler). This will allow e.g. MD codes written in C++ to just incorporate Plumed.c (maybe renamed into Plumed.cpp), without the need of configuring a plain C compiler.

Plumed interface can be used from C, C++ and FORTRAN. Everything concerning plumed is hidden inside a single object type, which is described in C by a structure (struct plumed), in C++ by a class (PLMD::Plumed) and in FORTRAN by a fixed-length string (CHARACTER(LEN=32)). Obviously C++ can use both struct and class interfaces, but the first should be preferred. The reference interface is the C one, whereas FORTRAN and C++ interfaces are implemented as wrappers around it.

In the C++ interface, all the routines are implemented as methods of PLMD::Plumed. In the C and FORTRAN interfaces, all the routines are named plumed_*, to avoid potential name clashes. Notice that the entire plumed library is implemented in C++, and it is hidden inside the PLMD namespace.

Handlers to the plumed object can be converted among different representations, to allow inter-operability among languages. In C, there are tools to convert to/from FORTRAN, whereas in C++ there are tools to convert to/from FORTRAN and C.

These handlers only contain a pointer to the real structure, so that when a plumed object is brought from one language to another, it brings a reference to the same environment.

Moreover, to simplify life in all cases where a single Plumed object is required for the entire simulation (which covers most of the practical applications with conventional MD codes) it is possible to take advantage of a global interface, which is implicitly referring to a unique global instance. The global object should still be initialized and finalized properly.

The basic method to send a message to plumed is

  (C) plumed_cmd
  (C++) PLMD::Plumed::cmd
  (FORTRAN)  PLUMED_F_CMD

To initialize a plumed object, use:

  (C)        plumed_create
  (C++)      (constructor of PLMD::Plumed)
  (FORTRAN)  PLUMED_F_CREATE

To finalize it, use

  (C)        plumed_finalize
  (C++)      (destructor of PLMD::Plumed)
  (FORTRAN)  PLUMED_F_FINALIZE

To access to the global-object, use

  (C)        plumed_gcreate, plumed_gfinalize, plumed_gcmd
  (C++)      PLMD::Plumed::gcreate, PLMD::Plumed::gfinalize, PLMD::Plumed::gcmd
  (FORTRAN)  PLUMED_F_GCREATE, PLUMED_F_GFINALIZE, PLUMED_F_GCMD

To check if the global object has been initialized, use

  (C)        plumed_ginitialized
  (C++)      PLMD::Plumed::ginitialized
  (FORTRAN)  PLUMED_F_GINITIALIZED

To check if plumed library is available (this is useful for runtime linking), use

  (C)        plumed_installed
  (C++)      PLMD::Plumed::installed
  (FORTRAN)  PLUMED_F_INSTALLED

To convert handlers use

  (C)        plumed_c2f                 (C to FORTRAN)
  (C)        plumed_f2c                 (FORTRAN to C)
  (C++)      Plumed(plumed) constructor (C to C++)
  (C++)      operator plumed() cast     (C++ to C)
  (C++)      Plumed(char*)  constructor (FORTRAN to C++)
  (C++)      toFortran(char*)           (C++ to FORTRAN)
  FORTRAN interface
    SUBROUTINE PLUMED_F_INSTALLED(i)
      INTEGER,           INTENT(OUT)   :: i
    SUBROUTINE PLUMED_F_GINITIALIZED(i)
      INTEGER,           INTENT(OUT)   :: i
    SUBROUTINE PLUMED_F_GCREATE()
    SUBROUTINE PLUMED_F_GCMD(key,val)
      CHARACTER(LEN=*), INTENT(IN)     :: key
      UNSPECIFIED_TYPE, INTENT(INOUT)  :: val(*)
    SUBROUTINE PLUMED_F_GFINALIZE()
    SUBROUTINE PLUMED_F_GLOBAL(p)
      CHARACTER(LEN=32), INTENT(OUT)   :: p
    SUBROUTINE PLUMED_F_CREATE(p)
      CHARACTER(LEN=32), INTENT(OUT)   :: p
    SUBROUTINE PLUMED_F_CMD(p,key,val)
      CHARACTER(LEN=32), INTENT(IN)    :: p
      CHARACTER(LEN=*),  INTENT(IN)    :: key
      UNSPECIFIED_TYPE,  INTENT(INOUT) :: val(*)
    SUBROUTINE PLUMED_F_FINALIZE(p)
      CHARACTER(LEN=32), INTENT(IN)    :: p

The main routine is "cmd", which accepts two arguments: key is a string containing the name of the command val is the argument. it is declared const so as to use allow passing const objects, but in practice plumed is going to modify val in several cases (using a const_cast). In some cases val can be omitted: just pass a NULL pointer (in C++, val is optional and can be omitted). The set of possible keys is the real API of the plumed library, and will be expanded with time. New commands will be added, but backward compatibility will be retained as long as possible.

To pass plumed a callback function use the following syntax (not available in FORTRAN yet)

    plumed_function_holder ff;
    ff.p=your_function;
    plumed_cmd(plumed,"xxxx",&ff);

(this is passing the your_function() function to the "xxxx" command)