%load_ext autoreload
%autoreload 2

import qiskit_metal as metal
from qiskit_metal import designs, draw
from qiskit_metal import MetalGUI, Dict, open_docs

%metal_heading Welcome to Qiskit Metal!

from qiskit_metal.qlibrary.qubits.transmon_pocket_6 import TransmonPocket6

from qiskit_metal.qlibrary.tlines.meandered import RouteMeander
from qiskit_metal.qlibrary.tlines.pathfinder import RoutePathfinder
from qiskit_metal.qlibrary.tlines.straight_path import RouteStraight

from qiskit_metal.qlibrary.lumped.cap_n_interdigital import CapNInterdigital
from qiskit_metal.qlibrary.couplers.cap_n_interdigital_tee import CapNInterdigitalTee

from qiskit_metal.qlibrary.terminations.launchpad_wb import LaunchpadWirebond

design = metal.designs.DesignPlanar()

gui = metal.MetalGUI(design)

design.overwrite_enabled = True
design.chips.main

design.chips.main.size.size_x = '6mm'
design.chips.main.size.size_y = '6mm'

TransmonPocket6.get_template_options(design)

q_0 = TransmonPocket6(design,'Q_0', options = dict(
        pos_x='-1.25mm', 
        pos_y='0.5mm', 
        gds_cell_name ='FakeJunction_01',
        hfss_inductance ='14nH',
        pad_width = '425 um', 
        pocket_height = '650um',
        connection_pads=dict(
            readout = dict(loc_W=0, loc_H=1, pad_width = '80um', pad_gap = '50um'),
            bus_01 = dict(loc_W=1, loc_H=-1, pad_width = '60um', pad_gap = '10um'),
            bus_02 = dict(loc_W=-1, loc_H=-1, pad_width = '60um', pad_gap = '10um')        
    )))

q_1 = TransmonPocket6(design,'Q_1', options = dict(
        pos_x='1.25mm', 
        pos_y='0.5mm', 
        gds_cell_name ='FakeJunction_01',
        hfss_inductance ='14nH',
        pad_width = '425 um', 
        pocket_height = '650um',
        connection_pads=dict(
            readout = dict(loc_W=0, loc_H=1, pad_width = '80um', pad_gap = '50um'),
            bus_01 = dict(loc_W=-1, loc_H=-1, pad_width = '60um', pad_gap = '10um'),
            bus_12 = dict(loc_W=1, loc_H=-1, pad_width = '60um', pad_gap = '10um') 
    )))


q_2 = TransmonPocket6(design,'Q_2', options = dict(
        pos_x='0mm', 
        pos_y='-1.35mm', 
        gds_cell_name ='FakeJunction_01',
        hfss_inductance ='14nH',
        pad_width = '425 um', 
        pocket_height = '650um',
        connection_pads=dict(
            readout = dict(loc_W=0, loc_H=-1, pad_width = '80um', pad_gap = '50um'),
            bus_02 = dict(loc_W=-1, loc_H=1, pad_width = '60um', pad_gap = '10um'),
            bus_12 = dict(loc_W=1, loc_H=1, pad_width = '60um', pad_gap = '10um') 
    )))

gui.rebuild()
gui.autoscale()

from qiskit_metal.analyses.em.cpw_calculations import guided_wavelength

def find_resonator_length(frequency, line_width, line_gap, N): 
    #frequency in GHz
    #line_width/line_gap in um
    #N -> 2 for lambda/2, 4 for lambda/4
    #substrate dimensions and properties already set
    
    [lambdaG, etfSqrt, q] = guided_wavelength(frequency*10**9, line_width*10**-6,
                                              line_gap*10**-6, 750*10**-6, 200*10**-9, 11.9)
    return str(lambdaG/N*10**3)+" mm"

?guided_wavelength

q_0.pins.keys()

find_resonator_length(5.8,10,6,2) #Note: What might be wrong with this length?

bus_01 = RouteMeander(design,'Bus_01', options = dict(hfss_wire_bonds = True, 
                                            pin_inputs=Dict(
                                                start_pin=Dict(
                                                    component='Q_0',
                                                    pin='bus_01'),
                                                end_pin=Dict(
                                                    component='Q_1',
                                                    pin='bus_01')
                                            ),
                                            lead=Dict(
                                                start_straight='125um',
                                                end_straight = '125um'
                                            ),
                                            meander=Dict(
                                                asymmetry = '50um'),
                                            fillet = "99um",
                                            total_length = '10.3mm'))

gui.rebuild()
gui.autoscale()

bus_02 = RouteMeander(design,'Bus_02', options = dict(hfss_wire_bonds = True, 
                                            pin_inputs=Dict(
                                                start_pin=Dict(
                                                    component='Q_0',
                                                    pin='bus_02'),
                                                end_pin=Dict(
                                                    component='Q_2',
                                                    pin='bus_02')
                                            ),
                                            lead=Dict(
                                                start_straight='125um',
                                                end_straight = '125um'
                                            ),
                                            meander=Dict(
                                                asymmetry = '50um'),
                                            fillet = "99um",
                                            total_length = '10mm'))


bus_12 = RouteMeander(design,'Bus_12', options = dict(hfss_wire_bonds = True, 
                                            pin_inputs=Dict(
                                                start_pin=Dict(
                                                    component='Q_1',
                                                    pin='bus_12'),
                                                end_pin=Dict(
                                                    component='Q_2',
                                                    pin='bus_12')
                                            ),
                                            lead=Dict(
                                                start_straight='125um',
                                                end_straight = '125um'
                                            ),
                                            meander=Dict(
                                                asymmetry = '50um'),
                                            fillet = "99um",
                                            total_length = '9.7mm'))


gui.rebuild()
gui.autoscale()

from collections import OrderedDict

bus_01 = RouteMeander(design,'Bus_01', options = dict(hfss_wire_bonds = True, 
                                            pin_inputs=Dict(
                                                start_pin=Dict(
                                                    component='Q_0',
                                                    pin='bus_01'),
                                                end_pin=Dict(
                                                    component='Q_1',
                                                    pin='bus_01')
                                            ),
                                            lead=Dict(
                                                start_straight='125um',
                                                end_straight = '125um'
                                            ),
                                            meander=Dict(
                                                asymmetry = '-350um'),
                                            fillet = "99um",
                                            total_length = '10.3mm'))


jogs_start = OrderedDict()
jogs_start[0] = ["L", '350um']
jogs_start[1] = ["L", '500um']

bus_02 = RouteMeander(design,'Bus_02', options = dict(hfss_wire_bonds = True, 
                                            pin_inputs=Dict(
                                                start_pin=Dict(
                                                    component='Q_0',
                                                    pin='bus_02'),
                                                end_pin=Dict(
                                                    component='Q_2',
                                                    pin='bus_02')
                                            ),
                                            lead=Dict(
                                                start_straight='125um',
                                                end_straight = '225um',
                                                start_jogged_extension=jogs_start,
                                                #end_jogged_extension = jogs_end
                                            ),
                                            meander=Dict(
                                                asymmetry = '-50um'),
                                            fillet = "99um",
                                            total_length = '10mm'))


jogs_start = OrderedDict()
jogs_start[0] = ["R", '350um']
jogs_start[1] = ["R", '700um']

bus_12 = RouteMeander(design,'Bus_12', options = dict(hfss_wire_bonds = True, 
                                            pin_inputs=Dict(
                                                start_pin=Dict(
                                                    component='Q_1',
                                                    pin='bus_12'),
                                                end_pin=Dict(
                                                    component='Q_2',
                                                    pin='bus_12')
                                            ),
                                            lead=Dict(
                                                start_straight='325um',
                                                end_straight = '25um',
                                                start_jogged_extension=jogs_start
                                            ),
                                            meander=Dict(
                                                asymmetry = '50um'),
                                            fillet = "99um",
                                            total_length = '9.7mm'))


gui.rebuild()
gui.autoscale()

launch_readout_q_0 = LaunchpadWirebond(design, 'Launch_Readout_Q_0', 
                                       options = dict(pos_x = '-2mm', 
                                                      pos_y ='2.5mm', 
                                                      orientation = '-90'))
launch_readout_q_1 = LaunchpadWirebond(design, 'Launch_Readout_Q_1', 
                                       options = dict(pos_x = '2mm', 
                                                      pos_y ='2.5mm', 
                                                      orientation = '-90'))

launch_readout_q_2 = LaunchpadWirebond(design, 'Launch_Readout_Q_2', 
                                       options = dict(pos_x = '-2mm', 
                                                      pos_y ='-2.5mm', 
                                                      orientation = '90'))

gui.rebuild()
gui.autoscale()

cap_readout_q_2 = CapNInterdigital(design,'Cap_Readout_Q_2', options = dict(pos_x = '-2mm', pos_y ='-2.25mm', orientation = '0'))

cap_readout_q_0 = CapNInterdigitalTee(design,'Cap_Readout_Q_0', options=dict(pos_x = '-1.5mm', pos_y = '2.25mm', 
                                                           orientation = '0'))

cap_readout_q_1 = CapNInterdigitalTee(design,'Cap_Readout_Q_1', options=dict(pos_x = '1.5mm', pos_y = '2.25mm', 
                                                           orientation = '0'))

gui.rebuild()
gui.autoscale()

find_resonator_length(7.2,10,6,2)

jogs_start = OrderedDict()
jogs_start[0] = ["L", '350um']
#jogs_start[1] = ["R", '700um']

readout_0 = RouteMeander(design,'Readout_0', options = dict(hfss_wire_bonds = True, 
                                            pin_inputs=Dict(
                                                start_pin=Dict(
                                                    component='Q_0',
                                                    pin='readout'),
                                                end_pin=Dict(
                                                    component='Cap_Readout_Q_0',
                                                    pin='second_end')
                                            ),
                                            lead=Dict(
                                                start_straight='125um',
                                                end_straight = '25um',
                                                start_jogged_extension=jogs_start,
                                                #end_jogged_extension = jogs_end
                                            ),
                                            meander=Dict(
                                                asymmetry = '50um'),
                                            fillet = "99um",
                                            total_length = '8.8mm'))

jogs_start = OrderedDict()
jogs_start[0] = ["R", '350um']

readout_1 = RouteMeander(design,'Readout_1', options = dict(hfss_wire_bonds = True, 
                                            pin_inputs=Dict(
                                                start_pin=Dict(
                                                    component='Q_1',
                                                    pin='readout'),
                                                end_pin=Dict(
                                                    component='Cap_Readout_Q_1',
                                                    pin='second_end')
                                            ),
                                            lead=Dict(
                                                start_straight='125um',
                                                end_straight = '25um',
                                                start_jogged_extension=jogs_start,
                                                #end_jogged_extension = jogs_end
                                            ),
                                            meander=Dict(
                                                asymmetry = '50um'),
                                            fillet = "99um",
                                            total_length = '8.5mm'))


readout_2 = RouteMeander(design,'Readout_2', options = dict(hfss_wire_bonds = True, 
                                            pin_inputs=Dict(
                                                start_pin=Dict(
                                                    component='Q_2',
                                                    pin='readout'),
                                                end_pin=Dict(
                                                    component='Cap_Readout_Q_2',
                                                    pin='north_end')
                                            ),
                                            lead=Dict(
                                                start_straight='125um',
                                                end_straight = '25um',
                                            ),
                                            meander=Dict(
                                                asymmetry = '200um'),
                                            fillet = "99um",
                                            total_length = '8.3mm'))

gui.rebuild()
gui.autoscale()

tl_readout_q_2= RouteStraight(design,'TL_Readout_Q_2', options = dict(hfss_wire_bonds = True,
                                           pin_inputs=Dict(
                                               start_pin=Dict(
                                                   component='Cap_Readout_Q_2',
                                                   pin='south_end'),
                                               end_pin=Dict(
                                                    component='Launch_Readout_Q_2',
                                                    pin='tie')),
                                            trace_width = '10um',
                                            trace_gap = '6um'
                                            ))

tl_readout_q_0 = RoutePathfinder(design,'TL_Readout_Q_0', options = dict(hfss_wire_bonds = True,
                                            pin_inputs=Dict(
                                                start_pin=Dict(
                                                    component='Cap_Readout_Q_0',
                                                    pin='prime_start'),
                                                end_pin=Dict(
                                                    component='Launch_Readout_Q_0',
                                                    pin='tie')),
                                            fillet = '99um',
                                            trace_width = '10um',
                                            trace_gap = '6um'
                                            ))

tl_readout_q_1 = RoutePathfinder(design,'TL_Readout_Q_1', options = dict(hfss_wire_bonds = True,
                                            pin_inputs=Dict(
                                                start_pin=Dict(
                                                    component='Cap_Readout_Q_1',
                                                    pin='prime_end'),
                                                end_pin=Dict(
                                                    component='Launch_Readout_Q_1',
                                                    pin='tie')),
                                            fillet = '99um',
                                            trace_width = '10um',
                                            trace_gap = '6um'
                                            ))

tl_readout_q_01= RouteStraight(design,'TL_Readout_Q_01', options = dict(hfss_wire_bonds = True,
                                           pin_inputs=Dict(
                                               start_pin=Dict(
                                                   component='Cap_Readout_Q_0',
                                                   pin='prime_end'),
                                               end_pin=Dict(
                                                    component='Cap_Readout_Q_1',
                                                    pin='prime_start')),
                                            trace_width = '10um',
                                            trace_gap = '6um'
                                            ))

gui.rebuild()
gui.autoscale()

from qiskit_metal.analyses.quantization import LOManalysis
q_0_LOM = LOManalysis(design, "q3d")

q_0_LOM.sim.setup

q_0_LOM.setup

q_0_LOM.setup.freq_readout = 6.8
q_0_LOM.setup.freq_bus = [5.8,6.0]
q_0_LOM.setup

q_0.pins.keys()

q_0_LOM.run(components=['Q_0'], open_terminations=[('Q_0', 'readout'), ('Q_0', 'bus_01'), ('Q_0', 'bus_02')])

q_0_LOM.plot_convergence();
q_0_LOM.plot_convergence_chi()

q_0_LOM.sim.setup.percent_error = 0.1
q_0_LOM.sim.setup.max_passes = 20
q_0_LOM.run()

q_0_LOM.plot_convergence();
q_0_LOM.plot_convergence_chi()

q_0_LOM.sim.capacitance_matrix

q_0_LOM.lumped_oscillator

q_0.options.pad_gap = '28um'
q_0.options.connection_pads.readout.pad_gap = '22um'
q_0.options.connection_pads.readout.pad_width = '100um'
q_0.options.connection_pads.bus_01.pad_width = '135um'
q_0.options.connection_pads.bus_02.pad_width = '135um'

q_0_LOM.setup.junctions.Lj = 14.9

gui.rebuild()

q_0_LOM.run(name="Q_0_LOM_2",components=['Q_0'], open_terminations=[('Q_0', 'readout'), ('Q_0', 'bus_01'), ('Q_0', 'bus_02')])

q_0_LOM.lumped_oscillator

q_0.options.hfss_inductance = '14.9nH'

gui.rebuild()

q_0_LOM.sim.close()

from qiskit_metal.analyses.quantization import EPRanalysis
bus_02_EPR = EPRanalysis(design, "hfss")

bus_02_EPR.sim.setup

bus_02_EPR.sim.setup.n_modes = 2
bus_02_EPR.sim.run_sim(name="Bus_02_Sim", components=['Q_0','Q_2','Bus_02'], 
                   ignored_jjs = [('Q_0','rect_jj'),('Q_2','rect_jj')], 
                   box_plus_buffer = False)

bus_02_EPR.sim.plot_convergences()

bus_02_EPR.get_frequencies()

bus_02_EPR.sim.plot_fields('main')
#bus_02_EPR.sim.save_screenshot()

from qiskit_metal.analyses.sweep_and_optimize.sweeping import Sweeping
sweep = Sweeping(design)

?sweep.sweep_one_option_get_eigenmode_solution_data

em_setup_args = Dict(min_freq_ghz=3,
                    n_modes=1,
                    max_passes=12,
                    max_delta_f = 0.1)

all_sweeps, return_code = sweep.sweep_one_option_get_eigenmode_solution_data(
    'Bus_02',
    'total_length', 
    ['9.4mm', '9.3mm', '9.2mm'],
    ['Bus_02','Q_0','Q_2'],
    [],
    [('Q_0','rect_jj'),('Q_2','rect_jj')],
    design_name="GetEigenModeSolution",
    setup_args=em_setup_args)

frequency = {}
for key in all_sweeps.keys():
    frequency[key] = all_sweeps[key]['frequency']
    
frequency

bus_02.options.total_length = '9.35mm'

bus_02_EPR.sim.close()

q_1.options.pad_gap = '28um'
q_1.options.connection_pads.readout.pad_gap = '20um'
q_1.options.connection_pads.readout.pad_width = '100um'
q_1.options.connection_pads.bus_12.pad_width = '130um'
q_1.options.hfss_inductance = '13.9nH'
bus_01.options.total_length = '9.55mm'
gui.rebuild()

three_mode_EPR = EPRanalysis(design, "hfss")

three_mode_EPR.sim.setup.max_passes = 18
three_mode_EPR.sim.setup.max_delta_f = 0.025
three_mode_EPR.sim.setup.n_modes = 3
three_mode_EPR.sim.setup.vars = Dict(Lj0= '14.9 nH', Cj0= '0 fF',
                           Lj1= '13.9 nH', Cj1= '0 fF')

three_mode_EPR.sim.run_sim(name="Three_Mode",
                components=['Q_0', 'Q_1', 'Bus_01'])

three_mode_EPR.sim.plot_convergences()

del three_mode_EPR.setup.junctions['jj']

three_mode_EPR.setup.junctions.jj0 = Dict(rect='JJ_rect_Lj_Q_0_rect_jj', line='JJ_Lj_Q_0_rect_jj_',
                  Lj_variable='Lj0', Cj_variable='Cj0')
three_mode_EPR.setup.junctions.jj1 = Dict(rect='JJ_rect_Lj_Q_1_rect_jj', line='JJ_Lj_Q_1_rect_jj_',
                  Lj_variable='Lj1', Cj_variable='Cj1')
three_mode_EPR.setup.sweep_variable = 'Lj0'
three_mode_EPR.setup

three_mode_EPR.setup

three_mode_EPR.run_epr()

three_mode_EPR.sim.close()

mt_gds = design.renderers.gds

mt_gds.options

mt_gds.options.path_filename = '../resources/Fake_Junctions.GDS'

mt_gds.options.no_cheese.buffer = '40um'
mt_gds.options.max_points = 2555
mt_gds.options.cheese.cheese_0_x = '3um'
mt_gds.options.cheese.cheese_0_y = '3um'
mt_gds.options.cheese.delta_x = '50um'
mt_gds.options.cheese.delta_y = '50um'
mt_gds.options.cheese.view_in_file= {'main': {1: True}}
mt_gds.options.fabricate = True

mt_gds.export_to_gds("MetalTutorial.gds")