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()