diff --git a/AUTHORS b/AUTHORS index 2c4b483650..d1bbfd08f8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -5,8 +5,8 @@ # For contributions made under a Corporate CLA, the organization is # added to this file. # -# If you have contributed to the repository and wish to be added to this file -# please submit a request. +# If you have contributed to the repository and want to be added to this file, +# submit a request. # # -ANSYS, Inc. +ANSYS, Inc. \ No newline at end of file diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ffcfd83556..f16e7c9963 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,4 +1,4 @@ -# Authors +# Contributors ## Project Lead diff --git a/doc/.vale.ini b/doc/.vale.ini index 211f6a2074..4f0b670983 100644 --- a/doc/.vale.ini +++ b/doc/.vale.ini @@ -20,7 +20,7 @@ WordTemplate = \b(?:%s)\b Packages = Google # Define the Ansys vocabulary -Vocab = Ansys +Vocab = ANSYS [*.{md,rst}] diff --git a/doc/styles/Vocab/ANSYS/accept.txt b/doc/styles/Vocab/ANSYS/accept.txt index 3f94bc337b..05a4aa7fb1 100644 --- a/doc/styles/Vocab/ANSYS/accept.txt +++ b/doc/styles/Vocab/ANSYS/accept.txt @@ -10,3 +10,4 @@ isort Juptyer Makefile pytest +subdesigns diff --git a/pyproject.toml b/pyproject.toml index 5a4ac055e5..7b96e6957d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "flit_core.buildapi" [project] # Check https://flit.readthedocs.io/en/latest/pyproject_toml.html for all available sections name = "ansys-edb-core" -version = "0.1.7" +version = "0.1.8" description = "A python wrapper for Ansys Edb service" readme = "README.rst" requires-python = ">=3.8" @@ -26,7 +26,7 @@ classifiers = [ # FIXME: add ansys-api-edb version dependencies = [ - "ansys-api-edb==1.0.7", + "ansys-api-edb==1.0.9", "protobuf>=3.19.3,<5", "grpcio>=1.44.0" ] diff --git a/src/ansys/edb/core/hierarchy/pin_group.py b/src/ansys/edb/core/hierarchy/pin_group.py index 727fac3993..663126248a 100644 --- a/src/ansys/edb/core/hierarchy/pin_group.py +++ b/src/ansys/edb/core/hierarchy/pin_group.py @@ -4,13 +4,14 @@ from ansys.edb.core.inner import messages from ansys.edb.core.inner.conn_obj import ConnObj from ansys.edb.core.primitive.primitive import PadstackInstance -from ansys.edb.core.session import StubAccessor, StubType +from ansys.edb.core.session import PinGroupServiceStub, StubAccessor, StubType +from ansys.edb.core.terminal.terminals import PinGroupTerminal class PinGroup(ConnObj): """Represents a pin group object.""" - __stub = StubAccessor(StubType.pin_group) + __stub: PinGroupServiceStub = StubAccessor(StubType.pin_group) layout_obj_type = LayoutObjType.PIN_GROUP @classmethod @@ -110,3 +111,11 @@ def remove_pins(self, pins): List of padstick instances. """ self.__stub.RemovePins(messages.pin_group_pins_modify_message(self, pins)) + + @property + def pin_group_terminal(self): + """:class:`.PinGroupTerminal`: Terminal this pin group is part of. + + This property is read-only. + """ + return PinGroupTerminal(self.__stub.GetPinGroupTerminal(self.msg)) diff --git a/src/ansys/edb/core/inner/messages.py b/src/ansys/edb/core/inner/messages.py index 6004508699..0ebf319c78 100644 --- a/src/ansys/edb/core/inner/messages.py +++ b/src/ansys/edb/core/inner/messages.py @@ -299,7 +299,7 @@ def polygon_data_with_circle_message(pd, center, radius): def polygon_data_with_point_message(pd, point): """Convert to a ``PolygonDataWithPointMessage`` object.""" - return PolygonDataWithPointMessage(polygon=polygon_data_message(pd), point=point_message(point)) + return PolygonDataWithPointMessage(target=polygon_data_message(pd), point=point_message(point)) def polygon_data_with_points_message(pd, point=None, polygon=None): diff --git a/src/ansys/edb/core/layout/layout.py b/src/ansys/edb/core/layout/layout.py index b6803d9f1f..197d166375 100644 --- a/src/ansys/edb/core/layout/layout.py +++ b/src/ansys/edb/core/layout/layout.py @@ -19,6 +19,34 @@ from ansys.edb.core.terminal.terminals import Terminal +def _geometry_simplifications_settings_msg(layout, layer, tol): + """Create a GeometrySimplificationSettingsMessage.""" + return layout_pb2.GeometrySimplificationSettingsMessage( + layout_layer=messages.layer_ref_property_message(layout, layer), + tolerance=messages.value_message(tol), + ) + + +def _geometry_simplifications_settings_with_option_msg(layout, layer, tol, option): + """Create a GeometrySimplificationSettingsWithOptionMessage.""" + return layout_pb2.GeometrySimplificationSettingsWithOptionMessage( + geom_simplification_settings=_geometry_simplifications_settings_msg(layout, layer, tol), + option=option, + ) + + +def _via_simplifications_settings_with_option_msg( + layout, layer, tol, option, simplification_method +): + """Create a ViaSimplificationSettingsMessage.""" + return layout_pb2.ViaSimplificationSettingsMessage( + geom_simplification_settings_with_option=_geometry_simplifications_settings_with_option_msg( + layout, layer, tol, option + ), + simplification_method=simplification_method, + ) + + class Layout(ObjBase, variable_server.VariableServer): """Represents a layout.""" @@ -279,6 +307,28 @@ def layout_instance(self): """ return layout_instance.LayoutInstance(self.__stub.GetLayoutInstance(self.msg)) + def reconstruct_arcs(self, layer, tolerance): + """Reconstruct arcs of polygons on a layer. + + Parameters + ---------- + layer : str or :class:`.Layer` + Layer to reconstruct arcs on. + tolerance : :class:`.Value` + Tolerance. + """ + self.__stub.ReconstructArcs(_geometry_simplifications_settings_msg(self, layer, tolerance)) + + def unite_primitives(self, layer): + """Unite primitives on a layer. + + Parameters + ---------- + layer : str or :class:`.Layer` + Layer to unite primitives on. + """ + self.__stub.UnitePrimitives(messages.layer_ref_property_message(self, layer)) + def create_stride(self, filename): """Create a Stride model from an MCAD file. @@ -325,3 +375,92 @@ def create_3d_comp(self, filename): 3D composite model created. """ return McadModel.create_3d_comp(layout=self, filename=filename) + + def group_vias( + self, + layer, + max_grouping_distance="100um", + persistent_vias=False, + group_by_proximity=True, + check_containment=True, + ): + """Create via groups from the primitives on the specified layer. + + Parameters + ---------- + layer : str or :class:`.Layer` + Layer containing the primitives to be grouped. + max_grouping_distance : :term:`ValueLike` + Maximum distance between vias in a via group . + persistent_vias : bool + Whether to preserve primitives during via group creation. If ``False`` + primitives are deleted during via group creation. + group_by_proximity : bool + If ``True``, vias are grouped by proximity (relative position to each other). + If ``False``, vias are grouped by range (any vias within the specified maximum + grouping distance of each other are grouped) + check_containment : boo + If ``True``, the connectivity of via groups is checked and enforced to prevent + short circuits in geometry connecting to the via group. If false, vias are + grouped regardless of the connectivity of touching geometry. + """ + self.__stub.GroupVias( + layout_pb2.ViaGroupingSettingsMessage( + via_simplification_settings=_via_simplifications_settings_with_option_msg( + self, layer, max_grouping_distance, check_containment, group_by_proximity + ), + persistent=persistent_vias, + ) + ) + + def snap_vias( + self, + layer, + via_snapping_tol=3, + prim_snapping_tol="0.05um", + snap_by_area_factor=True, + remove_dangling_vias=True, + ): + """Snap vias on the specified layer to touching geometry. + + Parameters + ---------- + layer : str or :class:`.Layer` + Layer containing the vias to be snapped. + via_snapping_tol : :term:`ValueLike` + Tolerance for snapping vias. If snap_by_area_factor is ``True``, this + value should not have a unit. + prim_snapping_tol : :term:`ValueLike` + Tolerance for snapping primitives. + snap_by_area_factor : bool + If ``True``, the via snapping tolerance is a factor of the surface area of the via. + If ``False``, the via snapping tolerance is treated as an absolute distance. + remove_dangling_vias : bool + If ``True``, vias not connected to any geometry are removed. + """ + self.__stub.SnapVias( + layout_pb2.ViaSnappingSettingsMessage( + via_simplification_settings=_via_simplifications_settings_with_option_msg( + self, layer, via_snapping_tol, remove_dangling_vias, snap_by_area_factor + ), + prim_snapping_tol=messages.value_message(prim_snapping_tol), + ) + ) + + def snap_primitives(self, layer, tol="0.05um", check_connectivity=True): + """Snap primitives on the specified layer to touching geometry. + + Parameters + ---------- + layer : str or :class:`.Layer` + Layer containing the primitives to be snapped. + tol : :term:`ValueLike` + Tolerance for snapping primitives. + check_connectivity : bool + If ``True``, the connectivity of primitives is checked and enforced to prevent + short circuits in geometry connecting to the primitives. If false, primitives are + grouped regardless of the connectivity of touching geometry. + """ + self.__stub.SnapPrimitives( + _geometry_simplifications_settings_with_option_msg(self, layer, tol, check_connectivity) + ) diff --git a/src/ansys/edb/core/primitive/primitive.py b/src/ansys/edb/core/primitive/primitive.py index a0a2aa8044..e661120302 100644 --- a/src/ansys/edb/core/primitive/primitive.py +++ b/src/ansys/edb/core/primitive/primitive.py @@ -1325,7 +1325,7 @@ def _set_elevation_message(b, cell_instance, lyrname): ) -class PadstackInstance(Primitive): +class PadstackInstance(conn_obj.ConnObj): """Representis a padstack instance object.""" __stub: padstack_instance_pb2_grpc.PadstackInstanceServiceStub = StubAccessor( diff --git a/src/ansys/edb/core/simulation_setup/simulation_settings.py b/src/ansys/edb/core/simulation_setup/simulation_settings.py index 7dcff5309d..83faad67ac 100644 --- a/src/ansys/edb/core/simulation_setup/simulation_settings.py +++ b/src/ansys/edb/core/simulation_setup/simulation_settings.py @@ -69,22 +69,22 @@ class SettingsOptions(SimulationSettingsBase): __stub: SettingsOptionsServiceStub = StubAccessor(StubType.sim_settings_options) @property - def do_lamda_refine(self): + def do_lambda_refine(self): """:obj:`bool`: Flag indicating if lambda refinement is used during meshing.""" return self.__stub.GetDoLamdaRefineFlag(self.msg).value - @do_lamda_refine.setter - def do_lamda_refine(self, do_lamda_refine): - self.__stub.SetDoLamdaRefineFlag(messages.bool_property_message(self, do_lamda_refine)) + @do_lambda_refine.setter + def do_lambda_refine(self, do_lambda_refine): + self.__stub.SetDoLamdaRefineFlag(messages.bool_property_message(self, do_lambda_refine)) @property - def lamda_target(self): + def lambda_target(self): """:obj:`float`: Target lambda value for lambda refinement.""" return self.__stub.GetLamdaTarget(self.msg).value - @lamda_target.setter - def lamda_target(self, lamda_target): - self.__stub.SetLamdaTarget(messages.double_property_message(self, lamda_target)) + @lambda_target.setter + def lambda_target(self, lambda_target): + self.__stub.SetLamdaTarget(messages.double_property_message(self, lambda_target)) @property def mesh_size_factor(self): @@ -96,12 +96,12 @@ def mesh_size_factor(self, mesh_size_factor): self.__stub.SetMeshSizefactor(messages.double_property_message(self, mesh_size_factor)) @property - def use_default_lamda_value(self): + def use_default_lambda_value(self): """:obj:`bool`: Flag indicating if the default lambda target value is used.""" return self.__stub.GetLamdaTarget(self.msg).value - @use_default_lamda_value.setter - def use_default_lamda_value(self, use_default_value): + @use_default_lambda_value.setter + def use_default_lambda_value(self, use_default_value): self.__stub.SetDoLamdaRefineFlag(messages.bool_property_message(self, use_default_value)) diff --git a/src/ansys/edb/core/simulation_setup/simulation_setup.py b/src/ansys/edb/core/simulation_setup/simulation_setup.py index 14a0463fa6..9a2221ff88 100644 --- a/src/ansys/edb/core/simulation_setup/simulation_setup.py +++ b/src/ansys/edb/core/simulation_setup/simulation_setup.py @@ -86,8 +86,6 @@ class InterpolatingSweepData: Use fast sweep. adaptive_sampling : bool Use adaptive sampling. - enforce_dc_and_causality : bool - Enforce dc point and causality. matrix_conv_entry_list : list[MatrixConvergenceDataEntry] Matrix convergence data for frequency sweep. min_subranges : int @@ -109,7 +107,6 @@ def __init__(self): self.use_full_basis = True self.fast_sweep = False self.adaptive_sampling = False - self.enforce_dc_and_causality = False self.matrix_conv_entry_list = [] self.min_subranges = 1 self.min_solutions = 0 @@ -261,7 +258,6 @@ def _interpolating_sweep_data_msg(interp_sweep_data): interp_use_full_basis=interp_sweep_data.use_full_basis, fast_sweep=interp_sweep_data.fast_sweep, adaptive_sampling=interp_sweep_data.adaptive_sampling, - enforce_dc_and_causality=interp_sweep_data.enforce_dc_and_causality, matrix_conv_entry_list=messages.mx_convergence_entry_msg_list( interp_sweep_data.matrix_conv_entry_list ), @@ -326,7 +322,6 @@ def _msg_to_interpolating_sweep_data(msg): interp_sweep_data.use_full_basis = msg.interp_use_full_basis interp_sweep_data.fast_sweep = msg.fast_sweep interp_sweep_data.adaptive_sampling = msg.adaptive_sampling - interp_sweep_data.enforce_dc_and_causality = msg.enforce_dc_and_causality interp_sweep_data.matrix_conv_entry_list = map_list( msg.matrix_conv_entry_list, _msg_to_matrix_convergence_entry ) diff --git a/src/ansys/edb/core/simulation_setup/siwave_simulation_settings.py b/src/ansys/edb/core/simulation_setup/siwave_simulation_settings.py index 1d12aba049..69ee412ccf 100644 --- a/src/ansys/edb/core/simulation_setup/siwave_simulation_settings.py +++ b/src/ansys/edb/core/simulation_setup/siwave_simulation_settings.py @@ -48,6 +48,13 @@ class SParamDCBehavior(Enum): OPEN_DC = pb.OPEN_DC +class ACDCMergeMode(Enum): + """Provides an enum representing AC/DC merge mode types.""" + + DEFAULT = pb.DEFAULT + FAST = pb.FAST + + class SIWaveSimulationSettings(SimulationSettings): """Represents SIWave simulation settings.""" @@ -259,6 +266,19 @@ def mesh_frequency(self): def mesh_frequency(self, mesh_frequency): self.__stub.SetMeshFrequency(messages.string_property_message(self, mesh_frequency)) + @property + def ac_dc_merge_mode(self): + """:obj:`int`: AC/DC merge mode.""" + return ACDCMergeMode(self.__stub.GetAcDcMergeMode(self.msg).ac_dc_merge_mode) + + @ac_dc_merge_mode.setter + def ac_dc_merge_mode(self, ac_dc_merge_mode): + self.__stub.SetAcDcMergeMode( + pb.ACDCMergeModePropertyMessage( + target=self.msg, ac_dc_merge_mode=ac_dc_merge_mode.value + ) + ) + @property def return_current_distribution(self): """:obj:`bool`: Flag indicating if return current distribution is traced.""" diff --git a/src/ansys/edb/core/terminal/terminals.py b/src/ansys/edb/core/terminal/terminals.py index 89cc7cde0c..d52e768862 100644 --- a/src/ansys/edb/core/terminal/terminals.py +++ b/src/ansys/edb/core/terminal/terminals.py @@ -639,7 +639,7 @@ def layer(self): @layer.setter def layer(self, value): - self.params = (messages.edb_obj_message(value), self.point) + self.params = (value, self.point) @property def point(self): @@ -648,7 +648,7 @@ def point(self): @point.setter def point(self, value): - self.params = (self.layer, messages.point_message(value)) + self.params = (self.layer, value) class PadstackInstanceTerminal(Terminal): @@ -695,7 +695,7 @@ def params(self): res = self.__stub.GetParameters(self.msg) padstack_instance = primitive.PadstackInstance(res.padstack_instance) - layer = Layer(res.layer).cast() + layer = Layer(res.layer.id).cast() return padstack_instance, layer @params.setter diff --git a/tests/e2e/scratch/sim_setup_scratch.py b/tests/e2e/scratch/sim_setup_scratch.py index 7cf6b9f485..51772e6f44 100644 --- a/tests/e2e/scratch/sim_setup_scratch.py +++ b/tests/e2e/scratch/sim_setup_scratch.py @@ -237,17 +237,16 @@ def do_dcr_test(settings: HFSSDCRSettings): def do_options_test(settings: HFSSSettingsOptions): - og_do_lamda_refine = settings.do_lamda_refine - settings.do_lamda_refine = not og_do_lamda_refine - new_do_lamda_refine = settings.do_lamda_refine + og_do_lamda_refine = settings.do_lambda_refine + settings.do_lambda_refine = not og_do_lamda_refine + new_do_lamda_refine = settings.do_lambda_refine - og_lamda_target = settings.lamda_target - settings.lamda_target = og_lamda_target + 0.75 - new_lamda_target = settings.lamda_target - - og_use_default_lamda_value = settings.use_default_lamda_value - settings.use_default_lamda_value = not og_use_default_lamda_value - new_use_default_lamda_value = settings.use_default_lamda_value + og_lamda_target = settings.lambda_target + settings.lambda_target = og_lamda_target + 0.75 + new_lamda_target = settings.lambda_target + og_use_default_lamda_value = settings.use_default_lambda_value + settings.use_default_lambda_value = not og_use_default_lamda_value + new_use_default_lamda_value = settings.use_default_lambda_value og_max_refinement_per_pass = settings.max_refinement_per_pass settings.max_refinement_per_pass = og_max_refinement_per_pass + 1 @@ -308,7 +307,9 @@ def do_hfss_sim_settings_test(settings: HFSSSimulationSettings): def do_test(): - db = Database.create("test.aedb") + test_db_path = "test.aedb" + Database.delete(test_db_path) + db = Database.create(test_db_path) test_cell = Cell.create(db, CellType.CIRCUIT_CELL, "test_cell") hfss_sim_setup = HfssSimulationSetup.create(test_cell, "test_sim_setup")