示例#1
0
文件: tpa.py 项目: chrinide/adcc
# solve for Eigenvalues
state = adcc.adc2(scfres, n_singlets=1, conv_tol=1e-8)

# setup modified transition moments
dips = state.reference_state.operators.electric_dipole
rhss = [
    compute_modified_transition_moments(state.matrix, dip, "adc2")
    for dip in dips
]

S = np.zeros((len(state.excitation_energies), 3, 3))
for f, ee in enumerate(state.excitation_energies):
    freq = ee / 2.0
    matrix = ShiftedMat("adc2", state.ground_state, freq)
    preconditioner = JacobiPreconditioner(matrix)
    explicit_symmetrisation = IndexSymmetrisation(matrix)
    preconditioner.update_shifts(freq)
    response = []
    # solve all systems of equations
    for mu in range(3):
        rhs = rhss[mu]
        x0 = preconditioner.apply(rhs)
        res = conjugate_gradient(
            matrix, rhs=rhs, x0=x0, callback=default_print,
            Pinv=preconditioner, conv_tol=1e-6,
            explicit_symmetrisation=explicit_symmetrisation
        )
        response.append(res)
    for mu in range(3):
        for nu in range(mu, 3):
示例#2
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