def __add__(self, other) -> "MullikenContribution":
     l = "".join(set([self.l, other.l]))
     d = self.contribution + other.contribution
     s1 = string2symbols(self.symbol)
     s2 = string2symbols(other.symbol)
     s = Formula.from_list(s1 + s2).format("reduce")
     return MullikenContribution(s, d, l)
示例#2
0
def check(key_value_pairs):
    for key, value in key_value_pairs.items():
        if not word.match(key) or key in reserved_keys:
            raise ValueError('Bad key: {}'.format(key))
        try:
            string2symbols(key)
        except ValueError:
            pass
        else:
            warnings.warn(
                'It is best not to use keys ({0}) that are also a '
                'chemical formula.  If you do a "db.select({0!r})",'
                'you will not find rows with your key.  Instead, you wil get '
                'rows containing the atoms in the formula!'.format(key))
        if not isinstance(value, (numbers.Real, basestring, np.bool_)):
            raise ValueError('Bad value for {!r}: {}'.format(key, value))
        if isinstance(value, basestring):
            for t in [int, float]:
                if str_represents(value, t):
                    raise ValueError('Value ' + value +
                                     ' is put in as string ' +
                                     'but can be interpreted as ' +
                                     '{}! Please convert '.format(t.__name__) +
                                     'to {} using '.format(t.__name__) +
                                     '{}(value) before '.format(t.__name__) +
                                     'writing to the database OR change ' +
                                     'to a different string.')
示例#3
0
 def __add__(self, other) -> "DOSContribution":
     assert (self.values.shape == other.values.shape
             ), "DOS contributions shape does not match for addition."
     d = self.values + other.values
     l = "".join(set([self.l, other.l]))
     s1 = string2symbols(self.symbol)
     s2 = string2symbols(other.symbol)
     s = Formula.from_list(s1 + s2).format("reduce").format("metal")
     return DOSContribution(s, d, l)
示例#4
0
文件: bulk.py 项目: shuchingou/ase
def _orthorhombic_bulk(name, crystalstructure, a, covera=None, u=None):
    if crystalstructure == 'fcc':
        b = a / sqrt(2)
        atoms = Atoms(2 * name,
                      cell=(b, b, a),
                      pbc=True,
                      scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)])
    elif crystalstructure == 'bcc':
        atoms = Atoms(2 * name,
                      cell=(a, a, a),
                      pbc=True,
                      scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)])
    elif crystalstructure == 'hcp':
        atoms = Atoms(4 * name,
                      cell=(a, a * sqrt(3), covera * a),
                      scaled_positions=[(0, 0, 0), (0.5, 0.5, 0),
                                        (0.5, 1 / 6, 0.5), (0, 2 / 3, 0.5)],
                      pbc=True)
    elif crystalstructure == 'diamond':
        atoms = _orthorhombic_bulk(2 * name, 'zincblende', a)
    elif crystalstructure == 'zincblende':
        s1, s2 = string2symbols(name)
        b = a / sqrt(2)
        atoms = Atoms(2 * name,
                      cell=(b, b, a),
                      pbc=True,
                      scaled_positions=[(0, 0, 0), (0.5, 0, 0.25),
                                        (0.5, 0.5, 0.5), (0, 0.5, 0.75)])
    elif crystalstructure == 'rocksalt':
        s1, s2 = string2symbols(name)
        b = a / sqrt(2)
        atoms = Atoms(2 * name,
                      cell=(b, b, a),
                      pbc=True,
                      scaled_positions=[(0, 0, 0), (0.5, 0.5, 0),
                                        (0.5, 0.5, 0.5), (0, 0, 0.5)])
    elif crystalstructure == 'cesiumchloride':
        atoms = Atoms(name,
                      cell=(a, a, a),
                      pbc=True,
                      scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)])
    elif crystalstructure == 'wurtzite':
        u = u or 0.25 + 1 / 3 / covera**2
        atoms = Atoms(4 * name,
                      cell=(a, a * 3**0.5, covera * a),
                      scaled_positions=[(0, 0, 0), (0, 1 / 3, 0.5 - u),
                                        (0, 1 / 3, 0.5), (0, 0, 1 - u),
                                        (0.5, 0.5, 0), (0.5, 5 / 6, 0.5 - u),
                                        (0.5, 5 / 6, 0.5), (0.5, 0.5, 1 - u)],
                      pbc=True)
    else:
        raise incompatible_cell(want='orthorhombic', have=crystalstructure)

    return atoms
示例#5
0
    def strain(self, atoms=None):
        """Return a fingerprint with the espected strain of the
        site atoms and the termination atoms.

        Parameters
        ----------
        atoms : object
            ASE Atoms object.

        Returns
        ----------
        features : list
            If None was passed, the elements are strings, naming the feature.
        """
        if atoms is None:
            return ['strain_site', 'strain_term']
        else:
            if ('key_value_pairs' in atoms.info and
                    'term' in atoms.info['key_value_pairs']):
                term = atoms.info['key_value_pairs']['term']
                term_numbers = [atomic_numbers[s] for s in
                                string2symbols(term)]
            elif 'termination_atoms' in atoms.subsets:
                term = atoms.subsets['termination_atoms']
                term_numbers = atoms.numbers[term]
            else:
                raise NotImplementedError("strain fingerprint.")
            if ('key_value_pairs' in atoms.info and
                    'bulk' in atoms.info['key_value_pairs']):
                bulk = atoms.info['key_value_pairs']['bulk']
                bulk_numbers = [atomic_numbers[s] for s in
                                string2symbols(bulk)]
            elif 'bulk_atoms' in atoms.subsets:
                bulk = atoms.subsets['bulk_atoms']
                bulk_numbers = atoms.numbers[bulk]
            else:
                raise NotImplementedError("strain fingerprint.")
            site = atoms.subsets['site_atoms']
            site_numbers = atoms.numbers[site]
            rbulk = []
            rterm = []
            rsite = []
            for b in bulk_numbers:
                rbulk.append(get_radius(b))
            for t in term_numbers:
                rterm.append(get_radius(t))
            for z in site_numbers:
                rsite.append(get_radius(z))
            av_term = np.average(rterm)
            av_bulk = np.average(rbulk)
            av_site = np.average(rsite)
            strain_site = (av_site - av_bulk) / av_bulk
            strain_term = (av_term - av_bulk) / av_bulk
            return [strain_site, strain_term]
示例#6
0
    def bulk(self, atoms=None):
        """Return a fingerprint vector with propeties averaged over
        the bulk atoms.

        Parameters
        ----------
        atoms : object
            ASE Atoms object.

        Returns
        ----------
        features : list
            If None was passed, the elements are strings, naming the feature.
        """
        labels = make_labels(self.slab_params, '', '_bulk')
        labels.append('ground_state_magmom_bulk')
        if atoms is None:
            return labels
        else:
            if ('key_value_pairs' in atoms.info and
                    'bulk' in atoms.info['key_value_pairs']):
                bulk = atoms.info['key_value_pairs']['bulk']
                numbers = [atomic_numbers[s] for s in string2symbols(bulk)]
            elif 'bulk_atoms' in atoms.subsets:
                bulk = atoms.subsets['bulk_atoms']
                numbers = atoms.numbers[bulk]
            else:
                raise NotImplementedError("bulk fingerprint.")
            dat = list_mendeleev_params(numbers, params=self.slab_params)
            result = list(np.nanmean(dat, axis=0))
            result += [np.nanmean([gs_magmom[z] for z in numbers])]
            check_labels(labels, result, atoms)
            return result
示例#7
0
    def term(self, atoms=None):
        """Return a fingerprint vector with propeties averaged over the
        termination atoms.

        Parameters
        ----------
        atoms : object
        """
        labels = make_labels(self.slab_params, '', '_term')
        labels.append('ground_state_magmom_term')
        if atoms is None:
            return labels
        else:
            if ('key_value_pairs' in atoms.info and
                    'term' in atoms.info['key_value_pairs']):
                term = atoms.info['key_value_pairs']['term']
                numbers = [atomic_numbers[s] for s in string2symbols(term)]
            elif 'termination_atoms' in atoms.subsets:
                term = atoms.subsets['termination_atoms']
                numbers = atoms.numbers[term]
            else:
                raise NotImplementedError("termination fingerprint.")
            dat = list_mendeleev_params(numbers, params=self.slab_params)
            result = list(np.nanmean(dat, axis=0))
            result += [np.nanmean([gs_magmom[z] for z in numbers])]
            check_labels(labels, result, atoms)
            return result
def dia_100_2x1(sym, a0):
    sym = string2symbols(sym)
    if len(sym) == 1:
        a = Diamond(sym[0],
                    size             = [2*nx, nx, nz],
                    latticeconstant  = a0,
                    directions=[ [1,-1,0], [1,1,0], [0,0,1] ]
                    )
    else:
        a = B3(sym,
               size             = [2*nx, nx, nz],
               latticeconstant  = a0,
               directions=[ [1,-1,0], [1,1,0], [0,0,1] ]
               )
    sx, sy, sz = a.get_cell().diagonal()
    a.translate([sx/(8*nx), sy/(8*nx), sz/(8*nz)])

    bulk = a.copy()
    
    for i in a:
        if i.z < sz/(4*nz) or i.z > sz-sz/(4*nz):
            if i.x < sx/2:
                i.x = i.x+0.5
            else:
                i.x = i.x-0.5

    return bulk, a
示例#9
0
def formula2ads_index(atoms, species):
    """Return the indexes of atoms, which have symbols matching the chemical
    formula of the adsorbate. This function will not work for adsorbates
    containing the same elements as the slab.

    Parameters
    ----------
    atoms : ase atoms object.
        atoms.info must be a dictionary containing the key 'key_value_pairs',
        which is expected to contain CatMAP standard adsorbate structure
        key value pairs. See the ase db to catmap module in catmap.
        the key value pair 'species' must be the
        chemical formula of the adsorbate.
    species : str
        chemical formula of the adsorbate.
    """
    try:
        composition = string2symbols(species)
    except ValueError:
        print(species)
        raise
    ads_atoms = [a.index for a in atoms if a.symbol in composition]
    if sorted(symbols2numbers(species)) != sorted(atoms[ads_atoms].numbers):
        raise AssertionError("ads atoms identification by formula failed.")
    return ads_atoms
示例#10
0
def dia_100_2x1(sym, a0):
    sym = string2symbols(sym)
    if len(sym) == 1:
        a = Diamond(sym[0],
                    size=[2 * nx, nx, nz],
                    latticeconstant=a0,
                    directions=[[1, -1, 0], [1, 1, 0], [0, 0, 1]])
    else:
        a = B3(sym,
               size=[2 * nx, nx, nz],
               latticeconstant=a0,
               directions=[[1, -1, 0], [1, 1, 0], [0, 0, 1]])
    sx, sy, sz = a.get_cell().diagonal()
    a.translate([sx / (8 * nx), sy / (8 * nx), sz / (8 * nz)])

    bulk = a.copy()

    for i in a:
        if i.z < sz / (4 * nz) or i.z > sz - sz / (4 * nz):
            if i.x < sx / 2:
                i.x = i.x + 0.5
            else:
                i.x = i.x - 0.5

    return bulk, a
    def plot_majority_contribution(
        self,
        contributions=[],
        axes=None,
        colors=[],
        labels=[],
        show_colorbar=True,
        **kwargs,
    ):
        """Utility function to show majority contributions of given list of contributions.

        A majority-projection only shows the largest contribution to each k-point and band.
        """
        kwargs = self._process_kwargs(kwargs)
        kwargs["mode"] = "majority"

        if contributions == []:
            species = list(
                dict.fromkeys(
                    string2symbols(self.structure.get_chemical_formula())))
            contributions = [(j, "tot") for j in species]
            labels = species

        self.plot_contributions(
            axes=axes,
            contributions=contributions,
            colors=colors,
            labels=labels,
            show_colorbar=show_colorbar,
            **kwargs,
        )
        return axes
    def plot_all_species(self,
                         axes=None,
                         l="tot",
                         colors=[],
                         show_legend=True,
                         **kwargs):
        """Utility function to all show species contributions.

        Args:
            l (str, optional): Angular momentum. Defaults to "tot".
        """
        kwargs = self._process_kwargs(kwargs)

        species = list(
            dict.fromkeys(string2symbols(
                self.structure.get_chemical_formula())))
        contributions = [(j, "tot") for j in species]
        labels = species

        if len(colors) == 0:
            colors = [jmol_colors[symbols2numbers(n)][0] for n in labels]

        assert len(labels) == len(
            colors), "Number of symbols does not match number of colors."

        self.plot_contributions(
            axes=axes,
            contributions=contributions,
            colors=colors,
            labels=labels,
            show_legend=show_legend,
            **kwargs,
        )
        return axes
示例#13
0
def formula2stoich(formula):
    symbols = string2symbols(formula)
    unique_symbols = list(set(symbols))
    count = [symbols.count(us) for us in unique_symbols]
    idx = np.argsort(count)
    count = [count[i] for i in idx]
    unique_symbols = [unique_symbols[i] for i in idx]
    stoich = '_'.join([str(c) for c in count])
    return stoich, unique_symbols
示例#14
0
def build_molecule(args):
    try:
        # Known molecule or atom?
        atoms = molecule(args.name)
    except NotImplementedError:
        symbols = string2symbols(args.name)
        if len(symbols) == 1:
            Z = atomic_numbers[symbols[0]]
            magmom = ground_state_magnetic_moments[Z]
            atoms = Atoms(args.name, magmoms=[magmom])
        elif len(symbols) == 2:
            # Dimer
            if args.bond_length is None:
                b = (covalent_radii[atomic_numbers[symbols[0]]] +
                     covalent_radii[atomic_numbers[symbols[1]]])
            else:
                b = args.bond_length
            atoms = Atoms(args.name, positions=[(0, 0, 0),
                                                (b, 0, 0)])
        else:
            raise ValueError('Unknown molecule: ' + args.name)
    else:
        if len(atoms) == 2 and args.bond_length is not None:
            atoms.set_distance(0, 1, args.bond_length)

    if args.unit_cell is None:
        if args.vacuum:
            atoms.center(vacuum=args.vacuum)
        else:
            atoms.center(about=[0, 0, 0])
    else:
        a = [float(x) for x in args.unit_cell.split(',')]
        if len(a) == 1:
            cell = [a[0], a[0], a[0]]
        elif len(a) == 3:
            cell = a
        else:
            a, b, c, alpha, beta, gamma = a
            degree = np.pi / 180.0
            cosa = np.cos(alpha * degree)
            cosb = np.cos(beta * degree)
            sinb = np.sin(beta * degree)
            cosg = np.cos(gamma * degree)
            sing = np.sin(gamma * degree)
            cell = [[a, 0, 0],
                    [b * cosg, b * sing, 0],
                    [c * cosb, c * (cosa - cosb * cosg) / sing,
                     c * np.sqrt(
                        sinb**2 - ((cosa - cosb * cosg) / sing)**2)]]
        atoms.cell = cell
        atoms.center()

    atoms.pbc = args.periodic

    return atoms
示例#15
0
def slab_positions2ads_index(atoms, slab, species):
    """Return the indexes of adsorbate atoms identified by comparing positions
    to a reference slab structure.

    Parameters
    ----------
    atoms : object
    """
    composition = string2symbols(species)
    ads_atoms = []
    for symbol in composition:
        if (composition.count(symbol) == atoms.get_chemical_symbols().count(
                symbol)):
            ads_atoms += [
                atom.index for atom in atoms if atom.symbol == symbol
            ]

    ua_ads, uc_ads = np.unique(ads_atoms, return_counts=True)
    ua_comp, uc_comp = np.unique(composition, return_counts=True)
    if ua_ads == ua_comp and uc_ads == uc_comp:
        return ads_atoms

    p_a = atoms.get_positions()
    p_r = slab.get_positions()

    for s in composition:
        if s in np.array(atoms.get_chemical_symbols())[ads_atoms]:
            continue
        symbol_count = composition.count(s)
        index_a = np.where(np.array(atoms.get_chemical_symbols()) == s)[0]
        index_r = np.where(np.array(slab.get_chemical_symbols()) == s)[0]
        _, dist = get_distances(p_a[index_a, :],
                                p2=p_r[index_r, :],
                                cell=atoms.cell,
                                pbc=True)
        # Assume all slab atoms are closest to their reference counterpart.
        deviations = np.min(dist, axis=1)
        # Sort deviations.
        ascending = np.argsort(deviations)
        # The highest deviations are assumed to be new atoms.
        ads_atoms += list(index_a[ascending[-symbol_count:]])

    # Final check.
    ua_ads, uc_ads = np.unique(np.array(
        atoms.get_chemical_symbols())[ads_atoms].sort(),
                               return_counts=True)
    ua_comp, uc_comp = np.unique(composition.sort(), return_counts=True)
    if ua_ads != ua_comp:
        msg = str(ua_ads) + " != " + str(ua_comp)
        raise AssertionError(msg)
    elif uc_ads != uc_comp:
        msg = str(uc_ads) + " != " + str(uc_comp)
        raise AssertionError(msg)

    return ads_atoms
示例#16
0
 def set_symbol(self, symbol):
     assert type(symbol) == str, "Symbol must be a string."
     try:
         s = string2symbols(symbol)
     except Exception as expt:
         raise Exception(
             "String could not be interpreted as atomic symbols.")
     assert all(k in chemical_symbols
                for k in s), "Symbol is not an element from the PSE."
     s = Formula.from_list(s).format("reduce").format("metal")
     self._symbol = s
示例#17
0
def get_atomtypes_from_formula(formula):
    """Return atom types from chemical formula (optionally prepended
    with and underscore).
    """
    from ase.symbols import string2symbols
    symbols = string2symbols(formula.split('_')[0])
    atomtypes = [symbols[0]]
    for s in symbols[1:]:
        if s != atomtypes[-1]:
            atomtypes.append(s)
    return atomtypes
示例#18
0
def parse_formula(formula):
    aq = formula.endswith('(aq)')
    if aq:
        formula = formula[:-4]
    charge = formula.count('+') - formula.count('-')
    if charge:
        formula = formula.rstrip('+-')
    count = {}
    for symbol in string2symbols(formula):
        count[symbol] = count.get(symbol, 0) + 1
    return count, charge, aq
示例#19
0
def connectivity2ads_index(atoms, species):
    """Return the indexes of atoms from the global list of adsorbate symbols.

    Parameters
    ----------
    atoms : object
        ASE atoms object with connectivity attached.
        This represents an adsorbate*slab structure.
    species : str
        chemical formula of the adsorbate.
    """
    composition = string2symbols(species)
    ads_atoms = []
    for symbol in composition:
        if (composition.count(symbol) == atoms.get_chemical_symbols().count(
                symbol)):
            ads_atoms += [
                atom.index for atom in atoms if atom.symbol == symbol
            ]

    if len(ads_atoms) == len(composition):
        return ads_atoms
    elif len(ads_atoms) == 0:
        raise AssertionError("Formula adsorbate identification failed.")

    # If an atom in species also occurs in the slab, infer by connectivity.
    connected_atoms = []
    for atom in ads_atoms:
        edges = atoms.connectivity[atom, :]
        connected_atoms += [
            i for i, bonds in enumerate(edges)
            if bonds > 0 and atoms[i].symbol in composition
            and atoms[i].symbol != atoms[atom].symbol
        ]
    ads_atoms += connected_atoms

    # Final check.
    ua_ads, uc_ads = np.unique(np.array(
        atoms.get_chemical_symbols())[ads_atoms].sort(),
                               return_counts=True)
    ua_comp, uc_comp = np.unique(composition.sort(), return_counts=True)
    if ua_ads != ua_comp:
        msg = str(ua_ads) + " != " + str(ua_comp)
        raise AssertionError(msg)
    elif uc_ads != uc_comp:
        msg = str(uc_ads) + " != " + str(uc_comp)
        raise AssertionError(msg)

    return list(np.unique(ads_atoms))
示例#20
0
def atomization_energies(E):
    """Write given atomization energies to file atomization_energies.csv."""
    Ea = {}
    fd = open('atomization_energies.csv', 'w')
    for formula in sorted(molecules):
        ea = -E[formula]
        for a in string2symbols(data[formula]['symbols']):
            ea += E[a]
        eavasp = atomization_vasp[formula][1] * kcal / mol
        Ea[formula] = (ea, eavasp)
        name = latex(data[formula]['name'])
        fd.write('`%s`, %.3f, %.3f, %+.3f\n' %
                 (name[1:-1], ea, eavasp, ea - eavasp))

    return Ea
示例#21
0
def dia_111(sym, a0):
    sym = string2symbols(sym)
    if len(sym) == 1:
        a = Diamond(sym[0],
                    size=[nx, nx, nz],
                    latticeconstant=a0,
                    directions=[[1, -1, 0], [1, 1, -2], [1, 1, 1]])
    else:
        a = B3(sym,
               size=[nx, nx, nz],
               latticeconstant=a0,
               directions=[[1, -1, 0], [1, 1, -2], [1, 1, 1]])
    sx, sy, sz = a.get_cell().diagonal()
    a.translate([sx / (12 * nx), sy / (4 * nx), sz / (12 * nz)])
    return a
示例#22
0
def dia_111_pandey(sym, a0, nx=nx, ny=nx, nz=nz):
    """2x1 Pandey reconstructed (111) surface."""
    sym = string2symbols(sym)
    if len(sym) == 1:
        a = Diamond(sym[0],
                    size             = [nx, ny, nz],
                    latticeconstant  = a0,
                    directions=[ [1,-1,0], [1,1,-2], [1,1,1] ]
                    )
    else:
        a = B3(sym,
               size             = [nx, ny, nz],
               latticeconstant  = a0,
               directions=[ [1,-1,0], [1,1,-2], [1,1,1] ]
               )
    sx, sy, sz = a.get_cell().diagonal()
    a.translate([sx/(12*nx), sy/(4*ny), sz/(6*nz)])
    a.set_scaled_positions(a.get_scaled_positions()%1.0)

    bulk = a.copy()

    bondlen = a0*sqrt(3)/4

    x, y, z = a.positions.T
    mask = np.abs(z-z.max()) < 0.1*a0
    top1, top2 = np.arange(len(a))[mask].reshape(-1, 2).T
    mask = np.logical_and(np.abs(z-z.max()) < bondlen, np.logical_not(mask))
    topA, topB = np.arange(len(a))[mask].reshape(-1, 2).T
    y[topA] += bondlen/3
    y[topB] -= bondlen/3
    y[top1] += bondlen
    x[top1] += a.cell[0,0]/(2*nx)
    x[top2] += a.cell[0,0]/(2*nx)

    mask = np.abs(z-z.min()) < 0.1*a0
    bot1, bot2 = np.arange(len(a))[mask].reshape(-1, 2).T
    mask = np.logical_and(np.abs(z-z.min()) < bondlen, np.logical_not(mask))
    botA, botB = np.arange(len(a))[mask].reshape(-1, 2).T
    y[botA] += bondlen/3
    y[botB] -= bondlen/3
    y[bot2] -= bondlen
    x[bot2] += a.cell[0,0]/(2*nx)
    x[bot1] += a.cell[0,0]/(2*nx)

    a.set_scaled_positions(a.get_scaled_positions()%1.0)

    return bulk, a
示例#23
0
def dia_111(sym, a0):
    sym = string2symbols(sym)
    if len(sym) == 1:
        a = Diamond(sym[0],
                    size             = [nx, nx, nz],
                    latticeconstant  = a0,
                    directions=[ [1,-1,0], [1,1,-2], [1,1,1] ]
                    )
    else:
        a = B3(sym,
               size             = [nx, nx, nz],
               latticeconstant  = a0,
               directions=[ [1,-1,0], [1,1,-2], [1,1,1] ]
               )
    sx, sy, sz = a.get_cell().diagonal()
    a.translate([sx/(12*nx), sy/(4*nx), sz/(12*nz)])
    return a
示例#24
0
def dia_111_pandey(sym, a0, nx=nx, ny=nx, nz=nz):
    """2x1 Pandey reconstructed (111) surface."""
    sym = string2symbols(sym)
    if len(sym) == 1:
        a = Diamond(sym[0],
                    size=[nx, ny, nz],
                    latticeconstant=a0,
                    directions=[[1, -1, 0], [1, 1, -2], [1, 1, 1]])
    else:
        a = B3(sym,
               size=[nx, ny, nz],
               latticeconstant=a0,
               directions=[[1, -1, 0], [1, 1, -2], [1, 1, 1]])
    sx, sy, sz = a.get_cell().diagonal()
    a.translate([sx / (12 * nx), sy / (4 * ny), sz / (6 * nz)])
    a.set_scaled_positions(a.get_scaled_positions() % 1.0)

    bulk = a.copy()

    bondlen = a0 * sqrt(3) / 4

    x, y, z = a.positions.T
    mask = np.abs(z - z.max()) < 0.1 * a0
    top1, top2 = np.arange(len(a))[mask].reshape(-1, 2).T
    mask = np.logical_and(np.abs(z - z.max()) < bondlen, np.logical_not(mask))
    topA, topB = np.arange(len(a))[mask].reshape(-1, 2).T
    y[topA] += bondlen / 3
    y[topB] -= bondlen / 3
    y[top1] += bondlen
    x[top1] += a.cell[0, 0] / (2 * nx)
    x[top2] += a.cell[0, 0] / (2 * nx)

    mask = np.abs(z - z.min()) < 0.1 * a0
    bot1, bot2 = np.arange(len(a))[mask].reshape(-1, 2).T
    mask = np.logical_and(np.abs(z - z.min()) < bondlen, np.logical_not(mask))
    botA, botB = np.arange(len(a))[mask].reshape(-1, 2).T
    y[botA] += bondlen / 3
    y[botB] -= bondlen / 3
    y[bot2] -= bondlen
    x[bot2] += a.cell[0, 0] / (2 * nx)
    x[bot1] += a.cell[0, 0] / (2 * nx)

    a.set_scaled_positions(a.get_scaled_positions() % 1.0)

    return bulk, a
示例#25
0
def get_formation_energies(energy_dict,ref_dict):
    formation_energies = {}
    for key in energy_dict.keys(): #iterate through keys
        E0 = energy_dict[key] #raw energy
        name,site = key.split('_') #split key into name/site
        if 'slab' not in name: #do not include empty site energy (0)
            if site == '111':
                E0 -= ref_dict[site] #subtract slab energy if adsorbed
            #remove - from transition-states
            formula = name.replace('-','')
            #get the composition as a list of atomic species
            composition = string2symbols(formula)
            #for each atomic species, subtract off the reference energy
            for atom in composition:
                E0 -= ref_dict[atom]
            #round to 3 decimals since this is the accuracy of DFT
            E0 = round(E0,3)
            formation_energies[key] = E0
    return formation_energies
示例#26
0
def get_stoich_formula(formula, return_elements=True):
    """Get element independent stoichiometry formula
    i.e. TiO2 -> AB2"""
    alphabet = list(string.ascii_uppercase)
    elem_list = string2symbols(formula)

    unique_symbols, counts = np.unique(elem_list, return_counts=True)

    sorted_idx = np.argsort(counts)

    formula = ''
    for i, j in enumerate(sorted_idx):
        if counts[j] > 1:
            formula += alphabet[i] + str(counts[j])
        else:
            formula += alphabet[i]
    if return_elements:
        return formula, unique_symbols
    else:
        return formula
示例#27
0
def solvated(symbols):
    """Extract solvation energies from database.

    symbols: str
        Extract only those molecules that contain the chemical elements
        given by the symbols string (plus water and H+).

    Data from:

        Johnson JW, Oelkers EH, Helgeson HC (1992)
        Comput Geosci 18(7):899.
        doi:10.1016/0098-3004(92)90029-Q

    and:

        Pourbaix M (1966)
        Atlas of electrochemical equilibria in aqueous solutions.
        No. v. 1 in Atlas of Electrochemical Equilibria in Aqueous Solutions.
        Pergamon Press, New York.

    Returns list of (name, energy) tuples.
    """

    if isinstance(symbols, basestring):
        symbols = set(string2symbols(symbols))
    if len(_solvated) == 0:
        for line in _aqueous.splitlines():
            energy, formula = line.split(',')
            name = formula + '(aq)'
            count, charge, aq = parse_formula(name)
            energy = float(energy) * 0.001 * units.kcal / units.mol
            _solvated.append((name, count, charge, aq, energy))
    references = []
    for name, count, charge, aq, energy in _solvated:
        for symbol in count:
            if symbol not in 'HO' and symbol not in symbols:
                break
        else:
            references.append((name, energy))
    return references
示例#28
0
def get_composition(species_string):
    """
    Convert string of species into a dictionary of species and the number of each species.

    :param species_string: A string of the reaction species. Should be a chemical formula string
                           that may also contain '-','&',or,'pe'. 'pe' is a special case corresponding
                           to a proton-electron pair and has the compositon of H, while ele corresponds to an electron and has no associated atoms.
    :type species: str

    """
    composition = {}
    # clean up transition states and electrochem
    species_string = species_string.replace('-','')
    species_string = species_string.replace('pe','H')
    species_string = species_string.replace('&','')
    species_string = species_string.replace('ele','')
    try:
        symbs = string2symbols(species_string)
        for a in set(symbs):
            composition[a] = symbs.count(a)
    except ValueError:
        composition = None
    return composition
示例#29
0
def get_composition(species_string):
    """
    Convert string of species into a dictionary of species and the number of each species.

    :param species_string: A string of the reaction species. Should be a chemical formula string
                           that may also contain '-','&',or,'pe'. 'pe' is a special case corresponding
                           to a proton-electron pair and has the compositon of H, while ele corresponds to an electron and has no associated atoms.
    :type species: str

    """
    composition = {}
    # clean up transition states and electrochem
    species_string = species_string.replace('-', '')
    species_string = species_string.replace('pe', 'H')
    species_string = species_string.replace('&', '')
    species_string = species_string.replace('ele', '')
    try:
        symbs = string2symbols(species_string)
        for a in set(symbs):
            composition[a] = symbs.count(a)
    except ValueError:
        composition = None
    return composition
示例#30
0
def get_atomization_energy(name):
    """Determine extrapolated experimental atomization energy from the database.

    The atomization energy is extrapolated from experimental heats of
    formation at room temperature, using calculated zero-point energies
    and thermal corrections.

    The atomization energy is returned in kcal/mol = 43.36 meV:

    >>> from ase.units import *; print kcal / mol
    0.0433641146392

    """
    d = data[name]
    e = d['enthalpy']
    z = d['ZPE']
    dh = d['thermal correction']
    ae = -e + z + dh
    for a in string2symbols(d['symbols']):
        h = data[a]['enthalpy']
        dh = data[a]['thermal correction']
        ae += h - dh
    return ae
示例#31
0
文件: cli.py 项目: malik-ust/CatHub
def organize(**kwargs):
    """Read reactions from non-organized folder"""

    # do argument wrangling  before turning it into an obect
    # since namedtuples are immutable
    if len(kwargs['adsorbates']) == 0:
        print("""Warning: no adsorbates specified,
        can't pick up reaction reaction energies.""")
        print("         Enter adsorbates like --adsorbates CO,O,CO2")
        print("         [Comma-separated list without spaces.]")
    kwargs['adsorbates'] = list(
        map(
            lambda x: (''.join(sorted(string2symbols(x)))),
            kwargs['adsorbates'].split(','),
        ))
    if kwargs['energy_corrections']:
        e_c_dict = {}
        for e_c in kwargs['energy_corrections'].split(','):
            key, value = e_c.split('=')
            e_c_dict.update({key: float(value)})
        kwargs['energy_corrections'] = e_c_dict

    options = collections.namedtuple('options', kwargs.keys())(**kwargs)
    _organize.main(options=options)
示例#32
0
def z2ads_index(atoms, species):
    """ Returns the indexes of the n atoms with the highest position
    in the z direction,
    where n is the number of atoms in the chemical formula from the species
    key value pair.

    Parameters
    ----------
    atoms : ase atoms object.
        atoms.info must be a dictionary containing the key 'key_value_pairs',
        which is expected to contain CatMAP standard adsorbate structure
        key value pairs. See the ase db to catmap module in catmap.
        the key value pair 'species'.
    species : str
        chemical formula of the adsorbate.
    """
    composition = string2symbols(species)
    n_ads = len(composition)
    z = atoms.get_positions()[:, 2]
    ads_atoms = np.argsort(z)[-n_ads:]
    if sorted(symbols2numbers(species)) != sorted(atoms[ads_atoms].numbers):
        raise AssertionError("adsorbate identification by z coord failed. " +
                             str(species))
    return ads_atoms
示例#33
0
def last2ads_index(atoms, species):
    """Return the indexes of the last n atoms in the atoms object, where n is
    the length of the composition of the adsorbate species. This function will
    work on atoms objects, where the slab was set up first,
    and the adsorbate was added after.

    Parameters
    ----------
    atoms : ase atoms object.
        atoms.info must be a dictionary containing the key 'key_value_pairs',
        which is expected to contain CATMAP standard adsorbate structure
        key value pairs. See the ase db to catmap module in catmap.
        the key value pair 'species' must be the
        chemical formula of the adsorbate.
    species : str
        chemical formula of the adsorbate.
    """
    n_ads = len(string2symbols(species))
    natoms = len(atoms)
    ads_atoms = list(range(natoms - n_ads, natoms))
    if sorted(symbols2numbers(species)) != sorted(atoms[ads_atoms].numbers):
        raise AssertionError("last index adsorbate identification failed.")
    warnings.warn("Adsorbate identified by last index.")
    return ads_atoms
示例#34
0
文件: bulk.py 项目: essil1/ase-laser
def bulk(name, crystalstructure=None, a=None, c=None, covera=None, u=None,
         orthorhombic=False, cubic=False):
    """Creating bulk systems.

    Crystal structure and lattice constant(s) will be guessed if not
    provided.

    name: str
        Chemical symbol or symbols as in 'MgO' or 'NaCl'.
    crystalstructure: str
        Must be one of sc, fcc, bcc, hcp, diamond, zincblende,
        rocksalt, cesiumchloride, fluorite or wurtzite.
    a: float
        Lattice constant.
    c: float
        Lattice constant.
    covera: float
        c/a ratio used for hcp.  Default is ideal ratio: sqrt(8/3).
    u: float
        Internal coordinate for Wurtzite structure.
    orthorhombic: bool
        Construct orthorhombic unit cell instead of primitive cell
        which is the default.
    cubic: bool
        Construct cubic unit cell if possible.
    """

    if covera is not None and c is not None:
        raise ValueError("Don't specify both c and c/a!")

    xref = None
    ref = {}

    if name in chemical_symbols:
        Z = atomic_numbers[name]
        ref = reference_states[Z]
        if ref is not None:
            xref = ref['symmetry']

    structures = {'sc': 1, 'fcc': 1, 'bcc': 1, 'hcp': 1, 'diamond': 1,
                  'zincblende': 2, 'rocksalt':2, 'cesiumchloride':2,
                  'fluorite': 3, 'wurtzite': 2}

    if crystalstructure is None:
        crystalstructure = xref
        if crystalstructure not in structures:
            raise ValueError('No suitable reference data for bulk {}.'
                             '  Reference data: {}'
                             .format(name, ref))

    if crystalstructure not in structures:
        raise ValueError('Unknown structure: {}.'
                         .format(crystalstructure))

    # Check name:
    n = len(string2symbols(name))
    n0 = structures[crystalstructure]
    if n != n0:
        raise ValueError('Please specify {} for {} and not {}'
                         .format(plural(n0, 'atom'), crystalstructure, n))

    if a is None:
        if xref != crystalstructure:
            raise ValueError('You need to specify the lattice constant.')
        try:
            a = ref['a']
        except KeyError:
            raise KeyError('No reference lattice parameter "a" for "{}"'
                           .format(name))

    if crystalstructure in ['hcp', 'wurtzite']:
        cubic = False
        if c is not None:
            covera = c / a
        elif covera is None:
            if xref == crystalstructure:
                covera = ref['c/a']
            else:
                covera = sqrt(8 / 3)

    if orthorhombic and crystalstructure != 'sc':
        return _orthorhombic_bulk(name, crystalstructure, a, covera, u)

    if cubic and crystalstructure in ['bcc', 'cesiumchloride']:
        return _orthorhombic_bulk(name, crystalstructure, a, covera)

    if cubic and crystalstructure != 'sc':
        return _cubic_bulk(name, crystalstructure, a)

    if crystalstructure == 'sc':
        atoms = Atoms(name, cell=(a, a, a), pbc=True)
    elif crystalstructure == 'fcc':
        b = a / 2
        atoms = Atoms(name, cell=[(0, b, b), (b, 0, b), (b, b, 0)], pbc=True)
    elif crystalstructure == 'bcc':
        b = a / 2
        atoms = Atoms(name, cell=[(-b, b, b), (b, -b, b), (b, b, -b)],
                      pbc=True)
    elif crystalstructure == 'hcp':
        atoms = Atoms(2 * name,
                      scaled_positions=[(0, 0, 0),
                                        (1 / 3, 2 / 3, 0.5)],
                      cell=[(a, 0, 0),
                            (-a / 2, a * sqrt(3) / 2, 0),
                            (0, 0, covera * a)],
                      pbc=True)
    elif crystalstructure == 'diamond':
        atoms = bulk(2 * name, 'zincblende', a)
    elif crystalstructure == 'zincblende':
        s1, s2 = string2symbols(name)
        atoms = bulk(s1, 'fcc', a) + bulk(s2, 'fcc', a)
        atoms.positions[1] += a / 4
    elif crystalstructure == 'rocksalt':
        s1, s2 = string2symbols(name)
        atoms = bulk(s1, 'fcc', a) + bulk(s2, 'fcc', a)
        atoms.positions[1, 0] += a / 2
    elif crystalstructure == 'cesiumchloride':
        s1, s2 = string2symbols(name)
        atoms = bulk(s1, 'sc', a) + bulk(s2, 'sc', a)
        atoms.positions[1, :] += a / 2
    elif crystalstructure == 'fluorite':
        s1, s2, s3 = string2symbols(name)
        atoms = bulk(s1, 'fcc', a) + bulk(s2, 'fcc', a) + bulk(s3, 'fcc', a)
        atoms.positions[1, :] += a / 4
        atoms.positions[2, :] += a * 3 / 4
    elif crystalstructure == 'wurtzite':
        u = u or 0.25 + 1 / 3 / covera**2
        atoms = Atoms(2 * name,
                      scaled_positions=[(0, 0, 0),
                                        (1 / 3, 2 / 3, 0.5 - u),
                                        (1 / 3, 2 / 3, 0.5),
                                        (0, 0, 1 - u)],
                      cell=[(a, 0, 0),
                            (-a / 2, a * sqrt(3) / 2, 0),
                            (0, 0, a * covera)],
                      pbc=True)
    else:
        raise ValueError('Unknown crystal structure: ' + crystalstructure)

    return atoms
示例#35
0
    def set_output_attrs(self,rxn_parameters):
        """
        :param rxn_parameters: Reaction parameters.
        :type rxn_parameters: list
        """
        if True in [v in self.mapper._solver_output 
                for v in self.output_variables]:
            cvgs = self._coverage
            self._coverage = list(self.solver.get_coverage( 
                    rxn_parameters,c0=cvgs)) #verify coverage

            self._rate = list(self.solver.get_rate(rxn_parameters,
                    coverages=self._coverage))

        if (
                'turnover_frequency' in self.output_variables or
                'production_rate' in self.output_variables or
                'consumption_rate' in self.output_variables or
                'rxn_direction' in self.output_variables):

            self._turnover_frequency = self.get_turnover_frequency(
                    rxn_parameters)
        
        if 'selectivity' in self.output_variables:
            self._selectivity = self.get_selectivity(rxn_parameters)
            self.output_labels['selectivity'] = self.gas_names

        if 'carbon_selectivity' in self.output_variables:
            weights = []
            for g in self.gas_names:
                name,site = g.split('_')
                weight = string2symbols(name).count('C')
                weights.append(weight)
            self._carbon_selectivity = self.get_selectivity(rxn_parameters,weights=weights)
            self.output_labels['carbon_selectivity'] = self.gas_names


        if 'rate_control' in self.output_variables:
            self._rate_control = self.get_rate_control(rxn_parameters)
            self.output_labels['rate_control'] = [self.gas_names,self.parameter_names]

        if 'selectivity_control' in self.output_variables:
            self._selectivity_control = self.get_selectivity_control(rxn_parameters)
            self.output_labels['selectivity_control'] = [self.gas_names,self.parameter_names]

        if 'rxn_order' in self.output_variables:
            self._rxn_order = self.get_rxn_order(rxn_parameters)
            self.output_labels['rxn_order'] = [self.gas_names,self.gas_names]

        if 'apparent_activation_energy' in self.output_variables:
                self._apparent_activation_energy = self.get_apparent_activation_energy(rxn_parameters)
                self.output_labels['apparent_activation_energy'] = self.gas_names

        if 'interacting_energy' in self.output_variables:
            if self.adsorbate_interaction_model in [None,'ideal']:
                self._interacting_energy = rxn_parameters
            else:
                self._interacting_energy = self.get_interacting_energies(rxn_parameters)
            self.output_labels['interacting_energy'] = self.adsorbate_names+self.transition_state_names

        if 'directional_rates' in self.output_variables:
            self._directional_rates = self.get_directional_rates(rxn_parameters)
            self.output_labels['directional_rates'] = [str(rxn) + ' forward' for rxn in self.elementary_rxns] + \
                [str(rxn) + ' reverse' for rxn in self.elementary_rxns]

        if 'turnover_frequency' in self.output_variables:
            self.output_labels['turnover_frequency'] = self.gas_names

        for out in self.output_variables:
            if out == 'production_rate':
                self._production_rate = [max(0,r) 
                        for r in self._turnover_frequency]
                self.output_labels['production_rate'] = self.gas_names
            if out == 'consumption_rate':
                self._consumption_rate = [max(0,-r) 
                        for r in self._turnover_frequency]
                self.output_labels['consumption_rate'] = self.gas_names
            if out == 'forward_rate':
                self._forward_rate = [max(0,r) 
                        for r in self._rate]
                self.output_labels['forward_rate'] = self.elementary_rxns
            if out == 'reverse_rate':
                self._reverse_rate = [max(0,-r) 
                        for r in self._rate]
                self.output_labels['reverse_rate'] = self.elementary_rxns
            if out == 'rxn_direction':
                self._rxn_direction = [np.sign(r) 
                        for r in self._turnover_frequency]
                self.output_labels['rxn_direction'] = self.elementary_rxns
            if out == 'rate_constant':
                self._rate_constant = list(self._kf)+list(self._kr)
                self.output_labels['rate_constant'] = self.elementary_rxns + self.elementary_rxns
            if out == 'forward_rate_constant':
                self._forward_rate_constant = list(self._kf)
                self.output_labels['forward_rate_constant'] = self.elementary_rxns
            if out == 'reverse_rate_constant':
                self._reverse_rate_constant = list(self._kr)
                self.output_labels['reverse_rate_constant'] = self.elementary_rxns
            if out == 'equilibrium_constant':
                self._equilibrium_constant = [kf/kr 
                        for kf,kr in zip(self._kf,self._kr)]
                self.output_labels['equilibrium_constant'] = self.elementary_rxns