|
|
| """μ μ λ¨κ³ κ²μ¬.
|
|
|
| μ¬κΈ°μ 보λ κ²μ **νμκ³Ό μ격**λΏμ΄λ€. μ€μ μ±μ (μ κΈ°ννμ°½Β·λ¦¬ν¬ μ΄λ)μ μμ»€κ° νλ€.
|
| μ€νμ΄μ€λ MP λ°μ΄ν°λ GPU λ μμΌλ―λ‘, μ¬κΈ°μ λ¬Όμ±μ νμ νλ μ²νλ©΄ μ λλ€.
|
|
|
| κ±°μ μ μ°Έκ°μκ° **κ³ μΉ μ μλ κ²**μλ§ μ΄λ€. κ°μ μ»μ§ λͺ»ν νλͺ©μ κ±°μ μ΄ μλλΌ λ³΄λ₯λ‘ λλ€.
|
| """
|
| import re
|
|
|
|
|
| SUPPORTED = set("""
|
| H Li Be B C N O F Na Mg Al Si P S Cl K Ca Sc Ti V Cr Mn Fe Co Ni Cu Zn
|
| Ga Ge As Se Br Rb Sr Y Zr Nb Mo Tc Ru Rh Pd Ag Cd In Sn Sb Te I Cs Ba
|
| La Ce Pr Nd Pm Sm Eu Gd Tb Dy Ho Er Tm Yb Lu Hf Ta W Re Os Ir Pt Au Hg
|
| Tl Pb Bi Ac Th Pa U Np Pu
|
| """.split())
|
|
|
| _CIF_HINT = ("data_", "_cell_length_a", "_atom_site")
|
|
|
|
|
| def parse_formula(text):
|
| """ννμμ μ‘°μ±μΌλ‘. **κ΄νΈλ₯Ό λ°λμ μ²λ¦¬νλ€.**
|
|
|
| μ§μ μ κ·μμΌλ‘ νμΌλ©΄ `LiZr2(PO4)3` κ° P1O4 κ° λμ΄ μ‘°μ±μ΄ ν΅μ§Έλ‘ νλ¦°λ€.
|
| Materials Project μμ μ΄ LGPS λ₯Ό `Li10Ge(PS6)2` λ‘ μ μΌλ―λ‘ μ΄κ±΄ μμΈκ° μλλΌ κΈ°λ³Έμ΄λ€.
|
| """
|
| from pymatgen.core import Composition
|
| c = Composition(str(text).strip())
|
| return {str(k): float(v) for k, v in c.get_el_amt_dict().items()}
|
|
|
|
|
| def check(text, cif=None, require_elements=("Li",), max_atoms=60,
|
| supported=None, max_elements=6):
|
| """μ μ νμ . (ok, reason, info) λ₯Ό λλ €μ€λ€."""
|
| supported = supported or SUPPORTED
|
| raw = (text or "").strip()
|
| if not raw:
|
| return False, "ννμμ μ
λ ₯ν΄ μ£ΌμΈμ.", {}
|
| if len(raw) > 120:
|
| return False, "ννμμ΄ λ무 κΉλλ€.", {}
|
| if not re.match(r"^[A-Za-z0-9()\[\]\.\s]+$", raw):
|
| return False, "ννμμ μΈ μ μλ λ¬Έμκ° μμ΅λλ€.", {}
|
|
|
| try:
|
| comp = parse_formula(raw)
|
| except Exception:
|
| return False, "ννμμ ν΄μνμ§ λͺ»νμ΅λλ€. μ: Li3YCl6, LiZr2(PO4)3", {}
|
| if not comp:
|
| return False, "ννμμ ν΄μνμ§ λͺ»νμ΅λλ€.", {}
|
|
|
| for el in require_elements:
|
| if el not in comp:
|
| return False, "λ¦¬ν¬ μ ν΄μ§ μμ¦μ
λλ€. %s λ₯Ό ν¬ν¨ν΄μΌ ν©λλ€." % el, {}
|
|
|
| bad = sorted(e for e in comp if e not in supported)
|
| if bad:
|
| return False, ("κ³μ° κΈ°μ€ μνκ° μλ μμμ
λλ€: %s" % ", ".join(bad)), {}
|
|
|
| if len(comp) > max_elements:
|
| return False, "μμκ° %d μ’
μ λμ΅λλ€ (νμ¬ %d μ’
)." % (max_elements, len(comp)), {}
|
|
|
|
|
|
|
| from math import gcd
|
| from functools import reduce
|
| integral = all(abs(v - round(v)) < 1e-6 for v in comp.values())
|
| if integral:
|
| ints = {k: int(round(v)) for k, v in comp.items()}
|
| g = reduce(gcd, ints.values()) or 1
|
| reduced = {k: v // g for k, v in ints.items()}
|
| else:
|
| reduced = dict(comp)
|
| n_atom = sum(reduced.values())
|
| if n_atom > max_atoms:
|
| return False, ("κΈ°μ½ μ‘°μ±μ μμ μκ° %d κ°λ‘ μν %d λ₯Ό λμ΅λλ€."
|
| % (n_atom, max_atoms)), {}
|
|
|
| info = {"composition": comp, "reduced": reduced,
|
| "n_atoms": n_atom, "n_elements": len(comp)}
|
|
|
| if cif:
|
| c = str(cif)
|
| if len(c) > 400_000:
|
| return False, "ꡬ쑰 νμΌμ΄ λ무 ν½λλ€ (400KB μν).", {}
|
| if not any(h in c for h in _CIF_HINT):
|
| return False, "ꡬ쑰 νμΌμ΄ CIF νμμΌλ‘ 보μ΄μ§ μμ΅λλ€.", {}
|
| info["has_structure"] = True
|
|
|
| return True, "", info
|
|
|