Example #1
0
 def test_init(self):
     inner_charge = np.random.rand(10) - 0.5
     outer_charge = np.random.rand(10) - 0.5
     inner_velo = np.random.rand(10, 3) - 0.5
     outer_velo = np.random.rand(10, 3) - 0.5
     m = Molecule(["H"] * 10,
                  np.random.rand(10, 3) * 100,
                  site_properties={
                      "ff_map": ["D"] * 10,
                      "charge": inner_charge,
                      "velocities": inner_velo
                  })
     # q and v from site properties, while type from species_string
     topo = Topology(sites=m)
     self.assertListEqual(topo.type_by_sites, ["H"] * 10)
     np.testing.assert_array_equal(topo.charges, inner_charge)
     np.testing.assert_array_equal(topo.velocities, inner_velo)
     # q and v from overriding, while type from site property
     topo_override = Topology(sites=m,
                              ff_label="ff_map",
                              charges=outer_charge,
                              velocities=outer_velo)
     self.assertListEqual(topo_override.type_by_sites, ["D"] * 10)
     np.testing.assert_array_equal(topo_override.charges, outer_charge)
     np.testing.assert_array_equal(topo_override.velocities, outer_velo)
     # test using a list of sites instead of SiteCollection
     topo_from_list = Topology(sites=m.sites)
     self.assertListEqual(topo_from_list.type_by_sites, topo.type_by_sites)
     np.testing.assert_array_equal(topo_from_list.charges, topo.charges)
     np.testing.assert_array_equal(topo_from_list.velocities,
                                   topo.velocities)
Example #2
0
 def test_polymer_chain_topologies(self):
     topology_random = Topology.from_bonding(self.peo_polymer.molecule)
     topology_linear = Topology.from_bonding(self.peo_polymer_linear.molecule)
     self.assertNotEqual(topology_linear.topologies["Bonds"],
                         topology_random.topologies["Bonds"])
     self.assertNotEqual(topology_linear.topologies["Angles"],
                         topology_random.topologies["Angles"])
     self.assertNotEqual(topology_linear.topologies["Dihedrals"],
                         topology_random.topologies["Dihedrals"])
Example #3
0
 def test_polymer_chain_topologies(self):
     topology_random = Topology.from_bonding(self.peo_polymer.molecule)
     topology_linear = Topology.from_bonding(self.peo_polymer_linear.molecule)
     self.assertNotEqual(topology_linear.topologies["Bonds"], topology_random.topologies["Bonds"])
     self.assertNotEqual(topology_linear.topologies["Angles"], topology_random.topologies["Angles"])
     self.assertNotEqual(
         topology_linear.topologies["Dihedrals"],
         topology_random.topologies["Dihedrals"],
     )
Example #4
0
 def setUpClass(cls):
     cls.peptide = LammpsData.\
         from_file(filename=os.path.join(test_dir, "data.peptide"))
     cls.quartz = LammpsData.\
         from_file(filename=os.path.join(test_dir, "data.quartz"),
                   atom_style="atomic")
     mass_info = [("h", 1.007970), ("otip", 15.999400), ("htip", 1.007970)]
     pair_coeffs = [[0.0380000011, 2.4499714540],
                    [0.1520725945, 3.1506561105],
                    [0.0000000000, 0.0000000000]]
     mol_coeffs = {
         "Bond Coeffs":
             [{"coeffs": [398.7500, 0.7461], "types": [("h", "h")]},
              {"coeffs": [540.6336, 0.9570], "types": [("otip", "htip")]}],
         "Angle Coeffs": [{"coeffs": [50.0000, 104.5200],
                           "types": [("htip", "otip", "htip")]}]
     }
     ff = ForceField(mass_info=mass_info, pair_coeffs=pair_coeffs,
                     mol_coeffs=mol_coeffs)
     h2 = Molecule(["H", "H"], [[4.6, 5.0, 2.5], [5.4, 5.0, 2.5]],
                   site_properties={"ff_map": ["h", "h"]})
     water = Molecule(["O", "H", "H"],
                      [[5.0, 5.0, 7.5], [4.0, 5.0, 7.5], [5.0, 4.0, 7.5]],
                      site_properties={"ff_map": ["otip"] + ["htip"] * 2,
                                       "charge": [-0.834, 0.417, 0.417]})
     topologies = [Topology.from_bonding(m, atom_type="ff_map")
                   for m in [h2, water]]
     cls.h2_water = LammpsData.\
         from_ff_and_topologies(ff=ff, topologies=topologies,
                                box_bounds=[[0, 10]] * 3)
     cls.maxDiff = None
Example #5
0
 def test_from_bonding(self):
     # He: no bonding topologies
     helium = Molecule(["He"], [[0, 0, 0]])
     topo_he = Topology.from_bonding(molecule=helium)
     self.assertIsNone(topo_he.topologies)
     # H2: 1 bond only
     hydrogen = Molecule(["H"] * 2, [[0, 0, 0], [0, 0, 0.7414]])
     topo_h = Topology.from_bonding(molecule=hydrogen)
     tp_h = topo_h.topologies
     self.assertListEqual(tp_h["Bonds"], [[0, 1]])
     self.assertNotIn("Angles", tp_h)
     self.assertNotIn("Dihedrals", tp_h)
     # water: 2 bonds and 1 angle only
     water = Molecule(["O", "H", "H"],
                      [[0.0000, 0.0000, 0.1173], [0.0000, 0.7572, -0.4692],
                       [0.0000, -0.7572, -0.4692]])
     topo_water = Topology.from_bonding(molecule=water)
     tp_water = topo_water.topologies
     self.assertListEqual(tp_water["Bonds"], [[0, 1], [0, 2]])
     self.assertListEqual(tp_water["Angles"], [[1, 0, 2]])
     self.assertNotIn("Dihedrals", tp_water)
     # EtOH
     etoh = Molecule(["C", "C", "O", "H", "H", "H", "H", "H", "H"],
                     [[1.1879, -0.3829, 0.0000], [0.0000, 0.5526, 0.0000],
                      [-1.1867, -0.2472, 0.0000], [-1.9237, 0.3850, 0.0000],
                      [2.0985, 0.2306, 0.0000], [1.1184, -1.0093, 0.8869],
                      [1.1184, -1.0093, -0.8869], [-0.0227, 1.1812, 0.8852],
                      [-0.0227, 1.1812, -0.8852]])
     topo_etoh = Topology.from_bonding(molecule=etoh)
     tp_etoh = topo_etoh.topologies
     self.assertEqual(len(tp_etoh["Bonds"]), 8)
     etoh_bonds = [[0, 1], [0, 4], [0, 5], [0, 6], [1, 2], [1, 7], [1, 8],
                   [2, 3]]
     np.testing.assert_array_equal(tp_etoh["Bonds"], etoh_bonds)
     self.assertEqual(len(tp_etoh["Angles"]), 13)
     etoh_angles = [[1, 0, 4], [1, 0, 5], [1, 0, 6], [4, 0, 5], [4, 0, 6],
                    [5, 0, 6], [0, 1, 2], [0, 1, 7], [0, 1, 8], [2, 1, 7],
                    [2, 1, 8], [7, 1, 8], [1, 2, 3]]
     np.testing.assert_array_equal(tp_etoh["Angles"], etoh_angles)
     self.assertEqual(len(tp_etoh["Dihedrals"]), 12)
     etoh_dihedrals = [[4, 0, 1, 2], [4, 0, 1, 7], [4, 0, 1,
                                                    8], [5, 0, 1, 2],
                       [5, 0, 1, 7], [5, 0, 1, 8], [6, 0, 1,
                                                    2], [6, 0, 1, 7],
                       [6, 0, 1, 8], [0, 1, 2, 3], [7, 1, 2, 3],
                       [8, 1, 2, 3]]
     np.testing.assert_array_equal(tp_etoh["Dihedrals"], etoh_dihedrals)
     self.assertIsNotNone(json.dumps(topo_etoh.as_dict()))
     # bond flag to off
     topo_etoh0 = Topology.from_bonding(molecule=etoh,
                                        bond=False,
                                        angle=True,
                                        dihedral=True)
     self.assertIsNone(topo_etoh0.topologies)
     # angle or dihedral flag to off
     topo_etoh1 = Topology.from_bonding(molecule=etoh, angle=False)
     self.assertNotIn("Angles", topo_etoh1.topologies)
     topo_etoh2 = Topology.from_bonding(molecule=etoh, dihedral=False)
     self.assertNotIn("Dihedrals", topo_etoh2.topologies)
Example #6
0
 def test_from_bonding(self):
     # He: no bonding topologies
     helium = Molecule(["He"], [[0, 0, 0]])
     topo_he = Topology.from_bonding(molecule=helium)
     self.assertIsNone(topo_he.topologies)
     # H2: 1 bond only
     hydrogen = Molecule(["H"] * 2, [[0, 0, 0], [0, 0, 0.7414]])
     topo_h = Topology.from_bonding(molecule=hydrogen)
     tp_h = topo_h.topologies
     self.assertListEqual(tp_h["Bonds"], [[0, 1]])
     self.assertNotIn("Angles", tp_h)
     self.assertNotIn("Dihedrals", tp_h)
     # water: 2 bonds and 1 angle only
     water = Molecule(["O", "H", "H"], [[0.0000, 0.0000, 0.1173],
                                        [0.0000, 0.7572, -0.4692],
                                        [0.0000, -0.7572, -0.4692]])
     topo_water = Topology.from_bonding(molecule=water)
     tp_water = topo_water.topologies
     self.assertListEqual(tp_water["Bonds"], [[0, 1], [0, 2]])
     self.assertListEqual(tp_water["Angles"], [[1, 0, 2]])
     self.assertNotIn("Dihedrals", tp_water)
     # EtOH
     etoh = Molecule(["C", "C", "O", "H", "H", "H", "H", "H", "H"],
                     [[1.1879, -0.3829, 0.0000],
                      [0.0000, 0.5526, 0.0000],
                      [-1.1867, -0.2472, 0.0000],
                      [-1.9237, 0.3850, 0.0000],
                      [2.0985, 0.2306, 0.0000],
                      [1.1184, -1.0093, 0.8869],
                      [1.1184, -1.0093, -0.8869],
                      [-0.0227, 1.1812, 0.8852],
                      [-0.0227, 1.1812, -0.8852]])
     topo_etoh = Topology.from_bonding(molecule=etoh)
     tp_etoh = topo_etoh.topologies
     self.assertEqual(len(tp_etoh["Bonds"]), 8)
     etoh_bonds = [[0, 1], [0, 4], [0, 5], [0, 6],
                   [1, 2], [1, 7], [1, 8], [2, 3]]
     np.testing.assert_array_equal(tp_etoh["Bonds"], etoh_bonds)
     self.assertEqual(len(tp_etoh["Angles"]), 13)
     etoh_angles = [[1, 0, 4], [1, 0, 5], [1, 0, 6], [4, 0, 5], [4, 0, 6],
                    [5, 0, 6], [0, 1, 2], [0, 1, 7], [0, 1, 8], [2, 1, 7],
                    [2, 1, 8], [7, 1, 8], [1, 2, 3]]
     np.testing.assert_array_equal(tp_etoh["Angles"], etoh_angles)
     self.assertEqual(len(tp_etoh["Dihedrals"]), 12)
     etoh_dihedrals = [[4, 0, 1, 2], [4, 0, 1, 7], [4, 0, 1, 8],
                       [5, 0, 1, 2], [5, 0, 1, 7], [5, 0, 1, 8],
                       [6, 0, 1, 2], [6, 0, 1, 7], [6, 0, 1, 8],
                       [0, 1, 2, 3], [7, 1, 2, 3], [8, 1, 2, 3]]
     np.testing.assert_array_equal(tp_etoh["Dihedrals"], etoh_dihedrals)
     self.assertIsNotNone(json.dumps(topo_etoh.as_dict()))
     # bond flag to off
     topo_etoh0 = Topology.from_bonding(molecule=etoh, bond=False,
                                        angle=True, dihedral=True)
     self.assertIsNone(topo_etoh0.topologies)
     # angle or dihedral flag to off
     topo_etoh1 = Topology.from_bonding(molecule=etoh, angle=False)
     self.assertNotIn("Angles", topo_etoh1.topologies)
     topo_etoh2 = Topology.from_bonding(molecule=etoh, dihedral=False)
     self.assertNotIn("Dihedrals", topo_etoh2.topologies)
Example #7
0
    def write_data_file(self, organism, job_dir_path, composition_space):
        """
        Writes the file (called in.data) containing the structure that LAMMPS
        reads.

        Args:
            organism: the Organism whose structure to write

            job_dir_path: the path the job directory (as a string) where the
                file will be written

            composition_space: the CompositionSpace of the search
        """

        # get xhi, yhi and zhi from the lattice vectors
        lattice_coords = organism.cell.lattice.matrix
        xhi = lattice_coords[0][0]
        yhi = lattice_coords[1][1]
        zhi = lattice_coords[2][2]
        box_bounds = [[0.0, xhi], [0.0, yhi], [0.0, zhi]]

        # get xy, xz and yz from the lattice vectors
        xy = lattice_coords[1][0]
        xz = lattice_coords[2][0]
        yz = lattice_coords[2][1]
        box_tilts = [xy, xz, yz]

        # parse the element symbols and atom_style from the lammps input
        # script, preserving the order in which the element symbols appear
        # TODO: not all formats give the element symbols at the end of the line
        #       containing the pair_coeff keyword. Find a better way.
        elements_dict = collections.OrderedDict()
        num_elements = len(composition_space.get_all_elements())
        if num_elements == 1:
            single_element = composition_space.get_all_elements()
            elements_dict[single_element[0].symbol] = single_element[0]
        else:
            with open(self.input_script, 'r') as f:
                lines = f.readlines()
                for line in lines:
                    if 'pair_coeff' in line:
                        element_symbols = line.split()[-1 * num_elements:]
                    elif 'atom_style' in line:
                        atom_style_in_script = line.split()[1]
                for symbol in element_symbols:
                    elements_dict[symbol] = Element(symbol)

        # make a LammpsData object and use it write the in.data file
        force_field = ForceField(elements_dict.items())
        topology = Topology(organism.cell.sites)
        lammps_data = LammpsData.from_ff_and_topologies(
            force_field, [topology],
            box_bounds,
            box_tilts,
            atom_style=atom_style_in_script)
        lammps_data.write_file(job_dir_path + '/in.data')
Example #8
0
    def test_from_ff_and_topologies(self):
        mass = OrderedDict()
        mass["H"] = 1.0079401
        mass["O"] = 15.999400
        nonbond_coeffs = [[0.00774378, 0.98], [0.1502629, 3.1169]]
        topo_coeffs = {
            "Bond Coeffs": [{"coeffs": [176.864, 0.9611], "types": [("H", "O")]}],
            "Angle Coeffs": [
                {"coeffs": [42.1845, 109.4712], "types": [("H", "O", "H")]}
            ],
        }
        ff = ForceField(mass.items(), nonbond_coeffs, topo_coeffs)
        with gzip.open(os.path.join(test_dir, "topologies_ice.json.gz")) as f:
            topo_dicts = json.load(f)
        topologies = [Topology.from_dict(d) for d in topo_dicts]
        box = LammpsBox(
            [[-0.75694412, 44.165558], [0.38127473, 47.066074], [0.17900842, 44.193867]]
        )
        ice = LammpsData.from_ff_and_topologies(box=box, ff=ff, topologies=topologies)
        atoms = ice.atoms
        bonds = ice.topology["Bonds"]
        angles = ice.topology["Angles"]
        np.testing.assert_array_equal(atoms.index.values, np.arange(1, len(atoms) + 1))
        np.testing.assert_array_equal(bonds.index.values, np.arange(1, len(bonds) + 1))
        np.testing.assert_array_equal(
            angles.index.values, np.arange(1, len(angles) + 1)
        )

        i = random.randint(0, len(topologies) - 1)
        sample = topologies[i]
        in_atoms = ice.atoms[ice.atoms["molecule-ID"] == i + 1]
        np.testing.assert_array_equal(
            in_atoms.index.values, np.arange(3 * i + 1, 3 * i + 4)
        )
        np.testing.assert_array_equal(in_atoms["type"].values, [2, 1, 1])
        np.testing.assert_array_equal(in_atoms["q"].values, sample.charges)
        np.testing.assert_array_equal(
            in_atoms[["x", "y", "z"]].values, sample.sites.cart_coords
        )
        broken_topo_coeffs = {
            "Bond Coeffs": [{"coeffs": [176.864, 0.9611], "types": [("H", "O")]}],
            "Angle Coeffs": [
                {"coeffs": [42.1845, 109.4712], "types": [("H", "H", "H")]}
            ],
        }
        broken_ff = ForceField(mass.items(), nonbond_coeffs, broken_topo_coeffs)
        ld_woangles = LammpsData.from_ff_and_topologies(
            box=box, ff=broken_ff, topologies=[sample]
        )
        self.assertNotIn("Angles", ld_woangles.topology)
Example #9
0
    def test_from_ff_and_topologies(self):
        mass = OrderedDict()
        mass["H"] = 1.0079401
        mass["O"] = 15.999400
        nonbond_coeffs = [[0.00774378, 0.98], [0.1502629, 3.1169]]
        topo_coeffs = {"Bond Coeffs": [{"coeffs": [176.864, 0.9611],
                                        "types": [("H", "O")]}],
                       "Angle Coeffs": [{"coeffs": [42.1845, 109.4712],
                                         "types": [("H", "O", "H")]}]}
        ff = ForceField(mass.items(), nonbond_coeffs, topo_coeffs)
        with gzip.open(os.path.join(test_dir, "topologies_ice.json.gz")) as f:
            topo_dicts = json.load(f)
        topologies = [Topology.from_dict(d) for d in topo_dicts]
        box_bounds = [[-0.75694412, 44.165558],
                      [0.38127473, 47.066074],
                      [0.17900842, 44.193867]]
        ice = LammpsData.from_ff_and_topologies(ff=ff, topologies=topologies,
                                                box_bounds=box_bounds)
        atoms = ice.atoms
        bonds = ice.topology["Bonds"]
        angles = ice.topology["Angles"]
        np.testing.assert_array_equal(atoms.index.values,
                                      np.arange(1, len(atoms) + 1))
        np.testing.assert_array_equal(bonds.index.values,
                                      np.arange(1, len(bonds) + 1))
        np.testing.assert_array_equal(angles.index.values,
                                      np.arange(1, len(angles) + 1))

        i = random.randint(0, len(topologies) - 1)
        sample = topologies[i]
        in_atoms = ice.atoms[ice.atoms["molecule-ID"] == i + 1]
        np.testing.assert_array_equal(in_atoms.index.values,
                                      np.arange(3 * i + 1, 3 * i + 4))
        np.testing.assert_array_equal(in_atoms["type"].values, [2, 1, 1])
        np.testing.assert_array_equal(in_atoms["q"].values, sample.charges)
        np.testing.assert_array_equal(in_atoms[["x", "y", "z"]].values,
                                      sample.sites.cart_coords)
        broken_topo_coeffs = {"Bond Coeffs": [{"coeffs": [176.864, 0.9611],
                                               "types": [("H", "O")]}],
                              "Angle Coeffs": [{"coeffs": [42.1845, 109.4712],
                                                "types": [("H", "H", "H")]}]}
        broken_ff = ForceField(mass.items(), nonbond_coeffs,
                               broken_topo_coeffs)
        ld_woangles = LammpsData.from_ff_and_topologies(ff=broken_ff,
                                                        topologies=[sample],
                                                        box_bounds=box_bounds)
        self.assertNotIn("Angles", ld_woangles.topology)
    def _get_gaussian_ff_top_single(self, filename=None):
        """
        run antechamber using gaussian output file, then run parmchk
        to generate missing force field parameters. Store and return
        the force field and topology information in ff_mol.

        Args:
            filename: gaussian output file of the molecule

        Returns:
            Amberff namedtuple object that contains information on force field and
            topology
        """
        scratch = tempfile.gettempdir()
        Amberff = namedtuple("Amberff", ["force_field", "topology"])
        with ScratchDir(scratch,
                        copy_from_current_on_enter=True,
                        copy_to_current_on_exit=True) as d:
            # self._convert_to_pdb(mol, 'mol.pdb')
            # self.molname = filename.split('.')[0]
            self._run_antechamber(filename)
            self._run_parmchk()
            # if antechamber can't find parameters go to gaff_example.dat
            try:
                mol = Molecule.from_file('mol.rtf')
                print('mol.rtf file exists')
            except TopCorruptionException:
                correct_corrupted_top_files('mol.rtf', 'gaff_data.txt')
                top = Topology.from_file('mol.rtf')
                print('mol.rtf file does not exist')
            try:
                gff = ForceField.from_file('mol.frcmod')
            except FFCorruptionException:
                correct_corrupted_frcmod_files('ANTECHAMBER.FRCMOD',
                                               'gaff_data.txt')
                gff = ForceField.from_file('ANTECHAMBER.FRCMOD')
            # gff.set_atom_mappings('ANTECHAMBER_AC.AC')
            # gff.read_charges()
            # decorate the molecule with the sire property "atomname"
            #mol.add_site_property("atomname", (list(gff.atom_index.values())))
        return Amberff(gff, top)
Example #11
0
 def setUpClass(cls):
     cls.peptide = LammpsData.\
         from_file(filename=os.path.join(test_dir, "data.peptide"))
     cls.quartz = LammpsData.\
         from_file(filename=os.path.join(test_dir, "data.quartz"),
                   atom_style="atomic")
     mass_info = [("h", 1.007970), ("otip", 15.999400), ("htip", 1.007970)]
     pair_coeffs = [[0.0380000011, 2.4499714540],
                    [0.1520725945, 3.1506561105],
                    [0.0000000000, 0.0000000000]]
     mol_coeffs = {
         "Bond Coeffs": [{
             "coeffs": [398.7500, 0.7461],
             "types": [("h", "h")]
         }, {
             "coeffs": [540.6336, 0.9570],
             "types": [("otip", "htip")]
         }],
         "Angle Coeffs": [{
             "coeffs": [50.0000, 104.5200],
             "types": [("htip", "otip", "htip")]
         }]
     }
     ff = ForceField(mass_info=mass_info,
                     pair_coeffs=pair_coeffs,
                     mol_coeffs=mol_coeffs)
     h2 = Molecule(["H", "H"], [[4.6, 5.0, 2.5], [5.4, 5.0, 2.5]],
                   site_properties={"ff_map": ["h", "h"]})
     water = Molecule(["O", "H", "H"],
                      [[5.0, 5.0, 7.5], [4.0, 5.0, 7.5], [5.0, 4.0, 7.5]],
                      site_properties={
                          "ff_map": ["otip"] + ["htip"] * 2,
                          "charge": [-0.834, 0.417, 0.417]
                      })
     topologies = [
         Topology.from_bonding(m, atom_type="ff_map") for m in [h2, water]
     ]
     cls.h2_water = LammpsData.\
         from_ff_and_topologies(ff=ff, topologies=topologies,
                                box_bounds=[[0, 10]] * 3)
     cls.maxDiff = None
Example #12
0
 def test_from_ff_and_topologies(self):
     ff = ForceField.from_file(os.path.join(test_dir, "ff_peptide.yaml"))
     with open(os.path.join(test_dir, "topologies_peptide.json")) as f:
         topo_dicts = json.load(f)
     topologies = [Topology.from_dict(d) for d in topo_dicts]
     peptide = LammpsData.\
         from_ff_and_topologies(ff=ff, topologies=topologies,
                                box_bounds=[[-50, 150]] * 3)
     self.assertListEqual(peptide.masses, ff.masses)
     force_field = ff.get_pair_coeffs()
     for kw in ff.mol_coeffs.keys():
         sec, _ = ff.get_coeffs_and_mapper(kw)
         force_field.update(sec)
     self.assertDictEqual(peptide.force_field, force_field)
     back_atom_map = {v: k for k, v in ff.atom_map.items()}
     # test the 1st topology, the peptide
     pep = topologies[0]
     # atoms and velocities sections
     i = random.randint(0, len(pep.sites) - 1)
     site = pep.sites[i]
     in_atoms = peptide.atoms[i]
     self.assertEqual(in_atoms["molecule-ID"], 1)
     self.assertEqual(in_atoms["id"], i + 1)
     self.assertEqual(in_atoms["type"],
                      ff.atom_map[site.properties["ff_map"]])
     self.assertEqual(in_atoms["q"], pep.charges[i])
     self.assertEqual(in_atoms["x"], site.x)
     self.assertEqual(in_atoms["y"], site.y)
     self.assertEqual(in_atoms["z"], site.z)
     in_velos = peptide.velocities[i]
     self.assertEqual(in_velos["id"], i + 1)
     self.assertListEqual(in_velos["velocity"], pep.velocities[i])
     # topology sections
     for t in ["Bond", "Angle", "Dihedral", "Improper"]:
         topo_sec = "%ss" % t
         ff_sec = "%s Coeffs" % t
         kw = t.lower()
         i = random.randint(0, len(pep.topologies[topo_sec]) - 1)
         sample = pep.topologies[topo_sec][i]
         in_topos = peptide.topology[topo_sec][i]
         self.assertEqual(in_topos["id"], i + 1, "%s" % t)
         np.testing.assert_array_equal(in_topos[kw],
                                       np.array(sample) + 1, "%s" % t)
         topo_type_id = in_topos["type"]
         types = ff.mol_coeffs[ff_sec][topo_type_id - 1]["types"]
         sample_type = tuple([pep.sites[j].properties["ff_map"]
                              for j in sample])
         self.assertIn(sample_type, types, "%s" % t)
     # test a random solvent (water) molecule
     i = random.randint(1, len(topologies) - 1)
     solv = topologies[i]
     stack = {"Atoms": 0, "Bonds": 0, "Angles": 0}
     for topo in topologies[:i]:
         stack["Atoms"] += len(topo.sites)
         stack["Bonds"] += len(topo.topologies["Bonds"])
         stack["Angles"] += len(topo.topologies["Angles"])
     # atoms and velocities sections
     in_atoms = [d for d in peptide.atoms if d["molecule-ID"] == i + 1]
     self.assertEqual(len(in_atoms), len(solv.sites))
     aids, types, charges, coords = [], [], [], []
     for d in in_atoms:
         aids.append(d["id"])
         types.append(d["type"])
         charges.append(d["q"])
         coords.append([d["x"], d["y"], d["z"]])
     np.testing.assert_array_equal(aids, np.arange(len(solv.sites))
                                   + stack["Atoms"] + 1)
     self.assertListEqual(types, [ff.atom_map[t] for t in solv.types])
     self.assertListEqual(charges, solv.charges)
     np.testing.assert_array_equal(coords, solv.sites.cart_coords)
     in_velos = peptide.velocities[stack["Atoms"]: stack["Atoms"]
                                                   + len(in_atoms)]
     vids, velocities = [], []
     for d in in_velos:
         vids.append(d["id"])
         velocities.append(d["velocity"])
     self.assertListEqual(vids, aids)
     np.testing.assert_array_equal(velocities, solv.velocities)
     # topology sections
     for t in ["Bond", "Angle"]:
         topo_sec = "%ss" % t
         ff_sec = "%s Coeffs" % t
         kw = t.lower()
         sample = solv.topologies[topo_sec][0]
         i = stack[topo_sec]
         in_topos = peptide.topology[topo_sec][i]
         self.assertEqual(in_topos["id"], i + 1, "%s" % t)
         np.testing.assert_array_equal(in_topos[kw], np.array(sample)
                                       + stack["Atoms"] + 1, "%s" % t)
         topo_type_id = in_topos["type"]
         types = ff.mol_coeffs[ff_sec][topo_type_id - 1]["types"]
         sample_type = tuple([solv.sites[j].properties["ff_map"]
                              for j in sample])
         self.assertIn(sample_type, types, "%s" % t)
Example #13
0
    def get_ion(
        ion: Union[Ion, str],
        parameter_set: str = "auto",
        water_model: str = "auto",
        mixing_rule: Optional[str] = None,
    ) -> LammpsData:
        """
        Retrieve force field parameters for an ion in water.

        Args:
            ion: Formula of the ion (e.g., "Li+"). Not case sensitive. May be
                passed as either a string or an Ion object.
            parameter_set: Force field parameters to use for ions.
                Valid choices are:
                    1. "jj" for the Jensen and Jorgensen parameters (2006)"
                    2. "jc" for Joung-Cheatham parameters (2008)
                    3. "lm" for the Li and Merz group parameters (2020-2021)"
                The default parameter set is "auto", which assigns a recommended
                parameter set that is compatible with the chosen water model.
            water_model: Water model to use. Models must be given as a string
                (not case sensitive). "-" and "/" are ignored. Hence "tip3pfb"
                and "TIP3P-FB" are both valid inputs for the TIP3P-FB water model.
                Available water models are:
                    1. SPC
                    2. SPC/E
                    3. TIP3P-EW
                    4. TIP3P-FB
                    5. OPC3
                    6. TIP4P-EW
                    7. TIP4P-2005
                    8. TIP4P-FB
                    9. OPC
                The default water model is "auto", which assigns a recommended
                water model that is compatible with the chosen ion parameters. Other
                combinations are possible at your own risk. See documentation.

            When both the parameter_set and water_model are set to "auto", the function returns the
            Joung-Cheatham parameters for the SPC/E water model.

                For a systematic comparison of the performance of different water models, refer to

                    Sachini et al., Systematic Comparison of the Structural and Dynamic Properties of
                    Commonly Used Water Models for Molecular Dynamics Simulations. J. Chem. Inf. Model.
                    2021, 61, 9, 4521–4536. https://doi.org/10.1021/acs.jcim.1c00794

            mixing_rule: The mixing rule to use for the ion parameter. Default to None, which does not
                change the original mixing rule of the parameter set. Available choices are 'LB'
                (Lorentz-Berthelot or arithmetic) and 'geometric'. If the specified mixing rule does not
                match the default mixing rule of the parameter set, the output parameter will be converted
                accordingly.


        Returns:
            Force field parameters for the chosen water model.
        """
        alias = {
            "aq": "aqvist",
            "jj": "jensen_jorgensen",
            "jc": "joung_cheatham",
            "lm": "li_merz"
        }
        default_sets = {
            "spc": "N/A",
            "spce": "jc",
            "tip3p": "jc",
            "tip3pew": "N/A",
            "tip3pfb": "lm",
            "opc3": "lm",
            "tip4p2005": "N/A",
            "tip4p": "jj",
            "tip4pew": "jc",
            "tip4pfb": "lm",
            "opc": "lm",
            "jj": "tip4p",
            "jc": "spce",
            "lm": "tip4pfb",
        }
        water_model = water_model.replace("-", "").replace("/", "").lower()
        parameter_set = parameter_set.lower()

        if water_model == "auto" and parameter_set == "auto":
            water_model = "spce"
            parameter_set = "jc"
        elif parameter_set == "auto":
            parameter_set = default_sets.get(water_model, parameter_set)
            if parameter_set == "N/A":
                raise ValueError(
                    f"The {water_model} water model has no specifically parameterized ion parameter sets"
                    "Please try a different water model.")
        elif water_model == "auto":
            water_model = default_sets.get(parameter_set, water_model)

        parameter_set = alias.get(parameter_set, parameter_set)

        # Make the Ion object to get mass and charge
        if isinstance(ion, Ion):
            ion_obj = ion
        else:
            ion_obj = Ion.from_formula(ion.capitalize())

        # load ion data as a list of IonLJData objects
        ion_data = loadfn(os.path.join(DATA_DIR, "ion_lj_params.json"))

        # make sure the ion is in the DataFrame
        key = ion_obj.reduced_formula
        filtered_data = [d for d in ion_data if d.formula == key]
        if len(filtered_data) == 0:
            raise ValueError(
                f"Ion {key} not found in database. Please try a different ion."
            )

        # make sure the parameter set is in the DataFrame
        filtered_data = [
            d for d in filtered_data
            if d.name == parameter_set and d.water_model == water_model
        ]
        if len(filtered_data) == 0:
            raise ValueError(
                f"No {parameter_set} parameters for water model {water_model} for ion {key}. "
                "See documentation and try a different combination.")

        if len(filtered_data) != 1:
            raise ValueError(
                f"Something is wrong: multiple ion data entries for {key}, {parameter_set}, and {water_model}"
            )

        # we only consider monatomic ions at present
        # construct a cubic LammpsBox from a lattice
        lat = Lattice([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
        box = lattice_2_lmpbox(lat)[0]
        # put it in the center of a cubic Structure
        struct = Structure(lat, ion_obj, [[0.5, 0.5, 0.5]])
        # construct Topology with the ion centered in the box
        topo = Topology(struct, charges=[ion_obj.charge])

        # retrieve Lennard-Jones parameters
        # construct ForceField object
        sigma = filtered_data[0].sigma
        epsilon = filtered_data[0].epsilon
        if mixing_rule is None:
            pass
        else:
            default_mixing = filtered_data[0].combining_rule
            water_sigma = WATER_SIGMA.get(filtered_data[0].water_model)
            if mixing_rule.lower() in [
                    "lb", "arithmetic", "lorentz-berthelot",
                    "lorentz berthelot"
            ]:
                mixing_rule = "LB"
            elif mixing_rule.lower() == "geometric":
                mixing_rule = "geometric"
            else:
                raise ValueError(
                    "Invalid mixing rule. Supported mixing rules are 'LB'(arithmetic) and 'geometric'. "
                )
            if default_mixing == mixing_rule:
                pass
            elif default_mixing == "LB" and mixing_rule == "geometric":
                sigma = ((water_sigma + sigma) / 2)**2 / water_sigma
                print(
                    "The parameter mixing rule has been converted from the original 'LB' to 'geometric'.\n"
                    "Please use the parameter set with caution!")
            else:
                sigma = 2 * ((water_sigma * sigma)**(1 / 2)) - water_sigma
                print(
                    "The parameter mixing rule has been converted from the original 'geometric' to 'LB'.\n"
                    "Please use the parameter set with caution!")
        ff = ForceField([(str(e), e) for e in ion_obj.elements],
                        nonbond_coeffs=[[epsilon, sigma]])

        return LammpsData.from_ff_and_topologies(box,
                                                 ff, [topo],
                                                 atom_style="full")
Example #14
0
    def __init__(self,
                 input_file,
                 final_molecule,
                 forcefield,
                 box_size,
                 topologies=None,
                 constituent_molecules=None,
                 mols_number=None,
                 user_settings=None,
                 ff_site_property=None,
                 input_filename="lammps.in",
                 data_filename="lammps.data",
                 lammps_cmd="lammps",
                 db_file=None,
                 parents=None,
                 log_filename="log.lammps",
                 dump_filenames=None,
                 name="LammpsFFFW",
                 **kwargs):
        """
        Write lammps input from forcefield and topology, run lammps, store results. Can be used
        with RunPackmol firework.

        Args:
            input_file (str): path to lammps input(or template) file.
            final_molecule (str/Molecule): either path to the moelcule of Molecule object.
            forcefield (ForceField): pymatgen.io.lammps.force_field.ForceField object
            box_size (list):  list of list of low and high values for each dimension [[xlow, xhigh], ...]
            topologies ([Topology]): list of pymatgen.io.lammps.topology.Topology objects, one for
                each constituent molecule.
            constituent_molecules ([Molecule]): list of Molecule objects that make up the final_molecule
            mols_number (list): list of number of each constituent moelcule.
            user_settings (dict):
            ff_site_property (str): the site property used for forcefiled mapping
            input_filename (str): name of the input file to be written
            data_filename (str):name of the data file to be written
            lammps_cmd (str): lammps command run (without the input file)
            db_file (str): path to the db settings
            parents (list): list of Fireworks
            log_filename (str): lammps log file name
            dump_filenames (str): list of dump files
            name (str): firework name
            **kwargs:
        """

        user_settings = user_settings or {}
        constituent_molecules = constituent_molecules or [final_molecule]
        mols_number = mols_number or [1]
        topologies = topologies or Topology.from_molecule(
            final_molecule, ff_map=ff_site_property)

        tasks = [
            WriteInputFromForceFieldAndTopology(
                input_file=input_file,
                final_molecule=final_molecule,
                constituent_molecules=constituent_molecules,
                mols_number=mols_number,
                forcefield=forcefield,
                topologies=topologies,
                input_filename=input_filename,
                user_settings=user_settings,
                data_filename=data_filename,
                ff_site_property=ff_site_property,
                box_size=box_size),
            RunLammpsDirect(lammps_cmd=lammps_cmd,
                            input_filename=input_filename),
            LammpsToDB(input_filename=input_filename,
                       data_filename=data_filename,
                       log_filename=log_filename,
                       dump_filenames=dump_filenames,
                       db_file=db_file,
                       additional_fields={"task_label": name})
        ]

        super(LammpsForceFieldFW, self).__init__(tasks,
                                                 parents=parents,
                                                 name=name,
                                                 **kwargs)
Example #15
0
 def test_from_ff_and_topologies(self):
     ff = ForceField.from_file(os.path.join(test_dir, "ff_peptide.yaml"))
     with open(os.path.join(test_dir, "topologies_peptide.json")) as f:
         topo_dicts = json.load(f)
     topologies = [Topology.from_dict(d) for d in topo_dicts]
     peptide = LammpsData.\
         from_ff_and_topologies(ff=ff, topologies=topologies,
                                box_bounds=[[-50, 150]] * 3)
     self.assertListEqual(peptide.masses, ff.masses)
     force_field = ff.get_pair_coeffs()
     for kw in ff.mol_coeffs.keys():
         sec, _ = ff.get_coeffs_and_mapper(kw)
         force_field.update(sec)
     self.assertDictEqual(peptide.force_field, force_field)
     back_atom_map = {v: k for k, v in ff.atom_map.items()}
     # test the 1st topology, the peptide
     pep = topologies[0]
     # atoms and velocities sections
     i = random.randint(0, len(pep.sites) - 1)
     site = pep.sites[i]
     in_atoms = peptide.atoms[i]
     self.assertEqual(in_atoms["molecule-ID"], 1)
     self.assertEqual(in_atoms["id"], i + 1)
     self.assertEqual(in_atoms["type"],
                      ff.atom_map[site.properties["ff_map"]])
     self.assertEqual(in_atoms["q"], pep.charges[i])
     self.assertEqual(in_atoms["x"], site.x)
     self.assertEqual(in_atoms["y"], site.y)
     self.assertEqual(in_atoms["z"], site.z)
     in_velos = peptide.velocities[i]
     self.assertEqual(in_velos["id"], i + 1)
     self.assertListEqual(in_velos["velocity"], pep.velocities[i])
     # topology sections
     for t in ["Bond", "Angle", "Dihedral", "Improper"]:
         topo_sec = "%ss" % t
         ff_sec = "%s Coeffs" % t
         kw = t.lower()
         i = random.randint(0, len(pep.topologies[topo_sec]) - 1)
         sample = pep.topologies[topo_sec][i]
         in_topos = peptide.topology[topo_sec][i]
         self.assertEqual(in_topos["id"], i + 1, "%s" % t)
         np.testing.assert_array_equal(in_topos[kw],
                                       np.array(sample) + 1, "%s" % t)
         topo_type_id = in_topos["type"]
         types = ff.mol_coeffs[ff_sec][topo_type_id - 1]["types"]
         sample_type = tuple(
             [pep.sites[j].properties["ff_map"] for j in sample])
         self.assertIn(sample_type, types, "%s" % t)
     # test a random solvent (water) molecule
     i = random.randint(1, len(topologies) - 1)
     solv = topologies[i]
     stack = {"Atoms": 0, "Bonds": 0, "Angles": 0}
     for topo in topologies[:i]:
         stack["Atoms"] += len(topo.sites)
         stack["Bonds"] += len(topo.topologies["Bonds"])
         stack["Angles"] += len(topo.topologies["Angles"])
     # atoms and velocities sections
     in_atoms = [d for d in peptide.atoms if d["molecule-ID"] == i + 1]
     self.assertEqual(len(in_atoms), len(solv.sites))
     aids, types, charges, coords = [], [], [], []
     for d in in_atoms:
         aids.append(d["id"])
         types.append(d["type"])
         charges.append(d["q"])
         coords.append([d["x"], d["y"], d["z"]])
     np.testing.assert_array_equal(
         aids,
         np.arange(len(solv.sites)) + stack["Atoms"] + 1)
     self.assertListEqual(types, [ff.atom_map[t] for t in solv.types])
     self.assertListEqual(charges, solv.charges)
     np.testing.assert_array_equal(coords, solv.sites.cart_coords)
     in_velos = peptide.velocities[stack["Atoms"]:stack["Atoms"] +
                                   len(in_atoms)]
     vids, velocities = [], []
     for d in in_velos:
         vids.append(d["id"])
         velocities.append(d["velocity"])
     self.assertListEqual(vids, aids)
     np.testing.assert_array_equal(velocities, solv.velocities)
     # topology sections
     for t in ["Bond", "Angle"]:
         topo_sec = "%ss" % t
         ff_sec = "%s Coeffs" % t
         kw = t.lower()
         sample = solv.topologies[topo_sec][0]
         i = stack[topo_sec]
         in_topos = peptide.topology[topo_sec][i]
         self.assertEqual(in_topos["id"], i + 1, "%s" % t)
         np.testing.assert_array_equal(
             in_topos[kw],
             np.array(sample) + stack["Atoms"] + 1, "%s" % t)
         topo_type_id = in_topos["type"]
         types = ff.mol_coeffs[ff_sec][topo_type_id - 1]["types"]
         sample_type = tuple(
             [solv.sites[j].properties["ff_map"] for j in sample])
         self.assertIn(sample_type, types, "%s" % t)