From 58a68ec3364fac116f116740c914c56245d16efd Mon Sep 17 00:00:00 2001 From: anur7 Date: Tue, 5 Nov 2024 16:43:12 +0100 Subject: [PATCH 01/14] FEAT: added missing input parameters (issue #4779) --- src/ansys/aedt/core/maxwell.py | 86 +++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/src/ansys/aedt/core/maxwell.py b/src/ansys/aedt/core/maxwell.py index d2d9fac129d..54b461f28f4 100644 --- a/src/ansys/aedt/core/maxwell.py +++ b/src/ansys/aedt/core/maxwell.py @@ -1810,33 +1810,69 @@ def assign_radiation(self, assignment, radiation=None): @pyaedt_function_handler(objects="assignment") def enable_harmonic_force( self, - assignment, + objects, force_type=0, window_function="Rectangular", - use_number_of_last_cycles=True, - last_cycles_number=1, + use_number_of_cycles_from_stop_time=True, + number_of_cycles_from_stop_time=1, + start_time="0s", + use_number_of_cycles_for_stop_time=True, + number_of_cycles_for_stop_time=1, + stop_time="0.01s", + output_frequency_range_type="Use All", + output_frequency_range_start="0Hz", + number_of_output_frequencies=10, + output_frequency_range_stop="1000Hz", calculate_force="Harmonic", + enable_inverter_feedback=False, ): """Enable the harmonic force calculation for the transient analysis. Parameters ---------- - assignment : list - List of object names for force calculations. + objects : list + Defines a list of object names for force calculations, for example: + ["arc_01","arc_02","arc_03"] force_type : int, optional - Force type. Options are ``0`` for objects, ``1`` for surface, and ``2`` for volumetric. + Force Type. ``0`` for Object Based, ``1`` for Element Based (Surface), ``2`` for + Element Based (Volumetric). window_function : str, optional Windowing function. Default is ``"Rectangular"``. Available options are: ``"Rectangular"``, ``"Tri"``, ``"Van Hann"``, ``"Hamming"``, ``"Blackman"``, ``"Lanczos"``, ``"Welch"``. - use_number_of_last_cycles : bool, optional - Use number of last cycles for force calculations. Default is ``True``. - last_cycles_number : int, optional - Defines the number of cycles to compute if `use_number_of_last_cycle` is ``True``. - calculate_force : sr, optional + use_number_of_cycles_from_stop_time : bool, optional + If True, the harmonic force will be computed using the transient force during the + defined number of cycles backwards from stop time. + If False, the defined time range will be used. Default is ``True``. + number_of_cycles_from_stop_time : int, optional + Defines the number of cycles from stop time for harmonic force computation, + if `use_number_of_cycles_from_stop_time` is ``True``. + start_time : str, optional + Defines the time range start time for harmonic force computation, + if `use_number_of_cycles_from_stop_time` is ``False``. + use_number_of_cycles_for_stop_time : bool, optional + If True, the time range stop time is defined using the number of cycles. + The harmonic force will be computed using the defined number of cycles forward from the start time. + If False, the time range stop time is defined using the stop time. + The harmonic force will be computed using the transient force between the start time and the stop time. + Default is ``True``. + number_of_cycles_for_stop_time + Defines the time range for harmonic force computation using the number of cycles, + if `use_number_of_cycles_for_stop_time` is ``True``. + stop_time : str, optional + Defines the time range stop time for harmonic force computation, + if `use_number_of_cycles_for_stop_time` is ``False``. + output_frequency_range_type : str, optional + Defines the type of the output frequency range. Default is ``"Use All"``. + Available options are: ``"Use All"``, ``"Use Number"``, ``"Use Range"``. + output_frequency_range_start : str, optional + output_frequency_range_number : int, optional + Number of frequencies to output. + output_frequency_range_stop : str, optional + calculate_force : str, optional How to calculate force. The default is ``"Harmonic"``. - Options are ``"Harmonic"`` and ``"Transient"``. - + Options are ``"Harmonic"``, ``"Transient"`` and ``"Harmonic and Transient"`` + enable_inverter_feedback : bool, optional Returns ------- @@ -1851,27 +1887,35 @@ def enable_harmonic_force( self.odesign.EnableHarmonicForceCalculation( [ "EnabledObjects:=", - assignment, + objects, "ForceType:=", force_type, "WindowFunctionType:=", window_function, "UseNumberOfLastCycles:=", - use_number_of_last_cycles, + use_number_of_cycles_from_stop_time, "NumberOfLastCycles:=", - last_cycles_number, + number_of_cycles_from_stop_time, "StartTime:=", - "0s", + start_time, "UseNumberOfCyclesForStopTime:=", - True, + use_number_of_cycles_for_stop_time, "NumberOfCyclesForStopTime:=", - 1, + number_of_cycles_for_stop_time, "StopTime:=", - "0.01s", + stop_time, "OutputFreqRangeType:=", - "Use All", + output_frequency_range_type, + "OutputFreqRangeStart:=", + output_frequency_range_start, + "OutputFreqRangeNum:=", + str(number_of_output_frequencies), + "OutputFreqRangeStop:=", + output_frequency_range_stop, "CaculateForceType:=", calculate_force + " Force", + "EnableInverterFeedback:=", + enable_inverter_feedback, ] ) return True From bf8c9e98aa93fb422449d2b40a6948a67249b2ec Mon Sep 17 00:00:00 2001 From: anur7 Date: Mon, 18 Nov 2024 12:24:27 +0100 Subject: [PATCH 02/14] FEAT: implemented method for Eddy Current solver (issue #4779) --- src/ansys/aedt/core/maxwell.py | 122 ++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 41 deletions(-) diff --git a/src/ansys/aedt/core/maxwell.py b/src/ansys/aedt/core/maxwell.py index 54b461f28f4..063a36d510a 100644 --- a/src/ansys/aedt/core/maxwell.py +++ b/src/ansys/aedt/core/maxwell.py @@ -1810,7 +1810,10 @@ def assign_radiation(self, assignment, radiation=None): @pyaedt_function_handler(objects="assignment") def enable_harmonic_force( self, - objects, + assignment, + coordinate_system="Global", + axis=2, + is_positive=True, force_type=0, window_function="Rectangular", use_number_of_cycles_from_stop_time=True, @@ -1821,18 +1824,24 @@ def enable_harmonic_force( stop_time="0.01s", output_frequency_range_type="Use All", output_frequency_range_start="0Hz", - number_of_output_frequencies=10, output_frequency_range_stop="1000Hz", + number_of_output_frequencies=10, calculate_force="Harmonic", enable_inverter_feedback=False, + switching_frequency="4000Hz", + maximum_frequency="8000Hz", ): """Enable the harmonic force calculation for the transient analysis. Parameters ---------- - objects : list + assignment : list Defines a list of object names for force calculations, for example: ["arc_01","arc_02","arc_03"] + coordinate_system: str, optional + axis : int, optional + ``0`` for X-axis, ``1`` for Y-axis, ``2`` for Z-axis + is_positive : bool, optional force_type : int, optional Force Type. ``0`` for Object Based, ``1`` for Element Based (Surface), ``2`` for Element Based (Volumetric). @@ -1866,13 +1875,15 @@ def enable_harmonic_force( Defines the type of the output frequency range. Default is ``"Use All"``. Available options are: ``"Use All"``, ``"Use Number"``, ``"Use Range"``. output_frequency_range_start : str, optional + output_frequency_range_stop : str, optional output_frequency_range_number : int, optional Number of frequencies to output. - output_frequency_range_stop : str, optional calculate_force : str, optional How to calculate force. The default is ``"Harmonic"``. Options are ``"Harmonic"``, ``"Transient"`` and ``"Harmonic and Transient"`` enable_inverter_feedback : bool, optional + switching_frequency: str, optional + maximum_frequency: str, optional Returns ------- @@ -1880,45 +1891,74 @@ def enable_harmonic_force( ``True`` when successful, ``False`` when failed. """ - if self.solution_type != "Transient": - self.logger.error("This methods work only with Maxwell Transient Analysis.") + if self.solution_type not in [ + "EddyCurrent", + "Transient", + "TransientXY", + "TransientZ", + "TransientAPhiFormulation", + ]: + self.logger.error("This method is not valid for this solution type.") return False assignment = self.modeler.convert_to_selections(assignment, True) - self.odesign.EnableHarmonicForceCalculation( - [ - "EnabledObjects:=", - objects, - "ForceType:=", - force_type, - "WindowFunctionType:=", - window_function, - "UseNumberOfLastCycles:=", - use_number_of_cycles_from_stop_time, - "NumberOfLastCycles:=", - number_of_cycles_from_stop_time, - "StartTime:=", - start_time, - "UseNumberOfCyclesForStopTime:=", - use_number_of_cycles_for_stop_time, - "NumberOfCyclesForStopTime:=", - number_of_cycles_for_stop_time, - "StopTime:=", - stop_time, - "OutputFreqRangeType:=", - output_frequency_range_type, - "OutputFreqRangeStart:=", - output_frequency_range_start, - "OutputFreqRangeNum:=", - str(number_of_output_frequencies), - "OutputFreqRangeStop:=", - output_frequency_range_stop, - "CaculateForceType:=", - calculate_force + " Force", - "EnableInverterFeedback:=", - enable_inverter_feedback, - ] - ) - return True + if self.solution_type == "EddyCurrent": + if self.solution_type in ["EddyCurrentXY", "EddyCurrentZ"]: + axis = 2 + else: + axis + self.odesign.EnableHarmonicForceCalculation( + [ + "EnabledObjects:=", + assignment, + "Coordinate System:=", + coordinate_system, + "Axis:=", + axis, + "Is Positive:=", + is_positive, + ] + ) + return True + elif self.solution_type in ["Transient", "TransientXY", "TransientZ"]: + self.odesign.EnableHarmonicForceCalculation( + [ + "EnabledObjects:=", + assignment, + "ForceType:=", + force_type, + "WindowFunctionType:=", + window_function, + "UseNumberOfLastCycles:=", + use_number_of_cycles_from_stop_time, + "NumberOfLastCycles:=", + number_of_cycles_from_stop_time, + "StartTime:=", + start_time, + "UseNumberOfCyclesForStopTime:=", + use_number_of_cycles_for_stop_time, + "NumberOfCyclesForStopTime:=", + number_of_cycles_for_stop_time, + "StopTime:=", + stop_time, + "OutputFreqRangeType:=", + output_frequency_range_type, + "OutputFreqRangeStart:=", + output_frequency_range_start, + "OutputFreqRangeStop:=", + output_frequency_range_stop, + "OutputFreqRangeNum:=", + str(number_of_output_frequencies), + "CaculateForceType:=", + calculate_force + " Force", + "EnableInverterFeedback:=", + enable_inverter_feedback, + "SwitchingFrequency:=", + switching_frequency, + "MaximumFrequency:=", + maximum_frequency, + ] + ) + return True @pyaedt_function_handler(layout_component_name="assignment") def enable_harmonic_force_on_layout_component( From 3b32bd931be9850952a0f83b26c3efb288351bd1 Mon Sep 17 00:00:00 2001 From: anur7 Date: Fri, 22 Nov 2024 14:25:36 +0100 Subject: [PATCH 03/14] FEAT:minor improvement --- src/ansys/aedt/core/maxwell.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/ansys/aedt/core/maxwell.py b/src/ansys/aedt/core/maxwell.py index 063a36d510a..c36240b54cc 100644 --- a/src/ansys/aedt/core/maxwell.py +++ b/src/ansys/aedt/core/maxwell.py @@ -50,7 +50,7 @@ class Maxwell(object): def __init__(self): - pass + self.solution_type = None @property def symmetry_multiplier(self): @@ -1826,7 +1826,7 @@ def enable_harmonic_force( output_frequency_range_start="0Hz", output_frequency_range_stop="1000Hz", number_of_output_frequencies=10, - calculate_force="Harmonic", + calculate_force=0, enable_inverter_feedback=False, switching_frequency="4000Hz", maximum_frequency="8000Hz", @@ -1878,9 +1878,9 @@ def enable_harmonic_force( output_frequency_range_stop : str, optional output_frequency_range_number : int, optional Number of frequencies to output. - calculate_force : str, optional - How to calculate force. The default is ``"Harmonic"``. - Options are ``"Harmonic"``, ``"Transient"`` and ``"Harmonic and Transient"`` + calculate_force : int, optional + How to calculate force: ``0`` for ``"Harmonic"``, ``1`` for ``"Transient"``, + and ``2`` for``"Harmonic and Transient"``. The default is ``0``. enable_inverter_feedback : bool, optional switching_frequency: str, optional maximum_frequency: str, optional @@ -1900,12 +1900,9 @@ def enable_harmonic_force( ]: self.logger.error("This method is not valid for this solution type.") return False - assignment = self.modeler.convert_to_selections(assignment, True) if self.solution_type == "EddyCurrent": - if self.solution_type in ["EddyCurrentXY", "EddyCurrentZ"]: - axis = 2 - else: - axis + if self.is3d is False and axis != 2: + self.logger.warning("For 2D EddyCurrent solver only Z-axis is available.") self.odesign.EnableHarmonicForceCalculation( [ "EnabledObjects:=", @@ -1920,6 +1917,19 @@ def enable_harmonic_force( ) return True elif self.solution_type in ["Transient", "TransientXY", "TransientZ"]: + if calculate_force == 0: + calculate_force = "Harmonic" + if calculate_force == 1: + calculate_force = "Transient" + if calculate_force == 2: + calculate_force = "Harmonic and Transient" + if self.solution_type == "TransientZ" and force_type == 0 and calculate_force == 1: + calculate_force = 0 + self.logger.warning( + """Object-Based Transient Force calculation is not supported + for non-rotational transient solutions. Only Harmonic Force will + be calculated.""" + ) self.odesign.EnableHarmonicForceCalculation( [ "EnabledObjects:=", From 598a53bbbb8542f8af9e985fa9df43bb495d5c1e Mon Sep 17 00:00:00 2001 From: anur7 Date: Thu, 28 Nov 2024 13:32:24 +0100 Subject: [PATCH 04/14] FEAT:improvement for transient solver --- src/ansys/aedt/core/maxwell.py | 39 ++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/ansys/aedt/core/maxwell.py b/src/ansys/aedt/core/maxwell.py index 71c6e6db940..1860497874d 100644 --- a/src/ansys/aedt/core/maxwell.py +++ b/src/ansys/aedt/core/maxwell.py @@ -1833,6 +1833,8 @@ def enable_harmonic_force( ): """Enable the harmonic force calculation for the transient analysis. + Available for Maxwell Eddy Current and Transient designs. + Parameters ---------- assignment : list @@ -1855,7 +1857,8 @@ def enable_harmonic_force( If False, the defined time range will be used. Default is ``True``. number_of_cycles_from_stop_time : int, optional Defines the number of cycles from stop time for harmonic force computation, - if `use_number_of_cycles_from_stop_time` is ``True``. + if `use_number_of_cycles_from_stop_time` is ``True``. For TransientZ and TransientAphiFormulation, + it is equal to 1. start_time : str, optional Defines the time range start time for harmonic force computation, if `use_number_of_cycles_from_stop_time` is ``False``. @@ -1867,7 +1870,8 @@ def enable_harmonic_force( Default is ``True``. number_of_cycles_for_stop_time Defines the time range for harmonic force computation using the number of cycles, - if `use_number_of_cycles_for_stop_time` is ``True``. + if `use_number_of_cycles_for_stop_time` is ``True``. For TransientZ and TransientAphiFormulation, + it is equal to 1. stop_time : str, optional Defines the time range stop time for harmonic force computation, if `use_number_of_cycles_for_stop_time` is ``False``. @@ -1894,14 +1898,13 @@ def enable_harmonic_force( if self.solution_type not in [ "EddyCurrent", "Transient", - "TransientXY", - "TransientZ", "TransientAPhiFormulation", ]: - self.logger.error("This method is not valid for this solution type.") + self.logger.error(f"This method is not valid for {self.solution_type} solvers.") return False if self.solution_type == "EddyCurrent": - if self.is3d is False and axis != 2: + if not self.is3d and axis != 2: + axis = 2 self.logger.warning("For 2D EddyCurrent solver only Z-axis is available.") self.odesign.EnableHarmonicForceCalculation( [ @@ -1916,20 +1919,28 @@ def enable_harmonic_force( ] ) return True - elif self.solution_type in ["Transient", "TransientXY", "TransientZ"]: + elif self.solution_type == "Transient": if calculate_force == 0: calculate_force = "Harmonic" if calculate_force == 1: calculate_force = "Transient" if calculate_force == 2: calculate_force = "Harmonic and Transient" - if self.solution_type == "TransientZ" and force_type == 0 and calculate_force == 1: - calculate_force = 0 - self.logger.warning( - """Object-Based Transient Force calculation is not supported - for non-rotational transient solutions. Only Harmonic Force will - be calculated.""" - ) + if self.geometry_mode == "about Z" or self.solution_type == "TransientAphiFormulation": + if force_type == 0 and calculate_force == "Transient": + calculate_force = "Harmonic" + self.logger.warning( + "Object-Based Transient Force calculation is not supported for " + "non-rotational transient solutions. Only Harmonic Force will be calculated." + ) + if self.geometry_mode == "about Z" or self.solution_type == "TransientAphiFormulation": + if number_of_cycles_from_stop_time != 1 or number_of_cycles_for_stop_time != 1: + self.logger.info( + " ``number_of_cycles_from_stop_time´´ and ``number_of_cycles_for_stop_time´´" + "are equal to 1 for TransientZ and TransientAphiFormulation." + ) + number_of_cycles_from_stop_time = 1 + number_of_cycles_for_stop_time = 1 self.odesign.EnableHarmonicForceCalculation( [ "EnabledObjects:=", From 6dbd081921707103d442b5691dda8a8b83d19998 Mon Sep 17 00:00:00 2001 From: anur7 Date: Thu, 28 Nov 2024 17:19:58 +0100 Subject: [PATCH 05/14] FEAT: some docstring improvements --- src/ansys/aedt/core/maxwell.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ansys/aedt/core/maxwell.py b/src/ansys/aedt/core/maxwell.py index 1860497874d..f3d77732cc0 100644 --- a/src/ansys/aedt/core/maxwell.py +++ b/src/ansys/aedt/core/maxwell.py @@ -1841,9 +1841,14 @@ def enable_harmonic_force( Defines a list of object names for force calculations, for example: ["arc_01","arc_02","arc_03"] coordinate_system: str, optional + Defines the coordinate system. The default is ``Global``. axis : int, optional - ``0`` for X-axis, ``1`` for Y-axis, ``2`` for Z-axis + Defines the rotation axis used to generate full model for a partial model + of electric machine.``0`` for X-axis, ``1`` for Y-axis, ``2`` for Z-axis. + The default is ``2``. is_positive : bool, optional + Defines the rotation axis direction: ``True`` if ``Positive`` and ``False`` if ``Negative``. + The default is ``True``. force_type : int, optional Force Type. ``0`` for Object Based, ``1`` for Element Based (Surface), ``2`` for Element Based (Volumetric). From fe0157dd452db41f0560e9f49f1d90cbb15ccb29 Mon Sep 17 00:00:00 2001 From: anur7 Date: Mon, 2 Dec 2024 16:34:19 +0100 Subject: [PATCH 06/14] FEAT: some implementation improvements --- src/ansys/aedt/core/maxwell.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/ansys/aedt/core/maxwell.py b/src/ansys/aedt/core/maxwell.py index f3d77732cc0..4b61b88accb 100644 --- a/src/ansys/aedt/core/maxwell.py +++ b/src/ansys/aedt/core/maxwell.py @@ -1924,25 +1924,38 @@ def enable_harmonic_force( ] ) return True - elif self.solution_type == "Transient": + elif self.solution_type in ["Transient", "TransientAPhiFormulation"]: if calculate_force == 0: calculate_force = "Harmonic" if calculate_force == 1: calculate_force = "Transient" if calculate_force == 2: calculate_force = "Harmonic and Transient" - if self.geometry_mode == "about Z" or self.solution_type == "TransientAphiFormulation": + if not self.is3d and self.geometry_mode == "about Z": if force_type == 0 and calculate_force == "Transient": calculate_force = "Harmonic" self.logger.warning( "Object-Based Transient Force calculation is not supported for " "non-rotational transient solutions. Only Harmonic Force will be calculated." ) - if self.geometry_mode == "about Z" or self.solution_type == "TransientAphiFormulation": if number_of_cycles_from_stop_time != 1 or number_of_cycles_for_stop_time != 1: self.logger.info( " ``number_of_cycles_from_stop_time´´ and ``number_of_cycles_for_stop_time´´" - "are equal to 1 for TransientZ and TransientAphiFormulation." + "are equal to 1 for TransientZ." + ) + number_of_cycles_from_stop_time = 1 + number_of_cycles_for_stop_time = 1 + if self.solution_type == "TransientAPhiFormulation": + if force_type == 0 and calculate_force == "Transient": + calculate_force = "Harmonic" + self.logger.warning( + "Object-Based Transient Force calculation is not supported for " + "non-rotational transient solutions. Only Harmonic Force will be calculated." + ) + if number_of_cycles_from_stop_time != 1 or number_of_cycles_for_stop_time != 1: + self.logger.info( + " ``number_of_cycles_from_stop_time´´ and ``number_of_cycles_for_stop_time´´" + "are equal to 1 for TransientAphiFormulation." ) number_of_cycles_from_stop_time = 1 number_of_cycles_for_stop_time = 1 From 1e93929badb953d654452989b39524e513aba099 Mon Sep 17 00:00:00 2001 From: anur7 Date: Wed, 4 Dec 2024 17:53:44 +0100 Subject: [PATCH 07/14] FEAT:minor improvement --- src/ansys/aedt/core/maxwell.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/ansys/aedt/core/maxwell.py b/src/ansys/aedt/core/maxwell.py index 4b61b88accb..7dc423a7cb0 100644 --- a/src/ansys/aedt/core/maxwell.py +++ b/src/ansys/aedt/core/maxwell.py @@ -1815,6 +1815,7 @@ def enable_harmonic_force( axis=2, is_positive=True, force_type=0, + calculate_force=0, window_function="Rectangular", use_number_of_cycles_from_stop_time=True, number_of_cycles_from_stop_time=1, @@ -1826,7 +1827,6 @@ def enable_harmonic_force( output_frequency_range_start="0Hz", output_frequency_range_stop="1000Hz", number_of_output_frequencies=10, - calculate_force=0, enable_inverter_feedback=False, switching_frequency="4000Hz", maximum_frequency="8000Hz", @@ -1873,7 +1873,8 @@ def enable_harmonic_force( If False, the time range stop time is defined using the stop time. The harmonic force will be computed using the transient force between the start time and the stop time. Default is ``True``. - number_of_cycles_for_stop_time + For TransientZ and TransientAphiFormulation, it is ``False``. + number_of_cycles_for_stop_time: int, optional Defines the time range for harmonic force computation using the number of cycles, if `use_number_of_cycles_for_stop_time` is ``True``. For TransientZ and TransientAphiFormulation, it is equal to 1. @@ -1885,7 +1886,7 @@ def enable_harmonic_force( Available options are: ``"Use All"``, ``"Use Number"``, ``"Use Range"``. output_frequency_range_start : str, optional output_frequency_range_stop : str, optional - output_frequency_range_number : int, optional + number_of_output_frequencies : int, optional Number of frequencies to output. calculate_force : int, optional How to calculate force: ``0`` for ``"Harmonic"``, ``1`` for ``"Transient"``, @@ -1938,13 +1939,13 @@ def enable_harmonic_force( "Object-Based Transient Force calculation is not supported for " "non-rotational transient solutions. Only Harmonic Force will be calculated." ) - if number_of_cycles_from_stop_time != 1 or number_of_cycles_for_stop_time != 1: - self.logger.info( + if use_number_of_cycles_from_stop_time == True or use_number_of_cycles_for_stop_time == True: + self.logger.warning( " ``number_of_cycles_from_stop_time´´ and ``number_of_cycles_for_stop_time´´" - "are equal to 1 for TransientZ." + "are not available for TransientZ." ) - number_of_cycles_from_stop_time = 1 - number_of_cycles_for_stop_time = 1 + use_number_of_cycles_from_stop_time = False + use_number_of_cycles_for_stop_time = False if self.solution_type == "TransientAPhiFormulation": if force_type == 0 and calculate_force == "Transient": calculate_force = "Harmonic" @@ -1952,13 +1953,13 @@ def enable_harmonic_force( "Object-Based Transient Force calculation is not supported for " "non-rotational transient solutions. Only Harmonic Force will be calculated." ) - if number_of_cycles_from_stop_time != 1 or number_of_cycles_for_stop_time != 1: - self.logger.info( + if use_number_of_cycles_from_stop_time == True or use_number_of_cycles_for_stop_time == True: + self.logger.warning( " ``number_of_cycles_from_stop_time´´ and ``number_of_cycles_for_stop_time´´" - "are equal to 1 for TransientAphiFormulation." + "are not available for TransientAphiFormulation." ) - number_of_cycles_from_stop_time = 1 - number_of_cycles_for_stop_time = 1 + use_number_of_cycles_from_stop_time = False + use_number_of_cycles_for_stop_time = False self.odesign.EnableHarmonicForceCalculation( [ "EnabledObjects:=", From cd0ad85436a293041034a8d1450ecfdfb1dd3bac Mon Sep 17 00:00:00 2001 From: anur7 Date: Thu, 5 Dec 2024 17:55:41 +0100 Subject: [PATCH 08/14] FEAT:minor improvement --- src/ansys/aedt/core/maxwell.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/ansys/aedt/core/maxwell.py b/src/ansys/aedt/core/maxwell.py index 7dc423a7cb0..da68dde2dd1 100644 --- a/src/ansys/aedt/core/maxwell.py +++ b/src/ansys/aedt/core/maxwell.py @@ -1823,7 +1823,7 @@ def enable_harmonic_force( use_number_of_cycles_for_stop_time=True, number_of_cycles_for_stop_time=1, stop_time="0.01s", - output_frequency_range_type="Use All", + output_frequency_range_type=0, output_frequency_range_start="0Hz", output_frequency_range_stop="1000Hz", number_of_output_frequencies=10, @@ -1881,9 +1881,10 @@ def enable_harmonic_force( stop_time : str, optional Defines the time range stop time for harmonic force computation, if `use_number_of_cycles_for_stop_time` is ``False``. - output_frequency_range_type : str, optional - Defines the type of the output frequency range. Default is ``"Use All"``. - Available options are: ``"Use All"``, ``"Use Number"``, ``"Use Range"``. + output_frequency_range_type : int, optional + Defines the type of the output frequency range. ``0`` for ``"Use All"``, + ``1`` for ``"Use Range"``, and ``2`` for ``"Use Number"``. + The default is ``0``. output_frequency_range_start : str, optional output_frequency_range_stop : str, optional number_of_output_frequencies : int, optional @@ -1932,6 +1933,12 @@ def enable_harmonic_force( calculate_force = "Transient" if calculate_force == 2: calculate_force = "Harmonic and Transient" + if output_frequency_range_type == 0: + output_frequency_range_type = "Use All" + if output_frequency_range_type == 1: + output_frequency_range_type = "Use Range" + if output_frequency_range_type == 2: + output_frequency_range_type = "Use Number" if not self.is3d and self.geometry_mode == "about Z": if force_type == 0 and calculate_force == "Transient": calculate_force = "Harmonic" From 3d074540d4fed3ab16dbde8a8456451d24f69dd3 Mon Sep 17 00:00:00 2001 From: anur7 Date: Mon, 9 Dec 2024 13:25:15 +0100 Subject: [PATCH 09/14] doc improved, added example --- src/ansys/aedt/core/maxwell.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/ansys/aedt/core/maxwell.py b/src/ansys/aedt/core/maxwell.py index da68dde2dd1..68be94e8520 100644 --- a/src/ansys/aedt/core/maxwell.py +++ b/src/ansys/aedt/core/maxwell.py @@ -1860,10 +1860,10 @@ def enable_harmonic_force( If True, the harmonic force will be computed using the transient force during the defined number of cycles backwards from stop time. If False, the defined time range will be used. Default is ``True``. + For ``"TransientZ"`` and ``"TransientAphiFormulation"`` it is ``False``. number_of_cycles_from_stop_time : int, optional Defines the number of cycles from stop time for harmonic force computation, - if `use_number_of_cycles_from_stop_time` is ``True``. For TransientZ and TransientAphiFormulation, - it is equal to 1. + if `use_number_of_cycles_from_stop_time` is ``True``. start_time : str, optional Defines the time range start time for harmonic force computation, if `use_number_of_cycles_from_stop_time` is ``False``. @@ -1873,11 +1873,10 @@ def enable_harmonic_force( If False, the time range stop time is defined using the stop time. The harmonic force will be computed using the transient force between the start time and the stop time. Default is ``True``. - For TransientZ and TransientAphiFormulation, it is ``False``. + For ``"TransientZ"`` and ``"TransientAphiFormulation"`` it is ``False``. number_of_cycles_for_stop_time: int, optional Defines the time range for harmonic force computation using the number of cycles, - if `use_number_of_cycles_for_stop_time` is ``True``. For TransientZ and TransientAphiFormulation, - it is equal to 1. + if `use_number_of_cycles_for_stop_time` is ``True``. stop_time : str, optional Defines the time range stop time for harmonic force computation, if `use_number_of_cycles_for_stop_time` is ``False``. @@ -1886,21 +1885,42 @@ def enable_harmonic_force( ``1`` for ``"Use Range"``, and ``2`` for ``"Use Number"``. The default is ``0``. output_frequency_range_start : str, optional + The start frequency of calculated harmonic force components. output_frequency_range_stop : str, optional + The end frequency of calculated harmonic force components. number_of_output_frequencies : int, optional Number of frequencies to output. calculate_force : int, optional How to calculate force: ``0`` for ``"Harmonic"``, ``1`` for ``"Transient"``, and ``2`` for``"Harmonic and Transient"``. The default is ``0``. enable_inverter_feedback : bool, optional + If ``True`` it enables inverter feedback. The default is ``False``. switching_frequency: str, optional + The switching frequency is available if `enable_inverter_feedback´ is ``True``. + The default value is ``"4000Hz"``. maximum_frequency: str, optional + The maximum frequency is available, if `enable_inverter_feedback´ is ``True``. + The default value is ``"8000Hz"``. Returns ------- bool ``True`` when successful, ``False`` when failed. + References + ----------- + + >>> odesign.EnableHarmonicForceCalculation + + Examples + --------- + + Enable harmonic force in Maxwell 3D for magnetic transient solver: + + >>> from ansys.aedt.core import Maxwell3d + >>> m3d = Maxwell3d() + >>> m3d.enable_harmonic_force(assignment="Stator",number_of_cycles_from_stop_time=3) + """ if self.solution_type not in [ "EddyCurrent", From e4c83f7489e89bc50d05bbb20c0aab139110d08b Mon Sep 17 00:00:00 2001 From: anur7 Date: Wed, 11 Dec 2024 17:56:33 +0100 Subject: [PATCH 10/14] improved implementation and UT --- src/ansys/aedt/core/maxwell.py | 36 +++++-------------------- tests/system/solvers/test_00_analyze.py | 10 ++++--- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/src/ansys/aedt/core/maxwell.py b/src/ansys/aedt/core/maxwell.py index c59ce630f41..5721e0d777a 100644 --- a/src/ansys/aedt/core/maxwell.py +++ b/src/ansys/aedt/core/maxwell.py @@ -1900,7 +1900,7 @@ def enable_harmonic_force( The switching frequency is available if `enable_inverter_feedback´ is ``True``. The default value is ``"4000Hz"``. maximum_frequency: str, optional - The maximum frequency is available, if `enable_inverter_feedback´ is ``True``. + The maximum frequency is available if `enable_inverter_feedback´ is ``True``. The default value is ``"8000Hz"``. Returns @@ -1948,46 +1948,24 @@ def enable_harmonic_force( ) return True elif self.solution_type in ["Transient", "TransientAPhiFormulation"]: - if calculate_force == 0: - calculate_force = "Harmonic" - if calculate_force == 1: - calculate_force = "Transient" - if calculate_force == 2: - calculate_force = "Harmonic and Transient" - if output_frequency_range_type == 0: - output_frequency_range_type = "Use All" - if output_frequency_range_type == 1: - output_frequency_range_type = "Use Range" - if output_frequency_range_type == 2: - output_frequency_range_type = "Use Number" - if not self.is3d and self.geometry_mode == "about Z": + force = ["Harmonic", "Transient", "Harmonic and Transient"] + calculate_force = force[calculate_force] + range_type = ["Use All", "Use Range", "Use Number"] + output_frequency_range_type = range_type[output_frequency_range_type] + if not self.is3d and self.geometry_mode == "about Z" or self.solution_type == "TransientAPhiFormulation": if force_type == 0 and calculate_force == "Transient": calculate_force = "Harmonic" self.logger.warning( "Object-Based Transient Force calculation is not supported for " "non-rotational transient solutions. Only Harmonic Force will be calculated." ) - if use_number_of_cycles_from_stop_time == True or use_number_of_cycles_for_stop_time == True: + if use_number_of_cycles_from_stop_time or use_number_of_cycles_for_stop_time: self.logger.warning( " ``number_of_cycles_from_stop_time´´ and ``number_of_cycles_for_stop_time´´" "are not available for TransientZ." ) use_number_of_cycles_from_stop_time = False use_number_of_cycles_for_stop_time = False - if self.solution_type == "TransientAPhiFormulation": - if force_type == 0 and calculate_force == "Transient": - calculate_force = "Harmonic" - self.logger.warning( - "Object-Based Transient Force calculation is not supported for " - "non-rotational transient solutions. Only Harmonic Force will be calculated." - ) - if use_number_of_cycles_from_stop_time == True or use_number_of_cycles_for_stop_time == True: - self.logger.warning( - " ``number_of_cycles_from_stop_time´´ and ``number_of_cycles_for_stop_time´´" - "are not available for TransientAphiFormulation." - ) - use_number_of_cycles_from_stop_time = False - use_number_of_cycles_for_stop_time = False self.odesign.EnableHarmonicForceCalculation( [ "EnabledObjects:=", diff --git a/tests/system/solvers/test_00_analyze.py b/tests/system/solvers/test_00_analyze.py index 346ac718ce0..815e08cca36 100644 --- a/tests/system/solvers/test_00_analyze.py +++ b/tests/system/solvers/test_00_analyze.py @@ -503,9 +503,9 @@ def test_06_m3d_harmonic_forces(self, m3dtransient): ["Stator"], force_type=2, window_function="Rectangular", - use_number_of_last_cycles=True, - last_cycles_number=3, - calculate_force="Harmonic", + use_number_of_cycles_from_stop_time=True, + number_of_cycles_from_stop_time=3, + calculate_force=0, ) m3dtransient.save_project() m3dtransient.analyze(m3dtransient.active_setup, cores=4, use_auto_settings=False) @@ -513,6 +513,10 @@ def test_06_m3d_harmonic_forces(self, m3dtransient): start_frequency=1, stop_frequency=100, number_of_frequency=None ) assert m3dtransient.export_element_based_harmonic_force(number_of_frequency=5) + m3dtransient.solution_type = m3dtransient.SOLUTIONS.Maxwell3d.EddyCurrent + assert m3dtransient.enable_harmonic_force(assignment=["Stator"]) + m3dtransient.solution_type = m3dtransient.SOLUTIONS.Maxwell3d.Magnetostatic + assert not m3dtransient.enable_harmonic_force(assignment=["Stator"]) def test_07_export_maxwell_fields(self, m3dtransient): m3dtransient.analyze(m3dtransient.active_setup, cores=4, use_auto_settings=False) From c1364de25e75aa877f8a356fe985fa2b65537fb9 Mon Sep 17 00:00:00 2001 From: anur7 Date: Thu, 12 Dec 2024 11:52:37 +0100 Subject: [PATCH 11/14] substituted "self.solution_type = None" with "pass" as it was before --- src/ansys/aedt/core/maxwell.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ansys/aedt/core/maxwell.py b/src/ansys/aedt/core/maxwell.py index a2fab45d134..936f4380ce7 100644 --- a/src/ansys/aedt/core/maxwell.py +++ b/src/ansys/aedt/core/maxwell.py @@ -50,7 +50,7 @@ class Maxwell(object): def __init__(self): - self.solution_type = None + pass @property def symmetry_multiplier(self): From ea81b390cd3ee53950cfaf24bd52524d436783c0 Mon Sep 17 00:00:00 2001 From: Giulia Malinverno Date: Wed, 18 Dec 2024 10:13:02 +0100 Subject: [PATCH 12/14] fix test --- src/ansys/aedt/core/maxwell.py | 15 +++---- tests/system/solvers/test_00_analyze.py | 56 +++++++++++++------------ 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/src/ansys/aedt/core/maxwell.py b/src/ansys/aedt/core/maxwell.py index 22445590dcf..180ca894cc8 100644 --- a/src/ansys/aedt/core/maxwell.py +++ b/src/ansys/aedt/core/maxwell.py @@ -1934,13 +1934,14 @@ def enable_harmonic_force( "Object-Based Transient Force calculation is not supported for " "non-rotational transient solutions. Only Harmonic Force will be calculated." ) - if use_number_of_cycles_from_stop_time or use_number_of_cycles_for_stop_time: - self.logger.warning( - " ``number_of_cycles_from_stop_time´´ and ``number_of_cycles_for_stop_time´´" - "are not available for TransientZ." - ) - use_number_of_cycles_from_stop_time = False - use_number_of_cycles_for_stop_time = False + if not self.is3d and self.geometry_mode == "about Z": + if use_number_of_cycles_from_stop_time or use_number_of_cycles_for_stop_time: + self.logger.warning( + " ``number_of_cycles_from_stop_time´´ and ``number_of_cycles_for_stop_time´´" + "are not available for TransientZ." + ) + use_number_of_cycles_from_stop_time = False + use_number_of_cycles_for_stop_time = False self.odesign.EnableHarmonicForceCalculation( [ "EnabledObjects:=", diff --git a/tests/system/solvers/test_00_analyze.py b/tests/system/solvers/test_00_analyze.py index 815e08cca36..267ea6130a1 100644 --- a/tests/system/solvers/test_00_analyze.py +++ b/tests/system/solvers/test_00_analyze.py @@ -115,12 +115,6 @@ def circuit_com(add_app): return app -@pytest.fixture(scope="class") -def m3dtransient(add_app): - app = add_app(application=Maxwell3d, project_name=transient, subfolder=test_subfolder) - return app - - class TestClass: @pytest.fixture(autouse=True) def init(self, local_scratch, icepak_app, hfss3dl_solve): @@ -498,8 +492,10 @@ def test_05d_circuit_push_excitation_time(self, circuit_app): setup = circuit_app.create_setup(setup_name, setup_type="NexximTransient") assert circuit_app.push_time_excitations(instance="U1", setup=setup_name) - def test_06_m3d_harmonic_forces(self, m3dtransient): - assert m3dtransient.enable_harmonic_force( + def test_06_m3d_harmonic_forces(self, add_app): + aedtapp = add_app(application=Maxwell3d, project_name=transient, subfolder=test_subfolder) + + assert aedtapp.enable_harmonic_force( ["Stator"], force_type=2, window_function="Rectangular", @@ -507,23 +503,28 @@ def test_06_m3d_harmonic_forces(self, m3dtransient): number_of_cycles_from_stop_time=3, calculate_force=0, ) - m3dtransient.save_project() - m3dtransient.analyze(m3dtransient.active_setup, cores=4, use_auto_settings=False) - assert m3dtransient.export_element_based_harmonic_force( + aedtapp.save_project() + aedtapp.analyze(aedtapp.active_setup, cores=4, use_auto_settings=False) + assert aedtapp.export_element_based_harmonic_force( start_frequency=1, stop_frequency=100, number_of_frequency=None ) - assert m3dtransient.export_element_based_harmonic_force(number_of_frequency=5) - m3dtransient.solution_type = m3dtransient.SOLUTIONS.Maxwell3d.EddyCurrent - assert m3dtransient.enable_harmonic_force(assignment=["Stator"]) - m3dtransient.solution_type = m3dtransient.SOLUTIONS.Maxwell3d.Magnetostatic - assert not m3dtransient.enable_harmonic_force(assignment=["Stator"]) + assert aedtapp.export_element_based_harmonic_force(number_of_frequency=5) + aedtapp.solution_type = aedtapp.SOLUTIONS.Maxwell3d.EddyCurrent + assert aedtapp.enable_harmonic_force(assignment=["Stator"]) + aedtapp.solution_type = aedtapp.SOLUTIONS.Maxwell3d.Magnetostatic + assert not aedtapp.enable_harmonic_force(assignment=["Stator"]) + aedtapp.solution_type = aedtapp.SOLUTIONS.Maxwell3d.TransientAPhiFormulation + assert aedtapp.enable_harmonic_force(assignment=["Stator"]) + aedtapp.close_project(aedtapp.project_name) + + def test_07_export_maxwell_fields(self, add_app): + aedtapp = add_app(application=Maxwell3d, project_name=transient, subfolder=test_subfolder) - def test_07_export_maxwell_fields(self, m3dtransient): - m3dtransient.analyze(m3dtransient.active_setup, cores=4, use_auto_settings=False) + aedtapp.analyze(aedtapp.active_setup, cores=4, use_auto_settings=False) fld_file_3 = os.path.join(self.local_scratch.path, "test_fld_3.fld") - assert m3dtransient.post.export_field_file( + assert aedtapp.post.export_field_file( quantity="Mag_B", - solution=m3dtransient.nominal_sweep, + solution=aedtapp.nominal_sweep, variations={}, output_file=fld_file_3, assignment="Coil_A2", @@ -532,23 +533,24 @@ def test_07_export_maxwell_fields(self, m3dtransient): ) assert os.path.exists(fld_file_3) fld_file_4 = os.path.join(self.local_scratch.path, "test_fld_4.fld") - assert not m3dtransient.post.export_field_file( + assert not aedtapp.post.export_field_file( quantity="Mag_B", - solution=m3dtransient.nominal_sweep, - variations=m3dtransient.available_variations.nominal_w_values_dict, + solution=aedtapp.nominal_sweep, + variations=aedtapp.available_variations.nominal_w_values_dict, output_file=fld_file_4, assignment="Coil_A2", objects_type="invalid", ) - setup = m3dtransient.setups[0] - m3dtransient.setups[0].delete() - assert not m3dtransient.post.export_field_file( + setup = aedtapp.setups[0] + aedtapp.setups[0].delete() + assert not aedtapp.post.export_field_file( quantity="Mag_B", variations={}, output_file=fld_file_4, assignment="Coil_A2" ) - new_setup = m3dtransient.create_setup(name=setup.name, setup_type=setup.setuptype) + new_setup = aedtapp.create_setup(name=setup.name, setup_type=setup.setuptype) new_setup.props = setup.props new_setup.update() + aedtapp.close_project(aedtapp.project_name) def test_08_compute_erl(self, circuit_erl): touchstone_file = circuit_erl.export_touchstone() From c636463f026e2deb6d69bb3207d6fc8b114c8fa8 Mon Sep 17 00:00:00 2001 From: anur7 Date: Wed, 19 Feb 2025 10:13:45 +0100 Subject: [PATCH 13/14] improved unit test for enable harmonic force method, made independent test 06 from test 07 --- tests/system/solvers/test_00_analyze.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/tests/system/solvers/test_00_analyze.py b/tests/system/solvers/test_00_analyze.py index ad98fdc1308..d2e71971e55 100644 --- a/tests/system/solvers/test_00_analyze.py +++ b/tests/system/solvers/test_00_analyze.py @@ -142,7 +142,8 @@ def circuit_com(add_app): @pytest.fixture(scope="class") def m3dtransient(add_app): app = add_app(application=Maxwell3d, project_name=transient, subfolder=test_subfolder) - return app + yield app + app.close_project(app.project_name) class TestClass: @@ -506,8 +507,6 @@ def test_05d_circuit_push_excitation_time(self, circuit_app): assert circuit_app.push_time_excitations(instance="U1", setup=setup_name) def test_06_m3d_harmonic_forces(self, m3dtransient): - aedtapp = add_app(application=Maxwell3d, project_name=transient, subfolder=test_subfolder) - assert m3dtransient.enable_harmonic_force( ["Stator"], force_type=2, @@ -516,19 +515,16 @@ def test_06_m3d_harmonic_forces(self, m3dtransient): number_of_cycles_from_stop_time=3, calculate_force=0, ) - aedtapp.save_project() - aedtapp.analyze(aedtapp.active_setup, cores=4, use_auto_settings=False) + m3dtransient.solution_type = m3dtransient.SOLUTIONS.Maxwell3d.EddyCurrent + assert m3dtransient.enable_harmonic_force(assignment=["Stator"]) + m3dtransient.solution_type = m3dtransient.SOLUTIONS.Maxwell3d.TransientAPhiFormulation + assert m3dtransient.enable_harmonic_force(assignment=["Stator"]) + + def test_06_export_element_based_harmonic_force(self, m3dtransient): assert m3dtransient.export_element_based_harmonic_force( start_frequency=1, stop_frequency=100, number_of_frequency=None ) - assert aedtapp.export_element_based_harmonic_force(number_of_frequency=5) - aedtapp.solution_type = aedtapp.SOLUTIONS.Maxwell3d.EddyCurrent - assert aedtapp.enable_harmonic_force(assignment=["Stator"]) - aedtapp.solution_type = aedtapp.SOLUTIONS.Maxwell3d.Magnetostatic - assert not aedtapp.enable_harmonic_force(assignment=["Stator"]) - aedtapp.solution_type = aedtapp.SOLUTIONS.Maxwell3d.TransientAPhiFormulation - assert aedtapp.enable_harmonic_force(assignment=["Stator"]) - aedtapp.close_project(aedtapp.project_name) + assert m3dtransient.export_element_based_harmonic_force(number_of_frequency=5) def test_07_export_maxwell_fields(self, m3dtransient): fld_file_3 = os.path.join(self.local_scratch.path, "test_fld_3.fld") From db146d9baf28c741923608f571211c1f67ec9589 Mon Sep 17 00:00:00 2001 From: anur7 Date: Thu, 20 Feb 2025 14:24:16 +0100 Subject: [PATCH 14/14] unit test --- tests/system/solvers/test_00_analyze.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/solvers/test_00_analyze.py b/tests/system/solvers/test_00_analyze.py index d2e71971e55..da03339ca17 100644 --- a/tests/system/solvers/test_00_analyze.py +++ b/tests/system/solvers/test_00_analyze.py @@ -518,7 +518,7 @@ def test_06_m3d_harmonic_forces(self, m3dtransient): m3dtransient.solution_type = m3dtransient.SOLUTIONS.Maxwell3d.EddyCurrent assert m3dtransient.enable_harmonic_force(assignment=["Stator"]) m3dtransient.solution_type = m3dtransient.SOLUTIONS.Maxwell3d.TransientAPhiFormulation - assert m3dtransient.enable_harmonic_force(assignment=["Stator"]) + assert m3dtransient.enable_harmonic_force(assignment=["Stator"], calculate_force=1) def test_06_export_element_based_harmonic_force(self, m3dtransient): assert m3dtransient.export_element_based_harmonic_force(