From 4b9d1a8305804973c61601fba9e32ced6879aacf Mon Sep 17 00:00:00 2001 From: Samuel Lopez <85613111+Samuelopez-ansys@users.noreply.github.com> Date: Fri, 5 May 2023 15:06:43 +0200 Subject: [PATCH] Insert Layout component (#2968) * Read Layout component in User defined component class * Insert Layout Component * Add unittest * Add example * Fix bug * Fix UT and codevoc * Fix UT --- .github/workflows/ironpython.yml | 1 + .../T08/Layoutcomponent_231.aedbcomp | Bin 0 -> 14861 bytes _unittest/test_08_Primitives3D.py | 28 +++ pyaedt/__init__.py | 1 + pyaedt/generic/general_methods.py | 1 + pyaedt/modeler/cad/Primitives3D.py | 236 ++++++++++++++++++ pyaedt/modeler/cad/components_3d.py | 72 +++++- 7 files changed, 336 insertions(+), 3 deletions(-) create mode 100644 _unittest/example_models/T08/Layoutcomponent_231.aedbcomp diff --git a/.github/workflows/ironpython.yml b/.github/workflows/ironpython.yml index 70f1b6ea4e7..658d948108f 100644 --- a/.github/workflows/ironpython.yml +++ b/.github/workflows/ironpython.yml @@ -31,6 +31,7 @@ jobs: Set-Item -Path env:ANSYSEM_FEATURE_SF159726_SCRIPTOBJECT_ENABLE -Value "1" Set-Item -Path env:ANSYSEM_FEATURE_SF222134_CABLE_MODELING_ENHANCEMENTS_ENABLE -Value "1" Set-Item -Path env:ANSYSEM_FEATURE_F395486_RIGID_FLEX_BENDING_ENABLE -Value "1" + Set-Item -Path env:ANSYSEM_FEATURE_S432616_LAYOUT_COMPONENT_IN_3D_ENABLE -Value "1" $processA = start-process 'cmd' -ArgumentList '/c .\_unittest_ironpython\run_unittests_batchmode.cmd --test-filter test_0*.py' -PassThru $processB = start-process 'cmd' -ArgumentList '/c .\_unittest_ironpython\run_unittests_batchmode.cmd --test-filter test_1*.py' -PassThru $processC = start-process 'cmd' -ArgumentList '/c .\_unittest_ironpython\run_unittests_batchmode.cmd --test-filter test_2*.py' -PassThru diff --git a/_unittest/example_models/T08/Layoutcomponent_231.aedbcomp b/_unittest/example_models/T08/Layoutcomponent_231.aedbcomp new file mode 100644 index 0000000000000000000000000000000000000000..6817d49bdf91a9169bc09f25e7ebbe389b22a7b6 GIT binary patch literal 14861 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 "2022.2": assembly = "assembly_231" @@ -57,6 +58,7 @@ def setup_class(self): self.flatten = BasisTest.add_app(self, project_name=components_flatten, subfolder=test_subfolder) test_54b_project = os.path.join(local_path, "example_models", test_subfolder, polyline + ".aedt") self.test_54b_project = self.local_scratch.copyfile(test_54b_project) + self.layout_component = os.path.join(local_path, "example_models", test_subfolder, layout_comp) def teardown_class(self): BasisTest.my_teardown(self) @@ -1731,3 +1733,29 @@ def test_84_replace_3dcomponent(self): object_list=[box2.name], ) assert len(self.aedtapp.modeler.user_defined_components) == 2 + + @pytest.mark.skipif( + config["desktopVersion"] < "2023.1" or is_ironpython, reason="Method available in beta from 2023.1" + ) + def test_85_insert_layoutcomponent(self): + self.aedtapp.insert_design("LayoutComponent") + self.aedtapp.solution_type = "Modal" + assert not self.aedtapp.modeler.insert_layout_component( + self.layout_component, name=None, parameter_mapping=False + ) + self.aedtapp.solution_type = "Terminal" + comp = self.aedtapp.modeler.insert_layout_component(self.layout_component, name=None, parameter_mapping=False) + assert isinstance(comp, UserDefinedComponent) + assert len(self.aedtapp.modeler.modeler.user_defined_components[comp.name].parts) == 3 + comp2 = self.aedtapp.modeler.insert_layout_component( + self.layout_component, name="new_layout", parameter_mapping=True + ) + assert isinstance(comp2, UserDefinedComponent) + assert len(comp2.parameters) == 2 + assert comp2.show_layout + comp2.show_layout = False + assert not comp2.show_layout + comp2.show_layout = True + assert comp2.fast_transformation + comp2.fast_transformation = False + assert not comp2.fast_transformation diff --git a/pyaedt/__init__.py b/pyaedt/__init__.py index dc6add8bd8e..7377bc9999b 100644 --- a/pyaedt/__init__.py +++ b/pyaedt/__init__.py @@ -8,6 +8,7 @@ os.environ["ANSYSEM_FEATURE_SF159726_SCRIPTOBJECT_ENABLE"] = "1" os.environ["ANSYSEM_FEATURE_SF222134_CABLE_MODELING_ENHANCEMENTS_ENABLE"] = "1" os.environ["ANSYSEM_FEATURE_F395486_RIGID_FLEX_BENDING_ENABLE"] = "1" +os.environ["ANSYSEM_FEATURE_S432616_LAYOUT_COMPONENT_IN_3D_ENABLE"] = "1" pyaedt_path = os.path.dirname(__file__) diff --git a/pyaedt/generic/general_methods.py b/pyaedt/generic/general_methods.py index f5e75eda04b..0e646753dbf 100644 --- a/pyaedt/generic/general_methods.py +++ b/pyaedt/generic/general_methods.py @@ -1745,6 +1745,7 @@ def __init__(self): "ANSYSEM_FEATURE_SF159726_SCRIPTOBJECT_ENABLE": "1", "ANSYSEM_FEATURE_SF222134_CABLE_MODELING_ENHANCEMENTS_ENABLE": "1", "ANSYSEM_FEATURE_F395486_RIGID_FLEX_BENDING_ENABLE": "1", + "ANSYSEM_FEATURE_S432616_LAYOUT_COMPONENT_IN_3D_ENABLE": "1", } if is_linux: self._aedt_environment_variables["ANS_NODEPCHECK"] = "1" diff --git a/pyaedt/modeler/cad/Primitives3D.py b/pyaedt/modeler/cad/Primitives3D.py index 6f0b151e6a3..de3ed7e9ed7 100644 --- a/pyaedt/modeler/cad/Primitives3D.py +++ b/pyaedt/modeler/cad/Primitives3D.py @@ -11,6 +11,7 @@ from math import tan import os +from pyaedt import Edb from pyaedt import Icepak from pyaedt.generic import LoadAEDTFile from pyaedt.generic.general_methods import _retry_ntimes @@ -1426,6 +1427,241 @@ def insert_3d_component( else: return udm_obj + @pyaedt_function_handler() + def insert_layout_component( + self, + comp_file, + coordinate_system="Global", + name=None, + parameter_mapping=False, + ): + """Insert a new layout component. + + Parameters + ---------- + comp_file : str + Path of the component file. Either ``".aedb"`` and ``".aedbcomp"`` are allowed. + coordinate_system : str, optional + Target coordinate system. The default is ``"Global"``. + name : str, optional + 3D component name. The default is ``None``. + parameter_mapping : bool, optional + Map the layout parameters in the target HFSS design. The default is ``False``. + + Returns + ------- + :class:`pyaedt.modeler.components_3d.UserDefinedComponent` + User defined component object. + + References + ---------- + + >>> oEditor.InsertNativeComponent + + Examples + -------- + >>> from pyaedt import Hfss + >>> app = Hfss() + >>> layout_component = "path/to/layout_component/component.aedbcomp" + >>> comp = app.modeler.insert_layout_component(layout_component) + + """ + if self._app.solution_type != "Terminal" and self._app.solution_type != "TransientAPhiFormulation": + self.logger.warning("Solution type must be terminal in HFSS or APhi in Maxwell") + return False + + component_name = os.path.splitext(os.path.basename(comp_file))[0] + aedt_component_name = component_name + if component_name not in self._app.o_component_manager.GetNames(): + compInfo = ["NAME:" + str(component_name), "Info:=", []] + + compInfo.extend( + [ + "CircuitEnv:=", + 0, + "Refbase:=", + "U", + "NumParts:=", + 1, + "ModSinceLib:=", + True, + "Terminal:=", + [], + "CompExtID:=", + 9, + "ModelEDBFilePath:=", + comp_file, + "EDBCompPassword:=", + "", + ] + ) + + aedt_component_name = self._app.o_component_manager.Add(compInfo) + + if not name or name in self.modeler.user_defined_component_names: + name = generate_unique_name("LC") + + # Open Layout component and get information + aedb_component_path = comp_file + if os.path.splitext(os.path.basename(comp_file))[1] == ".aedbcomp": + aedb_project_path = os.path.join(self._app.project_path, self._app.project_name + ".aedb") + aedb_component_path = os.path.join( + aedb_project_path, "LayoutComponents", aedt_component_name, aedt_component_name + ".aedb" + ) + aedb_component_path = aedb_component_path.replace("/", "\\") + + component_obj = Edb( + edbpath=aedb_component_path, + isreadonly=True, + edbversion=self._app._aedt_version, + student_version=self._app.student_version, + ) + + # Extract and map parameters + parameters = {} + for param in component_obj.design_variables: + parameters[param] = [param + "_" + name, component_obj.design_variables[param].value_string] + if parameter_mapping: + self._app[param + "_" + name] = component_obj.design_variables[param].value_string + + # Get coordinate systems + component_cs = list(component_obj.components.components.keys()) + component_obj.close_edb() + + vArg1 = ["NAME:InsertNativeComponentData"] + vArg1.append("TargetCS:=") + vArg1.append(coordinate_system) + vArg1.append("SubmodelDefinitionName:=") + vArg1.append("LC") + varg2 = ["NAME:ComponentPriorityLists"] + vArg1.append(varg2) + vArg1.append("NextUniqueID:=") + vArg1.append(0) + vArg1.append("MoveBackwards:=") + vArg1.append(False) + vArg1.append("DatasetType:=") + vArg1.append("ComponentDatasetType") + varg3 = ["NAME:DatasetDefinitions"] + vArg1.append(varg3) + varg4 = [ + "NAME:BasicComponentInfo", + "ComponentName:=", + "LC", + "Company:=", + "", + "Company URL:=", + "", + "Model Number:=", + "", + "Help URL:=", + "", + "Version:=", + "1.0", + "Notes:=", + "", + "IconTypeL:=", + "Layout Component", + ] + vArg1.append(varg4) + varg5 = [ + "NAME:GeometryDefinitionParameters", + ] + if parameters and parameter_mapping: + for param in parameters: + varg5.append("VariableProp:=") + varg5.append([parameters[param][0], "D", "", parameters[param][1]]) + + varg5.append(["NAME:VariableOrders"]) + vArg1.append(varg5) + + varg6 = ["NAME:DesignDefinitionParameters", ["NAME:VariableOrders"]] + vArg1.append(varg6) + + varg7 = ["NAME:MaterialDefinitionParameters", ["NAME:VariableOrders"]] + vArg1.append(varg7) + + vArg1.append("DefReferenceCSID:=") + vArg1.append(1) + vArg1.append("MapInstanceParameters:=") + vArg1.append("DesignVariable") + vArg1.append("UniqueDefinitionIdentifier:=") + vArg1.append("") + vArg1.append("OriginFilePath:=") + vArg1.append("") + vArg1.append("IsLocal:=") + vArg1.append(False) + vArg1.append("ChecksumString:=") + vArg1.append("") + vArg1.append("ChecksumHistory:=") + vArg1.append([]) + vArg1.append("VersionHistory:=") + vArg1.append([]) + + varg8 = ["NAME:VariableMap"] + + for param in parameters: + varg8.append(param + ":=") + if parameter_mapping: + varg8.append(parameters[param][0]) + else: + varg8.append(parameters[param][1]) + + varg9 = [ + "NAME:NativeComponentDefinitionProvider", + "Type:=", + "Layout Component", + "Unit:=", + "mm", + "Version:=", + 1.1, + "EDBDefinition:=", + aedt_component_name, + varg8, + "ReferenceCS:=", + "Global", + "CSToImport:=", + ] + + if component_cs: + varg10 = component_cs + varg10.append("Global") + else: + varg10 = ["Global"] + varg9.append(varg10) + vArg1.append(varg9) + + varg11 = ["NAME:InstanceParameters"] + varg11.append("GeometryParameters:=") + + if parameters and parameter_mapping: + varg12 = "" + for param in parameters: + varg12 += " {0}='{1}'".format(parameters[param][0], parameters[param][0]) + else: + varg12 = "" + varg11.append(varg12[1:]) + + varg11.append("MaterialParameters:=") + varg11.append("") + varg11.append("DesignParameters:=") + varg11.append("") + vArg1.append(varg11) + + try: + new_object_name = self.oeditor.InsertNativeComponent(vArg1) + udm_obj = False + if new_object_name: + obj_list = list(self.oeditor.Get3DComponentPartNames(new_object_name)) + for new_name in obj_list: + self._create_object(new_name) + + udm_obj = self._create_user_defined_component(new_object_name) + if name: + udm_obj.name = name + except Exception: # pragma: no cover + udm_obj = False + return udm_obj + @pyaedt_function_handler() def get_3d_component_object_list(self, componentname): """Retrieve all objects belonging to a 3D component. diff --git a/pyaedt/modeler/cad/components_3d.py b/pyaedt/modeler/cad/components_3d.py index fb583934572..1fb8186dbd3 100644 --- a/pyaedt/modeler/cad/components_3d.py +++ b/pyaedt/modeler/cad/components_3d.py @@ -102,6 +102,8 @@ def __init__(self, primitives, name=None, props=None, component_type=None): self._group_name = None self._is3dcomponent = None self._mesh_assembly = None + self._show_layout = None + self._fast_transformation = None if name: self._m_name = name else: @@ -123,7 +125,7 @@ def __init__(self, primitives, name=None, props=None, component_type=None): OrderedDict( { "TargetCS": self._target_coordinate_system, - "SubmodelDefinitionName": component, + "SubmodelDefinitionName": self.definition_name, "ComponentPriorityLists": OrderedDict({}), "NextUniqueID": 0, "MoveBackwards": False, @@ -131,7 +133,7 @@ def __init__(self, primitives, name=None, props=None, component_type=None): "DatasetDefinitions": OrderedDict({}), "BasicComponentInfo": OrderedDict( { - "ComponentName": component, + "ComponentName": self.definition_name, "Company": "", "Company URL": "", "Model Number": "", @@ -300,6 +302,66 @@ def mesh_assembly(self, ma): self._primitives.oeditor.GetChildObject(self.name).SetPropValue(key, ma) self._mesh_assembly = ma + @property + def show_layout(self): + """Show layout flag. + + Returns + ------- + bool + ``True`` if show layout is checked and if the component is a Layout Component, + ``None`` if other cases. + + """ + key = "Show Layout" + if self.is3dcomponent and key in self._primitives.oeditor.GetChildObject(self.name).GetPropNames(): + show_layout = self._primitives.oeditor.GetChildObject(self.name).GetPropValue(key) + self._show_layout = show_layout + return show_layout + else: + return None + + @show_layout.setter + def show_layout(self, show_layout): + key = "Show Layout" + if ( + self.is3dcomponent + and isinstance(show_layout, bool) + and key in self._primitives.oeditor.GetChildObject(self.name).GetPropNames() + ): + self._primitives.oeditor.GetChildObject(self.name).SetPropValue(key, show_layout) + self._show_layout = show_layout + + @property + def fast_transformation(self): + """Show layout flag. + + Returns + ------- + bool + ``True`` if fast transformation is checked and if the component is a Layout Component, + ``None`` if other cases. + + """ + key = "Fast Transformation" + if self.is3dcomponent and key in self._primitives.oeditor.GetChildObject(self.name).GetPropNames(): + fast_transformation = self._primitives.oeditor.GetChildObject(self.name).GetPropValue(key) + self._fast_transformation = fast_transformation + return fast_transformation + else: + return None + + @fast_transformation.setter + def fast_transformation(self, fast_transformation): + key = "Fast Transformation" + if ( + self.is3dcomponent + and isinstance(fast_transformation, bool) + and key in self._primitives.oeditor.GetChildObject(self.name).GetPropNames() + ): + self._primitives.oeditor.GetChildObject(self.name).SetPropValue(key, fast_transformation) + self._fast_transformation = fast_transformation + @property def name(self): """Name of the object. @@ -378,7 +440,11 @@ def parts(self): :class:`pyaedt.modeler.Object3d` """ - component_parts = list(self._primitives.oeditor.GetChildObject(self.name).GetChildNames()) + if self.is3dcomponent: + component_parts = list(self._primitives.oeditor.Get3DComponentPartNames(self.name)) + else: + component_parts = list(self._primitives.oeditor.GetChildObject(self.name).GetChildNames()) + parts_id = [ self._primitives._object_names_to_ids[part] for part in self._primitives._object_names_to_ids