Beispiel #1
0
def _mesolve_list_str_td(H_list, rho0, tlist, c_list, e_ops, args, opt,
                         progress_bar):
    """
    Internal function for solving the master equation. See mesolve for usage.
    """

    if debug:
        print(inspect.stack()[0][3])

    #
    # check initial state: must be a density matrix
    #
    if isket(rho0):
        rho0 = rho0 * rho0.dag()

    #
    # construct liouvillian
    #
    Lconst = 0

    Ldata = []
    Linds = []
    Lptrs = []
    Lcoeff = []

    # loop over all hamiltonian terms, convert to superoperator form and
    # add the data of sparse matrix representation to
    for h_spec in H_list:

        if isinstance(h_spec, Qobj):
            h = h_spec

            if isoper(h):
                Lconst += -1j * (spre(h) - spost(h))
            elif issuper(h):
                Lconst += h
            else:
                raise TypeError("Incorrect specification of time-dependent " +
                                "Hamiltonian (expected operator or " +
                                "superoperator)")

        elif isinstance(h_spec, list):
            h = h_spec[0]
            h_coeff = h_spec[1]

            if isoper(h):
                L = -1j * (spre(h) - spost(h))
            elif issuper(h):
                L = h
            else:
                raise TypeError("Incorrect specification of time-dependent " +
                                "Hamiltonian (expected operator or " +
                                "superoperator)")

            Ldata.append(L.data.data)
            Linds.append(L.data.indices)
            Lptrs.append(L.data.indptr)
            Lcoeff.append(h_coeff)

        else:
            raise TypeError("Incorrect specification of time-dependent " +
                            "Hamiltonian (expected string format)")

    # loop over all collapse operators
    for c_spec in c_list:

        if isinstance(c_spec, Qobj):
            c = c_spec

            if isoper(c):
                cdc = c.dag() * c
                Lconst += spre(c) * spost(c.dag()) - 0.5 * spre(cdc) \
                                                   - 0.5 * spost(cdc)
            elif issuper(c):
                Lconst += c
            else:
                raise TypeError("Incorrect specification of time-dependent " +
                                "Liouvillian (expected operator or " +
                                "superoperator)")

        elif isinstance(c_spec, list):
            c = c_spec[0]
            c_coeff = c_spec[1]

            if isoper(c):
                cdc = c.dag() * c
                L = spre(c) * spost(c.dag()) - 0.5 * spre(cdc) \
                                             - 0.5 * spost(cdc)
                c_coeff = "(" + c_coeff + ")**2"
            elif issuper(c):
                L = c
            else:
                raise TypeError("Incorrect specification of time-dependent " +
                                "Liouvillian (expected operator or " +
                                "superoperator)")

            Ldata.append(L.data.data)
            Linds.append(L.data.indices)
            Lptrs.append(L.data.indptr)
            Lcoeff.append(c_coeff)

        else:
            raise TypeError("Incorrect specification of time-dependent " +
                            "collapse operators (expected string format)")

    # add the constant part of the lagrangian
    if Lconst != 0:
        Ldata.append(Lconst.data.data)
        Linds.append(Lconst.data.indices)
        Lptrs.append(Lconst.data.indptr)
        Lcoeff.append("1.0")

    # the total number of liouvillian terms (hamiltonian terms +
    # collapse operators)
    n_L_terms = len(Ldata)

    #
    # setup ode args string: we expand the list Ldata, Linds and Lptrs into
    # and explicit list of parameters
    #
    string_list = []
    for k in range(n_L_terms):
        string_list.append("Ldata[%d], Linds[%d], Lptrs[%d]" % (k, k, k))
    for name, value in args.items():
        string_list.append(str(value))
    parameter_string = ",".join(string_list)

    #
    # generate and compile new cython code if necessary
    #
    if not opt.rhs_reuse or odeconfig.tdfunc is None:
        if opt.rhs_filename is None:
            odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)
        else:
            odeconfig.tdname = opt.rhs_filename
        cgen = Codegen(h_terms=n_L_terms,
                       h_tdterms=Lcoeff,
                       args=args,
                       odeconfig=odeconfig)
        cgen.generate(odeconfig.tdname + ".pyx")

        code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                       '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc = cyq_td_ode_rhs

    #
    # setup integrator
    #
    initial_vector = mat2vec(rho0.full()).ravel()
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator('zvode',
                     method=opt.method,
                     order=opt.order,
                     atol=opt.atol,
                     rtol=opt.rtol,
                     nsteps=opt.nsteps,
                     first_step=opt.first_step,
                     min_step=opt.min_step,
                     max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params(' + parameter_string + ')', '<string>',
                   'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return _generic_ode_solve(r, rho0, tlist, e_ops, opt, progress_bar)
Beispiel #2
0
def _mesolve_list_td(H_func, rho0, tlist, c_op_list, e_ops, args, opt,
                     progress_bar):
    """!
    Evolve the density matrix using an ODE solver with time dependent
    Hamiltonian.
    """

    if debug:
        print(inspect.stack()[0][3])

    #
    # check initial state
    #
    if isket(rho0):
        # if initial state is a ket and no collapse operator where given,
        # fall back on the unitary schrodinger equation solver
        if len(c_op_list) == 0:
            return _sesolve_list_td(H_func, rho0, tlist, e_ops, args, opt)

        # Got a wave function as initial state: convert to density matrix.
        rho0 = ket2dm(rho0)

    #
    # construct liouvillian
    #
    if len(H_func) != 2:
        raise TypeError('Time-dependent Hamiltonian list must have two terms.')
    if not isinstance(H_func[0], (list, np.ndarray)) or len(H_func[0]) <= 1:
        raise TypeError('Time-dependent Hamiltonians must be a list ' +
                        'with two or more terms')
    if (not isinstance(H_func[1], (list, np.ndarray))) or \
       (len(H_func[1]) != (len(H_func[0]) - 1)):
        raise TypeError('Time-dependent coefficients must be list with ' +
                        'length N-1 where N is the number of ' +
                        'Hamiltonian terms.')

    if opt.rhs_reuse and odeconfig.tdfunc is None:
        rhs_generate(H_func, args)

    lenh = len(H_func[0])
    if opt.tidy:
        H_func[0] = [(H_func[0][k]).tidyup() for k in range(lenh)]
    L_func = [[liouvillian_fast(H_func[0][0], c_op_list)], H_func[1]]
    for m in range(1, lenh):
        L_func[0].append(liouvillian_fast(H_func[0][m], []))

    # create data arrays for time-dependent RHS function
    Ldata = [L_func[0][k].data.data for k in range(lenh)]
    Linds = [L_func[0][k].data.indices for k in range(lenh)]
    Lptrs = [L_func[0][k].data.indptr for k in range(lenh)]
    # setup ode args string
    string = ""
    for k in range(lenh):
        string += ("Ldata[%d], Linds[%d], Lptrs[%d]," % (k, k, k))

    if args:
        td_consts = args.items()
        for elem in td_consts:
            string += str(elem[1])
            if elem != td_consts[-1]:
                string += (",")

    # run code generator
    if not opt.rhs_reuse or odeconfig.tdfunc is None:
        if opt.rhs_filename is None:
            odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)
        else:
            odeconfig.tdname = opt.rhs_filename
        cgen = Codegen(h_terms=n_L_terms,
                       h_tdterms=Lcoeff,
                       args=args,
                       odeconfig=odeconfig)
        cgen.generate(odeconfig.tdname + ".pyx")

        code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                       '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc = cyq_td_ode_rhs

    #
    # setup integrator
    #
    initial_vector = mat2vec(rho0.full()).ravel()
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator('zvode',
                     method=opt.method,
                     order=opt.order,
                     atol=opt.atol,
                     rtol=opt.rtol,
                     nsteps=opt.nsteps,
                     first_step=opt.first_step,
                     min_step=opt.min_step,
                     max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params(' + string + ')', '<string>', 'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return _generic_ode_solve(r, rho0, tlist, e_ops, opt, progress_bar)
Beispiel #3
0
def _sesolve_list_str_td(H_list, psi0, tlist, expt_ops, args, opt):
    """
    Internal function for solving the master equation. See mesolve for usage.
    """

    if debug:
        print(inspect.stack()[0][3])

    #
    # check initial state: must be a density matrix
    #
    if not isket(psi0):
        raise TypeError("The unitary solver requires a ket as initial state")

    #
    # construct liouvillian
    #
    Ldata = []
    Linds = []
    Lptrs = []
    Lcoeff = []

    # loop over all hamiltonian terms, convert to superoperator form and
    # add the data of sparse matrix representation to h_coeff
    for h_spec in H_list:

        if isinstance(h_spec, Qobj):
            h = h_spec
            h_coeff = "1.0"

        elif isinstance(h_spec, list):
            h = h_spec[0]
            h_coeff = h_spec[1]

        else:
            raise TypeError("Incorrect specification of time-dependent " +
                            "Hamiltonian (expected string format)")

        L = -1j * h

        Ldata.append(L.data.data)
        Linds.append(L.data.indices)
        Lptrs.append(L.data.indptr)
        Lcoeff.append(h_coeff)

    # the total number of liouvillian terms (hamiltonian terms +
    # collapse operators)
    n_L_terms = len(Ldata)

    #
    # setup ode args string: we expand the list Ldata, Linds and Lptrs into
    # and explicit list of parameters
    #
    string_list = []
    for k in range(n_L_terms):
        string_list.append("Ldata[" + str(k) + "],Linds[" + str(k) +
                           "],Lptrs[" + str(k) + "]")
    for name, value in args.items():
        string_list.append(str(value))
    parameter_string = ",".join(string_list)

    #
    # generate and compile new cython code if necessary
    #
    if not opt.rhs_reuse or odeconfig.tdfunc is None:
        if opt.rhs_filename is None:
            odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)
        else:
            odeconfig.tdname = opt.rhs_filename
        cgen = Codegen(h_terms=n_L_terms,
                       h_tdterms=Lcoeff,
                       args=args,
                       odeconfig=odeconfig)
        cgen.generate(odeconfig.tdname + ".pyx")

        code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                       '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc = cyq_td_ode_rhs

    #
    # setup integrator
    #
    initial_vector = psi0.full()
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator('zvode',
                     method=opt.method,
                     order=opt.order,
                     atol=opt.atol,
                     rtol=opt.rtol,
                     nsteps=opt.nsteps,
                     first_step=opt.first_step,
                     min_step=opt.min_step,
                     max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params(' + parameter_string + ')', '<string>',
                   'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return _generic_ode_solve(r, psi0, tlist, expt_ops, opt, lambda x: x)
Beispiel #4
0
def rhs_generate(H, psi0, tlist, c_ops, e_ops, ntraj=500, args={}, options=Odeoptions(), solver="me", name=None):
    """
    Used to generate the Cython functions for solving the dynamics of a
    given system before using the parfor function.  
    
    Parameters
    ----------
    H : qobj
        System Hamiltonian.
    psi0 : qobj 
        Initial state vector
    tlist : array_like 
        Times at which results are recorded.
    ntraj : int 
        Number of trajectories to run.
    c_ops : array_like 
        ``list`` or ``array`` of collapse operators.
    e_ops : array_like 
        ``list`` or ``array`` of operators for calculating expectation values.
    args : dict
        Arguments for time-dependent Hamiltonian and collapse operator terms.
    options : Odeoptions
        Instance of ODE solver options.
    solver: str
        String indicating which solver "me" or "mc"
    name: str
        Name of generated RHS
    
    """
    _reset_odeconfig()  # clear odeconfig
    # ------------------------
    # GENERATE MCSOLVER DATA
    # ------------------------
    if solver == "mc":
        odeconfig.tlist = tlist
        if isinstance(ntraj, (list, ndarray)):
            odeconfig.ntraj = sort(ntraj)[-1]
        else:
            odeconfig.ntraj = ntraj
        # check for type of time-dependence (if any)
        time_type, h_stuff, c_stuff = _ode_checks(H, c_ops, "mc")
        h_terms = len(h_stuff[0]) + len(h_stuff[1]) + len(h_stuff[2])
        c_terms = len(c_stuff[0]) + len(c_stuff[1]) + len(c_stuff[2])
        # set time_type for use in multiprocessing
        odeconfig.tflag = time_type
        # check for collapse operators
        if c_terms > 0:
            odeconfig.cflag = 1
        else:
            odeconfig.cflag = 0
        # Configure data
        _mc_data_config(H, psi0, h_stuff, c_ops, c_stuff, args, e_ops, options)
        os.environ["CFLAGS"] = "-w"
        import pyximport

        pyximport.install(setup_args={"include_dirs": [numpy.get_include()]})
        if odeconfig.tflag in array([1, 11]):
            code = compile(
                "from " + odeconfig.tdname + " import cyq_td_ode_rhs,col_spmv,col_expect", "<string>", "exec"
            )
            exec(code)
            odeconfig.tdfunc = cyq_td_ode_rhs
            odeconfig.colspmv = col_spmv
            odeconfig.colexpect = col_expect
        else:
            code = compile("from " + odeconfig.tdname + " import cyq_td_ode_rhs", "<string>", "exec")
            exec(code)
            odeconfig.tdfunc = cyq_td_ode_rhs
        try:
            os.remove(odeconfig.tdname + ".pyx")
        except:
            print("Error removing pyx file.  File not found.")

    # ------------------------
    # GENERATE MESOLVER STUFF
    # ------------------------
    elif solver == "me":

        odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)
        cgen = Codegen(h_terms=n_L_terms, h_tdterms=Lcoeff, args=args)
        cgen.generate(odeconfig.tdname + ".pyx")
        os.environ["CFLAGS"] = "-O3 -w"
        import pyximport

        pyximport.install(setup_args={"include_dirs": [numpy.get_include()]})
        code = compile("from " + odeconfig.tdname + " import cyq_td_ode_rhs", "<string>", "exec")
        exec(code)
        odeconfig.tdfunc = cyq_td_ode_rhs
Beispiel #5
0
def wfsolve_list_td(H_func, psi0, tlist, expt_ops,H_args, opt):
    """!
    Evolve the wave function using an ODE solver with time-dependent
    Hamiltonian.
    """

    if not isket(psi0):
        raise TypeError("psi0 must be a ket")
        
    #
    # configure time-dependent terms and setup ODE solver
    #
    if len(H_func)!=2:
        raise TypeError('Time-dependent Hamiltonian list must have two terms.')
    if (not isinstance(H_func[0],(list,ndarray))) or (len(H_func[0])<=1):
        raise TypeError('Time-dependent Hamiltonians must be a list with two or more terms')
    if (not isinstance(H_func[1],(list,ndarray))) or (len(H_func[1])!=(len(H_func[0])-1)):
        raise TypeError('Time-dependent coefficients must be list with length N-1 where N is the number of Hamiltonian terms.')
    tflag=1
    if opt.rhs_reuse==True and odeconfig.tdfunc==None:
        print("No previous time-dependent RHS found.")
        print("Generating one for you...")
        rhs_generate(H_func,H_args)
    lenh=len(H_func[0])
    if opt.tidy:
        H_func[0]=[(H_func[0][k]).tidyup() for k in range(lenh)]
    #create data arrays for time-dependent RHS function
    Hdata=[-1.0j*H_func[0][k].data.data for k in range(lenh)]
    Hinds=[H_func[0][k].data.indices for k in range(lenh)]
    Hptrs=[H_func[0][k].data.indptr for k in range(lenh)]
    #setup ode args string
    string=""
    for k in range(lenh):
        string+="Hdata["+str(k)+"],Hinds["+str(k)+"],Hptrs["+str(k)+"],"

    if H_args:
        td_consts=H_args.items()
        for elem in td_consts:
            string+=str(elem[1])
            if elem!=td_consts[-1]:
                string+=(",")
    #run code generator
    if not opt.rhs_reuse:
        odeconfig.tdname="rhs"+str(odeconfig.cgen_num)
        cgen=Codegen(h_terms=n_L_terms,h_tdterms=Lcoeff, args=args)
        cgen.generate(odeconfig.tdname+".pyx")
        os.environ['CFLAGS'] = '-O3 -w'
        import pyximport
        pyximport.install(setup_args={'include_dirs':[numpy.get_include()]})
        code = compile('from '+odeconfig.tdname+' import cyq_td_ode_rhs', '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc=cyq_td_ode_rhs
    #
    # setup integrator
    #
    initial_vector = psi0.full()
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator('zvode', method=opt.method, order=opt.order,
                              atol=opt.atol, rtol=opt.rtol, #nsteps=opt.nsteps,
                              #first_step=opt.first_step, min_step=opt.min_step,
                              max_step=opt.max_step)                              
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params('+string+')', '<string>', 'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return generic_ode_solve(r, psi0, tlist, expt_ops, opt, lambda x: x)
Beispiel #6
0
def _mesolve_list_td(H_func, rho0, tlist, c_op_list, expt_ops, H_args, opt):
    """!
    Evolve the density matrix using an ODE solver with time dependent
    Hamiltonian.
    """
    n_op = len(c_op_list)
    
    #
    # check initial state
    #
    if isket(rho0):
        # if initial state is a ket and no collapse operator where given,
        # fallback on the unitary schrodinger equation solver
        if n_op == 0:
            return _wfsolve_list_td(H_func, rho0, tlist, expt_ops, H_args, opt)

        # Got a wave function as initial state: convert to density matrix.
        rho0 = ket2dm(rho0)

    #
    # construct liouvillian
    #

    if len(H_func)!=2:
        raise TypeError('Time-dependent Hamiltonian list must have two terms.')
    if (not isinstance(H_func[0],(list,ndarray))) or (len(H_func[0])<=1):
        raise TypeError('Time-dependent Hamiltonians must be a list with two or more terms')
    if (not isinstance(H_func[1],(list,ndarray))) or (len(H_func[1])!=(len(H_func[0])-1)):
        raise TypeError('Time-dependent coefficients must be list with length ' +
                        'N-1 where N is the number of Hamiltonian terms.')
    if opt.rhs_reuse==True and odeconfig.tdfunc==None:
        print("No previous time-dependent RHS found.")
        print("Generating one for you...")
        rhs_generate(H_func,H_args)
    lenh=len(H_func[0])
    if opt.tidy:
        H_func[0]=[(H_func[0][k]).tidyup() for k in range(lenh)]
    L_func=[[liouvillian(H_func[0][0], c_op_list)],H_func[1]]
    for m in range(1, lenh):
        L_func[0].append(liouvillian(H_func[0][m],[]))

    #create data arrays for time-dependent RHS function
    Ldata=[L_func[0][k].data.data for k in range(lenh)]
    Linds=[L_func[0][k].data.indices for k in range(lenh)]
    Lptrs=[L_func[0][k].data.indptr for k in range(lenh)]
    #setup ode args string
    string=""
    for k in range(lenh):
        string+="Ldata["+str(k)+"],Linds["+str(k)+"],Lptrs["+str(k)+"],"
    if H_args:
        td_consts=H_args.items()
        for elem in td_consts:
            string+=str(elem[1])
            if elem!=td_consts[-1]:
                string+=(",")
    
    #run code generator
    if not opt.rhs_reuse or odeconfig.tdfunc == None:
        if opt.rhs_filename==None:
            odeconfig.tdname="rhs"+str(odeconfig.cgen_num)
        else:
            odeconfig.tdname=opt.rhs_filename
        cgen=Codegen(h_terms=n_L_terms,h_tdterms=Lcoeff, args=args)
        cgen.generate(odeconfig.tdname+".pyx")
        os.environ['CFLAGS'] = '-O3 -w'
        import pyximport
        pyximport.install(setup_args={'include_dirs':[numpy.get_include()]})
        code = compile('from '+odeconfig.tdname+' import cyq_td_ode_rhs', '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc=cyq_td_ode_rhs
        
    #
    # setup integrator
    #
    initial_vector = mat2vec(rho0.full())
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator('zvode', method=opt.method, order=opt.order,
                              atol=opt.atol, rtol=opt.rtol, nsteps=opt.nsteps,
                              first_step=opt.first_step, min_step=opt.min_step,
                              max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params('+string+')', '<string>', 'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return _generic_ode_solve(r, rho0, tlist, expt_ops, opt, vec2mat)
Beispiel #7
0
def rhs_generate(H, c_ops, args={}, options=Odeoptions(), name=None):
    """
    Generates the Cython functions needed for solving the dynamics of a
    given system using the mesolve function inside a parfor loop.

    Parameters
    ----------
    H : qobj
        System Hamiltonian.
    c_ops : list
        ``list`` of collapse operators.
    args : dict
        Arguments for time-dependent Hamiltonian and collapse operator terms.
    options : Odeoptions
        Instance of ODE solver options.
    name: str
        Name of generated RHS

    Notes
    -----
    Using this function with any solver other than the mesolve function
    will result in an error.

    """
    odeconfig.reset()
    odeconfig.options = options

    if name:
        odeconfig.tdname = name
    else:
        odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)

    Lconst = 0

    Ldata = []
    Linds = []
    Lptrs = []
    Lcoeff = []

    # loop over all hamiltonian terms, convert to superoperator form and
    # add the data of sparse matrix represenation to
    for h_spec in H:
        if isinstance(h_spec, Qobj):
            h = h_spec
            Lconst += -1j * (spre(h) - spost(h))

        elif isinstance(h_spec, list):
            h = h_spec[0]
            h_coeff = h_spec[1]

            L = -1j * (spre(h) - spost(h))

            Ldata.append(L.data.data)
            Linds.append(L.data.indices)
            Lptrs.append(L.data.indptr)
            Lcoeff.append(h_coeff)

        else:
            raise TypeError("Incorrect specification of time-dependent " +
                            "Hamiltonian (expected string format)")

    # loop over all collapse operators
    for c_spec in c_ops:
        if isinstance(c_spec, Qobj):
            c = c_spec
            cdc = c.dag() * c
            Lconst += spre(c) * spost(
                c.dag()) - 0.5 * spre(cdc) - 0.5 * spost(cdc)

        elif isinstance(c_spec, list):
            c = c_spec[0]
            c_coeff = c_spec[1]

            cdc = c.dag() * c
            L = spre(c) * spost(c.dag()) - 0.5 * spre(cdc) - 0.5 * spost(cdc)

            Ldata.append(L.data.data)
            Linds.append(L.data.indices)
            Lptrs.append(L.data.indptr)
            Lcoeff.append("(" + c_coeff + ")**2")

        else:
            raise TypeError("Incorrect specification of time-dependent " +
                            "collapse operators (expected string format)")

    # add the constant part of the lagrangian
    if Lconst != 0:
        Ldata.append(Lconst.data.data)
        Linds.append(Lconst.data.indices)
        Lptrs.append(Lconst.data.indptr)
        Lcoeff.append("1.0")

    # the total number of liouvillian terms (hamiltonian terms + collapse
    # operators)
    n_L_terms = len(Ldata)

    cgen = Codegen(h_terms=n_L_terms,
                   h_tdterms=Lcoeff,
                   args=args,
                   odeconfig=odeconfig)
    cgen.generate(odeconfig.tdname + ".pyx")

    code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                   '<string>', 'exec')
    exec(code)

    odeconfig.tdfunc = cyq_td_ode_rhs
    try:
        os.remove(odeconfig.tdname + ".pyx")
    except:
        pass
Beispiel #8
0
def _sesolve_list_str_td(H_list, psi0, tlist, e_ops, args, opt,
                         progress_bar):
    """
    Internal function for solving the master equation. See mesolve for usage.
    """

    if debug:
        print(inspect.stack()[0][3])

    #
    # check initial state: must be a density matrix
    #
    if not isket(psi0):
        raise TypeError("The unitary solver requires a ket as initial state")

    #
    # construct liouvillian
    #
    Ldata = []
    Linds = []
    Lptrs = []
    Lcoeff = []

    # loop over all hamiltonian terms, convert to superoperator form and
    # add the data of sparse matrix representation to h_coeff
    for h_spec in H_list:

        if isinstance(h_spec, Qobj):
            h = h_spec
            h_coeff = "1.0"

        elif isinstance(h_spec, list):
            h = h_spec[0]
            h_coeff = h_spec[1]

        else:
            raise TypeError("Incorrect specification of time-dependent " +
                            "Hamiltonian (expected string format)")

        L = -1j * h

        Ldata.append(L.data.data)
        Linds.append(L.data.indices)
        Lptrs.append(L.data.indptr)
        Lcoeff.append(h_coeff)

    # the total number of liouvillian terms (hamiltonian terms +
    # collapse operators)
    n_L_terms = len(Ldata)

    #
    # setup ode args string: we expand the list Ldata, Linds and Lptrs into
    # and explicit list of parameters
    #
    string_list = []
    for k in range(n_L_terms):
        string_list.append("Ldata[%d], Linds[%d], Lptrs[%d]" % (k, k, k))
    for name, value in args.items():
        string_list.append(str(value))
    parameter_string = ",".join(string_list)

    #
    # generate and compile new cython code if necessary
    #
    if not opt.rhs_reuse or odeconfig.tdfunc is None:
        if opt.rhs_filename is None:
            odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)
        else:
            odeconfig.tdname = opt.rhs_filename
        cgen = Codegen(h_terms=n_L_terms, h_tdterms=Lcoeff, args=args,
                       odeconfig=odeconfig)
        cgen.generate(odeconfig.tdname + ".pyx")

        code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                       '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc = cyq_td_ode_rhs

    #
    # setup integrator
    #
    initial_vector = psi0.full().ravel()
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator('zvode', method=opt.method, order=opt.order,
                     atol=opt.atol, rtol=opt.rtol, nsteps=opt.nsteps,
                     first_step=opt.first_step, min_step=opt.min_step,
                     max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params(' + parameter_string + ')',
                   '<string>', 'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return _generic_ode_solve(r, psi0, tlist, e_ops, opt, progress_bar,dims=psi0.dims)
Beispiel #9
0
def _mesolve_list_td(H_func, rho0, tlist, c_op_list, expt_ops, H_args, opt):
    """!
    Evolve the density matrix using an ODE solver with time dependent
    Hamiltonian.
    """
    n_op = len(c_op_list)

    #
    # check initial state
    #
    if isket(rho0):
        # if initial state is a ket and no collapse operator where given,
        # fallback on the unitary schrodinger equation solver
        if n_op == 0:
            return _wfsolve_list_td(H_func, rho0, tlist, expt_ops, H_args, opt)

        # Got a wave function as initial state: convert to density matrix.
        rho0 = ket2dm(rho0)

    #
    # construct liouvillian
    #

    if len(H_func) != 2:
        raise TypeError('Time-dependent Hamiltonian list must have two terms.')
    if (not isinstance(H_func[0], (list, ndarray))) or (len(H_func[0]) <= 1):
        raise TypeError(
            'Time-dependent Hamiltonians must be a list with two or more terms'
        )
    if (not isinstance(H_func[1], (list, ndarray))) or (len(H_func[1]) !=
                                                        (len(H_func[0]) - 1)):
        raise TypeError(
            'Time-dependent coefficients must be list with length ' +
            'N-1 where N is the number of Hamiltonian terms.')
    if opt.rhs_reuse == True and odeconfig.tdfunc == None:
        print("No previous time-dependent RHS found.")
        print("Generating one for you...")
        rhs_generate(H_func, H_args)
    lenh = len(H_func[0])
    if opt.tidy:
        H_func[0] = [(H_func[0][k]).tidyup() for k in range(lenh)]
    L_func = [[liouvillian(H_func[0][0], c_op_list)], H_func[1]]
    for m in range(1, lenh):
        L_func[0].append(liouvillian(H_func[0][m], []))

    #create data arrays for time-dependent RHS function
    Ldata = [L_func[0][k].data.data for k in range(lenh)]
    Linds = [L_func[0][k].data.indices for k in range(lenh)]
    Lptrs = [L_func[0][k].data.indptr for k in range(lenh)]
    #setup ode args string
    string = ""
    for k in range(lenh):
        string += "Ldata[" + str(k) + "],Linds[" + str(k) + "],Lptrs[" + str(
            k) + "],"
    if H_args:
        td_consts = H_args.items()
        for elem in td_consts:
            string += str(elem[1])
            if elem != td_consts[-1]:
                string += (",")

    #run code generator
    if not opt.rhs_reuse or odeconfig.tdfunc == None:
        if opt.rhs_filename == None:
            odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)
        else:
            odeconfig.tdname = opt.rhs_filename
        cgen = Codegen(h_terms=n_L_terms, h_tdterms=Lcoeff, args=args)
        cgen.generate(odeconfig.tdname + ".pyx")
        os.environ['CFLAGS'] = '-O3 -w'
        import pyximport
        pyximport.install(setup_args={'include_dirs': [numpy.get_include()]})
        code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                       '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc = cyq_td_ode_rhs

    #
    # setup integrator
    #
    initial_vector = mat2vec(rho0.full())
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator('zvode',
                     method=opt.method,
                     order=opt.order,
                     atol=opt.atol,
                     rtol=opt.rtol,
                     nsteps=opt.nsteps,
                     first_step=opt.first_step,
                     min_step=opt.min_step,
                     max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params(' + string + ')', '<string>', 'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return _generic_ode_solve(r, rho0, tlist, expt_ops, opt, vec2mat)
Beispiel #10
0
def _sesolve_list_td(H_func, psi0, tlist, e_ops, args, opt, progress_bar):
    """!
    Evolve the wave function using an ODE solver with time-dependent
    Hamiltonian.
    """

    if debug:
        print(inspect.stack()[0][3])

    if not isket(psi0):
        raise TypeError("psi0 must be a ket")

    #
    # configure time-dependent terms and setup ODE solver
    #
    if len(H_func) != 2:
        raise TypeError('Time-dependent Hamiltonian list must have two terms.')
    if (not isinstance(H_func[0], (list, np.ndarray))) or \
       (len(H_func[0]) <= 1):
        raise TypeError(
            'Time-dependent Hamiltonians must be a list with two ' +
            'or more terms')
    if (not isinstance(H_func[1], (list, np.ndarray))) or \
       (len(H_func[1]) != (len(H_func[0]) - 1)):
        raise TypeError('Time-dependent coefficients must be list with ' +
                        'length N-1 where N is the number of ' +
                        'Hamiltonian terms.')
    tflag = 1
    if opt.rhs_reuse and odeconfig.tdfunc is None:
        print("No previous time-dependent RHS found.")
        print("Generating one for you...")
        rhs_generate(H_func, args)
    lenh = len(H_func[0])
    if opt.tidy:
        H_func[0] = [(H_func[0][k]).tidyup() for k in range(lenh)]
    # create data arrays for time-dependent RHS function
    Hdata = [-1.0j * H_func[0][k].data.data for k in range(lenh)]
    Hinds = [H_func[0][k].data.indices for k in range(lenh)]
    Hptrs = [H_func[0][k].data.indptr for k in range(lenh)]
    # setup ode args string
    string = ""
    for k in range(lenh):
        string += ("Hdata[" + str(k) + "],Hinds[" + str(k) + "],Hptrs[" +
                   str(k) + "],")

    if args:
        td_consts = args.items()
        for elem in td_consts:
            string += str(elem[1])
            if elem != td_consts[-1]:
                string += (",")

    # run code generator
    if not opt.rhs_reuse or odeconfig.tdfunc is None:
        if opt.rhs_filename is None:
            odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)
        else:
            odeconfig.tdname = opt.rhs_filename
        cgen = Codegen(h_terms=n_L_terms,
                       h_tdterms=Lcoeff,
                       args=args,
                       odeconfig=odeconfig)
        cgen.generate(odeconfig.tdname + ".pyx")

        code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                       '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc = cyq_td_ode_rhs
    #
    # setup integrator
    #
    initial_vector = psi0.full().ravel()
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator('zvode',
                     method=opt.method,
                     order=opt.order,
                     atol=opt.atol,
                     rtol=opt.rtol,
                     nsteps=opt.nsteps,
                     first_step=opt.first_step,
                     min_step=opt.min_step,
                     max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params(' + string + ')', '<string>', 'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return _generic_ode_solve(r,
                              psi0,
                              tlist,
                              e_ops,
                              opt,
                              progress_bar,
                              dims=psi0.dims)
Beispiel #11
0
def _mc_data_config(H, psi0, h_stuff, c_ops, c_stuff, args, e_ops, options):
    """Creates the appropriate data structures for the monte carlo solver
    based on the given time-dependent, or indepdendent, format.
    """

    #take care of expectation values, if any
    if any(e_ops):
        odeconfig.e_num = len(e_ops)
        for op in e_ops:
            if isinstance(op, list):
                op = op[0]
            odeconfig.e_ops_data.append(op.data.data)
            odeconfig.e_ops_ind.append(op.data.indices)
            odeconfig.e_ops_ptr.append(op.data.indptr)
            odeconfig.e_ops_isherm.append(op.isherm)

        odeconfig.e_ops_data = array(odeconfig.e_ops_data)
        odeconfig.e_ops_ind = array(odeconfig.e_ops_ind)
        odeconfig.e_ops_ptr = array(odeconfig.e_ops_ptr)
        odeconfig.e_ops_isherm = array(odeconfig.e_ops_isherm)
    #----

    #take care of collapse operators, if any
    if any(c_ops):
        odeconfig.c_num = len(c_ops)
        for c_op in c_ops:
            if isinstance(c_op, list):
                c_op = c_op[0]
            n_op = c_op.dag() * c_op
            odeconfig.c_ops_data.append(c_op.data.data)
            odeconfig.c_ops_ind.append(c_op.data.indices)
            odeconfig.c_ops_ptr.append(c_op.data.indptr)
            #norm ops
            odeconfig.n_ops_data.append(n_op.data.data)
            odeconfig.n_ops_ind.append(n_op.data.indices)
            odeconfig.n_ops_ptr.append(n_op.data.indptr)
        #to array
        odeconfig.c_ops_data = array(odeconfig.c_ops_data)
        odeconfig.c_ops_ind = array(odeconfig.c_ops_ind)
        odeconfig.c_ops_ptr = array(odeconfig.c_ops_ptr)

        odeconfig.n_ops_data = array(odeconfig.n_ops_data)
        odeconfig.n_ops_ind = array(odeconfig.n_ops_ind)
        odeconfig.n_ops_ptr = array(odeconfig.n_ops_ptr)
    #----

    #--------------------------------------------
    # START CONSTANT H & C_OPS CODE
    #--------------------------------------------
    if odeconfig.tflag == 0:
        if odeconfig.cflag:
            odeconfig.c_const_inds = arange(len(c_ops))
            for c_op in c_ops:
                n_op = c_op.dag() * c_op
                H -= 0.5j * n_op  #combine Hamiltonian and collapse terms into one
        #construct Hamiltonian data structures
        if options.tidy:
            H = H.tidyup(options.atol)
        odeconfig.h_data = -1.0j * H.data.data
        odeconfig.h_ind = H.data.indices
        odeconfig.h_ptr = H.data.indptr
    #----

    #--------------------------------------------
    # START STRING BASED TIME-DEPENDENCE
    #--------------------------------------------
    elif odeconfig.tflag in array([1, 10, 11]):
        #take care of arguments for collapse operators, if any
        if any(args):
            for item in args.items():
                odeconfig.c_args.append(item[1])
        #constant Hamiltonian / string-type collapse operators
        if odeconfig.tflag == 1:
            H_inds = arange(1)
            H_tdterms = 0
            len_h = 1
            C_inds = arange(odeconfig.c_num)
            C_td_inds = array(c_stuff[2])  #find inds of time-dependent terms
            C_const_inds = setdiff1d(C_inds,
                                     C_td_inds)  #find inds of constant terms
            C_tdterms = [c_ops[k][1] for k in C_td_inds
                         ]  #extract time-dependent coefficients (strings)
            odeconfig.c_const_inds = C_const_inds  #store indicies of constant collapse terms
            odeconfig.c_td_inds = C_td_inds  #store indicies of time-dependent collapse terms

            for k in odeconfig.c_const_inds:
                H -= 0.5j * (c_ops[k].dag() * c_ops[k])
            if options.tidy:
                H = H.tidyup(options.atol)
            odeconfig.h_data = [H.data.data]
            odeconfig.h_ind = [H.data.indices]
            odeconfig.h_ptr = [H.data.indptr]
            for k in odeconfig.c_td_inds:
                op = c_ops[k][0].dag() * c_ops[k][0]
                odeconfig.h_data.append(-0.5j * op.data.data)
                odeconfig.h_ind.append(op.data.indices)
                odeconfig.h_ptr.append(op.data.indptr)
            odeconfig.h_data = -1.0j * array(odeconfig.h_data)
            odeconfig.h_ind = array(odeconfig.h_ind)
            odeconfig.h_ptr = array(odeconfig.h_ptr)
            #--------------------------------------------
            # END OF IF STATEMENT
            #--------------------------------------------

        #string-type Hamiltonian & at least one string-type collapse operator
        else:
            H_inds = arange(len(H))
            H_td_inds = array(h_stuff[2])  #find inds of time-dependent terms
            H_const_inds = setdiff1d(H_inds,
                                     H_td_inds)  #find inds of constant terms
            H_tdterms = [
                H[k][1] for k in H_td_inds
            ]  #extract time-dependent coefficients (strings or functions)
            H = array([sum(H[k] for k in H_const_inds)] +
                      [H[k][0] for k in H_td_inds
                       ])  #combine time-INDEPENDENT terms into one.
            len_h = len(H)
            H_inds = arange(len_h)
            odeconfig.h_td_inds = arange(
                1, len_h)  #store indicies of time-dependent Hamiltonian terms
            #if there are any collpase operators
            if odeconfig.c_num > 0:
                if odeconfig.tflag == 10:  #constant collapse operators
                    odeconfig.c_const_inds = arange(odeconfig.c_num)
                    for k in odeconfig.c_const_inds:
                        H[0] -= 0.5j * (c_ops[k].dag() * c_ops[k])
                    C_inds = arange(odeconfig.c_num)
                    C_tdterms = array([])
                #-----
                else:  #some time-dependent collapse terms
                    C_inds = arange(odeconfig.c_num)
                    C_td_inds = array(
                        c_stuff[2])  #find inds of time-dependent terms
                    C_const_inds = setdiff1d(
                        C_inds, C_td_inds)  #find inds of constant terms
                    C_tdterms = [
                        c_ops[k][1] for k in C_td_inds
                    ]  #extract time-dependent coefficients (strings)
                    odeconfig.c_const_inds = C_const_inds  #store indicies of constant collapse terms
                    odeconfig.c_td_inds = C_td_inds  #store indicies of time-dependent collapse terms
                    for k in odeconfig.c_const_inds:
                        H[0] -= 0.5j * (c_ops[k].dag() * c_ops[k])
            else:  #set empty objects if no collapse operators
                C_const_inds = arange(odeconfig.c_num)
                odeconfig.c_const_inds = arange(odeconfig.c_num)
                odeconfig.c_td_inds = array([])
                C_tdterms = array([])
                C_inds = array([])

            #tidyup
            if options.tidy:
                H = array([H[k].tidyup(options.atol) for k in range(len_h)])
            #construct data sets
            odeconfig.h_data = [H[k].data.data for k in range(len_h)]
            odeconfig.h_ind = [H[k].data.indices for k in range(len_h)]
            odeconfig.h_ptr = [H[k].data.indptr for k in range(len_h)]
            for k in odeconfig.c_td_inds:
                odeconfig.h_data.append(-0.5j * odeconfig.n_ops_data[k])
                odeconfig.h_ind.append(odeconfig.n_ops_ind[k])
                odeconfig.h_ptr.append(odeconfig.n_ops_ptr[k])
            odeconfig.h_data = -1.0j * array(odeconfig.h_data)
            odeconfig.h_ind = array(odeconfig.h_ind)
            odeconfig.h_ptr = array(odeconfig.h_ptr)
            #--------------------------------------------
            # END OF ELSE STATEMENT
            #--------------------------------------------

        #set execuatble code for collapse expectation values and spmv
        col_spmv_code = "state=odeconfig.colspmv(j,ODE.t,odeconfig.c_ops_data[j],odeconfig.c_ops_ind[j],odeconfig.c_ops_ptr[j],ODE.y"
        col_expect_code = "n_dp+=[odeconfig.colexpect(i,ODE.t,odeconfig.n_ops_data[i],odeconfig.n_ops_ind[i],odeconfig.n_ops_ptr[i],ODE.y"
        for kk in range(len(odeconfig.c_args)):
            col_spmv_code += ",odeconfig.c_args[" + str(kk) + "]"
            col_expect_code += ",odeconfig.c_args[" + str(kk) + "]"
        col_spmv_code += ")"
        col_expect_code += ") for i in odeconfig.c_td_inds]"
        odeconfig.col_spmv_code = compile(col_spmv_code, '<string>', 'exec')
        odeconfig.col_expect_code = compile(col_expect_code, '<string>',
                                            'exec')
        #----

        #setup ode args string
        odeconfig.string = ""
        data_range = range(len(odeconfig.h_data))
        for k in data_range:
            odeconfig.string += "odeconfig.h_data[" + str(
                k) + "],odeconfig.h_ind[" + str(
                    k) + "],odeconfig.h_ptr[" + str(k) + "]"
            if k != data_range[-1]:
                odeconfig.string += ","
        #attach args to ode args string
        if len(odeconfig.c_args) > 0:
            for kk in range(len(odeconfig.c_args)):
                odeconfig.string += "," + "odeconfig.c_args[" + str(kk) + "]"
        #----
        name = "rhs" + str(odeconfig.cgen_num)
        odeconfig.tdname = name
        cgen = Codegen(H_inds,
                       H_tdterms,
                       odeconfig.h_td_inds,
                       args,
                       C_inds,
                       C_tdterms,
                       odeconfig.c_td_inds,
                       type='mc')
        cgen.generate(name + ".pyx")
        #----
    #--------------------------------------------
    # END OF STRING TYPE TIME DEPENDENT CODE
    #--------------------------------------------

    #--------------------------------------------
    # START PYTHON FUNCTION BASED TIME-DEPENDENCE
    #--------------------------------------------
    elif odeconfig.tflag in array([2, 20, 22]):

        #take care of Hamiltonian
        if odeconfig.tflag == 2:  # constant Hamiltonian, at least one function based collapse operators
            H_inds = array([0])
            H_tdterms = 0
            len_h = 1
        else:  # function based Hamiltonian
            H_inds = arange(len(H))
            H_td_inds = array(h_stuff[1])  #find inds of time-dependent terms
            H_const_inds = setdiff1d(H_inds,
                                     H_td_inds)  #find inds of constant terms
            odeconfig.h_funcs = array([H[k][1] for k in H_td_inds])
            odeconfig.h_func_args = args
            Htd = array([H[k][0] for k in H_td_inds])
            odeconfig.h_td_inds = arange(len(Htd))
            H = sum(H[k] for k in H_const_inds)

        #take care of collapse operators
        C_inds = arange(odeconfig.c_num)
        C_td_inds = array(c_stuff[1])  #find inds of time-dependent terms
        C_const_inds = setdiff1d(C_inds,
                                 C_td_inds)  #find inds of constant terms
        odeconfig.c_const_inds = C_const_inds  #store indicies of constant collapse terms
        odeconfig.c_td_inds = C_td_inds  #store indicies of time-dependent collapse terms
        odeconfig.c_funcs = zeros(odeconfig.c_num, dtype=FunctionType)
        for k in odeconfig.c_td_inds:
            odeconfig.c_funcs[k] = c_ops[k][1]
        odeconfig.c_func_args = args

        #combine constant collapse terms with constant H and construct data
        for k in odeconfig.c_const_inds:
            H -= 0.5j * (c_ops[k].dag() * c_ops[k])
        if options.tidy:
            H = H.tidyup(options.atol)
            Htd = array(
                [Htd[j].tidyup(options.atol) for j in odeconfig.h_td_inds])
            #setup cosntant H terms data
        odeconfig.h_data = -1.0j * H.data.data
        odeconfig.h_ind = H.data.indices
        odeconfig.h_ptr = H.data.indptr

        #setup td H terms data
        odeconfig.h_td_data = array(
            [-1.0j * Htd[k].data.data for k in odeconfig.h_td_inds])
        odeconfig.h_td_ind = array(
            [Htd[k].data.indices for k in odeconfig.h_td_inds])
        odeconfig.h_td_ptr = array(
            [Htd[k].data.indptr for k in odeconfig.h_td_inds])
        #--------------------------------------------
        # END PYTHON FUNCTION BASED TIME-DEPENDENCE
        #--------------------------------------------

    #--------------------------------------------
    # START PYTHON FUNCTION BASED HAMILTONIAN
    #--------------------------------------------
    elif odeconfig.tflag == 3:
        #take care of Hamiltonian
        odeconfig.h_funcs = H
        odeconfig.h_func_args = args

        #take care of collapse operators
        odeconfig.c_const_inds = arange(odeconfig.c_num)
        odeconfig.c_td_inds = array([])  #find inds of time-dependent terms
        if len(odeconfig.c_const_inds) > 0:
            H = 0
            for k in odeconfig.c_const_inds:
                H -= 0.5j * (c_ops[k].dag() * c_ops[k])
            if options.tidy:
                H = H.tidyup(options.atol)
            odeconfig.h_data = -1.0j * H.data.data
            odeconfig.h_ind = H.data.indices
            odeconfig.h_ptr = H.data.indptr
Beispiel #12
0
def wfsolve_list_td(H_func, psi0, tlist, expt_ops, H_args, opt):
    """!
    Evolve the wave function using an ODE solver with time-dependent
    Hamiltonian.
    """

    if not isket(psi0):
        raise TypeError("psi0 must be a ket")

    #
    # configure time-dependent terms and setup ODE solver
    #
    if len(H_func) != 2:
        raise TypeError('Time-dependent Hamiltonian list must have two terms.')
    if (not isinstance(H_func[0], (list, ndarray))) or (len(H_func[0]) <= 1):
        raise TypeError(
            'Time-dependent Hamiltonians must be a list with two or more terms'
        )
    if (not isinstance(H_func[1], (list, ndarray))) or (len(H_func[1]) !=
                                                        (len(H_func[0]) - 1)):
        raise TypeError(
            'Time-dependent coefficients must be list with length N-1 where N is the number of Hamiltonian terms.'
        )
    tflag = 1
    if opt.rhs_reuse == True and odeconfig.tdfunc == None:
        print("No previous time-dependent RHS found.")
        print("Generating one for you...")
        rhs_generate(H_func, H_args)
    lenh = len(H_func[0])
    if opt.tidy:
        H_func[0] = [(H_func[0][k]).tidyup() for k in range(lenh)]
    #create data arrays for time-dependent RHS function
    Hdata = [-1.0j * H_func[0][k].data.data for k in range(lenh)]
    Hinds = [H_func[0][k].data.indices for k in range(lenh)]
    Hptrs = [H_func[0][k].data.indptr for k in range(lenh)]
    #setup ode args string
    string = ""
    for k in range(lenh):
        string += "Hdata[" + str(k) + "],Hinds[" + str(k) + "],Hptrs[" + str(
            k) + "],"

    if H_args:
        td_consts = H_args.items()
        for elem in td_consts:
            string += str(elem[1])
            if elem != td_consts[-1]:
                string += (",")
    #run code generator
    if not opt.rhs_reuse:
        odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)
        cgen = Codegen(h_terms=n_L_terms, h_tdterms=Lcoeff, args=args)
        cgen.generate(odeconfig.tdname + ".pyx")
        os.environ['CFLAGS'] = '-O3 -w'
        import pyximport
        pyximport.install(setup_args={'include_dirs': [numpy.get_include()]})
        code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                       '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc = cyq_td_ode_rhs
    #
    # setup integrator
    #
    initial_vector = psi0.full()
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator(
        'zvode',
        method=opt.method,
        order=opt.order,
        atol=opt.atol,
        rtol=opt.rtol,  #nsteps=opt.nsteps,
        #first_step=opt.first_step, min_step=opt.min_step,
        max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params(' + string + ')', '<string>', 'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return generic_ode_solve(r, psi0, tlist, expt_ops, opt, lambda x: x)
Beispiel #13
0
def mesolve_list_str_td(H_list, rho0, tlist, c_list, expt_ops, args, opt):
    """
    Internal function for solving the master equation. See mesolve for usage.   
    """

    #
    # check initial state: must be a density matrix
    #
    if isket(rho0):
        rho0 = rho0 * rho0.dag()

    #
    # construct liouvillian
    #
    n_op = len(c_list)

    Lconst = 0

    Ldata = []
    Linds = []
    Lptrs = []
    Lcoeff = []

    # loop over all hamiltonian terms, convert to superoperator form and
    # add the data of sparse matrix represenation to
    for h_spec in H_list:

        if isinstance(h_spec, Qobj):
            h = h_spec

            Lconst += -1j * (spre(h) - spost(h))  # apply tidyup ?

        elif isinstance(h_spec, list):
            h = h_spec[0]
            h_coeff = h_spec[1]

            L = -1j * (spre(h) - spost(h))  # apply tidyup ?

            Ldata.append(L.data.data)
            Linds.append(L.data.indices)
            Lptrs.append(L.data.indptr)
            Lcoeff.append(h_coeff)

        else:
            raise TypeError(
                "Incorrect specification of time-dependent Hamiltonian (expected string format)"
            )

    # loop over all collapse operators
    for c_spec in c_list:

        if isinstance(c_spec, Qobj):
            c = c_spec

            cdc = c.dag() * c
            Lconst += spre(c) * spost(c.dag()) - 0.5 * spre(cdc) - 0.5 * spost(
                cdc)  # apply tidyup?

        elif isinstance(c_spec, list):
            c = c_spec[0]
            c_coeff = c_spec[1]

            cdc = c.dag() * c
            L = spre(c) * spost(c.dag()) - 0.5 * spre(cdc) - 0.5 * spost(
                cdc)  # apply tidyup?

            Ldata.append(L.data.data)
            Linds.append(L.data.indices)
            Lptrs.append(L.data.indptr)
            Lcoeff.append("(" + c_coeff + ")**2")

        else:
            raise TypeError(
                "Incorrect specification of time-dependent collapse operators (expected string format)"
            )

    # add the constant part of the lagrangian
    if Lconst != 0:
        Ldata.append(Lconst.data.data)
        Linds.append(Lconst.data.indices)
        Lptrs.append(Lconst.data.indptr)
        Lcoeff.append("1.0")

    # the total number of liouvillian terms (hamiltonian terms + collapse operators)
    n_L_terms = len(Ldata)

    #
    # setup ode args string: we expand the list Ldata, Linds and Lptrs into
    # and explicit list of parameters
    #
    string_list = []
    for k in range(n_L_terms):
        string_list.append("Ldata[" + str(k) + "],Linds[" + str(k) +
                           "],Lptrs[" + str(k) + "]")
    for name, value in args.items():
        string_list.append(str(value))
    parameter_string = ",".join(string_list)

    #
    # generate and compile new cython code if necessary
    #
    if not opt.rhs_reuse or odeconfig.tdfunc == None:
        odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)
        cgen = Codegen(h_terms=n_L_terms, h_tdterms=Lcoeff, args=args)
        cgen.generate(odeconfig.tdname + ".pyx")
        os.environ['CFLAGS'] = '-O3 -w'
        import pyximport
        pyximport.install(setup_args={'include_dirs': [numpy.get_include()]})
        code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                       '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc = cyq_td_ode_rhs

    #
    # setup integrator
    #
    initial_vector = mat2vec(rho0.full())
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator('zvode',
                     method=opt.method,
                     order=opt.order,
                     atol=opt.atol,
                     rtol=opt.rtol,
                     nsteps=opt.nsteps,
                     first_step=opt.first_step,
                     min_step=opt.min_step,
                     max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params(' + parameter_string + ')', '<string>',
                   'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return generic_ode_solve(r, rho0, tlist, expt_ops, opt, vec2mat)
Beispiel #14
0
def _mesolve_list_td(H_func, rho0, tlist, c_op_list, e_ops, args, opt,
                     progress_bar):
    """!
    Evolve the density matrix using an ODE solver with time dependent
    Hamiltonian.
    """

    if debug:
        print(inspect.stack()[0][3])

    #
    # check initial state
    #
    if isket(rho0):
        # if initial state is a ket and no collapse operator where given,
        # fall back on the unitary schrodinger equation solver
        if len(c_op_list) == 0:
            return _sesolve_list_td(H_func, rho0, tlist, e_ops, args, opt)

        # Got a wave function as initial state: convert to density matrix.
        rho0 = ket2dm(rho0)

    #
    # construct liouvillian
    #
    if len(H_func) != 2:
        raise TypeError('Time-dependent Hamiltonian list must have two terms.')
    if not isinstance(H_func[0], (list, np.ndarray)) or len(H_func[0]) <= 1:
        raise TypeError('Time-dependent Hamiltonians must be a list ' +
                        'with two or more terms')
    if (not isinstance(H_func[1], (list, np.ndarray))) or \
       (len(H_func[1]) != (len(H_func[0]) - 1)):
        raise TypeError('Time-dependent coefficients must be list with ' +
                        'length N-1 where N is the number of ' +
                        'Hamiltonian terms.')

    if opt.rhs_reuse and odeconfig.tdfunc is None:
        rhs_generate(H_func, args)

    lenh = len(H_func[0])
    if opt.tidy:
        H_func[0] = [(H_func[0][k]).tidyup() for k in range(lenh)]
    L_func = [[liouvillian_fast(H_func[0][0], c_op_list)], H_func[1]]
    for m in range(1, lenh):
        L_func[0].append(liouvillian_fast(H_func[0][m], []))

    # create data arrays for time-dependent RHS function
    Ldata = [L_func[0][k].data.data for k in range(lenh)]
    Linds = [L_func[0][k].data.indices for k in range(lenh)]
    Lptrs = [L_func[0][k].data.indptr for k in range(lenh)]
    # setup ode args string
    string = ""
    for k in range(lenh):
        string += ("Ldata[%d], Linds[%d], Lptrs[%d]," % (k, k, k))

    if args:
        td_consts = args.items()
        for elem in td_consts:
            string += str(elem[1])
            if elem != td_consts[-1]:
                string += (",")

    # run code generator
    if not opt.rhs_reuse or odeconfig.tdfunc is None:
        if opt.rhs_filename is None:
            odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)
        else:
            odeconfig.tdname = opt.rhs_filename
        cgen = Codegen(h_terms=n_L_terms, h_tdterms=Lcoeff, args=args,
                       odeconfig=odeconfig)
        cgen.generate(odeconfig.tdname + ".pyx")

        code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                       '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc = cyq_td_ode_rhs

    #
    # setup integrator
    #
    initial_vector = mat2vec(rho0.full()).ravel()
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator('zvode', method=opt.method, order=opt.order,
                     atol=opt.atol, rtol=opt.rtol, nsteps=opt.nsteps,
                     first_step=opt.first_step, min_step=opt.min_step,
                     max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params(' + string + ')', '<string>', 'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return _generic_ode_solve(r, rho0, tlist, e_ops, opt, progress_bar)
Beispiel #15
0
def _mc_data_config(H,psi0,h_stuff,c_ops,c_stuff,args,e_ops,options):
    """Creates the appropriate data structures for the monte carlo solver
    based on the given time-dependent, or indepdendent, format.
    """
    
    #take care of expectation values, if any
    if any(e_ops):
        odeconfig.e_num=len(e_ops)
        for op in e_ops:
            if isinstance(op,list):
                op=op[0]
            odeconfig.e_ops_data.append(op.data.data)
            odeconfig.e_ops_ind.append(op.data.indices)
            odeconfig.e_ops_ptr.append(op.data.indptr)
            odeconfig.e_ops_isherm.append(op.isherm)
        
        odeconfig.e_ops_data=array(odeconfig.e_ops_data)
        odeconfig.e_ops_ind=array(odeconfig.e_ops_ind)
        odeconfig.e_ops_ptr=array(odeconfig.e_ops_ptr)
        odeconfig.e_ops_isherm=array(odeconfig.e_ops_isherm)
    #----
    
    #take care of collapse operators, if any
    if any(c_ops):
        odeconfig.c_num=len(c_ops)
        for c_op in c_ops:
            if isinstance(c_op,list):
                c_op=c_op[0]
            n_op=c_op.dag()*c_op
            odeconfig.c_ops_data.append(c_op.data.data)
            odeconfig.c_ops_ind.append(c_op.data.indices)
            odeconfig.c_ops_ptr.append(c_op.data.indptr)
            #norm ops
            odeconfig.n_ops_data.append(n_op.data.data)
            odeconfig.n_ops_ind.append(n_op.data.indices)
            odeconfig.n_ops_ptr.append(n_op.data.indptr)
        #to array
        odeconfig.c_ops_data=array(odeconfig.c_ops_data)
        odeconfig.c_ops_ind=array(odeconfig.c_ops_ind)
        odeconfig.c_ops_ptr=array(odeconfig.c_ops_ptr)
        
        odeconfig.n_ops_data=array(odeconfig.n_ops_data)
        odeconfig.n_ops_ind=array(odeconfig.n_ops_ind)
        odeconfig.n_ops_ptr=array(odeconfig.n_ops_ptr)
    #----
    
    
    #--------------------------------------------
    # START CONSTANT H & C_OPS CODE
    #--------------------------------------------
    if odeconfig.tflag==0:
        if odeconfig.cflag:
            odeconfig.c_const_inds=arange(len(c_ops))
            for c_op in c_ops:
                n_op=c_op.dag()*c_op
                H -= 0.5j * n_op #combine Hamiltonian and collapse terms into one
        #construct Hamiltonian data structures
        if options.tidy:
            H=H.tidyup(options.atol)
        odeconfig.h_data=-1.0j*H.data.data
        odeconfig.h_ind=H.data.indices
        odeconfig.h_ptr=H.data.indptr  
    #----
    
    #--------------------------------------------
    # START STRING BASED TIME-DEPENDENCE
    #--------------------------------------------
    elif odeconfig.tflag in array([1,10,11]):
        #take care of arguments for collapse operators, if any
        if any(args):
            for item in args.items():
                odeconfig.c_args.append(item[1])
        #constant Hamiltonian / string-type collapse operators
        if odeconfig.tflag==1:
            H_inds=arange(1)
            H_tdterms=0
            len_h=1
            C_inds=arange(odeconfig.c_num)
            C_td_inds=array(c_stuff[2]) #find inds of time-dependent terms
            C_const_inds=setdiff1d(C_inds,C_td_inds) #find inds of constant terms
            C_tdterms=[c_ops[k][1] for k in C_td_inds] #extract time-dependent coefficients (strings)
            odeconfig.c_const_inds=C_const_inds#store indicies of constant collapse terms
            odeconfig.c_td_inds=C_td_inds#store indicies of time-dependent collapse terms
            
            for k in odeconfig.c_const_inds:
                H-=0.5j*(c_ops[k].dag()*c_ops[k])
            if options.tidy:
                H=H.tidyup(options.atol)
            odeconfig.h_data=[H.data.data]
            odeconfig.h_ind=[H.data.indices]
            odeconfig.h_ptr=[H.data.indptr]
            for k in odeconfig.c_td_inds:
                op=c_ops[k][0].dag()*c_ops[k][0]
                odeconfig.h_data.append(-0.5j*op.data.data)
                odeconfig.h_ind.append(op.data.indices)
                odeconfig.h_ptr.append(op.data.indptr)
            odeconfig.h_data=-1.0j*array(odeconfig.h_data)
            odeconfig.h_ind=array(odeconfig.h_ind)
            odeconfig.h_ptr=array(odeconfig.h_ptr)
            #--------------------------------------------
            # END OF IF STATEMENT
            #--------------------------------------------
        
        
        #string-type Hamiltonian & at least one string-type collapse operator
        else:
            H_inds=arange(len(H))
            H_td_inds=array(h_stuff[2]) #find inds of time-dependent terms
            H_const_inds=setdiff1d(H_inds,H_td_inds) #find inds of constant terms
            H_tdterms=[H[k][1] for k in H_td_inds] #extract time-dependent coefficients (strings or functions)
            H=array([sum(H[k] for k in H_const_inds)]+[H[k][0] for k in H_td_inds]) #combine time-INDEPENDENT terms into one.
            len_h=len(H)
            H_inds=arange(len_h)
            odeconfig.h_td_inds=arange(1,len_h)#store indicies of time-dependent Hamiltonian terms
            #if there are any collpase operators
            if odeconfig.c_num>0:
                if odeconfig.tflag==10: #constant collapse operators
                    odeconfig.c_const_inds=arange(odeconfig.c_num)
                    for k in odeconfig.c_const_inds:
                        H[0]-=0.5j*(c_ops[k].dag()*c_ops[k])
                    C_inds=arange(odeconfig.c_num)
                    C_tdterms=array([])
                #-----
                else:#some time-dependent collapse terms
                    C_inds=arange(odeconfig.c_num)
                    C_td_inds=array(c_stuff[2]) #find inds of time-dependent terms
                    C_const_inds=setdiff1d(C_inds,C_td_inds) #find inds of constant terms
                    C_tdterms=[c_ops[k][1] for k in C_td_inds] #extract time-dependent coefficients (strings)
                    odeconfig.c_const_inds=C_const_inds#store indicies of constant collapse terms
                    odeconfig.c_td_inds=C_td_inds#store indicies of time-dependent collapse terms
                    for k in odeconfig.c_const_inds:
                        H[0]-=0.5j*(c_ops[k].dag()*c_ops[k])
            else:#set empty objects if no collapse operators
                C_const_inds=arange(odeconfig.c_num)
                odeconfig.c_const_inds=arange(odeconfig.c_num)
                odeconfig.c_td_inds=array([])
                C_tdterms=array([])
                C_inds=array([])
            
            #tidyup
            if options.tidy:
                H=array([H[k].tidyup(options.atol) for k in range(len_h)])
            #construct data sets
            odeconfig.h_data=[H[k].data.data for k in range(len_h)]
            odeconfig.h_ind=[H[k].data.indices for k in range(len_h)]
            odeconfig.h_ptr=[H[k].data.indptr for k in range(len_h)]
            for k in odeconfig.c_td_inds:
                odeconfig.h_data.append(-0.5j*odeconfig.n_ops_data[k])
                odeconfig.h_ind.append(odeconfig.n_ops_ind[k])
                odeconfig.h_ptr.append(odeconfig.n_ops_ptr[k])
            odeconfig.h_data=-1.0j*array(odeconfig.h_data)
            odeconfig.h_ind=array(odeconfig.h_ind)
            odeconfig.h_ptr=array(odeconfig.h_ptr)
            #--------------------------------------------
            # END OF ELSE STATEMENT
            #--------------------------------------------
        
        #set execuatble code for collapse expectation values and spmv
        col_spmv_code="state=odeconfig.colspmv(j,ODE.t,odeconfig.c_ops_data[j],odeconfig.c_ops_ind[j],odeconfig.c_ops_ptr[j],ODE.y"
        col_expect_code="n_dp+=[odeconfig.colexpect(i,ODE.t,odeconfig.n_ops_data[i],odeconfig.n_ops_ind[i],odeconfig.n_ops_ptr[i],ODE.y"
        for kk in range(len(odeconfig.c_args)):
            col_spmv_code+=",odeconfig.c_args["+str(kk)+"]"
            col_expect_code+=",odeconfig.c_args["+str(kk)+"]"
        col_spmv_code+=")"
        col_expect_code+=") for i in odeconfig.c_td_inds]"
        odeconfig.col_spmv_code=compile(col_spmv_code,'<string>', 'exec')
        odeconfig.col_expect_code=compile(col_expect_code,'<string>', 'exec')    
        #----
        
        #setup ode args string
        odeconfig.string=""
        data_range=range(len(odeconfig.h_data))
        for k in data_range:
            odeconfig.string+="odeconfig.h_data["+str(k)+"],odeconfig.h_ind["+str(k)+"],odeconfig.h_ptr["+str(k)+"]"
            if k!=data_range[-1]:
                odeconfig.string+="," 
        #attach args to ode args string
        if len(odeconfig.c_args)>0:
            for kk in range(len(odeconfig.c_args)):
                odeconfig.string+=","+"odeconfig.c_args["+str(kk)+"]"
        #----
        name="rhs"+str(odeconfig.cgen_num)
        odeconfig.tdname=name
        cgen=Codegen(H_inds,H_tdterms,odeconfig.h_td_inds,args,C_inds,C_tdterms,odeconfig.c_td_inds,type='mc')
        cgen.generate(name+".pyx")
        #----
    #--------------------------------------------
    # END OF STRING TYPE TIME DEPENDENT CODE
    #--------------------------------------------
    
    #--------------------------------------------
    # START PYTHON FUNCTION BASED TIME-DEPENDENCE
    #--------------------------------------------
    elif odeconfig.tflag in array([2,20,22]):
        
        #take care of Hamiltonian
        if odeconfig.tflag==2:# constant Hamiltonian, at least one function based collapse operators
            H_inds=array([0])
            H_tdterms=0
            len_h=1
        else:# function based Hamiltonian
            H_inds=arange(len(H))
            H_td_inds=array(h_stuff[1]) #find inds of time-dependent terms
            H_const_inds=setdiff1d(H_inds,H_td_inds) #find inds of constant terms    
            odeconfig.h_funcs=array([H[k][1] for k in H_td_inds])
            odeconfig.h_func_args=args
            Htd=array([H[k][0] for k in H_td_inds])
            odeconfig.h_td_inds=arange(len(Htd))
            H=sum(H[k] for k in H_const_inds)
        
        #take care of collapse operators
        C_inds=arange(odeconfig.c_num)
        C_td_inds=array(c_stuff[1]) #find inds of time-dependent terms
        C_const_inds=setdiff1d(C_inds,C_td_inds) #find inds of constant terms
        odeconfig.c_const_inds=C_const_inds#store indicies of constant collapse terms
        odeconfig.c_td_inds=C_td_inds#store indicies of time-dependent collapse terms    
        odeconfig.c_funcs=zeros(odeconfig.c_num,dtype=FunctionType)
        for k in odeconfig.c_td_inds:
            odeconfig.c_funcs[k]=c_ops[k][1]
        odeconfig.c_func_args=args
            
        #combine constant collapse terms with constant H and construct data
        for k in odeconfig.c_const_inds:
            H-=0.5j*(c_ops[k].dag()*c_ops[k])
        if options.tidy:
            H=H.tidyup(options.atol)
            Htd=array([Htd[j].tidyup(options.atol) for j in odeconfig.h_td_inds])
            #setup cosntant H terms data
        odeconfig.h_data=-1.0j*H.data.data
        odeconfig.h_ind=H.data.indices
        odeconfig.h_ptr=H.data.indptr     
        
        #setup td H terms data
        odeconfig.h_td_data=array([-1.0j*Htd[k].data.data for k in odeconfig.h_td_inds])
        odeconfig.h_td_ind=array([Htd[k].data.indices for k in odeconfig.h_td_inds])
        odeconfig.h_td_ptr=array([Htd[k].data.indptr for k in odeconfig.h_td_inds])
        #--------------------------------------------
        # END PYTHON FUNCTION BASED TIME-DEPENDENCE
        #--------------------------------------------
     
     
    #--------------------------------------------
    # START PYTHON FUNCTION BASED HAMILTONIAN
    #--------------------------------------------
    elif odeconfig.tflag==3:
         #take care of Hamiltonian
         odeconfig.h_funcs=H
         odeconfig.h_func_args=args
         
         #take care of collapse operators
         odeconfig.c_const_inds=arange(odeconfig.c_num)
         odeconfig.c_td_inds=array([]) #find inds of time-dependent terms 
         if len(odeconfig.c_const_inds)>0:
             H=0
             for k in odeconfig.c_const_inds:
                 H-=0.5j*(c_ops[k].dag()*c_ops[k])
             if options.tidy:
                 H=H.tidyup(options.atol)
             odeconfig.h_data=-1.0j*H.data.data
             odeconfig.h_ind=H.data.indices
             odeconfig.h_ptr=H.data.indptr
Beispiel #16
0
def rhs_generate(H,c_ops,args={},options=Odeoptions(),name=None):
    """
    Generates the Cython functions needed for solving the dynamics of a
    given system using the mesolve function inside a parfor loop.  
    
    Parameters
    ----------
    H : qobj
        System Hamiltonian.
    c_ops : list
        ``list`` of collapse operators.
    args : dict
        Arguments for time-dependent Hamiltonian and collapse operator terms.
    options : Odeoptions
        Instance of ODE solver options.
    name: str
        Name of generated RHS
    
    Notes
    -----
    Using this function with any solver other than the mesolve function
    will result in an error.
    
    """
    _reset_odeconfig() #clear odeconfig
    if name:
        odeconfig.tdname=name
    else:
        odeconfig.tdname="rhs"+str(odeconfig.cgen_num)
    
    n_op = len(c_ops)

    Lconst = 0        

    Ldata = []
    Linds = []
    Lptrs = []
    Lcoeff = []
    
    # loop over all hamiltonian terms, convert to superoperator form and 
    # add the data of sparse matrix represenation to 
    for h_spec in H:
        if isinstance(h_spec, Qobj):
            h = h_spec
            Lconst += -1j*(spre(h) - spost(h)) 
        
        elif isinstance(h_spec, list): 
            h = h_spec[0]
            h_coeff = h_spec[1]

            L = -1j*(spre(h) - spost(h))

            Ldata.append(L.data.data)
            Linds.append(L.data.indices)
            Lptrs.append(L.data.indptr)
            Lcoeff.append(h_coeff)
            
        else:
            raise TypeError("Incorrect specification of time-dependent " + 
                             "Hamiltonian (expected string format)")
    
    # loop over all collapse operators        
    for c_spec in c_ops:
        if isinstance(c_spec, Qobj):
            c = c_spec
            cdc = c.dag() * c
            Lconst += spre(c) * spost(c.dag()) - 0.5 * spre(cdc) - 0.5 * spost(cdc) 

        elif isinstance(c_spec, list): 
            c = c_spec[0]
            c_coeff = c_spec[1]

            cdc = c.dag() * c
            L = spre(c) * spost(c.dag()) - 0.5 * spre(cdc) - 0.5 * spost(cdc) 

            Ldata.append(L.data.data)
            Linds.append(L.data.indices)
            Lptrs.append(L.data.indptr)
            Lcoeff.append("("+c_coeff+")**2")

        else:
            raise TypeError("Incorrect specification of time-dependent " + 
                             "collapse operators (expected string format)")

     # add the constant part of the lagrangian
    if Lconst != 0:
        Ldata.append(Lconst.data.data)
        Linds.append(Lconst.data.indices)
        Lptrs.append(Lconst.data.indptr)
        Lcoeff.append("1.0")


    # the total number of liouvillian terms (hamiltonian terms + collapse operators)      
    n_L_terms = len(Ldata)
    
    cgen=Codegen(h_terms=n_L_terms,h_tdterms=Lcoeff, args=args)
    cgen.generate(odeconfig.tdname+".pyx")
    os.environ['CFLAGS'] = '-O3 -w'
    import pyximport
    pyximport.install(setup_args={'include_dirs':[numpy.get_include()]})
    code = compile('from '+odeconfig.tdname+' import cyq_td_ode_rhs', '<string>', 'exec')
    exec(code)
    odeconfig.tdfunc=cyq_td_ode_rhs
    try:
        os.remove(odeconfig.tdname+".pyx")
    except:
        pass
Beispiel #17
0
def _mesolve_list_str_td(H_list, rho0, tlist, c_list, expt_ops, args, opt):
    """
    Internal function for solving the master equation. See mesolve for usage.   
    """
    
    #
    # check initial state: must be a density matrix
    #
    if isket(rho0):
        rho0 = rho0 * rho0.dag()

    #
    # construct liouvillian
    #       
    n_op = len(c_list)

    Lconst = 0        

    Ldata = []
    Linds = []
    Lptrs = []
    Lcoeff = []
    
    # loop over all hamiltonian terms, convert to superoperator form and 
    # add the data of sparse matrix represenation to 
    for h_spec in H_list:
    
        if isinstance(h_spec, Qobj):
            h = h_spec

            Lconst += -1j*(spre(h) - spost(h)) 
   
        elif isinstance(h_spec, list): 
            h = h_spec[0]
            h_coeff = h_spec[1]
            
            L = -1j*(spre(h) - spost(h))
            
            Ldata.append(L.data.data)
            Linds.append(L.data.indices)
            Lptrs.append(L.data.indptr)
            Lcoeff.append(h_coeff) 

        else:
            raise TypeError("Incorrect specification of time-dependent " + 
                            "Hamiltonian (expected string format)")
                
        
    # loop over all collapse operators        
    for c_spec in c_list:

        if isinstance(c_spec, Qobj):
            c = c_spec
            
            cdc = c.dag() * c
            Lconst += spre(c) * spost(c.dag()) - 0.5 * spre(cdc) - 0.5 * spost(cdc) 
   
        elif isinstance(c_spec, list): 
            c = c_spec[0]
            c_coeff = c_spec[1]
            
            cdc = c.dag() * c
            L = spre(c) * spost(c.dag()) - 0.5 * spre(cdc) - 0.5 * spost(cdc) 

            Ldata.append(L.data.data)
            Linds.append(L.data.indices)
            Lptrs.append(L.data.indptr)
            Lcoeff.append("("+c_coeff+")**2")

        else:
            raise TypeError("Incorrect specification of time-dependent " + 
                            "collapse operators (expected string format)")
                
    # add the constant part of the lagrangian
    if Lconst != 0:
        Ldata.append(Lconst.data.data)
        Linds.append(Lconst.data.indices)
        Lptrs.append(Lconst.data.indptr)
        Lcoeff.append("1.0")


    # the total number of liouvillian terms (hamiltonian terms + collapse operators)      
    n_L_terms = len(Ldata)      
    #
    # setup ode args string: we expand the list Ldata, Linds and Lptrs into
    # and explicit list of parameters
    # 
    string_list = []
    for k in range(n_L_terms):
        string_list.append("Ldata["+str(k)+"],Linds["+str(k)+"],Lptrs["+str(k)+"]")
    for name, value in args.items():
        string_list.append(str(value))
    parameter_string = ",".join(string_list)
   
    #
    # generate and compile new cython code if necessary
    #
    if not opt.rhs_reuse or odeconfig.tdfunc == None:
        if opt.rhs_filename==None:
            odeconfig.tdname="rhs"+str(odeconfig.cgen_num)
        else:
            odeconfig.tdname=opt.rhs_filename
        cgen=Codegen(h_terms=n_L_terms,h_tdterms=Lcoeff, args=args)
        cgen.generate(odeconfig.tdname+".pyx")
        os.environ['CFLAGS'] = '-O3 -w'
        import pyximport
        pyximport.install(setup_args={'include_dirs':[numpy.get_include()]})
        code = compile('from '+odeconfig.tdname+' import cyq_td_ode_rhs', '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc=cyq_td_ode_rhs
        
    #
    # setup integrator
    #
    initial_vector = mat2vec(rho0.full())
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator('zvode', method=opt.method, order=opt.order,
                              atol=opt.atol, rtol=opt.rtol, nsteps=opt.nsteps,
                              first_step=opt.first_step, min_step=opt.min_step,
                              max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params('+parameter_string+')', '<string>', 'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return _generic_ode_solve(r, rho0, tlist, expt_ops, opt, vec2mat)    
Beispiel #18
0
def _sesolve_list_td(H_func, psi0, tlist, e_ops, args, opt, progress_bar):
    """!
    Evolve the wave function using an ODE solver with time-dependent
    Hamiltonian.
    """

    if debug:
        print(inspect.stack()[0][3])

    if not isket(psi0):
        raise TypeError("psi0 must be a ket")

    #
    # configure time-dependent terms and setup ODE solver
    #
    if len(H_func) != 2:
        raise TypeError('Time-dependent Hamiltonian list must have two terms.')
    if (not isinstance(H_func[0], (list, np.ndarray))) or \
       (len(H_func[0]) <= 1):
        raise TypeError('Time-dependent Hamiltonians must be a list with two '
                        + 'or more terms')
    if (not isinstance(H_func[1], (list, np.ndarray))) or \
       (len(H_func[1]) != (len(H_func[0]) - 1)):
        raise TypeError('Time-dependent coefficients must be list with ' +
                        'length N-1 where N is the number of ' +
                        'Hamiltonian terms.')
    tflag = 1
    if opt.rhs_reuse and odeconfig.tdfunc is None:
        print("No previous time-dependent RHS found.")
        print("Generating one for you...")
        rhs_generate(H_func, args)
    lenh = len(H_func[0])
    if opt.tidy:
        H_func[0] = [(H_func[0][k]).tidyup() for k in range(lenh)]
    # create data arrays for time-dependent RHS function
    Hdata = [-1.0j * H_func[0][k].data.data for k in range(lenh)]
    Hinds = [H_func[0][k].data.indices for k in range(lenh)]
    Hptrs = [H_func[0][k].data.indptr for k in range(lenh)]
    # setup ode args string
    string = ""
    for k in range(lenh):
        string += ("Hdata[" + str(k) + "],Hinds[" + str(k) +
                   "],Hptrs[" + str(k) + "],")

    if args:
        td_consts = args.items()
        for elem in td_consts:
            string += str(elem[1])
            if elem != td_consts[-1]:
                string += (",")

    # run code generator
    if not opt.rhs_reuse or odeconfig.tdfunc is None:
        if opt.rhs_filename is None:
            odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)
        else:
            odeconfig.tdname = opt.rhs_filename
        cgen = Codegen(h_terms=n_L_terms, h_tdterms=Lcoeff, args=args,
                       odeconfig=odeconfig)
        cgen.generate(odeconfig.tdname + ".pyx")

        code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                       '<string>', 'exec')
        exec(code, globals())
        odeconfig.tdfunc = cyq_td_ode_rhs
    #
    # setup integrator
    #
    initial_vector = psi0.full().ravel()
    r = scipy.integrate.ode(odeconfig.tdfunc)
    r.set_integrator('zvode', method=opt.method, order=opt.order,
                     atol=opt.atol, rtol=opt.rtol, nsteps=opt.nsteps,
                     first_step=opt.first_step, min_step=opt.min_step,
                     max_step=opt.max_step)
    r.set_initial_value(initial_vector, tlist[0])
    code = compile('r.set_f_params(' + string + ')', '<string>', 'exec')
    exec(code)

    #
    # call generic ODE code
    #
    return _generic_ode_solve(r, psi0, tlist, e_ops, opt, progress_bar,dims=psi0.dims)
Beispiel #19
0
def rhs_generate(H,
                 psi0,
                 tlist,
                 c_ops,
                 e_ops,
                 ntraj=500,
                 args={},
                 options=Odeoptions(),
                 solver='me',
                 name=None):
    """
    Used to generate the Cython functions for solving the dynamics of a
    given system before using the parfor function.  
    
    Parameters
    ----------
    H : qobj
        System Hamiltonian.
    psi0 : qobj 
        Initial state vector
    tlist : array_like 
        Times at which results are recorded.
    ntraj : int 
        Number of trajectories to run.
    c_ops : array_like 
        ``list`` or ``array`` of collapse operators.
    e_ops : array_like 
        ``list`` or ``array`` of operators for calculating expectation values.
    args : dict
        Arguments for time-dependent Hamiltonian and collapse operator terms.
    options : Odeoptions
        Instance of ODE solver options.
    solver: str
        String indicating which solver "me" or "mc"
    name: str
        Name of generated RHS
    
    """
    _reset_odeconfig()  #clear odeconfig
    #------------------------
    # GENERATE MCSOLVER DATA
    #------------------------
    if solver == 'mc':
        odeconfig.tlist = tlist
        if isinstance(ntraj, (list, ndarray)):
            odeconfig.ntraj = sort(ntraj)[-1]
        else:
            odeconfig.ntraj = ntraj
        #check for type of time-dependence (if any)
        time_type, h_stuff, c_stuff = _ode_checks(H, c_ops, 'mc')
        h_terms = len(h_stuff[0]) + len(h_stuff[1]) + len(h_stuff[2])
        c_terms = len(c_stuff[0]) + len(c_stuff[1]) + len(c_stuff[2])
        #set time_type for use in multiprocessing
        odeconfig.tflag = time_type
        #check for collapse operators
        if c_terms > 0:
            odeconfig.cflag = 1
        else:
            odeconfig.cflag = 0
        #Configure data
        _mc_data_config(H, psi0, h_stuff, c_ops, c_stuff, args, e_ops, options)
        os.environ['CFLAGS'] = '-w'
        import pyximport
        pyximport.install(setup_args={'include_dirs': [numpy.get_include()]})
        if odeconfig.tflag in array([1, 11]):
            code = compile(
                'from ' + odeconfig.tdname +
                ' import cyq_td_ode_rhs,col_spmv,col_expect', '<string>',
                'exec')
            exec(code)
            odeconfig.tdfunc = cyq_td_ode_rhs
            odeconfig.colspmv = col_spmv
            odeconfig.colexpect = col_expect
        else:
            code = compile(
                'from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                '<string>', 'exec')
            exec(code)
            odeconfig.tdfunc = cyq_td_ode_rhs
        try:
            os.remove(odeconfig.tdname + ".pyx")
        except:
            print("Error removing pyx file.  File not found.")

    #------------------------
    # GENERATE MESOLVER STUFF
    #------------------------
    elif solver == 'me':

        odeconfig.tdname = "rhs" + str(odeconfig.cgen_num)
        cgen = Codegen(h_terms=n_L_terms, h_tdterms=Lcoeff, args=args)
        cgen.generate(odeconfig.tdname + ".pyx")
        os.environ['CFLAGS'] = '-O3 -w'
        import pyximport
        pyximport.install(setup_args={'include_dirs': [numpy.get_include()]})
        code = compile('from ' + odeconfig.tdname + ' import cyq_td_ode_rhs',
                       '<string>', 'exec')
        exec(code)
        odeconfig.tdfunc = cyq_td_ode_rhs