def setUp(self,verbose=False): self.verbose = verbose # # PURE ELECTRONIC AGGREGATE # m1 = Molecule([0.0, 1.0]) m2 = Molecule([0.0, 1.0]) agg = Aggregate(molecules=[m1, m2]) agg.set_resonance_coupling(0,1, 0.1) agg.build() self.ham = agg.get_Hamiltonian() KK12 = ProjectionOperator(1, 2, dim=self.ham.dim) KK21 = ProjectionOperator(2, 1, dim=self.ham.dim) self.rates = (1.0/100.0, 1.0/200.0) self.sbi = SystemBathInteraction([KK12,KK21], rates=self.rates) self.sbi.set_system(agg) # # VIBRONIC AGGREGATE # vm1 = Molecule([0.0, 1.0]) vm2 = Molecule([0.0, 1.0]) mod1 = Mode(0.01) mod2 = Mode(0.01) vm1.add_Mode(mod1) vm2.add_Mode(mod2) mod1.set_nmax(0, 3) mod1.set_nmax(1, 3) mod2.set_nmax(0, 3) mod2.set_nmax(1, 3) vagg = Aggregate(molecules=[vm1, vm2]) vagg.set_resonance_coupling(0, 1, 0.1) vagg.build() self.vham = vagg.get_Hamiltonian() self.vsbi = SystemBathInteraction([KK12, KK21], rates=self.rates) self.vsbi.set_system(vagg)
def setUp(self): m1 = Molecule(name="Molecule 1", elenergies=[0.0, 1.0]) m2 = Molecule(name="Molecule 2", elenergies=[0.0, 1.0]) time = TimeAxis(0.0, 1000, 1.0) params = dict(ftype="OverdampedBrownian", reorg=20, cortime=100, T=300) with energy_units("1/cm"): fc = CorrelationFunction(time, params) m1.set_transition_environment((0,1), fc) m1.position = [0.0, 0.0, 0.0] m1.set_dipole(0,1,[10.0, 0.0, 0.0]) m2.set_transition_environment((0,1), fc) m2.position = [10.0, 0.0, 0.0] m2.set_dipole(0,1,[10.0, 0.0, 0.0]) self.agg = Aggregate(name="TestAgg", molecules=[m1,m2]) self.agg.set_coupling_by_dipole_dipole() self.agg.build() m3 = Molecule(name="Molecule 1", elenergies=[0.0, 1.0]) m4 = Molecule(name="Molecule 2", elenergies=[0.0, 1.0]) m3.add_Mode(Mode(0.01)) m4.add_Mode(Mode(0.01)) mod3 = m3.get_Mode(0) mod4 = m4.get_Mode(0) mod3.set_nmax(0, 4) mod3.set_nmax(1, 4) mod3.set_HR(1, 0.1) mod4.set_nmax(0, 4) mod4.set_nmax(1, 4) mod4.set_HR(1, 0.3) self.vagg = Aggregate(molecules=[m3, m4]) self.vagg.build()
# # ############################################################################### """) # # The same Hamiltonian using the Molecule class # from quantarhei import Molecule m = Molecule(name="Mol 1", elenergies=[0.0, 1.0]) m.set_adiabatic_coupling(0,1,0.4) from quantarhei import Mode vib1 = Mode(frequency=0.01) m.add_Mode(vib1) vib1.set_shift(1, 0.5) vib1.set_nmax(0, 5) vib1.set_nmax(1, 5) Hm = m.get_Hamiltonian() print(Hm) print(m) psi_vib = StateVector(10) psi_vib.data[3] = 1.0 prop_vib = StateVectorPropagator(time, Hm)
m = Molecule("RC-P",en) # Transition dipole moment from 0 -> 2 (exciton state) is set to # a unit vector in the direction of x-axis (this choice is arbitrary) di = numpy.sqrt(23.0)*0.20819434 m.set_dipole(0,2,[di,0.0,0.0]) # # To represent CT coordinate, we add an explicite harmonic mode # to the molecule. # # First the mode with frequency 10 1/cm is created qct = Mode(frequency=10.0) # and registered with the molecule m.add_Mode(qct) # In the CT state, the equilibrium coordinate is shifted towards # charge separation. In the ground state and the exciton, no shift # of the coordinate is assumed (see the text (!!!!) for justification.) qct.set_shift(1,1.0) # By default, the Mode we created is harmonic. The number of states # by which it is represented is set to 2 (which is a very small number). # Let us increase the number of states to represent the oscillators # in the three electronic states of the molecule to some chosen N[0], N[1] # and N[2] (see the text (!!!!) for the choice of values). # # we create an array of 3 zeros N = numpy.zeros(3,dtype=numpy.int) # set all of them to the value of 10
def test_saving_of_molecule(self): """Testing the saving capability of the Molecule class """ use_temporary_file = True with energy_units("1/cm"): mod = Mode(frequency=150) mod1 = Mode(frequency=100) m2 = Molecule(elenergies=[0.0, 2.0]) m2.add_Mode(mod) m2.add_Mode(mod1) if use_temporary_file: #drv = "core" #bcs = False #with h5py.File('tempfile.hdf5', # driver=drv, # backing_store=bcs) as f: with tempfile.TemporaryFile() as f: #self.m.save_as(f,"Molecule") self.m.save(f, test=True) # reread it m = Molecule() #m.load_as(f,"Molecule") m = m.load(f, test=True) else: #with h5py.File('tempfile.hdf5') as f: with open('tempfile.qrp', 'wb') as f: #self.m.save_as(f,"Molecules") self.m.save(f) #with h5py.File('tempfile.hdf5') as f: with open('tempfile.qrp', 'rb') as f: m = Molecule() #m.load_as(f,"Molecules") m = m.load(f) self.assertEqual(self.m.name, m.name) self.assertEqual(self.m.nel, m.nel) numpy.testing.assert_array_equal(self.m.elenergies, m.elenergies) numpy.testing.assert_array_equal( self.m.get_transition_environment((0, 1)).data, self.fc.data) #with h5py.File('tempfile.hdf5', # driver=drv, # backing_store=bcs) as f: with tempfile.TemporaryFile() as f: #self.m.save_as(f,"Molecule") m2.save(f, test=True) # reread it m3 = Molecule() #m.load_as(f,"Molecule") m3 = m3.load(f, test=True) self.assertEqual(m2.name, m3.name) self.assertEqual(m2.nel, m3.nel) numpy.testing.assert_array_equal(m2.elenergies, m3.elenergies) self.assertEqual(m2.get_Mode(0).get_energy(0), mod.get_energy(0)) self.assertEqual(m2.get_Mode(1).get_energy(0), mod1.get_energy(0))
class TestMoleculeVibrations(unittest.TestCase): def setUp(self): en = [0.0, 1.0] self.m = Molecule(name="Molecule", elenergies=en) mod1 = Mode(frequency=0.1) self.m.add_Mode(mod1) mod1.set_nmax(0, 3) mod1.set_nmax(1, 3) en2 = [0.0, 0.1, 0.1] self.m2 = Molecule(name="AdMolecule", elenergies=en2) self.m2.set_adiabatic_coupling(1, 2, 0.02) mod2 = Mode(frequency=0.01) self.m2.add_Mode(mod2) mod2.set_nmax(0, 3) mod2.set_nmax(1, 3) mod2.set_nmax(2, 3) def test_molecule_with_vibrations_1(self): """Testing hamiltonian of a two-level molecule with one mode """ H1 = self.m.get_Hamiltonian() H1expected = numpy.diag([0.0, 0.1, 0.2, 1.0, 1.1, 1.2]) self.assertTrue(numpy.allclose(H1expected, H1.data)) mod1 = self.m.get_Mode(0) mod1.set_nmax(1, 2) H2 = self.m.get_Hamiltonian() H2expected = numpy.diag([0.0, 0.1, 0.2, 1.0, 1.1]) self.assertTrue(numpy.allclose(H2expected, H2.data)) def test_thermal_density_matrix_0_temp(self): """Thermal density matrix: molecule with one mode, zero temperature """ rho_eq = self.m.get_thermal_ReducedDensityMatrix() # Check if the matrix is diagonal dat = rho_eq.data.copy() for i in range(dat.shape[0]): dat[i, i] = 0.0 zer = numpy.zeros(dat.shape, dtype=numpy.float) self.assertTrue(numpy.allclose(dat, zer)) # Check if diagonal is a thermal population pop = numpy.zeros(dat.shape[0]) # get temperature from the molecule T = self.m.get_temperature() self.assertEquals(T, 0.0) # get density matrix rho = self.m.get_thermal_ReducedDensityMatrix() rpop = rho.get_populations() if numpy.abs(T) < 1.0e-10: pop[0] = 1.0 else: # thermal populations pass self.assertTrue(numpy.allclose(pop, rpop)) def test_thermal_density_matrix_finite_temp(self): """Thermal density matrix: molecule with one mode, finite temperature """ timeAxis = TimeAxis(0.0, 1000, 1.0) params = { "ftype": "OverdampedBrownian", "T": 300, "reorg": 30, "cortime": 100 } with energy_units("1/cm"): cfcion = CorrelationFunction(timeAxis, params) self.m.set_egcf((0, 1), cfcion) rho_eq = self.m.get_thermal_ReducedDensityMatrix() # Check if the matrix is diagonal dat = rho_eq.data.copy() for i in range(dat.shape[0]): dat[i, i] = 0.0 zer = numpy.zeros(dat.shape, dtype=numpy.float) self.assertTrue(numpy.allclose(dat, zer)) # Check if diagonal is a thermal population pop = numpy.zeros(dat.shape[0]) # get temperature from the molecule T = self.m.get_temperature() self.assertTrue(T == 300.0) # get density matrix rpop = rho_eq.get_populations() # get Hamiltonian H = self.m.get_Hamiltonian() 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 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))
# VIBRONIC Aggregate of two molecules # m1v = Molecule([0.0, 1.0]) m2v = Molecule([0.0, 1.1]) m3v = Molecule([0.0, 1.2]) from quantarhei import Mode mod1 = Mode(0.01) mod2 = Mode(0.01) mod3 = Mode(0.01) Nvib = 2 m1v.add_Mode(mod1) mod1.set_nmax(0, Nvib) mod1.set_nmax(1, Nvib) mod1.set_HR(1, 0.3) m2v.add_Mode(mod2) mod2.set_nmax(0, Nvib) mod2.set_nmax(1, Nvib) mod2.set_HR(1, 0.3) m3v.add_Mode(mod3) mod3.set_nmax(0, Nvib) mod3.set_nmax(1, Nvib) mod3.set_HR(1, 0.3) vagg = Aggregate(molecules=[m1v, m2v, m3v])
def test_saving_of_molecule(self): """Testing the saving capability of the Molecule class """ use_temporary_file = True with energy_units("1/cm"): mod = Mode(frequency=150) mod1 = Mode(frequency=100) m2 = Molecule(elenergies=[0.0, 2.0]) m2.add_Mode(mod) m2.add_Mode(mod1) if use_temporary_file: #drv = "core" #bcs = False #with h5py.File('tempfile.hdf5', # driver=drv, # backing_store=bcs) as f: with tempfile.TemporaryFile() as f: #self.m.save_as(f,"Molecule") self.m.save(f, test=True) # reread it m = Molecule() #m.load_as(f,"Molecule") m = m.load(f, test=True) else: #with h5py.File('tempfile.hdf5') as f: with open('tempfile.qrp', 'wb') as f: #self.m.save_as(f,"Molecules") self.m.save(f) #with h5py.File('tempfile.hdf5') as f: with open('tempfile.qrp', 'rb') as f: m = Molecule() #m.load_as(f,"Molecules") m = m.load(f) self.assertEqual(self.m.name, m.name) self.assertEqual(self.m.nel, m.nel) numpy.testing.assert_array_equal(self.m.elenergies, m.elenergies) numpy.testing.assert_array_equal( self.m.get_transition_environment((0,1)).data, self.fc.data) #with h5py.File('tempfile.hdf5', # driver=drv, # backing_store=bcs) as f: with tempfile.TemporaryFile() as f: #self.m.save_as(f,"Molecule") m2.save(f, test=True) # reread it m3 = Molecule() #m.load_as(f,"Molecule") m3 = m3.load(f, test=True) self.assertEqual(m2.name, m3.name) self.assertEqual(m2.nel, m3.nel) numpy.testing.assert_array_equal(m2.elenergies, m3.elenergies) self.assertEqual(m2.get_Mode(0).get_energy(0), mod.get_energy(0)) self.assertEqual(m2.get_Mode(1).get_energy(0), mod1.get_energy(0))
class TestMoleculeVibrations(unittest.TestCase): def setUp(self): en = [0.0, 1.0] self.m = Molecule(name="Molecule",elenergies=en) mod1 = Mode(frequency=0.1) self.m.add_Mode(mod1) mod1.set_nmax(0,3) mod1.set_nmax(1,3) en2 = [0.0,0.1,0.1] self.m2 = Molecule(name="AdMolecule",elenergies=en2) self.m2.set_adiabatic_coupling(1,2,0.02) mod2 = Mode(frequency=0.01) self.m2.add_Mode(mod2) mod2.set_nmax(0,3) mod2.set_nmax(1,3) mod2.set_nmax(2,3) def test_molecule_with_vibrations_1(self): """Testing hamiltonian of a two-level molecule with one mode """ H1 = self.m.get_Hamiltonian() H1expected = numpy.diag([0.0, 0.1, 0.2, 1.0, 1.1, 1.2]) self.assertTrue(numpy.allclose(H1expected,H1.data)) mod1 = self.m.get_Mode(0) mod1.set_nmax(1,2) H2 = self.m.get_Hamiltonian() H2expected = numpy.diag([0.0, 0.1, 0.2, 1.0, 1.1]) self.assertTrue(numpy.allclose(H2expected,H2.data)) def test_thermal_density_matrix_0_temp(self): """Thermal density matrix: molecule with one mode, zero temperature """ rho_eq = self.m.get_thermal_ReducedDensityMatrix() # Check if the matrix is diagonal dat = rho_eq.data.copy() for i in range(dat.shape[0]): dat[i,i] = 0.0 zer = numpy.zeros(dat.shape,dtype=numpy.float) self.assertTrue(numpy.allclose(dat,zer)) # Check if diagonal is a thermal population pop = numpy.zeros(dat.shape[0]) # get temperature from the molecule T = self.m.get_temperature() self.assertEquals(T,0.0) # get density matrix rho = self.m.get_thermal_ReducedDensityMatrix() rpop = rho.get_populations() if numpy.abs(T) < 1.0e-10: pop[0] = 1.0 else: # thermal populations pass self.assertTrue(numpy.allclose(pop,rpop)) def test_thermal_density_matrix_finite_temp(self): """Thermal density matrix: molecule with one mode, finite temperature """ timeAxis = TimeAxis(0.0,1000,1.0) params = {"ftype":"OverdampedBrownian", "T":300, "reorg":30, "cortime":100} with energy_units("1/cm"): cfcion = CorrelationFunction(timeAxis,params) self.m.set_egcf((0,1),cfcion) rho_eq = self.m.get_thermal_ReducedDensityMatrix() # Check if the matrix is diagonal dat = rho_eq.data.copy() for i in range(dat.shape[0]): dat[i,i] = 0.0 zer = numpy.zeros(dat.shape,dtype=numpy.float) self.assertTrue(numpy.allclose(dat,zer)) # Check if diagonal is a thermal population pop = numpy.zeros(dat.shape[0]) # get temperature from the molecule T = self.m.get_temperature() self.assertTrue(T==300.0) # get density matrix rpop = rho_eq.get_populations() # get Hamiltonian H = self.m.get_Hamiltonian() 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 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))