Interactor

Interactor is one of the base modules of UAMMD.

Interactor encapsulates the concept of a group of particles interacting, either with each other or with some external influence. An Interactor can be issued to compute, for each particle, the forces, energies and/or virial due to a certain interaction. To do so it can access the current state of the particles (like positions, velocities, etc) via ParticleData.

The Interactor interface class has the following API:

class Interactor : public virtual uammd::ParameterUpdatable

Interface for interaction modules computing forces, energies, and related quantities.

An Interactor acts on a group of particles and defines a computation interface through the ::sum() function. This function can compute various physical quantities based on the interaction model implemented by the derived class.

Additionally, because Interactor inherits from ParameterUpdatable, it may also respond to parameter update calls during simulation.

Subclassed by uammd::BondedForces< BondType, particlesPerBond >, uammd::DPPoissonSlab, uammd::Deserno, uammd::ExternalForces< Functor >, uammd::PairForces< Potential, NeighbourList >, uammd::Poisson, uammd::SPH

Public Functions

inline Interactor(shared_ptr<ParticleGroup> pg, std::string name = "noName")

Constructor using a specific particle group.

Parameters:
  • pg – Shared pointer to a ParticleGroup.

  • name – Optional name for the interactor.

virtual void sum(Computables comp, cudaStream_t st = 0) = 0

Compute the interaction quantities based on specified Computables. After calling ::sum the relevant particle properties will be updated and can be accessed via ParticleData.

Note

This method must be implemented by any derived Interactor class.

Parameters:
  • comp – Struct indicating which quantities should be computed.

  • st – CUDA stream for computation. All CUDA calls are guaranteed to be synchronous with respect to this stream.

inline std::string getName()

Get the name of the interactor.

Protected Attributes

string name

Name of the interactor, mainly used for logging.

shared_ptr<ParticleData> pd

Shared pointer to the particle data.

shared_ptr<ParticleGroup> pg

Group of particles the interactor acts on.

shared_ptr<System> sys

Access to the simulation System instance. This is just a convenience member, since the same instance can be accessed via ::ParticleData::getSystem .

struct Computables

Flags specifying which physical quantities to compute.

This structure allows the caller to specify which types of data (force, energy, virial, etc.) should be computed during the ::sum() operation. Additional user-defined quantities can also be included via the EXTRA_COMPUTABLES macro.

Public Members

bool force = false

Compute forces on particles.

bool energy = false

Compute energy contributions.

bool virial = false

Compute virial contributions.

bool stress = false

Compute stress contributions.

Hint

Interactors can subscribe to the ParameterUpdatable interface, which Integrator will use to communicate changes in parameters (such as the current simulation time).

Warning

Interactors should throw an exception if an unsatisfiable Computable is requested (for instance, due to a lack of implementation).

Adding new computables:

EXTRA_COMPUTABLES

Macro to define additional computable quantities at compile time.

This macro allows the user to extend the set of quantities that an Interactor can compute by defining additional fields in the Computables structure.

It should be defined as a Boost.Preprocessor sequence of identifiers. These identifiers will be expanded into boolean flags in the Computables struct.

Example

#define EXTRA_COMPUTABLES (myComputable1)(myComputable2)
#include "uammd.cuh"
// Now the Interactor::Computables struct passed down to sum() will have
// additional boolean fields myComputable1 and myComputable2.

Warning

This macro must be defined before including any uammd headers.

Using an already available Interactor:

Each Interactor has its own requirements for initialization, visit the page for the one you are interested in for further instructions.

Once initialized all Interactors can be seamlessly added to any Integrator.

Let us see, for instance, how to create a triply periodic electrostatics Interactor and add it to an already created Brownian Dynamics Integrator:

#include"Interactor/SpectralEwaldPoisson.cuh" //The Interactor for triply periodic electrostatics
...
//Assume bd is a BD::EulerMaruyama Integrator previously created
//Assume pd is a ParticleData
//Each Interactor requires a different set of parameters, that exists in an structure called
// ModuleName::Parameters
Poisson::Parameters par;
par.box = Box({128, 128, 128});
par.epsilon = 1;
par.gw = 1.0;
par.tolerance = 1e-4;
//The Interactor is created here by providing it with a ParticleData and the required parameters, which you can learn about in the page of the module page
auto poisson = make_shared<Poisson>(pd, par);
//At this point we can either issue the Interactor to compute the forces/energies/virials
//poisson->sum({.force= true, .energy = false, .virial=false});
//Or pass it to an Integrator
bd->addInteractor(poisson);

Creating a new Interactor

In order to create a new Interactor module, write a class that inherits from it and overrides the sum method. You will then have access to all its members, and will be able to use it as an Interactor for all intends and purposes.

See Pair Forces for an example of an Interactor.

Note that the sum method is expected to update the relevant properties in ParticleData (for instance using pd->getForce(...) if force is true in Computables).

A minimal example of an Interactor:

#include<uammd.cuh>
#include<Interactor/Interactor.cuh>
using namespace uammd;

//A class that needs to behave as
// an UAMMD Interactor must inherit from it
class MyInteractor: public Interactor{
  public:
  //The constructor must initialize the base Interactor class, for which a ParticleData instance is required.
  //Other than that, it can take any necessary arguments (such as a group of parameters).
  MyInteractor(std::shared_ptr<ParticleData> pd):
          Interactor(pd, "MyInteractor"){
    //Any required initialization
  }

  //An Interactor can be issued, mainly
  // by Integrators, to sum
  // forces, energies and/or virial
  // on the particles
  virtual void sum(Computables comp, cudaStream_t st) override{
    //"sys" and "pd" are provided by the Interactor base class
    sys->log<System::MESSAGE>("Computing interaction");
    if(comp.force){
      //Sum forces to each particle
      //For instance, adding a force to the x coordinate
      // of the first particle
      auto forces = pd->getForce(access::cpu, access::write);
      forces[0].x += 1;
    }
    if(comp.energy){
      //Sum energies to each particle
    }
    if(comp.virial){
      //Sum virial to each particle
    }
  }
};

Note that Interactor is what is a pure-virtual class. This means that Interactor is not a class that can be used by itself (such as, for instance, ParticleData). It is a conceptual base class that must be inherited from.

Hint

Any class inheriting from Interactor will have access to an instance of System with the name sys, that can be used to query properties of the GPU and log messages, and a ParticleData instance with the name pd.

Available Interactors

You can see a list of implemented Interactors in the side bar.