Skip to content
Marco Garten edited this page May 2, 2016 · 21 revisions

You are here: Home > Developer Documentation > Develop Plugins


This section will show you how to write your own plugins for PIConGPU. However, you should be familiar with how to use plugins in PIConGPU, first. Last but not least, make sure the plugin you want to create does not already exist.

Plugins in PIConGPU are based on the plugin management system of the underlying libPMacc. Hence, all plugins are ultimately derived from PMacc::IPlugin. libPMacc defines a registration/notification interface. Registered plugins can specify the period with which they want to get notified on simulation progress (iterations). Additionally, the IPlugin interface defines methods that enable program-wide checkpoints required for restarting the simulation.

Developing a lightweight plugin

All user-plugins should be created as new classes in the $PICSRC/src/picongpu/plugins/ directory. Assuming that your new plugin will be named MyPlugin create the following file MyPlugin.hpp:

#pragma once

#include "plugins/ILightweightPlugin.hpp"

namespace picongpu
{
using namespace PMacc;

class MyPlugin : public ILightweightPlugin
{
public:
  MyPlugin()
  {
    /* register our plugin during creation */
    Environment<>::get().PluginConnector().registerPlugin(this);
  }

  std::string pluginGetName() const
  {
    return "MyPlugin";
  }

  void notify(uint32_t currentStep)
  {
    /* notification callback for simulation step currentStep
     * called every notifyPeriod steps */
  }

  void pluginRegisterHelp(po::options_description& desc)
  {
    /* register command line parameters for your plugin */
    desc.add_options()
      ("myplugin.period", po::value<uint32_t > (&notifyPeriod)->default_value(0),
       "Enable MyPlugin [for each n-th step]");
  }

  void setMappingDescription(MappingDesc *cellDescription)
  {
  }

private:
  uint32_t notifyPeriod;

  void pluginLoad()
  {
    /* called when plugin is loaded, command line flags are available here
     * set notification period for our plugin at the PluginConnector */
    Environment<>::get().PluginConnector().setNotificationPeriod(this, notifyPeriod);
  }

  void pluginUnload()
  {
    /* called when plugin is unloaded, cleanup here */
  }
};
}

Then, we just need to add an instance of the plugin to $PICSRC/src/picongpu/plugins/PluginController.hpp:

#include "plugins/MyPlugin.hpp"
...
/**
* Initialises the controller by adding all user plugins to its internal list.
*/
virtual void init()
{
  ...
  /**
    * Add your plugin here, ...
    */
  plugins.push_back(new MyPlugin());
}
...

Developing a checkpoint/restart-capable plugin

PIConGPU features a checkpointing/restart mechanism that allows users to create checkpoint for certain simulation steps from which the simulation can be restarted afterwards in a new run.

To enable this mechanism for your plugin, we need to inherit from ISimulationPlugin instead of ILightweightPlugin. Given that you have the class MyPlugin from the above example, the following changes are necessary:

#include "plugins/ISimulationPlugin.hpp"

class MyPlugin : public ISimulationPlugin
{
public:
  ...
  void restart(uint32_t restartStep, const std::string restartDirectory)
  {
    /* restart from a checkpoint here
     * will be called only once per simulation and before notify() */
  }

  void checkpoint(uint32_t currentStep, const std::string restartDirectory)
  {
    /* create a persistent checkpoint here
     * will be called before notify() if both will be called for the same timestep */
  }
  ...
}

Handle outgoing particles

If a plugin needs to process particles which are leaving the global simulation volume it can overload IPlugin::onParticleLeave(). This method is called on this event for each species that was constructed with the GuardHandlerCallPlugins policy (in ParticleDescription).