Coverage for /builds/ase/ase/ase/phasediagram.py: 68.38%
370 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
1# fmt: off
3import fractions
4import functools
5import re
6from collections import OrderedDict
7from typing import Dict, List, Tuple
9import numpy as np
10from scipy.spatial import ConvexHull
12import ase.units as units
13from ase.formula import Formula
14from ase.utils import deprecated
16_solvated: List[Tuple[str, Dict[str, int], float, bool, float]] = []
19def parse_formula(formula):
20 aq = formula.endswith('(aq)')
21 if aq:
22 formula = formula[:-4]
23 charge = formula.count('+') - formula.count('-')
24 if charge:
25 formula = formula.rstrip('+-')
26 count = Formula(formula).count()
27 return count, charge, aq
30def float2str(x):
31 f = fractions.Fraction(x).limit_denominator(100)
32 n = f.numerator
33 d = f.denominator
34 if abs(n / d - f) > 1e-6:
35 return f'{f:.3f}'
36 if d == 0:
37 return '0'
38 if f.denominator == 1:
39 return str(n)
40 return f'{f.numerator}/{f.denominator}'
43def solvated(symbols):
44 """Extract solvation energies from database.
46 symbols: str
47 Extract only those molecules that contain the chemical elements
48 given by the symbols string (plus water and H+).
50 Data from:
52 Johnson JW, Oelkers EH, Helgeson HC (1992)
53 Comput Geosci 18(7):899.
54 doi:10.1016/0098-3004(92)90029-Q
56 and:
58 Pourbaix M (1966)
59 Atlas of electrochemical equilibria in aqueous solutions.
60 No. v. 1 in Atlas of Electrochemical Equilibria in Aqueous Solutions.
61 Pergamon Press, New York.
63 Returns list of (name, energy) tuples.
64 """
66 if isinstance(symbols, str):
67 symbols = Formula(symbols).count().keys()
68 if len(_solvated) == 0:
69 for line in _aqueous.splitlines():
70 energy, formula = line.split(',')
71 name = formula + '(aq)'
72 count, charge, aq = parse_formula(name)
73 energy = float(energy) * 0.001 * units.kcal / units.mol
74 _solvated.append((name, count, charge, aq, energy))
75 references = []
76 for name, count, charge, aq, energy in _solvated:
77 for symbol in count:
78 if symbol not in 'HO' and symbol not in symbols:
79 break
80 else:
81 references.append((name, energy))
82 return references
85def bisect(A, X, Y, f):
86 a = []
87 for i in [0, -1]:
88 for j in [0, -1]:
89 if A[i, j] == -1:
90 A[i, j] = f(X[i], Y[j])
91 a.append(A[i, j])
93 if np.ptp(a) == 0:
94 A[:] = a[0]
95 return
96 if a[0] == a[1]:
97 A[0] = a[0]
98 if a[1] == a[3]:
99 A[:, -1] = a[1]
100 if a[3] == a[2]:
101 A[-1] = a[3]
102 if a[2] == a[0]:
103 A[:, 0] = a[2]
104 if not (A == -1).any():
105 return
106 i = len(X) // 2
107 j = len(Y) // 2
108 bisect(A[:i + 1, :j + 1], X[:i + 1], Y[:j + 1], f)
109 bisect(A[:i + 1, j:], X[:i + 1], Y[j:], f)
110 bisect(A[i:, :j + 1], X[i:], Y[:j + 1], f)
111 bisect(A[i:, j:], X[i:], Y[j:], f)
114def print_results(results):
115 total_energy = 0.0
116 print('reference coefficient energy')
117 print('------------------------------------')
118 for name, coef, energy in results:
119 total_energy += coef * energy
120 if abs(coef) < 1e-7:
121 continue
122 print(f'{name:14}{float2str(coef):>10}{energy:12.3f}')
123 print('------------------------------------')
124 print(f'Total energy: {total_energy:22.3f}')
125 print('------------------------------------')
128class Pourbaix:
129 @deprecated(
130 'Use ase.pourbaix.Pourbaix. '
131 'This class will be removed in a future version of ASE.')
132 def __init__(self, references, formula=None, T=300.0, **kwargs):
133 """Pourbaix object.
135 references: list of (name, energy) tuples
136 Examples of names: ZnO2, H+(aq), H2O(aq), Zn++(aq), ...
137 formula: str
138 Stoichiometry. Example: ``'ZnO'``. Can also be given as
139 keyword arguments: ``Pourbaix(refs, Zn=1, O=1)``.
140 T: float
141 Temperature in Kelvin.
143 .. deprecated:: 3.24.0
144 """
146 if formula:
147 assert not kwargs
148 kwargs = parse_formula(formula)[0]
150 if 'O' not in kwargs:
151 kwargs['O'] = 0
152 if 'H' not in kwargs:
153 kwargs['H'] = 0
155 self.kT = units.kB * T
156 self.references = []
157 for name, energy in references:
158 if name == 'O':
159 continue
160 count, charge, aq = parse_formula(name)
161 if all(symbol in kwargs for symbol in count):
162 self.references.append((count, charge, aq, energy, name))
164 self.references.append(({}, -1, False, 0.0, 'e-')) # an electron
166 self.count = kwargs
168 self.N = {'e-': 0}
169 for symbol in kwargs:
170 if symbol not in self.N:
171 self.N[symbol] = len(self.N)
173 def decompose(self, U, pH, verbose=True, concentration=1e-6):
174 """Decompose material.
176 U: float
177 Potential in V.
178 pH: float
179 pH value.
180 verbose: bool
181 Default is True.
182 concentration: float
183 Concentration of solvated references.
185 Returns optimal coefficients and energy:
187 >>> from ase.phasediagram import Pourbaix, solvated
188 >>> refs = solvated('CoO') + [
189 ... ('Co', 0.0),
190 ... ('CoO', -2.509),
191 ... ('Co3O4', -9.402)]
192 >>> pb = Pourbaix(refs, Co=3, O=4)
193 >>> coefs, energy = pb.decompose(U=1.5, pH=0,
194 ... concentration=1e-6,
195 ... verbose=True)
196 0 HCoO2-(aq) -3.974
197 1 CoO2--(aq) -3.098
198 2 H2O(aq) -2.458
199 3 CoOH+(aq) -2.787
200 4 CoO(aq) -2.265
201 5 CoOH++(aq) -1.355
202 6 Co++(aq) -0.921
203 7 H+(aq) 0.000
204 8 Co+++(aq) 1.030
205 9 Co 0.000
206 10 CoO -2.509
207 11 Co3O4 -9.402
208 12 e- -1.500
209 reference coefficient energy
210 ------------------------------------
211 H2O(aq) 4 -2.458
212 Co++(aq) 3 -0.921
213 H+(aq) -8 0.000
214 e- -2 -1.500
215 ------------------------------------
216 Total energy: -9.596
217 ------------------------------------
218 """
220 alpha = np.log(10) * self.kT
221 entropy = -np.log(concentration) * self.kT
223 # We want to minimize np.dot(energies, x) under the constraints:
224 #
225 # np.dot(x, eq2) == eq1
226 #
227 # with bounds[i,0] <= x[i] <= bounds[i, 1].
228 #
229 # First two equations are charge and number of hydrogens, and
230 # the rest are the remaining species.
232 eq1 = [0] + list(self.count.values())
233 eq2 = []
234 energies = []
235 bounds = []
236 names = []
237 for count, charge, aq, energy, name in self.references:
238 eq = np.zeros(len(self.N))
239 eq[0] = charge
240 for symbol, n in count.items():
241 eq[self.N[symbol]] = n
242 eq2.append(eq)
243 if name in ['H2O(aq)', 'H+(aq)', 'e-']:
244 bounds.append((-np.inf, np.inf))
245 if name == 'e-':
246 energy = -U
247 elif name == 'H+(aq)':
248 energy = -pH * alpha
249 else:
250 bounds.append((0, np.inf))
251 if aq:
252 energy -= entropy
253 if verbose:
254 print('{:<5}{:10}{:10.3f}'.format(len(energies),
255 name, energy))
256 energies.append(energy)
257 names.append(name)
259 from scipy.optimize import linprog
261 result = linprog(c=energies,
262 A_eq=np.transpose(eq2),
263 b_eq=eq1,
264 bounds=bounds)
266 if verbose:
267 print_results(zip(names, result.x, energies))
269 return result.x, result.fun
271 def diagram(self, U, pH, plot=True, show=False, ax=None):
272 """Calculate Pourbaix diagram.
274 U: list of float
275 Potentials in V.
276 pH: list of float
277 pH values.
278 plot: bool
279 Create plot.
280 show: bool
281 Open graphical window and show plot.
282 ax: matplotlib axes object
283 When creating plot, plot onto the given axes object.
284 If none given, plot onto the current one.
285 """
286 a = np.empty((len(U), len(pH)), int)
287 a[:] = -1
288 colors = {}
289 f = functools.partial(self.colorfunction, colors=colors)
290 bisect(a, U, pH, f)
291 compositions = [None] * len(colors)
292 names = [ref[-1] for ref in self.references]
293 for indices, color in colors.items():
294 compositions[color] = ' + '.join(names[i] for i in indices
295 if names[i] not in
296 ['H2O(aq)', 'H+(aq)', 'e-'])
297 text = []
298 for i, name in enumerate(compositions):
299 b = (a == i)
300 x = np.dot(b.sum(1), U) / b.sum()
301 y = np.dot(b.sum(0), pH) / b.sum()
302 name = re.sub(r'(\S)([+-]+)', r'\1$^{\2}$', name)
303 name = re.sub(r'(\d+)', r'$_{\1}$', name)
304 text.append((x, y, name))
306 if plot:
307 import matplotlib.cm as cm
308 import matplotlib.pyplot as plt
309 if ax is None:
310 ax = plt.gca()
312 # rasterized pcolormesh has a bug which leaves a tiny
313 # white border. Unrasterized pcolormesh produces
314 # unreasonably large files. Avoid this by using the more
315 # general imshow.
316 ax.imshow(a, cmap=cm.Accent,
317 extent=[min(pH), max(pH), min(U), max(U)],
318 origin='lower',
319 aspect='auto')
321 for x, y, name in text:
322 ax.text(y, x, name, horizontalalignment='center')
323 ax.set_xlabel('pH')
324 ax.set_ylabel('potential [V]')
325 ax.set_xlim(min(pH), max(pH))
326 ax.set_ylim(min(U), max(U))
327 if show:
328 plt.show()
330 return a, compositions, text
332 def colorfunction(self, U, pH, colors):
333 coefs, _energy = self.decompose(U, pH, verbose=False)
334 indices = tuple(sorted(np.where(abs(coefs) > 1e-3)[0]))
335 color = colors.get(indices)
336 if color is None:
337 color = len(colors)
338 colors[indices] = color
339 return color
342class PhaseDiagram:
343 def __init__(self, references, filter='', verbose=True):
344 """Phase-diagram.
346 references: list of (name, energy) tuples
347 List of references. The energy must be the total energy and not
348 energy per atom. The names can also be dicts like
349 ``{'Zn': 1, 'O': 2}`` which would be equivalent to ``'ZnO2'``.
350 filter: str or list of str
351 Use only those references that match the given filter.
352 Example: ``filter='ZnO'`` will select those that
353 contain zinc or oxygen.
354 verbose: bool
355 Write information.
356 """
358 if not references:
359 raise ValueError("You must provide a non-empty list of references"
360 " for the phase diagram! "
361 "You have provided '{}'".format(references))
362 filter = parse_formula(filter)[0]
364 self.verbose = verbose
366 self.species = OrderedDict()
367 self.references = []
368 for name, energy in references:
369 if isinstance(name, str):
370 count = parse_formula(name)[0]
371 else:
372 count = name
374 if filter and any(symbol not in filter for symbol in count):
375 continue
377 if not isinstance(name, str):
378 name = Formula.from_dict(count).format('metal')
380 natoms = 0
381 for symbol, n in count.items():
382 natoms += n
383 if symbol not in self.species:
384 self.species[symbol] = len(self.species)
385 self.references.append((count, energy, name, natoms))
387 ns = len(self.species)
388 self.symbols = [None] * ns
389 for symbol, id in self.species.items():
390 self.symbols[id] = symbol
392 if verbose:
393 print('Species:', ', '.join(self.symbols))
394 print('References:', len(self.references))
395 for i, (count, energy, name, natoms) in enumerate(self.references):
396 print(f'{i:<5}{name:10}{energy:10.3f}')
398 self.points = np.zeros((len(self.references), ns + 1))
399 for s, (count, energy, name, natoms) in enumerate(self.references):
400 for symbol, n in count.items():
401 self.points[s, self.species[symbol]] = n / natoms
402 self.points[s, -1] = energy / natoms
404 if len(self.points) == ns:
405 # Simple case that qhull would choke on:
406 self.simplices = np.arange(ns).reshape((1, ns))
407 self.hull = np.ones(ns, bool)
408 elif ns == 1:
409 # qhull also doesn't like ns=1:
410 i = self.points[:, 1].argmin()
411 self.simplices = np.array([[i]])
412 self.hull = np.zeros(len(self.points), bool)
413 self.hull[i] = True
414 else:
415 hull = ConvexHull(self.points[:, 1:])
417 # Find relevant simplices:
418 ok = hull.equations[:, -2] < 0
419 self.simplices = hull.simplices[ok]
421 # Create a mask for those points that are on the convex hull:
422 self.hull = np.zeros(len(self.points), bool)
423 for simplex in self.simplices:
424 self.hull[simplex] = True
426 if verbose:
427 print('Simplices:', len(self.simplices))
429 def decompose(self, formula=None, **kwargs):
430 """Find the combination of the references with the lowest energy.
432 formula: str
433 Stoichiometry. Example: ``'ZnO'``. Can also be given as
434 keyword arguments: ``decompose(Zn=1, O=1)``.
436 Example::
438 pd = PhaseDiagram(...)
439 pd.decompose(Zn=1, O=3)
441 Returns energy, indices of references and coefficients."""
443 if formula:
444 assert not kwargs
445 kwargs = parse_formula(formula)[0]
447 point = np.zeros(len(self.species))
448 N = 0
449 for symbol, n in kwargs.items():
450 point[self.species[symbol]] = n
451 N += n
453 # Find coordinates within each simplex:
454 X = self.points[self.simplices, 1:-1] - point[1:] / N
456 # Find the simplex with positive coordinates that sum to
457 # less than one:
458 eps = 1e-14
459 candidates = []
460 for i, Y in enumerate(X):
461 try:
462 x = np.linalg.solve((Y[1:] - Y[:1]).T, -Y[0])
463 except np.linalg.linalg.LinAlgError:
464 continue
465 if (x > -eps).all() and x.sum() < 1 + eps:
466 indices = self.simplices[i]
467 points = self.points[indices]
469 scaledcoefs = [1 - x.sum()]
470 scaledcoefs.extend(x)
472 energy = N * np.dot(scaledcoefs, points[:, -1])
473 candidates.append((energy, indices, points, scaledcoefs))
475 # Pick the one with lowest energy:
476 energy, indices, points, scaledcoefs = min(
477 candidates, key=lambda x: x[0])
479 coefs = []
480 results = []
481 for coef, s in zip(scaledcoefs, indices):
482 _count, e, name, natoms = self.references[s]
483 coef *= N / natoms
484 coefs.append(coef)
485 results.append((name, coef, e))
487 if self.verbose:
488 print_results(results)
490 return energy, indices, np.array(coefs)
492 def plot(self, ax=None, dims=None, show=False, **plotkwargs):
493 """Make 2-d or 3-d plot of datapoints and convex hull.
495 Default is 2-d for 2- and 3-component diagrams and 3-d for a
496 4-component diagram.
497 """
498 import matplotlib.pyplot as plt
500 N = len(self.species)
502 if dims is None:
503 if N <= 3:
504 dims = 2
505 else:
506 dims = 3
508 if ax is None:
509 projection = None
510 if dims == 3:
511 projection = '3d'
512 from mpl_toolkits.mplot3d import Axes3D
513 Axes3D # silence pyflakes
514 fig = plt.figure()
515 ax = fig.add_subplot(projection=projection)
516 else:
517 if dims == 3 and not hasattr(ax, 'set_zlim'):
518 raise ValueError('Cannot make 3d plot unless axes projection '
519 'is 3d')
521 if dims == 2:
522 if N == 2:
523 self.plot2d2(ax, **plotkwargs)
524 elif N == 3:
525 self.plot2d3(ax)
526 else:
527 raise ValueError('Can only make 2-d plots for 2 and 3 '
528 'component systems!')
529 else:
530 if N == 3:
531 self.plot3d3(ax)
532 elif N == 4:
533 self.plot3d4(ax)
534 else:
535 raise ValueError('Can only make 3-d plots for 3 and 4 '
536 'component systems!')
537 if show:
538 plt.show()
539 return ax
541 def plot2d2(self, ax=None,
542 only_label_simplices=False, only_plot_simplices=False):
543 x, e = self.points[:, 1:].T
544 names = [re.sub(r'(\d+)', r'$_{\1}$', ref[2])
545 for ref in self.references]
546 hull = self.hull
547 simplices = self.simplices
548 xlabel = self.symbols[1]
549 ylabel = 'energy [eV/atom]'
551 if ax:
552 for i, j in simplices:
553 ax.plot(x[[i, j]], e[[i, j]], '-b')
554 ax.plot(x[hull], e[hull], 'sg')
555 if not only_plot_simplices:
556 ax.plot(x[~hull], e[~hull], 'or')
558 if only_plot_simplices or only_label_simplices:
559 x = x[self.hull]
560 e = e[self.hull]
561 names = [name for name, h in zip(names, self.hull) if h]
562 for a, b, name in zip(x, e, names):
563 ax.text(a, b, name, ha='center', va='top')
565 ax.set_xlabel(xlabel)
566 ax.set_ylabel(ylabel)
568 return (x, e, names, hull, simplices, xlabel, ylabel)
570 def plot2d3(self, ax=None):
571 x, y = self.points[:, 1:-1].T.copy()
572 x += y / 2
573 y *= 3**0.5 / 2
574 names = [re.sub(r'(\d+)', r'$_{\1}$', ref[2])
575 for ref in self.references]
576 hull = self.hull
577 simplices = self.simplices
579 if ax:
580 for i, j, k in simplices:
581 ax.plot(x[[i, j, k, i]], y[[i, j, k, i]], '-b')
582 ax.plot(x[hull], y[hull], 'og')
583 ax.plot(x[~hull], y[~hull], 'sr')
584 for a, b, name in zip(x, y, names):
585 ax.text(a, b, name, ha='center', va='top')
587 return (x, y, names, hull, simplices)
589 def plot3d3(self, ax):
590 x, y, e = self.points[:, 1:].T
592 ax.scatter(x[self.hull], y[self.hull], e[self.hull],
593 c='g', marker='o')
594 ax.scatter(x[~self.hull], y[~self.hull], e[~self.hull],
595 c='r', marker='s')
597 for a, b, c, ref in zip(x, y, e, self.references):
598 name = re.sub(r'(\d+)', r'$_{\1}$', ref[2])
599 ax.text(a, b, c, name, ha='center', va='bottom')
601 for i, j, k in self.simplices:
602 ax.plot(x[[i, j, k, i]],
603 y[[i, j, k, i]],
604 zs=e[[i, j, k, i]], c='b')
606 ax.set_xlim3d(0, 1)
607 ax.set_ylim3d(0, 1)
608 ax.view_init(azim=115, elev=30)
609 ax.set_xlabel(self.symbols[1])
610 ax.set_ylabel(self.symbols[2])
611 ax.set_zlabel('energy [eV/atom]')
613 def plot3d4(self, ax):
614 x, y, z = self.points[:, 1:-1].T
615 a = x / 2 + y + z / 2
616 b = 3**0.5 * (x / 2 + y / 6)
617 c = (2 / 3)**0.5 * z
619 ax.scatter(a[self.hull], b[self.hull], c[self.hull],
620 c='g', marker='o')
621 ax.scatter(a[~self.hull], b[~self.hull], c[~self.hull],
622 c='r', marker='s')
624 for x, y, z, ref in zip(a, b, c, self.references):
625 name = re.sub(r'(\d+)', r'$_{\1}$', ref[2])
626 ax.text(x, y, z, name, ha='center', va='bottom')
628 for i, j, k, w in self.simplices:
629 ax.plot(a[[i, j, k, i, w, k, j, w]],
630 b[[i, j, k, i, w, k, j, w]],
631 zs=c[[i, j, k, i, w, k, j, w]], c='b')
633 ax.set_xlim3d(0, 1)
634 ax.set_ylim3d(0, 1)
635 ax.set_zlim3d(0, 1)
636 ax.view_init(azim=115, elev=30)
639_aqueous = """\
640-525700,SiF6--
641-514100,Rh(SO4)3----
642-504800,Ru(SO4)3----
643-499900,Pd(SO4)3----
644-495200,Ru(SO4)3---
645-485700,H4P2O7
646-483700,Rh(SO4)3---
647-483600,H3P2O7-
648-480400,H2P2O7--
649-480380,Pt(SO4)3----
650-471400,HP2O7---
651-458700,P2O7----
652-447500,LaF4-
653-437600,LaH2PO4++
654-377900,LaF3
655-376299,Ca(HSiO3)+
656-370691,BeF4--
657-355400,BF4-
658-353025,Mg(HSiO3)+
659-346900,LaSO4+
660-334100,Rh(SO4)2--
661-325400,Ru(SO4)2--
662-319640,Pd(SO4)2--
663-317900,Ru(SO4)2-
664-312970,Cr2O7--
665-312930,CaSO4
666-307890,NaHSiO3
667-307800,LaF2+
668-307000,LaHCO3++
669-306100,Rh(SO4)2-
670-302532,BeF3-
671-300670,Pt(SO4)2--
672-299900,LaCO3+
673-289477,MgSO4
674-288400,LaCl4-
675-281500,HZrO3-
676-279200,HHfO3-
677-276720,Sr(HCO3)+
678-275700,Ba(HCO3)+
679-273830,Ca(HCO3)+
680-273100,H3PO4
681-270140,H2PO4-
682-266500,S2O8--
683-264860,Sr(CO3)
684-264860,SrCO3
685-263830,Ba(CO3)
686-263830,BaCO3
687-262850,Ca(CO3)
688-262850,CaCO3
689-260310,HPO4--
690-257600,LaCl3
691-250200,Mg(HCO3)+
692-249200,H3VO4
693-248700,S4O6--
694-246640,KSO4-
695-243990,H2VO4-
696-243500,PO4---
697-243400,KHSO4
698-242801,HSiO3-
699-241700,HYO2
700-241476,NaSO4-
701-239700,HZrO2+
702-239300,LaO2H
703-238760,Mg(CO3)
704-238760,MgCO3
705-237800,HHfO2+
706-236890,Ag(CO3)2---
707-236800,HNbO3
708-236600,LaF++
709-235640,MnSO4
710-233400,ZrO2
711-233000,HVO4--
712-231600,HScO2
713-231540,B(OH)3
714-231400,HfO2
715-231386,BeF2
716-231000,S2O6--
717-229000,S3O6--
718-229000,S5O6--
719-228460,HTiO3-
720-227400,YO2-
721-227100,NbO3-
722-226700,LaCl2+
723-223400,HWO4-
724-221700,LaO2-
725-218500,WO4--
726-218100,ScO2-
727-214900,VO4---
728-210000,YOH++
729-208900,LaOH++
730-207700,HAlO2
731-206400,HMoO4-
732-204800,H3PO3
733-202350,H2PO3-
734-202290,SrF+
735-201807,BaF+
736-201120,BaF+
737-200400,MoO4--
738-200390,CaF+
739-199190,SiO2
740-198693,AlO2-
741-198100,YO+
742-195900,LaO+
743-195800,LaCl++
744-194000,CaCl2
745-194000,HPO3--
746-191300,LaNO3++
747-190400,ZrOH+++
748-189000,HfOH+++
749-189000,S2O5--
750-187600,ZrO++
751-186000,HfO++
752-183700,HCrO4-
753-183600,ScO+
754-183100,H3AsO4
755-180630,HSO4-
756-180010,H2AsO4-
757-177930,SO4--
758-177690,MgF+
759-174800,CrO4--
760-173300,SrOH+
761-172300,BaOH+
762-172200,HBeO2-
763-171300,CaOH+
764-170790,HAsO4--
765-166000,ReO4-
766-165800,SrCl+
767-165475,Al(OH)++
768-165475,AlOH++
769-164730,BaCl+
770-164000,La+++
771-163800,Y+++
772-163100,CaCl+
773-162240,BO2-
774-158493,BeF+
775-158188,AlO+
776-155700,VOOH+
777-155164,CdF2
778-154970,AsO4---
779-153500,Rh(SO4)
780-152900,BeO2--
781-152370,HSO5-
782-151540,RuCl6---
783-149255,MgOH+
784-147400,H2S2O4
785-146900,HS2O4-
786-146081,CdCl4--
787-145521,BeCl2
788-145200,Ru(SO4)
789-145056,PbF2
790-143500,S2O4--
791-140330,H2AsO3-
792-140300,VO2+
793-140282,HCO3-
794-140200,Sc+++
795-139900,BeOH+
796-139700,MgCl+
797-139200,Ru(SO4)+
798-139000,Pd(SO4)
799-138160,HF2-
800-138100,HCrO2
801-138000,TiO++
802-137300,HGaO2
803-136450,RbF
804-134760,Sr++
805-134030,Ba++
806-133270,Zr++++
807-133177,PbCl4--
808-132600,Hf++++
809-132120,Ca++
810-129310,ZnCl3-
811-128700,GaO2-
812-128600,BeO
813-128570,NaF
814-128000,H2S2O3
815-127500,Rh(SO4)+
816-127200,HS2O3-
817-126191,CO3--
818-126130,HSO3-
819-125300,CrO2-
820-125100,H3PO2
821-124900,S2O3--
822-123641,MnF+
823-122400,H2PO2-
824-121000,HMnO2-
825-120700,RuCl5--
826-120400,MnO4--
827-120300,Pt(SO4)
828-119800,HInO2
829-116300,SO3--
830-115971,CdCl3-
831-115609,Al+++
832-115316,BeCl+
833-112280,AgCl4---
834-111670,TiO2++
835-111500,VOH++
836-111430,Ag(CO3)-
837-110720,HZnO2-
838-108505,Mg++
839-108100,HSeO4-
840-108000,LiOH
841-107600,MnO4-
842-106988,HgCl4--
843-106700,InO2-
844-106700,VO++
845-106100,VO+
846-105500,SeO4--
847-105100,RbOH
848-105000,CsOH
849-104500,KOH
850-104109,ZnF+
851-103900,PdCl4--
852-103579,CuCl4--
853-102600,MnO2--
854-102150,PbCl3-
855-101850,H2SeO3
856-101100,HFeO2
857-100900,CsCl
858-100500,CrOH++
859-99900,NaOH
860-99800,VOH+
861-99250,LiCl
862-98340,HSeO3-
863-98300,ZnCl2
864-97870,RbCl
865-97400,HSbO2
866-97300,HSnO2-
867-97300,MnOH+
868-97016,InF++
869-96240,HAsO2
870-95430,KCl
871-95400,HFeO2-
872-94610,CsBr
873-93290,ZnO2--
874-93250,RhCl4--
875-92910,NaCl
876-92800,CrO+
877-92250,CO2
878-91210,PtCl4--
879-91157,FeF+
880-91100,GaOH++
881-91010,RbBr
882-90550,Be++
883-90010,KBr
884-89963,CuCl3--
885-89730,RuCl4-
886-88400,SeO3--
887-88000,FeO2-
888-87373,CdF+
889-86600,GaO+
890-86500,HCdO2-
891-86290,MnCl+
892-85610,NaBr
893-84851,CdCl2
894-83900,RuCl4--
895-83650,AsO2-
896-83600,Ti+++
897-83460,CsI
898-83400,HCoO2-
899-82710,AgCl3--
900-82400,SbO2-
901-81980,HNiO2-
902-81732,CoF+
903-81500,MnO
904-81190,ZnOH+
905-81000,HPbO2-
906-79768,NiF+
907-79645,FeF++
908-79300,HBiO2
909-78900,RbI
910-77740,KI
911-77700,La++
912-77500,RhCl4-
913-75860,PbF+
914-75338,CuCl3-
915-75216,TlF
916-75100,Ti++
917-74600,InOH++
918-74504,HgCl3-
919-73480,FeCl2
920-72900,NaI
921-71980,SO2
922-71662,HF
923-71600,RuO4--
924-71200,PbCl2
925-69933,Li+
926-69810,PdCl3-
927-69710,Cs+
928-69400,InO+
929-67811,AuCl3--
930-67800,Rb+
931-67510,K+
932-67420,ZnO
933-67340,F-
934-67300,CdO2--
935-66850,ZnCl+
936-65850,FeOH+
937-65550,TlOH
938-64200,NiO2--
939-63530,RhCl3-
940-63200,CoO2--
941-62591,Na+
942-61700,BiO2-
943-61500,CdOH+
944-60100,HCuO2-
945-59226,InCl++
946-58600,SnOH+
947-58560,RuCl3
948-58038,CuCl2-
949-57900,V+++
950-57800,FeOH++
951-57760,PtCl3-
952-57600,HTlO2
953-56690,H2O
954-56025,CoOH+
955-55100,Mn++
956-54380,RuCl3-
957-53950,PbOH+
958-53739,CuF+
959-53600,SnO
960-53100,FeO+
961-53030,FeCl+
962-52850,NiOH+
963-52627,CdCl+
964-52000,V++
965-51560,AgCl2-
966-50720,FeO
967-49459,AgF
968-49300,Cr+++
969-47500,CdO
970-46190,RhCl3
971-46142,CuCl2
972-45200,HHgO2-
973-45157,CoCl+
974-44000,CoO
975-42838,HgCl2
976-41600,TlO2-
977-41200,CuO2--
978-40920,NiCl+
979-39815,TlCl
980-39400,Cr++
981-39350,PbO
982-39340,NiO
983-39050,PbCl+
984-38000,Ga+++
985-37518,FeCl++
986-36781,AuCl2-
987-35332,AuCl4-
988-35200,Zn++
989-35160,PdCl2
990-33970,RhCl2
991-32300,BiOH++
992-31700,HIO3
993-31379,Cl-
994-30600,IO3-
995-30410,HCl
996-30204,HgF+
997-30200,CuOH+
998-29300,BiO+
999-28682,CO
1000-26507,NO3-
1001-26440,RuCl2+
1002-25590,Br3-
1003-25060,RuCl2
1004-24870,Br-
1005-24730,HNO3
1006-23700,HIO
1007-23400,In+++
1008-23280,OCN-
1009-23000,CoOH++
1010-22608,CuCl
1011-22290,PtCl2
1012-21900,AgOH
1013-21870,Fe++
1014-20800,CuO
1015-20300,Mn+++
1016-20058,Pb(HS)2
1017-19700,HBrO
1018-19100,HClO
1019-19100,ScOH++
1020-18990,NH4+
1021-18971,Pb(HS)3-
1022-18560,Cd++
1023-18290,Rh(OH)+
1024-17450,AgCl
1025-16250,CuCl+
1026-14780,RhCl2+
1027-14000,IO4-
1028-13130,Pd(OH)+
1029-13000,Co++
1030-12700,HgOH+
1031-12410,I-
1032-12300,I3-
1033-12190,Ru(OH)2++
1034-12100,HNO2
1035-11500,PdO
1036-10900,Ni++
1037-10470,Ru(OH)+
1038-10450,RuO+
1039-9200,IO-
1040-8900,HgO
1041-8800,ClO-
1042-8000,BrO-
1043-7740,Tl+
1044-7738,AgNO3
1045-7700,NO2-
1046-7220,RhO
1047-6673,H2S
1048-6570,Sn++
1049-6383,NH3
1050-5710,Pb++
1051-5500,AgO-
1052-4500,TlOH++
1053-4120,Fe+++
1054-3380,RhCl+
1055-3200,TlO+
1056-3184,AuCl
1057-2155,HgCl+
1058-2040,ClO4-
1059-1900,ClO3-
1060-1130,PtO
1061-820,Rh(OH)++
10620,Ag(HS)2-
10630,H+
1064230,RuO
10651400,HClO2
10661560,Pt(OH)+
10672429,Au(HS)2-
10682500,PdCl+
10692860,HS-
10703140,RhO+
10713215,Xe
10723554,Kr
10733890,Ar
10744100,ClO2-
10754347,N2
10764450,BrO3-
10774565,Ne
10784658,He
10795210,RuCl+
10807100,RuCl++
10818600,H2N2O2
10829375,TlCl++
108310500,HSe-
108411950,Cu+
108515675,Cu++
108615700,S5--
108716500,S4--
108817600,S3--
108918200,HN2O2-
109018330,RhCl++
109118380,PtCl+
109218427,Ag+
109319000,S2--
109419500,SeCN-
109519700,N2H5+
109621100,N2H6++
109722160,SCN-
109822880,Bi+++
109927700,Rh++
110028200,BrO4-
110128600,HCN
110232000,Co+++
110333200,N2O2--
110435900,Ru++
110536710,Hg2++
110639360,Hg++
110741200,CN-
110841440,Ru+++
110942200,Pd++
111051300,Tl+++
111152450,Rh+++
111261600,Pt++
111364300,Ag++
1114103600,Au+++"""