This script facilitates the calculation of the velocity of a dislocation or other moving defect. The script requires only a LAMMPS dump file containing atom positions and will output a data file of timestep and defect position.
The script makes several assumptions.
The script also requires version 2.7 or newer of Ovito.
There are two ways to use the script, within the graphical Ovito program, or from the command line using the Ovitos scripting utility.
From the command line, simply run the command below. You may need to specify explicitly the path to the ovitos
executable in your Ovito distribution.
ovitos dis_mobility.py dump.atom.positions
In the gui, you will need to add four modifiers such that they are in the following order (top to bottom) in the modifier list.
The Polyhedral Template Matching modifier will determine the crystal structure on a per atom basis. It requires no setup for this case.
We will use this modifier to select all the atoms that are not a part of the defect that we are concerned about. In the expression box, add the conditional statement
StructureType == BULK || Position.Y < BELOW_MID || Position.Y > ABOVE_MID
Where BULK
is 1 if your material has an FCC bulk structure, 2 for HCP, or 3 for BCC.BELOW_MID and ABOVE_MID
should be a distance above and below the defect, for example, 30 Angstroms below and above the center of the cell in the Z direction, respectively.
This modifier will delete all selected particles, as the name says. It requires no setup.
This modifier will load the code from the script to create the defect position data file. You will need to make sure that the source file below is somewhere on your PYTHONPATH. Then, add the following to the script window, keeping the default import lines, but replacing the default modify
function definition.
from dis_mobility import get_dislocation_position modify = get_dislocation_position
# Calculate the speed of a dislocation # Bradley Huddleston, February 15, 2017 # # To use this within Ovito in the Python Script modifier, # use the following lines in triple quotes as the python script. # Replace SIMPATH with your simulation directory, and '99' with # the number of timesteps in your output file. """ from ovito.data import * import os os.chdir('SIMPATH') import dis_mobility as dm modify = dm.get_dislocation_position dm.initialize_data(99) """ from ovito import * import numpy as np import os assert(version[0] >= 2 and version[1] >= 7) def get_dislocation_position(frame, input, output): x_extent = output.cell.matrix[0,0] positions = output.particle_properties.position.marray #.copy() # Eliminate all periodic images positions[(positions[:,0] > x_extent),0] = positions[(positions[:,0] > x_extent),0] - x_extent # Edit positions to put dislocation all on same side if frame == 0: global core_spread core_spread = np.max(positions[:,0]) - np.min(positions[:,0]) if core_spread > 0.5*x_extent: core_spread = None elif core_spread: ref = positions[0,0] for i,p in enumerate(positions): if i == 0: continue if (p[0] - ref) > core_spread*1.3: p[0] -= x_extent ref = np.mean(positions[0:(i+1),0]) dislocation = np.mean(positions,0)[0] timestep = output.attributes['Timestep'] while (pos[frame - 1] - dislocation) > 0.25*x_extent: dislocation += x_extent with open('posVStime.txt','a+') as f: f.write('{}\t{}\n'.format(timestep, dislocation)) time[frame] = timestep pos[frame] = dislocation def initialize_data(num): global time, pos, core_spread time = np.zeros(num) pos = np.zeros(num) core_spread = None if os.path.exists('posVStime.txt'): data = np.loadtxt('posVStime.txt') time.put(range(len(data[:,0])),data[:,0]) pos.put(range(len(data[:,1])),data[:,1]) # If run from the command line setup required modifiers if __name__ == "__main__": from sys import argv if len(argv) < 2: raise Exception("Filename required as an argument.") filename = argv[-1] # Parse input arguments # Default values if len(argv) > 2: keyargs = argv[1:-1] i = 0 while (i < len(keyargs)): key = keyargs[i].split('-')[1] i += 1 if (key is "h") or (key is "help"): print("Usage: ovitos dis_mobility.py [OPTIONS] [FILENAME]\n\t-h,help\tThis help message\n") else: raise Exception("Unknown option: " + key) # ### Setup ovitos ### # Import file if len([s for s in filename if s == '*']) > 0: node = io.import_file(filename) else: node = io.import_file(filename, multiple_frames=True) # Create CNA or PTM modifier # if version[1] = 7: #structure = modifiers.CommonNeighborAnalysisModifier() #elif version[1] > 7: structure = modifiers.PolyhedralTemplateMatchingModifier() node.modifiers.append(structure) node.compute() # Estimate bulk structure nfcc = node.output.attributes['PolyhedralTemplateMatching.counts.FCC'] nbcc = node.output.attributes['PolyhedralTemplateMatching.counts.BCC'] nhcp = node.output.attributes['PolyhedralTemplateMatching.counts.HCP'] struct_ID = np.argmax([nfcc,nhcp,nbcc]) + 1 # Add expression select y_extent = node.output.cell.matrix[1,1] bulk = modifiers.SelectExpressionModifier( expression = 'StructureType == {} || Position.Y < {} || Position.Y > {}'.format( struct_ID, y_extent/2.0 - 30.0, y_extent/2.0 + 30.0)) node.modifiers.append(bulk) # Add delete selected delete = modifiers.DeleteSelectedParticlesModifier() node.modifiers.append(delete) numframes = node.source.num_frames frames = range(numframes) initialize_data(numframes) for frame in frames: if frame < numframes: dataset.anim.current_frame = frame # Advance frame. else: continue node.compute() get_dislocation_position(frame, node.output, node.output)