Skip to content

Commit

Permalink
Fix Ion formula parsing bug; add more special formulas (#3942)
Browse files Browse the repository at this point in the history
* fix Ion parsing bug introduced by commit
b4a70ee

* Ion: special handling of CH4, NH4, N3-, SCN-, formate, oxalate

* pre-commit auto-fixes

* Element / Species - add n_electrons

* Revert "Element / Species - add n_electrons"

This reverts commit 97ea180.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
rkingsbury and pre-commit-ci[bot] authored Jul 31, 2024
1 parent 720fdf8 commit 660ba7a
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 3 deletions.
35 changes: 33 additions & 2 deletions src/pymatgen/core/ion.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,10 @@ def get_reduced_formula_and_factor(
el_amt_dict = {k: int(round(v)) for k, v in comp.get_el_amt_dict().items()}
formula, factor = reduce_formula(el_amt_dict, iupac_ordering=iupac_ordering)

if (self.composition.get("H") and self.composition.get("O")) is not None:
# This line checks specifically that the contains an equal amount of O and H. When that is the case,
# they should be displayed as "OH" rather than "HO".
if self.composition.get("H") == self.composition.get("O"):
formula = formula.replace("HO", "OH")

if nH2O > 0:
formula += f".{nH2O}H2O"

Expand All @@ -187,6 +188,13 @@ def get_reduced_formula_and_factor(
elif formula == "H2CO":
formula = "CH3COOH"
factor /= 2
# phosphoric acid system
elif formula == "PH3O4":
formula = "H3PO4"
elif formula == "PHO4":
formula = "HPO4"
elif formula == "P(HO2)2":
formula = "H2PO4"
# acetate
elif formula == "H3(CO)2":
formula = "CH3COO"
Expand All @@ -205,6 +213,29 @@ def get_reduced_formula_and_factor(
elif formula == "O" and factor % 3 == 0:
formula = "O3"
factor /= 3
# ammonia
elif formula == "H4N":
formula = "NH4"
elif formula == "H3N":
formula = "NH3"
# methane
elif formula == "H4C":
formula = "CH4"
# thiocyanate
elif formula == "CSN":
formula = "SCN"
# triiodide, nitride, an phosphide
elif formula in ["I", "N", "P"] and self.charge == -1:
formula += "3"
factor /= 3
# formate # codespell:ignore
elif formula == "HCOO":
formula = "HCO2"
# oxalate
elif formula == "CO2":
formula = "C2O4"
factor *= 2
# diatomic gases
elif formula in {"O", "N", "F", "Cl", "H"} and factor % 2 == 0:
formula += "2"
factor /= 2
Expand Down
9 changes: 8 additions & 1 deletion tests/core/test_ion.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def test_charge_from_formula(self):
assert Ion.from_formula("SO42-").charge == -1
assert Ion.from_formula("SO4--").charge == -2
assert Ion.from_formula("SO4[--]").charge == -2
assert Ion.from_formula("N3-").charge == -1

assert Ion.from_formula("Na[+-+]").charge == 1

Expand All @@ -59,19 +60,25 @@ def test_special_formulas(self):
("O3", "O3(aq)"),
("O2", "O2(aq)"),
("N2", "N2(aq)"),
("NaOH", "NaOH(aq)"),
("H4O4", "H2O2(aq)"),
("OH-", "OH[-1]"),
("H2PO4-", "H2PO4[-1]"),
("CH3COO-", "CH3COO[-1]"),
("CH3COOH", "CH3COOH(aq)"),
("CH3OH", "CH3OH(aq)"),
("H4CO", "CH3OH(aq)"),
("CH4", "CH4(aq)"),
("NH4+", "NH4[+1]"),
("NH3", "NH3(aq)"),
("N3-", "N3[-1]"),
("HCOO-", "HCO2[-1]"),
("C2H6O", "C2H5OH(aq)"),
("C3H8O", "C3H7OH(aq)"),
("C4H10O", "C4H9OH(aq)"),
("Fe(OH)4+", "Fe(OH)4[+1]"),
("Zr(OH)4", "Zr(OH)4(aq)"),
]

for tup in special_formulas:
assert Ion.from_formula(tup[0]).reduced_formula == tup[1]

Expand Down

0 comments on commit 660ba7a

Please sign in to comment.