Exemple #1
0
def get_r6_1d_dressed_coupling_nn(V0, rc, L, ktrunc, bc, verbose=False):
    """ Return coupling list for the following "dressed-state" n-n interaction:
        V(r) = V0 / (r/r)^6 + 1
        """
    check_bc(bc)
    f = get_r6_dressed_interaction(V0, rc)
    return get_1d_r_coupling_nn(f, L, ktrunc, bc, verbose=verbose)
Exemple #2
0
def get_min_dist(x1, x2, y1, y2, Lx, Ly, bc):
    check_bc(bc)
    if bc == 'periodic':
        dx = min_lin_dist_pbc(x2 - x1, Lx)
        dy = min_lin_dist_pbc(y2 - y1, Ly)
    else:
        dx = np.abs(x2 - x1)
        dy = np.abs(y2 - y1)
    return np.sqrt(dx**2 + dy**2)
Exemple #3
0
def make_dressed_r6_1d(Delta,
                       Omega,
                       V0,
                       Rc,
                       ktrunc,
                       basis,
                       gamma=None,
                       bc='periodic',
                       dtype=np.float64,
                       verbose=False):
    """ Returns quspin hamiltonian:
        
        H = -sum_i Delta_i n_i -  sum_i (omega_i)/2) x_i + sum_(pairs ij) V_ij n_i n_j
        where
        V_ij =  V0 / ( (r / Rc)^6 + 1)
        for a 1d lattice.
     gamma (optional, default None): a list of two single-site amplitude-decay rates, specifying upper and lower decay rates respectively.
                If a list of gamma values is specifed, a nonhermitian term
                -1j * (gamma[0]/2) * sum_i n_i - 1j * (gamma[1]/2) * sum_i (1-n_i)
                will be added to the hamiltonian
                
                
                ktrunc = integer, interaction truncation. H will include 1/r^6 interactions of the form shown above up to kth-nearest-neighbors
                
            If verbose=True: some info on hamiltonian construction is given.
                """
    check_bc(bc)
    L = basis.L
    if not isinstance(basis, boson_basis_1d):
        raise TypeError("invalid basis type")
    if not (gamma is None):
        try:
            if len(gamma) != 2:
                raise ValueError("List of decay rates should have length 2.")
        except TypeError:
            raise TypeError("Gamma should be a list")
    check_herm = True
    if gamma is not None:
        vprint(verbose, "Decay provided. herm=false, dtype=complex")
        check_herm = False
        dtype = np.complex128
    static = get_r6_1d_dressed_static(Delta,
                                      Omega,
                                      V0,
                                      Rc,
                                      L,
                                      ktrunc,
                                      gamma,
                                      bc,
                                      verbose=verbose)
    dynamic = []
    return hamiltonian(static,
                       dynamic,
                       basis=basis,
                       dtype=dtype,
                       check_herm=check_herm)
Exemple #4
0
def make_nnZ(n,
             Jn,
             Jx,
             coup_list,
             L,
             basis=None,
             bc='periodic',
             dtype=np.float64):
    """ return uniform 1d hamiltonian with interactions up to nth-nearest-neighbors. 
        coup_list = list of couplings [V1, ..., Vn] such that each pair of sites (i, i+n) has an interaction term V_n n_i n_i+n, where n are the on-site density operators. The single-site hamiltonian is
       
        """
    check_bc(bc)
    if basis is None:
        basis = get_hcb_basis(L)
    if not isinstance(basis, boson_basis_1d):
        raise TypeError(
            "this function is only implemented for hard-core bosons")
    static = get_nnZ_static_hcb(n, Jn, Jx, L, coup_list, bc=bc)
    dynamic = []
    return hamiltonian(static, dynamic, basis=basis, dtype=np.float64)
Exemple #5
0
def get_1d_r_coupling_nn(f, L, ktrunc, bc, verbose=False):
    """ Return coupling list [[J, i, i+k], ...] for n-n coupling in a boson model (n being the occupation operator)
        f = some function of r, the inter-site distance, which determines the coupling between sites i and i+r (independent of index i). The form of the corresponding Hamiltonian is
        H = sum (pairs i,j) f(|i-j|) ni nj
        the sum running over all distinct pairs.
        
        If an LxL hermitian matrix is input as f, the off-diagonal elements of that matrix will be used directly to construct the hamiltonian, ie
        H = sum (pairs ij) f_ij ni nj
        In that case, the truncation range will be ignored.
        
        ktrunc = defines the cutoff range for the potential f: sites separated by more than ktrunc will not interact (will not be included in the coupling list)
        """
    check_bc(bc)
    if isinstance(f, np.ndarray):
        vprint("Direct coupling matrix provided. Truncation length ignored.")
        coupling_nn = get_coupling_from_matrix(L, f, verbose=verbose)
    else:
        vprint(verbose,
               "Scalar interaction provided. f(r) matrix will be constructed")
        #max number of couplings per site
        if bc == 'open':
            nc = min(ktrunc, L - 1)
        else:
            nc = min(ktrunc, L // 2)

        coup_list = np.empty(nc)
        if ktrunc >= L:
            print("Warning--interactions longer than L are discarded.")
        for i in range(1, nc + 1):
            v = f(i)
            if i == L / 2 and bc == 'periodic':  #this bond will be overcounted in the final sum
                v = v / 2.0
            coup_list[i - 1] = v

        coupling_nn = []
        for i in range(nc):
            coupling_nn = coupling_nn + get_nth_order_coupling(
                coup_list[i], L, i + 1, bc)
    return coupling_nn
Exemple #6
0
def make_kladder_symmetric_SPIN(Delta,
                                Omega,
                                V1,
                                V2,
                                k,
                                L,
                                basis=None,
                                bc='periodic'):
    """ Returns the following hamiltonian:
        H = - Delta sum_i n_i - (Omega/2) sum_i X_i + V1 sum_e (nn)_e
        where the last term joins any two sites which are the same or adjacent rungs.
        
        Assumes periodic boundary conditions (in the sense that the last rung joins to the first)
        L = number of rungs
        k = width (number of sites) of each rung
        
      Site ordering: The index i of the individual sites always increases left-to-right. At the end of the ladder, it moves down one step and keeps increasing.
      For a example, for a 2-ladder of length 8 the sites are as follows:
          0  1  2  3  4  5  6  7
          8  9  10 11 12 13 14 15
          
     This is 'thread' ordering, as opposed to 'snake' ordering where sites i, i+1 are always adjacent.  
     
        
    """
    raise TypeError("deprecated")
    check_bc(bc)
    if bc == 'open':
        raise TypeError("Ladder with open BC's is not implemented!")
    if basis is None:
        print("Generating basis")
        basis = spin_basis_1d(k * L, pauli=True)

    #coupling strengths in the Pauli basis
    #special case, the next-nearest will overcount by factor 2
    if L == 4:
        V2 = V2 / 2.0
    Jx_pauli = -(Omega / 2.0)
    Jz_pauli = -Delta / 2.0 + (V1 / 4.0) * (3 * k - 1) + (V2 / 4.0) * 2 * k
    Jzz_pauli_1nn = V1 / 4.0
    Jzz_pauli_2nn = V2 / 4.0

    N = k * L
    coupling_x = get_site_coupling(Jx_pauli, N)
    coupling_z = get_site_coupling(Jz_pauli, N)

    #matrix which stores the thread-order labels
    site_labels = np.empty((k, L), dtype=int)
    for i in range(k):
        site_labels[i, :] = np.array(range(L)) + i * L

    #all terms proportional to V1, ie nearest-neighbor sites
    coupling_zz_1nn = []

    for i in range(L):
        #this adds the interactions between sites on the same rung
        prs = get_all_pairs(site_labels[:, i])
        coupling_zz_1nn += [[Jzz_pauli_1nn] + p for p in prs]
        #this adds the interactions between sites on neighboring rungs
        for j in range(k):
            coupling_zz_1nn += [[
                Jzz_pauli_1nn, site_labels[j, i], site_labels[m, (i + 1) % L]
            ] for m in range(k)]

    #all terms proportional to V2, i.e. next-nearest-neighbor rungs
    coupling_zz_2nn = []
    for i in range(L):
        for j in range(k):
            coupling_zz_2nn += [[
                Jzz_pauli_2nn, site_labels[j, i], site_labels[m, (i + 2) % L]
            ] for m in range(k)]

    static = [["z", coupling_z], ["x", coupling_x],
              ["zz", coupling_zz_1nn + coupling_zz_2nn]]
    dynamic = []

    return hamiltonian(static, dynamic, basis=basis)
Exemple #7
0
def make_kladder_symmetric(Delta,
                           Omega,
                           V1,
                           V2,
                           k,
                           L,
                           basis=None,
                           bc='periodic',
                           dtype=np.float64):
    """ Returns the following hamiltonian:
        H = - Delta sum_i n_i - (Omega/2) sum_i X_i + V1 sum_e (nn)_e
        where the last term joins any two sites which are the same or adjacent rungs.
        
        Assumes periodic boundary conditions (in the sense that the last rung joins to the first)
        L = number of rungs
        k = width (number of sites) of each rung
        
      Site ordering: The index i of the individual sites always increases left-to-right. At the end of the ladder, it moves down one step and keeps increasing.
      For a example, for a 2-ladder of length 8 the sites are as follows:
          0  1  2  3  4  5  6  7
          8  9  10 11 12 13 14 15
          
     This is 'thread' ordering, as opposed to 'snake' ordering where sites i, i+1 are always adjacent.  
     
        
    """

    check_bc(bc)
    if bc == 'open':
        raise TypeError("Ladder with open BC's is not implemented!")
    if basis is None:
        print("Generating basis")
        basis = get_hcb_basis(k * L)
    if not (isinstance(basis, boson_basis_1d)
            or isinstance(basis, boson_basis_general)):
        raise TypeError("Only implemented for hcb basis")

    #special case, the next-nearest will overcount by factor 2
    if L == 4:
        V2 = V2 / 2.0
    Jx = -(Omega / 2.0)
    Jn = -Delta
    Jnn_nn1 = V1
    Jnn_nn2 = V2
    #total number of sites
    N = k * L
    coupling_x = get_site_coupling(Jx, N)
    coupling_n = get_site_coupling(Jn, N)

    #matrix which stores the thread-order labels
    site_labels = np.empty((k, L), dtype=int)
    for i in range(k):
        site_labels[i, :] = np.array(range(L)) + i * L

    #all terms proportional to V1, ie nearest-neighbor sites
    coupling_nn_nn1 = []

    for i in range(L):
        #this adds the interactions between sites on the same rung
        prs = get_all_pairs(site_labels[:, i])
        coupling_nn_nn1 += [[Jnn_nn1] + p for p in prs]
        #this adds the interactions between sites on neighboring rungs
        for j in range(k):
            coupling_nn_nn1 += [[
                Jnn_nn1, site_labels[j, i], site_labels[m, (i + 1) % L]
            ] for m in range(k)]

    #all terms proportional to V2, i.e. next-nearest-neighbor rungs
    coupling_nn_nn2 = []
    for i in range(L):
        for j in range(k):
            coupling_nn_nn2 += [[
                Jnn_nn2, site_labels[j, i], site_labels[m, (i + 2) % L]
            ] for m in range(k)]

    static = [["n", coupling_n], ["+", coupling_x], ["-", coupling_x],
              ["nn", coupling_nn_nn1 + coupling_nn_nn2]]
    dynamic = []

    return hamiltonian(static, dynamic, basis=basis, dtype=dtype)
Exemple #8
0
def make_r6_1d(Delta,
               Omega,
               V,
               ktrunc,
               basis,
               gamma=None,
               bc='open',
               dtype=np.float64,
               verbose=False):
    """returns the hamiltonian operator for a 1d rydberg chain with laser parameters as input. 
        HCB basis.
        
        H = -sum_i Delta_i n_i -  sum_i (omega_i)/2) x_i + sum_(ij) V_ij n_i n_j
        where
        V_ij = C / a^6 (i-j)^6
        for a 1d lattice.
        
        
        Inputs:
            Delta, Omega -- n and x couplings respectively
            V: the nearest-neighbor interaction (|i-j|=1)
            If Delta and Omega are scalars, a uniform hamiltonian is generated with delta_i= delta, etc. If they are iterables, the ith element will specify the coupling (eg delta_i) at the ith site.
            
            If V is input as a single scalar,
                Vij= V / |i-j|^6
                
            V may also be input as a hermitian matrix, in which case the i,j element will specify Vij. Note that in that case you'll have to put in power-law behavior by hand.
            
            gamma (optional, default None): a list of two single-site amplitude-decay rates, specifying upper and lower decay rates respectively.
            If a list of gamma values is specifed, a nonhermitian term
            -1j * (gamma[0]/2) * sum_i n_i - 1j * (gamma[1]/2) * sum_i (1-n_i)
            will be added to the hamiltonian
            
            
            ktrunc = integer, interaction truncation. H will include 1/r^6 interactions of the form shown above up to kth-nearest-neighbors
            
        If verbose=True: some info on hamiltonian construction is given.

    """
    check_bc(bc)
    L = basis.L
    if not isinstance(basis, boson_basis_1d):
        raise TypeError("invalid basis type")
    if not (gamma is None):
        try:
            if len(gamma) != 2:
                raise ValueError("List of decay rates should have length 2.")
        except TypeError:
            raise TypeError("Gamma should be a list")

    check_herm = True
    if gamma is not None:
        vprint(verbose, "Decay provided. herm=false, dtype=complex")
        check_herm = False
        dtype = np.complex128

    static = get_r6_1d_static(Delta,
                              Omega,
                              V,
                              L,
                              ktrunc,
                              gamma,
                              bc=bc,
                              verbose=verbose)
    dynamic = []
    return hamiltonian(static,
                       dynamic,
                       basis=basis,
                       dtype=dtype,
                       check_herm=check_herm)