crystal_distance.py ダウンロード/コピー

crystal_distance.py をダウンロード

crystal_distance.py
crystal_distance.py
  1import sys
  2import os
  3from numpy import sin, cos, tan, arcsin, arccos, arctan, exp, log, sqrt
  4import numpy as np
  5from numpy import linalg as la
  6from mpl_toolkits.mplot3d import Axes3D
  7import matplotlib.pyplot as plt
  8
  9from tkcrystalbase import *
 10
 11
 12"""
 13結晶中の原子間距離を計算するスクリプト。
 14
 15このスクリプトは、与えられた格子定数と原子サイト情報に基づき、結晶中の原子間距離を計算し、表示します。
 16実空間および逆空間の格子情報(格子ベクトル、メトリックテンソル、単位胞体積)も計算し、表示します。
 17計算された原子間距離は、指定された距離範囲内でソートされて出力されます。
 18
 19:doc:`crystal_distance_usage`
 20"""
 21
 22
 23# Lattice parameters (angstrom and degree)
 24#lattice_parameters = [ 5.62, 5.62, 5.62, 60.0, 60.0, 60.0]
 25lattice_parameters = [ 5.62, 5.62, 5.62, 90.0, 90.0, 90.0]
 26
 27# Site information (atom name, site label, atomic number, atomic mass, charge, radius, color, position)
 28sites = [
 29         ['Na', 'Na1', 11, 22.98997, +1.0, 0.7, 'red',  np.array([0.0, 0.0, 0.0])]
 30        ,['Na', 'Na2', 11, 22.98997, +1.0, 0.7, 'red',  np.array([0.0, 0.5, 0.5])]
 31        ,['Na', 'Na3', 11, 22.98997, +1.0, 0.7, 'red',  np.array([0.5, 0.0, 0.5])]
 32        ,['Na', 'Na4', 11, 22.98997, +1.0, 0.7, 'red',  np.array([0.5, 0.5, 0.0])]
 33        ,['Cl', 'Cl1', 17, 35.4527,  -1.0, 1.4, 'blue', np.array([0.5, 0.0, 0.0])]
 34        ,['Cl', 'Cl2', 17, 35.4527,  -1.0, 1.4, 'blue', np.array([0.5, 0.5, 0.5])]
 35        ,['Cl', 'Cl3', 17, 35.4527,  -1.0, 1.4, 'blue', np.array([0.0, 0.0, 0.5])]
 36        ,['Cl', 'Cl4', 17, 35.4527,  -1.0, 1.4, 'blue', np.array([0.0, 0.5, 0.0])]
 37        ]
 38
 39# Distance range
 40rmin = 0.1  # angstrom. used to judge identical site
 41rmax = 4.5  # angstrom.
 42
 43
 44def main():
 45    """
 46    結晶の格子情報と原子間距離を計算し、結果を出力するメイン関数。
 47
 48    この関数は、`lattice_parameters` と `sites` グローバル変数で定義された情報に基づき、
 49    以下の処理を実行します。
 50
 51    1. 実空間の格子ベクトル、メトリックテンソル、単位胞体積を計算し、標準出力に表示します。
 52    2. 逆空間の格子ベクトル、逆格子メトリックテンソル、逆格子単位胞体積を計算し、標準出力に表示します。
 53    3. `rmin` と `rmax` で指定された範囲内で、全ての原子ペア間の原子間距離を計算します。
 54       この際、周囲の単位胞(`nxmax`, `nymax`, `nzmax` の範囲)に存在する原子も考慮します。
 55    4. 計算された原子間距離を昇順にソートし、各距離と関連するサイト情報、単位胞のオフセットを標準出力に表示します。
 56    """
 57    print("")
 58    print("Lattice parameters:", lattice_parameters)
 59    aij = cal_lattice_vectors(lattice_parameters)
 60    print("Lattice vectors:")
 61    print("  ax: ({:10.4g}, {:10.4g}, {:10.4g}) A".format(aij[0][0], aij[0][1], aij[0][2]))
 62    print("  ay: ({:10.4g}, {:10.4g}, {:10.4g}) A".format(aij[1][0], aij[1][1], aij[1][2]))
 63    print("  az: ({:10.4g}, {:10.4g}, {:10.4g}) A".format(aij[2][0], aij[2][1], aij[2][2]))
 64    inf = cal_metrics(lattice_parameters)
 65    gij = inf['gij']
 66    print("Metric tensor:")
 67    print("  gij: ({:10.4g}, {:10.4g}, {:10.4g}) A".format(*gij[0]))
 68    print("       ({:10.4g}, {:10.4g}, {:10.4g}) A".format(*gij[1]))
 69    print("       ({:10.4g}, {:10.4g}, {:10.4g}) A".format(*gij[2]))
 70    print("")
 71    volume = cal_volume(aij)
 72    print("Volume: {:12.4g} A^3".format(volume))
 73
 74    print("")
 75    print("Unit cell volume: {:12.4g} A^3".format(volume))
 76    Raij  = cal_reciprocal_lattice_vectors(aij)
 77    Rlatt = cal_reciprocal_lattice_parameters(Raij)
 78    Rinf  = cal_metrics(Rlatt)
 79    Rgij  = Rinf['gij']
 80    print("Reciprocal lattice parameters:", Rlatt)
 81    print("Reciprocal lattice vectors:")
 82    print("  Rax: ({:10.4g}, {:10.4g}, {:10.4g}) A^-1".format(*Raij[0]))
 83    print("  Ray: ({:10.4g}, {:10.4g}, {:10.4g}) A^-1".format(*Raij[1]))
 84    print("  Raz: ({:10.4g}, {:10.4g}, {:10.4g}) A^-1".format(*Raij[2]))
 85    print("Reciprocal lattice metric tensor:")
 86    print("  Rgij: ({:10.4g}, {:10.4g}, {:10.4g}) A^-1".format(*Rgij[0]))
 87    print("        ({:10.4g}, {:10.4g}, {:10.4g}) A^-1".format(*Rgij[1]))
 88    print("        ({:10.4g}, {:10.4g}, {:10.4g}) A^-1".format(*Rgij[2]))
 89    Rvolume = cal_volume(Raij)
 90    print("Reciprocal unit cell volume: {:12.4g} A^-3".format(Rvolume))
 91
 92# Calculate the range of unit cells
 93    nxmax = int(rmax / lattice_parameters[0]) + 1
 94    nymax = int(rmax / lattice_parameters[1]) + 1
 95    nzmax = int(rmax / lattice_parameters[2]) + 1
 96    print("")
 97    print("nmax:", nxmax, nymax, nzmax)
 98
 99# Calculate interatomic distances and store them in rlist list variable
100    rlist = []
101    for isite0 in range(len(sites)):
102        site0 = sites[isite0]
103        name0, label0, z0, M0, q0, r0, color0, pos0 = site0
104        for isite1 in range(len(sites)):
105            site1 = sites[isite1]
106            name1, label1, z1, M1, q1, r1, color1, pos1 = site1
107            for iz in range(-nzmax, nzmax+1):
108             for iy in range(-nymax, nymax+1):
109              for ix in range(-nxmax, nxmax+1):
110                dis = distance(pos0, pos1 + np.array([ix, iy, iz]), gij)
111                if dis < rmin or rmax < dis:
112                    continue
113
114                rlist.append([dis, site0, site1, ix, iy, iz])
115
116#                print("  {:4} ({:8.4g}, {:8.4g}, {:8.4g}) - {:4} ({:8.4g}, {:8.4g}, {:8.4g}) + ({:2d}, {:2d}, {:2d}): dis = {:10.4g} A"
117#                    .format(label0, pos0[0], pos0[1], pos0[2], label1, pos1[0], pos1[1], pos1[2], ix, iy, iz, dis))
118
119# Sort rlist by distance (x[0] priority)
120    rlist.sort(key = lambda x: (x[0], x[1], x[3], x[4], x[5], x[2]))
121
122    print("")
123    print("Interatomic distances:")
124    for rinf in rlist:
125        dis, site0, site1, ix, iy, iz = rinf
126        name0, label0, z0, M0, q0, r0, color0, pos0 = site0
127        name1, label1, z1, M1, q1, r1, color1, pos1 = site1
128        print("  {:4} ({:8.4g}, {:8.4g}, {:8.4g}) - {:4} ({:8.4g}, {:8.4g}, {:8.4g}) + ({:2d}, {:2d}, {:2d}): dis = {:10.4g} A"
129            .format(label0, pos0[0], pos0[1], pos0[2], label1, pos1[0], pos1[1], pos1[2], ix, iy, iz, dis))
130
131    print("")
132    exit()
133
134
135if __name__ == '__main__':
136    main()