diff --git a/_unittest/test_20_HFSS.py b/_unittest/test_20_HFSS.py index 111c53630ee..3856d3d1b7b 100644 --- a/_unittest/test_20_HFSS.py +++ b/_unittest/test_20_HFSS.py @@ -667,7 +667,9 @@ def test_12_create_perfects_on_objects(self): def test_13_create_impedance_on_objects(self): box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 5], "imp1", "Copper") box2 = self.aedtapp.modeler.create_box([0, 0, 10], [10, 10, 5], "imp2", "copper") - imp = self.aedtapp.create_impedance_between_objects("imp1", "imp2", self.aedtapp.AxisDir.XPos, "TL2", 50, 25) + imp = self.aedtapp.create_impedance_between_objects( + box1.name, box2.name, self.aedtapp.AxisDir.XPos, "TL1", 50, 25 + ) assert imp.name in self.aedtapp.modeler.get_boundaries_name() assert imp.update() @@ -677,14 +679,14 @@ def test_14_create_lumpedrlc_on_objects(self): box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 5], "rlc1", "Copper") box2 = self.aedtapp.modeler.create_box([0, 0, 10], [10, 10, 5], "rlc2", "copper") imp = self.aedtapp.create_lumped_rlc_between_objects( - "rlc1", "rlc2", self.aedtapp.AxisDir.XPos, Rvalue=50, Lvalue=1e-9 + box1.name, box2.name, self.aedtapp.AxisDir.XPos, Rvalue=50, Lvalue=1e-9 ) assert imp.name in self.aedtapp.modeler.get_boundaries_name() assert imp.update() box3 = self.aedtapp.modeler.create_box([0, 0, 20], [10, 10, 5], "rlc3", "copper") lumped_rlc2 = self.aedtapp.create_lumped_rlc_between_objects( - "rlc2", "rlc3", self.aedtapp.AxisDir.XPos, Rvalue=50, Lvalue=1e-9, Cvalue=1e-9 + box2.name, box3.name, self.aedtapp.AxisDir.XPos, Rvalue=50, Lvalue=1e-9, Cvalue=1e-9 ) assert lumped_rlc2.name in self.aedtapp.modeler.get_boundaries_name() assert lumped_rlc2.update() @@ -710,9 +712,24 @@ def test_16_create_impedance_on_sheets(self): rect = self.aedtapp.modeler.create_rectangle( self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="ImpBound", matname="Copper" ) - imp = self.aedtapp.assign_impedance_to_sheet("imp1", "TL2", 50, 25) - assert imp.name in self.aedtapp.modeler.get_boundaries_name() - assert imp.update() + imp1 = self.aedtapp.assign_impedance_to_sheet(rect.name, "TL2", 50, 25) + assert imp1.name in self.aedtapp.modeler.get_boundaries_name() + assert imp1.update() + + impedance_box = self.aedtapp.modeler.create_box([0, -100, 0], [200, 200, 200], "ImpedanceBox") + ids = self.aedtapp.modeler.get_object_faces(impedance_box.name)[:3] + + imp2 = self.aedtapp.assign_impedance_to_sheet(ids, sourcename="ImpedanceToFaces", resistance=60, reactance=-20) + assert imp2.name in self.aedtapp.modeler.get_boundaries_name() + + rect2 = self.aedtapp.modeler.create_rectangle( + self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="AniImpBound", matname="Copper" + ) + assert not self.aedtapp.assign_impedance_to_sheet(rect2.name, "TL3", [50, 20, 0, 0], [25, 0, 5]) + imp2 = self.aedtapp.assign_impedance_to_sheet(rect2.name, "TL3", [50, 20, 0, 0], [25, 0, 5, 0]) + assert imp2.name in self.aedtapp.modeler.get_boundaries_name() + imp3 = self.aedtapp.assign_impedance_to_sheet(impedance_box.top_face_z.id, "TL4", [50, 20, 0, 0], [25, 0, 5, 0]) + assert imp3.name in self.aedtapp.modeler.get_boundaries_name() def test_17_create_lumpedrlc_on_sheets(self): rect = self.aedtapp.modeler.create_rectangle( diff --git a/examples/02-HFSS/Probe_Fed_Patch.py b/examples/02-HFSS/Probe_Fed_Patch.py index 640c92c148d..03bae1cf75e 100644 --- a/examples/02-HFSS/Probe_Fed_Patch.py +++ b/examples/02-HFSS/Probe_Fed_Patch.py @@ -34,7 +34,7 @@ # You can set ``non_graphical`` to ``True`` to view # HFSS while the notebook cells are executed. -non_graphical = True +non_graphical = False length_units = "mm" freq_units = "GHz" @@ -84,7 +84,7 @@ stackup.resize_around_element(patch) pad_length = [3, 3, 3, 3, 3, 3] # Air bounding box buffer in mm. region = hfss.modeler.create_region(pad_length, is_percentage=False) -hfss.assign_radiation_boundary_to_objects(region) +hfss.assign_radiation_boundary_to_objects(region.name) patch.create_probe_port(ground, rel_x_offset=0.485) setup = hfss.create_setup(setupname="Setup1", @@ -115,4 +115,4 @@ # Release AEDT and clean up temporary folders and files. hfss.release_desktop() -tmpdir.cleanup() \ No newline at end of file +tmpdir.cleanup() diff --git a/examples/03-Maxwell/Maxwell2D_Transient.py b/examples/03-Maxwell/Maxwell2D_Transient.py index 69e7d25de63..7014226eae3 100644 --- a/examples/03-Maxwell/Maxwell2D_Transient.py +++ b/examples/03-Maxwell/Maxwell2D_Transient.py @@ -71,7 +71,7 @@ # ~~~~~~~~~~~~~~~~~ # Create an air region. -region = maxwell_2d.modeler.create_region([100, 100, 100, 100, 100, 100]) +region = maxwell_2d.modeler.create_region([100, 100, 100, 100]) ############################################################################### # Assign windings and balloon diff --git a/examples/05-Q3D/Q2D_Armoured_Cable.py b/examples/05-Q3D/Q2D_Armoured_Cable.py index 054c152613b..0b4800a79bf 100644 --- a/examples/05-Q3D/Q2D_Armoured_Cable.py +++ b/examples/05-Q3D/Q2D_Armoured_Cable.py @@ -199,7 +199,7 @@ # Create region # ~~~~~~~~~~~~~ -region = q2d.modeler.create_region([500, 500, 500, 500, 0, 0]) +region = q2d.modeler.create_region([500, 500, 500, 500]) region.material_name = "vacuum" ########################################################## @@ -228,12 +228,6 @@ q2d_setup = q2d.create_setup(setupname=setup_name) q2d_sweep = q2d_setup.add_sweep(sweepname=sweep_name) -q2d_sweep.props["RangeType"] = "LogScale" -q2d_sweep.props["RangeStart"] = "0Hz" -q2d_sweep.props["RangeEnd"] = "3MHz" -q2d_sweep.props["RangeCount"] = 10 -q2d_sweep.props["RangeSamples"] = 1 -q2d_sweep.update() ########################################################## # Analyze setup diff --git a/pyaedt/hfss.py b/pyaedt/hfss.py index fbd191c88f6..a94d78c642a 100644 --- a/pyaedt/hfss.py +++ b/pyaedt/hfss.py @@ -226,9 +226,18 @@ def field_setup_names(self): class BoundaryType(object): """Creates and manages boundaries.""" - (PerfectE, PerfectH, Aperture, Radiation, Impedance, LayeredImp, LumpedRLC, FiniteCond, Hybrid, FEBI) = range( - 0, 10 - ) + ( + PerfectE, + PerfectH, + Aperture, + Radiation, + Impedance, + LayeredImp, + LumpedRLC, + FiniteCond, + Hybrid, + FEBI, + ) = range(0, 10) @property def hybrid(self): @@ -3633,8 +3642,8 @@ def assign_impedance_to_sheet(self, sheet_name, sourcename=None, resistance=50, Parameters ---------- - sheet_name : str - Name of the sheet to apply the boundary to. + sheet_name : str or list + Name of the sheet or list to apply the boundary to. sourcename : str, optional Name of the impedance. The default is ``None``. resistance : optional @@ -3675,17 +3684,127 @@ def assign_impedance_to_sheet(self, sheet_name, sourcename=None, resistance=50, sourcename = generate_unique_name("Imped") elif sourcename in self.modeler.get_boundaries_name(): sourcename = generate_unique_name(sourcename) + + objects = self.modeler.convert_to_selections(sheet_name, True) + props = OrderedDict( { - "Objects": [sheet_name], - "Resistance": str(resistance), - "Reactance": str(reactance), - "InfGroundPlane": is_infground, + "Faces": objects, } ) + if isinstance(objects[0], str): + props = OrderedDict( + { + "Objects": objects, + } + ) + props["Resistance"] = str(resistance) + props["Reactance"] = str(reactance) + props["InfGroundPlane"] = is_infground + return self._create_boundary(sourcename, props, "Impedance") return False + @pyaedt_function_handler() + def assign_impedance_to_sheet( + self, sheet_name, sourcename=None, resistance=50.0, reactance=0.0, is_infground=False, reference_cs="Global" + ): + """Create an impedance taking one sheet. + + Parameters + ---------- + sheet_name : str or list + Name of the sheet or list to apply the boundary to. + sourcename : str, optional + Name of the impedance. The default is ``None``. + resistance : float or list, optional + Resistance value in ohms. The default is ``50.0``. + If a list of four elements is passed, an anisotropic impedance is assigned with the following order, + [``Zxx``, ``Zxy``, ``Zyx``, ``Zyy``]. + reactance : optional + Reactance value in ohms. The default is ``0.0``. + If a list of four elements is passed, an anisotropic impedance is assigned with the following order, + [``Zxx``, ``Zxy``, ``Zyx``, ``Zyy``]. + is_infground : bool, optional + Whether the impedance is an infinite ground. The default is ``False``. + reference_cs : str, optional + Name of the coordinate system for the XY plane. The default is ``"Global"``. + This parameter is only used for anisotropic impedance assignment. + + Returns + ------- + :class:`pyaedt.modules.Boundary.BoundaryObject` + Boundary object if successful, ``False`` otherwise. + + References + ---------- + + >>> oModule.AssignImpedance + + Examples + -------- + + Create a sheet and use it to create an impedance. + + >>> sheet = hfss.modeler.create_rectangle(hfss.PLANE.XY, + ... [0, 0, -90], [10, 2], name="ImpedanceSheet", + ... matname="Copper") + >>> impedance_to_sheet = hfss.assign_impedance_to_sheet(sheet.name, "ImpedanceFromSheet", 100, 50) + + Create a sheet and use it to create an anisotropic impedance. + + >>> sheet = hfss.modeler.create_rectangle(hfss.PLANE.XY, + ... [0, 0, -90], [10, 2], name="ImpedanceSheet", + ... matname="Copper") + >>> anistropic_impedance_to_sheet = hfss.assign_impedance_to_sheet(sheet.name, "ImpedanceFromSheet", + ... [377, 0, 0, 377], [0, 50, 0, 0]) + + """ + + if self.solution_type in ["Modal", "Terminal", "Transient Network"]: + if not sourcename: + sourcename = generate_unique_name("Imped") + elif sourcename in self.modeler.get_boundaries_name(): + sourcename = generate_unique_name(sourcename) + + objects = self.modeler.convert_to_selections(sheet_name, True) + + props = OrderedDict( + { + "Faces": objects, + } + ) + if isinstance(objects[0], str): + props = OrderedDict( + { + "Objects": objects, + } + ) + + if isinstance(resistance, list) and isinstance(reactance, list): + if len(resistance) == 4 and len(reactance) == 4: + props["UseInfiniteGroundPlane"] = is_infground + props["CoordSystem"] = reference_cs + props["HasExternalLink"] = False + props["ZxxResistance"] = str(resistance[0]) + props["ZxxReactance"] = str(reactance[0]) + props["ZxyResistance"] = str(resistance[1]) + props["ZxyReactance"] = str(reactance[1]) + props["ZyxResistance"] = str(resistance[2]) + props["ZyxReactance"] = str(reactance[2]) + props["ZyyResistance"] = str(resistance[3]) + props["ZyyReactance"] = str(reactance[3]) + else: + self.logger.error("Number of elements in resistance and reactance must be four.") + return False + return self._create_boundary(sourcename, props, "Anisotropic Impedance") + else: + props["Resistance"] = str(resistance) + props["Reactance"] = str(reactance) + props["InfGroundPlane"] = is_infground + return self._create_boundary(sourcename, props, "Impedance") + return False + @pyaedt_function_handler() def create_circuit_port_from_edges( self, diff --git a/pyproject.toml b/pyproject.toml index 739ea4ee756..614073dea19 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,7 @@ dependencies = [ [project.optional-dependencies] tests = [ "imageio>=2.30.0,<2.35", - "ipython>=7.30.0,<8.23", + "ipython>=7.30.0,<8.24", "joblib>=1.0.0,<1.4", "matplotlib>=3.5.0,<3.9", "mock>=5.1.0,<5.2",