def test_distance(self, molecule, control_filepath, delete_tmp_dir): ms = MoleculeSystem(molecule, frozen_indices={2, 3}) ms.add_distance(0, 1, weights=1.0, value=2.5) assert ms.has_inconsistencies() with temp_dir(delete_tmp_dir) as tmp_dir: ms.to_file("coord", fmt="coord") shutil.copy2(control_filepath, "control") dr = DefineRunner(parameters=dr_parameters) assert dr.run_update_internal_coords() ms_new = MoleculeSystem.from_file("coord") assert not ms_new.has_inconsistencies() # check that intdef is present and that the value has been updated assert len(ms_new.int_def) == 1 assert ms_new.int_def[0].value == pytest.approx( ms.int_def[0].value, abs=1e-4) # check that there are the same user-defined bonds assert ms.user_defined_bonds == ms_new.user_defined_bonds # check that in redundant the coordinate has been taken into account dg = DataGroups.from_file("coord") redundant = dg.sdg("redundant", strict=True) assert re.search(r"\d+\s+f\s+1\.0+\s+stre\s+1\s+2\s+val=\s*2.5", redundant) # check the presence of the same frozen atoms assert ms.frozen_indices == ms_new.frozen_indices assert str(ms_new.int_def[0]) assert_MSONable(ms_new)
def test_distance_linear_combination(self, molecule, control_filepath, delete_tmp_dir): ms = MoleculeSystem(molecule) ms.add_distance([0, 1], [1, 2], weights=[1.0, 1.0], value=None) assert not ms.has_inconsistencies() with temp_dir(delete_tmp_dir) as tmp_dir: ms.to_file("coord", fmt="coord") shutil.copy2(control_filepath, "control") dr = DefineRunner(parameters=dr_parameters) assert dr.run_update_internal_coords() ms_new = MoleculeSystem.from_file("coord") assert not ms_new.has_inconsistencies() # check that intdef is present and that the value has been updated assert len(ms_new.int_def) == 1 assert ms_new.int_def[0].value == pytest.approx(2.70995, abs=1e-4) # check that in redundant the coordinate has been taken into account dg = DataGroups.from_file("coord") redundant = dg.sdg("redundant", strict=True) assert re.search( r"\d+\s+f\s+1\.0+\s+stre\s+1\s+2\s+val=\s*2\.70\d+\s+1\.0+\s+stre\s+2\s+3\s*$", redundant, re.DOTALL | re.MULTILINE)
def test_disordered(self, molecule_filepath): m = Molecule.from_file(molecule_filepath) assert not m.is_ordered with pytest.raises( ValueError, match=r'^MoleculeSystem does not handle disordered structures.$' ): MoleculeSystem(m).to_coord_string()
def test_to_coord_string(self, molecule): ms = MoleculeSystem(molecule) test_value = """ 0.00000000000000 0.00000000000000 0.00000000000000 c 0.00000000000000 0.00000000000000 2.86118897312869 o 0.00000000000000 0.00000000000000 -2.86118897312869 o """ dg = DataGroups(ms.to_coord_string()) assert len(dg.dg_list) == 2 check_dg(dg.sdg("coord", strict=True), test_value) ms.frozen_indices = {0, 1} test_value = """ 0.00000000000000 0.00000000000000 0.00000000000000 c f 0.00000000000000 0.00000000000000 2.86118897312869 o f 0.00000000000000 0.00000000000000 -2.86118897312869 o """ dg = DataGroups(ms.to_coord_string()) assert len(dg.dg_list) == 2 check_dg(dg.sdg("coord", strict=True), test_value)
def test_linp(self, molecule, control_filepath, delete_tmp_dir): ms = MoleculeSystem(molecule) ms.int_def.append( PerpendicularBendingAngle(indices=[[0, 1, 2, 3]], value=20, status="f")) assert ms.has_inconsistencies() with temp_dir(delete_tmp_dir) as tmp_dir: ms.to_file("coord", fmt="coord") shutil.copy2(control_filepath, "control") dr = DefineRunner(parameters=dr_parameters) assert dr.run_update_internal_coords() ms_new = MoleculeSystem.from_file("coord") assert not ms_new.has_inconsistencies() # check that intdef is present and that the value has been updated assert len(ms_new.int_def) == 1 assert ms_new.int_def[0].value == pytest.approx( ms.int_def[0].value, abs=1e-4) # check that there are the same user-defined bonds assert ms.user_defined_bonds == ms_new.user_defined_bonds # check that in redundant the coordinate has been taken into account dg = DataGroups.from_file("coord") redundant = dg.sdg("redundant", strict=True) assert re.search( r"\d+\s+f\s+1\.0+\s+linp\s+1\s+2\s+3\s+4\s+val=\s*20", redundant) assert str(ms_new.int_def[0])
def test_to_file(self, molecule, delete_tmp_dir): ms = MoleculeSystem(molecule) with temp_dir(delete_tmp_dir) as tmp_dir: fname = os.path.join(tmp_dir, 'coord_test') ms.to_file(filepath=fname, fmt="coord") assert os.path.isfile("coord_test") dg = DataGroups.from_file("coord_test") assert dg.show_data_group("coord") is not None ms.to_file("mol_test.xyz") assert os.path.isfile("mol_test.xyz") assert ms.from_file("mol_test.xyz") is not None
def test_check_index(self, molecule): ms = MoleculeSystem(molecule) with pytest.raises( ValueError, match= "One of the indices representing the atoms is negative or larger then the number of sites" ): ms._check_index([5]) with pytest.raises( ValueError, match= "One of the indices representing the atoms is negative or larger then the number of sites" ): ms._check_index([-1]) assert ms._check_index([4]) is None
def from_string(cls, string): """ Creates Gradient object reading from a given file. Args: string (str): the string of the "grad" datagroup. """ # skip the first as it is before the first cycles = string.split("cycle =")[1:] gradients = [] energies = [] molecules = [] for c in cycles: lines = c.splitlines() header = lines[0] match = re.search(r"energy\s+=\s+([+-]?[0-9]*[.]?[0-9]+)", header) energies.append(float(match.group(1))) coordinates = [] grad = [] for l in lines[1:]: l = l.replace("D", "E") lsp = l.split() if not lsp: continue # can be with or without frozen indices if len(lsp) == 4 or len(lsp) == 5: coordinates.append(l) elif len(lsp) == 3: grad.append([float(g) for g in lsp]) else: raise RuntimeError( "Encountered line with unexpected number of tokens: {}" .format(l)) gradients.append(grad) mol, fi = get_mol_and_indices_frozen("\n".join(coordinates)) molecules.append(MoleculeSystem(molecule=mol, frozen_indices=fi)) return cls(gradients=gradients, energies=energies, molecules=molecules)
def test_dummy_atoms(self, molecule_filepath): ms = MoleculeSystem.from_file(molecule_filepath, fmt="coord") mol = ms.molecule print(mol[-1].specie) print(mol[-1].specie.__class__) # Pymatgen's Specie and DummySpecie have been changed to Species and # DummySpecies in v2020.10.9. We keep testing both for backward compatibility. assert isinstance(mol[-1].specie, (DummySpecies, DummySpecie)) assert mol[-1].specie.symbol == "Q" test_value2 = """ 0.00000000000000 0.00000000000000 -0.12178983933899 o 1.41713420892173 0.00000000000000 0.96657854674257 h -1.41713420892173 0.00000000000000 0.96657854674257 h 0.00000000000000 0.00000000000000 0.00000000000000 q """ dg = DataGroups(ms.to_coord_string()) assert len(dg.dg_list) == 2 check_dg(dg.sdg("coord", strict=True), test_value2) assert_MSONable(ms)
def test_add_dihedral(self, molecule): ms = MoleculeSystem(molecule) ms.add_dihedral(1, 2, 3, 4) assert not ms.has_inconsistencies() assert len(ms.user_defined_bonds) == 3 ms.add_dihedral(0, 1, 2, 3, status="k", add_user_def_bonds=False, value=35.26438972) assert not ms.has_inconsistencies() assert len(ms.user_defined_bonds) == 3 ms.add_dihedral(2, 3, 4, 1, value=10) assert ms.has_inconsistencies() ms.add_dihedral([0, 1], [2, 3], [3, 4], [1, 0]) assert len(ms.int_def[-1].indices) == 2 with pytest.raises(ValueError): ms.add_dihedral([1, 2, 3], [1, 2], [2, 3], [3, 4])
def test_add_bond_angle(self, molecule): ms = MoleculeSystem(molecule) ms.add_bond_angle(1, 2, 3) assert not ms.has_inconsistencies() assert len(ms.user_defined_bonds) == 2 ms.add_bond_angle(0, 1, 2, status="k", add_user_def_bonds=False, value=35.26438972) assert not ms.has_inconsistencies() assert len(ms.user_defined_bonds) == 2 ms.add_bond_angle(2, 3, 4, value=10, weights=1.0) assert ms.has_inconsistencies() ms.add_bond_angle([0, 1], [2, 3], [3, 4]) assert len(ms.int_def[-1].indices) == 2 with pytest.raises(ValueError): ms.add_bond_angle([1, 2, 3], [1, 2], [2, 3])
def test_add_distance(self, molecule): ms = MoleculeSystem(molecule) ms.add_distance(1, 2) assert not ms.has_inconsistencies() assert len(ms.user_defined_bonds) == 1 ms.add_distance(0, 1, status="k", add_user_def_bonds=False, value=2.058455873547) assert not ms.has_inconsistencies() assert len(ms.user_defined_bonds) == 1 ms.add_distance(2, 3, value=10, weights=1.0) assert ms.has_inconsistencies() ms.add_distance([0, 1], [2, 3]) assert len(ms.int_def[-1].indices) == 2 with pytest.raises(ValueError): ms.add_distance([1, 2, 3], [1, 2]) assert_MSONable(ms)
def test_from_string(self): # basic test string = """ $coord .00000000000000 .00000000000000 .00000000000000 n -1.15103063747470 -1.99364354517457 .00000000000000 o 2.30206127494940 .00000000000000 .00000000000000 o -1.15103063747470 1.99364354517457 .00000000000000 o $end """ ms = MoleculeSystem.from_string(string=string, fmt="coord") mol = ms.molecule assert mol[1].coords[0] == pytest.approx(-0.6090991821345737) assert len(mol) == 4 assert len(ms.frozen_indices) == 0 assert_MSONable(ms) # no coord with pytest.raises(ValueError, match=r'^The string does not contain \$coord!$'): MoleculeSystem.from_string(string="$end", fmt="coord") # with frozen and internal definitions string = """ $coord .00000000000000 .00000000000000 .00000000000000 n f -1.15103063747470 -1.99364354517457 .00000000000000 o 2.30206127494940 .00000000000000 .00000000000000 o -1.15103063747470 1.99364354517457 .00000000000000 o f $intdef # definitions of internal coordinates 1 k 1.0000000000000 stre 1 2 val= 2.43987 2 f 1.0000000000000 bend 1 2 3 -0.5000000000000 bend 2 3 4 $end """ ms = MoleculeSystem.from_string(string=string, fmt="coord") mol = ms.molecule assert mol[1].coords[0] == pytest.approx(-0.6090991821345737) assert len(mol) == 4 assert ms.frozen_indices == {0, 3} assert len(ms.int_def) == 2 assert ms.int_def[0].value == pytest.approx(2.43987) assert ms.int_def[1].value == None assert ms.int_def[0].status == "k" assert ms.int_def[1].status == "f" assert ms.int_def[0].indices[0] == [0, 1] assert len(ms.int_def[1].indices) == 2 assert ms.int_def[1].weights[1] == pytest.approx(-0.5) dg = DataGroups(ms.to_coord_string()) dg_ref = DataGroups(string) assert len(dg.dg_list) == 3 check_dg(dg.sdg("coord", strict=True), dg_ref.sdg("coord", strict=True)) check_dg(dg.sdg("intdef", strict=True), dg_ref.sdg("intdef", strict=True)) # with user-defined bonds string = """ $coord .00000000000000 .00000000000000 .00000000000000 n -1.15103063747470 -1.99364354517457 .00000000000000 o 2.30206127494940 .00000000000000 .00000000000000 o -1.15103063747470 1.99364354517457 .00000000000000 o $user-defined bonds 1-2, 2 - 3,3|4 $end """ ms = MoleculeSystem.from_string(string=string, fmt="coord") mol = ms.molecule assert mol[1].coords[0] == pytest.approx(-0.6090991821345737) assert len(mol) == 4 assert ms.user_defined_bonds == {(0, "-", 1), (1, "-", 2), (2, "|", 3)} dg = DataGroups(ms.to_coord_string()) dg_ref = DataGroups(string) assert len(dg.dg_list) == 3 check_dg(dg.sdg("coord", strict=True), dg_ref.sdg("coord", strict=True)) check_user_defined_bonds_dg( dg.sdg("user-defined bonds", strict=True), dg_ref.sdg("user-defined bonds", strict=True)) # malformed user-defined bonds string = """ $coord .00000000000000 .00000000000000 .00000000000000 n -1.15103063747470 -1.99364354517457 .00000000000000 o 2.30206127494940 .00000000000000 .00000000000000 o -1.15103063747470 1.99364354517457 .00000000000000 o $user-defined bonds 1-2, 2 3,3|4 $end """ with pytest.raises(ValueError, match="Cannot parse user-defined bonds.*"): MoleculeSystem.from_string(string=string, fmt="coord") # from xyz format ms = MoleculeSystem.from_string(mol.to(fmt="xyz"), fmt="xyz") assert ms.molecule[1].coords[0] == pytest.approx(-0.6090991821345737)