Example #1
0
def _nto_pairs(
    molecule: mtr.Molecule,
    settings: mtr.Settings,
    num_nto_pairs: int,
    n_x: int,
    n_y: int,
    n_z: int,
) -> mtr.QChemInput:
    # number of alpha electrons
    n_alpha = int(round((sum(molecule.atomic_numbers) + molecule.charge) / 2))

    inp = mtr.QChemInput(settings=mtr.Settings())

    for i in range(settings["rem", "cis_n_roots"]):
        s = copy.deepcopy(settings)
        s["rem", "scf_guess"] = "read"
        s["rem", "skip_cis_rpa"] = True
        s["rem", "nto_pairs"] = True
        s["rem", "make_cube_files"] = "ntos"
        s["rem", "cubefile_state"] = i + 1
        s["plots", "comment"] = (
            f"\n  {n_x} -10.0 10.0\n" + f"  {n_y} -10.0 10.0\n" +
            f"  {n_z} -10.0 10.0\n" + f"  {2*num_nto_pairs} 0 0 0\n  " +
            " ".join(f"{n_alpha + i}"
                     for i in range(-num_nto_pairs + 1, num_nto_pairs + 1)))

        inp += mtr.QChemInput(settings=s)

    return inp
Example #2
0
    def compute(
        self,
        molecule: mtr.Molecule,
        settings: Optional[mtr.Settings] = None,
    ) -> mtr.Quantity:
        s = mtr.Settings() if settings is None else copy.deepcopy(settings)
        input_settings = self.defaults(s)

        neutral_sp = self.engine.single_point_frontier(self.gs_io,
                                                       name="neutral")
        cation_sp = self.engine.single_point(self.cation_io, name="cation")
        anion_sp = self.engine.single_point(self.anion_io, name="anion")

        cation = copy.deepcopy(molecule)
        cation.charge += 1
        cation.multiplicity = cation.multiplicity % 2 + 1

        anion = copy.deepcopy(molecule)
        anion.charge -= 1
        anion.multiplicity = anion.multiplicity % 2 + 1

        neutral_sp.requires(
            molecule=molecule,
            settings=input_settings,
        )
        cation_sp.requires(
            molecule=cation,
            settings=input_settings,
        )
        anion_sp.requires(
            molecule=anion,
            settings=input_settings,
        )

        wf = Workflow(neutral_sp, cation_sp, anion_sp)

        out = wf.compute()

        neutral, h**o, lumo = out["neutral"]
        cation = out["cation"]
        anion = out["anion"]

        ea = neutral - anion
        ip = cation - neutral

        J_squared = (ip + h**o)**2
        if ea > 0 * ea.unit:
            J_squared += (ea + lumo)**2

        return np.sqrt(J_squared.convert(mtr.eV**2).value.item()) * mtr.eV
Example #3
0
    def compute(
        self,
        molecule: mtr.Molecule,
        settings: Optional[mtr.Settings] = None,
        arguments: Optional[Iterable[str]] = None,
    ) -> Any:
        s = mtr.Settings() if settings is None else copy.deepcopy(settings)

        inp = mtr.QChemInput(molecule, settings=self.defaults(s))

        with self.io() as io:
            inp.write(io.inp)

            self.engine.execute(self.io, arguments=arguments)

            return self.parse(io.out)
Example #4
0
        def _objective(omega: float, _alpha: float) -> float:
            beta = 1 / epsilon - _alpha
            s = mtr.Settings() if settings is None else copy.deepcopy(settings)
            s = self.defaults(s)
            s["rem", "hf_sr"] = int(round(1000 * _alpha))
            s["rem", "hf_lr"] = int(1000 / epsilon)
            s["xc_functional"] = (
                ("X", "HF", _alpha),
                ("X", "wPBE", beta),
                ("X", "PBE", 1 - _alpha - beta),
                ("C", "PBE", 1.0),
            )
            omega = int(round(1000 * omega))
            s["rem", "omega"] = s["rem", "omega2"] = omega

            wd = mtr.expand(f"{io.work_dir}/{omega}")

            gs_io = mtr.IO("gs.in", "gs.out", wd)
            cation_io = mtr.IO("cation.in", "cation.out", wd)
            anion_io = mtr.IO("anion.in", "anion.out", wd)

            ke = self.engine.koopman_error(gs_io, cation_io, anion_io)

            return ke.compute(molecule, s).value
Example #5
0
    def compute(
        self,
        molecule: mtr.Molecule,
        settings: Optional[mtr.Settings] = None,
        num_nto_pairs: Optional[int] = 0,
        n_x: Optional[int] = 50,
        n_y: Optional[int] = 50,
        n_z: Optional[int] = 50,
    ) -> mtr.Molecule:
        s = mtr.Settings() if settings is None else copy.deepcopy(settings)

        inp = mtr.QChemInput(molecule, settings=self.defaults(s))

        if num_nto_pairs > 0:
            inp += _nto_pairs(molecule, s, num_nto_pairs, n_x, n_y, n_z)

        with self.io() as io:
            inp.write(io.inp)

            self.engine.execute(self.io)

            molecule.electronic_excitations = self.parse(io.out)

        return molecule
Example #6
0
 def __add__(self, other: mtr.QChemInput) -> str:
     return QChemInput(string=str(self) + "\n@@@\n\n" + str(other),
                       settings=mtr.Settings())
Example #7
0
def test_write_qchem_tdscf():
    settings = materia.Settings(
        dt=0.02,
        Stabilize=0,
        TCLOn=0,
        MaxIter=100,
        ApplyImpulse=1,
        ApplyCw=0,
        FieldFreq=0.7,
        Tau=0.07,
        FieldAmplitude=0.001,
        ExDir=1.0,
        EyDir=1.0,
        EzDir=1.0,
        Print=0,
        StatusEvery=10,
        SaveDipoles=1,
        DipolesEvery=2,
        SavePopulations=0,
        SaveFockEnergies=0,
        WriteDensities=0,
        SaveEvery=500,
        FourierEvery=5000,
        MMUT=1,
        LFLPPC=0,
    )

    out_str = textwrap.dedent("""                                 dt=0.02
                                 Stabilize=0
                                 TCLOn=0
                                 MaxIter=100
                                 ApplyImpulse=1
                                 ApplyCw=0
                                 FieldFreq=0.7
                                 Tau=0.07
                                 FieldAmplitude=0.001
                                 ExDir=1.0
                                 EyDir=1.0
                                 EzDir=1.0
                                 Print=0
                                 StatusEvery=10
                                 SaveDipoles=1
                                 DipolesEvery=2
                                 SavePopulations=0
                                 SaveFockEnergies=0
                                 WriteDensities=0
                                 SaveEvery=500
                                 FourierEvery=5000
                                 MMUT=1
                                 LFLPPC=0""")
    # FIXME: make this test work on Windows using pathlib

    mock_open = mock.mock_open()
    # mock_expand = mock.MagicMock(side_effect=lambda s: s)
    mock_os_makedirs = mock.MagicMock(side_effect=lambda s: s)

    with mock.patch("builtins.open", mock_open):
        with mock.patch("os.makedirs", mock_os_makedirs):
            materia.WriteQChemTDSCF(settings=settings,
                                    work_directory="/mock/path/to/dir").run()

        # mock_expand.assert_called_once_with("/mock/path")
    mock_os_makedirs.assert_called_once_with("/mock/path/to/dir")
    mock_open.assert_called_once_with("/mock/path/to/dir/TDSCF.prm", "w")
    mock_open().write.assert_called_once_with(out_str)
Example #8
0
def test_vasp_input():
    s = mtr.Settings()
    s["incar", "PREC"] = "Normal"
    s["incar", "ENCUT"] = 550
    s["incar", "IBRION"] = -1
    s["incar", "NSW"] = 0
    s["incar", "ISIF"] = 2
    s["incar", "NELMIN"] = 2
    s["incar", "EDIFF"] = 1.0e-5
    s["incar", "EDIFFG"] = -0.02
    s["incar", "VOSKOWN"] = 1
    s["incar", "NBLOCK"] = 1
    s["incar", "NWRITE"] = 1
    s["incar", "NELM"] = 60
    s["incar", "LUSE_VDW"] = True
    s["incar", "LASPH"] = True
    s["incar", "AGGAC"] = 0.0000
    s["incar", "GGA"] = "MK"
    s["incar", "PARAM1"] = 0.1234
    s["incar", "PARAM2"] = 1.0000
    s["incar", "ALGO"] = "Normal (blocked Davidson)"
    s["incar", "ISPIN"] = 2
    s["incar", "INIWAV"] = 1
    s["incar", "ISTART"] = 0
    s["incar", "ICHARG"] = 2
    s["incar", "LWAVE"] = False
    s["incar", "LCHARG"] = False
    s["incar", "ADDGRID"] = False
    s["incar", "ISMEAR"] = 1
    s["incar", "SIGMA"] = 0.2
    s["incar", "LREAL"] = False
    s["incar", "RWIGS"] = (1.17, 0.73)
    s["incar", "LDAU"] = True
    s["incar", "LDAUTYPE"] = 2
    s["incar", "LDAUL"] = (2, -1)
    s["incar", "LDAUU"] = (8.00, 0.00)
    s["incar", "LDAUJ"] = (4.00, 0.00)
    s["incar", "LDAUPRINT"] = 2
    s["poscar",
      "comment"] = "(Fe2 O3)24  (P1) ~ (COD #9015065)_1_2x2x1_1 0 0 1\
      surface_1 (#1)_2x2x1_1 (MD #5) (VASP)"

    s["poscar", "scaling"] = 1.0
    s["poscar", "bravais_matrix"] = np.hstack([[10.0498, 0, 0], [0, 8.7034, 0],
                                               [0, 0, 28.7163]])
    s["poscar", "Direct"] = True
    s["poscar", "num_atoms"] = (48, 72)
    s["kpoints", "comment"] = "Automatic grid"
    s["kpoints", "mesh_type"] = "Gamma"
    s["kpoints", "grid"] = (4, 4, 1)
    s["kpoints", "shift"] = (0.0, 0.0, 0.0)

    vasp_str = """PREC = Normal
ENCUT = 550
IBRION = -1
NSW = 0
ISIF = 2
NELMIN = 2
EDIFF = 1e-05
EDIFFG = -0.02
VOSKOWN = 1
NBLOCK = 1
NWRITE = 1
NELM = 60
LUSE_VDW = .TRUE.
LASPH = .TRUE.
AGGAC = 0.0
GGA = MK
PARAM1 = 0.1234
PARAM2 = 1.0
ALGO = Normal (blocked Davidson)
ISPIN = 2
INIWAV = 1
ISTART = 0
ICHARG = 2
LWAVE = .FALSE.
LCHARG = .FALSE.
ADDGRID = .FALSE.
ISMEAR = 1
SIGMA = 0.2
LREAL = .FALSE.
RWIGS = 1.17 0.73
LDAU = .TRUE.
LDAUTYPE = 2
LDAUL = 2 -1
LDAUU = 8.0 0.0
LDAUJ = 4.0 0.0
LDAUPRINT = 2
(Fe2 O3)24  (P1) ~ (COD #9015065)_1_2x2x1_1 0 0 1  surface_1 (#1)_2x2x1_1 (MD #5) (VASP)
1.0
10.0498  0.0  0.0
0.0  8.7034  0.0
0.0  0.0  28.7163
48 72

Automatic grid
Gamma
4  4  1
0.0  0.0  0.0


"""

    assert str(mtr.VASPInput(s) == vasp_str)