From ac9fda4378da87cf381c5f7c42ded8a31f8cc476 Mon Sep 17 00:00:00 2001 From: mcapodif Date: Wed, 9 Jul 2025 14:41:48 +0200 Subject: [PATCH 1/9] Added a new class to customize Page Ports and added 2 new properties for getter and setter: microwave_port to change the visualization of the port and the reference node. --- .../modeler/circuits/object_3d_circuit.py | 91 +++++++++++++++++++ .../modeler/circuits/primitives_circuit.py | 16 +++- tests/system/general/test_21_Circuit.py | 13 ++- 3 files changed, 116 insertions(+), 4 deletions(-) diff --git a/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py b/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py index 2778ba4ce80..2828819c65e 100644 --- a/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py +++ b/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py @@ -1155,6 +1155,97 @@ def component_path(self): return (data[1][12][1].split(" ")[1])[1:-1] +class PortComponent(CircuitComponent): + """Manages circuit components.""" + + def __init__(self, circuit_components, tabname="PassedParameterTab", custom_editor=None): + CircuitComponent.__init__(self, circuit_components, tabname, custom_editor) + self._reference_node = None + self._microwave_port = False + + @property + def microwave_port(self): + """Get the visualization of the port. + + Returns + ------- + bool + """ + return self._microwave_port + + @microwave_port.setter + def microwave_port(self, value): + name = self.name.split("@")[-1] + self._microwave_port = value + self._circuit_components._app.odesign.ChangePortProperty( + name, + [ + f"NAME:{name}", + "IIPortName:=", + name, + "SymbolType:=", + 0 if self._microwave_port is False else 1, + "DoPostProcess:=", + False, + ], + [], + ) + + @property + def reference_node(self): + """Get the reference node of the port. + + Returns + ------- + str + Reference node name. + """ + if not self._reference_node: + try: + self._get_property_value("RefNode") + self._reference_node = self._get_property_value("RefNode") + except Exception: + self._reference_node = "Ground" + return self._reference_node + + @reference_node.setter + def reference_node(self, value): + """Set the reference node of the port. + + Parameters + ---------- + value : str + Reference node name. + """ + name = self.name.split("@")[-1] + if value != "Ground" and self.reference_node != "Ground": + args = ["NAME:ChangedProps", ["NAME:RefNode", "Value:=", value]] + self._circuit_components._app.odesign.ChangePortProperty( + name, [f"NAME:{name}", "IIPortName:=", name], [["NAME:Properties", args]] + ) + elif value != "Ground": + args = [ + "NAME:NewProps", + ["NAME:RefNode", "PropType:=", "TextProp", "OverridingDef:=", True, "Value:=", value], + ] + + self._circuit_components._app.odesign.ChangePortProperty( + name, [f"NAME:{name}", "IIPortName:=", name], [["NAME:Properties", args]] + ) + self._reference_node = value + else: + self._circuit_components._app.odesign.ChangePortProperty( + name, + [ + f"NAME:{name}", + "IIPortName:=", + name, + ], + [["NAME:Properties", [], ["NAME:DeletedProps", "RefNode"]]], + ) + self._reference_node = "Ground" + + class Wire(object): """Creates and manipulates a wire.""" diff --git a/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py b/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py index 4cf2efa87e3..19fc9545147 100644 --- a/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py +++ b/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py @@ -37,6 +37,7 @@ from ansys.aedt.core.generic.numbers import is_number from ansys.aedt.core.internal.load_aedt_file import load_keyword_in_aedt_file from ansys.aedt.core.modeler.circuits.object_3d_circuit import CircuitComponent +from ansys.aedt.core.modeler.circuits.object_3d_circuit import PortComponent from ansys.aedt.core.modeler.circuits.object_3d_circuit import Wire @@ -1376,7 +1377,10 @@ def refresh_all_ids(self): if not self.get_obj_id(el): name = el.split(";") if len(name) > 1: - o = CircuitComponent(self, tabname=self.tab_name) + if name[0].startswith("IPort"): + o = PortComponent(self, tabname=self.tab_name) + else: + o = CircuitComponent(self, tabname=self.tab_name) o.name = name[0] if len(name) == 2: o.schematic_id = int(name[1]) @@ -1406,7 +1410,10 @@ def add_id_to_component(self, id, name=None): if name: name = name.split(";") if len(name) > 1 and str(id) == name[1]: - o = CircuitComponent(self, tabname=self.tab_name) + if name[0].startswith("IPort"): + o = PortComponent(self, tabname=self.tab_name) + else: + o = CircuitComponent(self, tabname=self.tab_name) o.name = name[0] if len(name) > 2: o.id = int(name[1]) @@ -1421,7 +1428,10 @@ def add_id_to_component(self, id, name=None): for el in obj: name = el.split(";") if len(name) > 1 and str(id) == name[1]: - o = CircuitComponent(self, tabname=self.tab_name) + if name[0].startswith("IPort"): + o = PortComponent(self, tabname=self.tab_name) + else: + o = CircuitComponent(self, tabname=self.tab_name) o.name = name[0] if len(name) > 2: o.id = int(name[1]) diff --git a/tests/system/general/test_21_Circuit.py b/tests/system/general/test_21_Circuit.py index 61a9e9c3510..3e331bc302b 100644 --- a/tests/system/general/test_21_Circuit.py +++ b/tests/system/general/test_21_Circuit.py @@ -206,9 +206,20 @@ def test_12_connect_components(self, aedtapp): def test_12a_connect_components(self, aedtapp): myind = aedtapp.modeler.schematic.create_inductor("L101", 1e-9) myres = aedtapp.modeler.schematic.create_resistor("R101", 50) - aedtapp.modeler.schematic.create_interface_port("Port2") + mycap = aedtapp.modeler.schematic.create_capacitor("C1", 1) + p2 = aedtapp.modeler.schematic.create_interface_port("Port2") + p2.microwave_port = True + assert p2.microwave_port + assert "Port2" in aedtapp.modeler.schematic.nets assert myind.pins[1].connect_to_component(myres.pins[1], "port_name_test") + assert mycap.pins[0].connect_to_component(myres.pins[0], "port_name_test2") + p2.reference_node = myres.pins[1].net + assert p2.reference_node == myres.pins[1].net + p2.reference_node = mycap.pins[0].net + assert p2.reference_node == mycap.pins[0].net + p2.reference_node = "Ground" + assert p2.reference_node == "Ground" assert "port_name_test" in aedtapp.modeler.schematic.nets def test_13_properties(self, aedtapp): From bfc16e835925a965873c3077c270a744057443f4 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Wed, 9 Jul 2025 12:44:41 +0000 Subject: [PATCH 2/9] chore: adding changelog file 6374.added.md [dependabot-skip] --- doc/changelog.d/6374.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/6374.added.md diff --git a/doc/changelog.d/6374.added.md b/doc/changelog.d/6374.added.md new file mode 100644 index 00000000000..ef2f38a6471 --- /dev/null +++ b/doc/changelog.d/6374.added.md @@ -0,0 +1 @@ +Added a new class to customize page ports and added 2 new properties \ No newline at end of file From 7ed619a5d78dbe4d35884e4dfeaf97e860d35f9d Mon Sep 17 00:00:00 2001 From: mcapodif Date: Thu, 10 Jul 2025 15:32:30 +0200 Subject: [PATCH 3/9] fixed grpc_plugin_dll_class.py --- .../core/internal/grpc_plugin_dll_class.py | 11 ++++++++-- .../modeler/circuits/object_3d_circuit.py | 22 +++++++++---------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/ansys/aedt/core/internal/grpc_plugin_dll_class.py b/src/ansys/aedt/core/internal/grpc_plugin_dll_class.py index 36921a4ffd6..d47994ad934 100644 --- a/src/ansys/aedt/core/internal/grpc_plugin_dll_class.py +++ b/src/ansys/aedt/core/internal/grpc_plugin_dll_class.py @@ -204,8 +204,15 @@ def __GetPropAttributes(self): def __dir__(self): ret = super().__dir__().copy() - for attrName, _ in self.__GetPropAttributes(): - ret.append(attrName) + try: + for attrName, _ in self.__GetPropAttributes().items(): + ret.append(attrName) + except Exception: + try: + for attrName, _ in self.__GetPropAttributes(): + ret.append(attrName) + except Exception: + return ret return ret def __getattr__(self, attrName): diff --git a/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py b/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py index 2828819c65e..3f355d99696 100644 --- a/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py +++ b/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py @@ -1160,8 +1160,8 @@ class PortComponent(CircuitComponent): def __init__(self, circuit_components, tabname="PassedParameterTab", custom_editor=None): CircuitComponent.__init__(self, circuit_components, tabname, custom_editor) - self._reference_node = None - self._microwave_port = False + self.__reference_node = None + self.___microwave_port = False @property def microwave_port(self): @@ -1171,12 +1171,12 @@ def microwave_port(self): ------- bool """ - return self._microwave_port + return self.___microwave_port @microwave_port.setter def microwave_port(self, value): name = self.name.split("@")[-1] - self._microwave_port = value + self.___microwave_port = value self._circuit_components._app.odesign.ChangePortProperty( name, [ @@ -1184,7 +1184,7 @@ def microwave_port(self, value): "IIPortName:=", name, "SymbolType:=", - 0 if self._microwave_port is False else 1, + 0 if self.___microwave_port is False else 1, "DoPostProcess:=", False, ], @@ -1200,13 +1200,13 @@ def reference_node(self): str Reference node name. """ - if not self._reference_node: + if not self.__reference_node: try: self._get_property_value("RefNode") - self._reference_node = self._get_property_value("RefNode") + self.__reference_node = self._get_property_value("RefNode") except Exception: - self._reference_node = "Ground" - return self._reference_node + self.__reference_node = "Ground" + return self.__reference_node @reference_node.setter def reference_node(self, value): @@ -1232,7 +1232,7 @@ def reference_node(self, value): self._circuit_components._app.odesign.ChangePortProperty( name, [f"NAME:{name}", "IIPortName:=", name], [["NAME:Properties", args]] ) - self._reference_node = value + self.__reference_node = value else: self._circuit_components._app.odesign.ChangePortProperty( name, @@ -1243,7 +1243,7 @@ def reference_node(self, value): ], [["NAME:Properties", [], ["NAME:DeletedProps", "RefNode"]]], ) - self._reference_node = "Ground" + self.__reference_node = "Ground" class Wire(object): From f8355400a6c844ce8a421d9d620e242a132b4771 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Mon, 14 Jul 2025 08:52:04 +0200 Subject: [PATCH 4/9] Update SECURITY.md --- SECURITY.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 3488c81b767..b2c1e34b656 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -22,7 +22,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --> - ## Reporting a vulnerability +# Security Policy + +## Reporting a vulnerability > [!CAUTION] > Do not use GitHub issues to report any security vulnerabilities. @@ -32,7 +34,7 @@ mentioning the repository and the details of your finding. The team will address Provide the PyAnsys Core team with this information: - - Any specific configuration settings needed to reproduce the problem - - Step-by-step guidance to reproduce the problem - - The exact location of the problematic source code, including tag, branch, commit, or a direct URL - - The potential consequences of the vulnerability, along with a description of how an attacker could take advantage of the issue \ No newline at end of file +- Any specific configuration settings needed to reproduce the problem +- Step-by-step guidance to reproduce the problem +- The exact location of the problematic source code, including tag, branch, commit, or a direct URL +- The potential consequences of the vulnerability, along with a description of how an attacker could take advantage of the issue From a63d9cd5cd076f8bbe4bafea17c31f1d2fd6c696 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Mon, 14 Jul 2025 09:21:29 +0200 Subject: [PATCH 5/9] Change private property --- src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py b/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py index 3f355d99696..beaf95af553 100644 --- a/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py +++ b/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py @@ -1161,7 +1161,7 @@ class PortComponent(CircuitComponent): def __init__(self, circuit_components, tabname="PassedParameterTab", custom_editor=None): CircuitComponent.__init__(self, circuit_components, tabname, custom_editor) self.__reference_node = None - self.___microwave_port = False + self.__microwave_port = False @property def microwave_port(self): @@ -1171,12 +1171,12 @@ def microwave_port(self): ------- bool """ - return self.___microwave_port + return self.__microwave_port @microwave_port.setter def microwave_port(self, value): name = self.name.split("@")[-1] - self.___microwave_port = value + self.__microwave_port = value self._circuit_components._app.odesign.ChangePortProperty( name, [ @@ -1184,7 +1184,7 @@ def microwave_port(self, value): "IIPortName:=", name, "SymbolType:=", - 0 if self.___microwave_port is False else 1, + 0 if self.__microwave_port is False else 1, "DoPostProcess:=", False, ], From d25983c69e69e4bbcfe0e00089b05c6f669ed666 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Mon, 14 Jul 2025 12:32:37 +0200 Subject: [PATCH 6/9] Replace PortComponent to Excitation --- .../aedt/core/application/analysis_nexxim.py | 8 +- .../modeler/circuits/object_3d_circuit.py | 106 +----- .../modeler/circuits/primitives_circuit.py | 56 +-- .../core/modules/boundary/circuit_boundary.py | 322 ++++++++---------- tests/system/general/test_21_Circuit.py | 5 +- 5 files changed, 194 insertions(+), 303 deletions(-) diff --git a/src/ansys/aedt/core/application/analysis_nexxim.py b/src/ansys/aedt/core/application/analysis_nexxim.py index 7e8da70debf..5715a3cfbf7 100644 --- a/src/ansys/aedt/core/application/analysis_nexxim.py +++ b/src/ansys/aedt/core/application/analysis_nexxim.py @@ -90,7 +90,7 @@ def __init__( self._modeler = None self._post = None - self._internal_excitations = None + self._internal_excitations = {} self._internal_sources = None self._configurations = ConfigurationsNexxim(self) if not settings.lazy_load: @@ -366,9 +366,11 @@ def design_excitations(self): >>> oModule.GetExcitations """ props = {} + port = "" if not self._internal_excitations: - for port in self.excitation_names: - props[port] = Excitations(self, port) + for comp in self.modeler.schematic.components: + if comp.name in self.excitation_names: + props[port] = comp self._internal_excitations = props else: props = self._internal_excitations diff --git a/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py b/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py index beaf95af553..5a7f1e1047f 100644 --- a/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py +++ b/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py @@ -290,7 +290,7 @@ def connect_to_component( for cmp in assignment: if "Port" in cmp._circuit_comp.composed_name: try: - page_name = cmp._circuit_comp.name.split("@")[1].replace(";", "_") + page_name = cmp._circuit_comp.composed_name.split("@")[1].replace(";", "_") break except Exception: self._component._circuit_components.logger.debug( @@ -400,7 +400,8 @@ def composed_name(self): return self.name + ";" + str(self.schematic_id) def __init__(self, circuit_components, tabname="PassedParameterTab", custom_editor=None): - self.name = "" + self.__name = "" + self._circuit_components = circuit_components if custom_editor: self._oeditor = custom_editor @@ -423,6 +424,7 @@ def __init__(self, circuit_components, tabname="PassedParameterTab", custom_edit self._component_info = {} self._model_data = {} self._refdes = None + self.is_port = False @pyaedt_function_handler() def _get_property_value(self, prop_name, tab_name=None): @@ -506,6 +508,15 @@ def delete(self): break return True + @property + def name(self): + """Name of the component.""" + return self.__name + + @name.setter + def name(self, value): + self.__name = value + @property def refdes(self): """Reference designator.""" @@ -1155,97 +1166,6 @@ def component_path(self): return (data[1][12][1].split(" ")[1])[1:-1] -class PortComponent(CircuitComponent): - """Manages circuit components.""" - - def __init__(self, circuit_components, tabname="PassedParameterTab", custom_editor=None): - CircuitComponent.__init__(self, circuit_components, tabname, custom_editor) - self.__reference_node = None - self.__microwave_port = False - - @property - def microwave_port(self): - """Get the visualization of the port. - - Returns - ------- - bool - """ - return self.__microwave_port - - @microwave_port.setter - def microwave_port(self, value): - name = self.name.split("@")[-1] - self.__microwave_port = value - self._circuit_components._app.odesign.ChangePortProperty( - name, - [ - f"NAME:{name}", - "IIPortName:=", - name, - "SymbolType:=", - 0 if self.__microwave_port is False else 1, - "DoPostProcess:=", - False, - ], - [], - ) - - @property - def reference_node(self): - """Get the reference node of the port. - - Returns - ------- - str - Reference node name. - """ - if not self.__reference_node: - try: - self._get_property_value("RefNode") - self.__reference_node = self._get_property_value("RefNode") - except Exception: - self.__reference_node = "Ground" - return self.__reference_node - - @reference_node.setter - def reference_node(self, value): - """Set the reference node of the port. - - Parameters - ---------- - value : str - Reference node name. - """ - name = self.name.split("@")[-1] - if value != "Ground" and self.reference_node != "Ground": - args = ["NAME:ChangedProps", ["NAME:RefNode", "Value:=", value]] - self._circuit_components._app.odesign.ChangePortProperty( - name, [f"NAME:{name}", "IIPortName:=", name], [["NAME:Properties", args]] - ) - elif value != "Ground": - args = [ - "NAME:NewProps", - ["NAME:RefNode", "PropType:=", "TextProp", "OverridingDef:=", True, "Value:=", value], - ] - - self._circuit_components._app.odesign.ChangePortProperty( - name, [f"NAME:{name}", "IIPortName:=", name], [["NAME:Properties", args]] - ) - self.__reference_node = value - else: - self._circuit_components._app.odesign.ChangePortProperty( - name, - [ - f"NAME:{name}", - "IIPortName:=", - name, - ], - [["NAME:Properties", [], ["NAME:DeletedProps", "RefNode"]]], - ) - self.__reference_node = "Ground" - - class Wire(object): """Creates and manipulates a wire.""" diff --git a/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py b/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py index 19fc9545147..ef2a8fa59e9 100644 --- a/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py +++ b/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py @@ -37,8 +37,8 @@ from ansys.aedt.core.generic.numbers import is_number from ansys.aedt.core.internal.load_aedt_file import load_keyword_in_aedt_file from ansys.aedt.core.modeler.circuits.object_3d_circuit import CircuitComponent -from ansys.aedt.core.modeler.circuits.object_3d_circuit import PortComponent from ansys.aedt.core.modeler.circuits.object_3d_circuit import Wire +from ansys.aedt.core.modules.boundary.circuit_boundary import Excitations class CircuitComponents(object): @@ -354,18 +354,17 @@ def create_interface_port(self, name, location=None, angle=0): return False xpos, ypos = self._get_location(location) - # id = self.create_unique_id() + arg1 = ["NAME:IPortProps", "Name:=", name] arg2 = ["NAME:Attributes", "Page:=", 1, "X:=", xpos, "Y:=", ypos, "Angle:=", angle, "Flip:=", False] comp_name = self.oeditor.CreateIPort(arg1, arg2) id = int(comp_name.split(";")[1]) self.add_id_to_component(id, comp_name) - # return id, self.components[id].composed_name - for el in self.components: - if ("IPort@" + name + ";" + str(id)) in self.components[el].composed_name: - return self._app.design_excitations[name] - return False + + self._app._internal_excitations[name] = self.components[id] + + return self._app.design_excitations[name] @pyaedt_function_handler() def create_page_port(self, name, location=None, angle=0, label_position="Auto"): @@ -1378,10 +1377,13 @@ def refresh_all_ids(self): name = el.split(";") if len(name) > 1: if name[0].startswith("IPort"): - o = PortComponent(self, tabname=self.tab_name) + port_name = name[0].replace("IPort@", "") + o = Excitations(app=self._app, name=port_name) + o.is_port = True else: o = CircuitComponent(self, tabname=self.tab_name) - o.name = name[0] + o.name = name[0] + if len(name) == 2: o.schematic_id = int(name[1]) objID = int(o.schematic_id) @@ -1389,18 +1391,22 @@ def refresh_all_ids(self): o.id = int(name[1]) o.schematic_id = name[2] objID = int(o.schematic_id) + + if o.is_port: + o._props = o._excitation_props() self.components[objID] = o return len(self.components) - @pyaedt_function_handler() - def add_id_to_component(self, id, name=None): + @pyaedt_function_handler(id="component_id") + def add_id_to_component(self, component_id, name=None): """Add an ID to a component. Parameters ---------- - id : int + component_id : int ID to assign to the component. - + name : str, optional + Component name. The default is ``None``. Returns ------- int @@ -1409,12 +1415,14 @@ def add_id_to_component(self, id, name=None): """ if name: name = name.split(";") - if len(name) > 1 and str(id) == name[1]: + if len(name) > 1 and str(component_id) == name[1]: if name[0].startswith("IPort"): - o = PortComponent(self, tabname=self.tab_name) + port_name = name[0].replace("IPort@", "") + o = Excitations(app=self._app, name=port_name) + o.is_port = True else: o = CircuitComponent(self, tabname=self.tab_name) - o.name = name[0] + o.name = name[0] if len(name) > 2: o.id = int(name[1]) o.schematic_id = int(name[2]) @@ -1422,17 +1430,23 @@ def add_id_to_component(self, id, name=None): else: o.schematic_id = int(name[1]) objID = o.schematic_id + + if o.is_port: + o._props = o._excitation_props() + self.components[objID] = o return len(self.components) obj = self.oeditor.GetAllElements() for el in obj: name = el.split(";") - if len(name) > 1 and str(id) == name[1]: + if len(name) > 1 and str(component_id) == name[1]: if name[0].startswith("IPort"): - o = PortComponent(self, tabname=self.tab_name) + port_name = name[0].replace("IPort@", "") + o = Excitations(app=self._app, name=port_name) + o.is_port = True else: o = CircuitComponent(self, tabname=self.tab_name) - o.name = name[0] + o.name = name[0] if len(name) > 2: o.id = int(name[1]) o.schematic_id = int(name[2]) @@ -1440,6 +1454,10 @@ def add_id_to_component(self, id, name=None): else: o.schematic_id = int(name[1]) objID = o.schematic_id + + if o.is_port: + o._props = o._excitation_props() + self.components[objID] = o return len(self.components) diff --git a/src/ansys/aedt/core/modules/boundary/circuit_boundary.py b/src/ansys/aedt/core/modules/boundary/circuit_boundary.py index 3c192a32a06..372e6c163e2 100644 --- a/src/ansys/aedt/core/modules/boundary/circuit_boundary.py +++ b/src/ansys/aedt/core/modules/boundary/circuit_boundary.py @@ -26,6 +26,7 @@ import re from ansys.aedt.core.generic.general_methods import pyaedt_function_handler +from ansys.aedt.core.modeler.circuits.object_3d_circuit import CircuitComponent from ansys.aedt.core.modules.circuit_templates import SourceKeys @@ -1284,33 +1285,16 @@ def tone(self, value): self._child.SetPropValue("TONE", value) -class Excitations(object): - """Manages Excitations in Circuit Projects. - - Examples - -------- - - """ +class Excitations(CircuitComponent): + """Manages Excitations in Circuit Projects.""" def __init__(self, app, name): self._app = app self._name = name - for comp in self._app.modeler.schematic.components: - if ( - "PortName" in self._app.modeler.schematic.components[comp].parameters.keys() - and self._app.modeler.schematic.components[comp].parameters["PortName"] == self.name - ): - self.schematic_id = comp - self.id = self._app.modeler.schematic.components[comp].id - self._angle = self._app.modeler.schematic.components[comp].angle - self.levels = self._app.modeler.schematic.components[comp].levels - self._location = self._app.modeler.schematic.components[comp].location - self._mirror = self._app.modeler.schematic.components[comp].mirror - self.pins = self._app.modeler.schematic.components[comp].pins - self._use_symbol_color = self._app.modeler.schematic.components[comp].usesymbolcolor - break - self._props = self._excitation_props(name) - self._auto_update = True + CircuitComponent.__init__(self, app.modeler, tabname="PassedParameterTab", custom_editor=None) + + self._props = {} + self.__reference_node = None @property def name(self): @@ -1329,72 +1313,15 @@ def name(self, port_name): # Take previous properties self._app.odesign.RenamePort(self._name, port_name) self._name = port_name - self._app.modeler.schematic.components[self.schematic_id].name = "IPort@" + port_name + # self.name = "IPort@" + port_name self.pins[0].name = "IPort@" + port_name + ";" + str(self.schematic_id) else: self._logger.warning("Name %s already assigned in the design", port_name) @property - def angle(self): - """Symbol angle. - - Returns - ------- - float - """ - return self._angle - - @angle.setter - def angle(self, angle): - self._app.modeler.schematic.components[self.schematic_id].angle = angle - - @property - def mirror(self): - """Enable port mirror. - - Returns - ------- - bool - """ - return self._mirror - - @mirror.setter - def mirror(self, mirror_value=True): - self._app.modeler.schematic.components[self.schematic_id].mirror = mirror_value - self._mirror = mirror_value - - @property - def location(self): - """Port location. - - Returns - ------- - list - """ - return self._location - - @location.setter - def location(self, location_xy): - # The command must be called two times. - self._app.modeler.schematic.components[self.schematic_id].location = location_xy - self._app.modeler.schematic.components[self.schematic_id].location = location_xy - self._location = location_xy - - @property - def use_symbol_color(self): - """Use symbol color. - - Returns - ------- - list - """ - return self._use_symbol_color - - @use_symbol_color.setter - def use_symbol_color(self, use_color=True): - self._app.modeler.schematic.components[self.schematic_id].usesymbolcolor = use_color - self._app.modeler.schematic.components[self.schematic_id].set_use_symbol_color(use_color) - self._use_symbol_color = use_color + def composed_name(self): + """Composed names.""" + return "IPort@" + self.name + ";" + str(self.schematic_id) @property def impedance(self): @@ -1409,12 +1336,8 @@ def impedance(self): @impedance.setter def impedance(self, termination=None): if termination and len(termination) == 2: - self._app.modeler.schematic.components[self.schematic_id].change_property( - ["NAME:rz", "Value:=", termination[0]] - ) - self._app.modeler.schematic.components[self.schematic_id].change_property( - ["NAME:iz", "Value:=", termination[1]] - ) + self.change_property(["NAME:rz", "Value:=", termination[0]]) + self.change_property(["NAME:iz", "Value:=", termination[1]]) self._props["rz"] = termination[0] self._props["iz"] = termination[1] @@ -1431,9 +1354,7 @@ def enable_noise(self): @enable_noise.setter def enable_noise(self, enable=False): - self._app.modeler.schematic.components[self.schematic_id].change_property( - ["NAME:EnableNoise", "Value:=", enable] - ) + self.change_property(["NAME:EnableNoise", "Value:=", enable]) self._props["EnableNoise"] = enable @property @@ -1450,9 +1371,7 @@ def noise_temperature(self): @noise_temperature.setter def noise_temperature(self, noise=None): if noise: - self._app.modeler.schematic.components[self.schematic_id].change_property( - ["NAME:noisetemp", "Value:=", noise] - ) + self.change_property(["NAME:noisetemp", "Value:=", noise]) self._props["noisetemp"] = noise @property @@ -1484,18 +1403,52 @@ def reference_node(self): ------- str """ - if self._props["RefNode"] == "Z": - return "Ground" - return self._props["RefNode"] + + if self._props["RefNode"] != "Z": + try: + self.__reference_node = self._props["RefNode"] + except Exception: # pragma: no cover + self.__reference_node = "Ground" + else: + self.__reference_node = "Ground" + return self.__reference_node @reference_node.setter - def reference_node(self, ref_node=None): - if ref_node: - self._logger.warning("Set reference node only working with gRPC") - if ref_node == "Ground": - ref_node = "Z" - self._props["RefNode"] = ref_node - self.update() + def reference_node(self, value): + """Set the reference node of the port. + + Parameters + ---------- + value : str + Reference node name. + """ + name = self.name.split("@")[-1] + if value != "Ground" and self.reference_node != "Ground": + args = ["NAME:ChangedProps", ["NAME:RefNode", "Value:=", value]] + self._circuit_components._app.odesign.ChangePortProperty( + name, [f"NAME:{name}", "IIPortName:=", name], [["NAME:Properties", args]] + ) + elif value != "Ground": + args = [ + "NAME:NewProps", + ["NAME:RefNode", "PropType:=", "TextProp", "OverridingDef:=", True, "Value:=", value], + ] + + self._circuit_components._app.odesign.ChangePortProperty( + name, [f"NAME:{name}", "IIPortName:=", name], [["NAME:Properties", args]] + ) + else: + self._circuit_components._app.odesign.ChangePortProperty( + name, + [ + f"NAME:{name}", + "IIPortName:=", + name, + ], + [["NAME:Properties", [], ["NAME:DeletedProps", "RefNode"]]], + ) + self.__reference_node = value + self._props["RefNode"] = self.__reference_node @property def enabled_sources(self): @@ -1530,91 +1483,84 @@ def enabled_analyses(self, analyses=None): self.update() @pyaedt_function_handler() - def _excitation_props(self, port): + def _excitation_props(self): excitation_prop_dict = {} - for comp in self._app.modeler.schematic.components: - if ( - "PortName" in self._app.modeler.schematic.components[comp].parameters.keys() - and self._app.modeler.schematic.components[comp].parameters["PortName"] == port - ): - excitation_prop_dict["rz"] = "50ohm" - excitation_prop_dict["iz"] = "0ohm" - excitation_prop_dict["term"] = None - excitation_prop_dict["TerminationData"] = None - excitation_prop_dict["RefNode"] = "Z" - excitation_prop_dict["EnableNoise"] = False - excitation_prop_dict["noisetemp"] = "16.85cel" - - if "RefNode" in self._app.modeler.schematic.components[comp].parameters: - excitation_prop_dict["RefNode"] = self._app.modeler.schematic.components[comp].parameters["RefNode"] - if "term" in self._app.modeler.schematic.components[comp].parameters: - excitation_prop_dict["term"] = self._app.modeler.schematic.components[comp].parameters["term"] - excitation_prop_dict["TerminationData"] = self._app.modeler.schematic.components[comp].parameters[ - "TerminationData" - ] - else: - if "rz" in self._app.modeler.schematic.components[comp].parameters: - excitation_prop_dict["rz"] = self._app.modeler.schematic.components[comp].parameters["rz"] - excitation_prop_dict["iz"] = self._app.modeler.schematic.components[comp].parameters["iz"] + port = "" + if "PortName" in self.parameters.keys(): + excitation_prop_dict["rz"] = "50ohm" + excitation_prop_dict["iz"] = "0ohm" + excitation_prop_dict["term"] = None + excitation_prop_dict["TerminationData"] = None + excitation_prop_dict["RefNode"] = "Z" + excitation_prop_dict["EnableNoise"] = False + excitation_prop_dict["noisetemp"] = "16.85cel" + + if "RefNode" in self.parameters: + excitation_prop_dict["RefNode"] = self.parameters["RefNode"] + if "term" in self.parameters: + excitation_prop_dict["term"] = self.parameters["term"] + excitation_prop_dict["TerminationData"] = self.parameters["TerminationData"] + else: + if "rz" in self.parameters: + excitation_prop_dict["rz"] = self.parameters["rz"] + excitation_prop_dict["iz"] = self.parameters["iz"] - if "EnableNoise" in self._app.modeler.schematic.components[comp].parameters: - if self._app.modeler.schematic.components[comp].parameters["EnableNoise"] == "true": - excitation_prop_dict["EnableNoise"] = True - else: - excitation_prop_dict["EnableNoise"] = False + if "EnableNoise" in self.parameters: + if self.parameters["EnableNoise"] == "true": + excitation_prop_dict["EnableNoise"] = True + else: + excitation_prop_dict["EnableNoise"] = False - excitation_prop_dict["noisetemp"] = self._app.modeler.schematic.components[comp].parameters[ - "noisetemp" - ] + excitation_prop_dict["noisetemp"] = self.parameters["noisetemp"] - if not self._app.design_properties or not self._app.design_properties["NexximPorts"]["Data"]: - excitation_prop_dict["SymbolType"] = 0 - else: - excitation_prop_dict["SymbolType"] = self._app.design_properties["NexximPorts"]["Data"][port][ - "SymbolType" - ] + if not self._app.design_properties or not self._app.design_properties["NexximPorts"]["Data"]: + excitation_prop_dict["SymbolType"] = 0 + else: + excitation_prop_dict["SymbolType"] = self._app.design_properties["NexximPorts"]["Data"][port][ + "SymbolType" + ] - if "pnum" in self._app.modeler.schematic.components[comp].parameters: - excitation_prop_dict["pnum"] = self._app.modeler.schematic.components[comp].parameters["pnum"] - else: - excitation_prop_dict["pnum"] = None - source_port = [] - if not self._app.design_properties: - enabled_ports = None - else: - enabled_ports = self._app.design_properties["ComponentConfigurationData"]["EnabledPorts"] - if isinstance(enabled_ports, dict): - for source in enabled_ports: - if enabled_ports[source] and port in enabled_ports[source]: - source_port.append(source) - excitation_prop_dict["EnabledPorts"] = source_port - - components_port = [] - if not self._app.design_properties: - multiple = None - else: - multiple = self._app.design_properties["ComponentConfigurationData"]["EnabledMultipleComponents"] - if isinstance(multiple, dict): - for source in multiple: - if multiple[source] and port in multiple[source]: - components_port.append(source) - excitation_prop_dict["EnabledMultipleComponents"] = components_port - - port_analyses = {} - if not self._app.design_properties: - enabled_analyses = None - else: - enabled_analyses = self._app.design_properties["ComponentConfigurationData"]["EnabledAnalyses"] - if isinstance(enabled_analyses, dict): - for source in enabled_analyses: - if ( - enabled_analyses[source] - and port in enabled_analyses[source] - and source in excitation_prop_dict["EnabledPorts"] - ): - port_analyses[source] = enabled_analyses[source][port] - excitation_prop_dict["EnabledAnalyses"] = port_analyses - return excitation_prop_dict + if "pnum" in self.parameters: + excitation_prop_dict["pnum"] = self.parameters["pnum"] + else: + excitation_prop_dict["pnum"] = None + source_port = [] + if not self._app.design_properties: + enabled_ports = None + else: + enabled_ports = self._app.design_properties["ComponentConfigurationData"]["EnabledPorts"] + if isinstance(enabled_ports, dict): + for source in enabled_ports: + if enabled_ports[source] and port in enabled_ports[source]: + source_port.append(source) + excitation_prop_dict["EnabledPorts"] = source_port + + components_port = [] + if not self._app.design_properties: + multiple = None + else: + multiple = self._app.design_properties["ComponentConfigurationData"]["EnabledMultipleComponents"] + if isinstance(multiple, dict): + for source in multiple: + if multiple[source] and port in multiple[source]: + components_port.append(source) + excitation_prop_dict["EnabledMultipleComponents"] = components_port + + port_analyses = {} + if not self._app.design_properties: + enabled_analyses = None + else: + enabled_analyses = self._app.design_properties["ComponentConfigurationData"]["EnabledAnalyses"] + if isinstance(enabled_analyses, dict): + for source in enabled_analyses: + if ( + enabled_analyses[source] + and port in enabled_analyses[source] + and source in excitation_prop_dict["EnabledPorts"] + ): + port_analyses[source] = enabled_analyses[source][port] + excitation_prop_dict["EnabledAnalyses"] = port_analyses + return excitation_prop_dict @pyaedt_function_handler() def update(self): @@ -1686,6 +1632,10 @@ def delete(self): """ self._app.modeler._odesign.DeletePort(self.name) + for k, v in self._circuit_components.components.items(): + if v.name == self.name: + del self._circuit_components.components[k] + break return True @property diff --git a/tests/system/general/test_21_Circuit.py b/tests/system/general/test_21_Circuit.py index 3e331bc302b..ad96d4ba58f 100644 --- a/tests/system/general/test_21_Circuit.py +++ b/tests/system/general/test_21_Circuit.py @@ -208,8 +208,9 @@ def test_12a_connect_components(self, aedtapp): myres = aedtapp.modeler.schematic.create_resistor("R101", 50) mycap = aedtapp.modeler.schematic.create_capacitor("C1", 1) p2 = aedtapp.modeler.schematic.create_interface_port("Port2") - p2.microwave_port = True - assert p2.microwave_port + assert not p2.microwave_symbol + p2.microwave_symbol = True + assert p2.microwave_symbol assert "Port2" in aedtapp.modeler.schematic.nets assert myind.pins[1].connect_to_component(myres.pins[1], "port_name_test") From 61f46f789c97e303a747c3d956a0df428d1a445f Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Mon, 14 Jul 2025 13:30:49 +0200 Subject: [PATCH 7/9] Replace PortComponent to Excitation --- src/ansys/aedt/core/application/analysis_nexxim.py | 4 ++-- src/ansys/aedt/core/modules/boundary/circuit_boundary.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ansys/aedt/core/application/analysis_nexxim.py b/src/ansys/aedt/core/application/analysis_nexxim.py index 5715a3cfbf7..d1797c84c91 100644 --- a/src/ansys/aedt/core/application/analysis_nexxim.py +++ b/src/ansys/aedt/core/application/analysis_nexxim.py @@ -366,11 +366,11 @@ def design_excitations(self): >>> oModule.GetExcitations """ props = {} - port = "" + if not self._internal_excitations: for comp in self.modeler.schematic.components: if comp.name in self.excitation_names: - props[port] = comp + props[comp.name] = comp self._internal_excitations = props else: props = self._internal_excitations diff --git a/src/ansys/aedt/core/modules/boundary/circuit_boundary.py b/src/ansys/aedt/core/modules/boundary/circuit_boundary.py index 372e6c163e2..f6c3dfc15aa 100644 --- a/src/ansys/aedt/core/modules/boundary/circuit_boundary.py +++ b/src/ansys/aedt/core/modules/boundary/circuit_boundary.py @@ -1485,8 +1485,9 @@ def enabled_analyses(self, analyses=None): @pyaedt_function_handler() def _excitation_props(self): excitation_prop_dict = {} - port = "" + if "PortName" in self.parameters.keys(): + port = self.parameters["PortName"] excitation_prop_dict["rz"] = "50ohm" excitation_prop_dict["iz"] = "0ohm" excitation_prop_dict["term"] = None From a198e5f491ae8e9b0737e9ae2820076caf2dd28f Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Mon, 14 Jul 2025 14:42:04 +0200 Subject: [PATCH 8/9] Replace PortComponent to Excitation --- .../aedt/core/application/analysis_nexxim.py | 4 +- .../modeler/circuits/object_3d_circuit.py | 363 +++++++++++++++++- .../modeler/circuits/primitives_circuit.py | 8 +- .../modeler/circuits/primitives_nexxim.py | 2 +- src/ansys/aedt/core/modeler/schematic.py | 6 +- .../core/modules/boundary/circuit_boundary.py | 361 ----------------- tests/system/general/test_21_Circuit.py | 2 +- 7 files changed, 373 insertions(+), 373 deletions(-) diff --git a/src/ansys/aedt/core/application/analysis_nexxim.py b/src/ansys/aedt/core/application/analysis_nexxim.py index d1797c84c91..bd767ef240d 100644 --- a/src/ansys/aedt/core/application/analysis_nexxim.py +++ b/src/ansys/aedt/core/application/analysis_nexxim.py @@ -28,8 +28,8 @@ from ansys.aedt.core.generic.general_methods import pyaedt_function_handler from ansys.aedt.core.generic.settings import settings from ansys.aedt.core.modeler.circuits.object_3d_circuit import CircuitComponent +from ansys.aedt.core.modeler.circuits.object_3d_circuit import Excitations from ansys.aedt.core.modules.boundary.circuit_boundary import CurrentSinSource -from ansys.aedt.core.modules.boundary.circuit_boundary import Excitations from ansys.aedt.core.modules.boundary.circuit_boundary import PowerIQSource from ansys.aedt.core.modules.boundary.circuit_boundary import PowerSinSource from ansys.aedt.core.modules.boundary.circuit_boundary import Sources @@ -368,7 +368,7 @@ def design_excitations(self): props = {} if not self._internal_excitations: - for comp in self.modeler.schematic.components: + for comp in self.modeler.schematic.components.values(): if comp.name in self.excitation_names: props[comp.name] = comp self._internal_excitations = props diff --git a/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py b/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py index 5a7f1e1047f..be320c38927 100644 --- a/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py +++ b/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py @@ -1143,6 +1143,8 @@ def create_pin_def(pin_name, x, y, angle): @property def component_path(self): """Component definition path.""" + if self.component_info.get("Info", None) is None: + return None component_definition = self.component_info["Info"] model_data = self._circuit_components.omodel_manager.GetData(component_definition) if "sssfilename:=" in model_data and model_data[model_data.index("sssfilename:=") + 1]: @@ -1151,8 +1153,8 @@ def component_path(self): return model_data[model_data.index("filename:=") + 1] component_data = self._circuit_components.o_component_manager.GetData(component_definition) if not component_data: - self._circuit_components._app.logger.warning("Component " + self.refdes + " has no path") - return False + # self._circuit_components._app.logger.warning("Component " + self.refdes + " has no path") + return None if len(component_data[2][5]) == 0: for data in component_data: if isinstance(data, list) and isinstance(data[0], str) and data[0] == "NAME:Parameters": @@ -1312,3 +1314,360 @@ def set_net_name(self, name, split_wires=False): ) self.composed_name = f"Wire@{name};{self.composed_name.split(';')[1]}" return True + + +class Excitations(CircuitComponent): + """Manages Excitations in Circuit Projects.""" + + def __init__(self, circuit_components, name): + self._name = name + CircuitComponent.__init__(self, circuit_components, tabname="PassedParameterTab", custom_editor=None) + + self._props = {} + self.__reference_node = None + + @property + def name(self): + """Excitation name. + + Returns + ------- + str + """ + return self._name + + @name.setter + def name(self, port_name): + if port_name not in self._circuit_components._app.excitation_names: + if port_name != self._name: + # Take previous properties + self._circuit_components._app.odesign.RenamePort(self._name, port_name) + self._name = port_name + self.pins[0].name = "IPort@" + port_name + ";" + str(self.schematic_id) + else: + self._logger.warning("Name %s already assigned in the design", port_name) + + @property + def composed_name(self): + """Composed names.""" + return "IPort@" + self.name + ";" + str(self.schematic_id) + + @property + def impedance(self): + """Port termination. + + Returns + ------- + list + """ + return [self._props["rz"], self._props["iz"]] + + @impedance.setter + def impedance(self, termination=None): + if termination and len(termination) == 2: + self.change_property(["NAME:rz", "Value:=", termination[0]]) + self.change_property(["NAME:iz", "Value:=", termination[1]]) + self._props["rz"] = termination[0] + self._props["iz"] = termination[1] + + @property + def enable_noise(self): + """Enable noise. + + Returns + ------- + bool + """ + + return self._props["EnableNoise"] + + @enable_noise.setter + def enable_noise(self, enable=False): + self.change_property(["NAME:EnableNoise", "Value:=", enable]) + self._props["EnableNoise"] = enable + + @property + def noise_temperature(self): + """Enable noise. + + Returns + ------- + str + """ + + return self._props["noisetemp"] + + @noise_temperature.setter + def noise_temperature(self, noise=None): + if noise: + self.change_property(["NAME:noisetemp", "Value:=", noise]) + self._props["noisetemp"] = noise + + @property + def microwave_symbol(self): + """Enable microwave symbol. + + Returns + ------- + bool + """ + if self._props["SymbolType"] == 1: + return True + else: + return False + + @microwave_symbol.setter + def microwave_symbol(self, enable=False): + if enable: + self._props["SymbolType"] = 1 + else: + self._props["SymbolType"] = 0 + self.update() + + @property + def reference_node(self): + """Reference node. + + Returns + ------- + str + """ + + if self._props["RefNode"] != "Z": + try: + self.__reference_node = self._props["RefNode"] + except Exception: # pragma: no cover + self.__reference_node = "Ground" + else: + self.__reference_node = "Ground" + return self.__reference_node + + @reference_node.setter + def reference_node(self, value): + """Set the reference node of the port. + + Parameters + ---------- + value : str + Reference node name. + """ + name = self.name.split("@")[-1] + if value != "Ground" and self.reference_node != "Ground": + args = ["NAME:ChangedProps", ["NAME:RefNode", "Value:=", value]] + self._circuit_components._app.odesign.ChangePortProperty( + name, [f"NAME:{name}", "IIPortName:=", name], [["NAME:Properties", args]] + ) + elif value != "Ground": + args = [ + "NAME:NewProps", + ["NAME:RefNode", "PropType:=", "TextProp", "OverridingDef:=", True, "Value:=", value], + ] + + self._circuit_components._app.odesign.ChangePortProperty( + name, [f"NAME:{name}", "IIPortName:=", name], [["NAME:Properties", args]] + ) + else: + self._circuit_components._app.odesign.ChangePortProperty( + name, + [ + f"NAME:{name}", + "IIPortName:=", + name, + ], + [["NAME:Properties", [], ["NAME:DeletedProps", "RefNode"]]], + ) + self.__reference_node = value + self._props["RefNode"] = self.__reference_node + + @property + def enabled_sources(self): + """Enabled sources. + + Returns + ------- + list + """ + return self._props["EnabledPorts"] + + @enabled_sources.setter + def enabled_sources(self, sources=None): + if sources: + self._props["EnabledPorts"] = sources + self.update() + + @property + def enabled_analyses(self): + """Enabled analyses. + + Returns + ------- + dict + """ + return self._props["EnabledAnalyses"] + + @enabled_analyses.setter + def enabled_analyses(self, analyses=None): + if analyses: + self._props["EnabledAnalyses"] = analyses + self.update() + + @pyaedt_function_handler() + def _excitation_props(self): + excitation_prop_dict = {} + + if "PortName" in self.parameters.keys(): + port = self.parameters["PortName"] + excitation_prop_dict["rz"] = "50ohm" + excitation_prop_dict["iz"] = "0ohm" + excitation_prop_dict["term"] = None + excitation_prop_dict["TerminationData"] = None + excitation_prop_dict["RefNode"] = "Z" + excitation_prop_dict["EnableNoise"] = False + excitation_prop_dict["noisetemp"] = "16.85cel" + + if "RefNode" in self.parameters: + excitation_prop_dict["RefNode"] = self.parameters["RefNode"] + if "term" in self.parameters: + excitation_prop_dict["term"] = self.parameters["term"] + excitation_prop_dict["TerminationData"] = self.parameters["TerminationData"] + else: + if "rz" in self.parameters: + excitation_prop_dict["rz"] = self.parameters["rz"] + excitation_prop_dict["iz"] = self.parameters["iz"] + + if "EnableNoise" in self.parameters: + if self.parameters["EnableNoise"] == "true": + excitation_prop_dict["EnableNoise"] = True + else: + excitation_prop_dict["EnableNoise"] = False + + excitation_prop_dict["noisetemp"] = self.parameters["noisetemp"] + + app = self._circuit_components._app + if not app.design_properties or not app.design_properties["NexximPorts"]["Data"]: + excitation_prop_dict["SymbolType"] = 0 + else: + excitation_prop_dict["SymbolType"] = app.design_properties["NexximPorts"]["Data"][port]["SymbolType"] + + if "pnum" in self.parameters: + excitation_prop_dict["pnum"] = self.parameters["pnum"] + else: + excitation_prop_dict["pnum"] = None + source_port = [] + if not app.design_properties: + enabled_ports = None + else: + enabled_ports = app.design_properties["ComponentConfigurationData"]["EnabledPorts"] + if isinstance(enabled_ports, dict): + for source in enabled_ports: + if enabled_ports[source] and port in enabled_ports[source]: + source_port.append(source) + excitation_prop_dict["EnabledPorts"] = source_port + + components_port = [] + if not app.design_properties: + multiple = None + else: + multiple = app.design_properties["ComponentConfigurationData"]["EnabledMultipleComponents"] + if isinstance(multiple, dict): + for source in multiple: + if multiple[source] and port in multiple[source]: + components_port.append(source) + excitation_prop_dict["EnabledMultipleComponents"] = components_port + + port_analyses = {} + if not app.design_properties: + enabled_analyses = None + else: + enabled_analyses = app.design_properties["ComponentConfigurationData"]["EnabledAnalyses"] + if isinstance(enabled_analyses, dict): + for source in enabled_analyses: + if ( + enabled_analyses[source] + and port in enabled_analyses[source] + and source in excitation_prop_dict["EnabledPorts"] + ): + port_analyses[source] = enabled_analyses[source][port] + excitation_prop_dict["EnabledAnalyses"] = port_analyses + return excitation_prop_dict + + @pyaedt_function_handler() + def update(self): + """Update the excitation in AEDT. + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + """ + + # self._logger.warning("Property port update only working with GRPC") + + if self._props["RefNode"] == "Ground": + self._props["RefNode"] = "Z" + + arg0 = [ + "NAME:" + self.name, + "IIPortName:=", + self.name, + "SymbolType:=", + self._props["SymbolType"], + "DoPostProcess:=", + False, + ] + + arg1 = ["NAME:ChangedProps"] + arg2 = [] + + # Modify RefNode + if self._props["RefNode"] != "Z": + arg2 = [ + "NAME:NewProps", + ["NAME:RefNode", "PropType:=", "TextProp", "OverridingDef:=", True, "Value:=", self._props["RefNode"]], + ] + + # Modify Termination + if self._props["term"] and self._props["TerminationData"]: + arg2 = [ + "NAME:NewProps", + ["NAME:term", "PropType:=", "TextProp", "OverridingDef:=", True, "Value:=", self._props["term"]], + ] + + for prop in self._props: + skip1 = (prop == "rz" or prop == "iz") and isinstance(self._props["term"], str) + skip2 = prop == "EnabledPorts" or prop == "EnabledMultipleComponents" or prop == "EnabledAnalyses" + skip3 = prop == "SymbolType" + skip4 = prop == "TerminationData" and not isinstance(self._props["term"], str) + if not skip1 and not skip2 and not skip3 and not skip4 and self._props[prop] is not None: + command = ["NAME:" + prop, "Value:=", self._props[prop]] + arg1.append(command) + + arg1 = [["NAME:Properties", arg2, arg1]] + self._circuit_components._app.odesign.ChangePortProperty(self.name, arg0, arg1) + + for source in self._circuit_components._app.sources: + self._app.sources[source].update() + return True + + @pyaedt_function_handler() + def delete(self): + """Delete the port in AEDT. + + Returns + ------- + bool + ``True`` when successful, ``False`` when failed. + + """ + self._circuit_components._app.modeler._odesign.DeletePort(self.name) + for k, v in self._circuit_components.components.items(): + if v.name == self.name: + del self._circuit_components.components[k] + break + return True + + @property + def _logger(self): + """Logger.""" + return self._app.logger diff --git a/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py b/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py index ef2a8fa59e9..6b00436564a 100644 --- a/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py +++ b/src/ansys/aedt/core/modeler/circuits/primitives_circuit.py @@ -37,8 +37,8 @@ from ansys.aedt.core.generic.numbers import is_number from ansys.aedt.core.internal.load_aedt_file import load_keyword_in_aedt_file from ansys.aedt.core.modeler.circuits.object_3d_circuit import CircuitComponent +from ansys.aedt.core.modeler.circuits.object_3d_circuit import Excitations from ansys.aedt.core.modeler.circuits.object_3d_circuit import Wire -from ansys.aedt.core.modules.boundary.circuit_boundary import Excitations class CircuitComponents(object): @@ -1378,7 +1378,7 @@ def refresh_all_ids(self): if len(name) > 1: if name[0].startswith("IPort"): port_name = name[0].replace("IPort@", "") - o = Excitations(app=self._app, name=port_name) + o = Excitations(self, name=port_name) o.is_port = True else: o = CircuitComponent(self, tabname=self.tab_name) @@ -1418,7 +1418,7 @@ def add_id_to_component(self, component_id, name=None): if len(name) > 1 and str(component_id) == name[1]: if name[0].startswith("IPort"): port_name = name[0].replace("IPort@", "") - o = Excitations(app=self._app, name=port_name) + o = Excitations(self, name=port_name) o.is_port = True else: o = CircuitComponent(self, tabname=self.tab_name) @@ -1442,7 +1442,7 @@ def add_id_to_component(self, component_id, name=None): if len(name) > 1 and str(component_id) == name[1]: if name[0].startswith("IPort"): port_name = name[0].replace("IPort@", "") - o = Excitations(app=self._app, name=port_name) + o = Excitations(self, name=port_name) o.is_port = True else: o = CircuitComponent(self, tabname=self.tab_name) diff --git a/src/ansys/aedt/core/modeler/circuits/primitives_nexxim.py b/src/ansys/aedt/core/modeler/circuits/primitives_nexxim.py index b2143499d79..68776d2ca18 100644 --- a/src/ansys/aedt/core/modeler/circuits/primitives_nexxim.py +++ b/src/ansys/aedt/core/modeler/circuits/primitives_nexxim.py @@ -39,7 +39,7 @@ from ansys.aedt.core.modeler.circuits.object_3d_circuit import CircuitComponent from ansys.aedt.core.modeler.circuits.primitives_circuit import CircuitComponents from ansys.aedt.core.modeler.circuits.primitives_circuit import ComponentCatalog -from ansys.aedt.core.modules.boundary.circuit_boundary import Excitations +from ansys.aedt.core.modeler.circuits.primitives_circuit import Excitations class NexximComponents(CircuitComponents): diff --git a/src/ansys/aedt/core/modeler/schematic.py b/src/ansys/aedt/core/modeler/schematic.py index c6929103bc0..459e2f14402 100644 --- a/src/ansys/aedt/core/modeler/schematic.py +++ b/src/ansys/aedt/core/modeler/schematic.py @@ -186,8 +186,10 @@ def connect_schematic_components( components = self.schematic.components else: components = self.components - start = components[starting_component] - end = components[ending_component] + starting_component = self._get_components_selections(starting_component) + ending_component = self._get_components_selections(ending_component) + start = components[starting_component[0]] + end = components[ending_component[0]] if isinstance(pin_starting, (int, str)): pin_starting = [pin_starting] if isinstance(pin_ending, (int, str)): diff --git a/src/ansys/aedt/core/modules/boundary/circuit_boundary.py b/src/ansys/aedt/core/modules/boundary/circuit_boundary.py index f6c3dfc15aa..417a8cf8f15 100644 --- a/src/ansys/aedt/core/modules/boundary/circuit_boundary.py +++ b/src/ansys/aedt/core/modules/boundary/circuit_boundary.py @@ -26,7 +26,6 @@ import re from ansys.aedt.core.generic.general_methods import pyaedt_function_handler -from ansys.aedt.core.modeler.circuits.object_3d_circuit import CircuitComponent from ansys.aedt.core.modules.circuit_templates import SourceKeys @@ -1283,363 +1282,3 @@ def tone(self): def tone(self, value): self._props["TONE"] = value self._child.SetPropValue("TONE", value) - - -class Excitations(CircuitComponent): - """Manages Excitations in Circuit Projects.""" - - def __init__(self, app, name): - self._app = app - self._name = name - CircuitComponent.__init__(self, app.modeler, tabname="PassedParameterTab", custom_editor=None) - - self._props = {} - self.__reference_node = None - - @property - def name(self): - """Excitation name. - - Returns - ------- - str - """ - return self._name - - @name.setter - def name(self, port_name): - if port_name not in self._app.excitation_names: - if port_name != self._name: - # Take previous properties - self._app.odesign.RenamePort(self._name, port_name) - self._name = port_name - # self.name = "IPort@" + port_name - self.pins[0].name = "IPort@" + port_name + ";" + str(self.schematic_id) - else: - self._logger.warning("Name %s already assigned in the design", port_name) - - @property - def composed_name(self): - """Composed names.""" - return "IPort@" + self.name + ";" + str(self.schematic_id) - - @property - def impedance(self): - """Port termination. - - Returns - ------- - list - """ - return [self._props["rz"], self._props["iz"]] - - @impedance.setter - def impedance(self, termination=None): - if termination and len(termination) == 2: - self.change_property(["NAME:rz", "Value:=", termination[0]]) - self.change_property(["NAME:iz", "Value:=", termination[1]]) - self._props["rz"] = termination[0] - self._props["iz"] = termination[1] - - @property - def enable_noise(self): - """Enable noise. - - Returns - ------- - bool - """ - - return self._props["EnableNoise"] - - @enable_noise.setter - def enable_noise(self, enable=False): - self.change_property(["NAME:EnableNoise", "Value:=", enable]) - self._props["EnableNoise"] = enable - - @property - def noise_temperature(self): - """Enable noise. - - Returns - ------- - str - """ - - return self._props["noisetemp"] - - @noise_temperature.setter - def noise_temperature(self, noise=None): - if noise: - self.change_property(["NAME:noisetemp", "Value:=", noise]) - self._props["noisetemp"] = noise - - @property - def microwave_symbol(self): - """Enable microwave symbol. - - Returns - ------- - bool - """ - if self._props["SymbolType"] == 1: - return True - else: - return False - - @microwave_symbol.setter - def microwave_symbol(self, enable=False): - if enable: - self._props["SymbolType"] = 1 - else: - self._props["SymbolType"] = 0 - self.update() - - @property - def reference_node(self): - """Reference node. - - Returns - ------- - str - """ - - if self._props["RefNode"] != "Z": - try: - self.__reference_node = self._props["RefNode"] - except Exception: # pragma: no cover - self.__reference_node = "Ground" - else: - self.__reference_node = "Ground" - return self.__reference_node - - @reference_node.setter - def reference_node(self, value): - """Set the reference node of the port. - - Parameters - ---------- - value : str - Reference node name. - """ - name = self.name.split("@")[-1] - if value != "Ground" and self.reference_node != "Ground": - args = ["NAME:ChangedProps", ["NAME:RefNode", "Value:=", value]] - self._circuit_components._app.odesign.ChangePortProperty( - name, [f"NAME:{name}", "IIPortName:=", name], [["NAME:Properties", args]] - ) - elif value != "Ground": - args = [ - "NAME:NewProps", - ["NAME:RefNode", "PropType:=", "TextProp", "OverridingDef:=", True, "Value:=", value], - ] - - self._circuit_components._app.odesign.ChangePortProperty( - name, [f"NAME:{name}", "IIPortName:=", name], [["NAME:Properties", args]] - ) - else: - self._circuit_components._app.odesign.ChangePortProperty( - name, - [ - f"NAME:{name}", - "IIPortName:=", - name, - ], - [["NAME:Properties", [], ["NAME:DeletedProps", "RefNode"]]], - ) - self.__reference_node = value - self._props["RefNode"] = self.__reference_node - - @property - def enabled_sources(self): - """Enabled sources. - - Returns - ------- - list - """ - return self._props["EnabledPorts"] - - @enabled_sources.setter - def enabled_sources(self, sources=None): - if sources: - self._props["EnabledPorts"] = sources - self.update() - - @property - def enabled_analyses(self): - """Enabled analyses. - - Returns - ------- - dict - """ - return self._props["EnabledAnalyses"] - - @enabled_analyses.setter - def enabled_analyses(self, analyses=None): - if analyses: - self._props["EnabledAnalyses"] = analyses - self.update() - - @pyaedt_function_handler() - def _excitation_props(self): - excitation_prop_dict = {} - - if "PortName" in self.parameters.keys(): - port = self.parameters["PortName"] - excitation_prop_dict["rz"] = "50ohm" - excitation_prop_dict["iz"] = "0ohm" - excitation_prop_dict["term"] = None - excitation_prop_dict["TerminationData"] = None - excitation_prop_dict["RefNode"] = "Z" - excitation_prop_dict["EnableNoise"] = False - excitation_prop_dict["noisetemp"] = "16.85cel" - - if "RefNode" in self.parameters: - excitation_prop_dict["RefNode"] = self.parameters["RefNode"] - if "term" in self.parameters: - excitation_prop_dict["term"] = self.parameters["term"] - excitation_prop_dict["TerminationData"] = self.parameters["TerminationData"] - else: - if "rz" in self.parameters: - excitation_prop_dict["rz"] = self.parameters["rz"] - excitation_prop_dict["iz"] = self.parameters["iz"] - - if "EnableNoise" in self.parameters: - if self.parameters["EnableNoise"] == "true": - excitation_prop_dict["EnableNoise"] = True - else: - excitation_prop_dict["EnableNoise"] = False - - excitation_prop_dict["noisetemp"] = self.parameters["noisetemp"] - - if not self._app.design_properties or not self._app.design_properties["NexximPorts"]["Data"]: - excitation_prop_dict["SymbolType"] = 0 - else: - excitation_prop_dict["SymbolType"] = self._app.design_properties["NexximPorts"]["Data"][port][ - "SymbolType" - ] - - if "pnum" in self.parameters: - excitation_prop_dict["pnum"] = self.parameters["pnum"] - else: - excitation_prop_dict["pnum"] = None - source_port = [] - if not self._app.design_properties: - enabled_ports = None - else: - enabled_ports = self._app.design_properties["ComponentConfigurationData"]["EnabledPorts"] - if isinstance(enabled_ports, dict): - for source in enabled_ports: - if enabled_ports[source] and port in enabled_ports[source]: - source_port.append(source) - excitation_prop_dict["EnabledPorts"] = source_port - - components_port = [] - if not self._app.design_properties: - multiple = None - else: - multiple = self._app.design_properties["ComponentConfigurationData"]["EnabledMultipleComponents"] - if isinstance(multiple, dict): - for source in multiple: - if multiple[source] and port in multiple[source]: - components_port.append(source) - excitation_prop_dict["EnabledMultipleComponents"] = components_port - - port_analyses = {} - if not self._app.design_properties: - enabled_analyses = None - else: - enabled_analyses = self._app.design_properties["ComponentConfigurationData"]["EnabledAnalyses"] - if isinstance(enabled_analyses, dict): - for source in enabled_analyses: - if ( - enabled_analyses[source] - and port in enabled_analyses[source] - and source in excitation_prop_dict["EnabledPorts"] - ): - port_analyses[source] = enabled_analyses[source][port] - excitation_prop_dict["EnabledAnalyses"] = port_analyses - return excitation_prop_dict - - @pyaedt_function_handler() - def update(self): - """Update the excitation in AEDT. - - Returns - ------- - bool - ``True`` when successful, ``False`` when failed. - - """ - - # self._logger.warning("Property port update only working with GRPC") - - if self._props["RefNode"] == "Ground": - self._props["RefNode"] = "Z" - - arg0 = [ - "NAME:" + self.name, - "IIPortName:=", - self.name, - "SymbolType:=", - self._props["SymbolType"], - "DoPostProcess:=", - False, - ] - - arg1 = ["NAME:ChangedProps"] - arg2 = [] - - # Modify RefNode - if self._props["RefNode"] != "Z": - arg2 = [ - "NAME:NewProps", - ["NAME:RefNode", "PropType:=", "TextProp", "OverridingDef:=", True, "Value:=", self._props["RefNode"]], - ] - - # Modify Termination - if self._props["term"] and self._props["TerminationData"]: - arg2 = [ - "NAME:NewProps", - ["NAME:term", "PropType:=", "TextProp", "OverridingDef:=", True, "Value:=", self._props["term"]], - ] - - for prop in self._props: - skip1 = (prop == "rz" or prop == "iz") and isinstance(self._props["term"], str) - skip2 = prop == "EnabledPorts" or prop == "EnabledMultipleComponents" or prop == "EnabledAnalyses" - skip3 = prop == "SymbolType" - skip4 = prop == "TerminationData" and not isinstance(self._props["term"], str) - if not skip1 and not skip2 and not skip3 and not skip4 and self._props[prop] is not None: - command = ["NAME:" + prop, "Value:=", self._props[prop]] - arg1.append(command) - - arg1 = [["NAME:Properties", arg2, arg1]] - self._app.odesign.ChangePortProperty(self.name, arg0, arg1) - - for source in self._app.sources: - self._app.sources[source].update() - return True - - @pyaedt_function_handler() - def delete(self): - """Delete the port in AEDT. - - Returns - ------- - bool - ``True`` when successful, ``False`` when failed. - - """ - self._app.modeler._odesign.DeletePort(self.name) - for k, v in self._circuit_components.components.items(): - if v.name == self.name: - del self._circuit_components.components[k] - break - return True - - @property - def _logger(self): - """Logger.""" - return self._app.logger diff --git a/tests/system/general/test_21_Circuit.py b/tests/system/general/test_21_Circuit.py index ad96d4ba58f..46c7ddbb955 100644 --- a/tests/system/general/test_21_Circuit.py +++ b/tests/system/general/test_21_Circuit.py @@ -725,7 +725,7 @@ def test_41_assign_excitations(self, aedtapp): port.angle = 90.0 port.location = ["100mil", "200mil"] - assert port.location == ["100mil", "200mil"] + assert port.location == [100, 200] port.mirror = True assert port.mirror port.name = "Port3" From 5c3672b4a08fc3b3a60da2de4b817781ef2d02f7 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Mon, 14 Jul 2025 14:48:17 +0200 Subject: [PATCH 9/9] Fix _app --- src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py b/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py index be320c38927..482ebeaaca5 100644 --- a/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py +++ b/src/ansys/aedt/core/modeler/circuits/object_3d_circuit.py @@ -1647,7 +1647,7 @@ def update(self): self._circuit_components._app.odesign.ChangePortProperty(self.name, arg0, arg1) for source in self._circuit_components._app.sources: - self._app.sources[source].update() + self._circuit_components._app.sources[source].update() return True @pyaedt_function_handler()