Author Topic: OVITO WS Python Script  (Read 1618 times)

jhart

  • Newbie
  • *
  • Posts: 22
OVITO WS Python Script
« on: January 18, 2017, 08:45:55 PM »
Hello,

I am trying to calculate defect properties of a system that contains two atom types, Mg and O. There are 6 things that I would like to calculate:

Mg Vacancies
O Vacancies
Mg Antisites
O Antisites

The last two points I need to be broken down into:

Mg -> O
Mg -> 2O
O -> Mg
O -> 2Mg

(Sometimes I find more than one atom in this site).

I have the example code on the website, but I am not sure how to modify it for all 6 properties. Ideally, I could just create one file with the timestep, and all 6 properties. I tried to do it, but I just get 0 for all columns. What is wrong with my code?


Code: [Select]
from ovito.io import *
from ovito.data import *
from ovito.modifiers import *
import numpy as np

node = import_file("../cascade.dump",multiple_frames = True)

# Perform Wigner-Seitz analysis:
ws = WignerSeitzAnalysisModifier(
    per_type_occupancies = True,
    eliminate_cell_deformation = True)
ws.reference.load("../../../../../../STP/position_perfect_300.dump")
node.modifiers.append(ws)

# Define a modifier function that selects sites of type A=1 which
# are occupied by exactly one atom of type B=2.
def modify(frame, input, output):

    # Retrieve the two-dimensional Numpy array with the site occupancy numbers.
    occupancies = input.particle_properties['Occupancy'].array
   
    # Get the site types as additional input:
    site_type = input.particle_properties.particle_type.array

    # Calculate total occupancy of every site:
    total_occupancy = np.sum(occupancies, axis=1)

    # Set up a particle selection by creating the Selection property:
    selection1 = output.create_particle_property(ParticleProperty.Type.Selection).marray
    selection2 = output.create_particle_property(ParticleProperty.Type.Selection).marray
    selection3 = output.create_particle_property(ParticleProperty.Type.Selection).marray
    selection4 = output.create_particle_property(ParticleProperty.Type.Selection).marray
    selection5 = output.create_particle_property(ParticleProperty.Type.Selection).marray
    selection6 = output.create_particle_property(ParticleProperty.Type.Selection).marray
   
    # Select A-sites occupied by exactly one B-atom (the second entry of the Occupancy
    # array must be 1, and all others 0). Note that the Occupancy array uses 0-based
    # indexing, while atom type IDs are typically 1-based.
    selection1[:] = (site_type == 1) & (occupancies[:,0] == 0) & (occupancies[:,1] == 0)
    selection2[:] = (site_type == 1) & (occupancies[:,0] == 0) & (occupancies[:,1] == 1)
    selection3[:] = (site_type == 1) & (occupancies[:,0] == 0) & (occupancies[:,1] == 2)
    selection4[:] = (site_type == 2) & (occupancies[:,0] == 0) & (occupancies[:,1] == 0)
    selection5[:] = (site_type == 2) & (occupancies[:,0] == 1) & (occupancies[:,1] == 0)
    selection6[:] = (site_type == 2) & (occupancies[:,0] == 2) & (occupancies[:,1] == 0)
    # Additionally output the total number of antisites as a global attribute:
    output.attributes['O_Vac'] = np.count_nonzero(selection1)
    output.attributes['O_Anti'] = np.count_nonzero(selection2)
    output.attributes['O_Anti_2'] = np.count_nonzero(selection3)
    output.attributes['Metal_Vac'] = np.count_nonzero(selection4)
    output.attributes['Metal_Anti'] = np.count_nonzero(selection5)
    output.attributes['Metal_Anti_2'] = np.count_nonzero(selection6)
# Insert Python modifier into the data pipeline.
node.modifiers.append(PythonScriptModifier(function = modify))

# Let OVITO do the computation and export the number of identified
# antisites as a function of simulation time to a text file:
export_file(node, "defects.txt", "txt",
    columns = ['Timestep', 'O_Vac', 'O_Anti', 'O_Anti_2', 'Metal_Vac', 'Metal_Anti','Metal_Anti_2'],
    multiple_frames = True)

# Export the XYZ coordinates of just the antisites by removing all other atoms.
node.modifiers.append(InvertSelectionModifier())
node.modifiers.append(DeleteSelectedParticlesModifier())
export_file(node, "antisites.xyz", "xyz", columns = ['Position.X', 'Position.Y', 'Position.Z'],
    multiple_frames = True)
« Last Edit: January 18, 2017, 09:35:52 PM by jhart »

Alexander Stukowski

  • Administrator
  • Hero Member
  • *****
  • Posts: 588
Re: OVITO WS Python Script
« Reply #1 on: January 19, 2017, 09:08:37 AM »
Hi

The problem is that Ovito only allows one particle selection to exist at a time. More specifically, a DataCollection can only hold one particle property named "Selection". Particles cannot have multiple selection properties associated with them. So if you do

Code: [Select]
    # Set up a particle selection by creating the Selection property:
    selection1 = output.create_particle_property(ParticleProperty.Type.Selection).marray
    selection2 = output.create_particle_property(ParticleProperty.Type.Selection).marray
    selection3 = output.create_particle_property(ParticleProperty.Type.Selection).marray
    selection4 = output.create_particle_property(ParticleProperty.Type.Selection).marray
    selection5 = output.create_particle_property(ParticleProperty.Type.Selection).marray
    selection6 = output.create_particle_property(ParticleProperty.Type.Selection).marray

then the repeated call to create_particle_property() will always return the same particle property and all variables selection1 though selection6 will refer to the same Numpy data array and the following code will lead to wrong results.

Since your are mainly interested in the defect counts, I recommend that you do not create particle selections at all. Instead, just create temporary Numpy arrays and count non-zero entries:

Code: [Select]
selection1 = (site_type == 1) & (occupancies[:,0] == 0) & (occupancies[:,1] == 0)
selection2 = (site_type == 1) & (occupancies[:,0] == 0) & (occupancies[:,1] == 1)
...
output.attributes['O_Vac'] = np.count_nonzero(selection1)
output.attributes['O_Anti'] = np.count_nonzero(selection2)
...

If you want, however, you can still let the modifier function generate a particle selection, but only one!