Ejemplo n.º 1
0
def test_modify_data_group_options(testdir):
    cc = DataGroups.from_file(
        os.path.join(testdir, 'control', "control_test-energy"))
    cc.modify_data_group_options("dft", {
        "gridsize": "gridsize m5",
        "ntheta": "ntheta 30"
    })

    dg = cc.show_data_group("dft")
    mod_lines = set(s.strip() for s in dg.splitlines())
    assert mod_lines == {"gridsize m5", "ntheta 30", "functional b-p", ""}

    cc = DataGroups.from_file(
        os.path.join(testdir, 'control', "control_test-energy"))
    cc.modify_data_group_options("dft", {"gridsize": None, "ntheta": None})

    dg = cc.show_data_group("dft")
    mod_lines = set(s.strip() for s in dg.splitlines())
    assert mod_lines == {"functional b-p", ""}

    cc = DataGroups.empty()
    cc.modify_data_group_options("dft", {
        "gridsize": None,
        "ntheta": "ntheta 30"
    })
    dg = cc.show_data_group("dft")
    mod_lines = set(s.strip() for s in dg.splitlines())
    assert mod_lines == {"ntheta 30", ""}
Ejemplo n.º 2
0
 def testrun_update_internal_coords(self, molecule_filepath,
                                    delete_tmp_dir):
     define_opt = get_define_template("dscf")
     define_opt["ired"] = True
     with temp_dir(delete_tmp_dir) as tmp:
         # run the full to generate all the files
         self.run_define_runner(define_opt, molecule_filepath)
         s = States.from_file("control")
         dg = DataGroups.from_file("coord")
         dg.kdg("redundant")
         dg.to_file("coord")
         # do not remove mos to trigger another path in DefineRunner
         self.run_define_runner({"ired": True}, None, "internal")
         dg_new = DataGroups.from_file("coord")
         assert dg_new.sdg("redundant")
Ejemplo n.º 3
0
def test_show_subfile_fname(testdir):
    cc = DataGroups.from_file(
        os.path.join(testdir, 'control', "control_test-energy"))
    assert cc.show_subfile_fname("redundant") == "coord"

    with pytest.raises(RuntimeError):
        cc.show_subfile_fname("scfintunit", raise_if_regular_and_subfile=True)
Ejemplo n.º 4
0
    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])
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
def test_show_data_group_option(testdir):
    cc = DataGroups.from_file(
        os.path.join(testdir, 'control', "control_test-energy"))

    assert cc.show_data_group_option("dft", "gridsize") == "   m3"
    assert cc.show_data_group_option("fake_dg", "fake_option") is None
    assert cc.show_data_group_option("dft", "fake_option") is None
    assert cc.show_data_group_option("dft", "fake_option",
                                     default="test") == "test"
Ejemplo n.º 8
0
    def remove_last_gradient(self, filename="control", backup_suffix=None):
        """
        Removes last gradient step from the grad data group and writes it to
        the correct file, depending on the original location of the data group.
        N.B. if the gradients are in control and not in an external file, this
        will call the to_file of the current instance of Control. If other
        modifications have been done to the dg_list will be written to the
        file as well.

        Args:
            filename (str): name of the file to which the current instance of
                Control will be written in case the gradients are control.
                If gradients are in external file it will be ignored.
            backup_suffix (str): if not None a file named filename+backup_suffix
                will be created with the current content of Control.

        Raises:
            RuntimeError: if there is no gradient step to be removed or if
                gradient file is missing.
        """
        grad_dg = self.show_data_group("grad",
                                       default="",
                                       show_from_subfile=True)

        if "cycle" not in grad_dg:
            raise RuntimeError(
                'No gradient to remove in the "grad" data group.')

        # take the string until before the last "cycle"
        m = re.match(r"(.+)\n\s*cycle.+$", grad_dg, re.DOTALL)
        new_grad_dg = m.group(1)

        block_data = self.show_data_group("grad",
                                          default="",
                                          show_from_subfile=False)

        dg_filename = self._get_subfile_fname(
            block_data, raise_if_regular_and_subfile=False)

        if dg_filename:
            dg = DataGroups.from_file(dg_filename)
            dg.change_data_group("grad", new_grad_dg)
            if backup_suffix:
                shutil.copy2(dg_filename, dg_filename + backup_suffix)
            dg.to_file(dg_filename)
        elif not filename:
            raise ValueError(
                "The datagroup is in the current file. An output filename"
                "should be specified.")
        else:
            self.change_data_group("grad", new_grad_dg)
            if backup_suffix:
                shutil.copy2(filename, filename + backup_suffix)
            self.to_file(filename)
Ejemplo n.º 9
0
def test_compare(testdir):
    cc1 = DataGroups.from_file(
        os.path.join(testdir, 'control', "control_test-energy"))
    cc2 = DataGroups.from_file(
        os.path.join(testdir, 'control', "control_test-energy"))
    assert cc1.compare(cc2) is None

    dg_missing = cc2.dg_list.pop(0)
    assert dg_missing in cc1.compare(cc2)

    cc2 = DataGroups.from_file(
        os.path.join(testdir, 'control', "control_test-energy"))
    cc2.cdg("symmetry", "c1")
    assert "symmetry" in cc1.compare(cc2)

    cc2 = DataGroups.from_file(
        os.path.join(testdir, 'control', "control_test-energy"))
    cc2.cdg("thize", "0.001")
    assert "thize" in cc1.compare(cc2)
    assert "thize" in cc1.compare(cc2, tol=1e-6)
    assert cc1.compare(cc2, tol=1e-2) is None
Ejemplo n.º 10
0
    def remove_last_energy(self, filename="control", backup_suffix=None):
        """
        Removes last energy step from the energy data group and writes it to
        the correct file, depending on the original location of the data group.
        N.B. if the energies are in control and not in an external file, this
        will call the to_file of the current instance of Control. If other
        modifications have been done to the dg_list will be written to the
        file as well.

        Args:
            filename (str): name of the file to which the current instance of
                Control will be written in case the energies are control.
                If energies are in external file it will be ignored.
            backup_suffix (str): if not None a file named filename+backup_suffix
                will be created with the current content of Control.

        Raises:
            RuntimeError: if there is no energy step to be removed or if energy
                file is missing.
        """
        energy_dg = self.show_data_group("energy",
                                         default="",
                                         show_from_subfile=True)

        energy_dg_sp = energy_dg.split("\n")
        if len(energy_dg_sp) < 3:
            raise RuntimeError(
                'No energy to remove in the "energy" data group.')
        energy_dg_sp.pop(-2)
        new_energy_dg_sp = '\n'.join(energy_dg_sp)

        block_data = self.show_data_group("energy",
                                          default="",
                                          show_from_subfile=False)

        dg_filename = self._get_subfile_fname(
            block_data, raise_if_regular_and_subfile=False)

        if dg_filename:
            dg = DataGroups.from_file(dg_filename)
            dg.change_data_group("energy", new_energy_dg_sp)
            if backup_suffix:
                shutil.copy2(dg_filename, dg_filename + backup_suffix)
            dg.to_file(dg_filename)
        elif not filename:
            raise ValueError(
                "The datagroup is in the current file. An output filename"
                "should be specified.")
        else:
            self.change_data_group("energy", new_energy_dg_sp)
            if backup_suffix:
                shutil.copy2(filename, filename + backup_suffix)
            self.to_file(filename)
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
    def from_file(cls, filename='gradient'):
        """
        Creates Gradient object reading from a given file.

        Args:
            filename (str): Name of the file from which this Gradient object
                should be read, default is "gradient".
        """
        dg = DataGroups.from_file(filename)
        string = dg.show_data_group("grad",
                                    show_from_subfile=True,
                                    raise_if_missing_subfile=True)
        return cls.from_string(string)
Ejemplo n.º 13
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
Ejemplo n.º 14
0
    def from_file(cls, filename='energy'):
        """Creates Energy object reading from a given file.

        Args:
            filename (str): Name of the file from which this Energy object
                should be read, default is "energy".
        Raises:
            RuntimeError: if the energy file comes from a subfile and is missing.
        """
        dg = DataGroups.from_file(filename)
        string = dg.show_data_group("energy",
                                    show_from_subfile=True,
                                    raise_if_missing_subfile=True)
        return cls.from_string(string)
Ejemplo n.º 15
0
    def from_file(cls, shells_type, filename="control"):
        """
        Generates an instance of Shells from a file containing
        the datagroup.

        Args:
            shells_type (str): the type of shell. The supported type are
                "closed", "alpha" or "beta".
            filename (str): the name of the file.

        Returns:
            Shells

        Raises:
            ValueError: if the shell of the specified type is not present
        """

        dg = DataGroups.from_file(filename)
        string = dg.show_data_group("{} shells".format(shells_type))
        if not string:
            raise ValueError("No shells of type {} if file {}".format(
                shells_type, filename))

        return cls.from_string(string)
Ejemplo n.º 16
0
    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)
Ejemplo n.º 17
0
def test_sdg_subfiles(testdir, delete_tmp_dir):
    with temp_dir(delete_tmp_dir):
        for fname in ['control', 'coord', 'energy', 'mos', 'basis']:
            shutil.copy2(
                os.path.join(testdir, 'control',
                             '{}_test-subfiles'.format(fname)), fname)
        cc = DataGroups.from_file("control")
        energy_dg = cc.sdg(data_group='energy',
                           show_from_subfile=True,
                           raise_if_multiple_subfiles=False,
                           raise_if_missing_subfile=False,
                           raise_if_regular_and_subfile=False)
        assert energy_dg == '      SCF               ' \
                            'SCFKIN            SCFPOT\n' \
                            '     1   -40.48328750375' \
                            '    39.86406749278   -80.34735499653\n'
        udef_bonds_dg = cc.sdg(data_group='user-defined bonds',
                               show_from_subfile=True,
                               raise_if_multiple_subfiles=False,
                               raise_if_missing_subfile=False,
                               raise_if_regular_and_subfile=False)
        assert udef_bonds_dg == '\n'
        udef_bonds_dg = cc.sdg(data_group='user-defined bonds',
                               show_from_subfile=False,
                               raise_if_multiple_subfiles=False,
                               raise_if_missing_subfile=False,
                               raise_if_regular_and_subfile=False)
        assert udef_bonds_dg == '    file=coord\n'
        redundant_dg = cc.sdg(data_group='redundant',
                              show_from_subfile=True,
                              raise_if_multiple_subfiles=False,
                              raise_if_missing_subfile=False,
                              raise_if_regular_and_subfile=False)
        assert redundant_dg.startswith('\n     number_of_atoms'
                                       '             5\n'
                                       '     degrees_of_freedom'
                                       '          9\n'
                                       '     internal_coordinates'
                                       '        9\n'
                                       '     frozen_coordinates'
                                       '          0\n'
                                       '   1 k  1.0000000000000 stre'
                                       '    1    2'
                                       '           val=   2.06326\n')
        assert redundant_dg.endswith('         7\n           8'
                                     '           0.699953222    8    0\n'
                                     '         8\n           9'
                                     '           0.699953222    9    0\n'
                                     '         9\n')
        basis_dg = cc.sdg(data_group='basis',
                          show_from_subfile=True,
                          raise_if_multiple_subfiles=False,
                          raise_if_missing_subfile=False,
                          raise_if_regular_and_subfile=False)
        assert basis_dg.startswith('\n*\nc SVP\n*\n')
        assert basis_dg.endswith('   1  p\n'
                                 ' 0.80000000000       1.0000000000\n*\n')
        mos_dg = cc.sdg(data_group='scfmo',
                        show_from_subfile=True,
                        raise_if_multiple_subfiles=False,
                        raise_if_missing_subfile=False,
                        raise_if_regular_and_subfile=False)
        assert mos_dg.startswith('    scfconv=6   format(4d20.14)\n'
                                 '     1  a1     '
                                 'eigenvalue=-.98973943603420D+01'
                                 '   nsaos=6\n')
        assert mos_dg.endswith('-.11000018463806D+01-.60830569311504D+00'
                               '0.13711445998604D+010.13421520432673D+01\n'
                               '0.53804368223874D+00-.91129252301913D+00'
                               '0.11101532709297D+01\n')
        scfintunit_dg = cc.sdg(data_group='scfintunit',
                               show_from_subfile=True,
                               raise_if_multiple_subfiles=False,
                               raise_if_missing_subfile=False,
                               raise_if_regular_and_subfile=False)
        assert scfintunit_dg == '\n unit=30       size=35' \
                                '       file=twoint1\n' \
                                ' unit=31       size=35' \
                                '       file=twoint2\n'
        with pytest.raises(RuntimeError,
                           match='Multiple "file=FILENAME" directives.'):
            cc.sdg(data_group='scfintunit',
                   show_from_subfile=True,
                   raise_if_multiple_subfiles=True,
                   raise_if_missing_subfile=False,
                   raise_if_regular_and_subfile=False)

        with pytest.raises(RuntimeError,
                           match=r'Both a reference to a file '
                           r'\("file=FILENAME"\) and regular data '
                           r'blocks are in the data group.'):
            cc.sdg(data_group='user-defined',
                   show_from_subfile=True,
                   raise_if_multiple_subfiles=False,
                   raise_if_missing_subfile=False,
                   raise_if_regular_and_subfile=True)

        with pytest.raises(RuntimeError,
                           match='File "gradient" for data group "grad" '
                           'is missing.'):
            cc.sdg(data_group='grad',
                   show_from_subfile=True,
                   raise_if_multiple_subfiles=False,
                   raise_if_missing_subfile=True,
                   raise_if_regular_and_subfile=False)

        grad_db = cc.sdg(data_group='grad',
                         show_from_subfile=True,
                         raise_if_multiple_subfiles=False,
                         raise_if_missing_subfile=False,
                         raise_if_regular_and_subfile=False)
        assert grad_db == '    file=gradient\n'

        # create a gradient empty file and check that the behavior is the same
        # as when the file is missing
        touch_file("gradient")
        with pytest.raises(RuntimeError,
                           match='File "gradient" for data group "grad" '
                           'is missing.'):
            cc.sdg(data_group='grad',
                   show_from_subfile=True,
                   raise_if_multiple_subfiles=False,
                   raise_if_missing_subfile=True,
                   raise_if_regular_and_subfile=False)

        grad_db = cc.sdg(data_group='grad',
                         show_from_subfile=True,
                         raise_if_multiple_subfiles=False,
                         raise_if_missing_subfile=False,
                         raise_if_regular_and_subfile=False)
        assert grad_db == '    file=gradient\n'
Ejemplo n.º 18
0
    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)
Ejemplo n.º 19
0
def test_datagroups():
    """Testing the DataGroups object."""
    # Testing : no input
    with pytest.raises(expected_exception=ValueError,
                       match=r'^Both "string" and "dg_list" are None.$'):
        DataGroups()

    # Testing initialization
    dg = DataGroups(string=' $title\n$end')
    assert dg.initial_string == ' $title\n$end'
    assert str(dg) == '$title\n$end\n'
    assert dg.dg_list == ['$title\n', '$end\n']
    assert dg.ndg == 1

    dg = DataGroups(
        dg_list=['$title title\n', '$coord  file=coord\n', '$end\n'])
    assert dg.initial_string == '$title title\n$coord  file=coord\n$end\n'

    assert str(dg) == '$title title\n$coord  file=coord\n$end\n'

    dg = DataGroups(
        string=' $title\n$end',
        dg_list=['$title title\n', '$coord  file=coord\n', '$end\n'])
    assert dg.initial_string == ' $title\n$end'
    assert str(dg) == '$title title\n$coord  file=coord\n$end\n'

    # Testing add data group
    dg.add_data_group('scfiterlimit', '30')
    assert dg.dg_list[-2] == '$scfiterlimit 30\n'
    assert dg.initial_string == ' $title\n$end'
    assert str(dg) == '$title title\n$coord  file=coord\n' \
                      '$scfiterlimit 30\n$end\n'

    # Testing show data group
    coord_data_block = dg.show_data_group('coord')
    assert coord_data_block == '  file=coord\n'
    assert dg.show_data_group("non_existing_dg") is None
    assert dg.show_data_group("non_existing_dg",
                              default="fake_value") == "fake_value"

    # Testing kill data group
    dg.kill_data_group('coord')
    assert dg.dg_list == ['$title title\n', '$scfiterlimit 30\n', '$end\n']

    # Testing add data group with "-" and space
    dg = DataGroups.empty()
    dg.add_data_group('user-defined bonds', '    file=coord')
    assert dg.dg_list[-2] == '$user-defined bonds    file=coord\n'

    # Testing add data group with existing data group
    dg.add_data_group('scfiterlimit', '30')
    with pytest.raises(expected_exception=RuntimeError,
                       match=r'^Data group "\$scfiterlimit" already exists '
                       r'in this DataGroups object.$'):
        dg.add_data_group('scfiterlimit', '60')

    # Testing add data group with invalid name
    dg = DataGroups.empty()
    invalid_name_regex = r'^Data group should start with a letter and be ' \
                         r'followed by alphanumeric characters, a space, "-", "_", "\(" or "\)".$'
    with pytest.raises(expected_exception=ValueError,
                       match=invalid_name_regex):
        dg.add_data_group('0datagroup', '')

    with pytest.raises(expected_exception=ValueError,
                       match=invalid_name_regex):
        dg.add_data_group('data.group', '')

    # Testing show data group with strict=False
    dg = DataGroups(dg_list=[
        '$title title\n', '$coord  file=coord\n', '$scfiterlimit 30\n',
        '$scfconv 6\n', '$scfdamp   start=0.700  '
        'step=0.050  min=0.050\n', '$end\n'
    ])
    scfiter_data_block = dg.show_data_group('scfiter', strict=False)
    assert scfiter_data_block == '30\n'
    scfda_data_block = dg.show_data_group('scfda', strict=False)
    assert scfda_data_block == '  start=0.700  step=0.050  min=0.050\n'

    # Testing show data group with strict=False with multiple matches
    with pytest.raises(expected_exception=RuntimeError,
                       match=r'^Found multiple occurrences of data group '
                       r'"\$scf".$'):
        dg.show_data_group('scf', strict=False)

    # Testing change data group
    scfiterlimit_data_block = dg.show_data_group('scfiterlimit', strict=True)
    assert scfiterlimit_data_block == ' 30\n'
    dg.change_data_group('scfiterlimit', '40')
    scfiterlimit_data_block = dg.show_data_group('scfiterlimit', strict=True)
    assert scfiterlimit_data_block == ' 40\n'
    assert str(dg).endswith('step=0.050  min=0.050\n$scfiterlimit 40\n$end\n')
    # when the value is None change_data_group should remove the data group
    dg.change_data_group('scfiterlimit', None)
    assert "scfiterlimit" not in str(dg)

    # Testing as_dict/from_dict
    dg = DataGroups(dg_list=[
        '$title title\n', '$coord  file=coord\n', '$scfiterlimit 30\n',
        '$scfconv 6\n', '$scfdamp   start=0.700  '
        'step=0.050  min=0.050\n', '$end\n'
    ])
    dg_dict = dg.as_dict()
    dg_from_dict = DataGroups.from_dict(dg_dict)
    assert dg.dg_list == dg_from_dict.dg_list
    assert str(dg) == str(dg_from_dict)
    assert dg.initial_string == dg_from_dict.initial_string

    dg = DataGroups(dg_list=[
        '$title title\n', '$coord  file=coord\n', '$scfiterlimit 30\n',
        '$scfconv 6\n', '$scfdamp   start=0.700  '
        'step=0.050  min=0.050\n', '$end\n'
    ],
                    string='$title\n$end\n')
    dg_dict = dg.as_dict()
    dg_from_dict = DataGroups.from_dict(dg_dict)
    assert dg.dg_list == dg_from_dict.dg_list
    assert str(dg) == str(dg_from_dict)
    assert dg.initial_string == dg_from_dict.initial_string

    # Test to_file and from_file
    with tempfile.TemporaryDirectory() as tmpdir:
        fname = os.path.join(tmpdir, 'control_test')
        dg.to_file(filename=fname)
        dg_from_file = DataGroups.from_file(filename=fname)
        assert dg.dg_list == dg_from_file.dg_list
Ejemplo n.º 20
0
def test_empty(control):
    c = DataGroups.empty()
    assert "$end" == str(c).strip()
Ejemplo n.º 21
0
    def from_string(cls, string, fmt="coord"):
        """
        Creates an instance from a string. Could be the string of a coord file
        or any format supported by pymatgen Molecule.

        Args:
            string (str): the string with the data.
            fmt (str): the format of the data. could be "coord" for Turbomole
                coord file or any format supported in pymatgen Molecule.

        Returns:
            An instance of MoleculeSystem.
        """

        if fmt == "coord":
            dg = DataGroups(string=string)
            coordinates_str = dg.sdg("$coord", strict=True)
            if not coordinates_str:
                raise ValueError("The string does not contain $coord!")
            mol, fi = get_mol_and_indices_frozen(coordinates_str)

            int_def_str = dg.sdg("$intdef", strict=True)
            int_def = []
            if int_def_str:
                lines = []
                # remove empty lines and comments
                for l in int_def_str.splitlines():
                    lstrip = l.strip()
                    if lstrip and not lstrip.startswith("#"):
                        lines.append(l)
                int_def_str = "\n".join(lines)
                # split based on the presence of the index plus the status.
                # In a case like this:
                #    1 k  1.0000000000000 stre    4    1           val=   1.80084
                #    2 k  1.0000000000000 bend    4    3    1      val= 106.27756
                #         1.0000000000000 bend    3    2    1
                #         1.0000000000000 bend    2    4    1
                #    3 f  1.0000000000000 tors    1    2    3    4
                # will split in 3 groups based on the presence of the digit plus k, f, d or i
                # at the beginning of the line.
                r = r"^\s*\d+\s+[kfdi]\s+.*?(?=\s*\d+\s+[kfdi]\s+|\Z)"
                for group in re.findall(r, int_def_str,
                                        re.DOTALL | re.MULTILINE):
                    int_def.append(InternalDefinition.from_string(group))

            user_def_bonds_str = dg.sdg("$user-defined bonds", strict=True)
            user_def_bonds = set()
            if user_def_bonds_str:
                # parses a line of this form:
                # 1-2, 3-4, 5|6
                # splitting first on "," and then on "-" and "|"
                for l in user_def_bonds_str.splitlines():
                    l = l.strip()
                    if not l or l.startswith("#"):
                        continue
                    for bond in l.split(","):
                        for separator in ("-", "|"):
                            if separator in bond:
                                bond_indices = bond.split(separator)
                                if len(bond_indices) != 2:
                                    raise ValueError(
                                        "Cannot parse user-defined bonds for line: {}"
                                        .format(l))
                                index_1 = int(bond_indices[0]) - 1
                                index_2 = int(bond_indices[1]) - 1
                                user_def_bonds.add(
                                    (index_1, separator, index_2))
                                break
                        else:
                            raise ValueError(
                                "Cannot parse user-defined bonds for line: {}".
                                format(l))

            return cls(mol,
                       int_def=int_def,
                       frozen_indices=fi,
                       user_defined_bonds=user_def_bonds)

        else:
            return cls(Molecule.from_str(string, fmt))