def test_get_atoms(self):
        molecule = Molecule()

        # get_atoms() should return list of len 0 before any atoms added to Molecule
        self.assertEqual(len(molecule.get_atoms()), 0)

        fragment0 = Fragment(0, 1)
        atom0 = Atom("H", 0, 0, 0)

        fragment0.add_atom(atom0)

        molecule.add_fragment(fragment0)

        self.assertEqual(molecule.get_atoms()[0], atom0)
        # get_atoms() should return list of len 1 after 1 atom added to Molecule
        self.assertEqual(len(molecule.get_atoms()), 1)

        fragment1 = Fragment(0, 1)
        atom1 = Atom("H", 0, 0, 0)
        atom2 = Atom("He", 234, -0.1, 32)
        atom3 = Atom("He", 34, 43.53, 0)

        fragment1.add_atom(atom1)
        fragment1.add_atom(atom2)
        fragment1.add_atom(atom3)

        molecule.add_fragment(fragment1)

        self.assertEqual(molecule.get_atoms()[0], atom0)
        self.assertEqual(molecule.get_atoms()[1], atom1)
        self.assertEqual(molecule.get_atoms()[2], atom2)
        self.assertEqual(molecule.get_atoms()[3], atom3)
        # get_atoms() should return list of len 4 after 4 atoms added to molecule
        self.assertEqual(len(molecule.get_atoms()), 4)
    def test_add_fragment_and_get_fragments(self):
        molecule = Molecule()

        # get_fragments() should return list of len 0 before any fragments added to Molecule
        self.assertEqual(len(molecule.get_fragments()), 0)

        fragment0 = Fragment(-3, 2)
        atom0 = Atom("H", 0, 0, 0)

        fragment0.add_atom(atom0)

        molecule.add_fragment(fragment0)

        self.assertEqual(molecule.get_fragments()[0], fragment0)
        # get_fragments() should return list of len 1 after 1 fragment added to Molecule
        self.assertEqual(len(molecule.get_fragments()), 1)

        fragment1 = Fragment(1, 1)
        atom1 = Atom("H", 0, 0, 0)
        atom2 = Atom("He", 234, -0.1, 32)
        atom3 = Atom("He", 34, 43.53, 0)

        fragment1.add_atom(atom1)
        fragment1.add_atom(atom2)
        fragment1.add_atom(atom3)

        molecule.add_fragment(fragment1)

        self.assertEqual(molecule.get_fragments()[0], fragment0)
        self.assertEqual(molecule.get_fragments()[1], fragment1)
        # get_fragments() should return list of len 2 after 2 fragments added to Molecule
        self.assertEqual(len(molecule.get_fragments()), 2)
    def get_optimized_energies(self, method, basis, cp, tag):
        """
        Returns a list of pairs of [molecule, energies] where energies is an array of the form [E0, ...] of molecules in the database with the given
        method, basis, cp and tag and optimized geometries

        % can be used as a wildcard to stand in for any method, basis, cp, or tag. 

        Args:
            method  - retrieve only energies computed with this method
            basis   - retrieve only energies computed with this basis
            cp      - retrieve only energies computed with this coutnerpoise correction
            tag     - retrieve only energies with this tag

        Returns:
            a generator of [molecule, [E0, E1, E2, E01, ...]] pairs from the calculated energies in this database using the given model and tag of optimized geometries
        """

        # get a list of all calculations that have the appropriate method, basis, and cp
        calculation_ids = [
            elements[0] for elements in self.cursor.execute(
                "SELECT ROWID FROM Calculations WHERE model_id=(SELECT ROWID FROM Models WHERE method LIKE ? AND basis LIKE ? AND cp LIKE ? AND tag LIKE ? AND optimized=?)",
                (method, basis, cp, tag, 1)).fetchall()
        ]

        for calculation_id in calculation_ids:

            # get the molecule id corresponding to this calculation
            molecule_id = self.cursor.execute(
                "SELECT molecule_id FROM Calculations WHERE ROWID=?",
                (calculation_id, )).fetchone()[0]

            # Reconstruct the molecule from the information in this database
            molecule = Molecule()

            # loop over all rows in the Fragments table that correspond to this molecule
            for fragment_id, charge, spin in self.cursor.execute(
                    "SELECT ROWID, charge, spin FROM Fragments WHERE molecule_id=?",
                (molecule_id, )).fetchall():
                fragment = Fragment(charge, spin)

                # loop over all rows in the Atoms table that correspond to this fragment
                for symbol, x, y, z in self.cursor.execute(
                        "SELECT symbol, x, y, z FROM Atoms WHERE fragment_id=?",
                    (fragment_id, )).fetchall():
                    fragment.add_atom(Atom(symbol, x, y, z))

                molecule.add_fragment(fragment)

            # get the energies corresponding to this calculation
            energies = [
                energy_index_value_pair[1]
                for energy_index_value_pair in sorted(
                    self.cursor.execute(
                        "SELECT energy_index, energy FROM Energies WHERE calculation_id=?",
                        (calculation_id, )).fetchall())
            ]

            yield molecule, energies
    def test_get_num_atoms(self):
        molecule = Molecule()

        # get_num_atoms() should return 0 before any atoms added to molecule
        self.assertEqual(molecule.get_num_atoms(), 0)

        fragment0 = Fragment(-1, 2)
        atom0 = Atom("F", 0, 0, 0)

        fragment0.add_atom(atom0)

        molecule.add_fragment(fragment0)

        # get_num_fragments() should return 1 after 1 atom added to molecule
        self.assertEqual(molecule.get_num_atoms(), 1)

        fragment1 = Fragment(-1, 2)
        atom1 = Atom("F", 0, 0, 3)
        atom2 = Atom("Cl", 0, 0, 0)

        fragment1.add_atom(atom1)
        fragment1.add_atom(atom2)

        molecule.add_fragment(fragment1)

        # get_num_fragments() should return 3 after 3 atoms added to molecule
        self.assertEqual(molecule.get_num_atoms(), 3)
    def test_get_spin_multiplicity(self):
        fragment = Fragment(0, 2)

        self.assertEqual(fragment.get_spin_multiplicity(), 2)

        fragment = Fragment(-3, 1)

        self.assertEqual(fragment.get_spin_multiplicity(), 1)

        fragment = Fragment(12, 5)

        self.assertEqual(fragment.get_spin_multiplicity(), 5)
    def test_get_charge(self):
        fragment = Fragment(0, 2)

        self.assertEqual(fragment.get_charge(), 0)

        fragment = Fragment(-3, 1)

        self.assertEqual(fragment.get_charge(), -3)

        fragment = Fragment(12, 5)

        self.assertEqual(fragment.get_charge(), 12)
    def test_get_spin_multiplicity(self):
        molecule = Molecule()

        # get_spin_multiplicity() should return 1 before any fragments added to Molecule
        self.assertEqual(molecule.get_spin_multiplicity(), 1)

        fragment0 = Fragment(-1, 3)

        molecule.add_fragment(fragment0)

        # get_spin_multiplicity() should return 3 after first fragment added to Molecule
        self.assertEquals(molecule.get_spin_multiplicity(), 3)

        fragment1 = Fragment(3, 1)

        molecule.add_fragment(fragment1)

        # get_spin_multiplicity() should return 3 after second fragment added to Molecule
        self.assertEquals(molecule.get_spin_multiplicity(), 3)
    def test_get_charge(self):
        molecule = Molecule()

        # get_charge() should return 0 before any fragments added to Molecule
        self.assertEqual(molecule.get_charge(), 0)

        fragment0 = Fragment(-1, 3)

        molecule.add_fragment(fragment0)

        # get_charge() should return -1 after first fragment added to Molecule
        self.assertEquals(molecule.get_charge(), -1)

        fragment1 = Fragment(3, 1)

        molecule.add_fragment(fragment1)

        # get_charge() should return 2 after second fragment added to Molecule
        self.assertEquals(molecule.get_charge(), 2)
Exemple #9
0
"""
Test script for minimal psi4 calculation
"""
import sys
sys.path.insert(0, "../src")

from molecule import Fragment, Molecule
import psi4

minimal_frag = Fragment()

minimal_frag.natoms = 3
minimal_frag.symbols = ['O', 'H', 'H']
minimal_frag.coordinates = [[-0.0005900753, 0.0000000000, -0.0004526740],
                            [0.9256102457, 0.0000000000, -0.2481132352],
                            [-0.0000930743, 0.0000000000, 0.9582869092]]

minimal_mol = Molecule()
minimal_mol.natoms = 3
minimal_mol.fragments = [minimal_frag]

psi4.core.set_output_file("/dev/null", False)
psi4.set_memory("1GB")

psi4_mol = psi4.core.Molecule.create_molecule_from_string(
    minimal_mol.mol_comb_str([0]))
psi4_mol.update_geometry()
psi4.set_num_threads(6)
energy = psi4.energy("HF/STO-3G", molecule=psi4_mol)

print(energy)
def xyz_to_molecules(f, config):

    # Keep in mind that you're passing in a file from initializer, not a
    # directory!

    # number of atoms in each fragment
    atoms_per_fragment = []
    # charge of each fragment
    charge_per_fragment = []
    # spin of each fragment
    spin_per_fragment = []

    # Don't try to find the settings.ini, we should now REQUIRE it instead
    '''
    if "settings.ini" in dir_contents:
        # create config object
        config = configparser.SafeConfigParser(allow_no_value=False)

        # read the conflig file into the configuration
        config.read(directory + "/settings.ini")
    '''

    # the for loop just changes the string array to an int array
    atoms_per_fragment = [
        int(atom_count)
        for atom_count in config["molecule"]["fragments"].split(",")
    ]
    charge_per_fragment = [
        int(charge) for charge in config["molecule"]["charges"].split(",")
    ]
    spin_per_fragment = [
        int(spin) for spin in config["molecule"]["spins"].split(",")
    ]

    # define the list of molecules
    molecules = []

    # Duplicate file openings
    '''
    # loop thru all files in directory
    for file_name in dir_contents:
        # check if file_name is an xyz file
        if file_name[-4:] == ".xyz":
            # parse the xyz file
            xyz = open(directory + "/" + file_name, "r")
    '''
    while True:

        # read first line of file, should be num of atoms
        atom_num_line = readline(f)
        # check for end of input
        if atom_num_line == "":
            break

        # check for consistance between number of atoms in xyz file
        # and number of atoms in fragments array
        if int(atom_num_line) != sum(atoms_per_fragment):
            raise ValueError(
                "Atom count specified in xyz file does not match count in ini file"
            )
        # read and discard the comment line
        readline(f, True)

        # init Molecule object
        molecule = Molecule()
        molecule.natoms = atoms_per_fragment
        molecule.charges = charge_per_fragment
        molecule.spins = spin_per_fragment

        # start reading atom lines
        for atom_count, charge, spin in zip(atoms_per_fragment,
                                            charge_per_fragment,
                                            spin_per_fragment):

            # init Fragment object
            fragment = Fragment(charge, spin)

            for i in range(0, atom_count):
                # read a line
                atom_line = readline(f, True)

                # extract atom info from line
                symbol, x, y, z = atom_line.split()

                # add atom to fragment
                fragment.add_atom(Atom(symbol, float(x), float(y), float(z)))

            # add fragment to molecule
            molecule.add_fragment(fragment)

        # add molecule to list of molecules
        molecules.append(molecule)

    return molecules
    def get_missing_energy(self):
        """
        Returns a single Calculation object, which contains the info a user needs to calculate an energy missing in the table.

        The user should calculate the energy, then call either set_energy() or set_failed()

        Args:
            None

        Returns:
            A Calculation object describing the calculation to be performed
        """

        # retrieve a pending job from the Jobs table
        try:
            job_id = self.cursor.execute(
                "SELECT ROWID FROM Jobs WHERE status=?",
                ("pending", )).fetchone()[0]
        except TypeError:
            # this error will be thrown if there are no more energies to calculate, because None[0] throws a TypeError
            return None

        # retrieve the calculation and energy to be calculated for this job from the Energies table
        calculation_id, energy_index = self.cursor.execute(
            "SELECT calculation_id, energy_index FROM Energies WHERE job_id=?",
            (job_id, )).fetchone()

        # retrieve the molecule and model from the Calculations table
        molecule_id, model_id, tag, optimized = self.cursor.execute(
            "SELECT molecule_id, model_id, tag, optimized FROM Calculations WHERE ROWID=?",
            (calculation_id, )).fetchone()

        # retrieve the method, basis, and cp for this model
        method, basis, cp = self.cursor.execute(
            "SELECT method, basis, cp FROM Models WHERE ROWID=?",
            (model_id, )).fetchone()

        # Reconstruct the molecule from the information in this database
        molecule = Molecule()

        # loop over all rows in the Fragments table that correspond to this molecule
        for fragment_id, charge, spin in self.cursor.execute(
                "SELECT ROWID, charge, spin FROM Fragments WHERE molecule_id=?",
            (molecule_id, )).fetchall():
            fragment = Fragment(charge, spin)

            # loop over all rows in the Atoms table that correspond to this fragment
            for symbol, x, y, z in self.cursor.execute(
                    "SELECT symbol, x, y, z FROM Atoms WHERE fragment_id=?",
                (fragment_id, )).fetchall():
                fragment.add_atom(Atom(symbol, x, y, z))

            molecule.add_fragment(fragment)

        # get the indicies of the fragments to include in this calculation
        fragment_indicies = energy_index_to_fragment_indicies(
            energy_index, molecule.get_num_fragments())

        # update the job with its start date and running status
        self.cursor.execute(
            "UPDATE Jobs SET status=?, start_date=? WHERE ROWID=?",
            ("running", datetime.datetime.today().strftime('%Y/%m/%d'),
             job_id))

        return Calculation(molecule, method, basis, True if cp == 1 else False,
                           fragment_indicies, job_id)
    def test_add_atom_and_get_atoms(self):
        fragment = Fragment(0, 1)

        # get_atom() should return list of length 0 before any atoms added to fragment
        self.assertEqual(len(fragment.get_atoms()), 0)

        atom0 = Atom("H", 0, 0, 0)

        fragment.add_atom(atom0)

        self.assertEqual(fragment.get_atoms()[0], atom0)
        # get_atom() should return list of length 1 after 1 atom added to fragment
        self.assertEqual(len(fragment.get_atoms()), 1)

        atom1 = Atom("Cl", 400, 32, 23)

        fragment.add_atom(atom1)

        self.assertEqual(fragment.get_atoms()[0], atom1)
        self.assertEqual(fragment.get_atoms()[1], atom0)
        # get_atom() should return list of length 2 after 2 atoms added to fragment
        self.assertEqual(len(fragment.get_atoms()), 2)
    def test_to_standard_xyz(self):
        molecule = Molecule()

        fragment0 = Fragment(-1, 1)
        fragment0.add_atom(Atom("H", 5, 3, 0.00343))
        fragment0.add_atom(Atom("Cl", 2, 0, -13))
        fragment0.add_atom(Atom("He", 6, 2, 0.343))

        molecule.add_fragment(fragment0)

        self.assertEqual(molecule.to_xyz(), fragment0.to_xyz()[:-1])

        fragment1 = Fragment(-2, 1)
        fragment1.add_atom(Atom("Ar", 0.23430523424, -34, -234.5235))

        molecule.add_fragment(fragment1)

        self.assertEqual(molecule.to_xyz(),
                         fragment1.to_xyz() + fragment0.to_xyz()[:-1])

        fragment2 = Fragment(0, 2)
        fragment2.add_atom(Atom("Xe", 0, 0, 0))
        fragment2.add_atom(Atom("Br", 62, 5, 0.001))

        molecule.add_fragment(fragment2)
        self.assertEqual(
            molecule.to_xyz(),
            fragment1.to_xyz() + fragment2.to_xyz() + fragment0.to_xyz()[:-1])
    def test_to_xyz(self):
        fragment = Fragment(-2, 2)

        # to_xyz() should return empty string when no atoms are added to fragment
        self.assertEqual(fragment.to_xyz(), "")

        atom0 = Atom("H", 0, 0, 0)

        fragment.add_atom(atom0)

        # to_xyz() should return string of first atom after only 1 atom added
        self.assertEqual(fragment.to_xyz(), atom0.to_xyz() + "\n")

        atom1 = Atom("Cl", 5, 7, -3)

        fragment.add_atom(atom1)

        # to_xyz() should return string of 2 atoms after 2nd atom added
        self.assertEqual(fragment.to_xyz(),
                         atom1.to_xyz() + "\n" + atom0.to_xyz() + "\n")

        atom2 = Atom("Xe", 10.234235, -0.00000234, 2.353523)

        fragment.add_atom(atom2)

        # to_xyz() should return string of 3 atoms after only 3rd atom added
        self.assertEqual(
            fragment.to_xyz(),
            atom1.to_xyz() + "\n" + atom0.to_xyz() + "\n" + atom2.to_xyz() +
            "\n")
    def test_get_num_atoms(self):
        fragment = Fragment(3, 2)

        # get_num_atoms() should return 0 before any Atoms added to Fragment
        self.assertEqual(fragment.get_num_atoms(), 0)

        fragment.add_atom(Atom("H", 0, 0, 0))

        # get_num_atoms() should return 1 after single atom added to Fragment
        self.assertEqual(fragment.get_num_atoms(), 1)

        fragment.add_atom(Atom("Al", 0, 0, 0))

        # get_num_atoms() should return 2 after second atom added to Fragment
        self.assertEqual(fragment.get_num_atoms(), 2)

        fragment.add_atom(Atom("He", 0, 0, 0))

        # get_num_atoms() should return 3 after third atom added to Fragment
        self.assertEqual(fragment.get_num_atoms(), 3)