示例#1
0
    def test_obtain_guesses_by_inspection(self):
        from adcc.workflow import obtain_guesses_by_inspection

        refstate = cache.refstate["h2o_sto3g"]
        ground_state = adcc.LazyMp(refstate)
        matrix2 = adcc.AdcMatrix("adc2", ground_state)
        matrix1 = adcc.AdcMatrix("adc1", ground_state)

        # Test that the right number of guesses is returned ...
        for mat in [matrix1, matrix2]:
            for i in range(4, 9):
                res = obtain_guesses_by_inspection(mat,
                                                   n_guesses=i,
                                                   kind="singlet")
                assert len(res) == i

        for i in range(4, 9):
            res = obtain_guesses_by_inspection(matrix2,
                                               n_guesses=i,
                                               kind="triplet",
                                               n_guesses_doubles=2)
            assert len(res) == i

        with pytest.raises(InputError):
            obtain_guesses_by_inspection(matrix1,
                                         n_guesses=4,
                                         kind="any",
                                         n_guesses_doubles=2)
        with pytest.raises(InputError):
            obtain_guesses_by_inspection(matrix1, n_guesses=40, kind="any")
示例#2
0
def dump_matrix(basis, method):
    key = basis.replace("*", "s").replace("-", "").lower()
    fn = "water_" + key + "_" + method + ".hdf5"
    if os.path.isfile(fn):
        with h5py.File(fn, "r") as fp:
            return np.asarray(fp["adc_matrix"])

    mol = gto.M(atom="""O 0 0 0
                H 0 0 1.795239827225189
                H 1.693194615993441 0 -0.599043184453037""",
                basis=basis,
                unit="Bohr")
    scfres = scf.RHF(mol)
    scfres.conv_tol = 1e-13
    scfres.kernel()

    mat = adcc.AdcMatrix(method, adcc.ReferenceState(scfres))
    key = basis.replace("*", "s").replace("-", "").lower()
    mat = mat.to_dense_matrix()

    fn = "water_" + key + "_" + method + ".hdf5"
    if not os.path.isfile(fn):
        with h5py.File(fn, "w") as fp:
            fp.create_dataset("adc_matrix", data=mat, compression="gzip")
    with h5py.File(fn, "r") as fp:
        return np.asarray(fp["adc_matrix"])
示例#3
0
 def test_intermediates_adc2(self):
     ground_state = adcc.LazyMp(cache.refstate["h2o_sto3g"])
     matrix = adcc.AdcMatrix("adc2", ground_state)
     assert isinstance(matrix.intermediates, Intermediates)
     intermediates = Intermediates(ground_state)
     matrix.intermediates = intermediates
     assert matrix.intermediates == intermediates
示例#4
0
    def test_adc2_shift_invert_triplets(self):
        refdata = cache.reference_data["h2o_sto3g"]
        matrix = adcc.AdcMatrix("adc2", LazyMp(cache.refstate["h2o_sto3g"]))
        conv_tol = 1e-5
        shift = -0.5

        # Construct shift and inverted matrix:
        shinv = IterativeInverse(AdcMatrixShifted(matrix, shift),
                                 conv_tol=conv_tol / 10,
                                 Pinv=JacobiPreconditioner,
                                 callback=cg_print)

        # Solve for triplets
        guesses = adcc.guesses_triplet(matrix, n_guesses=5, block="ph")
        symm = IndexSpinSymmetrisation(matrix, enforce_spin_kind="triplet")
        res = lanczos(shinv,
                      guesses,
                      n_ep=5,
                      callback=la_print,
                      explicit_symmetrisation=symm)
        assert res.converged

        # Undo spectral transformation and compare
        eigenvalues = sorted(1 / res.eigenvalues - shift)
        ref_triplets = refdata["adc2"]["triplet"]["eigenvalues"][:5]
        assert eigenvalues == approx(ref_triplets)
示例#5
0
class TestAdcMatrixInterface(unittest.TestCase):
    def test_properties_adc2(self):
        case = "h2o_sto3g"
        method = "adc2"

        reference_state = cache.refstate[case]
        ground_state = adcc.LazyMp(reference_state)
        matrix = adcc.AdcMatrix(method, ground_state)

        assert matrix.ndim == 2
        assert not matrix.is_core_valence_separated
        assert matrix.shape == (1640, 1640)
        assert len(matrix) == 1640

        assert matrix.axis_blocks == ["ph", "pphh"]
        assert sorted(matrix.axis_spaces.keys()) == matrix.axis_blocks
        assert sorted(matrix.axis_lengths.keys()) == matrix.axis_blocks
        assert matrix.axis_spaces["ph"] == ["o1", "v1"]
        assert matrix.axis_spaces["pphh"] == ["o1", "o1", "v1", "v1"]
        assert matrix.axis_lengths["ph"] == 40
        assert matrix.axis_lengths["pphh"] == 1600

        assert matrix.reference_state == reference_state
        assert matrix.mospaces == reference_state.mospaces
        assert isinstance(matrix.timer, adcc.timings.Timer)
示例#6
0
class TestAdcMatrixShifted(unittest.TestCase):
    def construct_matrices(self, case, shift):
        reference_state = cache.refstate[case]
        ground_state = adcc.LazyMp(reference_state)
        matrix = adcc.AdcMatrix("adc3", ground_state)
        shifted = AdcMatrixShifted(matrix, shift)
        return matrix, shifted
示例#7
0
class TestAdcMatrixInterface(unittest.TestCase):
    def test_properties_adc2(self):
        case = "h2o_sto3g"
        method = "adc2"

        reference_state = cache.refstate[case]
        ground_state = adcc.LazyMp(reference_state)
        matrix = adcc.AdcMatrix(method, ground_state)

        assert matrix.ndim == 2
        assert not matrix.is_core_valence_separated
        assert matrix.shape == (1640, 1640)
        assert len(matrix) == 1640

        assert matrix.blocks == ["s", "d"]
        assert matrix.has_block("s")
        assert matrix.has_block("d")
        assert not matrix.has_block("t")
        assert matrix.block_spaces("s") == ["o1", "v1"]
        assert matrix.block_spaces("d") == ["o1", "o1", "v1", "v1"]

        assert matrix.reference_state == reference_state
        assert matrix.mospaces == reference_state.mospaces
        assert isinstance(matrix.timer, adcc.timings.Timer)
        assert isinstance(matrix.to_cpp(), libadcc.AdcMatrix)
示例#8
0
    def template_pcm_linear_response_formaldehyde(self, basis, method, backend):
        if method != "adc1":
            pytest.skip("Reference only exists for adc1.")

        c = config[backend]
        basename = f"formaldehyde_{basis}_pcm_{method}"
        result = c["data"][basename]

        run_hf = c["run_hf"]
        scfres = run_hf(static_data.xyz["formaldehyde"], basis, charge=0,
                        multiplicity=1, conv_tol=1e-12, conv_tol_grad=1e-11,
                        max_iter=150, pcm_options=c["pcm_options"])

        assert_allclose(scfres.energy_scf, result["energy_scf"], atol=1e-8)

        matrix = adcc.AdcMatrix(method, scfres)
        solvent = AdcExtraTerm(matrix, {'ph_ph': block_ph_ph_0_pcm})

        matrix += solvent
        assert len(matrix.extra_terms)

        state = adcc.run_adc(matrix, n_singlets=5, conv_tol=1e-7,
                             environment=False)
        assert_allclose(
            state.excitation_energy_uncorrected,
            result["lr_excitation_energy"],
            atol=1e-5
        )

        state_cis = adcc.ExcitedStates(state, property_method="adc0")
        assert_allclose(
            state_cis.oscillator_strength,
            result["lr_osc_strength"], atol=1e-3
        )

        # invalid combination
        with pytest.raises(InputError):
            adcc.run_adc(scfres, method=method, n_singlets=5,
                         environment={"linear_response": True, "ptlr": True})

        # no environment specified
        with pytest.raises(InputError):
            adcc.run_adc(scfres, method=method, n_singlets=5)

        # automatically add coupling term
        state = adcc.run_adc(scfres, method=method, n_singlets=5,
                             conv_tol=1e-7, environment="linear_response")
        assert_allclose(
            state.excitation_energy_uncorrected,
            result["lr_excitation_energy"],
            atol=1e-5
        )

        if backend == "psi4":
            # remove cavity files from PSI4 PCM calculations
            remove_cavity_psi4()
示例#9
0
    def test_adc2_triplets(self):
        refdata = cache.reference_data["h2o_sto3g"]
        matrix = adcc.AdcMatrix("adc2", LazyMp(cache.refstate["h2o_sto3g"]))

        # Solve for triplets
        guesses = adcc.guesses_triplet(matrix, n_guesses=6, block="ph")
        res = lanczos(matrix, guesses, n_ep=6, which="SM")

        ref_triplets = refdata["adc2"]["triplet"]["eigenvalues"][:6]
        assert res.converged
        assert res.eigenvalues == approx(ref_triplets)
示例#10
0
    def test_adc2_triplets(self):
        refdata = cache.reference_data["h2o_sto3g"]
        matrix = adcc.AdcMatrix("adc2", LazyMp(cache.refstate["h2o_sto3g"]))

        # Solve for triplets
        guesses = adcc.guesses_triplet(matrix, n_guesses=10, block="s")
        res = jacobi_davidson(matrix, guesses, n_ep=10)

        ref_triplets = refdata["adc2"]["triplet"]["eigenvalues"]
        assert res.converged
        assert res.eigenvalues == approx(ref_triplets)
示例#11
0
class TestAdcMatrix(unittest.TestCase):
    def construct_matrix(self, case, method):
        refdata = cache.reference_data[case]
        matdata = refdata[method]["matrix"]
        if "cvs" in method:
            refstate = cache.refstate_cvs[case]
        else:
            refstate = cache.refstate[case]

        matrix = adcc.AdcMatrix(method, refstate)
        return matrix, matdata
示例#12
0
    def template_pe_linear_response_formaldehyde(self, basis, method, backend):
        if method != "adc2":
            pytest.skip("Reference only exists for adc2.")
        basename = f"formaldehyde_{basis}_pe_{method}"
        tm_result = tmole_data[basename]
        pe_options = {"potfile": pe_potentials["fa_6w"]}
        scfres = cached_backend_hf(backend,
                                   "formaldehyde",
                                   basis,
                                   pe_options=pe_options)
        assert_allclose(scfres.energy_scf, tm_result["energy_scf"], atol=1e-8)

        matrix = adcc.AdcMatrix(method, scfres)
        solvent = AdcExtraTerm(matrix, {'ph_ph': block_ph_ph_0_pe})

        # manually add the coupling term
        matrix += solvent
        assert len(matrix.extra_terms)

        assert_allclose(matrix.ground_state.energy(2),
                        tm_result["energy_mp2"],
                        atol=1e-8)
        state = adcc.run_adc(matrix,
                             n_singlets=5,
                             conv_tol=1e-7,
                             environment=False)
        assert_allclose(state.excitation_energy_uncorrected,
                        tm_result["excitation_energy"],
                        atol=1e-6)

        # invalid combination
        with pytest.raises(InputError):
            adcc.run_adc(scfres,
                         method=method,
                         n_singlets=5,
                         environment={
                             "linear_response": True,
                             "ptlr": True
                         })
        # no scheme specified
        with pytest.raises(InputError):
            adcc.run_adc(scfres, method=method, n_singlets=5)

        # automatically add coupling term
        state = adcc.run_adc(scfres,
                             method=method,
                             n_singlets=5,
                             conv_tol=1e-7,
                             environment="linear_response")
        assert_allclose(state.excitation_energy_uncorrected,
                        tm_result["excitation_energy"],
                        atol=1e-6)
示例#13
0
    def test_estimate_n_guesses(self):
        from adcc.workflow import estimate_n_guesses

        refstate = cache.refstate["h2o_sto3g"]
        ground_state = adcc.LazyMp(refstate)
        matrix = adcc.AdcMatrix("adc2", ground_state)

        # Check minimal number of guesses is 4 and at some point
        # we get more than four guesses
        assert 4 == estimate_n_guesses(matrix, n_states=1, singles_only=True)
        assert 4 == estimate_n_guesses(matrix, n_states=2, singles_only=True)
        for i in range(3, 20):
            assert i <= estimate_n_guesses(
                matrix, n_states=i, singles_only=True)
示例#14
0
    def test_adc1_linear_solve(self):
        conv_tol = 1e-9
        matrix = adcc.AdcMatrix("adc1", cache.refstate["h2o_sto3g"])
        rhs = adcc.guess_zero(matrix)
        rhs["s"].set_random()

        guess = rhs.copy()
        guess["s"].set_random()
        res = conjugate_gradient(matrix,
                                 rhs,
                                 guess,
                                 callback=cgprint,
                                 conv_tol=conv_tol)
        residual = matrix @ res.solution - rhs
        assert np.sqrt(residual @ residual) < conv_tol
示例#15
0
 def test_functionality(self):
     ground_state = adcc.LazyMp(cache.refstate["h2o_sto3g"])
     matrix = adcc.AdcMatrix("adc2", ground_state)
     vectors = [adcc.guess_zero(matrix) for i in range(2)]
     for vec in vectors:
         vec.set_random()
     v, w = vectors
     with pytest.raises(AttributeError):
         v.pph
     with pytest.raises(AttributeError):
         v.pph = w.ph
     # setattr with expression
     z = adcc.zeros_like(v)
     z.ph = v.ph + w.ph
     z -= w
     np.testing.assert_allclose(v.ph.to_ndarray(), z.ph.to_ndarray())
示例#16
0
    def template_singles_view(self, method):
        if "cvs" in method:
            reference_state = cache.refstate_cvs["h2o_sto3g"]
            shape = (8, 8)
            spaces_s = ["o2", "v1"]
        else:
            reference_state = cache.refstate["h2o_sto3g"]
            shape = (40, 40)
            spaces_s = ["o1", "v1"]
        matrix = adcc.AdcMatrix(method, adcc.LazyMp(reference_state))
        view = adcc.AdcBlockView(matrix, "s")

        assert view.ndim == 2
        assert view.is_core_valence_separated == ("cvs" in method)
        assert view.shape == shape
        assert len(view) == shape[0]

        assert view.blocks == ["s"]
        assert view.has_block("s")
        assert not view.has_block("d")
        assert not view.has_block("t")
        assert view.block_spaces("s") == spaces_s

        assert view.reference_state == reference_state
        assert view.mospaces == reference_state.mospaces
        assert isinstance(view.timer, adcc.timings.Timer)
        assert view.to_cpp() == matrix.to_cpp()

        # Check diagonal
        diff = matrix.diagonal("s") - view.diagonal("s")
        assert diff.dot(diff) < 1e-12

        # Check @ (one vector and multiple vectors)
        invec = adcc.guess_zero(matrix)
        invec["s"].set_random()
        # "d" left as zero
        invec_singles = adcc.AmplitudeVector(invec["s"])

        ref = matrix @ invec
        res = view @ invec_singles
        diff = res["s"] - ref["s"]
        assert diff.dot(diff) < 1e-12

        res = view @ [invec_singles, invec_singles, invec_singles]
        diff = [res[i]["s"] - ref["s"] for i in range(3)]
        assert max(d.dot(d) for d in diff) < 1e-12
示例#17
0
    def template_singles_view(self, method):
        if "cvs" in method:
            reference_state = cache.refstate_cvs["h2o_sto3g"]
            shape = (8, 8)
            spaces_ph = ["o2", "v1"]
        else:
            reference_state = cache.refstate["h2o_sto3g"]
            shape = (40, 40)
            spaces_ph = ["o1", "v1"]
        matrix = adcc.AdcMatrix(method, adcc.LazyMp(reference_state))
        view = matrix.block_view("ph_ph")

        assert view.ndim == 2
        assert view.is_core_valence_separated == ("cvs" in method)
        assert view.shape == shape
        assert len(view) == shape[0]

        assert view.axis_blocks == ["ph"]
        assert sorted(view.axis_spaces.keys()) == view.axis_blocks
        assert sorted(view.axis_lengths.keys()) == view.axis_blocks
        assert view.axis_spaces["ph"] == spaces_ph
        assert view.axis_lengths["ph"] == shape[0]

        assert view.reference_state == reference_state
        assert view.mospaces == reference_state.mospaces
        assert isinstance(view.timer, adcc.timings.Timer)

        # Check diagonal
        diff = matrix.diagonal().ph - view.diagonal().ph
        assert diff.dot(diff) < 1e-12

        # Check @ (one vector and multiple vectors)
        invec = adcc.guess_zero(matrix)
        invec.ph.set_random()
        # "d" left as zero
        invec_singles = adcc.AmplitudeVector(ph=invec.ph)

        ref = matrix @ invec
        res = view @ invec_singles
        diff = res.ph - ref.ph
        assert diff.dot(diff) < 1e-12

        res = view @ [invec_singles, invec_singles, invec_singles]
        diff = [res[i].ph - ref.ph for i in range(3)]
        assert max(d.dot(d) for d in diff) < 1e-12
示例#18
0
    def test_matvec_adc2(self):
        ground_state = adcc.LazyMp(cache.refstate["h2o_sto3g"])
        matrix = adcc.AdcMatrix("adc2", ground_state)

        vectors = [adcc.guess_zero(matrix) for i in range(3)]
        for vec in vectors:
            vec.set_random()
        v, w, x = vectors

        # Compute references:
        refv = matrix.matvec(v)
        refw = matrix.matvec(w)
        refx = matrix.matvec(x)

        # @ operator (1 vector)
        resv = matrix @ v
        diffv = refv - resv
        assert diffv.ph.dot(diffv.ph) < 1e-12
        assert diffv.pphh.dot(diffv.pphh) < 1e-12

        # @ operator (multiple vectors)
        resv, resw, resx = matrix @ [v, w, x]
        diffs = [refv - resv, refw - resw, refx - resx]
        for i in range(3):
            assert diffs[i].ph.dot(diffs[i].ph) < 1e-12
            assert diffs[i].pphh.dot(diffs[i].pphh) < 1e-12

        # compute matvec
        resv = matrix.matvec(v)
        diffv = refv - resv
        assert diffv.ph.dot(diffv.ph) < 1e-12
        assert diffv.pphh.dot(diffv.pphh) < 1e-12

        resv = matrix.rmatvec(v)
        diffv = refv - resv
        assert diffv.ph.dot(diffv.ph) < 1e-12
        assert diffv.pphh.dot(diffv.pphh) < 1e-12

        # Test apply
        resv.ph = matrix.block_apply("ph_ph", v.ph)
        resv.ph += matrix.block_apply("ph_pphh", v.pphh)
        refv = matrix.matvec(v)
        diffv = resv.ph - refv.ph
        assert diffv.dot(diffv) < 1e-12
示例#19
0
class TestAdcMatrixDenseExport(unittest.TestCase):
    def base_test(self, case, method, conv_tol=1e-8, **kwargs):
        kwargs.setdefault("n_states", 10)
        n_states = kwargs["n_states"]
        if "cvs" in method:
            refstate = cache.refstate_cvs[case]
        else:
            refstate = cache.refstate[case]

        matrix = adcc.AdcMatrix(method, refstate)
        state = adcc.run_adc(matrix, method=method, conv_tol=conv_tol, **kwargs)

        dense = matrix.to_dense_matrix()
        assert_allclose(dense, dense.T, rtol=1e-10, atol=1e-12)

        n_decimals = 10
        spectrum = np.linalg.eigvalsh(dense)
        rounded = np.unique(np.round(spectrum, n_decimals))[:n_states]
        assert_allclose(state.excitation_energies, rounded, atol=10 * conv_tol)
示例#20
0
    def test_diagonalise_adcmatrix(self):
        from adcc.workflow import diagonalise_adcmatrix

        refdata = cache.reference_data["h2o_sto3g"]
        matrix = adcc.AdcMatrix("adc2",
                                adcc.LazyMp(cache.refstate["h2o_sto3g"]))

        res = diagonalise_adcmatrix(matrix,
                                    n_states=3,
                                    kind="singlet",
                                    eigensolver="davidson")
        ref_singlets = refdata["adc2"]["singlet"]["eigenvalues"]
        assert res.converged
        assert res.eigenvalues == approx(ref_singlets[:3])

        guesses = adcc.guesses_singlet(matrix, n_guesses=6, block="ph")
        res = diagonalise_adcmatrix(matrix,
                                    n_states=3,
                                    kind="singlet",
                                    guesses=guesses)
        ref_singlets = refdata["adc2"]["singlet"]["eigenvalues"]
        assert res.converged
        assert res.eigenvalues == approx(ref_singlets[:3])

        with pytest.raises(InputError):  # Too low tolerance
            res = diagonalise_adcmatrix(matrix,
                                        n_states=9,
                                        kind="singlet",
                                        eigensolver="davidson",
                                        conv_tol=1e-14)

        with pytest.raises(InputError):  # Wrong solver method
            res = diagonalise_adcmatrix(matrix,
                                        n_states=9,
                                        kind="singlet",
                                        eigensolver="blubber")

        with pytest.raises(InputError):  # Too few guesses
            res = diagonalise_adcmatrix(matrix,
                                        n_states=9,
                                        kind="singlet",
                                        eigensolver="davidson",
                                        guesses=guesses)
示例#21
0
    def test_matvec_adc2(self):
        ground_state = adcc.LazyMp(cache.refstate["h2o_sto3g"])
        matrix = adcc.AdcMatrix("adc2", ground_state)
        cppmatrix = libadcc.AdcMatrix("adc2", ground_state)

        vectors = [adcc.guess_zero(matrix) for i in range(3)]
        for vec in vectors:
            vec["s"].set_random()
            vec["d"].set_random()
        v, w, x = vectors

        # Compute references:
        refv = adcc.empty_like(v)
        refw = adcc.empty_like(w)
        refx = adcc.empty_like(x)
        cppmatrix.compute_matvec(v.to_cpp(), refv.to_cpp())
        cppmatrix.compute_matvec(w.to_cpp(), refw.to_cpp())
        cppmatrix.compute_matvec(x.to_cpp(), refx.to_cpp())

        # @ operator (1 vector)
        resv = matrix @ v
        diffv = refv - resv
        assert diffv["s"].dot(diffv["s"]) < 1e-12
        assert diffv["d"].dot(diffv["d"]) < 1e-12

        # @ operator (multiple vectors)
        resv, resw, resx = matrix @ [v, w, x]
        diffs = [refv - resv, refw - resw, refx - resx]
        for i in range(3):
            assert diffs[i]["s"].dot(diffs[i]["s"]) < 1e-12
            assert diffs[i]["d"].dot(diffs[i]["d"]) < 1e-12

        # compute matvec
        matrix.compute_matvec(v, resv)
        diffv = refv - resv
        assert diffv["s"].dot(diffv["s"]) < 1e-12
        assert diffv["d"].dot(diffv["d"]) < 1e-12

        matrix.compute_apply("ss", v["s"], resv["s"])
        cppmatrix.compute_apply("ss", v["s"], refv["s"])
        diffv = resv["s"] - refv["s"]
        assert diffv.dot(diffv) < 1e-12
示例#22
0
    def base_adc2(self, kind, guess_function, max_iter=100):
        refdata = cache.reference_data["h2o_sto3g"]
        matrix = adcc.AdcMatrix("adc2", cache.refstate["h2o_sto3g"])

        conv_tol = 1e-6
        guesses = guess_function(matrix, n_guesses=1)
        symm = IndexSpinSymmetrisation(matrix, enforce_spin_kind=kind)
        inverse = IterativeInverse(matrix,
                                   Pinv=JacobiPreconditioner,
                                   conv_tol=conv_tol / 10,
                                   construct_guess=guess_from_previous)
        res = power_method(inverse,
                           guesses[0],
                           conv_tol=conv_tol,
                           explicit_symmetrisation=symm,
                           callback=powprint,
                           max_iter=max_iter)

        ref_singlets = refdata["adc2"][kind]["eigenvalues"]
        assert res.converged
        assert 1 / res.eigenvalues[0] == approx(ref_singlets[0])
示例#23
0
    def test_construct_adcmatrix(self):
        from adcc.workflow import construct_adcmatrix

        #
        # Construction from hfdata
        #
        hfdata = cache.hfdata["h2o_sto3g"]

        res = construct_adcmatrix(hfdata, method="adc3")
        assert isinstance(res, adcc.AdcMatrix)
        assert res.method == adcc.AdcMethod("adc3")
        assert res.mospaces.core_orbitals == []
        assert res.mospaces.frozen_core == []
        assert res.mospaces.frozen_virtual == []

        res = construct_adcmatrix(hfdata, method="cvs-adc3", core_orbitals=1)
        assert isinstance(res, adcc.AdcMatrix)
        assert res.method == adcc.AdcMethod("cvs-adc3")
        assert res.mospaces.core_orbitals == [0, 7]
        assert res.mospaces.frozen_core == []
        assert res.mospaces.frozen_virtual == []

        res = construct_adcmatrix(hfdata, method="adc2", frozen_core=1)
        assert res.mospaces.core_orbitals == []
        assert res.mospaces.frozen_core == [0, 7]
        assert res.mospaces.frozen_virtual == []

        res = construct_adcmatrix(hfdata, method="adc2", frozen_virtual=1)
        assert res.mospaces.core_orbitals == []
        assert res.mospaces.frozen_core == []
        assert res.mospaces.frozen_virtual == [6, 13]

        res = construct_adcmatrix(hfdata,
                                  method="adc2",
                                  frozen_virtual=1,
                                  frozen_core=1)
        assert res.mospaces.core_orbitals == []
        assert res.mospaces.frozen_core == [0, 7]
        assert res.mospaces.frozen_virtual == [6, 13]

        invalid_cases = [
            dict(),  # Missing method
            dict(method="dadadad"),  # Unknown method
            dict(frozen_core=1),  # Missing method
            dict(frozen_virtual=3),  # Missing method
            dict(core_orbitals=4),  # Missing method
            dict(method="cvs-adc2"),  # No core_orbitals
            dict(method="cvs-adc2", frozen_core=1),
            dict(method="adc2", core_orbitals=3),  # Extra core parameter
            dict(method="adc2", core_orbitals=3, frozen_virtual=2),
        ]
        for case in invalid_cases:
            with pytest.raises(InputError):
                construct_adcmatrix(hfdata, **case)

        #
        # Construction from LazyMp or ReferenceState
        #
        refst_ful = cache.refstate["h2o_sto3g"]
        refst_cvs = cache.refstate_cvs["h2o_sto3g"]
        gs_ful, gs_cvs = adcc.LazyMp(refst_ful), adcc.LazyMp(refst_cvs)

        for obj in [gs_ful, refst_ful]:
            res = construct_adcmatrix(obj, method="adc2")
            assert isinstance(res, adcc.AdcMatrix)
            assert res.method == adcc.AdcMethod("adc2")

            with pytest.raises(InputError, match=r"Cannot run a core-valence"):
                construct_adcmatrix(obj, method="cvs-adc2x")
            with pytest.warns(UserWarning,
                              match=r"^Ignored frozen_core parameter"):
                construct_adcmatrix(obj, frozen_core=3, method="adc1")
            with pytest.warns(UserWarning,
                              match=r"^Ignored frozen_virtual parameter"):
                construct_adcmatrix(obj, frozen_virtual=1, method="adc3")

        for obj in [gs_cvs, refst_cvs]:
            res = construct_adcmatrix(obj, method="cvs-adc2x")
            assert isinstance(res, adcc.AdcMatrix)
            assert res.method == adcc.AdcMethod("cvs-adc2x")

            with pytest.raises(InputError):
                construct_adcmatrix(obj)  # Missing method
            with pytest.raises(InputError, match=r"Cannot run a general"):
                construct_adcmatrix(obj, method="adc2")
            with pytest.warns(UserWarning,
                              match=r"^Ignored core_orbitals parameter"):
                construct_adcmatrix(obj, core_orbitals=2, method="cvs-adc1")

        #
        # Construction from ADC matrix
        #
        mtx_ful = adcc.AdcMatrix("adc2", gs_ful)
        mtx_cvs = adcc.AdcMatrix("cvs-adc2", gs_cvs)
        assert construct_adcmatrix(mtx_ful) == mtx_ful
        assert construct_adcmatrix(mtx_ful, method="adc2") == mtx_ful
        assert construct_adcmatrix(mtx_cvs) == mtx_cvs
        assert construct_adcmatrix(mtx_cvs, method="cvs-adc2") == mtx_cvs

        with pytest.warns(UserWarning, match=r"Ignored method parameter"):
            construct_adcmatrix(mtx_ful, method="adc3")
        with pytest.warns(UserWarning,
                          match=r"^Ignored core_orbitals parameter"):
            construct_adcmatrix(mtx_cvs, core_orbitals=2)
        with pytest.warns(UserWarning,
                          match=r"^Ignored frozen_core parameter"):
            construct_adcmatrix(mtx_ful, frozen_core=3)
        with pytest.warns(UserWarning,
                          match=r"^Ignored frozen_virtual parameter"):
            construct_adcmatrix(mtx_cvs, frozen_virtual=1)
示例#24
0
    def test_extra_term(self):
        ground_state = adcc.LazyMp(cache.refstate["h2o_sto3g"])
        matrix_adc1 = adcc.AdcMatrix("adc1", ground_state)
        with pytest.raises(TypeError):
            matrix_adc1 += 42
        matrix = adcc.AdcMatrix("adc2", ground_state)

        with pytest.raises(TypeError):
            adcc.AdcMatrix("adc2", ground_state, diagonal_precomputed=42)
        with pytest.raises(ValueError):
            adcc.AdcMatrix("adc2",
                           ground_state,
                           diagonal_precomputed=matrix.diagonal() + 42)
        with pytest.raises(TypeError):
            AdcExtraTerm(matrix, "fail")
        with pytest.raises(TypeError):
            AdcExtraTerm(matrix, {"fail": "not_callable"})

        shift = -0.3
        shifted = AdcMatrixShifted(matrix, shift)
        # TODO: need to use AmplitudeVector to differentiate between
        # diagonals for ph and pphh
        # if we just pass numbers, i.e., shift
        # we get 2*shift on the diagonal
        ones = matrix.diagonal().ones_like()

        def __shift_ph(hf, mp, intermediates):
            def apply(invec):
                return adcc.AmplitudeVector(ph=shift * invec.ph)

            diag = adcc.AmplitudeVector(ph=shift * ones.ph)
            return AdcBlock(apply, diag)

        def __shift_pphh(hf, mp, intermediates):
            def apply(invec):
                return adcc.AmplitudeVector(pphh=shift * invec.pphh)

            diag = adcc.AmplitudeVector(pphh=shift * ones.pphh)
            return AdcBlock(apply, diag)

        extra = AdcExtraTerm(matrix, {
            'ph_ph': __shift_ph,
            'pphh_pphh': __shift_pphh
        })
        # cannot add to 'pphh_pphh' in ADC(1) matrix
        with pytest.raises(ValueError):
            matrix_adc1 += extra

        shifted_2 = matrix + extra
        shifted_3 = extra + matrix
        for manual in [shifted_2, shifted_3]:
            assert_allclose(shifted.diagonal().ph.to_ndarray(),
                            manual.diagonal().ph.to_ndarray(),
                            atol=1e-12)
            assert_allclose(shifted.diagonal().pphh.to_ndarray(),
                            manual.diagonal().pphh.to_ndarray(),
                            atol=1e-12)
            vec = adcc.guess_zero(matrix)
            vec.set_random()
            ref = shifted @ vec
            ret = manual @ vec
            diff_s = ref.ph - ret.ph
            diff_d = ref.pphh - ret.pphh
            assert np.max(np.abs(diff_s.to_ndarray())) < 1e-12
            assert np.max(np.abs(diff_d.to_ndarray())) < 1e-12
示例#25
0
 def test_diagonal_adc2(self):
     ground_state = adcc.LazyMp(cache.refstate["h2o_sto3g"])
     matrix = adcc.AdcMatrix("adc2", ground_state)
     cppmatrix = libadcc.AdcMatrix("adc2", ground_state)
     diff = cppmatrix.diagonal("s") - matrix.diagonal("s")
     assert diff.dot(diff) < 1e-12
示例#26
0
        assert matrix.axis_spaces["ph"] == ["o1", "v1"]
        assert matrix.axis_spaces["pphh"] == ["o1", "o1", "v1", "v1"]
        assert matrix.axis_lengths["ph"] == 40
        assert matrix.axis_lengths["pphh"] == 1600

        assert matrix.reference_state == reference_state
        assert matrix.mospaces == reference_state.mospaces
        assert isinstance(matrix.timer, adcc.timings.Timer)

    def test_properties_cvs_adc1(self):
        case = "h2o_sto3g"
        method = "cvs-adc1"

        reference_state = cache.refstate_cvs[case]
        ground_state = adcc.LazyMp(reference_state)
        matrix = adcc.AdcMatrix(method, ground_state)

        assert matrix.ndim == 2
        assert matrix.is_core_valence_separated
        assert matrix.shape == (8, 8)
        assert len(matrix) == 8

        assert matrix.axis_blocks == ["ph"]
        assert sorted(matrix.axis_spaces.keys()) == matrix.axis_blocks
        assert sorted(matrix.axis_lengths.keys()) == matrix.axis_blocks
        assert matrix.axis_spaces["ph"] == ["o2", "v1"]
        assert matrix.axis_lengths["ph"] == 8

        assert matrix.reference_state == reference_state
        assert matrix.mospaces == reference_state.mospaces
        assert isinstance(matrix.timer, adcc.timings.Timer)
示例#27
0
 def test_reference_h2o_adc2x(self):
     ground_state = adcc.LazyMp(cache.refstate["h2o_sto3g"])
     matrix = adcc.AdcMatrix("adc2x", ground_state)
     self.base_reference(matrix, self.get_ref_h2o())
示例#28
0
 def test_reference_cn_adc3(self):
     ground_state = adcc.LazyMp(cache.refstate["cn_sto3g"])
     matrix = adcc.AdcMatrix("adc3", ground_state)
     self.base_reference(matrix, self.get_ref_cn())
示例#29
0
def relax_cvs(scfres, method, state, ctol=5e-5):
    singles_block_only = False
    if adcc.AdcMethod(method).level > 1 and "d" not in state.matrix.blocks:
        singles_block_only = True
        # Singles block only method
        refstate = adcc.ReferenceState(scfres)
        origmatrix = adcc.AdcBlockView(adcc.AdcMatrix(method, refstate), "s")
    else:
        refstate = adcc.ReferenceState(scfres)
        origmatrix = adcc.AdcMatrix(method, refstate)
    matrix = AdcMatrixShifted(origmatrix)
    explicit_symmetrisation = IndexSpinSymmetrisation(
        matrix, enforce_spin_kind=state.kind)

    assert state.kind == "singlet"
    fullvec = [
        guess_zero(matrix, spin_block_symmetrisation="symmetric")
        for i in range(len(state.excitation_vectors))
    ]
    for i in range(len(state.excitation_vectors)):
        project_amplitude(state.excitation_vectors[i], fullvec[i])

    preconditioner = JacobiPreconditioner(matrix)

    relaxed_vec = []
    relaxed_ene = []
    residual_norms = []
    for i in range(len(state.excitation_vectors)):
        print("=================")
        print("    State {}".format(i))
        print("=================")
        vec = fullvec[i].copy(
        )  # Not sure this copy is needed, do it for safety
        origvec = vec
        ene = state.excitation_energies[i]
        eneold = ene
        histories = []
        residual = 100000
        xold = vec
        preconditioner.update_shifts(ene - 1e-2)
        matrix.update_omega(ene - 1e-3)
        print("-->  Starting energy {}: {}".format(i, ene))

        for it in range(100):
            eps = 1e-3  # numerical fuzzing to improve conditioning
            if residual > eps / 10 and it > 0:
                matrix.update_omega(ene - eps)
                preconditioner.update_shifts(ene - eps)

            res = conjugate_gradient(
                matrix,
                rhs=xold,
                x0=xold,
                callback=default_print,
                Pinv=preconditioner,
                conv_tol=ctol / 10,
                max_iter=400,
            )
            x = res.solution
            x = explicit_symmetrisation.symmetrise([x], [origvec])[0]
            x /= np.sqrt(x @ x)

            ene = x @ matrix.matmul_orig(x)
            enediff = ene - eneold
            overlap = np.sqrt(np.abs(origvec @ x))
            resres = matrix.matmul_orig(x) - ene * x
            residual = np.sqrt(resres @ resres)
            print("-->  Energy {}:   {} (enediff: {})"
                  "".format(it, ene, enediff))
            print("-->  Overlap {}:  {}".format(it, overlap))
            print("-->  Residual {}: {}".format(it, residual))

            if np.abs(overlap - 1) > 0.2:
                if not histories:
                    if i == 0:
                        print(
                            "     !!! Low overlap detected and got no history"
                            "... trying again")
                        xold = origvec
                    else:
                        raise RuntimeError("Low overlap and got no history.")

                # Pick the energy of the historic result with the best overlap
                # (smallest aberration from 1)
                ene = sorted(histories, key=lambda x: x[1])[0][0] + eps
                print(
                    "     !!! Low overlap detected! Changing shift to {:.6g} "
                    "and trying again !!!".format(ene))
                xold = origvec
            elif residual < ctol:
                print("-->   converged")
                break
            else:
                xold = x
                eneold = ene
                histories.append((ene, np.abs(overlap - 1)))

        residual_norms.append(np.sqrt(resres @ resres))
        relaxed_vec.append(x)
        relaxed_ene.append(ene)

    class CvsRelaxationState:
        pass

    res = CvsRelaxationState()
    res.matrix = origmatrix
    res.kind = "singlet"
    res.eigenvectors = relaxed_vec
    res.eigenvalues = np.array(relaxed_ene)

    property_method = None
    if singles_block_only:
        # To not get crashes on property calculation (missing doubles part)
        property_method = "adc1"

    sstate = adcc.ExcitedStates(res,
                                method=method,
                                property_method=property_method)
    sstate.residual_norms = np.array(residual_norms)
    return sstate