예제 #1
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
예제 #2
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
예제 #3
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
예제 #4
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
예제 #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())