From 221238af90e51c0605f516dd36c45abb0cead2ce Mon Sep 17 00:00:00 2001 From: Devin Date: Wed, 24 Apr 2024 11:57:45 +0200 Subject: [PATCH 01/29] Add array_element_phase() method to analysis_hf.py --- pyaedt/application/analysis_hf.py | 61 +++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/pyaedt/application/analysis_hf.py b/pyaedt/application/analysis_hf.py index b6a1e60d455..ee78a89812a 100644 --- a/pyaedt/application/analysis_hf.py +++ b/pyaedt/application/analysis_hf.py @@ -360,3 +360,64 @@ def export_touchstone( impedance=impedance, comments=gamma_impedance_comments, ) + + +def array_element_phase(m, n, theta_name="theta_scan", phi_name="phi_scan"): + """Return an expression for the phase angle in an array excitation. + + Parameters + ---------- + m : int, required + Index of a rectangular antenna array element in the x-direction. + n : int, required + Index of a rectangular antenna array element in the y-direction. + theta_name : str, optional + Post-processing variable name in HFSS to be used to generate + the theta component of the phase angle expression. Default is ``"theta_scan"``. + phi_name : str, optional + Post-processing variable name in HFSS to be used to generate + the phi component of the phase angle expression. Default is ``"phi_scan"`` + + Returns + ------- + str + The phase angle expression that will be imposed on the (m,n) element of + the antenna array. + + """ + # px is the term for the phase variation in the x-direction + # py is the term for the phase variation in the y-direction. + + if n > 0: + add_char = " + " + else: + add_char = " - " + if m == 0: + px = "" + elif m == -1: + px = "-pi*sin(theta_scan)*cos(phi_scan)" + elif m == 1: + px = "pi*sin(theta_scan)*cos(phi_scan)" + else: + px = str(m) + "*pi*sin(theta_scan)*cos(phi_scan)" + if n == 0: + py = "" + elif n == -1 or n == 1: + py = "pi*sin(theta_scan)*sin(phi_scan)" + + else: + py = str(abs(n)) + "*pi*sin(theta_scan)*sin(phi_scan)" + if m == 0: + if n == 0: + return "0" + elif n < 0: + return "-" + py + else: + return py + elif n == 0: + if m == 0: + return "0" + else: + return px + else: + return px + add_char + py From 26095f6974c3c6d8758ccc8c80d4bbbee20db463 Mon Sep 17 00:00:00 2001 From: Devin Date: Fri, 3 May 2024 10:11:07 +0200 Subject: [PATCH 02/29] Update for ant FF post-processing - Add default matplotlib settings to plot.py - Add decorator update_plot_settings to plot.py - Update some docstrings - Correct some errors of return type for plotting methods. --- pyaedt/application/analysis_hf.py | 16 +++---- pyaedt/generic/plot.py | 70 ++++++++++++++++++++++++------- pyaedt/hfss.py | 9 ++-- pyaedt/modules/solutions.py | 65 ++++++++++++++++------------ 4 files changed, 109 insertions(+), 51 deletions(-) diff --git a/pyaedt/application/analysis_hf.py b/pyaedt/application/analysis_hf.py index ee78a89812a..d31756cdee6 100644 --- a/pyaedt/application/analysis_hf.py +++ b/pyaedt/application/analysis_hf.py @@ -362,18 +362,18 @@ def export_touchstone( ) -def array_element_phase(m, n, theta_name="theta_scan", phi_name="phi_scan"): - """Return an expression for the phase angle in an array excitation. +def phase_expression(m, n, theta_name="theta_scan", phi_name="phi_scan"): + """Return an expression for the source phase angle in a rectangular antenna array. Parameters ---------- m : int, required - Index of a rectangular antenna array element in the x-direction. + Index of the rectangular antenna array element in the x-direction. n : int, required - Index of a rectangular antenna array element in the y-direction. + Index of the rectangular antenna array element in the y-direction. theta_name : str, optional - Post-processing variable name in HFSS to be used to generate - the theta component of the phase angle expression. Default is ``"theta_scan"``. + Post-processing variable name in HFSS that is used for the + theta component of the phase angle expression. Default is ``"theta_scan"``. phi_name : str, optional Post-processing variable name in HFSS to be used to generate the phi component of the phase angle expression. Default is ``"phi_scan"`` @@ -381,8 +381,8 @@ def array_element_phase(m, n, theta_name="theta_scan", phi_name="phi_scan"): Returns ------- str - The phase angle expression that will be imposed on the (m,n) element of - the antenna array. + The phase angle expression for the (m,n) source of + the (m,n) antenna array element. """ # px is the term for the phase variation in the x-direction diff --git a/pyaedt/generic/plot.py b/pyaedt/generic/plot.py index 76c8a18b5ad..d1862d836b6 100644 --- a/pyaedt/generic/plot.py +++ b/pyaedt/generic/plot.py @@ -38,13 +38,37 @@ from matplotlib.path import Path import matplotlib.pyplot as plt + rc_params = { + "axes.titlesize": 26, # Use these default settings for Matplotlb axes. + "axes.labelsize": 20, # Apply the settings only in this module. + "xtick.labelsize": 18, + "ytick.labelsize": 18, + } + except ImportError: warnings.warn( "The Matplotlib module is required to run some functionalities of PostProcess.\n" "Install with \n\npip install matplotlib\n\nRequires CPython." ) except Exception: - pass + warnings.warn("Unknown error while attempting to import matplotlib.") + + +# Override default settings for matplotlib +def update_plot_settings(func, *args, **kwargs): + if callable(func): + + def wrapper(*args, **kwargs): + default_rc_params = plt.rcParams.copy() + plt.rcParams.update(rc_params) # Apply new settings. + out = func(*args, **kwargs) + plt.rcParams.update(default_rc_params) + return out + + else: + wrapper = None + raise TypeError("First argument must be callable.") + return wrapper @pyaedt_function_handler() @@ -100,6 +124,7 @@ def is_float(istring): try: return float(istring.strip()) except Exception: + settings.logger.error("Unable to convert '" + isring.strip() + "' to a float.") return 0 @@ -293,8 +318,9 @@ def _parse_streamline(filepath): @pyaedt_function_handler() +@update_plot_settings def plot_polar_chart( - plot_data, size=(2000, 1000), show_legend=True, xlabel="", ylabel="", title="", snapshot_path=None + plot_data, size=(2000, 1000), show_legend=True, xlabel="", ylabel="", title="", snapshot_path=None, show=True ): """Create a matplotlib polar plot based on a list of data. @@ -315,6 +341,14 @@ def plot_polar_chart( Plot Title label. snapshot_path : str Full path to image file if a snapshot is needed. + show : Bool + Set to ``True`` if the figure should be rendered. Default is ``True``, otherwise + figure is not drawn. + + Returns + ------- + :class:`matplotlib.pyplot.Figure` + Matplotlib fig object. """ dpi = 100.0 @@ -344,12 +378,13 @@ def plot_polar_chart( fig.set_size_inches(size[0] / dpi, size[1] / dpi) if snapshot_path: fig.savefig(snapshot_path) - else: + if show: fig.show() return fig @pyaedt_function_handler() +@update_plot_settings def plot_3d_chart(plot_data, size=(2000, 1000), xlabel="", ylabel="", title="", snapshot_path=None): """Create a matplotlib 3D plot based on a list of data. @@ -371,7 +406,7 @@ def plot_3d_chart(plot_data, size=(2000, 1000), xlabel="", ylabel="", title="", Returns ------- - :class:`matplotlib.plt` + :class:`matplotlib.pyplot.Figure` Matplotlib fig object. """ dpi = 100.0 @@ -403,9 +438,9 @@ def plot_3d_chart(plot_data, size=(2000, 1000), xlabel="", ylabel="", title="", @pyaedt_function_handler() +@update_plot_settings def plot_2d_chart(plot_data, size=(2000, 1000), show_legend=True, xlabel="", ylabel="", title="", snapshot_path=None): """Create a matplotlib plot based on a list of data. - Parameters ---------- plot_data : list of list @@ -427,7 +462,7 @@ def plot_2d_chart(plot_data, size=(2000, 1000), show_legend=True, xlabel="", yla Returns ------- - :class:`matplotlib.plt` + :class:`matplotlib.pyplot.Figure` Matplotlib fig object. """ dpi = 100.0 @@ -460,6 +495,7 @@ def plot_2d_chart(plot_data, size=(2000, 1000), show_legend=True, xlabel="", yla @pyaedt_function_handler() +@update_plot_settings def plot_matplotlib( plot_data, size=(2000, 1000), @@ -511,8 +547,8 @@ def plot_matplotlib( Returns ------- - :class:`matplotlib.plt` - Matplotlib fig object. + :class:`matplotlib.pyplot.Figure` + Matplotlib Figure object. """ dpi = 100.0 figsize = (size[0] / dpi, size[1] / dpi) @@ -569,13 +605,16 @@ def plot_matplotlib( if snapshot_path: plt.savefig(snapshot_path) - elif show: + if show: plt.show() - return plt + return fig @pyaedt_function_handler() -def plot_contour(qty_to_plot, x, y, size=(2000, 1600), xlabel="", ylabel="", title="", levels=64, snapshot_path=None): +@update_plot_settings +def plot_contour( + qty_to_plot, x, y, size=(2000, 1600), xlabel="", ylabel="", title="", levels=64, snapshot_path=None, show=True +): """Create a matplotlib contour plot. Parameters @@ -598,10 +637,13 @@ def plot_contour(qty_to_plot, x, y, size=(2000, 1600), xlabel="", ylabel="", tit Color map levels. Default is `64`. snapshot_path : str, optional Full path to image to save. Default is None. + show : Bool, optional + Set to ``True`` if the figure should be rendered. + Default is ``True``. Returns ------- - :class:`matplotlib.plt` + :class:`matplotlib.pyplot.Figure` Matplotlib fig object. """ dpi = 100.0 @@ -625,9 +667,9 @@ def plot_contour(qty_to_plot, x, y, size=(2000, 1600), xlabel="", ylabel="", tit plt.colorbar() if snapshot_path: plt.savefig(snapshot_path) - else: + if show: plt.show() - return plt + return fig class ObjClass(object): diff --git a/pyaedt/hfss.py b/pyaedt/hfss.py index fd668db9f00..40bc7a0aa00 100644 --- a/pyaedt/hfss.py +++ b/pyaedt/hfss.py @@ -5235,13 +5235,14 @@ def set_differential_pair( @pyaedt_function_handler(array_name="name", json_file="input_data") def add_3d_component_array_from_json(self, input_data, name=None): - """Add or edit a 3D component array from a JSON file or TOML file. + """Add or edit a 3D component array from a JSON file, TOML file or dict. The 3D component is placed in the layout if it is not present. Parameters ---------- input_data : str, dict - Full path to either the JSON file or dictionary containing the array information. + Full path to either the JSON file, TOML file or the dictionary + containing the array information. name : str, optional Name of the boundary to add or edit. @@ -5416,7 +5417,9 @@ def get_antenna_ffd_solution_data( variations=None, overwrite=True, ): - """Export antennas parameters to Far Field Data (FFD) files and return the ``FfdSolutionDataExporter`` object. + """Export antennas parameters to Far Field Data (FFD) files and return an + instance of + ``FfdSolutionDataExporter`` object. For phased array cases, only one phased array is calculated. diff --git a/pyaedt/modules/solutions.py b/pyaedt/modules/solutions.py index b1022423974..c6c91c799da 100644 --- a/pyaedt/modules/solutions.py +++ b/pyaedt/modules/solutions.py @@ -1088,18 +1088,21 @@ def ifft_to_file( class FfdSolutionData(object): - """Contains information from the far field solution data. + """Antenna array far-field data class. - Load far field data from the element pattern files. + Read embedded element patterns generated in HFSS and provide the Python interface + to plot and analyze the array far-field data. Parameters ---------- eep_files : list or str - List of element pattern files for each frequency. - If the input is string, it is assumed to be a single frequency. + List of embedded element pattern files for each frequency. + If data is only provided for a single frequency, then a string may be passed + instead of a 1-element list. frequencies : list, str, int, or float List of frequencies. - If the input is not a list, it is assumed to be a single frequency. + If data is only available for a single frequency, then a float or int may be passed + instead of a 1-element list. Examples -------- @@ -1526,12 +1529,13 @@ def plot_farfield_contour( quantity="RealizedGain", phi=0, theta=0, - title="RectangularPlot", + title=None, quantity_format="dB10", image_path=None, levels=64, show=True, - **kwargs + polar=True, + **kwargs, ): # fmt: on """Create a contour plot of a specified quantity. @@ -1562,15 +1566,12 @@ def plot_farfield_contour( Returns ------- - :class:`matplotlib.plt` - Whether to show the plotted curve. - If ``show=True``, a Matplotlib figure instance of the plot is returned. - If ``show=False``, the plotted curve is returned. + :class:`matplotlib.pyplot.figure` Examples -------- >>> import pyaedt - >>> app = pyaedt.Hfss(specified_version="2023.2", designname="Antenna") + >>> app = pyaedt.Hfss(specified_version="2024.1", designname="Antenna") >>> setup_name = "Setup1 : LastAdaptive" >>> frequencies = [77e9] >>> sphere = "3D" @@ -1578,6 +1579,8 @@ def plot_farfield_contour( >>> data.plot_farfield_contour() """ + if not title: + title = "Polar Plot" if polar else "Rectangular Plot" for k in kwargs: if k == "convert_to_db": # pragma: no cover self.logger.warning("`convert_to_db` is deprecated since v0.7.8. Use `quantity_format` instead.") @@ -1602,19 +1605,17 @@ def plot_farfield_contour( return False data_to_plot = np.reshape(data_to_plot, (data["nTheta"], data["nPhi"])) th, ph = np.meshgrid(data["Theta"], data["Phi"]) - if show: - return plot_contour( - x=th, - y=ph, - qty_to_plot=data_to_plot, - xlabel="Theta (degree)", - ylabel="Phi (degree)", - title=title, - levels=levels, - snapshot_path=image_path, - ) - else: - return data_to_plot + return plot_contour( + x=th, + y=ph, + qty_to_plot=data_to_plot, + xlabel="Theta (degree)", + ylabel="Phi (degree)", + title=title, + levels=levels, + snapshot_path=image_path, + show=show, + ) # fmt: off @pyaedt_function_handler(farfield_quantity="quantity", @@ -2420,7 +2421,19 @@ def _rotation_to_euler_angles(R): class FfdSolutionDataExporter(FfdSolutionData): - """Export far field solution data. + """Class to enable export of embedded element pattern data from HFSS. + + An instance of this class is returned from the method + :meth:`pyaedt.Hfss.get_antenna_ffd_solution_data`. This method allows creation of + the embedded + element pattern (eep) files for an antenna array that has been solved in HFSS. The + ``frequencies`` and ``eep_files`` properties can then be passed as arguments to + instantiate an instance of :class:`pyaedt.modules.solutions.FfdSolutionData` for + subsequent analysis and post-processing of the array data. + + Note that this class is derived from :class:`FfdSolutionData` and can be used directly for + far-field postprocessing and array analysis, but remains a property of the + :class:`pyaedt.Hfss` application. Parameters ---------- From 4601e8ec5500fd5a8ce556755de6a4783ff98cc7 Mon Sep 17 00:00:00 2001 From: Devin Date: Fri, 3 May 2024 18:37:22 +0200 Subject: [PATCH 03/29] Update solutions.py Bring all plotting and rendering into the method plot_farfield_contour so that it can be customized to far-field data. --- pyaedt/hfss.py | 16 ++++++++- pyaedt/modules/solutions.py | 72 +++++++++++++++++++++++++++++-------- 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/pyaedt/hfss.py b/pyaedt/hfss.py index 40bc7a0aa00..82721e21c8f 100644 --- a/pyaedt/hfss.py +++ b/pyaedt/hfss.py @@ -5416,6 +5416,7 @@ def get_antenna_ffd_solution_data( sphere=None, variations=None, overwrite=True, + link_to_hfss=True, ): """Export antennas parameters to Far Field Data (FFD) files and return an instance of @@ -5436,12 +5437,19 @@ def get_antenna_ffd_solution_data( Variation dictionary. overwrite : bool, optional Whether to overwrite FFD files. The default is ``True``. + link_to_hfss : bool, optional + If this is set to ``False`` then return an instance of + :class:`pyaedt.modules.solutions.FfdSolutionData` which is independent from the + running HFSS instance. The default is ``True`` which returns an instance of + :class:`pyaedt.modules.solutions.FfdSolutionDataExporter` which requires a connection + to an instance of the :class:`Hfss`` class. Returns ------- :class:`pyaedt.modules.solutions.FfdSolutionDataExporter` SolutionData object. """ + from pyaedt.modules.solutions import FfdSolutionData from pyaedt.modules.solutions import FfdSolutionDataExporter if not variations: @@ -5468,7 +5476,7 @@ def get_antenna_ffd_solution_data( ) self.logger.info("Far field sphere %s is created.", setup) - return FfdSolutionDataExporter( + ffd = FfdSolutionDataExporter( self, sphere_name=sphere, setup_name=setup, @@ -5476,6 +5484,12 @@ def get_antenna_ffd_solution_data( variations=variations, overwrite=overwrite, ) + if link_to_hfss: + return ffd + else: + eep_file = ffd.eep_files + frequencies = ffd.frequencies + return FfdSolutionData(frequencies=frequencies, eep_files=eep_file) @pyaedt_function_handler() def set_material_threshold(self, threshold=100000): diff --git a/pyaedt/modules/solutions.py b/pyaedt/modules/solutions.py index c6c91c799da..73eaf8fd9ed 100644 --- a/pyaedt/modules/solutions.py +++ b/pyaedt/modules/solutions.py @@ -8,6 +8,8 @@ import sys import time +import matplotlib.pyplot as plt + from pyaedt import is_ironpython from pyaedt import pyaedt_function_handler from pyaedt.application.Variables import decompose_variable_value @@ -24,7 +26,6 @@ from pyaedt.generic.plot import is_notebook from pyaedt.generic.plot import plot_2d_chart from pyaedt.generic.plot import plot_3d_chart -from pyaedt.generic.plot import plot_contour from pyaedt.generic.plot import plot_polar_chart from pyaedt.generic.settings import settings from pyaedt.modeler.cad.elements3d import FacePrimitive @@ -1529,12 +1530,14 @@ def plot_farfield_contour( quantity="RealizedGain", phi=0, theta=0, + size=None, title=None, quantity_format="dB10", image_path=None, levels=64, show=True, polar=True, + max_theta=180, **kwargs, ): # fmt: on @@ -1550,6 +1553,9 @@ def plot_farfield_contour( Phi scan angle in degrees. The default is ``0``. theta : float, int, optional Theta scan angle in degrees. The default is ``0``. + size : tuple, optional + Image size in pixel (width, height). Default is ``None`` in which case resolution + is determined automatically. title : str, optional Plot title. The default is ``"RectangularPlot"``. quantity_format : str, optional @@ -1563,10 +1569,17 @@ def plot_farfield_contour( show : bool, optional Whether to show the plot. The default is ``True``. If ``False``, the Matplotlib instance of the plot is shown. + polar : bool, optional + Generate the plot in polar coordinates. The default is ``True``. If ``False``, the plot + will be rectangular. + max_theta : float or int, optional + Maxmum theta angle for plotting. The default is ``180`` which plots the far-field for + all angles. Setting ``max_theta`` to 90 will limit the displayed data to the upper + hemisphere, that is (0 < theta < 90). Returns ------- - :class:`matplotlib.pyplot.figure` + :class:`matplotlib.pyplot.Figure` Examples -------- @@ -1580,7 +1593,7 @@ def plot_farfield_contour( """ if not title: - title = "Polar Plot" if polar else "Rectangular Plot" + title = quantity for k in kwargs: if k == "convert_to_db": # pragma: no cover self.logger.warning("`convert_to_db` is deprecated since v0.7.8. Use `quantity_format` instead.") @@ -1597,25 +1610,54 @@ def plot_farfield_contour( if quantity not in data: # pragma: no cover self.logger.error("Far field quantity is not available.") return False + select = np.abs(data["Theta"]) <= max_theta # Limit theta range for plotting. - data_to_plot = data[quantity] + data_to_plot = data[quantity][select, :] data_to_plot = conversion_function(data_to_plot, quantity_format) if not isinstance(data_to_plot, np.ndarray): # pragma: no cover self.logger.error("Wrong format quantity") return False - data_to_plot = np.reshape(data_to_plot, (data["nTheta"], data["nPhi"])) - th, ph = np.meshgrid(data["Theta"], data["Phi"]) - return plot_contour( - x=th, - y=ph, - qty_to_plot=data_to_plot, - xlabel="Theta (degree)", - ylabel="Phi (degree)", - title=title, + ph, th = np.meshgrid(data["Phi"], data["Theta"][select]) + ph = ph * np.pi/180 if polar else ph + # Convert to radians for polar plot. + + # TODO: Is it necessary to set the plot size? + + default_figsize = plt.rcParams["figure.figsize"] + if size: # Retain this code to remain consistent with other plotting methods. + dpi = 100.0 + figsize = (size[0] / dpi, size[1] / dpi) + plt.rcParams["figure.figsize"] = figsize + else: + figsize = default_figsize + + projection = 'polar' if polar else 'rectilinear' + fig, ax = plt.subplots(subplot_kw={'projection': projection}, figsize=figsize) + + fig.suptitle(title) + ax.set_xlabel("$\phi$ (Degrees)") + if polar: + ax.set_rticks(np.linspace(0, max_theta, 3)) + else: + ax.set_ylabel("$\\theta (Degrees") + + plt.contourf( + ph, + th, + data_to_plot, levels=levels, - snapshot_path=image_path, - show=show, + cmap="jet", ) + cbar = plt.colorbar() + cbar.set_label(quantity_format, rotation=270, labelpad=20) + + if image_path: + plt.savefig(image_path) + if show: + plt.show() + + plt.rcParams["figure.figsize"] = default_figsize + return fig # fmt: off @pyaedt_function_handler(farfield_quantity="quantity", From 2c15cfafcaa4dc39c8875ac0062a750a36a5e5e2 Mon Sep 17 00:00:00 2001 From: Devin Date: Sat, 4 May 2024 09:45:48 +0200 Subject: [PATCH 04/29] Fix Iron Python comma error Iron Python does not allow a comma after the **kwargs in plot_farfield_contour --- pyaedt/modules/solutions.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyaedt/modules/solutions.py b/pyaedt/modules/solutions.py index 248a1b5a9ea..610ca4616d1 100644 --- a/pyaedt/modules/solutions.py +++ b/pyaedt/modules/solutions.py @@ -1538,8 +1538,7 @@ def plot_farfield_contour( show=True, polar=True, max_theta=180, - **kwargs, - ): + **kwargs): # fmt: on """Create a contour plot of a specified quantity. From 911704664260af320f1b6bd2bbb24ff17458a69c Mon Sep 17 00:00:00 2001 From: Devin Date: Sat, 4 May 2024 09:47:19 +0200 Subject: [PATCH 05/29] Fix Iron Python comma error Iron Python does not allow a comma after the **kwargs in plot_farfield_contour --- pyaedt/modules/solutions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyaedt/modules/solutions.py b/pyaedt/modules/solutions.py index 610ca4616d1..e50786c0bb2 100644 --- a/pyaedt/modules/solutions.py +++ b/pyaedt/modules/solutions.py @@ -1538,7 +1538,8 @@ def plot_farfield_contour( show=True, polar=True, max_theta=180, - **kwargs): + **kwargs + ): # fmt: on """Create a contour plot of a specified quantity. From 51510307b934a6db0662d1aac7df095c460eb88b Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Mon, 6 May 2024 14:23:28 +0200 Subject: [PATCH 06/29] Import matplotlib if not ironpython --- pyaedt/modules/solutions.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyaedt/modules/solutions.py b/pyaedt/modules/solutions.py index e50786c0bb2..09b0e81c8e4 100644 --- a/pyaedt/modules/solutions.py +++ b/pyaedt/modules/solutions.py @@ -8,8 +8,6 @@ import sys import time -import matplotlib.pyplot as plt - from pyaedt import is_ironpython from pyaedt import pyaedt_function_handler from pyaedt.application.Variables import decompose_variable_value @@ -46,6 +44,10 @@ import pyvista as pv except ImportError: pv = None + try: + import matplotlib.pyplot as plt + except ImportError: + plt = None class SolutionData(object): From 84b67ec0fe1f36ab12591cb4938ad122123653af Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Wed, 8 May 2024 12:41:14 +0200 Subject: [PATCH 07/29] Test unittest --- .github/workflows/ci_cd.yml | 944 +++++++++++++------------- _unittest/test_12_1_PostProcessing.py | 652 ------------------ 2 files changed, 472 insertions(+), 1124 deletions(-) delete mode 100644 _unittest/test_12_1_PostProcessing.py diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index e6c7f71fcf3..302c98676ae 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -36,306 +36,306 @@ jobs: use-upper-case: true # TODO: Update to ansys/actions/doc-style@v6 - doc-style: - name: Documentation style check - runs-on: ubuntu-latest - steps: - - name: Check documentation style - uses: ansys/actions/doc-style@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - vale-config: "doc/.vale.ini" - vale-version: "2.29.6" - - smoke-tests: - name: Build wheelhouse and smoke tests - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest] - python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] - steps: - - name: Build wheelhouse and perform smoke test - uses: ansys/actions/build-wheelhouse@v4 - with: - library-name: ${{ env.PACKAGE_NAME }} - operating-system: ${{ matrix.os }} - python-version: ${{ matrix.python-version }} - target: 'all' - - - name: Import python package - run: | - python -c "import pyaedt; from pyaedt import __version__" - - # TODO: Update to ansys/actions/doc-build@v6 once we remove examples - doc-build: - name: Documentation build without examples - runs-on: ubuntu-latest - needs: [doc-style] - steps: - - name: Install Git and checkout project - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Update pip - run: | - pip install --upgrade pip - - - name: Install pyaedt and documentation dependencies - run: | - pip install .[doc-no-examples] - - - name: Retrieve PyAEDT version - id: version - run: | - echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT - echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")" - - - name: Install doc build requirements - run: | - sudo apt update - sudo apt install graphviz texlive-latex-extra latexmk texlive-xetex texlive-fonts-extra -y - - # TODO: Update this step once pyaedt-examples is ready - - name: Build HTML documentation without examples - run: | - make -C doc clean - make -C doc html-no-examples - - # Verify that sphinx generates no warnings - - name: Check for warnings - run: | - python doc/print_errors.py - - - name: Upload HTML documentation without examples artifact - uses: actions/upload-artifact@v3 - with: - name: documentation-no-examples-html - path: doc/_build/html - retention-days: 7 - - - name: Build PDF documentation without examples - run: | - make -C doc pdf-no-examples - - - name: Upload PDF documentation without examples artifact - uses: actions/upload-artifact@v3 - with: - name: documentation-no-examples-pdf - path: doc/_build/latex/PyAEDT-Documentation-*.pdf - retention-days: 7 - -# # ================================================================================================= -# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -# # ================================================================================================= - - doc-build-with-examples: - name: Documentation build with examples - if: github.event_name == 'push' && contains(github.ref, 'refs/tags') - runs-on: [ self-hosted, Windows, pyaedt ] - needs: [doc-style] - timeout-minutes: 720 - steps: - - name: Install Git and checkout project - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Create virtual environment - run: | - python -m venv .venv - .venv\Scripts\Activate.ps1 - python -m pip install pip -U - python -m pip install wheel setuptools -U - python -c "import sys; print(sys.executable)" - - - name: Install pyaedt and documentation dependencies - run: | - .venv\Scripts\Activate.ps1 - pip install .[doc] - - - name: Retrieve PyAEDT version - id: version - run: | - .venv\Scripts\Activate.ps1 - echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT - echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")" - - - name: Install CI dependencies (e.g. vtk-osmesa) - run: | - .venv\Scripts\Activate.ps1 - # Uninstall conflicting dependencies - pip uninstall --yes vtk - pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.2.20230527.dev0 - - # TODO: Update this step once pyaedt-examples is ready - # NOTE: Use environment variable to keep the doctree and avoid redundant build for PDF pages - - name: Build HTML documentation with examples - env: - SPHINXBUILD_KEEP_DOCTREEDIR: "1" - run: | - .venv\Scripts\Activate.ps1 - .\doc\make.bat clean - .\doc\make.bat html - - # TODO: Keeping this commented as reminder of https://github.com/ansys/pyaedt/issues/4296 - # # Verify that sphinx generates no warnings - # - name: Check for warnings - # run: | - # .venv\Scripts\Activate.ps1 - # python doc/print_errors.py - - # Use environment variable to remove the doctree after the build of PDF pages - - name: Build PDF documentation with examples - env: - SPHINXBUILD_KEEP_DOCTREEDIR: "0" - run: | - .venv\Scripts\Activate.ps1 - .\doc\make.bat pdf - - - name: Add assets to HTML docs - run: | - zip -r documentation-html.zip ./doc/_build/html - mv documentation-html.zip ./doc/_build/html/_static/assets/download/ - cp doc/_build/latex/PyAEDT-Documentation-*.pdf ./doc/_build/html/_static/assets/download/pyaedt.pdf - - - name: Upload HTML documentation with examples artifact - uses: actions/upload-artifact@v3 - with: - name: documentation-html - path: doc/_build/html - retention-days: 7 - - - name: Upload PDF documentation without examples artifact - uses: actions/upload-artifact@v3 - with: - name: documentation-pdf - path: doc/_build/latex/PyAEDT-Documentation-*.pdf - retention-days: 7 - -# # ================================================================================================= -# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -# # ================================================================================================= - - test-solvers-windows: - name: Testing solvers and coverage (Windows) - needs: [smoke-tests] - runs-on: [ self-hosted, Windows, pyaedt ] - steps: - - name: Install Git and checkout project - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Create virtual environment - run: | - python -m venv .venv - .venv\Scripts\Activate.ps1 - python -m pip install pip -U - python -m pip install wheel setuptools -U - python -c "import sys; print(sys.executable)" - - - name: Install pyaedt and tests dependencies - run: | - .venv\Scripts\Activate.ps1 - pip install .[tests] - pip install pytest-azurepipelines - - - name: Install CI dependencies (e.g. vtk-osmesa) - run: | - .venv\Scripts\Activate.ps1 - # Uninstall conflicting dependencies - pip uninstall --yes vtk - pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.2.20230527.dev0 - - - name: Run tests on _unittest_solvers - env: - PYTHONMALLOC: malloc - run: | - .venv\Scripts\Activate.ps1 - pytest --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest_solvers - - - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - name: codecov-system-solver-tests - file: ./coverage.xml - flags: system,solver - - - name: Upload pytest test results - uses: actions/upload-artifact@v3 - with: - name: pytest-solver-results - path: junit/test-results.xml - if: ${{ always() }} - -# # ================================================================================================= -# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -# # ================================================================================================= - - # TODO: Si if we can use ansys/actions - test-solvers-linux: - name: Testing solvers and coverage (Linux) - needs: [smoke-tests] - runs-on: [ self-hosted, Linux, pyaedt ] - env: - ANSYSEM_ROOT241: '/opt/AnsysEM/v241/Linux64' - ANS_NODEPCHECK: '1' - steps: - - name: Install Git and checkout project - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Create virtual environment - run: | - export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH - python -m venv .venv - source .venv/bin/activate - python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org pip -U - python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org wheel setuptools -U - python -c "import sys; print(sys.executable)" - - - name: Install pyaedt and tests dependencies - run: | - export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH - source .venv/bin/activate - pip install .[tests] - pip install pytest-azurepipelines - - - name: Run tests on _unittest_solvers - run: | - export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH - source .venv/bin/activate - pytest --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest_solvers - - - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - name: codecov-system-solver-tests - file: ./coverage.xml - flags: system,solver - - - name: Upload pytest test results - uses: actions/upload-artifact@v3 - with: - name: pytest-solver-results - path: junit/test-results.xml - if: ${{ always() }} +# doc-style: +# name: Documentation style check +# runs-on: ubuntu-latest +# steps: +# - name: Check documentation style +# uses: ansys/actions/doc-style@v4 +# with: +# token: ${{ secrets.GITHUB_TOKEN }} +# vale-config: "doc/.vale.ini" +# vale-version: "2.29.6" +# +# smoke-tests: +# name: Build wheelhouse and smoke tests +# runs-on: ${{ matrix.os }} +# strategy: +# fail-fast: false +# matrix: +# os: [ubuntu-latest, windows-latest] +# python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] +# steps: +# - name: Build wheelhouse and perform smoke test +# uses: ansys/actions/build-wheelhouse@v4 +# with: +# library-name: ${{ env.PACKAGE_NAME }} +# operating-system: ${{ matrix.os }} +# python-version: ${{ matrix.python-version }} +# target: 'all' +# +# - name: Import python package +# run: | +# python -c "import pyaedt; from pyaedt import __version__" +# +# # TODO: Update to ansys/actions/doc-build@v6 once we remove examples +# doc-build: +# name: Documentation build without examples +# runs-on: ubuntu-latest +# needs: [doc-style] +# steps: +# - name: Install Git and checkout project +# uses: actions/checkout@v4 +# +# - name: Setup Python +# uses: actions/setup-python@v5 +# with: +# python-version: ${{ env.MAIN_PYTHON_VERSION }} +# +# - name: Update pip +# run: | +# pip install --upgrade pip +# +# - name: Install pyaedt and documentation dependencies +# run: | +# pip install .[doc-no-examples] +# +# - name: Retrieve PyAEDT version +# id: version +# run: | +# echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT +# echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")" +# +# - name: Install doc build requirements +# run: | +# sudo apt update +# sudo apt install graphviz texlive-latex-extra latexmk texlive-xetex texlive-fonts-extra -y +# +# # TODO: Update this step once pyaedt-examples is ready +# - name: Build HTML documentation without examples +# run: | +# make -C doc clean +# make -C doc html-no-examples +# +# # Verify that sphinx generates no warnings +# - name: Check for warnings +# run: | +# python doc/print_errors.py +# +# - name: Upload HTML documentation without examples artifact +# uses: actions/upload-artifact@v3 +# with: +# name: documentation-no-examples-html +# path: doc/_build/html +# retention-days: 7 +# +# - name: Build PDF documentation without examples +# run: | +# make -C doc pdf-no-examples +# +# - name: Upload PDF documentation without examples artifact +# uses: actions/upload-artifact@v3 +# with: +# name: documentation-no-examples-pdf +# path: doc/_build/latex/PyAEDT-Documentation-*.pdf +# retention-days: 7 +# +## # ================================================================================================= +## # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +## # ================================================================================================= +# +# doc-build-with-examples: +# name: Documentation build with examples +# if: github.event_name == 'push' && contains(github.ref, 'refs/tags') +# runs-on: [ self-hosted, Windows, pyaedt ] +# needs: [doc-style] +# timeout-minutes: 720 +# steps: +# - name: Install Git and checkout project +# uses: actions/checkout@v4 +# +# - name: Setup Python +# uses: actions/setup-python@v5 +# with: +# python-version: ${{ env.MAIN_PYTHON_VERSION }} +# +# - name: Create virtual environment +# run: | +# python -m venv .venv +# .venv\Scripts\Activate.ps1 +# python -m pip install pip -U +# python -m pip install wheel setuptools -U +# python -c "import sys; print(sys.executable)" +# +# - name: Install pyaedt and documentation dependencies +# run: | +# .venv\Scripts\Activate.ps1 +# pip install .[doc] +# +# - name: Retrieve PyAEDT version +# id: version +# run: | +# .venv\Scripts\Activate.ps1 +# echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT +# echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")" +# +# - name: Install CI dependencies (e.g. vtk-osmesa) +# run: | +# .venv\Scripts\Activate.ps1 +# # Uninstall conflicting dependencies +# pip uninstall --yes vtk +# pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.2.20230527.dev0 +# +# # TODO: Update this step once pyaedt-examples is ready +# # NOTE: Use environment variable to keep the doctree and avoid redundant build for PDF pages +# - name: Build HTML documentation with examples +# env: +# SPHINXBUILD_KEEP_DOCTREEDIR: "1" +# run: | +# .venv\Scripts\Activate.ps1 +# .\doc\make.bat clean +# .\doc\make.bat html +# +# # TODO: Keeping this commented as reminder of https://github.com/ansys/pyaedt/issues/4296 +# # # Verify that sphinx generates no warnings +# # - name: Check for warnings +# # run: | +# # .venv\Scripts\Activate.ps1 +# # python doc/print_errors.py +# +# # Use environment variable to remove the doctree after the build of PDF pages +# - name: Build PDF documentation with examples +# env: +# SPHINXBUILD_KEEP_DOCTREEDIR: "0" +# run: | +# .venv\Scripts\Activate.ps1 +# .\doc\make.bat pdf +# +# - name: Add assets to HTML docs +# run: | +# zip -r documentation-html.zip ./doc/_build/html +# mv documentation-html.zip ./doc/_build/html/_static/assets/download/ +# cp doc/_build/latex/PyAEDT-Documentation-*.pdf ./doc/_build/html/_static/assets/download/pyaedt.pdf +# +# - name: Upload HTML documentation with examples artifact +# uses: actions/upload-artifact@v3 +# with: +# name: documentation-html +# path: doc/_build/html +# retention-days: 7 +# +# - name: Upload PDF documentation without examples artifact +# uses: actions/upload-artifact@v3 +# with: +# name: documentation-pdf +# path: doc/_build/latex/PyAEDT-Documentation-*.pdf +# retention-days: 7 +# +## # ================================================================================================= +## # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +## # ================================================================================================= +# +# test-solvers-windows: +# name: Testing solvers and coverage (Windows) +# needs: [smoke-tests] +# runs-on: [ self-hosted, Windows, pyaedt ] +# steps: +# - name: Install Git and checkout project +# uses: actions/checkout@v4 +# +# - name: Setup Python +# uses: actions/setup-python@v5 +# with: +# python-version: ${{ env.MAIN_PYTHON_VERSION }} +# +# - name: Create virtual environment +# run: | +# python -m venv .venv +# .venv\Scripts\Activate.ps1 +# python -m pip install pip -U +# python -m pip install wheel setuptools -U +# python -c "import sys; print(sys.executable)" +# +# - name: Install pyaedt and tests dependencies +# run: | +# .venv\Scripts\Activate.ps1 +# pip install .[tests] +# pip install pytest-azurepipelines +# +# - name: Install CI dependencies (e.g. vtk-osmesa) +# run: | +# .venv\Scripts\Activate.ps1 +# # Uninstall conflicting dependencies +# pip uninstall --yes vtk +# pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.2.20230527.dev0 +# +# - name: Run tests on _unittest_solvers +# env: +# PYTHONMALLOC: malloc +# run: | +# .venv\Scripts\Activate.ps1 +# pytest --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest_solvers +# +# - uses: codecov/codecov-action@v4 +# with: +# token: ${{ secrets.CODECOV_TOKEN }} +# name: codecov-system-solver-tests +# file: ./coverage.xml +# flags: system,solver +# +# - name: Upload pytest test results +# uses: actions/upload-artifact@v3 +# with: +# name: pytest-solver-results +# path: junit/test-results.xml +# if: ${{ always() }} +# +## # ================================================================================================= +## # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +## # ================================================================================================= +# +# # TODO: Si if we can use ansys/actions +# test-solvers-linux: +# name: Testing solvers and coverage (Linux) +# needs: [smoke-tests] +# runs-on: [ self-hosted, Linux, pyaedt ] +# env: +# ANSYSEM_ROOT241: '/opt/AnsysEM/v241/Linux64' +# ANS_NODEPCHECK: '1' +# steps: +# - name: Install Git and checkout project +# uses: actions/checkout@v4 +# +# - name: Setup Python +# uses: actions/setup-python@v5 +# with: +# python-version: ${{ env.MAIN_PYTHON_VERSION }} +# +# - name: Create virtual environment +# run: | +# export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH +# python -m venv .venv +# source .venv/bin/activate +# python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org pip -U +# python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org wheel setuptools -U +# python -c "import sys; print(sys.executable)" +# +# - name: Install pyaedt and tests dependencies +# run: | +# export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH +# source .venv/bin/activate +# pip install .[tests] +# pip install pytest-azurepipelines +# +# - name: Run tests on _unittest_solvers +# run: | +# export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH +# source .venv/bin/activate +# pytest --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest_solvers +# +# - uses: codecov/codecov-action@v4 +# with: +# token: ${{ secrets.CODECOV_TOKEN }} +# name: codecov-system-solver-tests +# file: ./coverage.xml +# flags: system,solver +# +# - name: Upload pytest test results +# uses: actions/upload-artifact@v3 +# with: +# name: pytest-solver-results +# path: junit/test-results.xml +# if: ${{ always() }} # # ================================================================================================= # # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv @@ -343,7 +343,7 @@ jobs: test-windows: name: Testing and coverage (Windows) - needs: [smoke-tests] +# needs: [smoke-tests] runs-on: [ self-hosted, Windows, pyaedt ] steps: - name: Install Git and checkout project @@ -400,174 +400,174 @@ jobs: name: pytest-results path: junit/test-results.xml if: ${{ always() }} - -# # ================================================================================================= -# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -# # ================================================================================================= - - # TODO: Si if we can use ansys/actions - test-linux: - name: Testing and coverage (Linux) - needs: [smoke-tests] - runs-on: [ self-hosted, Linux, pyaedt ] - env: - ANSYSEM_ROOT241: '/opt/AnsysEM/v241/Linux64' - ANS_NODEPCHECK: '1' - steps: - - name: Install Git and checkout project - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Create virtual environment - run: | - export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH - python -m venv .venv - source .venv/bin/activate - python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org pip -U - python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org wheel setuptools -U - python -c "import sys; print(sys.executable)" - - - name: Install pyaedt and tests dependencies - run: | - export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH - source .venv/bin/activate - pip install .[tests] - pip install pytest-azurepipelines - - - name: Install CI dependencies (e.g. vtk-osmesa) - run: | - source .venv/bin/activate - # Uninstall conflicting dependencies - pip uninstall --yes vtk - pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.2.20230527.dev0 - - - name: Run tests on _unittest - uses: nick-fields/retry@v3 - with: - max_attempts: 2 - retry_on: error - timeout_minutes: 50 - command: | - export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH - source .venv/bin/activate - pytest -n 4 --dist loadfile --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest - - - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - name: codecov-system-solver-tests - file: ./coverage.xml - flags: system,solver - - - name: Upload pytest test results - uses: actions/upload-artifact@v3 - with: - name: pytest-solver-results - path: junit/test-results.xml - if: ${{ always() }} - -# # ================================================================================================= -# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -# # ================================================================================================= - - test-ironpython-windows: - name: Testing IronPython and coverage (Windows) - needs: [smoke-tests] - runs-on: [ self-hosted, Windows, pyaedt ] - steps: - - uses: actions/checkout@v4 - - - name: Run Ironpython tests - timeout-minutes: 5 - run: | - $processA = start-process 'cmd' -ArgumentList '/c .\_unittest_ironpython\run_unittests_batchmode.cmd' -PassThru - $processA.WaitForExit() - - - name: Get log content - run: | - get-content .\_unittest_ironpython\pyaedt_unit_test_ironpython.log - - - name: Check for errors - run: | - $test_errors_failures = Select-String -Path .\_unittest_ironpython\pyaedt_unit_test_ironpython.log -Pattern "TextTestResult errors=" - if ($test_errors_failures -ne $null) - { - exit 1 - } - - package: - name: Package library - needs: [test-windows, test-solvers-windows, test-ironpython-windows, test-linux, test-solvers-linux, doc-build] - runs-on: ubuntu-latest - steps: - - name: Build library source and wheel artifacts - uses: ansys/actions/build-library@v4 - with: - library-name: ${{ env.PACKAGE_NAME }} - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - # TODO: Si if we can fix the PDF issue and leverage classic ansys/release-github - release: - name: Release project - if: github.event_name == 'push' && contains(github.ref, 'refs/tags') - needs: [package, doc-build-with-examples] - runs-on: ubuntu-latest - steps: - - name: Release to the public PyPI repository - uses: ansys/actions/release-pypi-public@v4 - with: - library-name: ${{ env.PACKAGE_NAME }} - twine-username: "__token__" - twine-token: ${{ secrets.PYPI_TOKEN }} - - - name: Release to GitHub - uses: ansys/actions/release-github@v4 - with: - library-name: ${{ env.PACKAGE_NAME }} - - upload-release-doc: - name: Upload release documentation - if: github.event_name == 'push' && contains(github.ref, 'refs/tags') - runs-on: ubuntu-latest - needs: [release] - steps: - - name: Deploy the stable documentation - uses: ansys/actions/doc-deploy-stable@v4 - with: - cname: ${{ env.DOCUMENTATION_CNAME }} - token: ${{ secrets.GITHUB_TOKEN }} - doc-artifact-name: 'documentation-html' - - doc-index-stable: - name: Deploy stable docs index - if: github.event_name == 'push' && contains(github.ref, 'refs/tags') - runs-on: ubuntu-latest - needs: upload-release-doc - steps: - - name: Install Git and clone project - uses: actions/checkout@v4 - - - name: Install the package requirements - run: pip install -e . - - - name: Get the version to PyMeilisearch - run: | - VERSION=$(python -c "from pyaedt import __version__; print('.'.join(__version__.split('.')[:2]))") - VERSION_MEILI=$(python -c "from pyaedt import __version__; print('-'.join(__version__.split('.')[:2]))") - echo "Calculated VERSION: $VERSION" - echo "Calculated VERSION_MEILI: $VERSION_MEILI" - echo "VERSION=$VERSION" >> $GITHUB_ENV - echo "VERSION_MEILI=$VERSION_MEILI" >> $GITHUB_ENV - - - name: Deploy the latest documentation index - uses: ansys/actions/doc-deploy-index@v4 - with: - cname: ${{ env.DOCUMENTATION_CNAME }}/version/${{ env.VERSION }} - index-name: pyaedt-v${{ env.VERSION_MEILI }} - host-url: ${{ env.MEILISEARCH_HOST_URL }} - api-key: ${{ env.MEILISEARCH_API_KEY }} - python-version: ${{ env.MAIN_PYTHON_VERSION }} +# +## # ================================================================================================= +## # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +## # ================================================================================================= +# +# # TODO: Si if we can use ansys/actions +# test-linux: +# name: Testing and coverage (Linux) +# needs: [smoke-tests] +# runs-on: [ self-hosted, Linux, pyaedt ] +# env: +# ANSYSEM_ROOT241: '/opt/AnsysEM/v241/Linux64' +# ANS_NODEPCHECK: '1' +# steps: +# - name: Install Git and checkout project +# uses: actions/checkout@v4 +# +# - name: Setup Python +# uses: actions/setup-python@v5 +# with: +# python-version: ${{ env.MAIN_PYTHON_VERSION }} +# +# - name: Create virtual environment +# run: | +# export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH +# python -m venv .venv +# source .venv/bin/activate +# python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org pip -U +# python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org wheel setuptools -U +# python -c "import sys; print(sys.executable)" +# +# - name: Install pyaedt and tests dependencies +# run: | +# export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH +# source .venv/bin/activate +# pip install .[tests] +# pip install pytest-azurepipelines +# +# - name: Install CI dependencies (e.g. vtk-osmesa) +# run: | +# source .venv/bin/activate +# # Uninstall conflicting dependencies +# pip uninstall --yes vtk +# pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.2.20230527.dev0 +# +# - name: Run tests on _unittest +# uses: nick-fields/retry@v3 +# with: +# max_attempts: 2 +# retry_on: error +# timeout_minutes: 50 +# command: | +# export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH +# source .venv/bin/activate +# pytest -n 4 --dist loadfile --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest +# +# - uses: codecov/codecov-action@v4 +# with: +# token: ${{ secrets.CODECOV_TOKEN }} +# name: codecov-system-solver-tests +# file: ./coverage.xml +# flags: system,solver +# +# - name: Upload pytest test results +# uses: actions/upload-artifact@v3 +# with: +# name: pytest-solver-results +# path: junit/test-results.xml +# if: ${{ always() }} +# +## # ================================================================================================= +## # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +## # ================================================================================================= +# +# test-ironpython-windows: +# name: Testing IronPython and coverage (Windows) +# needs: [smoke-tests] +# runs-on: [ self-hosted, Windows, pyaedt ] +# steps: +# - uses: actions/checkout@v4 +# +# - name: Run Ironpython tests +# timeout-minutes: 5 +# run: | +# $processA = start-process 'cmd' -ArgumentList '/c .\_unittest_ironpython\run_unittests_batchmode.cmd' -PassThru +# $processA.WaitForExit() +# +# - name: Get log content +# run: | +# get-content .\_unittest_ironpython\pyaedt_unit_test_ironpython.log +# +# - name: Check for errors +# run: | +# $test_errors_failures = Select-String -Path .\_unittest_ironpython\pyaedt_unit_test_ironpython.log -Pattern "TextTestResult errors=" +# if ($test_errors_failures -ne $null) +# { +# exit 1 +# } +# +# package: +# name: Package library +# needs: [test-windows, test-solvers-windows, test-ironpython-windows, test-linux, test-solvers-linux, doc-build] +# runs-on: ubuntu-latest +# steps: +# - name: Build library source and wheel artifacts +# uses: ansys/actions/build-library@v4 +# with: +# library-name: ${{ env.PACKAGE_NAME }} +# python-version: ${{ env.MAIN_PYTHON_VERSION }} +# +# # TODO: Si if we can fix the PDF issue and leverage classic ansys/release-github +# release: +# name: Release project +# if: github.event_name == 'push' && contains(github.ref, 'refs/tags') +# needs: [package, doc-build-with-examples] +# runs-on: ubuntu-latest +# steps: +# - name: Release to the public PyPI repository +# uses: ansys/actions/release-pypi-public@v4 +# with: +# library-name: ${{ env.PACKAGE_NAME }} +# twine-username: "__token__" +# twine-token: ${{ secrets.PYPI_TOKEN }} +# +# - name: Release to GitHub +# uses: ansys/actions/release-github@v4 +# with: +# library-name: ${{ env.PACKAGE_NAME }} +# +# upload-release-doc: +# name: Upload release documentation +# if: github.event_name == 'push' && contains(github.ref, 'refs/tags') +# runs-on: ubuntu-latest +# needs: [release] +# steps: +# - name: Deploy the stable documentation +# uses: ansys/actions/doc-deploy-stable@v4 +# with: +# cname: ${{ env.DOCUMENTATION_CNAME }} +# token: ${{ secrets.GITHUB_TOKEN }} +# doc-artifact-name: 'documentation-html' +# +# doc-index-stable: +# name: Deploy stable docs index +# if: github.event_name == 'push' && contains(github.ref, 'refs/tags') +# runs-on: ubuntu-latest +# needs: upload-release-doc +# steps: +# - name: Install Git and clone project +# uses: actions/checkout@v4 +# +# - name: Install the package requirements +# run: pip install -e . +# +# - name: Get the version to PyMeilisearch +# run: | +# VERSION=$(python -c "from pyaedt import __version__; print('.'.join(__version__.split('.')[:2]))") +# VERSION_MEILI=$(python -c "from pyaedt import __version__; print('-'.join(__version__.split('.')[:2]))") +# echo "Calculated VERSION: $VERSION" +# echo "Calculated VERSION_MEILI: $VERSION_MEILI" +# echo "VERSION=$VERSION" >> $GITHUB_ENV +# echo "VERSION_MEILI=$VERSION_MEILI" >> $GITHUB_ENV +# +# - name: Deploy the latest documentation index +# uses: ansys/actions/doc-deploy-index@v4 +# with: +# cname: ${{ env.DOCUMENTATION_CNAME }}/version/${{ env.VERSION }} +# index-name: pyaedt-v${{ env.VERSION_MEILI }} +# host-url: ${{ env.MEILISEARCH_HOST_URL }} +# api-key: ${{ env.MEILISEARCH_API_KEY }} +# python-version: ${{ env.MAIN_PYTHON_VERSION }} diff --git a/_unittest/test_12_1_PostProcessing.py b/_unittest/test_12_1_PostProcessing.py deleted file mode 100644 index addd18ff579..00000000000 --- a/_unittest/test_12_1_PostProcessing.py +++ /dev/null @@ -1,652 +0,0 @@ -import os -import sys -import uuid - -from _unittest.conftest import config -import pytest - -from pyaedt.generic.general_methods import is_linux -from pyaedt.generic.general_methods import read_json -from pyaedt.generic.plot import _parse_aedtplt -from pyaedt.generic.plot import _parse_streamline -from pyaedt.generic.settings import settings - -if config["desktopVersion"] > "2022.2": - test_field_name = "Potter_Horn_231" - test_project_name = "coax_setup_solved_231" - array = "array_simple_231" - sbr_file = "poc_scat_small_231" - q3d_file = "via_gsg_231" - m2d_file = "m2d_field_lines_test_231" - -else: - test_field_name = "Potter_Horn" - test_project_name = "coax_setup_solved" - array = "array_simple" - sbr_file = "poc_scat_small" - q3d_file = "via_gsg" - m2d_file = "m2d_field_lines_test" - -test_circuit_name = "Switching_Speed_FET_And_Diode" -eye_diagram = "SimpleChannel" -ami = "ami" -test_subfolder = "T12" -settings.enable_pandas_output = True - - -@pytest.fixture(scope="class") -def aedtapp(add_app): - app = add_app(project_name=test_project_name, subfolder=test_subfolder) - return app - - -class TestClass: - @pytest.fixture(autouse=True) - def init(self, aedtapp, local_scratch): - self.aedtapp = aedtapp - self.local_scratch = local_scratch - - @pytest.mark.skipif(config["NonGraphical"], reason="Failing on build machine when running in parallel.") - def test_01_export_model_picture(self): - path = self.aedtapp.post.export_model_picture(full_name=os.path.join(self.local_scratch.path, "images2.jpg")) - assert path - path = self.aedtapp.post.export_model_picture( - full_name=os.path.join(self.local_scratch.path, "images3.jpg"), - show_axis=True, - show_grid=False, - show_ruler=True, - ) - assert os.path.exists(path) - path = self.aedtapp.post.export_model_picture(full_name=os.path.join(self.local_scratch.path, "images4.jpg")) - assert path - - def test_01B_Field_Plot(self): - assert len(self.aedtapp.post.available_display_types()) > 0 - assert len(self.aedtapp.post.available_report_types) > 0 - assert len(self.aedtapp.post.available_report_quantities()) > 0 - assert len(self.aedtapp.post.available_report_solutions()) > 0 - cutlist = ["Global:XY", "Global:XZ", "Global:YZ"] - setup_name = self.aedtapp.existing_analysis_sweeps[0] - assert self.aedtapp.setups[0].is_solved - quantity_name = "ComplexMag_E" - intrinsic = {"Freq": "5GHz", "Phase": "180deg"} - min_value = self.aedtapp.post.get_scalar_field_value(quantity_name, "Minimum", setup_name, intrinsics="5GHz") - plot1 = self.aedtapp.post.create_fieldplot_cutplane(cutlist, quantity_name, setup_name, intrinsic) - plot1.IsoVal = "Tone" - plot1.update_field_plot_settings() - plot1.update() - assert self.aedtapp.post.field_plots[plot1.name].IsoVal == "Tone" - assert plot1.change_plot_scale(min_value, "30000") - assert self.aedtapp.post.create_fieldplot_volume("inner", "Vector_E", setup_name, intrinsic) - assert self.aedtapp.post.create_fieldplot_surface( - self.aedtapp.modeler["outer"].faces[0].id, "Mag_E", setup_name, intrinsic - ) - assert self.aedtapp.post.create_fieldplot_surface(self.aedtapp.modeler["outer"], "Mag_E", setup_name, intrinsic) - assert self.aedtapp.post.create_fieldplot_surface( - self.aedtapp.modeler["outer"].faces, "Mag_E", setup_name, intrinsic - ) - assert not self.aedtapp.post.create_fieldplot_surface(123123123, "Mag_E", setup_name, intrinsic) - assert len(self.aedtapp.setups[0].sweeps[0].frequencies) > 0 - assert isinstance(self.aedtapp.setups[0].sweeps[0].basis_frequencies, list) - assert len(self.aedtapp.setups[0].sweeps[1].basis_frequencies) == 2 - mesh_file_path = self.aedtapp.post.export_mesh_obj(setup_name, intrinsic) - assert os.path.exists(mesh_file_path) - mesh_file_path2 = self.aedtapp.post.export_mesh_obj( - setup_name, intrinsic, export_air_objects=True, on_surfaces=False - ) - assert os.path.exists(mesh_file_path2) - - min_value = self.aedtapp.post.get_scalar_field_value( - "E", "Minimum", setup_name, intrinsics="5GHz", is_vector=True - ) - - @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="Not running in ironpython") - def test_01_Animate_plt(self): - cutlist = ["Global:XY"] - phases = [str(i * 5) + "deg" for i in range(2)] - model_gif = self.aedtapp.post.plot_animated_field( - quantity="Mag_E", - assignment=cutlist, - plot_type="CutPlane", - setup=self.aedtapp.nominal_adaptive, - intrinsics={"Freq": "5GHz", "Phase": "0deg"}, - variation_variable="Phase", - variations=phases, - show=False, - export_gif=True, - export_path=self.local_scratch.path, - ) - assert os.path.exists(model_gif.gif_file) - setup_name = self.aedtapp.existing_analysis_sweeps[0] - intrinsic = {"Freq": "5GHz", "Phase": "180deg"} - pl1 = self.aedtapp.post.create_fieldplot_volume("NewObject_IJD39Q", "Mag_E", setup_name, intrinsic) - model_gif2 = self.aedtapp.post.animate_fields_from_aedtplt( - plot_name=pl1.name, - plot_folder=None, - variation_variable="Phase", - variations=phases, - project_path="", - export_gif=False, - show=False, - ) - model_gif2.gif_file = os.path.join(self.aedtapp.working_directory, "test2.gif") - model_gif2.camera_position = [0, 50, 200] - model_gif2.focal_point = [0, 50, 0] - model_gif2.animate() - assert os.path.exists(model_gif2.gif_file) - - @pytest.mark.skipif(config["NonGraphical"] == True, reason="Not running in non-graphical mode") - def test_02_export_fields(self): - quantity_name2 = "ComplexMag_H" - setup_name = "Setup1 : LastAdaptive" - intrinsic = {"Freq": "5GHz", "Phase": "180deg"} - vollist = ["NewObject_IJD39Q"] - plot2 = self.aedtapp.post.create_fieldplot_volume(vollist, quantity_name2, setup_name, intrinsic) - - self.aedtapp.post.export_field_jpg( - os.path.join(self.local_scratch.path, "prova2.jpg"), plot2.name, plot2.plot_folder - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "prova2.jpg")) - assert os.path.exists(plot2.export_image(os.path.join(self.local_scratch.path, "test_x.jpg"))) - - def test_03_create_scattering(self): - setup_name = "Setup1 : Sweep" - portnames = ["1", "2"] - assert self.aedtapp.create_scattering("MyTestScattering") - setup_name = "Setup2 : Sweep" - assert not self.aedtapp.create_scattering("MyTestScattering2", setup_name, portnames, portnames) - - def test_03_get_solution_data(self): - self.aedtapp.analyze(self.aedtapp.active_setup) - trace_names = [] - portnames = ["1", "2"] - for el in portnames: - for el2 in portnames: - trace_names.append("S(" + el + "," + el2 + ")") - cxt = ["Domain:=", "Sweep"] - families = {"Freq": ["All"]} - for el in self.aedtapp.available_variations.nominal_w_values_dict: - families[el] = self.aedtapp.available_variations.nominal_w_values_dict[el] - - my_data = self.aedtapp.post.get_solution_data(expressions=trace_names, variations=families) - assert my_data - assert my_data.expressions - assert len(my_data.data_db10(trace_names[0])) > 0 - assert len(my_data.data_imag(trace_names[0])) > 0 - assert len(my_data.data_real(trace_names[0])) > 0 - assert len(my_data.data_magnitude(trace_names[0])) > 0 - assert my_data.export_data_to_csv(os.path.join(self.local_scratch.path, "output.csv")) - assert os.path.exists(os.path.join(self.local_scratch.path, "output.csv")) - assert self.aedtapp.get_touchstone_data("Setup1") - - def test_04_export_touchstone(self): - setup_name = "Setup1" - sweep_name = "Sweep" - self.aedtapp.export_touchstone( - setup_name, sweep_name, os.path.join(self.local_scratch.path, "Setup1_Sweep.S2p") - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "Setup1_Sweep.S2p")) - - sweep_name = None - self.aedtapp.export_touchstone( - setup_name, sweep_name, os.path.join(self.local_scratch.path, "Setup1_Sweep2.S2p") - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "Setup1_Sweep2.S2p")) - setup_name = None - self.aedtapp.export_touchstone( - setup_name, sweep_name, os.path.join(self.local_scratch.path, "Setup1_Sweep3.S2p") - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "Setup1_Sweep3.S2p")) - - assert self.aedtapp.export_touchstone(setup_name, sweep_name) - - @pytest.mark.skipif(config["desktopVersion"] != "2023.1", reason="Not running in non-graphical mode") - def test_05_export_report_to_jpg(self): - self.aedtapp.post.export_report_to_jpg(self.local_scratch.path, "MyTestScattering") - assert os.path.exists(os.path.join(self.local_scratch.path, "MyTestScattering.jpg")) - - def test_06_export_report_to_csv(self): - self.aedtapp.post.export_report_to_csv( - self.local_scratch.path, - "MyTestScattering", - start="3GHz", - end="6GHz", - step="0.12GHz", - uniform=True, - use_trace_number_format=False, - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "MyTestScattering.csv")) - - def test_06_export_report_to_rdat(self): - self.aedtapp.post.export_report_to_file(self.local_scratch.path, "MyTestScattering", ".rdat") - assert os.path.exists(os.path.join(self.local_scratch.path, "MyTestScattering.rdat")) - - def test_07_export_fields_from_Calculator(self): - self.aedtapp.post.export_field_file_on_grid( - "E", - "Setup1 : LastAdaptive", - self.aedtapp.available_variations.nominal_w_values_dict, - os.path.join(self.local_scratch.path, "Efield.fld"), - grid_stop=[5, 5, 5], - grid_step=[0.5, 0.5, 0.5], - is_vector=True, - intrinsics="5GHz", - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "Efield.fld")) - - self.aedtapp.post.export_field_file_on_grid( - "Mag_E", - "Setup1 : LastAdaptive", - self.aedtapp.available_variations.nominal_w_values_dict, - os.path.join(self.local_scratch.path, "MagEfieldSph.fld"), - grid_type="Spherical", - grid_stop=[5, 300, 300], - grid_step=[5, 50, 50], - is_vector=False, - intrinsics="5GHz", - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "MagEfieldSph.fld")) - - self.aedtapp.post.export_field_file_on_grid( - "Mag_E", - "Setup1 : LastAdaptive", - self.aedtapp.available_variations.nominal_w_values_dict, - os.path.join(self.local_scratch.path, "MagEfieldCyl.fld"), - grid_type="Cylindrical", - grid_stop=[5, 300, 5], - grid_step=[5, 50, 5], - is_vector=False, - intrinsics="5GHz", - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "MagEfieldCyl.fld")) - - # @pytest.mark.skipif( - # config["NonGraphical"], reason="Skipped because it cannot run on build machine in non-graphical mode" - # ) - def test_07_copydata(self): - assert self.aedtapp.post.copy_report_data("MyTestScattering") - - def test_08_manipulate_report(self): - assert self.aedtapp.post.rename_report("MyTestScattering", "MyNewScattering") - assert [plot for plot in self.aedtapp.post.plots if plot.plot_name == "MyNewScattering"] - assert not self.aedtapp.post.rename_report("invalid", "MyNewScattering") - - def test_09_manipulate_report(self): - assert self.aedtapp.post.create_report("dB(S(1,1))") - assert self.aedtapp.post.create_report( - expressions="MaxMagDeltaS", - variations={"Pass": ["All"]}, - primary_sweep_variable="Pass", - report_category="Modal Solution Data", - plot_type="Rectangular Plot", - ) - new_report = self.aedtapp.post.reports_by_category.modal_solution("dB(S(1,1))") - assert new_report.create() - - data = self.aedtapp.post.get_solution_data("S(1,1)") - assert data.primary_sweep == "Freq" - assert data.expressions[0] == "S(1,1)" - assert len(self.aedtapp.post.all_report_names) > 0 - - new_report = self.aedtapp.post.reports_by_category.modal_solution( - "dB(S(1,1))", setup=self.aedtapp.nominal_sweep - ) - assert new_report.create() - - def test_09c_import_into_report(self): - new_report = self.aedtapp.create_scattering("import_test") - csv_file_path = self.aedtapp.post.export_report_to_csv(self.local_scratch.path, "import_test") - rdat_file_path = self.aedtapp.post.export_report_to_file(self.local_scratch.path, "import_test", ".rdat") - plot_name = new_report.plot_name - - trace_names = [] - trace_names.append(new_report.expressions[0]) - families = {"Freq": ["All"]} - for el in self.aedtapp.available_variations.nominal_w_values_dict: - families[el] = self.aedtapp.available_variations.nominal_w_values_dict[el] - - # get solution data and save in .csv file - my_data = self.aedtapp.post.get_solution_data(expressions=trace_names, variations=families) - my_data.export_data_to_csv(os.path.join(self.local_scratch.path, "output.csv")) - csv_solution_data_file_path = os.path.join(self.local_scratch.path, "output.csv") - assert not new_report.import_traces(csv_solution_data_file_path, plot_name) - - # test import with correct inputs from csv - assert new_report.import_traces(csv_file_path, plot_name) - # test import with correct inputs from rdat - assert new_report.import_traces(rdat_file_path, plot_name) - # test import with not existing plot_name - with pytest.raises(ValueError): - new_report.import_traces(csv_file_path, "plot_name") - # test import with random file path - with pytest.raises(FileExistsError): - new_report.import_traces(str(uuid.uuid4()), plot_name) - # test import without plot_name - with pytest.raises(ValueError): - new_report.import_traces(csv_file_path, None) - - def test_09d_delete_traces_from_report(self): - new_report = self.aedtapp.create_scattering("delete_traces_test") - traces_to_delete = [new_report.expressions[0]] - plot_name = new_report.plot_name - assert new_report.delete_traces(plot_name, traces_to_delete) - with pytest.raises(ValueError): - new_report.delete_traces("plot_name", traces_to_delete) - with pytest.raises(ValueError): - new_report.delete_traces(plot_name, ["V(out)_Test"]) - - def test_09e_add_traces_to_report(self): - new_report = self.aedtapp.create_scattering("add_traces_test") - traces = new_report.get_solution_data().expressions - assert new_report.add_trace_to_report(traces) - setup = self.aedtapp.post.plots[0].setup - variations = self.aedtapp.post.plots[0].variations["height"] = "10mm" - assert not new_report.add_trace_to_report(traces, setup, variations) - variations = self.aedtapp.post.plots[0].variations - assert new_report.add_trace_to_report(traces, setup, variations) - setup = "Transient" - assert not new_report.add_trace_to_report(traces, setup, variations) - - def test_09f_update_trace_name(self): - report = [plot for plot in self.aedtapp.post.plots if plot.plot_name == "add_traces_test"][0] - old_trace_name = report.traces[0].name - assert old_trace_name in report.traces[0].aedt_name - new_name = "update_trace_name_test" - report.traces[0].name = new_name - assert new_name in report.traces[0].aedt_name - - def test_09g_update_traces_in_report(self): - new_report = self.aedtapp.create_scattering("update_traces_test") - traces = new_report.get_solution_data().expressions - assert new_report.update_trace_in_report(traces) - setup = self.aedtapp.post.plots[0].setup - variations = self.aedtapp.post.plots[0].variations["height"] = "10mm" - assert not new_report.add_trace_to_report(traces, setup, variations) - variations = self.aedtapp.post.plots[0].variations - assert new_report.update_trace_in_report(traces, setup, variations) - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non-graphical mode in version earlier than 2022.2." - ) - def test_09h_create_monitor(self): # pragma: no cover - assert self.aedtapp.post.create_report("dB(S(1,1))") - new_report = self.aedtapp.post.reports_by_category.modal_solution("dB(S(1,1))") - assert new_report.create() - - assert new_report.add_cartesian_x_marker("3GHz") - assert new_report.add_cartesian_y_marker("-55") - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", - reason="Skipped because it cannot run on build machine in non-graphical mode", - ) - def test_09i_add_line_from_point(self): # pragma: no cover - new_report = self.aedtapp.post.reports_by_category.modal_solution("dB(S(1,1))") - assert new_report.create() - assert new_report.add_limit_line_from_points([3, 5, 5, 3], [-50, -50, -60, -60], "GHz") - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non-graphical mode in version earlier than 2022.2." - ) - def test_09l_add_line_from_equation(self): - new_report = self.aedtapp.post.reports_by_category.modal_solution("dB(S(1,1))") - assert new_report.create() - assert new_report.add_limit_line_from_equation(start_x=1, stop_x=20, step=0.5, units="GHz") - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non-graphical mode in version earlier than 2022.2." - ) - def test_09m_edit_properties(self): - report = self.aedtapp.post.create_report("dB(S(1,1))") - assert report.edit_grid() - assert report.edit_grid(minor_x=False) - assert report.edit_grid(major_y=False) - assert report.edit_grid(major_color=(0, 0, 125)) - assert report.edit_grid(major_color=(0, 255, 0)) - assert report.edit_grid(style_major="Dot") - assert report.edit_x_axis(font="Courier", font_size=14, italic=True, bold=False, color=(0, 128, 0)) - assert report.edit_y_axis(font="Courier", font_size=14, italic=True, bold=False, color=(0, 128, 0)) - assert report.edit_x_axis( - font="Courier", font_size=14, italic=True, bold=False, color=(0, 128, 0), label="Freq" - ) - assert report.edit_y_axis( - font="Courier", font_size=14, italic=True, bold=False, color=(0, 128, 0), label="Touchstone" - ) - - assert report.edit_x_axis_scaling( - linear_scaling=True, - min_scale="1GHz", - max_scale="5GHz", - minor_tick_divs=10, - min_spacing="0.5GHz", - units="MHz", - ) - assert report.edit_y_axis_scaling( - linear_scaling=False, min_scale="-50", max_scale="10", minor_tick_divs=10, min_spacing="5" - ) - assert report.edit_legend( - show_solution_name=True, show_variation_key=False, show_trace_name=False, back_color=(255, 255, 255) - ) - assert report.edit_header( - company_name="PyAEDT", - show_design_name=True, - font="Arial", - title_size=12, - subtitle_size=12, - italic=False, - bold=False, - color=(0, 125, 125), - ) - assert report.edit_general_settings( - background_color=(128, 255, 255), - plot_color=(255, 0, 255), - enable_y_stripes=True, - field_width=6, - precision=6, - use_scientific_notation=True, - ) - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non-graphical mode in version earlier than 2022.2." - ) - def test_09n_add_line_from_point(self): # pragma: no cover - new_report = self.aedtapp.post.reports_by_category.modal_solution("dB(S(1,1))") - new_report.create() - style = new_report.traces[0].LINESTYLE - trace = new_report.traces[0].TRACETYPE - symbols = new_report.traces[0].SYMBOLSTYLE - - assert new_report.traces[0].set_trace_properties( - trace_style=style.Dot, width=5, trace_type=trace.Digital, color=(0, 255, 0) - ) - assert new_report.traces[0].set_symbol_properties( - show=True, style=symbols.Box, show_arrows=False, fill=False, color=(0, 0, 255) - ) - new_report.add_limit_line_from_points([3, 5, 5, 3], [-50, -50, -60, -60], "GHz") - assert new_report.limit_lines[0].set_line_properties( - style=style.Dot, width=4, hatch_above=False, violation_emphasis=True, hatch_pixels=1, color=(255, 255, 0) - ) - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non-graphical mode in version earlier than 2022.2." - ) - def test_09o_add_note(self): # pragma: no cover - new_report = self.aedtapp.post.reports_by_category.modal_solution() - new_report.create() - - new_report.add_note("Test", 8000, 1500) - assert new_report.notes[0].set_note_properties( - back_color=(0, 0, 255), - border_visibility=False, - border_width=3, - font="Cambria", - italic=True, - bold=True, - font_size=10, - color=(255, 0, 0), - ) - - def test_10_delete_report(self): - plots_number = len(self.aedtapp.post.plots) - assert self.aedtapp.post.delete_report("MyNewScattering") - assert len(self.aedtapp.post.plots) == plots_number - 1 - assert self.aedtapp.post.delete_report() - assert len(self.aedtapp.post.plots) == 0 - - def test_12_steal_on_focus(self): - assert self.aedtapp.post.steal_focus_oneditor() - - @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="Not running in ironpython") - def test_14_Field_Ploton_cutplanedesignname(self): - cutlist = ["Global:XY"] - setup_name = self.aedtapp.existing_analysis_sweeps[0] - quantity_name = "ComplexMag_E" - intrinsic = {"Freq": "5GHz", "Phase": "180deg"} - self.aedtapp.logger.info("Generating the plot") - plot1 = self.aedtapp.post.create_fieldplot_cutplane(cutlist, quantity_name, setup_name, intrinsic) - plot1.IsoVal = "Tone" - assert plot1.update_field_plot_settings() - self.aedtapp.logger.info("Generating the image") - plot_obj = self.aedtapp.post.plot_field_from_fieldplot( - plot_name=plot1.name, - project_path=self.local_scratch.path, - mesh_plot=False, - image_format="jpg", - view="xy", - plot_label=plot1.name + " label", - show=False, - ) - assert os.path.exists(plot_obj.image_file) - os.unlink(plot_obj.image_file) - plot_obj.x_scale = 1.1 - plot_obj.y_scale = 0.9 - plot_obj.z_scale = 0.3 - assert plot_obj.x_scale == 1.1 - assert plot_obj.y_scale == 0.9 - assert plot_obj.z_scale == 0.3 - - plot_obj.background_image = os.path.join(self.local_scratch.path, "file_not_exists.jpg") - assert not plot_obj.background_image - plot_obj.convert_fields_in_db = True - plot_obj.log_multiplier = 20 - plot_obj.plot(plot_obj.image_file) - assert os.path.exists(plot_obj.image_file) - - plot_obj = self.aedtapp.post.plot_field_from_fieldplot( - plot_name=plot1.name, - project_path=self.local_scratch.path, - mesh_plot=False, - image_format="jpg", - view="xy", - plot_label=plot1.name + " label", - show=False, - file_format="aedtplt", - ) - assert os.path.exists(plot_obj.image_file) - plot_obj.plot(plot_obj.image_file) - - @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="Not running in IronPython.") - def test_14B_Field_Ploton_Vector(self): - cutlist = ["Global:XY"] - setup_name = self.aedtapp.existing_analysis_sweeps[0] - quantity_name = "Vector_E" - intrinsic = {"Freq": "5GHz", "Phase": "180deg"} - self.aedtapp.logger.info("Generating the plot") - plot1 = self.aedtapp.post.create_fieldplot_cutplane( - cutlist, quantity_name, setup_name, intrinsic, filter_objects=self.aedtapp.modeler.object_names - ) - plot1.IsoVal = "Tone" - assert plot1.update_field_plot_settings() - self.aedtapp.logger.info("Generating the image") - plot_obj = self.aedtapp.post.plot_field( - "Vector_E", - cutlist, - "CutPlane", - setup=setup_name, - intrinsics=intrinsic, - mesh_on_fields=False, - view="isometric", - show=False, - export_path=self.local_scratch.path, - image_format="jpg", - ) - assert os.path.exists(plot_obj.image_file) - - @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="Not running in ironpython") - def test_15_export_plot(self): - obj = self.aedtapp.post.plot_model_obj( - show=False, export_path=os.path.join(self.local_scratch.path, "image.jpg") - ) - assert os.path.exists(obj.image_file) - obj2 = self.aedtapp.post.plot_model_obj( - show=False, export_path=os.path.join(self.local_scratch.path, "image2.jpg"), plot_as_separate_objects=False - ) - assert os.path.exists(obj2.image_file) - - @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="Not running in ironpython") - def test_16_create_field_plot(self): - cutlist = ["Global:XY"] - plot = self.aedtapp.post._create_fieldplot( - assignment=cutlist, - quantity="Mag_E", - setup=self.aedtapp.nominal_adaptive, - intrinsics={}, - list_type="CutPlane", - ) - assert plot - - def test_53_line_plot(self): - udp1 = [0, 0, 0] - udp2 = [1, 0, 0] - setup_name = "Setup1 : LastAdaptive" - intrinsic = {"Freq": "5GHz", "Phase": "180deg"} - self.aedtapp.modeler.create_polyline([udp1, udp2], name="Poly1", non_model=True) - assert self.aedtapp.post.create_fieldplot_line("Poly1", "Mag_E", setup_name, intrinsic) - - def test_55_reload(self, add_app): - self.aedtapp.save_project() - app2 = add_app(project_name=self.aedtapp.project_name, just_open=True) - assert len(app2.post.field_plots) == len(self.aedtapp.post.field_plots) - - def test_58_test_no_report(self): - assert not self.aedtapp.post.reports_by_category.eye_diagram() - assert self.aedtapp.post.reports_by_category.eigenmode() - - def test_59_test_parse_vector(self): - local_path = os.path.dirname(os.path.realpath(__file__)) - - out = _parse_aedtplt(os.path.join(local_path, "example_models", test_subfolder, "test_vector.aedtplt")) - assert isinstance(out[0], list) - assert isinstance(out[1], list) - assert isinstance(out[2], list) - assert isinstance(out[3], bool) - assert _parse_aedtplt( - os.path.join(local_path, "example_models", test_subfolder, "test_vector_no_solutions.aedtplt") - ) - - def test_60_test_parse_vector(self): - local_path = os.path.dirname(os.path.realpath(__file__)) - out = _parse_streamline(os.path.join(local_path, "example_models", test_subfolder, "test_streamline.fldplt")) - assert isinstance(out, list) - - def test_61_export_mesh(self): - assert os.path.exists(self.aedtapp.export_mesh_stats("Setup1")) - - def test_67_sweep_from_json(self): - local_path = os.path.dirname(os.path.realpath(__file__)) - dict_vals = read_json(os.path.join(local_path, "example_models", "report_json", "Modal_Report_Simple.json")) - assert self.aedtapp.post.create_report_from_configuration(report_settings=dict_vals) - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" - ) - def test_70_sweep_from_json(self): - local_path = os.path.dirname(os.path.realpath(__file__)) - assert self.aedtapp.post.create_report_from_configuration( - os.path.join(local_path, "example_models", "report_json", "Modal_Report.json") - ) - - def test_74_dynamic_update(self): - val = self.aedtapp.post.update_report_dynamically - self.aedtapp.post.update_report_dynamically = not val - assert self.aedtapp.post.update_report_dynamically != val From 15fe8d0d65db1d1a3dc4e4433f09389f51c8f026 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Wed, 8 May 2024 12:50:06 +0200 Subject: [PATCH 08/29] Replace logger with warning --- pyaedt/generic/plot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaedt/generic/plot.py b/pyaedt/generic/plot.py index d1862d836b6..2a13ec9f3c8 100644 --- a/pyaedt/generic/plot.py +++ b/pyaedt/generic/plot.py @@ -124,7 +124,7 @@ def is_float(istring): try: return float(istring.strip()) except Exception: - settings.logger.error("Unable to convert '" + isring.strip() + "' to a float.") + warnings.warn("Unable to convert '" + isring.strip() + "' to a float.") return 0 From e23a5166b0756dd48e23ef2804ffee24d097a166 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Wed, 8 May 2024 12:54:27 +0200 Subject: [PATCH 09/29] Replace logger with warning --- pyaedt/generic/plot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyaedt/generic/plot.py b/pyaedt/generic/plot.py index 2a13ec9f3c8..c41a31dc821 100644 --- a/pyaedt/generic/plot.py +++ b/pyaedt/generic/plot.py @@ -124,7 +124,7 @@ def is_float(istring): try: return float(istring.strip()) except Exception: - warnings.warn("Unable to convert '" + isring.strip() + "' to a float.") + warnings.warn("Unable to convert '" + istring.strip() + "' to a float.") return 0 From 37c5aabfc7328d676f11b6e985361951ad11f68c Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Wed, 8 May 2024 13:43:50 +0200 Subject: [PATCH 10/29] Remove post processing tests --- _unittest/test_12_PostProcessing.py | 974 ---------------- _unittest/test_20_HFSS.py | 1638 --------------------------- 2 files changed, 2612 deletions(-) delete mode 100644 _unittest/test_12_PostProcessing.py delete mode 100644 _unittest/test_20_HFSS.py diff --git a/_unittest/test_12_PostProcessing.py b/_unittest/test_12_PostProcessing.py deleted file mode 100644 index 5f6e828181b..00000000000 --- a/_unittest/test_12_PostProcessing.py +++ /dev/null @@ -1,974 +0,0 @@ -import os -import sys - -from _unittest.conftest import config -import pytest - -from pyaedt import Circuit -from pyaedt import Icepak -from pyaedt import Maxwell2d -from pyaedt import Q2d -from pyaedt import Q3d -from pyaedt.generic.general_methods import is_linux -from pyaedt.generic.pdf import AnsysReport -from pyaedt.generic.plot import _parse_aedtplt -from pyaedt.generic.plot import _parse_streamline -from pyaedt.generic.settings import settings -from pyaedt.modules.solutions import FfdSolutionData - -if config["desktopVersion"] > "2022.2": - test_field_name = "Potter_Horn_231" - test_project_name = "coax_setup_solved_231" - array = "array_simple_231" - sbr_file = "poc_scat_small_231" - q3d_file = "via_gsg_231" - m2d_file = "m2d_field_lines_test_231" - -else: - test_field_name = "Potter_Horn" - test_project_name = "coax_setup_solved" - array = "array_simple" - sbr_file = "poc_scat_small" - q3d_file = "via_gsg" - m2d_file = "m2d_field_lines_test" - -test_circuit_name = "Switching_Speed_FET_And_Diode" -test_emi_name = "EMI_RCV_241" -eye_diagram = "SimpleChannel" -ami = "ami" -ipk_post_proj = "for_icepak_post" -test_subfolder = "T12" -settings.enable_pandas_output = True - - -@pytest.fixture(scope="class") -def field_test(add_app): - app = add_app(project_name=test_field_name, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def circuit_test(add_app): - app = add_app(project_name=test_circuit_name, design_name="Diode", application=Circuit, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def emi_receiver_test(add_app): - app = add_app(project_name=test_emi_name, design_name="CE_band", application=Circuit, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def diff_test(add_app, circuit_test): - app = add_app(project_name=circuit_test.project_name, design_name="diff", application=Circuit, just_open=True) - return app - - -@pytest.fixture(scope="class") -def sbr_test(add_app): - app = add_app(project_name=sbr_file, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def q3dtest(add_app): - app = add_app(project_name=q3d_file, application=Q3d, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def q2dtest(add_app, q3dtest): - app = add_app(project_name=q3dtest.project_name, application=Q2d, just_open=True) - return app - - -@pytest.fixture(scope="class") -def eye_test(add_app, q3dtest): - app = add_app(project_name=eye_diagram, application=Circuit, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def icepak_post(add_app): - app = add_app(project_name=ipk_post_proj, application=Icepak, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def ami_test(add_app, q3dtest): - app = add_app(project_name=ami, application=Circuit, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def array_test(add_app, q3dtest): - app = add_app(project_name=array, subfolder=test_subfolder, solution_type="Modal") - return app - - -@pytest.fixture(scope="class") -def m2dtest(add_app, q3dtest): - app = add_app(project_name=m2d_file, application=Maxwell2d, subfolder=test_subfolder) - return app - - -class TestClass: - @pytest.fixture(autouse=True) - def init(self, local_scratch): - self.local_scratch = local_scratch - - def test_09_manipulate_report(self, field_test): - variations = field_test.available_variations.nominal_w_values_dict - variations["Theta"] = ["All"] - variations["Phi"] = ["All"] - variations["Freq"] = ["30GHz"] - field_test.set_source_context(["1"]) - context = {"Context": "3D", "SourceContext": "1:1"} - assert field_test.post.create_report( - "db(GainTotal)", - field_test.nominal_adaptive, - variations=variations, - primary_sweep_variable="Phi", - secondary_sweep_variable="Theta", - report_category="Far Fields", - plot_type="3D Polar Plot", - context=context, - ) - assert field_test.post.create_report( - "db(GainTotal)", - field_test.nominal_adaptive, - variations=variations, - primary_sweep_variable="Phi", - secondary_sweep_variable="Theta", - report_category="Far Fields", - plot_type="3D Polar Plot", - context="3D", - ) - report = AnsysReport() - report.create() - assert report.add_project_info(field_test) - - def test_09_manipulate_report_B(self, field_test): - variations = field_test.available_variations.nominal_w_values_dict - variations["Theta"] = ["All"] - variations["Phi"] = ["All"] - variations["Freq"] = ["30GHz"] - new_report = field_test.post.reports_by_category.far_field("db(RealizedGainTotal)", field_test.nominal_adaptive) - new_report.variations = variations - new_report.report_type = "3D Polar Plot" - new_report.far_field_sphere = "3D" - assert new_report.create() - - new_report2 = field_test.post.reports_by_category.far_field( - "db(RealizedGainTotal)", field_test.nominal_adaptive, "3D", "1:1" - ) - new_report2.variations = variations - new_report2.report_type = "3D Polar Plot" - assert new_report2.create() - - new_report3 = field_test.post.reports_by_category.antenna_parameters( - "db(PeakRealizedGain)", field_test.nominal_adaptive, "3D" - ) - new_report3.report_type = "Data Table" - assert new_report3.create() - new_report4 = field_test.post.reports_by_category.antenna_parameters( - "db(PeakRealizedGain)", infinite_sphere="3D" - ) - new_report4.report_type = "Data Table" - assert new_report4.create() - - def test_09_manipulate_report_C(self, field_test): - variations = field_test.available_variations.nominal_w_values_dict - variations["Theta"] = ["All"] - variations["Phi"] = ["All"] - variations["Freq"] = ["30GHz"] - field_test.analyze(field_test.active_setup) - data = field_test.post.get_solution_data( - "GainTotal", - field_test.nominal_adaptive, - variations=variations, - primary_sweep_variable="Theta", - report_category="Far Fields", - context="3D", - ) - assert data.plot(is_polar=True) - assert data.plot_3d() - assert field_test.post.create_3d_plot(data) - - def test_09_manipulate_report_D(self, field_test): - variations = field_test.available_variations.nominal_w_values_dict - variations["Theta"] = ["All"] - variations["Phi"] = ["All"] - variations["Freq"] = ["30GHz"] - context = {"Context": "3D", "SourceContext": "1:1"} - data = field_test.post.get_solution_data( - "GainTotal", - field_test.nominal_adaptive, - variations=variations, - primary_sweep_variable="Theta", - report_category="Far Fields", - context=context, - ) - assert data.plot(is_polar=True) - assert data.plot_3d() - assert field_test.post.create_3d_plot(data) - assert data.primary_sweep == "Theta" - assert len(data.data_magnitude("GainTotal")) > 0 - assert not data.data_magnitude("GainTotal2") - assert field_test.post.create_report( - "S(1,1)", field_test.nominal_sweep, variations=variations, plot_type="Smith Chart" - ) - - def test_09_manipulate_report_E(self, field_test): - field_test.modeler.create_polyline([[0, 0, 0], [0, 5, 30]], name="Poly1", non_model=True) - variations2 = field_test.available_variations.nominal_w_values_dict - - assert field_test.setups[0].create_report( - "Mag_E", primary_sweep_variable="Distance", report_category="Fields", context="Poly1" - ) - new_report = field_test.post.reports_by_category.fields("Mag_H", field_test.nominal_adaptive) - new_report.variations = variations2 - new_report.polyline = "Poly1" - assert new_report.create() - new_report = field_test.post.reports_by_category.fields("Mag_H") - new_report.variations = variations2 - new_report.polyline = "Poly1" - assert new_report.create() - new_report = field_test.post.reports_by_category.modal_solution("S(1,1)") - new_report.report_type = "Smith Chart" - assert new_report.create() - data = field_test.setups[0].get_solution_data( - "Mag_E", variations=variations2, primary_sweep_variable="Theta", report_category="Fields", context="Poly1" - ) - assert data.units_sweeps["Phase"] == "deg" - - assert field_test.post.get_far_field_data( - expressions="RealizedGainTotal", setup_sweep_name=field_test.nominal_adaptive, domain="3D" - ) - data_farfield2 = field_test.post.get_far_field_data( - expressions="RealizedGainTotal", - setup_sweep_name=field_test.nominal_adaptive, - domain={"Context": "3D", "SourceContext": "1:1"}, - ) - assert data_farfield2.plot(formula="db20", is_polar=True) - - assert field_test.post.reports_by_category.terminal_solution() - - assert not field_test.post.get_solution_data_per_variation( - solution_type="Far Fields", expressions="RealizedGainTotal" - ) - - def test_09b_export_report_A(self, circuit_test): - files = circuit_test.export_results() - assert len(files) > 0 - report = AnsysReport() - report.create() - assert report.add_project_info(circuit_test) - - def test_09b_export_report_B(self, q2dtest): - q2dtest.analyze() - files = q2dtest.export_results() - assert len(files) > 0 - - def test_09b_export_report_C(self, q3dtest): - q3dtest.analyze_setup("Setup1") - files = q3dtest.export_results() - assert len(files) > 0 - - @pytest.mark.skipif(is_linux, reason="Crashing on Linux") - def test_17_circuit(self, circuit_test): - assert not circuit_test.setups[0].is_solved - - circuit_test.analyze_setup("LNA") - circuit_test.analyze_setup("Transient") - assert circuit_test.setups[0].is_solved - assert circuit_test.setups[0].create_report(["dB(S(Port1, Port1))", "dB(S(Port1, Port2))"]) - new_report = circuit_test.post.reports_by_category.standard( - ["dB(S(Port1, Port1))", "dB(S(Port1, Port2))"], "LNA" - ) - assert new_report.create() - data1 = circuit_test.post.get_solution_data(["dB(S(Port1,Port1))", "dB(S(Port1,Port2))"], "LNA") - assert data1.primary_sweep == "Freq" - assert circuit_test.post.create_report(["V(net_11)"], "Transient", "Time") - data11 = circuit_test.post.get_solution_data(setup_sweep_name="LNA", math_formula="dB") - assert data11.primary_sweep == "Freq" - assert "dB(S(Port2,Port1))" in data11.expressions - assert circuit_test.post.create_report(["V(net_11)"], "Transient", "Time") - new_report = circuit_test.post.reports_by_category.standard(["V(net_11)"], "Transient") - new_report.domain = "Time" - assert new_report.create() - data2 = circuit_test.post.get_solution_data(["V(net_11)"], "Transient", "Time") - assert data2.primary_sweep == "Time" - assert len(data2.data_magnitude()) > 0 - context = {"algorithm": "FFT", "max_frequency": "100MHz", "time_stop": "200ns", "test": ""} - data3 = circuit_test.post.get_solution_data(["V(net_11)"], "Transient", "Spectral", context=context) - assert data3.units_sweeps["Spectrum"] == circuit_test.odesktop.GetDefaultUnit("Frequency") - assert len(data3.data_real()) > 0 - new_report = circuit_test.post.reports_by_category.spectral(["dB(V(net_11))"], "Transient") - new_report.window = "Hanning" - new_report.max_freq = "1GHz" - new_report.time_start = "1ns" - new_report.time_stop = "190ns" - new_report.plot_continous_spectrum = True - assert new_report.create() - new_report = circuit_test.post.reports_by_category.spectral(["dB(V(net_11))"]) - assert new_report.create() - new_report = circuit_test.post.reports_by_category.spectral(["dB(V(net_11))", "dB(V(Port1))"], "Transient") - new_report.window = "Kaiser" - new_report.adjust_coherent_gain = False - new_report.kaiser_coeff = 2 - new_report.algorithm = "Fourier Transform" - new_report.max_freq = "1GHz" - new_report.time_start = "1ns" - new_report.time_stop = "190ns" - new_report.plot_continous_spectrum = False - assert new_report.create() - assert circuit_test.post.create_report(["dB(V(net_11))", "dB(V(Port1))"], domain="Spectrum") - new_report = circuit_test.post.reports_by_category.spectral(None, "Transient") - new_report.window = "Hanning" - new_report.max_freq = "1GHz" - new_report.time_start = "1ns" - new_report.time_stop = "190ns" - new_report.plot_continous_spectrum = True - assert new_report.create() - - @pytest.mark.skipif(is_linux, reason="Crashing on Linux") - def test_18_diff_plot(self, diff_test): - assert len(diff_test.post.available_display_types()) > 0 - assert len(diff_test.post.available_report_types) > 0 - assert len(diff_test.post.available_report_quantities()) > 0 - assert len(diff_test.post.available_report_solutions()) > 0 - diff_test.analyze_setup("LinearFrequency") - assert diff_test.setups[0].is_solved - variations = diff_test.available_variations.nominal_w_values_dict - variations["Freq"] = ["All"] - variations["l1"] = ["All"] - assert diff_test.post.create_report( - ["dB(S(Diff1, Diff1))"], - "LinearFrequency", - variations=variations, - primary_sweep_variable="l1", - context="Differential Pairs", - ) - new_report1 = diff_test.post.reports_by_category.standard() - assert new_report1.expressions - new_report = diff_test.post.reports_by_category.standard("dB(S(1,1))") - new_report.differential_pairs = True - assert new_report.create() - assert new_report.get_solution_data() - new_report2 = diff_test.post.reports_by_category.standard("TDRZ(1)") - new_report2.differential_pairs = True - new_report2.pulse_rise_time = 3e-12 - new_report2.time_windowing = 3 - new_report2.domain = "Time" - - assert new_report2.create() - - data1 = diff_test.post.get_solution_data( - ["S(Diff1, Diff1)"], - "LinearFrequency", - variations=variations, - primary_sweep_variable="Freq", - context="Differential Pairs", - ) - assert data1.primary_sweep == "Freq" - data1.plot(formula="db20", snapshot_path=os.path.join(self.local_scratch.path, "temp1.jpg")) - data1.primary_sweep = "l1" - assert data1.primary_sweep == "l1" - assert len(data1.data_magnitude()) == 5 - assert data1.plot("S(Diff1, Diff1)", snapshot_path=os.path.join(self.local_scratch.path, "temp2.jpg")) - assert data1.plot(formula="db20", snapshot_path=os.path.join(self.local_scratch.path, "temp3.jpg")) - assert data1.plot(formula="db10", snapshot_path=os.path.join(self.local_scratch.path, "temp4.jpg")) - assert data1.plot(formula="mag", snapshot_path=os.path.join(self.local_scratch.path, "temp5.jpg")) - assert data1.plot(formula="re", snapshot_path=os.path.join(self.local_scratch.path, "temp6.jpg")) - assert data1.plot(formula="im", snapshot_path=os.path.join(self.local_scratch.path, "temp7.jpg")) - assert data1.plot(formula="phasedeg", snapshot_path=os.path.join(self.local_scratch.path, "temp8.jpg")) - assert data1.plot(formula="phaserad", snapshot_path=os.path.join(self.local_scratch.path, "temp9.jpg")) - - assert diff_test.create_touchstone_report( - name="Diff_plot", curves=["dB(S(Diff1, Diff1))"], solution="LinearFrequency", differential_pairs=True - ) - - @pytest.mark.skipif(is_linux, reason="Failing on Linux") - def test_51_get_efields(self, field_test): - assert field_test.post.get_efields_data(ff_setup="3D") - - @pytest.mark.skipif( - is_linux or sys.version_info < (3, 8), reason="plot_scene method is not supported in ironpython" - ) - def test_55_time_plot(self, sbr_test): - sbr_test.analyze(sbr_test.active_setup, use_auto_settings=False) - assert sbr_test.setups[0].is_solved - solution_data = sbr_test.post.get_solution_data( - expressions=["NearEX", "NearEY", "NearEZ"], report_category="Near Fields", context="Near_Field" - ) - assert solution_data - assert len(solution_data.primary_sweep_values) > 0 - assert len(solution_data.primary_sweep_variations) > 0 - assert solution_data.set_active_variation(0) - assert not solution_data.set_active_variation(99) - t_matrix = solution_data.ifft("NearE", window=True) - assert t_matrix.any() - frames_list = solution_data.ifft_to_file( - coord_system_center=[-0.15, 0, 0], db_val=True, csv_path=os.path.join(sbr_test.working_directory, "csv") - ) - assert os.path.exists(frames_list) - sbr_test.post.plot_scene( - frames_list, os.path.join(sbr_test.working_directory, "animation.gif"), norm_index=5, dy_rng=35, show=False - ) - assert os.path.exists(os.path.join(sbr_test.working_directory, "animation.gif")) - sbr_test.post.plot_scene( - frames_list, - os.path.join(sbr_test.working_directory, "animation2.gif"), - norm_index=5, - dy_rng=35, - show=False, - convert_fields_in_db=True, - log_multiplier=20.0, - ) - assert os.path.exists(os.path.join(sbr_test.working_directory, "animation2.gif")) - - def test_56_test_export_q3d_results(self, q3dtest): - q3dtest.analyze(q3dtest.active_setup) - assert os.path.exists(q3dtest.export_convergence("Setup1")) - assert os.path.exists(q3dtest.export_profile("Setup1")) - new_report = q3dtest.post.reports_by_category.standard(q3dtest.get_traces_for_plot()) - assert new_report.create() - q3dtest.modeler.create_polyline([[0, -5, 0.425], [0.5, 5, 0.5]], name="Poly1", non_model=True) - new_report = q3dtest.post.reports_by_category.cg_fields("SmoothQ", polyline="Poly1") - assert new_report.create() - new_report = q3dtest.post.reports_by_category.rl_fields("Mag_SurfaceJac", polyline="Poly1") - assert new_report.create() - new_report = q3dtest.post.reports_by_category.dc_fields("Mag_VolumeJdc", polyline="Poly1") - assert new_report.create() - assert len(q3dtest.post.plots) == 6 - - def test_57_test_export_q2d_results(self, q2dtest): - q2dtest.analyze(q2dtest.active_setup) - assert os.path.exists(q2dtest.export_convergence("Setup1")) - assert os.path.exists(q2dtest.export_profile("Setup1")) - new_report = q2dtest.post.reports_by_category.standard(q2dtest.get_traces_for_plot()) - assert new_report.create() - q2dtest.modeler.create_polyline([[-1.9, -0.1, 0], [-1.2, -0.2, 0]], name="Poly1", non_model=True) - new_report = q2dtest.post.reports_by_category.cg_fields("Mag_E", polyline="Poly1") - assert new_report.create() - new_report = q2dtest.post.reports_by_category.rl_fields("Mag_H", polyline="Poly1") - assert new_report.create() - sol = new_report.get_solution_data() - sol.enable_pandas_output = True - data = sol.full_matrix_real_imag - data_mag = sol.full_matrix_mag_phase - sol.data_magnitude() - sol.enable_pandas_output = False - assert len(q2dtest.post.plots) == 3 - new_report = q2dtest.post.reports_by_category.standard() - assert new_report.get_solution_data() - - def test_58_test_no_report(self, q3dtest): - assert not q3dtest.post.reports_by_category.modal_solution() - assert not q3dtest.post.reports_by_category.terminal_solution() - - def test_58_test_no_report_B(self, q2dtest): - assert not q2dtest.post.reports_by_category.far_field() - assert not q2dtest.post.reports_by_category.near_field() - assert not q2dtest.post.reports_by_category.eigenmode() - - def test_59_test_parse_vector(self): - local_path = os.path.dirname(os.path.realpath(__file__)) - - out = _parse_aedtplt(os.path.join(local_path, "example_models", test_subfolder, "test_vector.aedtplt")) - assert isinstance(out[0], list) - assert isinstance(out[1], list) - assert isinstance(out[2], list) - assert isinstance(out[3], bool) - assert _parse_aedtplt( - os.path.join(local_path, "example_models", test_subfolder, "test_vector_no_solutions.aedtplt") - ) - - def test_60_test_parse_vector(self): - local_path = os.path.dirname(os.path.realpath(__file__)) - out = _parse_streamline(os.path.join(local_path, "example_models", test_subfolder, "test_streamline.fldplt")) - assert isinstance(out, list) - - def test_61_export_mesh(self, q3dtest): - assert os.path.exists(q3dtest.export_mesh_stats("Setup1")) - assert os.path.exists(q3dtest.export_mesh_stats("Setup1", setup_type="AC RL")) - - def test_62_eye_diagram(self, eye_test): - eye_test.analyze(eye_test.active_setup) - rep = eye_test.post.reports_by_category.eye_diagram("AEYEPROBE(OutputEye)", "QuickEyeAnalysis") - rep.time_start = "0ps" - rep.time_stop = "50us" - rep.unit_interval = "1e-9" - assert rep.create() - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" - ) - def test_63_mask(self, eye_test): - eye_test.analyze(eye_test.active_setup) - rep = eye_test.post.reports_by_category.eye_diagram("AEYEPROBE(OutputEye)", "QuickEyeAnalysis") - rep.time_start = "0ps" - rep.time_stop = "50us" - rep.unit_interval = "1e-9" - rep.create() - assert rep.eye_mask([[0.5, 0], [0.62, 450], [1.2, 450], [1.42, 0], [1.2, -450], [0.62, -450], [0.5, 0]]) - assert rep.eye_mask( - [[0.5, 0], [0.62, 450], [1.2, 450], [1.42, 0], [1.2, -450], [0.62, -450], [0.5, 0]], - enable_limits=True, - upper_limit=800, - lower_limit=-800, - ) - assert os.path.exists(rep.export_mask_violation()) - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" - ) - def test_64_eye_meas(self, eye_test): - eye_test.analyze(eye_test.active_setup) - rep = eye_test.post.reports_by_category.eye_diagram("AEYEPROBE(OutputEye)", "QuickEyeAnalysis") - rep.time_start = "0ps" - rep.time_stop = "50us" - rep.unit_interval = "1e-9" - rep.create() - assert rep.add_all_eye_measurements() - assert rep.clear_all_eye_measurements() - assert rep.add_trace_characteristics("MinEyeHeight") - - def test_65_eye_from_json(self, eye_test): - local_path = os.path.dirname(os.path.realpath(__file__)) - assert eye_test.post.create_report_from_configuration( - os.path.join(local_path, "example_models", "report_json", "EyeDiagram_Report_simple.json"), - solution_name="QuickEyeAnalysis", - ) - - def test_66_spectral_from_json(self, circuit_test): - local_path = os.path.dirname(os.path.realpath(__file__)) - circuit_test.analyze_setup("Transient") - assert circuit_test.post.create_report_from_configuration( - os.path.join(local_path, "example_models", "report_json", "Spectral_Report_Simple.json"), - solution_name="Transient", - ) - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" - ) - def test_68_eye_from_json(self, eye_test): - local_path = os.path.dirname(os.path.realpath(__file__)) - assert eye_test.post.create_report_from_configuration( - os.path.join(local_path, "example_models", "report_json", "EyeDiagram_Report.toml"), - solution_name="QuickEyeAnalysis", - ) - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" - ) - def test_69_spectral_from_json(self, circuit_test): - local_path = os.path.dirname(os.path.realpath(__file__)) - circuit_test.analyze_setup("Transient") - assert circuit_test.post.create_report_from_configuration( - os.path.join(local_path, "example_models", "report_json", "Spectral_Report.json"), solution_name="Transient" - ) - - def test_70_far_field_data(self): - local_path = os.path.dirname(os.path.realpath(__file__)) - eep_file1 = os.path.join(local_path, "example_models", test_subfolder, "eep", "eep.txt") - eep_file2 = os.path.join(local_path, "example_models", test_subfolder, "eep", "eep.txt") - frequencies = [0.9e9, "0.9GHz"] - eep_files = [eep_file1, eep_file2] - - ffdata = FfdSolutionData(frequencies=frequencies[1], eep_files=eep_file1) - assert len(ffdata.frequencies) == 1 - - ffdata = FfdSolutionData(frequencies=frequencies, eep_files=eep_files) - assert len(ffdata.frequencies) == 2 - farfield = ffdata.combine_farfield() - assert "rETheta" in farfield - - ffdata.taper = "cosine" - assert ffdata.combine_farfield() - ffdata.taper = "taper" - assert not ffdata.taper == "taper" - - ffdata.origin = [0, 2] - assert ffdata.origin != [0, 2] - ffdata.origin = [0, 0, 1] - assert ffdata.origin == [0, 0, 1] - - img1 = os.path.join(self.local_scratch.path, "ff_2d1.jpg") - ffdata.plot_2d_cut(primary_sweep="Theta", secondary_sweep_value="all", image_path=img1) - assert os.path.exists(img1) - img2 = os.path.join(self.local_scratch.path, "ff_2d2.jpg") - ffdata.plot_2d_cut(secondary_sweep_value=[0, 1], image_path=img2) - assert os.path.exists(img2) - img3 = os.path.join(self.local_scratch.path, "ff_2d2.jpg") - ffdata.plot_2d_cut(image_path=img3) - assert os.path.exists(img3) - curve_2d = ffdata.plot_2d_cut(show=False) - assert len(curve_2d[0]) == 3 - data = ffdata.polar_plot_3d(show=False) - assert len(data) == 3 - - img4 = os.path.join(self.local_scratch.path, "ff_3d1.jpg") - ffdata.polar_plot_3d_pyvista( - quantity="RealizedGain", - image_path=img4, - show=False, - background=[255, 0, 0], - show_geometry=False, - convert_to_db=True, - ) - assert os.path.exists(img4) - data_pyvista = ffdata.polar_plot_3d_pyvista( - quantity="RealizedGain", show=False, background=[255, 0, 0], show_geometry=False, convert_to_db=True - ) - assert data_pyvista - - @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="FarFieldSolution not supported by IronPython") - def test_71_antenna_plot(self, field_test): - ffdata = field_test.get_antenna_ffd_solution_data(frequencies=30e9, sphere="3D") - ffdata.phase_offset = [0, 90] - assert ffdata.phase_offset == [0, 90] - ffdata.phase_offset = [0] - assert ffdata.phase_offset != [0.0] - assert ffdata.plot_farfield_contour( - quantity="RealizedGain", - title="Contour at {}Hz".format(ffdata.frequency), - image_path=os.path.join(self.local_scratch.path, "contour.jpg"), - convert_to_db=True, - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "contour.jpg")) - - ffdata.plot_2d_cut( - quantity="RealizedGain", - primary_sweep="theta", - secondary_sweep_value=[-180, -75, 75], - title="Azimuth at {}Hz".format(ffdata.frequency), - image_path=os.path.join(self.local_scratch.path, "2d1.jpg"), - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "2d1.jpg")) - ffdata.plot_2d_cut( - quantity="RealizedGain", - primary_sweep="phi", - secondary_sweep_value=30, - title="Azimuth at {}Hz".format(ffdata.frequency), - image_path=os.path.join(self.local_scratch.path, "2d2.jpg"), - ) - - assert os.path.exists(os.path.join(self.local_scratch.path, "2d2.jpg")) - - ffdata.polar_plot_3d( - quantity="RealizedGain", image_path=os.path.join(self.local_scratch.path, "3d1.jpg"), convert_to_db=True - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "3d1.jpg")) - - ffdata.polar_plot_3d_pyvista( - quantity="RealizedGain", - image_path=os.path.join(self.local_scratch.path, "3d2.jpg"), - show=False, - convert_to_db=True, - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "3d2.jpg")) - - try: - p = ffdata.polar_plot_3d_pyvista(quantity="RealizedGain", show=False, convert_to_db=True) - assert isinstance(p, object) - except Exception: - assert True - - @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="FarFieldSolution not supported by IronPython") - def test_72_antenna_plot(self, array_test): - ffdata = array_test.get_antenna_ffd_solution_data(frequencies=3.5e9, sphere="3D") - ffdata.frequency = 3.5e9 - assert ffdata.plot_farfield_contour( - quantity="RealizedGain", - title="Contour at {}Hz".format(ffdata.frequency), - image_path=os.path.join(self.local_scratch.path, "contour.jpg"), - convert_to_db=True, - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "contour.jpg")) - - ffdata.plot_2d_cut( - quantity="RealizedGain", - primary_sweep="theta", - secondary_sweep_value=[-180, -75, 75], - title="Azimuth at {}Hz".format(ffdata.frequency), - image_path=os.path.join(self.local_scratch.path, "2d1.jpg"), - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "2d1.jpg")) - ffdata.plot_2d_cut( - quantity="RealizedGain", - primary_sweep="phi", - secondary_sweep_value=30, - title="Azimuth at {}Hz".format(ffdata.frequency), - image_path=os.path.join(self.local_scratch.path, "2d2.jpg"), - ) - - assert os.path.exists(os.path.join(self.local_scratch.path, "2d2.jpg")) - - ffdata.polar_plot_3d( - quantity="RealizedGain", image_path=os.path.join(self.local_scratch.path, "3d1.jpg"), convert_to_db=True - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "3d1.jpg")) - - ffdata.polar_plot_3d_pyvista( - quantity="RealizedGain", - image_path=os.path.join(self.local_scratch.path, "3d2.jpg"), - show=False, - convert_to_db=True, - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "3d2.jpg")) - ffdata1 = array_test.get_antenna_ffd_solution_data(frequencies=3.5e9, sphere="3D", overwrite=False) - assert ffdata1.plot_farfield_contour( - quantity="RealizedGain", - title="Contour at {}Hz".format(ffdata1.frequency), - image_path=os.path.join(self.local_scratch.path, "contour1.jpg"), - convert_to_db=True, - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "contour1.jpg")) - - def test_73_ami_solution_data(self, ami_test): - ami_test.solution_type = "NexximAMI" - assert ami_test.post.get_solution_data( - expressions="WaveAfterProbe", - domain="Time", - variations=ami_test.available_variations.nominal, - ) - - assert ami_test.post.get_solution_data( - expressions="WaveAfterSource", - domain="Time", - variations=ami_test.available_variations.nominal, - ) - - assert ami_test.post.get_solution_data( - expressions="InitialWave", - domain="Time", - variations=ami_test.available_variations.nominal, - ) - - assert ami_test.post.get_solution_data( - expressions="WaveAfterChannel", - domain="Time", - variations=ami_test.available_variations.nominal, - ) - - assert ami_test.post.get_solution_data( - expressions="ClockTics", - domain="Clock Times", - variations=ami_test.available_variations.nominal, - ) - probe_name = "b_input_43" - source_name = "b_output4_42" - plot_type = "WaveAfterProbe" - setup_name = "AMIAnalysis" - - ignore_bits = 1000 - unit_interval = 0.1e-9 - assert not ami_test.post.sample_ami_waveform( - setup_name, - probe_name, - source_name, - ami_test.available_variations.nominal, - unit_interval, - ignore_bits, - plot_type, - ) - ignore_bits = 5 - unit_interval = 0.1e-9 - plot_type = "InitialWave" - data1 = ami_test.post.sample_ami_waveform( - setup_name, - probe_name, - source_name, - ami_test.available_variations.nominal, - unit_interval, - ignore_bits, - plot_type, - ) - assert len(data1[0]) == 45 - - settings.enable_pandas_output = False - ignore_bits = 5 - unit_interval = 0.1e-9 - clock_tics = [1e-9, 2e-9, 3e-9] - data2 = ami_test.post.sample_ami_waveform( - setup_name, - probe_name, - source_name, - ami_test.available_variations.nominal, - unit_interval, - ignore_bits, - plot_type=None, - clock_tics=clock_tics, - ) - assert len(data2) == 4 - assert len(data2[0]) == 3 - - def test_75_plot_field_line_traces(self, m2dtest): - m2dtest.modeler.model_units = "mm" - rect = m2dtest.modeler.create_rectangle( - origin=["1mm", "5mm", "0mm"], sizes=["-1mm", "-10mm", 0], name="Ground", material="copper" - ) - rect.solve_inside = False - circle = m2dtest.modeler.create_circle( - position=["-10mm", "0", "0"], - radius="1mm", - num_sides="0", - is_covered=True, - name="Electrode", - material="copper", - ) - circle.solve_inside = False - m2dtest.modeler.create_region([20, 100, 20, 100]) - assert not m2dtest.post.create_fieldplot_line_traces("Ground", "Region", "Ground", plot_name="LineTracesTest") - m2dtest.solution_type = "Electrostatic" - assert not m2dtest.post.create_fieldplot_line_traces("Invalid", "Region", "Ground", plot_name="LineTracesTest1") - assert not m2dtest.post.create_fieldplot_line_traces("Ground", "Invalid", "Ground", plot_name="LineTracesTest2") - assert not m2dtest.post.create_fieldplot_line_traces("Ground", "Region", "Invalid", plot_name="LineTracesTest3") - m2dtest.assign_voltage(rect.name, amplitude=0, name="Ground") - m2dtest.assign_voltage(circle.name, amplitude=50e6, name="50kV") - setup_name = "test" - m2dtest.create_setup(name=setup_name) - m2dtest.analyze_setup(setup_name) - plot = m2dtest.post.create_fieldplot_line_traces(["Ground", "Electrode"], "Region", plot_name="LineTracesTest4") - assert plot - assert m2dtest.post.create_fieldplot_line_traces( - ["Ground", "Electrode"], "Region", "Ground", plot_name="LineTracesTest5" - ) - assert m2dtest.post.create_fieldplot_line_traces(["Ground", "Electrode"], plot_name="LineTracesTest6") - assert not m2dtest.post.create_fieldplot_line_traces( - ["Ground", "Electrode"], "Region", ["Invalid"], plot_name="LineTracesTest7" - ) - assert not m2dtest.post.create_fieldplot_line_traces( - ["Ground", "Electrode"], ["Invalid"], plot_name="LineTracesTest8" - ) - plot.TraceStepLength = "0.002mm" - plot.SeedingPointsNumber = 20 - plot.LineStyle = "Cylinder" - plot.LineWidth = 3 - assert plot.update() - el_id = [obj.id for obj in m2dtest.modeler.object_list if obj.name == "Electrode"] - plot.seeding_faces.append(el_id[0]) - assert plot.update() - plot.volumes.append(el_id[0]) - plot.update() - plot.surfaces.append(el_id[0]) - plot.update() - plot.seeding_faces.append(8) - assert not plot.update() - plot.volumes.append(8) - assert not plot.update() - plot.surfaces.append(8) - assert not plot.update() - - @pytest.mark.skipif(config["desktopVersion"] < "2024.1", reason="EMI receiver available from 2024R1.") - def test_76_emi_receiver(self, emi_receiver_test): - emi_receiver_test.analyze() - new_report = emi_receiver_test.post.reports_by_category.emi_receiver() - new_report.band = "2" - new_report.emission = "RE" - new_report.time_start = "1ns" - new_report.time_stop = "2us" - new_report.net = "net_invented" - assert new_report.net != "net_invented" - assert new_report.create() - new_report2 = emi_receiver_test.post.reports_by_category.emi_receiver( - ["dBu(Average[net_6])", "dBu(Peak[net_6])", "dBu(QuasiPeak[net_6])", "dBu(RMS[net_6])"], "EMItransient" - ) - assert new_report2.net == "net_6" - new_report2.time_stop = "2.5us" - assert new_report2.create() - - def test_98_get_variations(self, field_test): - vars = field_test.available_variations.get_variation_strings() - assert vars - variations = field_test.available_variations.variations() - assert isinstance(variations, list) - assert isinstance(variations[0], list) - vars_dict = field_test.available_variations.variations(output_as_dict=True) - assert isinstance(vars_dict, list) - assert isinstance(vars_dict[0], dict) - - def test_z99_delete_variations(self, q3dtest): - assert q3dtest.cleanup_solution() - - def test_z99_delete_variations_B(self, field_test): - vars = field_test.available_variations.get_variation_strings() - assert field_test.cleanup_solution(vars, entire_solution=False) - assert field_test.cleanup_solution(vars, entire_solution=True) - - def test_76_ipk_get_scalar_field_value(self, icepak_post): - assert icepak_post.post.get_scalar_field_value( - "Heat_Flow_Rate", - scalar_function="Integrate", - solution=None, - variations={"power_block": "0.25W", "power_source": "0.075W"}, - is_vector=False, - intrinsics=None, - phase=None, - object_name="cube2", - object_type="surface", - adjacent_side=False, - ) - assert icepak_post.post.get_scalar_field_value( - "Heat_Flow_Rate", - scalar_function="Integrate", - solution=None, - variations={"power_block": "0.6W", "power_source": "0.15W"}, - is_vector=False, - intrinsics=None, - phase=None, - object_name="cube2", - object_type="surface", - adjacent_side=False, - ) - assert icepak_post.post.get_scalar_field_value( - "Heat_Flow_Rate", - scalar_function="Integrate", - solution=None, - variations={"power_block": "0.6W", "power_source": "0.15W"}, - is_vector=False, - intrinsics=None, - phase=None, - object_name="cube2", - object_type="surface", - adjacent_side=True, - ) - assert icepak_post.post.get_scalar_field_value( - "Temperature", - scalar_function="Maximum", - solution=None, - variations={"power_block": "0.6W", "power_source": "0.15W"}, - is_vector=False, - intrinsics=None, - phase=None, - object_name="cube1", - object_type="volume", - adjacent_side=False, - ) - assert icepak_post.post.get_scalar_field_value( - "Temperature", - scalar_function="Maximum", - solution=None, - variations={"power_block": "0.6W", "power_source": "0.15W"}, - is_vector=False, - intrinsics=None, - phase=None, - object_name="cube2", - object_type="surface", - adjacent_side=False, - ) - assert icepak_post.post.get_scalar_field_value( - "Temperature", - scalar_function="Value", - solution=None, - variations=None, - is_vector=False, - intrinsics=None, - phase=None, - object_name="Point1", - object_type="point", - adjacent_side=False, - ) diff --git a/_unittest/test_20_HFSS.py b/_unittest/test_20_HFSS.py deleted file mode 100644 index bc7a6d1e34c..00000000000 --- a/_unittest/test_20_HFSS.py +++ /dev/null @@ -1,1638 +0,0 @@ -import math -import os -import shutil - -from _unittest.conftest import config -from _unittest.conftest import local_path -from _unittest.conftest import settings -import pytest - -small_number = 1e-10 # Used for checking equivalence. - -from pyaedt.generic.near_field_import import convert_nearfield_data - -test_subfolder = "T20" - -if config["desktopVersion"] > "2022.2": - component = "Circ_Patch_5GHz_232.a3dcomp" -else: - component = "Circ_Patch_5GHz.a3dcomp" - -if config["desktopVersion"] > "2023.1": - diff_proj_name = "differential_pairs_231" -else: - diff_proj_name = "differential_pairs" - -component_array = "Array_232" - - -@pytest.fixture(scope="class") -def aedtapp(add_app): - app = add_app(project_name="Test_20", design_name="test_20") - return app - - -@pytest.fixture(scope="class") -def fall_back_name(aedtapp): - name = aedtapp.design_name - return name - - -class TestClass: - @pytest.fixture(autouse=True) - def init(self, aedtapp, fall_back_name, local_scratch): - self.aedtapp = aedtapp - self.fall_back_name = fall_back_name - self.local_scratch = local_scratch - - def test_01_save(self): - project_name = "Test_Exercse201119" - test_project = os.path.join(self.local_scratch.path, project_name + ".aedt") - self.aedtapp.save_project(test_project) - assert os.path.exists(test_project) - - def test_01A_check_setup(self): - assert self.aedtapp.active_setup is None - - def test_02_create_primitive(self): - coax1_len = 200 - coax2_len = 70 - r1 = 3.0 - r2 = 10.0 - r1_sq = 9.0 # Used to test area later. - coax1_origin = self.aedtapp.modeler.Position(0, 0, 0) # Thru coax origin. - coax2_origin = self.aedtapp.modeler.Position(125, 0, -coax2_len) # Perpendicular coax 1. - - inner_1 = self.aedtapp.modeler.create_cylinder(self.aedtapp.AXIS.X, coax1_origin, r1, coax1_len, 0, "inner_1") - assert isinstance(inner_1.id, int) - inner_2 = self.aedtapp.modeler.create_cylinder( - self.aedtapp.AXIS.Z, coax2_origin, r1, coax2_len, 0, "inner_2", material="copper" - ) - assert len(inner_2.faces) == 3 # Cylinder has 3 faces. - # Check area of circular face. - assert abs(min([f.area for f in inner_2.faces]) - math.pi * r1_sq) < small_number - outer_1 = self.aedtapp.modeler.create_cylinder(self.aedtapp.AXIS.X, coax1_origin, r2, coax1_len, 0, "outer_1") - assert isinstance(outer_1.id, int) - outer_2 = self.aedtapp.modeler.create_cylinder(self.aedtapp.AXIS.Z, coax2_origin, r2, coax2_len, 0, "outer_2") - - # Check the area of the outer surface of the cylinder "outer_2". - assert abs(max([f.area for f in outer_2.faces]) - 2 * coax2_len * r2 * math.pi) < small_number - inner = self.aedtapp.modeler.unite( - ["inner_1", "inner_2"], - ) - outer = self.aedtapp.modeler.unite( - ["outer_1", "outer_2"], - ) - assert outer == "outer_1" - assert inner == "inner_1" - assert self.aedtapp.modeler.subtract(outer_1, inner_1, keep_originals=True) - - def test_03_2_assign_material(self): - udp = self.aedtapp.modeler.Position(0, 0, 0) - coax_length = 80 - cyl_1 = self.aedtapp.modeler.create_cylinder(self.aedtapp.AXIS.X, udp, 10, coax_length, 0, "insulator") - self.aedtapp.modeler.subtract(cyl_1, "inner_1", keep_originals=True) - self.aedtapp.modeler["inner_1"].material_name = "Copper" - cyl_1.material_name = "teflon_based" - assert self.aedtapp.modeler["inner_1"].material_name == "copper" - assert cyl_1.material_name == "teflon_based" - - def test_04_assign_coating(self): - id = self.aedtapp.modeler.get_obj_id( - "inner_1", - ) - args = { - "mat": "aluminum", - "usethickness": True, - "thickness": "0.5mm", - "istwoside": True, - "issheelElement": True, # TODO: Is "sheelElement" a typo in native API? - "usehuray": True, - "radius": "0.75um", - "ratio": "3", - } - coat = self.aedtapp.assign_coating([id, "inner_1", 41], **args) - coat.name = "Coating1inner" - assert coat.update() - assert coat.object_properties - material = coat.props.get("Material", "") - assert material == "aluminum" - assert not self.aedtapp.assign_coating(["insulator2", 45]) - - def test_05_create_wave_port_from_sheets(self): - udp = self.aedtapp.modeler.Position(0, 0, 0) - o5 = self.aedtapp.modeler.create_circle(self.aedtapp.PLANE.YZ, udp, 10, name="sheet1") - self.aedtapp.solution_type = "Terminal" - outer_1 = self.aedtapp.modeler["outer_1"] - # TODO: Consider allowing a TEM port to be created. - assert not self.aedtapp.wave_port(o5) - - port = self.aedtapp.wave_port( - assignment=o5, - reference=[outer_1.name], - integration_line=self.aedtapp.AxisDir.XNeg, - modes=2, - impedance=40, - name="sheet1_Port", - renormalize=False, - deembed=5, - terminals_rename=False, - ) - - assert port.object_properties - assert port.name == "sheet1_Port" - assert port.name in [i.name for i in self.aedtapp.boundaries] - assert port.props["RenormalizeAllTerminals"] is False - - udp = self.aedtapp.modeler.Position(80, 0, 0) - o6 = self.aedtapp.modeler.create_circle(self.aedtapp.PLANE.YZ, udp, 10, name="sheet1a") - self.aedtapp.modeler.subtract(o6, "inner_1", keep_originals=True) - - port = self.aedtapp.wave_port( - assignment=o6, - reference=[outer_1.name], - create_pec_cap=True, - integration_line=self.aedtapp.AxisDir.XNeg, - modes=2, - impedance=40, - name="sheet1a_Port", - renormalize=True, - deembed=0, - ) - assert port.name == "sheet1a_Port" - assert port.name in [i.name for i in self.aedtapp.boundaries] - assert port.props["DoDeembed"] is False - - # Get the object for "outer_1". - outer_1 = self.aedtapp.modeler["outer_1"] - bottom_port = self.aedtapp.wave_port( - outer_1.bottom_face_z, reference=outer_1.name, create_pec_cap=True, name="bottom_probe_port" - ) - assert bottom_port.name == "bottom_probe_port" - pec_objects = self.aedtapp.modeler.get_objects_by_material("pec") - assert len(pec_objects) == 2 # PEC cap created. - self.aedtapp.solution_type = "Modal" - assert len(self.aedtapp.boundaries) == 4 - udp = self.aedtapp.modeler.Position(200, 0, 0) - o6 = self.aedtapp.modeler.create_circle(self.aedtapp.PLANE.YZ, udp, 10, name="sheet2") - port = self.aedtapp.wave_port( - assignment=o6, - integration_line=self.aedtapp.AxisDir.XPos, - modes=2, - impedance=40, - name="sheet2_Port", - renormalize=True, - deembed=5, - ) - assert port.name == "sheet2_Port" - assert port.name in [i.name for i in self.aedtapp.boundaries] - assert port.props["RenormalizeAllTerminals"] is True - - id6 = self.aedtapp.modeler.create_box([20, 20, 20], [10, 10, 2], name="My_Box", material="Copper") - id7 = self.aedtapp.modeler.create_box([20, 25, 30], [10, 2, 2], material="Copper") - rect = self.aedtapp.modeler.create_rectangle(self.aedtapp.PLANE.YZ, [20, 25, 20], [2, 10]) - port3 = self.aedtapp.wave_port( - assignment=rect, - integration_line=self.aedtapp.AxisDir.ZNeg, - modes=1, - impedance=30, - name="sheet3_Port", - renormalize=False, - deembed=5, - ) - assert port3.name in [i.name for i in self.aedtapp.boundaries] - - def test_06a_create_linear_count_sweep(self): - setup = self.aedtapp.create_setup("MySetup") - setup.props["Frequency"] = "1GHz" - setup.props["BasisOrder"] = 2 - setup.props["MaximumPasses"] = 1 - assert setup.update() - assert self.aedtapp.create_linear_count_sweep("MySetup", "GHz", 0.8, 1.2, 401) - assert not self.aedtapp.setups[0].sweeps[0].is_solved - assert self.aedtapp.create_linear_count_sweep("MySetup", "GHz", 0.8, 1.2, 401) - assert self.aedtapp.create_linear_count_sweep( - setup="MySetup", - unit="GHz", - start_frequency=1.1e3, - stop_frequency=1200.1, - num_of_freq_points=1234, - sweep_type="Interpolating", - ) - assert self.aedtapp.create_linear_count_sweep( - setup="MySetup", - unit="MHz", - start_frequency=1.1e3, - stop_frequency=1200.1, - num_of_freq_points=1234, - sweep_type="Interpolating", - ) - assert self.aedtapp.create_linear_count_sweep( - setup="MySetup", - unit="MHz", - start_frequency=1.1e3, - stop_frequency=1200.1, - num_of_freq_points=1234, - sweep_type="Fast", - ) - num_points = 1752 - freq_start = 1.1e3 - freq_stop = 1200.1 - units = "MHz" - sweep = self.aedtapp.create_linear_count_sweep( - setup="MySetup", - unit="MHz", - start_frequency=freq_start, - stop_frequency=freq_stop, - num_of_freq_points=num_points, - ) - assert sweep.props["RangeCount"] == num_points - assert sweep.props["RangeStart"] == str(freq_start) + units - assert sweep.props["RangeEnd"] == str(freq_stop) + units - assert sweep.props["Type"] == "Discrete" - - # Create a linear count sweep with the incorrect sweep type. - with pytest.raises(AttributeError) as execinfo: - self.aedtapp.create_linear_count_sweep( - setup="MySetup", - unit="MHz", - start_frequency=1.1e3, - stop_frequency=1200.1, - num_of_freq_points=1234, - sweep_type="Incorrect", - ) - assert ( - execinfo.args[0] - == "Invalid value for `sweep_type`. The value must be 'Discrete', 'Interpolating', or 'Fast'." - ) - self.aedtapp["der_var"] = "1mm" - self.aedtapp["der_var2"] = "2mm" - setup2 = self.aedtapp.create_setup("MySetup_2", setup_type=0) - assert setup2.add_derivatives("der_var") - assert "der_var" in setup2.get_derivative_variables() - assert setup2.add_derivatives("der_var2") - assert "der_var2" in setup2.get_derivative_variables() - assert "der_var" in setup2.get_derivative_variables() - setup2.delete() - setup3 = self.aedtapp.create_setup("MySetup_3", setup_type=0) - assert setup3.add_derivatives("der_var") - assert "der_var" in setup3.get_derivative_variables() - assert setup3.add_derivatives("der_var2") - assert "der_var2" in setup3.get_derivative_variables() - assert "der_var" in setup3.get_derivative_variables() - setup3.delete() - - def test_06b_setup_exists(self): - assert self.aedtapp.active_setup is not None - assert self.aedtapp.nominal_sweep is not None - - def test_06c_create_linear_step_sweep(self): - step_size = 153.8 - freq_start = 1.1e3 - freq_stop = 1200.1 - units = "MHz" - sweep = self.aedtapp.create_linear_step_sweep( - setup="MySetup", - name=None, - unit=units, - start_frequency=freq_start, - stop_frequency=freq_stop, - step_size=step_size, - ) - assert sweep.props["RangeStep"] == str(step_size) + units - assert sweep.props["RangeStart"] == str(freq_start) + units - assert sweep.props["RangeEnd"] == str(freq_stop) + units - assert sweep.props["Type"] == "Discrete" - - step_size = 53.8 - freq_start = 1.2e3 - freq_stop = 1305.1 - units = "MHz" - sweep = self.aedtapp.create_linear_step_sweep( - setup="MySetup", - name="StepFast", - unit=units, - start_frequency=freq_start, - stop_frequency=freq_stop, - step_size=step_size, - sweep_type="Fast", - ) - assert sweep.props["RangeStep"] == str(step_size) + units - assert sweep.props["RangeStart"] == str(freq_start) + units - assert sweep.props["RangeEnd"] == str(freq_stop) + units - assert sweep.props["Type"] == "Fast" - - # Create a linear step sweep with the incorrect sweep type. - with pytest.raises(AttributeError) as execinfo: - self.aedtapp.create_linear_step_sweep( - setup="MySetup", - name="StepFast", - unit=units, - start_frequency=freq_start, - stop_frequency=freq_stop, - step_size=step_size, - sweep_type="Incorrect", - ) - assert ( - execinfo.args[0] - == "Invalid value for 'sweep_type'. The value must be 'Discrete', 'Interpolating', or 'Fast'." - ) - - def test_06d_create_single_point_sweep(self): - assert self.aedtapp.create_single_point_sweep( - setup="MySetup", - unit="MHz", - freq=1.2e3, - ) - setup = self.aedtapp.get_setup("MySetup") - assert setup.create_single_point_sweep( - unit="GHz", - freq=1.2, - save_single_field=False, - ) - assert self.aedtapp.create_single_point_sweep( - setup="MySetup", - unit="GHz", - freq=[1.1, 1.2, 1.3], - ) - assert self.aedtapp.create_single_point_sweep( - setup="MySetup", unit="GHz", freq=[1.1e1, 1.2e1, 1.3e1], save_single_field=[True, False, True] - ) - settings.enable_error_handler = True - assert not self.aedtapp.create_single_point_sweep( - setup="MySetup", unit="GHz", freq=[1, 2e2, 3.4], save_single_field=[True, False] - ) - settings.enable_error_handler = False - - def test_06e_delete_setup(self): - setup_name = "SetupToDelete" - setuptd = self.aedtapp.create_setup(name=setup_name) - assert setuptd.name in self.aedtapp.existing_analysis_setups - assert self.aedtapp.delete_setup(setup_name) - assert setuptd.name not in self.aedtapp.existing_analysis_setups - - def test_06f_sweep_add_subrange(self): - self.aedtapp.modeler.create_box([0, 0, 20], [10, 10, 5], "box_sweep", "Copper") - self.aedtapp.modeler.create_box([0, 0, 30], [10, 10, 5], "box_sweep2", "Copper") - self.aedtapp.wave_port( - assignment="box_sweep", - reference="box_sweep2", - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XNeg, - modes=1, - impedance=75, - name="WaveForSweep", - renormalize=False, - ) - setup = self.aedtapp.create_setup(name="MySetupForSweep") - assert not setup.get_sweep() - sweep = setup.add_sweep() - sweep1 = setup.get_sweep(sweep.name) - assert sweep1 == sweep - sweep2 = setup.get_sweep() - assert sweep2 == sweep1 - assert sweep.add_subrange("LinearCount", 1, 3, 10, "GHz") - assert sweep.add_subrange("LinearCount", 2, 4, 10, "GHz") - assert sweep.add_subrange("LinearStep", 1.1, 2.1, 0.4, "GHz") - assert sweep.add_subrange("LinearCount", 1, 1.5, 5, "MHz") - assert sweep.add_subrange("LogScale", 1, 3, 10, "GHz") - - def test_06g_sweep_clear_subrange(self): - self.aedtapp.modeler.create_box([0, 0, 50], [10, 10, 5], "box_sweep3", "Copper") - self.aedtapp.modeler.create_box([0, 0, 60], [10, 10, 5], "box_sweep4", "Copper") - self.aedtapp.wave_port( - assignment="box_sweep3", - reference="box_sweep4", - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XNeg, - modes=1, - impedance=50, - name="WaveForSweepWithClear", - renormalize=False, - ) - - setup = self.aedtapp.create_setup(name="MySetupClearSweep") - sweep = setup.add_sweep() - assert sweep.add_subrange("LinearCount", 1.1, 3.6, 10, "GHz", clear=True) - assert sweep.props["RangeType"] == "LinearCount" - assert sweep.props["RangeStart"] == "1.1GHz" - assert sweep.props["RangeEnd"] == "3.6GHz" - assert sweep.props["RangeCount"] == 10 - assert sweep.add_subrange("LinearCount", 2, 5, 10, "GHz") - setup.update() - sweep.update() - assert sweep.add_subrange("LinearCount", 3, 8, 10, "GHz", clear=True) - assert sweep.props["RangeType"] == "LinearCount" - assert sweep.props["RangeStart"] == "3GHz" - assert sweep.props["RangeEnd"] == "8GHz" - assert sweep.props["RangeCount"] == 10 - assert sweep.add_subrange("LinearStep", 1.1, 2.1, 0.4, "GHz", clear=True) - assert sweep.props["RangeType"] == "LinearStep" - assert sweep.props["RangeStart"] == "1.1GHz" - assert sweep.props["RangeEnd"] == "2.1GHz" - assert sweep.props["RangeStep"] == "0.4GHz" - assert sweep.add_subrange("LogScale", 1, 3, 10, clear=True) - assert sweep.props["RangeType"] == "LogScale" - assert sweep.props["RangeStart"] == "1GHz" - assert sweep.props["RangeEnd"] == "3GHz" - assert sweep.props["RangeSamples"] == 10 - sweep.props["Type"] = "Discrete" - sweep.update() - assert sweep.add_subrange("SinglePoints", 23, clear=True) - assert sweep.props["RangeType"] == "SinglePoints" - assert sweep.props["RangeStart"] == "23GHz" - assert sweep.props["RangeEnd"] == "23GHz" - assert sweep.props["SaveSingleField"] == False - - def test_06z_validate_setup(self): - list, ok = self.aedtapp.validate_full_design(ports=len(self.aedtapp.excitations)) - assert ok - - def test_07_set_power(self): - assert self.aedtapp.edit_source("sheet1_Port" + ":1", "10W") - assert self.aedtapp.edit_sources( - {"sheet1_Port" + ":1": "10W", "sheet2_Port:1": ("20W", "20deg")}, - include_port_post_processing=True, - max_available_power="40W", - ) - assert self.aedtapp.edit_sources( - {"sheet1_Port" + ":1": "10W", "sheet2_Port:1": ("20W", "0deg", True)}, - include_port_post_processing=True, - use_incident_voltage=True, - ) - - def test_08_create_circuit_port_from_edges(self): - plane = self.aedtapp.PLANE.XY - rect_1 = self.aedtapp.modeler.create_rectangle(plane, [10, 10, 10], [10, 10], name="rect1_for_port") - edges1 = self.aedtapp.modeler.get_object_edges(rect_1.id) - e1 = edges1[0] - rect_2 = self.aedtapp.modeler.create_rectangle(plane, [30, 10, 10], [10, 10], name="rect2_for_port") - edges2 = self.aedtapp.modeler.get_object_edges(rect_2.id) - e2 = edges2[0] - - self.aedtapp.solution_type = "Modal" - assert self.aedtapp.composite is False - self.aedtapp.composite = True - assert self.aedtapp.composite is True - self.aedtapp.composite = False - self.aedtapp.hybrid = False - assert self.aedtapp.hybrid is False - self.aedtapp.hybrid = True - assert self.aedtapp.hybrid is True - - assert ( - self.aedtapp.circuit_port( - e1, e2, impedance=50.1, name="port10", renormalize=False, renorm_impedance="50" - ).name - == "port10" - ) - assert ( - self.aedtapp.circuit_port( - e1, e2, impedance="50+1i*55", name="port11", renormalize=True, renorm_impedance=15.4 - ).name - == "port11" - ) - assert self.aedtapp.set_source_context(["port10", "port11"]) - - assert self.aedtapp.set_source_context([]) - - assert self.aedtapp.set_source_context(["port10", "port11"], 0) - - assert self.aedtapp.set_source_context(["port10", "port11", "sheet1_Port"]) - - assert self.aedtapp.set_source_context(["port10", "port11", "sheet1_Port"], 0) - - self.aedtapp.solution_type = "Terminal" - assert ( - self.aedtapp.circuit_port( - e1, e2, impedance=50.1, name="port20", renormalize=False, renorm_impedance="50+1i*55" - ).name - == "port20" - ) - bound = self.aedtapp.circuit_port(e1, e2, impedance="50.1", name="port32", renormalize=True) - assert bound - bound.name = "port21" - assert bound.update() - self.aedtapp.solution_type = "Modal" - - def test_09_create_waveport_on_objects(self): - box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 5], "BoxWG1", "Copper") - box2 = self.aedtapp.modeler.create_box([0, 0, 10], [10, 10, 5], "BoxWG2", "copper") - box2.material_name = "Copper" - port = self.aedtapp.wave_port( - assignment="BoxWG1", - reference="BoxWG2", - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XNeg, - modes=1, - impedance=50, - name="Wave1", - renormalize=False, - ) - assert port.name == "Wave1" - port2 = self.aedtapp.wave_port( - assignment="BoxWG1", - reference="BoxWG2", - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XPos, - modes=2, - impedance=25, - name="Wave1", - renormalize=True, - deembed=5, - ) - - assert port2.name != "Wave1" and "Wave1" in port2.name - self.aedtapp.solution_type = "Terminal" - assert self.aedtapp.wave_port( - assignment="BoxWG1", - reference="BoxWG2", - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XPos, - modes=2, - impedance=25, - name="Wave3", - renormalize=True, - ) - - self.aedtapp.solution_type = "Modal" - assert self.aedtapp.wave_port( - assignment="BoxWG1", - reference="BoxWG2", - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XPos, - modes=2, - impedance=25, - name="Wave4", - renormalize=True, - deembed=5, - ) - - def test_09a_create_waveport_on_true_surface_objects(self): - cs = self.aedtapp.PLANE.XY - o1 = self.aedtapp.modeler.create_cylinder( - cs, [0, 0, 0], radius=5, height=100, num_sides=0, name="inner", material="Copper" - ) - o3 = self.aedtapp.modeler.create_cylinder( - cs, [0, 0, 0], radius=10, height=100, num_sides=0, name="outer", material="Copper" - ) - port1 = self.aedtapp.wave_port( - assignment=o1.name, - reference=o3.name, - create_port_sheet=True, - create_pec_cap=True, - integration_line=self.aedtapp.AxisDir.XNeg, - name="P1", - ) - assert port1.name.startswith("P1") - - def test_10_create_lumped_on_objects(self): - box1 = self.aedtapp.modeler.create_box([0, 0, 50], [10, 10, 5], "BoxLumped1") - box1.material_name = "Copper" - box2 = self.aedtapp.modeler.create_box([0, 0, 60], [10, 10, 5], "BoxLumped2") - box2.material_name = "Copper" - port = self.aedtapp.lumped_port( - assignment="BoxLumped1", - reference="BoxLumped2", - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XNeg, - impedance=50, - name="Lump1xx", - renormalize=True, - ) - assert not self.aedtapp.lumped_port( - assignment="BoxLumped1111", - reference="BoxLumped2", - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XNeg, - impedance=50, - name="Lump1xx", - renormalize=True, - ) - - assert self.aedtapp.lumped_port( - assignment="BoxLumped1", - reference="BoxLumped2", - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XPos, - impedance=50, - ) - - assert port.name == "Lump1xx" - port.name = "Lump1" - assert port.update() - port = self.aedtapp.lumped_port( - assignment="BoxLumped1", - reference="BoxLumped2", - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XNeg, - impedance=50, - name="Lump2", - renormalize=False, - deembed=True, - ) - - def test_11_create_circuit_on_objects(self): - self.aedtapp.insert_design("test_11") - box1 = self.aedtapp.modeler.create_box([0, 0, 80], [10, 10, 5], "BoxCircuit1", "Copper") - box2 = self.aedtapp.modeler.create_box([0, 0, 100], [10, 10, 5], "BoxCircuit2", "copper") - box2.material_name = "Copper" - port = self.aedtapp.circuit_port( - "BoxCircuit1", "BoxCircuit2", self.aedtapp.AxisDir.XNeg, 50, "Circ1", True, 50, False - ) - assert port.name == "Circ1" - assert not self.aedtapp.circuit_port( - "BoxCircuit44", "BoxCircuit2", self.aedtapp.AxisDir.XNeg, 50, "Circ1", True, 50, False - ) - self.aedtapp.delete_design("test_11", self.fall_back_name) - - def test_12_create_perfects_on_objects(self): - self.aedtapp.insert_design("test_12") - box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 5], "perfect1", "Copper") - box2 = self.aedtapp.modeler.create_box([0, 0, 10], [10, 10, 5], "perfect2", "copper") - pe = self.aedtapp.create_perfecth_from_objects("perfect1", "perfect2", self.aedtapp.AxisDir.ZPos) - ph = self.aedtapp.create_perfecte_from_objects("perfect1", "perfect2", self.aedtapp.AxisDir.ZNeg) - assert pe.name in self.aedtapp.modeler.get_boundaries_name() - assert pe.update() - assert ph.name in self.aedtapp.modeler.get_boundaries_name() - assert ph.update() - self.aedtapp.delete_design("test_12", self.fall_back_name) - - def test_13_create_impedance_on_objects(self): - box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 5], "imp1", "Copper") - box2 = self.aedtapp.modeler.create_box([0, 0, 10], [10, 10, 5], "imp2", "copper") - imp = self.aedtapp.create_impedance_between_objects( - box1.name, box2.name, self.aedtapp.AxisDir.XPos, "TL1", 50, 25 - ) - assert imp.name in self.aedtapp.modeler.get_boundaries_name() - assert imp.update() - - pytest.mark.skipif(config["desktopVersion"] > "2023.2", reason="Crashing Desktop") - - def test_14_create_lumpedrlc_on_objects(self): - box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 5], "rlc1", "Copper") - box2 = self.aedtapp.modeler.create_box([0, 0, 10], [10, 10, 5], "rlc2", "copper") - imp = self.aedtapp.create_lumped_rlc_between_objects( - box1.name, box2.name, self.aedtapp.AxisDir.XPos, resistance=50, inductance=1e-9 - ) - assert imp.name in self.aedtapp.modeler.get_boundaries_name() - assert imp.update() - - box3 = self.aedtapp.modeler.create_box([0, 0, 20], [10, 10, 5], "rlc3", "copper") - lumped_rlc2 = self.aedtapp.create_lumped_rlc_between_objects( - box2.name, box3.name, self.aedtapp.AxisDir.XPos, resistance=50, inductance=1e-9, capacitance=1e-9 - ) - assert lumped_rlc2.name in self.aedtapp.modeler.get_boundaries_name() - assert lumped_rlc2.update() - - def test_15_create_perfects_on_sheets(self): - rect = self.aedtapp.modeler.create_rectangle( - self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="RectBound", material="Copper" - ) - pe = self.aedtapp.assign_perfecte_to_sheets(rect.name) - assert pe.name in self.aedtapp.modeler.get_boundaries_name() - ph = self.aedtapp.assign_perfecth_to_sheets(rect.name) - assert ph.name in self.aedtapp.modeler.get_boundaries_name() - solution_type = self.aedtapp.solution_type - - self.aedtapp.solution_type = "Eigen Mode" - perfect_h_eigen = self.aedtapp.assign_perfecth_to_sheets(rect.name) - assert perfect_h_eigen.name in self.aedtapp.modeler.get_boundaries_name() - perfect_e_eigen = self.aedtapp.assign_perfecte_to_sheets(rect.name) - assert perfect_e_eigen.name in self.aedtapp.modeler.get_boundaries_name() - self.aedtapp.solution_type = "solution_type" - - def test_16_create_impedance_on_sheets(self): - rect = self.aedtapp.modeler.create_rectangle( - self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="ImpBound", material="Copper" - ) - imp1 = self.aedtapp.assign_impedance_to_sheet(rect.name, "TL2", 50, 25) - assert imp1.name in self.aedtapp.modeler.get_boundaries_name() - assert imp1.update() - - impedance_box = self.aedtapp.modeler.create_box([0, -100, 0], [200, 200, 200], "ImpedanceBox") - ids = self.aedtapp.modeler.get_object_faces(impedance_box.name)[:3] - - imp2 = self.aedtapp.assign_impedance_to_sheet(ids, resistance=60, reactance=-20) - assert imp2.name in self.aedtapp.modeler.get_boundaries_name() - - rect2 = self.aedtapp.modeler.create_rectangle( - self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="AniImpBound", material="Copper" - ) - assert not self.aedtapp.assign_impedance_to_sheet(rect2.name, "TL3", [50, 20, 0, 0], [25, 0, 5]) - imp2 = self.aedtapp.assign_impedance_to_sheet(rect2.name, "TL3", [50, 20, 0, 0], [25, 0, 5, 0]) - assert imp2.name in self.aedtapp.modeler.get_boundaries_name() - imp3 = self.aedtapp.assign_impedance_to_sheet(impedance_box.top_face_z.id, "TL4", [50, 20, 0, 0], [25, 0, 5, 0]) - assert imp3.name in self.aedtapp.modeler.get_boundaries_name() - - def test_17_create_lumpedrlc_on_sheets(self): - rect = self.aedtapp.modeler.create_rectangle( - self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="rlcBound", material="Copper" - ) - imp = self.aedtapp.assign_lumped_rlc_to_sheet( - rect.name, self.aedtapp.AxisDir.XPos, resistance=50, inductance=1e-9 - ) - names = self.aedtapp.modeler.get_boundaries_name() - assert imp.name in self.aedtapp.modeler.get_boundaries_name() - - rect2 = self.aedtapp.modeler.create_rectangle( - self.aedtapp.PLANE.XY, [0, 0, 10], [10, 2], name="rlcBound2", material="Copper" - ) - imp = self.aedtapp.assign_lumped_rlc_to_sheet( - rect.name, self.aedtapp.AxisDir.XPos, rlc_type="Serial", resistance=50, inductance=1e-9 - ) - names = self.aedtapp.modeler.get_boundaries_name() - assert imp.name in self.aedtapp.modeler.get_boundaries_name() - assert self.aedtapp.assign_lumped_rlc_to_sheet( - rect.name, [rect.bottom_edge_x.midpoint, rect.bottom_edge_y.midpoint], inductance=1e-9 - ) - assert not self.aedtapp.assign_lumped_rlc_to_sheet(rect.name, [rect.bottom_edge_x.midpoint], inductance=1e-9) - - def test_17B_update_assignment(self): - bound = self.aedtapp.assign_perfecth_to_sheets(self.aedtapp.modeler["My_Box"].faces[0].id) - assert bound - bound.props["Faces"].append(self.aedtapp.modeler["My_Box"].faces[1]) - assert bound.update_assignment() - - def test_18_create_sources_on_objects(self): - box1 = self.aedtapp.modeler.create_box([30, 0, 0], [40, 10, 5], "BoxVolt1", "Copper") - box2 = self.aedtapp.modeler.create_box([30, 0, 10], [40, 10, 5], "BoxVolt2", "Copper") - port = self.aedtapp.create_voltage_source_from_objects( - box1.name, "BoxVolt2", self.aedtapp.AxisDir.XNeg, "Volt1" - ) - assert port.name in self.aedtapp.excitations - port = self.aedtapp.create_current_source_from_objects("BoxVolt1", "BoxVolt2", self.aedtapp.AxisDir.XPos) - assert port.name in self.aedtapp.excitations - - def test_19_create_lumped_on_sheet(self): - rect = self.aedtapp.modeler.create_rectangle( - self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="lump_port", material="Copper" - ) - port = self.aedtapp.lumped_port( - assignment=rect.name, - create_port_sheet=False, - integration_line=self.aedtapp.AxisDir.XNeg, - impedance=50, - name="Lump_sheet", - renormalize=True, - ) - - assert port.name + ":1" in self.aedtapp.excitations - port2 = self.aedtapp.lumped_port( - assignment=rect.name, - create_port_sheet=False, - integration_line=self.aedtapp.AxisDir.XNeg, - impedance=50, - name="Lump_sheet2", - renormalize=True, - deembed=True, - ) - - assert port2.name + ":1" in self.aedtapp.excitations - port3 = self.aedtapp.lumped_port( - assignment=rect.name, - create_port_sheet=False, - integration_line=[rect.bottom_edge_x.midpoint, rect.bottom_edge_y.midpoint], - impedance=50, - name="Lump_sheet3", - renormalize=True, - deembed=True, - ) - - assert port3.name + ":1" in self.aedtapp.excitations - assert not self.aedtapp.lumped_port( - assignment=rect.name, - create_port_sheet=False, - integration_line=[rect.bottom_edge_x.midpoint], - impedance=50, - name="Lump_sheet4", - renormalize=True, - deembed=True, - ) - - def test_20_create_voltage_on_sheet(self): - rect = self.aedtapp.modeler.create_rectangle( - self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="lump_volt", material="Copper" - ) - port = self.aedtapp.assign_voltage_source_to_sheet(rect.name, self.aedtapp.AxisDir.XNeg, "LumpVolt1") - assert port.name in self.aedtapp.excitations - assert self.aedtapp.get_property_value("BoundarySetup:LumpVolt1", "VoltageMag", "Excitation") == "1V" - port = self.aedtapp.assign_voltage_source_to_sheet( - rect.name, [rect.bottom_edge_x.midpoint, rect.bottom_edge_y.midpoint], "LumpVolt2" - ) - assert port.name in self.aedtapp.excitations - port = self.aedtapp.assign_voltage_source_to_sheet(rect.name, [rect.bottom_edge_x.midpoint], "LumpVolt2") - assert not port - - def test_21_create_open_region(self): - assert self.aedtapp.create_open_region("1GHz") - assert len(self.aedtapp.field_setups) == 3 - assert self.aedtapp.create_open_region("1GHz", "FEBI") - assert self.aedtapp.create_open_region("1GHz", "PML", True, "-z") - - def test_22_create_length_mesh(self): - box1 = self.aedtapp.modeler.create_box([30, 0, 0], [40, 10, 5], "BoxCircuit1", "Copper") - mesh = self.aedtapp.mesh.assign_length_mesh(["BoxCircuit1"]) - assert mesh - mesh.props["NumMaxElem"] = "100" - assert mesh.props["NumMaxElem"] == self.aedtapp.odesign.GetChildObject("Mesh").GetChildObject( - mesh.name - ).GetPropValue("Max Elems") - - def test_23_create_skin_depth(self): - box1 = self.aedtapp.modeler.create_box([30, 0, 0], [40, 10, 5], "BoxCircuit2", "Copper") - mesh = self.aedtapp.mesh.assign_skin_depth(["BoxCircuit2"], "1mm") - assert mesh - mesh.props["SkinDepth"] = "3mm" - assert mesh.props["SkinDepth"] == self.aedtapp.odesign.GetChildObject("Mesh").GetChildObject( - mesh.name - ).GetPropValue("Skin Depth") - - def test_24_create_curvilinear(self): - box1 = self.aedtapp.modeler.create_box([30, 0, 0], [40, 10, 5], "BoxCircuit3", "Copper") - mesh = self.aedtapp.mesh.assign_curvilinear_elements(["BoxCircuit3"]) - assert mesh - mesh.props["Apply"] = False - assert mesh.props["Apply"] == self.aedtapp.odesign.GetChildObject("Mesh").GetChildObject( - mesh.name - ).GetPropValue("Apply Curvilinear Elements") - mesh.delete() - assert len(self.aedtapp.mesh.meshoperations) == 2 - - def test_30_assign_initial_mesh(self): - assert self.aedtapp.mesh.assign_initial_mesh_from_slider(6) - - def test_30a_add_mesh_link(self): - self.aedtapp.duplicate_design(self.aedtapp.design_name) - self.aedtapp.set_active_design(self.aedtapp.design_list[0]) - assert self.aedtapp.setups[0].add_mesh_link(design=self.aedtapp.design_list[1]) - meshlink_props = self.aedtapp.setups[0].props["MeshLink"] - assert meshlink_props["Project"] == "This Project*" - assert meshlink_props["PathRelativeTo"] == "TargetProject" - assert meshlink_props["Design"] == self.aedtapp.design_list[1] - assert meshlink_props["Soln"] == "MySetup : LastAdaptive" - assert sorted(list(meshlink_props["Params"].keys())) == sorted(self.aedtapp.available_variations.variables) - assert sorted(list(meshlink_props["Params"].values())) == sorted(self.aedtapp.available_variations.variables) - assert not self.aedtapp.setups[0].add_mesh_link(design="") - assert self.aedtapp.setups[0].add_mesh_link( - design=self.aedtapp.design_list[1], solution="MySetup : LastAdaptive" - ) - assert not self.aedtapp.setups[0].add_mesh_link( - design=self.aedtapp.design_list[1], solution="Setup_Test : LastAdaptive" - ) - assert self.aedtapp.setups[0].add_mesh_link( - design=self.aedtapp.design_list[1], parameters=self.aedtapp.available_variations.nominal_w_values_dict - ) - example_project = os.path.join( - local_path, "../_unittest/example_models", test_subfolder, diff_proj_name + ".aedt" - ) - example_project_copy = os.path.join(self.local_scratch.path, diff_proj_name + "_copy.aedt") - shutil.copyfile(example_project, example_project_copy) - assert self.aedtapp.setups[0].add_mesh_link(design=self.aedtapp.design_list[1], project=example_project_copy) - - def test_31_create_microstrip_port(self): - self.aedtapp.insert_design("Microstrip") - self.aedtapp.solution_type = "Modal" - ms = self.aedtapp.modeler.create_box([4, 5, 0], [1, 100, 0.2], name="MS1", material="copper") - sub = self.aedtapp.modeler.create_box([0, 5, -2], [20, 100, 2], name="SUB1", material="FR4_epoxy") - gnd = self.aedtapp.modeler.create_box([0, 5, -2.2], [20, 100, 0.2], name="GND1", material="FR4_epoxy") - port = self.aedtapp.wave_port( - assignment=gnd.name, - reference=ms.name, - create_port_sheet=True, - integration_line=1, - name="MS1", - is_microstrip=True, - ) - assert port.name == "MS1" - assert port.update() - self.aedtapp.solution_type = "Terminal" - assert self.aedtapp.wave_port( - assignment=gnd.name, - reference=ms.name, - create_port_sheet=True, - integration_line=1, - name="MS2", - is_microstrip=True, - ) - assert self.aedtapp.wave_port( - assignment=gnd.name, - reference=ms.name, - create_port_sheet=True, - integration_line=1, - impedance=77, - name="MS3", - deembed=1, - is_microstrip=True, - ) - - def test_32_get_property_value(self): - rect = self.aedtapp.modeler.create_rectangle( - self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="RectProp", material="Copper" - ) - pe = self.aedtapp.assign_perfecte_to_sheets(rect.name, "PerfectE_1") - setup = self.aedtapp.create_setup("MySetup2") - setup.props["Frequency"] = "1GHz" - assert self.aedtapp.get_property_value("BoundarySetup:PerfectE_1", "Inf Ground Plane", "Boundary") == "false" - assert self.aedtapp.get_property_value("AnalysisSetup:MySetup2", "Solution Freq", "Setup") == "1GHz" - - def test_33_copy_solid_bodies(self, add_app): - project_name = "HfssCopiedProject" - design_name = "HfssCopiedBodies" - new_design = add_app(project_name=project_name, design_name=design_name) - num_orig_bodies = len(self.aedtapp.modeler.solid_names) - assert new_design.copy_solid_bodies_from(self.aedtapp, no_vacuum=False, no_pec=False) - assert len(new_design.modeler.solid_bodies) == num_orig_bodies - new_design.delete_design(design_name) - new_design.close_project(project_name) - - def test_34_object_material_properties(self): - self.aedtapp.insert_design("ObjMat") - self.aedtapp.solution_type = "Modal" - ms = self.aedtapp.modeler.create_box([4, 5, 0], [1, 100, 0.2], name="MS1", material="copper") - props = self.aedtapp.get_object_material_properties("MS1", "conductivity") - assert props - - def test_35_set_export_touchstone(self): - assert self.aedtapp.set_export_touchstone(True) - assert self.aedtapp.set_export_touchstone(False) - - def test_36_assign_radiation_to_objects(self): - self.aedtapp.modeler.create_box([-100, -100, -100], [200, 200, 200], name="Rad_box") - rad = self.aedtapp.assign_radiation_boundary_to_objects("Rad_box") - rad.name = "Radiation1" - assert rad.update() - - def test_37_assign_radiation_to_objects(self): - self.aedtapp.modeler.create_box([-100, -100, -100], [200, 200, 200], name="Rad_box2") - ids = [i.id for i in self.aedtapp.modeler["Rad_box2"].faces] - assert self.aedtapp.assign_radiation_boundary_to_faces(ids) - - def test_38_get_all_sources(self): - sources = self.aedtapp.get_all_sources() - assert isinstance(sources, list) - - def test_40_assign_current_source_to_sheet(self): - sheet = self.aedtapp.modeler.create_rectangle( - self.aedtapp.PLANE.XY, [0, 0, 0], [5, 1], name="RectangleForSource", material="Copper" - ) - assert self.aedtapp.assign_current_source_to_sheet(sheet.name) - assert self.aedtapp.assign_current_source_to_sheet( - sheet.name, [sheet.bottom_edge_x.midpoint, sheet.bottom_edge_y.midpoint] - ) - assert not self.aedtapp.assign_current_source_to_sheet(sheet.name, [sheet.bottom_edge_x.midpoint]) - - def test_41_export_step(self): - file_name = "test" - self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 10]) - assert self.aedtapp.export_3d_model(file_name, self.aedtapp.working_directory, ".x_t", [], []) - assert os.path.exists(os.path.join(self.aedtapp.working_directory, file_name + ".x_t")) - - def test_42_floquet_port(self): - self.aedtapp.insert_design("floquet") - self.aedtapp.solution_type = "Modal" - - box1 = self.aedtapp.modeler.create_box([-100, -100, -100], [200, 200, 200], name="Rad_box2") - assert self.aedtapp.create_floquet_port( - box1.faces[0], modes=7, deembed_distance=1, reporter_filter=[False, True, False, False, False, False, False] - ) - assert self.aedtapp.create_floquet_port( - box1.faces[1], modes=7, deembed_distance=1, reporter_filter=[False, True, False, False, False, False, False] - ) - sheet = self.aedtapp.modeler.create_rectangle( - self.aedtapp.PLANE.XY, [-100, -100, -100], [200, 200], name="RectangleForSource", material="Copper" - ) - bound = self.aedtapp.create_floquet_port(sheet, modes=4, deembed_distance=1, reporter_filter=False) - assert bound - bound.name = "Floquet1" - assert bound.update() - self.aedtapp.delete_design("floquet", self.fall_back_name) - - def test_43_autoassign_pairs(self): - self.aedtapp.insert_design("lattice") - box1 = self.aedtapp.modeler.create_box([-100, -100, -100], [200, 200, 200], name="Rad_box2") - assert len(self.aedtapp.auto_assign_lattice_pairs(box1)) == 2 - box1.delete() - box1 = self.aedtapp.modeler.create_box([-100, -100, -100], [200, 200, 200], name="Rad_box2") - if config["desktopVersion"] > "2022.2": - assert self.aedtapp.assign_lattice_pair([box1.faces[2], box1.faces[5]]) - primary = self.aedtapp.assign_primary(box1.faces[4], [100, -100, -100], [100, 100, -100]) - - else: - assert self.aedtapp.assign_lattice_pair([box1.faces[2], box1.faces[4]]) - primary = self.aedtapp.assign_primary(box1.faces[1], [100, -100, -100], [100, 100, -100]) - assert primary - primary.name = "Prim1" - assert primary.update() - sec = self.aedtapp.assign_secondary( - box1.faces[0], primary.name, [100, -100, 100], [100, 100, 100], reverse_v=True - ) - sec.name = "Sec1" - assert sec.update() - self.aedtapp.delete_design("lattice", self.fall_back_name) - - def test_44_create_infinite_sphere(self): - self.aedtapp.insert_design("InfSphere") - air = self.aedtapp.modeler.create_box([0, 0, 0], [20, 20, 20], name="rad", material="vacuum") - self.aedtapp.assign_radiation_boundary_to_objects(air) - bound = self.aedtapp.insert_infinite_sphere( - definition="El Over Az", - x_start=1, - x_stop=91, - x_step=45, - y_start=2, - y_stop=92, - y_step=10, - use_slant_polarization=True, - polarization_angle=30, - ) - assert bound - assert bound.azimuth_start == "1deg" - assert bound.azimuth_stop == "91deg" - assert bound.azimuth_step == "45deg" - assert bound.elevation_start == "2deg" - assert bound.elevation_stop == "92deg" - assert bound.elevation_step == "10deg" - assert bound.slant_angle == "30deg" - assert bound.polarization == "Slant" - bound.azimuth_start = 20 - assert bound.azimuth_start == "20deg" - assert bound.delete() - bound = self.aedtapp.insert_infinite_sphere( - definition="Az Over El", - x_start=1, - x_stop=91, - x_step=45, - y_start=2, - y_stop=92, - y_step=10, - use_slant_polarization=True, - polarization_angle=30, - ) - assert bound.azimuth_start == "2deg" - - def test_45_set_autoopen(self): - assert self.aedtapp.set_auto_open(True, "PML") - - def test_45_terminal_port(self): - self.aedtapp.insert_design("Design_Terminal") - self.aedtapp.solution_type = "Terminal" - box1 = self.aedtapp.modeler.create_box([-100, -100, 0], [200, 200, 5], name="gnd", material="copper") - box2 = self.aedtapp.modeler.create_box([-100, -100, 20], [200, 200, 25], name="sig", material="copper") - sheet = self.aedtapp.modeler.create_rectangle(self.aedtapp.PLANE.YZ, [-100, -100, 5], [200, 15], "port") - port = self.aedtapp.lumped_port( - assignment=box1, - reference=box2.name, - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XNeg, - impedance=75, - name="Lump1", - renormalize=True, - ) - - assert "Lump1_T1" in self.aedtapp.excitations - port2 = self.aedtapp.lumped_port( - assignment=sheet.name, - reference=box1, - create_port_sheet=False, - integration_line=self.aedtapp.AxisDir.XNeg, - impedance=33, - name="Lump_sheet", - renormalize=True, - ) - assert port2.name + "_T1" in self.aedtapp.excitations - port3 = self.aedtapp.lumped_port( - assignment=box1, - reference=box2.name, - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XNeg, - impedance=50, - name="Lump3", - renormalize=False, - deembed=True, - ) - assert port3.name + "_T1" in self.aedtapp.excitations - self.aedtapp.delete_design("Design_Terminal", self.fall_back_name) - - def test_45B_terminal_port(self): - self.aedtapp.insert_design("Design_Terminal_2") - self.aedtapp.solution_type = "Terminal" - box1 = self.aedtapp.modeler.create_box([-100, -100, 0], [200, 200, 5], name="gnd2z", material="copper") - box2 = self.aedtapp.modeler.create_box([-100, -100, 20], [200, 200, 25], name="sig2z", material="copper") - box3 = self.aedtapp.modeler.create_box([-40, -40, -20], [80, 80, 10], name="box3", material="copper") - box4 = self.aedtapp.modeler.create_box([-40, -40, 10], [80, 80, 10], name="box4", material="copper") - box1.display_wireframe = True - box2.display_wireframe = True - box3.display_wireframe = True - box4.display_wireframe = True - self.aedtapp.modeler.fit_all() - portz = self.aedtapp.create_spiral_lumped_port(box1, box2) - assert portz - - n_boundaries = len(self.aedtapp.boundaries) - assert n_boundaries == 4 - - box5 = self.aedtapp.modeler.create_box([-50, -15, 200], [150, -10, 200], name="gnd2y", material="copper") - box6 = self.aedtapp.modeler.create_box([-50, 10, 200], [150, 15, 200], name="sig2y", material="copper") - box5.display_wireframe = True - box6.display_wireframe = True - self.aedtapp.modeler.fit_all() - porty = self.aedtapp.create_spiral_lumped_port(box5, box6) - assert porty - - n_boundaries = len(self.aedtapp.boundaries) - assert n_boundaries == 8 - - box7 = self.aedtapp.modeler.create_box([-15, 300, 0], [-10, 200, 100], name="gnd2x", material="copper") - box8 = self.aedtapp.modeler.create_box([15, 300, 0], [10, 200, 100], name="sig2x", material="copper") - box7.display_wireframe = True - box8.display_wireframe = True - self.aedtapp.modeler.fit_all() - portx = self.aedtapp.create_spiral_lumped_port(box7, box8) - assert portx - - n_boundaries = len(self.aedtapp.boundaries) - assert n_boundaries == 12 - - # Use two boxes with different dimensions. - with pytest.raises(AttributeError) as execinfo: - self.aedtapp.create_spiral_lumped_port(box1, box3) - assert execinfo.args[0] == "The closest faces of the two objects must be identical in shape." - - # Rotate box3 so that, box3 and box4 are not collinear anymore. - # Spiral lumped port can only be created based on 2 collinear objects. - box3.rotate(axis="X", angle=90) - with pytest.raises(AttributeError) as execinfo: - self.aedtapp.create_spiral_lumped_port(box3, box4) - assert execinfo.args[0] == "The two objects must have parallel adjacent faces." - - # Rotate back box3 - # rotate them slightly so that they are still parallel, but not aligned anymore with main planes. - box3.rotate(axis="X", angle=-90) - box3.rotate(axis="Y", angle=5) - box4.rotate(axis="Y", angle=5) - with pytest.raises(AttributeError) as execinfo: - self.aedtapp.create_spiral_lumped_port(box3, box4) - assert ( - execinfo.args[0] - == "The closest faces of the two objects must be aligned with the main planes of the reference system." - ) - self.aedtapp.delete_design("Design_Terminal_2", self.fall_back_name) - - def test_46_mesh_settings(self): - assert self.aedtapp.mesh.initial_mesh_settings - assert self.aedtapp.mesh.initial_mesh_settings.props - - def test_47_convert_near_field(self): - example_project = os.path.join(local_path, "../_unittest/example_models", "nf_test") - assert os.path.exists(convert_nearfield_data(example_project, output_folder=self.local_scratch.path)) - - def test_48_traces(self): - assert len(self.aedtapp.excitations) > 0 - assert len(self.aedtapp.get_traces_for_plot()) > 0 - - def test_49_port_creation_exception(self): - box1 = self.aedtapp.modeler.create_box([-400, -40, -20], [80, 80, 10], name="gnd49", material="copper") - box2 = self.aedtapp.modeler.create_box([-400, -40, 10], [80, 80, 10], name="sig49", material="copper") - - self.aedtapp.solution_type = "Modal" - # Spiral lumped port can only be created in a 'Terminal' solution. - with pytest.raises(Exception) as execinfo: - self.aedtapp.create_spiral_lumped_port(box1, box2) - assert execinfo.args[0] == "This method can be used only in 'Terminal' solutions." - self.aedtapp.solution_type = "Terminal" - - # Try to modify SBR+ TX RX antenna settings in a solution that is different from SBR+ - # should not be possible. - assert not self.aedtapp.set_sbr_txrx_settings({"TX1": "RX1"}) - - # SBR linked antenna can only be created within an SBR+ solution. - assert not self.aedtapp.create_sbr_linked_antenna(self.aedtapp, field_type="farfield") - - # Chirp I doppler setup only works within an SBR+ solution. - assert self.aedtapp.create_sbr_chirp_i_doppler_setup(sweep_time_duration=20) == (False, False) - - # Chirp IQ doppler setup only works within an SBR+ solution. - assert self.aedtapp.create_sbr_chirp_iq_doppler_setup(sweep_time_duration=10) == (False, False) - - def test_50_set_differential_pair(self, add_app): - hfss1 = add_app(project_name=diff_proj_name, design_name="Hfss_Terminal", subfolder=test_subfolder) - assert hfss1.set_differential_pair( - assignment="P2_T1", - reference="P2_T2", - differential_mode=None, - common_reference=34, - differential_reference=123, - active=True, - matched=False, - ) - assert not hfss1.set_differential_pair(assignment="P2_T1", reference="P2_T3") - hfss2 = add_app(design_name="Hfss_Transient") - assert hfss2.set_differential_pair( - assignment="P2_T1", - reference="P2_T2", - differential_mode=None, - common_reference=34, - differential_reference=123, - active=True, - matched=False, - ) - assert not hfss2.set_differential_pair(assignment="P2_T1", reference="P2_T3") - hfss2.close_project() - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", - reason="Not working in non-graphical in version lower than 2022.2", - ) - def test_51a_array(self): - self.aedtapp.insert_design("Array_simple", "Modal") - from pyaedt.generic.general_methods import read_json - - if config["desktopVersion"] > "2023.1": - dict_in = read_json( - os.path.join(local_path, "../_unittest/example_models", test_subfolder, "array_simple_232.json") - ) - dict_in["Circ_Patch_5GHz_232_1"] = os.path.join( - local_path, "../_unittest/example_models", test_subfolder, component - ) - dict_in["cells"][(3, 3)] = {"name": "Circ_Patch_5GHz_232_1"} - else: - dict_in = read_json( - os.path.join(local_path, "../_unittest/example_models", test_subfolder, "array_simple.json") - ) - dict_in["Circ_Patch_5GHz1"] = os.path.join( - local_path, "../_unittest/example_models", test_subfolder, component - ) - dict_in["cells"][(3, 3)] = {"name": "Circ_Patch_5GHz1"} - - assert self.aedtapp.add_3d_component_array_from_json(dict_in) - array_name = self.aedtapp.component_array_names[0] - assert self.aedtapp.component_array[array_name].cells[2][2].rotation == 0 - assert self.aedtapp.component_array_names - dict_in["cells"][(3, 3)]["rotation"] = 90 - component_array = self.aedtapp.add_3d_component_array_from_json(dict_in) - assert component_array.cells[2][2].rotation == 90 - component_array.cells[2][2].rotation = 0 - assert component_array.cells[2][2].rotation == 0 - - def test_51b_set_material_threshold(self): - assert self.aedtapp.set_material_threshold() - threshold = 123123123 - assert self.aedtapp.set_material_threshold(threshold) - assert self.aedtapp.set_material_threshold(str(threshold)) - assert not self.aedtapp.set_material_threshold("e") - - def test_52_crate_setup_hybrid_sbr(self, add_app): - aedtapp = add_app(project_name="test_52") - udp = aedtapp.modeler.Position(0, 0, 0) - coax_dimension = 200 - aedtapp.modeler.create_cylinder(aedtapp.AXIS.X, udp, 3, coax_dimension, 0, "inner") - aedtapp.modeler.create_cylinder(aedtapp.AXIS.X, udp, 10, coax_dimension, 0, "outer") - aedtapp.hybrid = True - assert aedtapp.assign_hybrid_region(["inner"]) - bound = aedtapp.assign_hybrid_region("outer", name="new_hybrid", hybrid_region="IE") - assert bound.props["Type"] == "IE" - bound.props["Type"] = "PO" - assert bound.props["Type"] == "PO" - aedtapp.close_project(save_project=False) - - def test_53_import_source_excitation(self, add_app): - aedtapp = add_app(solution_type="Modal", project_name="test_53") - freq_domain = os.path.join(local_path, "../_unittest/example_models", test_subfolder, "S Parameter Table 1.csv") - time_domain = os.path.join(local_path, "../_unittest/example_models", test_subfolder, "Sinusoidal.csv") - - box1 = aedtapp.modeler.create_box([0, 0, 0], [10, 20, 20]) - aedtapp.wave_port(assignment=box1.bottom_face_x, create_port_sheet=False, name="Port1") - aedtapp.create_setup() - assert aedtapp.edit_source_from_file(aedtapp.excitations[0], freq_domain, is_time_domain=False, x_scale=1e9) - assert aedtapp.edit_source_from_file( - aedtapp.excitations[0], time_domain, is_time_domain=True, x_scale=1e-6, y_scale=1e-3, data_format="Voltage" - ) - aedtapp.close_project(save_project=False) - - def test_54_assign_symmetry(self, add_app): - aedtapp = add_app(project_name="test_54", solution_type="Modal") - aedtapp.modeler.create_box([0, -100, 0], [200, 200, 200], name="SymmetryForFaces") - ids = [i.id for i in aedtapp.modeler["SymmetryForFaces"].faces] - assert aedtapp.assign_symmetry(ids) - assert aedtapp.assign_symmetry([ids[0], ids[1], ids[2]]) - assert not aedtapp.assign_symmetry(aedtapp.modeler.object_list[0].faces[0]) - assert aedtapp.assign_symmetry([aedtapp.modeler.object_list[0].faces[0]]) - assert aedtapp.assign_symmetry( - [ - aedtapp.modeler.object_list[0].faces[0], - aedtapp.modeler.object_list[0].faces[1], - aedtapp.modeler.object_list[0].faces[2], - ] - ) - assert not aedtapp.assign_symmetry(ids[0]) - assert not aedtapp.assign_symmetry("test") - assert aedtapp.set_impedance_multiplier(2) - aedtapp.close_project(save_project=False) - - def test_55_create_near_field_sphere(self): - air = self.aedtapp.modeler.create_box([0, 0, 0], [20, 20, 20], name="rad", material="vacuum") - self.aedtapp.assign_radiation_boundary_to_objects(air) - bound = self.aedtapp.insert_near_field_sphere( - radius=20, - radius_units="cm", - x_start=-180, - x_stop=180, - x_step=10, - y_start=0, - y_stop=180, - y_step=10, - angle_units="deg", - custom_radiation_faces=None, - custom_coordinate_system=None, - name=None, - ) - bound.name = "Test_Sphere" - assert self.aedtapp.field_setup_names[0] == bound.name - - def test_56_create_near_field_box(self): - bound = self.aedtapp.insert_near_field_box( - u_length=20, - u_samples=21, - v_length=20, - v_samples=21, - w_length=20, - w_samples=21, - units="mm", - custom_radiation_faces=None, - custom_coordinate_system=None, - name=None, - ) - - assert bound - - def test_57_create_near_field_rectangle(self): - bound = self.aedtapp.insert_near_field_rectangle( - u_length=20, - u_samples=21, - v_length=20, - v_samples=21, - units="mm", - custom_radiation_faces=None, - custom_coordinate_system=None, - name=None, - ) - bound.props["Length"] = "50mm" - assert bound - - def test_58_create_near_field_line(self): - test_points = [ - ["0mm", "0mm", "0mm"], - ["100mm", "20mm", "0mm"], - ["71mm", "71mm", "0mm"], - ["0mm", "100mm", "0mm"], - ] - line = self.aedtapp.modeler.create_polyline(test_points) - bound = self.aedtapp.insert_near_field_line( - assignment=line.name, points=1000, custom_radiation_faces=None, name=None - ) - bound.props["NumPts"] = "200" - assert bound - - def test_59_test_nastran(self): - self.aedtapp.insert_design("Nas_teest") - example_project = os.path.join(local_path, "../_unittest/example_models", test_subfolder, "test_cad.nas") - example_project2 = os.path.join(local_path, "../_unittest/example_models", test_subfolder, "test_cad_2.nas") - - cads = self.aedtapp.modeler.import_nastran(example_project) - assert len(cads) > 0 - assert self.aedtapp.modeler.import_nastran(example_project2) - - def test_60_set_variable(self): - self.aedtapp.variable_manager.set_variable("var_test", expression="123") - self.aedtapp["var_test"] = "234" - assert "var_test" in self.aedtapp.variable_manager.design_variable_names - assert self.aedtapp.variable_manager.design_variables["var_test"].expression == "234" - - def test_61_create_lumped_ports_on_object_driven_terminal(self): - self.aedtapp.insert_design("test_61") - self.aedtapp.solution_type = "Terminal" - box1 = self.aedtapp.modeler.create_box([0, 0, 50], [10, 10, 5], "BoxLumped1") - box1.material_name = "Copper" - box2 = self.aedtapp.modeler.create_box([0, 0, 60], [10, 10, 5], "BoxLumped2") - box2.material_name = "Copper" - - _ = self.aedtapp.lumped_port( - signal=box1.name, - reference=box2.name, - create_port_sheet=True, - port_on_plane=True, - integration_line=self.aedtapp.AxisDir.XNeg, - impedance=50, - name="Lump1xx", - renormalize=True, - deembed=False, - ) - - term = [term for term in self.aedtapp.boundaries if term.type == "Terminal"][0] - assert self.aedtapp.boundaries[0].type == "Terminal" - term.name = "test" - assert term.name == "test" - term.props["TerminalResistance"] = "1ohm" - assert term.props["TerminalResistance"] == "1ohm" - assert not self.aedtapp.set_impedance_multiplier(2) - - def test_62_set_power_calc(self): - assert self.aedtapp.set_radiated_power_calc_method() - assert self.aedtapp.set_radiated_power_calc_method("Radiation Surface Integral") - assert self.aedtapp.set_radiated_power_calc_method("Far Field Integral") - - def test_63_set_phase_center_per_port(self): - self.aedtapp.insert_design("PhaseCenter") - self.aedtapp.solution_type = "Modal" - box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 5], "BoxWG1", "Copper") - box2 = self.aedtapp.modeler.create_box([0, 0, 10], [10, 10, 5], "BoxWG2", "copper") - box2.material_name = "Copper" - port = self.aedtapp.wave_port( - assignment="BoxWG1", - reference="BoxWG2", - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XNeg, - modes=1, - impedance=50, - name="Wave1", - renormalize=False, - ) - port2 = self.aedtapp.wave_port( - assignment="BoxWG1", - reference="BoxWG2", - create_port_sheet=True, - integration_line=self.aedtapp.AxisDir.XNeg, - modes=1, - impedance=50, - name="Wave2", - renormalize=False, - ) - if self.aedtapp.desktop_class.is_grpc_api: - assert self.aedtapp.set_phase_center_per_port() - assert self.aedtapp.set_phase_center_per_port(["Global", "Global"]) - else: - assert not self.aedtapp.set_phase_center_per_port() - assert not self.aedtapp.set_phase_center_per_port(["Global", "Global"]) - - assert not self.aedtapp.set_phase_center_per_port(["Global"]) - assert not self.aedtapp.set_phase_center_per_port("Global") - - @pytest.mark.skipif(config["NonGraphical"], reason="Test fails on build machine") - def test_64_import_dxf(self): - self.aedtapp.insert_design("dxf") - dxf_file = os.path.join(local_path, "example_models", "cad", "DXF", "dxf2.dxf") - dxf_layers = self.aedtapp.get_dxf_layers(dxf_file) - assert isinstance(dxf_layers, list) - assert self.aedtapp.import_dxf(dxf_file, dxf_layers) - - def test_65_component_array(self, add_app): - hfss_array = add_app(project_name=component_array, subfolder=test_subfolder) - assert len(hfss_array.component_array) == 1 - - array = hfss_array.component_array["A1"] - assert array.name == hfss_array.component_array_names[0] - - cell1 = array.get_cell(1, 1) - cell2 = array[1, 1] - assert cell2 - assert cell1.rotation == 0 - - assert not array.get_cell(0, 0) - assert not array.get_cell(10, 0) - - lc = array.lattice_vector() - assert len(lc) == 6 - - assert len(array.component_names) == 4 - - assert len(array.post_processing_cells) == 4 - post_cells = array.post_processing_cells - post_cells["Radome_Corner1"] = [8, 1] - array.post_processing_cells = post_cells - assert array.post_processing_cells["Radome_Corner1"] == [8, 1] - - array.cells[0][1].component = None - assert not array.cells[0][1].component - - array.cells[1][1].rotation = 90 - assert array.cells[1][1].rotation == 90 - - array.cells[1][1].rotation = 10 - assert not array.cells[1][1].rotation == 10 - - array.cells[1][1].is_active = False - array.cells[1][1].is_active = 1 - assert not array.cells[1][1].is_active - - assert array.cells[1][2].component == array.component_names[2] - assert not array.cells[1][2].component == "test" - - array.cells[0][1].component = array.component_names[3] - assert array.cells[0][1].component == array.component_names[3] - - hfss_array.component_array["A1"].name = "Array_new" - assert hfss_array.component_array_names[0] == "Array_new" - hfss_array.component_array["Array_new"].name = "A1" - - omodel = hfss_array.get_oo_object(hfss_array.odesign, "Model") - oarray = hfss_array.get_oo_object(omodel, "A1") - - assert array.visible - array.visible = False - assert not oarray.GetPropValue("Visible") - array.visible = True - assert oarray.GetPropValue("Visible") - - assert array.show_cell_number - array.show_cell_number = False - assert not oarray.GetPropValue("Show Cell Number") - array.show_cell_number = True - assert oarray.GetPropValue("Show Cell Number") - - assert array.render == "Shaded" - array.render = "Wireframe" - assert oarray.GetPropValue("Render") == "Wireframe" - array.render = "Shaded" - assert oarray.GetPropValue("Render") == "Shaded" - array.render = "Shaded1" - assert not array.render == "Shaded1" - - a_choices = array.a_vector_choices - assert array.a_vector_name in a_choices - array.a_vector_name = a_choices[0] - assert oarray.GetPropValue("A Vector") == a_choices[0] - array.a_vector_name = "Test" - assert not array.a_vector_name == "Test" - - b_choices = array.b_vector_choices - assert array.b_vector_name in b_choices - array.b_vector_name = b_choices[1] - assert oarray.GetPropValue("B Vector") == b_choices[1] - array.b_vector_name = "Test" - assert not array.b_vector_name == "Test" - - assert array.a_size == 8 - - assert array.b_size == 8 - - assert array.a_length == 0.64 - - assert array.b_length == 0.64 - - assert len(array.lattice_vector()) == 6 - - assert array.padding_cells == 0 - array.padding_cells = 2 - assert oarray.GetPropValue("Padding") == "2" - array.padding_cells = 0 - - assert array.coordinate_system == "Global" - array.coordinate_system = "Corner" - array.coordinate_system = "Global" - - array_csv = os.path.join(local_path, "../_unittest/example_models", test_subfolder, "array_info.csv") - array_info = array.parse_array_info_from_csv(array_csv) - assert len(array_info) == 4 - assert array_info["component"][1] == "02_Patch1" - - assert len(array.get_component_objects()) == 4 - - assert len(array.get_cell_position()) == array.a_size - - # Delete 3D Component - hfss_array.modeler.user_defined_components["03_Radome_Side1"].delete() - array.update_properties() - assert len(array.component_names) == 3 - assert len(array.post_processing_cells) == 3 - - array.delete() - assert not hfss_array.component_array - - def test_66_assign_febi(self, add_app): - aedtapp = add_app(project_name="test_66") - udp = aedtapp.modeler.Position(0, 0, 0) - coax_dimension = 200 - aedtapp.modeler.create_cylinder(aedtapp.AXIS.X, udp, 3, coax_dimension, 0, "inner") - aedtapp.modeler.create_cylinder(aedtapp.AXIS.X, udp, 10, coax_dimension, 0, "outer") - aedtapp.hybrid = True - assert aedtapp.assign_febi(["inner"]) - assert len(aedtapp.boundaries) == 1 - aedtapp.close_project(save_project=False) - - def test_67_transient_composite(self, add_app): - aedtapp = add_app(project_name="test_66") - aedtapp.solution_type = "Transient Composite" - assert aedtapp.solution_type == "Transient Composite" - aedtapp.close_project(save_project=False) - - @pytest.mark.skipif(config["NonGraphical"], reason="Test fails on build machine") - def test_68_import_gds_3d(self): - self.aedtapp.insert_design("gds_import_H3D") - gds_file = os.path.join(local_path, "example_models", "cad", "GDS", "gds1.gds") - assert self.aedtapp.import_gds_3d(gds_file, {7: (100, 10), 9: (110, 5)}) - assert self.aedtapp.import_gds_3d(gds_file, {7: (0, 0), 9: (0, 0)}) - assert self.aedtapp.import_gds_3d(gds_file, {7: (100e-3, 10e-3), 9: (110e-3, 5e-3)}, "mm", 0) - assert not self.aedtapp.import_gds_3d(gds_file, {}) - gds_file = os.path.join(local_path, "example_models", "cad", "GDS", "gds1not.gds") - assert not self.aedtapp.import_gds_3d(gds_file, {7: (100, 10), 9: (110, 5)}) From 8dcbf5c329185bdc803135a874554a99f7e2def7 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Wed, 8 May 2024 14:16:28 +0200 Subject: [PATCH 11/29] Add post processing 1 test --- _unittest/test_12_1_PostProcessing.py | 683 ++++++++++++++++++++++++++ 1 file changed, 683 insertions(+) create mode 100644 _unittest/test_12_1_PostProcessing.py diff --git a/_unittest/test_12_1_PostProcessing.py b/_unittest/test_12_1_PostProcessing.py new file mode 100644 index 00000000000..8e0278bc9c0 --- /dev/null +++ b/_unittest/test_12_1_PostProcessing.py @@ -0,0 +1,683 @@ +import os +import sys +import uuid + +from _unittest.conftest import config +import pytest + +from pyaedt.generic.general_methods import is_linux +from pyaedt.generic.general_methods import read_json +from pyaedt.generic.plot import _parse_aedtplt +from pyaedt.generic.plot import _parse_streamline +from pyaedt.generic.settings import settings + +if config["desktopVersion"] > "2022.2": + test_field_name = "Potter_Horn_231" + test_project_name = "coax_setup_solved_231" + array = "array_simple_231" + sbr_file = "poc_scat_small_231" + q3d_file = "via_gsg_231" + m2d_file = "m2d_field_lines_test_231" + +else: + test_field_name = "Potter_Horn" + test_project_name = "coax_setup_solved" + array = "array_simple" + sbr_file = "poc_scat_small" + q3d_file = "via_gsg" + m2d_file = "m2d_field_lines_test" + +test_circuit_name = "Switching_Speed_FET_And_Diode" +eye_diagram = "SimpleChannel" +ami = "ami" +test_subfolder = "T12" +settings.enable_pandas_output = True + + +@pytest.fixture(scope="class") +def aedtapp(add_app): + app = add_app(project_name=test_project_name, subfolder=test_subfolder) + return app + + +class TestClass: + @pytest.fixture(autouse=True) + def init(self, aedtapp, local_scratch): + self.aedtapp = aedtapp + self.local_scratch = local_scratch + + @pytest.mark.skipif(config["NonGraphical"], reason="Failing on build machine when running in parallel.") + def test_01_export_model_picture(self): + path = self.aedtapp.post.export_model_picture(full_name=os.path.join(self.local_scratch.path, "images2.jpg")) + assert path + path = self.aedtapp.post.export_model_picture( + full_name=os.path.join(self.local_scratch.path, "images3.jpg"), + show_axis=True, + show_grid=False, + show_ruler=True, + ) + assert os.path.exists(path) + path = self.aedtapp.post.export_model_picture(full_name=os.path.join(self.local_scratch.path, "images4.jpg")) + assert path + + def test_01B_Field_Plot(self): + assert len(self.aedtapp.post.available_display_types()) > 0 + assert len(self.aedtapp.post.available_report_types) > 0 + assert len(self.aedtapp.post.available_report_quantities()) > 0 + assert len(self.aedtapp.post.available_report_solutions()) > 0 + cutlist = ["Global:XY", "Global:XZ", "Global:YZ"] + setup_name = self.aedtapp.existing_analysis_sweeps[0] + assert self.aedtapp.setups[0].is_solved + quantity_name = "ComplexMag_E" + intrinsic = {"Freq": "5GHz", "Phase": "180deg"} + min_value = self.aedtapp.post.get_scalar_field_value(quantity_name, "Minimum", setup_name, intrinsics="5GHz") + plot1 = self.aedtapp.post.create_fieldplot_cutplane(cutlist, quantity_name, setup_name, intrinsic) + plot1.IsoVal = "Tone" + plot1.update_field_plot_settings() + plot1.update() + assert self.aedtapp.post.field_plots[plot1.name].IsoVal == "Tone" + assert plot1.change_plot_scale(min_value, "30000") + assert self.aedtapp.post.create_fieldplot_volume("inner", "Vector_E", setup_name, intrinsic) + assert self.aedtapp.post.create_fieldplot_surface( + self.aedtapp.modeler["outer"].faces[0].id, "Mag_E", setup_name, intrinsic + ) + assert self.aedtapp.post.create_fieldplot_surface(self.aedtapp.modeler["outer"], "Mag_E", setup_name, intrinsic) + assert self.aedtapp.post.create_fieldplot_surface( + self.aedtapp.modeler["outer"].faces, "Mag_E", setup_name, intrinsic + ) + assert not self.aedtapp.post.create_fieldplot_surface(123123123, "Mag_E", setup_name, intrinsic) + assert len(self.aedtapp.setups[0].sweeps[0].frequencies) > 0 + assert isinstance(self.aedtapp.setups[0].sweeps[0].basis_frequencies, list) + assert len(self.aedtapp.setups[0].sweeps[1].basis_frequencies) == 2 + mesh_file_path = self.aedtapp.post.export_mesh_obj(setup_name, intrinsic) + assert os.path.exists(mesh_file_path) + mesh_file_path2 = self.aedtapp.post.export_mesh_obj( + setup_name, intrinsic, export_air_objects=True, on_surfaces=False + ) + assert os.path.exists(mesh_file_path2) + + min_value = self.aedtapp.post.get_scalar_field_value( + "E", "Minimum", setup_name, intrinsics="5GHz", is_vector=True + ) + + @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="Not running in ironpython") + def test_01_Animate_plt(self): + cutlist = ["Global:XY"] + phases = [str(i * 5) + "deg" for i in range(2)] + model_gif = self.aedtapp.post.plot_animated_field( + quantity="Mag_E", + assignment=cutlist, + plot_type="CutPlane", + setup=self.aedtapp.nominal_adaptive, + intrinsics={"Freq": "5GHz", "Phase": "0deg"}, + variation_variable="Phase", + variations=phases, + show=False, + export_gif=True, + export_path=self.local_scratch.path, + ) + assert os.path.exists(model_gif.gif_file) + setup_name = self.aedtapp.existing_analysis_sweeps[0] + intrinsic = {"Freq": "5GHz", "Phase": "180deg"} + pl1 = self.aedtapp.post.create_fieldplot_volume("NewObject_IJD39Q", "Mag_E", setup_name, intrinsic) + model_gif2 = self.aedtapp.post.animate_fields_from_aedtplt( + plot_name=pl1.name, + plot_folder=None, + variation_variable="Phase", + variations=phases, + project_path="", + export_gif=False, + show=False, + ) + model_gif2.gif_file = os.path.join(self.aedtapp.working_directory, "test2.gif") + model_gif2.camera_position = [0, 50, 200] + model_gif2.focal_point = [0, 50, 0] + model_gif2.animate() + assert os.path.exists(model_gif2.gif_file) + + @pytest.mark.skipif(config["NonGraphical"] == True, reason="Not running in non-graphical mode") + def test_02_export_fields(self): + quantity_name2 = "ComplexMag_H" + setup_name = "Setup1 : LastAdaptive" + intrinsic = {"Freq": "5GHz", "Phase": "180deg"} + vollist = ["NewObject_IJD39Q"] + plot2 = self.aedtapp.post.create_fieldplot_volume(vollist, quantity_name2, setup_name, intrinsic) + + self.aedtapp.post.export_field_jpg( + os.path.join(self.local_scratch.path, "prova2.jpg"), plot2.name, plot2.plot_folder + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "prova2.jpg")) + assert os.path.exists(plot2.export_image(os.path.join(self.local_scratch.path, "test_x.jpg"))) + + def test_03_create_scattering(self): + setup_name = "Setup1 : Sweep" + portnames = ["1", "2"] + assert self.aedtapp.create_scattering("MyTestScattering") + setup_name = "Setup2 : Sweep" + assert not self.aedtapp.create_scattering("MyTestScattering2", setup_name, portnames, portnames) + + def test_03_get_solution_data(self): + self.aedtapp.analyze(self.aedtapp.active_setup) + trace_names = [] + portnames = ["1", "2"] + for el in portnames: + for el2 in portnames: + trace_names.append("S(" + el + "," + el2 + ")") + cxt = ["Domain:=", "Sweep"] + families = {"Freq": ["All"]} + for el in self.aedtapp.available_variations.nominal_w_values_dict: + families[el] = self.aedtapp.available_variations.nominal_w_values_dict[el] + + my_data = self.aedtapp.post.get_solution_data(expressions=trace_names, variations=families) + assert my_data + assert my_data.expressions + assert len(my_data.data_db10(trace_names[0])) > 0 + assert len(my_data.data_imag(trace_names[0])) > 0 + assert len(my_data.data_real(trace_names[0])) > 0 + assert len(my_data.data_magnitude(trace_names[0])) > 0 + assert my_data.export_data_to_csv(os.path.join(self.local_scratch.path, "output.csv")) + assert os.path.exists(os.path.join(self.local_scratch.path, "output.csv")) + assert self.aedtapp.get_touchstone_data("Setup1") + + def test_04_export_touchstone(self): + setup_name = "Setup1" + sweep_name = "Sweep" + self.aedtapp.export_touchstone( + setup_name, sweep_name, os.path.join(self.local_scratch.path, "Setup1_Sweep.S2p") + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "Setup1_Sweep.S2p")) + + sweep_name = None + self.aedtapp.export_touchstone( + setup_name, sweep_name, os.path.join(self.local_scratch.path, "Setup1_Sweep2.S2p") + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "Setup1_Sweep2.S2p")) + setup_name = None + self.aedtapp.export_touchstone( + setup_name, sweep_name, os.path.join(self.local_scratch.path, "Setup1_Sweep3.S2p") + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "Setup1_Sweep3.S2p")) + + assert self.aedtapp.export_touchstone(setup_name, sweep_name) + + @pytest.mark.skipif(config["desktopVersion"] != "2023.1", reason="Not running in non-graphical mode") + def test_05_export_report_to_jpg(self): + self.aedtapp.post.export_report_to_jpg(self.local_scratch.path, "MyTestScattering") + assert os.path.exists(os.path.join(self.local_scratch.path, "MyTestScattering.jpg")) + + def test_06_export_report_to_csv(self): + self.aedtapp.post.export_report_to_csv( + self.local_scratch.path, + "MyTestScattering", + start="3GHz", + end="6GHz", + step="0.12GHz", + uniform=True, + use_trace_number_format=False, + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "MyTestScattering.csv")) + + def test_06_export_report_to_rdat(self): + self.aedtapp.post.export_report_to_file(self.local_scratch.path, "MyTestScattering", ".rdat") + assert os.path.exists(os.path.join(self.local_scratch.path, "MyTestScattering.rdat")) + + def test_07_export_fields_from_Calculator(self): + self.aedtapp.post.export_field_file_on_grid( + "E", + "Setup1 : LastAdaptive", + self.aedtapp.available_variations.nominal_w_values_dict, + os.path.join(self.local_scratch.path, "Efield.fld"), + grid_stop=[5, 5, 5], + grid_step=[0.5, 0.5, 0.5], + is_vector=True, + intrinsics="5GHz", + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "Efield.fld")) + + self.aedtapp.post.export_field_file_on_grid( + "Mag_E", + "Setup1 : LastAdaptive", + self.aedtapp.available_variations.nominal_w_values_dict, + os.path.join(self.local_scratch.path, "MagEfieldSph.fld"), + grid_type="Spherical", + grid_stop=[5, 300, 300], + grid_step=[5, 50, 50], + is_vector=False, + intrinsics="5GHz", + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "MagEfieldSph.fld")) + + self.aedtapp.post.export_field_file_on_grid( + "Mag_E", + "Setup1 : LastAdaptive", + self.aedtapp.available_variations.nominal_w_values_dict, + os.path.join(self.local_scratch.path, "MagEfieldCyl.fld"), + grid_type="Cylindrical", + grid_stop=[5, 300, 5], + grid_step=[5, 50, 5], + is_vector=False, + intrinsics="5GHz", + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "MagEfieldCyl.fld")) + + # @pytest.mark.skipif( + # config["NonGraphical"], reason="Skipped because it cannot run on build machine in non-graphical mode" + # ) + def test_07_copydata(self): + assert self.aedtapp.post.copy_report_data("MyTestScattering") + + def test_08_manipulate_report(self): + assert self.aedtapp.post.rename_report("MyTestScattering", "MyNewScattering") + assert [plot for plot in self.aedtapp.post.plots if plot.plot_name == "MyNewScattering"] + assert not self.aedtapp.post.rename_report("invalid", "MyNewScattering") + + def test_09_manipulate_report(self): + assert self.aedtapp.post.create_report("dB(S(1,1))") + assert self.aedtapp.post.create_report( + expressions="MaxMagDeltaS", + variations={"Pass": ["All"]}, + primary_sweep_variable="Pass", + report_category="Modal Solution Data", + plot_type="Rectangular Plot", + ) + new_report = self.aedtapp.post.reports_by_category.modal_solution("dB(S(1,1))") + assert new_report.create() + + data = self.aedtapp.post.get_solution_data("S(1,1)") + assert data.primary_sweep == "Freq" + assert data.expressions[0] == "S(1,1)" + assert len(self.aedtapp.post.all_report_names) > 0 + + new_report = self.aedtapp.post.reports_by_category.modal_solution( + "dB(S(1,1))", setup=self.aedtapp.nominal_sweep + ) + assert new_report.create() + + def test_09c_import_into_report(self): + new_report = self.aedtapp.create_scattering("import_test") + csv_file_path = self.aedtapp.post.export_report_to_csv(self.local_scratch.path, "import_test") + rdat_file_path = self.aedtapp.post.export_report_to_file(self.local_scratch.path, "import_test", ".rdat") + plot_name = new_report.plot_name + + trace_names = [] + trace_names.append(new_report.expressions[0]) + families = {"Freq": ["All"]} + for el in self.aedtapp.available_variations.nominal_w_values_dict: + families[el] = self.aedtapp.available_variations.nominal_w_values_dict[el] + + # get solution data and save in .csv file + my_data = self.aedtapp.post.get_solution_data(expressions=trace_names, variations=families) + my_data.export_data_to_csv(os.path.join(self.local_scratch.path, "output.csv")) + csv_solution_data_file_path = os.path.join(self.local_scratch.path, "output.csv") + assert not new_report.import_traces(csv_solution_data_file_path, plot_name) + + # test import with correct inputs from csv + assert new_report.import_traces(csv_file_path, plot_name) + # test import with correct inputs from rdat + assert new_report.import_traces(rdat_file_path, plot_name) + # test import with not existing plot_name + with pytest.raises(ValueError): + new_report.import_traces(csv_file_path, "plot_name") + # test import with random file path + with pytest.raises(FileExistsError): + new_report.import_traces(str(uuid.uuid4()), plot_name) + # test import without plot_name + with pytest.raises(ValueError): + new_report.import_traces(csv_file_path, None) + + def test_09d_delete_traces_from_report(self): + new_report = self.aedtapp.create_scattering("delete_traces_test") + traces_to_delete = [new_report.expressions[0]] + plot_name = new_report.plot_name + assert new_report.delete_traces(plot_name, traces_to_delete) + with pytest.raises(ValueError): + new_report.delete_traces("plot_name", traces_to_delete) + with pytest.raises(ValueError): + new_report.delete_traces(plot_name, ["V(out)_Test"]) + + def test_09e_add_traces_to_report(self): + new_report = self.aedtapp.create_scattering("add_traces_test") + traces = new_report.get_solution_data().expressions + assert new_report.add_trace_to_report(traces) + setup = self.aedtapp.post.plots[0].setup + variations = self.aedtapp.post.plots[0].variations["height"] = "10mm" + assert not new_report.add_trace_to_report(traces, setup, variations) + variations = self.aedtapp.post.plots[0].variations + assert new_report.add_trace_to_report(traces, setup, variations) + setup = "Transient" + assert not new_report.add_trace_to_report(traces, setup, variations) + + def test_09f_update_trace_name(self): + report = [plot for plot in self.aedtapp.post.plots if plot.plot_name == "add_traces_test"][0] + old_trace_name = report.traces[0].name + assert old_trace_name in report.traces[0].aedt_name + new_name = "update_trace_name_test" + report.traces[0].name = new_name + assert new_name in report.traces[0].aedt_name + + def test_09g_update_traces_in_report(self): + new_report = self.aedtapp.create_scattering("update_traces_test") + traces = new_report.get_solution_data().expressions + assert new_report.update_trace_in_report(traces) + setup = self.aedtapp.post.plots[0].setup + variations = self.aedtapp.post.plots[0].variations["height"] = "10mm" + assert not new_report.add_trace_to_report(traces, setup, variations) + variations = self.aedtapp.post.plots[0].variations + assert new_report.update_trace_in_report(traces, setup, variations) + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non-graphical mode in version earlier than 2022.2." + ) + def test_09h_create_monitor(self): # pragma: no cover + assert self.aedtapp.post.create_report("dB(S(1,1))") + new_report = self.aedtapp.post.reports_by_category.modal_solution("dB(S(1,1))") + assert new_report.create() + + assert new_report.add_cartesian_x_marker("3GHz") + assert new_report.add_cartesian_y_marker("-55") + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", + reason="Skipped because it cannot run on build machine in non-graphical mode", + ) + def test_09i_add_line_from_point(self): # pragma: no cover + new_report = self.aedtapp.post.reports_by_category.modal_solution("dB(S(1,1))") + assert new_report.create() + assert new_report.add_limit_line_from_points([3, 5, 5, 3], [-50, -50, -60, -60], "GHz") + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non-graphical mode in version earlier than 2022.2." + ) + def test_09l_add_line_from_equation(self): + new_report = self.aedtapp.post.reports_by_category.modal_solution("dB(S(1,1))") + assert new_report.create() + assert new_report.add_limit_line_from_equation(start_x=1, stop_x=20, step=0.5, units="GHz") + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non-graphical mode in version earlier than 2022.2." + ) + def test_09m_edit_properties(self): + report = self.aedtapp.post.create_report("dB(S(1,1))") + assert report.edit_grid() + assert report.edit_grid(minor_x=False) + assert report.edit_grid(major_y=False) + assert report.edit_grid(major_color=(0, 0, 125)) + assert report.edit_grid(major_color=(0, 255, 0)) + assert report.edit_grid(style_major="Dot") + assert report.edit_x_axis(font="Courier", font_size=14, italic=True, bold=False, color=(0, 128, 0)) + assert report.edit_y_axis(font="Courier", font_size=14, italic=True, bold=False, color=(0, 128, 0)) + assert report.edit_x_axis( + font="Courier", font_size=14, italic=True, bold=False, color=(0, 128, 0), label="Freq" + ) + assert report.edit_y_axis( + font="Courier", font_size=14, italic=True, bold=False, color=(0, 128, 0), label="Touchstone" + ) + + assert report.edit_x_axis_scaling( + linear_scaling=True, + min_scale="1GHz", + max_scale="5GHz", + minor_tick_divs=10, + min_spacing="0.5GHz", + units="MHz", + ) + assert report.edit_y_axis_scaling( + linear_scaling=False, min_scale="-50", max_scale="10", minor_tick_divs=10, min_spacing="5" + ) + assert report.edit_legend( + show_solution_name=True, show_variation_key=False, show_trace_name=False, back_color=(255, 255, 255) + ) + assert report.edit_header( + company_name="PyAEDT", + show_design_name=True, + font="Arial", + title_size=12, + subtitle_size=12, + italic=False, + bold=False, + color=(0, 125, 125), + ) + assert report.edit_general_settings( + background_color=(128, 255, 255), + plot_color=(255, 0, 255), + enable_y_stripes=True, + field_width=6, + precision=6, + use_scientific_notation=True, + ) + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non-graphical mode in version earlier than 2022.2." + ) + def test_09n_add_line_from_point(self): # pragma: no cover + new_report = self.aedtapp.post.reports_by_category.modal_solution("dB(S(1,1))") + new_report.create() + style = new_report.traces[0].LINESTYLE + trace = new_report.traces[0].TRACETYPE + symbols = new_report.traces[0].SYMBOLSTYLE + + assert new_report.traces[0].set_trace_properties( + trace_style=style.Dot, width=5, trace_type=trace.Digital, color=(0, 255, 0) + ) + assert new_report.traces[0].set_symbol_properties( + show=True, style=symbols.Box, show_arrows=False, fill=False, color=(0, 0, 255) + ) + new_report.add_limit_line_from_points([3, 5, 5, 3], [-50, -50, -60, -60], "GHz") + assert new_report.limit_lines[0].set_line_properties( + style=style.Dot, width=4, hatch_above=False, violation_emphasis=True, hatch_pixels=1, color=(255, 255, 0) + ) + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non-graphical mode in version earlier than 2022.2." + ) + def test_09o_add_note(self): # pragma: no cover + new_report = self.aedtapp.post.reports_by_category.modal_solution() + new_report.create() + + new_report.add_note("Test", 8000, 1500) + assert new_report.notes[0].set_note_properties( + back_color=(0, 0, 255), + border_visibility=False, + border_width=3, + font="Cambria", + italic=True, + bold=True, + font_size=10, + color=(255, 0, 0), + ) + + def test_10_delete_report(self): + plots_number = len(self.aedtapp.post.plots) + assert self.aedtapp.post.delete_report("MyNewScattering") + assert len(self.aedtapp.post.plots) == plots_number - 1 + assert self.aedtapp.post.delete_report() + assert len(self.aedtapp.post.plots) == 0 + + def test_12_steal_on_focus(self): + assert self.aedtapp.post.steal_focus_oneditor() + + @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="Not running in ironpython") + def test_14_Field_Ploton_cutplanedesignname(self): + cutlist = ["Global:XY"] + setup_name = self.aedtapp.existing_analysis_sweeps[0] + quantity_name = "ComplexMag_E" + intrinsic = {"Freq": "5GHz", "Phase": "180deg"} + self.aedtapp.logger.info("Generating the plot") + plot1 = self.aedtapp.post.create_fieldplot_cutplane(cutlist, quantity_name, setup_name, intrinsic) + plot1.IsoVal = "Tone" + assert plot1.update_field_plot_settings() + self.aedtapp.logger.info("Generating the image") + plot_obj = self.aedtapp.post.plot_field_from_fieldplot( + plot_name=plot1.name, + project_path=self.local_scratch.path, + mesh_plot=False, + image_format="jpg", + view="xy", + plot_label=plot1.name + " label", + show=False, + ) + assert os.path.exists(plot_obj.image_file) + os.unlink(plot_obj.image_file) + plot_obj.x_scale = 1.1 + plot_obj.y_scale = 0.9 + plot_obj.z_scale = 0.3 + assert plot_obj.x_scale == 1.1 + assert plot_obj.y_scale == 0.9 + assert plot_obj.z_scale == 0.3 + + plot_obj.background_image = os.path.join(self.local_scratch.path, "file_not_exists.jpg") + assert not plot_obj.background_image + plot_obj.convert_fields_in_db = True + plot_obj.log_multiplier = 20 + plot_obj.plot(plot_obj.image_file) + assert os.path.exists(plot_obj.image_file) + + plot_obj = self.aedtapp.post.plot_field_from_fieldplot( + plot_name=plot1.name, + project_path=self.local_scratch.path, + mesh_plot=False, + image_format="jpg", + view="xy", + plot_label=plot1.name + " label", + show=False, + file_format="aedtplt", + ) + assert os.path.exists(plot_obj.image_file) + plot_obj.plot(plot_obj.image_file) + + @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="Not running in IronPython.") + def test_14B_Field_Ploton_Vector(self): + cutlist = ["Global:XY"] + setup_name = self.aedtapp.existing_analysis_sweeps[0] + quantity_name = "Vector_E" + intrinsic = {"Freq": "5GHz", "Phase": "180deg"} + self.aedtapp.logger.info("Generating the plot") + plot1 = self.aedtapp.post.create_fieldplot_cutplane( + cutlist, quantity_name, setup_name, intrinsic, filter_objects=self.aedtapp.modeler.object_names + ) + plot1.IsoVal = "Tone" + assert plot1.update_field_plot_settings() + self.aedtapp.logger.info("Generating the image") + plot_obj = self.aedtapp.post.plot_field( + "Vector_E", + cutlist, + "CutPlane", + setup=setup_name, + intrinsics=intrinsic, + mesh_on_fields=False, + view="isometric", + show=False, + export_path=self.local_scratch.path, + image_format="jpg", + ) + assert os.path.exists(plot_obj.image_file) + + @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="Not running in ironpython") + def test_15_export_plot(self): + obj = self.aedtapp.post.plot_model_obj( + show=False, export_path=os.path.join(self.local_scratch.path, "image.jpg") + ) + assert os.path.exists(obj.image_file) + obj2 = self.aedtapp.post.plot_model_obj( + show=False, export_path=os.path.join(self.local_scratch.path, "image2.jpg"), plot_as_separate_objects=False + ) + assert os.path.exists(obj2.image_file) + + @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="Not running in ironpython") + def test_16_create_field_plot(self): + cutlist = ["Global:XY"] + plot = self.aedtapp.post._create_fieldplot( + assignment=cutlist, + quantity="Mag_E", + setup=self.aedtapp.nominal_adaptive, + intrinsics={}, + list_type="CutPlane", + ) + assert plot + + def test_53_line_plot(self): + udp1 = [0, 0, 0] + udp2 = [1, 0, 0] + setup_name = "Setup1 : LastAdaptive" + intrinsic = {"Freq": "5GHz", "Phase": "180deg"} + self.aedtapp.modeler.create_polyline([udp1, udp2], name="Poly1", non_model=True) + assert self.aedtapp.post.create_fieldplot_line("Poly1", "Mag_E", setup_name, intrinsic) + + def test_55_reload(self, add_app): + self.aedtapp.save_project() + app2 = add_app(project_name=self.aedtapp.project_name, just_open=True) + assert len(app2.post.field_plots) == len(self.aedtapp.post.field_plots) + + def test_58_test_no_report(self): + assert not self.aedtapp.post.reports_by_category.eye_diagram() + assert self.aedtapp.post.reports_by_category.eigenmode() + + def test_59_test_parse_vector(self): + local_path = os.path.dirname(os.path.realpath(__file__)) + + out = _parse_aedtplt( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "test_vector.aedtplt", + ) + ) + assert isinstance(out[0], list) + assert isinstance(out[1], list) + assert isinstance(out[2], list) + assert isinstance(out[3], bool) + assert _parse_aedtplt( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "test_vector_no_solutions.aedtplt", + ) + ) + + def test_60_test_parse_vector(self): + local_path = os.path.dirname(os.path.realpath(__file__)) + out = _parse_streamline( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "test_streamline.fldplt", + ) + ) + assert isinstance(out, list) + + def test_61_export_mesh(self): + assert os.path.exists(self.aedtapp.export_mesh_stats("Setup1")) + + def test_67_sweep_from_json(self): + local_path = os.path.dirname(os.path.realpath(__file__)) + dict_vals = read_json( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + "report_json", + "Modal_Report_Simple.json", + ) + ) + assert self.aedtapp.post.create_report_from_configuration(report_settings=dict_vals) + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" + ) + def test_70_sweep_from_json(self): + local_path = os.path.dirname(os.path.realpath(__file__)) + assert self.aedtapp.post.create_report_from_configuration( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + "report_json", + "Modal_Report.json", + ) + ) + + def test_74_dynamic_update(self): + val = self.aedtapp.post.update_report_dynamically + self.aedtapp.post.update_report_dynamically = not val + assert self.aedtapp.post.update_report_dynamically != val From b5693d455d9220f5347e8d5a039fb87a8ad698fd Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Wed, 8 May 2024 14:53:00 +0200 Subject: [PATCH 12/29] Fix UT --- _unittest/test_12_1_PostProcessing.py | 41 ++++----------------------- 1 file changed, 5 insertions(+), 36 deletions(-) diff --git a/_unittest/test_12_1_PostProcessing.py b/_unittest/test_12_1_PostProcessing.py index 8e0278bc9c0..addd18ff579 100644 --- a/_unittest/test_12_1_PostProcessing.py +++ b/_unittest/test_12_1_PostProcessing.py @@ -615,37 +615,18 @@ def test_58_test_no_report(self): def test_59_test_parse_vector(self): local_path = os.path.dirname(os.path.realpath(__file__)) - out = _parse_aedtplt( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "test_vector.aedtplt", - ) - ) + out = _parse_aedtplt(os.path.join(local_path, "example_models", test_subfolder, "test_vector.aedtplt")) assert isinstance(out[0], list) assert isinstance(out[1], list) assert isinstance(out[2], list) assert isinstance(out[3], bool) assert _parse_aedtplt( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "test_vector_no_solutions.aedtplt", - ) + os.path.join(local_path, "example_models", test_subfolder, "test_vector_no_solutions.aedtplt") ) def test_60_test_parse_vector(self): local_path = os.path.dirname(os.path.realpath(__file__)) - out = _parse_streamline( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "test_streamline.fldplt", - ) - ) + out = _parse_streamline(os.path.join(local_path, "example_models", test_subfolder, "test_streamline.fldplt")) assert isinstance(out, list) def test_61_export_mesh(self): @@ -653,14 +634,7 @@ def test_61_export_mesh(self): def test_67_sweep_from_json(self): local_path = os.path.dirname(os.path.realpath(__file__)) - dict_vals = read_json( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - "report_json", - "Modal_Report_Simple.json", - ) - ) + dict_vals = read_json(os.path.join(local_path, "example_models", "report_json", "Modal_Report_Simple.json")) assert self.aedtapp.post.create_report_from_configuration(report_settings=dict_vals) @pytest.mark.skipif( @@ -669,12 +643,7 @@ def test_67_sweep_from_json(self): def test_70_sweep_from_json(self): local_path = os.path.dirname(os.path.realpath(__file__)) assert self.aedtapp.post.create_report_from_configuration( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - "report_json", - "Modal_Report.json", - ) + os.path.join(local_path, "example_models", "report_json", "Modal_Report.json") ) def test_74_dynamic_update(self): From 5c4bcde275521857547c6522d8c3ffc4d251e411 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Wed, 8 May 2024 17:09:46 +0200 Subject: [PATCH 13/29] Fix UT --- _unittest/test_12_PostProcessing.py | 1026 +++++++++++++++++++++++++++ 1 file changed, 1026 insertions(+) create mode 100644 _unittest/test_12_PostProcessing.py diff --git a/_unittest/test_12_PostProcessing.py b/_unittest/test_12_PostProcessing.py new file mode 100644 index 00000000000..1712bd9d95f --- /dev/null +++ b/_unittest/test_12_PostProcessing.py @@ -0,0 +1,1026 @@ +import os +import sys + +from _unittest.conftest import config +import pytest + +from pyaedt import Circuit +from pyaedt import Icepak +from pyaedt import Maxwell2d +from pyaedt import Q2d +from pyaedt import Q3d +from pyaedt.generic.general_methods import is_linux +from pyaedt.generic.pdf import AnsysReport +from pyaedt.generic.plot import _parse_aedtplt +from pyaedt.generic.plot import _parse_streamline +from pyaedt.generic.settings import settings +from pyaedt.modules.solutions import FfdSolutionData + +if config["desktopVersion"] > "2022.2": + test_field_name = "Potter_Horn_231" + test_project_name = "coax_setup_solved_231" + array = "array_simple_231" + sbr_file = "poc_scat_small_231" + q3d_file = "via_gsg_231" + m2d_file = "m2d_field_lines_test_231" + +else: + test_field_name = "Potter_Horn" + test_project_name = "coax_setup_solved" + array = "array_simple" + sbr_file = "poc_scat_small" + q3d_file = "via_gsg" + m2d_file = "m2d_field_lines_test" + +test_circuit_name = "Switching_Speed_FET_And_Diode" +test_emi_name = "EMI_RCV_241" +eye_diagram = "SimpleChannel" +ami = "ami" +ipk_post_proj = "for_icepak_post" +test_subfolder = "T12" +settings.enable_pandas_output = True + + +@pytest.fixture(scope="class") +def field_test(add_app): + app = add_app(project_name=test_field_name, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def circuit_test(add_app): + app = add_app(project_name=test_circuit_name, design_name="Diode", application=Circuit, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def emi_receiver_test(add_app): + app = add_app(project_name=test_emi_name, design_name="CE_band", application=Circuit, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def diff_test(add_app, circuit_test): + app = add_app(project_name=circuit_test.project_name, design_name="diff", application=Circuit, just_open=True) + return app + + +@pytest.fixture(scope="class") +def sbr_test(add_app): + app = add_app(project_name=sbr_file, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def q3dtest(add_app): + app = add_app(project_name=q3d_file, application=Q3d, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def q2dtest(add_app, q3dtest): + app = add_app(project_name=q3dtest.project_name, application=Q2d, just_open=True) + return app + + +@pytest.fixture(scope="class") +def eye_test(add_app, q3dtest): + app = add_app(project_name=eye_diagram, application=Circuit, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def icepak_post(add_app): + app = add_app(project_name=ipk_post_proj, application=Icepak, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def ami_test(add_app, q3dtest): + app = add_app(project_name=ami, application=Circuit, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def array_test(add_app, q3dtest): + app = add_app(project_name=array, subfolder=test_subfolder, solution_type="Modal") + return app + + +@pytest.fixture(scope="class") +def m2dtest(add_app, q3dtest): + app = add_app(project_name=m2d_file, application=Maxwell2d, subfolder=test_subfolder) + return app + + +class TestClass: + @pytest.fixture(autouse=True) + def init(self, local_scratch): + self.local_scratch = local_scratch + + def test_09_manipulate_report(self, field_test): + variations = field_test.available_variations.nominal_w_values_dict + variations["Theta"] = ["All"] + variations["Phi"] = ["All"] + variations["Freq"] = ["30GHz"] + field_test.set_source_context(["1"]) + context = {"Context": "3D", "SourceContext": "1:1"} + assert field_test.post.create_report( + "db(GainTotal)", + field_test.nominal_adaptive, + variations=variations, + primary_sweep_variable="Phi", + secondary_sweep_variable="Theta", + report_category="Far Fields", + plot_type="3D Polar Plot", + context=context, + ) + assert field_test.post.create_report( + "db(GainTotal)", + field_test.nominal_adaptive, + variations=variations, + primary_sweep_variable="Phi", + secondary_sweep_variable="Theta", + report_category="Far Fields", + plot_type="3D Polar Plot", + context="3D", + ) + report = AnsysReport() + report.create() + assert report.add_project_info(field_test) + + def test_09_manipulate_report_B(self, field_test): + variations = field_test.available_variations.nominal_w_values_dict + variations["Theta"] = ["All"] + variations["Phi"] = ["All"] + variations["Freq"] = ["30GHz"] + new_report = field_test.post.reports_by_category.far_field("db(RealizedGainTotal)", field_test.nominal_adaptive) + new_report.variations = variations + new_report.report_type = "3D Polar Plot" + new_report.far_field_sphere = "3D" + assert new_report.create() + + new_report2 = field_test.post.reports_by_category.far_field( + "db(RealizedGainTotal)", field_test.nominal_adaptive, "3D", "1:1" + ) + new_report2.variations = variations + new_report2.report_type = "3D Polar Plot" + assert new_report2.create() + + new_report3 = field_test.post.reports_by_category.antenna_parameters( + "db(PeakRealizedGain)", field_test.nominal_adaptive, "3D" + ) + new_report3.report_type = "Data Table" + assert new_report3.create() + new_report4 = field_test.post.reports_by_category.antenna_parameters( + "db(PeakRealizedGain)", infinite_sphere="3D" + ) + new_report4.report_type = "Data Table" + assert new_report4.create() + + def test_09_manipulate_report_C(self, field_test): + variations = field_test.available_variations.nominal_w_values_dict + variations["Theta"] = ["All"] + variations["Phi"] = ["All"] + variations["Freq"] = ["30GHz"] + field_test.analyze(field_test.active_setup) + data = field_test.post.get_solution_data( + "GainTotal", + field_test.nominal_adaptive, + variations=variations, + primary_sweep_variable="Theta", + report_category="Far Fields", + context="3D", + ) + assert data.plot(is_polar=True) + assert data.plot_3d() + assert field_test.post.create_3d_plot(data) + + def test_09_manipulate_report_D(self, field_test): + variations = field_test.available_variations.nominal_w_values_dict + variations["Theta"] = ["All"] + variations["Phi"] = ["All"] + variations["Freq"] = ["30GHz"] + context = {"Context": "3D", "SourceContext": "1:1"} + data = field_test.post.get_solution_data( + "GainTotal", + field_test.nominal_adaptive, + variations=variations, + primary_sweep_variable="Theta", + report_category="Far Fields", + context=context, + ) + assert data.plot(is_polar=True) + assert data.plot_3d() + assert field_test.post.create_3d_plot(data) + assert data.primary_sweep == "Theta" + assert len(data.data_magnitude("GainTotal")) > 0 + assert not data.data_magnitude("GainTotal2") + assert field_test.post.create_report( + "S(1,1)", field_test.nominal_sweep, variations=variations, plot_type="Smith Chart" + ) + + def test_09_manipulate_report_E(self, field_test): + field_test.modeler.create_polyline([[0, 0, 0], [0, 5, 30]], name="Poly1", non_model=True) + variations2 = field_test.available_variations.nominal_w_values_dict + + assert field_test.setups[0].create_report( + "Mag_E", primary_sweep_variable="Distance", report_category="Fields", context="Poly1" + ) + new_report = field_test.post.reports_by_category.fields("Mag_H", field_test.nominal_adaptive) + new_report.variations = variations2 + new_report.polyline = "Poly1" + assert new_report.create() + new_report = field_test.post.reports_by_category.fields("Mag_H") + new_report.variations = variations2 + new_report.polyline = "Poly1" + assert new_report.create() + new_report = field_test.post.reports_by_category.modal_solution("S(1,1)") + new_report.report_type = "Smith Chart" + assert new_report.create() + data = field_test.setups[0].get_solution_data( + "Mag_E", variations=variations2, primary_sweep_variable="Theta", report_category="Fields", context="Poly1" + ) + assert data.units_sweeps["Phase"] == "deg" + + assert field_test.post.get_far_field_data( + expressions="RealizedGainTotal", setup_sweep_name=field_test.nominal_adaptive, domain="3D" + ) + data_farfield2 = field_test.post.get_far_field_data( + expressions="RealizedGainTotal", + setup_sweep_name=field_test.nominal_adaptive, + domain={"Context": "3D", "SourceContext": "1:1"}, + ) + assert data_farfield2.plot(formula="db20", is_polar=True) + + assert field_test.post.reports_by_category.terminal_solution() + + assert not field_test.post.get_solution_data_per_variation( + solution_type="Far Fields", expressions="RealizedGainTotal" + ) + + def test_09b_export_report_A(self, circuit_test): + files = circuit_test.export_results() + assert len(files) > 0 + report = AnsysReport() + report.create() + assert report.add_project_info(circuit_test) + + def test_09b_export_report_B(self, q2dtest): + q2dtest.analyze() + files = q2dtest.export_results() + assert len(files) > 0 + + def test_09b_export_report_C(self, q3dtest): + q3dtest.analyze_setup("Setup1") + files = q3dtest.export_results() + assert len(files) > 0 + + @pytest.mark.skipif(is_linux, reason="Crashing on Linux") + def test_17_circuit(self, circuit_test): + assert not circuit_test.setups[0].is_solved + + circuit_test.analyze_setup("LNA") + circuit_test.analyze_setup("Transient") + assert circuit_test.setups[0].is_solved + assert circuit_test.setups[0].create_report(["dB(S(Port1, Port1))", "dB(S(Port1, Port2))"]) + new_report = circuit_test.post.reports_by_category.standard( + ["dB(S(Port1, Port1))", "dB(S(Port1, Port2))"], "LNA" + ) + assert new_report.create() + data1 = circuit_test.post.get_solution_data(["dB(S(Port1,Port1))", "dB(S(Port1,Port2))"], "LNA") + assert data1.primary_sweep == "Freq" + assert circuit_test.post.create_report(["V(net_11)"], "Transient", "Time") + data11 = circuit_test.post.get_solution_data(setup_sweep_name="LNA", math_formula="dB") + assert data11.primary_sweep == "Freq" + assert "dB(S(Port2,Port1))" in data11.expressions + assert circuit_test.post.create_report(["V(net_11)"], "Transient", "Time") + new_report = circuit_test.post.reports_by_category.standard(["V(net_11)"], "Transient") + new_report.domain = "Time" + assert new_report.create() + data2 = circuit_test.post.get_solution_data(["V(net_11)"], "Transient", "Time") + assert data2.primary_sweep == "Time" + assert len(data2.data_magnitude()) > 0 + context = {"algorithm": "FFT", "max_frequency": "100MHz", "time_stop": "200ns", "test": ""} + data3 = circuit_test.post.get_solution_data(["V(net_11)"], "Transient", "Spectral", context=context) + assert data3.units_sweeps["Spectrum"] == circuit_test.odesktop.GetDefaultUnit("Frequency") + assert len(data3.data_real()) > 0 + new_report = circuit_test.post.reports_by_category.spectral(["dB(V(net_11))"], "Transient") + new_report.window = "Hanning" + new_report.max_freq = "1GHz" + new_report.time_start = "1ns" + new_report.time_stop = "190ns" + new_report.plot_continous_spectrum = True + assert new_report.create() + new_report = circuit_test.post.reports_by_category.spectral(["dB(V(net_11))"]) + assert new_report.create() + new_report = circuit_test.post.reports_by_category.spectral(["dB(V(net_11))", "dB(V(Port1))"], "Transient") + new_report.window = "Kaiser" + new_report.adjust_coherent_gain = False + new_report.kaiser_coeff = 2 + new_report.algorithm = "Fourier Transform" + new_report.max_freq = "1GHz" + new_report.time_start = "1ns" + new_report.time_stop = "190ns" + new_report.plot_continous_spectrum = False + assert new_report.create() + assert circuit_test.post.create_report(["dB(V(net_11))", "dB(V(Port1))"], domain="Spectrum") + new_report = circuit_test.post.reports_by_category.spectral(None, "Transient") + new_report.window = "Hanning" + new_report.max_freq = "1GHz" + new_report.time_start = "1ns" + new_report.time_stop = "190ns" + new_report.plot_continous_spectrum = True + assert new_report.create() + + @pytest.mark.skipif(is_linux, reason="Crashing on Linux") + def test_18_diff_plot(self, diff_test): + assert len(diff_test.post.available_display_types()) > 0 + assert len(diff_test.post.available_report_types) > 0 + assert len(diff_test.post.available_report_quantities()) > 0 + assert len(diff_test.post.available_report_solutions()) > 0 + diff_test.analyze_setup("LinearFrequency") + assert diff_test.setups[0].is_solved + variations = diff_test.available_variations.nominal_w_values_dict + variations["Freq"] = ["All"] + variations["l1"] = ["All"] + assert diff_test.post.create_report( + ["dB(S(Diff1, Diff1))"], + "LinearFrequency", + variations=variations, + primary_sweep_variable="l1", + context="Differential Pairs", + ) + new_report1 = diff_test.post.reports_by_category.standard() + assert new_report1.expressions + new_report = diff_test.post.reports_by_category.standard("dB(S(1,1))") + new_report.differential_pairs = True + assert new_report.create() + assert new_report.get_solution_data() + new_report2 = diff_test.post.reports_by_category.standard("TDRZ(1)") + new_report2.differential_pairs = True + new_report2.pulse_rise_time = 3e-12 + new_report2.time_windowing = 3 + new_report2.domain = "Time" + + assert new_report2.create() + + data1 = diff_test.post.get_solution_data( + ["S(Diff1, Diff1)"], + "LinearFrequency", + variations=variations, + primary_sweep_variable="Freq", + context="Differential Pairs", + ) + assert data1.primary_sweep == "Freq" + data1.plot(formula="db20", snapshot_path=os.path.join(self.local_scratch.path, "temp1.jpg")) + data1.primary_sweep = "l1" + assert data1.primary_sweep == "l1" + assert len(data1.data_magnitude()) == 5 + assert data1.plot("S(Diff1, Diff1)", snapshot_path=os.path.join(self.local_scratch.path, "temp2.jpg")) + assert data1.plot(formula="db20", snapshot_path=os.path.join(self.local_scratch.path, "temp3.jpg")) + assert data1.plot(formula="db10", snapshot_path=os.path.join(self.local_scratch.path, "temp4.jpg")) + assert data1.plot(formula="mag", snapshot_path=os.path.join(self.local_scratch.path, "temp5.jpg")) + assert data1.plot(formula="re", snapshot_path=os.path.join(self.local_scratch.path, "temp6.jpg")) + assert data1.plot(formula="im", snapshot_path=os.path.join(self.local_scratch.path, "temp7.jpg")) + assert data1.plot(formula="phasedeg", snapshot_path=os.path.join(self.local_scratch.path, "temp8.jpg")) + assert data1.plot(formula="phaserad", snapshot_path=os.path.join(self.local_scratch.path, "temp9.jpg")) + + assert diff_test.create_touchstone_report( + name="Diff_plot", curves=["dB(S(Diff1, Diff1))"], solution="LinearFrequency", differential_pairs=True + ) + + @pytest.mark.skipif(is_linux, reason="Failing on Linux") + def test_51_get_efields(self, field_test): + assert field_test.post.get_efields_data(ff_setup="3D") + + @pytest.mark.skipif( + is_linux or sys.version_info < (3, 8), reason="plot_scene method is not supported in ironpython" + ) + def test_55_time_plot(self, sbr_test): + sbr_test.analyze(sbr_test.active_setup, use_auto_settings=False) + assert sbr_test.setups[0].is_solved + solution_data = sbr_test.post.get_solution_data( + expressions=["NearEX", "NearEY", "NearEZ"], report_category="Near Fields", context="Near_Field" + ) + assert solution_data + assert len(solution_data.primary_sweep_values) > 0 + assert len(solution_data.primary_sweep_variations) > 0 + assert solution_data.set_active_variation(0) + assert not solution_data.set_active_variation(99) + t_matrix = solution_data.ifft("NearE", window=True) + assert t_matrix.any() + frames_list = solution_data.ifft_to_file( + coord_system_center=[-0.15, 0, 0], db_val=True, csv_path=os.path.join(sbr_test.working_directory, "csv") + ) + assert os.path.exists(frames_list) + sbr_test.post.plot_scene( + frames_list, os.path.join(sbr_test.working_directory, "animation.gif"), norm_index=5, dy_rng=35, show=False + ) + assert os.path.exists(os.path.join(sbr_test.working_directory, "animation.gif")) + sbr_test.post.plot_scene( + frames_list, + os.path.join(sbr_test.working_directory, "animation2.gif"), + norm_index=5, + dy_rng=35, + show=False, + convert_fields_in_db=True, + log_multiplier=20.0, + ) + assert os.path.exists(os.path.join(sbr_test.working_directory, "animation2.gif")) + + def test_56_test_export_q3d_results(self, q3dtest): + q3dtest.analyze(q3dtest.active_setup) + assert os.path.exists(q3dtest.export_convergence("Setup1")) + assert os.path.exists(q3dtest.export_profile("Setup1")) + new_report = q3dtest.post.reports_by_category.standard(q3dtest.get_traces_for_plot()) + assert new_report.create() + q3dtest.modeler.create_polyline([[0, -5, 0.425], [0.5, 5, 0.5]], name="Poly1", non_model=True) + new_report = q3dtest.post.reports_by_category.cg_fields("SmoothQ", polyline="Poly1") + assert new_report.create() + new_report = q3dtest.post.reports_by_category.rl_fields("Mag_SurfaceJac", polyline="Poly1") + assert new_report.create() + new_report = q3dtest.post.reports_by_category.dc_fields("Mag_VolumeJdc", polyline="Poly1") + assert new_report.create() + assert len(q3dtest.post.plots) == 6 + + def test_57_test_export_q2d_results(self, q2dtest): + q2dtest.analyze(q2dtest.active_setup) + assert os.path.exists(q2dtest.export_convergence("Setup1")) + assert os.path.exists(q2dtest.export_profile("Setup1")) + new_report = q2dtest.post.reports_by_category.standard(q2dtest.get_traces_for_plot()) + assert new_report.create() + q2dtest.modeler.create_polyline([[-1.9, -0.1, 0], [-1.2, -0.2, 0]], name="Poly1", non_model=True) + new_report = q2dtest.post.reports_by_category.cg_fields("Mag_E", polyline="Poly1") + assert new_report.create() + new_report = q2dtest.post.reports_by_category.rl_fields("Mag_H", polyline="Poly1") + assert new_report.create() + sol = new_report.get_solution_data() + sol.enable_pandas_output = True + data = sol.full_matrix_real_imag + data_mag = sol.full_matrix_mag_phase + sol.data_magnitude() + sol.enable_pandas_output = False + assert len(q2dtest.post.plots) == 3 + new_report = q2dtest.post.reports_by_category.standard() + assert new_report.get_solution_data() + + def test_58_test_no_report(self, q3dtest): + assert not q3dtest.post.reports_by_category.modal_solution() + assert not q3dtest.post.reports_by_category.terminal_solution() + + def test_58_test_no_report_B(self, q2dtest): + assert not q2dtest.post.reports_by_category.far_field() + assert not q2dtest.post.reports_by_category.near_field() + assert not q2dtest.post.reports_by_category.eigenmode() + + def test_59_test_parse_vector(self): + local_path = os.path.dirname(os.path.realpath(__file__)) + + out = _parse_aedtplt( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "test_vector.aedtplt", + ) + ) + assert isinstance(out[0], list) + assert isinstance(out[1], list) + assert isinstance(out[2], list) + assert isinstance(out[3], bool) + assert _parse_aedtplt( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "test_vector_no_solutions.aedtplt", + ) + ) + + def test_60_test_parse_vector(self): + local_path = os.path.dirname(os.path.realpath(__file__)) + out = _parse_streamline( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "test_streamline.fldplt", + ) + ) + assert isinstance(out, list) + + def test_61_export_mesh(self, q3dtest): + assert os.path.exists(q3dtest.export_mesh_stats("Setup1")) + assert os.path.exists(q3dtest.export_mesh_stats("Setup1", setup_type="AC RL")) + + def test_62_eye_diagram(self, eye_test): + eye_test.analyze(eye_test.active_setup) + rep = eye_test.post.reports_by_category.eye_diagram("AEYEPROBE(OutputEye)", "QuickEyeAnalysis") + rep.time_start = "0ps" + rep.time_stop = "50us" + rep.unit_interval = "1e-9" + assert rep.create() + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" + ) + def test_63_mask(self, eye_test): + eye_test.analyze(eye_test.active_setup) + rep = eye_test.post.reports_by_category.eye_diagram("AEYEPROBE(OutputEye)", "QuickEyeAnalysis") + rep.time_start = "0ps" + rep.time_stop = "50us" + rep.unit_interval = "1e-9" + rep.create() + assert rep.eye_mask([[0.5, 0], [0.62, 450], [1.2, 450], [1.42, 0], [1.2, -450], [0.62, -450], [0.5, 0]]) + assert rep.eye_mask( + [[0.5, 0], [0.62, 450], [1.2, 450], [1.42, 0], [1.2, -450], [0.62, -450], [0.5, 0]], + enable_limits=True, + upper_limit=800, + lower_limit=-800, + ) + assert os.path.exists(rep.export_mask_violation()) + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" + ) + def test_64_eye_meas(self, eye_test): + eye_test.analyze(eye_test.active_setup) + rep = eye_test.post.reports_by_category.eye_diagram("AEYEPROBE(OutputEye)", "QuickEyeAnalysis") + rep.time_start = "0ps" + rep.time_stop = "50us" + rep.unit_interval = "1e-9" + rep.create() + assert rep.add_all_eye_measurements() + assert rep.clear_all_eye_measurements() + assert rep.add_trace_characteristics("MinEyeHeight") + + def test_65_eye_from_json(self, eye_test): + local_path = os.path.dirname(os.path.realpath(__file__)) + assert eye_test.post.create_report_from_configuration( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + "report_json", + "EyeDiagram_Report_simple.json", + ), + solution_name="QuickEyeAnalysis", + ) + + def test_66_spectral_from_json(self, circuit_test): + local_path = os.path.dirname(os.path.realpath(__file__)) + circuit_test.analyze_setup("Transient") + assert circuit_test.post.create_report_from_configuration( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + "report_json", + "Spectral_Report_Simple.json", + ), + solution_name="Transient", + ) + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" + ) + def test_68_eye_from_json(self, eye_test): + local_path = os.path.dirname(os.path.realpath(__file__)) + assert eye_test.post.create_report_from_configuration( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + "report_json", + "EyeDiagram_Report.toml", + ), + solution_name="QuickEyeAnalysis", + ) + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" + ) + def test_69_spectral_from_json(self, circuit_test): + local_path = os.path.dirname(os.path.realpath(__file__)) + circuit_test.analyze_setup("Transient") + assert circuit_test.post.create_report_from_configuration( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + "report_json", + "Spectral_Report.json", + ), + solution_name="Transient", + ) + + def test_70_far_field_data(self): + local_path = os.path.dirname(os.path.realpath(__file__)) + eep_file1 = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "eep", + "eep.txt", + ) + eep_file2 = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "eep", + "eep.txt", + ) + frequencies = [0.9e9, "0.9GHz"] + eep_files = [eep_file1, eep_file2] + + ffdata = FfdSolutionData(frequencies=frequencies[1], eep_files=eep_file1) + assert len(ffdata.frequencies) == 1 + + ffdata = FfdSolutionData(frequencies=frequencies, eep_files=eep_files) + assert len(ffdata.frequencies) == 2 + farfield = ffdata.combine_farfield() + assert "rETheta" in farfield + + ffdata.taper = "cosine" + assert ffdata.combine_farfield() + ffdata.taper = "taper" + assert not ffdata.taper == "taper" + + ffdata.origin = [0, 2] + assert ffdata.origin != [0, 2] + ffdata.origin = [0, 0, 1] + assert ffdata.origin == [0, 0, 1] + + img1 = os.path.join(self.local_scratch.path, "ff_2d1.jpg") + ffdata.plot_2d_cut(primary_sweep="Theta", secondary_sweep_value="all", image_path=img1) + assert os.path.exists(img1) + img2 = os.path.join(self.local_scratch.path, "ff_2d2.jpg") + ffdata.plot_2d_cut(secondary_sweep_value=[0, 1], image_path=img2) + assert os.path.exists(img2) + img3 = os.path.join(self.local_scratch.path, "ff_2d2.jpg") + ffdata.plot_2d_cut(image_path=img3) + assert os.path.exists(img3) + curve_2d = ffdata.plot_2d_cut(show=False) + assert len(curve_2d[0]) == 3 + data = ffdata.polar_plot_3d(show=False) + assert len(data) == 3 + + img4 = os.path.join(self.local_scratch.path, "ff_3d1.jpg") + ffdata.polar_plot_3d_pyvista( + quantity="RealizedGain", + image_path=img4, + show=False, + background=[255, 0, 0], + show_geometry=False, + convert_to_db=True, + ) + assert os.path.exists(img4) + data_pyvista = ffdata.polar_plot_3d_pyvista( + quantity="RealizedGain", show=False, background=[255, 0, 0], show_geometry=False, convert_to_db=True + ) + assert data_pyvista + + @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="FarFieldSolution not supported by IronPython") + def test_71_antenna_plot(self, field_test): + ffdata = field_test.get_antenna_ffd_solution_data(frequencies=30e9, sphere="3D") + ffdata.phase_offset = [0, 90] + assert ffdata.phase_offset == [0, 90] + ffdata.phase_offset = [0] + assert ffdata.phase_offset != [0.0] + assert ffdata.plot_farfield_contour( + quantity="RealizedGain", + title="Contour at {}Hz".format(ffdata.frequency), + image_path=os.path.join(self.local_scratch.path, "contour.jpg"), + convert_to_db=True, + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "contour.jpg")) + + ffdata.plot_2d_cut( + quantity="RealizedGain", + primary_sweep="theta", + secondary_sweep_value=[-180, -75, 75], + title="Azimuth at {}Hz".format(ffdata.frequency), + image_path=os.path.join(self.local_scratch.path, "2d1.jpg"), + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "2d1.jpg")) + ffdata.plot_2d_cut( + quantity="RealizedGain", + primary_sweep="phi", + secondary_sweep_value=30, + title="Azimuth at {}Hz".format(ffdata.frequency), + image_path=os.path.join(self.local_scratch.path, "2d2.jpg"), + ) + + assert os.path.exists(os.path.join(self.local_scratch.path, "2d2.jpg")) + + ffdata.polar_plot_3d( + quantity="RealizedGain", image_path=os.path.join(self.local_scratch.path, "3d1.jpg"), convert_to_db=True + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "3d1.jpg")) + + ffdata.polar_plot_3d_pyvista( + quantity="RealizedGain", + image_path=os.path.join(self.local_scratch.path, "3d2.jpg"), + show=False, + convert_to_db=True, + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "3d2.jpg")) + + try: + p = ffdata.polar_plot_3d_pyvista(quantity="RealizedGain", show=False, convert_to_db=True) + assert isinstance(p, object) + except Exception: + assert True + + @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="FarFieldSolution not supported by IronPython") + def test_72_antenna_plot(self, array_test): + ffdata = array_test.get_antenna_ffd_solution_data(frequencies=3.5e9, sphere="3D") + ffdata.frequency = 3.5e9 + assert ffdata.plot_farfield_contour( + quantity="RealizedGain", + title="Contour at {}Hz".format(ffdata.frequency), + image_path=os.path.join(self.local_scratch.path, "contour.jpg"), + convert_to_db=True, + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "contour.jpg")) + + ffdata.plot_2d_cut( + quantity="RealizedGain", + primary_sweep="theta", + secondary_sweep_value=[-180, -75, 75], + title="Azimuth at {}Hz".format(ffdata.frequency), + image_path=os.path.join(self.local_scratch.path, "2d1.jpg"), + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "2d1.jpg")) + ffdata.plot_2d_cut( + quantity="RealizedGain", + primary_sweep="phi", + secondary_sweep_value=30, + title="Azimuth at {}Hz".format(ffdata.frequency), + image_path=os.path.join(self.local_scratch.path, "2d2.jpg"), + ) + + assert os.path.exists(os.path.join(self.local_scratch.path, "2d2.jpg")) + + ffdata.polar_plot_3d( + quantity="RealizedGain", image_path=os.path.join(self.local_scratch.path, "3d1.jpg"), convert_to_db=True + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "3d1.jpg")) + + ffdata.polar_plot_3d_pyvista( + quantity="RealizedGain", + image_path=os.path.join(self.local_scratch.path, "3d2.jpg"), + show=False, + convert_to_db=True, + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "3d2.jpg")) + ffdata1 = array_test.get_antenna_ffd_solution_data(frequencies=3.5e9, sphere="3D", overwrite=False) + assert ffdata1.plot_farfield_contour( + quantity="RealizedGain", + title="Contour at {}Hz".format(ffdata1.frequency), + image_path=os.path.join(self.local_scratch.path, "contour1.jpg"), + convert_to_db=True, + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "contour1.jpg")) + + def test_73_ami_solution_data(self, ami_test): + ami_test.solution_type = "NexximAMI" + assert ami_test.post.get_solution_data( + expressions="WaveAfterProbe", + domain="Time", + variations=ami_test.available_variations.nominal, + ) + + assert ami_test.post.get_solution_data( + expressions="WaveAfterSource", + domain="Time", + variations=ami_test.available_variations.nominal, + ) + + assert ami_test.post.get_solution_data( + expressions="InitialWave", + domain="Time", + variations=ami_test.available_variations.nominal, + ) + + assert ami_test.post.get_solution_data( + expressions="WaveAfterChannel", + domain="Time", + variations=ami_test.available_variations.nominal, + ) + + assert ami_test.post.get_solution_data( + expressions="ClockTics", + domain="Clock Times", + variations=ami_test.available_variations.nominal, + ) + probe_name = "b_input_43" + source_name = "b_output4_42" + plot_type = "WaveAfterProbe" + setup_name = "AMIAnalysis" + + ignore_bits = 1000 + unit_interval = 0.1e-9 + assert not ami_test.post.sample_ami_waveform( + setup_name, + probe_name, + source_name, + ami_test.available_variations.nominal, + unit_interval, + ignore_bits, + plot_type, + ) + ignore_bits = 5 + unit_interval = 0.1e-9 + plot_type = "InitialWave" + data1 = ami_test.post.sample_ami_waveform( + setup_name, + probe_name, + source_name, + ami_test.available_variations.nominal, + unit_interval, + ignore_bits, + plot_type, + ) + assert len(data1[0]) == 45 + + settings.enable_pandas_output = False + ignore_bits = 5 + unit_interval = 0.1e-9 + clock_tics = [1e-9, 2e-9, 3e-9] + data2 = ami_test.post.sample_ami_waveform( + setup_name, + probe_name, + source_name, + ami_test.available_variations.nominal, + unit_interval, + ignore_bits, + plot_type=None, + clock_tics=clock_tics, + ) + assert len(data2) == 4 + assert len(data2[0]) == 3 + + def test_75_plot_field_line_traces(self, m2dtest): + m2dtest.modeler.model_units = "mm" + rect = m2dtest.modeler.create_rectangle( + origin=["1mm", "5mm", "0mm"], sizes=["-1mm", "-10mm", 0], name="Ground", material="copper" + ) + rect.solve_inside = False + circle = m2dtest.modeler.create_circle( + position=["-10mm", "0", "0"], + radius="1mm", + num_sides="0", + is_covered=True, + name="Electrode", + material="copper", + ) + circle.solve_inside = False + m2dtest.modeler.create_region([20, 100, 20, 100]) + assert not m2dtest.post.create_fieldplot_line_traces("Ground", "Region", "Ground", plot_name="LineTracesTest") + m2dtest.solution_type = "Electrostatic" + assert not m2dtest.post.create_fieldplot_line_traces("Invalid", "Region", "Ground", plot_name="LineTracesTest1") + assert not m2dtest.post.create_fieldplot_line_traces("Ground", "Invalid", "Ground", plot_name="LineTracesTest2") + assert not m2dtest.post.create_fieldplot_line_traces("Ground", "Region", "Invalid", plot_name="LineTracesTest3") + m2dtest.assign_voltage(rect.name, amplitude=0, name="Ground") + m2dtest.assign_voltage(circle.name, amplitude=50e6, name="50kV") + setup_name = "test" + m2dtest.create_setup(name=setup_name) + m2dtest.analyze_setup(setup_name) + plot = m2dtest.post.create_fieldplot_line_traces(["Ground", "Electrode"], "Region", plot_name="LineTracesTest4") + assert plot + assert m2dtest.post.create_fieldplot_line_traces( + ["Ground", "Electrode"], "Region", "Ground", plot_name="LineTracesTest5" + ) + assert m2dtest.post.create_fieldplot_line_traces(["Ground", "Electrode"], plot_name="LineTracesTest6") + assert not m2dtest.post.create_fieldplot_line_traces( + ["Ground", "Electrode"], "Region", ["Invalid"], plot_name="LineTracesTest7" + ) + assert not m2dtest.post.create_fieldplot_line_traces( + ["Ground", "Electrode"], ["Invalid"], plot_name="LineTracesTest8" + ) + plot.TraceStepLength = "0.002mm" + plot.SeedingPointsNumber = 20 + plot.LineStyle = "Cylinder" + plot.LineWidth = 3 + assert plot.update() + el_id = [obj.id for obj in m2dtest.modeler.object_list if obj.name == "Electrode"] + plot.seeding_faces.append(el_id[0]) + assert plot.update() + plot.volumes.append(el_id[0]) + plot.update() + plot.surfaces.append(el_id[0]) + plot.update() + plot.seeding_faces.append(8) + assert not plot.update() + plot.volumes.append(8) + assert not plot.update() + plot.surfaces.append(8) + assert not plot.update() + + @pytest.mark.skipif(config["desktopVersion"] < "2024.1", reason="EMI receiver available from 2024R1.") + def test_76_emi_receiver(self, emi_receiver_test): + emi_receiver_test.analyze() + new_report = emi_receiver_test.post.reports_by_category.emi_receiver() + new_report.band = "2" + new_report.emission = "RE" + new_report.time_start = "1ns" + new_report.time_stop = "2us" + new_report.net = "net_invented" + assert new_report.net != "net_invented" + assert new_report.create() + new_report2 = emi_receiver_test.post.reports_by_category.emi_receiver( + ["dBu(Average[net_6])", "dBu(Peak[net_6])", "dBu(QuasiPeak[net_6])", "dBu(RMS[net_6])"], "EMItransient" + ) + assert new_report2.net == "net_6" + new_report2.time_stop = "2.5us" + assert new_report2.create() + + def test_98_get_variations(self, field_test): + vars = field_test.available_variations.get_variation_strings() + assert vars + variations = field_test.available_variations.variations() + assert isinstance(variations, list) + assert isinstance(variations[0], list) + vars_dict = field_test.available_variations.variations(output_as_dict=True) + assert isinstance(vars_dict, list) + assert isinstance(vars_dict[0], dict) + + def test_z99_delete_variations(self, q3dtest): + assert q3dtest.cleanup_solution() + + def test_z99_delete_variations_B(self, field_test): + vars = field_test.available_variations.get_variation_strings() + assert field_test.cleanup_solution(vars, entire_solution=False) + assert field_test.cleanup_solution(vars, entire_solution=True) + + def test_76_ipk_get_scalar_field_value(self, icepak_post): + assert icepak_post.post.get_scalar_field_value( + "Heat_Flow_Rate", + scalar_function="Integrate", + solution=None, + variations={"power_block": "0.25W", "power_source": "0.075W"}, + is_vector=False, + intrinsics=None, + phase=None, + object_name="cube2", + object_type="surface", + adjacent_side=False, + ) + assert icepak_post.post.get_scalar_field_value( + "Heat_Flow_Rate", + scalar_function="Integrate", + solution=None, + variations={"power_block": "0.6W", "power_source": "0.15W"}, + is_vector=False, + intrinsics=None, + phase=None, + object_name="cube2", + object_type="surface", + adjacent_side=False, + ) + assert icepak_post.post.get_scalar_field_value( + "Heat_Flow_Rate", + scalar_function="Integrate", + solution=None, + variations={"power_block": "0.6W", "power_source": "0.15W"}, + is_vector=False, + intrinsics=None, + phase=None, + object_name="cube2", + object_type="surface", + adjacent_side=True, + ) + assert icepak_post.post.get_scalar_field_value( + "Temperature", + scalar_function="Maximum", + solution=None, + variations={"power_block": "0.6W", "power_source": "0.15W"}, + is_vector=False, + intrinsics=None, + phase=None, + object_name="cube1", + object_type="volume", + adjacent_side=False, + ) + assert icepak_post.post.get_scalar_field_value( + "Temperature", + scalar_function="Maximum", + solution=None, + variations={"power_block": "0.6W", "power_source": "0.15W"}, + is_vector=False, + intrinsics=None, + phase=None, + object_name="cube2", + object_type="surface", + adjacent_side=False, + ) + assert icepak_post.post.get_scalar_field_value( + "Temperature", + scalar_function="Value", + solution=None, + variations=None, + is_vector=False, + intrinsics=None, + phase=None, + object_name="Point1", + object_type="point", + adjacent_side=False, + ) From a6ce50dff7d91caed24583ee27e81d49ceb008e1 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Wed, 8 May 2024 17:13:14 +0200 Subject: [PATCH 14/29] Fix UT --- _unittest/test_12_PostProcessing.py | 70 ++++------------------------- 1 file changed, 9 insertions(+), 61 deletions(-) diff --git a/_unittest/test_12_PostProcessing.py b/_unittest/test_12_PostProcessing.py index 1712bd9d95f..107fd611da9 100644 --- a/_unittest/test_12_PostProcessing.py +++ b/_unittest/test_12_PostProcessing.py @@ -477,37 +477,18 @@ def test_58_test_no_report_B(self, q2dtest): def test_59_test_parse_vector(self): local_path = os.path.dirname(os.path.realpath(__file__)) - out = _parse_aedtplt( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "test_vector.aedtplt", - ) - ) + out = _parse_aedtplt(os.path.join(local_path, "example_models", test_subfolder, "test_vector.aedtplt")) assert isinstance(out[0], list) assert isinstance(out[1], list) assert isinstance(out[2], list) assert isinstance(out[3], bool) assert _parse_aedtplt( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "test_vector_no_solutions.aedtplt", - ) + os.path.join(local_path, "example_models", test_subfolder, "test_vector_no_solutions.aedtplt") ) def test_60_test_parse_vector(self): local_path = os.path.dirname(os.path.realpath(__file__)) - out = _parse_streamline( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "test_streamline.fldplt", - ) - ) + out = _parse_streamline(os.path.join(local_path, "example_models", test_subfolder, "test_streamline.fldplt")) assert isinstance(out, list) def test_61_export_mesh(self, q3dtest): @@ -558,12 +539,7 @@ def test_64_eye_meas(self, eye_test): def test_65_eye_from_json(self, eye_test): local_path = os.path.dirname(os.path.realpath(__file__)) assert eye_test.post.create_report_from_configuration( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - "report_json", - "EyeDiagram_Report_simple.json", - ), + os.path.join(local_path, "example_models", "report_json", "Spectral_Report_Simple.json"), solution_name="QuickEyeAnalysis", ) @@ -571,12 +547,7 @@ def test_66_spectral_from_json(self, circuit_test): local_path = os.path.dirname(os.path.realpath(__file__)) circuit_test.analyze_setup("Transient") assert circuit_test.post.create_report_from_configuration( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - "report_json", - "Spectral_Report_Simple.json", - ), + os.path.join(local_path, "example_models", "report_json", "Spectral_Report_Simple.json"), solution_name="Transient", ) @@ -586,12 +557,7 @@ def test_66_spectral_from_json(self, circuit_test): def test_68_eye_from_json(self, eye_test): local_path = os.path.dirname(os.path.realpath(__file__)) assert eye_test.post.create_report_from_configuration( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - "report_json", - "EyeDiagram_Report.toml", - ), + os.path.join(local_path, "example_models", "report_json", "EyeDiagram_Report.toml"), solution_name="QuickEyeAnalysis", ) @@ -602,31 +568,13 @@ def test_69_spectral_from_json(self, circuit_test): local_path = os.path.dirname(os.path.realpath(__file__)) circuit_test.analyze_setup("Transient") assert circuit_test.post.create_report_from_configuration( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - "report_json", - "Spectral_Report.json", - ), - solution_name="Transient", + os.path.join(local_path, "example_models", "report_json", "Spectral_Report.json"), solution_name="Transient" ) def test_70_far_field_data(self): local_path = os.path.dirname(os.path.realpath(__file__)) - eep_file1 = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "eep", - "eep.txt", - ) - eep_file2 = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "eep", - "eep.txt", - ) + eep_file1 = os.path.join(local_path, "example_models", test_subfolder, "eep", "eep.txt") + eep_file2 = os.path.join(local_path, "example_models", test_subfolder, "eep", "eep.txt") frequencies = [0.9e9, "0.9GHz"] eep_files = [eep_file1, eep_file2] From 32be8b3144854bf140f0697f862a993146acc731 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Wed, 8 May 2024 17:13:50 +0200 Subject: [PATCH 15/29] Fix UT --- _unittest/test_12_PostProcessing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_unittest/test_12_PostProcessing.py b/_unittest/test_12_PostProcessing.py index 107fd611da9..5f6e828181b 100644 --- a/_unittest/test_12_PostProcessing.py +++ b/_unittest/test_12_PostProcessing.py @@ -539,7 +539,7 @@ def test_64_eye_meas(self, eye_test): def test_65_eye_from_json(self, eye_test): local_path = os.path.dirname(os.path.realpath(__file__)) assert eye_test.post.create_report_from_configuration( - os.path.join(local_path, "example_models", "report_json", "Spectral_Report_Simple.json"), + os.path.join(local_path, "example_models", "report_json", "EyeDiagram_Report_simple.json"), solution_name="QuickEyeAnalysis", ) From e56e142f012c8799a19aa5464dd4ce3d534e7ce8 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Thu, 9 May 2024 09:52:21 +0200 Subject: [PATCH 16/29] Fix UT --- _unittest/test_12_PostProcessing.py | 974 --------------- _unittest/test_20_HFSS.py | 1694 +++++++++++++++++++++++++++ 2 files changed, 1694 insertions(+), 974 deletions(-) delete mode 100644 _unittest/test_12_PostProcessing.py create mode 100644 _unittest/test_20_HFSS.py diff --git a/_unittest/test_12_PostProcessing.py b/_unittest/test_12_PostProcessing.py deleted file mode 100644 index 5f6e828181b..00000000000 --- a/_unittest/test_12_PostProcessing.py +++ /dev/null @@ -1,974 +0,0 @@ -import os -import sys - -from _unittest.conftest import config -import pytest - -from pyaedt import Circuit -from pyaedt import Icepak -from pyaedt import Maxwell2d -from pyaedt import Q2d -from pyaedt import Q3d -from pyaedt.generic.general_methods import is_linux -from pyaedt.generic.pdf import AnsysReport -from pyaedt.generic.plot import _parse_aedtplt -from pyaedt.generic.plot import _parse_streamline -from pyaedt.generic.settings import settings -from pyaedt.modules.solutions import FfdSolutionData - -if config["desktopVersion"] > "2022.2": - test_field_name = "Potter_Horn_231" - test_project_name = "coax_setup_solved_231" - array = "array_simple_231" - sbr_file = "poc_scat_small_231" - q3d_file = "via_gsg_231" - m2d_file = "m2d_field_lines_test_231" - -else: - test_field_name = "Potter_Horn" - test_project_name = "coax_setup_solved" - array = "array_simple" - sbr_file = "poc_scat_small" - q3d_file = "via_gsg" - m2d_file = "m2d_field_lines_test" - -test_circuit_name = "Switching_Speed_FET_And_Diode" -test_emi_name = "EMI_RCV_241" -eye_diagram = "SimpleChannel" -ami = "ami" -ipk_post_proj = "for_icepak_post" -test_subfolder = "T12" -settings.enable_pandas_output = True - - -@pytest.fixture(scope="class") -def field_test(add_app): - app = add_app(project_name=test_field_name, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def circuit_test(add_app): - app = add_app(project_name=test_circuit_name, design_name="Diode", application=Circuit, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def emi_receiver_test(add_app): - app = add_app(project_name=test_emi_name, design_name="CE_band", application=Circuit, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def diff_test(add_app, circuit_test): - app = add_app(project_name=circuit_test.project_name, design_name="diff", application=Circuit, just_open=True) - return app - - -@pytest.fixture(scope="class") -def sbr_test(add_app): - app = add_app(project_name=sbr_file, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def q3dtest(add_app): - app = add_app(project_name=q3d_file, application=Q3d, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def q2dtest(add_app, q3dtest): - app = add_app(project_name=q3dtest.project_name, application=Q2d, just_open=True) - return app - - -@pytest.fixture(scope="class") -def eye_test(add_app, q3dtest): - app = add_app(project_name=eye_diagram, application=Circuit, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def icepak_post(add_app): - app = add_app(project_name=ipk_post_proj, application=Icepak, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def ami_test(add_app, q3dtest): - app = add_app(project_name=ami, application=Circuit, subfolder=test_subfolder) - return app - - -@pytest.fixture(scope="class") -def array_test(add_app, q3dtest): - app = add_app(project_name=array, subfolder=test_subfolder, solution_type="Modal") - return app - - -@pytest.fixture(scope="class") -def m2dtest(add_app, q3dtest): - app = add_app(project_name=m2d_file, application=Maxwell2d, subfolder=test_subfolder) - return app - - -class TestClass: - @pytest.fixture(autouse=True) - def init(self, local_scratch): - self.local_scratch = local_scratch - - def test_09_manipulate_report(self, field_test): - variations = field_test.available_variations.nominal_w_values_dict - variations["Theta"] = ["All"] - variations["Phi"] = ["All"] - variations["Freq"] = ["30GHz"] - field_test.set_source_context(["1"]) - context = {"Context": "3D", "SourceContext": "1:1"} - assert field_test.post.create_report( - "db(GainTotal)", - field_test.nominal_adaptive, - variations=variations, - primary_sweep_variable="Phi", - secondary_sweep_variable="Theta", - report_category="Far Fields", - plot_type="3D Polar Plot", - context=context, - ) - assert field_test.post.create_report( - "db(GainTotal)", - field_test.nominal_adaptive, - variations=variations, - primary_sweep_variable="Phi", - secondary_sweep_variable="Theta", - report_category="Far Fields", - plot_type="3D Polar Plot", - context="3D", - ) - report = AnsysReport() - report.create() - assert report.add_project_info(field_test) - - def test_09_manipulate_report_B(self, field_test): - variations = field_test.available_variations.nominal_w_values_dict - variations["Theta"] = ["All"] - variations["Phi"] = ["All"] - variations["Freq"] = ["30GHz"] - new_report = field_test.post.reports_by_category.far_field("db(RealizedGainTotal)", field_test.nominal_adaptive) - new_report.variations = variations - new_report.report_type = "3D Polar Plot" - new_report.far_field_sphere = "3D" - assert new_report.create() - - new_report2 = field_test.post.reports_by_category.far_field( - "db(RealizedGainTotal)", field_test.nominal_adaptive, "3D", "1:1" - ) - new_report2.variations = variations - new_report2.report_type = "3D Polar Plot" - assert new_report2.create() - - new_report3 = field_test.post.reports_by_category.antenna_parameters( - "db(PeakRealizedGain)", field_test.nominal_adaptive, "3D" - ) - new_report3.report_type = "Data Table" - assert new_report3.create() - new_report4 = field_test.post.reports_by_category.antenna_parameters( - "db(PeakRealizedGain)", infinite_sphere="3D" - ) - new_report4.report_type = "Data Table" - assert new_report4.create() - - def test_09_manipulate_report_C(self, field_test): - variations = field_test.available_variations.nominal_w_values_dict - variations["Theta"] = ["All"] - variations["Phi"] = ["All"] - variations["Freq"] = ["30GHz"] - field_test.analyze(field_test.active_setup) - data = field_test.post.get_solution_data( - "GainTotal", - field_test.nominal_adaptive, - variations=variations, - primary_sweep_variable="Theta", - report_category="Far Fields", - context="3D", - ) - assert data.plot(is_polar=True) - assert data.plot_3d() - assert field_test.post.create_3d_plot(data) - - def test_09_manipulate_report_D(self, field_test): - variations = field_test.available_variations.nominal_w_values_dict - variations["Theta"] = ["All"] - variations["Phi"] = ["All"] - variations["Freq"] = ["30GHz"] - context = {"Context": "3D", "SourceContext": "1:1"} - data = field_test.post.get_solution_data( - "GainTotal", - field_test.nominal_adaptive, - variations=variations, - primary_sweep_variable="Theta", - report_category="Far Fields", - context=context, - ) - assert data.plot(is_polar=True) - assert data.plot_3d() - assert field_test.post.create_3d_plot(data) - assert data.primary_sweep == "Theta" - assert len(data.data_magnitude("GainTotal")) > 0 - assert not data.data_magnitude("GainTotal2") - assert field_test.post.create_report( - "S(1,1)", field_test.nominal_sweep, variations=variations, plot_type="Smith Chart" - ) - - def test_09_manipulate_report_E(self, field_test): - field_test.modeler.create_polyline([[0, 0, 0], [0, 5, 30]], name="Poly1", non_model=True) - variations2 = field_test.available_variations.nominal_w_values_dict - - assert field_test.setups[0].create_report( - "Mag_E", primary_sweep_variable="Distance", report_category="Fields", context="Poly1" - ) - new_report = field_test.post.reports_by_category.fields("Mag_H", field_test.nominal_adaptive) - new_report.variations = variations2 - new_report.polyline = "Poly1" - assert new_report.create() - new_report = field_test.post.reports_by_category.fields("Mag_H") - new_report.variations = variations2 - new_report.polyline = "Poly1" - assert new_report.create() - new_report = field_test.post.reports_by_category.modal_solution("S(1,1)") - new_report.report_type = "Smith Chart" - assert new_report.create() - data = field_test.setups[0].get_solution_data( - "Mag_E", variations=variations2, primary_sweep_variable="Theta", report_category="Fields", context="Poly1" - ) - assert data.units_sweeps["Phase"] == "deg" - - assert field_test.post.get_far_field_data( - expressions="RealizedGainTotal", setup_sweep_name=field_test.nominal_adaptive, domain="3D" - ) - data_farfield2 = field_test.post.get_far_field_data( - expressions="RealizedGainTotal", - setup_sweep_name=field_test.nominal_adaptive, - domain={"Context": "3D", "SourceContext": "1:1"}, - ) - assert data_farfield2.plot(formula="db20", is_polar=True) - - assert field_test.post.reports_by_category.terminal_solution() - - assert not field_test.post.get_solution_data_per_variation( - solution_type="Far Fields", expressions="RealizedGainTotal" - ) - - def test_09b_export_report_A(self, circuit_test): - files = circuit_test.export_results() - assert len(files) > 0 - report = AnsysReport() - report.create() - assert report.add_project_info(circuit_test) - - def test_09b_export_report_B(self, q2dtest): - q2dtest.analyze() - files = q2dtest.export_results() - assert len(files) > 0 - - def test_09b_export_report_C(self, q3dtest): - q3dtest.analyze_setup("Setup1") - files = q3dtest.export_results() - assert len(files) > 0 - - @pytest.mark.skipif(is_linux, reason="Crashing on Linux") - def test_17_circuit(self, circuit_test): - assert not circuit_test.setups[0].is_solved - - circuit_test.analyze_setup("LNA") - circuit_test.analyze_setup("Transient") - assert circuit_test.setups[0].is_solved - assert circuit_test.setups[0].create_report(["dB(S(Port1, Port1))", "dB(S(Port1, Port2))"]) - new_report = circuit_test.post.reports_by_category.standard( - ["dB(S(Port1, Port1))", "dB(S(Port1, Port2))"], "LNA" - ) - assert new_report.create() - data1 = circuit_test.post.get_solution_data(["dB(S(Port1,Port1))", "dB(S(Port1,Port2))"], "LNA") - assert data1.primary_sweep == "Freq" - assert circuit_test.post.create_report(["V(net_11)"], "Transient", "Time") - data11 = circuit_test.post.get_solution_data(setup_sweep_name="LNA", math_formula="dB") - assert data11.primary_sweep == "Freq" - assert "dB(S(Port2,Port1))" in data11.expressions - assert circuit_test.post.create_report(["V(net_11)"], "Transient", "Time") - new_report = circuit_test.post.reports_by_category.standard(["V(net_11)"], "Transient") - new_report.domain = "Time" - assert new_report.create() - data2 = circuit_test.post.get_solution_data(["V(net_11)"], "Transient", "Time") - assert data2.primary_sweep == "Time" - assert len(data2.data_magnitude()) > 0 - context = {"algorithm": "FFT", "max_frequency": "100MHz", "time_stop": "200ns", "test": ""} - data3 = circuit_test.post.get_solution_data(["V(net_11)"], "Transient", "Spectral", context=context) - assert data3.units_sweeps["Spectrum"] == circuit_test.odesktop.GetDefaultUnit("Frequency") - assert len(data3.data_real()) > 0 - new_report = circuit_test.post.reports_by_category.spectral(["dB(V(net_11))"], "Transient") - new_report.window = "Hanning" - new_report.max_freq = "1GHz" - new_report.time_start = "1ns" - new_report.time_stop = "190ns" - new_report.plot_continous_spectrum = True - assert new_report.create() - new_report = circuit_test.post.reports_by_category.spectral(["dB(V(net_11))"]) - assert new_report.create() - new_report = circuit_test.post.reports_by_category.spectral(["dB(V(net_11))", "dB(V(Port1))"], "Transient") - new_report.window = "Kaiser" - new_report.adjust_coherent_gain = False - new_report.kaiser_coeff = 2 - new_report.algorithm = "Fourier Transform" - new_report.max_freq = "1GHz" - new_report.time_start = "1ns" - new_report.time_stop = "190ns" - new_report.plot_continous_spectrum = False - assert new_report.create() - assert circuit_test.post.create_report(["dB(V(net_11))", "dB(V(Port1))"], domain="Spectrum") - new_report = circuit_test.post.reports_by_category.spectral(None, "Transient") - new_report.window = "Hanning" - new_report.max_freq = "1GHz" - new_report.time_start = "1ns" - new_report.time_stop = "190ns" - new_report.plot_continous_spectrum = True - assert new_report.create() - - @pytest.mark.skipif(is_linux, reason="Crashing on Linux") - def test_18_diff_plot(self, diff_test): - assert len(diff_test.post.available_display_types()) > 0 - assert len(diff_test.post.available_report_types) > 0 - assert len(diff_test.post.available_report_quantities()) > 0 - assert len(diff_test.post.available_report_solutions()) > 0 - diff_test.analyze_setup("LinearFrequency") - assert diff_test.setups[0].is_solved - variations = diff_test.available_variations.nominal_w_values_dict - variations["Freq"] = ["All"] - variations["l1"] = ["All"] - assert diff_test.post.create_report( - ["dB(S(Diff1, Diff1))"], - "LinearFrequency", - variations=variations, - primary_sweep_variable="l1", - context="Differential Pairs", - ) - new_report1 = diff_test.post.reports_by_category.standard() - assert new_report1.expressions - new_report = diff_test.post.reports_by_category.standard("dB(S(1,1))") - new_report.differential_pairs = True - assert new_report.create() - assert new_report.get_solution_data() - new_report2 = diff_test.post.reports_by_category.standard("TDRZ(1)") - new_report2.differential_pairs = True - new_report2.pulse_rise_time = 3e-12 - new_report2.time_windowing = 3 - new_report2.domain = "Time" - - assert new_report2.create() - - data1 = diff_test.post.get_solution_data( - ["S(Diff1, Diff1)"], - "LinearFrequency", - variations=variations, - primary_sweep_variable="Freq", - context="Differential Pairs", - ) - assert data1.primary_sweep == "Freq" - data1.plot(formula="db20", snapshot_path=os.path.join(self.local_scratch.path, "temp1.jpg")) - data1.primary_sweep = "l1" - assert data1.primary_sweep == "l1" - assert len(data1.data_magnitude()) == 5 - assert data1.plot("S(Diff1, Diff1)", snapshot_path=os.path.join(self.local_scratch.path, "temp2.jpg")) - assert data1.plot(formula="db20", snapshot_path=os.path.join(self.local_scratch.path, "temp3.jpg")) - assert data1.plot(formula="db10", snapshot_path=os.path.join(self.local_scratch.path, "temp4.jpg")) - assert data1.plot(formula="mag", snapshot_path=os.path.join(self.local_scratch.path, "temp5.jpg")) - assert data1.plot(formula="re", snapshot_path=os.path.join(self.local_scratch.path, "temp6.jpg")) - assert data1.plot(formula="im", snapshot_path=os.path.join(self.local_scratch.path, "temp7.jpg")) - assert data1.plot(formula="phasedeg", snapshot_path=os.path.join(self.local_scratch.path, "temp8.jpg")) - assert data1.plot(formula="phaserad", snapshot_path=os.path.join(self.local_scratch.path, "temp9.jpg")) - - assert diff_test.create_touchstone_report( - name="Diff_plot", curves=["dB(S(Diff1, Diff1))"], solution="LinearFrequency", differential_pairs=True - ) - - @pytest.mark.skipif(is_linux, reason="Failing on Linux") - def test_51_get_efields(self, field_test): - assert field_test.post.get_efields_data(ff_setup="3D") - - @pytest.mark.skipif( - is_linux or sys.version_info < (3, 8), reason="plot_scene method is not supported in ironpython" - ) - def test_55_time_plot(self, sbr_test): - sbr_test.analyze(sbr_test.active_setup, use_auto_settings=False) - assert sbr_test.setups[0].is_solved - solution_data = sbr_test.post.get_solution_data( - expressions=["NearEX", "NearEY", "NearEZ"], report_category="Near Fields", context="Near_Field" - ) - assert solution_data - assert len(solution_data.primary_sweep_values) > 0 - assert len(solution_data.primary_sweep_variations) > 0 - assert solution_data.set_active_variation(0) - assert not solution_data.set_active_variation(99) - t_matrix = solution_data.ifft("NearE", window=True) - assert t_matrix.any() - frames_list = solution_data.ifft_to_file( - coord_system_center=[-0.15, 0, 0], db_val=True, csv_path=os.path.join(sbr_test.working_directory, "csv") - ) - assert os.path.exists(frames_list) - sbr_test.post.plot_scene( - frames_list, os.path.join(sbr_test.working_directory, "animation.gif"), norm_index=5, dy_rng=35, show=False - ) - assert os.path.exists(os.path.join(sbr_test.working_directory, "animation.gif")) - sbr_test.post.plot_scene( - frames_list, - os.path.join(sbr_test.working_directory, "animation2.gif"), - norm_index=5, - dy_rng=35, - show=False, - convert_fields_in_db=True, - log_multiplier=20.0, - ) - assert os.path.exists(os.path.join(sbr_test.working_directory, "animation2.gif")) - - def test_56_test_export_q3d_results(self, q3dtest): - q3dtest.analyze(q3dtest.active_setup) - assert os.path.exists(q3dtest.export_convergence("Setup1")) - assert os.path.exists(q3dtest.export_profile("Setup1")) - new_report = q3dtest.post.reports_by_category.standard(q3dtest.get_traces_for_plot()) - assert new_report.create() - q3dtest.modeler.create_polyline([[0, -5, 0.425], [0.5, 5, 0.5]], name="Poly1", non_model=True) - new_report = q3dtest.post.reports_by_category.cg_fields("SmoothQ", polyline="Poly1") - assert new_report.create() - new_report = q3dtest.post.reports_by_category.rl_fields("Mag_SurfaceJac", polyline="Poly1") - assert new_report.create() - new_report = q3dtest.post.reports_by_category.dc_fields("Mag_VolumeJdc", polyline="Poly1") - assert new_report.create() - assert len(q3dtest.post.plots) == 6 - - def test_57_test_export_q2d_results(self, q2dtest): - q2dtest.analyze(q2dtest.active_setup) - assert os.path.exists(q2dtest.export_convergence("Setup1")) - assert os.path.exists(q2dtest.export_profile("Setup1")) - new_report = q2dtest.post.reports_by_category.standard(q2dtest.get_traces_for_plot()) - assert new_report.create() - q2dtest.modeler.create_polyline([[-1.9, -0.1, 0], [-1.2, -0.2, 0]], name="Poly1", non_model=True) - new_report = q2dtest.post.reports_by_category.cg_fields("Mag_E", polyline="Poly1") - assert new_report.create() - new_report = q2dtest.post.reports_by_category.rl_fields("Mag_H", polyline="Poly1") - assert new_report.create() - sol = new_report.get_solution_data() - sol.enable_pandas_output = True - data = sol.full_matrix_real_imag - data_mag = sol.full_matrix_mag_phase - sol.data_magnitude() - sol.enable_pandas_output = False - assert len(q2dtest.post.plots) == 3 - new_report = q2dtest.post.reports_by_category.standard() - assert new_report.get_solution_data() - - def test_58_test_no_report(self, q3dtest): - assert not q3dtest.post.reports_by_category.modal_solution() - assert not q3dtest.post.reports_by_category.terminal_solution() - - def test_58_test_no_report_B(self, q2dtest): - assert not q2dtest.post.reports_by_category.far_field() - assert not q2dtest.post.reports_by_category.near_field() - assert not q2dtest.post.reports_by_category.eigenmode() - - def test_59_test_parse_vector(self): - local_path = os.path.dirname(os.path.realpath(__file__)) - - out = _parse_aedtplt(os.path.join(local_path, "example_models", test_subfolder, "test_vector.aedtplt")) - assert isinstance(out[0], list) - assert isinstance(out[1], list) - assert isinstance(out[2], list) - assert isinstance(out[3], bool) - assert _parse_aedtplt( - os.path.join(local_path, "example_models", test_subfolder, "test_vector_no_solutions.aedtplt") - ) - - def test_60_test_parse_vector(self): - local_path = os.path.dirname(os.path.realpath(__file__)) - out = _parse_streamline(os.path.join(local_path, "example_models", test_subfolder, "test_streamline.fldplt")) - assert isinstance(out, list) - - def test_61_export_mesh(self, q3dtest): - assert os.path.exists(q3dtest.export_mesh_stats("Setup1")) - assert os.path.exists(q3dtest.export_mesh_stats("Setup1", setup_type="AC RL")) - - def test_62_eye_diagram(self, eye_test): - eye_test.analyze(eye_test.active_setup) - rep = eye_test.post.reports_by_category.eye_diagram("AEYEPROBE(OutputEye)", "QuickEyeAnalysis") - rep.time_start = "0ps" - rep.time_stop = "50us" - rep.unit_interval = "1e-9" - assert rep.create() - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" - ) - def test_63_mask(self, eye_test): - eye_test.analyze(eye_test.active_setup) - rep = eye_test.post.reports_by_category.eye_diagram("AEYEPROBE(OutputEye)", "QuickEyeAnalysis") - rep.time_start = "0ps" - rep.time_stop = "50us" - rep.unit_interval = "1e-9" - rep.create() - assert rep.eye_mask([[0.5, 0], [0.62, 450], [1.2, 450], [1.42, 0], [1.2, -450], [0.62, -450], [0.5, 0]]) - assert rep.eye_mask( - [[0.5, 0], [0.62, 450], [1.2, 450], [1.42, 0], [1.2, -450], [0.62, -450], [0.5, 0]], - enable_limits=True, - upper_limit=800, - lower_limit=-800, - ) - assert os.path.exists(rep.export_mask_violation()) - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" - ) - def test_64_eye_meas(self, eye_test): - eye_test.analyze(eye_test.active_setup) - rep = eye_test.post.reports_by_category.eye_diagram("AEYEPROBE(OutputEye)", "QuickEyeAnalysis") - rep.time_start = "0ps" - rep.time_stop = "50us" - rep.unit_interval = "1e-9" - rep.create() - assert rep.add_all_eye_measurements() - assert rep.clear_all_eye_measurements() - assert rep.add_trace_characteristics("MinEyeHeight") - - def test_65_eye_from_json(self, eye_test): - local_path = os.path.dirname(os.path.realpath(__file__)) - assert eye_test.post.create_report_from_configuration( - os.path.join(local_path, "example_models", "report_json", "EyeDiagram_Report_simple.json"), - solution_name="QuickEyeAnalysis", - ) - - def test_66_spectral_from_json(self, circuit_test): - local_path = os.path.dirname(os.path.realpath(__file__)) - circuit_test.analyze_setup("Transient") - assert circuit_test.post.create_report_from_configuration( - os.path.join(local_path, "example_models", "report_json", "Spectral_Report_Simple.json"), - solution_name="Transient", - ) - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" - ) - def test_68_eye_from_json(self, eye_test): - local_path = os.path.dirname(os.path.realpath(__file__)) - assert eye_test.post.create_report_from_configuration( - os.path.join(local_path, "example_models", "report_json", "EyeDiagram_Report.toml"), - solution_name="QuickEyeAnalysis", - ) - - @pytest.mark.skipif( - config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" - ) - def test_69_spectral_from_json(self, circuit_test): - local_path = os.path.dirname(os.path.realpath(__file__)) - circuit_test.analyze_setup("Transient") - assert circuit_test.post.create_report_from_configuration( - os.path.join(local_path, "example_models", "report_json", "Spectral_Report.json"), solution_name="Transient" - ) - - def test_70_far_field_data(self): - local_path = os.path.dirname(os.path.realpath(__file__)) - eep_file1 = os.path.join(local_path, "example_models", test_subfolder, "eep", "eep.txt") - eep_file2 = os.path.join(local_path, "example_models", test_subfolder, "eep", "eep.txt") - frequencies = [0.9e9, "0.9GHz"] - eep_files = [eep_file1, eep_file2] - - ffdata = FfdSolutionData(frequencies=frequencies[1], eep_files=eep_file1) - assert len(ffdata.frequencies) == 1 - - ffdata = FfdSolutionData(frequencies=frequencies, eep_files=eep_files) - assert len(ffdata.frequencies) == 2 - farfield = ffdata.combine_farfield() - assert "rETheta" in farfield - - ffdata.taper = "cosine" - assert ffdata.combine_farfield() - ffdata.taper = "taper" - assert not ffdata.taper == "taper" - - ffdata.origin = [0, 2] - assert ffdata.origin != [0, 2] - ffdata.origin = [0, 0, 1] - assert ffdata.origin == [0, 0, 1] - - img1 = os.path.join(self.local_scratch.path, "ff_2d1.jpg") - ffdata.plot_2d_cut(primary_sweep="Theta", secondary_sweep_value="all", image_path=img1) - assert os.path.exists(img1) - img2 = os.path.join(self.local_scratch.path, "ff_2d2.jpg") - ffdata.plot_2d_cut(secondary_sweep_value=[0, 1], image_path=img2) - assert os.path.exists(img2) - img3 = os.path.join(self.local_scratch.path, "ff_2d2.jpg") - ffdata.plot_2d_cut(image_path=img3) - assert os.path.exists(img3) - curve_2d = ffdata.plot_2d_cut(show=False) - assert len(curve_2d[0]) == 3 - data = ffdata.polar_plot_3d(show=False) - assert len(data) == 3 - - img4 = os.path.join(self.local_scratch.path, "ff_3d1.jpg") - ffdata.polar_plot_3d_pyvista( - quantity="RealizedGain", - image_path=img4, - show=False, - background=[255, 0, 0], - show_geometry=False, - convert_to_db=True, - ) - assert os.path.exists(img4) - data_pyvista = ffdata.polar_plot_3d_pyvista( - quantity="RealizedGain", show=False, background=[255, 0, 0], show_geometry=False, convert_to_db=True - ) - assert data_pyvista - - @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="FarFieldSolution not supported by IronPython") - def test_71_antenna_plot(self, field_test): - ffdata = field_test.get_antenna_ffd_solution_data(frequencies=30e9, sphere="3D") - ffdata.phase_offset = [0, 90] - assert ffdata.phase_offset == [0, 90] - ffdata.phase_offset = [0] - assert ffdata.phase_offset != [0.0] - assert ffdata.plot_farfield_contour( - quantity="RealizedGain", - title="Contour at {}Hz".format(ffdata.frequency), - image_path=os.path.join(self.local_scratch.path, "contour.jpg"), - convert_to_db=True, - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "contour.jpg")) - - ffdata.plot_2d_cut( - quantity="RealizedGain", - primary_sweep="theta", - secondary_sweep_value=[-180, -75, 75], - title="Azimuth at {}Hz".format(ffdata.frequency), - image_path=os.path.join(self.local_scratch.path, "2d1.jpg"), - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "2d1.jpg")) - ffdata.plot_2d_cut( - quantity="RealizedGain", - primary_sweep="phi", - secondary_sweep_value=30, - title="Azimuth at {}Hz".format(ffdata.frequency), - image_path=os.path.join(self.local_scratch.path, "2d2.jpg"), - ) - - assert os.path.exists(os.path.join(self.local_scratch.path, "2d2.jpg")) - - ffdata.polar_plot_3d( - quantity="RealizedGain", image_path=os.path.join(self.local_scratch.path, "3d1.jpg"), convert_to_db=True - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "3d1.jpg")) - - ffdata.polar_plot_3d_pyvista( - quantity="RealizedGain", - image_path=os.path.join(self.local_scratch.path, "3d2.jpg"), - show=False, - convert_to_db=True, - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "3d2.jpg")) - - try: - p = ffdata.polar_plot_3d_pyvista(quantity="RealizedGain", show=False, convert_to_db=True) - assert isinstance(p, object) - except Exception: - assert True - - @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="FarFieldSolution not supported by IronPython") - def test_72_antenna_plot(self, array_test): - ffdata = array_test.get_antenna_ffd_solution_data(frequencies=3.5e9, sphere="3D") - ffdata.frequency = 3.5e9 - assert ffdata.plot_farfield_contour( - quantity="RealizedGain", - title="Contour at {}Hz".format(ffdata.frequency), - image_path=os.path.join(self.local_scratch.path, "contour.jpg"), - convert_to_db=True, - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "contour.jpg")) - - ffdata.plot_2d_cut( - quantity="RealizedGain", - primary_sweep="theta", - secondary_sweep_value=[-180, -75, 75], - title="Azimuth at {}Hz".format(ffdata.frequency), - image_path=os.path.join(self.local_scratch.path, "2d1.jpg"), - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "2d1.jpg")) - ffdata.plot_2d_cut( - quantity="RealizedGain", - primary_sweep="phi", - secondary_sweep_value=30, - title="Azimuth at {}Hz".format(ffdata.frequency), - image_path=os.path.join(self.local_scratch.path, "2d2.jpg"), - ) - - assert os.path.exists(os.path.join(self.local_scratch.path, "2d2.jpg")) - - ffdata.polar_plot_3d( - quantity="RealizedGain", image_path=os.path.join(self.local_scratch.path, "3d1.jpg"), convert_to_db=True - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "3d1.jpg")) - - ffdata.polar_plot_3d_pyvista( - quantity="RealizedGain", - image_path=os.path.join(self.local_scratch.path, "3d2.jpg"), - show=False, - convert_to_db=True, - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "3d2.jpg")) - ffdata1 = array_test.get_antenna_ffd_solution_data(frequencies=3.5e9, sphere="3D", overwrite=False) - assert ffdata1.plot_farfield_contour( - quantity="RealizedGain", - title="Contour at {}Hz".format(ffdata1.frequency), - image_path=os.path.join(self.local_scratch.path, "contour1.jpg"), - convert_to_db=True, - ) - assert os.path.exists(os.path.join(self.local_scratch.path, "contour1.jpg")) - - def test_73_ami_solution_data(self, ami_test): - ami_test.solution_type = "NexximAMI" - assert ami_test.post.get_solution_data( - expressions="WaveAfterProbe", - domain="Time", - variations=ami_test.available_variations.nominal, - ) - - assert ami_test.post.get_solution_data( - expressions="WaveAfterSource", - domain="Time", - variations=ami_test.available_variations.nominal, - ) - - assert ami_test.post.get_solution_data( - expressions="InitialWave", - domain="Time", - variations=ami_test.available_variations.nominal, - ) - - assert ami_test.post.get_solution_data( - expressions="WaveAfterChannel", - domain="Time", - variations=ami_test.available_variations.nominal, - ) - - assert ami_test.post.get_solution_data( - expressions="ClockTics", - domain="Clock Times", - variations=ami_test.available_variations.nominal, - ) - probe_name = "b_input_43" - source_name = "b_output4_42" - plot_type = "WaveAfterProbe" - setup_name = "AMIAnalysis" - - ignore_bits = 1000 - unit_interval = 0.1e-9 - assert not ami_test.post.sample_ami_waveform( - setup_name, - probe_name, - source_name, - ami_test.available_variations.nominal, - unit_interval, - ignore_bits, - plot_type, - ) - ignore_bits = 5 - unit_interval = 0.1e-9 - plot_type = "InitialWave" - data1 = ami_test.post.sample_ami_waveform( - setup_name, - probe_name, - source_name, - ami_test.available_variations.nominal, - unit_interval, - ignore_bits, - plot_type, - ) - assert len(data1[0]) == 45 - - settings.enable_pandas_output = False - ignore_bits = 5 - unit_interval = 0.1e-9 - clock_tics = [1e-9, 2e-9, 3e-9] - data2 = ami_test.post.sample_ami_waveform( - setup_name, - probe_name, - source_name, - ami_test.available_variations.nominal, - unit_interval, - ignore_bits, - plot_type=None, - clock_tics=clock_tics, - ) - assert len(data2) == 4 - assert len(data2[0]) == 3 - - def test_75_plot_field_line_traces(self, m2dtest): - m2dtest.modeler.model_units = "mm" - rect = m2dtest.modeler.create_rectangle( - origin=["1mm", "5mm", "0mm"], sizes=["-1mm", "-10mm", 0], name="Ground", material="copper" - ) - rect.solve_inside = False - circle = m2dtest.modeler.create_circle( - position=["-10mm", "0", "0"], - radius="1mm", - num_sides="0", - is_covered=True, - name="Electrode", - material="copper", - ) - circle.solve_inside = False - m2dtest.modeler.create_region([20, 100, 20, 100]) - assert not m2dtest.post.create_fieldplot_line_traces("Ground", "Region", "Ground", plot_name="LineTracesTest") - m2dtest.solution_type = "Electrostatic" - assert not m2dtest.post.create_fieldplot_line_traces("Invalid", "Region", "Ground", plot_name="LineTracesTest1") - assert not m2dtest.post.create_fieldplot_line_traces("Ground", "Invalid", "Ground", plot_name="LineTracesTest2") - assert not m2dtest.post.create_fieldplot_line_traces("Ground", "Region", "Invalid", plot_name="LineTracesTest3") - m2dtest.assign_voltage(rect.name, amplitude=0, name="Ground") - m2dtest.assign_voltage(circle.name, amplitude=50e6, name="50kV") - setup_name = "test" - m2dtest.create_setup(name=setup_name) - m2dtest.analyze_setup(setup_name) - plot = m2dtest.post.create_fieldplot_line_traces(["Ground", "Electrode"], "Region", plot_name="LineTracesTest4") - assert plot - assert m2dtest.post.create_fieldplot_line_traces( - ["Ground", "Electrode"], "Region", "Ground", plot_name="LineTracesTest5" - ) - assert m2dtest.post.create_fieldplot_line_traces(["Ground", "Electrode"], plot_name="LineTracesTest6") - assert not m2dtest.post.create_fieldplot_line_traces( - ["Ground", "Electrode"], "Region", ["Invalid"], plot_name="LineTracesTest7" - ) - assert not m2dtest.post.create_fieldplot_line_traces( - ["Ground", "Electrode"], ["Invalid"], plot_name="LineTracesTest8" - ) - plot.TraceStepLength = "0.002mm" - plot.SeedingPointsNumber = 20 - plot.LineStyle = "Cylinder" - plot.LineWidth = 3 - assert plot.update() - el_id = [obj.id for obj in m2dtest.modeler.object_list if obj.name == "Electrode"] - plot.seeding_faces.append(el_id[0]) - assert plot.update() - plot.volumes.append(el_id[0]) - plot.update() - plot.surfaces.append(el_id[0]) - plot.update() - plot.seeding_faces.append(8) - assert not plot.update() - plot.volumes.append(8) - assert not plot.update() - plot.surfaces.append(8) - assert not plot.update() - - @pytest.mark.skipif(config["desktopVersion"] < "2024.1", reason="EMI receiver available from 2024R1.") - def test_76_emi_receiver(self, emi_receiver_test): - emi_receiver_test.analyze() - new_report = emi_receiver_test.post.reports_by_category.emi_receiver() - new_report.band = "2" - new_report.emission = "RE" - new_report.time_start = "1ns" - new_report.time_stop = "2us" - new_report.net = "net_invented" - assert new_report.net != "net_invented" - assert new_report.create() - new_report2 = emi_receiver_test.post.reports_by_category.emi_receiver( - ["dBu(Average[net_6])", "dBu(Peak[net_6])", "dBu(QuasiPeak[net_6])", "dBu(RMS[net_6])"], "EMItransient" - ) - assert new_report2.net == "net_6" - new_report2.time_stop = "2.5us" - assert new_report2.create() - - def test_98_get_variations(self, field_test): - vars = field_test.available_variations.get_variation_strings() - assert vars - variations = field_test.available_variations.variations() - assert isinstance(variations, list) - assert isinstance(variations[0], list) - vars_dict = field_test.available_variations.variations(output_as_dict=True) - assert isinstance(vars_dict, list) - assert isinstance(vars_dict[0], dict) - - def test_z99_delete_variations(self, q3dtest): - assert q3dtest.cleanup_solution() - - def test_z99_delete_variations_B(self, field_test): - vars = field_test.available_variations.get_variation_strings() - assert field_test.cleanup_solution(vars, entire_solution=False) - assert field_test.cleanup_solution(vars, entire_solution=True) - - def test_76_ipk_get_scalar_field_value(self, icepak_post): - assert icepak_post.post.get_scalar_field_value( - "Heat_Flow_Rate", - scalar_function="Integrate", - solution=None, - variations={"power_block": "0.25W", "power_source": "0.075W"}, - is_vector=False, - intrinsics=None, - phase=None, - object_name="cube2", - object_type="surface", - adjacent_side=False, - ) - assert icepak_post.post.get_scalar_field_value( - "Heat_Flow_Rate", - scalar_function="Integrate", - solution=None, - variations={"power_block": "0.6W", "power_source": "0.15W"}, - is_vector=False, - intrinsics=None, - phase=None, - object_name="cube2", - object_type="surface", - adjacent_side=False, - ) - assert icepak_post.post.get_scalar_field_value( - "Heat_Flow_Rate", - scalar_function="Integrate", - solution=None, - variations={"power_block": "0.6W", "power_source": "0.15W"}, - is_vector=False, - intrinsics=None, - phase=None, - object_name="cube2", - object_type="surface", - adjacent_side=True, - ) - assert icepak_post.post.get_scalar_field_value( - "Temperature", - scalar_function="Maximum", - solution=None, - variations={"power_block": "0.6W", "power_source": "0.15W"}, - is_vector=False, - intrinsics=None, - phase=None, - object_name="cube1", - object_type="volume", - adjacent_side=False, - ) - assert icepak_post.post.get_scalar_field_value( - "Temperature", - scalar_function="Maximum", - solution=None, - variations={"power_block": "0.6W", "power_source": "0.15W"}, - is_vector=False, - intrinsics=None, - phase=None, - object_name="cube2", - object_type="surface", - adjacent_side=False, - ) - assert icepak_post.post.get_scalar_field_value( - "Temperature", - scalar_function="Value", - solution=None, - variations=None, - is_vector=False, - intrinsics=None, - phase=None, - object_name="Point1", - object_type="point", - adjacent_side=False, - ) diff --git a/_unittest/test_20_HFSS.py b/_unittest/test_20_HFSS.py new file mode 100644 index 00000000000..ba3f4ddaab1 --- /dev/null +++ b/_unittest/test_20_HFSS.py @@ -0,0 +1,1694 @@ +import math +import os +import shutil + +from _unittest.conftest import config +from _unittest.conftest import local_path +from _unittest.conftest import settings +import pytest + +small_number = 1e-10 # Used for checking equivalence. + +from pyaedt.generic.near_field_import import convert_nearfield_data + +test_subfolder = "T20" + +if config["desktopVersion"] > "2022.2": + component = "Circ_Patch_5GHz_232.a3dcomp" +else: + component = "Circ_Patch_5GHz.a3dcomp" + +if config["desktopVersion"] > "2023.1": + diff_proj_name = "differential_pairs_231" +else: + diff_proj_name = "differential_pairs" + +component_array = "Array_232" + + +@pytest.fixture(scope="class") +def aedtapp(add_app): + app = add_app(project_name="Test_20", design_name="test_20") + return app + + +@pytest.fixture(scope="class") +def fall_back_name(aedtapp): + name = aedtapp.design_name + return name + + +class TestClass: + @pytest.fixture(autouse=True) + def init(self, aedtapp, fall_back_name, local_scratch): + self.aedtapp = aedtapp + self.fall_back_name = fall_back_name + self.local_scratch = local_scratch + + def test_01_save(self): + project_name = "Test_Exercse201119" + test_project = os.path.join(self.local_scratch.path, project_name + ".aedt") + self.aedtapp.save_project(test_project) + assert os.path.exists(test_project) + + def test_01A_check_setup(self): + assert self.aedtapp.active_setup is None + + def test_02_create_primitive(self): + coax1_len = 200 + coax2_len = 70 + r1 = 3.0 + r2 = 10.0 + r1_sq = 9.0 # Used to test area later. + coax1_origin = self.aedtapp.modeler.Position(0, 0, 0) # Thru coax origin. + coax2_origin = self.aedtapp.modeler.Position(125, 0, -coax2_len) # Perpendicular coax 1. + + inner_1 = self.aedtapp.modeler.create_cylinder(self.aedtapp.AXIS.X, coax1_origin, r1, coax1_len, 0, "inner_1") + assert isinstance(inner_1.id, int) + inner_2 = self.aedtapp.modeler.create_cylinder( + self.aedtapp.AXIS.Z, coax2_origin, r1, coax2_len, 0, "inner_2", material="copper" + ) + assert len(inner_2.faces) == 3 # Cylinder has 3 faces. + # Check area of circular face. + assert abs(min([f.area for f in inner_2.faces]) - math.pi * r1_sq) < small_number + outer_1 = self.aedtapp.modeler.create_cylinder(self.aedtapp.AXIS.X, coax1_origin, r2, coax1_len, 0, "outer_1") + assert isinstance(outer_1.id, int) + outer_2 = self.aedtapp.modeler.create_cylinder(self.aedtapp.AXIS.Z, coax2_origin, r2, coax2_len, 0, "outer_2") + + # Check the area of the outer surface of the cylinder "outer_2". + assert abs(max([f.area for f in outer_2.faces]) - 2 * coax2_len * r2 * math.pi) < small_number + inner = self.aedtapp.modeler.unite( + ["inner_1", "inner_2"], + ) + outer = self.aedtapp.modeler.unite( + ["outer_1", "outer_2"], + ) + assert outer == "outer_1" + assert inner == "inner_1" + assert self.aedtapp.modeler.subtract(outer_1, inner_1, keep_originals=True) + + def test_03_2_assign_material(self): + udp = self.aedtapp.modeler.Position(0, 0, 0) + coax_length = 80 + cyl_1 = self.aedtapp.modeler.create_cylinder(self.aedtapp.AXIS.X, udp, 10, coax_length, 0, "insulator") + self.aedtapp.modeler.subtract(cyl_1, "inner_1", keep_originals=True) + self.aedtapp.modeler["inner_1"].material_name = "Copper" + cyl_1.material_name = "teflon_based" + assert self.aedtapp.modeler["inner_1"].material_name == "copper" + assert cyl_1.material_name == "teflon_based" + + def test_04_assign_coating(self): + id = self.aedtapp.modeler.get_obj_id( + "inner_1", + ) + args = { + "mat": "aluminum", + "usethickness": True, + "thickness": "0.5mm", + "istwoside": True, + "issheelElement": True, # TODO: Is "sheelElement" a typo in native API? + "usehuray": True, + "radius": "0.75um", + "ratio": "3", + } + coat = self.aedtapp.assign_coating([id, "inner_1", 41], **args) + coat.name = "Coating1inner" + assert coat.update() + assert coat.object_properties + material = coat.props.get("Material", "") + assert material == "aluminum" + assert not self.aedtapp.assign_coating(["insulator2", 45]) + + def test_05_create_wave_port_from_sheets(self): + udp = self.aedtapp.modeler.Position(0, 0, 0) + o5 = self.aedtapp.modeler.create_circle(self.aedtapp.PLANE.YZ, udp, 10, name="sheet1") + self.aedtapp.solution_type = "Terminal" + outer_1 = self.aedtapp.modeler["outer_1"] + # TODO: Consider allowing a TEM port to be created. + assert not self.aedtapp.wave_port(o5) + + port = self.aedtapp.wave_port( + assignment=o5, + reference=[outer_1.name], + integration_line=self.aedtapp.AxisDir.XNeg, + modes=2, + impedance=40, + name="sheet1_Port", + renormalize=False, + deembed=5, + terminals_rename=False, + ) + + assert port.object_properties + assert port.name == "sheet1_Port" + assert port.name in [i.name for i in self.aedtapp.boundaries] + assert port.props["RenormalizeAllTerminals"] is False + + udp = self.aedtapp.modeler.Position(80, 0, 0) + o6 = self.aedtapp.modeler.create_circle(self.aedtapp.PLANE.YZ, udp, 10, name="sheet1a") + self.aedtapp.modeler.subtract(o6, "inner_1", keep_originals=True) + + port = self.aedtapp.wave_port( + assignment=o6, + reference=[outer_1.name], + create_pec_cap=True, + integration_line=self.aedtapp.AxisDir.XNeg, + modes=2, + impedance=40, + name="sheet1a_Port", + renormalize=True, + deembed=0, + ) + assert port.name == "sheet1a_Port" + assert port.name in [i.name for i in self.aedtapp.boundaries] + assert port.props["DoDeembed"] is False + + # Get the object for "outer_1". + outer_1 = self.aedtapp.modeler["outer_1"] + bottom_port = self.aedtapp.wave_port( + outer_1.bottom_face_z, reference=outer_1.name, create_pec_cap=True, name="bottom_probe_port" + ) + assert bottom_port.name == "bottom_probe_port" + pec_objects = self.aedtapp.modeler.get_objects_by_material("pec") + assert len(pec_objects) == 2 # PEC cap created. + self.aedtapp.solution_type = "Modal" + assert len(self.aedtapp.boundaries) == 4 + udp = self.aedtapp.modeler.Position(200, 0, 0) + o6 = self.aedtapp.modeler.create_circle(self.aedtapp.PLANE.YZ, udp, 10, name="sheet2") + port = self.aedtapp.wave_port( + assignment=o6, + integration_line=self.aedtapp.AxisDir.XPos, + modes=2, + impedance=40, + name="sheet2_Port", + renormalize=True, + deembed=5, + ) + assert port.name == "sheet2_Port" + assert port.name in [i.name for i in self.aedtapp.boundaries] + assert port.props["RenormalizeAllTerminals"] is True + + id6 = self.aedtapp.modeler.create_box([20, 20, 20], [10, 10, 2], name="My_Box", material="Copper") + id7 = self.aedtapp.modeler.create_box([20, 25, 30], [10, 2, 2], material="Copper") + rect = self.aedtapp.modeler.create_rectangle(self.aedtapp.PLANE.YZ, [20, 25, 20], [2, 10]) + port3 = self.aedtapp.wave_port( + assignment=rect, + integration_line=self.aedtapp.AxisDir.ZNeg, + modes=1, + impedance=30, + name="sheet3_Port", + renormalize=False, + deembed=5, + ) + assert port3.name in [i.name for i in self.aedtapp.boundaries] + + def test_06a_create_linear_count_sweep(self): + setup = self.aedtapp.create_setup("MySetup") + setup.props["Frequency"] = "1GHz" + setup.props["BasisOrder"] = 2 + setup.props["MaximumPasses"] = 1 + assert setup.update() + assert self.aedtapp.create_linear_count_sweep("MySetup", "GHz", 0.8, 1.2, 401) + assert not self.aedtapp.setups[0].sweeps[0].is_solved + assert self.aedtapp.create_linear_count_sweep("MySetup", "GHz", 0.8, 1.2, 401) + assert self.aedtapp.create_linear_count_sweep( + setup="MySetup", + unit="GHz", + start_frequency=1.1e3, + stop_frequency=1200.1, + num_of_freq_points=1234, + sweep_type="Interpolating", + ) + assert self.aedtapp.create_linear_count_sweep( + setup="MySetup", + unit="MHz", + start_frequency=1.1e3, + stop_frequency=1200.1, + num_of_freq_points=1234, + sweep_type="Interpolating", + ) + assert self.aedtapp.create_linear_count_sweep( + setup="MySetup", + unit="MHz", + start_frequency=1.1e3, + stop_frequency=1200.1, + num_of_freq_points=1234, + sweep_type="Fast", + ) + num_points = 1752 + freq_start = 1.1e3 + freq_stop = 1200.1 + units = "MHz" + sweep = self.aedtapp.create_linear_count_sweep( + setup="MySetup", + unit="MHz", + start_frequency=freq_start, + stop_frequency=freq_stop, + num_of_freq_points=num_points, + ) + assert sweep.props["RangeCount"] == num_points + assert sweep.props["RangeStart"] == str(freq_start) + units + assert sweep.props["RangeEnd"] == str(freq_stop) + units + assert sweep.props["Type"] == "Discrete" + + # Create a linear count sweep with the incorrect sweep type. + with pytest.raises(AttributeError) as execinfo: + self.aedtapp.create_linear_count_sweep( + setup="MySetup", + unit="MHz", + start_frequency=1.1e3, + stop_frequency=1200.1, + num_of_freq_points=1234, + sweep_type="Incorrect", + ) + assert ( + execinfo.args[0] + == "Invalid value for `sweep_type`. The value must be 'Discrete', 'Interpolating', or 'Fast'." + ) + self.aedtapp["der_var"] = "1mm" + self.aedtapp["der_var2"] = "2mm" + setup2 = self.aedtapp.create_setup("MySetup_2", setup_type=0) + assert setup2.add_derivatives("der_var") + assert "der_var" in setup2.get_derivative_variables() + assert setup2.add_derivatives("der_var2") + assert "der_var2" in setup2.get_derivative_variables() + assert "der_var" in setup2.get_derivative_variables() + setup2.delete() + setup3 = self.aedtapp.create_setup("MySetup_3", setup_type=0) + assert setup3.add_derivatives("der_var") + assert "der_var" in setup3.get_derivative_variables() + assert setup3.add_derivatives("der_var2") + assert "der_var2" in setup3.get_derivative_variables() + assert "der_var" in setup3.get_derivative_variables() + setup3.delete() + + def test_06b_setup_exists(self): + assert self.aedtapp.active_setup is not None + assert self.aedtapp.nominal_sweep is not None + + def test_06c_create_linear_step_sweep(self): + step_size = 153.8 + freq_start = 1.1e3 + freq_stop = 1200.1 + units = "MHz" + sweep = self.aedtapp.create_linear_step_sweep( + setup="MySetup", + name=None, + unit=units, + start_frequency=freq_start, + stop_frequency=freq_stop, + step_size=step_size, + ) + assert sweep.props["RangeStep"] == str(step_size) + units + assert sweep.props["RangeStart"] == str(freq_start) + units + assert sweep.props["RangeEnd"] == str(freq_stop) + units + assert sweep.props["Type"] == "Discrete" + + step_size = 53.8 + freq_start = 1.2e3 + freq_stop = 1305.1 + units = "MHz" + sweep = self.aedtapp.create_linear_step_sweep( + setup="MySetup", + name="StepFast", + unit=units, + start_frequency=freq_start, + stop_frequency=freq_stop, + step_size=step_size, + sweep_type="Fast", + ) + assert sweep.props["RangeStep"] == str(step_size) + units + assert sweep.props["RangeStart"] == str(freq_start) + units + assert sweep.props["RangeEnd"] == str(freq_stop) + units + assert sweep.props["Type"] == "Fast" + + # Create a linear step sweep with the incorrect sweep type. + with pytest.raises(AttributeError) as execinfo: + self.aedtapp.create_linear_step_sweep( + setup="MySetup", + name="StepFast", + unit=units, + start_frequency=freq_start, + stop_frequency=freq_stop, + step_size=step_size, + sweep_type="Incorrect", + ) + assert ( + execinfo.args[0] + == "Invalid value for 'sweep_type'. The value must be 'Discrete', 'Interpolating', or 'Fast'." + ) + + def test_06d_create_single_point_sweep(self): + assert self.aedtapp.create_single_point_sweep( + setup="MySetup", + unit="MHz", + freq=1.2e3, + ) + setup = self.aedtapp.get_setup("MySetup") + assert setup.create_single_point_sweep( + unit="GHz", + freq=1.2, + save_single_field=False, + ) + assert self.aedtapp.create_single_point_sweep( + setup="MySetup", + unit="GHz", + freq=[1.1, 1.2, 1.3], + ) + assert self.aedtapp.create_single_point_sweep( + setup="MySetup", unit="GHz", freq=[1.1e1, 1.2e1, 1.3e1], save_single_field=[True, False, True] + ) + settings.enable_error_handler = True + assert not self.aedtapp.create_single_point_sweep( + setup="MySetup", unit="GHz", freq=[1, 2e2, 3.4], save_single_field=[True, False] + ) + settings.enable_error_handler = False + + def test_06e_delete_setup(self): + setup_name = "SetupToDelete" + setuptd = self.aedtapp.create_setup(name=setup_name) + assert setuptd.name in self.aedtapp.existing_analysis_setups + assert self.aedtapp.delete_setup(setup_name) + assert setuptd.name not in self.aedtapp.existing_analysis_setups + + def test_06f_sweep_add_subrange(self): + self.aedtapp.modeler.create_box([0, 0, 20], [10, 10, 5], "box_sweep", "Copper") + self.aedtapp.modeler.create_box([0, 0, 30], [10, 10, 5], "box_sweep2", "Copper") + self.aedtapp.wave_port( + assignment="box_sweep", + reference="box_sweep2", + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XNeg, + modes=1, + impedance=75, + name="WaveForSweep", + renormalize=False, + ) + setup = self.aedtapp.create_setup(name="MySetupForSweep") + assert not setup.get_sweep() + sweep = setup.add_sweep() + sweep1 = setup.get_sweep(sweep.name) + assert sweep1 == sweep + sweep2 = setup.get_sweep() + assert sweep2 == sweep1 + assert sweep.add_subrange("LinearCount", 1, 3, 10, "GHz") + assert sweep.add_subrange("LinearCount", 2, 4, 10, "GHz") + assert sweep.add_subrange("LinearStep", 1.1, 2.1, 0.4, "GHz") + assert sweep.add_subrange("LinearCount", 1, 1.5, 5, "MHz") + assert sweep.add_subrange("LogScale", 1, 3, 10, "GHz") + + def test_06g_sweep_clear_subrange(self): + self.aedtapp.modeler.create_box([0, 0, 50], [10, 10, 5], "box_sweep3", "Copper") + self.aedtapp.modeler.create_box([0, 0, 60], [10, 10, 5], "box_sweep4", "Copper") + self.aedtapp.wave_port( + assignment="box_sweep3", + reference="box_sweep4", + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XNeg, + modes=1, + impedance=50, + name="WaveForSweepWithClear", + renormalize=False, + ) + + setup = self.aedtapp.create_setup(name="MySetupClearSweep") + sweep = setup.add_sweep() + assert sweep.add_subrange("LinearCount", 1.1, 3.6, 10, "GHz", clear=True) + assert sweep.props["RangeType"] == "LinearCount" + assert sweep.props["RangeStart"] == "1.1GHz" + assert sweep.props["RangeEnd"] == "3.6GHz" + assert sweep.props["RangeCount"] == 10 + assert sweep.add_subrange("LinearCount", 2, 5, 10, "GHz") + setup.update() + sweep.update() + assert sweep.add_subrange("LinearCount", 3, 8, 10, "GHz", clear=True) + assert sweep.props["RangeType"] == "LinearCount" + assert sweep.props["RangeStart"] == "3GHz" + assert sweep.props["RangeEnd"] == "8GHz" + assert sweep.props["RangeCount"] == 10 + assert sweep.add_subrange("LinearStep", 1.1, 2.1, 0.4, "GHz", clear=True) + assert sweep.props["RangeType"] == "LinearStep" + assert sweep.props["RangeStart"] == "1.1GHz" + assert sweep.props["RangeEnd"] == "2.1GHz" + assert sweep.props["RangeStep"] == "0.4GHz" + assert sweep.add_subrange("LogScale", 1, 3, 10, clear=True) + assert sweep.props["RangeType"] == "LogScale" + assert sweep.props["RangeStart"] == "1GHz" + assert sweep.props["RangeEnd"] == "3GHz" + assert sweep.props["RangeSamples"] == 10 + sweep.props["Type"] = "Discrete" + sweep.update() + assert sweep.add_subrange("SinglePoints", 23, clear=True) + assert sweep.props["RangeType"] == "SinglePoints" + assert sweep.props["RangeStart"] == "23GHz" + assert sweep.props["RangeEnd"] == "23GHz" + assert sweep.props["SaveSingleField"] == False + + def test_06z_validate_setup(self): + list, ok = self.aedtapp.validate_full_design(ports=len(self.aedtapp.excitations)) + assert ok + + def test_07_set_power(self): + assert self.aedtapp.edit_source("sheet1_Port" + ":1", "10W") + assert self.aedtapp.edit_sources( + {"sheet1_Port" + ":1": "10W", "sheet2_Port:1": ("20W", "20deg")}, + include_port_post_processing=True, + max_available_power="40W", + ) + assert self.aedtapp.edit_sources( + {"sheet1_Port" + ":1": "10W", "sheet2_Port:1": ("20W", "0deg", True)}, + include_port_post_processing=True, + use_incident_voltage=True, + ) + + def test_08_create_circuit_port_from_edges(self): + plane = self.aedtapp.PLANE.XY + rect_1 = self.aedtapp.modeler.create_rectangle(plane, [10, 10, 10], [10, 10], name="rect1_for_port") + edges1 = self.aedtapp.modeler.get_object_edges(rect_1.id) + e1 = edges1[0] + rect_2 = self.aedtapp.modeler.create_rectangle(plane, [30, 10, 10], [10, 10], name="rect2_for_port") + edges2 = self.aedtapp.modeler.get_object_edges(rect_2.id) + e2 = edges2[0] + + self.aedtapp.solution_type = "Modal" + assert self.aedtapp.composite is False + self.aedtapp.composite = True + assert self.aedtapp.composite is True + self.aedtapp.composite = False + self.aedtapp.hybrid = False + assert self.aedtapp.hybrid is False + self.aedtapp.hybrid = True + assert self.aedtapp.hybrid is True + + assert ( + self.aedtapp.circuit_port( + e1, e2, impedance=50.1, name="port10", renormalize=False, renorm_impedance="50" + ).name + == "port10" + ) + assert ( + self.aedtapp.circuit_port( + e1, e2, impedance="50+1i*55", name="port11", renormalize=True, renorm_impedance=15.4 + ).name + == "port11" + ) + assert self.aedtapp.set_source_context(["port10", "port11"]) + + assert self.aedtapp.set_source_context([]) + + assert self.aedtapp.set_source_context(["port10", "port11"], 0) + + assert self.aedtapp.set_source_context(["port10", "port11", "sheet1_Port"]) + + assert self.aedtapp.set_source_context(["port10", "port11", "sheet1_Port"], 0) + + self.aedtapp.solution_type = "Terminal" + assert ( + self.aedtapp.circuit_port( + e1, e2, impedance=50.1, name="port20", renormalize=False, renorm_impedance="50+1i*55" + ).name + == "port20" + ) + bound = self.aedtapp.circuit_port(e1, e2, impedance="50.1", name="port32", renormalize=True) + assert bound + bound.name = "port21" + assert bound.update() + self.aedtapp.solution_type = "Modal" + + def test_09_create_waveport_on_objects(self): + box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 5], "BoxWG1", "Copper") + box2 = self.aedtapp.modeler.create_box([0, 0, 10], [10, 10, 5], "BoxWG2", "copper") + box2.material_name = "Copper" + port = self.aedtapp.wave_port( + assignment="BoxWG1", + reference="BoxWG2", + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XNeg, + modes=1, + impedance=50, + name="Wave1", + renormalize=False, + ) + assert port.name == "Wave1" + port2 = self.aedtapp.wave_port( + assignment="BoxWG1", + reference="BoxWG2", + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XPos, + modes=2, + impedance=25, + name="Wave1", + renormalize=True, + deembed=5, + ) + + assert port2.name != "Wave1" and "Wave1" in port2.name + self.aedtapp.solution_type = "Terminal" + assert self.aedtapp.wave_port( + assignment="BoxWG1", + reference="BoxWG2", + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XPos, + modes=2, + impedance=25, + name="Wave3", + renormalize=True, + ) + + self.aedtapp.solution_type = "Modal" + assert self.aedtapp.wave_port( + assignment="BoxWG1", + reference="BoxWG2", + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XPos, + modes=2, + impedance=25, + name="Wave4", + renormalize=True, + deembed=5, + ) + + def test_09a_create_waveport_on_true_surface_objects(self): + cs = self.aedtapp.PLANE.XY + o1 = self.aedtapp.modeler.create_cylinder( + cs, [0, 0, 0], radius=5, height=100, num_sides=0, name="inner", material="Copper" + ) + o3 = self.aedtapp.modeler.create_cylinder( + cs, [0, 0, 0], radius=10, height=100, num_sides=0, name="outer", material="Copper" + ) + port1 = self.aedtapp.wave_port( + assignment=o1.name, + reference=o3.name, + create_port_sheet=True, + create_pec_cap=True, + integration_line=self.aedtapp.AxisDir.XNeg, + name="P1", + ) + assert port1.name.startswith("P1") + + def test_10_create_lumped_on_objects(self): + box1 = self.aedtapp.modeler.create_box([0, 0, 50], [10, 10, 5], "BoxLumped1") + box1.material_name = "Copper" + box2 = self.aedtapp.modeler.create_box([0, 0, 60], [10, 10, 5], "BoxLumped2") + box2.material_name = "Copper" + port = self.aedtapp.lumped_port( + assignment="BoxLumped1", + reference="BoxLumped2", + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XNeg, + impedance=50, + name="Lump1xx", + renormalize=True, + ) + assert not self.aedtapp.lumped_port( + assignment="BoxLumped1111", + reference="BoxLumped2", + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XNeg, + impedance=50, + name="Lump1xx", + renormalize=True, + ) + + assert self.aedtapp.lumped_port( + assignment="BoxLumped1", + reference="BoxLumped2", + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XPos, + impedance=50, + ) + + assert port.name == "Lump1xx" + port.name = "Lump1" + assert port.update() + port = self.aedtapp.lumped_port( + assignment="BoxLumped1", + reference="BoxLumped2", + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XNeg, + impedance=50, + name="Lump2", + renormalize=False, + deembed=True, + ) + + def test_11_create_circuit_on_objects(self): + self.aedtapp.insert_design("test_11") + box1 = self.aedtapp.modeler.create_box([0, 0, 80], [10, 10, 5], "BoxCircuit1", "Copper") + box2 = self.aedtapp.modeler.create_box([0, 0, 100], [10, 10, 5], "BoxCircuit2", "copper") + box2.material_name = "Copper" + port = self.aedtapp.circuit_port( + "BoxCircuit1", "BoxCircuit2", self.aedtapp.AxisDir.XNeg, 50, "Circ1", True, 50, False + ) + assert port.name == "Circ1" + assert not self.aedtapp.circuit_port( + "BoxCircuit44", "BoxCircuit2", self.aedtapp.AxisDir.XNeg, 50, "Circ1", True, 50, False + ) + self.aedtapp.delete_design("test_11", self.fall_back_name) + + def test_12_create_perfects_on_objects(self): + self.aedtapp.insert_design("test_12") + box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 5], "perfect1", "Copper") + box2 = self.aedtapp.modeler.create_box([0, 0, 10], [10, 10, 5], "perfect2", "copper") + pe = self.aedtapp.create_perfecth_from_objects("perfect1", "perfect2", self.aedtapp.AxisDir.ZPos) + ph = self.aedtapp.create_perfecte_from_objects("perfect1", "perfect2", self.aedtapp.AxisDir.ZNeg) + assert pe.name in self.aedtapp.modeler.get_boundaries_name() + assert pe.update() + assert ph.name in self.aedtapp.modeler.get_boundaries_name() + assert ph.update() + self.aedtapp.delete_design("test_12", self.fall_back_name) + + def test_13_create_impedance_on_objects(self): + box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 5], "imp1", "Copper") + box2 = self.aedtapp.modeler.create_box([0, 0, 10], [10, 10, 5], "imp2", "copper") + imp = self.aedtapp.create_impedance_between_objects( + box1.name, box2.name, self.aedtapp.AxisDir.XPos, "TL1", 50, 25 + ) + assert imp.name in self.aedtapp.modeler.get_boundaries_name() + assert imp.update() + + pytest.mark.skipif(config["desktopVersion"] > "2023.2", reason="Crashing Desktop") + + def test_14_create_lumpedrlc_on_objects(self): + box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 5], "rlc1", "Copper") + box2 = self.aedtapp.modeler.create_box([0, 0, 10], [10, 10, 5], "rlc2", "copper") + imp = self.aedtapp.create_lumped_rlc_between_objects( + box1.name, box2.name, self.aedtapp.AxisDir.XPos, resistance=50, inductance=1e-9 + ) + assert imp.name in self.aedtapp.modeler.get_boundaries_name() + assert imp.update() + + box3 = self.aedtapp.modeler.create_box([0, 0, 20], [10, 10, 5], "rlc3", "copper") + lumped_rlc2 = self.aedtapp.create_lumped_rlc_between_objects( + box2.name, box3.name, self.aedtapp.AxisDir.XPos, resistance=50, inductance=1e-9, capacitance=1e-9 + ) + assert lumped_rlc2.name in self.aedtapp.modeler.get_boundaries_name() + assert lumped_rlc2.update() + + def test_15_create_perfects_on_sheets(self): + rect = self.aedtapp.modeler.create_rectangle( + self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="RectBound", material="Copper" + ) + pe = self.aedtapp.assign_perfecte_to_sheets(rect.name) + assert pe.name in self.aedtapp.modeler.get_boundaries_name() + ph = self.aedtapp.assign_perfecth_to_sheets(rect.name) + assert ph.name in self.aedtapp.modeler.get_boundaries_name() + solution_type = self.aedtapp.solution_type + + self.aedtapp.solution_type = "Eigen Mode" + perfect_h_eigen = self.aedtapp.assign_perfecth_to_sheets(rect.name) + assert perfect_h_eigen.name in self.aedtapp.modeler.get_boundaries_name() + perfect_e_eigen = self.aedtapp.assign_perfecte_to_sheets(rect.name) + assert perfect_e_eigen.name in self.aedtapp.modeler.get_boundaries_name() + self.aedtapp.solution_type = "solution_type" + + def test_16_create_impedance_on_sheets(self): + rect = self.aedtapp.modeler.create_rectangle( + self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="ImpBound", material="Copper" + ) + imp1 = self.aedtapp.assign_impedance_to_sheet(rect.name, "TL2", 50, 25) + assert imp1.name in self.aedtapp.modeler.get_boundaries_name() + assert imp1.update() + + impedance_box = self.aedtapp.modeler.create_box([0, -100, 0], [200, 200, 200], "ImpedanceBox") + ids = self.aedtapp.modeler.get_object_faces(impedance_box.name)[:3] + + imp2 = self.aedtapp.assign_impedance_to_sheet(ids, resistance=60, reactance=-20) + assert imp2.name in self.aedtapp.modeler.get_boundaries_name() + + rect2 = self.aedtapp.modeler.create_rectangle( + self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="AniImpBound", material="Copper" + ) + assert not self.aedtapp.assign_impedance_to_sheet(rect2.name, "TL3", [50, 20, 0, 0], [25, 0, 5]) + imp2 = self.aedtapp.assign_impedance_to_sheet(rect2.name, "TL3", [50, 20, 0, 0], [25, 0, 5, 0]) + assert imp2.name in self.aedtapp.modeler.get_boundaries_name() + imp3 = self.aedtapp.assign_impedance_to_sheet(impedance_box.top_face_z.id, "TL4", [50, 20, 0, 0], [25, 0, 5, 0]) + assert imp3.name in self.aedtapp.modeler.get_boundaries_name() + + def test_17_create_lumpedrlc_on_sheets(self): + rect = self.aedtapp.modeler.create_rectangle( + self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="rlcBound", material="Copper" + ) + imp = self.aedtapp.assign_lumped_rlc_to_sheet( + rect.name, self.aedtapp.AxisDir.XPos, resistance=50, inductance=1e-9 + ) + names = self.aedtapp.modeler.get_boundaries_name() + assert imp.name in self.aedtapp.modeler.get_boundaries_name() + + rect2 = self.aedtapp.modeler.create_rectangle( + self.aedtapp.PLANE.XY, [0, 0, 10], [10, 2], name="rlcBound2", material="Copper" + ) + imp = self.aedtapp.assign_lumped_rlc_to_sheet( + rect.name, self.aedtapp.AxisDir.XPos, rlc_type="Serial", resistance=50, inductance=1e-9 + ) + names = self.aedtapp.modeler.get_boundaries_name() + assert imp.name in self.aedtapp.modeler.get_boundaries_name() + assert self.aedtapp.assign_lumped_rlc_to_sheet( + rect.name, [rect.bottom_edge_x.midpoint, rect.bottom_edge_y.midpoint], inductance=1e-9 + ) + assert not self.aedtapp.assign_lumped_rlc_to_sheet(rect.name, [rect.bottom_edge_x.midpoint], inductance=1e-9) + + def test_17B_update_assignment(self): + bound = self.aedtapp.assign_perfecth_to_sheets(self.aedtapp.modeler["My_Box"].faces[0].id) + assert bound + bound.props["Faces"].append(self.aedtapp.modeler["My_Box"].faces[1]) + assert bound.update_assignment() + + def test_18_create_sources_on_objects(self): + box1 = self.aedtapp.modeler.create_box([30, 0, 0], [40, 10, 5], "BoxVolt1", "Copper") + box2 = self.aedtapp.modeler.create_box([30, 0, 10], [40, 10, 5], "BoxVolt2", "Copper") + port = self.aedtapp.create_voltage_source_from_objects( + box1.name, "BoxVolt2", self.aedtapp.AxisDir.XNeg, "Volt1" + ) + assert port.name in self.aedtapp.excitations + port = self.aedtapp.create_current_source_from_objects("BoxVolt1", "BoxVolt2", self.aedtapp.AxisDir.XPos) + assert port.name in self.aedtapp.excitations + + def test_19_create_lumped_on_sheet(self): + rect = self.aedtapp.modeler.create_rectangle( + self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="lump_port", material="Copper" + ) + port = self.aedtapp.lumped_port( + assignment=rect.name, + create_port_sheet=False, + integration_line=self.aedtapp.AxisDir.XNeg, + impedance=50, + name="Lump_sheet", + renormalize=True, + ) + + assert port.name + ":1" in self.aedtapp.excitations + port2 = self.aedtapp.lumped_port( + assignment=rect.name, + create_port_sheet=False, + integration_line=self.aedtapp.AxisDir.XNeg, + impedance=50, + name="Lump_sheet2", + renormalize=True, + deembed=True, + ) + + assert port2.name + ":1" in self.aedtapp.excitations + port3 = self.aedtapp.lumped_port( + assignment=rect.name, + create_port_sheet=False, + integration_line=[rect.bottom_edge_x.midpoint, rect.bottom_edge_y.midpoint], + impedance=50, + name="Lump_sheet3", + renormalize=True, + deembed=True, + ) + + assert port3.name + ":1" in self.aedtapp.excitations + assert not self.aedtapp.lumped_port( + assignment=rect.name, + create_port_sheet=False, + integration_line=[rect.bottom_edge_x.midpoint], + impedance=50, + name="Lump_sheet4", + renormalize=True, + deembed=True, + ) + + def test_20_create_voltage_on_sheet(self): + rect = self.aedtapp.modeler.create_rectangle( + self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="lump_volt", material="Copper" + ) + port = self.aedtapp.assign_voltage_source_to_sheet(rect.name, self.aedtapp.AxisDir.XNeg, "LumpVolt1") + assert port.name in self.aedtapp.excitations + assert self.aedtapp.get_property_value("BoundarySetup:LumpVolt1", "VoltageMag", "Excitation") == "1V" + port = self.aedtapp.assign_voltage_source_to_sheet( + rect.name, [rect.bottom_edge_x.midpoint, rect.bottom_edge_y.midpoint], "LumpVolt2" + ) + assert port.name in self.aedtapp.excitations + port = self.aedtapp.assign_voltage_source_to_sheet(rect.name, [rect.bottom_edge_x.midpoint], "LumpVolt2") + assert not port + + def test_21_create_open_region(self): + assert self.aedtapp.create_open_region("1GHz") + assert len(self.aedtapp.field_setups) == 3 + assert self.aedtapp.create_open_region("1GHz", "FEBI") + assert self.aedtapp.create_open_region("1GHz", "PML", True, "-z") + + def test_22_create_length_mesh(self): + box1 = self.aedtapp.modeler.create_box([30, 0, 0], [40, 10, 5], "BoxCircuit1", "Copper") + mesh = self.aedtapp.mesh.assign_length_mesh(["BoxCircuit1"]) + assert mesh + mesh.props["NumMaxElem"] = "100" + assert mesh.props["NumMaxElem"] == self.aedtapp.odesign.GetChildObject("Mesh").GetChildObject( + mesh.name + ).GetPropValue("Max Elems") + + def test_23_create_skin_depth(self): + box1 = self.aedtapp.modeler.create_box([30, 0, 0], [40, 10, 5], "BoxCircuit2", "Copper") + mesh = self.aedtapp.mesh.assign_skin_depth(["BoxCircuit2"], "1mm") + assert mesh + mesh.props["SkinDepth"] = "3mm" + assert mesh.props["SkinDepth"] == self.aedtapp.odesign.GetChildObject("Mesh").GetChildObject( + mesh.name + ).GetPropValue("Skin Depth") + + def test_24_create_curvilinear(self): + box1 = self.aedtapp.modeler.create_box([30, 0, 0], [40, 10, 5], "BoxCircuit3", "Copper") + mesh = self.aedtapp.mesh.assign_curvilinear_elements(["BoxCircuit3"]) + assert mesh + mesh.props["Apply"] = False + assert mesh.props["Apply"] == self.aedtapp.odesign.GetChildObject("Mesh").GetChildObject( + mesh.name + ).GetPropValue("Apply Curvilinear Elements") + mesh.delete() + assert len(self.aedtapp.mesh.meshoperations) == 2 + + def test_30_assign_initial_mesh(self): + assert self.aedtapp.mesh.assign_initial_mesh_from_slider(6) + + def test_30a_add_mesh_link(self): + self.aedtapp.duplicate_design(self.aedtapp.design_name) + self.aedtapp.set_active_design(self.aedtapp.design_list[0]) + assert self.aedtapp.setups[0].add_mesh_link(design=self.aedtapp.design_list[1]) + meshlink_props = self.aedtapp.setups[0].props["MeshLink"] + assert meshlink_props["Project"] == "This Project*" + assert meshlink_props["PathRelativeTo"] == "TargetProject" + assert meshlink_props["Design"] == self.aedtapp.design_list[1] + assert meshlink_props["Soln"] == "MySetup : LastAdaptive" + assert sorted(list(meshlink_props["Params"].keys())) == sorted(self.aedtapp.available_variations.variables) + assert sorted(list(meshlink_props["Params"].values())) == sorted(self.aedtapp.available_variations.variables) + assert not self.aedtapp.setups[0].add_mesh_link(design="") + assert self.aedtapp.setups[0].add_mesh_link( + design=self.aedtapp.design_list[1], solution="MySetup : LastAdaptive" + ) + assert not self.aedtapp.setups[0].add_mesh_link( + design=self.aedtapp.design_list[1], solution="Setup_Test : LastAdaptive" + ) + assert self.aedtapp.setups[0].add_mesh_link( + design=self.aedtapp.design_list[1], parameters=self.aedtapp.available_variations.nominal_w_values_dict + ) + example_project = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + diff_proj_name + ".aedt", + ) + example_project_copy = os.path.join(self.local_scratch.path, diff_proj_name + "_copy.aedt") + shutil.copyfile(example_project, example_project_copy) + assert self.aedtapp.setups[0].add_mesh_link(design=self.aedtapp.design_list[1], project=example_project_copy) + + def test_31_create_microstrip_port(self): + self.aedtapp.insert_design("Microstrip") + self.aedtapp.solution_type = "Modal" + ms = self.aedtapp.modeler.create_box([4, 5, 0], [1, 100, 0.2], name="MS1", material="copper") + sub = self.aedtapp.modeler.create_box([0, 5, -2], [20, 100, 2], name="SUB1", material="FR4_epoxy") + gnd = self.aedtapp.modeler.create_box([0, 5, -2.2], [20, 100, 0.2], name="GND1", material="FR4_epoxy") + port = self.aedtapp.wave_port( + assignment=gnd.name, + reference=ms.name, + create_port_sheet=True, + integration_line=1, + name="MS1", + is_microstrip=True, + ) + assert port.name == "MS1" + assert port.update() + self.aedtapp.solution_type = "Terminal" + assert self.aedtapp.wave_port( + assignment=gnd.name, + reference=ms.name, + create_port_sheet=True, + integration_line=1, + name="MS2", + is_microstrip=True, + ) + assert self.aedtapp.wave_port( + assignment=gnd.name, + reference=ms.name, + create_port_sheet=True, + integration_line=1, + impedance=77, + name="MS3", + deembed=1, + is_microstrip=True, + ) + + def test_32_get_property_value(self): + rect = self.aedtapp.modeler.create_rectangle( + self.aedtapp.PLANE.XY, [0, 0, 0], [10, 2], name="RectProp", material="Copper" + ) + pe = self.aedtapp.assign_perfecte_to_sheets(rect.name, "PerfectE_1") + setup = self.aedtapp.create_setup("MySetup2") + setup.props["Frequency"] = "1GHz" + assert self.aedtapp.get_property_value("BoundarySetup:PerfectE_1", "Inf Ground Plane", "Boundary") == "false" + assert self.aedtapp.get_property_value("AnalysisSetup:MySetup2", "Solution Freq", "Setup") == "1GHz" + + def test_33_copy_solid_bodies(self, add_app): + project_name = "HfssCopiedProject" + design_name = "HfssCopiedBodies" + new_design = add_app(project_name=project_name, design_name=design_name) + num_orig_bodies = len(self.aedtapp.modeler.solid_names) + assert new_design.copy_solid_bodies_from(self.aedtapp, no_vacuum=False, no_pec=False) + assert len(new_design.modeler.solid_bodies) == num_orig_bodies + new_design.delete_design(design_name) + new_design.close_project(project_name) + + def test_34_object_material_properties(self): + self.aedtapp.insert_design("ObjMat") + self.aedtapp.solution_type = "Modal" + ms = self.aedtapp.modeler.create_box([4, 5, 0], [1, 100, 0.2], name="MS1", material="copper") + props = self.aedtapp.get_object_material_properties("MS1", "conductivity") + assert props + + def test_35_set_export_touchstone(self): + assert self.aedtapp.set_export_touchstone(True) + assert self.aedtapp.set_export_touchstone(False) + + def test_36_assign_radiation_to_objects(self): + self.aedtapp.modeler.create_box([-100, -100, -100], [200, 200, 200], name="Rad_box") + rad = self.aedtapp.assign_radiation_boundary_to_objects("Rad_box") + rad.name = "Radiation1" + assert rad.update() + + def test_37_assign_radiation_to_objects(self): + self.aedtapp.modeler.create_box([-100, -100, -100], [200, 200, 200], name="Rad_box2") + ids = [i.id for i in self.aedtapp.modeler["Rad_box2"].faces] + assert self.aedtapp.assign_radiation_boundary_to_faces(ids) + + def test_38_get_all_sources(self): + sources = self.aedtapp.get_all_sources() + assert isinstance(sources, list) + + def test_40_assign_current_source_to_sheet(self): + sheet = self.aedtapp.modeler.create_rectangle( + self.aedtapp.PLANE.XY, [0, 0, 0], [5, 1], name="RectangleForSource", material="Copper" + ) + assert self.aedtapp.assign_current_source_to_sheet(sheet.name) + assert self.aedtapp.assign_current_source_to_sheet( + sheet.name, [sheet.bottom_edge_x.midpoint, sheet.bottom_edge_y.midpoint] + ) + assert not self.aedtapp.assign_current_source_to_sheet(sheet.name, [sheet.bottom_edge_x.midpoint]) + + def test_41_export_step(self): + file_name = "test" + self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 10]) + assert self.aedtapp.export_3d_model(file_name, self.aedtapp.working_directory, ".x_t", [], []) + assert os.path.exists(os.path.join(self.aedtapp.working_directory, file_name + ".x_t")) + + def test_42_floquet_port(self): + self.aedtapp.insert_design("floquet") + self.aedtapp.solution_type = "Modal" + + box1 = self.aedtapp.modeler.create_box([-100, -100, -100], [200, 200, 200], name="Rad_box2") + assert self.aedtapp.create_floquet_port( + box1.faces[0], modes=7, deembed_distance=1, reporter_filter=[False, True, False, False, False, False, False] + ) + assert self.aedtapp.create_floquet_port( + box1.faces[1], modes=7, deembed_distance=1, reporter_filter=[False, True, False, False, False, False, False] + ) + sheet = self.aedtapp.modeler.create_rectangle( + self.aedtapp.PLANE.XY, [-100, -100, -100], [200, 200], name="RectangleForSource", material="Copper" + ) + bound = self.aedtapp.create_floquet_port(sheet, modes=4, deembed_distance=1, reporter_filter=False) + assert bound + bound.name = "Floquet1" + assert bound.update() + self.aedtapp.delete_design("floquet", self.fall_back_name) + + def test_43_autoassign_pairs(self): + self.aedtapp.insert_design("lattice") + box1 = self.aedtapp.modeler.create_box([-100, -100, -100], [200, 200, 200], name="Rad_box2") + assert len(self.aedtapp.auto_assign_lattice_pairs(box1)) == 2 + box1.delete() + box1 = self.aedtapp.modeler.create_box([-100, -100, -100], [200, 200, 200], name="Rad_box2") + if config["desktopVersion"] > "2022.2": + assert self.aedtapp.assign_lattice_pair([box1.faces[2], box1.faces[5]]) + primary = self.aedtapp.assign_primary(box1.faces[4], [100, -100, -100], [100, 100, -100]) + + else: + assert self.aedtapp.assign_lattice_pair([box1.faces[2], box1.faces[4]]) + primary = self.aedtapp.assign_primary(box1.faces[1], [100, -100, -100], [100, 100, -100]) + assert primary + primary.name = "Prim1" + assert primary.update() + sec = self.aedtapp.assign_secondary( + box1.faces[0], primary.name, [100, -100, 100], [100, 100, 100], reverse_v=True + ) + sec.name = "Sec1" + assert sec.update() + self.aedtapp.delete_design("lattice", self.fall_back_name) + + def test_44_create_infinite_sphere(self): + self.aedtapp.insert_design("InfSphere") + air = self.aedtapp.modeler.create_box([0, 0, 0], [20, 20, 20], name="rad", material="vacuum") + self.aedtapp.assign_radiation_boundary_to_objects(air) + bound = self.aedtapp.insert_infinite_sphere( + definition="El Over Az", + x_start=1, + x_stop=91, + x_step=45, + y_start=2, + y_stop=92, + y_step=10, + use_slant_polarization=True, + polarization_angle=30, + ) + assert bound + assert bound.azimuth_start == "1deg" + assert bound.azimuth_stop == "91deg" + assert bound.azimuth_step == "45deg" + assert bound.elevation_start == "2deg" + assert bound.elevation_stop == "92deg" + assert bound.elevation_step == "10deg" + assert bound.slant_angle == "30deg" + assert bound.polarization == "Slant" + bound.azimuth_start = 20 + assert bound.azimuth_start == "20deg" + assert bound.delete() + bound = self.aedtapp.insert_infinite_sphere( + definition="Az Over El", + x_start=1, + x_stop=91, + x_step=45, + y_start=2, + y_stop=92, + y_step=10, + use_slant_polarization=True, + polarization_angle=30, + ) + assert bound.azimuth_start == "2deg" + + def test_45_set_autoopen(self): + assert self.aedtapp.set_auto_open(True, "PML") + + def test_45_terminal_port(self): + self.aedtapp.insert_design("Design_Terminal") + self.aedtapp.solution_type = "Terminal" + box1 = self.aedtapp.modeler.create_box([-100, -100, 0], [200, 200, 5], name="gnd", material="copper") + box2 = self.aedtapp.modeler.create_box([-100, -100, 20], [200, 200, 25], name="sig", material="copper") + sheet = self.aedtapp.modeler.create_rectangle(self.aedtapp.PLANE.YZ, [-100, -100, 5], [200, 15], "port") + port = self.aedtapp.lumped_port( + assignment=box1, + reference=box2.name, + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XNeg, + impedance=75, + name="Lump1", + renormalize=True, + ) + + assert "Lump1_T1" in self.aedtapp.excitations + port2 = self.aedtapp.lumped_port( + assignment=sheet.name, + reference=box1, + create_port_sheet=False, + integration_line=self.aedtapp.AxisDir.XNeg, + impedance=33, + name="Lump_sheet", + renormalize=True, + ) + assert port2.name + "_T1" in self.aedtapp.excitations + port3 = self.aedtapp.lumped_port( + assignment=box1, + reference=box2.name, + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XNeg, + impedance=50, + name="Lump3", + renormalize=False, + deembed=True, + ) + assert port3.name + "_T1" in self.aedtapp.excitations + self.aedtapp.delete_design("Design_Terminal", self.fall_back_name) + + def test_45B_terminal_port(self): + self.aedtapp.insert_design("Design_Terminal_2") + self.aedtapp.solution_type = "Terminal" + box1 = self.aedtapp.modeler.create_box([-100, -100, 0], [200, 200, 5], name="gnd2z", material="copper") + box2 = self.aedtapp.modeler.create_box([-100, -100, 20], [200, 200, 25], name="sig2z", material="copper") + box3 = self.aedtapp.modeler.create_box([-40, -40, -20], [80, 80, 10], name="box3", material="copper") + box4 = self.aedtapp.modeler.create_box([-40, -40, 10], [80, 80, 10], name="box4", material="copper") + box1.display_wireframe = True + box2.display_wireframe = True + box3.display_wireframe = True + box4.display_wireframe = True + self.aedtapp.modeler.fit_all() + portz = self.aedtapp.create_spiral_lumped_port(box1, box2) + assert portz + + n_boundaries = len(self.aedtapp.boundaries) + assert n_boundaries == 4 + + box5 = self.aedtapp.modeler.create_box([-50, -15, 200], [150, -10, 200], name="gnd2y", material="copper") + box6 = self.aedtapp.modeler.create_box([-50, 10, 200], [150, 15, 200], name="sig2y", material="copper") + box5.display_wireframe = True + box6.display_wireframe = True + self.aedtapp.modeler.fit_all() + porty = self.aedtapp.create_spiral_lumped_port(box5, box6) + assert porty + + n_boundaries = len(self.aedtapp.boundaries) + assert n_boundaries == 8 + + box7 = self.aedtapp.modeler.create_box([-15, 300, 0], [-10, 200, 100], name="gnd2x", material="copper") + box8 = self.aedtapp.modeler.create_box([15, 300, 0], [10, 200, 100], name="sig2x", material="copper") + box7.display_wireframe = True + box8.display_wireframe = True + self.aedtapp.modeler.fit_all() + portx = self.aedtapp.create_spiral_lumped_port(box7, box8) + assert portx + + n_boundaries = len(self.aedtapp.boundaries) + assert n_boundaries == 12 + + # Use two boxes with different dimensions. + with pytest.raises(AttributeError) as execinfo: + self.aedtapp.create_spiral_lumped_port(box1, box3) + assert execinfo.args[0] == "The closest faces of the two objects must be identical in shape." + + # Rotate box3 so that, box3 and box4 are not collinear anymore. + # Spiral lumped port can only be created based on 2 collinear objects. + box3.rotate(axis="X", angle=90) + with pytest.raises(AttributeError) as execinfo: + self.aedtapp.create_spiral_lumped_port(box3, box4) + assert execinfo.args[0] == "The two objects must have parallel adjacent faces." + + # Rotate back box3 + # rotate them slightly so that they are still parallel, but not aligned anymore with main planes. + box3.rotate(axis="X", angle=-90) + box3.rotate(axis="Y", angle=5) + box4.rotate(axis="Y", angle=5) + with pytest.raises(AttributeError) as execinfo: + self.aedtapp.create_spiral_lumped_port(box3, box4) + assert ( + execinfo.args[0] + == "The closest faces of the two objects must be aligned with the main planes of the reference system." + ) + self.aedtapp.delete_design("Design_Terminal_2", self.fall_back_name) + + def test_46_mesh_settings(self): + assert self.aedtapp.mesh.initial_mesh_settings + assert self.aedtapp.mesh.initial_mesh_settings.props + + def test_47_convert_near_field(self): + example_project = os.path.join( + local_path, "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", "nf_test" + ) + assert os.path.exists(convert_nearfield_data(example_project, output_folder=self.local_scratch.path)) + + def test_48_traces(self): + assert len(self.aedtapp.excitations) > 0 + assert len(self.aedtapp.get_traces_for_plot()) > 0 + + def test_49_port_creation_exception(self): + box1 = self.aedtapp.modeler.create_box([-400, -40, -20], [80, 80, 10], name="gnd49", material="copper") + box2 = self.aedtapp.modeler.create_box([-400, -40, 10], [80, 80, 10], name="sig49", material="copper") + + self.aedtapp.solution_type = "Modal" + # Spiral lumped port can only be created in a 'Terminal' solution. + with pytest.raises(Exception) as execinfo: + self.aedtapp.create_spiral_lumped_port(box1, box2) + assert execinfo.args[0] == "This method can be used only in 'Terminal' solutions." + self.aedtapp.solution_type = "Terminal" + + # Try to modify SBR+ TX RX antenna settings in a solution that is different from SBR+ + # should not be possible. + assert not self.aedtapp.set_sbr_txrx_settings({"TX1": "RX1"}) + + # SBR linked antenna can only be created within an SBR+ solution. + assert not self.aedtapp.create_sbr_linked_antenna(self.aedtapp, field_type="farfield") + + # Chirp I doppler setup only works within an SBR+ solution. + assert self.aedtapp.create_sbr_chirp_i_doppler_setup(sweep_time_duration=20) == (False, False) + + # Chirp IQ doppler setup only works within an SBR+ solution. + assert self.aedtapp.create_sbr_chirp_iq_doppler_setup(sweep_time_duration=10) == (False, False) + + def test_50_set_differential_pair(self, add_app): + hfss1 = add_app(project_name=diff_proj_name, design_name="Hfss_Terminal", subfolder=test_subfolder) + assert hfss1.set_differential_pair( + assignment="P2_T1", + reference="P2_T2", + differential_mode=None, + common_reference=34, + differential_reference=123, + active=True, + matched=False, + ) + assert not hfss1.set_differential_pair(assignment="P2_T1", reference="P2_T3") + hfss2 = add_app(design_name="Hfss_Transient") + assert hfss2.set_differential_pair( + assignment="P2_T1", + reference="P2_T2", + differential_mode=None, + common_reference=34, + differential_reference=123, + active=True, + matched=False, + ) + assert not hfss2.set_differential_pair(assignment="P2_T1", reference="P2_T3") + hfss2.close_project() + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", + reason="Not working in non-graphical in version lower than 2022.2", + ) + def test_51a_array(self): + self.aedtapp.insert_design("Array_simple", "Modal") + from pyaedt.generic.general_methods import read_json + + if config["desktopVersion"] > "2023.1": + dict_in = read_json( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "array_simple_232.json", + ) + ) + dict_in["Circ_Patch_5GHz_232_1"] = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + component, + ) + dict_in["cells"][(3, 3)] = {"name": "Circ_Patch_5GHz_232_1"} + else: + dict_in = read_json( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "array_simple.json", + ) + ) + dict_in["Circ_Patch_5GHz1"] = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + component, + ) + dict_in["cells"][(3, 3)] = {"name": "Circ_Patch_5GHz1"} + + assert self.aedtapp.add_3d_component_array_from_json(dict_in) + array_name = self.aedtapp.component_array_names[0] + assert self.aedtapp.component_array[array_name].cells[2][2].rotation == 0 + assert self.aedtapp.component_array_names + dict_in["cells"][(3, 3)]["rotation"] = 90 + component_array = self.aedtapp.add_3d_component_array_from_json(dict_in) + assert component_array.cells[2][2].rotation == 90 + component_array.cells[2][2].rotation = 0 + assert component_array.cells[2][2].rotation == 0 + + def test_51b_set_material_threshold(self): + assert self.aedtapp.set_material_threshold() + threshold = 123123123 + assert self.aedtapp.set_material_threshold(threshold) + assert self.aedtapp.set_material_threshold(str(threshold)) + assert not self.aedtapp.set_material_threshold("e") + + def test_52_crate_setup_hybrid_sbr(self, add_app): + aedtapp = add_app(project_name="test_52") + udp = aedtapp.modeler.Position(0, 0, 0) + coax_dimension = 200 + aedtapp.modeler.create_cylinder(aedtapp.AXIS.X, udp, 3, coax_dimension, 0, "inner") + aedtapp.modeler.create_cylinder(aedtapp.AXIS.X, udp, 10, coax_dimension, 0, "outer") + aedtapp.hybrid = True + assert aedtapp.assign_hybrid_region(["inner"]) + bound = aedtapp.assign_hybrid_region("outer", name="new_hybrid", hybrid_region="IE") + assert bound.props["Type"] == "IE" + bound.props["Type"] = "PO" + assert bound.props["Type"] == "PO" + aedtapp.close_project(save_project=False) + + def test_53_import_source_excitation(self, add_app): + aedtapp = add_app(solution_type="Modal", project_name="test_53") + freq_domain = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "S Parameter Table 1.csv", + ) + time_domain = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "Sinusoidal.csv", + ) + + box1 = aedtapp.modeler.create_box([0, 0, 0], [10, 20, 20]) + aedtapp.wave_port(assignment=box1.bottom_face_x, create_port_sheet=False, name="Port1") + aedtapp.create_setup() + assert aedtapp.edit_source_from_file(aedtapp.excitations[0], freq_domain, is_time_domain=False, x_scale=1e9) + assert aedtapp.edit_source_from_file( + aedtapp.excitations[0], time_domain, is_time_domain=True, x_scale=1e-6, y_scale=1e-3, data_format="Voltage" + ) + aedtapp.close_project(save_project=False) + + def test_54_assign_symmetry(self, add_app): + aedtapp = add_app(project_name="test_54", solution_type="Modal") + aedtapp.modeler.create_box([0, -100, 0], [200, 200, 200], name="SymmetryForFaces") + ids = [i.id for i in aedtapp.modeler["SymmetryForFaces"].faces] + assert aedtapp.assign_symmetry(ids) + assert aedtapp.assign_symmetry([ids[0], ids[1], ids[2]]) + assert not aedtapp.assign_symmetry(aedtapp.modeler.object_list[0].faces[0]) + assert aedtapp.assign_symmetry([aedtapp.modeler.object_list[0].faces[0]]) + assert aedtapp.assign_symmetry( + [ + aedtapp.modeler.object_list[0].faces[0], + aedtapp.modeler.object_list[0].faces[1], + aedtapp.modeler.object_list[0].faces[2], + ] + ) + assert not aedtapp.assign_symmetry(ids[0]) + assert not aedtapp.assign_symmetry("test") + assert aedtapp.set_impedance_multiplier(2) + aedtapp.close_project(save_project=False) + + def test_55_create_near_field_sphere(self): + air = self.aedtapp.modeler.create_box([0, 0, 0], [20, 20, 20], name="rad", material="vacuum") + self.aedtapp.assign_radiation_boundary_to_objects(air) + bound = self.aedtapp.insert_near_field_sphere( + radius=20, + radius_units="cm", + x_start=-180, + x_stop=180, + x_step=10, + y_start=0, + y_stop=180, + y_step=10, + angle_units="deg", + custom_radiation_faces=None, + custom_coordinate_system=None, + name=None, + ) + bound.name = "Test_Sphere" + assert self.aedtapp.field_setup_names[0] == bound.name + + def test_56_create_near_field_box(self): + bound = self.aedtapp.insert_near_field_box( + u_length=20, + u_samples=21, + v_length=20, + v_samples=21, + w_length=20, + w_samples=21, + units="mm", + custom_radiation_faces=None, + custom_coordinate_system=None, + name=None, + ) + + assert bound + + def test_57_create_near_field_rectangle(self): + bound = self.aedtapp.insert_near_field_rectangle( + u_length=20, + u_samples=21, + v_length=20, + v_samples=21, + units="mm", + custom_radiation_faces=None, + custom_coordinate_system=None, + name=None, + ) + bound.props["Length"] = "50mm" + assert bound + + def test_58_create_near_field_line(self): + test_points = [ + ["0mm", "0mm", "0mm"], + ["100mm", "20mm", "0mm"], + ["71mm", "71mm", "0mm"], + ["0mm", "100mm", "0mm"], + ] + line = self.aedtapp.modeler.create_polyline(test_points) + bound = self.aedtapp.insert_near_field_line( + assignment=line.name, points=1000, custom_radiation_faces=None, name=None + ) + bound.props["NumPts"] = "200" + assert bound + + def test_59_test_nastran(self): + self.aedtapp.insert_design("Nas_teest") + example_project = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "test_cad.nas", + ) + example_project2 = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "test_cad_2.nas", + ) + + cads = self.aedtapp.modeler.import_nastran(example_project) + assert len(cads) > 0 + assert self.aedtapp.modeler.import_nastran(example_project2) + + def test_60_set_variable(self): + self.aedtapp.variable_manager.set_variable("var_test", expression="123") + self.aedtapp["var_test"] = "234" + assert "var_test" in self.aedtapp.variable_manager.design_variable_names + assert self.aedtapp.variable_manager.design_variables["var_test"].expression == "234" + + def test_61_create_lumped_ports_on_object_driven_terminal(self): + self.aedtapp.insert_design("test_61") + self.aedtapp.solution_type = "Terminal" + box1 = self.aedtapp.modeler.create_box([0, 0, 50], [10, 10, 5], "BoxLumped1") + box1.material_name = "Copper" + box2 = self.aedtapp.modeler.create_box([0, 0, 60], [10, 10, 5], "BoxLumped2") + box2.material_name = "Copper" + + _ = self.aedtapp.lumped_port( + signal=box1.name, + reference=box2.name, + create_port_sheet=True, + port_on_plane=True, + integration_line=self.aedtapp.AxisDir.XNeg, + impedance=50, + name="Lump1xx", + renormalize=True, + deembed=False, + ) + + term = [term for term in self.aedtapp.boundaries if term.type == "Terminal"][0] + assert self.aedtapp.boundaries[0].type == "Terminal" + term.name = "test" + assert term.name == "test" + term.props["TerminalResistance"] = "1ohm" + assert term.props["TerminalResistance"] == "1ohm" + assert not self.aedtapp.set_impedance_multiplier(2) + + def test_62_set_power_calc(self): + assert self.aedtapp.set_radiated_power_calc_method() + assert self.aedtapp.set_radiated_power_calc_method("Radiation Surface Integral") + assert self.aedtapp.set_radiated_power_calc_method("Far Field Integral") + + def test_63_set_phase_center_per_port(self): + self.aedtapp.insert_design("PhaseCenter") + self.aedtapp.solution_type = "Modal" + box1 = self.aedtapp.modeler.create_box([0, 0, 0], [10, 10, 5], "BoxWG1", "Copper") + box2 = self.aedtapp.modeler.create_box([0, 0, 10], [10, 10, 5], "BoxWG2", "copper") + box2.material_name = "Copper" + port = self.aedtapp.wave_port( + assignment="BoxWG1", + reference="BoxWG2", + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XNeg, + modes=1, + impedance=50, + name="Wave1", + renormalize=False, + ) + port2 = self.aedtapp.wave_port( + assignment="BoxWG1", + reference="BoxWG2", + create_port_sheet=True, + integration_line=self.aedtapp.AxisDir.XNeg, + modes=1, + impedance=50, + name="Wave2", + renormalize=False, + ) + if self.aedtapp.desktop_class.is_grpc_api: + assert self.aedtapp.set_phase_center_per_port() + assert self.aedtapp.set_phase_center_per_port(["Global", "Global"]) + else: + assert not self.aedtapp.set_phase_center_per_port() + assert not self.aedtapp.set_phase_center_per_port(["Global", "Global"]) + + assert not self.aedtapp.set_phase_center_per_port(["Global"]) + assert not self.aedtapp.set_phase_center_per_port("Global") + + @pytest.mark.skipif(config["NonGraphical"], reason="Test fails on build machine") + def test_64_import_dxf(self): + self.aedtapp.insert_design("dxf") + dxf_file = os.path.join( + local_path, "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", "cad", "DXF", "dxf2.dxf" + ) + dxf_layers = self.aedtapp.get_dxf_layers(dxf_file) + assert isinstance(dxf_layers, list) + assert self.aedtapp.import_dxf(dxf_file, dxf_layers) + + def test_65_component_array(self, add_app): + hfss_array = add_app(project_name=component_array, subfolder=test_subfolder) + assert len(hfss_array.component_array) == 1 + + array = hfss_array.component_array["A1"] + assert array.name == hfss_array.component_array_names[0] + + cell1 = array.get_cell(1, 1) + cell2 = array[1, 1] + assert cell2 + assert cell1.rotation == 0 + + assert not array.get_cell(0, 0) + assert not array.get_cell(10, 0) + + lc = array.lattice_vector() + assert len(lc) == 6 + + assert len(array.component_names) == 4 + + assert len(array.post_processing_cells) == 4 + post_cells = array.post_processing_cells + post_cells["Radome_Corner1"] = [8, 1] + array.post_processing_cells = post_cells + assert array.post_processing_cells["Radome_Corner1"] == [8, 1] + + array.cells[0][1].component = None + assert not array.cells[0][1].component + + array.cells[1][1].rotation = 90 + assert array.cells[1][1].rotation == 90 + + array.cells[1][1].rotation = 10 + assert not array.cells[1][1].rotation == 10 + + array.cells[1][1].is_active = False + array.cells[1][1].is_active = 1 + assert not array.cells[1][1].is_active + + assert array.cells[1][2].component == array.component_names[2] + assert not array.cells[1][2].component == "test" + + array.cells[0][1].component = array.component_names[3] + assert array.cells[0][1].component == array.component_names[3] + + hfss_array.component_array["A1"].name = "Array_new" + assert hfss_array.component_array_names[0] == "Array_new" + hfss_array.component_array["Array_new"].name = "A1" + + omodel = hfss_array.get_oo_object(hfss_array.odesign, "Model") + oarray = hfss_array.get_oo_object(omodel, "A1") + + assert array.visible + array.visible = False + assert not oarray.GetPropValue("Visible") + array.visible = True + assert oarray.GetPropValue("Visible") + + assert array.show_cell_number + array.show_cell_number = False + assert not oarray.GetPropValue("Show Cell Number") + array.show_cell_number = True + assert oarray.GetPropValue("Show Cell Number") + + assert array.render == "Shaded" + array.render = "Wireframe" + assert oarray.GetPropValue("Render") == "Wireframe" + array.render = "Shaded" + assert oarray.GetPropValue("Render") == "Shaded" + array.render = "Shaded1" + assert not array.render == "Shaded1" + + a_choices = array.a_vector_choices + assert array.a_vector_name in a_choices + array.a_vector_name = a_choices[0] + assert oarray.GetPropValue("A Vector") == a_choices[0] + array.a_vector_name = "Test" + assert not array.a_vector_name == "Test" + + b_choices = array.b_vector_choices + assert array.b_vector_name in b_choices + array.b_vector_name = b_choices[1] + assert oarray.GetPropValue("B Vector") == b_choices[1] + array.b_vector_name = "Test" + assert not array.b_vector_name == "Test" + + assert array.a_size == 8 + + assert array.b_size == 8 + + assert array.a_length == 0.64 + + assert array.b_length == 0.64 + + assert len(array.lattice_vector()) == 6 + + assert array.padding_cells == 0 + array.padding_cells = 2 + assert oarray.GetPropValue("Padding") == "2" + array.padding_cells = 0 + + assert array.coordinate_system == "Global" + array.coordinate_system = "Corner" + array.coordinate_system = "Global" + + array_csv = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "array_info.csv", + ) + array_info = array.parse_array_info_from_csv(array_csv) + assert len(array_info) == 4 + assert array_info["component"][1] == "02_Patch1" + + assert len(array.get_component_objects()) == 4 + + assert len(array.get_cell_position()) == array.a_size + + # Delete 3D Component + hfss_array.modeler.user_defined_components["03_Radome_Side1"].delete() + array.update_properties() + assert len(array.component_names) == 3 + assert len(array.post_processing_cells) == 3 + + array.delete() + assert not hfss_array.component_array + + def test_66_assign_febi(self, add_app): + aedtapp = add_app(project_name="test_66") + udp = aedtapp.modeler.Position(0, 0, 0) + coax_dimension = 200 + aedtapp.modeler.create_cylinder(aedtapp.AXIS.X, udp, 3, coax_dimension, 0, "inner") + aedtapp.modeler.create_cylinder(aedtapp.AXIS.X, udp, 10, coax_dimension, 0, "outer") + aedtapp.hybrid = True + assert aedtapp.assign_febi(["inner"]) + assert len(aedtapp.boundaries) == 1 + aedtapp.close_project(save_project=False) + + def test_67_transient_composite(self, add_app): + aedtapp = add_app(project_name="test_66") + aedtapp.solution_type = "Transient Composite" + assert aedtapp.solution_type == "Transient Composite" + aedtapp.close_project(save_project=False) + + @pytest.mark.skipif(config["NonGraphical"], reason="Test fails on build machine") + def test_68_import_gds_3d(self): + self.aedtapp.insert_design("gds_import_H3D") + gds_file = os.path.join( + local_path, "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", "cad", "GDS", "gds1.gds" + ) + assert self.aedtapp.import_gds_3d(gds_file, {7: (100, 10), 9: (110, 5)}) + assert self.aedtapp.import_gds_3d(gds_file, {7: (0, 0), 9: (0, 0)}) + assert self.aedtapp.import_gds_3d(gds_file, {7: (100e-3, 10e-3), 9: (110e-3, 5e-3)}, "mm", 0) + assert not self.aedtapp.import_gds_3d(gds_file, {}) + gds_file = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + "cad", + "GDS", + "gds1not.gds", + ) + assert not self.aedtapp.import_gds_3d(gds_file, {7: (100, 10), 9: (110, 5)}) From 3e84f54d983340144cf9d614aa224ada963a4af0 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Thu, 9 May 2024 09:56:36 +0200 Subject: [PATCH 17/29] Fix UT --- _unittest/test_20_HFSS.py | 84 +++++++-------------------------------- 1 file changed, 14 insertions(+), 70 deletions(-) diff --git a/_unittest/test_20_HFSS.py b/_unittest/test_20_HFSS.py index ba3f4ddaab1..bc7a6d1e34c 100644 --- a/_unittest/test_20_HFSS.py +++ b/_unittest/test_20_HFSS.py @@ -884,10 +884,7 @@ def test_30a_add_mesh_link(self): design=self.aedtapp.design_list[1], parameters=self.aedtapp.available_variations.nominal_w_values_dict ) example_project = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - diff_proj_name + ".aedt", + local_path, "../_unittest/example_models", test_subfolder, diff_proj_name + ".aedt" ) example_project_copy = os.path.join(self.local_scratch.path, diff_proj_name + "_copy.aedt") shutil.copyfile(example_project, example_project_copy) @@ -1187,9 +1184,7 @@ def test_46_mesh_settings(self): assert self.aedtapp.mesh.initial_mesh_settings.props def test_47_convert_near_field(self): - example_project = os.path.join( - local_path, "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", "nf_test" - ) + example_project = os.path.join(local_path, "../_unittest/example_models", "nf_test") assert os.path.exists(convert_nearfield_data(example_project, output_folder=self.local_scratch.path)) def test_48_traces(self): @@ -1255,34 +1250,18 @@ def test_51a_array(self): if config["desktopVersion"] > "2023.1": dict_in = read_json( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "array_simple_232.json", - ) + os.path.join(local_path, "../_unittest/example_models", test_subfolder, "array_simple_232.json") ) dict_in["Circ_Patch_5GHz_232_1"] = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - component, + local_path, "../_unittest/example_models", test_subfolder, component ) dict_in["cells"][(3, 3)] = {"name": "Circ_Patch_5GHz_232_1"} else: dict_in = read_json( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "array_simple.json", - ) + os.path.join(local_path, "../_unittest/example_models", test_subfolder, "array_simple.json") ) dict_in["Circ_Patch_5GHz1"] = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - component, + local_path, "../_unittest/example_models", test_subfolder, component ) dict_in["cells"][(3, 3)] = {"name": "Circ_Patch_5GHz1"} @@ -1319,18 +1298,8 @@ def test_52_crate_setup_hybrid_sbr(self, add_app): def test_53_import_source_excitation(self, add_app): aedtapp = add_app(solution_type="Modal", project_name="test_53") - freq_domain = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "S Parameter Table 1.csv", - ) - time_domain = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "Sinusoidal.csv", - ) + freq_domain = os.path.join(local_path, "../_unittest/example_models", test_subfolder, "S Parameter Table 1.csv") + time_domain = os.path.join(local_path, "../_unittest/example_models", test_subfolder, "Sinusoidal.csv") box1 = aedtapp.modeler.create_box([0, 0, 0], [10, 20, 20]) aedtapp.wave_port(assignment=box1.bottom_face_x, create_port_sheet=False, name="Port1") @@ -1427,18 +1396,8 @@ def test_58_create_near_field_line(self): def test_59_test_nastran(self): self.aedtapp.insert_design("Nas_teest") - example_project = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "test_cad.nas", - ) - example_project2 = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "test_cad_2.nas", - ) + example_project = os.path.join(local_path, "../_unittest/example_models", test_subfolder, "test_cad.nas") + example_project2 = os.path.join(local_path, "../_unittest/example_models", test_subfolder, "test_cad_2.nas") cads = self.aedtapp.modeler.import_nastran(example_project) assert len(cads) > 0 @@ -1522,9 +1481,7 @@ def test_63_set_phase_center_per_port(self): @pytest.mark.skipif(config["NonGraphical"], reason="Test fails on build machine") def test_64_import_dxf(self): self.aedtapp.insert_design("dxf") - dxf_file = os.path.join( - local_path, "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", "cad", "DXF", "dxf2.dxf" - ) + dxf_file = os.path.join(local_path, "example_models", "cad", "DXF", "dxf2.dxf") dxf_layers = self.aedtapp.get_dxf_layers(dxf_file) assert isinstance(dxf_layers, list) assert self.aedtapp.import_dxf(dxf_file, dxf_layers) @@ -1634,12 +1591,7 @@ def test_65_component_array(self, add_app): array.coordinate_system = "Corner" array.coordinate_system = "Global" - array_csv = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "array_info.csv", - ) + array_csv = os.path.join(local_path, "../_unittest/example_models", test_subfolder, "array_info.csv") array_info = array.parse_array_info_from_csv(array_csv) assert len(array_info) == 4 assert array_info["component"][1] == "02_Patch1" @@ -1677,18 +1629,10 @@ def test_67_transient_composite(self, add_app): @pytest.mark.skipif(config["NonGraphical"], reason="Test fails on build machine") def test_68_import_gds_3d(self): self.aedtapp.insert_design("gds_import_H3D") - gds_file = os.path.join( - local_path, "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", "cad", "GDS", "gds1.gds" - ) + gds_file = os.path.join(local_path, "example_models", "cad", "GDS", "gds1.gds") assert self.aedtapp.import_gds_3d(gds_file, {7: (100, 10), 9: (110, 5)}) assert self.aedtapp.import_gds_3d(gds_file, {7: (0, 0), 9: (0, 0)}) assert self.aedtapp.import_gds_3d(gds_file, {7: (100e-3, 10e-3), 9: (110e-3, 5e-3)}, "mm", 0) assert not self.aedtapp.import_gds_3d(gds_file, {}) - gds_file = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - "cad", - "GDS", - "gds1not.gds", - ) + gds_file = os.path.join(local_path, "example_models", "cad", "GDS", "gds1not.gds") assert not self.aedtapp.import_gds_3d(gds_file, {7: (100, 10), 9: (110, 5)}) From e31a33ace5607262fdf75414d5e4a1d4f1a22eba Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Thu, 9 May 2024 14:59:36 +0200 Subject: [PATCH 18/29] Fix UT --- _unittest/test_12_PostProcessing.py | 1026 +++++++++++++++++++++++++++ 1 file changed, 1026 insertions(+) create mode 100644 _unittest/test_12_PostProcessing.py diff --git a/_unittest/test_12_PostProcessing.py b/_unittest/test_12_PostProcessing.py new file mode 100644 index 00000000000..1712bd9d95f --- /dev/null +++ b/_unittest/test_12_PostProcessing.py @@ -0,0 +1,1026 @@ +import os +import sys + +from _unittest.conftest import config +import pytest + +from pyaedt import Circuit +from pyaedt import Icepak +from pyaedt import Maxwell2d +from pyaedt import Q2d +from pyaedt import Q3d +from pyaedt.generic.general_methods import is_linux +from pyaedt.generic.pdf import AnsysReport +from pyaedt.generic.plot import _parse_aedtplt +from pyaedt.generic.plot import _parse_streamline +from pyaedt.generic.settings import settings +from pyaedt.modules.solutions import FfdSolutionData + +if config["desktopVersion"] > "2022.2": + test_field_name = "Potter_Horn_231" + test_project_name = "coax_setup_solved_231" + array = "array_simple_231" + sbr_file = "poc_scat_small_231" + q3d_file = "via_gsg_231" + m2d_file = "m2d_field_lines_test_231" + +else: + test_field_name = "Potter_Horn" + test_project_name = "coax_setup_solved" + array = "array_simple" + sbr_file = "poc_scat_small" + q3d_file = "via_gsg" + m2d_file = "m2d_field_lines_test" + +test_circuit_name = "Switching_Speed_FET_And_Diode" +test_emi_name = "EMI_RCV_241" +eye_diagram = "SimpleChannel" +ami = "ami" +ipk_post_proj = "for_icepak_post" +test_subfolder = "T12" +settings.enable_pandas_output = True + + +@pytest.fixture(scope="class") +def field_test(add_app): + app = add_app(project_name=test_field_name, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def circuit_test(add_app): + app = add_app(project_name=test_circuit_name, design_name="Diode", application=Circuit, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def emi_receiver_test(add_app): + app = add_app(project_name=test_emi_name, design_name="CE_band", application=Circuit, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def diff_test(add_app, circuit_test): + app = add_app(project_name=circuit_test.project_name, design_name="diff", application=Circuit, just_open=True) + return app + + +@pytest.fixture(scope="class") +def sbr_test(add_app): + app = add_app(project_name=sbr_file, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def q3dtest(add_app): + app = add_app(project_name=q3d_file, application=Q3d, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def q2dtest(add_app, q3dtest): + app = add_app(project_name=q3dtest.project_name, application=Q2d, just_open=True) + return app + + +@pytest.fixture(scope="class") +def eye_test(add_app, q3dtest): + app = add_app(project_name=eye_diagram, application=Circuit, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def icepak_post(add_app): + app = add_app(project_name=ipk_post_proj, application=Icepak, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def ami_test(add_app, q3dtest): + app = add_app(project_name=ami, application=Circuit, subfolder=test_subfolder) + return app + + +@pytest.fixture(scope="class") +def array_test(add_app, q3dtest): + app = add_app(project_name=array, subfolder=test_subfolder, solution_type="Modal") + return app + + +@pytest.fixture(scope="class") +def m2dtest(add_app, q3dtest): + app = add_app(project_name=m2d_file, application=Maxwell2d, subfolder=test_subfolder) + return app + + +class TestClass: + @pytest.fixture(autouse=True) + def init(self, local_scratch): + self.local_scratch = local_scratch + + def test_09_manipulate_report(self, field_test): + variations = field_test.available_variations.nominal_w_values_dict + variations["Theta"] = ["All"] + variations["Phi"] = ["All"] + variations["Freq"] = ["30GHz"] + field_test.set_source_context(["1"]) + context = {"Context": "3D", "SourceContext": "1:1"} + assert field_test.post.create_report( + "db(GainTotal)", + field_test.nominal_adaptive, + variations=variations, + primary_sweep_variable="Phi", + secondary_sweep_variable="Theta", + report_category="Far Fields", + plot_type="3D Polar Plot", + context=context, + ) + assert field_test.post.create_report( + "db(GainTotal)", + field_test.nominal_adaptive, + variations=variations, + primary_sweep_variable="Phi", + secondary_sweep_variable="Theta", + report_category="Far Fields", + plot_type="3D Polar Plot", + context="3D", + ) + report = AnsysReport() + report.create() + assert report.add_project_info(field_test) + + def test_09_manipulate_report_B(self, field_test): + variations = field_test.available_variations.nominal_w_values_dict + variations["Theta"] = ["All"] + variations["Phi"] = ["All"] + variations["Freq"] = ["30GHz"] + new_report = field_test.post.reports_by_category.far_field("db(RealizedGainTotal)", field_test.nominal_adaptive) + new_report.variations = variations + new_report.report_type = "3D Polar Plot" + new_report.far_field_sphere = "3D" + assert new_report.create() + + new_report2 = field_test.post.reports_by_category.far_field( + "db(RealizedGainTotal)", field_test.nominal_adaptive, "3D", "1:1" + ) + new_report2.variations = variations + new_report2.report_type = "3D Polar Plot" + assert new_report2.create() + + new_report3 = field_test.post.reports_by_category.antenna_parameters( + "db(PeakRealizedGain)", field_test.nominal_adaptive, "3D" + ) + new_report3.report_type = "Data Table" + assert new_report3.create() + new_report4 = field_test.post.reports_by_category.antenna_parameters( + "db(PeakRealizedGain)", infinite_sphere="3D" + ) + new_report4.report_type = "Data Table" + assert new_report4.create() + + def test_09_manipulate_report_C(self, field_test): + variations = field_test.available_variations.nominal_w_values_dict + variations["Theta"] = ["All"] + variations["Phi"] = ["All"] + variations["Freq"] = ["30GHz"] + field_test.analyze(field_test.active_setup) + data = field_test.post.get_solution_data( + "GainTotal", + field_test.nominal_adaptive, + variations=variations, + primary_sweep_variable="Theta", + report_category="Far Fields", + context="3D", + ) + assert data.plot(is_polar=True) + assert data.plot_3d() + assert field_test.post.create_3d_plot(data) + + def test_09_manipulate_report_D(self, field_test): + variations = field_test.available_variations.nominal_w_values_dict + variations["Theta"] = ["All"] + variations["Phi"] = ["All"] + variations["Freq"] = ["30GHz"] + context = {"Context": "3D", "SourceContext": "1:1"} + data = field_test.post.get_solution_data( + "GainTotal", + field_test.nominal_adaptive, + variations=variations, + primary_sweep_variable="Theta", + report_category="Far Fields", + context=context, + ) + assert data.plot(is_polar=True) + assert data.plot_3d() + assert field_test.post.create_3d_plot(data) + assert data.primary_sweep == "Theta" + assert len(data.data_magnitude("GainTotal")) > 0 + assert not data.data_magnitude("GainTotal2") + assert field_test.post.create_report( + "S(1,1)", field_test.nominal_sweep, variations=variations, plot_type="Smith Chart" + ) + + def test_09_manipulate_report_E(self, field_test): + field_test.modeler.create_polyline([[0, 0, 0], [0, 5, 30]], name="Poly1", non_model=True) + variations2 = field_test.available_variations.nominal_w_values_dict + + assert field_test.setups[0].create_report( + "Mag_E", primary_sweep_variable="Distance", report_category="Fields", context="Poly1" + ) + new_report = field_test.post.reports_by_category.fields("Mag_H", field_test.nominal_adaptive) + new_report.variations = variations2 + new_report.polyline = "Poly1" + assert new_report.create() + new_report = field_test.post.reports_by_category.fields("Mag_H") + new_report.variations = variations2 + new_report.polyline = "Poly1" + assert new_report.create() + new_report = field_test.post.reports_by_category.modal_solution("S(1,1)") + new_report.report_type = "Smith Chart" + assert new_report.create() + data = field_test.setups[0].get_solution_data( + "Mag_E", variations=variations2, primary_sweep_variable="Theta", report_category="Fields", context="Poly1" + ) + assert data.units_sweeps["Phase"] == "deg" + + assert field_test.post.get_far_field_data( + expressions="RealizedGainTotal", setup_sweep_name=field_test.nominal_adaptive, domain="3D" + ) + data_farfield2 = field_test.post.get_far_field_data( + expressions="RealizedGainTotal", + setup_sweep_name=field_test.nominal_adaptive, + domain={"Context": "3D", "SourceContext": "1:1"}, + ) + assert data_farfield2.plot(formula="db20", is_polar=True) + + assert field_test.post.reports_by_category.terminal_solution() + + assert not field_test.post.get_solution_data_per_variation( + solution_type="Far Fields", expressions="RealizedGainTotal" + ) + + def test_09b_export_report_A(self, circuit_test): + files = circuit_test.export_results() + assert len(files) > 0 + report = AnsysReport() + report.create() + assert report.add_project_info(circuit_test) + + def test_09b_export_report_B(self, q2dtest): + q2dtest.analyze() + files = q2dtest.export_results() + assert len(files) > 0 + + def test_09b_export_report_C(self, q3dtest): + q3dtest.analyze_setup("Setup1") + files = q3dtest.export_results() + assert len(files) > 0 + + @pytest.mark.skipif(is_linux, reason="Crashing on Linux") + def test_17_circuit(self, circuit_test): + assert not circuit_test.setups[0].is_solved + + circuit_test.analyze_setup("LNA") + circuit_test.analyze_setup("Transient") + assert circuit_test.setups[0].is_solved + assert circuit_test.setups[0].create_report(["dB(S(Port1, Port1))", "dB(S(Port1, Port2))"]) + new_report = circuit_test.post.reports_by_category.standard( + ["dB(S(Port1, Port1))", "dB(S(Port1, Port2))"], "LNA" + ) + assert new_report.create() + data1 = circuit_test.post.get_solution_data(["dB(S(Port1,Port1))", "dB(S(Port1,Port2))"], "LNA") + assert data1.primary_sweep == "Freq" + assert circuit_test.post.create_report(["V(net_11)"], "Transient", "Time") + data11 = circuit_test.post.get_solution_data(setup_sweep_name="LNA", math_formula="dB") + assert data11.primary_sweep == "Freq" + assert "dB(S(Port2,Port1))" in data11.expressions + assert circuit_test.post.create_report(["V(net_11)"], "Transient", "Time") + new_report = circuit_test.post.reports_by_category.standard(["V(net_11)"], "Transient") + new_report.domain = "Time" + assert new_report.create() + data2 = circuit_test.post.get_solution_data(["V(net_11)"], "Transient", "Time") + assert data2.primary_sweep == "Time" + assert len(data2.data_magnitude()) > 0 + context = {"algorithm": "FFT", "max_frequency": "100MHz", "time_stop": "200ns", "test": ""} + data3 = circuit_test.post.get_solution_data(["V(net_11)"], "Transient", "Spectral", context=context) + assert data3.units_sweeps["Spectrum"] == circuit_test.odesktop.GetDefaultUnit("Frequency") + assert len(data3.data_real()) > 0 + new_report = circuit_test.post.reports_by_category.spectral(["dB(V(net_11))"], "Transient") + new_report.window = "Hanning" + new_report.max_freq = "1GHz" + new_report.time_start = "1ns" + new_report.time_stop = "190ns" + new_report.plot_continous_spectrum = True + assert new_report.create() + new_report = circuit_test.post.reports_by_category.spectral(["dB(V(net_11))"]) + assert new_report.create() + new_report = circuit_test.post.reports_by_category.spectral(["dB(V(net_11))", "dB(V(Port1))"], "Transient") + new_report.window = "Kaiser" + new_report.adjust_coherent_gain = False + new_report.kaiser_coeff = 2 + new_report.algorithm = "Fourier Transform" + new_report.max_freq = "1GHz" + new_report.time_start = "1ns" + new_report.time_stop = "190ns" + new_report.plot_continous_spectrum = False + assert new_report.create() + assert circuit_test.post.create_report(["dB(V(net_11))", "dB(V(Port1))"], domain="Spectrum") + new_report = circuit_test.post.reports_by_category.spectral(None, "Transient") + new_report.window = "Hanning" + new_report.max_freq = "1GHz" + new_report.time_start = "1ns" + new_report.time_stop = "190ns" + new_report.plot_continous_spectrum = True + assert new_report.create() + + @pytest.mark.skipif(is_linux, reason="Crashing on Linux") + def test_18_diff_plot(self, diff_test): + assert len(diff_test.post.available_display_types()) > 0 + assert len(diff_test.post.available_report_types) > 0 + assert len(diff_test.post.available_report_quantities()) > 0 + assert len(diff_test.post.available_report_solutions()) > 0 + diff_test.analyze_setup("LinearFrequency") + assert diff_test.setups[0].is_solved + variations = diff_test.available_variations.nominal_w_values_dict + variations["Freq"] = ["All"] + variations["l1"] = ["All"] + assert diff_test.post.create_report( + ["dB(S(Diff1, Diff1))"], + "LinearFrequency", + variations=variations, + primary_sweep_variable="l1", + context="Differential Pairs", + ) + new_report1 = diff_test.post.reports_by_category.standard() + assert new_report1.expressions + new_report = diff_test.post.reports_by_category.standard("dB(S(1,1))") + new_report.differential_pairs = True + assert new_report.create() + assert new_report.get_solution_data() + new_report2 = diff_test.post.reports_by_category.standard("TDRZ(1)") + new_report2.differential_pairs = True + new_report2.pulse_rise_time = 3e-12 + new_report2.time_windowing = 3 + new_report2.domain = "Time" + + assert new_report2.create() + + data1 = diff_test.post.get_solution_data( + ["S(Diff1, Diff1)"], + "LinearFrequency", + variations=variations, + primary_sweep_variable="Freq", + context="Differential Pairs", + ) + assert data1.primary_sweep == "Freq" + data1.plot(formula="db20", snapshot_path=os.path.join(self.local_scratch.path, "temp1.jpg")) + data1.primary_sweep = "l1" + assert data1.primary_sweep == "l1" + assert len(data1.data_magnitude()) == 5 + assert data1.plot("S(Diff1, Diff1)", snapshot_path=os.path.join(self.local_scratch.path, "temp2.jpg")) + assert data1.plot(formula="db20", snapshot_path=os.path.join(self.local_scratch.path, "temp3.jpg")) + assert data1.plot(formula="db10", snapshot_path=os.path.join(self.local_scratch.path, "temp4.jpg")) + assert data1.plot(formula="mag", snapshot_path=os.path.join(self.local_scratch.path, "temp5.jpg")) + assert data1.plot(formula="re", snapshot_path=os.path.join(self.local_scratch.path, "temp6.jpg")) + assert data1.plot(formula="im", snapshot_path=os.path.join(self.local_scratch.path, "temp7.jpg")) + assert data1.plot(formula="phasedeg", snapshot_path=os.path.join(self.local_scratch.path, "temp8.jpg")) + assert data1.plot(formula="phaserad", snapshot_path=os.path.join(self.local_scratch.path, "temp9.jpg")) + + assert diff_test.create_touchstone_report( + name="Diff_plot", curves=["dB(S(Diff1, Diff1))"], solution="LinearFrequency", differential_pairs=True + ) + + @pytest.mark.skipif(is_linux, reason="Failing on Linux") + def test_51_get_efields(self, field_test): + assert field_test.post.get_efields_data(ff_setup="3D") + + @pytest.mark.skipif( + is_linux or sys.version_info < (3, 8), reason="plot_scene method is not supported in ironpython" + ) + def test_55_time_plot(self, sbr_test): + sbr_test.analyze(sbr_test.active_setup, use_auto_settings=False) + assert sbr_test.setups[0].is_solved + solution_data = sbr_test.post.get_solution_data( + expressions=["NearEX", "NearEY", "NearEZ"], report_category="Near Fields", context="Near_Field" + ) + assert solution_data + assert len(solution_data.primary_sweep_values) > 0 + assert len(solution_data.primary_sweep_variations) > 0 + assert solution_data.set_active_variation(0) + assert not solution_data.set_active_variation(99) + t_matrix = solution_data.ifft("NearE", window=True) + assert t_matrix.any() + frames_list = solution_data.ifft_to_file( + coord_system_center=[-0.15, 0, 0], db_val=True, csv_path=os.path.join(sbr_test.working_directory, "csv") + ) + assert os.path.exists(frames_list) + sbr_test.post.plot_scene( + frames_list, os.path.join(sbr_test.working_directory, "animation.gif"), norm_index=5, dy_rng=35, show=False + ) + assert os.path.exists(os.path.join(sbr_test.working_directory, "animation.gif")) + sbr_test.post.plot_scene( + frames_list, + os.path.join(sbr_test.working_directory, "animation2.gif"), + norm_index=5, + dy_rng=35, + show=False, + convert_fields_in_db=True, + log_multiplier=20.0, + ) + assert os.path.exists(os.path.join(sbr_test.working_directory, "animation2.gif")) + + def test_56_test_export_q3d_results(self, q3dtest): + q3dtest.analyze(q3dtest.active_setup) + assert os.path.exists(q3dtest.export_convergence("Setup1")) + assert os.path.exists(q3dtest.export_profile("Setup1")) + new_report = q3dtest.post.reports_by_category.standard(q3dtest.get_traces_for_plot()) + assert new_report.create() + q3dtest.modeler.create_polyline([[0, -5, 0.425], [0.5, 5, 0.5]], name="Poly1", non_model=True) + new_report = q3dtest.post.reports_by_category.cg_fields("SmoothQ", polyline="Poly1") + assert new_report.create() + new_report = q3dtest.post.reports_by_category.rl_fields("Mag_SurfaceJac", polyline="Poly1") + assert new_report.create() + new_report = q3dtest.post.reports_by_category.dc_fields("Mag_VolumeJdc", polyline="Poly1") + assert new_report.create() + assert len(q3dtest.post.plots) == 6 + + def test_57_test_export_q2d_results(self, q2dtest): + q2dtest.analyze(q2dtest.active_setup) + assert os.path.exists(q2dtest.export_convergence("Setup1")) + assert os.path.exists(q2dtest.export_profile("Setup1")) + new_report = q2dtest.post.reports_by_category.standard(q2dtest.get_traces_for_plot()) + assert new_report.create() + q2dtest.modeler.create_polyline([[-1.9, -0.1, 0], [-1.2, -0.2, 0]], name="Poly1", non_model=True) + new_report = q2dtest.post.reports_by_category.cg_fields("Mag_E", polyline="Poly1") + assert new_report.create() + new_report = q2dtest.post.reports_by_category.rl_fields("Mag_H", polyline="Poly1") + assert new_report.create() + sol = new_report.get_solution_data() + sol.enable_pandas_output = True + data = sol.full_matrix_real_imag + data_mag = sol.full_matrix_mag_phase + sol.data_magnitude() + sol.enable_pandas_output = False + assert len(q2dtest.post.plots) == 3 + new_report = q2dtest.post.reports_by_category.standard() + assert new_report.get_solution_data() + + def test_58_test_no_report(self, q3dtest): + assert not q3dtest.post.reports_by_category.modal_solution() + assert not q3dtest.post.reports_by_category.terminal_solution() + + def test_58_test_no_report_B(self, q2dtest): + assert not q2dtest.post.reports_by_category.far_field() + assert not q2dtest.post.reports_by_category.near_field() + assert not q2dtest.post.reports_by_category.eigenmode() + + def test_59_test_parse_vector(self): + local_path = os.path.dirname(os.path.realpath(__file__)) + + out = _parse_aedtplt( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "test_vector.aedtplt", + ) + ) + assert isinstance(out[0], list) + assert isinstance(out[1], list) + assert isinstance(out[2], list) + assert isinstance(out[3], bool) + assert _parse_aedtplt( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "test_vector_no_solutions.aedtplt", + ) + ) + + def test_60_test_parse_vector(self): + local_path = os.path.dirname(os.path.realpath(__file__)) + out = _parse_streamline( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "test_streamline.fldplt", + ) + ) + assert isinstance(out, list) + + def test_61_export_mesh(self, q3dtest): + assert os.path.exists(q3dtest.export_mesh_stats("Setup1")) + assert os.path.exists(q3dtest.export_mesh_stats("Setup1", setup_type="AC RL")) + + def test_62_eye_diagram(self, eye_test): + eye_test.analyze(eye_test.active_setup) + rep = eye_test.post.reports_by_category.eye_diagram("AEYEPROBE(OutputEye)", "QuickEyeAnalysis") + rep.time_start = "0ps" + rep.time_stop = "50us" + rep.unit_interval = "1e-9" + assert rep.create() + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" + ) + def test_63_mask(self, eye_test): + eye_test.analyze(eye_test.active_setup) + rep = eye_test.post.reports_by_category.eye_diagram("AEYEPROBE(OutputEye)", "QuickEyeAnalysis") + rep.time_start = "0ps" + rep.time_stop = "50us" + rep.unit_interval = "1e-9" + rep.create() + assert rep.eye_mask([[0.5, 0], [0.62, 450], [1.2, 450], [1.42, 0], [1.2, -450], [0.62, -450], [0.5, 0]]) + assert rep.eye_mask( + [[0.5, 0], [0.62, 450], [1.2, 450], [1.42, 0], [1.2, -450], [0.62, -450], [0.5, 0]], + enable_limits=True, + upper_limit=800, + lower_limit=-800, + ) + assert os.path.exists(rep.export_mask_violation()) + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" + ) + def test_64_eye_meas(self, eye_test): + eye_test.analyze(eye_test.active_setup) + rep = eye_test.post.reports_by_category.eye_diagram("AEYEPROBE(OutputEye)", "QuickEyeAnalysis") + rep.time_start = "0ps" + rep.time_stop = "50us" + rep.unit_interval = "1e-9" + rep.create() + assert rep.add_all_eye_measurements() + assert rep.clear_all_eye_measurements() + assert rep.add_trace_characteristics("MinEyeHeight") + + def test_65_eye_from_json(self, eye_test): + local_path = os.path.dirname(os.path.realpath(__file__)) + assert eye_test.post.create_report_from_configuration( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + "report_json", + "EyeDiagram_Report_simple.json", + ), + solution_name="QuickEyeAnalysis", + ) + + def test_66_spectral_from_json(self, circuit_test): + local_path = os.path.dirname(os.path.realpath(__file__)) + circuit_test.analyze_setup("Transient") + assert circuit_test.post.create_report_from_configuration( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + "report_json", + "Spectral_Report_Simple.json", + ), + solution_name="Transient", + ) + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" + ) + def test_68_eye_from_json(self, eye_test): + local_path = os.path.dirname(os.path.realpath(__file__)) + assert eye_test.post.create_report_from_configuration( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + "report_json", + "EyeDiagram_Report.toml", + ), + solution_name="QuickEyeAnalysis", + ) + + @pytest.mark.skipif( + config["desktopVersion"] < "2022.2", reason="Not working in non graphical in version lower than 2022.2" + ) + def test_69_spectral_from_json(self, circuit_test): + local_path = os.path.dirname(os.path.realpath(__file__)) + circuit_test.analyze_setup("Transient") + assert circuit_test.post.create_report_from_configuration( + os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + "report_json", + "Spectral_Report.json", + ), + solution_name="Transient", + ) + + def test_70_far_field_data(self): + local_path = os.path.dirname(os.path.realpath(__file__)) + eep_file1 = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "eep", + "eep.txt", + ) + eep_file2 = os.path.join( + local_path, + "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", + test_subfolder, + "eep", + "eep.txt", + ) + frequencies = [0.9e9, "0.9GHz"] + eep_files = [eep_file1, eep_file2] + + ffdata = FfdSolutionData(frequencies=frequencies[1], eep_files=eep_file1) + assert len(ffdata.frequencies) == 1 + + ffdata = FfdSolutionData(frequencies=frequencies, eep_files=eep_files) + assert len(ffdata.frequencies) == 2 + farfield = ffdata.combine_farfield() + assert "rETheta" in farfield + + ffdata.taper = "cosine" + assert ffdata.combine_farfield() + ffdata.taper = "taper" + assert not ffdata.taper == "taper" + + ffdata.origin = [0, 2] + assert ffdata.origin != [0, 2] + ffdata.origin = [0, 0, 1] + assert ffdata.origin == [0, 0, 1] + + img1 = os.path.join(self.local_scratch.path, "ff_2d1.jpg") + ffdata.plot_2d_cut(primary_sweep="Theta", secondary_sweep_value="all", image_path=img1) + assert os.path.exists(img1) + img2 = os.path.join(self.local_scratch.path, "ff_2d2.jpg") + ffdata.plot_2d_cut(secondary_sweep_value=[0, 1], image_path=img2) + assert os.path.exists(img2) + img3 = os.path.join(self.local_scratch.path, "ff_2d2.jpg") + ffdata.plot_2d_cut(image_path=img3) + assert os.path.exists(img3) + curve_2d = ffdata.plot_2d_cut(show=False) + assert len(curve_2d[0]) == 3 + data = ffdata.polar_plot_3d(show=False) + assert len(data) == 3 + + img4 = os.path.join(self.local_scratch.path, "ff_3d1.jpg") + ffdata.polar_plot_3d_pyvista( + quantity="RealizedGain", + image_path=img4, + show=False, + background=[255, 0, 0], + show_geometry=False, + convert_to_db=True, + ) + assert os.path.exists(img4) + data_pyvista = ffdata.polar_plot_3d_pyvista( + quantity="RealizedGain", show=False, background=[255, 0, 0], show_geometry=False, convert_to_db=True + ) + assert data_pyvista + + @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="FarFieldSolution not supported by IronPython") + def test_71_antenna_plot(self, field_test): + ffdata = field_test.get_antenna_ffd_solution_data(frequencies=30e9, sphere="3D") + ffdata.phase_offset = [0, 90] + assert ffdata.phase_offset == [0, 90] + ffdata.phase_offset = [0] + assert ffdata.phase_offset != [0.0] + assert ffdata.plot_farfield_contour( + quantity="RealizedGain", + title="Contour at {}Hz".format(ffdata.frequency), + image_path=os.path.join(self.local_scratch.path, "contour.jpg"), + convert_to_db=True, + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "contour.jpg")) + + ffdata.plot_2d_cut( + quantity="RealizedGain", + primary_sweep="theta", + secondary_sweep_value=[-180, -75, 75], + title="Azimuth at {}Hz".format(ffdata.frequency), + image_path=os.path.join(self.local_scratch.path, "2d1.jpg"), + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "2d1.jpg")) + ffdata.plot_2d_cut( + quantity="RealizedGain", + primary_sweep="phi", + secondary_sweep_value=30, + title="Azimuth at {}Hz".format(ffdata.frequency), + image_path=os.path.join(self.local_scratch.path, "2d2.jpg"), + ) + + assert os.path.exists(os.path.join(self.local_scratch.path, "2d2.jpg")) + + ffdata.polar_plot_3d( + quantity="RealizedGain", image_path=os.path.join(self.local_scratch.path, "3d1.jpg"), convert_to_db=True + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "3d1.jpg")) + + ffdata.polar_plot_3d_pyvista( + quantity="RealizedGain", + image_path=os.path.join(self.local_scratch.path, "3d2.jpg"), + show=False, + convert_to_db=True, + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "3d2.jpg")) + + try: + p = ffdata.polar_plot_3d_pyvista(quantity="RealizedGain", show=False, convert_to_db=True) + assert isinstance(p, object) + except Exception: + assert True + + @pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="FarFieldSolution not supported by IronPython") + def test_72_antenna_plot(self, array_test): + ffdata = array_test.get_antenna_ffd_solution_data(frequencies=3.5e9, sphere="3D") + ffdata.frequency = 3.5e9 + assert ffdata.plot_farfield_contour( + quantity="RealizedGain", + title="Contour at {}Hz".format(ffdata.frequency), + image_path=os.path.join(self.local_scratch.path, "contour.jpg"), + convert_to_db=True, + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "contour.jpg")) + + ffdata.plot_2d_cut( + quantity="RealizedGain", + primary_sweep="theta", + secondary_sweep_value=[-180, -75, 75], + title="Azimuth at {}Hz".format(ffdata.frequency), + image_path=os.path.join(self.local_scratch.path, "2d1.jpg"), + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "2d1.jpg")) + ffdata.plot_2d_cut( + quantity="RealizedGain", + primary_sweep="phi", + secondary_sweep_value=30, + title="Azimuth at {}Hz".format(ffdata.frequency), + image_path=os.path.join(self.local_scratch.path, "2d2.jpg"), + ) + + assert os.path.exists(os.path.join(self.local_scratch.path, "2d2.jpg")) + + ffdata.polar_plot_3d( + quantity="RealizedGain", image_path=os.path.join(self.local_scratch.path, "3d1.jpg"), convert_to_db=True + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "3d1.jpg")) + + ffdata.polar_plot_3d_pyvista( + quantity="RealizedGain", + image_path=os.path.join(self.local_scratch.path, "3d2.jpg"), + show=False, + convert_to_db=True, + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "3d2.jpg")) + ffdata1 = array_test.get_antenna_ffd_solution_data(frequencies=3.5e9, sphere="3D", overwrite=False) + assert ffdata1.plot_farfield_contour( + quantity="RealizedGain", + title="Contour at {}Hz".format(ffdata1.frequency), + image_path=os.path.join(self.local_scratch.path, "contour1.jpg"), + convert_to_db=True, + ) + assert os.path.exists(os.path.join(self.local_scratch.path, "contour1.jpg")) + + def test_73_ami_solution_data(self, ami_test): + ami_test.solution_type = "NexximAMI" + assert ami_test.post.get_solution_data( + expressions="WaveAfterProbe", + domain="Time", + variations=ami_test.available_variations.nominal, + ) + + assert ami_test.post.get_solution_data( + expressions="WaveAfterSource", + domain="Time", + variations=ami_test.available_variations.nominal, + ) + + assert ami_test.post.get_solution_data( + expressions="InitialWave", + domain="Time", + variations=ami_test.available_variations.nominal, + ) + + assert ami_test.post.get_solution_data( + expressions="WaveAfterChannel", + domain="Time", + variations=ami_test.available_variations.nominal, + ) + + assert ami_test.post.get_solution_data( + expressions="ClockTics", + domain="Clock Times", + variations=ami_test.available_variations.nominal, + ) + probe_name = "b_input_43" + source_name = "b_output4_42" + plot_type = "WaveAfterProbe" + setup_name = "AMIAnalysis" + + ignore_bits = 1000 + unit_interval = 0.1e-9 + assert not ami_test.post.sample_ami_waveform( + setup_name, + probe_name, + source_name, + ami_test.available_variations.nominal, + unit_interval, + ignore_bits, + plot_type, + ) + ignore_bits = 5 + unit_interval = 0.1e-9 + plot_type = "InitialWave" + data1 = ami_test.post.sample_ami_waveform( + setup_name, + probe_name, + source_name, + ami_test.available_variations.nominal, + unit_interval, + ignore_bits, + plot_type, + ) + assert len(data1[0]) == 45 + + settings.enable_pandas_output = False + ignore_bits = 5 + unit_interval = 0.1e-9 + clock_tics = [1e-9, 2e-9, 3e-9] + data2 = ami_test.post.sample_ami_waveform( + setup_name, + probe_name, + source_name, + ami_test.available_variations.nominal, + unit_interval, + ignore_bits, + plot_type=None, + clock_tics=clock_tics, + ) + assert len(data2) == 4 + assert len(data2[0]) == 3 + + def test_75_plot_field_line_traces(self, m2dtest): + m2dtest.modeler.model_units = "mm" + rect = m2dtest.modeler.create_rectangle( + origin=["1mm", "5mm", "0mm"], sizes=["-1mm", "-10mm", 0], name="Ground", material="copper" + ) + rect.solve_inside = False + circle = m2dtest.modeler.create_circle( + position=["-10mm", "0", "0"], + radius="1mm", + num_sides="0", + is_covered=True, + name="Electrode", + material="copper", + ) + circle.solve_inside = False + m2dtest.modeler.create_region([20, 100, 20, 100]) + assert not m2dtest.post.create_fieldplot_line_traces("Ground", "Region", "Ground", plot_name="LineTracesTest") + m2dtest.solution_type = "Electrostatic" + assert not m2dtest.post.create_fieldplot_line_traces("Invalid", "Region", "Ground", plot_name="LineTracesTest1") + assert not m2dtest.post.create_fieldplot_line_traces("Ground", "Invalid", "Ground", plot_name="LineTracesTest2") + assert not m2dtest.post.create_fieldplot_line_traces("Ground", "Region", "Invalid", plot_name="LineTracesTest3") + m2dtest.assign_voltage(rect.name, amplitude=0, name="Ground") + m2dtest.assign_voltage(circle.name, amplitude=50e6, name="50kV") + setup_name = "test" + m2dtest.create_setup(name=setup_name) + m2dtest.analyze_setup(setup_name) + plot = m2dtest.post.create_fieldplot_line_traces(["Ground", "Electrode"], "Region", plot_name="LineTracesTest4") + assert plot + assert m2dtest.post.create_fieldplot_line_traces( + ["Ground", "Electrode"], "Region", "Ground", plot_name="LineTracesTest5" + ) + assert m2dtest.post.create_fieldplot_line_traces(["Ground", "Electrode"], plot_name="LineTracesTest6") + assert not m2dtest.post.create_fieldplot_line_traces( + ["Ground", "Electrode"], "Region", ["Invalid"], plot_name="LineTracesTest7" + ) + assert not m2dtest.post.create_fieldplot_line_traces( + ["Ground", "Electrode"], ["Invalid"], plot_name="LineTracesTest8" + ) + plot.TraceStepLength = "0.002mm" + plot.SeedingPointsNumber = 20 + plot.LineStyle = "Cylinder" + plot.LineWidth = 3 + assert plot.update() + el_id = [obj.id for obj in m2dtest.modeler.object_list if obj.name == "Electrode"] + plot.seeding_faces.append(el_id[0]) + assert plot.update() + plot.volumes.append(el_id[0]) + plot.update() + plot.surfaces.append(el_id[0]) + plot.update() + plot.seeding_faces.append(8) + assert not plot.update() + plot.volumes.append(8) + assert not plot.update() + plot.surfaces.append(8) + assert not plot.update() + + @pytest.mark.skipif(config["desktopVersion"] < "2024.1", reason="EMI receiver available from 2024R1.") + def test_76_emi_receiver(self, emi_receiver_test): + emi_receiver_test.analyze() + new_report = emi_receiver_test.post.reports_by_category.emi_receiver() + new_report.band = "2" + new_report.emission = "RE" + new_report.time_start = "1ns" + new_report.time_stop = "2us" + new_report.net = "net_invented" + assert new_report.net != "net_invented" + assert new_report.create() + new_report2 = emi_receiver_test.post.reports_by_category.emi_receiver( + ["dBu(Average[net_6])", "dBu(Peak[net_6])", "dBu(QuasiPeak[net_6])", "dBu(RMS[net_6])"], "EMItransient" + ) + assert new_report2.net == "net_6" + new_report2.time_stop = "2.5us" + assert new_report2.create() + + def test_98_get_variations(self, field_test): + vars = field_test.available_variations.get_variation_strings() + assert vars + variations = field_test.available_variations.variations() + assert isinstance(variations, list) + assert isinstance(variations[0], list) + vars_dict = field_test.available_variations.variations(output_as_dict=True) + assert isinstance(vars_dict, list) + assert isinstance(vars_dict[0], dict) + + def test_z99_delete_variations(self, q3dtest): + assert q3dtest.cleanup_solution() + + def test_z99_delete_variations_B(self, field_test): + vars = field_test.available_variations.get_variation_strings() + assert field_test.cleanup_solution(vars, entire_solution=False) + assert field_test.cleanup_solution(vars, entire_solution=True) + + def test_76_ipk_get_scalar_field_value(self, icepak_post): + assert icepak_post.post.get_scalar_field_value( + "Heat_Flow_Rate", + scalar_function="Integrate", + solution=None, + variations={"power_block": "0.25W", "power_source": "0.075W"}, + is_vector=False, + intrinsics=None, + phase=None, + object_name="cube2", + object_type="surface", + adjacent_side=False, + ) + assert icepak_post.post.get_scalar_field_value( + "Heat_Flow_Rate", + scalar_function="Integrate", + solution=None, + variations={"power_block": "0.6W", "power_source": "0.15W"}, + is_vector=False, + intrinsics=None, + phase=None, + object_name="cube2", + object_type="surface", + adjacent_side=False, + ) + assert icepak_post.post.get_scalar_field_value( + "Heat_Flow_Rate", + scalar_function="Integrate", + solution=None, + variations={"power_block": "0.6W", "power_source": "0.15W"}, + is_vector=False, + intrinsics=None, + phase=None, + object_name="cube2", + object_type="surface", + adjacent_side=True, + ) + assert icepak_post.post.get_scalar_field_value( + "Temperature", + scalar_function="Maximum", + solution=None, + variations={"power_block": "0.6W", "power_source": "0.15W"}, + is_vector=False, + intrinsics=None, + phase=None, + object_name="cube1", + object_type="volume", + adjacent_side=False, + ) + assert icepak_post.post.get_scalar_field_value( + "Temperature", + scalar_function="Maximum", + solution=None, + variations={"power_block": "0.6W", "power_source": "0.15W"}, + is_vector=False, + intrinsics=None, + phase=None, + object_name="cube2", + object_type="surface", + adjacent_side=False, + ) + assert icepak_post.post.get_scalar_field_value( + "Temperature", + scalar_function="Value", + solution=None, + variations=None, + is_vector=False, + intrinsics=None, + phase=None, + object_name="Point1", + object_type="point", + adjacent_side=False, + ) From 87ee574ca3b4035b214c258fb24faf2649eee141 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Thu, 9 May 2024 15:01:57 +0200 Subject: [PATCH 19/29] Fix UT --- _unittest/test_12_PostProcessing.py | 70 ++++------------------------- 1 file changed, 9 insertions(+), 61 deletions(-) diff --git a/_unittest/test_12_PostProcessing.py b/_unittest/test_12_PostProcessing.py index 1712bd9d95f..5f6e828181b 100644 --- a/_unittest/test_12_PostProcessing.py +++ b/_unittest/test_12_PostProcessing.py @@ -477,37 +477,18 @@ def test_58_test_no_report_B(self, q2dtest): def test_59_test_parse_vector(self): local_path = os.path.dirname(os.path.realpath(__file__)) - out = _parse_aedtplt( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "test_vector.aedtplt", - ) - ) + out = _parse_aedtplt(os.path.join(local_path, "example_models", test_subfolder, "test_vector.aedtplt")) assert isinstance(out[0], list) assert isinstance(out[1], list) assert isinstance(out[2], list) assert isinstance(out[3], bool) assert _parse_aedtplt( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "test_vector_no_solutions.aedtplt", - ) + os.path.join(local_path, "example_models", test_subfolder, "test_vector_no_solutions.aedtplt") ) def test_60_test_parse_vector(self): local_path = os.path.dirname(os.path.realpath(__file__)) - out = _parse_streamline( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "test_streamline.fldplt", - ) - ) + out = _parse_streamline(os.path.join(local_path, "example_models", test_subfolder, "test_streamline.fldplt")) assert isinstance(out, list) def test_61_export_mesh(self, q3dtest): @@ -558,12 +539,7 @@ def test_64_eye_meas(self, eye_test): def test_65_eye_from_json(self, eye_test): local_path = os.path.dirname(os.path.realpath(__file__)) assert eye_test.post.create_report_from_configuration( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - "report_json", - "EyeDiagram_Report_simple.json", - ), + os.path.join(local_path, "example_models", "report_json", "EyeDiagram_Report_simple.json"), solution_name="QuickEyeAnalysis", ) @@ -571,12 +547,7 @@ def test_66_spectral_from_json(self, circuit_test): local_path = os.path.dirname(os.path.realpath(__file__)) circuit_test.analyze_setup("Transient") assert circuit_test.post.create_report_from_configuration( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - "report_json", - "Spectral_Report_Simple.json", - ), + os.path.join(local_path, "example_models", "report_json", "Spectral_Report_Simple.json"), solution_name="Transient", ) @@ -586,12 +557,7 @@ def test_66_spectral_from_json(self, circuit_test): def test_68_eye_from_json(self, eye_test): local_path = os.path.dirname(os.path.realpath(__file__)) assert eye_test.post.create_report_from_configuration( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - "report_json", - "EyeDiagram_Report.toml", - ), + os.path.join(local_path, "example_models", "report_json", "EyeDiagram_Report.toml"), solution_name="QuickEyeAnalysis", ) @@ -602,31 +568,13 @@ def test_69_spectral_from_json(self, circuit_test): local_path = os.path.dirname(os.path.realpath(__file__)) circuit_test.analyze_setup("Transient") assert circuit_test.post.create_report_from_configuration( - os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - "report_json", - "Spectral_Report.json", - ), - solution_name="Transient", + os.path.join(local_path, "example_models", "report_json", "Spectral_Report.json"), solution_name="Transient" ) def test_70_far_field_data(self): local_path = os.path.dirname(os.path.realpath(__file__)) - eep_file1 = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "eep", - "eep.txt", - ) - eep_file2 = os.path.join( - local_path, - "../../../../../../../AnsysDev/repos/pyaedt/_unittest/example_models", - test_subfolder, - "eep", - "eep.txt", - ) + eep_file1 = os.path.join(local_path, "example_models", test_subfolder, "eep", "eep.txt") + eep_file2 = os.path.join(local_path, "example_models", test_subfolder, "eep", "eep.txt") frequencies = [0.9e9, "0.9GHz"] eep_files = [eep_file1, eep_file2] From f3aea68dd4f8dcbb9a69dce4b908b8dde9b7409c Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Thu, 9 May 2024 15:21:21 +0200 Subject: [PATCH 20/29] Do not show contour plot in the unit test --- _unittest/test_12_PostProcessing.py | 8 +++++++- pyaedt/modules/solutions.py | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/_unittest/test_12_PostProcessing.py b/_unittest/test_12_PostProcessing.py index 5f6e828181b..02080a3f663 100644 --- a/_unittest/test_12_PostProcessing.py +++ b/_unittest/test_12_PostProcessing.py @@ -637,6 +637,7 @@ def test_71_antenna_plot(self, field_test): title="Contour at {}Hz".format(ffdata.frequency), image_path=os.path.join(self.local_scratch.path, "contour.jpg"), convert_to_db=True, + show=False, ) assert os.path.exists(os.path.join(self.local_scratch.path, "contour.jpg")) @@ -659,7 +660,10 @@ def test_71_antenna_plot(self, field_test): assert os.path.exists(os.path.join(self.local_scratch.path, "2d2.jpg")) ffdata.polar_plot_3d( - quantity="RealizedGain", image_path=os.path.join(self.local_scratch.path, "3d1.jpg"), convert_to_db=True + quantity="RealizedGain", + image_path=os.path.join(self.local_scratch.path, "3d1.jpg"), + convert_to_db=True, + show=False, ) assert os.path.exists(os.path.join(self.local_scratch.path, "3d1.jpg")) @@ -686,6 +690,7 @@ def test_72_antenna_plot(self, array_test): title="Contour at {}Hz".format(ffdata.frequency), image_path=os.path.join(self.local_scratch.path, "contour.jpg"), convert_to_db=True, + show=False, ) assert os.path.exists(os.path.join(self.local_scratch.path, "contour.jpg")) @@ -725,6 +730,7 @@ def test_72_antenna_plot(self, array_test): title="Contour at {}Hz".format(ffdata1.frequency), image_path=os.path.join(self.local_scratch.path, "contour1.jpg"), convert_to_db=True, + show=False, ) assert os.path.exists(os.path.join(self.local_scratch.path, "contour1.jpg")) diff --git a/pyaedt/modules/solutions.py b/pyaedt/modules/solutions.py index 09b0e81c8e4..bd800acdcef 100644 --- a/pyaedt/modules/solutions.py +++ b/pyaedt/modules/solutions.py @@ -1655,7 +1655,7 @@ def plot_farfield_contour( if image_path: plt.savefig(image_path) - if show: + if show: # pragma: no cover plt.show() plt.rcParams["figure.figsize"] = default_figsize @@ -1910,7 +1910,7 @@ def polar_plot_3d( x = r * np.sin(theta_grid) * np.cos(phi_grid) y = r * np.sin(theta_grid) * np.sin(phi_grid) z = r * np.cos(theta_grid) - if show: + if show: # pragma: no cover plot_3d_chart([x, y, z], xlabel="Theta", ylabel="Phi", title=title, snapshot_path=image_path) else: return x, y, z From 2dd6e0df0b494be501ea93d7f8e98d8d3ba194fe Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Thu, 9 May 2024 15:29:48 +0200 Subject: [PATCH 21/29] Do not show contour plot in the unit test --- _unittest/test_12_PostProcessing.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_unittest/test_12_PostProcessing.py b/_unittest/test_12_PostProcessing.py index 02080a3f663..7fdfd84677c 100644 --- a/_unittest/test_12_PostProcessing.py +++ b/_unittest/test_12_PostProcessing.py @@ -647,6 +647,7 @@ def test_71_antenna_plot(self, field_test): secondary_sweep_value=[-180, -75, 75], title="Azimuth at {}Hz".format(ffdata.frequency), image_path=os.path.join(self.local_scratch.path, "2d1.jpg"), + show=False, ) assert os.path.exists(os.path.join(self.local_scratch.path, "2d1.jpg")) ffdata.plot_2d_cut( @@ -655,6 +656,7 @@ def test_71_antenna_plot(self, field_test): secondary_sweep_value=30, title="Azimuth at {}Hz".format(ffdata.frequency), image_path=os.path.join(self.local_scratch.path, "2d2.jpg"), + show=False, ) assert os.path.exists(os.path.join(self.local_scratch.path, "2d2.jpg")) @@ -700,6 +702,7 @@ def test_72_antenna_plot(self, array_test): secondary_sweep_value=[-180, -75, 75], title="Azimuth at {}Hz".format(ffdata.frequency), image_path=os.path.join(self.local_scratch.path, "2d1.jpg"), + show=False, ) assert os.path.exists(os.path.join(self.local_scratch.path, "2d1.jpg")) ffdata.plot_2d_cut( @@ -708,6 +711,7 @@ def test_72_antenna_plot(self, array_test): secondary_sweep_value=30, title="Azimuth at {}Hz".format(ffdata.frequency), image_path=os.path.join(self.local_scratch.path, "2d2.jpg"), + show=False, ) assert os.path.exists(os.path.join(self.local_scratch.path, "2d2.jpg")) From 9b17634b7c1b55cdfba847a444870b0f27a401a4 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Thu, 9 May 2024 15:49:01 +0200 Subject: [PATCH 22/29] Do not show contour plot in the unit test --- _unittest/test_12_PostProcessing.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/_unittest/test_12_PostProcessing.py b/_unittest/test_12_PostProcessing.py index 7fdfd84677c..2375a7e7acb 100644 --- a/_unittest/test_12_PostProcessing.py +++ b/_unittest/test_12_PostProcessing.py @@ -647,7 +647,6 @@ def test_71_antenna_plot(self, field_test): secondary_sweep_value=[-180, -75, 75], title="Azimuth at {}Hz".format(ffdata.frequency), image_path=os.path.join(self.local_scratch.path, "2d1.jpg"), - show=False, ) assert os.path.exists(os.path.join(self.local_scratch.path, "2d1.jpg")) ffdata.plot_2d_cut( @@ -656,16 +655,12 @@ def test_71_antenna_plot(self, field_test): secondary_sweep_value=30, title="Azimuth at {}Hz".format(ffdata.frequency), image_path=os.path.join(self.local_scratch.path, "2d2.jpg"), - show=False, ) assert os.path.exists(os.path.join(self.local_scratch.path, "2d2.jpg")) ffdata.polar_plot_3d( - quantity="RealizedGain", - image_path=os.path.join(self.local_scratch.path, "3d1.jpg"), - convert_to_db=True, - show=False, + quantity="RealizedGain", image_path=os.path.join(self.local_scratch.path, "3d1.jpg"), convert_to_db=True ) assert os.path.exists(os.path.join(self.local_scratch.path, "3d1.jpg")) From 400a1f0555dc48dcd070c36382a2c486fc8e27b7 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Thu, 9 May 2024 16:22:09 +0200 Subject: [PATCH 23/29] Uncomment YAML --- .github/workflows/ci_cd.yml | 944 ++++++++++++++++++------------------ 1 file changed, 472 insertions(+), 472 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 302c98676ae..6ef32825149 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -36,314 +36,314 @@ jobs: use-upper-case: true # TODO: Update to ansys/actions/doc-style@v6 -# doc-style: -# name: Documentation style check -# runs-on: ubuntu-latest -# steps: -# - name: Check documentation style -# uses: ansys/actions/doc-style@v4 -# with: -# token: ${{ secrets.GITHUB_TOKEN }} -# vale-config: "doc/.vale.ini" -# vale-version: "2.29.6" -# -# smoke-tests: -# name: Build wheelhouse and smoke tests -# runs-on: ${{ matrix.os }} -# strategy: -# fail-fast: false -# matrix: -# os: [ubuntu-latest, windows-latest] -# python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] -# steps: -# - name: Build wheelhouse and perform smoke test -# uses: ansys/actions/build-wheelhouse@v4 -# with: -# library-name: ${{ env.PACKAGE_NAME }} -# operating-system: ${{ matrix.os }} -# python-version: ${{ matrix.python-version }} -# target: 'all' -# -# - name: Import python package -# run: | -# python -c "import pyaedt; from pyaedt import __version__" -# -# # TODO: Update to ansys/actions/doc-build@v6 once we remove examples -# doc-build: -# name: Documentation build without examples -# runs-on: ubuntu-latest -# needs: [doc-style] -# steps: -# - name: Install Git and checkout project -# uses: actions/checkout@v4 -# -# - name: Setup Python -# uses: actions/setup-python@v5 -# with: -# python-version: ${{ env.MAIN_PYTHON_VERSION }} -# -# - name: Update pip -# run: | -# pip install --upgrade pip -# -# - name: Install pyaedt and documentation dependencies -# run: | -# pip install .[doc-no-examples] -# -# - name: Retrieve PyAEDT version -# id: version -# run: | -# echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT -# echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")" -# -# - name: Install doc build requirements -# run: | -# sudo apt update -# sudo apt install graphviz texlive-latex-extra latexmk texlive-xetex texlive-fonts-extra -y -# -# # TODO: Update this step once pyaedt-examples is ready -# - name: Build HTML documentation without examples -# run: | -# make -C doc clean -# make -C doc html-no-examples -# -# # Verify that sphinx generates no warnings -# - name: Check for warnings -# run: | -# python doc/print_errors.py -# -# - name: Upload HTML documentation without examples artifact -# uses: actions/upload-artifact@v3 -# with: -# name: documentation-no-examples-html -# path: doc/_build/html -# retention-days: 7 -# -# - name: Build PDF documentation without examples -# run: | -# make -C doc pdf-no-examples -# -# - name: Upload PDF documentation without examples artifact -# uses: actions/upload-artifact@v3 -# with: -# name: documentation-no-examples-pdf -# path: doc/_build/latex/PyAEDT-Documentation-*.pdf -# retention-days: 7 -# -## # ================================================================================================= -## # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -## # ================================================================================================= -# -# doc-build-with-examples: -# name: Documentation build with examples -# if: github.event_name == 'push' && contains(github.ref, 'refs/tags') -# runs-on: [ self-hosted, Windows, pyaedt ] -# needs: [doc-style] -# timeout-minutes: 720 -# steps: -# - name: Install Git and checkout project -# uses: actions/checkout@v4 -# -# - name: Setup Python -# uses: actions/setup-python@v5 -# with: -# python-version: ${{ env.MAIN_PYTHON_VERSION }} -# -# - name: Create virtual environment -# run: | -# python -m venv .venv -# .venv\Scripts\Activate.ps1 -# python -m pip install pip -U -# python -m pip install wheel setuptools -U -# python -c "import sys; print(sys.executable)" -# -# - name: Install pyaedt and documentation dependencies -# run: | -# .venv\Scripts\Activate.ps1 -# pip install .[doc] -# -# - name: Retrieve PyAEDT version -# id: version -# run: | -# .venv\Scripts\Activate.ps1 -# echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT -# echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")" -# -# - name: Install CI dependencies (e.g. vtk-osmesa) -# run: | -# .venv\Scripts\Activate.ps1 -# # Uninstall conflicting dependencies -# pip uninstall --yes vtk -# pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.2.20230527.dev0 -# -# # TODO: Update this step once pyaedt-examples is ready -# # NOTE: Use environment variable to keep the doctree and avoid redundant build for PDF pages -# - name: Build HTML documentation with examples -# env: -# SPHINXBUILD_KEEP_DOCTREEDIR: "1" -# run: | -# .venv\Scripts\Activate.ps1 -# .\doc\make.bat clean -# .\doc\make.bat html -# -# # TODO: Keeping this commented as reminder of https://github.com/ansys/pyaedt/issues/4296 -# # # Verify that sphinx generates no warnings -# # - name: Check for warnings -# # run: | -# # .venv\Scripts\Activate.ps1 -# # python doc/print_errors.py -# -# # Use environment variable to remove the doctree after the build of PDF pages -# - name: Build PDF documentation with examples -# env: -# SPHINXBUILD_KEEP_DOCTREEDIR: "0" -# run: | -# .venv\Scripts\Activate.ps1 -# .\doc\make.bat pdf -# -# - name: Add assets to HTML docs -# run: | -# zip -r documentation-html.zip ./doc/_build/html -# mv documentation-html.zip ./doc/_build/html/_static/assets/download/ -# cp doc/_build/latex/PyAEDT-Documentation-*.pdf ./doc/_build/html/_static/assets/download/pyaedt.pdf -# -# - name: Upload HTML documentation with examples artifact -# uses: actions/upload-artifact@v3 -# with: -# name: documentation-html -# path: doc/_build/html -# retention-days: 7 -# -# - name: Upload PDF documentation without examples artifact -# uses: actions/upload-artifact@v3 -# with: -# name: documentation-pdf -# path: doc/_build/latex/PyAEDT-Documentation-*.pdf -# retention-days: 7 -# -## # ================================================================================================= -## # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -## # ================================================================================================= -# -# test-solvers-windows: -# name: Testing solvers and coverage (Windows) -# needs: [smoke-tests] -# runs-on: [ self-hosted, Windows, pyaedt ] -# steps: -# - name: Install Git and checkout project -# uses: actions/checkout@v4 -# -# - name: Setup Python -# uses: actions/setup-python@v5 -# with: -# python-version: ${{ env.MAIN_PYTHON_VERSION }} -# -# - name: Create virtual environment -# run: | -# python -m venv .venv -# .venv\Scripts\Activate.ps1 -# python -m pip install pip -U -# python -m pip install wheel setuptools -U -# python -c "import sys; print(sys.executable)" -# -# - name: Install pyaedt and tests dependencies -# run: | -# .venv\Scripts\Activate.ps1 -# pip install .[tests] -# pip install pytest-azurepipelines -# -# - name: Install CI dependencies (e.g. vtk-osmesa) -# run: | -# .venv\Scripts\Activate.ps1 -# # Uninstall conflicting dependencies -# pip uninstall --yes vtk -# pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.2.20230527.dev0 -# -# - name: Run tests on _unittest_solvers -# env: -# PYTHONMALLOC: malloc -# run: | -# .venv\Scripts\Activate.ps1 -# pytest --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest_solvers -# -# - uses: codecov/codecov-action@v4 -# with: -# token: ${{ secrets.CODECOV_TOKEN }} -# name: codecov-system-solver-tests -# file: ./coverage.xml -# flags: system,solver -# -# - name: Upload pytest test results -# uses: actions/upload-artifact@v3 -# with: -# name: pytest-solver-results -# path: junit/test-results.xml -# if: ${{ always() }} -# -## # ================================================================================================= -## # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -## # ================================================================================================= -# -# # TODO: Si if we can use ansys/actions -# test-solvers-linux: -# name: Testing solvers and coverage (Linux) -# needs: [smoke-tests] -# runs-on: [ self-hosted, Linux, pyaedt ] -# env: -# ANSYSEM_ROOT241: '/opt/AnsysEM/v241/Linux64' -# ANS_NODEPCHECK: '1' -# steps: -# - name: Install Git and checkout project -# uses: actions/checkout@v4 -# -# - name: Setup Python -# uses: actions/setup-python@v5 -# with: -# python-version: ${{ env.MAIN_PYTHON_VERSION }} -# -# - name: Create virtual environment -# run: | -# export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH -# python -m venv .venv -# source .venv/bin/activate -# python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org pip -U -# python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org wheel setuptools -U -# python -c "import sys; print(sys.executable)" -# -# - name: Install pyaedt and tests dependencies -# run: | -# export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH -# source .venv/bin/activate -# pip install .[tests] -# pip install pytest-azurepipelines -# -# - name: Run tests on _unittest_solvers -# run: | -# export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH -# source .venv/bin/activate -# pytest --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest_solvers -# -# - uses: codecov/codecov-action@v4 -# with: -# token: ${{ secrets.CODECOV_TOKEN }} -# name: codecov-system-solver-tests -# file: ./coverage.xml -# flags: system,solver -# -# - name: Upload pytest test results -# uses: actions/upload-artifact@v3 -# with: -# name: pytest-solver-results -# path: junit/test-results.xml -# if: ${{ always() }} + doc-style: + name: Documentation style check + runs-on: ubuntu-latest + steps: + - name: Check documentation style + uses: ansys/actions/doc-style@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + vale-config: "doc/.vale.ini" + vale-version: "2.29.6" + + smoke-tests: + name: Build wheelhouse and smoke tests + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] + steps: + - name: Build wheelhouse and perform smoke test + uses: ansys/actions/build-wheelhouse@v4 + with: + library-name: ${{ env.PACKAGE_NAME }} + operating-system: ${{ matrix.os }} + python-version: ${{ matrix.python-version }} + target: 'all' + + - name: Import python package + run: | + python -c "import pyaedt; from pyaedt import __version__" + + # TODO: Update to ansys/actions/doc-build@v6 once we remove examples + doc-build: + name: Documentation build without examples + runs-on: ubuntu-latest + needs: [doc-style] + steps: + - name: Install Git and checkout project + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ env.MAIN_PYTHON_VERSION }} + + - name: Update pip + run: | + pip install --upgrade pip + + - name: Install pyaedt and documentation dependencies + run: | + pip install .[doc-no-examples] + + - name: Retrieve PyAEDT version + id: version + run: | + echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT + echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")" + + - name: Install doc build requirements + run: | + sudo apt update + sudo apt install graphviz texlive-latex-extra latexmk texlive-xetex texlive-fonts-extra -y + + # TODO: Update this step once pyaedt-examples is ready + - name: Build HTML documentation without examples + run: | + make -C doc clean + make -C doc html-no-examples + + # Verify that sphinx generates no warnings + - name: Check for warnings + run: | + python doc/print_errors.py + + - name: Upload HTML documentation without examples artifact + uses: actions/upload-artifact@v3 + with: + name: documentation-no-examples-html + path: doc/_build/html + retention-days: 7 + + - name: Build PDF documentation without examples + run: | + make -C doc pdf-no-examples + + - name: Upload PDF documentation without examples artifact + uses: actions/upload-artifact@v3 + with: + name: documentation-no-examples-pdf + path: doc/_build/latex/PyAEDT-Documentation-*.pdf + retention-days: 7 + +# # ================================================================================================= +# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +# # ================================================================================================= + + doc-build-with-examples: + name: Documentation build with examples + if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + runs-on: [ self-hosted, Windows, pyaedt ] + needs: [doc-style] + timeout-minutes: 720 + steps: + - name: Install Git and checkout project + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ env.MAIN_PYTHON_VERSION }} + + - name: Create virtual environment + run: | + python -m venv .venv + .venv\Scripts\Activate.ps1 + python -m pip install pip -U + python -m pip install wheel setuptools -U + python -c "import sys; print(sys.executable)" + + - name: Install pyaedt and documentation dependencies + run: | + .venv\Scripts\Activate.ps1 + pip install .[doc] + + - name: Retrieve PyAEDT version + id: version + run: | + .venv\Scripts\Activate.ps1 + echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT + echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")" + + - name: Install CI dependencies (e.g. vtk-osmesa) + run: | + .venv\Scripts\Activate.ps1 + # Uninstall conflicting dependencies + pip uninstall --yes vtk + pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.2.20230527.dev0 + + # TODO: Update this step once pyaedt-examples is ready + # NOTE: Use environment variable to keep the doctree and avoid redundant build for PDF pages + - name: Build HTML documentation with examples + env: + SPHINXBUILD_KEEP_DOCTREEDIR: "1" + run: | + .venv\Scripts\Activate.ps1 + .\doc\make.bat clean + .\doc\make.bat html + + # TODO: Keeping this commented as reminder of https://github.com/ansys/pyaedt/issues/4296 + # # Verify that sphinx generates no warnings + # - name: Check for warnings + # run: | + # .venv\Scripts\Activate.ps1 + # python doc/print_errors.py + + # Use environment variable to remove the doctree after the build of PDF pages + - name: Build PDF documentation with examples + env: + SPHINXBUILD_KEEP_DOCTREEDIR: "0" + run: | + .venv\Scripts\Activate.ps1 + .\doc\make.bat pdf + + - name: Add assets to HTML docs + run: | + zip -r documentation-html.zip ./doc/_build/html + mv documentation-html.zip ./doc/_build/html/_static/assets/download/ + cp doc/_build/latex/PyAEDT-Documentation-*.pdf ./doc/_build/html/_static/assets/download/pyaedt.pdf + + - name: Upload HTML documentation with examples artifact + uses: actions/upload-artifact@v3 + with: + name: documentation-html + path: doc/_build/html + retention-days: 7 + + - name: Upload PDF documentation without examples artifact + uses: actions/upload-artifact@v3 + with: + name: documentation-pdf + path: doc/_build/latex/PyAEDT-Documentation-*.pdf + retention-days: 7 # # ================================================================================================= # # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv # # ================================================================================================= + test-solvers-windows: + name: Testing solvers and coverage (Windows) + needs: [smoke-tests] + runs-on: [ self-hosted, Windows, pyaedt ] + steps: + - name: Install Git and checkout project + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ env.MAIN_PYTHON_VERSION }} + + - name: Create virtual environment + run: | + python -m venv .venv + .venv\Scripts\Activate.ps1 + python -m pip install pip -U + python -m pip install wheel setuptools -U + python -c "import sys; print(sys.executable)" + + - name: Install pyaedt and tests dependencies + run: | + .venv\Scripts\Activate.ps1 + pip install .[tests] + pip install pytest-azurepipelines + + - name: Install CI dependencies (e.g. vtk-osmesa) + run: | + .venv\Scripts\Activate.ps1 + # Uninstall conflicting dependencies + pip uninstall --yes vtk + pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.2.20230527.dev0 + + - name: Run tests on _unittest_solvers + env: + PYTHONMALLOC: malloc + run: | + .venv\Scripts\Activate.ps1 + pytest --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest_solvers + + - uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + name: codecov-system-solver-tests + file: ./coverage.xml + flags: system,solver + + - name: Upload pytest test results + uses: actions/upload-artifact@v3 + with: + name: pytest-solver-results + path: junit/test-results.xml + if: ${{ always() }} + +# # ================================================================================================= +# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +# # ================================================================================================= + + # TODO: Si if we can use ansys/actions + test-solvers-linux: + name: Testing solvers and coverage (Linux) + needs: [smoke-tests] + runs-on: [ self-hosted, Linux, pyaedt ] + env: + ANSYSEM_ROOT241: '/opt/AnsysEM/v241/Linux64' + ANS_NODEPCHECK: '1' + steps: + - name: Install Git and checkout project + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ env.MAIN_PYTHON_VERSION }} + + - name: Create virtual environment + run: | + export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH + python -m venv .venv + source .venv/bin/activate + python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org pip -U + python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org wheel setuptools -U + python -c "import sys; print(sys.executable)" + + - name: Install pyaedt and tests dependencies + run: | + export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH + source .venv/bin/activate + pip install .[tests] + pip install pytest-azurepipelines + + - name: Run tests on _unittest_solvers + run: | + export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH + source .venv/bin/activate + pytest --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest_solvers + + - uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + name: codecov-system-solver-tests + file: ./coverage.xml + flags: system,solver + + - name: Upload pytest test results + uses: actions/upload-artifact@v3 + with: + name: pytest-solver-results + path: junit/test-results.xml + if: ${{ always() }} + + # ================================================================================================= + # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + # ================================================================================================= + test-windows: name: Testing and coverage (Windows) -# needs: [smoke-tests] + needs: [smoke-tests] runs-on: [ self-hosted, Windows, pyaedt ] steps: - name: Install Git and checkout project @@ -400,174 +400,174 @@ jobs: name: pytest-results path: junit/test-results.xml if: ${{ always() }} -# -## # ================================================================================================= -## # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -## # ================================================================================================= -# -# # TODO: Si if we can use ansys/actions -# test-linux: -# name: Testing and coverage (Linux) -# needs: [smoke-tests] -# runs-on: [ self-hosted, Linux, pyaedt ] -# env: -# ANSYSEM_ROOT241: '/opt/AnsysEM/v241/Linux64' -# ANS_NODEPCHECK: '1' -# steps: -# - name: Install Git and checkout project -# uses: actions/checkout@v4 -# -# - name: Setup Python -# uses: actions/setup-python@v5 -# with: -# python-version: ${{ env.MAIN_PYTHON_VERSION }} -# -# - name: Create virtual environment -# run: | -# export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH -# python -m venv .venv -# source .venv/bin/activate -# python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org pip -U -# python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org wheel setuptools -U -# python -c "import sys; print(sys.executable)" -# -# - name: Install pyaedt and tests dependencies -# run: | -# export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH -# source .venv/bin/activate -# pip install .[tests] -# pip install pytest-azurepipelines -# -# - name: Install CI dependencies (e.g. vtk-osmesa) -# run: | -# source .venv/bin/activate -# # Uninstall conflicting dependencies -# pip uninstall --yes vtk -# pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.2.20230527.dev0 -# -# - name: Run tests on _unittest -# uses: nick-fields/retry@v3 -# with: -# max_attempts: 2 -# retry_on: error -# timeout_minutes: 50 -# command: | -# export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH -# source .venv/bin/activate -# pytest -n 4 --dist loadfile --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest -# -# - uses: codecov/codecov-action@v4 -# with: -# token: ${{ secrets.CODECOV_TOKEN }} -# name: codecov-system-solver-tests -# file: ./coverage.xml -# flags: system,solver -# -# - name: Upload pytest test results -# uses: actions/upload-artifact@v3 -# with: -# name: pytest-solver-results -# path: junit/test-results.xml -# if: ${{ always() }} -# -## # ================================================================================================= -## # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -## # ================================================================================================= -# -# test-ironpython-windows: -# name: Testing IronPython and coverage (Windows) -# needs: [smoke-tests] -# runs-on: [ self-hosted, Windows, pyaedt ] -# steps: -# - uses: actions/checkout@v4 -# -# - name: Run Ironpython tests -# timeout-minutes: 5 -# run: | -# $processA = start-process 'cmd' -ArgumentList '/c .\_unittest_ironpython\run_unittests_batchmode.cmd' -PassThru -# $processA.WaitForExit() -# -# - name: Get log content -# run: | -# get-content .\_unittest_ironpython\pyaedt_unit_test_ironpython.log -# -# - name: Check for errors -# run: | -# $test_errors_failures = Select-String -Path .\_unittest_ironpython\pyaedt_unit_test_ironpython.log -Pattern "TextTestResult errors=" -# if ($test_errors_failures -ne $null) -# { -# exit 1 -# } -# -# package: -# name: Package library -# needs: [test-windows, test-solvers-windows, test-ironpython-windows, test-linux, test-solvers-linux, doc-build] -# runs-on: ubuntu-latest -# steps: -# - name: Build library source and wheel artifacts -# uses: ansys/actions/build-library@v4 -# with: -# library-name: ${{ env.PACKAGE_NAME }} -# python-version: ${{ env.MAIN_PYTHON_VERSION }} -# -# # TODO: Si if we can fix the PDF issue and leverage classic ansys/release-github -# release: -# name: Release project -# if: github.event_name == 'push' && contains(github.ref, 'refs/tags') -# needs: [package, doc-build-with-examples] -# runs-on: ubuntu-latest -# steps: -# - name: Release to the public PyPI repository -# uses: ansys/actions/release-pypi-public@v4 -# with: -# library-name: ${{ env.PACKAGE_NAME }} -# twine-username: "__token__" -# twine-token: ${{ secrets.PYPI_TOKEN }} -# -# - name: Release to GitHub -# uses: ansys/actions/release-github@v4 -# with: -# library-name: ${{ env.PACKAGE_NAME }} -# -# upload-release-doc: -# name: Upload release documentation -# if: github.event_name == 'push' && contains(github.ref, 'refs/tags') -# runs-on: ubuntu-latest -# needs: [release] -# steps: -# - name: Deploy the stable documentation -# uses: ansys/actions/doc-deploy-stable@v4 -# with: -# cname: ${{ env.DOCUMENTATION_CNAME }} -# token: ${{ secrets.GITHUB_TOKEN }} -# doc-artifact-name: 'documentation-html' -# -# doc-index-stable: -# name: Deploy stable docs index -# if: github.event_name == 'push' && contains(github.ref, 'refs/tags') -# runs-on: ubuntu-latest -# needs: upload-release-doc -# steps: -# - name: Install Git and clone project -# uses: actions/checkout@v4 -# -# - name: Install the package requirements -# run: pip install -e . -# -# - name: Get the version to PyMeilisearch -# run: | -# VERSION=$(python -c "from pyaedt import __version__; print('.'.join(__version__.split('.')[:2]))") -# VERSION_MEILI=$(python -c "from pyaedt import __version__; print('-'.join(__version__.split('.')[:2]))") -# echo "Calculated VERSION: $VERSION" -# echo "Calculated VERSION_MEILI: $VERSION_MEILI" -# echo "VERSION=$VERSION" >> $GITHUB_ENV -# echo "VERSION_MEILI=$VERSION_MEILI" >> $GITHUB_ENV -# -# - name: Deploy the latest documentation index -# uses: ansys/actions/doc-deploy-index@v4 -# with: -# cname: ${{ env.DOCUMENTATION_CNAME }}/version/${{ env.VERSION }} -# index-name: pyaedt-v${{ env.VERSION_MEILI }} -# host-url: ${{ env.MEILISEARCH_HOST_URL }} -# api-key: ${{ env.MEILISEARCH_API_KEY }} -# python-version: ${{ env.MAIN_PYTHON_VERSION }} + +# # ================================================================================================= +# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +# # ================================================================================================= + + # TODO: Si if we can use ansys/actions + test-linux: + name: Testing and coverage (Linux) + needs: [smoke-tests] + runs-on: [ self-hosted, Linux, pyaedt ] + env: + ANSYSEM_ROOT241: '/opt/AnsysEM/v241/Linux64' + ANS_NODEPCHECK: '1' + steps: + - name: Install Git and checkout project + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ env.MAIN_PYTHON_VERSION }} + + - name: Create virtual environment + run: | + export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH + python -m venv .venv + source .venv/bin/activate + python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org pip -U + python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org wheel setuptools -U + python -c "import sys; print(sys.executable)" + + - name: Install pyaedt and tests dependencies + run: | + export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH + source .venv/bin/activate + pip install .[tests] + pip install pytest-azurepipelines + + - name: Install CI dependencies (e.g. vtk-osmesa) + run: | + source .venv/bin/activate + # Uninstall conflicting dependencies + pip uninstall --yes vtk + pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.2.20230527.dev0 + + - name: Run tests on _unittest + uses: nick-fields/retry@v3 + with: + max_attempts: 2 + retry_on: error + timeout_minutes: 50 + command: | + export LD_LIBRARY_PATH=${{ env.ANSYSEM_ROOT241 }}/common/mono/Linux64/lib64:${{ env.ANSYSEM_ROOT241 }}/Delcross:$LD_LIBRARY_PATH + source .venv/bin/activate + pytest -n 4 --dist loadfile --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest + + - uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + name: codecov-system-solver-tests + file: ./coverage.xml + flags: system,solver + + - name: Upload pytest test results + uses: actions/upload-artifact@v3 + with: + name: pytest-solver-results + path: junit/test-results.xml + if: ${{ always() }} + +# # ================================================================================================= +# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +# # ================================================================================================= + + test-ironpython-windows: + name: Testing IronPython and coverage (Windows) + needs: [smoke-tests] + runs-on: [ self-hosted, Windows, pyaedt ] + steps: + - uses: actions/checkout@v4 + + - name: Run Ironpython tests + timeout-minutes: 5 + run: | + $processA = start-process 'cmd' -ArgumentList '/c .\_unittest_ironpython\run_unittests_batchmode.cmd' -PassThru + $processA.WaitForExit() + + - name: Get log content + run: | + get-content .\_unittest_ironpython\pyaedt_unit_test_ironpython.log + + - name: Check for errors + run: | + $test_errors_failures = Select-String -Path .\_unittest_ironpython\pyaedt_unit_test_ironpython.log -Pattern "TextTestResult errors=" + if ($test_errors_failures -ne $null) + { + exit 1 + } + + package: + name: Package library + needs: [test-windows, test-solvers-windows, test-ironpython-windows, test-linux, test-solvers-linux, doc-build] + runs-on: ubuntu-latest + steps: + - name: Build library source and wheel artifacts + uses: ansys/actions/build-library@v4 + with: + library-name: ${{ env.PACKAGE_NAME }} + python-version: ${{ env.MAIN_PYTHON_VERSION }} + + # TODO: Si if we can fix the PDF issue and leverage classic ansys/release-github + release: + name: Release project + if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + needs: [package, doc-build-with-examples] + runs-on: ubuntu-latest + steps: + - name: Release to the public PyPI repository + uses: ansys/actions/release-pypi-public@v4 + with: + library-name: ${{ env.PACKAGE_NAME }} + twine-username: "__token__" + twine-token: ${{ secrets.PYPI_TOKEN }} + + - name: Release to GitHub + uses: ansys/actions/release-github@v4 + with: + library-name: ${{ env.PACKAGE_NAME }} + + upload-release-doc: + name: Upload release documentation + if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + runs-on: ubuntu-latest + needs: [release] + steps: + - name: Deploy the stable documentation + uses: ansys/actions/doc-deploy-stable@v4 + with: + cname: ${{ env.DOCUMENTATION_CNAME }} + token: ${{ secrets.GITHUB_TOKEN }} + doc-artifact-name: 'documentation-html' + + doc-index-stable: + name: Deploy stable docs index + if: github.event_name == 'push' && contains(github.ref, 'refs/tags') + runs-on: ubuntu-latest + needs: upload-release-doc + steps: + - name: Install Git and clone project + uses: actions/checkout@v4 + + - name: Install the package requirements + run: pip install -e . + + - name: Get the version to PyMeilisearch + run: | + VERSION=$(python -c "from pyaedt import __version__; print('.'.join(__version__.split('.')[:2]))") + VERSION_MEILI=$(python -c "from pyaedt import __version__; print('-'.join(__version__.split('.')[:2]))") + echo "Calculated VERSION: $VERSION" + echo "Calculated VERSION_MEILI: $VERSION_MEILI" + echo "VERSION=$VERSION" >> $GITHUB_ENV + echo "VERSION_MEILI=$VERSION_MEILI" >> $GITHUB_ENV + + - name: Deploy the latest documentation index + uses: ansys/actions/doc-deploy-index@v4 + with: + cname: ${{ env.DOCUMENTATION_CNAME }}/version/${{ env.VERSION }} + index-name: pyaedt-v${{ env.VERSION_MEILI }} + host-url: ${{ env.MEILISEARCH_HOST_URL }} + api-key: ${{ env.MEILISEARCH_API_KEY }} + python-version: ${{ env.MAIN_PYTHON_VERSION }} From 2f9a381deef26ec36863c063fff2ee6ec94f624b Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Thu, 9 May 2024 16:23:10 +0200 Subject: [PATCH 24/29] Uncomment YAML --- .github/workflows/ci_cd.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 6ef32825149..20a004824f7 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -130,9 +130,9 @@ jobs: path: doc/_build/latex/PyAEDT-Documentation-*.pdf retention-days: 7 -# # ================================================================================================= -# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -# # ================================================================================================= + # ================================================================================================= + # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + # ================================================================================================= doc-build-with-examples: name: Documentation build with examples From d8a281f78545adf7b1a5b363be85b6b73e3c9b9f Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Thu, 9 May 2024 16:25:21 +0200 Subject: [PATCH 25/29] Uncomment YAML --- .github/workflows/ci_cd.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 20a004824f7..f3c93f74339 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -221,9 +221,9 @@ jobs: path: doc/_build/latex/PyAEDT-Documentation-*.pdf retention-days: 7 -# # ================================================================================================= -# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -# # ================================================================================================= + # ================================================================================================= + # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + # ================================================================================================= test-solvers-windows: name: Testing solvers and coverage (Windows) @@ -280,9 +280,9 @@ jobs: path: junit/test-results.xml if: ${{ always() }} -# # ================================================================================================= -# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -# # ================================================================================================= + # ================================================================================================= + # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + # ================================================================================================= # TODO: Si if we can use ansys/actions test-solvers-linux: @@ -401,9 +401,9 @@ jobs: path: junit/test-results.xml if: ${{ always() }} -# # ================================================================================================= -# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -# # ================================================================================================= + # ================================================================================================= + # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + # ================================================================================================= # TODO: Si if we can use ansys/actions test-linux: @@ -470,9 +470,9 @@ jobs: path: junit/test-results.xml if: ${{ always() }} -# # ================================================================================================= -# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -# # ================================================================================================= + # ================================================================================================= + # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + # ================================================================================================= test-ironpython-windows: name: Testing IronPython and coverage (Windows) From 3574747630d1f684077ac84772e515e5ab29a420 Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Thu, 9 May 2024 16:29:05 +0200 Subject: [PATCH 26/29] Uncomment YAML --- .github/workflows/ci_cd.yml | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index f3c93f74339..f68a3cce4ab 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -130,9 +130,9 @@ jobs: path: doc/_build/latex/PyAEDT-Documentation-*.pdf retention-days: 7 - # ================================================================================================= - # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - # ================================================================================================= +# # ================================================================================================= +# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +# # ================================================================================================= doc-build-with-examples: name: Documentation build with examples @@ -221,9 +221,9 @@ jobs: path: doc/_build/latex/PyAEDT-Documentation-*.pdf retention-days: 7 - # ================================================================================================= - # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - # ================================================================================================= +# # ================================================================================================= +# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +# # ================================================================================================= test-solvers-windows: name: Testing solvers and coverage (Windows) @@ -280,9 +280,9 @@ jobs: path: junit/test-results.xml if: ${{ always() }} - # ================================================================================================= - # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - # ================================================================================================= +# # ================================================================================================= +# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +# # ================================================================================================= # TODO: Si if we can use ansys/actions test-solvers-linux: @@ -337,9 +337,9 @@ jobs: path: junit/test-results.xml if: ${{ always() }} - # ================================================================================================= - # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - # ================================================================================================= +# # ================================================================================================= +# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +# # ================================================================================================= test-windows: name: Testing and coverage (Windows) @@ -401,9 +401,9 @@ jobs: path: junit/test-results.xml if: ${{ always() }} - # ================================================================================================= - # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - # ================================================================================================= +# # ================================================================================================= +# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +# # ================================================================================================= # TODO: Si if we can use ansys/actions test-linux: @@ -470,9 +470,9 @@ jobs: path: junit/test-results.xml if: ${{ always() }} - # ================================================================================================= - # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - # ================================================================================================= +# # ================================================================================================= +# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +# # ================================================================================================= test-ironpython-windows: name: Testing IronPython and coverage (Windows) From 1c56d4b13223e95cc781a6072a85472034f3c57e Mon Sep 17 00:00:00 2001 From: Samuelopez-ansys Date: Thu, 9 May 2024 16:29:59 +0200 Subject: [PATCH 27/29] Uncomment YAML --- .github/workflows/ci_cd.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index f68a3cce4ab..e6c7f71fcf3 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -130,9 +130,9 @@ jobs: path: doc/_build/latex/PyAEDT-Documentation-*.pdf retention-days: 7 -# # ================================================================================================= -# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -# # ================================================================================================= +# # ================================================================================================= +# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +# # ================================================================================================= doc-build-with-examples: name: Documentation build with examples From 8cb438bd399faf5550f8f0aedc2939bd67598a4c Mon Sep 17 00:00:00 2001 From: Devin <38879940+dcrawforAtAnsys@users.noreply.github.com> Date: Mon, 13 May 2024 08:33:29 +0200 Subject: [PATCH 28/29] Apply suggestions from code review Add suggestions from @pipkat Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- pyaedt/application/analysis_hf.py | 18 ++++++++-------- pyaedt/generic/plot.py | 26 +++++++++++------------ pyaedt/hfss.py | 19 +++++++++-------- pyaedt/modules/solutions.py | 34 +++++++++++++++---------------- 4 files changed, 49 insertions(+), 48 deletions(-) diff --git a/pyaedt/application/analysis_hf.py b/pyaedt/application/analysis_hf.py index d31756cdee6..fd7208b791c 100644 --- a/pyaedt/application/analysis_hf.py +++ b/pyaedt/application/analysis_hf.py @@ -368,25 +368,25 @@ def phase_expression(m, n, theta_name="theta_scan", phi_name="phi_scan"): Parameters ---------- m : int, required - Index of the rectangular antenna array element in the x-direction. + Index of the rectangular antenna array element in the x direction. n : int, required - Index of the rectangular antenna array element in the y-direction. + Index of the rectangular antenna array element in the y direction. theta_name : str, optional - Post-processing variable name in HFSS that is used for the - theta component of the phase angle expression. Default is ``"theta_scan"``. + Postprocessing variable name in HFSS to use for the + theta component of the phase angle expression. The default is ``"theta_scan"``. phi_name : str, optional - Post-processing variable name in HFSS to be used to generate - the phi component of the phase angle expression. Default is ``"phi_scan"`` + Postprocessing variable name in HFSS to use to generate + the phi component of the phase angle expression. The default is ``"phi_scan"`` Returns ------- str - The phase angle expression for the (m,n) source of + Phase angle expression for the (m,n) source of the (m,n) antenna array element. """ - # px is the term for the phase variation in the x-direction - # py is the term for the phase variation in the y-direction. + # px is the term for the phase variation in the x direction. + # py is the term for the phase variation in the y direction. if n > 0: add_char = " + " diff --git a/pyaedt/generic/plot.py b/pyaedt/generic/plot.py index c41a31dc821..b7bc681492e 100644 --- a/pyaedt/generic/plot.py +++ b/pyaedt/generic/plot.py @@ -51,7 +51,7 @@ "Install with \n\npip install matplotlib\n\nRequires CPython." ) except Exception: - warnings.warn("Unknown error while attempting to import matplotlib.") + warnings.warn("Unknown error occurred while attempting to import Matplotlib.") # Override default settings for matplotlib @@ -322,7 +322,7 @@ def _parse_streamline(filepath): def plot_polar_chart( plot_data, size=(2000, 1000), show_legend=True, xlabel="", ylabel="", title="", snapshot_path=None, show=True ): - """Create a matplotlib polar plot based on a list of data. + """Create a Matplotlib polar plot based on a list of data. Parameters ---------- @@ -338,17 +338,17 @@ def plot_polar_chart( ylabel : str Plot Y label. title : str - Plot Title label. + Plot title label. snapshot_path : str - Full path to image file if a snapshot is needed. - show : Bool - Set to ``True`` if the figure should be rendered. Default is ``True``, otherwise + Full path to the image file if a snapshot is needed. + show : bool, optional + Whether to render the figure. The default is ``True``. If ``False``, the figure is not drawn. Returns ------- :class:`matplotlib.pyplot.Figure` - Matplotlib fig object. + Matplotlib figure object. """ dpi = 100.0 @@ -386,7 +386,7 @@ def plot_polar_chart( @pyaedt_function_handler() @update_plot_settings def plot_3d_chart(plot_data, size=(2000, 1000), xlabel="", ylabel="", title="", snapshot_path=None): - """Create a matplotlib 3D plot based on a list of data. + """Create a Matplotlib 3D plot based on a list of data. Parameters ---------- @@ -407,7 +407,7 @@ def plot_3d_chart(plot_data, size=(2000, 1000), xlabel="", ylabel="", title="", Returns ------- :class:`matplotlib.pyplot.Figure` - Matplotlib fig object. + Matplotlib figure object. """ dpi = 100.0 @@ -440,7 +440,7 @@ def plot_3d_chart(plot_data, size=(2000, 1000), xlabel="", ylabel="", title="", @pyaedt_function_handler() @update_plot_settings def plot_2d_chart(plot_data, size=(2000, 1000), show_legend=True, xlabel="", ylabel="", title="", snapshot_path=None): - """Create a matplotlib plot based on a list of data. + """Create a Matplotlib plot based on a list of data. Parameters ---------- plot_data : list of list @@ -463,7 +463,7 @@ def plot_2d_chart(plot_data, size=(2000, 1000), show_legend=True, xlabel="", yla Returns ------- :class:`matplotlib.pyplot.Figure` - Matplotlib fig object. + Matplotlib figure object. """ dpi = 100.0 figsize = (size[0] / dpi, size[1] / dpi) @@ -615,7 +615,7 @@ def plot_matplotlib( def plot_contour( qty_to_plot, x, y, size=(2000, 1600), xlabel="", ylabel="", title="", levels=64, snapshot_path=None, show=True ): - """Create a matplotlib contour plot. + """Create a Matplotlib contour plot. Parameters ---------- @@ -644,7 +644,7 @@ def plot_contour( Returns ------- :class:`matplotlib.pyplot.Figure` - Matplotlib fig object. + Matplotlib figure object. """ dpi = 100.0 figsize = (size[0] / dpi, size[1] / dpi) diff --git a/pyaedt/hfss.py b/pyaedt/hfss.py index 12f7be0b003..bea573d1011 100644 --- a/pyaedt/hfss.py +++ b/pyaedt/hfss.py @@ -5237,13 +5237,13 @@ def set_differential_pair( @pyaedt_function_handler(array_name="name", json_file="input_data") def add_3d_component_array_from_json(self, input_data, name=None): - """Add or edit a 3D component array from a JSON file, TOML file or dict. + """Add or edit a 3D component array from a JSON file, TOML file, or dictionary. The 3D component is placed in the layout if it is not present. Parameters ---------- input_data : str, dict - Full path to either the JSON file, TOML file or the dictionary + Full path to either the JSON file, TOML file, or the dictionary containing the array information. name : str, optional Name of the boundary to add or edit. @@ -5420,8 +5420,8 @@ def get_antenna_ffd_solution_data( overwrite=True, link_to_hfss=True, ): - """Export antennas parameters to Far Field Data (FFD) files and return an - instance of + """Export the antenna parameters to Far Field Data (FFD) files and return an + instance of the ``FfdSolutionDataExporter`` object. For phased array cases, only one phased array is calculated. @@ -5440,11 +5440,12 @@ def get_antenna_ffd_solution_data( overwrite : bool, optional Whether to overwrite FFD files. The default is ``True``. link_to_hfss : bool, optional - If this is set to ``False`` then return an instance of - :class:`pyaedt.modules.solutions.FfdSolutionData` which is independent from the - running HFSS instance. The default is ``True`` which returns an instance of - :class:`pyaedt.modules.solutions.FfdSolutionDataExporter` which requires a connection - to an instance of the :class:`Hfss`` class. + Whether to return an instance of the + :class:`pyaedt.modules.solutions.FfdSolutionDataExporter` class, + which requires a connection to an instance of the :class:`Hfss` class. + The default is `` True``. If ``False``, returns an instance of + :class:`pyaedt.modules.solutions.FfdSolutionData` class, which is + independent from the running HFSS instance. Returns ------- diff --git a/pyaedt/modules/solutions.py b/pyaedt/modules/solutions.py index bd800acdcef..a4176ef30f0 100644 --- a/pyaedt/modules/solutions.py +++ b/pyaedt/modules/solutions.py @@ -1091,21 +1091,21 @@ def ifft_to_file( class FfdSolutionData(object): - """Antenna array far-field data class. + """Provides antenna array far-field data. - Read embedded element patterns generated in HFSS and provide the Python interface + Read embedded element patterns generated in HFSS and return the Python interface to plot and analyze the array far-field data. Parameters ---------- eep_files : list or str List of embedded element pattern files for each frequency. - If data is only provided for a single frequency, then a string may be passed - instead of a 1-element list. + If data is only provided for a single frequency, then a string can be passed + instead of a one-element list. frequencies : list, str, int, or float List of frequencies. - If data is only available for a single frequency, then a float or int may be passed - instead of a 1-element list. + If data is only available for a single frequency, then a float or integer may be passed + instead of a one-element list. Examples -------- @@ -1556,7 +1556,7 @@ def plot_farfield_contour( theta : float, int, optional Theta scan angle in degrees. The default is ``0``. size : tuple, optional - Image size in pixel (width, height). Default is ``None`` in which case resolution + Image size in pixel (width, height). The default is ``None``, in which case resolution is determined automatically. title : str, optional Plot title. The default is ``"RectangularPlot"``. @@ -1573,10 +1573,10 @@ def plot_farfield_contour( instance of the plot is shown. polar : bool, optional Generate the plot in polar coordinates. The default is ``True``. If ``False``, the plot - will be rectangular. + generated is rectangular. max_theta : float or int, optional - Maxmum theta angle for plotting. The default is ``180`` which plots the far-field for - all angles. Setting ``max_theta`` to 90 will limit the displayed data to the upper + Maxmum theta angle for plotting. The default is ``180``, which plots the far-field data for + all angles. Setting ``max_theta`` to 90 limits the displayed data to the upper hemisphere, that is (0 < theta < 90). Returns @@ -2467,16 +2467,16 @@ def _rotation_to_euler_angles(R): class FfdSolutionDataExporter(FfdSolutionData): """Class to enable export of embedded element pattern data from HFSS. - An instance of this class is returned from the method - :meth:`pyaedt.Hfss.get_antenna_ffd_solution_data`. This method allows creation of + An instance of this class is returned from the + :meth:`pyaedt.Hfss.get_antenna_ffd_solution_data` method. This method allows creation of the embedded - element pattern (eep) files for an antenna array that has been solved in HFSS. The + element pattern (EEP) files for an antenna array that have been solved in HFSS. The ``frequencies`` and ``eep_files`` properties can then be passed as arguments to - instantiate an instance of :class:`pyaedt.modules.solutions.FfdSolutionData` for - subsequent analysis and post-processing of the array data. + instantiate an instance of the :class:`pyaedt.modules.solutions.FfdSolutionData` class for + subsequent analysis and postprocessing of the array data. - Note that this class is derived from :class:`FfdSolutionData` and can be used directly for - far-field postprocessing and array analysis, but remains a property of the + Note that this class is derived from the :class:`FfdSolutionData` class and can be used directly for + far-field postprocessing and array analysis, but it remains a property of the :class:`pyaedt.Hfss` application. Parameters From 2dbf36980b0a4d1a623ac2ab6ebcab127862fed6 Mon Sep 17 00:00:00 2001 From: Devin <38879940+dcrawforAtAnsys@users.noreply.github.com> Date: Mon, 13 May 2024 13:40:16 +0200 Subject: [PATCH 29/29] Update pyaedt/generic/plot.py Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- pyaedt/generic/plot.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyaedt/generic/plot.py b/pyaedt/generic/plot.py index b7bc681492e..839ac8aea27 100644 --- a/pyaedt/generic/plot.py +++ b/pyaedt/generic/plot.py @@ -634,12 +634,12 @@ def plot_contour( title : str, optional Plot Title Label. Default is `""`. levels : int, optional - Color map levels. Default is `64`. + Color map levels. The default is ``64``. snapshot_path : str, optional - Full path to image to save. Default is None. - show : Bool, optional - Set to ``True`` if the figure should be rendered. - Default is ``True``. + Full path to save the image save. The default is ``None``. + show : bool, optional + Whether to render the figure. The default is ``True``. If + ``False``, the image is not drawn. Returns -------