def error_deriv(self, Φ, z_step, list_index_aux_stable=None): """ The error associated with losing all flux terms into the k auxiliary and n’ state. Where k is in H_t and n' is in S_t. .. math:: \sum_{n \in \mathcal{S}_{t}} \\left\\vert \\frac{\delta_{a} \psi^{(\\vec{k})}_{t,n}}{\delta t_a} \\right\\vert^2 .. math:: \sum_{\\vec{k} \in \mathcal{H}_{t}} \\left\\vert \\frac{\delta_{a} \psi^{(\\vec{k})}_{t,n}}{\delta t_a} \\right\\vert^2 PARAMETERS ---------- 1. Φ : np.array The current full hierarchy vector 2. z_step : list the list of noise terms (compressed) for the next timestep 3. list_index_aux_stable : list a list relative indices for the stable auxiliaries RETURNS ------- 1. E2_del_phi : np.array the error associated with losing flux to a component (either hierarchy or state basis element) in H_t direct sum S_t """ if list_index_aux_stable is not None: # Error arises for flux only out of the stable auxiliaries # -------------------------------------------------------- Φ_stab = np.zeros(self.n_state * self.n_hier, dtype=np.complex128) Φ_stab_v = Φ_stab.view().reshape([self.n_state, self.n_hier], order="F") Φ_stab_v[:, list_index_aux_stable] = Φ.view().reshape( [self.n_state, self.n_hier], order="F" )[:, list_index_aux_stable] else: Φ_stab = Φ list_avg_L2 = [ operator_expectation(L, Φ[: self.n_state]) for L in self.system.list_L2_coo ] P1_del_phi = ( self.eom.K2_k @ Φ_stab + self.eom.K2_kp1 @ Φ_stab + self.eom.K2_km1 @ Φ_stab ) for j in range(len(self.system.list_absindex_L2)): P1_del_phi += z_step[j] * self.eom.Z2_k[j] @ Φ_stab P1_del_phi += np.conj(list_avg_L2[j]) * self.eom.Z2_kp1[j] @ Φ_stab E2_del_phi = np.abs( P1_del_phi.reshape([self.n_state, self.n_hier], order="F") / hbar ) return E2_del_phi
def error_deriv(self, Φ, z_step, list_index_aux_stable=None): """ The error associated with losing all flux terms into the k auxiliary and n state, where k is in A_t and n is in S_t. This corresponds to equation 29 in arXiv:2008.06496 PARAMETERS ---------- 1. Φ : np.array The current full hierarchy vector 2. z_step : list the list of noise terms (compressed) for the next timestep 3. list_index_aux_stable : list a list relative indices for the stable auxiliaries RETURNS ------- 1. E2_del_phi : np.array the error associated with losing flux to a component (either hierarchy or state basis element) in H_t direct sum S_t """ if list_index_aux_stable is not None: # Error arises for flux only out of the stable auxiliaries # -------------------------------------------------------- Φ_stab = np.zeros(self.n_state * self.n_hier, dtype=np.complex128) Φ_stab_v = Φ_stab.view().reshape([self.n_state, self.n_hier], order="F") Φ_stab_v[:, list_index_aux_stable] = Φ.view().reshape( [self.n_state, self.n_hier], order="F")[:, list_index_aux_stable] else: Φ_stab = Φ list_avg_L2 = [ operator_expectation(L, Φ[:self.n_state]) for L in self.system.list_L2_coo ] P1_del_phi = (self.eom.K2_k @ Φ_stab + self.eom.K2_kp1 @ Φ_stab + self.eom.K2_km1 @ Φ_stab) for j in range(len(self.system.list_absindex_L2)): P1_del_phi += z_step[j] * self.eom.Z2_k[j] @ Φ_stab P1_del_phi += np.conj(list_avg_L2[j]) * self.eom.Z2_kp1[j] @ Φ_stab E2_del_phi = np.abs( P1_del_phi.reshape([self.n_state, self.n_hier], order="F") / hbar) return E2_del_phi
def test_calc_deltz_zmem(): lind_dict = hops.basis.system.param["LIST_L2_COO"] lop_list = lind_dict lavg_list = [operator_expectation(L2, hops.psi) for L2 in lop_list] g_list = hops.basis.system.param["G"] w_list = hops.basis.system.param["W"] z_mem = np.array([0.0 for g in g_list]) d_zmem = calc_delta_zmem( z_mem, lavg_list, g_list, w_list, hops.basis.system.param["LIST_INDEX_L2_BY_NMODE1"], np.array(range(len(g_list))), ) assert len(d_zmem) == len(g_list) assert d_zmem[0] == 10.0 assert d_zmem[1] == 5.0 assert d_zmem[2] == 0 assert d_zmem[3] == 0 assert type(d_zmem) == type(np.array([]))
def test_compress_zmem(): lind_dict = hops.basis.system.param["LIST_L2_COO"] lop_list = lind_dict lavg_list = [operator_expectation(L2, hops.psi) for L2 in lop_list] g_list = hops.basis.system.param["G"] w_list = hops.basis.system.param["W"] z_mem = np.array([0.0 for g in g_list]) z_mem = calc_delta_zmem( z_mem, lavg_list, g_list, w_list, hops.basis.system.param["LIST_INDEX_L2_BY_NMODE1"], range(len(g_list)), ) z_compress = compress_zmem( z_mem, hops.basis.system.param["LIST_INDEX_L2_BY_NMODE1"], hops.basis.system.list_absindex_mode, ) assert len(z_compress) == 2 assert z_compress[0] == 15.0 assert z_compress[1] == 0.0
def test_l_avg_calculation(): lind_dict = hops.basis.system.param["LIST_L2_COO"] lop_list = lind_dict lavg_list = [operator_expectation(L2, hops.psi) for L2 in lop_list] assert lavg_list[0] == 1.0 assert lavg_list[1] == 0.0
def dsystem_dt( Φ, z_mem1_tmp, z_rnd1_tmp, z_rnd2_tmp, K2_stable=K2_stable, Z2_k=self.Z2_k, Z2_kp1=self.Z2_kp1, list_L2=list_L2, list_index_L2_by_hmode=system.list_index_L2_by_hmode, list_mode_absindex_L2=system.param["LIST_INDEX_L2_BY_HMODE"], nsys=system.size, list_absindex_L2=system.list_absindex_L2, list_absindex_mode=system.list_absindex_mode, list_g=system.param["G"], list_w=system.param["W"], list_tuple_index_phi1_L2_mode=list_tuple_index_phi1_L2_mode, ): """ This is the core function for calculating the time-evolution of the wave function. The logic here becomes slightly complicated because we need use both the relative and absolute indices at different points. z_hat1_tmp : relative z_rnd1_tmp : absolute z_rnd2_tmp: absolute z_mem1_tmp : absolute list_avg_L2 : relative Z2_k, Z2_kp1 : relative Φ_deriv : relative z_mem1_deriv : absolute The nonlinear evolution equation used to perform this calculation takes the following form: ~ Ψ̇_t^(k)=(-iH-kw+(z~_t)L)ψ_t^(k) + κα(0)Lψ_t^(k-1) - (L†-〈L†〉_t)ψ_t^(k+1) with z~ = z^* + ∫ds(a^*)(t-s)〈L†〉 A super operator notation is implemented in this code. PARAMETERS ---------- 1. Φ : np.array current full hierarchy 2. z_mem1_tmp : np.array array of memory values for each mode 3. z_rnd1_tmp : np.array array of random noise corresponding to NOISE1 for the set of time points required in the integration 4. z_rnd2_tmp : np.array array of random noise corresponding to NOISE2 for the set of time points required in the integration 5. K2_stable : np.array the component of the super operator that does not depend on noise 6. Z2_k : np.array the component of the super operator that is multiplied by noise z and maps the Kth hierarchy to the Kth hierarchy 7. Z2_kp1 : np.array the component of the super operator that is multiplied by noise z and maps the (K+1) hierarchy to the kth hierarchy 8. list_L2 : list list of L operators 9. list_index_L2_by_hmode : list list of length equal to the number of modes in the current hierarchy basis and each entry is an index for the relative list_L2. 10. list_mode_absindex_L2 : list list of length equal to the number of 'modes' in the current hierarchy basis and each entry is an index for the absolute list_L2. 11. nsys : int t he current dimension (size) of the system basis 12. list_absindex_L2 : list list of length equal to the number of L-operators in the current system basis where each element is the index for the absolute list_L2 13. list_absindex_mode : list list of length equal to the number of modes in the current system basis that corresponds to the absolute index of the modes 14. list_g : list list of pre exponential factors for bath correlation functions 15. list_w : list list of exponents for bath correlation functions (w = γ+iΩ) 16. list_tuple_index_phi1_index_L2 : list list of tuples with each tuple containing the index of the first auxiliary mode (phi1) in the hierarchy and the index of the corresponding L operator RETURNS ------- 1. Φ_deriv : np.array the derivative of phi with respect to time 2. z_mem1_deriv : np.array the derivative of z_mem with respect to time """ # Construct Noise Terms # --------------------- z_hat1_tmp = np.conj( z_rnd1_tmp[list_absindex_L2]) + compress_zmem( z_mem1_tmp, list_index_L2_by_hmode, list_absindex_mode) z_tmp2 = z_rnd2_tmp[list_absindex_L2] # Construct other fluctuating terms # --------------------------------- list_avg_L2 = [ operator_expectation(L, Φ[:nsys]) for L in list_L2 ] # <L> norm_corr = calc_norm_corr( Φ, z_hat1_tmp, list_avg_L2, list_L2, nsys, list_tuple_index_phi1_L2_mode, np.array(list_g)[np.array(list_absindex_mode)], np.array(list_w)[np.array(list_absindex_mode)], ) # calculate dphi/dt # ----------------- Φ_deriv = K2_stable @ Φ Φ_deriv -= norm_corr * Φ for j in range(len(list_avg_L2)): # ASSUMING: L = L^* Φ_deriv += (z_hat1_tmp[j] + 2 * np.real(z_tmp2[j])) * (Z2_k[j] @ Φ) Φ_deriv += np.conj(list_avg_L2[j]) * (Z2_kp1[j] @ Φ) # calculate dz/dt # --------------- z_mem1_deriv = calc_delta_zmem( z_mem1_tmp, list_avg_L2, list_g, list_w, list_mode_absindex_L2, list_absindex_mode, ) return Φ_deriv, z_mem1_deriv