Example M1: Calculating mean square displacement

This example presents a user-defined modifier function for calculating the mean square displacement (MSD) for a system of moving particles. OVITO provides the built-in Displacement Vectors modifier, which calculates the individual displacement of each particle. It stores its results in the "Displacement Magnitude" particle property. So all our user-defined modifier function needs to do is to sum up the squared displacement magnitudes and divide by the number of particles:

import numpy

def modify(frame, data):
    # Access the per-particle displacement magnitudes computed by the 
    # 'Displacement Vectors' modifier preceding this user-defined modifier in the 
    # data pipeline:
    displacement_magnitudes = data.particles['Displacement Magnitude']

    # Compute MSD:
    msd = numpy.sum(displacement_magnitudes ** 2) / len(displacement_magnitudes)

    # Output value as a global attribute to make it available within OVITO:
    data.attributes["MSD"] = msd 

When used within the graphical program, the MSD value computed by this custom modifier may be exported to a text file as a function of simulation time using OVITO’s standard file export feature (Select Table of Values as output format).

Alternatively, we can make use of the custom modifier function from within a non-interactive batch script, which is run with the ovitos interpreter. Then we have to insert the CalculateDisplacementsModifier programmatically:

from ovito.io import import_file, export_file
from ovito.modifiers import CalculateDisplacementsModifier
import numpy

# Load input data and create a data pipeline.
pipeline = import_file("input/simulation.dump")

# Calculate per-particle displacements with respect to initial simulation frame:
pipeline.modifiers.append(CalculateDisplacementsModifier())

# Define the custom modifier function:
def calculate_msd(frame, data):

    # Access the per-particle displacement magnitudes computed by the 
    # CalculateDisplacementsModifier that precedes this user-defined modifier in the 
    # data pipeline:
    displacement_magnitudes = data.particles['Displacement Magnitude']

    # Compute MSD:
    msd = numpy.sum(displacement_magnitudes ** 2) / len(displacement_magnitudes)

    # Output MSD value as a global attribute: 
    data.attributes["MSD"] = msd 

# Insert user-defined modifier function into the data pipeline.
pipeline.modifiers.append(calculate_msd)

# Export calculated MSD value to a text file and let OVITO's data pipeline do the rest:
export_file(pipeline, "output/msd_data.txt", 
    format = "txt/attr",
    columns = ["Timestep", "MSD"],
    multiple_frames = True)