Example #1
0
time_axis = qr.TimeAxis(0.0, propagation_N_steps, propagation_dt)

agg_el.diagonalize()

#
#  Absorption Spectrum calculated by the pathway method
#

# initial conditions before excitation
rho0 = agg_el.get_DensityMatrix(condition_type="thermal", temperature=0.0)
# electronic Hamiltonian
ham = agg_el.get_Hamiltonian()
# first order Liouville pathways
pthways = agg_el.liouville_pathways_1(lab=lab, ham=ham, etol=1.0e-5, verbose=0)
# absorption spectrum calculator
mac = qr.MockAbsSpectrumCalculator(time_axis, system=agg_el)
mac.bootstrap(rwa=qr.convert(12200.0, "1/cm", "int"), shape="Gaussian")
mac.set_pathways(pthways)

# here we calculate the spectrum
abs1 = mac.calculate()
abs1.normalize2(norm=0.53)

#
# Absorption by standard method
#
try:
    abscalc = qr.load_parcel("../model/in/calcAbs.qrp")
except:
    pass
#
Example #2
0
m4.set_transition_dephasing((0, 1), 1.0 / 200.0)

#
# Create the aggregate of the two molecules
#
agg2 = qr.Aggregate(molecules=[m3, m4])

#
# Build the aggregate
#
agg2.build()

#
#  Absorption Spectrum by pathway method
#
mac = qr.MockAbsSpectrumCalculator(time, system=agg2)
mac.bootstrap(rwa=qr.convert(10000.0, "1/cm", "int"),
              shape="Gaussian",
              lab=lab)

abs1 = mac.calculate(raw=False)
abs1.normalize2()

#
# Plot the absorption spectrum
#
with qr.energy_units("1/cm"):
    abs1.plot(axis=[9000, 12000, 0.0, 1.01], color="r", show=False)

mac.bootstrap(rwa=qr.convert(10000.0, "1/cm", "int"), shape="Voigt", lab=lab)
abs2 = mac.calculate()
Example #3
0
def run(omega,
        HR,
        dE,
        JJ,
        rate,
        E0,
        vib_loc="up",
        use_vib=True,
        detailed_balance=False,
        temperature=77.0,
        stype=qr.signal_REPH,
        save_eUt=False,
        t2_save_pathways=[],
        dname=None,
        trimer=None,
        disE=None):
    """Runs a complete set of simulations for a single set of parameters


    If disE is not None it tries to run averaging over Gaussian energetic
    disorder.

    """
    if dname is None:
        dname = "sim_" + vib_loc

    use_trimer = trimer["useit"]
    rate_sp = trimer["rate"]

    #
    #  PARAMETERS FROM INPUT FILE
    #
    dip1 = INP.dip1  # [1.5, 0.0, 0.0]
    dip2 = INP.dip2  # [-1.0, -1.0, 0.0]
    width = INP.feature_width  # 100.0
    width2 = INP.feature_width2

    normalize_maps_to_maximu = False
    trim_maps = False

    units = "1/cm"
    with qr.energy_units(units):

        data_descr = "_dO="+str(dE)+"_omega="+str(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"

    # parameters of the SP
    if use_trimer:
        E2 = trimer["E2"]
        epsa = (E0 + E2) / 2.0
        DE = trimer["DE"]
        J2 = 0.5 * numpy.sqrt(((E0 - E2)**2) - (DE**2))
        ESP2 = epsa + DE / 2.0
        ESP1 = epsa - DE / 2.0

    #
    #   Model system is a dimer of molecules
    #
    with qr.energy_units("1/cm"):

        if not use_trimer:

            if disE is not None:
                mol1 = qr.Molecule([0.0, E0 + disE[0]])
                mol2 = qr.Molecule([0.0, E0 + dE + disE[1]])
                print("Monomer 1 energy:", E0 + disE[0], "1/cm")
                print("Monomer 2 energy:", E0 + dE + disE[1], "1/cm")
            else:
                mol1 = qr.Molecule([0.0, E0])
                mol2 = qr.Molecule([0.0, E0 + dE])
                print("Monomer 1 energy:", E0, "1/cm")
                print("Monomer 2 energy:", E0 + dE, "1/cm")
        else:

            if disE is not None:
                mol1 = qr.Molecule([0.0, ESP2 + disE[0]])
                mol2 = qr.Molecule([0.0, E0 + dE + disE[1]])
                print("Monomer 1 (SP_high) energy:", ESP2 + disE[0], "1/cm")
                print("Monomer 2 (B) energy:", E0 + dE + disE[1], "1/cm")
            else:
                mol1 = qr.Molecule([0.0, ESP2])
                mol2 = qr.Molecule([0.0, E0 + dE])
                print("Monomer 1 (SP_high) energy:", ESP2, "1/cm")
                print("Monomer 2 (B) energy:", E0 + dE, "1/cm")
            if disE is not None:
                mol3 = qr.Molecule([0.0, ESP1 + disE[2]])
                print("Monomer 3 (SP_low) energy:", ESP1 + disE[2], "1/cm")
            else:
                mol3 = qr.Molecule([0.0, ESP1])
                print("Monomer 3 (SP_low) energy:", ESP1, "1/cm")
            mol3.set_transition_width((0, 1), width2)
            mol3.set_dipole(0, 1, trimer["dipsp"])

        mol1.set_transition_width((0, 1), width2)
        mol1.set_dipole(0, 1, dip1)

        mol2.set_transition_width((0, 1), width)
        mol2.set_dipole(0, 1, dip2)

    if use_trimer:
        agg = qr.Aggregate([mol1, mol2, mol3])
    else:
        agg = qr.Aggregate([mol1, mol2])

    if use_trimer:

        with qr.energy_units("1/cm"):
            agg.set_resonance_coupling(0, 1, JJ)
            print("B - SP_high coupling:", JJ, "1/cm")
            agg.set_resonance_coupling(0, 2, J2)
            print("SP coupling:", J2, "1/cm")

    else:

        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:

        with qr.energy_units("1/cm"):
            mod1 = qr.Mode(omega)
            mod2 = qr.Mode(omega)

        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]:
            print("Vibrations set for SP_high molecule")
            mol1.add_Mode(mod1)
            mod1.set_nmax(0, INP.vibmode["no_g_vib"])
            mod1.set_nmax(1, INP.vibmode["no_e_vib"])
            mod1.set_HR(1, HR)

        if set_vib[1]:
            print("Vibrations set for B molecule")
            mol2.add_Mode(mod2)
            mod2.set_nmax(0, INP.vibmode["no_g_vib"])
            mod2.set_nmax(1, INP.vibmode["no_e_vib"])
            mod2.set_HR(1, HR)

    #
    # Before we build the aggregate, we make its copy to have an unbuilt version
    #
    agg3 = agg.deepcopy()
    aggA = agg.deepcopy()

    #
    # here we build the complete aggregate and its electronic only version
    #
    agg.build(mult=1)
    agg_el.build(mult=1)
    aggA.build(mult=1)

    # total Hamiltonian
    HH = agg.get_Hamiltonian()
    # electronic Hamiltonian
    He = agg_el.get_Hamiltonian()

    #
    # Laboratory setup
    #
    lab = qr.LabSetup()
    lab.set_polarizations(pulse_polarizations=[X, X, X],
                          detection_polarization=X)

    #
    # Time axis for the calculation of excited state evolution
    #
    t2_N_steps = INP.t2_N_steps
    t2_time_step = INP.t2_time_step
    time2 = qr.TimeAxis(0.0, t2_N_steps, t2_time_step)

    #
    # Containers for 2D maps with positive and negative frequencies
    #
    cont_p = qr.TwoDResponseContainer(t2axis=time2)
    cont_m = qr.TwoDResponseContainer(t2axis=time2)
    cont_tot = qr.TwoDResponseContainer(t2axis=time2)

    #
    # spectra will be indexed by the times in the time axis `time2`
    #
    cont_p.use_indexing_type(time2)
    cont_m.use_indexing_type(time2)
    cont_tot.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 = INP.t1_N_steps
    t1_time_step = INP.t1_time_step
    t3_N_steps = INP.t3_N_steps
    t3_time_step = INP.t3_time_step
    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 = []

    print("Relaxation rates: ", rate, rate_sp, "1/fs")

    with qr.eigenbasis_of(He):

        if use_trimer:
            if He.data[3, 3] < He.data[2, 2]:
                Exception("Electronic states not orderred!")
            operators.append(qr.qm.ProjectionOperator(2, 3, dim=He.dim))
            with qr.energy_units("1/cm"):
                print("2 <- 3 : energies = ", He.data[2, 2], He.data[3, 3],
                      "1/cm")
            rates.append(rate)
            print("Transfer time 2 <- 3:", 1.0 / rate, "fs")

            if He.data[2, 2] < He.data[1, 1]:
                Exception("Electronic states not orderred!")
            operators.append(qr.qm.ProjectionOperator(1, 2, dim=He.dim))
            with qr.energy_units("1/cm"):
                print("1 <- 2 : energies = ", He.data[1, 1], He.data[2, 2],
                      "1/cm")
            rates.append(rate_sp)
            print("Transfer time 1 <- 2", 1.0 / rate_sp, "fs")

        else:

            if He.data[2, 2] < He.data[1, 1]:
                Exception("Electronic states not orderred!")
            operators.append(qr.qm.ProjectionOperator(1, 2, dim=He.dim))
            with qr.energy_units("1/cm"):
                print("1 <- 2 : energies = ", He.data[1, 1], He.data[2, 2],
                      "1/cm")
            rates.append(rate_sp)
            print("Transfer time 1 <- 2", 1.0 / rate, "fs")

    # include detailed balace
    if detailed_balance:
        if use_trimer:
            with qr.eigenbasis_of(He):
                T = temperature  #77.0
                Den = (He.data[3, 3] - He.data[2, 2]) / (kB_int * T)
                operators.append(qr.qm.ProjectionOperator(3, 2, dim=He.dim))
                thermal_fac = numpy.exp(-Den)
                rates.append(rate * thermal_fac)
                Den = (He.data[2, 2] - He.data[1, 1]) / (kB_int * T)
                operators.append(qr.qm.ProjectionOperator(2, 1, dim=He.dim))
                thermal_fac = numpy.exp(-Den)
                rates.append(rate_sp * thermal_fac)

        else:

            with qr.eigenbasis_of(He):
                T = temperature  #77.0
                Den = (He.data[2, 2] - He.data[1, 1]) / (kB_int * T)
                operators.append(qr.qm.ProjectionOperator(2, 1, dim=He.dim))
                thermal_fac = numpy.exp(-Den)
            rates.append(rate * thermal_fac)

    sbi = qr.qm.SystemBathInteraction(sys_operators=operators, rates=rates)
    sbi.set_system(agg)

    #
    # Lindblad form for relaxation
    #
    LF = qr.qm.ElectronicLindbladForm(HH, sbi, as_operators=True)

    #
    # Pure dephasing
    #
    p_deph = qr.qm.ElectronicPureDephasing(agg, dtype="Gaussian")

    # we simplify calculations by converting dephasing to
    # corresponding Lorentzian form
    p_deph.convert_to("Lorentzian")

    eUt = qr.qm.EvolutionSuperOperator(time2,
                                       HH,
                                       relt=LF,
                                       pdeph=p_deph,
                                       mode="all")
    eUt.set_dense_dt(INP.fine_splitting)

    print("---")

    #
    # We calculate evolution superoperator
    #
    eUt.calculate(show_progress=False)

    # save the evolution operator
    if save_eUt:
        eut_name = os.path.join(
            dname, "eUt" + "_omega2=" + str(omega) + data_descr + obj_ext)
        eUt.save(eut_name)

    #
    # Prepare aggregate with all states (including 2-EX band)
    #
    agg3.build(mult=2)
    agg3.diagonalize()

    agg_el.diagonalize()
    print("")
    print("Square of the transition dipoles")
    print(agg_el.D2)
    print("")
    print("---")

    #
    # calculation of absorption spectrum
    #
    time1 = qr.TimeAxis(0.0, 1000, 5.0)
    absc = qr.MockAbsSpectrumCalculator(time1, system=aggA)
    with qr.energy_units("1/cm"):
        absc.bootstrap(rwa=E0)

    spctrm = absc.calculate()
    spctrm.normalize2()

    with qr.energy_units("1/cm"):
        spctrm.plot(show=False, axis=[10500.0, 13500.0, 0.0, 1.1])
        spctrm.savefig(os.path.join(dname, "abs.png"))
        spctrm.save_data(os.path.join(dname, "abs.dat"))

    pways = dict()

    olow_cm = omega - INP.omega_uncertainty / 2.0
    ohigh_cm = omega + INP.omega_uncertainty / 2.0
    olow = qr.convert(olow_cm, "1/cm", "int")
    ohigh = qr.convert(ohigh_cm, "1/cm", "int")

    for t2 in time2.data:

        # this could save some memory of pathways become too big
        pways = dict()

        print("T2 =", t2, "fs (of T2_max =", time2.max, "fs)")

        twod = msc.calculate_one_system(t2,
                                        agg3,
                                        eUt,
                                        lab,
                                        pways=pways,
                                        dtol=1.0e-12,
                                        selection=[["omega2", [olow, ohigh]]])
        pws = pways[str(t2)]
        npa = len(pws)
        has_R = False
        has_NR = False
        for pw in pws:
            if pw.pathway_type == "NR":
                has_NR = True
            elif pw.pathway_type == "R":
                has_R = True

        if t2 in t2_save_pathways:
            pws_name = os.path.join(
                dname, "pws_t2=" + str(t2) + "_omega2=" + str(omega) +
                data_descr + obj_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,
                                        dtol=1.0e-12,
                                        selection=[["omega2", [-ohigh,
                                                               -olow]]])

        pws = pways[str(t2)]
        npa = len(pws)
        #print(" m:", npa)
        has_R = False
        has_NR = False
        for pw in pws:
            if pw.pathway_type == "NR":
                has_NR = True
            elif pw.pathway_type == "R":
                has_R = True

        #print(" R:", has_R, ", NR:", has_NR)

        if t2 in t2_save_pathways:
            pws_name = os.path.join(
                dname, "pws_t2=" + str(t2) + "_omega2=" + str(-omega) +
                data_descr + obj_ext)
            qr.save_parcel(pways[str(t2)], pws_name)

        cont_m.set_spectrum(twod)

        # calculation without pre-selecting pathways
        twod = msc.calculate_one_system(t2,
                                        agg3,
                                        eUt,
                                        lab,
                                        pways=pways,
                                        dtol=1.0e-12)

        cont_tot.set_spectrum(twod)

    # saving total spectrum to a directory for further analysis
    try:
        saveit = INP.total_spectrum["save_it"]
    except:
        saveit = False

    if saveit:
        try:
            dform = INP.total_spectrum["data_format"]
        except:
            dform = "dat"
        try:
            stp = INP.total_spectrum["spectra_type"]
            if stp == "TOTL":
                stype = qr.signal_TOTL
            elif stp == "REPH":
                stype = qr.signal_REPH
            elif stp == "NONR":
                stype = qr.signal_NONR
            else:
                raise Exception("Wrong signal type")
        except:
            stype = qr.signal_REPH

        save_spectra(cont_tot, ext=dform, dir=dname, stype=stype)

    #
    # Save aggregate when a single calculation is done
    #
    if save_eUt:
        fname = os.path.join(dname, "aggregate.qrp")
        agg3.save(fname)

    #
    # Window function for subsequenty FFT
    #
    window = func.Tukey(time2, r=INP.tukey_window_r, sym=False)

    #
    # FFT with the window function
    #
    # Specify REPH, NONR or `total` to get different types of spectra
    #
    print("Calculating 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 = INP.trim_maps_to
        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

    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)

    sstm = platform.system()
    #print(sstm)
    if sstm != "Windows":
        import resource
        memo = resource.getrusage(
            resource.RUSAGE_SELF).ru_maxrss / (1024 * 1024)
        print("Memory usage: ", memo, "in MB")

    return (sp1_p_re, sp1_p_nr, sp2_m_re, sp2_m_nr)
Example #4
0
# setting system bath interaction to provide lineshape
with qr.energy_units("1/cm"):
    mol.set_transition_width((0, 1), width)

# building aggregate
agg.build()
HH = agg.get_Hamiltonian()

# check the aggregate
print(agg)

#
# calculation of absorption spectrum
#
time1 = qr.TimeAxis(0.0, 1000, 5.0)
absc = qr.MockAbsSpectrumCalculator(time1, system=agg)
with qr.energy_units("1/cm"):
    absc.bootstrap(rwa=E0)

spctrm = absc.calculate()
spctrm.normalize2()

with qr.energy_units("1/cm"):
    spctrm.plot(show=False, axis=[9000.0, 13000.0, 0.0, 1.1])
    spctrm.savefig("abs.png")

#
# calculation of 2D spectrum
#
time2 = qr.TimeAxis(0.0, 10, 10.0)
time3 = qr.TimeAxis(0.0, time1.length, time1.step)
Example #5
0
# absorption from effective theory
from quantarhei import LabSetup
from quantarhei.utils.vectors import X, Y, Z

lab = LabSetup()
lab.set_polarizations(pulse_polarizations=[X, X, X], detection_polarization=X)

agg_eff.diagonalize()

print("\nEffetive model exciation energies:")
print("Energies in 1/cm:")
N1 = agg_eff.nmono
print([qr.convert(agg_eff.HH[i, i], "int", "1/cm") for i in range(1, N1 + 1)])
print("")

mabsc = qr.MockAbsSpectrumCalculator(time, system=agg_eff)
rho0 = agg_eff.get_DensityMatrix(condition_type="thermal", temperature=0.0)
ham = agg_eff.get_Hamiltonian()

pthways = agg_eff.liouville_pathways_1(lab=lab,
                                       ham=ham,
                                       etol=1.0e-5,
                                       verbose=0)

mabsc.bootstrap(rwa=qr.convert(10000.0, "1/cm", "int"), shape="Gaussian")

mabsc.set_pathways(pthways)

abs1 = mabsc.calculate(raw=False)
abs1.normalize2()