Grain boundary structure initialization from atomic-resolution HAADF STEM imaging [wiki] [paper]
This repo is currently private in order to protect the MaterialEyes© source code while under development. Contact me if you are are a potential user or developer and I will set you up with the proper permissions to view/contribute to the code.
This is an example of an atomic–resolution HAADF STEM image of a CdTe (100)-(110) grain boundary with tilt. In many optimization approaches, a solver might benefit from a good initial guess on where to start; That is what this code provides. It is assumed that the orientation and the chemical composition of each constituent crystal is known.
image credit: Guo, Jinglong,
# Import main ingrained package modules
from ingrained.structure import Bicrystal
from ingrained.optimize import CongruityBuilder
# For top grain
grain_1 = {}
grain_1["chemical_formula"] = "CdTe"
grain_1["space_group"] = "F-43m"
# screen to viewer
grain_1["uvw_project"] = [1,1,0]
# upward on screen
grain_1["uvw_upward"] = [-1,1,0]
# CCW around "uvw_project"
grain_1["tilt_angle"] = 8
# maximum width (Å)
grain_1["max_dimension"] = 40
# For bottom grain
grain_2 = {}
grain_2["chemical_formula"] = "CdTe"
grain_2["space_group"] = "F-43m"
# screen to viewer
grain_2["uvw_project"] = [1,1,0]
# upward on screen
grain_2["uvw_upward"] = [0,0,1]
# CCW around "uvw_project"
grain_2["tilt_angle"] = 0
# maximum width (Å)
grain_2["max_dimension"] = 40
Bicrystal
from grain information and setup optimization.bicrystal = Bicrystal([grain_1,grain_2], \
minmax_width=(10,40), \
minmax_depth=(8,20))
# Use pixel scaling (dm3) to constrain size
if dm3lib.DM3(dm3_path).pxsize[1].decode('UTF-8') == 'nm':
pixsz = dm3lib.DM3(dm3_path).pxsize[0]*10
# Constraints
iw = [-1,2.5] # interface widths (Å)
df = [0.75,1.75] # defocus values (Å)
px = [0.85*pixsz,1.15*pixsz] # allowable pixel sizes (Å)
bx = [0.0,0.15] # x-border red. ratio (vert)
by = [0.0,0.15] # y-border red. ratio (horiz)
# Initialize ConguityBuilder to optimize fit
congruity = CongruityBuilder(bicrystal=bicrystal,dm3=dm3_path)
# Define a starting point for optimization
# | iw | df | bx | by | px |
x0 = [-0.1, 1.3, 0, 0.1, pixsz]
res1 = congruity.find_correspondence(optimizer='COBYLA', \
initial_solution=x0, constraint_list=[iw,df,bx,by,px])
⋮
Final Solution:
>>> IW : -0.6078157487413525
>>> DF : 1.4319874724494737
>>> PX : 0.163556437666011
>>> BX : 0.1542803492239945
>>> BY : 0.11378092964375788
🌀 FOM : 0.7996850224295375
Optimization terminated successfully.
Current function value: 0.799685
Iterations: 4
Function evaluations: 805
The final parameterization provides an optimal correspondence solution between the experimental image and the proposed initial structure. Notice the high degree of similarity between the simulation and experiment!