示例#1
0
def _lanczos_error_equation_to_optimize_delta_t(T, krylov_basis, t0, tf,
                                                target_tolerance):
    """
    Function to optimize in order to obtain the optimal number of
    Lanczos algorithm iterations, governed by the optimal timestep size between
    Lanczos iteractions.
    """
    eigenvalues1, eigenvectors1 = eigh(T[0:, 0:])
    U1 = np.matmul(krylov_basis[0:, 0:].T, eigenvectors1)
    e01 = eigenvectors1.conj().T[:, 0]

    eigenvalues2, eigenvectors2 = eigh(T[0:-1, 0:T.shape[1] - 1])
    U2 = np.matmul(krylov_basis[0:-1, :].T, eigenvectors2)
    e02 = eigenvectors2.conj().T[:, 0]

    def f(t):
        delta_t = -1j * (t - t0)

        aux1 = np.multiply(np.exp(delta_t * eigenvalues1), e01)
        psi1 = np.matmul(U1, aux1)

        aux2 = np.multiply(np.exp(delta_t * eigenvalues2), e02)
        psi2 = np.matmul(U2, aux2)

        error = np.linalg.norm(psi1 - psi2)

        steps = max(1, (tf - t0) // (t - t0))
        return np.log10(error) + np.log10(steps) - np.log10(target_tolerance)

    return f
示例#2
0
def _evolve(t0: float, krylov_basis: np.ndarray, T_m: np.ndarray):
    """
    Computes the time evolution operator 'U(t - t0) psi0_k', where 'psi0_k'
    is the first basis element of the Krylov subspace, as a function of time.
    Parameters
    ------------
    t0: float
        Initial time for the time evolution.
    krylov_basis: np.ndarray
        Krylov basis projector operator.
    T_m: np.ndarray
        Tridiagonal matrix decomposition of the system given by lanczos
        algorithm.
    Returns
    ---------
    time_evolution: function
        Time evolution given by the Krylov subspace approximation.
    """

    eigenvalues, eigenvectors = eigh(T_m)
    U = np.matmul(krylov_basis.T, eigenvectors)
    e0 = eigenvectors.conj().T[:, 0]

    def time_evolution(t):
        delta_t = t - t0
        aux = np.multiply(np.exp(-1j * delta_t * eigenvalues), e0)
        return np.matmul(U, aux)

    return time_evolution
示例#3
0
文件: wigner.py 项目: maij/qutip
def _wigner_fourier(psi, xvec, g=np.sqrt(2)):
    """
    Evaluate the Wigner function via the Fourier transform.
    """
    if psi.type == 'bra':
        psi = psi.dag()
    if psi.type == 'ket':
        return _psi_wigner_fft(psi.full(), xvec, g)
    elif psi.type == 'oper':
        eig_vals, eig_vecs = eigh(psi.full())
        W = 0
        for ii in range(psi.shape[0]):
            W1, yvec = _psi_wigner_fft(
                np.reshape(eig_vecs[:, ii], (psi.shape[0], 1)), xvec, g)
            W += eig_vals[ii] * W1
        return W, yvec
示例#4
0
def exactsolve(H, psi0, tlist):
    """Calculates exact solution by direct diagonalization."""

    dims = psi0.dims
    H = H.full()
    psi0 = psi0.full()

    eigenvalues, eigenvectors = eigh(H)

    psi_base_diag = np.matmul(eigenvectors.conj().T, psi0)
    U = np.exp(np.outer(-1j * eigenvalues, tlist))
    psi_list = np.matmul(
        eigenvectors, np.multiply(U, psi_base_diag.reshape([-1, 1]))
    )
    exact_results = Result()
    exact_results.states = [Qobj(state, dims=dims) for state in psi_list.T]

    return exact_results
示例#5
0
文件: wigner.py 项目: maij/qutip
 def __call__(self, state: Qobj):
     """
     Get the Husimi-Q function for the given state vector or density matrix,
     over the coordinates used to initialise the class.  If called multiple
     times, the states do not need to have the same dimensions, but none of
     them can have tensor-product structure.
     """
     state = _qfunc_check_state(state)
     alphas = self._alphas(state.shape[0])
     if state.isket:
         return self._single(state.full().ravel(), alphas) / np.pi
     # We don't use Qobj.eigenstates() to avoid building many unnecessary
     # CSR versions of dense matrices.
     values, vectors = eigh(state.full())
     vectors = vectors.T
     out = values[0] * self._single(vectors[0], alphas)
     for value, vector in zip(values[1:], vectors[1:]):
         out += value * self._single(vector, alphas)
     return out / np.pi
示例#6
0
文件: wigner.py 项目: maij/qutip
def qfunc(
        state: Qobj,
        xvec,
        yvec,
        g: float = sqrt(2),
        precompute_memory: float = 1024,
):
    r"""
    Husimi-Q function of a given state vector or density matrix at phase-space
    points ``0.5 * g * (xvec + i*yvec)``.

    Parameters
    ----------
    state : :obj:`.Qobj`
        A state vector or density matrix.  This cannot have tensor-product
        structure.

    xvec, yvec : array_like
        x- and y-coordinates at which to calculate the Husimi-Q function.

    g : float, default sqrt(2)
        Scaling factor for ``a = 0.5 * g * (x + iy)``.  The value of `g` is
        related to the value of :math:`\hbar` in the commutation relation
        :math:`[x,\,y] = i\hbar` via :math:`\hbar=2/g^2`, so the default
        corresponds to :math:`\hbar=1`.

    precompute_memory : real, default 1024
        Size in MB that may be used during calculations as working space when
        dealing with density-matrix inputs.  This is ignored for state-vector
        inputs.  The bound is not quite exact due to other, order-of-magnitude
        smaller, intermediaries being necessary, but is a good approximation.
        If you want to use the same iterative algorithm for density matrices
        that is used for single kets, set ``precompute_memory=None``.

    Returns
    --------
    ndarray
        Values representing the Husimi-Q function calculated over the specified
        range ``[xvec, yvec]``.

    See Also
    --------
    :obj:`.QFunc` :
        a class-based version, more efficient if you want to calculate the
        Husimi-Q function for several states over the same coordinates.
    """
    state = _qfunc_check_state(state)
    xvec, yvec = _qfunc_check_coordinates(xvec, yvec)
    required_memory = state.shape[0] * xvec.size * yvec.size * 16 / (1024**2)
    enough_memory = (precompute_memory is not None
                     and precompute_memory > required_memory)
    if state.isoper and enough_memory:
        return QFunc(xvec, yvec, g)(state)
    if precompute_memory is not None and state.isoper:
        warnings.warn(
            "Falling back to iterative algorithm due to lack of memory."
            f" Needed {required_memory:.2f} MB, but only allowed to use"
            f" {precompute_memory:.2f} MB.  Increase `precompute_memory` to"
            " raise limit, or set to `None` to suppress warning.")
    alpha_grid = _QFuncCoherentGrid(xvec, yvec, g)
    if state.isket:
        out = _qfunc_iterative_single(state.full().ravel(), alpha_grid, g)
        out /= np.pi
        return out
    # We don't use Qobj.eigenstates() to avoid building many unnecessary CSR
    # versions of dense matrices.
    values, vectors = eigh(state.full())
    vectors = vectors.T
    out = values[0] * _qfunc_iterative_single(vectors[0], alpha_grid, g)
    for value, vector in zip(values[1:], vectors[1:]):
        out += value * _qfunc_iterative_single(vector, alpha_grid, g)
    out /= np.pi
    return out