Skip to content

Commit

Permalink
Merge branch 'main' into adm_aedt_file_3dcomponents_cell
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuelopez-ansys authored Oct 26, 2023
2 parents 5421636 + 103bdf1 commit e70c387
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 8 deletions.
12 changes: 11 additions & 1 deletion _unittest/test_00_EDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -729,16 +729,26 @@ def test_063_create_custom_cutout(self):
edbapp.nets.nets
assert edbapp.cutout(
signal_list=["1V0"],
reference_list=["GND"],
reference_list=[
"GND",
"LVDS_CH08_N",
"LVDS_CH08_P",
"LVDS_CH10_N",
"LVDS_CH10_P",
"LVDS_CH04_P",
"LVDS_CH04_N",
],
extent_type="Bounding",
number_of_threads=4,
extent_defeature=0.001,
preserve_components_with_model=True,
keep_lines_as_path=True,
)
assert "A0_N" not in edbapp.nets.nets
assert isinstance(edbapp.nets.find_and_fix_disjoint_nets("GND", order_by_area=True), list)
assert isinstance(edbapp.nets.find_and_fix_disjoint_nets("GND", keep_only_main_net=True), list)
assert isinstance(edbapp.nets.find_and_fix_disjoint_nets("GND", clean_disjoints_less_than=0.005), list)

edbapp.close()

@pytest.mark.skipif(sys.version_info < (3, 8), reason="Method works in CPython only")
Expand Down
20 changes: 18 additions & 2 deletions _unittest/test_09_VariableManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,9 @@ def test_13_postprocessing(self):
def test_14_intrinsics(self):
self.aedtapp["fc"] = "Freq"
assert self.aedtapp["fc"] == "Freq"
assert self.aedtapp.variable_manager.dependent_variables["fc"].numeric_value == 1.0
assert self.aedtapp.variable_manager.dependent_variables["fc"].units == "GHz"
assert self.aedtapp.variable_manager.dependent_variables["fc"].units == self.aedtapp.odesktop.GetDefaultUnit(
"Frequency"
)

def test_15_arrays(self):
self.aedtapp["arr_index"] = 0
Expand Down Expand Up @@ -658,3 +659,18 @@ def test_31_test_validator_float_type_invalidate(self, validation_float_input):
validation_errors = generate_validation_errors(property_names, expected_settings, actual_settings)

assert len(validation_errors) == 1

def test_32_delete_unused_variables(self):
self.aedtapp.insert_design("used_variables")
self.aedtapp["used_var"] = "1mm"
self.aedtapp["unused_var"] = "1mm"
self.aedtapp["$project_used_var"] = "1"
self.aedtapp.modeler.create_rectangle(0, ["used_var", "used_var", "used_var"], [10, 20])
mat1 = self.aedtapp.materials.add_material("new_copper2")
mat1.permittivity = "$project_used_var"
assert self.aedtapp.variable_manager.delete_variable("unused_var")
self.aedtapp["unused_var"] = "1mm"
number_of_variables = len(self.aedtapp.variable_manager.variable_names)
assert self.aedtapp.variable_manager.delete_unused_variables()
new_number_of_variables = len(self.aedtapp.variable_manager.variable_names)
assert number_of_variables != new_number_of_variables
11 changes: 11 additions & 0 deletions pyaedt/application/Design.py
Original file line number Diff line number Diff line change
Expand Up @@ -3196,6 +3196,17 @@ def delete_variable(self, sVarName):
"""
return self.variable_manager.delete_variable(sVarName)

@pyaedt_function_handler()
def delete_unused_variables(self):
"""Delete design and project unused variables.
Returns
-------
bool
``True`` when successful, ``False`` when failed.
"""
return self.variable_manager.delete_unused_variables()

@pyaedt_function_handler()
def insert_design(self, design_name=None, solution_type=None):
"""Add a design of a specified type.
Expand Down
75 changes: 75 additions & 0 deletions pyaedt/application/Variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,81 @@ def delete_variable(self, var_name):
return True
return False

@pyaedt_function_handler()
def is_used_variable(self, var_name):
"""Find if a variable is used.
Parameters
----------
var_name : str
Name of the variable.
Returns
-------
bool
``True`` when successful, ``False`` when failed.
"""
used = False
# Modeler
for obj in self._app.modeler.objects.values():
used = self._find_used_variable_history(obj.history(), var_name)
if used:
self._logger.warning("{} used in modeler.".format(var_name))
return used

# Material
for mat in self._app.materials.material_keys.values():
for _, v in mat._props.items():
if isinstance(v, str) and var_name in re.findall("[$a-zA-Z0-9_]+", v):
used = True
self._logger.warning("{} used in the material: {}.".format(var_name, mat.name))
return used
return used

def _find_used_variable_history(self, history, var_name):
"""Find if a variable is used.
Parameters
----------
history : :class:`pyaedt.modeler.cad.elements3d.BinaryTree`
Object history.
var_name : str
Name of the variable.
Returns
-------
bool
``True`` when successful, ``False`` when failed.
"""
used = False
for _, v in history.props.items():
if isinstance(v, str) and var_name in re.findall("[a-zA-Z0-9_]+", v):
return True
for el in history.children.values():
used = self._find_used_variable_history(el, var_name)
if used:
return True
return used

@pyaedt_function_handler()
def delete_unused_variables(self):
"""Delete unused design and project variables.
Returns
-------
bool
``True`` when successful, ``False`` when failed.
"""
var_list = self.variable_names

for var in var_list[:]:
if not self.is_used_variable(var):
self.delete_variable(var)
return True

@pyaedt_function_handler()
def _get_var_list_from_aedt(self, desktop_object):
var_list = []
Expand Down
39 changes: 38 additions & 1 deletion pyaedt/edb.py
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,7 @@ def cutout(
maximum_iterations=10,
preserve_components_with_model=False,
simple_pad_check=True,
keep_lines_as_path=False,
):
"""Create a cutout using an approach entirely based on PyAEDT.
This method replaces all legacy cutout methods in PyAEDT.
Expand Down Expand Up @@ -1663,6 +1664,11 @@ def cutout(
Whether to use the center of the pad to find the intersection with extent or use the bounding box.
Second method is much slower and requires to disable multithread on padstack removal.
Default is `True`.
keep_lines_as_path : bool, optional
Whether to keep the lines as Path after they are cutout or convert them to PolygonData.
This feature works only in Electronics Desktop (3D Layout).
If the flag is set to ``True`` it can cause issues in SiWave once the Edb is imported.
Default is ``False`` to generate PolygonData of cut lines.
Returns
-------
Expand Down Expand Up @@ -1752,6 +1758,7 @@ def cutout(
preserve_components_with_model=preserve_components_with_model,
include_partial=include_partial_instances,
simple_pad_check=simple_pad_check,
keep_lines_as_path=keep_lines_as_path,
)
if self.are_port_reference_terminals_connected():
if output_aedb_path:
Expand Down Expand Up @@ -1791,6 +1798,7 @@ def cutout(
preserve_components_with_model=preserve_components_with_model,
include_partial=include_partial_instances,
simple_pad_check=simple_pad_check,
keep_lines_as_path=keep_lines_as_path,
)
if result and not open_cutout_at_end and self.edbpath != legacy_path:
self.save_edb()
Expand Down Expand Up @@ -1996,6 +2004,7 @@ def _create_cutout_multithread(
preserve_components_with_model=False,
include_partial=False,
simple_pad_check=True,
keep_lines_as_path=False,
):
if is_ironpython: # pragma: no cover
self.logger.error("Method working only in Cpython")
Expand Down Expand Up @@ -2033,6 +2042,7 @@ def _create_cutout_multithread(
i.net_object.Delete()
reference_pinsts = []
reference_prims = []
reference_paths = []
for i in self.padstacks.instances.values():
net_name = i.net_name
id = i.id
Expand All @@ -2046,7 +2056,10 @@ def _create_cutout_multithread(
if net_name not in all_list:
i.delete()
elif net_name in reference_list and not i.is_void:
reference_prims.append(i)
if keep_lines_as_path and i.type == "Path":
reference_paths.append(i)
else:
reference_prims.append(i)
self.logger.info_timer("Net clean up")
self.logger.reset_timer()

Expand Down Expand Up @@ -2094,6 +2107,17 @@ def intersect(poly1, poly2):
def subtract(poly, voids):
return poly.Subtract(convert_py_list_to_net_list(poly), convert_py_list_to_net_list(voids))

def clip_path(path):
pdata = path.polygon_data.edb_api
int_data = _poly.GetIntersectionType(pdata)
if int_data == 0:
prims_to_delete.append(path)
return
result = path._edb_object.SetClipInfo(_poly, True)
if not result:
self.logger.info("Failed to clip path {}. Clipping as polygon.".format(path.id))
reference_prims.append(path)

def clean_prim(prim_1): # pragma: no cover
pdata = prim_1.polygon_data.edb_api
int_data = _poly.GetIntersectionType(pdata)
Expand Down Expand Up @@ -2139,6 +2163,11 @@ def pins_clean(pinst):
self.logger.info_timer("Padstack Instances removal completed")
self.logger.reset_timer()

# with ThreadPoolExecutor(number_of_threads) as pool:
# pool.map(lambda item: clip_path(item), reference_paths)

for item in reference_paths:
clip_path(item)
with ThreadPoolExecutor(number_of_threads) as pool:
pool.map(lambda item: clean_prim(item), reference_prims)

Expand All @@ -2147,6 +2176,7 @@ def pins_clean(pinst):

for prim in prims_to_delete:
prim.delete()

self.logger.info_timer("Primitives cleanup completed")
self.logger.reset_timer()

Expand Down Expand Up @@ -2182,6 +2212,7 @@ def create_cutout_multithread(
remove_single_pin_components=False,
use_pyaedt_extent_computing=False,
extent_defeature=0,
keep_lines_as_path=False,
):
"""Create a cutout using an approach entirely based on pyaedt.
It does in sequence:
Expand Down Expand Up @@ -2222,6 +2253,11 @@ def create_cutout_multithread(
extent_defeature : float, optional
Defeature the cutout before applying it to produce simpler geometry for mesh (Experimental).
It applies only to Conforming bounding box. Default value is ``0`` which disable it.
keep_lines_as_path : bool, optional
Whether to keep the lines as Path after they are cutout or convert them to PolygonData.
This feature works only in Electronics Desktop (3D Layout).
If the flag is set to True it can cause issues in SiWave once the Edb is imported.
Default is ``False`` to generate PolygonData of cut lines.
Returns
-------
Expand Down Expand Up @@ -2261,6 +2297,7 @@ def create_cutout_multithread(
remove_single_pin_components=remove_single_pin_components,
use_pyaedt_extent_computing=use_pyaedt_extent_computing,
extent_defeature=extent_defeature,
keep_lines_as_path=keep_lines_as_path,
)

@pyaedt_function_handler()
Expand Down
8 changes: 4 additions & 4 deletions pyaedt/edb_core/dotnet/primitive.py
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ def end_cap_style(self):
**end_cap2** : End cap style of path end end cap.
"""
return self.prim_obj.GetEndCapStyle()
return self._edb_object.GetEndCapStyle()

@end_cap_style.setter
def end_cap_style(self, end_cap1, end_cap2):
Expand All @@ -759,7 +759,7 @@ def end_cap_style(self, end_cap1, end_cap2):
end_cap2: :class:`PathEndCapType`
End cap style of path end end cap.
"""
self.prim_obj.SetEndCapStyle(end_cap1, end_cap2)
self._edb_object.SetEndCapStyle(end_cap1, end_cap2)

@property
def get_clip_info(self):
Expand All @@ -777,7 +777,7 @@ def get_clip_info(self):
**keep_inside** : Indicates whether the part of the path inside the polygon is preserved.
"""
return self.prim_obj.GetClipInfo()
return self._edb_object.GetClipInfo()

@get_clip_info.setter
def get_clip_info(self, clipping_poly, keep_inside=True):
Expand All @@ -790,7 +790,7 @@ def get_clip_info(self, clipping_poly, keep_inside=True):
keep_inside: bool
Indicates whether the part of the path inside the polygon should be preserved.
"""
self.prim_obj.SetClipInfo(
self._edb_object.SetClipInfo(
clipping_poly,
keep_inside,
)
Expand Down

0 comments on commit e70c387

Please sign in to comment.