Forum Navigation
You need to log in to create posts and topics.

Vacancy cluster analysis

I am looking at clusters of interstitial atoms forming alongside vacancies and aiming to find out what the interstitial:vacancy ratio is.

I use the wigner-seitz defect analysis and then expression select to display the vacancies. Then in a different pipeline display the interstitials and perform cluster analysis.

Is there a way to count the vacancies associated with each cluster?

Previously I had manually counted them but the clusters I am now analysing are too large to do that accurately.

Many thanks

Uploaded files:
  • 2250K_cluster_end.png

Hi,

it is not directly possible with a simple python modifier in the desktop application, but here's an idea for a workaround. If you like you can save the following script and apply to your existing scene by clicking File-> Run python script.

import ovito
from ovito.data import *
import numpy as np

pipeline1 = ovito.scene.pipelines[1]
pipeline2 = ovito.scene.pipelines[0]

n_frames = pipeline1.source.num_frames
V = {}

for frame in range(pipeline1.source.num_frames):
    interstitials = pipeline1.compute(frame)
    cluster_ids = interstitials.particles["Cluster"]
    vacancies = pipeline2.compute(frame)

    #Initialize neighbor finder object:
    cutoff = 0.5
    finder = CutoffNeighborFinder(cutoff, vacancies)

    #Count number of vacancies found in specified cutoff distance of each interstitial particle sharing the same cluster id
    vacancy_dict = {}
    for c_id in cluster_ids:
        vacancy_ids = []
        interstitials_of_current_cluster = interstitials.particles.positions[cluster_ids == c_id]
        for p in interstitials_of_current_cluster:
            for neigh in finder.find_at(p):
                vacancy_ids.append(neigh.index)
        vacancy_dict[c_id] = set(vacancy_ids) 
    V[frame] = vacancy_dict


# Add vacancy count to "Cluster Data Table" in pipeline1
def modify(frame: int, data: DataCollection, V = V ):
    v_count = data.tables['clusters_'].create_property("Vacancy count", dtype = int, components = 1)
    for cluster_id, particle_ids in V[frame].items():
        v_count[cluster_id-1] = len(particle_ids)   
pipeline1.modifiers.append(modify)

# Add cluster_id as particle property to vacancies in pipeline 2 for validation
def modify2(frame: int, data: DataCollection, V = V):
    particle_property = data.particles_.create_property("Cluster_id", data = np.zeros(data.particles.count))
    for cluster_id, particle_ids in V[frame].items():
        for index in particle_ids:
           particle_property[index] = cluster_id   
pipeline2.modifiers.append(modify2)

This code snippet will look up positions of the interstitials (and their corresponding cluster ids) from the first pipeline and use these coordinates in the second pipeline in the CutoffNeighborFinder find.at() method.

Finally, the script adds the vacancy count to the initial cluster list visible in the Data Inspector of pipeline 1. It also adds the cluster ids to the vacancy particle properties in the second pipeline for cross-validation.
Let me know what you think.  You probably also have to play around with the cutoff value for the CutoffNeighborFinder function.

I can't guarantee that there is no easier/more elegant way to do this, but I hope this might serve as a short-term solution to your problem.

-Constanze

新的OVITO微信频道!
New for our users in China: OVITO on WeChat 

Official OVITO WeChat channel operated by Foshan Diesi Technology Co., Ltd.