def propagate(self): r"""Given a wavepacket :math:`\Psi` at time :math:`t` compute the propagated wavepacket at time :math:`t + \tau`. We perform exactly one timestep of size :math:`\tau` here. This propagation is done for all packets in the list :math:`\{\Psi_i\}_i` and neglects any interaction between two packets. """ # Cache some parameter values dt = self._dt Mi = self._Minv # Propagate all packets for packet in self._packets: # Unpack, no codata: packet = packet[0] eps = packet.get_eps() key = ("q", "p", "Q", "P", "S", "adQ") # Do a kinetic step of dt/2 for component in xrange(self._number_components): q, p, Q, P, S, adQ = packet.get_parameters(component=component, key=key) q = q + 0.5 * dt * dot(Mi, p) Q = Q + 0.5 * dt * dot(Mi, P) S = S + 0.25 * dt * dot(p.T, dot(Mi, p)) adQn = cont_angle(det(Q), reference=adQ)[0] packet.set_parameters((q, p, Q, P, S, adQn), component=component, key=key) # Do a potential step with the local quadratic part for component in xrange(self._number_components): q, p, Q, P, S = packet.get_parameters(component=component) V = self._potential.evaluate_local_quadratic_at(q, diagonal_component=component) p = p - dt * V[1] P = P - dt * dot(V[2], Q) S = S - dt * V[0] packet.set_parameters((q, p, Q, P, S), component=component) # Do a potential step with the local non-quadratic Taylor remainder innerproduct = packet.get_innerproduct() F = innerproduct.build_matrix(packet, packet, self._potential.evaluate_local_remainder_at) coefficients = packet.get_coefficient_vector() coefficients = self._matrix_exponential(F, coefficients, dt/eps**2) packet.set_coefficient_vector(coefficients) # Do a kinetic step of dt/2 for component in xrange(self._number_components): q, p, Q, P, S, adQ = packet.get_parameters(component=component, key=key) q = q + 0.5 * dt * dot(Mi, p) Q = Q + 0.5 * dt * dot(Mi, P) S = S + 0.25 * dt * dot(p.T, dot(Mi, p)) adQn = cont_angle(det(Q), reference=adQ)[0] packet.set_parameters((q, p, Q, P, S, adQn), component=component, key=key)
def _propkin(self, h, packet): """Do a kinetic step of size h. """ Mi = self._Minv key = ("q", "p", "Q", "P", "S", "adQ") q, p, Q, P, S, adQ = packet.get_parameters(key=key) q = q + h * dot(Mi, p) Q = Q + h * dot(Mi, P) S = S + 0.5 * h * dot(p.T, dot(Mi, p)) adQn = cont_angle(det(Q), reference=adQ)[0] packet.set_parameters((q, p, Q, P, S, adQn), key=key)