Creating custom order parameters

Often, you will find the need to create custom order parameters for your path sampling simulation. In PyRETIS, you can create new order parameters by making use of the generic OrderParameter class defined in the library. Technically speaking, you will have to sub-class OrderParameter and implement a method (like OrderParameter.calculate()) which actually calculates the order parameter. In addition, you can define additional collective variables to be calculated.

The short version of what we need to do in order to create a new order parameter is:

  1. Create a new Python class which is a sub-class of OrderParameter
  2. Write a method to initialise this class, that is the __init__ method. This method will be called when PyRETIS is setting up a new simulation and it will be fed variables from the PyRETIS input file.
  3. Write a method to calculate the order parameter. This should take in a System object as its argument.
  4. Setting up the input file to use the new order parameter.

Example: Creating a new order parameter

Let us see how this can be done in practice. To be concrete, we will consider an order parameter defined as follows: The distance between a particular particle and a plane positioned somewhere along the x-axis.

Step 1 and 2: Sub-classing OrderParameter

In order to define a new class to use with PyRETIS, we first import some additional libraries.

import numpy as np
from pyretis.orderparameter import OrderParameter

And we set up a new class, representing our new order parameter:

class PlaneDistanceX(OrderParameter):
    """A positional order parameter.

    This class defines a very simple order parameter which is just
    the position of a given particle.
    """

    def __init__(self, index, plane_position):
        """Initialize the order parameter.

        Parameters
        ----------
        index : integer
            Selects the particle to use.

        plane_position : float
            The location of the plane, along the x-axis.
        """
        txt = 'Distance from particle {} to the plane at {}'.format(
            index,
            plane_position)
        super().__init__('Plane distance, x-axis', desc=txt)
        self.index = index
        self.plane_position = plane_position

Here, we are initialising the class by storing two variables index and plane_position which identifies the particle we will consider and the location of the plane. In addition, we add some more information txt and a name when we initialise the parent class (the line calling super().__init__). This is simply following the convention defined by OrderParameter.

Step 3: Creating a method for calculating the order parameter

Next, we will write a method for actually calculating the order parameter. In order to do this, we need to know how we can interact with the System object, and this might be a good point to read the introduction to the API. In particular, we will mostly be interacting with the Particles class which we can access using System.particles.

Typically, our calculation of the order parameter will correspond to one of the two following cases:

  • We want to access the positions of the particles directly and calculate the order parameter. Here, just a new method to the PlaneDistanceX class we are creating as follows:

        def calculate(self, system):
            """Calculate the order parameter."""
            pos = system.particles.pos[self.index]
            dist = -np.abs(pos[0] - self.plane_position)
            return [dist]
    

    Here, we are making use of the index and position of the plane which we stored previously. Further, we are using the System.particles object in order to access the positions. Finally, we are returning the order parameter. But note that we return this as a negative number.

  • We are using an external engine (e.g. GROMACS) and we just want to reference the file containing the current configuration, and pass this file reference on to another external library or program.

    Here, we will make use of some external tools to obtain the order parameter, for simplicity, let us here make use of the mdtraj library. First, at the top of your file, add the import of this library:

    import numpy as np
    import mdtraj
    from pyretis.orderparameter import OrderParameter
    

    In order to access the file containing the configuration, we make use of the ParticlesExt.config attribute. Add the following method to the PlaneDistanceX class:

        def calculate(self, system):
            """Calculate the order parameter."""
            filename = system.particles.config[0]
            traj = mdtraj.load(filename)
            return some_function_to_obtain_order(traj)
    

Step 4: Making use of the new order parameter

We make use of the new order parameter by adding the Orderparameter section to the input file:

Orderparameter
--------------
class = PlaneDistanceX
module = orderparameter1.py
index = 0
plane_position = 1.0

As you can see, we specify the following:

  1. The name of the class.
  2. The name of the file where we have stored the new class.
  3. The value for the index parameter the order parameter takes in.
  4. The value for the plane_position parameter the order parameter takes in.