def atoms_and_bonds_from_structure(structure, atom_types, bond_types):
    """
    Defines the atoms and bonds from the structure and given information from params.
    
    Args:
        structure (obj): A pymatgen structural object created from the transformed matrix structure, with forces included as site properties.
        atom_types (list(obj)): AtomType objects including atom_type_index (int), label (str), mass (float), charge (float), and core_shell (str).
        bond_types (list(obj)): BondType objects including bond_type_index (int) and label (str).

    Returns:
        atoms (list(obj)): Atom objects including atom_index (int), molecule_index (int), coords (np.array), forces (np.array), and atom_type (obj:AtomType).
        bonds (list(obj)): Bond objects including bond_index (int), atom_indices (list(int)), and bond_type (obj:BondType).
    """
    atoms = []
    bonds = []
    atom_types_dict = {}
    atom_types_dict = {at.label: at for at in atom_types}
    bond_types_dict = {}
    bond_types_dict = {bt.label: bt for bt in bond_types}
    atom_index = 0
    bond_index = 0
    molecule_index = 0
    for site in structure:
        molecule_index += 1
        if site.species_string in atom_types_dict:  # not core-shell atom
            atom_index += 1
            atom_type = atom_types_dict[site.species_string]
            atoms.append(
                Atom(atom_index=atom_index,
                     molecule_index=molecule_index,
                     coords=site.coords,
                     atom_forces=site.properties['forces'],
                     atom_type=atom_type))
        else:  # need to handle core + shell
            atom_index += 1
            atom_type = atom_types_dict[site.species_string + ' core']
            atoms.append(
                Atom(atom_index=atom_index,
                     molecule_index=molecule_index,
                     coords=site.coords,
                     atom_forces=site.properties['forces'],
                     atom_type=atom_type))
            atom_index += 1
            atom_type = atom_types_dict[site.species_string + ' shell']
            atoms.append(
                Atom(atom_index=atom_index,
                     molecule_index=molecule_index,
                     coords=site.coords,
                     atom_forces=np.array([0.0, 0.0, 0.0]),
                     atom_type=atom_type))
            bond_index += 1
            bond_type = bond_types_dict['{}-{} spring'.format(
                site.species_string, site.species_string)]
            bonds.append(
                Bond(bond_index=bond_index,
                     atom_indices=[atom_index - 1, atom_index],
                     bond_type=bond_type))
    return atoms, bonds
Ejemplo n.º 2
0
def acetylene(bond_length_ch=None, bond_length_cc=None):

    if bond_length_ch == None:
        bl_ch = param.acetylene['c-h']['angstrom']
    else:
        bl_ch = bond_length_ch

    if bond_length_cc == None:
        bl_cc = param.acetylene['c-c']['angstrom']
    else:
        bl_cc = bond_length_ch

    # Centred on [0,0,0]
    return [Atom('H',[0,0,-bl_ch-0.5*bl_cc]), Atom('C', [0,0,-0.5*bl_cc]),
                Atom('C',[0,0,0.0.5*bl_cc]), Atom('H',[0,0,bl_ch+0.5*bl_cc])]
Ejemplo n.º 3
0
    def __init__(self, xyz, nn_distance):

        # parent class StructDesignerXYZ stores atom list initialized from xyz-file
        super(BasisTB, self).__init__(xyz=xyz, nn_distance=nn_distance)

        # each entry of the dictionary stores a label of the atom species as a key and
        # corresponding Atom object as a value. Each atom object contains infomation about number,
        # energy and symmetry of the orbitals
        self._orbitals_dict = Atom.atoms_factory(self.num_of_species.keys())

        # `quantum_number_lims` counts number of species and corresponding number
        # of orbitals for each; each atom kind is enumerated
        self.quantum_numbers_lims = []
        for item in self.num_of_species.keys():
            self.quantum_numbers_lims.append(
                OrderedDict([('atoms', self.num_of_species[item]),
                             ('l', self.orbitals_dict[item].num_of_orbitals)]))

        # count total number of basis functions
        self.basis_size = 0
        for item in self.quantum_numbers_lims:
            self.basis_size += reduce(mul, item.values())

        # compute offset index for each atom
        self._offsets = [0]
        for j in xrange(len(self.atom_list) - 1):
            self._offsets.append(
                self.orbitals_dict[self.atom_list.keys()[j]].num_of_orbitals)
        self._offsets = np.cumsum(self._offsets)
def xyz_file_to_atoms(filename):
    """
    From an .xyz file get a list of atoms

    Arguments:
        filename (str): .xyz filename

    Returns:
        (list(autode.atoms.Atom)): Atoms
    """

    atoms = []

    if not os.path.exists(filename):
        raise XYZfileDidNotExist

    if not filename.endswith('.xyz'):
        raise XYZfileWrongFormat

    # Open the file that exists and should(!) be in the correct format
    with open(filename, 'r') as xyz_file:

        try:
            # First item in an xyz file is the number of atoms
            n_atoms = int(xyz_file.readline().split()[0])

        except IndexError:
            raise XYZfileWrongFormat

        # XYZ lines should be the following 2 + n_atoms lines
        xyz_lines = xyz_file.readlines()[1:n_atoms + 1]

        for line in xyz_lines:

            try:
                atom_label, x, y, z = line.split()[:4]
                atoms.append(Atom(atomic_symbol=atom_label, x=x, y=y, z=z))

            except (IndexError, TypeError, ValueError):
                raise XYZfileWrongFormat

    return atoms
Ejemplo n.º 5
0
    def read_xyz(self):
        """
        Reads info from xyz file, whose path was given as
        absolute_path when the object was instantiated.

        Raises
        ------
        ValueError
            If the xyz file has extra lines between atoms.
            If a Lattice is found that has the wrong number of parameters.
        TypeError
            If non-numeric values are found for an atom's position.

        """
        self._check_read()

        lines = iter(self.content)
        line = next(lines)
        n_atoms = 0
        while True:
            try:
                n_atoms = int(line.split()[0])
            except TypeError:
                line = next(lines)
                continue
            else:
                break

        lattice_indexes = self._find("Lattice")
        must_invent_cell = False
        if len(lattice_indexes) > 0:
            lattice_index = lattice_indexes[0]
            lattice = find_between(self.content[lattice_index], '"', '"')
            try:
                xx, xy, xz, yx, yy, yz, zx, zy, zz = tuple(lattice.split())
            except ValueError:
                raise ValueError("Lattice in xyz file is bad")
            self.atoms.cell = [[xx, xy, xz], [yx, yy, yz], [zx, zy, zz]]
        else:  # if no "Lattice" is found, atoms.cell is invented below
            lattice_index = 0
            must_invent_cell = True

        for line in self.content[lattice_index + 1:]:
            if not line[0].isalpha():
                continue
            try:
                s, x, y, z = tuple(line.split())
            except ValueError:
                continue
                # raise ValueError("xyz file has a bad format, avoid extra lines")
            try:
                xyz = [float(x), float(y), float(z)]
            except TypeError:
                raise TypeError("bad positions in file: {} {} {}".format(
                    x, y, z))

            atom = Atom(atom_type=s, position=xyz)
            self.atoms.add_atom(atom)

        if len(self.atoms) != n_atoms:
            print("WARNING: {} atoms declared in file, {} atoms found in file".
                  format(n_atoms, len(self.atoms)))

        if must_invent_cell:
            gap = 10  # angstroms
            min_x = min(atom.position[0] for atom in self.atoms)
            max_x = max(atom.position[0] for atom in self.atoms)
            min_y = min(atom.position[1] for atom in self.atoms)
            max_y = max(atom.position[1] for atom in self.atoms)
            min_z = min(atom.position[2] for atom in self.atoms)
            max_z = max(atom.position[2] for atom in self.atoms)
            xx = max_x - min_x + gap
            yy = max_y - min_y + gap
            zz = max_z - min_z + gap
            self.atoms.cell = [[xx, 0, 0], [0, yy, 0], [0, 0, zz]]
Ejemplo n.º 6
0
    def read(self):

        index_start = self._find("Number of particles")[0]
        index_auxiliary = None
        index_atoms = None
        self.number_of_particles = int(self.content[index_start].split()[-1])

        h0_11, h0_12, h0_13, h0_21, h0_22, h0_23, h0_31, h0_32, h0_33 = 0, 0, 0, 0, 0, 0, 0, 0, 0

        if len(self._find(".NO_VELOCITY.")) == 1:
            self.has_velocity = False

        if len(self._find("A = 1 Angstrom")) == 0:
            print(
                "WARNING: distance units in cfg file may not be in Angstroms!")

        for (index, line) in enumerate(self.content[index_start:],
                                       index_start):
            if line.startswith("H0"):
                if "H0(1,1)" in line:
                    h0_11 = float(line.split()[-2])
                elif "H0(1,2)" in line:
                    h0_12 = float(line.split()[-2])
                elif "H0(1,3)" in line:
                    h0_13 = float(line.split()[-2])
                elif "H0(2,1)" in line:
                    h0_21 = float(line.split()[-2])
                elif "H0(2,2)" in line:
                    h0_22 = float(line.split()[-2])
                elif "H0(2,3)" in line:
                    h0_23 = float(line.split()[-2])
                elif "H0(3,1)" in line:
                    h0_31 = float(line.split()[-2])
                elif "H0(3,2)" in line:
                    h0_32 = float(line.split()[-2])
                elif "H0(3,3)" in line:
                    h0_33 = float(line.split()[-2])
            elif "entry_count" in line:
                self.entry_count = int(line.split()[-1])
                n_standard_args = 6 if self.has_velocity else 3
                for _ in range(self.entry_count - n_standard_args):
                    self.auxiliary.append(None)
                index_auxiliary = index + 1
                break
            else:
                continue

        self.atoms.cell = [[h0_11, h0_12, h0_13], [h0_21, h0_22, h0_23],
                           [h0_31, h0_32, h0_33]]

        for (index, line) in enumerate(self.content[index_auxiliary:],
                                       index_auxiliary):
            if line.startswith("auxiliary"):
                i = int(find_between(line, "[", "]"))
                _, __, auxiliary = tuple(line.split())
                self.auxiliary[i] = auxiliary
            else:
                index_atoms = index
                break

        for i in range(index_atoms, len(self.content), 3):
            typ = clear_end(self.content[i + 1], [" ", "\n", "\t"])
            if typ in self.ignore_types:
                continue
            mass = float(self.content[i + 0])
            etc = dict()
            if self.has_velocity:
                raise TypeError("cfg with velocities! not implemented yet!")
            else:
                x, y, z, *args = tuple(self.content[i + 2].split())
                atom = Atom(atom_type=typ,
                            position=[float(x), float(y),
                                      float(z)])
                atom.position = np.matmul(self.atoms.cell, atom.position)
                atom.type.mass = mass
                for (index, arg) in enumerate(args):
                    etc[self.auxiliary[index]] = arg  # string
                atom.etc = etc
                self.atoms.add_atom(atom)

        if self.number_of_particles != len(
                self.atoms) and not self.ignore_types:
            print("WARNING: file says {} atoms, but only {} were found".format(
                self.number_of_particles, len(self.atoms)))
Ejemplo n.º 7
0
    def check_bond_dissociation_energy_and_isomorphic_and_rings(
            self, bond_list, bbond_list):
        energy = 0.0

        reactant_graph = self.reac_mol_graph
        atoms = [
            Atom(atomic_symbol=reactant_graph.atoms[i].label)
            for i in range(reactant_graph.n_atoms)
        ]
        product = Species(atoms)
        graph = nx.Graph()

        for i in range(reactant_graph.n_atoms):
            graph.add_node(i,
                           atom_label=reactant_graph.atoms[i].label,
                           stereo=False)

        if bond_list is not None:
            [
                graph.add_edge(bond[0], bond[1], pi=False, active=False)
                for bond in bond_list
            ]
            product.graph = graph

        # Filter the isomorphic
        if is_isomorphic(reactant_graph.graph, product.graph):
            return False
        elif self.check_four_and_three_membered_rings(product.graph):
            return False
        else:
            # Filter the bond dissociation energy
            num = sum([bb[2] for bb in bbond_list])
            for break_bond in bbond_list:
                first_atom = reactant_graph.atoms[break_bond[0]].label
                second_atom = reactant_graph.atoms[break_bond[1]].label
                bond_type = break_bond[2]
                supported_element = ['C', 'N', 'H', 'O', 'S', 'Cl', 'Si']
                if first_atom not in supported_element or second_atom not in supported_element:
                    # use 100 instead
                    energy += 100
                else:
                    # consider if break double bond (2-->1 not break 2) then the bond dissociation use double bond energy - single bond energy
                    if num >= 3 and bond_type >= 2:
                        try:
                            energy += props.bond_dissociation_energy[
                                first_atom, second_atom, bond_type]
                            energy -= props.bond_dissociation_energy[
                                first_atom, second_atom, bond_type - 1]
                        except:
                            energy += props.bond_dissociation_energy[
                                second_atom, first_atom, bond_type]
                            energy -= props.bond_dissociation_energy[
                                second_atom, first_atom, bond_type - 1]
                    else:
                        try:
                            energy += props.bond_dissociation_energy[
                                first_atom, second_atom, bond_type]
                        except:
                            energy += props.bond_dissociation_energy[
                                second_atom, first_atom, bond_type]

            if energy / _constants.CAL2J > self.bond_dissociation_cutoff:
                return False
            else:
                return True
Ejemplo n.º 8
0
def carbon_dioxide(bond_length=None):
    if bond_length == None:
        bl = param.carbon_dioxide['c-h']['angstrom']
    else:
        bl = bond_length
    return [Atom('C', [0,0,0]), Atom('O', [0,0,-bl]), Atom('O',[0,0,bl])]
Ejemplo n.º 9
0
 def _water(r1 , r2 , theta):
     molecule = [Atom('O', [0, 0, 0]),
                 Atom('H', [0,  r1 * np.sin(theta / 2), r1 * np.cos(theta / 2)]),
                 Atom('H', [0, -r2 * np.sin(theta / 2), r2 * np.cos(theta / 2)])]
     return molecule