How to write a plugin#

Before discussing what each kind of plugin actually has to implement (see the next subsection), let us briefly go over what you actually have to do when implementing a new plugin. Essentially, the following steps are all you need to do:

  • Create a file, say my_plugin.cc that contains the declaration of the class you want to implement. This class must be derived from one of the Interface classes we will discuss below. The file also needs to contain the implementation of all member functions of your class.

    As discussed above, it is possible – but not necessary – to split this file into two: a header file, say my_plugin.h, and the my_plugin.cc file (or, if you prefer, into multiple source files). We do this for all the existing plugins in ASPECT so that the documentation of these plugins shows up in the doxygen-generated documentation. However, for your own plugins, there is typically no need for this split. The only occasion where this would be useful is if some plugin actually makes use of a different plugin (e.g., the implementation of a gravity model of your own may want to query some specifics of a geometry model you also implemented); in that case the using plugin needs to be able to see the declaration of the class of the used plugin, and for this you will need to put the declaration of the latter into a header file.

  • At the bottom of the my_plugin.cc file, put a statement that instantiates the plugin, documents it, and makes it available to the parameter file handlers by registering it. This is always done using one of the ASPECT_REGISTER_* macros that will be discussed in the next subsections; take a look at how they are used in the existing plugins in the ASPECT source files.

  • You need to compile the file. There are two ways by which this can be achieved:

    • Put the my_plugin.cc into one of the ASPECT source directories and call cmake . followed by make to ensure that it actually gets compiled. This approach has the advantage that you do not need to worry much about how the file actually gets compiled. On the other hand, every time you modify the file, calling make requires not only compiling this one file, but also linking the ASPECT binary. Furthermore, when you upgrade from one version of ASPECT to another, you need to remember to copy the my_plugin.cc file.

    • Put the my_plugin.cc file into a directory of your choice and compile it into a shared library, which will be loaded by ASPECT. While one could compile the .cc file with a command like

       # NOTE: Do not do this, but use the cmake command below!
       g++ -I/path/to/aspect/headers -I/path/to/deal.II/headers \
           -fPIC -shared my_plugin.cc -o my_plugin.so
      

      on Linux, but the command may be different on other systems. Having to remember all of these pieces is a hassle, and a much easier way is in fact to set up a small CMake project for this. To this end, simply copy the file doc/plugin-CMakeLists.txt to the directory where you have your plugin source files and rename it to CMakeLists.txt.

      You can then just run the commands

      cmake -DAspect_DIR=/path/to/aspect/build/ .
      make
      

      and it should compile your plugin files into a shared library libmy_plugin.so. A concrete example of this process is discussed in Running benchmarks that require code. Of course, you may want to choose different names for the source files source_1.cc, source_2.cc or the name of the plugin my_plugin inside the CMakeLists.txt.

      In essence, what the few lines inside the CMakeLists.txt do, is that they find an ASPECT installation (i.e., the directory where you configured and compiled it as discussed in Installation) in either the directory explicitly specified in the Aspect_DIR variable passed to cmake, the shell environment variable ASPECT_DIR, or just one directory up. It then sets up compiler paths and similar, and the following lines simply define the name of a plugin, list the source files for it, and define everything that’s necessary to compile them into a shared library. Calling make on the command line then simply compiles everything.

      Now you only need to tell ASPECT to load this shared library at startup so that the plugin becomes available at run time and can be selected from the input parameter file. This is done using the Additional shared libraries parameter in the input file, see Parameter name: Additional shared libraries:

      set Additional shared libraries = ./libmy_plugin.so
      

      This approach to build your own shared library has the upside that you can keep all files that define new plugins in your own directories where you also run the simulations, also making it easier to keep around your plugins as you upgrade your ASPECT installation. On the other hand, compiling the file into a shared library is a bit more that you need to do yourself. Nevertheless, this is the preferred approach.

      Recently, ASPECT learned to build debug and optimized builds from a single build directory as described in Debug or optimized mode. Since then, plugins will be compiled into libmy_plugin.debug.so, libmy_plugin.release.so, or both depending on how ASPECT was configured. You do not need to modify the Additional shared libraries to point to one or the other library, because ASPECT will automatically load the corresponding file if you just specify ./libmy_plugin.so.

Note

Complex projects built on ASPECT often require plugins of more than just one kind. For example, they may have plugins for the geometry, the material model, and for postprocessing. In such cases, you can either define multiple shared libraries by repeating the calls to PROJECT, ADD_LIBRARY and ASPECT_SETUP_PLUGIN for each shared library in your CMakeLists.txt file above, or you can just compile all of your source files into a single shared library. In the latter case, you only need to list a single library in your input file, but each plugin will still be selectable in the various sections of your input file as long as each of your classes has a corresponding ASPECT_REGISTER_* statement somewhere in the file where you have its definition. An even simpler approach is to just put everything into a single file – there is no requirement that different plugins are in separate files, though this is often convenient from a code organization point of view.

Note

If you choose to compile your plugins into a shared library yourself, you will need to recompile them every time you upgrade your ASPECT installation since we do not guarantee that the ASPECT application binary interface (ABI) will remain stable, even if it may not be necessary to actually change anything in the implementation of your plugin