Example #1
0
    def __init__(self, n_dims, sys_hamiltonian, sys_op, corr):
        """
        Parameters
        ----------
        n_dims : np.ndarray
            a vector representing the possible n
        sys_hamiltionian : np.ndarray
            H_s
        sys_op :
            X_s in in H_sb X_s (x) X_b 
        corr : Correlation
            Correlation caused by X_b
        """
        self.n_dims = n_dims
        self.k_max = len(n_dims)
        assert isinstance(corr, Correlation)
        assert self.k_max == corr.k_max
        self._i = len(n_dims)
        self._j = len(n_dims) + 1

        self.corr = corr
        assert sys_op.ndim == 2
        assert sys_op.shape == sys_hamiltonian.shape
        self.n_states = sys_op.shape[0]
        self.op = np.array(sys_op, dtype=DTYPE)
        self.h = np.array(sys_hamiltonian, dtype=DTYPE)
Example #2
0
 def normalize(self, forced=False):
     """Normalize the array of self. Only work when self.normalized.
     Set `forced` to `True` to normalize any way.
     """
     array = self.array
     if array is None or (not self.normalized and not forced):
         return
     axis = self.axis
     if axis is None:
         norm = np.array(self.local_norm())
         self.set_array(array / norm)
         ans = norm
     else:
         norm = linalg.norm
         shape = self.shape
         dim = shape.pop(axis)
         array = np.reshape(np.moveaxis(array, axis, 0), (dim, -1))
         vecs = []
         norm_list = []
         for vec_i in array:
             for vec_j in vecs:
                 vec_i -= vec_j * np.dot(np.conj(vec_j), vec_i)
             norm_ = norm(vec_i)
             vecs.append(vec_i / norm_)
             norm_list.append(norm_)
         array = np.array(vecs)
         array = np.moveaxis(np.reshape(array, [-1] + shape), 0, axis)
         self.set_array(array)
         ans = norm_list
     return ans
Example #3
0
def mat_element(mps1, mpo, mps2):
    r"""Calculate the matrix element :math:`\langle 1 | O | 2 \rangle` by
    contract_from_left, where :math:`| 1 \rangle`, :math:`| 2 \rangle` are MPS,
    :math:`O` is MPO.

    Parameters
    mps1 : [(_, _, _) ndarray]
        a list of MPS matrixes
    mpo : [(_, _, _, _) ndarray]
        a list of MPO matrixes or None
    mps2 : [(_, _, _) ndarray]
        a list of MPS matrixes

    Returns
    -------
        Matrix element :math:`\langle 1 | O | 2 \rangle` or
        :math:`\langle 1 | 2 \rangle` if mpo is None
    """
    if mpo is not None:
        L = np.array([[[1.0]]])
        for i in range(0, len(mpo)):
            L = contract_from_left(L, mps1[i], mpo[i], mps2[i])
        return L[0, 0, 0]
    else:
        L = np.array([[1.0]])
        assert len(mps1) == len(mps2)
        for i in range(0, len(mps1)):
            L = contract_from_left(L, mps1[i], None, mps2[i])
        return L[0, 0]
Example #4
0
 def inner_hamiltonian(self, prefix='I'):
     omega_list, lambda_list, dim_list = [
         getattr(self, name) for name in self.INNER
     ]
     coupling_list = list(
         np.sqrt(np.array(lambda_list) / 2) * np.array(omega_list))
     self.inner_prefix = prefix
     return self.vibration_hamiltonian(omega_list,
                                       coupling_list,
                                       dim_list,
                                       prefix=prefix)
Example #5
0
    def solve(self, n_state=None):
        r"""Solve the TISE with the potential energy given.

        Parameters
        ----------
        n_state : int, optional
            Number of states to be calculated, sorted by energy from low to
            high.

        Returns
        -------
        energy : [float]
        eigenstates : np.ndarray

        See Also
        ________
        DVR : Definition of all attributes.
        """
        if n_state is None:
            n_state = self.n - 1
        self._h_mat = self.h_mat()
        self.energy, v = eigsh(self._h_mat, k=n_state, which='SA')
        # self.energy, v = scipy.linalg.eigh(
        #     self._h_mat, eigvals=(0, n_state - 1))
        tmp = np.transpose(v)
        es = []
        for i in tmp:
            vi = i if i[0] >= 0.0 else -i
            es.append(vi)
        self.eigenstates = np.array(es)
        return self.energy, self.eigenstates
Example #6
0
    def _contract_Rs(mpo, mps):
        R_list = [np.array([[[1.0]]])]
        for i in range(len(mpo) - 1, 0, -1):
            R_list.append(
                contract_from_right(R_list[-1], mps[i], mpo[i], mps[i]))

        return R_list
Example #7
0
    def _solve_ode(self, diff, y0, ode_inter, reformer, updater):
        OdeSolver = getattr(integrate, self.ode_method)
        in_real = self.ode_in_real
        t0 = self.time
        if t0 is None:
            t0 = 0.0
        t1 = t0 + ode_inter
        if in_real:
            y0 = np.array((y0.real, y0.imag), dtype='float64')
            complex_diff = diff

            def diff(t, x):
                xc = np.array(x[0] + 1.0j * x[1], dtype='complex128')
                yc = complex_diff(t, xc)
                y = np.array((yc.real, yc.imag), dtype='float64')
                return y

        ode_solver = OdeSolver(diff, t0, y0, t1, vectorized=False)
        cmf_steps = self.cmf_steps
        for n in count(1):
            if ode_solver.status != 'running':
                logging.debug(
                    __('* Propagation done.  Average CMF steps: {}',
                       n // cmf_steps))
                break
            if n % cmf_steps == 0:
                if n >= self.max_ode_steps:
                    msg = __('Reach ODE limit {}', n)
                    logging.warning(msg)
                    raise RuntimeWarning(msg)
                if reformer is not None:
                    reformer()
            ode_solver.step()
            updater(ode_solver.y)
        return
Example #8
0
 def vibration_hamiltonian(self,
                           omega_list,
                           coupling_list,
                           dim_list,
                           prefix='V'):
     """
     Returns
     -------
     h_list: [[(str, ndarray)]]
     """
     elec_leaf = self.elec_leaf
     projector = np.array([[0., 0.], [0., 1.]])
     h_list = []
     zipped = zip(dim_list, omega_list, coupling_list)
     for n, (dim, omega, c) in enumerate(zipped):
         ph = Phonon(dim, omega)
         leaf = prefix + str(n)
         self.leaves.append(leaf)
         self.dimensions[leaf] = dim
         # ph part
         h_list.append([[leaf, ph.hamiltonian]])
         # e-ph part
         h_list.append([[leaf, -omega * ph.coordinate_operator],
                        [elec_leaf, 2. * (c / omega) * projector]])
         # e part
         h_list.append([[elec_leaf, 2. * (c / omega)**2 * projector]])
     return h_list
Example #9
0
def get_ext_wfns(n_states, wfns, op, search_method='krylov'):
    wfns = np.array(wfns)
    n_states = np.shape(wfns)[1]
    space = np.transpose(np.array(wfns))
    vecs = np.transpose(np.array(wfns))
    assert np.shape(space)[1] <= n_states
    if search_method == 'krylov':
        while True:
            space = linalg.orth(vecs)
            if np.shape(space)[0] >= n_states:
                break
            vecs = list(op @ vecs)
            np.concatenate((space, vecs), axis=1)
        psi = space[:, :n_states]
        return np.transpose(psi)
    else:
        raise NotImplementedError
Example #10
0
 def _calculate_dvr(self):
     # calculate grid points
     step_length = self.length / (self.n + 1)
     self.grid_points = np.array([self.a + step_length * i for i in range(1, self.n + 1)])
     # calculate U matrix
     j = np.arange(1, self.n + 1)[:, None]
     a = np.arange(1, self.n + 1)[None, :]
     self._u_mat = (np.sqrt(2 / (self.n + 1)) * np.sin(j * a * np.pi / (self.n + 1)))
     return self.grid_points, self._u_mat
Example #11
0
 def _calc_diag(self, func):
     v = []
     for i in range(self.dim):
         x = []
         sub = self.subindex(i)
         for j, n in enumerate(sub):
             x.append(self.grid_points_list[j][n])
         v.append(func(x))
     return np.array(v)
Example #12
0
 def field(t):
     mu, tau, t_d, omega = [getattr(self, name) for name in self.FIELD]
     h = [[0., mu], [mu, 0.]]
     delta = t - t_d
     coeff = (np.exp(-4. * np.log(2.) * (delta / tau)**2) *
              np.cos(omega * delta))
     ans = coeff * np.array(h)
     if ti_array is not None:
         ans += ti_array
     return ans
Example #13
0
 def __init__(self, gamma, lambda_, k_max=1, beta=None):
     if k_max != 1:
         raise NotImplementedError
     if beta is None:
         s = 0.0
     else:
         # Naive high temperature
         s = 2 * lambda_ / beta
     a = -gamma * lambda_
     super().__init__(
         k_max=k_max,
         beta=beta,
         coeff=np.array([s + 1.0j * a]),
         conj_coeff=np.array([s - 1.0j * a]),
         derivative=np.array([-gamma]),
     )
     self.gamma = gamma
     self.lambda_ = lambda_
     return
Example #14
0
    def asymm_coeff(self):

        def _a(k):
            if k == 0:
                a = -self.omega_0 * self.lambda_
            else:
                a = 0
            return a

        return np.array([_a(k) for k in range(self.k_max)])
Example #15
0
    def exp_coeff(self):
        """Masturaba Frequencies"""

        def _gamma(k):
            if k == 0:
                gamma = self.omega_0
            else:
                gamma = 2.0 * np.pi * k / (self.beta * self.hbar)
            return gamma

        return np.array([_gamma(k) for k in range(self.k_max)])
Example #16
0
    def symm_coeff(self):
        v, l, bh = self.omega_0, self.lambda_, self.beta * self.hbar

        def _s(k):
            if k == 0:
                s = v * l / np.tan(bh * v / 2.0)
            else:
                s = 2.0 * self.spectrum(self.exp_coeff[k]) / bh
            return s

        return np.array([_s(k) for k in range(self.k_max)])
Example #17
0
 def __init__(self,
              k_max=None,
              beta=None,
              coeff=None,
              conj_coeff=None,
              derivative=None):
     """
     k_max : int
         number of the terms in the basis functions
     beta : float
         Inverse temperature; 1 / (k_B T)
     """
     self.spectrum = None
     self.k_max = k_max
     self.beta = beta
     self.coeff = np.array(coeff,
                           dtype=DTYPE) if coeff is not None else None
     self.conj_coeff = np.array(
         conj_coeff, dtype=DTYPE) if conj_coeff is not None else None
     self.derivative = np.array(
         derivative, dtype=DTYPE) if derivative is not None else None
     return
Example #18
0
 def electron_hamiltonian(self, name='ELEC'):
     """
     Returns
     -------
     [(str, ndarray)]
     """
     e1, e2, v = [getattr(self, n) for n in self.ELEC]
     leaf = str(name)
     h = [[e1, v], [v, e2]]
     self.elec_leaf = leaf
     self.leaves.append(leaf)
     self.dimensions[leaf] = 2
     return [[[leaf, np.array(h)]]]
Example #19
0
 def _matvec(self, vec):
     v = np.reshape(vec, self.io_sizes)
     ans = np.zeros_like(v)
     for i, h_i in enumerate(self.h_list):
         v_i = np.swapaxes(v, -1, i)
         size_i = (self.io_sizes[:i] + self.io_sizes[i + 1:] + [self.io_sizes[i]])
         v_i = np.reshape(v_i, (-1, self.io_sizes[i]))
         tmp = np.array(list(map(h_i.dot, v_i)))
         tmp = np.reshape(tmp, size_i)
         ans += np.swapaxes(tmp, -1, i)
     ans = np.reshape(ans, -1)
     if self.v_rst is not None:
         ans = ans + self.v_rst * vec
     return ans
Example #20
0
    def __init__(self, root, h_list, f_list=None, use_str_name=False):
        """
        Parameters
        ----------
        root : Tensor
        h_list : [[(Leaf, array)]]
            h_list is a list of `term`, where `term` is a list of tuple like
            `(Leaf, array)`.  This is time independent part of Hamiltonian.
        f_list : [[(Leaf, float  ->  array)]]
            h_list is a list of `term`, where `term` is a list of tuple like
            `(Leaf, array)`.  This is time dependent part of Hamiltonian.
        use_str_name : bool
            whether to use str to replace Leaf above. Default is False.
        """
        self.root = root
        self.h_list = h_list
        self.f_list = f_list

        # For propogation purpose
        self.time = None
        self.overall_norm = 1
        self.init_energy = None

        # Type check
        for term in h_list:
            for pair in term:
                if not isinstance(pair[0], Leaf) and not use_str_name:
                    raise TypeError('0-th ary in tuple must be of type Leaf!')
                if np.array(pair[1]).ndim != 2:
                    raise TypeError('1-th ary in tuple must be 2-D ndarray!')
        if f_list is not None:
            for term in f_list:
                for pair in term:
                    if not isinstance(pair[0], Leaf) and not use_str_name:
                        raise TypeError('0-th ary in tuple must be of type '
                                        'Leaf!')
                    if not callable(pair[1]):
                        raise TypeError('1-th ary in tuple must be callable!')
        if use_str_name:
            all_terms = h_list if f_list is None else h_list + f_list
            leaves_dict = {leaf.name: leaf for leaf in root.leaves()}
            for term in all_terms:
                for _ in range(len(term)):
                    fst, snd = term.pop(0)
                    term.append((leaves_dict[str(fst)], snd))

        # Some cached data
        self.inv_density = {}  # {Tensor: ndarray}
        self.env_ = {}  # {(int, Tensor, int): ndarray}
        return
Example #21
0
 def _orthonormalize(self, use_svd=True):
     if use_svd and self._trial_vecs:
         trial_mat = np.transpose(np.array(self._trial_vecs))
         trial_mat = orth(trial_mat)
         self._trial_vecs = list(np.transpose(trial_mat))
     elif self._trial_vecs:
         vecs = []
         for vec_i in self._trial_vecs:
             for vec_j in vecs:
                 vec_i -= vec_j * np.dot(vec_j.conj(), vec_i)
             norm_ = norm(vec_i)
             if norm_ > 1.e-7:
                 vecs.append(vec_i / norm_)
         self._trial_vecs = vecs
     return self._trial_vecs
Example #22
0
    def gen_extended_rho(self, rho):
        """Get rho_n from rho with the conversion:
            rho[n_0, ..., n_(k-1), i, j]

        Parameters
        ----------
        rho : np.ndarray
        """
        shape = list(rho.shape)
        assert len(shape) == 2 and shape[0] == shape[1]
        # Let: rho_n[0, i, j] = rho and rho_n[n, i, j] = 0
        ext = np.zeros((np.prod(self.n_dims), ))
        ext[0] = 1
        rho_n = np.reshape(np.tensordot(ext, rho, axes=0),
                           list(self.n_dims) + shape)
        return np.array(rho_n, dtype=DTYPE)
Example #23
0
 def relaxation_hamiltonian(self, coupling_list, prefix='R'):
     """
     Returns
     -------
     h_list: [[(str, ndarray)]]
     """
     omega_list, _, dim_list = [getattr(self, name) for name in self.INNER]
     elec_leaf = self.elec_leaf
     projector = np.array([[0., 1.], [1., 0.]])
     h_list = []
     zipped = zip(dim_list, omega_list, coupling_list)
     for n, (dim, omega, c) in enumerate(zipped):
         ph = Phonon(dim, omega)
         leaf = prefix + str(n)
         # e-ph part
         h_list.append([[leaf, omega * ph.coordinate_operator],
                        [elec_leaf, (c / omega) * projector]])
     return h_list
Example #24
0
    def _single_eom(self, tensor, n, cache=False):
        """C.f. `Multi-Configuration Time Dependent Hartree Theory: a Tensor
        Network Perspective`, p38. This method does not contain the `i hbar`
        coefficient.

        Parameters
        ----------
        tensor : Tensor
            Must in a graph with all nodes' array set, including the leaves.
        n : int
            No. of Hamiltonian term.

        Return:
        -------
        array : ndarray
            With the same shape with tensor.shape.
        """
        partial_product = Tensor.partial_product
        partial_trace = Tensor.partial_trace
        partial_env = tensor.partial_env

        # Env Hamiltonians
        tmp = tensor.array
        for i in range(tensor.order):
            try:
                env_ = self.env_[(n, tensor, i)]
            except KeyError:
                env_ = partial_env(i, proper=True)
                if cache:
                    self.env_[(n, tensor, i)] = env_
            tmp = partial_product(tmp, i, env_)
        # For non-root nodes...
        if tensor.axis is not None:
            # Inversion
            axis, inv = tensor.axis, self.inv_density[tensor]
            tmp = partial_product(tmp, axis, inv)
            # Projection
            tmp_1 = np.array(tmp)
            array = tensor.array
            conj_array = np.conj(array)
            tmp = partial_trace(tmp, axis, conj_array, axis)
            tmp = partial_product(array, axis, tmp, j=1)
            tmp = (tmp_1 - tmp)
        return tmp
Example #25
0
    def _partial_transform(i, tensor, mat):
        r"""
        Parameters
        ----------
        i : int
        tensor : (..., m_i, ...) ndarray
        mat : (n_i, m_i) ndarray

        Returns
        -------
        tensor : (..., n_i, ...) ndarray
        """
        tensor_shape = list(tensor.shape)
        shape = tensor_shape[:i] + tensor_shape[i + 1:] + [mat.shape[0]]
        v_i = np.swapaxes(tensor, -1, i)
        v_i = np.reshape(v_i, (-1, mat.shape[1]))
        v_i = np.array(list(map(mat.dot, v_i)))
        v_i = np.reshape(v_i, shape)
        v_i = np.swapaxes(v_i, -1, i)
        return v_i
Example #26
0
def heisenberg(N, J=1.0, Jz=1.0, h=0):
    r"""Generate a MPO for Heisenberg Model.

    .. math::

        H = \sum^{N-2}_{i=0} \frac{J}{2} (S^+_i S^-_{i+1} + S^-_i S^+_{i+1})
            + J_z S^z_i S^z_{i+1}
            - \sum^{N-1}_{i=0} h S^z_i

    For 1-D antiferromagnetic, :math:`J = J_z = 1`.

    Parameters
    ----------
    N : int
        number of sites.
    J : float
        coupling constant.
    Jz : float
        coupling constant in z-direction.
    h : float
        external magnetic field.

    Returns
    -------
    mpo : [(5, 5, 2, 2) ndarray]
        A list of MPO matrixes.
    """
    # Local operators
    I = np.eye(2)
    Z = np.zeros((2, 2))
    Sz = np.array([[0.5, 0.0], [0.0, -0.5]])
    Sp = np.array([[0., 0.], [1., 0.]])
    Sm = np.array([[0., 1.], [0., 0.]])
    # left-hand edge: 1*5
    Wfirst = np.array(
        [[-h * Sz, (J / 2.) * Sm, (J / 2.) * Sp, (Jz / 2.) * Sz, I]])
    # mid: 5*5
    W = np.array([[I, Z, Z, Z, Z], [Sp, Z, Z, Z, Z], [Sm, Z, Z, Z, Z],
                  [Sz, Z, Z, Z, Z],
                  [-h * Sz, (J / 2.) * Sm, (J / 2.) * Sp, (Jz / 2.) * Sz, I]])
    # right-hand edge: 5*1
    Wlast = np.array([[I], [Sp], [Sm], [Sz], [-h * Sz]])
    mpo = [Wfirst] + ([W] * (N - 2)) + [Wlast]
    return mpo
Example #27
0
 def lowering(self, vec):
     self.check_vec(vec)
     ans = np.zeros_like(vec)
     tmp = np.array([np.sqrt(i) for i in range(self.dim)]) * vec
     ans[:-1] = tmp[1:]
     return ans
Example #28
0
 def raising(self, vec):
     self.check_vec(vec)
     ans = np.zeros_like(vec)
     ans[1:] = vec[:-1]
     ans *= np.array([np.sqrt(i) for i in range(self.dim)])
     return ans
Example #29
0
def test_mctdh(fname=None):
    sys_leaf = Leaf(name='sys0')

    ph_leaves = []
    for n, (omega, g) in enumerate(ph_parameters, 1):
        ph_leaf = Leaf(name='ph{}'.format(n))
        ph_leaves.append(ph_leaf)

    def ph_spf():
        t = Tensor(axis=0)
        t.name = 'spf' + str(hex(id(t)))[-4:]
        return t

    graph, root = huffman_tree(ph_leaves, obj_new=ph_spf, n_branch=2)
    try:
        graph[root].insert(0, sys_leaf)
    except KeyError:
        ph_leaf = root
        root = Tensor()
        graph[root] = [sys_leaf, ph_leaf]
    finally:
        root.name = 'wfn'
        root.axis = None

    stack = [root]
    while stack:
        parent = stack.pop()
        for child in graph[parent]:
            parent.link_to(parent.order, child, 0)
            if child in graph:
                stack.append(child)

    # Define the detailed parameters for the ML-MCTDH tree
    h_list = model.wfn_h_list(sys_leaf, ph_leaves)
    solver = MultiLayer(root, h_list)
    bond_dict = {}
    # Leaves
    for s, i, t, j in root.linkage_visitor():
        if t.name.startswith('sys'):
            bond_dict[(s, i, t, j)] = 2
        else:
            if isinstance(t, Leaf):
                bond_dict[(s, i, t, j)] = max_tier
            else:
                bond_dict[(s, i, t, j)] = rank_wfn
    solver.autocomplete(bond_dict)
    # set initial root array
    init_proj = np.array([[A, 0.0], [B, 0.0]]) / np.sqrt(A**2 + B**2)
    root_array = Tensor.partial_product(root.array, 0, init_proj, 1)
    root.set_array(root_array)

    solver = MultiLayer(root, h_list)
    solver.ode_method = 'RK45'
    solver.cmf_steps = solver.max_ode_steps  # constant mean-field
    solver.ps_method = 'split'
    solver.svd_err = 1.0e-14

    # Define the obersevable of interest
    logger = Logger(filename=prefix + fname, level='info').logger
    logger2 = Logger(filename=prefix + 'en_' + fname, level='info').logger
    for n, (time, r) in enumerate(
            solver.propagator(
                steps=count,
                ode_inter=dt_unit,
                split=True,
            )):
        if n % callback_interval == 0:
            t = Quantity(time).convert_to(unit='fs').value
            rho = r.partial_env(0, proper=False)
            logger.info("{}    {} {} {} {}".format(t, rho[0, 0], rho[0, 1],
                                                   rho[1, 0], rho[1, 1]))
            en = np.trace(rho @ model.h)
            logger2.info('{}    {}'.format(t, en))
Example #30
0
ph_parameters = [
    #(Quantity(400, 'cm-1').value_in_au, Quantity(500, 'cm-1').value_in_au),
    #(Quantity(800, 'cm-1').value_in_au, Quantity(500, 'cm-1').value_in_au),
    #(Quantity(1200, 'cm-1').value_in_au, Quantity(500, 'cm-1').value_in_au),
    (Quantity(1600, 'cm-1').value_in_au, Quantity(500, 'cm-1').value_in_au),
]
dof = len(ph_parameters)

drude = Drude(
    gamma=Quantity(20, 'cm-1').value_in_au,
    lambda_=Quantity(400, 'cm-1').value_in_au,
    beta=beta,
)

model = SBM(
    sys_ham=np.array([[-0.5 * e, v], [v, 0.5 * e]], dtype=DTYPE),
    sys_op=np.array([[-0.5, 0.0], [0.0, 0.5]], dtype=DTYPE),
    ph_parameters=ph_parameters,
    ph_dims=(dof * [max_tier]),
    bath_corr=drude,
    bath_dims=[max_tier],
)

# init state
A, B = 1.0, 1.0
wfn_0 = np.array([A, B]) / np.sqrt(A**2 + B**2)
rho_0 = np.tensordot(wfn_0, wfn_0, axes=0)

# Propagation
dt_unit = Quantity(0.001, 'fs').value_in_au
callback_interval = 100