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
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
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
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
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())