def to_formula(self, bag: 'BagType') -> Formula: if len(bag) != self.symbol_table.count(): raise ValueError(f'Bag {bag} does not fit symbol table') d = { self.symbol_table.get_symbol(index): count for index, count in enumerate(bag) } return Formula.from_dict(d)
def test_h0c1(): f = Formula.from_dict({'H': 0, 'C': 1}) assert f.format('hill') == 'C' with pytest.raises(ValueError): Formula.from_dict({'H': -1}) with pytest.raises(ValueError): Formula.from_dict({'H': 1.5}) with pytest.raises(ValueError): Formula.from_dict({7: 1})
def __init__(self, references, filter='', verbose=True): """Phase-diagram. references: list of (name, energy) tuples List of references. The energy must be the total energy and not energy per atom. The names can also be dicts like ``{'Zn': 1, 'O': 2}`` which would be equivalent to ``'ZnO2'``. filter: str or list of str Use only those references that match the given filter. Example: ``filter='ZnO'`` will select those that contain zinc or oxygen. verbose: bool Write information. """ if not references: raise ValueError("You must provide a non-empty list of references" " for the phase diagram! " "You have provided '{}'".format(references)) filter = parse_formula(filter)[0] self.verbose = verbose self.species = OrderedDict() self.references = [] for name, energy in references: if isinstance(name, str): count = parse_formula(name)[0] else: count = name if filter and any(symbol not in filter for symbol in count): continue if not isinstance(name, str): name = Formula.from_dict(count).format('metal') natoms = 0 for symbol, n in count.items(): natoms += n if symbol not in self.species: self.species[symbol] = len(self.species) self.references.append((count, energy, name, natoms)) ns = len(self.species) self.symbols = [None] * ns for symbol, id in self.species.items(): self.symbols[id] = symbol if verbose: print('Species:', ', '.join(self.symbols)) print('References:', len(self.references)) for i, (count, energy, name, natoms) in enumerate(self.references): print('{:<5}{:10}{:10.3f}'.format(i, name, energy)) self.points = np.zeros((len(self.references), ns + 1)) for s, (count, energy, name, natoms) in enumerate(self.references): for symbol, n in count.items(): self.points[s, self.species[symbol]] = n / natoms self.points[s, -1] = energy / natoms if len(self.points) == ns: # Simple case that qhull would choke on: self.simplices = np.arange(ns).reshape((1, ns)) self.hull = np.ones(ns, bool) else: hull = ConvexHull(self.points[:, 1:]) # Find relevant simplices: ok = hull.equations[:, -2] < 0 self.simplices = hull.simplices[ok] # Create a mask for those points that are on the convex hull: self.hull = np.zeros(len(self.points), bool) for simplex in self.simplices: self.hull[simplex] = True if verbose: print('Simplices:', len(self.simplices))
def remove_from_formula(formula: Formula, symbol: str) -> Formula: d = formula.count() d[symbol] -= 1 return Formula.from_dict(d)