def test_of_many_contexts_many_vars_1(self): """Testing several operators in nested basis management contexts """ x,Sh = numpy.linalg.eigh(self.H.data) Sh1 = numpy.linalg.inv(Sh) h_copy_tr1 = numpy.dot(Sh1,numpy.dot(self.h_copy,Sh)) b_copy_tr1 = numpy.dot(Sh1,numpy.dot(self.b_copy,Sh)) x,Sb = numpy.linalg.eigh(b_copy_tr1) Sb1 = numpy.linalg.inv(Sb) h_copy_tr2 = numpy.dot(Sb1,numpy.dot(h_copy_tr1,Sb)) b_copy_tr2 = numpy.dot(Sb1,numpy.dot(b_copy_tr1,Sb)) with eigenbasis_of(self.H): # in context 1 self.assertTrue(numpy.allclose(self.H.data,h_copy_tr1)) self.assertTrue(numpy.allclose(self.B.data,b_copy_tr1)) with eigenbasis_of(self.B): # in context 2 #print("In 2",self.B.manager.get_current_basis()) self.assertTrue(numpy.allclose(self.H.data,h_copy_tr2)) self.assertTrue(numpy.allclose(self.B.data,b_copy_tr2)) # in context 1 #print("Out 2 in 1",self.H.manager.get_current_basis()) self.assertTrue(numpy.allclose(self.H.data,h_copy_tr1)) self.assertTrue(numpy.allclose(self.B.data,b_copy_tr1)) # outside contexts #print("Out 1",self.H.manager.get_current_basis()) self.assertTrue(numpy.allclose(self.H.data,self.h_copy)) self.assertTrue(numpy.allclose(self.B.data,self.b_copy))
def test_transformation_in_different_basis(self): """(LINDBLAD) Testing transformations into different bases """ #Manager().warn_about_basis_change = True #Manager().warn_about_basis_changing_objects = True LT1 = LindbladForm(self.H1, self.sbi1, as_operators=True, name="LT1") LT2 = LindbladForm(self.H1, self.sbi1, as_operators=False, name="LT2") rho0 = ReducedDensityMatrix(dim=self.H1.dim, name="ahoj") with eigenbasis_of(self.H1): rho0.data[1, 1] = 0.7 rho0.data[0, 0] = 0.3 with eigenbasis_of(self.H1): rhot1_e = LT1.apply(rho0, copy=True) with eigenbasis_of(self.H1): rhot2_e = LT2.apply(rho0, copy=True) rhot1_l = LT1.apply(rho0, copy=True) rhot2_l = LT2.apply(rho0, copy=True) numpy.testing.assert_allclose(rhot1_l.data, rhot1_e.data) numpy.testing.assert_allclose(rhot2_l.data, rhot2_e.data) numpy.testing.assert_allclose(rhot1_e.data, rhot2_e.data) #, rtol=1.0e-2)
def test_transformation_in_different_basis(self): """(LINDBLAD) Testing transformations into different bases """ #Manager().warn_about_basis_change = True #Manager().warn_about_basis_changing_objects = True LT1 = LindbladForm(self.H1, self.sbi1, as_operators=True, name="LT1") LT2 = LindbladForm(self.H1, self.sbi1, as_operators=False, name="LT2") rho0 = ReducedDensityMatrix(dim=self.H1.dim, name="ahoj") with eigenbasis_of(self.H1): rho0.data[1,1] = 0.7 rho0.data[0,0] = 0.3 with eigenbasis_of(self.H1): rhot1_e = LT1.apply(rho0, copy=True) with eigenbasis_of(self.H1): rhot2_e = LT2.apply(rho0, copy=True) rhot1_l = LT1.apply(rho0, copy=True) rhot2_l = LT2.apply(rho0, copy=True) numpy.testing.assert_allclose(rhot1_l.data, rhot1_e.data) numpy.testing.assert_allclose(rhot2_l.data, rhot2_e.data) numpy.testing.assert_allclose(rhot1_e.data, rhot2_e.data) #, rtol=1.0e-2)
def test_propagation_in_different_basis(self): """(LINDBLAD) Testing comparison of propagations in different bases """ LT1 = LindbladForm(self.H1, self.sbi1, as_operators=True) LT2 = LindbladForm(self.H1, self.sbi1, as_operators=False) time = TimeAxis(0.0, 1000, 1.0) prop1 = ReducedDensityMatrixPropagator(time, self.H1, LT1) prop2 = ReducedDensityMatrixPropagator(time, self.H1, LT2) rho0 = ReducedDensityMatrix(dim=self.H1.dim) rho0.data[1,1] = 1.0 with eigenbasis_of(self.H1): rhot1_e = prop1.propagate(rho0) with eigenbasis_of(self.H1): rhot2_e = prop2.propagate(rho0) rhot1_l = prop1.propagate(rho0) rhot2_l = prop2.propagate(rho0) numpy.testing.assert_allclose(rhot1_l.data, rhot1_e.data) numpy.testing.assert_allclose(rhot2_l.data, rhot2_e.data) numpy.testing.assert_allclose(rhot1_e.data, rhot2_e.data) #, rtol=1.0e-2)
def test_propagation_in_different_basis(self): """(LINDBLAD) Testing comparison of propagations in different bases """ LT1 = LindbladForm(self.H1, self.sbi1, as_operators=True) LT2 = LindbladForm(self.H1, self.sbi1, as_operators=False) time = TimeAxis(0.0, 1000, 1.0) prop1 = ReducedDensityMatrixPropagator(time, self.H1, LT1) prop2 = ReducedDensityMatrixPropagator(time, self.H1, LT2) rho0 = ReducedDensityMatrix(dim=self.H1.dim) rho0.data[1, 1] = 1.0 with eigenbasis_of(self.H1): rhot1_e = prop1.propagate(rho0) with eigenbasis_of(self.H1): rhot2_e = prop2.propagate(rho0) rhot1_l = prop1.propagate(rho0) rhot2_l = prop2.propagate(rho0) numpy.testing.assert_allclose(rhot1_l.data, rhot1_e.data) numpy.testing.assert_allclose(rhot2_l.data, rhot2_e.data) numpy.testing.assert_allclose(rhot1_e.data, rhot2_e.data) #, rtol=1.0e-2)
def step_when_10(context, time_step, N_dense): """ When I calculate EvolutionSuperOperator step by step using PureDephasing D and Lindblad form L with {time_step} and {N_dense} """ HH = context.H L = context.L DD = context.D dt = float(time_step) N_dense = int(N_dense) Ntot = 1320 Nsteps = int(Ntot / N_dense) time2 = qr.TimeAxis(0, Nsteps, dt) context.time2 = time2 mode = "jit" print("Pure dephasing: ", DD.dtype) if mode == "jit": U = qr.qm.EvolutionSuperOperator(time2, ham=HH, relt=L, pdeph=DD, mode="jit") U.set_dense_dt(N_dense) U1 = qr.qm.EvolutionSuperOperator(time2, ham=HH, relt=L, pdeph=DD) with qr.eigenbasis_of(HH): for i in range(1, Nsteps): U.calculate_next() U1.data[i, :, :, :, :] = U.data[:, :, :, :] context.U = U1 elif mode == "all": U = qr.qm.EvolutionSuperOperator(time2, ham=HH, relt=L, pdeph=DD, mode="all") U.set_dense_dt(N_dense) with qr.eigenbasis_of(HH): U.calculate() context.U = U
def step_when_11(context, t_prop): """ And I propagate with Lindblad form L and PureDephasing D to get RE at time {t_prop} """ t = float(t_prop) # initial density matrix R = context.R HH = context.H RE = qr.ReducedDensityMatrix(dim=HH.dim) RE.data[:, :] = 0.0 time2 = context.time2 t2, dt2 = time2.locate(t) L = context.L D = context.D prop = qr.ReducedDensityMatrixPropagator(timeaxis=time2, Ham=HH, RTensor=L, PDeph=D) prop.setDtRefinement(10) with qr.eigenbasis_of(HH): rhot = prop.propagate(R) RE = qr.ReducedDensityMatrix(data=rhot.data[t2, :, :]) context.RE = RE
def step_when_11(context, N_dense): """ When I calculate evolution superoperator U with time step {N_dense} and D in place """ # parameter from outside Nd = int(N_dense) # all that is needed from context HH = context.H LL = context.L time = context.time DD = context.DD # time step and number of steps Nt = time.length dt = time.step # we will make Nd times longer steps Nt_u = int(Nt/Nd) dt_u = dt*Nd # new time axis time_u = qr.TimeAxis(0.0, Nt_u, dt_u) # calculate evolution superoperator U = qr.qm.EvolutionSuperOperator(time=time_u, ham=HH, relt=LL, pdeph=DD) U.set_dense_dt(Nd) with qr.eigenbasis_of(HH): U.calculate() # save into context context.U = U
def step_when_5(context): # here we retrieve in eigenbasis of B what was calculated in site basis with qr.eigenbasis_of(context.H): Rt_ = context.Rt._data context.Rt_ = Rt_
def step_when_2(context, time_step, N_dense): """ When I calculate EvolutionSuperOperator using only PureDephasing D with {time_step} and {N_dense} """ # get the associated time axis and the relaxation tensor and Hamiltonian dt = float(time_step) N_dense = int(N_dense) time = qr.TimeAxis(0, 1320, 1.0) time2 = qr.TimeAxis(0, 132, dt) context.time = time context.time2 = time2 HH = context.H DD = context.D print("Dephasing type: ", DD.dtype) # This tests if it is possible to ignore relaxation tensor in defining # evolution superoperator L = qr.qm.LindbladForm(HH, sbi=None) U = qr.qm.EvolutionSuperOperator(time2, ham=HH, relt=L, pdeph=DD) U.set_dense_dt(N_dense) with qr.eigenbasis_of(HH): U.calculate() context.U = U
def step_given_10(context, deph_type): """ And I set dephasing type as {deph_type} """ dd = context.dd DD = qr.qm.PureDephasing(drates=dd, dtype=deph_type) context.DD = DD time = context.time2 HH = context.H LL = context.L # define and calculate evolution superoperator U = qr.qm.EvolutionSuperOperator(time, ham=HH, relt=LL, pdeph=DD) with qr.eigenbasis_of(HH): U.calculate() context.U = U # initial density matrix R = qr.ReducedDensityMatrix(dim=HH.dim) R.data[2,2] = 1.0 context.R = R
def step_when_4(context, dtime, t_prop): """ And I multiply each coherence element by corresponding exponential decay with dephasing time {dtime} to get RE """ gamma = 1.0 / float(dtime) t = float(t_prop) R = context.R HH = context.H RE = qr.ReducedDensityMatrix(dim=HH.dim) RE.data[:, :] = 0.0 with qr.eigenbasis_of(HH): for i in range(4): for j in range(4): om = HH.data[i, i] - HH.data[j, j] if i != j: RE.data[i, j] = R.data[i, j] * numpy.exp(-1j * om * t - gamma * t) else: RE.data[i, j] = R.data[i, j] * numpy.exp(-1j * om * t) context.RE = RE
def step_and3(context): # here we retrieve in eigenbasis of B what was calculated in site basis with qr.eigenbasis_of(context.B): C_ = context.C._data context.C_ = C_
def step_when_7(context, dtime, t_prop): """ And I multiply each coherence element by corresponding Gaussian decay with dephasing time {dtime} to get RE at time {t_prop} """ delta = (1.0 / float(dtime))**2 t = float(t_prop) R = context.R HH = context.H RE = qr.ReducedDensityMatrix(dim=HH.dim) RE.data[:, :] = 0.0 with qr.eigenbasis_of(HH): for i in range(4): for j in range(4): om = HH.data[i, i] - HH.data[j, j] if i != j: RE.data[i, j] = R.data[i, j] * numpy.exp(-1j * om * t - (delta / 2.0) * (t**2)) else: RE.data[i, j] = R.data[i, j] * numpy.exp(-1j * om * t) context.RE = RE
def step_and3(context): # here we retrieve in eigenbasis of B what was calculated in site basis with qr.eigenbasis_of(context.B): C_ = context.C._data context.C_ = C_
def thermal_population_comparison(self, temp, atol): """Creates canonical populations and checks them against the results from relaxation tensor #begin_feature Then long time Redfield populations will correspond to canonical equilibrium with temperature <temp> K with atol <atol> #end_feature """ print("Testing Redfield theory") agg = world.aggregate rho0 = ReducedDensityMatrix(dim=world.N) H = world.aggregate.get_Hamiltonian() with eigenbasis_of(H): print("\nExpected thermal population at ", temp, "K") rhoT = agg.get_DensityMatrix(condition_type="thermal_excited_state", temperature=world.temperature) pop_T = numpy.zeros(world.N, dtype=numpy.float64) for i in range(world.N): pop_T[i] = numpy.real(rhoT.data[i,i]) print(i, ":", pop_T[i]) print("Final calculated population") rho0.data[world.N-1,world.N-1] = 1.0 rho_t = world.prop.propagate(rho0) pop_C = numpy.zeros(world.N, dtype=numpy.float64) for i in range(world.N): pop_C[i] = numpy.real(rho_t.data[world.time.length-1,i,i]) print(i, ":", pop_C[i]) print("absolute tolerance atol=", float(atol)) numpy.testing.assert_allclose(pop_C, pop_T, atol=float(atol))
def thermal_population_comparison(self, temp, atol): """Creates canonical populations and checks them against the results from relaxation tensor #begin_feature Then long time Redfield populations will correspond to canonical equilibrium with temperature <temp> K with atol <atol> #end_feature """ print("Testing Redfield theory") agg = world.aggregate rho0 = ReducedDensityMatrix(dim=world.N) H = world.aggregate.get_Hamiltonian() with eigenbasis_of(H): print("\nExpected thermal population at ", temp, "K") rhoT = agg.get_DensityMatrix(condition_type="thermal_excited_state", temperature=world.temperature) pop_T = numpy.zeros(world.N, dtype=numpy.float64) for i in range(world.N): pop_T[i] = numpy.real(rhoT.data[i, i]) print(i, ":", pop_T[i]) print("Final calculated population") rho0.data[world.N - 1, world.N - 1] = 1.0 rho_t = world.prop.propagate(rho0) pop_C = numpy.zeros(world.N, dtype=numpy.float64) for i in range(world.N): pop_C[i] = numpy.real(rho_t.data[world.time.length - 1, i, i]) print(i, ":", pop_C[i]) print("absolute tolerance atol=", float(atol)) numpy.testing.assert_allclose(pop_C, pop_T, atol=float(atol))
def step_when_12(context, time_step, N_dense): """ When I calculate EvolutionSuperOperator in one shot using only PureDephasing D with {time_step} and {N_dense} """ HH = context.H L = qr.qm.LindbladForm(HH, sbi=None) DD = context.D dt = float(time_step) N_dense = int(N_dense) Ntot = 1320 Nsteps = int(Ntot / N_dense) time2 = qr.TimeAxis(0, Nsteps, dt) context.time2 = time2 mode = "all" U = qr.qm.EvolutionSuperOperator(time2, ham=HH, relt=L, pdeph=DD, mode=mode) U.set_dense_dt(N_dense) if mode == "all": with qr.eigenbasis_of(HH): U.calculate() context.U = U elif mode == "jit": U1 = qr.qm.EvolutionSuperOperator(time2, ham=HH, relt=L, pdeph=DD) with qr.eigenbasis_of(HH): for i in range(1, Nsteps): U.calculate_next() U1.data[i, :, :, :, :] = U.data[:, :, :, :] context.U = U1
def step_and(context): S = context.S A = context.A B = context.B with qr.eigenbasis_of(B): S_matrix = S._data A_matrix = A._data context.S_ = S_matrix context.A_ = A_matrix
def step_and(context): S = context.S A = context.A B = context.B with qr.eigenbasis_of(B): S_matrix = S._data A_matrix = A._data context.S_ = S_matrix context.A_ = A_matrix
def test_get_Density_Matrix_thermal_excited(self): """(Aggregate) Testing the get_Densitymatrix method with `thermal_excited_state` condition type """ from quantarhei.core.units import kB_intK vagg = self.vagg H = vagg.get_Hamiltonian() N = H.data.shape[0] Nb0 = vagg.Nb[0] # zero temperature rho0 = vagg.get_DensityMatrix(condition_type="thermal_excited_state") tst0 = numpy.zeros((N, N), dtype=qr.COMPLEX) tst0[Nb0, Nb0] = 1.0 numpy.testing.assert_almost_equal(rho0.data, tst0) # room temperature kbT = kB_intK * 300.0 H = self.agg.get_Hamiltonian() N = H.data.shape[0] Nb0 = self.agg.Nb[0] with qr.eigenbasis_of(H): rho0 = self.agg.get_DensityMatrix( condition_type="thermal_excited_state", temperature=300) tst0 = numpy.zeros((N, N), dtype=qr.COMPLEX) with qr.eigenbasis_of(H): ssum = 0.0 for i in range(Nb0, N): tst0[i, i] = numpy.exp(-(H.data[i, i] - H.data[Nb0, Nb0]) / kbT) ssum += tst0[i, i] tst0 = tst0 / ssum numpy.testing.assert_almost_equal(rho0.data, tst0)
def test_of_single_context_single_var(self): """Testing single operator in a single basis management context """ x,Sh = numpy.linalg.eigh(self.H.data) Sh1 = numpy.linalg.inv(Sh) h_copy_tr = numpy.dot(Sh1,numpy.dot(self.h_copy,Sh)) with eigenbasis_of(self.H): self.assertTrue(numpy.allclose(self.H.data,h_copy_tr)) self.assertTrue(numpy.allclose(self.H.data,self.h_copy))
def step_when_3(context): H = context.H U = context.U R = context.R with qr.eigenbasis_of(H): Ut = U.at(context.time) U_matrix = Ut._data R_matrix = R._data context.U_ = U_matrix context.R_ = R_matrix
def test_get_Density_Matrix_thermal_excited(self): """(Aggregate) Testing the get_Densitymatrix method with `thermal_excited_state` condition type """ from quantarhei.core.units import kB_intK vagg = self.vagg H = vagg.get_Hamiltonian() N = H.data.shape[0] Nb0 = vagg.Nb[0] # zero temperature rho0 = vagg.get_DensityMatrix(condition_type="thermal_excited_state") tst0 = numpy.zeros((N,N),dtype=qr.COMPLEX) tst0[Nb0,Nb0] = 1.0 numpy.testing.assert_almost_equal(rho0.data, tst0) # room temperature kbT = kB_intK*300.0 H = self.agg.get_Hamiltonian() N = H.data.shape[0] Nb0 = self.agg.Nb[0] with qr.eigenbasis_of(H): rho0 = self.agg.get_DensityMatrix(condition_type="thermal_excited_state", temperature=300) tst0 = numpy.zeros((N,N),dtype=qr.COMPLEX) with qr.eigenbasis_of(H): ssum = 0.0 for i in range(Nb0, N): tst0[i,i] = numpy.exp(-(H.data[i,i]-H.data[Nb0,Nb0])/kbT) ssum += tst0[i,i] tst0 = tst0/ssum numpy.testing.assert_almost_equal(rho0.data, tst0)
def step_when_12(context): """ When I calculate evolution superoperator using H and L in exciton basis """ # define and calculate evolution superoperator time2 = context.time2 LL = context.L HH = context.H with qr.eigenbasis_of(HH): U = qr.qm.EvolutionSuperOperator(time2, ham=HH, relt=LL) U.set_dense_dt(10) U.calculate() context.U = U
def setUp(self, verbose=False): self.verbose = verbose time = TimeAxis(0.0, 1000, 1.0) with energy_units("1/cm"): params = { "ftype": "OverdampedBrownian", "reorg": 30.0, "T": 300.0, "cortime": 100.0 } cf1 = CorrelationFunction(time, params) cf2 = CorrelationFunction(time, params) sd = SpectralDensity(time, params) cm1 = CorrelationFunctionMatrix(time, 2, 1) cm1.set_correlation_function(cf1, [(0, 0), (1, 1)]) cm2 = CorrelationFunctionMatrix(time, 2, 1) cm2.set_correlation_function(cf2, [(0, 0), (1, 1)]) K11 = numpy.array([[1.0, 0.0], [0.0, 0.0]], dtype=numpy.float) K21 = numpy.array([[1.0, 0.0], [0.0, 0.0]], dtype=numpy.float) K12 = K11.copy() K22 = K21.copy() KK11 = Operator(data=K11) KK21 = Operator(data=K21) KK12 = Operator(data=K12) KK22 = Operator(data=K22) self.sbi1 = SystemBathInteraction([KK11, KK21], cm1) self.sbi2 = SystemBathInteraction([KK12, KK22], cm2) with energy_units("1/cm"): h1 = [[0.0, 100.0], [100.0, 0.0]] h2 = [[0.0, 100.0], [100.0, 0.0]] self.H1 = Hamiltonian(data=h1) self.H2 = Hamiltonian(data=h2) #sd.convert_2_spectral_density() with eigenbasis_of(self.H1): de = self.H1.data[1, 1] - self.H1.data[0, 0] self.c_omega_p = sd.at(de, approx="spline") #interp_data(de) self.c_omega_m = sd.at(-de, approx="spline") #interp_data(-de)
def step_given_14(context, dtime): """ Given I have a Hamiltonian H, Lidblad form L, PureDephasing object D with dephasing time {dtime} and initial density matrix R """ td = float(dtime) print("Dephasing time", td) context.td = td # create test aggregatedimer agg = qr.TestAggregate("trimer-2") with qr.energy_units("1/cm"): agg.set_resonance_coupling(0, 1, 100.0) agg.set_resonance_coupling(1, 2, 50.0) agg.build() HH = agg.get_Hamiltonian() context.H = HH print("Hamiltonian:") print(HH) L = qr.qm.LindbladForm(HH, sbi=None) context.L = L # initial density matrix R = qr.ReducedDensityMatrix(dim=HH.dim) with qr.eigenbasis_of(HH): R.data[1:4, 1:4] = 0.5 context.R = R dd = numpy.zeros((4, 4), dtype=qr.REAL) dd[1, 2] = 1.0 / td dd[2, 1] = 1.0 / td dd[1, 3] = 1.0 / td dd[3, 1] = 1.0 / td dd[2, 3] = 1.0 / td dd[3, 2] = 1.0 / td D = qr.qm.PureDephasing(drates=dd, dtype="Lorentzian") context.D = D
def setUp(self,verbose=False): self.verbose = verbose time = TimeAxis(0.0,1000,1.0) with energy_units("1/cm"): params = {"ftype":"OverdampedBrownian", "reorg":30.0, "T":300.0, "cortime":100.0} cf1 = CorrelationFunction(time,params) cf2 = CorrelationFunction(time,params) sd = SpectralDensity(time,params) cm1 = CorrelationFunctionMatrix(time,2,1) cm1.set_correlation_function(cf1,[(0,0),(1,1)]) cm2 = CorrelationFunctionMatrix(time,2,1) cm2.set_correlation_function(cf2,[(0,0),(1,1)]) K11 = numpy.array([[1.0, 0.0],[0.0, 0.0]],dtype=qr.REAL) K21 = numpy.array([[1.0, 0.0],[0.0, 0.0]],dtype=qr.REAL) K12 = K11.copy() K22 = K21.copy() KK11 = Operator(data=K11) KK21 = Operator(data=K21) KK12 = Operator(data=K12) KK22 = Operator(data=K22) self.sbi1 = SystemBathInteraction([KK11,KK21],cm1) self.sbi2 = SystemBathInteraction([KK12,KK22],cm2) with energy_units("1/cm"): h1 = [[0.0, 100.0],[100.0, 0.0]] h2 = [[0.0, 100.0],[100.0, 0.0]] self.H1 = Hamiltonian(data=h1) self.H2 = Hamiltonian(data=h2) #sd.convert_2_spectral_density() with eigenbasis_of(self.H1): de = self.H1.data[1,1]-self.H1.data[0,0] self.c_omega_p = sd.at(de,approx="spline") #interp_data(de) self.c_omega_m = sd.at(-de,approx="spline") #interp_data(-de)
def test_thermal_density_matrix_finite_temp_nondiag(self): """Thermal density matrix: finite temperature, non-diagonal Hamiltonian """ timeAxis = TimeAxis(0.0,1000,1.0) params = {"ftype":"OverdampedBrownian", "T":300.0, "reorg":30, "cortime":100} cfcion = CorrelationFunction(timeAxis,params) self.m2.set_egcf((0,1),cfcion) self.m2.set_egcf((0,2),cfcion) rho_eq = self.m2.get_thermal_ReducedDensityMatrix() pop = numpy.zeros(rho_eq._data.shape[0]) # get temperature from the molecule T = self.m2.get_temperature() self.assertTrue(numpy.abs(T-300.0)<1.0e-10) # get Hamiltonian H = self.m2.get_Hamiltonian() with eigenbasis_of(H): # get density matrix rpop = rho_eq.get_populations() if numpy.abs(T) < 1.0e-10: pop[0] = 1.0 else: # thermal populations psum = 0.0 for n in range(pop.shape[0]): pop[n] = numpy.exp(-H.data[n,n]/(kB_intK*T)) psum += pop[n] pop *= 1.0/psum self.assertTrue(numpy.allclose(pop,rpop))
def step_when_14(context): """ When I calculate evolution superoperator using H and L with "jit" settings in exciton basis """ # define and calculate evolution superoperator time2 = context.time2 LL = context.L HH = context.H with qr.eigenbasis_of(HH): U = qr.qm.EvolutionSuperOperator(time2, ham=HH, relt=LL, mode="jit") U.set_dense_dt(10) for tt in range(1,time2.length): U.calculate_next(save=True) context.U = U
def test_thermal_density_matrix_finite_temp_nondiag(self): """Thermal density matrix: finite temperature, non-diagonal Hamiltonian """ timeAxis = TimeAxis(0.0, 1000, 1.0) params = { "ftype": "OverdampedBrownian", "T": 300.0, "reorg": 30, "cortime": 100 } cfcion = CorrelationFunction(timeAxis, params) self.m2.set_egcf((0, 1), cfcion) self.m2.set_egcf((0, 2), cfcion) rho_eq = self.m2.get_thermal_ReducedDensityMatrix() pop = numpy.zeros(rho_eq._data.shape[0]) # get temperature from the molecule T = self.m2.get_temperature() self.assertTrue(numpy.abs(T - 300.0) < 1.0e-10) # get Hamiltonian H = self.m2.get_Hamiltonian() with eigenbasis_of(H): # get density matrix rpop = rho_eq.get_populations() if numpy.abs(T) < 1.0e-10: pop[0] = 1.0 else: # thermal populations psum = 0.0 for n in range(pop.shape[0]): pop[n] = numpy.exp(-H.data[n, n] / (kB_intK * T)) psum += pop[n] pop *= 1.0 / psum self.assertTrue(numpy.allclose(pop, rpop))
def step_when_8(context, time_step, N_dense): """ When I calculate EvolutionSuperOperator step by step using only PureDephasing D with {time_step} and {N_dense} """ # get the associated time axis and the relaxation tensor and Hamiltonian dt = float(time_step) N_dense = int(N_dense) Ntot = 1320 Nsteps = int(Ntot / N_dense) time = qr.TimeAxis(0, Ntot, 1.0) time2 = qr.TimeAxis(0, Nsteps, dt) context.time = time context.time2 = time2 HH = context.H DD = context.D print("Dephasing type: ", DD.dtype) # This tests if it is possible to ignore relaxation tensor in defining # evolution superoperator L = qr.qm.LindbladForm(HH, sbi=None) U = qr.qm.EvolutionSuperOperator(time2, ham=HH, relt=L, pdeph=DD, mode="jit") U.set_dense_dt(N_dense) U1 = qr.qm.EvolutionSuperOperator(time2, ham=HH, relt=L, pdeph=DD) with qr.eigenbasis_of(HH): for i in range(1, Nsteps): U.calculate_next() U1.data[i, :, :, :, :] = U.data[:, :, :, :] context.U = U1
def step_when_12(context): """ And I calculate dynamics of R using H, L and D to get R1 """ time = context.time2 HH = context.H LL = context.L DD = context.DD prop = qr.ReducedDensityMatrixPropagator(timeaxis=time, Ham=HH, RTensor=LL, PDeph=DD) R = context.R with qr.eigenbasis_of(HH): R1 = prop.propagate(R) context.R1 = R1
def step_when_15(context): """ When I calculate evolution superoperator using H and L with "no save jit" settings in exciton basis """ time2 = context.time2 LL = context.L HH = context.H with qr.eigenbasis_of(HH): U = qr.qm.EvolutionSuperOperator(time2, ham=HH, relt=LL, mode="jit") U2 = qr.qm.EvolutionSuperOperator(time2, ham=HH, relt=LL, mode="all") U2.set_dense_dt(10) for tt in range(1,time2.length): U.calculate_next() U2.data[tt,:,:,:,:] = U.data context.U = U2
def step_then_5(context, t_prop): """ Then RD equals RE at times {t_prop} """ RD = context.RD RE = context.RE with qr.eigenbasis_of(context.H): print(context.R) print("\nCalculated with U:") print("Shape: ", RD.data.shape) print(RD.data) print("\nReference calculation:") print("Shape: ", RE.data.shape) print(RE.data) print("\nMax diff:", numpy.amax(numpy.abs(RD.data - RE.data))) numpy.testing.assert_allclose(RD.data, RE.data, rtol=1.0e-5, atol=1.0e-5)
def run(omega, HR, dE, JJ, rate, vib_loc="up", use_vib=True, stype=qr.signal_REPH, make_movie=False): """Runs a complete set of simulations for a single set of parameters """ # # FIXED PARAMETERS # E0 = 10000.0 dip1 = [1.5, 0.0, 0.0] dip2 = [-1.0, -1.0, 0.0] width = 100.0 #rate = 1.0/50.0 normalize_maps_to_maximu = False trim_maps = False units = "1/cm" with qr.energy_units(units): data_descr = "_dO="+str(dE-omega)+"_HR="+str(HR)+"_J="+str(JJ) if use_vib: sys_char = "_vib" else: sys_char = "_ele" data_ext = sys_char+".png" obj_ext = sys_char+".qrp" # # Model system is a dimer of molecules # with qr.energy_units("1/cm"): mol1 = qr.Molecule([0.0, E0]) mol2 = qr.Molecule([0.0, E0+dE]) mod1 = qr.Mode(omega) mod2 = qr.Mode(omega) mol1.set_transition_width((0,1), qr.convert(width, "1/cm", "int")) mol1.set_dipole(0,1, dip1) mol2.set_transition_width((0,1), qr.convert(width, "1/cm", "int")) mol2.set_dipole(0,1, dip2) agg = qr.Aggregate([mol1, mol2]) with qr.energy_units("1/cm"): agg.set_resonance_coupling(0,1,JJ) # # Electronic only aggregate # agg_el = agg.deepcopy() # # if nuclear vibrations are to be added, do it here # if use_vib: if vib_loc == "down": set_vib = [True, False] elif vib_loc == "up": set_vib = [False, True] elif vib_loc == "both": set_vib = [True, True] else: raise Exception("Unknown location of the vibrations") if set_vib[0]: mol1.add_Mode(mod1) mod1.set_nmax(0, 3) mod1.set_nmax(1, 3) mod1.set_HR(1, HR) if set_vib[1]: mol2.add_Mode(mod2) mod2.set_nmax(0, 3) mod2.set_nmax(1, 3) mod2.set_HR(1, HR) agg3 = agg.deepcopy() agg.build(mult=1) agg_el.build(mult=1) HH = agg.get_Hamiltonian() He = agg_el.get_Hamiltonian() with qr.energy_units("1/cm"): with qr.eigenbasis_of(He): Ep_l = He.data[1,1] Ep_u = He.data[2,2] Ep = numpy.zeros((4,2)) Ep[0,0] = Ep_l Ep[0,1] = Ep_l Ep[1,0] = Ep_l Ep[1,1] = Ep_u Ep[2,0] = Ep_u Ep[2,1] = Ep_l Ep[3,0] = Ep_u Ep[3,1] = Ep_u # # Laboratory setup # lab = qr.LabSetup() lab.set_polarizations(pulse_polarizations=[X,X,X], detection_polarization=X) time2 = qr.TimeAxis(0.0, 100, 10.0) cont_p = qr.TwoDResponseContainer(t2axis=time2) cont_m = qr.TwoDResponseContainer(t2axis=time2) # # spectra will be indexed by the times in the time axis `time2` # cont_p.use_indexing_type(time2) # # We define two-time axes, which will be FFTed and will define # the omega_1 and omega_3 axes of the 2D spectrum # t1_N_steps = 100 t1_time_step = 10.0 t3_N_steps = 100 t3_time_step = 10.0 t1axis = qr.TimeAxis(0.0, t1_N_steps, t1_time_step) t3axis = qr.TimeAxis(0.0, t3_N_steps, t3_time_step) # # This calculator calculated 2D spectra from the effective width # msc = qr.MockTwoDResponseCalculator(t1axis, time2, t3axis) with qr.energy_units("1/cm"): msc.bootstrap(rwa=E0, shape="Gaussian") # # System-bath interaction including vibrational states # operators = [] rates = [] with qr.eigenbasis_of(He): operators.append(qr.qm.ProjectionOperator(1, 2, dim=He.dim)) rates.append(rate) sbi = qr.qm.SystemBathInteraction(sys_operators=operators, rates=rates) sbi.set_system(agg) # # Liouville form for relaxation # LF = qr.qm.ElectronicLindbladForm(HH, sbi, as_operators=True) # # Pure dephasing # p_deph = qr.qm.ElectronicPureDephasing(agg, dtype="Gaussian") eUt = qr.qm.EvolutionSuperOperator(time2, HH, relt=LF, pdeph=p_deph, mode="all") eUt.set_dense_dt(10) # # We calculate evolution superoperator # eUt.calculate(show_progress=False) # # Prepare aggregate with all states (including 2-EX band) # agg3.build(mult=2) agg3.diagonalize() pways = dict() t2_save_pathways = [300.0] olow = qr.convert(omega-30.0, "1/cm", "int") ohigh = qr.convert(omega+30.0, "1/cm", "int") for t2 in time2.data: # this could save some memory of pathways become too big pways = dict() print("t2 =", t2) twod = msc.calculate_one_system(t2, agg3, eUt, lab, pways=pways, selection=[["omega2",[olow, ohigh]]]) print("Number of pathways used for omega2 =",omega,":", len(pways[str(t2)])) if t2 in t2_save_pathways: pws_name = os.path.join("sim_"+vib_loc, "pws_t2="+str(t2)+ "_omega2="+str(omega)+data_descr+data_ext) qr.save_parcel(pways[str(t2)], pws_name) cont_p.set_spectrum(twod) twod = msc.calculate_one_system(t2, agg3, eUt, lab, pways=pways, selection=[["omega2",[-ohigh, -olow]]]) print("Number of pathways used for omega2 =",-omega,":", len(pways[str(t2)])) if t2 in t2_save_pathways: pws_name = os.path.join("sim_"+vib_loc, "pws_t2="+str(t2)+ "_omega2="+str(-omega)+data_descr+data_ext) qr.save_parcel(pways[str(t2)], pws_name) cont_m.set_spectrum(twod) if make_movie: with qr.energy_units("1/cm"): cont_p.make_movie("mov.mp4") fname = os.path.join("sim_"+vib_loc, "pways.qrp") qr.save_parcel(pways, fname) fname = os.path.join("sim_"+vib_loc, "aggregate.qrp") agg3.save(fname) # # Window function for subsequenty FFT # window = func.Tukey(time2, r=0.3, sym=False) # # FFT with the window function # # Specify REPH, NONR or `total` to get different types of spectra # print("\nCalculating FFT of the 2D maps") #fcont = cont.fft(window=window, dtype=stype) #, dpart="real", offset=0.0) fcont_p_re = cont_p.fft(window=window, dtype=qr.signal_REPH) fcont_p_nr = cont_p.fft(window=window, dtype=qr.signal_NONR) fcont_p_to = cont_p.fft(window=window, dtype=qr.signal_TOTL) if normalize_maps_to_maximu: fcont_p_re.normalize2(dpart=qr.part_ABS) fcont_p_nr.normalize2(dpart=qr.part_ABS) fcont_p_to.normalize2(dpart=qr.part_ABS) fcont_m_re = cont_m.fft(window=window, dtype=qr.signal_REPH) fcont_m_nr = cont_m.fft(window=window, dtype=qr.signal_NONR) fcont_m_to = cont_m.fft(window=window, dtype=qr.signal_TOTL) if normalize_maps_to_maximu: fcont_m_re.normalize2(dpart=qr.part_ABS) fcont_m_nr.normalize2(dpart=qr.part_ABS) fcont_m_to.normalize2(dpart=qr.part_ABS) if trim_maps: twin = [9500, 11000, 9500, 11000] with qr.energy_units("1/cm"): fcont_p_re.trimall_to(window=twin) fcont_p_nr.trimall_to(window=twin) fcont_p_to.trimall_to(window=twin) show_omega = omega # # Have a look which frequencies we actually have # # Ndat = len(fcont_re.axis.data) # print("\nNumber of frequency points:", Ndat) # print("In 1/cm they are:") # with qr.energy_units("1/cm"): # for k_i in range(Ndat): # print(k_i, fcont_re.axis.data[k_i]) with qr.frequency_units("1/cm"): sp1_p_re, show_Npoint1 = fcont_p_re.get_nearest(show_omega) sp2_p_re, show_Npoint2 = fcont_p_re.get_nearest(-show_omega) sp1_p_nr, show_Npoint1 = fcont_p_nr.get_nearest(show_omega) sp2_p_nr, show_Npoint2 = fcont_p_nr.get_nearest(-show_omega) sp1_p_to, show_Npoint1 = fcont_p_to.get_nearest(show_omega) sp2_p_to, show_Npoint2 = fcont_p_to.get_nearest(-show_omega) sp1_m_re, show_Npoint1 = fcont_m_re.get_nearest(show_omega) sp2_m_re, show_Npoint2 = fcont_m_re.get_nearest(-show_omega) sp1_m_nr, show_Npoint1 = fcont_m_nr.get_nearest(show_omega) sp2_m_nr, show_Npoint2 = fcont_m_nr.get_nearest(-show_omega) sp1_m_to, show_Npoint1 = fcont_m_to.get_nearest(show_omega) sp2_m_to, show_Npoint2 = fcont_m_to.get_nearest(-show_omega) # units = "1/cm" # with qr.energy_units(units): # # data_descr = "_dO="+str(dE-omega)+"_HR="+str(HR)+"_J="+str(JJ) # # if use_vib: # sys_char = "_vib" # else: # sys_char = "_ele" # data_ext = sys_char+".png" # obj_ext = sys_char+".qrp" with qr.energy_units(units): print("\nPlotting and saving spectrum at frequency:", fcont_p_re.axis.data[show_Npoint1], units) fftf_1 = os.path.join("sim_"+vib_loc, "twod_fft"+data_descr+ "_stype=REPH"+"_omega="+str(omega)+data_ext) sp1_p_re.plot(Npos_contours=10, spart=qr.part_ABS, label="Rephasing\n $\omega="+str(omega)+ "$ cm$^{-1}$", text_loc=[0.05,0.1], show_states=[Ep_l, Ep_u, Ep_u+numpy.abs(omega)], show_diagonal="-k") sp1_p_re.savefig(fftf_1) print("... saved into: ", fftf_1) fftf_2 = os.path.join("sim_"+vib_loc, "twod_fft"+data_descr+ "_stype=NONR"+"_omega="+str(omega)+data_ext) sp1_p_nr.plot(Npos_contours=10, spart=qr.part_ABS, label="Non-rephasing\n $\omega="+str(omega)+ "$ cm$^{-1}$", text_loc=[0.05,0.1], show_states=[Ep_l, Ep_u, Ep_u+numpy.abs(omega)], show_diagonal="-k") sp1_p_nr.savefig(fftf_2) print("... saved into: ", fftf_2) fftf_3 = os.path.join("sim_"+vib_loc, "twod_fft"+data_descr+ "_stype=tot"+"_omega="+str(omega)+data_ext) sp1_p_to.plot(Npos_contours=10, spart=qr.part_ABS, label="Total\n $\omega="+str(omega)+ "$ cm$^{-1}$", text_loc=[0.05,0.1], show_states=[Ep_l, Ep_u, Ep_u+numpy.abs(omega)], show_diagonal="-k") sp1_p_to.savefig(fftf_3) print("... saved into: ", fftf_3) # # Point evolutions at the expected peak positions # if show_plots: for ii in range(4): points = fcont_p_re.get_point_evolution(Ep[ii,0], Ep[ii,1], fcont_p_re.axis) points.apply_to_data(numpy.abs) if ii >= 3: points.plot(show=True) else: points.plot(show=False) print("\nPlotting and saving spectrum at frequency:", fcont_m_re.axis.data[show_Npoint2], units) fftf_4 = os.path.join("sim_"+vib_loc, "twod_fft"+data_descr+ "_stype=REPH"+"_omega="+str(-omega)+data_ext) sp2_m_re.plot(Npos_contours=10, spart=qr.part_ABS, label="Rephasing\n $\omega="+str(-omega)+ "$ cm$^{-1}$", text_loc=[0.05,0.1], show_states=[Ep_l, Ep_u, Ep_u+numpy.abs(omega)], show_diagonal="-k") sp2_m_re.savefig(fftf_4) print("... saved into: ", fftf_4) fftf_5 = os.path.join("sim_"+vib_loc, "twod_fft"+data_descr+ "_stype=NONR"+"_omega="+str(-omega)+data_ext) sp2_m_nr.plot(Npos_contours=10, spart=qr.part_ABS, label="Non-rephasing\n $\omega="+str(-omega)+ "$ cm$^{-1}$", text_loc=[0.05,0.1], show_states=[Ep_l, Ep_u, Ep_u+numpy.abs(omega)], show_diagonal="-k") sp2_m_nr.savefig(fftf_5) print("... saved into: ", fftf_5) fftf_6 = os.path.join("sim_"+vib_loc, "twod_fft"+data_descr+ "_stype=tot"+"_omega="+str(-omega)+data_ext) sp2_m_to.plot(Npos_contours=10, spart=qr.part_ABS, label="Total\n $\omega="+str(-omega)+ "$ cm$^{-1}$", text_loc=[0.05,0.1], show_states=[Ep_l, Ep_u, Ep_u+numpy.abs(omega)], show_diagonal="-k") sp2_m_to.savefig(fftf_6) print("... saved into: ", fftf_6) if show_plots: # # Point evolutions at the expected peak positions # for ii in range(4): points = fcont_p_re.get_point_evolution(Ep[ii,0], Ep[ii,1], fcont_m_re.axis) points.apply_to_data(numpy.abs) if ii >= 3: points.plot(show=True) else: points.plot(show=False) #points.apply_to_data(numpy.abs) #points.plot() # saving containers # fname = os.path.join("sim_"+vib_loc,"fcont_re"+data_descr+obj_ext) # print("Saving container into: "+fname) # fcont_p_re.save(fname) # fname = os.path.join("sim_"+vib_loc,"fcont_nr"+data_descr+obj_ext) # print("Saving container into: "+fname) # fcont_p_nr.save(fname) # fname = os.path.join("sim_"+vib_loc,"fcont_to"+data_descr+obj_ext) # print("Saving container into: "+fname) # fcont_p_to.save(fname) fname = os.path.join("sim_"+vib_loc,"cont_p"+data_descr+obj_ext) print("Saving container into: "+fname) cont_p.save(fname) fname = os.path.join("sim_"+vib_loc,"cont_m"+data_descr+obj_ext) print("Saving container into: "+fname) cont_m.save(fname) return (sp1_p_re, sp1_p_nr, sp2_m_re, sp2_m_nr)
def setUp(self, verbose=False): self.verbose = verbose # # Lindblad projection operators # K12 = numpy.array([[0.0, 1.0], [0.0, 0.0]], dtype=numpy.float) K21 = numpy.array([[0.0, 0.0], [1.0, 0.0]], dtype=numpy.float) KK12 = Operator(data=K12) KK21 = Operator(data=K21) self.KK12 = KK12 self.KK21 = KK21 # # Linbdlad rates # self.rates = (1.0 / 100.0, 1.0 / 200.0) # # System-bath interaction using operators and rates in site basis # self.sbi1 = SystemBathInteraction([KK12, KK21], rates=self.rates) self.sbi2 = SystemBathInteraction([KK12, KK21], rates=self.rates) # # Test Hamiltonians # with energy_units("1/cm"): h1 = [[100.0, 0.0], [0.0, 0.0]] h2 = [[100.0, 0.0], [0.0, 0.0]] self.H1 = Hamiltonian(data=h1) self.H2 = Hamiltonian(data=h2) h3 = [[100.0, 20.0], [20.0, 0.0]] self.H3 = Hamiltonian(data=h3) # less trivial Hamiltonian h4 = [[100.0, 200.0, 30.0], [200.0, 50.0, -100.0], [30.0, -100.0, 0.0]] self.H4 = Hamiltonian(data=h4) h4s = [[100.0, 0.0, 0.0], [0.0, 50.0, 0.0], [0.0, 0.0, 0.0]] self.H4s = Hamiltonian(data=h4s) # # Projection operators in eigenstate basis # with eigenbasis_of(self.H3): K_12 = ProjectionOperator(0, 1, dim=2) K_21 = ProjectionOperator(1, 0, dim=2) self.K_12 = K_12 self.K_21 = K_21 with eigenbasis_of(self.H4): Ke_12 = ProjectionOperator(0, 1, dim=3) Ke_21 = ProjectionOperator(1, 0, dim=3) Ke_23 = ProjectionOperator(1, 2, dim=3) Ke_32 = ProjectionOperator(2, 1, dim=3) Ks_12 = ProjectionOperator(0, 1, dim=3) Ks_21 = ProjectionOperator(1, 0, dim=3) Ks_23 = ProjectionOperator(1, 2, dim=3) Ks_32 = ProjectionOperator(2, 1, dim=3) self.rates4 = [1.0 / 100, 1.0 / 200, 1.0 / 150, 1.0 / 300] # # System-bath operators defined in exciton basis # self.sbi3 = SystemBathInteraction([K_12, K_21], rates=self.rates) self.sbi4e = SystemBathInteraction([Ke_12, Ke_21, Ke_23, Ke_32], rates=self.rates4) self.sbi4s = SystemBathInteraction([Ks_12, Ks_21, Ks_23, Ks_32], rates=self.rates4)
def test_comparison_of_exciton_dynamics(self): """Testing exciton basis dynamics by Lindblad """ # site basis form to be compared with LT1 = LindbladForm(self.H1, self.sbi1, as_operators=True) # exciton basis forms LT13 = LindbladForm(self.H3, self.sbi3, as_operators=True) LT23 = LindbladForm(self.H3, self.sbi3, as_operators=False) LT4e = LindbladForm(self.H4, self.sbi4e, as_operators=True) LT4s = LindbladForm(self.H4s, self.sbi4s, as_operators=True) time = TimeAxis(0.0, 1000, 1.0) # # Propagators # prop0 = ReducedDensityMatrixPropagator(time, self.H1, LT1) prop1 = ReducedDensityMatrixPropagator(time, self.H3, LT13) prop2 = ReducedDensityMatrixPropagator(time, self.H3, LT23) prop4e = ReducedDensityMatrixPropagator(time, self.H4, LT4e) prop4s = ReducedDensityMatrixPropagator(time, self.H4s, LT4s) # # Initial conditions # rho0 = ReducedDensityMatrix(dim=self.H3.dim) rho0c = ReducedDensityMatrix(dim=self.H1.dim) # excitonic with eigenbasis_of(self.H3): rho0c.data[1, 1] = 1.0 rho0.data[1, 1] = 1.0 rho04e = ReducedDensityMatrix(dim=self.H4.dim) rho04s = ReducedDensityMatrix(dim=self.H4.dim) with eigenbasis_of(self.H4): rho04e.data[2, 2] = 1.0 rho04s.data[2, 2] = 1.0 # # Propagations # rhotc = prop0.propagate(rho0c) rhot1 = prop1.propagate(rho0) rhot2 = prop2.propagate(rho0) rhot4e = prop4e.propagate(rho04e) rhot4s = prop4s.propagate(rho04s) # propagation with operator- and tensor forms should be the same numpy.testing.assert_allclose(rhot1.data, rhot2.data) #, rtol=1.0e-2) # # Population time evolution by Lindblad is independent # of the level structure and basis, as long as I compare # populations in basis in which the Lindblad form was defined # P = numpy.zeros((2, time.length)) Pc = numpy.zeros((2, time.length)) P4e = numpy.zeros((3, time.length)) P4s = numpy.zeros((3, time.length)) with eigenbasis_of(self.H3): for i in range(time.length): P[0, i] = numpy.real(rhot1.data[i, 0, 0]) # population of exciton 0 P[1, i] = numpy.real(rhot1.data[i, 1, 1]) # population of exciton 1 for i in range(time.length): Pc[0, i] = numpy.real(rhotc.data[i, 0, 0]) # population of exciton 0 Pc[1, i] = numpy.real(rhotc.data[i, 1, 1]) # population of exciton 1 # we compare populations numpy.testing.assert_allclose(Pc, P) #, rtol=1.0e-2) with eigenbasis_of(self.H4): for i in range(time.length): P4e[0, i] = numpy.real(rhot4e.data[i, 0, 0]) # population of exciton 0 P4e[1, i] = numpy.real(rhot4e.data[i, 1, 1]) # population of exciton 1 P4e[2, i] = numpy.real(rhot4e.data[i, 2, 2]) # population of exciton 1 for i in range(time.length): P4s[0, i] = numpy.real(rhot4s.data[i, 0, 0]) # population of exciton 0 P4s[1, i] = numpy.real(rhot4s.data[i, 1, 1]) # population of exciton 1 P4s[2, i] = numpy.real(rhot4s.data[i, 2, 2]) # population of exciton 1 # import matplotlib.pyplot as plt # # plt.plot(time.data,P4s[0,:], "-r") # plt.plot(time.data,P4s[1,:], "-r") # plt.plot(time.data,P4s[2,:], "-r") # plt.plot(time.data,P4e[0,:], "-g") # plt.plot(time.data,P4e[1,:], "-g") # plt.plot(time.data,P4e[2,:], "-g") # plt.show() numpy.testing.assert_allclose(P4e, P4s, atol=1.0e-8)
def state_vector_transformed_in_eig_of_hamiltonian(self): with eigenbasis_of(world.HH): vec = world.sv.data world.sv_transformed = vec
def test_comparison_of_exciton_dynamics(self): """Testing exciton basis dynamics by Lindblad """ # site basis form to be compared with LT1 = LindbladForm(self.H1, self.sbi1, as_operators=True) # exciton basis forms LT13 = LindbladForm(self.H3, self.sbi3, as_operators=True) LT23 = LindbladForm(self.H3, self.sbi3, as_operators=False) LT4e = LindbladForm(self.H4, self.sbi4e, as_operators=True) LT4s = LindbladForm(self.H4s, self.sbi4s, as_operators=True) time = TimeAxis(0.0, 1000, 1.0) # # Propagators # prop0 = ReducedDensityMatrixPropagator(time, self.H1, LT1) prop1 = ReducedDensityMatrixPropagator(time, self.H3, LT13) prop2 = ReducedDensityMatrixPropagator(time, self.H3, LT23) prop4e = ReducedDensityMatrixPropagator(time, self.H4, LT4e) prop4s = ReducedDensityMatrixPropagator(time, self.H4s, LT4s) # # Initial conditions # rho0 = ReducedDensityMatrix(dim=self.H3.dim) rho0c = ReducedDensityMatrix(dim=self.H1.dim) # excitonic with eigenbasis_of(self.H3): rho0c.data[1,1] = 1.0 rho0.data[1,1] = 1.0 rho04e = ReducedDensityMatrix(dim=self.H4.dim) rho04s = ReducedDensityMatrix(dim=self.H4.dim) with eigenbasis_of(self.H4): rho04e.data[2,2] = 1.0 rho04s.data[2,2] = 1.0 # # Propagations # rhotc = prop0.propagate(rho0c) rhot1 = prop1.propagate(rho0) rhot2 = prop2.propagate(rho0) rhot4e = prop4e.propagate(rho04e) rhot4s = prop4s.propagate(rho04s) # propagation with operator- and tensor forms should be the same numpy.testing.assert_allclose(rhot1.data,rhot2.data) #, rtol=1.0e-2) # # Population time evolution by Lindblad is independent # of the level structure and basis, as long as I compare # populations in basis in which the Lindblad form was defined # P = numpy.zeros((2, time.length)) Pc = numpy.zeros((2, time.length)) P4e = numpy.zeros((3, time.length)) P4s = numpy.zeros((3, time.length)) with eigenbasis_of(self.H3): for i in range(time.length): P[0,i] = numpy.real(rhot1.data[i,0,0]) # population of exciton 0 P[1,i] = numpy.real(rhot1.data[i,1,1]) # population of exciton 1 for i in range(time.length): Pc[0,i] = numpy.real(rhotc.data[i,0,0]) # population of exciton 0 Pc[1,i] = numpy.real(rhotc.data[i,1,1]) # population of exciton 1 # we compare populations numpy.testing.assert_allclose(Pc,P) #, rtol=1.0e-2) with eigenbasis_of(self.H4): for i in range(time.length): P4e[0,i] = numpy.real(rhot4e.data[i,0,0]) # population of exciton 0 P4e[1,i] = numpy.real(rhot4e.data[i,1,1]) # population of exciton 1 P4e[2,i] = numpy.real(rhot4e.data[i,2,2]) # population of exciton 1 for i in range(time.length): P4s[0,i] = numpy.real(rhot4s.data[i,0,0]) # population of exciton 0 P4s[1,i] = numpy.real(rhot4s.data[i,1,1]) # population of exciton 1 P4s[2,i] = numpy.real(rhot4s.data[i,2,2]) # population of exciton 1 # import matplotlib.pyplot as plt # # plt.plot(time.data,P4s[0,:], "-r") # plt.plot(time.data,P4s[1,:], "-r") # plt.plot(time.data,P4s[2,:], "-r") # plt.plot(time.data,P4e[0,:], "-g") # plt.plot(time.data,P4e[1,:], "-g") # plt.plot(time.data,P4e[2,:], "-g") # plt.show() numpy.testing.assert_allclose(P4e, P4s, atol=1.0e-8)
# we print its Hamiltonian to check everything is alright H = agg.get_Hamiltonian() with qr.energy_units("1/cm"): print(H) ############################################################################### # # EXCITED STATE DYNAMICS: Lindblad relaxation between eigenstates # ############################################################################### # time span of the excited state evolution (later t2 time of the 2D spectrum) t2_axis = qr.TimeAxis(0.0, 100, 10.0) # Lindblad relaxation operator with qr.eigenbasis_of(H): K = qr.qm.ProjectionOperator(1, 2, dim=H.dim) rates = [1.0 / 200.0] sbi = qr.qm.SystemBathInteraction(sys_operators=[K], rates=rates) L = qr.qm.LindbladForm(H, sbi) eUt = qr.EvolutionSuperOperator(time=t2_axis, ham=H, relt=L) eUt.set_dense_dt(10) eUt.calculate() if _show_plots_: with qr.eigenbasis_of(H): eUt.plot_element((2, 2, 2, 2), show=False)
print("Relaxation times") for k in range(hh.getDim(0)): for l in range(hh.getDim(0)): if (RRM.data[k,l] > 0) and ((l-k)==1): print(k,l,1.0/RRM.data[k,l]," fs") # # We are in position to calculate excited state dynamics of charge transfer # process. # # We set initial condition for the calculation. Sofar everything was # specified in the site-basis. We will switch to exciton basis with eigenbasis_of(hh): # get the ground state thermal density matrix rho_eq = m.get_thermal_ReducedDensityMatrix() # we set initial condition by exciting the molecule with the polarization # along its transition dipole moment # # # rho_ini = numpy.dot(dd.data[:,:,0],numpy.dot(rho_eq,dd.data[:,:,0])) rho_ini = rho_eq.excite_delta(dmoment=dd,epolarization=[1.0, 0.0, 0.0]) # we normalize the population of excited state to 1.0 rho_ini.normalize2(norm=1.0) # we need only population dynamics, so let us convert density matrix to
agg.set_resonance_coupling(1,3,qr.convert(100.0,"1/cm","int")) with tempfile.TemporaryDirectory() as tdir: path = os.path.join(tdir,"agg.qrp") qr.save_parcel(agg,path) agg2 = qr.load_parcel(path) agg2.build() H = agg2.get_Hamiltonian() print("...done") print("Setting up Lindblad form relaxation:") Ndim = 5 with qr.eigenbasis_of(H): K12 = qr.qm.ProjectionOperator(1, 2, dim=Ndim) K23 = qr.qm.ProjectionOperator(2, 3, dim=Ndim) K34 = qr.qm.ProjectionOperator(3, 4, dim=Ndim) sbi = qr.qm.SystemBathInteraction(sys_operators=[K12, K23, K34], rates=(1.0/200, 1.0/100.0, 1.0/150)) agg.set_SystemBathInteraction(sbi) agg.build() ham = agg.get_Hamiltonian() rt = qr.qm.LindbladForm(ham, sbi) # as_operators=False) print("...done")
Calculating relaxation tensor ******************************************************************************* """) m = qr.Manager() m.warn_about_basis_change = False sb_reference = qr.BasisReferenceOperator(ham.dim, name="site basis reference") # # Calculation of various relaxation tensors # ham.protect_basis() with qr.eigenbasis_of(ham): RRT = qr.qm.RedfieldRelaxationTensor(ham, sbi, name="Tensor 1") print("\nRelaxation times from the full relaxation tensor") for i in range(1, ham.dim): for j in range(1, ham.dim): print(i, "<-", j, ":", 1.0 / numpy.real(RRT.data[i, i, j, j])) print("\nCalculating relaxation rates") RRM = qr.qm.RedfieldRateMatrix(ham, sbi) print("\nRelaxation times from the rate matrix") for i in range(1, ham.dim): for j in range(1, ham.dim): print(i, "<-", j, ":", 1.0 / RRM.data[i, j])
frac.diagonalize() # In[44]: frac.report_on_expansion(3) # In[45]: HH = frac.get_Hamiltonian() with qr.eigenbasis_of(HH): with qr.energy_units("1/cm"): print([HH.data[i,i] for i in range(1,frac.nmono)]) # In[46]: # # Get components of the fractional model # indices_of_components = [] names_of_components = ["PM", "PL", "BM", "BL","PCT1", "PCT2"] #["BM", "BL"] # "HL", "HM", "BL", , "BCT" names_of_components3 = ["PM", "PL", "BL"] components = [] for name in names_of_components3:
def test_Lindblad_dynamics_comp(self): """Compares Lindblad dynamics calculated from propagator and superoperator """ # Aggregate import quantarhei as qr import quantarhei.models.modelgenerator as mgen time = qr.TimeAxis(0.0, 1000, 1.0) # create a model mg = mgen.ModelGenerator() agg = mg.get_Aggregate(name="trimer-1") agg.build() ham = agg.get_Hamiltonian() # calculate relaxation tensor with qr.eigenbasis_of(ham): # # Operator describing relaxation # from quantarhei.qm import Operator K = Operator(dim=ham.dim,real=True) K.data[1,2] = 1.0 # # System bath interaction with prescribed rate # from quantarhei.qm import SystemBathInteraction sbi = SystemBathInteraction(sys_operators=[K], rates=(1.0/100.0,)) agg.set_SystemBathInteraction(sbi) # # Corresponding Lindblad form # from quantarhei.qm import LindbladForm LF = LindbladForm(ham, sbi, as_operators=False) # # Evolution of reduced density matrix # prop = qr.ReducedDensityMatrixPropagator(time, ham, LF) # # Evolution by superoperator # eSO = qr.qm.EvolutionSuperOperator(time, ham, LF) eSO.set_dense_dt(5) eSO.calculate() # compare the two propagations pairs = [(1,3), (3,2), (3,3)] for p in pairs: rho_i1 = qr.ReducedDensityMatrix(dim=ham.dim) rho_i1.data[p[0],p[1]] = 1.0 rho_t1 = prop.propagate(rho_i1) exp_rho_t2 = eSO.data[:,:,:,p[0],p[1]] #import matplotlib.pyplot as plt #plt.plot(rho_t1.TimeAxis.data, numpy.real(rho_t1.data[:,p[0],p[1]])) #plt.plot(rho_t1.TimeAxis.data, numpy.real(exp_rho_t2[:,p[0],p[1]])) #plt.show() #numpy.testing.assert_allclose(RRT.data, rtd) numpy.testing.assert_allclose(numpy.real(rho_t1.data[:,:,:]), numpy.real(exp_rho_t2[:,:,:]), rtol=1.0e-7, atol=1.0e-6)
def test_LindbladWithVibrations_dynamics_comp(self): """Compares Lindblad dynamics of a system with vibrations calculated from propagator and superoperator """ # Aggregate import quantarhei as qr time = qr.TimeAxis(0.0, 1000, 1.0) # create a model with qr.energy_units("1/cm"): me1 = qr.Molecule([0.0, 12100.0]) me2 = qr.Molecule([0.0, 12000.0]) me3 = qr.Molecule([0.0, 12900.0]) agg_el = qr.Aggregate([me1, me2, me3]) agg_el.set_resonance_coupling(0, 1, qr.convert(150, "1/cm", to="int")) agg_el.set_resonance_coupling(1, 2, qr.convert(50, "1/cm", to="int")) m1 = qr.Molecule([0.0, 12100.0]) m2 = qr.Molecule([0.0, 12000.0]) m3 = qr.Molecule([0.0, 12900.0]) mod1 = qr.Mode(frequency=qr.convert(100, "1/cm", "int")) m1.add_Mode(mod1) mod1.set_HR(1, 0.01) agg = qr.Aggregate([m1, m2, m3]) agg.set_resonance_coupling(0, 1, qr.convert(150, "1/cm", to="int")) agg.set_resonance_coupling(1, 2, qr.convert(50, "1/cm", to="int")) agg_el.build() agg.build() hame = agg_el.get_Hamiltonian() ham = agg.get_Hamiltonian() # calculate relaxation tensor with qr.eigenbasis_of(hame): # # Operator describing relaxation # K = qr.qm.ProjectionOperator(1, 2, dim=hame.dim) # # System bath interaction with prescribed rate # from quantarhei.qm import SystemBathInteraction sbi = SystemBathInteraction(sys_operators=[K], rates=(1.0/100.0,)) sbi.set_system(agg) #agg.set_SystemBathInteraction(sbi) with qr.eigenbasis_of(ham): # # Corresponding Lindblad form # from quantarhei.qm import ElectronicLindbladForm LF = ElectronicLindbladForm(ham, sbi, as_operators=True) # # Evolution of reduced density matrix # prop = qr.ReducedDensityMatrixPropagator(time, ham, LF) # # Evolution by superoperator # eSO = qr.qm.EvolutionSuperOperator(time, ham, LF) eSO.set_dense_dt(5) eSO.calculate() # compare the two propagations pairs = [(5,4), (5,5), (6,5), (7,5)] for p in pairs: rho_i1 = qr.ReducedDensityMatrix(dim=ham.dim) rho_i1.data[p[0],p[1]] = 1.0 rho_t1 = prop.propagate(rho_i1) exp_rho_t2 = eSO.data[:,:,:,p[0],p[1]] #import matplotlib.pyplot as plt #plt.plot(rho_t1.TimeAxis.data, numpy.real(rho_t1.data[:,p[0],p[1]]), "-r") #plt.plot(rho_t1.TimeAxis.data, numpy.real(exp_rho_t2[:,p[0],p[1]]), "--g") #plt.show() #for kk in range(rho_t1.TimeAxis.length): # print(kk, numpy.real(rho_t1.data[kk,p[0],p[1]]),numpy.real(exp_rho_t2[kk,p[0],p[1]])) #numpy.testing.assert_allclose(RRT.data, rtd) numpy.testing.assert_allclose(numpy.real(rho_t1.data[:,:,:]), numpy.real(exp_rho_t2[:,:,:]), rtol=5.0e-2, atol=1.0e-3)
def test_redfield_dynamics_comp(self): """Compares Redfield dynamics calculated from propagator and superoperator """ # Aggregate import quantarhei as qr import quantarhei.models.modelgenerator as mgen time = qr.TimeAxis(0.0, 1000, 1.0) # create a model mg = mgen.ModelGenerator() agg = mg.get_Aggregate_with_environment(name="trimer-1_env", timeaxis=time ) agg.build() sbi = agg.get_SystemBathInteraction() ham = agg.get_Hamiltonian() # calculate relaxation tensor ham.protect_basis() with qr.eigenbasis_of(ham): RRT = qr.qm.RedfieldRelaxationTensor(ham, sbi) RRT.secularize() ham.unprotect_basis() with qr.eigenbasis_of(ham): # # Evolution of reduced density matrix # prop = qr.ReducedDensityMatrixPropagator(time, ham, RRT) # # Evolution by superoperator # eSO = qr.qm.EvolutionSuperOperator(time, ham, RRT) eSO.set_dense_dt(5) eSO.calculate() # compare the two propagations pairs = [(1,3), (3,2), (3,3)] for p in pairs: rho_i1 = qr.ReducedDensityMatrix(dim=ham.dim) rho_i1.data[p[0],p[1]] = 1.0 rho_t1 = prop.propagate(rho_i1) exp_rho_t2 = eSO.data[:,:,:,p[0],p[1]] #import matplotlib.pyplot as plt #plt.plot(rho_t1.TimeAxis.data, numpy.real(rho_t1.data[:,p[0],p[1]])) #plt.plot(rho_t1.TimeAxis.data, numpy.real(exp_rho_t2[:,p[0],p[1]])) #plt.show() #numpy.testing.assert_allclose(RRT.data, rtd) numpy.testing.assert_allclose(numpy.real(rho_t1.data[:,:,:]), numpy.real(exp_rho_t2[:,:,:]), rtol=1.0e-7, atol=1.0e-6)
# This is where time evolution of the state vector is calculated # It is stored in psi_t which is of StateVectorEvolution type # psi_t = prop.propagate(psi_0) print( """We plot the time dependence of the state vector elements on the plots below: First we plot the squares of the absolute values of the state vector elements in the eigenstate basis of the Hamiltonian. In other words, we plot the probabilites of finding the system in its eigenstates. In the same plot, we plot the real parts of the same elements. """) with eigenbasis_of(H): psi_t.plot(ptype="square", show=False) psi_t.plot(ptype="real") pause("\nNext we plot the same in the original basis...") print(""" Then we plot the same thing but in the basis of states in which defined the values. """) psi_t.plot(ptype="square", show=False) psi_t.plot(ptype="real")
def redfield_tensor(self): print("Redfield tensor calculation") # # Correlation function # params = { "ftype": world.ctype, "reorg": world.reorg, "cortime": world.ctime, "T": world.temp, "matsubara": world.mats } # FIXME: also time_units, temperature_units with energy_units(world.e_units): cf = CorrelationFunction(world.ta, params) # # Homodimer # with energy_units(world.h_units): en = world.senergy m1 = Molecule("mol1", [0.0, en]) m2 = Molecule("mol2", [0.0, en]) m1.set_egcf((0, 1), cf) m2.set_egcf((0, 1), cf) agg = Aggregate("Homodimer") agg.add_Molecule(m1) agg.add_Molecule(m2) # m = Manager() ## # with energy_units("1/cm"): # Hm = m1.get_Hamiltonian() # print(Hm) # print(m.convert_energy_2_current_u(Hm._data)) with energy_units(world.r_units): agg.set_resonance_coupling(0, 1, world.r_coupl) agg.build() H = agg.get_Hamiltonian() world.HH = H ## # with energy_units("1/cm"): # print(H) # print(m.convert_energy_2_current_u(H._data)) sbi = agg.get_SystemBathInteraction() H.protect_basis() with eigenbasis_of(H): RRT = RedfieldRelaxationTensor(H, sbi) dim = H.dim rates_T = numpy.zeros(dim * dim) k = 0 world.K12 = numpy.real(RRT.data[1, 1, 2, 2]) for i in range(dim): for j in range(dim): rates_T[k] = numpy.real(RRT.data[i, i, j, j]) k += 1 world.rates_T = rates_T
def setUp(self,verbose=False): self.verbose = verbose # # Lindblad projection operators # K12 = numpy.array([[0.0, 1.0],[0.0, 0.0]],dtype=numpy.float) K21 = numpy.array([[0.0, 0.0],[1.0, 0.0]],dtype=numpy.float) KK12 = Operator(data=K12) KK21 = Operator(data=K21) self.KK12 = KK12 self.KK21 = KK21 # # Linbdlad rates # self.rates = (1.0/100.0, 1.0/200.0) # # System-bath interaction using operators and rates in site basis # self.sbi1 = SystemBathInteraction([KK12,KK21], rates=self.rates) self.sbi2 = SystemBathInteraction([KK12,KK21], rates=self.rates) # # Test Hamiltonians # with energy_units("1/cm"): h1 = [[100.0, 0.0],[0.0, 0.0]] h2 = [[100.0, 0.0],[0.0, 0.0]] self.H1 = Hamiltonian(data=h1) self.H2 = Hamiltonian(data=h2) h3 = [[100.0, 20.0],[20.0, 0.0]] self.H3 = Hamiltonian(data=h3) # less trivial Hamiltonian h4 = [[100.0, 200.0, 30.0 ], [200.0, 50.0, -100.0], [30.0, -100.0, 0.0 ]] self.H4 = Hamiltonian(data=h4) h4s = [[100.0, 0.0, 0.0 ], [0.0, 50.0, 0.0], [0.0, 0.0, 0.0 ]] self.H4s = Hamiltonian(data=h4s) # # Projection operators in eigenstate basis # with eigenbasis_of(self.H3): K_12 = ProjectionOperator(0, 1, dim=2) K_21 = ProjectionOperator(1, 0, dim=2) self.K_12 = K_12 self.K_21 = K_21 with eigenbasis_of(self.H4): Ke_12 = ProjectionOperator(0, 1, dim=3) Ke_21 = ProjectionOperator(1, 0, dim=3) Ke_23 = ProjectionOperator(1, 2, dim=3) Ke_32 = ProjectionOperator(2, 1, dim=3) Ks_12 = ProjectionOperator(0, 1, dim=3) Ks_21 = ProjectionOperator(1, 0, dim=3) Ks_23 = ProjectionOperator(1, 2, dim=3) Ks_32 = ProjectionOperator(2, 1, dim=3) self.rates4 = [1.0/100, 1.0/200, 1.0/150, 1.0/300] # # System-bath operators defined in exciton basis # self.sbi3 = SystemBathInteraction([K_12, K_21], rates=self.rates) self.sbi4e = SystemBathInteraction([Ke_12, Ke_21, Ke_23, Ke_32], rates=self.rates4) self.sbi4s = SystemBathInteraction([Ks_12, Ks_21, Ks_23, Ks_32], rates=self.rates4)
mol = agg_el.get_Molecule_by_name(mol_name) mol.set_transition_width((0, 1), width) print("Aggregate has ", agg_el.nmono, "single excited electronic states") agg_el.build(mult=1) HHe = agg_el.get_Hamiltonian() # # Here we define system-bath interaction operators for relaxation in both # the purely electronic and the electro-vibrational Hamiltonian # # kb_intK = qr.core.units.kB_intK e1_dim = agg_el.Nel with qr.eigenbasis_of(HHe): operators = [] rates = [] for trt in transfer_times: ff = trt[0][0] ii = trt[0][1] rt = 1.0 / trt[1] if ii > ff: operators.append(qr.qm.ProjectionOperator(ff, ii, dim=e1_dim)) rates.append(rt) else: raise Exception("Only downhill rates should" + " be specified explicitely") # thermal factor for the rates DeltE = HHe.data[ii, ii] - HHe.data[ff, ff]
# # Look at its various components # H = ag.get_Hamiltonian() print("Shape of the operators") print(H.data.shape) with energy_units("1/cm"): print(H) D = ag.get_TransitionDipoleMoment() with eigenbasis_of(H): with energy_units("1/cm"): print(H) print("\nTransition dipole moments") print(D.data[0,1,:]) print(D.data[0,2,:]) print(D.data[0,3,:]) SS = H.diagonalize() H.undiagonalize() print("\nHamiltonian in internal units") print(H) print("\nTransformation matrix")