Esempio n. 1
0
def _orthorhombic_bulk(name, x, a, covera=None):
    if x == '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 x == 'bcc':
        atoms = Atoms(2 * name, cell=(a, a, a), pbc=True,
                      scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)])
    elif x == '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.0 / 6.0, 0.5),
                                        (0, 2.0 / 3.0, 0.5)],
                      pbc=True)
    elif x == 'diamond':
        atoms = _orthorhombic_bulk(2 * name, 'zincblende', a)
    elif x == '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 x == '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)])
    else:
        raise RuntimeError

    return atoms
Esempio n. 2
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))
    composition = string2symbols(species)
    for a in ads_atoms:
        if atoms[a].symbol not in composition:
            raise AssertionError("last index adsorbate identification failed.")
    warnings.warn("Adsorbate identified by last index.")
    return ads_atoms
Esempio n. 3
0
def valid_pair(row):
    ads_a = row['ads_a']
    ads_b = row['ads_b']
    gas = row['comp_g']

    atoms_a = row['atoms_a']
    atoms_b = row['atoms_b']

    #a must be shorter than b, no duplicates
    if len(atoms_a) >= len(atoms_b):
        return False

    if ads_a == 's':
        if gas == ads_b:
            return True
        else:
            return False
    else:
        #If first element (binding element) equal, may be good
        if row['site_a'] != row['site_b']:
            return False
        if ads_a[0] == ads_b[0]:
            comp_a = Counter(string2symbols(ads_a))
            comp_b = Counter(string2symbols(ads_b))
            diff = comp_b - comp_a
            dcomp = list(diff.elements())
            if len(dcomp) == 1 and gas == dcomp[0]:
                return True
            else:
                return False
        else:
            return False
Esempio n. 4
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)):
            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.')
Esempio n. 5
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.')
Esempio n. 6
0
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 RuntimeError

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

        Parameters
        ----------
            atoms : object
        """
        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]
Esempio n. 8
0
File: bulk.py Progetto: jboes/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 RuntimeError

    return atoms
Esempio n. 9
0
def gen222(name=None,
           A='Sr',
           B='Mn',
           O='O',
           latticeconstant=3.9,
           mag_order='FM',
           mag_atom=None,
           m=5,
           sort=True):
    if name is not None:
        symbols = string2symbols(name)
        A, B, O, _, _ = symbols

    atoms = PerovskiteCubic([A, B, O], latticeconstant=latticeconstant)
    atoms = atoms.repeat([2, 2, 2])
    if sort:
        my_write_vasp('UCPOSCAR', atoms, vasp5=True, sort=True)
        atoms = read_vasp('UCPOSCAR')

    spin_dn = {
        'FM': [],
        'A': [0, 1, 4, 5],
        'C': [0, 2, 5, 7],
        'G': [0, 3, 5, 6]
    }
    if mag_order != 'PM':
        mag = np.ones(8)
        mag[np.array(spin_dn[mag_order], int)] = -1.0
        if mag_atom is None:
            atoms = set_element_mag(atoms, B, mag * m)
        else:
            atoms = set_element_mag(atoms, mag_atom, mag * m)
    return atoms
Esempio n. 10
0
File: mmbjmp.py Progetto: jboes/ase
    def __getitem__(self, name):
        d = self.data[name]
        # the index of label in labels less one
        # (compound is already as key in d)
        a = d[self.labels.index("aexp") - 1]
        if name in ["Cr2CoGa", "Mn2CoAl", "Mn2CoGe", "Fe2CoSi"]:
            # http://en.wikipedia.org/wiki/Space_group
            sg = 216
        else:
            sg = 225
        symbols = string2symbols(name)
        symbols.pop(0)
        b = crystal(
            symbols=symbols,
            basis=[(1.0 / 4, 1.0 / 4, 1.0 / 4), (0.0, 0.0, 0.0), (1.0 / 2, 1.0 / 2, 1.0 / 2)],
            spacegroup=sg,
            cellpar=[a, a, a, 90, 90, 90],
            primitive_cell=True,
        )
        # set average moments on all atoms (add + 2.0)
        magmom = d[self.labels.index("mexp") - 1] + 2.0
        m = [magmom / len(b)] * len(b)
        # break spin symmetry between atoms no. 1 and 2
        m[1] = m[1] + m[2]
        m[2] = -m[2]
        b.set_initial_magnetic_moments(m)
        if 0:
            from ase.visualize import view

            view(b)

        return b
Esempio n. 11
0
def layers2ads_index(atoms, species):
    """ Returns the indexes of atoms in layers exceeding the number of layers
    stored in the key value pair 'layers'.

    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 and 'layers' must be an integer.
    species : str
        chemical formula of the adsorbate.
    """
    lz, li = auto_layers(atoms)
    layers = int(atoms.info['key_value_pairs']['layers'])
    ads_atoms = [a.index for a in atoms if li[a.index] > layers - 1]
    natoms = len(atoms)
    composition = string2symbols(species)
    n_ads = len(composition)
    ads_atoms = list(range(natoms - n_ads, natoms))
    if len(ads_atoms) != len(composition):
        raise AssertionError("ads atoms identification by layers failed.")
    return ads_atoms
Esempio n. 12
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
Esempio n. 13
0
def get_parameters(file, number=2):
    file = open(file)
    text = file.read()
    file.close()

    # Find elements
    s = -1
    for i in range(number):
        s = text.find('Optimization', s + 1)
        if s < 0:
            raise ValueError("No results in file (keyword Optimization missing in file)")
    e = text.find('\n', s)
    errfunc = float(text[s:e].split()[6])
    result = {}

    s = e + 1
    e = text.find('Fitting values', s) - 4
    for line in text[s:e].split('\n'):
        words = line.strip().split()
        if words[1] == 'parameters':
            elements = tuple(string2symbols(words[0]))
            result[elements] = []
        else:
            result[elements].append(float(words[1]))
    
    return result, errfunc
Esempio n. 14
0
def calc_formation_energy(symbl, ene, ref_dict, surf_name='surf'):
    """
    calculate the formation energy in terms of the symbol,  the energy and the reference energy dictory 
       <symbl> can CH2, CH2_s etc. 
    in ref_dict, the pure surface is denoted as 'slab'
    """

    from ase.atoms import string2symbols
    E0 = ene
    if '_s' in symbl:
        name, site = symbl.split('_')  #split key into name/site
        E0 -= ref_dict[surf_name]
    else:
        name = symbl

    #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)
    return E0
Esempio n. 15
0
    def build_system(self, name):
        try:
            # Known molecule or atom?
            atoms = molecule(name)
            if len(atoms) == 2 and self.bond_length is not None:
                atoms.set_distance(0, 1, self.bond_length)
        except NotImplementedError:
            symbols = string2symbols(name)
            if len(symbols) == 1:
                magmom = ground_state_magnetic_moments[atomic_numbers[
                    symbols[0]]]
                atoms = Atoms(name, magmoms=[magmom])
            elif len(symbols) == 2:
                # Dimer
                if self.bond_length is None:
                    b = (covalent_radii[atomic_numbers[symbols[0]]] +
                         covalent_radii[atomic_numbers[symbols[1]]])
                else:
                    b = self.bond_length
                atoms = Atoms(name, positions=[(0, 0, 0), (b, 0, 0)])
            else:
                raise ValueError('Unknown molecule: ' + name)

        if self.unit_cell is None:
            atoms.center(vacuum=self.vacuum)
        else:
            atoms.cell = self.unit_cell
            atoms.center()

        return atoms
Esempio n. 16
0
    def build_system(self, name):
        try:
            # Known molecule or atom?
            atoms = molecule(name)
            if len(atoms) == 2 and self.bond_length is not None:
                atoms.set_distance(0, 1, self.bond_length)
        except NotImplementedError:
            symbols = string2symbols(name)
            if len(symbols) == 1:
                Z = atomic_numbers[symbols[0]]
                magmom = ground_state_magnetic_moments[Z]
                atoms = Atoms(name, magmoms=[magmom])
            elif len(symbols) == 2:
                # Dimer
                if self.bond_length is None:
                    b = (covalent_radii[atomic_numbers[symbols[0]]] +
                         covalent_radii[atomic_numbers[symbols[1]]])
                else:
                    b = self.bond_length
                atoms = Atoms(name, positions=[(0, 0, 0),
                                               (b, 0, 0)])
            else:
                raise ValueError('Unknown molecule: ' + name)

        if self.unit_cell is None:
            atoms.center(vacuum=self.vacuum)
        else:
            atoms.cell = self.unit_cell
            atoms.center()

        return atoms
Esempio n. 17
0
    def bulk(self, atoms=None):
        """Return a fingerprint vector with propeties averaged over
        the bulk atoms.

        Parameters
        ----------
            atoms : object
        """
        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
Esempio n. 18
0
def get_atomic_stoichiometry(references):
    """
    Given a list of references (tuples of (symbol, molecule))
    return stoichiometry matrix that connects atomic symbols
    to its molecular references.
    """

    n = len(references)
    stoichiometry = np.ndarray((n, n), float)
    stoichiometry[:] = 0.
    key_index = {}
    for i, (key, species) in enumerate(references):

        # in case species uses a suffix like _gas
        species = species.split('_')[0]

        key_index[key] = i
        composition = string2symbols(species)
        for j, symbol in enumerate(composition):
            if symbol == key:
                stoichiometry[i, i] += 1
            else:
                stoichiometry[i, key_index[symbol]] -= 1
    for i in range(n):
        stoichiometry[i, i] = 1. / stoichiometry[i, i]

    for i in range(n):
        for j in range(n):
            if i != j:
                stoichiometry[i, j] *= stoichiometry[j, j]

    return stoichiometry.tolist()
Esempio n. 19
0
def construct_reference_system(
        symbols,
        candidates=['H2', 'H2O', 'NH3', 'CH4', 'CO', 'SH2', 'HCl', 'N2',
                    'O2']):
    """
    Take a list of symbols and construct gas phase
    references system, when possible avoiding O2.
    Candidates can be rearranged, where earlier candidates
    get higher preference than later candidates
    """

    # assume symbols sorted by atomic number
    references = {}
    added_symbols = []
    for symbol in symbols:
        added_symbols.append(symbol)
        for candidate in candidates:
            symbols = string2symbols(candidate)

            if set(added_symbols) == set(list(references.keys()) + symbols):
                references[symbol] = candidate
                break
        else:
            raise UserWarning(
                "No candidate satisfied {symbol}. Add more candidates".format(
                    **locals()))

    return sorted(references.items(),
                  key=lambda _x: ase.data.atomic_numbers[_x[0]])
Esempio n. 20
0
def molecules2symbols(molecules, add_hydrogen=True):
    """ 
    Take a list of molecules and return just a list of atomic
    symbols, possibly adding hydrogen
    """

    symbols = sorted(list(
        set(
            string2symbols(''.join(
                map(lambda _x: ''.join(string2symbols(_x)), molecules))))),
                     key=lambda _y: ase.data.atomic_numbers[_y])

    if add_hydrogen and not 'H' in symbols:
        symbols.insert(0, 'H')

    return symbols
Esempio n. 21
0
def get_stoichiometry_factors(adsorbates, references):
    """
    Take a list of adsorabtes and a corresponding reference
    system and return a list of dictionaries encoding the
    stoichiometry factors converting between adsorbates and
    reference molecules.
    """

    stoichiometry = get_atomic_stoichiometry(references)
    stoichiometry_factors = {}
    for adsorbate in adsorbates:
        for symbol in string2symbols(adsorbate):
            symbol_index = list(map(lambda _x: _x[0],
                                    references)).index(symbol)

            for (factor, (ref_symbol,
                          ref_molecule)) in zip(stoichiometry[symbol_index],
                                                references):
                stoichiometry_factors.setdefault(
                    adsorbate,
                    {})[ref_molecule] = stoichiometry_factors.setdefault(
                        adsorbate, {}).get(ref_molecule, 0) + factor

        nonzero_factors = {}
        for key, value in stoichiometry_factors[adsorbate].items():
            if not np.isclose(value, 0.):
                nonzero_factors[key] = value
        stoichiometry_factors[adsorbate] = nonzero_factors

    return stoichiometry_factors
Esempio n. 22
0
def get_formation_energies(energy_dict, ref_dict, surf_name='111'):
    """
    calculate the formation energy based on the energy data given in energy_dict using the reference energies given in ref_dict
    """
    from ase.atoms import string2symbols
    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 == surf_name:
                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
Esempio n. 23
0
def gen_primitive(name=None,A=None,B=None,O=None, latticeconstant=3.9, mag_order='FM', m=5):
    """
    generate primitive cell with magnetic order.

    Parameters:
    ---------------
    name: string
        ABO3, eg. BiFeO3, CsPbF3
    """
    if name is not None:
        symbols=string2symbols(name)
        A, B, O, _, _ = symbols
    atoms = PerovskiteCubic([A, B, O], latticeconstant=latticeconstant)
    direction_dict = {
        'A': ([1, 0, 0], [0, 1, 0], [0, 0, 2]),
        'C': ([1, -1, 0], [1, 1, 0], [0, 0, 1]),
        'G': ([0, 1, 1], [1, 0, 1], [1, 1, 0]),
        'FM': np.eye(3),
    }
    size_dict = {'A': (1, 1, 2), 'C': (1, 1, 1), 'G': (1, 1, 1)}
    A, B, O = atoms.get_chemical_symbols()[0:3]
    if mag_order == 'PM':
        atoms = atoms
    elif mag_order == 'FM':
        atoms = atoms
        atoms = set_element_mag(atoms, B, [m])
    else:
        atoms.translate([0.045] * 3)
        atoms = normalize(atoms)
        atoms = make_supercell(atoms, direction_dict[mag_order])
        atoms.translate([-0.045] * 3)
        atoms = set_element_mag(atoms, B, [m, -m])
    return atoms
Esempio n. 24
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 len(ads_atoms) != len(composition):
        raise AssertionError("ads atoms identification by formula failed.")
    return ads_atoms
Esempio n. 25
0
    def do_calculations(self, formulas):
        """Perform calculation on molecules, write results to .gpw files."""
        atoms = {}
        for formula in formulas:
            for symbol in string2symbols(formula.split('_')[0]):
                atoms[symbol] = None
        formulas = formulas + atoms.keys()

        for formula in formulas:
            if path.isfile(formula + '.gpw'):
                continue

            barrier()
            open(formula + '.gpw', 'w')
            s = molecule(formula)
            s.center(vacuum=self.vacuum)
            cell = s.get_cell()
            h = self.h
            s.set_cell((cell / (4 * h)).round() * 4 * h)
            s.center()
            calc = GPAW(h=h,
                        xc=self.xc,
                        eigensolver=self.eigensolver,
                        setups=self.setups,
                        basis=self.basis,
                        fixmom=True,
                        txt=formula + '.txt')

            if len(s) == 1:
                calc.set(hund=True)

            s.set_calculator(calc)

            if formula == 'BeH':
                calc.initialize(s)
                calc.nuclei[0].f_si = [(1, 0, 0.5, 0, 0),
                                       (0.5, 0, 0, 0, 0)]

            if formula in ['NO', 'ClO', 'CH']:
                s.positions[:, 1] += h * 1.5

            try:
                energy = s.get_potential_energy()
            except (RuntimeError, ConvergenceError):
                if rank == 0:
                    print >> sys.stderr, 'Error in', formula
                    traceback.print_exc(file=sys.stderr)
            else:
                print >> self.txt, formula, repr(energy)
                self.txt.flush()
                calc.write(formula)

            if formula in diatomic and self.calculate_dimer_bond_lengths:
                traj = PickleTrajectory(formula + '.traj', 'w')
                d = diatomic[formula][1]
                for x in range(-2, 3):
                    s.set_distance(0, 1, d * (1.0 + x * 0.02))
                    traj.write(s)
Esempio n. 26
0
def test_ddb(name):
    symbols = string2symbols(name)
    masses = [atomic_masses[atomic_numbers[s]] for s in symbols]

    # split ddb file
    dirname = "%s_PM_pjte" % name
    fname = os.path.join(dirname, 'abinito_DS2_DDB')
    reader = ddb_reader(fname)
    reader.gen_pjte_ddbs()
    ifcmat1d = get_mat1d(dirname, masses, term='TOT')
    #ifcmat1d=asr_1d(ifcmat1d)
    #print ifcmat1d
    eigvals, eigvecs = eigh(ifcmat1d, )
    s = np.sign(eigvals)
    #print eigvals
    #print "Phonon Freq (Ha):"
    #print s*np.sqrt(s*eigvals)/Ha
    print("Phonon Freq (cm-1):")
    print(s * np.sqrt(s * eigvals) * 19474.63 / Ha)
    #print np.dot(np.dot(v,ifcmat1d),v)

    
    print("--Eigen vector:--")
    v = eigvecs[:, 0]
    ifcmat1d_fr = get_mat1d(dirname, masses, term='FR')
    ifcmat1d_nfr = get_mat1d(dirname, masses, term='NFR')
    ifcmat1d_ew = get_mat1d(dirname, masses, term='EW')
    print(ifcmat1d_ew)
    print("self IFC")
    print([ifcmat1d[i,i] for i in range(5)])
    #func=lambda mat: np.sign(v)* np.sqrt(np.sign(v)*)
    def func(mat):
        eigv = np.dot(np.dot(v, mat), v)
        s = np.sign(eigv)
        return s * np.sqrt(s * eigv) * 19474.63 / Ha

    #print "w:"

    print("Total:", func(ifcmat1d))
    print("Frozen:", func(ifcmat1d_fr))
    print("Non-Frozen:", func(ifcmat1d_nfr))
    print("Ewald:", func(ifcmat1d_ew))

    for i in range(5):
        print("-- %s --"%symbols[i])
        v=[0,0,0,0,0]
        v[i]=1.0
        #func=lambda mat: np.sign(v)* np.sqrt(np.sign(v)*)
        def func(mat):
            eigv = np.dot(np.dot(v, mat), v)
            s = np.sign(eigv)
            return s * np.sqrt(s * eigv) * 19474.63 / Ha


        print("Total:", func(ifcmat1d))
        print("Frozen:", func(ifcmat1d_fr))
        print("Non-Frozen:", func(ifcmat1d_nfr))
        print("Ewald:", func(ifcmat1d_ew))
Esempio n. 27
0
    def do_calculations(self, formulas):
        """Perform calculation on molecules, write results to .gpw files."""
        atoms = {}
        for formula in formulas:
            for symbol in string2symbols(formula.split('_')[0]):
                atoms[symbol] = None
        formulas = formulas + atoms.keys()

        for formula in formulas:
            if path.isfile(formula + '.gpw'):
                continue

            barrier()
            open(formula + '.gpw', 'w')
            s = molecule(formula)
            s.center(vacuum=self.vacuum)
            cell = s.get_cell()
            h = self.h
            s.set_cell((cell / (4 * h)).round() * 4 * h)
            s.center()
            calc = GPAW(h=h,
                        xc=self.xc,
                        eigensolver=self.eigensolver,
                        setups=self.setups,
                        basis=self.basis,
                        fixmom=True,
                        txt=formula + '.txt')

            if len(s) == 1:
                calc.set(hund=True)

            s.set_calculator(calc)

            if formula == 'BeH':
                calc.initialize(s)
                calc.nuclei[0].f_si = [(1, 0, 0.5, 0, 0),
                                       (0.5, 0, 0, 0, 0)]

            if formula in ['NO', 'ClO', 'CH']:
                s.positions[:, 1] += h * 1.5

            try:
                energy = s.get_potential_energy()
            except (RuntimeError, ConvergenceError):
                if rank == 0:
                    print >> sys.stderr, 'Error in', formula
                    traceback.print_exc(file=sys.stderr)
            else:
                print >> self.txt, formula, repr(energy)
                self.txt.flush()
                calc.write(formula)

            if formula in diatomic and self.calculate_dimer_bond_lengths:
                traj = PickleTrajectory(formula + '.traj', 'w')
                d = diatomic[formula][1]
                for x in range(-2, 3):
                    s.set_distance(0, 1, d * (1.0 + x * 0.02))
                    traj.write(s)
Esempio n. 28
0
 def get_composition(species_string):
     composition = {}
     try:
         symbs = string2symbols(species_string.replace('-', ''))
         for a in set(symbs):
             composition[a] = symbs.count(a)
     except ValueError:
         composition = None
     return composition
Esempio n. 29
0
 def get_composition(species_string):
     composition = {}
     try:
         symbs = string2symbols(species_string.replace('-',''))
         for a in set(symbs):
             composition[a] = symbs.count(a)
     except ValueError:
         composition = None
     return composition
def solid_Lange(symbols,T):
    """Extract stable solid and their energies from database
       and calculate the specific Gibbs formation energies when T != 298.15 K.

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

    Data from:

        experimental literatures:  
        D. D. Wagman, et al., The NBS Tables of Chemical Thermodynamic Properties, in J. Phys. Chem. Ref. Data, 11: 2, 1982; 
        M. W. Chase, et al., JANAF Thermochemical Tables, 3rd ed., American Chemical Society and the American Institute of Physics, 
                              1986 (supplements to JANAF appear in J. Phys. Chem. Ref. Data); 
        Thermodynamic Research Center, TRC Thermodynamic Tables, Texas A&M University, College Station, Texas;
        I. Barin and O. Knacke, Thermochemical Properties of Inorganic Substances, Springer-Verlag, Berlin, 1973; 

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

    if isinstance(symbols, basestring):
        symbols = set(string2symbols(symbols))

    conn = sqlite3.connect('apps/pourbaix/data/data_ase/lange_handbook.db')
    cur = conn.cursor()
    cur.execute("SELECT * FROM lange_solids")
    rows = cur.fetchall()
    if len(_solids)==0:
        for row in rows:
            formula = row[0]
            energy =  row[4]
            heat_cap_std = row[6]
            entropy_f_std = row[7]
            name = formula + '(s)'
            count, charge, aq, s = parse_formula(name)
            if energy != "NULL":
                if T == 298.15:
                    energy = float(energy) * 0.010364   #convert from kJ/mol to eV
                    _solids.append((name, count, s, energy))
                elif T != 298.15 and entropy_f_std != "NULL" and heat_cap_std != "NULL" :
                    import math  #energy unit is eV
                    energy = (float(energy) - (T - 298.15)* float(entropy_f_std) +
                             float(heat_cap_std)/1000*(T-298.15) - 
                             2.303 * T* float(heat_cap_std)/1000*math.log10(T/298.15)) *0.010364
                    _solids.append((name, count, s, energy))

    conn.close()

    references_solid = []
    for name, count, s, energy in _solids:
        for symbol in count:
            if symbol not in 'HO' and symbol not in symbols:
                break
        else:
            references_solid.append((name, energy))
    return references_solid
Esempio n. 31
0
File: vasp.py Progetto: PHOTOX/fuase
def get_atomtypes_from_formula(formula):
    """Return atom types from chemical formula (optionally prepended
    with and underscore).
    """
    from ase.atoms import string2symbols
    symbols = string2symbols(formula.split('_')[0])
    atomtypes = [symbols[0]]
    for s in symbols[1:]:
        if s != atomtypes[-1]: atomtypes.append(s)
    return atomtypes
Esempio n. 32
0
File: vasp.py Progetto: slabanja/ase
def get_atomtypes_from_formula(formula):
    """Return atom types from chemical formula (optionally prepended
    with and underscore).
    """
    from ase.atoms import string2symbols
    symbols = string2symbols(formula.split('_')[0])
    atomtypes = [symbols[0]]
    for s in symbols[1:]:
        if s != atomtypes[-1]: atomtypes.append(s)
    return atomtypes
Esempio n. 33
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
Esempio n. 34
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
Esempio n. 35
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
Esempio n. 36
0
 def term(self, atoms=None):
     """ Returns a fingerprint vector with propeties of the element name
     saved in the atoms.info['key_value_pairs']['term'] """
     labels = ['atomic_number_term',
               'atomic_volume_term',
               'boiling_point_term',
               'density_term',
               'dipole_polarizability_term',
               'electron_affinity_term',
               'group_id_term',
               'lattice_constant_term',
               'melting_point_term',
               'period_term',
               'vdw_radius_term',
               'covalent_radius_cordero_term',
               'en_allen_term',
               'atomic_weight_term',
               'atomic_radius_term',
               'heat_of_formation_term',
               'dft_bulk_modulus_term',
               'dft_rhodensity_term',
               'dbcenter_term',
               'dbfilling_term',
               'dbwidth_term',
               'dbskew_term',
               'dbkurtosis_term',
               'oxi_min_term',
               'oxi_med_term',
               'oxi_max_term',
               'block_term',
               'ne_outer_term',
               'ne_s_term',
               'ne_p_term',
               'ne_d_term',
               'ne_f_term',
               'ionenergy_term',
               '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_length(labels, result, atoms)
         return result
Esempio n. 37
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
Esempio n. 38
0
def _orthorhombic_bulk(name, x, a, covera=None):
    if x == '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 x == 'bcc':
        atoms = Atoms(2 * name,
                      cell=(a, a, a),
                      pbc=True,
                      scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)])
    elif x == '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.0 / 6.0, 0.5),
                                        (0, 2.0 / 3.0, 0.5)],
                      pbc=True)
    elif x == 'diamond':
        atoms = _orthorhombic_bulk(2 * name, 'zincblende', a)
    elif x == '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 x == '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)])
    else:
        raise RuntimeError

    return atoms
Esempio n. 39
0
def add_ads(surf, facet, ads, site, fixed_line=True):
    """
    Add ads (string) to surf. Bonding atom is assumed to be the first in the ads string.
    e.g. CO means binding through C, OC means binding through O.
    if fixed_line == True: add fixed_line constraint to binding atom.
    """
    ads_atoms = read('%s/%s.traj' % (ads_prototype_dir, ads))
    bonding_atoms = [
        atom for atom in ads_atoms if atom.symbol == string2symbols(ads)[0]
    ]
    assert len(bonding_atoms) == 1, ""
    bonding_atom = bonding_atoms[0]
    bonding_atom_ind = bonding_atoms[0].index + len(surf)

    #figure out bonding atom position based n facet, site#
    try:  #use ase builtin method if possible
        add_adsorbate(surf, 'X', bond_lengths[site], site)
        bonding_atom_pos = surf[-1].position
        del surf[-1]
    except TypeError:
        #find top layer
        top_z = sorted(set([atom.z for atom in surf]))[-1]
        #find first atom in top layer
        top_atom_inds = [atom.index for atom in surf if atom.z == top_z]
        top_atom = surf[top_atom_inds.pop(np.argmin(
            top_atom_inds))]  #surface atom in top layer w/ lowest index
        top_atom2 = surf[top_atom_inds[np.argmin(
            surf.get_distances(top_atom.index,
                               top_atom_inds))]]  #1st NN to top_atom
        if facet == '211' and site == 'ontop':
            bonding_atom_pos = top_atom.position + np.array(
                [0, 0, bond_lengths[site]])
        elif facet == '211' and site == 'bridge':
            bonding_atom_pos = (top_atom.position +
                                top_atom2.position) / 2. + np.array(
                                    [0, 0, bond_lengths[site]])
        elif facet == '10m10' and site == 'bridge':
            bonding_atom_pos = (top_atom.position +
                                top_atom2.position) / 2. + np.array(
                                    [0, 0, bond_lengths[site]])
        else:
            raise Exception(
                "Cannot add adsorbate to %s-%s (not in ase.build.surface.add_adsorbate or custom definitions)"
                % (facet - site))

    surf += ads_atoms
    delta_vec = bonding_atom_pos - surf[bonding_atom_ind].position
    for i in range(len(surf) - len(ads_atoms), len(surf)):
        surf[i].position += delta_vec

    if fixed_line:
        surf.constraints.append(FixedLine(bonding_atom_ind, [0, 0, 1]))
    return surf
Esempio n. 40
0
def get_composition(species_string):
    composition = {}
    # clean up transition states and electrochem
    species_string = species_string.replace('-','')
    species_string = species_string.replace('pe','H')
    species_string = species_string.replace('&','')
    try:
        symbs = string2symbols(species_string)
        for a in set(symbs):
            composition[a] = symbs.count(a)
    except ValueError:
        composition = None
    return composition
Esempio n. 41
0
def _orthorhombic_bulk(name, x, a, covera=None):
    if x == "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 x == "bcc":
        atoms = Atoms(2 * name, cell=(a, a, a), pbc=True, scaled_positions=[(0, 0, 0), (0.5, 0.5, 0.5)])
    elif x == "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.0 / 6.0, 0.5), (0, 2.0 / 3.0, 0.5)],
            pbc=True,
        )
    elif x == "diamond":
        atoms = _orthorhombic_bulk(2 * name, "zincblende", a)
    elif x == "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 x == "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)],
        )
    else:
        raise RuntimeError

    return atoms
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
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
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
Esempio n. 45
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
Esempio n. 46
0
def random_solid(els, density, sx=None, sy=None):
    if isinstance(els, str):
        syms = string2symbols(els)
    else:
        syms = ""
        for sym, n in els:
            syms += n*sym
    r = np.random.rand(len(syms), 3)
    a = ase.Atoms(syms, positions=r, cell=[1,1,1], pbc=True)

    mass = np.sum(a.get_masses())
    if sx is not None and sy is not None:
        sz = ( 1e24*mass/(density*mol) )/(sx*sy)
        a.set_cell([sx,sy,sz], scale_atoms=True)
    else:
        a0 = ( 1e24*mass/(density*mol) )**(1./3)
        a.set_cell([a0,a0,a0], scale_atoms=True)
    a.set_initial_charges([0]*len(a))

    return a
def analyse(c, collection, category, category_ref=None):

    A = []
    for name in collection.names:
        ve = []  # volume, energy pairs
        for d in c.select(category=category, name=name):
            try:
                assert name == d.name
                ve.append((abs(np.linalg.det(d.cell)), d.energy))
            except AttributeError:
                ve.append((np.nan, np.nan))

        # sort according to volume
        ves = sorted(ve, key=lambda x: x[0])

        # EOS
        eos = EquationOfState([t[0] for t in ves],
                              [t[1] for t in ves])
        try:
            v, e0, B0, B1, R = eos.fit()
        except (ValueError, TypeError, LinAlgError):
            (v, e0, B0, B1, R) = (np.nan, np.nan, np.nan, np.nan, np.nan)
        if not R: R = [np.nan]  # sometimes R is an empty array
        if not isinstance(R, list): R = [R]  # sometimes R is not a list
        e = e0  # formation energy
        # number of unit formulas per cell
        nufpc = len(collection[name]) / len(string2symbols(name))
        # calculate formation energy wrt category_ref
        if category_ref:
            for d in c.select(category=category, name=name, x=1.000):
                for n in d.numbers:
                    # use gbrv structure (x=1.000)
                    for d1 in c.select(category=category_ref, name=chemical_symbols[n], x=1.000):
                        assert len(set(d1.numbers)) == 1
                        e = e - d1.energy / len(d1.numbers)
        e0 = e0 / nufpc
        e = e / nufpc
        v = v / nufpc
        B0 = B0 / kJ * 1.0e24  # GPa
        A.append((e, e0, v, B0, B1, R[0]))
    return np.array(A).T
Esempio n. 48
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, str):
        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
Esempio n. 49
0
def get_formation_energies(abinitio_energies, gas_ref_eng, surfaces,adsorbates):
    """
    Finds and prints formation energies from abinitio_energies
    Returns formation energy dictionary
    """
    ref_dict = {}
    formation_dict = {}
    ref_dict['H'] = 0.5*gas_ref_eng['H2_gas']
    ref_dict['O'] = gas_ref_eng['H2O_gas'] - 2*ref_dict['H']
    ref_dict['C'] = gas_ref_eng['CH4_gas'] - 4*ref_dict['H']
    for surf in surfaces:
        try:
            ref_dict[surf+'_clean'] = abinitio_energies[surf+'_clean']
        except:
            pass
        try:
            ref_dict[surf+'_Oc'] = abinitio_energies[surf+'_Oc']
        except:
            pass
        #Can also make ref_dict entries for those surfaces relevant to echem
        for ads in adsorbates:
            E0 = 0
            formula = ads.strip('-') #For transition states
            composition = string2symbols(formula)
            for atom in composition:
                E0 += ref_dict[atom]
            try:
                formation_dict[surf+'_'+ads+'_clean'] = abinitio_energies[surf+'_'+ads+'c'] - E0 - ref_dict[surf+'_clean']
            except:
                pass
            try:
                formation_dict[surf+'_'+ads+'_Oc'] =  abinitio_energies[surf+'_'+ads+'c+Oc'] - E0 - ref_dict[surf+'_Oc']
            except: 
                pass
    for key in sorted(formation_dict.keys()):
        surf,ads,coverage =  key.split('_')
        energy = formation_dict[key]
        print "{:10} {:10} {:10}  {:10}".format(surf, ads,coverage,energy)
    return formation_dict
Esempio n. 50
0
def get_parameters(file, number=2):
    file = open(file)
    text = file.read()
    file.close()

    # Find elements
    s = -1
    for i in range(number):
        s = text.find('Optimization', s + 1)
    s = text.find('\n', s) + 1
    e = text.find('parameters', s)
    elements = tuple(string2symbols(text[s:e].strip()))

    # Find parameters
    s = text.find('\n', e) + 1
    e = text.find('Fitting', s) - 4
    parameters = []
    for line in text[s:e].split('\n'):
        rows = line.split('  ')
        parameters.append(float(rows[2]))
    
    return elements, parameters
Esempio n. 51
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
Esempio n. 52
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
Esempio n. 53
0
def run(argv=None):
    if argv is None:
        argv = sys.argv[1:]
    elif isinstance(argv, str):
        argv = argv.split()
        
    parser = build_parser()
    opt, args = parser.parse_args(argv)
    
    if len(args) != 1:
        parser.error("incorrect number of arguments")
    name = args[0]

    if world.rank == 0:
        out = sys.stdout#open('%s-%s.results' % (name, opt.identifier), 'w')
    else:
        out = devnull

    a = None
    try:
        symbols = string2symbols(name)
    except ValueError:
        # name was not a chemical formula - must be a file name:
        atoms = read(name)
    else:
        if opt.crystal_structure:
            a = opt.lattice_constant
            if a is None:
                a = estimate_lattice_constant(name, opt.crystal_structure,
                                              opt.c_over_a)
                out.write('Using an estimated lattice constant of %.3f Ang\n' %
                          a)

            atoms = bulk(name, opt.crystal_structure, a, covera=opt.c_over_a,
                         orthorhombic=opt.orthorhombic, cubic=opt.cubic)
        else:
            try:
                # Molecule?
                atoms = molecule(name)
            except NotImplementedError:
                if len(symbols) == 1:
                    # Atom
                    atoms = Atoms(name)
                elif len(symbols) == 2:
                    # Dimer
                    atoms = Atoms(name, positions=[(0, 0, 0),
                                                   (opt.bond_length, 0, 0)])
                else:
                    raise ValueError('Unknown molecule: ' + name)

    if opt.magnetic_moment:
        magmom = opt.magnetic_moment.split(',')
        atoms.set_initial_magnetic_moments(np.tile(magmom,
                                                   len(atoms) // len(magmom)))

    if opt.repeat is not None:
        r = opt.repeat.split(',')
        if len(r) == 1:
            r = 3 * r
        atoms = atoms.repeat([int(c) for c in r])

    if opt.gui:
        view(atoms)
        return

    if opt.write_to_file:
        write(opt.write_to_file, atoms)
        return

    if opt.effective_medium_theory:
        Runner = EMTRunner
    else:
        Runner = GPAWRunner

    if opt.fit:
        strains = np.linspace(0.98, 1.02, 5)
    else:
        strains = None

    if opt.constrain_tags:
        tags = [int(t) for t in opt.constrain_tags.split(',')]
        constrain = FixAtoms(mask=[t in tags for t in atoms.get_tags()])
        atoms.constraints = [constrain]

    runner = Runner(name, atoms, strains, tag=opt.identifier,
                    clean=not opt.read,
                    fmax=opt.relax, out=out)

    if not opt.effective_medium_theory:
        # Import stuff that eval() may need to know:
        from gpaw.wavefunctions.pw import PW
        from gpaw.occupations import FermiDirac, MethfesselPaxton
            
        if opt.parameters:
            input_parameters = eval(open(opt.parameters).read())
        else:
            input_parameters = {}
        for key in defaults:
            value = getattr(opt, key)
            if value is not None:
                try:
                    input_parameters[key] = eval(value)
                except (NameError, SyntaxError):
                    input_parameters[key] = value

        runner.set_parameters(vacuum=opt.vacuum,
                              write_gpw_file=opt.write_gpw_file,
                              **input_parameters)

    runner.run()

    runner.summary(plot=opt.plot, a0=a)

    return runner
Esempio n. 54
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
Esempio n. 55
0
File: bulk.py Progetto: jboes/ase
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 raitio 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
    
    if name in chemical_symbols:
        Z = atomic_numbers[name]
        ref = reference_states[Z]
        if ref is not None:
            xref = ref['symmetry']

    if crystalstructure is None:
        crystalstructure = xref

    if a is None:
        if xref != crystalstructure:
            raise ValueError('You need to specify the lattice constant.')
        a = ref['a']

    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
Esempio n. 56
0
def evaluate_rate_expression(rate_expr, parameters={}):
    """Evaluates an expression for a typical kMC rate constant.
     External parameters can be passed in as dictionary, like the
     following:
        parameters = {'p_CO':{'value':1},
                      'T':{'value':1}}

     or as a list of parameters:
        parameters = [Parameter(), ... ]
     """
    import tokenize
    import StringIO
    import math
    from kmos import units

    # convert parameters to dict if passed as list of Parameters()
    if type(parameters) is list:
        param_dict = {}
        for parameter in parameters:
            param_dict[parameter.name] = {'value': parameter.value}
        parameters = param_dict

    if not rate_expr:
        rate_const = 0.0
    else:
        replaced_tokens = []

        # replace some aliases
        rate_expr = rate_expr.replace('beta', '(1./(kboltzmann*T))')
        try:
            input = StringIO.StringIO(rate_expr).readline
            tokens = list(tokenize.generate_tokens(input))
        except:
            raise Exception('Could not tokenize expression: %s' % input)
        for i, token, _, _, _ in tokens:
            if token in ['sqrt', 'exp', 'sin', 'cos', 'pi', 'pow', 'log']:
                replaced_tokens.append((i, 'math.' + token))
            elif token in dir(units):
                replaced_tokens.append((i, str(eval('units.' + token))))
            elif token.startswith('m_'):
                from ase.atoms import string2symbols
                from ase.data import atomic_masses
                from ase.data import atomic_numbers
                species_name = '_'.join(token.split('_')[1:])
                symbols = string2symbols(species_name)
                replaced_tokens.append((i,
                            '%s' % sum([atomic_masses[atomic_numbers[symbol]]
                            for symbol in symbols])))
            elif token.startswith('mu_'):
                # evaluate gas phase chemical potential if among
                # available JANAF tables if from current temperature
                # and corresponding partial pressure
                from kmos import species
                species_name = '_'.join(token.split('_')[1:])
                if species_name in dir(species):
                    if not 'T' in parameters:
                        raise Exception('Need "T" in parameters to evaluate chemical potential.')

                    if not ('p_%s' % species_name) in parameters:
                        raise Exception('Need "p_%s" in parameters to evaluate chemical potential.' % species_name)

                    replaced_tokens.append((i, 'species.%s.mu(%s,%s)' % (
                                   species_name,
                                   parameters['T']['value'],
                                   parameters['p_%s' % species_name]['value'],
                                   )))
                else:
                    print('No JANAF table assigned for %s' % species_name)
                    print('Setting chemical potential to zero')
                    replaced_tokens.append((i, '0'))
            elif token in parameters:
                parameter_str = str(parameters[token]['value'])
                # replace units used in parameters
                for unit in units.keys:
                    parameter_str = parameter_str.replace(
                                    unit, '%s' % eval('units.%s' % unit))
                replaced_tokens.append((i, parameter_str))
            else:
                replaced_tokens.append((i, token))

        rate_expr = tokenize.untokenize(replaced_tokens)
        try:
            rate_const = eval(rate_expr)
        except Exception, e:
            raise UserWarning(
            "Could not evaluate rate expression: %s\nException: %s" \
                % (rate_expr, e))
Esempio n. 57
0
def convpar(p):
    """
    Convert a parameter set from convenient Python dictionary to the format
    expected by the Fortran kernels.
    """

    if 'el' not in p:
        return p

    els = p['el']
    nel = len(els)

    q = { }
    for name, values in p.items():
        
        if isinstance(values, dict):
            # This is a dictionary. We need to first understand what it is and
            # then convert to the appropriate list
            m = 0
            for itype, value in values:
                if itype[0] == '_':
                    continue
                # Ask ASE to turn this into a list of symbols
                syms = string2symbols(itype)
                # Now turn this into a list of indices
                nums = [ els.index(sym) for sym in syms ]
                # We need to know the maximum number of symbols
                m = max(m, nums)

            default = 0.0
            if '__default__' in values:
                default = values['__default__']
            if m == 2:
                # These are pair indices
                new_values = [ default ]*pair_index(nel,nel,nel)
            elif m == 3:
                # These are triplet indices
                new_values = [ default ]*triplet_index(nel,nel,nel,nel)
            else:
                raise RuntimeError("Parameter '%s' appears to involve " \
                                   "interaction between %i atoms. Do not know "\
                                   "how to handle this." % ( name, nel ))

            for itype, value in values:
                if itype[0] == '_':
                    continue
                # Ask ASE to turn this into a list of symbols
                syms = string2symbols(itype)
                # Now turn this into a list of indices
                nums = [ els.index(sym) for sym in syms ]
                if len(nums) == m:
                    # Set value
                    if m == 2:
                        i,j = nums
                        new_values[pair_index(i,j,nel)] = value
                    elif m == 3:
                        i,j,k = nums
                        new_values[triple_index(i,j,k,nel)] = value
                else:
                    # We have fewer values than we need
                    if m == 3 and len(nums) == 1:
                        [k] = nums
                        for i in range(nel):
                            for j in range(nel):
                                # There is six possible permutations
                                new_values[triple_index(i,j,k,nel)] = value
                                new_values[triple_index(i,k,j,nel)] = value
                                new_values[triple_index(k,j,i,nel)] = value
                                new_values[triple_index(j,k,i,nel)] = value
                                new_values[triple_index(k,i,j,nel)] = value
                                new_values[triple_index(i,j,k,nel)] = value
                    elif m == 3 and len(nums) == 2:
                        [i,j] = nums
                        for k in range(nel):
                            # There is six possible permutations
                            new_values[triple_index(i,j,k,nel)] = value
                            new_values[triple_index(i,k,j,nel)] = value
                            new_values[triple_index(k,j,i,nel)] = value
                            new_values[triple_index(j,k,i,nel)] = value
                            new_values[triple_index(k,i,j,nel)] = value
                            new_values[triple_index(i,j,k,nel)] = value
                    else:
                        raise RuntimeError("Parameter '%s' appears to involve " \
                                           "interaction between %i atoms, but " \
                                           "only %i elements were provied. Do " \
                                           "not know how to handle this." \
                                           % ( name, nel, len(nums) ))
            values = new_values

        q[name] = values
    return q