Skip to content

Analysis of local polarization in (111)-oriented PTO thin films

The current script (developed by MXS or Shi Liu) used for calculating polarization (via the displacement of positive and negative charge centers) is orientation-independent. Therefore, it can be directly applied to compute the polarization distribution in the (111)-oriented thin films.

After obtaining the polarization data, an Autocorrelation Function (ACF) analysis can be performed on the polarization. This analysis helps determine the flexibility (or fluctuation) of the local polarization. For specific details, you can refer to Yuanjinsheng Liu's tutorial, "Calculation of dipole-dipole time-delayed correlation function C(r,t)".

However, a critical point must be noted: the resulting cross-sectional polarization maps (e.g., on the \(xy\)-plane) are not truly co-planar.

This discrepancy arises from the crystallographic coordinate transformation from the (001) to the (111) orientation. In a (001) orientation, supercell dimensions are typically integer multiples along the \(x, y, z\) axes ("Integer \(\times\) Integer \(\times\) Integer"). When transformed to the (111) orientation, the new basis vectors (e.g., corresponding to the original \([1\bar{1}0]\), \([11\bar{2}]\), and \([111]\) directions) result in supercell dimensions proportional to "Integer\(\sqrt{2}\) \(\times\) Integer\(\sqrt{6}\) \(\times\) Integer\(\sqrt{3}\)".

This coordinate transformation leads to a staggered or "zigzag" arrangement of the lattice at the atomic level along the new \(z\)-direction (the [111] axis). Consequently, when visualizing a polarization map on the \(xy\)-plane (which represents the (111) plane), it is crucial to understand that while it appears as a single flat slice, the adjacent unit cells depicted are not, in fact, located at the same crystallographic height. This structural property must be fully considered when analyzing the local polarization data.

How to construct a (111)-oriented supercell?

The first method is to construct a (001)-oriented supercell and then apply a coordinate transformation using a rotation matrix (e.g., ASE, pymatgen).

The second method is to construct it directly according to the (111) lattice arrangement, using the script below, which directly defines the fractional coordinate arrangement for each element (for details about the code, you can ask the AI):

#!/usr/bin/python
import os
import numpy as np
import sys
import random

#This python script creates a (nx,ny,nz) supercell of 111-PbTiO3

ux = 5.574884027 #3.9539*sqrt2
uy = 9.655982382 #3.9539*sqrt6
uz = 6.827810621 #3.9539*sqrt3

nx = 20
ny = 18  #*2=36
nz = 10  #*3=30
natom = 30 * nx * ny * nz
nAatoms = nBatoms = 6 * nx * ny * nz

lx = nx * ux
ly = ny * uy
lz = nz * uz

DPbx = 0.0
DPby = 0.0
DPbz = 0.25
DTix = 0.0
DTiy = 0.0
DTiz = 0.2

#delta = 0.0
factorSTO = float(sys.argv[1])
Nsample = int(factorSTO * nAatoms)
R1 = random.sample(range(nAatoms+1,nAatoms+nAatoms),Nsample)
totalSr = len(R1)
print("Total Zr atoms:", totalSr)
fr = open("random_numbers.dat", 'w')

f2 = open('PSTO_SS.data', 'w')
f2.write("\n")
f2.write("%d atoms\n" % natom)
f2.write(" 4 atom types\n")
f2.write(" %f %f xlo xhi\n" % (0.0, lx))
f2.write(" %f %f ylo yhi\n" % (0.0, ly))
f2.write(" %f %f zlo zhi\n" % (0.0, lz))
f2.write(" 0.0000000000 0.0000000000 0.0000000000 xy xz yz\n")
f2.write("\n")
f2.write("Atoms # atomic\n")
f2.write("\n")

f3 = open('PSTO_SS.xsf', 'w')
f3.write("CRYSTAL\n")
f3.write("PRIMVEC\n")
f3.write("%15.10f %15.10f %15.10f \n" % (lx, 0.0, 0.0))
f3.write("%15.10f %15.10f %15.10f \n" % (0.0, ly, 0.0))
f3.write("%15.10f %15.10f %15.10f \n" % (0.0, 0.0, lz))
f3.write("PRIMCOORD\n")
f3.write("   %d   %d \n" % (natom, 1))

#id mol type  x y z
#coord1,molID,typeID,charge
ID = 0
#molID = 1
for k in range(0, nz):
    for j in range(0, ny):
        for i in range(0, nx):
            # Pb
            x = 0.0 * ux + i * ux + DPbx
            y = 0.0 * uy + j * uy + DPby
            z = 0.0 * uz + k * uz + DPbz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 2, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Pb", x, y, z))  
        for i in range(0, nx):
            x = 1/2 * ux + i * ux + DPbx
            y = 1/2 * uy + j * uy + DPby
            z = 0.0 * uz + k * uz + DPbz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 2, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Pb", x, y, z))

    for j in range(0, ny):
        for i in range(0, nx):
            # Pb
            x = 1/2 * ux + i * ux + DPbx
            y = 1/6 * uy + j * uy + DPby
            z = 1/3 * uz + k * uz + DPbz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 2, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Pb", x, y, z))
        for i in range(0, nx):
            x = 0.0 * ux + i * ux + DPbx
            y = 2/3 * uy + j * uy + DPby
            z = 1/3 * uz + k * uz + DPbz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 2, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Pb", x, y, z))

    for j in range(0, ny):
        for i in range(0, nx):
            # Pb
            x = 0.0 * ux + i * ux + DPbx
            y = 1/3 * uy + j * uy + DPby
            z = 2/3 * uz + k * uz + DPbz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 2, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Pb", x, y, z))
        for i in range(0, nx):
            x = 1/2 * ux + i * ux + DPbx
            y = 5/6 * uy + j * uy + DPby
            z = 2/3 * uz + k * uz + DPbz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 2, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Pb", x, y, z))


for k in range(0, nz):
    for j in range(0, ny):
        for i in range(0, nx):
            # Ti
            x = 0.0 * ux + i * ux + DTix
            y = 1/3 * uy + j * uy + DTiy
            z = 1/6 * uz + k * uz + DTiz
            ID += 1
            if ID in R1:
                f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 10, x, y, z))
                f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Zr", x, y, z))
                fr.write('%d \n' % ID)
            else:
                f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 9, x, y, z))
                f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Ti", x, y, z))
        for i in range(0, nx):
            # Ti
            x = 1/2 * ux + i * ux + DTix
            y = 5/6 * uy + j * uy + DTiy
            z = 1/6 * uz + k * uz + DTiz
            ID += 1
            if ID in R1:
                f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 10, x, y, z))
                f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Zr", x, y, z))
                fr.write('%d \n' % ID)
            else:
                f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 9, x, y, z))
                f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Ti", x, y, z))

    for j in range(0, ny):
        for i in range(0, nx):
            # Ti
            x = 0.0 * ux + i * ux + DTix
            y = 0.0 * uy + j * uy + DTiy
            z = 1/2 * uz + k * uz + DTiz
            ID += 1
            if ID in R1:
                f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 10, x, y, z))
                f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Zr", x, y, z))
                fr.write('%d \n' % ID)
            else:
                f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 9, x, y, z))
                f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Ti", x, y, z))
        for i in range(0, nx):
            # Ti
            x = 1/2 * ux + i * ux + DTix
            y = 1/2 * uy + j * uy + DTiy
            z = 1/2 * uz + k * uz + DTiz
            ID += 1
            if ID in R1:
                f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 10, x, y, z))
                f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Zr", x, y, z))
                fr.write('%d \n' % ID)
            else:
                f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 9, x, y, z))
                f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Ti", x, y, z))

    for j in range(0, ny):
        for i in range(0, nx):
            # Ti
            x = 1/2 * ux + i * ux + DTix
            y = 1/6 * uy + j * uy + DTiy
            z = 5/6 * uz + k * uz + DTiz
            ID += 1
            if ID in R1:
                f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 10, x, y, z))
                f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Zr", x, y, z))
                fr.write('%d \n' % ID)
            else:
                f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 9, x, y, z))
                f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Ti", x, y, z))
        for i in range(0, nx):
            # Ti
            x = 0.0 * ux + i * ux + DTix
            y = 2/3 * uy + j * uy + DTiy
            z = 5/6 * uz + k * uz + DTiz
            ID += 1
            if ID in R1:
                f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 10, x, y, z))
                f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Zr", x, y, z))
                fr.write('%d \n' % ID)
            else:
                f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 9, x, y, z))
                f3.write('%s  %12.10f %12.10f %12.10f \n' % ("Ti", x, y, z))


for k in range(0, nz):
    for j in range(0, ny):
        for i in range(0, nx):
            #O1
            x = ux * 0.5 + i * ux
            y = uy * 0.0 + j * uy
            z = uz * 0.0 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 1/4 + i * ux
            y = uy * 1/4 + j * uy
            z = uz * 0.0 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 3/4 + i * ux
            y = uy * 1/4 + j * uy
            z = uz * 0.0 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 0.0 + i * ux
            y = uy * 0.5 + j * uy
            z = uz * 0.0 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 1/4 + i * ux
            y = uy * 3/4 + j * uy
            z = uz * 0.0 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 3/4 + i * ux
            y = uy * 3/4 + j * uy
            z = uz * 0.0 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            #O2
            x = ux * 0.0 + i * ux
            y = uy * 1/6 + j * uy
            z = uz * 1/3 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 1/4 + i * ux
            y = uy * 5/12 + j * uy
            z = uz * 1/3 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 3/4 + i * ux
            y = uy * 5/12 + j * uy
            z = uz * 1/3 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 1/2 + i * ux
            y = uy * 2/3 + j * uy
            z = uz * 1/3 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 1/4 + i * ux
            y = uy * 11/12 + j * uy
            z = uz * 1/3 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 3/4 + i * ux
            y = uy * 11/12 + j * uy
            z = uz * 1/3 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            #O3
            x = ux * 1/4 + i * ux
            y = uy * 1/12 + j * uy
            z = uz * 2/3 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 3/4 + i * ux
            y = uy * 1/12 + j * uy
            z = uz * 2/3 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 1/2 + i * ux
            y = uy * 1/3 + j * uy
            z = uz * 2/3 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 1/4 + i * ux
            y = uy * 7/12 + j * uy
            z = uz * 2/3 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 3/4 + i * ux
            y = uy * 7/12 + j * uy
            z = uz * 2/3 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))

            x = ux * 0.0 + i * ux
            y = uy * 5/6 + j * uy
            z = uz * 2/3 + k * uz
            ID += 1
            f2.write('%d %d %12.10f %12.10f %12.10f \n' % (ID, 15, x, y, z))
            f3.write('%s  %12.10f %12.10f %12.10f \n' % ("O", x, y, z))


f2.write("\n")
f3.write("\n")

f2.close()
f3.close()
fr.close()
print("ATOMS:", ID)