def diagonalize_critical_floquet_system(trap_freq, lattice_depth, site_spacing_um,
                               gamma,
                               n_sites, floquet_m_radius,
                               sort=True):
    """Build and diagonalize the Floquet problem for breathing lattice
    
    Inputs:
    trap_freq: Harmonic trapping frequency, E/h (Hz) units
    lattice_depth: Lattice depth parameter V_0 before a cos (not cos^2), E/h (Hz)
    site_spacing_um: Lattice site spacing, in microns
    gamma: Drive amplitude parameter, 0<gamma<1
    n_sites: Number of sites to include in the lattice, should be odd
    floquet_m_radius: Number of Floquet couplings to use, generates 2m+1 blocks
    
    Optional Inputs:
    sort [True]: If True, output eigenvalues and eigenvectors are return in order of increasing eigenvalue
    
    Globals Accessed: sim_mass?
    
    Returns 3 tuple:
    drive:     critical drive frequency used
    evals:     eigenvalues of floquet Hamiltonian (possibly sorted, not modulus)
    evecs:     eigenvectors of floquet Hamiltonian (possibly sorted)
    """
    # Compute needed coefficients
    n_floquet = 2*floquet_m_radius + 1
    lattice_tunneling = tunneling_J(lattice_depth, lattice_recoil_energy(site_spacing_um))
    jsq_scale = gen_jsq_coeffs(site_spacing_um, trap_freq, gamma, n_floquet)
    h0_scale = dc.all_chis(dc.y(gamma))
    crit_drive = dc.crit_drive_freq(dc.y(gamma), trap_freq)
    # Build up floquet problem
    jsq_block = on_site_jsq(n_sites)
    tun_block = tunneling_block(n_sites, lattice_tunneling)
    floquet_h = build_floquet_jsq(jsq_block, floquet_m_radius, jsq_scale)
    floquet_h = add_tunneling_blocks(floquet_h, floquet_m_radius, tun_block, h0_scale)
    floquet_h = add_floquet_diag(floquet_h, floquet_m_radius, crit_drive)
    # Some consistency checks, warn but do not stop.
    if not np.allclose(floquet_h.T, floquet_h):
        # More stringent, requires only real entries
        logger.warn("Symmetry test failed for this gamma {}".format(gamma))
    if not np.allclose(np.conj(floquet_h.T), floquet_h):
        logger.warn("Conjugate transpose test failed for this gamma {}".format(gamma))
    # Diagonalize, return results, copies because the inner workings of h5py aren't clear to me
    evals, evecs = LA.eigh(floquet_h) # Uses faster algo than eig(), guaranteed real evals too!
    if sort:
        sort_order = np.argsort(evals)
        return crit_drive, evals[sort_order], evecs[:, sort_order]
    else:
        return crit_drive, evals, evecs
Example #2
0
def build_sys(u_over_j, j_tunn, trap_freq, drive_freq, basis_states,
              floquet_radius, gamma):
    drive_y = drive_coefficients.y(gamma)
    drive_freq = drive_coefficients.crit_drive_freq(drive_y, trap_freq)
    m_list = np.arange(-floquet_radius, floquet_radius + 1)
    raw_int = fock_basis.onsite_interactions(basis_states)
    raw_hop = -j_tunn * fock_basis.nearest_neighbor_hopping(basis_states)
    raw_jsq_onsite = fock_basis.onsite_offset(
        fock_basis.jsq_offset(basis_states.shape[1]), basis_states)
    scale_idxs = np.abs(
        np.arange((2 * floquet_radius + 1))[np.newaxis, :] -
        np.arange((2 * floquet_radius + 1))[:, np.newaxis])
    small_xi_blocks = drive_coefficients.n_small_xis(2 * floquet_radius + 1,
                                                     drive_y)[scale_idxs]
    big_xi_blocks = drive_coefficients.n_big_xis(2 * floquet_radius + 1,
                                                 drive_y)[scale_idxs]
    jsq_prescale = tpf * (np.square(trap_freq * small_xi_blocks) -
                          np.square(drive_freq * big_xi_blocks))

    chi = drive_coefficients.all_chis(drive_y)
    chi_blocks = (np.diag(np.full(2 * floquet_radius + 1, chi[0])) +
                  np.diag(np.full(2 * floquet_radius, chi[1]), k=1) +
                  np.diag(np.full(2 * floquet_radius, chi[1]), k=-1) +
                  np.diag(np.full(2 * floquet_radius - 1, chi[2]), k=2) +
                  np.diag(np.full(2 * floquet_radius - 1, chi[2]), k=-2))
    floquet_interactions = 0.5 * u_over_j * j_tunn * np.kron(
        chi_blocks, raw_int)
    floquet_diag = np.kron(np.diag(m_list),
                           np.diag(np.full(basis_states.shape[0], drive_freq)))
    floquet_tunneling = np.kron(chi_blocks, raw_hop)
    floquet_offsets = np.kron(jsq_prescale, raw_jsq_onsite)
    return floquet_interactions + floquet_diag + floquet_tunneling + floquet_offsets
def gen_jsq_coeffs(site_spacing_um, trap_freq, gamma, n_floquet):
    """Generate the j^2 operators prefactors for the driven system
    
    Inputs:
    site_spacing_um: Site spacing, in microns
    trap_freq:       Harmonic trap frequency in Hz (Natural f, not omega)
    gamma:           Drive amplitude
    n_floquet:       number of Floquet couplings required"""
    # In paper, prefactor is 1/2 m * a^2 * (ang freq ^2), since we're requiring nat. freq, need 4 pi^2
    prefactor = 2.0 * np.pi * np.pi * sim_mass * um2 * site_spacing_um * site_spacing_um/h
    crit_xis = dc.n_crit_xis(n_floquet, dc.y(gamma))
    return (prefactor * trap_freq * trap_freq * crit_xis)
labelLines(all_lines, align=False)
for idx in np.arange(4):
    plt.loglog(gammas, np.flipud(np.abs(small[:,idx+1])), label=idx, c='k')
                       #ls=(':' if big[1,idx] < 0 else 'solid'), c=kelly_colors[idx])

ax.set_title('$|\\xi_n| = |(\\kappa^{2})_n|$')
ax.set_xlabel('$\\gamma$')
plt.xlim(1e-5,0.5)
plt.ylim(1e-12, 10)
plt.setp(ax.get_yticklabels(), visible=False)
ax.tick_params(axis='both', which='both', direction='in', bottom=True, left=True, top=True, right=True)

# Chis
chis = np.empty((3, len(gammas)))
for idx, gamma in enumerate(gammas):
    chis[:, idx] = dc.all_chis(dc.y(gamma))
ax1.loglog(gammas, chis.T)
ax1.set_title('$\\chi_n = (\\kappa^{-2})_n$')
ax1.set_xlabel('$\\gamma$')
plt.xlim(1e-5,0.5)
plt.ylim(1e-12, 10)
ax.xaxis.set_minor_locator(locmin)
ax.xaxis.set_minor_formatter(matplotlib.ticker.NullFormatter())
ax1.xaxis.set_minor_locator(locmin)
ax1.xaxis.set_minor_formatter(matplotlib.ticker.NullFormatter())
ax1.tick_params(axis='both', which='both', direction='in', bottom=True, left=True, top=True, right=True)
fig.tight_layout()
plt.subplots_adjust(wspace=0.0)
fig.savefig(outdir + 'fourier_loglog.pdf', dpi=300, pad_inches=0)

Example #5
0
# In[133]:

for idx, gamma in enumerate(gamma_vals):
    plt.plot(np.full(len(results[idx]), gamma),
             np.mod(results[idx] + 200., 1000.) - 200., ',k')
plt.ylim(-200, 800)
plt.xlim(0, 0.5)
plt.savefig('/home/zachsmith/Desktop/lines.png', dpi=300)

# In[152]:

f_drive = np.empty(len(gamma_vals))
for idx, gamma in enumerate(gamma_vals):
    plt.plot(np.full(len(results[idx]), gamma), results[idx], ',k')
    f_drive[idx] = drive_coefficients.crit_drive_freq(
        drive_coefficients.y(gamma), 25.)
plt.plot(gamma_vals, 0.5 * f_drive + 60, 'r')
plt.plot(gamma_vals, -0.5 * f_drive + 60, 'r')
plt.plot(gamma_vals, np.full(len(gamma_vals), 60), '--r')
plt.ylim(-0, 100)
plt.xlim(0, 0.5)
plt.tight_layout()
plt.savefig('/home/zachsmith/Desktop/lines.png', dpi=300)

# In[92]:

for idx, gamma in enumerate(gamma_vals):
    plt.plot(np.full(len(results[idx]), gamma), results[idx], ',k')
plt.ylim(-100, 200)
plt.xlim(0, 0.5)
plt.tight_layout()
Example #6
0
def diagonalize_floquet_system(trap_freq,
                               lattice_depth,
                               site_spacing_um,
                               drive_freq,
                               gamma,
                               n_mathieu_basis,
                               n_h0_states,
                               floquet_m_radius,
                               sort=True):
    """Build and diagonalize the Floquet problem for breathing lattice
    
    Inputs:
    trap_freq: Harmonic trapping frequency, E/h (Hz) units
    lattice_depth: Lattice depth parameter V_0 before a cos (not cos^2), E/h (Hz)
    site_spacing_um: Lattice site spacing, in microns
    drive_freq: Natural drive frequency, in (Hz)
    gamma: Drive amplitude parameter, 0<gamma<1
    n_mathieu_basis: Number of basis vectors to use in underlying mathieu function computation
    n_h0_states: Number of states to keep in time-averaged Hamiltonian, this is the size of the H-space in the Floquet problem
    floquet_m_radius: Number of Floquet couplings to use, generates 2m+1 blocks
    
    Optional Inputs:
    sort [True]: If True, output eigenvalues and eigenvectors are return in order of increasing eigenvalue
    
    Globals Accessed: sim_mass?
    
    Returns 3 tuple:
    h0_states: eigenstates of time-averaged Hamiltonian/basis states for floquet Hamiltonian
    evals:     eigenvalues of floquet Hamiltonian (possibly sorted, not modulus)
    evecs:     eigenvectors of floquet Hamiltonian (possibly sorted)
    """
    # Compute needed coefficients
    n_floquet = 2 * floquet_m_radius + 1
    lattice_tunneling = tunneling_J(lattice_depth,
                                    lattice_recoil_energy(site_spacing_um))
    raw_jsq_scale = gen_jsq_coeffs(site_spacing_um, drive_freq, trap_freq,
                                   gamma, n_floquet)
    h0_jsq_scale = raw_jsq_scale[0]
    h0_scale_factors = dc.all_chis(dc.y(gamma))
    adj_jsq_scale = adjust_jsq_coefs(raw_jsq_scale, h0_scale_factors)
    # Find solution to time-averaged part
    h0_en, h0_states = h0.lattice_plus_trap_sitespace(n_mathieu_basis,
                                                      n_h0_states,
                                                      lattice_tunneling,
                                                      h0_jsq_scale)
    # Build up floquet problem
    jsq_op = h0.jsq_op_statespace(h0_states)
    floquet_h = build_floquet_jsq(jsq_op, floquet_m_radius, adj_jsq_scale)
    floquet_h = add_h0_diags(floquet_h, floquet_m_radius, h0_en,
                             h0_scale_factors)
    floquet_h = add_floquet_diag(floquet_h, floquet_m_radius, drive_freq)
    # Some consistency checks, warn but do not stop.
    if not np.allclose(floquet_h.T, floquet_h):
        # More stringent, requires only real entries
        logger.warn("Symmetry test failed for this gamma {}".format(gamma))
    if not np.allclose(np.conj(floquet_h.T), floquet_h):
        logger.warn(
            "Conjugate transpose test failed for this gamma {}".format(gamma))
    # Diagonalize, return results, copies because the inner workings of h5py aren't clear to me
    evals, evecs = LA.eigh(
        floquet_h)  # Uses faster algo than eig(), guaranteed real evals too!
    if sort:
        sort_order = np.argsort(evals)
        return h0_states.T, evals[sort_order], evecs[:, sort_order]
    else:
        return h0_states.T, evals, evecs