Source code for ttheom.utils.prepare

import os
import numpy as np
import scipy.constants as c

from .io_qc import loadQC

[docs] def prepareSystemParams(numQ, freqQ, rhoIni, gateTime, idlingTime): """Build the system dictionary and normalize qubit frequencies. Parameters ---------- numQ : int Number of qubits. freqQ : list of float Qubit frequencies in GHz. rhoIni : numpy.ndarray, optional Initial density matrix of shape ``(2**numQ, 2**numQ)``. Defaults to the ground state ``|0><0|``. idlingTime : float, optional Idling time (unused; reserved for future use). gateTime : list of float, optional Gate times (unused; reserved for future use). Returns ------- omegaQmax : float Maximum qubit angular frequency (rad/ns). rho : dict System dictionary with keys ``'numQ'``, ``'rhoIni'``, ``'omegaQ'``. """ # normalize qubit frequencies to the maximum frequency omegaQ = 2*np.pi*np.array(freqQ) omegaQmax = max(omegaQ) omegaQ /= omegaQmax # initialize the density matrix if rhoIni is None: rhoIni = np.zeros((2**numQ, 2**numQ), dtype=np.complex128) rhoIni[0, 0] = 1 else: rhoIni = np.array(rhoIni, dtype=np.complex128) rho = {'numQ': numQ, 'rhoIni': rhoIni, 'omegaQ': omegaQ.tolist()} # prepare the gate list for single- and two-qubit gates gateList = [] for i in range(rho['numQ']): kwargs1Q = {'omega': float(-rho['omegaQ'][i]), 'gateTime': float(omegaQmax * gateTime[i]) } gateList.append([[i], 'rxyStep', kwargs1Q]) for i in range(rho['numQ']-1): kwargs2Q = {'gateTime': float(omegaQmax * gateTime[rho['numQ'] + i]) } gateList.append([[i, i+1], 'directCplStepVarJ', kwargs2Q]) idlingTime *= omegaQmax return omegaQmax, rho, gateList, idlingTime
[docs] def prepareBathParams(rho, omegaQmax, T, T1, omegaC, exp, tol): """Convert physical bath parameters to the internal bath dictionary format. Parameters ---------- rho : dict System dictionary; ``rho['numQ']`` gives the number of qubits. omegaQmax : float Maximum qubit angular frequency (GHz), used for unit conversion. T : float or list of float Temperature(s) in mK. T1 : float or list of float Energy-relaxation time(s) in µs. omegaC : float or list of float Bath cutoff frequency(ies). exp : float or list of float Spectral-density exponent(s). tol : float or list of float AAA tolerance(s) for the bath decomposition. Returns ------- bath : list of dict List of bath parameter dictionaries, one per qubit. """ # expand scalars to lists of length numQ if not isinstance(T, list) and not isinstance(T, np.ndarray): T = [T] * rho['numQ'] if not isinstance(T1, list) and not isinstance(T1, np.ndarray): T1 = [T1] * rho['numQ'] if not isinstance(omegaC, list) and not isinstance(omegaC, np.ndarray): omegaC = [omegaC] * rho['numQ'] if not isinstance(exp, list) and not isinstance(exp, np.ndarray): exp = [exp] * rho['numQ'] if not isinstance(tol, list) and not isinstance(tol, np.ndarray): tol = [tol] * rho['numQ'] # conversion T -> beta, T1 -> kappa beta = c.hbar * omegaQmax * 1e9 / (np.array(T) * 1e-3 * c.k) kappa = 1 / (omegaQmax * 1e9 * np.array(T1) * 1e-6 * 2 * np.pi) bath = [{'type': 'broadband', 'beta': float(beta[i]), 'kappa': float(kappa[i]), 'omegaC': omegaC[i], 'exp': exp[i], 'tol': tol[i]} for i in range(rho['numQ'])] return bath
[docs] def prepareParams(**kwargs): """Assemble all internal arguments needed to build the TT structure. Parameters ---------- numQ : int Number of qubits. freqQ : list of float Qubit frequencies in GHz. gateTime : list of float Gate times in ns. T : float or list of float Temperature(s) in mK. T1 : float or list of float Energy-relaxation time(s) in µs. omegaC : float or list of float Bath cutoff frequency(ies). exp : float or list of float Spectral-density exponent(s). tol : float or list of float AAA tolerance(s). rhoIni : numpy.ndarray Initial density matrix. idlingTime : float Idling time in ns. dtFB : float Integration time step in fs. depth : list of int FP-HEOM hierarchy depths. bondDim : int Maximum MPS bond dimension. Returns ------- params : dict Internal parameter dictionary with keys ``'omegaQmax'``, ``'rho'``, ``'gateList'``, ``'idlingTime'``, ``'bath'``, ``'dtFB'``, ``'depth'``, ``'bondDim'``, ``'stride'``, ``'isRK13'``, ``'useRFPlus'``, and ``'V'``. """ omegaQmax, rho, gateList, idlingTime = prepareSystemParams(kwargs['numQ'], kwargs['freqQ'], kwargs['rhoIni'], kwargs['gateTime'], kwargs['idlingTime']) bath = prepareBathParams(rho, omegaQmax, kwargs['T'], kwargs['T1'], kwargs['omegaC'], kwargs['exp'], kwargs['tol']) dtFB = kwargs['dtFB'] * omegaQmax * 1e-3 stride = int( kwargs['strideTime'] * omegaQmax / dtFB) V = np.array([[[0, 1],[1, 0]] for _ in range(rho['numQ'])], dtype=np.complex128) # output parameters for simulation params = {} params['omegaQmax'] = omegaQmax params['rho'] = rho params['gateList'] = gateList params['idlingTime'] = idlingTime params['bath'] = bath params['dtFB'] = dtFB params['depth'] = kwargs['depth'] params['bondDim'] = kwargs['bondDim'] params['stride'] = stride params['isRK13'] = kwargs.get('isRK13', False) params['useRFPlus'] = kwargs.get('useRFPlus', False) params['V'] = V return params
[docs] def getSystemKwargs(rho, omegaQmax, gateList, idlingTime): """Convert internal system parameters back to physical units. Parameters ---------- omegaQmax : float Maximum qubit angular frequency (rad/ns). rho : dict Internal system dictionary with keys ``'numQ'``, ``'omegaQ'``, ``'rhoReal'``, ``'rhoImag'``. Returns ------- numQ : int Number of qubits. freqQ : list of float Qubit frequencies in GHz. rhoIni : numpy.ndarray Initial density matrix (complex). """ numQ = rho['numQ'] rhoIni = rho['rhoIni'] freqQ = (np.array(rho['omegaQ']) * omegaQmax / (2*np.pi)).tolist() gateTime = [gateList[i][2]['gateTime']/omegaQmax for i in range(2*rho['numQ']-1) ] idlingTime /= omegaQmax # ns return numQ, freqQ, rhoIni, gateTime, idlingTime
[docs] def getBathKwargs(omegaQmax, bath): """Convert internal bath parameters back to physical units. Parameters ---------- omegaQmax : float Maximum qubit angular frequency (rad/ns). bath : list of dict List of internal bath parameter dictionaries. Returns ------- T : numpy.ndarray Temperatures in mK. T1 : numpy.ndarray Energy-relaxation times in µs. omegaC : list Cutoff frequencies. exp : list Spectral-density exponents. tol : list AAA tolerances. """ # conversion beta -> T, kappa -> T1 T = c.hbar * omegaQmax * 1e9 / (np.array([b['beta'] for b in bath]) * 1e-3 * c.k) T1 = 1 / (omegaQmax * 1e9 * np.array([b['kappa'] for b in bath]) * 1e-6 * 2 * np.pi) omegaC = [b['omegaC'] for b in bath] exp = [b['exp'] for b in bath] tol = [b['tol'] for b in bath] return T, T1, omegaC, exp, tol
[docs] def getKwargs(directory, fileName): """Reconstruct user-facing simulation kwargs from a saved QPY file. Parameters ---------- directory : str Directory containing the QPY file. fileName : str Base name of the file (without extension). Returns ------- kwargs : dict Parameter dictionary in physical units with keys ``'directory'``, ``'fileName'``, ``'numQ'``, ``'freqQ'``, ``'rhoIni'``, ``'gateTime'``, ``'idlingTime'``, ``'T'``, ``'T1'``, ``'omegaC'``, ``'exp'``, ``'tol'``, ``'dtFB'``, ``'depth'``, ``'bondDim'``, ``'strideTime'``, ``'useRFPlus'``, ``'isRK13'``, and ``'qc'``. """ qcFilePath = os.path.join(os.getcwd(), directory, 'qcData_' + fileName + '.qpy') qc, params = loadQC(qcFilePath) # apply function to prepare system, bath, and gate parameters numQ, freqQ, rhoIni, gateTime, idlingTime = getSystemKwargs(params['rho'], params['omegaQmax'], params['gateList'], params['idlingTime']) T, T1, omegaC, exp, tol = getBathKwargs(params['omegaQmax'], params['bath']) # convert back to physical units dtFB = params['dtFB'] / (1e-3 * params['omegaQmax']) # ps strideTime = params['stride'] * params['dtFB'] / params['omegaQmax'] # ns kwargs = { "directory": directory, "fileName": fileName, "numQ": numQ, "freqQ": freqQ, # GHz "rhoIni": rhoIni, "gateTime": gateTime, # ns "idlingTime": idlingTime, # ns "T": T, # mK "T1": T1, # us "omegaC": omegaC, "exp": exp, "tol": tol, "dtFB": dtFB, # fs "depth": params['depth'], "bondDim": params['bondDim'], "strideTime": strideTime, # ns "useRFPlus": params['useRFPlus'], "isRK13": params['isRK13'], } kwargs['qc'] = qc return kwargs