.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/00-fluent/tyler_sofrin_modes.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end <sphx_glr_download_examples_00-fluent_tyler_sofrin_modes.py>` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_00-fluent_tyler_sofrin_modes.py: .. _ref_ts_mode_calculator: Tyler-Sofrin Compressor Modes Post-Processing --------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 30-76 Objective ~~~~~~~~~ This example demonstrates PyFluent API's for * Read a case and data file * Create monitor points to calculate Fourier coefficients * Write Fourier coefficients to a file * Tyler-Sofrin mode Plot using the matplotlib library Background ~~~~~~~~~~ Tyler and Sofrin (1961) demonstrated that interactions between a rotor and a stator result in an infinite set of spinning modes. Each Tyler-Sofrin (TS) mode exhibits an m-lobed pattern and rotates at a speed given by the following equation: :math:`\text{speed} = \frac{BnΩ}{m}` Where: * m is the Tyler-Sofrin mode number, defined as 'm = nB + kV' * n is the impeller frequency harmonic * k is the vane harmonic * B is the number of rotating blades * V is the number of stationary vanes * Ω is the Rotor shaft speed, rad/s Example: * 8-blade rotor interacting with a 6-vane stator * 2-lobed pattern turning at (8)(1)/(2) = 4 times shaft speed Example Table ~~~~~~~~~~~~~ .. image:: ../../_static/ExampleTable.jpg :alt: Example Table Tyler-Sofrin Modes ~~~~~~~~~~~~~~~~~~ .. image:: ../../_static/TSmode.jpg :alt: Tyler-Sofrin Modes .. GENERATED FROM PYTHON SOURCE LINES 79-99 Example Note: Discrete Fourier Transform (DFT) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + In order to calculate the pressure related to each TS-mode, extend the simulation and perform the DFT of pressure at the desired blade passing frequency harmonics. + Disable the Hanning windowing (specifically for periodic flows like this one) to avoid getting half the expected magnitudes for periodic flows. Make sure to set the windowing parameter to 'None' when specifying the Discrete Fourier Transform (DFT) in the graphical user interface (GUI). + The DFT data will only be accurate if the sampling is done across the entire specified sampling period. .. note:: The .cas/.dat file provided with this example is for demonstration purposes only. A finer mesh is necessary for accurate acoustic analysis. This example uses data sets generated with Ansys Fluent V2023R2. .. GENERATED FROM PYTHON SOURCE LINES 101-103 Post-Processing Implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. GENERATED FROM PYTHON SOURCE LINES 106-108 Import required libraries/modules ===================================================================================== .. GENERATED FROM PYTHON SOURCE LINES 108-118 .. code-block:: Python import math from pathlib import Path import random import matplotlib.pyplot as plt import numpy as np import ansys.fluent.core as pyfluent from ansys.fluent.core import examples .. GENERATED FROM PYTHON SOURCE LINES 119-126 Specifying save path ===================================================================================== save_path can be specified as: + Path("E:/", "pyfluent-examples-tests") or + Path("E:/pyfluent-examples-tests") in a Windows machine for example, or + Path("~/pyfluent-examples-tests") in Linux. .. GENERATED FROM PYTHON SOURCE LINES 126-129 .. code-block:: Python save_path = Path(pyfluent.EXAMPLES_PATH) .. GENERATED FROM PYTHON SOURCE LINES 130-132 Downloading cas/dat file ===================================================================================== .. GENERATED FROM PYTHON SOURCE LINES 132-144 .. code-block:: Python import_filename = examples.download_file( "axial_comp_fullWheel_DFT_23R2.cas.h5", "pyfluent/examples/Tyler-Sofrin-Modes-Compressor", save_path=save_path, ) examples.download_file( "axial_comp_fullWheel_DFT_23R2.dat.h5", "pyfluent/examples/Tyler-Sofrin-Modes-Compressor", save_path=save_path, ) .. GENERATED FROM PYTHON SOURCE LINES 145-147 Launch Fluent session and print Fluent version ===================================================================================== .. GENERATED FROM PYTHON SOURCE LINES 147-152 .. code-block:: Python session = pyfluent.launch_fluent( ui_mode="gui", processor_count=4, product_version="25.1.0" ) print(session.get_fluent_version()) .. GENERATED FROM PYTHON SOURCE LINES 153-158 Reading case and data file ===================================================================================== .. note:: The dat file should correspond to the already completed DFT simulation. .. GENERATED FROM PYTHON SOURCE LINES 158-161 .. code-block:: Python session.file.read(file_type="case-data", file_name=import_filename) .. GENERATED FROM PYTHON SOURCE LINES 162-171 Define User constant/variables ===================================================================================== .. note:: The variable names should match the ones written from the DFT and can be identified by manually examining the solution variables as shown below: .. image:: ../../_static/var_names.jpg :alt: variable names .. GENERATED FROM PYTHON SOURCE LINES 171-187 .. code-block:: Python varname = [ "mean-static-pressure-dataset", "dft-static-pressure_10.00kHz-ta", "dft-static-pressure-1_21.43kHz-ta", "dft-static-pressure-2_30.00kHz-ta", ] n_mode = [0, 1, 2, 3] # Impeller frequency harmonics r = 0.082 # meters z = -0.037 # meters d_theta = 5 # degrees m_max = 50 # maximum TS mode number # Plot will be from -m_max to +m_max, incremented by m_inc m_inc = 2 # TS mode increment .. GENERATED FROM PYTHON SOURCE LINES 188-190 Create monitor points ===================================================================================== .. GENERATED FROM PYTHON SOURCE LINES 190-197 .. code-block:: Python for angle in range(0, 360, d_theta): x = math.cos(math.radians(angle)) * r y = math.sin(math.radians(angle)) * r pt_name = "point-" + str(angle) session.results.surfaces.point_surface[pt_name] = {} session.results.surfaces.point_surface[pt_name].point = [x, y, z] .. GENERATED FROM PYTHON SOURCE LINES 198-200 Compute Fourier coefficients at each monitor point (An, Bn) ===================================================================================== .. GENERATED FROM PYTHON SOURCE LINES 200-240 .. code-block:: Python An = np.zeros((len(varname), int(360 / d_theta))) Bn = np.zeros((len(varname), int(360 / d_theta))) for angle_ind, angle in enumerate(range(0, 360, d_theta)): for n_ind, variable in enumerate(varname): if len(variable) >= 4 and variable[:4] == "mean": session.solution.report_definitions.surface["mag-report"] = { "report_type": "surface-vertexavg", "surface_names": ["point-" + str(angle)], "field": str(variable), } mag = session.solution.report_definitions.compute( report_defs=["mag-report"] ) mag = mag[0]["mag-report"][0] An[n_ind][angle_ind] = mag Bn[n_ind][angle_ind] = 0 else: session.solution.report_definitions.surface["mag-report"] = { "report_type": "surface-vertexavg", "surface_names": ["point-" + str(angle)], "field": str(variable) + "-mag", } mag = session.solution.report_definitions.compute( report_defs=["mag-report"] ) mag = mag[0]["mag-report"][0] session.solution.report_definitions.surface["phase-report"] = { "report_type": "surface-vertexavg", "surface_names": ["point-" + str(angle)], "field": str(variable) + "-phase", } phase = session.solution.report_definitions.compute( report_defs=["phase-report"] ) phase = phase[0]["phase-report"][0] An[n_ind][angle_ind] = mag * math.cos(phase) Bn[n_ind][angle_ind] = -mag * math.sin(phase) .. GENERATED FROM PYTHON SOURCE LINES 241-247 Write Fourier coefficients to file ===================================================================================== .. note:: This step is only required if data is to be processed with other standalone tools. Update the path to the file accordingly. .. GENERATED FROM PYTHON SOURCE LINES 247-266 .. code-block:: Python fourier_coefficients_file = Path(save_path, "FourierCoefficients.txt") with open(fourier_coefficients_file, "w") as f: f.write("n theta An Bn \n") for n_ind, variable in enumerate(varname): for ind, x in enumerate(An[n_ind, :]): f.write( str(n_mode[n_ind]) + "," + str(ind * d_theta) + "," + str(An[n_ind, ind]) + "," + str(Bn[n_ind, ind]) + "\n" ) .. GENERATED FROM PYTHON SOURCE LINES 267-274 Calculate Resultant Pressure Field ===================================================================================== Create list of m values based on m_max and m_inc .. image:: ../../_static/TS_formulas.jpg :alt: variable names .. GENERATED FROM PYTHON SOURCE LINES 274-301 .. code-block:: Python m_mode = range(-m_max, m_max + m_inc, m_inc) # Initialize solution matrices with zeros Anm = np.zeros((len(varname), len(m_mode))) Bnm = np.zeros((len(varname), len(m_mode))) Pnm = np.zeros((len(varname), len(m_mode))) for n_ind, variable in enumerate(varname): # loop over n modes for m_ind, m in enumerate(m_mode): # loop over m modes for angle_ind, angle in enumerate( np.arange(0, math.radians(360), math.radians(d_theta)) ): # loop over all angles, in radians Anm[n_ind][m_ind] += An[n_ind][angle_ind] * math.cos(m * angle) - Bn[n_ind][ angle_ind ] * math.sin(m * angle) Bnm[n_ind][m_ind] += An[n_ind][angle_ind] * math.sin(m * angle) + Bn[n_ind][ angle_ind ] * math.cos(m * angle) Anm[n_ind][m_ind] = Anm[n_ind][m_ind] / (2 * math.pi) * math.radians(d_theta) Bnm[n_ind][m_ind] = Bnm[n_ind][m_ind] / (2 * math.pi) * math.radians(d_theta) Pnm[n_ind][m_ind] = math.sqrt(Anm[n_ind][m_ind] ** 2 + Bnm[n_ind][m_ind] ** 2) # P_00 is generally orders of magnitude larger than that of other modes. # Giving focus to other modes by setting P_00 equal to zero Pnm[0][int(len(m_mode) / 2)] = 0 .. GENERATED FROM PYTHON SOURCE LINES 302-305 Plot Tyler-Sofrin modes ===================================================================================== .. GENERATED FROM PYTHON SOURCE LINES 305-319 .. code-block:: Python fig = plt.figure() ax = plt.axes(projection="3d") ax.set_xlabel("Tyler-Sofrin Mode, m") ax.set_ylabel("Imp Freq Harmonic, n") ax.set_zlabel("Pnm [Pa]") plt.yticks(n_mode) for n_ind, n in enumerate(n_mode): x = m_mode y = np.full(Pnm.shape[1], n) z = Pnm[n_ind] rgb = (random.random(), random.random(), random.random()) ax.plot3D(x, y, z, c=rgb) plt.show() .. GENERATED FROM PYTHON SOURCE LINES 320-324 Tyler-Sofrin modes ===================================================================================== .. image:: ../../_static/ts_modes.png :alt: Tyler-Sofrin modes .. GENERATED FROM PYTHON SOURCE LINES 327-329 Close the session ===================================================================================== .. GENERATED FROM PYTHON SOURCE LINES 329-332 .. code-block:: Python session.exit() .. GENERATED FROM PYTHON SOURCE LINES 333-338 References ===================================================================================== [1] J.M. Tyler and T. G. Sofrin, Axial Flow Compressor Noise Studies,1961 Manly Memorial Award. .. _sphx_glr_download_examples_00-fluent_tyler_sofrin_modes.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: tyler_sofrin_modes.ipynb <tyler_sofrin_modes.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: tyler_sofrin_modes.py <tyler_sofrin_modes.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: tyler_sofrin_modes.zip <tyler_sofrin_modes.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_