slxrd.py ダウンロード/コピー
slxrd.py
slxrd.py
1"""
2X線回折シミュレーションスクリプト
3
4概要:
5 多層膜構造からのX線回折強度を計算し、CSVファイルに出力し、プロットします。
6 ブラッグの法則と複素ラウエ関数を用いて、異なるユニットセルが積層された構造の回折パターンをシミュレートします。
7
8関連リンク:
9 slxrd_usage
10"""
11
12import csv
13from pprint import pprint
14from math import sin, cos, asin, acos
15from cmath import sin as csin, cos as ccos, sqrt as csqrt, exp as cexp
16import numpy as np
17from matplotlib import pyplot as plt
18
19
20#=============================
21# 定数
22#=============================
23pi = 3.14159265358979323846
24pi2 = pi + pi
25pi2i = pi2 * 1j
26torad = 0.01745329251944 # rad/deg";
27todeg = 57.29577951472 # deg/rad";
28
29
30#=============================
31# 大域変数
32#=============================
33wl = 1.54 # angstrom
34outcsv = 'slxrd.csv'
35
36#=============================
37# 構造
38#=============================
39# 単位格子: c軸長、構造因子、繰り返し数
40cells = [
41 {'a': 4.0, 'F': 10.0, 'N': 5},
42 {'a': 4.1, 'F': 20.0, 'N': 5},
43 ]
44# 層構造: cellsの番号で指定
45#layers = [ 0 ]
46layers = [ 0, 1 ]
47#layers = [ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 ]
48#layers = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
49
50# 計算する2θ範囲、データ数
51range2Q = [5.0, 150.0]
52n2Q = 5001
53step2Q = (range2Q[1] - range2Q[0]) / (n2Q - 1)
54
55
56def cLaue(Q2, N, alatt, wl):
57 """
58 概要:
59 複素ラウエ関数を計算します。
60 詳細説明:
61 N個のユニットセルからなる単一周期構造の回折強度を記述するのに用いられるラウエ関数を複素数で計算します。
62 この関数は、周期構造からの回折の重ね合わせ効果を表現します。
63 引数:
64 :param Q2: 回折角度2θ(度)。
65 :type Q2: float
66 :param N: ユニットセルの繰り返し数。
67 :type N: int
68 :param alatt: ユニットセルの格子定数(Å)。
69 :type alatt: float
70 :param wl: X線の波長(Å)。
71 :type wl: float
72 戻り値:
73 :returns: 複素ラウエ関数の値。
74 :rtype: complex
75 """
76 delta = 2.0 * alatt * csin(Q2 / 2.0 * torad) / wl
77 return (1.0 - cexp(pi2i * delta * N)) / (1.0 - cexp(pi2i * delta))
78
79def diffQ(d, wl):
80 """
81 概要:
82 ブラッグの法則に基づき回折角度θを計算します。
83 詳細説明:
84 格子面間隔dとX線波長wlから、ブラッグの法則 (2d sinθ = nλ) を用いて、回折角度θを計算します。
85 sinθの値が物理的に許容範囲外の場合 (abs(sinθ) > 1.0) はNoneを返します。
86 引数:
87 :param d: 格子面間隔(Å)。
88 :type d: float
89 :param wl: X線の波長(Å)。
90 :type wl: float
91 戻り値:
92 :returns: 回折角度θ(度)。回折が生じない場合はNone。
93 :rtype: float or None
94 """
95 sinQ = wl / 2.0 / d
96 if abs(sinQ) > 1.0:
97 return None
98 Q = todeg * asin(sinQ)
99 return Q
100
101
102if __name__ == "__main__":
103# 構成単位格子の回折角度の計算
104 print("")
105 print("Diffraction angles from each unit cell")
106 for ic in range(len(cells)):
107 print("cell #{}: a={} F={} N={}"
108 .format(ic, cells[ic]['a'], cells[ic]['F'], cells[ic]['N']))
109 for l in range(1, 20):
110 d00l = cells[ic]['a'] / l
111 Q_00l = diffQ(d00l, wl)
112 if Q_00l is None:
113 break
114 Q2_00l = 2.0 * Q_00l
115 if range2Q[0] <= Q2_00l <= range2Q[1]:
116 sinQ = sin(torad * Q_00l)
117 LN = sin(pi * cells[ic]['N'] * cells[ic]['a'] * 2.0 * sinQ / wl)
118 L1 = sin(pi * 1 * cells[ic]['a'] * 2.0 * sinQ / wl)
119 LN2 = (LN * LN.conjugate()).real
120 L12 = (L1 * L1.conjugate()).real
121 I = LN2 / L12
122 print(" 2Q(00%2d)=%10.6g" % (l, Q2_00l),
123 " I = %8.4g = %8.4g / %8.4g" % (I, LN2, L12))
124
125# 繰り返し単位格子単位の回折角度の計算
126 print("")
127 print("Diffraction angles from each periodic unit cells unit")
128 for ic in range(len(cells)):
129 print("unit #{}: a={} F={} N={}"
130 .format(ic, cells[ic]['a'], cells[ic]['F'], cells[ic]['N']))
131 for n in range(1, 20):
132 sinQ = (n + 0.5) * wl / 2.0 / cells[ic]['N'] / cells[ic]['a']
133 if abs(sinQ) > 1.0:
134 break
135 Q2 = 2.0 * todeg * asin(sinQ)
136 LN = sin(pi * cells[ic]['N'] * cells[ic]['a'] * 2.0 * sinQ / wl)
137 L1 = sin(pi * 1 * cells[ic]['a'] * 2.0 * sinQ / wl)
138 LN2 = (LN * LN.conjugate()).real
139 L12 = (L1 * L1.conjugate()).real
140 I = LN2 / L12
141 if range2Q[0] <= Q2 <= range2Q[1]:
142 print(" 2Q(%2d)=%10.6g" % (n, Q2),
143 " I = %8.4g = %8.4g / %8.4g" % (I, LN2, L12))
144
145
146# 回折強度の計算
147 x = []
148 y = []
149 for i in range(n2Q):
150 Q2 = range2Q[0] + step2Q * i
151
152 t = 0.0
153 F = 0.0
154 for il in range(len(layers)):
155 cell = cells[layers[il]]
156 lf = cLaue(Q2, cell['N'], cell['a'], wl)
157 delta = 2.0 * t * sin(Q2 / 2.0 * torad) / wl
158 F += cells[ic]['F'] * lf * cexp(pi2i * delta)
159 t += cell['a'] * cell['N']
160
161 I = (F * F.conjugate()).real
162
163 x.append(Q2)
164 y.append(I)
165# print(i, ": ", Q2, lf2)
166
167
168# CSVファイルへ書き出し
169 print("")
170 print("Write to [{}]".format(outcsv))
171 try:
172 f = open(outcsv, 'w')
173 fout = csv.writer(f, lineterminator='\n')
174 fout.writerow(('2Q', 'Intensity'))
175 for i in range(0, len(x)):
176 fout.writerow((x[i], y[i]))
177 f.close()
178 except IOError:
179 print("Error: Can not write to [{}]".format(outcsv))
180
181
182# グラフプロット
183 plt.plot(x, y, linestyle = 'solid')
184 plt.xlabel('2Q')
185 plt.ylabel('Intensity')
186
187 plt.pause(0.001)
188 print("Press ENTER to exit")
189 input()