def test_gas_phase_example(self): """Test the gas phase enumerator examples.""" db_name = 'C2H6-example.db' with ReactionNetwork(db_name=db_name) as rn: rn.molecule_search( element_pool={ 'C': 2, 'H': 6 }, multiple_bond_search=False) molecules = rn.load_molecules() assert (len(molecules) == 17) rn.path_search(reconfiguration=False, substitution=False) pathways = rn.load_pathways() assert (len(pathways) == 27) names = np.empty(len(molecules) + 1, dtype='a5') names[0] = '' for k, v in molecules.items(): atn = nx.get_node_attributes(v.graph, 'number') hill = formula_hill(list(atn.values())) names[k] = hill for path in pathways: print('|{} + {} --> {} + {}|'.format(*names[path]))
def _get_species_name(self, index): site = self._get_site_index(index) if self.formula == 'hill': n = nx.get_node_attributes(self.molecules[index], 'atomic_number') name = formula_hill(list(n.values())) elif self.formula == 'smiles': name = get_smiles(self.molecules[index]) else: raise NotImplementedError(str(self.formula)) return '_'.join([name, site])
def test_gas_phase_example(): db_name = 'C2H6-example.db' with ReactionNetwork(db_name=db_name) as rn: rn.molecule_search(element_pool={ 'C': 2, 'H': 6 }, multiple_bond_search=False) molecules = rn.load_molecules() assert (len(molecules) == 17) for i, molecule in molecules.items(): plot_molecule(molecule, file_name='./images/molecule-{}.png'.format(i)) molecule = get_uff_coordinates(molecule, steps=50) rn.save_3d_structure(molecule) images = rn.load_3d_structures() assert (len(images) == 17) rn.path_search(reconfiguration=False, substitution=False) rn.plot_reaction_network(file_name='./images/reaction-network.png') pathways = rn.load_pathways() assert (len(pathways) == 27) names = np.empty(len(molecules) + 1, dtype='a5') names[0] = '' for k, v in molecules.items(): atn = nx.get_node_attributes(v.graph, 'number') hill = formula_hill(list(atn.values())) names[k] = hill for path in pathways: print('|{} + {} --> {} + {}|'.format(*names[path])) os.unlink(db_name)
def get_chemical_formula(self, mode='hill', empirical=False): """Get chemical formula. See documentation of ase.atoms.Atoms.get_chemical_formula().""" if mode in ('reduce', 'all') and empirical: warnings.warn("Empirical chemical formula not available " "for mode '{}'".format(mode)) if len(self) == 0: return '' numbers = self.numbers if mode == 'reduce': n = len(numbers) changes = np.concatenate( ([0], np.arange(1, n)[numbers[1:] != numbers[:-1]])) symbols = [chemical_symbols[e] for e in numbers[changes]] counts = np.append(changes[1:], n) - changes tokens = [] for s, c in zip(symbols, counts): tokens.append(s) if c > 1: tokens.append(str(c)) formula = ''.join(tokens) elif mode == 'hill': formula = formula_hill(numbers, empirical=empirical) elif mode == 'all': formula = ''.join([chemical_symbols[n] for n in numbers]) elif mode == 'metal': formula = formula_metal(numbers, empirical=empirical) else: raise ValueError("Use mode = 'all', 'reduce', 'hill' or 'metal'.") return formula
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, basestring): 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, basestring): name = formula_hill(count) 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 __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. """ filter = parse_formula(filter)[0] self.verbose = verbose self.species = {} self.references = [] for name, energy in references: if isinstance(name, basestring): count = parse_formula(name)[0] else: count = name name = formula_hill(count) if filter and any(symbol not in filter for symbol in count): continue 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)) self.symbols = [None] * len(self.species) 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('{0:<5}{1:10}{2:10.3f}'.format(i, name, energy)) self.points = np.zeros((len(self.references), len(self.species) + 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 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 __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. """ filter = parse_formula(filter)[0] self.verbose = verbose self.species = {} self.references = [] for name, energy in references: if isinstance(name, basestring): count = parse_formula(name)[0] else: count = name name = formula_hill(count) if filter and any(symbol not in filter for symbol in count): continue 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)) self.symbols = [None] * len(self.species) 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('{0:<5}{1:10}{2:10.3f}'.format(i, name, energy)) self.points = np.zeros((len(self.references), len(self.species) + 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 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))