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