zcbot/skills/pymatgen/materials.py

154 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
pymatgen skill helpers — 建材院无机材料场景常用映射 + MPRester 封装。
LLM 通过 `from skills.pymatgen.materials import CEMENT_PHASES, mp_rester` 使用。
"""
from __future__ import annotations
import os
from contextlib import contextmanager
# 中文/简写 → 化学式映射。覆盖建材院 R&D 高频物相。
# 添加新条目时:
# - key 用用户最自然的称呼(中文 / 行业简写),value 是 mp 能识别的化学式
# - 同一物相多种叫法都加 key,指向同一化学式(C3S / 硅酸三钙 / 阿利特 都是 Ca3SiO5)
CEMENT_PHASES: dict[str, str] = {
# ---- 硅酸盐水泥熟料矿物 ----
"C3S": "Ca3SiO5",
"硅酸三钙": "Ca3SiO5",
"阿利特": "Ca3SiO5",
"alite": "Ca3SiO5",
"C2S": "Ca2SiO4",
"硅酸二钙": "Ca2SiO4",
"贝利特": "Ca2SiO4",
"belite": "Ca2SiO4",
"C3A": "Ca3Al2O6",
"铝酸三钙": "Ca3Al2O6",
"C4AF": "Ca4Al2Fe2O10",
"铁铝酸四钙": "Ca4Al2Fe2O10",
"铁相": "Ca4Al2Fe2O10",
# ---- 水化产物 ----
"C-S-H": "Ca1.5SiO3.5·xH2O",
"水化硅酸钙": "Ca1.5SiO3.5·xH2O",
"CH": "Ca(OH)2",
"氢氧化钙": "Ca(OH)2",
"portlandite": "Ca(OH)2",
"钙矾石": "Ca6Al2(SO4)3(OH)12·26H2O",
"AFt": "Ca6Al2(SO4)3(OH)12·26H2O",
"ettringite": "Ca6Al2(SO4)3(OH)12·26H2O",
"AFm": "Ca4Al2(OH)12(SO4)·6H2O",
"单硫型水化硫铝酸钙": "Ca4Al2(OH)12(SO4)·6H2O",
# ---- 石膏 / 硫酸盐 ----
"石膏": "CaSO4·2H2O",
"二水石膏": "CaSO4·2H2O",
"gypsum": "CaSO4·2H2O",
"半水石膏": "CaSO4·0.5H2O",
"硬石膏": "CaSO4",
"anhydrite": "CaSO4",
# ---- 碳酸盐 / 碳化产物 ----
"方解石": "CaCO3",
"calcite": "CaCO3",
"文石": "CaCO3",
"aragonite": "CaCO3",
# ---- 陶瓷 / 耐火常见相 ----
"莫来石": "Al6Si2O13",
"mullite": "Al6Si2O13",
"堇青石": "Mg2Al4Si5O18",
"cordierite": "Mg2Al4Si5O18",
"刚玉": "Al2O3",
"α-Al2O3": "Al2O3",
"corundum": "Al2O3",
"方镁石": "MgO",
"periclase": "MgO",
"尖晶石": "MgAl2O4",
"spinel": "MgAl2O4",
"锆英石": "ZrSiO4",
"zircon": "ZrSiO4",
"石英": "SiO2",
"quartz": "SiO2",
"方石英": "SiO2",
"cristobalite": "SiO2",
"鳞石英": "SiO2",
"tridymite": "SiO2",
# ---- 玻璃常见组分晶相 ----
"钙长石": "CaAl2Si2O8",
"anorthite": "CaAl2Si2O8",
"钠长石": "NaAlSi3O8",
"albite": "NaAlSi3O8",
"硅灰石": "CaSiO3",
"wollastonite": "CaSiO3",
"透辉石": "CaMgSi2O6",
"diopside": "CaMgSi2O6",
# ---- 其他常见 ----
"白云石": "CaMg(CO3)2",
"dolomite": "CaMg(CO3)2",
"赤铁矿": "Fe2O3",
"hematite": "Fe2O3",
"磁铁矿": "Fe3O4",
"magnetite": "Fe3O4",
}
def lookup_phase(name: str) -> str:
"""中文/简写相名 → 化学式。命中返回化学式,未命中抛 KeyError(带建议)。"""
if name in CEMENT_PHASES:
return CEMENT_PHASES[name]
# 大小写不敏感再查一遍
lower = name.lower()
for k, v in CEMENT_PHASES.items():
if k.lower() == lower:
return v
raise KeyError(
f"{name!r} 不在 CEMENT_PHASES 映射表里。"
f"若是新相,直接把化学式喂给 pymatgen / Materials Project;"
f"若高频用,补到 skills/pymatgen/materials.py 的 CEMENT_PHASES。"
)
@contextmanager
def mp_rester(api_key: str | None = None):
"""
MPRester 上下文管理器封装,自动从 env(MP_API_KEY)拿 key。
用法:
with mp_rester() as mpr:
docs = mpr.materials.summary.search(formula="Ca3SiO5")
Args:
api_key: 显式传入则用,否则读 env MP_API_KEY。
Raises:
RuntimeError: env 未配置且未传入 api_key。
"""
key = api_key or os.environ.get("MP_API_KEY")
if not key:
raise RuntimeError(
"MP_API_KEY not set in env. "
"申请: https://materialsproject.org/api,然后写到项目根 .env 文件。"
)
from mp_api.client import MPRester # 局部 import,避免装包前 import skill 就崩
with MPRester(api_key=key) as mpr:
yield mpr