atominf_xrayutilities.py ダウンロード/コピー
atominf_xrayutilities.py をダウンロード
atominf_xrayutilities.py
atominf_xrayutilities.py
1"""
2X線反射率測定 (XRR) シミュレーションを行うためのスクリプト。
3
4xrayutilities と pymatgen を使用して多層膜サンプルのXRRプロファイルを計算し、プロットします。
5CIFファイルからの構造読み込みにも対応しています。
6
7:doc:`atominf_xrayutilities_usage`
8"""
9# pip install xrayutilities pymatgen matplotlib numpy
10
11import os
12import numpy as np
13import matplotlib.pyplot as plt
14import xrayutilities as xu
15from pymatgen.core import Composition, Structure
16
17
18# ====== 単位変換 ======
19def gcm3_to_kgm3(rho):
20 """
21 密度をg/cm³からkg/m³に変換します。
22
23 :param rho: 密度 (g/cm³)。
24 :type rho: float or int
25 :returns: 密度 (kg/m³)。
26 :rtype: float
27 """
28 return float(rho) * 1000.0
29
30
31def nm_to_A(t_nm):
32 """
33 厚さをナノメートル(nm)からオングストローム(A)に変換します。
34
35 :param t_nm: 厚さ (nm)。
36 :type t_nm: float or int
37 :returns: 厚さ (A)。
38 :rtype: float
39 """
40 return float(t_nm) * 10.0
41
42
43def is_cif_path(s):
44 """
45 与えられた文字列がCIFファイルのパスであるかを判定します。
46
47 文字列が `str` 型であり、`.cif` で終わる場合にTrueを返します(大文字・小文字を区別しない)。
48
49 :param s: 判定する文字列。
50 :type s: str
51 :returns: CIFファイルパスであればTrue、そうでなければFalse。
52 :rtype: bool
53 """
54 return isinstance(s, str) and s.lower().endswith(".cif")
55
56
57def load_from_cif(path):
58 """
59 指定されたCIFファイルから構造、化学式、密度を読み込みます。
60
61 `pymatgen` を使用してCIFファイルを解析し、`Structure`オブジェクト、
62 還元化学式、および密度 (g/cm³) を抽出します。
63
64 :param path: CIFファイルへのパス。
65 :type path: str
66 :returns:
67 - `structure` (`pymatgen.core.Structure`): 読み込まれた結晶構造オブジェクト。
68 - `formula` (str): 構造の還元化学式。
69 - `density` (float): 構造の密度 (g/cm³)。
70 :rtype: tuple[pymatgen.core.Structure, str, float]
71 """
72 structure = Structure.from_file(path)
73 formula = structure.composition.reduced_formula
74 density = float(structure.density)
75 return structure, formula, density
76
77
78def main():
79 """
80 多層膜のXRRシミュレーションを実行し、結果をプロットします。
81
82 層構造と基板の情報を定義し、それらから `xrayutilities` の `LayerStack` オブジェクトを構築します。
83 その後、XRRモデルを使用して反射率プロファイルを計算し、`matplotlib` で表示します。
84 CIFファイルからの層情報の読み込みもサポートしています。
85 """
86
87 # ====== 層構造 ======
88 layer_stack = [
89 {"composition": "TiO2", "density_gcm3": 4.23, "thickness_nm": 50.0, "roughness_A": 0.5},
90 {"composition": "Al2O3", "density_gcm3": 3.95, "thickness_nm": 30.0, "roughness_A": 0.5},
91 {"composition": "SiO2", "density_gcm3": 2.20, "thickness_nm": 100.0, "roughness_A": 0.5},
92 # {"composition": "sample.cif", "density_gcm3": 0.0, "thickness_nm": 10.0, "roughness_A": 0.5},
93 ]
94
95 substrate = {"composition": "Si", "density_gcm3": 2.33, "roughness_A": 0.5}
96
97 # ====== 表示:分子量 ======
98 print("各層の化学組成と分子量:")
99 for layer in layer_stack:
100 comp = layer["composition"]
101 if is_cif_path(comp):
102 _, formula, _ = load_from_cif(comp)
103 mw = Composition(formula).weight
104 print(f" {os.path.basename(comp)} ({formula}): {mw:.3f} g/mol")
105 else:
106 mw = Composition(comp).weight
107 print(f" {comp}: {mw:.3f} g/mol")
108
109 # ====== 基板 ======
110 sub_mat = xu.materials.Amorphous(substrate["composition"], gcm3_to_kgm3(substrate["density_gcm3"]))
111 stack = xu.simpack.Layer(sub_mat, float("inf"), roughness=substrate["roughness_A"])
112
113 # ====== 薄膜層 ======
114 for layer in layer_stack:
115 comp = layer["composition"]
116 rho = float(layer["density_gcm3"])
117
118 if is_cif_path(comp):
119 _, formula, rho_cif = load_from_cif(comp)
120 if rho <= 0.0:
121 rho = rho_cif
122 comp = formula
123
124 mat = xu.materials.Amorphous(comp, gcm3_to_kgm3(rho))
125 lay = xu.simpack.Layer(mat, nm_to_A(layer["thickness_nm"]), roughness=layer["roughness_A"])
126 stack = stack + lay
127
128 sample = xu.simpack.LayerStack("sample", stack)
129
130 # ====== XRR ======
131 model = xu.simpack.SpecularReflectivityModel(sample, energy="CuKa1")
132 alphai = np.linspace(0.05, 2.5, 2000)
133 R = model.simulate(alphai)
134
135 two_theta = 2 * alphai
136
137 plt.figure(figsize=(8, 5))
138 plt.semilogy(two_theta, R)
139 plt.xlabel("2θ (deg)")
140 plt.ylabel("Reflectivity")
141 plt.title("Multilayer XRR Simulation")
142 plt.grid(True, which="both")
143 plt.tight_layout()
144 plt.show()
145
146
147if __name__ == "__main__":
148 main()