Esempio n. 1
0
def sdot_integral(t1, t2, Snuc=None):
    """Returns the matrix element <Psi_1 | d/dt | Psi_2>."""
    if t1.state != t2.state:
        return complex(0., 0.)
    else:
        if Snuc is None:
            Snuc = nuclear.overlap(t1.phase(), t1.widths(), t1.x(), t1.p(),
                                   t2.phase(), t2.widths(), t2.x(), t2.p())
        t1_dx_t2 = nuclear.deldx(Snuc, t1.widths(), t1.x(), t1.p(),
                                 t2.widths(), t2.x(), t2.p())
        t1_dp_t2 = nuclear.deldp(Snuc, t1.widths(), t1.x(), t1.p(),
                                 t2.widths(), t2.x(), t2.p())
        sdot = (np.dot(t2.velocity(), t1_dx_t2) +
                np.dot(t2.force(), t1_dp_t2) + 1.j * t2.phase_dot() * Snuc)

        return sdot
Esempio n. 2
0
def v_integral(t1, t2, centroid=None, Snuc=None):
    """Returns potential coupling matrix element between two trajectories."""
    # if we are passed a single trajectory, this is a diagonal
    # matrix element -- simply return potential energy of trajectory
    if t1.label == t2.label:
        # Adiabatic energy
        v = t1.energy(t1.state)
        # DBOC
        if glbl.interface['coupling_order'] == 3:
            v += t1.scalar_coup(t1.state, t2.state)
        return v

    if Snuc is None:
        Snuc = nuclear.overlap(t1.phase(), t1.widths(), t1.x(), t1.p(),
                               t2.phase(), t2.widths(), t2.x(), t2.p())
#        Snuc = nuclear.overlap(t1,t2)

# off-diagonal matrix element, between trajectories on the same
# state (this also requires the centroid be present)
    elif t1.state == t2.state:
        # Adiabatic energy
        v = centroid.energy(t1.state) * Snuc
        # DBOC
        if glbl.interface['coupling_order'] == 3:
            v += centroid.scalar_coup(t1.state, t2.state) * Snuc
        return v

    # [necessarily] off-diagonal matrix element between trajectories
    # on different electronic states
    elif t1.state != t2.state:
        # Derivative coupling
        fij = centroid.derivative(t1.state, t2.state)
        v = 2. * np.vdot(
            fij,
            glbl.pes.kecoeff * nuclear.deldx(Snuc, t1.widths(), t1.x(), t1.p(),
                                             t2.widths(), t2.x(), t2.p()))
        #                       nuclear.deldx(t1, t2, S=Snuc))
        # Scalar coupling
        if glbl.interface['coupling_order'] > 1:
            v += centroid.scalar_coup(t1.state, t2.state) * Snuc
        return v

    else:
        print('ERROR in v_integral -- argument disagreement')
        return 0j
Esempio n. 3
0
def sdot_integral(t1, t2, Snuc=None, e_only=False, nuc_only=False):
    """Returns the matrix element <Psi_1 | d/dt | Psi_2>."""
    if t1.state != t2.state:
        return 0j

    else:
        if Snuc is None:
            Snuc = nuclear.overlap(t1.phase(), t1.widths(), t1.x(), t1.p(),
                                   t2.phase(), t2.widths(), t2.x(), t2.p())

        deldx = nuclear.deldx(Snuc, t1.widths(), t1.x(), t1.p(), t2.widths(),
                              t2.x(), t2.p())
        deldp = nuclear.deldp(Snuc, t1.widths(), t1.x(), t1.p(), t2.widths(),
                              t2.x(), t2.p())

        sdot = (np.dot(deldx, t2.velocity()) + np.dot(deldp, t2.force()) +
                1j * t2.phase_dot() * Snuc)

        return sdot
Esempio n. 4
0
def sdot_integral(traj1, traj2, centroid=None, Snuc=None, e_only=False, nuc_only=False):
    """Returns the matrix element <Psi_1 | d/dt | Psi_2>."""
    if Snuc is None:
        Snuc = nuclear.overlap(traj1.phase(),traj1.widths(),traj1.x(),traj1.p(),
                               traj2.phase(),traj2.widths(),traj2.x(),traj2.p())

    # overlap of electronic functions
    Selec = elec_overlap(traj1, traj2, centroid)

    # < chi | d / dx | chi'>
    deldx = nuclear.deldx(Snuc,traj1.phase(),traj1.widths(),traj1.x(),traj1.p(),
                               traj2.phase(),traj2.widths(),traj2.x(),traj2.p())
    # < chi | d / dp | chi'>
    deldp = nuclear.deldp(Snuc,traj1.phase(),traj1.widths(),traj1.x(),traj1.p(),
                               traj2.phase(),traj2.widths(),traj2.x(),traj2.p())

    # the nuclear contribution to the sdot matrix
    sdot = ( np.dot(traj2.velocity(), deldx) + np.dot(traj2.force(), deldp) 
            + 1j * traj2.phase_dot() * Snuc) * Selec

    # time-derivative of the electronic component
    
    return sdot
Esempio n. 5
0
def v_integral(t1, t2, centroid=None, Snuc=None):
    """Returns potential coupling matrix element between two trajectories.

    If we are passed a single trajectory, this is a diagonal matrix
    element -- simply return potential energy of trajectory.
    """

    if Snuc is None:
        Sij = nuclear.overlap(t1.phase(), t1.widths(), t1.x(), t1.p(),
                              t2.phase(), t2.widths(), t2.x(), t2.p())
    else:
        Sij = Snuc
    Sji = Sij.conjugate()

    if glbl.propagate['integral_order'] > 2:
        raise ValueError(
            'Integral_order > 2 not implemented for bra_ket_averaged')

    if t1.state == t2.state:
        state = t1.state
        # Adiabatic energy
        vij = t1.energy(state) * Sij
        vji = t2.energy(state) * Sji

        if glbl.propagate['integral_order'] > 0:
            o1_ij = nuclear.ordr1_vec(t1.widths(), t1.x(), t1.p(), t2.widths(),
                                      t2.x(), t2.p())
            o1_ji = nuclear.ordr1_vec(t2.widths(), t2.x(), t2.p(), t1.widths(),
                                      t1.x(), t1.p())
            vij += np.dot(o1_ij - t1.x() * Sij, t1.derivative(state, state))
            vji += np.dot(o1_ji - t2.x() * Sji, t2.derivative(state, state))

        if glbl.propagate['integral_order'] > 1:
            xcen = (t1.widths() * t1.x() +
                    t2.widths() * t2.x()) / (t1.widths() + t2.widths())
            o2_ij = nuclear.ordr2_vec(t1.widths(), t1.x(), t1.p(), t2.widths(),
                                      t2.x(), t2.p())
            o2_ji = nuclear.ordr2_vec(t2.widths(), t2.x(), t2.p(), t1.widths(),
                                      t1.x(), t1.p())

            for k in range(t1.dim):
                vij += 0.5 * o2_ij[k] * t1.hessian(state)[k, k]
                vji += 0.5 * o2_ji[k] * t2.hessian(state)[k, k]
                for l in range(k):
                    vij += 0.5 * (
                        (2. * o1_ij[k] * o1_ij[l] - xcen[k] * o1_ij[l] -
                         xcen[l] * o1_ij[k] - o1_ij[k] * t1.x()[l] -
                         o1_ij[l] * t1.x()[k] +
                         (t1.x()[k] * xcen[l] + t1.x()[l] * xcen[k]) * Sij) *
                        t1.hessian(state)[k, l])
                    vji += 0.5 * (
                        (2. * o1_ji[k] * o1_ji[l] - xcen[k] * o1_ji[l] -
                         xcen[l] * o1_ji[k] - o1_ji[k] * t2.x()[l] -
                         o1_ji[l] * t2.x()[k] +
                         (t2.x()[k] * xcen[l] + t2.x()[l] * xcen[k]) * Sji) *
                        t2.hessian(state)[k, l])

    # [necessarily] off-diagonal matrix element between trajectories
    # on different electronic states
    else:
        # Derivative coupling
        fij = t1.derivative(t1.state, t2.state)

        vij = 2. * np.vdot(
            t1.derivative(t1.state, t2.state),
            glbl.pes.kecoeff * nuclear.deldx(Sij, t1.widths(), t1.x(), t1.p(),
                                             t2.widths(), t2.x(), t2.p()))
        vji = 2. * np.vdot(
            t2.derivative(t2.state, t1.state),
            glbl.pes.kecoeff * nuclear.deldx(Sji, t2.widths(), t2.x(), t2.p(),
                                             t1.widths(), t1.x(), t1.p()))
    return 0.5 * (vij + vji.conjugate())