Exemple #1
0
def v_integral(traj1, traj2, centroid=None, Snuc=None):
    """Returns potential coupling matrix element between two trajectories."""
    # evaluate just the nuclear component (for re-use)
    if Snuc is None:
        Snuc = nuclear.overlap(traj1.phase(), traj1.widths(), traj1.x(),
                               traj1.p(), traj2.phase(), traj2.widths(),
                               traj2.x(), traj2.p())

    dx_1 = traj1.x() - centroid.x()
    dx_2 = traj2.x() - centroid.x()
    dp = traj1.p() - traj2.p()
    if traj1.tid == traj2.tid:
        vint = Snuc * (traj1.energy(traj1.state) + 0.5 *
                       np.dot(centroid.derivative(traj1.state, traj1.state),
                              dx_1 + dx_2 - 1j * dp))
    else:
        ave_ener = 0.5 * (centroid.energy(traj1.state) +
                          centroid.energy(traj2.state))
        dif_ener = 0.5 * (centroid.energy(traj1.state) -
                          centroid.energy(traj2.state))
        vint = Snuc * np.dot(
            centroid.derivative(traj1.state, traj2.state),
            ave_ener * dx_2 - ave_ener * dx_1 + 1j * dif_ener * dp)

    return vint
Exemple #2
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
Exemple #3
0
def v_integral(t1, t2, centroid=None, Snuc=None):
    """Returns potential coupling matrix element between two trajectories."""
    # evaluate just the nuclear component (for re-use)
    if Snuc is None:
        Snuc = nuclear.overlap(t1.phase(), t1.widths(), t1.x(), t1.p(),
                               t2.phase(), t2.widths(), t2.x(), t2.p())

    states = np.sort(np.array([t1.state, t2.state]))
    v_total = complex(0., 0.)

    # roll through terms in the hamiltonian
    for i in range(glbl.pes.ham.nterms):

        if np.array_equal(states, glbl.pes.ham.stalbl[i, :] - 1):
            # adiabatic states in diabatic basis -- cross terms between orthogonal
            # diabatic states are zero
            [s1, s2] = glbl.pes.ham.stalbl[i, :] - 1
            v_term = complex(1., 0.) * glbl.pes.ham.coe[i]
            for q in range(len(glbl.pes.ham.order[i])):
                qi = glbl.pes.ham.mode[i][q]
                v_term *= nuclear.prim_v_integral(glbl.pes.ham.order[i][q],
                                                  t1.widths()[qi],
                                                  t1.x()[qi],
                                                  t1.p()[qi],
                                                  t2.widths()[qi],
                                                  t2.x()[qi],
                                                  t2.p()[qi])
            v_total += v_term

    return v_total * Snuc
Exemple #4
0
def traj_overlap(traj1, traj2, nuc_only=False):
    """ Returns < Psi | Psi' >, the overlap integral of two trajectories"""
    if traj1.state != traj2.state and not nuc_only:
        return 0j
    else:
        return gauss.overlap(traj1.phase(), traj1.widths(), traj1.x(),
                             traj1.p(), traj2.phase(), traj2.widths(),
                             traj2.x(), traj2.p())
Exemple #5
0
def traj_overlap(traj1, traj2, centroid, nuc_only=False):
    """ Returns < Psi | Psi' >, the overlap integral of two trajectories"""
    nuc_ovrlp = nuclear.overlap(traj1.phase(), traj1.widths(), traj1.x(),
                                traj1.p(), traj2.phase(), traj2.widths(),
                                traj2.x(), traj2.p())

    if nuc_only:
        return nuc_ovrlp
    else:
        return nuc_ovrlp * elec_overlap(traj1, traj2, centroid)
Exemple #6
0
def s_integral(t1, t2, nuc_only=False, Snuc=None):
    """ Returns < Psi | Psi' >, the overlap of the nuclear
    component of the wave function only"""
    if t1.state != t2.state and not nuc_only:
        return 0j
    else:
        if Snuc is None:
            return nuclear.overlap(t1.phase(),t1.widths(),t1.x(),t1.p(),
                                   t2.phase(),t2.widths(),t2.x(),t2.p())
        else:
            return Snuc
Exemple #7
0
def ke_integral(t1, t2, Snuc=None):
    """Returns kinetic energy integral over trajectories."""
    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())

        ke = nuclear.deld2x(Snuc, t1.widths(), t1.x(), t1.p(), t2.widths(),
                            t2.x(), t2.p())

        return -sum(ke * glbl.pes.kecoeff)
Exemple #8
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
Exemple #9
0
def ke_integral(traj1, traj2, centroid=None, Snuc=None):
    """Returns kinetic energy integral over trajectories."""
    # evaluate just the nuclear component (for re-use)
    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)

    # < chi | del^2 / dx^2 | chi'>
    ke = nuclear.deld2x(Snuc, traj1.phase(), traj1.widths(), traj1.x(),
                        traj1.p(), traj2.phase(), traj2.widths(), traj2.x(),
                        traj2.p())

    return -sum(ke * vibronic.kecoeff) * Selec
Exemple #10
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
Exemple #11
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
Exemple #12
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())
Exemple #13
0
def nuc_overlap(t1, t2):
    """ Returns < Chi | Chi' >, the nuclear overlap integral of two trajectories"""
    return nuclear.overlap(t1.phase(),t1.widths(),t1.x(),t1.p(),
                           t2.phase(),t2.widths(),t2.x(),t2.p())