I am performing cluster analysis on systems composed of spherical, extended particles, and I need the analysis to account for the particles’ radii.
To illustrate the issue, I ran a simple test with two spherical particles, each with a radius of 10 Å, and placed them so that their centers are 30 Å apart, with the following dump file:
ITEM: ATOMS id type x y z radius
1 1 105 127 127 10
2 1 135 127 127 10
Ideally, the cluster cutoff should be applied to the surface-to-surface distance rather than the center-to-center distance. In this case, a cutoff of ≥10 Å (the distance between the surfaces) should be sufficient to consider them part of the same cluster. However, I only get them clustered together when the cutoff is ≥30 Å, which corresponds to the center-to-center distance.
In my actual simulations, particles can have varying radii, so accounting for their extension is essential. Is there a straightforward way to implement this in the cluster analysis?
This task is likely very difficult—if not impossible—using only OVITO’s built-in functionality. However, if you have access to OVITO Pro or the Python scripting interface, it can be solved quite easily. Here’s a rough outline of the steps involved:
Determine the maximum particle radius in the system.
Loop over all particles:
Use the Cutoff Neighbor Finder to identify neighbors within a distance of twice the maximum particle radius.
For each neighbor:
If the distance between the particles is less than or equal to the sum of their radii, create a bond between them.
Apply the Cluster Analysis modifier using the “bonds” neighbor mode.
Thank you so much for your helpful suggestions! I’m currently working on implementing them using Python scripting, as I need the code to be applicable to many data. However, I’m still not very familiar with the OVITO scripting system, and I believe there are still some issues with my code.
I’ve written the following lines to identify neighbors and create bonds when a certain condition is met:
from ovito.io import *
from ovito.data import *
from ovito.modifiers import *
from ovito.pipeline import *
import numpy as np
import time
cut = 11.7 # Cut-off for cluster analysis
pairs = []
def cluster_extended(frame: int, data: DataCollection):
# Find the maximum radius among the present particles
if 'Radius' in data.particles:
radii = data.particles['Radius']
max_radius = np.max(radii) # Find the maximum radius
print(f"The maximum radius of the particles is: {max_radius}")
else:
print("Particles do not have a 'Radius' property.")
# Manual creation of the bond list
positions = data.particles.positions
bond_list = []
# Find pairs at a distance that places them in the same cluster
distance = 2 * max_radius + cut
print(f"The set cut-off for the analysis is: {cut}")
print(f"The distance considered for finding neighbors is: {distance}")
# Create the neighbor finder with the exact distance
finder = CutoffNeighborFinder(distance, data)
for index in range(data.particles.count):
print(index)
neighbors = finder.find(index)
# Print the neighbors found for particle 1
for neigh in neighbors:
print(f"Particle {index} has as a neighbor particle {neigh.index}")
# Manual creation of the bond list
print(f"Distance between particles: {neigh.distance}")
if neigh.distance <= (data.particles['Radius'][neigh.index] + data.particles['Radius'][index] + cut):
i = index
j = neigh.index
if i < j: # Avoid duplicates
print("We need to create a bond!")
bond_list.append((i, j))
if bond_list:
bonds_array = np.array(bond_list, dtype=int)
# Create the Bonds object
bonds = Bonds()
bonds.create_property('Topology', data=bonds_array)
# Add the Bonds object to the scene
data.objects.append(bonds)
# Verify that OVITO recognizes it
for obj in data.objects:
if isinstance(obj, Bonds):
print("The 'Bonds' object was added correctly.")
print("Total number of bonds created:", obj.count)
else:
print("No bonds to create.")
Although it seems that the code correctly identifies the neighbors and creates the bonds, I encounter the following error when I add the Cluster Analysis modifier afterward:
RuntimeError: Modifier ‘Cluster analysis’ reported: This operation requires bonds as input, but the particle system has no bond topology defined.
This leads me to believe that the bonds are not actually being created. Could I be doing something wrong?
In this line, you’re creating a bonds object, but it’s independent and not linked to the rest of your simulation. For further processing, the bonds object needs to be associated with the data collection—specifically, with its particles object.