Coverage for /builds/hweiske/ase/ase/phasediagram.py: 67.03%
367 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-22 11:22 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-22 11:22 +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 for i, Y in enumerate(X):
452 try:
453 x = np.linalg.solve((Y[1:] - Y[:1]).T, -Y[0])
454 except np.linalg.linalg.LinAlgError:
455 continue
456 if (x > -eps).all() and x.sum() < 1 + eps:
457 break
458 else:
459 assert False, X
461 indices = self.simplices[i]
462 points = self.points[indices]
464 scaledcoefs = [1 - x.sum()]
465 scaledcoefs.extend(x)
467 energy = N * np.dot(scaledcoefs, points[:, -1])
469 coefs = []
470 results = []
471 for coef, s in zip(scaledcoefs, indices):
472 count, e, name, natoms = self.references[s]
473 coef *= N / natoms
474 coefs.append(coef)
475 results.append((name, coef, e))
477 if self.verbose:
478 print_results(results)
480 return energy, indices, np.array(coefs)
482 def plot(self, ax=None, dims=None, show=False, **plotkwargs):
483 """Make 2-d or 3-d plot of datapoints and convex hull.
485 Default is 2-d for 2- and 3-component diagrams and 3-d for a
486 4-component diagram.
487 """
488 import matplotlib.pyplot as plt
490 N = len(self.species)
492 if dims is None:
493 if N <= 3:
494 dims = 2
495 else:
496 dims = 3
498 if ax is None:
499 projection = None
500 if dims == 3:
501 projection = '3d'
502 from mpl_toolkits.mplot3d import Axes3D
503 Axes3D # silence pyflakes
504 fig = plt.figure()
505 ax = fig.add_subplot(projection=projection)
506 else:
507 if dims == 3 and not hasattr(ax, 'set_zlim'):
508 raise ValueError('Cannot make 3d plot unless axes projection '
509 'is 3d')
511 if dims == 2:
512 if N == 2:
513 self.plot2d2(ax, **plotkwargs)
514 elif N == 3:
515 self.plot2d3(ax)
516 else:
517 raise ValueError('Can only make 2-d plots for 2 and 3 '
518 'component systems!')
519 else:
520 if N == 3:
521 self.plot3d3(ax)
522 elif N == 4:
523 self.plot3d4(ax)
524 else:
525 raise ValueError('Can only make 3-d plots for 3 and 4 '
526 'component systems!')
527 if show:
528 plt.show()
529 return ax
531 def plot2d2(self, ax=None,
532 only_label_simplices=False, only_plot_simplices=False):
533 x, e = self.points[:, 1:].T
534 names = [re.sub(r'(\d+)', r'$_{\1}$', ref[2])
535 for ref in self.references]
536 hull = self.hull
537 simplices = self.simplices
538 xlabel = self.symbols[1]
539 ylabel = 'energy [eV/atom]'
541 if ax:
542 for i, j in simplices:
543 ax.plot(x[[i, j]], e[[i, j]], '-b')
544 ax.plot(x[hull], e[hull], 'sg')
545 if not only_plot_simplices:
546 ax.plot(x[~hull], e[~hull], 'or')
548 if only_plot_simplices or only_label_simplices:
549 x = x[self.hull]
550 e = e[self.hull]
551 names = [name for name, h in zip(names, self.hull) if h]
552 for a, b, name in zip(x, e, names):
553 ax.text(a, b, name, ha='center', va='top')
555 ax.set_xlabel(xlabel)
556 ax.set_ylabel(ylabel)
558 return (x, e, names, hull, simplices, xlabel, ylabel)
560 def plot2d3(self, ax=None):
561 x, y = self.points[:, 1:-1].T.copy()
562 x += y / 2
563 y *= 3**0.5 / 2
564 names = [re.sub(r'(\d+)', r'$_{\1}$', ref[2])
565 for ref in self.references]
566 hull = self.hull
567 simplices = self.simplices
569 if ax:
570 for i, j, k in simplices:
571 ax.plot(x[[i, j, k, i]], y[[i, j, k, i]], '-b')
572 ax.plot(x[hull], y[hull], 'og')
573 ax.plot(x[~hull], y[~hull], 'sr')
574 for a, b, name in zip(x, y, names):
575 ax.text(a, b, name, ha='center', va='top')
577 return (x, y, names, hull, simplices)
579 def plot3d3(self, ax):
580 x, y, e = self.points[:, 1:].T
582 ax.scatter(x[self.hull], y[self.hull], e[self.hull],
583 c='g', marker='o')
584 ax.scatter(x[~self.hull], y[~self.hull], e[~self.hull],
585 c='r', marker='s')
587 for a, b, c, ref in zip(x, y, e, self.references):
588 name = re.sub(r'(\d+)', r'$_{\1}$', ref[2])
589 ax.text(a, b, c, name, ha='center', va='bottom')
591 for i, j, k in self.simplices:
592 ax.plot(x[[i, j, k, i]],
593 y[[i, j, k, i]],
594 zs=e[[i, j, k, i]], c='b')
596 ax.set_xlim3d(0, 1)
597 ax.set_ylim3d(0, 1)
598 ax.view_init(azim=115, elev=30)
599 ax.set_xlabel(self.symbols[1])
600 ax.set_ylabel(self.symbols[2])
601 ax.set_zlabel('energy [eV/atom]')
603 def plot3d4(self, ax):
604 x, y, z = self.points[:, 1:-1].T
605 a = x / 2 + y + z / 2
606 b = 3**0.5 * (x / 2 + y / 6)
607 c = (2 / 3)**0.5 * z
609 ax.scatter(a[self.hull], b[self.hull], c[self.hull],
610 c='g', marker='o')
611 ax.scatter(a[~self.hull], b[~self.hull], c[~self.hull],
612 c='r', marker='s')
614 for x, y, z, ref in zip(a, b, c, self.references):
615 name = re.sub(r'(\d+)', r'$_{\1}$', ref[2])
616 ax.text(x, y, z, name, ha='center', va='bottom')
618 for i, j, k, w in self.simplices:
619 ax.plot(a[[i, j, k, i, w, k, j, w]],
620 b[[i, j, k, i, w, k, j, w]],
621 zs=c[[i, j, k, i, w, k, j, w]], c='b')
623 ax.set_xlim3d(0, 1)
624 ax.set_ylim3d(0, 1)
625 ax.set_zlim3d(0, 1)
626 ax.view_init(azim=115, elev=30)
629_aqueous = """\
630-525700,SiF6--
631-514100,Rh(SO4)3----
632-504800,Ru(SO4)3----
633-499900,Pd(SO4)3----
634-495200,Ru(SO4)3---
635-485700,H4P2O7
636-483700,Rh(SO4)3---
637-483600,H3P2O7-
638-480400,H2P2O7--
639-480380,Pt(SO4)3----
640-471400,HP2O7---
641-458700,P2O7----
642-447500,LaF4-
643-437600,LaH2PO4++
644-377900,LaF3
645-376299,Ca(HSiO3)+
646-370691,BeF4--
647-355400,BF4-
648-353025,Mg(HSiO3)+
649-346900,LaSO4+
650-334100,Rh(SO4)2--
651-325400,Ru(SO4)2--
652-319640,Pd(SO4)2--
653-317900,Ru(SO4)2-
654-312970,Cr2O7--
655-312930,CaSO4
656-307890,NaHSiO3
657-307800,LaF2+
658-307000,LaHCO3++
659-306100,Rh(SO4)2-
660-302532,BeF3-
661-300670,Pt(SO4)2--
662-299900,LaCO3+
663-289477,MgSO4
664-288400,LaCl4-
665-281500,HZrO3-
666-279200,HHfO3-
667-276720,Sr(HCO3)+
668-275700,Ba(HCO3)+
669-273830,Ca(HCO3)+
670-273100,H3PO4
671-270140,H2PO4-
672-266500,S2O8--
673-264860,Sr(CO3)
674-264860,SrCO3
675-263830,Ba(CO3)
676-263830,BaCO3
677-262850,Ca(CO3)
678-262850,CaCO3
679-260310,HPO4--
680-257600,LaCl3
681-250200,Mg(HCO3)+
682-249200,H3VO4
683-248700,S4O6--
684-246640,KSO4-
685-243990,H2VO4-
686-243500,PO4---
687-243400,KHSO4
688-242801,HSiO3-
689-241700,HYO2
690-241476,NaSO4-
691-239700,HZrO2+
692-239300,LaO2H
693-238760,Mg(CO3)
694-238760,MgCO3
695-237800,HHfO2+
696-236890,Ag(CO3)2---
697-236800,HNbO3
698-236600,LaF++
699-235640,MnSO4
700-233400,ZrO2
701-233000,HVO4--
702-231600,HScO2
703-231540,B(OH)3
704-231400,HfO2
705-231386,BeF2
706-231000,S2O6--
707-229000,S3O6--
708-229000,S5O6--
709-228460,HTiO3-
710-227400,YO2-
711-227100,NbO3-
712-226700,LaCl2+
713-223400,HWO4-
714-221700,LaO2-
715-218500,WO4--
716-218100,ScO2-
717-214900,VO4---
718-210000,YOH++
719-208900,LaOH++
720-207700,HAlO2
721-206400,HMoO4-
722-204800,H3PO3
723-202350,H2PO3-
724-202290,SrF+
725-201807,BaF+
726-201120,BaF+
727-200400,MoO4--
728-200390,CaF+
729-199190,SiO2
730-198693,AlO2-
731-198100,YO+
732-195900,LaO+
733-195800,LaCl++
734-194000,CaCl2
735-194000,HPO3--
736-191300,LaNO3++
737-190400,ZrOH+++
738-189000,HfOH+++
739-189000,S2O5--
740-187600,ZrO++
741-186000,HfO++
742-183700,HCrO4-
743-183600,ScO+
744-183100,H3AsO4
745-180630,HSO4-
746-180010,H2AsO4-
747-177930,SO4--
748-177690,MgF+
749-174800,CrO4--
750-173300,SrOH+
751-172300,BaOH+
752-172200,HBeO2-
753-171300,CaOH+
754-170790,HAsO4--
755-166000,ReO4-
756-165800,SrCl+
757-165475,Al(OH)++
758-165475,AlOH++
759-164730,BaCl+
760-164000,La+++
761-163800,Y+++
762-163100,CaCl+
763-162240,BO2-
764-158493,BeF+
765-158188,AlO+
766-155700,VOOH+
767-155164,CdF2
768-154970,AsO4---
769-153500,Rh(SO4)
770-152900,BeO2--
771-152370,HSO5-
772-151540,RuCl6---
773-149255,MgOH+
774-147400,H2S2O4
775-146900,HS2O4-
776-146081,CdCl4--
777-145521,BeCl2
778-145200,Ru(SO4)
779-145056,PbF2
780-143500,S2O4--
781-140330,H2AsO3-
782-140300,VO2+
783-140282,HCO3-
784-140200,Sc+++
785-139900,BeOH+
786-139700,MgCl+
787-139200,Ru(SO4)+
788-139000,Pd(SO4)
789-138160,HF2-
790-138100,HCrO2
791-138000,TiO++
792-137300,HGaO2
793-136450,RbF
794-134760,Sr++
795-134030,Ba++
796-133270,Zr++++
797-133177,PbCl4--
798-132600,Hf++++
799-132120,Ca++
800-129310,ZnCl3-
801-128700,GaO2-
802-128600,BeO
803-128570,NaF
804-128000,H2S2O3
805-127500,Rh(SO4)+
806-127200,HS2O3-
807-126191,CO3--
808-126130,HSO3-
809-125300,CrO2-
810-125100,H3PO2
811-124900,S2O3--
812-123641,MnF+
813-122400,H2PO2-
814-121000,HMnO2-
815-120700,RuCl5--
816-120400,MnO4--
817-120300,Pt(SO4)
818-119800,HInO2
819-116300,SO3--
820-115971,CdCl3-
821-115609,Al+++
822-115316,BeCl+
823-112280,AgCl4---
824-111670,TiO2++
825-111500,VOH++
826-111430,Ag(CO3)-
827-110720,HZnO2-
828-108505,Mg++
829-108100,HSeO4-
830-108000,LiOH
831-107600,MnO4-
832-106988,HgCl4--
833-106700,InO2-
834-106700,VO++
835-106100,VO+
836-105500,SeO4--
837-105100,RbOH
838-105000,CsOH
839-104500,KOH
840-104109,ZnF+
841-103900,PdCl4--
842-103579,CuCl4--
843-102600,MnO2--
844-102150,PbCl3-
845-101850,H2SeO3
846-101100,HFeO2
847-100900,CsCl
848-100500,CrOH++
849-99900,NaOH
850-99800,VOH+
851-99250,LiCl
852-98340,HSeO3-
853-98300,ZnCl2
854-97870,RbCl
855-97400,HSbO2
856-97300,HSnO2-
857-97300,MnOH+
858-97016,InF++
859-96240,HAsO2
860-95430,KCl
861-95400,HFeO2-
862-94610,CsBr
863-93290,ZnO2--
864-93250,RhCl4--
865-92910,NaCl
866-92800,CrO+
867-92250,CO2
868-91210,PtCl4--
869-91157,FeF+
870-91100,GaOH++
871-91010,RbBr
872-90550,Be++
873-90010,KBr
874-89963,CuCl3--
875-89730,RuCl4-
876-88400,SeO3--
877-88000,FeO2-
878-87373,CdF+
879-86600,GaO+
880-86500,HCdO2-
881-86290,MnCl+
882-85610,NaBr
883-84851,CdCl2
884-83900,RuCl4--
885-83650,AsO2-
886-83600,Ti+++
887-83460,CsI
888-83400,HCoO2-
889-82710,AgCl3--
890-82400,SbO2-
891-81980,HNiO2-
892-81732,CoF+
893-81500,MnO
894-81190,ZnOH+
895-81000,HPbO2-
896-79768,NiF+
897-79645,FeF++
898-79300,HBiO2
899-78900,RbI
900-77740,KI
901-77700,La++
902-77500,RhCl4-
903-75860,PbF+
904-75338,CuCl3-
905-75216,TlF
906-75100,Ti++
907-74600,InOH++
908-74504,HgCl3-
909-73480,FeCl2
910-72900,NaI
911-71980,SO2
912-71662,HF
913-71600,RuO4--
914-71200,PbCl2
915-69933,Li+
916-69810,PdCl3-
917-69710,Cs+
918-69400,InO+
919-67811,AuCl3--
920-67800,Rb+
921-67510,K+
922-67420,ZnO
923-67340,F-
924-67300,CdO2--
925-66850,ZnCl+
926-65850,FeOH+
927-65550,TlOH
928-64200,NiO2--
929-63530,RhCl3-
930-63200,CoO2--
931-62591,Na+
932-61700,BiO2-
933-61500,CdOH+
934-60100,HCuO2-
935-59226,InCl++
936-58600,SnOH+
937-58560,RuCl3
938-58038,CuCl2-
939-57900,V+++
940-57800,FeOH++
941-57760,PtCl3-
942-57600,HTlO2
943-56690,H2O
944-56025,CoOH+
945-55100,Mn++
946-54380,RuCl3-
947-53950,PbOH+
948-53739,CuF+
949-53600,SnO
950-53100,FeO+
951-53030,FeCl+
952-52850,NiOH+
953-52627,CdCl+
954-52000,V++
955-51560,AgCl2-
956-50720,FeO
957-49459,AgF
958-49300,Cr+++
959-47500,CdO
960-46190,RhCl3
961-46142,CuCl2
962-45200,HHgO2-
963-45157,CoCl+
964-44000,CoO
965-42838,HgCl2
966-41600,TlO2-
967-41200,CuO2--
968-40920,NiCl+
969-39815,TlCl
970-39400,Cr++
971-39350,PbO
972-39340,NiO
973-39050,PbCl+
974-38000,Ga+++
975-37518,FeCl++
976-36781,AuCl2-
977-35332,AuCl4-
978-35200,Zn++
979-35160,PdCl2
980-33970,RhCl2
981-32300,BiOH++
982-31700,HIO3
983-31379,Cl-
984-30600,IO3-
985-30410,HCl
986-30204,HgF+
987-30200,CuOH+
988-29300,BiO+
989-28682,CO
990-26507,NO3-
991-26440,RuCl2+
992-25590,Br3-
993-25060,RuCl2
994-24870,Br-
995-24730,HNO3
996-23700,HIO
997-23400,In+++
998-23280,OCN-
999-23000,CoOH++
1000-22608,CuCl
1001-22290,PtCl2
1002-21900,AgOH
1003-21870,Fe++
1004-20800,CuO
1005-20300,Mn+++
1006-20058,Pb(HS)2
1007-19700,HBrO
1008-19100,HClO
1009-19100,ScOH++
1010-18990,NH4+
1011-18971,Pb(HS)3-
1012-18560,Cd++
1013-18290,Rh(OH)+
1014-17450,AgCl
1015-16250,CuCl+
1016-14780,RhCl2+
1017-14000,IO4-
1018-13130,Pd(OH)+
1019-13000,Co++
1020-12700,HgOH+
1021-12410,I-
1022-12300,I3-
1023-12190,Ru(OH)2++
1024-12100,HNO2
1025-11500,PdO
1026-10900,Ni++
1027-10470,Ru(OH)+
1028-10450,RuO+
1029-9200,IO-
1030-8900,HgO
1031-8800,ClO-
1032-8000,BrO-
1033-7740,Tl+
1034-7738,AgNO3
1035-7700,NO2-
1036-7220,RhO
1037-6673,H2S
1038-6570,Sn++
1039-6383,NH3
1040-5710,Pb++
1041-5500,AgO-
1042-4500,TlOH++
1043-4120,Fe+++
1044-3380,RhCl+
1045-3200,TlO+
1046-3184,AuCl
1047-2155,HgCl+
1048-2040,ClO4-
1049-1900,ClO3-
1050-1130,PtO
1051-820,Rh(OH)++
10520,Ag(HS)2-
10530,H+
1054230,RuO
10551400,HClO2
10561560,Pt(OH)+
10572429,Au(HS)2-
10582500,PdCl+
10592860,HS-
10603140,RhO+
10613215,Xe
10623554,Kr
10633890,Ar
10644100,ClO2-
10654347,N2
10664450,BrO3-
10674565,Ne
10684658,He
10695210,RuCl+
10707100,RuCl++
10718600,H2N2O2
10729375,TlCl++
107310500,HSe-
107411950,Cu+
107515675,Cu++
107615700,S5--
107716500,S4--
107817600,S3--
107918200,HN2O2-
108018330,RhCl++
108118380,PtCl+
108218427,Ag+
108319000,S2--
108419500,SeCN-
108519700,N2H5+
108621100,N2H6++
108722160,SCN-
108822880,Bi+++
108927700,Rh++
109028200,BrO4-
109128600,HCN
109232000,Co+++
109333200,N2O2--
109435900,Ru++
109536710,Hg2++
109639360,Hg++
109741200,CN-
109841440,Ru+++
109942200,Pd++
110051300,Tl+++
110152450,Rh+++
110261600,Pt++
110364300,Ag++
1104103600,Au+++"""