Download core/elements.py from tmepass000/matter-os: direct link, hf CLI and curl.
- Browser
- Download file 3.52 kB
-
https://huggingface.co/tmepass000/matter-os/resolve/main/core/elements.py
- Command line
-
hf download hf://tmepass000/matter-os/core/elements.py
-
curl -L -o elements.py https://huggingface.co/tmepass000/matter-os/resolve/main/core/elements.py
3.52 kB
| """Periodic-table / isotope registry with charge, spin, electron-count metadata (decision 42). | |
| Data source: ase.data (atomic numbers, standard atomic masses, covalent radii; ASE is LGPL-2.1+). | |
| Common oxidation states are a small curated table for screening only. Isotopes beyond the | |
| standard-mass entry are not tabulated here: requests for specific isotopes are recorded as | |
| metadata and flagged (`isotope_data: not_tabulated`) rather than given invented masses. | |
| """ | |
| from __future__ import annotations | |
| from dataclasses import dataclass, field | |
| from ase.data import atomic_masses, atomic_numbers, chemical_symbols, covalent_radii | |
| # Valence electrons (main-group counting; transition metals: group number up to 12) | |
| _MAIN_VALENCE = { | |
| "H": 1, "He": 2, "Li": 1, "Be": 2, "B": 3, "C": 4, "N": 5, "O": 6, "F": 7, "Ne": 8, | |
| "Na": 1, "Mg": 2, "Al": 3, "Si": 4, "P": 5, "S": 6, "Cl": 7, "Ar": 8, | |
| "K": 1, "Ca": 2, "Ga": 3, "Ge": 4, "As": 5, "Se": 6, "Br": 7, "Kr": 8, | |
| "Sc": 3, "Ti": 4, "V": 5, "Cr": 6, "Mn": 7, "Fe": 8, "Co": 9, "Ni": 10, "Cu": 11, "Zn": 12, | |
| "Ag": 11, "Au": 11, "Pd": 10, "Pt": 10, "Rb": 1, "Sr": 2, "In": 3, "Sn": 4, "Sb": 5, "Te": 6, "I": 7, "Xe": 8, | |
| } | |
| COMMON_OXIDATION_STATES = { | |
| "H": [-1, 1], "Li": [1], "Be": [2], "B": [3], "C": [-4, 2, 4], "N": [-3, 3, 5], "O": [-2], "F": [-1], | |
| "Na": [1], "Mg": [2], "Al": [3], "Si": [-4, 4], "P": [-3, 3, 5], "S": [-2, 2, 4, 6], "Cl": [-1, 1, 5, 7], | |
| "K": [1], "Ca": [2], "Ti": [2, 3, 4], "V": [2, 3, 4, 5], "Cr": [2, 3, 6], "Mn": [2, 3, 4, 7], | |
| "Fe": [2, 3], "Co": [2, 3], "Ni": [2], "Cu": [1, 2], "Zn": [2], "Ag": [1], "Au": [1, 3], "Pd": [2, 4], "Pt": [2, 4], | |
| } | |
| NOBLE_GASES = {"He", "Ne", "Ar", "Kr", "Xe", "Rn"} | |
| class ElementInfo: | |
| symbol: str | |
| Z: int | |
| mass_amu: float | |
| covalent_radius_ang: float | |
| valence_electrons: int | None | |
| common_oxidation_states: list[int] = field(default_factory=list) | |
| flags: list[str] = field(default_factory=list) | |
| def element(symbol: str) -> ElementInfo: | |
| if symbol not in atomic_numbers or symbol == "X": | |
| raise ValueError(f"unknown element symbol: {symbol}") | |
| z = atomic_numbers[symbol] | |
| flags = [] | |
| if z > 86: | |
| flags.append("heavy_element_relativistic_effects_not_handled_by_default_solvers") | |
| if z > 103: | |
| flags.append("superheavy_regime_unsupported") | |
| val = _MAIN_VALENCE.get(symbol) | |
| if val is None: | |
| flags.append("valence_count_not_tabulated") | |
| return ElementInfo( | |
| symbol=symbol, | |
| Z=z, | |
| mass_amu=float(atomic_masses[z]), | |
| covalent_radius_ang=float(covalent_radii[z]), | |
| valence_electrons=val, | |
| common_oxidation_states=list(COMMON_OXIDATION_STATES.get(symbol, [])), | |
| flags=flags, | |
| ) | |
| def all_symbols() -> list[str]: | |
| return [s for s in chemical_symbols[1:]] | |
| def electron_count(symbols: list[str], charge: int = 0) -> int: | |
| return sum(atomic_numbers[s] for s in symbols) - int(charge) | |
| def spin_parity_ok(n_electrons: int, multiplicity: int) -> bool: | |
| """2S+1 must have parity consistent with electron count: even N -> odd multiplicity.""" | |
| return (n_electrons % 2) == ((multiplicity - 1) % 2) | |
| def isotope_metadata(symbol: str, mass_number: int | None) -> dict: | |
| info = element(symbol) | |
| if mass_number is None: | |
| return {"symbol": symbol, "mass_amu": info.mass_amu, "isotope_data": "standard_atomic_weight"} | |
| return {"symbol": symbol, "mass_number": mass_number, "mass_amu": None, "isotope_data": "not_tabulated"} | |