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

crystal_draw_cell.py をダウンロード

crystal_draw_cell.py
crystal_draw_cell.py
  1"""
  2概要: 単位格子と逆格子単位格子を描画するスクリプト。
  3詳細説明:
  4    本スクリプトは、指定された格子定数と原子サイト情報に基づいて、実空間および逆空間の単位格子と原子配置を3Dで描画します。
  5    格子定数から格子ベクトル、計量テンソル、単位格子の体積を計算し、その結果も表示します。
  6    逆格子についても同様の計算を行い、結果を表示します。
  7    生成された原子サイトは、指定された描画範囲に基づいて重複を避けながらリストに追加されます。
  8    最終的に、matplotlibを用いて実空間の単位格子、逆空間の単位格子、および原子配置を3Dプロットとして可視化し、表示します。
  9関連リンク: :doc:`crystal_draw_cell_usage`
 10"""
 11
 12import sys
 13import os
 14import copy
 15from numpy import sin, cos, tan, arcsin, arccos, arctan, exp, log, sqrt
 16import numpy as np
 17from numpy import linalg as la
 18
 19from tkcrystalbase import *
 20
 21
 22# Lattice parameters (angstrom and degree)
 23lattice_parameters = [ 5.62, 5.62, 5.62, 60.0, 60.0, 60.0]
 24#lattice_parameters = [ 5.62, 5.62, 5.62, 90.0, 90.0, 90.0]
 25
 26# Site information (atom name, site label, atomic number, atomic mass, charge, radius, color, position)
 27sites = [
 28         ['Na', 'Na1', 11, 22.98997, +1.0, 0.7, 'red',  np.array([0.0, 0.0, 0.0])]
 29        ,['Na', 'Na2', 11, 22.98997, +1.0, 0.7, 'red',  np.array([0.0, 0.5, 0.5])]
 30        ,['Na', 'Na3', 11, 22.98997, +1.0, 0.7, 'red',  np.array([0.5, 0.0, 0.5])]
 31        ,['Na', 'Na4', 11, 22.98997, +1.0, 0.7, 'red',  np.array([0.5, 0.5, 0.0])]
 32        ,['Cl', 'Cl1', 17, 35.4527,  -1.0, 1.4, 'blue', np.array([0.5, 0.0, 0.0])]
 33        ,['Cl', 'Cl2', 17, 35.4527,  -1.0, 1.4, 'blue', np.array([0.5, 0.5, 0.5])]
 34        ,['Cl', 'Cl3', 17, 35.4527,  -1.0, 1.4, 'blue', np.array([0.0, 0.0, 0.5])]
 35        ,['Cl', 'Cl4', 17, 35.4527,  -1.0, 1.4, 'blue', np.array([0.0, 0.5, 0.0])]
 36        ]
 37
 38# Coefficient for atomic size to plot
 39kr = 100.0
 40
 41# Distance to judge identical atom site, in angstrom
 42rmin = 0.1
 43
 44# Coefficient to plot reciprocal unit cell w.r.t. real space unit cell
 45kRUC = 0.8
 46
 47# Range of unit cells to draw crystal structure
 48nrange = [[-0.1, 1.1], [-0.1, 1.1], [-0.1, 1.1]]
 49
 50# Figure configuration
 51figsize = (12, 12)
 52
 53
 54def main():
 55    """
 56    概要: 結晶の単位格子と逆格子単位格子を計算し、3Dプロットで表示する。
 57    詳細説明:
 58        本関数は、グローバル変数 `lattice_parameters` と `sites` で定義された結晶情報を使用します。
 59        1. 格子定数から格子ベクトル、計量テンソル、単位格子の体積を計算し、コンソールに表示します。
 60        2. 逆格子についても同様の計算(逆格子ベクトル、逆格子定数、逆格子計量テンソル、逆格子単位格子の体積)を行い、コンソールに表示します。
 61        3. グローバル変数 `nrange` で指定された範囲に基づいて、結晶内のすべての原子サイトを生成し、重複を避けて `allsites` リストに格納します。
 62        4. matplotlibを用いて、実空間の単位格子、逆空間の単位格子、および原子配置を3Dで描画します。
 63        5. プロットのアスペクト比を調整し、表示します。
 64    引数: なし
 65    戻り値: なし
 66    """
 67    print("")
 68    print("Lattice parameters:", lattice_parameters)
 69    aij = cal_lattice_vectors(lattice_parameters)
 70    print("Lattice vectors:")
 71    print("  ax: ({:10.4g}, {:10.4g}, {:10.4g}) A".format(aij[0][0], aij[0][1], aij[0][2]))
 72    print("  ay: ({:10.4g}, {:10.4g}, {:10.4g}) A".format(aij[1][0], aij[1][1], aij[1][2]))
 73    print("  az: ({:10.4g}, {:10.4g}, {:10.4g}) A".format(aij[2][0], aij[2][1], aij[2][2]))
 74    inf = cal_metrics(lattice_parameters)
 75    gij = inf['gij']
 76    print("Metric tensor:")
 77    print("  gij: ({:10.4g}, {:10.4g}, {:10.4g}) A".format(*gij[0]))
 78    print("       ({:10.4g}, {:10.4g}, {:10.4g}) A".format(*gij[1]))
 79    print("       ({:10.4g}, {:10.4g}, {:10.4g}) A".format(*gij[2]))
 80    volume = cal_volume(aij)
 81    print("Volume: {:12.4g} A^3".format(volume))
 82
 83    print("")
 84    print("Unit cell volume: {:12.4g} A^3".format(volume))
 85    Raij  = cal_reciprocal_lattice_vectors(aij)
 86    Rlatt = cal_reciprocal_lattice_parameters(Raij)
 87    Rinf  = cal_metrics(Rlatt)
 88    Rgij  = Rinf['gij']
 89    print("Reciprocal lattice parameters:", Rlatt)
 90    print("Reciprocal lattice vectors:")
 91    print("  Rax: ({:10.4g}, {:10.4g}, {:10.4g}) A^-1".format(*Raij[0]))
 92    print("  Ray: ({:10.4g}, {:10.4g}, {:10.4g}) A^-1".format(*Raij[1]))
 93    print("  Raz: ({:10.4g}, {:10.4g}, {:10.4g}) A^-1".format(*Raij[2]))
 94    print("Reciprocal lattice metric tensor:")
 95    print("  Rgij: ({:10.4g}, {:10.4g}, {:10.4g}) A^-1".format(*Rgij[0]))
 96    print("        ({:10.4g}, {:10.4g}, {:10.4g}) A^-1".format(*Rgij[1]))
 97    print("        ({:10.4g}, {:10.4g}, {:10.4g}) A^-1".format(*Rgij[2]))
 98    Rvolume = cal_volume(Raij)
 99    print("Reciprocal unit cell volume: {:12.4g} A^-3".format(Rvolume))
100
101    allsites = []
102    for site in sites:
103        name, label, z, M, q, r, color, pos = copy.deepcopy(site)
104        pos01 = [reduce01(pos[0]), reduce01(pos[1]), reduce01(pos[2])]
105        for iz in range(int(nrange[2][0]) - 1, int(nrange[2][1]) + 1):
106         for iy in range(int(nrange[1][0]) - 1, int(nrange[1][1]) + 1):
107          for ix in range(int(nrange[0][0]) - 1, int(nrange[0][1]) + 1):
108            posn = [pos01[0] + ix, pos01[1] + iy, pos01[2] + iz]
109            if -0.1 <= posn[0] <= 1.1 and -0.1 <= posn[1] <= 1.1 and -0.1 <= posn[2] <= 1.1:
110                add_site(allsites, [name, label, z, M, q, r, color, posn], gij, rmin)
111
112    print("")
113    print("All sites to draw:")
114    for s in allsites:
115        print("  {:4}: {:4}: ({:8.3g}, {:8.3g}, {:8.3g}) Z={:6.3g}".format(s[0], s[1], s[7][0], s[7][1], s[7][2], s[4]))
116
117
118    fig = plt.figure(figsize = figsize)
119    ax = fig.add_subplot(111, projection='3d')
120
121# Real space unit cell
122    draw_unitcell(ax, allsites,  aij,  nrange, kr, linecolor = 'black')
123
124# Reciprocal space unit cell
125    k = max([*aij[0], *aij[1], *aij[2]]) / max([*Raij[0], *Raij[1], *Raij[2]]) * kRUC
126    kRaij = np.empty([3, 3])
127    for i in range(3):
128        for j in range(3):
129            kRaij[i][j] = k * Raij[i][j]
130    draw_unitcell(ax, None, kRaij, nrange, linecolor = 'red')
131
132# Note: set_aspect() is not implemented for 3D plots
133#    ax.set_aspect('equal','box')
134    xlim =ax.get_xlim()
135    ylim =ax.get_ylim()
136    zlim =ax.get_zlim()
137    lim = [min([xlim[0], ylim[0], zlim[0]]), max([xlim[1], ylim[1], zlim[1]])]
138    ax.set_xlim(lim)
139    ax.set_ylim(lim)
140    ax.set_zlim(lim)
141#    ax.set_xticks(np.linspace(*lim, 0))
142#    ax.set_yticks(np.linspace(*lim, 0))
143#    ax.set_zticks(np.linspace(*lim, 0))
144
145    plt.show()
146
147    print("")
148    exit()
149
150
151if __name__ == '__main__':
152    main()