Skip to content

Commit

Permalink
interpolation logic implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
shanto268 committed Dec 21, 2023
1 parent 52dc6d5 commit c2c4fc5
Show file tree
Hide file tree
Showing 6 changed files with 25,672 additions and 704 deletions.
13 changes: 9 additions & 4 deletions squadds/calcs/transmon_cross.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,17 @@ def EJ(self, w_q, alpha):
self.EJ = EJ
return EJ

def calculate_target_quantities(self, f_res, alpha, g, w_q, N, Z_0=50):
def calculate_target_quantities(self, f_res, alpha, g, w_q, res_type, Z_0=50):
EJ, EC = Transmon.find_EJ_EC(w_q, alpha)
C_q = Convert.Cs_from_Ec(EC, units_in='GHz', units_out='fF')
omega_r = 2 * np.pi * f_res
prefactor = np.sqrt(N * Z_0 * e**2 / (hbar * np.pi)) * (EJ / (8 * EC))**(1/4)
if res_type == "half":
res_type = 2
elif res_type == "quarter":
res_type = 4
else:
raise ValueError("res_type must be either 'half' or 'quarter'")
prefactor = np.sqrt(res_type * Z_0 * e**2 / (hbar * np.pi)) * (EJ / (8 * EC))**(1/4)
denominator = omega_r * prefactor
numerator = g * C_q
C_c = numerator / denominator
Expand All @@ -65,7 +71,6 @@ def g_and_alpha(self, C, C_c, f_q, EJ, f_r, res_type, Z0=50):

def g_alpha_freq(self, C, C_c, EJ, f_r, res_type, Z0=50):
scq.set_units("GHz")
C, C_c = abs(C) * 1e-15, abs(C_c) * 1e-15
C_q = C + C_c
if res_type == "half":
res_type = 2
Expand All @@ -74,7 +79,7 @@ def g_alpha_freq(self, C, C_c, EJ, f_r, res_type, Z0=50):
else:
raise ValueError("res_type must be either 'half' or 'quarter'")
g = self.g_from_cap_matrix(C, C_c, EJ, f_r, res_type, Z0)
EC = Convert.Ec_from_Cs(C_q, units_in='F', units_out='GHz')
EC = Convert.Ec_from_Cs(C_q, units_in='fF', units_out='GHz')
transmon = Transmon(EJ=EJ, EC=EC, ng=0, ncut=30)
alpha = transmon.anharmonicity() * 1E3 # MHz
freq = transmon.E01()
Expand Down
28 changes: 10 additions & 18 deletions squadds/core/analysis.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
import numpy as np
import pandas as pd
import warnings
import os
import scqubits as scq
from scqubits.core.transmon import TunableTransmon
from pandasai import SmartDataframe
from pandasai.llm import OpenAI, Starcoder, Falcon
from dotenv import load_dotenv
from squadds.calcs import *
import seaborn as sns

from squadds.core.metrics import *
from squadds.core.db import SQuADDS_DB


"""
Expand Down Expand Up @@ -196,7 +187,7 @@ def find_closest(self,
self._add_target_params_columns()

# Log if parameters outside of library
filtered_df = self.df[self.H_param_keys] # Filter DataFrame based on H_param_keys
filtered_df = self.df[self.target_params] # Filter DataFrame based on H_param_keys
self._outside_bounds(df=filtered_df, params=target_params, display=display)

# Set strategy dynamically based on the metric parameter
Expand Down Expand Up @@ -233,7 +224,8 @@ def find_closest(self,
self.closest_design = closest_df.iloc[0]["design_options"]

if len(self.selected_system) == 2: #TODO: make this more general
self.presimmed_closest_cpw_design = self.closest_design["cavity_claw"]
self.presimmed_closest_cpw_design = self.closest_df_entry["design_options_cavity_claw"]
self.presimmed_closest_qubit_design = self.closest_df_entry["design_options_qubit"]

return closest_df

Expand All @@ -259,7 +251,7 @@ def get_param(self, design, param):
raise NotImplementedError


def show_chosen_points(self):
def show_closest_point(self):
# Set Seaborn style and context
sns.set_style("whitegrid")
sns.set_context("paper", font_scale=1.4)
Expand All @@ -274,11 +266,11 @@ def show_chosen_points(self):
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6))

# First subplot: kappa_kHz vs fres
ax1.scatter(x=self.df['cavity_frequency_GHz'], y=self.df['kappa_kHz'], c=color_presim, marker=".", s=50, label="Pre-Simulated")
ax1.scatter(x=self.target_params["cavity_frequency_GHz"], y=self.target_params["kappa_kHz"], c='red', s=100, marker='x', label='Target')
ax1.scatter(x=self.df['cavity_frequency_GHz'], y=self.df['kappa_kHz'], color=color_presim, marker=".", s=50, label="Pre-Simulated")
ax1.scatter(x=self.target_params["cavity_frequency_GHz"], y=self.target_params["kappa_kHz"], color='red', s=100, marker='x', label='Target')
closest_fres = self.closest_df_entry["cavity_frequency_GHz"]
closest_kappa_kHz = self.closest_df_entry["kappa_kHz"]
ax1.scatter(closest_fres, closest_kappa_kHz, c=[color_database], s=100, marker='s', alpha=0.7, label='Closest')
ax1.scatter(closest_fres, closest_kappa_kHz, color=[color_database], s=100, marker='s', alpha=0.7, label='Closest')
ax1.set_xlabel(r'$f_{res}$ (Hz)', fontweight='bold', fontsize=24)
ax1.set_ylabel(r'$\kappa / 2 \pi$ (Hz)', fontweight='bold', fontsize=24)
ax1.tick_params(axis='both', which='major', labelsize=20)
Expand All @@ -287,11 +279,11 @@ def show_chosen_points(self):
text.set_fontweight('bold')

# Second subplot: g vs alpha
ax2.scatter(x=self.df['anharmonicity_MHz'], y=self.df['g_MHz'], c=color_presim, marker=".", s=50, label="Pre-Simulated")
ax2.scatter(x=self.target_params["anharmonicity_MHz"], y=self.target_params["g_MHz"], c='red', s=100, marker='x', label='Target')
ax2.scatter(x=self.df['anharmonicity_MHz'], y=self.df['g_MHz'], color=color_presim, marker=".", s=50, label="Pre-Simulated")
ax2.scatter(x=self.target_params["anharmonicity_MHz"], y=self.target_params["g_MHz"], color='red', s=100, marker='x', label='Target')
closest_alpha = [self.closest_df_entry["anharmonicity_MHz"]]
closest_g = [self.closest_df_entry["g_MHz"]]
ax2.scatter(closest_alpha, closest_g, c=[color_database], s=100, marker='s', alpha=0.7, label='Closest')
ax2.scatter(closest_alpha, closest_g, color=[color_database], s=100, marker='s', alpha=0.7, label='Closest')
ax2.set_xlabel(r'$\alpha / 2 \pi$ (MHz)', fontweight='bold', fontsize=24)
ax2.set_ylabel(r'$g / 2 \pi$ (MHz)', fontweight='bold', fontsize=24)
ax2.tick_params(axis='both', which='major', labelsize=20)
Expand Down
6 changes: 5 additions & 1 deletion squadds/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def convert_numpy(obj):

# Function to create a unified design_options dictionary
def create_unified_design_options(row):
# TODO: no hardcoding
"""
Create a unified design options dictionary based on the given row.
Expand All @@ -60,7 +61,10 @@ def create_unified_design_options(row):
dict: The unified design options dictionary.
"""
cavity_dict = convert_numpy(row["design_options_cavity_claw"])
coupler_type = row["coupler_type"]
try:
coupler_type = row["coupler_type"]
except:
coupler_type = "CLT"
qubit_dict = convert_numpy(row["design_options_qubit"])

device_dict = {
Expand Down
7 changes: 4 additions & 3 deletions squadds/interpolations/interpolator.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
from abc import ABC, abstractmethod
from squadds.core import Analyzer
import pandas as pd

class Interpolator(ABC):
"""Abstract class for interpolators."""

def __init__(self, df: pd.DataFrame, target_params: dict):
self.df = df
def __init__(self, analyzer: Analyzer, target_params: dict):
self.analyzer = analyzer # Correct the typo here
self.df = self.analyzer.df # And here
self.target_params = target_params

@abstractmethod
def get_design(self) -> pd.DataFrame:
"""Interpolate based on the target parameters.
Returns:
pd.DataFrame: DataFrame with interpolated design options.
"""
Expand Down
162 changes: 106 additions & 56 deletions squadds/interpolations/physics.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
from squadds.interpolations import Interpolator
import pandas as pd
from squadds.calcs import *
from squadds.core import *
import matplotlib.pyplot as plt
from pyEPR.calcs import Convert

def string_to_float(string):
return float(string[:-2])
class ScalingInterpolator(Interpolator):
"""Concrete class for scaling based interpolation."""

def __init__(self, df: pd.DataFrame, target_params: dict):
super().__init__(df, target_params)
"""Class for scaling-based interpolation."""
def __init__(self, analyzer: Analyzer, target_params: dict):
super().__init__(analyzer, target_params)

def get_design(self) -> pd.DataFrame:
"""Performs interpolation based on scaling logic.
Returns:
pd.DataFrame: DataFrame with interpolated design options.
"""
# Initialize lists to store the updated values
updated_design_options = []
required_LJs = []
presimmed_best_qubit_designs = []
presimmed_best_cpw_designs = []

# Extract target parameters
f_q_target = self.target_params['qubit_frequency_GHz']
g_target = self.target_params['g_MHz']
Expand All @@ -27,48 +21,104 @@ def get_design(self) -> pd.DataFrame:
kappa_target = self.target_params['kappa_kHz']
res_type = self.target_params['resonator_type']

# Placeholder for the calculate_target_quantities function
# C_q_target, C_C_target, E_J, E_C_target, EJ_over_EC = calculate_target_quantities(...)

# Placeholder for LJ_target calculation
LJ_target = 10 # This should be computed based on E_J
required_LJs.append(LJ_target)

# Placeholder for updating the DataFrame with anharmonicity, g, and qubit frequency
# self.df["g"], self.df["anharmonicity"], self.df["qubit_frequency"] = compute_g_alpha_freq(...)

# Placeholder logic for finding the best qubit-claw and cpw-claw design
# Implement actual logic here
idx1, closest_qubit_claw_design = 0, self.df.iloc[0] # Placeholder
idx2, closest_claw_cpw_design = 0, self.df.iloc[0] # Placeholder

# Calculate scaling factors
alpha_scaling = closest_qubit_claw_design['anharmonicity'] / alpha_target
g_scaling = g_target / closest_qubit_claw_design['g']

# Update the lengths based on the closest design and scaling
updated_cross_length = closest_qubit_claw_design['cross_length'] * alpha_scaling
updated_claw_length = closest_qubit_claw_design['claw_length'] * g_scaling * alpha_scaling
updated_resonator_length = closest_claw_cpw_design['total_length'] * (closest_claw_cpw_design['cavity_frequency'] / f_res_target)
updated_coupling_length = closest_claw_cpw_design['coupling_length'] * (kappa_target / closest_claw_cpw_design['kappa']) ** 0.5

# Append the updated lengths to the lists
updated_design_options.append({
'cross_length': updated_cross_length,
'claw_length': updated_claw_length,
'resonator_length': updated_resonator_length,
'coupling_length': updated_coupling_length
})
presimmed_best_qubit_designs.append(closest_qubit_claw_design)
presimmed_best_cpw_designs.append(closest_claw_cpw_design)

# Return DataFrame with updated values
return pd.DataFrame({
'updated_design_options': updated_design_options,
'required_LJs': required_LJs,
'presimmed_best_qubit_designs': presimmed_best_qubit_designs,
'presimmed_best_cpw_designs': presimmed_best_cpw_designs
self.df = self.analyzer.df

# Find the closest qubit-claw design
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"]["c"]['claw_length']) * g_scaling.values[0] * alpha_scaling.values[0]

# Scaling logic for cavity-coupler designs
# Filter DataFrame based on qubit coupling claw capacitance
cross_to_claw_cap_chosen = closest_qubit_claw_design['cross_to_claw'].iloc[0]

threshold = 0.3 # 30% threshold
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)]

# 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}

closest_cavity_cpw_design = self.analyzer.find_closest(target_params_cavity, num_top=1)
print(closest_cavity_cpw_design.iloc[0]["design_options"])

closest_kappa = closest_cavity_cpw_design['kappa_kHz'].values[0]
closest_f_cavity = closest_cavity_cpw_design['cavity_frequency_GHz'].values[0]
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]

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("="*50)
updated_coupling_length = string_to_float(closest_cavity_cpw_design["design_options_cavity_claw"].iloc[0]['cplr_opts']['coupling_length']) * kappa_scaling
# round updated_coupling_length to nearest integer
updated_coupling_length = round(updated_coupling_length)

"""
print("="*50)
print(f"Updated resonator length: {updated_resonator_length}")
print(f"Updated coupling length: {updated_coupling_length}")
print(f"Updated cross length: {updated_cross_length}")
print(f"Updated claw length: {updated_claw_length}")
print("="*50)
"""

# Reset the analyzer's DataFrame
self.analyzer.df = merged_df
self.analyzer.selected_system = system_chosen
self.analyzer.H_param_keys = H_params_chosen
print(closest_cavity_cpw_design.iloc[0]["design_options"])

# 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"]["c"]['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"]["c"]['Lj'] = f"{required_Lj}nH"

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"
cavity_design_options['cplr_opts']['coupling_length'] = f"{updated_coupling_length}um"

# Update the coupler options
coupler_design_options = cavity_design_options['cplr_opts']

interpolated_designs_df = pd.DataFrame({
"design_options_qubit": [qubit_design_options],
"design_options_cavity_claw": [cavity_design_options],
})

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"]["c"]["claw_cpw_length"] = "0um"

return interpolated_designs_df
Loading

0 comments on commit c2c4fc5

Please sign in to comment.