Flux Noise Mask Design

Still to do:

  • simulate mutual
  • simulate T1 limit from 100aF xy line

Problems with mask:

  • One of the XY lines is messed up
  • capacitances change resonator frequencies so nothing matches

Transmon Selected params:

  • w = 34, l_c = 90, w_c = 150:
    • C_q = 75.1fF
    • C_g = 3.87fF
    • C_resToGnd = 79.1fF
  • d_xy = 80: C_xy = 99.5fF

Charge Sensitive Selected params:

  • w = 14, l_c = 90, w_c = 200:
    • C_q = 48.5fF
    • C_g = 2.94fF
    • C_resToGnd = 107fF
  • d_xy = 50: C_xy = 95.5fF

In [8]:
import cpwtools
reload(cpwtools)
inductiveCoupling = __import__("Transmission Lines.inductiveCoupling")
import numpy as np
from scipy.constants import mu_0, epsilon_0, pi, hbar, e, c
from scipy.constants import physical_constants
from scipy.optimize import fsolve, root

CPW

We want to use the same cpw dimensions for resonator and feedline/purcell filter cpw's so the kinetic inductance correction is the same for everything.


In [9]:
cpw = cpwtools.CPW(material='al', w=10., s=7.)
print cpw


Cl = 0.000164468902665 pF/um
Ll = 0.000432649750216 nH/um
vph = 1.1854681054e8 m/s
z0 = 51.2892479688 Ohms

$\lambda/4$ readout resonators

IMPAs from Google will be good in the 4-6GHz range. We will aim for resonators near 6GHz, but have a spread from 5-6GHz on the mask. They should be spread every 30MHz or so.


In [10]:
L4 = cpwtools.QuarterLResonator(cpw,5920)
l_curve = 2*pi*50/4
coupling_length = 120
tot_length = l_curve*(1+1+2+2+2+2) + 2*1000 + 1150 + 350 + 500 + coupling_length # this coupling length ranges from 45-150 depending on desired Qc.  
                                                                                 # Plan for 45, can always trombone down
for f in [5,5.2,5.4,5.6,5.8,6]:
    length = L4.setLengthFromFreq(f*1e9)*1e6
    print"{:.1f}GHz: l = {:.2f}um  C_r = {:.2f}um  extension = {:.2f}um".format(
        f, length, 1e15*L4.C(), (tot_length-length)/2)

L4.setLengthFromFreq(5.93*1e9)
L4.addCapacitiveCoupling('g',79.1e-15)
print
L4.l = tot_length*1e-6
print ("The frequency is brought down by the capacitance to ground of the coupling capacitor at the end.  "
       "Unforunately, this capacitance was not taken into account for the mask.  The highest frequency we can go is {:.3f}GHz".format(L4.fl()/1e9))

print
# For charge sensitive (qubit 4)
L4.l = 4905e-6
L4.addCapacitiveCoupling('g',107e-15)
print 'charge sensitive:'
print"l = {:.2f}um  f_l = {:.3f}GHz  C_r = {:.2f}um  extension = {:.2f}um".format(
    L4.l*1e6, L4.fl()/1e9, 1e15*L4.C(), (tot_length-L4.l*1e6)/2)

# For 3 transmons:
print 'transmons:'
L4.addCapacitiveCoupling('g',79.1e-15)
f_start = 6.04
for f in [f_start,f_start-1*0.04,f_start-2*0.04,f_start-3*0.04]:
    length = L4.setLengthFromFreq(f*1e9)*1e6
    print"l = {:.2f}um  f_l = {:.3f}GHz  C_r = {:.2f}fF  extension = {:.2f}um".format(
        length, L4.fl()/1e9, 1e15*L4.C(), (tot_length-length)/2)

C_r = L4.C()


5.0GHz: l = 5927.34um  C_r = 487.43um  extension = -510.97um
5.2GHz: l = 5699.37um  C_r = 468.68um  extension = -396.98um
5.4GHz: l = 5488.28um  C_r = 451.33um  extension = -291.44um
5.6GHz: l = 5292.27um  C_r = 435.21um  extension = -193.44um
5.8GHz: l = 5109.78um  C_r = 420.20um  extension = -102.19um
6.0GHz: l = 4939.45um  C_r = 406.19um  extension = -17.03um

The frequency is brought down by the capacitance to ground of the coupling capacitor at the end.  Unforunately, this capacitance was not taken into account for the mask.  The highest frequency we can go is 5.534GHz

charge sensitive:
l = 4905.00um  f_l = 5.394GHz  C_r = 403.36um  extension = 0.20um
transmons:
l = 4906.74um  f_l = 5.533GHz  C_r = 403.50fF  extension = -0.67um
l = 4939.45um  f_l = 5.499GHz  C_r = 406.19fF  extension = -17.03um
l = 4972.60um  f_l = 5.465GHz  C_r = 408.92fF  extension = -33.60um
l = 5006.20um  f_l = 5.431GHz  C_r = 411.68fF  extension = -50.40um

Qubit parameters

From Ted Thorbeck's notes:
$E_c = \frac{e^2}{2C}$, $E_c/\hbar=\alpha=\text{anharmonicity}$
$E_J = \frac{I_o \Phi_0}{2 \pi} $
$\omega_q = \sqrt{8E_JE_c}/\hbar $
$g = \frac{1}{2} \frac{C_g}{\sqrt{(C_q+C_g)(C_r+C_g)}}\sqrt{\omega_r\omega_q}$

We want g in the range 25-200MHz for an ideal anharmonicity $\alpha$=250MHz


In [11]:
omega_r = 2*pi*5.49e9 # readout resonator (average) angular frequency
omega_q = 2*pi*4.625e9 # qubit angular frequency

def EkdivEc(ng=[0.5], Ec=1.0/4.0, Ej=2.0, N=50):
    # from https://github.com/thomasaref/TA_software/blob/3fea8a37d86239353dccd7a1b71dcedb41b7e64c/test_code/IDTQubitdesignpy.py#L62
    # calculates transmon energy level with N states (more states is better approximation)
    # effectively solves the mathieu equation but for fractional inputs (which doesn't work in scipy.special.mathieu_a
    d1=[]
    d2=[]
    d3=[]
    for a in ng:
        NL=2*N+1
        A=np.zeros((NL, NL))
        for b in range(0,NL):
            A[b, b]=4.0*Ec*(b-N-a)**2
            if b!=NL-1:
                A[b, b+1]= -Ej/2.0
            if b!=0:
                A[b, b-1]= -Ej/2.0
        w,v=np.linalg.eig(A)
        d1.append(min(w))#/h*1e-9)
        w=np.delete(w, w.argmin())
        d2.append(min(w))#/h*1e-9)
        w=np.delete(w, w.argmin())
        d3.append(min(w))#/h*1e-9)
    return np.array(d1), np.array(d2), np.array(d3)

class Qubit(object):
    name = None
    omega_q = None
    omega_r = None
    C_r = None
    C_g = None
    C_q = None
    
    def __init__(self, name=None):
        if name:
            self.name = name
    
    def E_c(self, c=None):
        if c is None:
            c = self.C_q + self.C_g
        return e**2/2/c

    def cap_g(self, g):
        return -((self.C_q+self.C_r)*(2*g)**2 + np.sqrt((self.C_q-self.C_r)**2*(2*g)**4 + 4*self.C_q*self.C_r*(2*g)**2*self.omega_q*self.omega_r)) / (2*((2*g)**2-self.omega_q*self.omega_r))

    def g(self):
        return 1./2*self.C_g/np.sqrt((self.C_q+self.C_g)*(self.C_r+self.C_g))*np.sqrt(self.omega_r*self.omega_q)
    
    def Chi_0(self):
        g = self.g()
        return -g**2/(self.omega_q-self.omega_r)
    
    def Chi(self):
        alpha = self.alpha(self.E_c(), self.E_j())
        Delta = self.omega_q-self.omega_r
        return -self.g()**2/Delta*(-alpha)/(Delta+alpha)
    
    def Q_r(self):
        return -self.omega_r/(2*self.Chi())
    
    def E01(self, E_c, E_j, ng=[0.0]):
        d1, d2, d3 = EkdivEc(ng, E_c, E_j)
        return d2[0]-d1[0]
    
    def alpha(self, E_c, E_j, ng=[0.0]):
        d1, d2, d3 = EkdivEc(ng, E_c, E_j)
        E12 = d3[0]-d2[0]
        E01 = d2[0]-d1[0]
        return (E12 - E01)/hbar
    
    def E_j(self):
        f = lambda ej: self.E01(self.E_c(), ej) - self.omega_q*hbar
        return fsolve(f, 2*pi*15e9*hbar)[0]
    
    def I_c(self):
        return 2*pi*self.E_j()/(physical_constants['mag. flux quantum'][0])
        
    
qb = Qubit()
transmon = Qubit('              Transmon')
charge_sensitive_qubit = Qubit('Charge Sensitive Qubit')
qubits = [transmon, charge_sensitive_qubit]
for q in qubits+[qb]:
    q.C_r = C_r     # qubit-resonator coupling in Hz
    q.omega_r = omega_r
    q.omega_q = omega_q
g = 2*pi*50e6     # qubit-resonator coupling in Hz

In [12]:
print('Range of C_q on the mask:')
print "C_q = 30fF: E_c = {:.2f}MHz".format( qb.E_c(30e6)/(2*pi*hbar)*1e15 )
print "C_q = 95fF: E_c = {:.2f}MHz".format( qb.E_c(95e6)/(2*pi*hbar)*1e15 )
print
print('Ideal:')
print "Transmon:          E_c = 250MHz: C_sigma = C_q + C_g = {:.2f}fF".format( e**2/2/250e6/(2*pi*hbar)*1e15 )
print "Charge Sensitive:  E_c = 385MHz: C_sigma = C_q + C_g = {:.2f}fF".format( e**2/2/385e6/(2*pi*hbar)*1e15 )


Range of C_q on the mask:
C_q = 30fF: E_c = 645.67MHz
C_q = 95fF: E_c = 203.90MHz

Ideal:
Transmon:          E_c = 250MHz: C_sigma = C_q + C_g = 77.48fF
Charge Sensitive:  E_c = 385MHz: C_sigma = C_q + C_g = 50.31fF

In [13]:
#We choose caps from the mask:
transmon.C_q = 78.7e-15
charge_sensitive_qubit.C_q = 48.5e-15
transmon.C_g = 0e-15
charge_sensitive_qubit.C_g = 0e-15

for q in qubits:
    print "{}:  C_q = {:.2f}fF  E_c = {:.2f}MHz  E_j = {:.2f}GHz  alpha = {:.2f}MHz  g = {:.2f}MHz  C_g = {:.2f}fF".format(
        q.name, 1e15*q.C_q, -q.E_c()/(2*pi*hbar)/1e6, q.E_j()/2/pi/hbar/1e9, q.alpha(q.E_c(),q.E_j())/(2*pi)/1e6, g/2/pi/1e6, 1e15*q.cap_g(g))


              Transmon:  C_q = 78.70fF  E_c = -246.13MHz  E_j = 12.12GHz  alpha = -283.25MHz  g = 50.00MHz  C_g = 3.67fF
Charge Sensitive Qubit:  C_q = 48.50fF  E_c = -399.39MHz  E_j = 8.02GHz  alpha = -579.81MHz  g = 50.00MHz  C_g = 2.90fF

In [14]:
# We choose the closest capacitance from the mask
transmon.C_g = 3.28e-15
charge_sensitive_qubit.C_g = 2.94e-15

for q in qubits:
    print "{}:  C_g = {:.2f}fF  g = {:.2f}MHz  Chi_0/2pi = {:.2f}MHz  Chi/2pi = {:.2f}MHz  Q_r = {:.0f}  1/kappa = {:.2f}ns  I_c={:.2f}nA".format(
        q.name, 1e15*q.cap_g(q.g()), q.g()/2/pi/1e6, 1e-6*q.Chi_0()/2/pi, 1e-6*q.Chi()/2/pi, q.Q_r(), q.Q_r()/omega_r*1e9, q.I_c()*1e9)


              Transmon:  C_g = 3.28fF  g = 44.81MHz  Chi_0/2pi = 2.32MHz  Chi/2pi = -0.55MHz  Q_r = 4971  1/kappa = 144.12ns  I_c=25.31nA
Charge Sensitive Qubit:  C_g = 2.94fF  g = 50.72MHz  Chi_0/2pi = 2.97MHz  Chi/2pi = -1.11MHz  Q_r = 2472  1/kappa = 71.65ns  I_c=16.95nA

In [15]:
for q in qubits:
    print "{}: Charge dispersion = {:.3f}MHz".format(q.name, (q.E01(q.E_c(), q.E_j(), [0.0]) - q.E01(q.E_c(), q.E_j(), [0.5]))/2/pi/hbar/1e6)


              Transmon: Charge dispersion = 0.005MHz
Charge Sensitive Qubit: Charge dispersion = 3.724MHz

In [16]:
# What variation in C_g should be included on mask for the C_q variation we have?
for C_q_ in [85e-15, 29e-15, e**2/2/250e6]:
    for g_ in [2*pi*25e6, 2*pi*50e6, 2*pi*200e6]:
        qb.C_q = C_q_
        print "C_q = {:.2f}fF  g = {:.2f}MHz  C_g = {:.2f}fF".format(
            1e15*C_q_, g_/2/pi/1e6, 1e15*qb.cap_g(g_))


C_q = 85.00fF  g = 25.00MHz  C_g = 1.88fF
C_q = 85.00fF  g = 50.00MHz  C_g = 3.81fF
C_q = 85.00fF  g = 200.00MHz  C_g = 16.55fF
C_q = 29.00fF  g = 25.00MHz  C_g = 1.11fF
C_q = 29.00fF  g = 50.00MHz  C_g = 2.26fF
C_q = 29.00fF  g = 200.00MHz  C_g = 10.21fF
C_q = 0.00fF  g = 25.00MHz  C_g = 0.04fF
C_q = 0.00fF  g = 50.00MHz  C_g = 0.16fF
C_q = 0.00fF  g = 200.00MHz  C_g = 2.61fF

Feedline with and without crossovers


In [17]:
cpw.setKineticInductanceCorrection(False)
print cpw
cpwx = cpwtools.CPWWithBridges(material='al', w=1e6*cpw.w, s=1e6*cpw.s, bridgeSpacing = 250, bridgeWidth = 3, t_oxide=0.16)
cpwx.setKineticInductanceCorrection(False)
print cpwx


Cl = 0.000164468902665 pF/um
Ll = 0.000432928941855 nH/um
vph = 1.18508579536e8 m/s
z0 = 51.3057939391 Ohms
Cl = 0.000190367402031 pF/um
Ll = 0.000344035246936 nH/um
vph = 1.23566924918e8 m/s
z0 = 42.5113775272 Ohms

Inductive Coupling

From [1], we have the dephasing of a qubit:
$\Gamma_\phi = \eta\frac{4\chi^2}{\kappa}\bar{n}$, where $\eta=\frac{\kappa^2}{\kappa^2+4\chi^2}$, $\bar{n}=\left(\frac{\Delta}{2g}\right)^2$
$\Gamma_\phi = \frac{4\chi^2\kappa}{\kappa^2+4\chi^2}\left(\frac{\Delta}{2g}\right)^2$
To maximize the efficiency of readout, we want to maximize the rate of information leaving the system (into the readout chain), or equivilently, maximize dephasing.
$\partial_\kappa\Gamma_\phi = 0 = -\frac{4\chi^2(\kappa^2-4\chi^2)}{(\kappa^2+4\chi^2)^2}$ when $2\chi=\kappa$.
$2\chi = \kappa_r = \omega_r/Q_r$
$ Q_{r,c} = \frac{8Z_0}{\pi(\omega M)^2}$ [2]
We want a $Q_c$ of 3k-30k

[1] Yan et al. The flux qubit revisited to enhance coherence and reproducibility. Nature Communications, 7, 1–9. http://doi.org/10.1038/ncomms12964
[2] Matt Beck's Thesis, p.39

__________ ________ _______ ________ _________ g |<- s1 ->|<--w1-->|<--s1--> |<--d-->|<--s2-->|<--w2-->|<--s2-->| g

In [46]:
d = 10
MperL = inductiveCoupling.inductiveCoupling.CalcMutual(cpw.w*1e6, cpw.w*1e6, cpw.s*1e6, cpw.s*1e6, d, 10*cpw.w*1e6)[0]


The inductance per unit length is 3.70e-08 H/m

In [47]:
for q in qubits:
    M = 1/(np.sqrt(q.Q_r()*pi/8/cpw.z0()**2)*omega_r)
    print "{}  M = {:.2f}pH  coupling length = {:.2f}um".format(q.name, M*1e12, M/MperL*1e6)


              Transmon  M = 33.66pH  coupling length = 908.73um
Charge Sensitive Qubit  M = 47.74pH  coupling length = 1288.82um

In [49]:
for q in [3000,6000,9000,15000,21000,27000,33000]:
    print "Q_c={}  l_c={:.2f}".format(q,1/(np.sqrt(q*pi/8/cpw.z0())*omega_r)/MperL*1e6)


Q_c=3000  l_c=1169.82
Q_c=6000  l_c=827.18
Q_c=9000  l_c=675.39
Q_c=15000  l_c=523.16
Q_c=21000  l_c=442.15
Q_c=27000  l_c=389.94
Q_c=33000  l_c=352.71

Purcell Filter

Do we even need a purcell filter? [3]
Without purcell filter: $\kappa_r T_1 \le \left(\frac{\Delta}{g}\right)^2$
With purcell filter: $\kappa_r T_1 \le \left(\frac{\Delta}{g}\right)^2 \left(\frac{\omega_r}{\omega_q}\right) \left(\frac{2\Delta}{\omega_r/Q_{pf}}\right)^2$
$\kappa_r = \omega_r/Q_r$

With the readout resonators spaced ~30MHz appart, we need a bandwidth of at least 4*30MHz=120MHz.
We have a range of readout resonators from 5-6GHz.

[3] Jeffrey et al. Fast accurate state measurement with superconducting qubits. Physical Review Letters, 112(19), 1–5. http://doi.org/10.1103/PhysRevLett.112.190504


In [22]:
purcell = cpwtools.HalfLResonator(cpw,11000)
purcell.addCapacitiveCoupling('in', 40e-15)
purcell.addCapacitiveCoupling('out', 130e-15)
print "f=5.0GHz  l={:.3f}um  Q_in={:.2f}  Q_out={:.2f}".format( purcell.setLengthFromFreq(5.0e9)*1e6, purcell.Qc('in'), purcell.Qc('out') )
print "f=5.5GHz  l={:.3f}um  Q_in={:.2f}  Q_out={:.2f}".format( purcell.setLengthFromFreq(5.5e9)*1e6, purcell.Qc('in'), purcell.Qc('out') )
print "f=6.0GHz  l={:.3f}um   Q_in={:.2f}  Q_out={:.2f}".format( purcell.setLengthFromFreq(6.0e9)*1e6, purcell.Qc('in'), purcell.Qc('out') )
print "f=5.925GHz  l={:.3f}um  Q_in={:.2f}  Q_out={:.2f}".format( purcell.setLengthFromFreq(5.925e9)*1e6, purcell.Qc('in'), purcell.Qc('out') )
print "f=4.8GHz  l={:.3f}um  Q_in={:.2f}  Q_out={:.2f}".format( purcell.setLengthFromFreq(4.8e9)*1e6, purcell.Qc('in'), purcell.Qc('out') )
print
print 'Min Frequency:'
purcell.l = (tot_length + 503*4)*1e-6
print "f={:.3f}GHz for l = {:.2f}um including pull of caps".format(1e-9*purcell.fl(), purcell.l*1e6)
print "V_out/V_in =", (purcell.Qc('in')/purcell.Qc('out'))**0.5
print "{:.2f}% power lost through input".format( 100*purcell.Ql()/purcell.Qc('in') )
print "{:.2f}% power lost through output".format( 100*purcell.Ql()/purcell.Qc('out') )
print "{:.2f}% power lost internally".format( 100*purcell.Ql()/purcell.Qint() )


f=5.0GHz  l=11850.858um  Q_in=397.15  Q_out=40.62
f=5.5GHz  l=10773.507um  Q_in=329.14  Q_out=34.02
f=6.0GHz  l=9875.715um   Q_in=277.35  Q_out=28.99
f=5.925GHz  l=10000.724um  Q_in=284.30  Q_out=29.67
f=4.8GHz  l=12344.644um  Q_in=430.46  Q_out=43.84

Min Frequency:
f=7.592GHz for l = 6917.40um including pull of caps
V_out/V_in = 2.9956074145327345
10.37% power lost through input
93.07% power lost through output
0.00% power lost internally

In [23]:
Delta = omega_q - omega_r
print "Delta = {:.3f}MHz".format(Delta/1e6/2/pi)
print "Purcell Filter FWHM = {:.2f}MHz".format(omega_q/purcell.Ql()/2/pi/1e6)
print "Purcell Filter Q_l = {:.2f}".format(purcell.Ql())
print

for q in qubits:
    print q.name
    kappa_r = omega_r/q.Q_r()
    print kappa_r
    print "T1 limit without purcell: {:.2f}us".format((Delta/q.g())**2/kappa_r * 1e6)
    print "T1 limit with purcell: {:.2f}us".format((Delta/q.g())**2 * (omega_r/omega_q) * (2*Delta/omega_r*purcell.Ql())**2/kappa_r * 1e6)
    print


Delta = -865.000MHz
Purcell Filter FWHM = 322.65MHz
Purcell Filter Q_l = 14.33

              Transmon
6938523.721174244
T1 limit without purcell: 53.72us
T1 limit with purcell: 1301.01us

Charge Sensitive Qubit
13956569.490743842
T1 limit without purcell: 20.84us
T1 limit with purcell: 504.73us


In [24]:
l_curve = 2*pi*50/4
tot_length = l_curve*(1+2+2+2+1)*2 + 4*1000 + 2569 + 4*450 + 2*106
print tot_length
print (tot_length - 11850)/4
print (tot_length - 10774)/4
print (tot_length - 9879)/4
purcell.l = (tot_length + 503*4)*1e-6
print purcell.fl()/1e9
print (tot_length - purcell.l*1e6)/4


9837.63706144
-503.090734641
-234.090734641
-10.340734641
4.625044159641565
-503.0

Notes

  • Looking at the chip left to right, top to bottom, we have Q1-Q4.
  • Q4 is the charge sensitive qubit. All others are normal transmons.
  • The capacitances really brought down the frequencies of all resonators. This made everything more difficult, and we only have Delta = 850MHz.
  • The qubit readout resonators inductive coupler for Q4 is 150um instead of 167um.
  • Turns out I had M~Z0 instead of M~Z0^2, so my coupling lengths are all off by a factor of 50.
  • Alex thinks the bias line might be T1 limiting?

In [ ]:


In [ ]:


In [ ]:


In [ ]: