diff --git a/src/pyedb/dotnet/edb.py b/src/pyedb/dotnet/edb.py index 28a8bc5cff..9035e3f87b 100644 --- a/src/pyedb/dotnet/edb.py +++ b/src/pyedb/dotnet/edb.py @@ -57,6 +57,9 @@ GapPort, WavePort, ) +from pyedb.dotnet.edb_core.edb_data.raptor_x_simulation_setup_data import ( + RaptorXSimulationSetup, +) from pyedb.dotnet.edb_core.edb_data.simulation_configuration import ( SimulationConfiguration, ) @@ -3584,6 +3587,8 @@ def setups(self): setups[i.GetName()] = SiwaveSYZSimulationSetup(self, i) elif i.GetType() == self.edb_api.utility.utility.SimulationSetupType.kSIWaveDCIR: setups[i.GetName()] = SiwaveDCSimulationSetup(self, i) + elif i.GetType() == self.edb_api.utility.utility.SimulationSetupType.kRaptorX: + setups[i.GetName()] = RaptorXSimulationSetup(self, i) return setups @property @@ -3642,6 +3647,30 @@ def create_hfss_setup(self, name=None): setup = HfssSimulationSetup(self).create(name) return setup + def create_raptorx_setup(self, name=None): + """Create an RaptorX simulation setup from a template. + + Parameters + ---------- + name : str, optional + Setup name. + + Returns + ------- + :class:`legacy.edb_core.edb_data.raptor_x_simulation_setup_data.RaptorXSimulationSetup` + + """ + if name in self.setups: + self.logger.error("Setup name already used in the layout") + return False + version = self.edbversion.split(".") + if int(version[0]) >= 2024 and int(version[-1]) >= 2 or int(version[0]) > 2024: + setup = RaptorXSimulationSetup(self).create(name) + return setup + else: + self.logger.error("RaptorX simulation only supported with Ansys release 2024R2 and higher") + return False + @pyedb_function_handler() def create_siwave_syz_setup(self, name=None): """Create a setup from a template. diff --git a/src/pyedb/dotnet/edb_core/edb_data/raptor_x_simulation_setup_data.py b/src/pyedb/dotnet/edb_core/edb_data/raptor_x_simulation_setup_data.py new file mode 100644 index 0000000000..47b5e016a7 --- /dev/null +++ b/src/pyedb/dotnet/edb_core/edb_data/raptor_x_simulation_setup_data.py @@ -0,0 +1,520 @@ +# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNE SS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from pyedb.dotnet.edb_core.edb_data.edbvalue import EdbValue +from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list +from pyedb.dotnet.edb_core.utilities.simulation_setup import ( + BaseSimulationSetup, + EdbFrequencySweep, +) +from pyedb.generic.data_handlers import pyedb_function_handler +from pyedb.generic.general_methods import generate_unique_name + + +class RaptorXSimulationSetup(BaseSimulationSetup): + """Manages EDB methods for RaptorX simulation setup.""" + + def __init__(self, pedb, edb_object=None): + super().__init__(pedb, edb_object) + self._pedb = pedb + self._setup_type = "kRaptorX" + self._edb_setup_info = None + self.logger = self._pedb.logger + + @pyedb_function_handler + def create(self, name=None): + """Create an HFSS setup.""" + self._name = name + self._create(name) + return self + + @property + def setup_type(self): + return self._setup_type + + @property + def settings(self): + return RaptorXSimulationSettings(self._edb_setup_info, self._pedb) + + @property + def enabled(self): + return self.settings.enabled + + @enabled.setter + def enabled(self, value): + self.settings.enabled = value + + @property + def position(self): + return self._edb_setup_info.Position + + @position.setter + def position(self, value): + if isinstance(value, int): + self._edb_setup_info.Position = value + else: + self.logger.error(f"RaptorX setup position input setter must be an integer. Provided value {value}") + + @property + def frequency_sweeps(self): + return list(self._edb_setup_info.SweepDataList) + + @pyedb_function_handler() + def add_frequency_sweep(self, name=None, frequency_sweep=None): + """Add frequency sweep. + + Parameters + ---------- + name : str, optional + Name of the frequency sweep. + frequency_sweep : list, optional + List of frequency points. + + Returns + ------- + :class:`pyedb.dotnet.edb_core.edb_data.hfss_simulation_setup_data.EdbFrequencySweep` + + Examples + -------- + >>> setup1 = edbapp.create_hfss_setup("setup1") + >>> setup1.add_frequency_sweep(frequency_sweep=[ + ... ["linear count", "0", "1kHz", 1], + ... ["log scale", "1kHz", "0.1GHz", 10], + ... ["linear scale", "0.1GHz", "10GHz", "0.1GHz"], + ... ]) + """ + if name in self.frequency_sweeps: + return False + if not name: + name = generate_unique_name("sweep") + return EdbFrequencySweep(self, frequency_sweep, name) + + +class RaptorXSimulationSettings(object): + def __init__(self, edb_setup_info, pedb): + self._pedb = pedb + self.logger = self._pedb.logger + self._edb_setup_info = edb_setup_info + self._simulation_settings = edb_setup_info.SimulationSettings + self._general_settings = RaptorXGeneralSettings(self._edb_setup_info, self._pedb) + self._advanced_settings = RaptorXSimulationAdvancedSettings(self._edb_setup_info, self._pedb) + self._simulation_settings = self._edb_setup_info.SimulationSettings + + @property + def general_settings(self): + return self._general_settings + + @property + def advanced_settings(self): + return self._advanced_settings + + @property + def enabled(self): + return self._simulation_settings.Enabled + + @enabled.setter + def enabled(self, value): + if isinstance(value, bool): + self._simulation_settings.Enabled = value + else: + self.logger.error(f"RaptorX setup enabled setter input must be a boolean. Provided value {value}") + + +class RaptorXGeneralSettings(object): + def __init__(self, edb_setup_info, pedb): + self._general_settings = edb_setup_info.SimulationSettings.GeneralSettings + self._pedb = pedb + self.logger = self._pedb.logger + + @property + def global_temperature(self): + """The simulation temperature. Units: C""" + return self._general_settings.GlobalTemperature + + @global_temperature.setter + def global_temperature(self, value): + self._general_settings.GlobalTemperature = EdbValue(value).tofloat + + @property + def max_frequency(self): + return self._general_settings.MaxFrequency + + @max_frequency.setter + def max_frequency(self, value): + """This allows user to specify the maximum simulation frequency, a parameter which controls how tight the model + mesh will be. User can override the default meshing frequency as defined by Max Frequency using the Advanced + settings > MeshFrequency. Example: "10GHz". + """ + self._general_settings.MaxFrequency = EdbValue(value).tostring + + +class RaptorXSimulationAdvancedSettings(object): + def __init__(self, edb_setup_info, pedb): + self._edb_setup_info = edb_setup_info + self._advanced_settings = edb_setup_info.SimulationSettings.AdvancedSettings + self._pedb = pedb + self.logger = self._pedb.logger + + @property + def auto_removal_sliver_poly(self): + return self._advanced_settings.AutoRemovalSliverPoly + + @auto_removal_sliver_poly.setter + def auto_removal_sliver_poly(self, value): + self._advanced_settings.AutoRemovalSliverPoly = EdbValue(value).tofloat + + @property + def cell_per_wave_length(self): + """This setting describes the number of cells that fit under each wavelength. The wavelength is + calculated according to the Max Frequency or the Mesh Frequency, unless specified by user through + this setting. E.g. Setting Cells/Wavelength to 20 means that an object will be divided into 10 cells + if its width or length is 1/2 wavelengths. + Units: unitless. + """ + return self._advanced_settings.CellsPerWavelength + + @cell_per_wave_length.setter + def cell_per_wave_length(self, value): + if isinstance(value, int): + self._advanced_settings.CellsPerWavelength = value + else: + self.logger.error(f"RaptorX cell_per_wave_length setter input must be an integer, value provided {value}") + + @property + def edge_mesh(self): + """This option controls both, the thickness and the width of the exterior conductor filament. + When specified, it prevails over the Mesh Frequency or Max Frequency during mesh calculation. + Example: "0.8um". + """ + return self._advanced_settings.EdgeMesh + + @edge_mesh.setter + def edge_mesh(self, value): + self._advanced_settings.EdgeMesh = EdbValue(value).tostring + + @property + def eliminate_slit_per_hole(self): + """This is a setting that internally simplifies layouts with strain relief or thermal relief slits and + holes. It will examine each hole separately against the whole polygon it belongs to. + If the area of the hole is below the threshold defined in this setting, then the hole will be filled. + Units: unitless. + """ + return self._advanced_settings.EliminateSlitPerHoles + + @eliminate_slit_per_hole.setter + def eliminate_slit_per_hole(self, value): + self._advanced_settings.EliminateSlitPerHoles = EdbValue(value).tofloat + + @property + def mesh_frequency(self): + """User can override the default meshing applied by setting a custom frequency for mesh generation. + Example: "1GHz". + """ + return self._advanced_settings.MeshFrequency + + @mesh_frequency.setter + def mesh_frequency(self, value): + self._advanced_settings.MeshFrequency = EdbValue(value).tostring + + @property + def net_settings_options(self): + """A list of Name, Value pairs that stores advanced option.""" + return [val for val in list(self._advanced_settings.NetSettingsOptions)] + + @net_settings_options.setter + def net_settings_options(self, value): + if isinstance(value, list): + self._advanced_settings.NetSettingsOptions = convert_py_list_to_net_list(value) + else: + self.logger.error( + f"RaptorX setup net_settings_options input setter must be a list. " f"Provided value {value}" + ) + + @property + def override_shrink_fac(self): + """Set the shrink factor explicitly, that is, review what-if scenarios of migrating to half-node + technologies. + Units: unitless. + """ + return self._advanced_settings.OverrideShrinkFac + + @override_shrink_fac.setter + def override_shrink_fac(self, value): + self._advanced_settings.OverrideShrinkFac = EdbValue(value).tofloat + + @property + def plane_projection_factor(self): + """To eliminate unnecessary mesh complexity of "large" metal planes and improve overall extraction time, + user can define the mesh of certain planes using a combination of the Plane Projection Factor and + settings of the Nets Advanced Options. + Units: unitless. + """ + return self._advanced_settings.PlaneProjectionFactor + + @plane_projection_factor.setter + def plane_projection_factor(self, value): + self._advanced_settings.PlaneProjectionFactor = EdbValue(value).tofloat + + @property + def use_accelerate_via_extraction(self): + """Setting this option will simplify/merge neighboring vias before sending the layout for processing + to the mesh engine and to the EM engine. + """ + return self._advanced_settings.UseAccelerateViaExtraction + + @use_accelerate_via_extraction.setter + def use_accelerate_via_extraction(self, value): + if isinstance(value, bool): + self._advanced_settings.UseAccelerateViaExtraction = value + else: + self.logger.error( + "RaptorX setup use_accelerate_via_extraction setter input must be boolean." f"Provided value {value}" + ) + + @property + def use_auto_removal_sliver_poly(self): + """Setting this option simplifies layouts by aligning slightly misaligned overlapping polygons.""" + return self._advanced_settings.UseAutoRemovalSliverPoly + + @use_auto_removal_sliver_poly.setter + def use_auto_removal_sliver_poly(self, value): + if isinstance(value, bool): + self._advanced_settings.UseAutoRemovalSliverPoly = value + else: + self.logger.error( + f"RaptorX setup use_auto_removal_sliver_poly setter must be a boolean. " f"Provided value {value}" + ) + + @property + def use_cells_per_wavelength(self): + """This setting describes the number of cells that fit under each wavelength. The wavelength is calculated + according to the Max Frequency or the Mesh Frequency, unless specified by user through this setting. + """ + return self._advanced_settings.UseCellsPerWavelength + + @use_cells_per_wavelength.setter + def use_cells_per_wavelength(self, value): + if isinstance(value, bool): + self._advanced_settings.UseCellsPerWavelength = value + else: + self.logger.error(f"RaptorX setup use_cells_per_wavelength setter must be boolean. Provided value {value}") + + @property + def use_edge_mesh(self): + """This option controls both, the thickness and the width of the exterior conductor filament. + When checked, it prevails over the Mesh Frequency or Max Frequency during mesh calculation. + """ + return self._advanced_settings.UseEdgeMesh + + @use_edge_mesh.setter + def use_edge_mesh(self, value): + if isinstance(value, bool): + self._advanced_settings.UseEdgeMesh = value + else: + self.logger.error(f"RaptorX setup use_edge_mesh setter must be a boolean. Provided value {value}") + + @property + def use_eliminate_slit_per_holes(self): + """This is a setting that internally simplifies layouts with strain relief or thermal relief slits and + holes. + """ + return self._advanced_settings.UseEliminateSlitPerHoles + + @use_eliminate_slit_per_holes.setter + def use_eliminate_slit_per_holes(self, value): + if isinstance(value, bool): + self._advanced_settings.UseEliminateSlitPerHoles = value + else: + self.logger.error( + f"RaptorX setup use_eliminate_slit_per_holes setter must be a boolean. " f"Provided value {value}" + ) + + @property + def use_enable_advanced_cap_effects(self): + """Applies all the capacitance related effects such as Conformal Dielectrics, Loading Effect, + Dielectric Damage. + """ + return self._advanced_settings.UseEnableAdvancedCapEffects + + @use_enable_advanced_cap_effects.setter + def use_enable_advanced_cap_effects(self, value): + if isinstance(value, bool): + self._advanced_settings.UseEnableAdvancedCapEffects = value + else: + self.logger.error( + f"RaptorX setup use_enable_advanced_cap_effects setter must be a boolean. " f"Provided value {value}" + ) + + @property + def use_enable_etch_transform(self): + """Pre-distorts the layout based on the foundry rules, applying the conductor's bias (positive/negative – + deflation/inflation) at the conductor edges due to unavoidable optical effects in the manufacturing process. + """ + return self._advanced_settings.UseEnableEtchTransform + + @use_enable_etch_transform.setter + def use_enable_etch_transform(self, value): + if isinstance(value, bool): + self._advanced_settings.UseEnableEtchTransform = value + else: + self.logger.error( + f"RaptorX setup use_enable_etch_transform setter must be a boolean. " f"Provided value {value}" + ) + + @property + def use_enable_hybrid_extraction(self): + """This setting allows the modelling engine to separate the layout into two parts in an attempt to + decrease the complexity of EM modelling. + """ + return self._edb_setup_info.UseEnableHybridExtraction + + @use_enable_hybrid_extraction.setter + def use_enable_hybrid_extraction(self, value): + if isinstance(value, bool): + self._advanced_settings.UseEnableHybridExtraction = value + else: + self.logger.error( + f"RaptorX setup use_enable_hybrid_extraction setter must be a boolean. " f"Provided value {value}" + ) + + @property + def use_enable_substrate_network_extraction(self): + """This setting models substrate coupling effects using an equivalent distributed RC network.""" + return self._advanced_settings.UseEnableSubstrateNetworkExtraction + + @use_enable_substrate_network_extraction.setter + def use_enable_substrate_network_extraction(self, value): + if isinstance(value, bool): + self._advanced_settings.UseEnableSubstrateNetworkExtraction = value + else: + self.logger.error( + f"RaptorX setup use_enable_substrate_network_extraction setter must be a boolean. " + f"Provided value {value}" + ) + + @property + def use_extract_floating_metals_dummy(self): + """Enables modeling of floating metals as dummy fills. Captures the effect of dummy fill by extracting + the effective capacitance between any pairs of metal segments in the design, in the presence of each + individual dummy metal islands. This setting cannot be used with UseExtractFloatingMetalsFloating. + """ + return self._advanced_settings.UseExtractFloatingMetalsDummy + + @use_extract_floating_metals_dummy.setter + def use_extract_floating_metals_dummy(self, value): + if isinstance(value, bool): + self._advanced_settings.UseExtractFloatingMetalsDummy = value + else: + self.logger.error( + f"RaptorX setup use_extract_floating_metals_dummy setter must be a boolean. " f"Provided value {value}" + ) + + @property + def use_extract_floating_metals_floating(self): + """Enables modeling of floating metals as floating nets. Floating metal are grouped into a single entity + and treated as an independent net. This setting cannot be used with UseExtractFloatingMetalsDummy. + """ + return self._advanced_settings.UseExtractFloatingMetalsFloating + + @use_extract_floating_metals_floating.setter + def use_extract_floating_metals_floating(self, value): + if isinstance(value, bool): + self._advanced_settings.UseExtractFloatingMetalsFloating = value + else: + self.logger.error( + f"RaptorX setup use_extract_floating_metals_floating setter must be a boolean. " + f"Provided value {value}" + ) + + @property + def use_lde(self): + """ + Takes into account the variation of resistivity as a function of a conductor’s drawn width and spacing to + its neighbors or as a function of its local density, due to dishing, slotting, cladding thickness, and so + on. + """ + return self._advanced_settings.UseLDE + + @use_lde.setter + def use_lde(self, value): + if isinstance(value, bool): + self._advanced_settings.UseLDE = value + else: + self.logger.error(f"RaptorX setup use_lde setter must be a boolean. Provided value {value}") + + @property + def use_mesh_frequency(self): + """ + User can override the default meshing applied by the mesh engine by checking this option and setting a + custom frequency for mesh generation. + """ + return self._advanced_settings.UseMeshFrequency + + @use_mesh_frequency.setter + def use_mesh_frequency(self, value): + if isinstance(value, bool): + self._advanced_settings.UseMeshFrequency = value + else: + self.logger.error(f"RaptorX setup use_mesh_frequency setter must be a boolean. Provided value {value}") + + @property + def use_override_shrink_fac(self): + """Set the shrink factor explicitly, that is, review what-if scenarios of migrating to half-node + technologies. + """ + return self._advanced_settings.UseOverrideShrinkFac + + @use_override_shrink_fac.setter + def use_override_shrink_fac(self, value): + if isinstance(value, bool): + self._advanced_settings.UseOverrideShrinkFac = value + else: + self.logger.error(f"RaptorX setup use_override_shrink_fac setter must be a boolean. Provided value {value}") + + @property + def use_plane_projection_factor(self): + """To eliminate unnecessary mesh complexity of "large" metal planes and improve overall + extraction time, user can define the mesh of certain planes using a combination of the Plane Projection + Factor and settings of the Nets Advanced Options. + """ + return self._advanced_settings.UsePlaneProjectionFactor + + @use_plane_projection_factor.setter + def use_plane_projection_factor(self, value): + if isinstance(value, bool): + self._advanced_settings.UsePlaneProjectionFactor = value + else: + self.logger.error( + f"RaptorX setup use_plane_projection_factor setter must be a boolean. " f"Provided value {value}" + ) + + @property + def use_relaxed_z_axis(self): + """Enabling this option provides a simplified mesh along the z-axis.""" + return self._advanced_settings.UseRelaxedZAxis + + @use_relaxed_z_axis.setter + def use_relaxed_z_axis(self, value): + if isinstance(value, bool): + self._advanced_settings.UseRelaxedZAxis = value + else: + self.logger.error(f"RaptorX setup use_relaxed_z_axis setter must be a boolean. " f"Provided value {value}") diff --git a/src/pyedb/dotnet/edb_core/utilities/simulation_setup.py b/src/pyedb/dotnet/edb_core/utilities/simulation_setup.py index ea3ba94fed..eef467a60b 100644 --- a/src/pyedb/dotnet/edb_core/utilities/simulation_setup.py +++ b/src/pyedb/dotnet/edb_core/utilities/simulation_setup.py @@ -56,6 +56,7 @@ def __init__(self, pedb, edb_setup=None): "kDDRwizard": None, "kQ3D": None, "kNumSetupTypes": None, + "kRaptorX": self._pedb.simsetupdata.RaptorX.RaptorXSimulationSettings, } if self._edb_object: self._name = self._edb_object.GetName() @@ -72,6 +73,8 @@ def _create(self, name=None): setup_type = self._setup_type_mapping[self._setup_type] edb_setup_info = self._pedb.simsetupdata.SimSetupInfo[setup_type]() edb_setup_info.Name = name + if edb_setup_info.get_SimSetupType().ToString() == "kRaptorX": + self._edb_setup_info = edb_setup_info self._edb_object = self._set_edb_setup_info(edb_setup_info) self._update_setup() @@ -96,6 +99,9 @@ def _set_edb_setup_info(self, edb_setup_info): "kQ3D": None, "kNumSetupTypes": None, } + version = self._pedb.edbversion.split(".") + if int(version[0]) == 2024 and int(version[1]) == 2 or int(version[0]) > 2024: + setup_type_mapping["kRaptorX"] = utility.RaptorXSimulationSetup setup_utility = setup_type_mapping[self._setup_type] return setup_utility(edb_setup_info) @@ -122,9 +128,8 @@ def enabled(self): @enabled.setter def enabled(self, value): - edb_setup_info = self.get_sim_setup_info - edb_setup_info.SimulationSettings.Enabled = value - self._edb_object = self._set_edb_setup_info(edb_setup_info) + self.get_sim_setup_info.SimulationSettings.Enabled = value + self._edb_object = self._set_edb_setup_info(self.get_sim_setup_info) self._update_setup() @property @@ -175,9 +180,12 @@ def _add_frequency_sweep(self, sweep_data): sweep_data: EdbFrequencySweep """ self._sweep_list[sweep_data.name] = sweep_data - edb_setup_info = self.get_sim_setup_info + if self.setup_type == "kRaptorX": + edb_setup_info = self._edb_setup_info + else: + edb_setup_info = self.get_sim_setup_info - if self._setup_type in ["kSIwave", "kHFSS"]: + if self._setup_type in ["kSIwave", "kHFSS", "kRaptorX"]: for _, v in self._sweep_list.items(): edb_setup_info.SweepDataList.Add(v._edb_object) @@ -197,14 +205,13 @@ def delete_frequency_sweep(self, sweep_data): self._sweep_list.pop(name) fsweep = [] - for k, val in self.frequency_sweeps.items(): - if not k == name: - fsweep.append(val) - self.get_sim_setup_info.SweepDataList.Clear() - for i in fsweep: - self.get_sim_setup_info.SweepDataList.Add(i._edb_object) - self._update_setup() - return True if name in self.frequency_sweeps else False + if self.frequency_sweeps: + fsweep = [val for key, val in self.frequency_sweeps.items() if not key == name] + self.get_sim_setup_info.SweepDataList.Clear() + for i in fsweep: + self.get_sim_setup_info.SweepDataList.Add(i._edb_object) + self._update_setup() + return True if name in self.frequency_sweeps else False @pyedb_function_handler() def add_frequency_sweep(self, name=None, frequency_sweep=None): @@ -722,6 +729,8 @@ def set_frequencies(self, frequency_list=None, update=True): ["linear scale", "0.1GHz", "10GHz", "0.1GHz"], ] temp = [] + if isinstance(frequency_list, list) and not isinstance(frequency_list[0], list): + frequency_list = [frequency_list] for i in frequency_list: if i[0] == "linear count": temp.extend(list(self._edb_sweep_data.SetFrequencies(i[1], i[2], i[3]))) diff --git a/tests/legacy/system/test_edb.py b/tests/legacy/system/test_edb.py index 7185e6e28c..1ee99ba879 100644 --- a/tests/legacy/system/test_edb.py +++ b/tests/legacy/system/test_edb.py @@ -1733,6 +1733,97 @@ def test_multizone(self, edb_examples): assert project_connexions edbapp.close_edb() + @pytest.mark.skipif( + not desktop_version == "2024.2" or int(desktop_version.split(".")[0]) >= 2025, + reason="Only supported with 2024.2 and higher", + ) + def test_add_raptorx_setup(self): + source_path = os.path.join(local_path, "example_models", test_subfolder, "ANSYS-HSD_V1.aedb") + target_path = os.path.join(self.local_scratch.path, "test_raptorx_setup", "test.aedb") + self.local_scratch.copyfolder(source_path, target_path) + edbapp = Edb(edbpath=target_path, edbversion=desktop_version) + setup = edbapp.create_raptorx_setup("test") + assert "test" in edbapp.setups + setup.add_frequency_sweep(frequency_sweep=["linear scale", "0.1GHz", "10GHz", "0.1GHz"]) + setup.enabled = False + assert not setup.enabled + assert len(setup.frequency_sweeps) == 1 + general_settings = setup.settings.general_settings + assert general_settings.global_temperature == 22.0 + general_settings.global_temperature = 35.0 + assert edbapp.setups["test"].settings.general_settings.global_temperature == 35.0 + assert general_settings.max_frequency == "10GHz" + general_settings.max_frequency = 20e9 + assert general_settings.max_frequency == "20GHz" + advanced_settings = setup.settings.advanced_settings + assert advanced_settings.auto_removal_sliver_poly == 0.001 + advanced_settings.auto_removal_sliver_poly = 0.002 + assert advanced_settings.auto_removal_sliver_poly == 0.002 + assert advanced_settings.cell_per_wave_length == 80 + advanced_settings.cell_per_wave_length = 60 + assert advanced_settings.cell_per_wave_length == 60 + assert advanced_settings.edge_mesh == "0.8um" + advanced_settings.edge_mesh = "1um" + assert advanced_settings.edge_mesh == "1um" + assert advanced_settings.eliminate_slit_per_hole == 5.0 + advanced_settings.eliminate_slit_per_hole = 4.0 + assert advanced_settings.eliminate_slit_per_hole == 4.0 + assert advanced_settings.mesh_frequency == "1GHz" + advanced_settings.mesh_frequency = "5GHz" + assert advanced_settings.mesh_frequency == "5GHz" + assert advanced_settings.override_shrink_fac == 1.0 + advanced_settings.override_shrink_fac = 1.5 + assert advanced_settings.override_shrink_fac == 1.5 + assert advanced_settings.plane_projection_factor == 1.0 + advanced_settings.plane_projection_factor = 1.4 + assert advanced_settings.plane_projection_factor == 1.4 + assert advanced_settings.use_accelerate_via_extraction + advanced_settings.use_accelerate_via_extraction = False + assert not advanced_settings.use_accelerate_via_extraction + assert not advanced_settings.use_auto_removal_sliver_poly + advanced_settings.use_auto_removal_sliver_poly = True + assert advanced_settings.use_auto_removal_sliver_poly + assert not advanced_settings.use_cells_per_wavelength + advanced_settings.use_cells_per_wavelength = True + assert advanced_settings.use_cells_per_wavelength + assert not advanced_settings.use_edge_mesh + advanced_settings.use_edge_mesh = True + assert advanced_settings.use_edge_mesh + assert not advanced_settings.use_eliminate_slit_per_holes + advanced_settings.use_eliminate_slit_per_holes = True + assert advanced_settings.use_eliminate_slit_per_holes + assert not advanced_settings.use_enable_advanced_cap_effects + advanced_settings.use_enable_advanced_cap_effects = True + assert advanced_settings.use_enable_advanced_cap_effects + assert not advanced_settings.use_enable_etch_transform + advanced_settings.use_enable_etch_transform = True + assert advanced_settings.use_enable_etch_transform + assert advanced_settings.use_enable_substrate_network_extraction + advanced_settings.use_enable_substrate_network_extraction = False + assert not advanced_settings.use_enable_substrate_network_extraction + assert not advanced_settings.use_extract_floating_metals_dummy + advanced_settings.use_extract_floating_metals_dummy = True + assert advanced_settings.use_extract_floating_metals_dummy + assert advanced_settings.use_extract_floating_metals_floating + advanced_settings.use_extract_floating_metals_floating = False + assert not advanced_settings.use_extract_floating_metals_floating + assert not advanced_settings.use_lde + advanced_settings.use_lde = True + assert advanced_settings.use_lde + assert not advanced_settings.use_mesh_frequency + advanced_settings.use_mesh_frequency = True + assert advanced_settings.use_mesh_frequency + assert not advanced_settings.use_override_shrink_fac + advanced_settings.use_override_shrink_fac = True + assert advanced_settings.use_override_shrink_fac + assert advanced_settings.use_plane_projection_factor + advanced_settings.use_plane_projection_factor = False + assert not advanced_settings.use_plane_projection_factor + assert not advanced_settings.use_relaxed_z_axis + advanced_settings.use_relaxed_z_axis = True + assert advanced_settings.use_relaxed_z_axis + edbapp.close() + def test_icepak(self, edb_examples): edbapp = edb_examples.get_si_verse(additional_files_folders=["siwave/icepak_component.pwrd"]) edbapp.siwave.icepak_use_minimal_comp_defaults = True