Source code for squadds.interpolations.physics
import pandas as pd
from pyEPR.calcs import Convert
from squadds import Analyzer
from squadds.core.utils import *
from squadds.interpolations.interpolator import Interpolator
[docs]
class ScalingInterpolator(Interpolator):
"""Class for scaling-based interpolation."""
def __init__(self, analyzer: Analyzer, target_params: dict):
super().__init__(analyzer, target_params)
[docs]
def get_design(self) -> pd.DataFrame:
"""
Retrieves the design options for qubit and cavity based on target parameters.
Returns:
pd.DataFrame: A DataFrame containing the design options for qubit and cavity.
"""
# Extract target parameters
f_q_target = self.target_params["qubit_frequency_GHz"]
g_target = self.target_params["g_MHz"]
alpha_target = self.target_params["anharmonicity_MHz"]
f_res_target = self.target_params["cavity_frequency_GHz"]
kappa_target = self.target_params["kappa_kHz"]
try:
res_type = self.target_params["resonator_type"]
except:
res_type = self.analyzer.selected_resonator_type
self.df = self.analyzer.df
# Find the closest qubit-claw design
if self.analyzer.selected_resonator_type == "half":
closest_qubit_claw_design = self.analyzer.find_closest(
{"qubit_frequency_GHz": f_q_target, "anharmonicity_MHz": alpha_target, "g_MHz": g_target},
parallel=True,
num_cpu="auto",
num_top=1,
)
else:
closest_qubit_claw_design = self.analyzer.find_closest(
{"qubit_frequency_GHz": f_q_target, "anharmonicity_MHz": alpha_target, "g_MHz": g_target}, num_top=1
)
# Scale values
alpha_scaling = closest_qubit_claw_design["anharmonicity_MHz"] / alpha_target
g_scaling = g_target / closest_qubit_claw_design["g_MHz"]
# Scale qubit and claw dimensions
updated_cross_length = (
string_to_float(closest_qubit_claw_design["design_options_qubit"].iloc[0]["cross_length"])
* alpha_scaling.values[0]
)
updated_claw_length = (
string_to_float(
closest_qubit_claw_design["design_options_qubit"].iloc[0]["connection_pads"]["readout"]["claw_length"]
)
* g_scaling.values[0]
* alpha_scaling.values[0]
)
# Scaling logic for cavity-coupler designs
# Filter DataFrame based on qubit coupling claw capacitance
try:
cross_to_claw_cap_chosen = closest_qubit_claw_design["cross_to_claw"].iloc[0]
except:
cross_to_claw_cap_chosen = closest_qubit_claw_design["cross_to_claw_closest"].iloc[0]
threshold = 0.3 # 30% threshold
try:
filtered_df = self.df[
(self.df["cross_to_claw"] >= (1 - threshold) * cross_to_claw_cap_chosen)
& (self.df["cross_to_claw"] <= (1 + threshold) * cross_to_claw_cap_chosen)
]
except:
filtered_df = self.df[
(self.df["cross_to_claw_closest"] >= (1 - threshold) * cross_to_claw_cap_chosen)
& (self.df["cross_to_claw_closest"] <= (1 + threshold) * cross_to_claw_cap_chosen)
]
# Find the closest cavity-coupler design
merged_df = self.analyzer.df.copy()
system_chosen = self.analyzer.selected_system
H_params_chosen = self.analyzer.H_param_keys
self.analyzer.df = filtered_df
self.analyzer.selected_system = "cavity_claw"
self.analyzer.H_param_keys = ["resonator_type", "cavity_frequency_GHz", "kappa_kHz"]
self.analyzer.target_params = {
"cavity_frequency_GHz": f_res_target,
"kappa_kHz": kappa_target,
"resonator_type": res_type,
}
target_params_cavity = {
"cavity_frequency_GHz": f_res_target,
"kappa_kHz": kappa_target,
"resonator_type": res_type,
}
if self.analyzer.selected_resonator_type == "half":
closest_cavity_cpw_design = self.analyzer.find_closest(
target_params_cavity, parallel=True, num_cpu="auto", num_top=1
)
else:
closest_cavity_cpw_design = self.analyzer.find_closest(target_params_cavity, num_top=1)
closest_kappa = closest_cavity_cpw_design["kappa_kHz"].values[0]
closest_f_cavity = closest_cavity_cpw_design["cavity_frequency_GHz"].values[0]
if self.analyzer.selected_resonator_type == "half":
closest_coupler_length = string_to_float(
closest_cavity_cpw_design["design_options_cavity_claw"].iloc[0]["cplr_opts"]["finger_length"]
)
else:
closest_coupler_length = string_to_float(
closest_cavity_cpw_design["design_options_cavity_claw"].iloc[0]["cplr_opts"]["coupling_length"]
)
# Scale resonator and coupling element dimensions
updated_resonator_length = (
string_to_float(closest_cavity_cpw_design["design_options_cavity_claw"].iloc[0]["cpw_opts"]["total_length"])
* (closest_cavity_cpw_design["cavity_frequency_GHz"] / f_res_target).values[0]
)
updated_resonator_length = round(updated_resonator_length)
res_scaling = closest_f_cavity / f_res_target
res_scaling = closest_f_cavity / f_res_target
kappa_scaling = np.sqrt(kappa_target / closest_kappa)
print("=" * 50)
print(f"Kappa scaling: {kappa_scaling}")
print(f"g scaling: {g_scaling.values[0]}")
print(f"alpha scaling: {alpha_scaling.values[0]}")
print(f"resonator scaling: {res_scaling}")
print("=" * 50)
updated_coupling_length = closest_coupler_length * kappa_scaling
# round updated_coupling_length to nearest integer
updated_coupling_length = round(updated_coupling_length)
# Reset the analyzer's DataFrame
self.analyzer.df = merged_df
self.analyzer.selected_system = system_chosen
self.analyzer.H_param_keys = H_params_chosen
# a dataframe with three empty colums
interpolated_designs_df = pd.DataFrame(
columns=["design_options_qubit", "design_options_cavity_claw", "design_options"]
)
# Update the qubit and cavity design options
qubit_design_options = closest_qubit_claw_design["design_options_qubit"].iloc[0]
qubit_design_options["cross_length"] = f"{updated_cross_length}um"
qubit_design_options["connection_pads"]["readout"]["claw_length"] = f"{updated_claw_length}um"
required_Lj = Convert.Lj_from_Ej(closest_qubit_claw_design["EJ"].iloc[0], units_in="GHz", units_out="nH")
qubit_design_options["aedt_hfss_inductance"] = required_Lj * 1e-9
qubit_design_options["aedt_q3d_inductance"] = required_Lj * 1e-9
qubit_design_options["q3d_inductance"] = required_Lj * 1e-9
qubit_design_options["hfss_inductance"] = required_Lj * 1e-9
qubit_design_options["connection_pads"]["readout"]["Lj"] = f"{required_Lj}nH"
# setting the `claw_cpw_length` params to zero
qubit_design_options["connection_pads"]["readout"]["claw_cpw_length"] = "0um"
cavity_design_options = closest_cavity_cpw_design["design_options_cavity_claw"].iloc[0]
cavity_design_options["cpw_opts"]["total_length"] = f"{updated_resonator_length}um"
if self.analyzer.selected_resonator_type == "half":
cavity_design_options["cplr_opts"]["finger_length"] = f"{updated_coupling_length}um"
else:
cavity_design_options["cplr_opts"]["coupling_length"] = f"{updated_coupling_length}um"
# update the claw of the cavity based on the one from the qubit
cavity_design_options["claw_opts"]["connection_pads"] = qubit_design_options["connection_pads"]
interpolated_designs_df = pd.DataFrame(
{
"coupler_type": self.analyzer.selected_coupler,
"design_options_qubit": [qubit_design_options],
"design_options_cavity_claw": [cavity_design_options],
"setup_qubit": [closest_qubit_claw_design["setup_qubit"].iloc[0]],
"setup_cavity_claw": [closest_cavity_cpw_design["setup_cavity_claw"].iloc[0]],
}
)
device_design_options = create_unified_design_options(interpolated_designs_df.iloc[0])
# add the device design options to the dataframe
interpolated_designs_df["design_options"] = [device_design_options]
interpolated_designs_df.iloc[0]["design_options"]["qubit_options"]["connection_pads"]["readout"][
"claw_cpw_length"
] = "0um"
return interpolated_designs_df