from typing import List, Dict, Tuple def add_li_y_antisite_average( x: float, # Y 位点:[(label, wyckoff, (fx,fy,fz), occ, multiplicity)] y_sites: List[Tuple[str, str, Tuple[float, float, float], float, int]] = None, # Li 位点:[(label, wyckoff, (fx,fy,fz), occ, multiplicity)] li_sites: List[Tuple[str, str, Tuple[float, float, float], float, int]] = None, # 可选:各位点的 B 因子(字典),不需要可留空 b_iso: Dict[str, float] = None, # 保留小数位 ndigits: int = 4 ) -> str: """ 把结构改写成含 x (相对于 Y 总数) 的 Li/Y 反位缺陷的“平均占据”CIF 块。 返回字符串,可直接粘贴到 CIF 的 atom_site loop 中。 """ # 默认使用表 S9(P-3̅m1)的坐标与占据;multiplicity 依据该空间群 if y_sites is None: y_sites = [ ("Y1", "1a", (0.0000, 0.0000, 0.0000), 1.0000, 1), ("Y2", "2d", (0.3333, 0.6666, 0.4880), 0.8269, 2), ("Y3", "2d", (0.3333, 0.6666,-0.0650), 0.1730, 2), ] if li_sites is None: li_sites = [ ("Li1", "6g", (0.3397, 0.3397, 0.0000), 1.0000, 6), ("Li2", "6h", (0.3397, 0.3397, 0.5000), 0.5000, 6), ] if b_iso is None: # 可按需要改 b_iso = {"Y": 1.10, "Li": 5.00, "Cl": 1.99} # 1) 总 Y 与总 Li(每原胞的“原子数贡献”): y_total = sum(m * occ for _,_,_,occ,m in y_sites) # 期望为 3 li_total = sum(m * occ for _,_,_,occ,m in li_sites) # 期望为 9 # 2) 需要交换的“Y 数量”(相对于每原胞) y_exchanged = x * y_total # 例如 x=0.0556 → ~0.1668 个 Y/原胞 # 3) 折算到 Li 子格的分配比例(保证电中性和计量) li_fraction = y_exchanged / li_total # 每个 Li 位点应引入的 Y 的比例 # 4) 生成 CIF loop 文本(同一坐标写两行,分别为主元素与反位元素) lines = [] header = [ "loop_", " _atom_site_label", " _atom_site_type_symbol", " _atom_site_fract_x", " _atom_site_fract_y", " _atom_site_fract_z", " _atom_site_occupancy", " _atom_site_B_iso_or_equiv", ] lines.extend(header) # 4a) 处理 Y 位点:Y → (1-x)*occ;Li_on_Y → x*occ for label, wyck, (fx,fy,fz), occ, mult in y_sites: y_main_occ = round(occ * (1.0 - x), ndigits) li_on_y_occ = round(occ * x, ndigits) lines.append(f" {label}_main Y {fx:.4f} {fy:.4f} {fz:.4f} {y_main_occ:.{ndigits}f} {b_iso.get('Y',1.0)}") lines.append(f" Li_on_{label} Li {fx:.4f} {fy:.4f} {fz:.4f} {li_on_y_occ:.{ndigits}f} {b_iso.get('Li',5.0)}") # 4b) 处理 Li 位点:Li → (1-li_fraction)*occ;Y_on_Li → li_fraction*occ for label, wyck, (fx,fy,fz), occ, mult in li_sites: li_main_occ = round(occ * (1.0 - li_fraction), ndigits) y_on_li_occ = round(occ * li_fraction, ndigits) lines.append(f" {label}_main Li {fx:.4f} {fy:.4f} {fz:.4f} {li_main_occ:.{ndigits}f} {b_iso.get('Li',5.0)}") lines.append(f" Y_on_{label} Y {fx:.4f} {fy:.4f} {fz:.4f} {y_on_li_occ:.{ndigits}f} {b_iso.get('Y',1.0)}") return "\n".join(lines) # === 示例 === # x=0.0556(与论文使用的 5.56% 一致,定义为相对于 Y 总数的比例): print(add_li_y_antisite_average(0.0556))