Source code for qutip.rhs_generate

__all__ = ['rhs_clear']

import os
import numpy as np
from types import FunctionType, BuiltinFunctionType
from functools import partial

from qutip.cy.codegen import Codegen
from qutip.solver import Options, config, solver_safe
from qutip.qobj import Qobj
from qutip.superoperator import spre, spost
from qutip.interpolate import Cubic_Spline


[docs]def rhs_clear(): """ Resets the string-format time-dependent Hamiltonian parameters. Parameters ---------- Returns ------- Nothing, just clears data from internal config module. """ # time-dependent (TD) function stuff config.tdfunc = None # Placeholder for TD RHS function. config.colspmv = None # Placeholder for TD col-spmv function. config.colexpect = None # Placeholder for TD col_expect function. config.string = None # Holds string of variables to be passed to solver config.tdname = None # Name of td .pyx file (used in parallel mc code) if "sesolve" in solver_safe: del solver_safe["sesolve"] if "mesolve" in solver_safe: del solver_safe["mesolve"] if "mcsolve" in solver_safe: del solver_safe["mcsolve"]
def _td_format_check(H, c_ops, solver='me'): """ Checks on time-dependent format. """ h_const = [] h_func = [] h_str = [] h_obj = [] # check H for incorrect format if isinstance(H, Qobj): pass elif isinstance(H, (FunctionType, BuiltinFunctionType, partial)): pass # n_func += 1 elif isinstance(H, list): for k, H_k in enumerate(H): if isinstance(H_k, Qobj): h_const.append(k) elif isinstance(H_k, list): if len(H_k) != 2 or not isinstance(H_k[0], Qobj): raise TypeError("Incorrect hamiltonian specification") else: if isinstance(H_k[1], (FunctionType, BuiltinFunctionType, partial)): h_func.append(k) elif isinstance(H_k[1], str): h_str.append(k) elif isinstance(H_k[1], Cubic_Spline): h_obj.append(k) elif hasattr(H_k[1], '__call__'): h_obj.append(k) elif isinstance(H_k[1], np.ndarray): h_str.append(k) else: raise TypeError("Incorrect hamiltonian specification") else: raise TypeError("Incorrect hamiltonian specification") # the the whole thing again for c_ops c_const = [] c_func = [] c_str = [] c_obj = [] if isinstance(c_ops, list): for k in range(len(c_ops)): if isinstance(c_ops[k], Qobj): c_const.append(k) elif isinstance(c_ops[k], list): if len(c_ops[k]) != 2: raise TypeError( "Incorrect collapse operator specification.") else: if isinstance(c_ops[k][1], (FunctionType, BuiltinFunctionType, partial)): c_func.append(k) elif isinstance(c_ops[k][1], str): c_str.append(k) elif isinstance(c_ops[k][1], Cubic_Spline): c_obj.append(k) elif hasattr(c_ops[k][1], '__call__'): c_func.append(k) elif isinstance(c_ops[k][1], np.ndarray): c_str.append(k) elif isinstance(c_ops[k][1], tuple): c_str.append(k) else: raise TypeError( "Incorrect collapse operator specification") else: raise TypeError("Incorrect collapse operator specification") # # if n_str == 0 and n_func == 0: # # no time-dependence at all # if ((len(h_str) > 0 and len(h_func) > 0) or (len(c_str) > 0 and len(c_func) > 0)): raise TypeError( "Cannot mix string and function type time-dependence formats") # check to see if Cython is installed and version is high enough. if len(h_str) > 0 or len(c_str) > 0: pass #try: # import Cython #except: # raise Exception( # "Unable to load Cython. Use Python function format.") #else: # if Cython.__version__ < '0.21': # raise Exception("Cython version (%s) is too old. Upgrade to" + # " version 0.21+" % Cython.__version__) # If only time-dependence is in Objects, then prefer string based format if (len(h_func) + len(c_func) + len(h_str) + len(c_str)) == 0: h_str += h_obj #Does nothing if not objects c_str += c_obj else: # Combine Hamiltonian objects if len(h_func) > 0: h_func += h_obj elif len(h_str) > 0: h_str += h_obj #Combine collapse objects if len(c_func) > 0: c_func += c_obj elif len(c_str) > 0: c_str += c_obj if solver == 'me': return (len(h_const + c_const), len(h_func) + len(c_func), len(h_str) + len(c_str)) elif solver == 'mc': # H C_ops # # -- ----- -- # NO NO 00 # NO STR 01 # NO FUNC 02 # # STR NO 10 # STR STR 11 # # FUNC NO 20 # # FUNC FUNC 22 if isinstance(H, FunctionType): time_type = 3 # Time-indepdent problems elif ((len(h_func) == len(h_str) == 0) and (len(c_func) == len(c_str) == 0)): time_type = 0 # constant Hamiltonian, time-dependent collapse operators elif len(h_func) == len(h_str) == 0: if len(c_str) > 0: time_type = 1 elif len(c_func) > 0: time_type = 2 else: raise Exception("Error determining time-dependence.") # list style Hamiltonian elif len(h_str) > 0: if len(c_func) == len(c_str) == 0: time_type = 10 elif len(c_str) > 0: time_type = 11 else: raise Exception("Error determining time-dependence.") # Python function style Hamiltonian elif len(h_func) > 0: if len(c_func) == len(c_str) == 0: time_type = 20 elif len(c_func) > 0: time_type = 22 else: raise Exception("Error determining time-dependence.") return time_type, [h_const, h_func, h_str], [c_const, c_func, c_str] def _td_wrap_array_str(H, c_ops, args, times): """ Wrap numpy-array based time-dependence in the string-based time dependence format """ n = 0 H_new = [] c_ops_new = [] args_new = {} if not isinstance(H, list): H_new = H else: for Hk in H: if isinstance(Hk, list) and isinstance(Hk[1], np.ndarray): H_op, H_td = Hk td_array_name = "_td_array_%d" % n H_td_str = '(0 if (t > %f) else %s[int(round(%d * (t/%f)))])' %\ (times[-1], td_array_name, len(times) - 1, times[-1]) args_new[td_array_name] = H_td H_new.append([H_op, H_td_str]) n += 1 else: H_new.append(Hk) if not isinstance(c_ops, list): c_ops_new = c_ops else: for ck in c_ops: if isinstance(ck, list) and isinstance(ck[1], np.ndarray): c_op, c_td = ck td_array_name = "_td_array_%d" % n c_td_str = '(0 if (t > %f) else %s[int(round(%d * (t/%f)))])' %\ (times[-1], td_array_name, len(times) - 1, times[-1]) args_new[td_array_name] = c_td c_ops_new.append([c_op, c_td_str]) n += 1 else: c_ops_new.append(ck) if not args_new: args_new = args elif isinstance(args, dict): args_new.update(args) else: raise ValueError("Time-dependent array format requires args to " + "be a dictionary") return H_new, c_ops_new, args_new