Example #1
0
    def print_imag_vector(self, mode_number=6, name=None):
        """Print a .xyz file with multiple structures visualising the largest
        magnitude imaginary mode

        Keyword Arguments:
            mode_number (int): Number of the normal mode to visualise,
                               6 (default) is the lowest frequency vibration
                               i.e. largest magnitude imaginary, if present
            name (str):
        """
        assert self.optts_calc is not None
        name = self.name if name is None else name

        disp = -0.5
        for i in range(40):
            atoms = get_displaced_atoms_along_mode(
                calc=self.optts_calc,
                mode_number=int(mode_number),
                disp_magnitude=disp,
                atoms=self.atoms)
            atoms_to_xyz_file(atoms=atoms, filename=f'{name}.xyz', append=True)

            # Add displacement so the final set of atoms are +0.5 Å displaced
            # along the mode, then displaced back again
            sign = 1 if i < 20 else -1
            disp += sign * 1.0 / 20.0

        return None
Example #2
0
    def print_geometries(self, name):
        """Print an xyz trajectory of the geometries in the path"""

        # Empty the file
        open(f'{name}.xyz', 'w').close()

        for i, image in enumerate(self):
            assert image.species is not None
            energy = image.energy if image.energy is not None else 'none'

            atoms_to_xyz_file(image.species.atoms,
                              f'{name}.xyz',
                              title_line=f'autodE path point {i}. E = {energy}',
                              append=True)
        return None
Example #3
0
    def print_xyz_file(self, title_line='', filename=None):
        """Print a standard xyz file from the Molecule's atoms"""

        if filename is None:
            filename = f'{self.name}.xyz'

        return atoms_to_xyz_file(self.atoms, filename, title_line=title_line)
Example #4
0
def test_making_xyz_file():

    atoms = [Atom('H'), Atom('H')]

    atoms_to_xyz_file(atoms, filename='test.xyz')
    atoms_to_xyz_file(atoms, filename='test.xyz', append=False)

    xyz_lines = open('test.xyz', 'r').readlines()
    assert len(xyz_lines) == 4

    # With append should add the next set of atoms to the same file
    atoms_to_xyz_file(atoms, filename='test.xyz', append=True)

    xyz_lines = open('test.xyz', 'r').readlines()
    assert len(xyz_lines) == 8

    with pytest.raises(AssertionError):
        # Requires some atoms
        atoms_to_xyz_file(atoms=None, filename='test.xyz')

        # Needs .xyz extension
        atoms_to_xyz_file(atoms, filename='test')

    os.remove('test.xyz')
Example #5
0
def get_simanl_atoms(species, dist_consts=None, conf_n=0, save_xyz=True):
    """
    Use a bonded + repulsive force field to generate 3D structure for a
    species. If the initial coordinates are reasonable e.g. from a previously
    generated 3D structure then add random displacement vectors and minimise
    to generate a conformer. Otherwise add atoms to the box sequentially
    until all atoms have been added, which generates a qualitatively reasonable
    3D geometry which should be optimised using a electronic structure method

    V(x) = Σ_bonds k(d - d0)^2 + Σ_ij c/d^n

    Arguments:
        species (autode.species.Species):

    Keyword Arguments:
        dist_consts (dict): Key = tuple of atom indexes, Value = distance

        conf_n (int): Number of this conformer

        save_xyz (bool): Whether or not to save a .xyz file of the structure
                         for fast reloading

    Returns:
        (list(autode.atoms.Atom)): Atoms
    """
    xyz_filename = f'{species.name}_conf{conf_n}_siman.xyz'

    saved_atoms = get_atoms_from_generated_file(species, xyz_filename)
    if saved_atoms is not None:
        return saved_atoms

    # To generate the potential requires bonds between atoms defined in a
    # molecular graph
    if species.graph is None:
        raise ex.NoMolecularGraph

    # Initialise a new random seed and make a copy of the species' atoms.
    # RandomState is thread safe
    rand = np.random.RandomState()
    atoms = get_atoms_rotated_stereocentres(species=species,
                                            atoms=deepcopy(species.atoms),
                                            rand=rand)

    # Add the distance constraints as fixed bonds
    d0 = get_ideal_bond_length_matrix(atoms=species.atoms,
                                      bonds=species.graph.edges())

    # Add distance constraints across stereocentres e.g. for a Z double bond
    # then modify d0 appropriately
    dist_consts = add_dist_consts_for_stereocentres(
        species=species,
        dist_consts={} if dist_consts is None else dist_consts)

    constrained_bonds = []
    for bond, length in dist_consts.items():
        i, j = bond
        d0[i, j] = length
        d0[j, i] = length
        constrained_bonds.append(bond)

    # Randomise coordinates that aren't fixed by shifting a maximum of
    # autode.Config.max_atom_displacement in x, y, z
    fixed_atom_indexes = get_non_random_atoms(species=species)

    # Shift by a factor defined in the config file if the coordinates are
    # reasonable but otherwise init in a 10 A cube
    reasonable_init_coords = ade.geom.are_coords_reasonable(
        species.coordinates)

    if reasonable_init_coords:
        factor = ade.Config.max_atom_displacement / np.sqrt(3)
        for i, atom in enumerate(atoms):
            if i not in fixed_atom_indexes:
                atom.translate(vec=factor * rand.uniform(-1, 1, 3))
    else:
        # Randomise in a 10 Å cubic box
        [atom.translate(vec=rand.uniform(-5, 5, 3)) for atom in atoms]

    logger.info('Minimising species...')
    st = time()
    if reasonable_init_coords:
        coords = get_coords_minimised_v(coords=np.array(
            [atom.coord for atom in atoms]),
                                        bonds=species.graph.edges,
                                        k=1.0,
                                        c=0.01,
                                        d0=d0,
                                        tol=1E-5,
                                        fixed_bonds=constrained_bonds)
    else:
        coords = get_coords_no_init_strucutre(atoms, species, d0,
                                              constrained_bonds)

    logger.info(f'                 ... ({time()-st:.3f} s)')

    # Set the coordinates of the new atoms
    for i, atom in enumerate(atoms):
        atom.coord = coords[i]

    # Print an xyz file so rerunning will read the file
    if save_xyz:
        atoms_to_xyz_file(atoms=atoms, filename=xyz_filename)

    return atoms