From 561362e550e64162e4a586150493799dd776d4c7 Mon Sep 17 00:00:00 2001 From: SamarthH Date: Wed, 11 May 2022 19:18:07 +0530 Subject: [PATCH] Implement Ability to Extract Q-factors from Eigenmode Simulations --- .../renderer_ansys/ansys_renderer.py | 24 ++++++++++++++--- .../renderers/renderer_ansys/hfss_renderer.py | 26 +++++++++++++------ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/qiskit_metal/renderers/renderer_ansys/ansys_renderer.py b/qiskit_metal/renderers/renderer_ansys/ansys_renderer.py index 6dc89c59c..4a97516d3 100644 --- a/qiskit_metal/renderers/renderer_ansys/ansys_renderer.py +++ b/qiskit_metal/renderers/renderer_ansys/ansys_renderer.py @@ -102,6 +102,7 @@ class QAnsysRenderer(QRendererAnalysis): * _Rj: 0 -- _Rj *must* be 0 for pyEPR analysis! _Rj has units of Ohms * max_mesh_length_jj: '7um' -- Maximum mesh length for Josephson junction elements * project_path: None -- Default project path; if None --> get active + * max_mesh_length_port: '7um' -- Maximum mesh length for Ports in Eigenmode Simulations * project_name: None -- Default project name * design_name: None -- Default design name * ansys_file_extension: '.aedt' -- Ansys file extension for 2016 version and newer @@ -122,6 +123,7 @@ class QAnsysRenderer(QRendererAnalysis): Cj=0, # Cj *must* be 0 for pyEPR analysis! Cj has units of femtofarads (fF) _Rj=0, # _Rj *must* be 0 for pyEPR analysis! _Rj has units of Ohms max_mesh_length_jj='7um', # maximum mesh length for Josephson junction elements + max_mesh_length_port='7um', # maximum mesh length for Ports in Eigenmode Simulations project_path=None, # default project path; if None --> get active project_name=None, # default project name design_name=None, # default design name @@ -748,6 +750,10 @@ def execute_design( self.clean_active_design() else: self.new_ansys_design(design_name, solution_type) + + # Save the solution type in order to choose between Lumped Port and RLC port for simulations + self.solution_type = solution_type + self.set_variables(vars_to_initialize) self.render_design(**design_selection) return self.pinfo.design.name @@ -987,9 +993,10 @@ def render_design( Chip_subtract_dict consists of component names (keys) and a set of all elements within each component that will eventually be subtracted from the ground plane. Add objects that are perfect conductors and/or have - meshing to self.assign_perfE and self.assign_mesh, respectively; both are initialized as empty lists. Note - that these objects are "refreshed" each time render_design is called (as opposed to in the init function) - to clear QAnsysRenderer of any leftover items from the last call to render_design. + meshing to self.assign_perfE and self.assign_mesh, respectively; both are initialized as empty lists. Similarly, + if the object is a port in an eigenmode simulation, add it to self.assign_port_mesh, which is initialized + as an empty list. Note that these objects are "refreshed" each time render_design is called (as opposed to + in the init function) to clear QAnsysRenderer of any leftover items from the last call to render_design. Among the components selected for export, there may or may not be unused (unconnected) pins. The second parameter, open_pins, contains tuples of the form (component_name, pin_name) that @@ -1573,6 +1580,17 @@ def add_mesh(self): MaxLength=self._options["max_mesh_length_jj"], ) + try: + exists_port_mesh = (len(self.assign_port_mesh) > 0) + except: + exists_port_mesh = False + + if exists_port_mesh: + self.modeler.mesh_length( + 'port_mesh', + self.assign_port_mesh, + MaxLength=self._options['max_mesh_length_port']) + # Still implementing def auto_wirebonds(self, table): """ diff --git a/qiskit_metal/renderers/renderer_ansys/hfss_renderer.py b/qiskit_metal/renderers/renderer_ansys/hfss_renderer.py index 6406d302f..a6235c7bd 100644 --- a/qiskit_metal/renderers/renderer_ansys/hfss_renderer.py +++ b/qiskit_metal/renderers/renderer_ansys/hfss_renderer.py @@ -13,6 +13,7 @@ # that they have been altered from the originals. # modified by Chalmers/SK/20210621 +# modified by Samarth Hawaldar from collections import defaultdict from pathlib import Path @@ -40,6 +41,7 @@ class QHFSSRenderer(QAnsysRenderer): * Cj: 0 -- Cj *must* be 0 for pyEPR analysis! Cj has units of femtofarads (fF) * _Rj: 0 -- _Rj *must* be 0 for pyEPR analysis! _Rj has units of Ohms * max_mesh_length_jj: '7um' -- Maximum mesh length for Josephson junction elements + * max_mesh_length_port: '7um' -- Maximum mesh length for Ports in Eigenmode Simulations * project_path: None -- Default project path; if None --> get active * project_name: None -- Default project name * design_name: None -- Default design name @@ -164,6 +166,7 @@ def render_design(self, self.chip_subtract_dict = defaultdict(set) self.assign_perfE = [] self.assign_mesh = [] + self.assign_port_mesh = [] self.jj_lumped_ports = {} self.jj_to_ignore = set() @@ -185,10 +188,10 @@ def render_design(self, self.render_chips(box_plus_buffer=box_plus_buffer) self.subtract_from_ground() - self.add_mesh() - self.metallize() if port_list: self.create_ports(port_list) + self.add_mesh() + self.metallize() def create_ports(self, port_list: list): """Add ports and their respective impedances in Ohms to designated pins @@ -224,10 +227,17 @@ def create_ports(self, port_list: list): y_max - y_min, 0, **dict(transparency=0.0)) axis = 'x' if abs(x1 - x0) > abs(y1 - y0) else 'y' - poly_ansys.make_lumped_port(axis, - z0=str(impedance) + 'ohm', - name=f'LumpPort_{qcomp}_{pin}') - self.modeler.rename_obj(poly_ansys, port_name) + if self.solution_type != 'eigenmode': + poly_ansys.make_lumped_port(axis, + z0=str(impedance) + 'ohm', + name=f'LumpPort_{qcomp}_{pin}') + self.modeler.rename_obj(poly_ansys, port_name) + else: + poly_ansys.make_rlc_boundary(axis, + r=str(impedance) + 'ohm', + name=f'RLCBoundary_{qcomp}_{pin}') + self.modeler.rename_obj(poly_ansys, port_name) + self.assign_port_mesh.append(port_name) # Draw line lump_line = self.modeler.draw_polyline( @@ -435,8 +445,8 @@ def add_drivenmodal_setup(self, *args, **kwargs): """Create a solution setup in Ansys HFSS Driven Modal. If user does - not provide arguments, they will be obtained from default_setup dict. - + not provide arguments, they will be obtained from default_setup dict. + Args: name (str, optional): Name of driven modal setup. Defaults to None. freq_ghz (int, optional): Frequency in GHz. Defaults to None.