.. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_plot_RienstraCutOns.py: How to compute wavenumbers and cut-ons ====================================== In this example, the wavenumbers and cut-on modes in a circular waveguide without flow are computed and plotted. The r esults correspondto Rienstra "Fundamentals of Duct Acoustics" (Figures 7 and 8). .. image:: ../../image/ripples.JPG :width: 800 1. Initialization ----------------- First, we import the packages needed for this example. .. code-block:: default import matplotlib.pyplot as plt import numpy import acdecom In this example we compute the wavenumbers for arbitrary mode orders in a circular duct of radius 0.1 m without background flow. .. code-block:: default section = "circular" radius = 1 # [m] Mach_number = 0 We create an object for our test section. We use the standard conditions for ambient air inside the duct, which are predefined. .. code-block:: default td = acdecom.WaveGuide(cross_section = section, dimensions=(radius,), M=Mach_number) From the *td* object, we can get the :class:`.WaveGuide` specific properties. .. code-block:: default print(td.get_domainvalues()) .. rst-class:: sphx-glr-script-out Out: .. code-block:: none {'density': 1.2002432611667804, 'dynamic_viscosity': 1.813e-05, 'specific_heat': 1002.8961443192019, 'heat_capacity': 1.401, 'thermal_conductivity': 0.02587, 'speed_of_sound': 343.35637592387417, 'Mach_number': 0, 'radius': 1, 'bulk-viscosity': 1.0878e-05} 2. Extract the Wavenumbers -------------------- We define a non-dimensional frequency from which we compute the maximum frequency for our decomposition. .. code-block:: default omega_nondimensional = 20 omega = omega_nondimensional * td.speed_of_sound/radius f_decomb = omega/(2*numpy.pi) We can conveniently compute the wavenumbers for an arbitrary set of modes by creating two arrays containing all combinations of *m* and *n*. In this example we compute the first 24 *m* modes and the first 10 *n* modes. .. code-block:: default m = numpy.arange(0,24) n = numpy.arange(0,10) nn, mm = numpy.meshgrid(n, m) From the mode arrays we compute the wavenumbers in the left and in the right running direction. We can alter the direction by setting the *sign* parameter. The :math:`p_+` direction has the sign 1 and the :math:`p_-` direction has the sign -1. .. code-block:: default k_left = td.get_wavenumber(mm, nn, sign = -1, f=f_decomb) k_right = td.get_wavenumber(mm, nn, sign = 1, f=f_decomb) 3. Plot ---- Finally, we can plot the real and the imaginary part of the wavenumbers on the m - n grid. .. code-block:: default text_params = {'ha': 'center', 'va': 'center', 'family': 'sans-serif', 'fontweight': 'bold'} fig, axs = plt.subplots(2,1,figsize = (10,10)) ax=axs[0] limit = numpy.max(numpy.abs(numpy.imag(k_right))) kimag_left = ax.pcolor(-n, m, numpy.imag(k_left), cmap="rainbow",vmin=-limit,vmax=limit) kimag_right = ax.pcolor(n, m, numpy.imag(k_right), cmap="rainbow",vmin=-limit,vmax=limit) ax.set_xticks(numpy.append(-n,n)) ax.set_yticks(m) ax.set_xticklabels(numpy.append(n,n)) ax.set_xlabel("n") ax.set_ylabel("m") ax.set_title("$Im(k_{mn})$, $\omega$ = "+str(omega_nondimensional)) fig.colorbar(kimag_left, ax=ax) ax.grid(b=True, which='major', color='#666666', linestyle='-') ax.text(numpy.max(n)*0.5,numpy.max(m)*0.5,"right running wave",bbox=dict(boxstyle="round", ec="k",fc="w"),**text_params) ax.text(-numpy.max(n)*0.5,numpy.max(m)*0.5,"left running wave",bbox=dict(boxstyle="round", ec="k",fc="w"),**text_params) ax=axs[1] limit = numpy.max(numpy.abs(numpy.real(k_right))) kimag_left = ax.pcolor(-n, m, numpy.real(k_left), cmap="rainbow",vmin=-limit,vmax=limit) kimag_right = ax.pcolor(n, m, numpy.real(k_right), cmap="rainbow",vmin=-limit,vmax=limit) ax.set_xticks(numpy.append(-n,n)) ax.set_xticklabels(numpy.append(n,n)) ax.set_yticks(m) ax.grid(b=True, which='major', color='#666666', linestyle='-') ax.text(numpy.max(n)*0.5,numpy.max(m)*0.5,"right running wave",bbox=dict(boxstyle="round", ec="k",fc="w"),**text_params) ax.text(-numpy.max(n)*0.5,numpy.max(m)*0.5,"left running wave",bbox=dict(boxstyle="round", ec="k",fc="w"),**text_params) ax.set_xlabel("n") ax.set_ylabel("m") ax.set_title("$Re(k_{mn})$, $\omega$ = "+str(omega_nondimensional)) fig.colorbar(kimag_left, ax=ax) plt.show() .. image:: /auto_examples/images/sphx_glr_plot_RienstraCutOns_001.png :alt: $Im(k_{mn})$, $\omega$ = 20, $Re(k_{mn})$, $\omega$ = 20 :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out Out: .. code-block:: none /home/docs/checkouts/readthedocs.org/user_builds/acdecom/checkouts/latest/examples/plot_RienstraCutOns.py:64: MatplotlibDeprecationWarning: shading='flat' when X and Y have the same dimensions as C is deprecated since 3.3. Either specify the corners of the quadrilaterals with X and Y, or pass shading='auto', 'nearest' or 'gouraud', or set rcParams['pcolor.shading']. This will become an error two minor releases later. kimag_left = ax.pcolor(-n, m, numpy.imag(k_left), cmap="rainbow",vmin=-limit,vmax=limit) /home/docs/checkouts/readthedocs.org/user_builds/acdecom/checkouts/latest/examples/plot_RienstraCutOns.py:65: MatplotlibDeprecationWarning: shading='flat' when X and Y have the same dimensions as C is deprecated since 3.3. Either specify the corners of the quadrilaterals with X and Y, or pass shading='auto', 'nearest' or 'gouraud', or set rcParams['pcolor.shading']. This will become an error two minor releases later. kimag_right = ax.pcolor(n, m, numpy.imag(k_right), cmap="rainbow",vmin=-limit,vmax=limit) /home/docs/checkouts/readthedocs.org/user_builds/acdecom/checkouts/latest/examples/plot_RienstraCutOns.py:80: MatplotlibDeprecationWarning: shading='flat' when X and Y have the same dimensions as C is deprecated since 3.3. Either specify the corners of the quadrilaterals with X and Y, or pass shading='auto', 'nearest' or 'gouraud', or set rcParams['pcolor.shading']. This will become an error two minor releases later. kimag_left = ax.pcolor(-n, m, numpy.real(k_left), cmap="rainbow",vmin=-limit,vmax=limit) /home/docs/checkouts/readthedocs.org/user_builds/acdecom/checkouts/latest/examples/plot_RienstraCutOns.py:81: MatplotlibDeprecationWarning: shading='flat' when X and Y have the same dimensions as C is deprecated since 3.3. Either specify the corners of the quadrilaterals with X and Y, or pass shading='auto', 'nearest' or 'gouraud', or set rcParams['pcolor.shading']. This will become an error two minor releases later. kimag_right = ax.pcolor(n, m, numpy.real(k_right), cmap="rainbow",vmin=-limit,vmax=limit) Additionally, we can compute the wavenumbers for a set of modes as a function of the frequency. Again, we create two arrays that contain the combinations of modes. Here, we compute only the *m* modes and set *n* to 0. .. code-block:: default m = numpy.arange(0, 17) n = numpy.zeros((m.shape[0],),dtype=int) We also create an array for the dimensionless frequencies from 0.1 to 20 and allocate arrays for the left and right running wavenumbers. .. code-block:: default omegas = numpy.linspace(0.1,20,100) k_left = numpy.zeros((m.shape[0],omegas.shape[0])) k_right = numpy.zeros((m.shape[0],omegas.shape[0])) We iterate through all the dimensionless frequencies and compute the wavenumbers for all modes. .. code-block:: default for ii,omega_nondimensional in enumerate(omegas): omega = omega_nondimensional * td.speed_of_sound / radius f_decomb = omega / (2 * numpy.pi) k_left[:,ii] = numpy.real(td.get_wavenumber(m,n,f=f_decomb,sign=-1)) k_right[:,ii] = numpy.real(td.get_wavenumber(m,n,f=f_decomb,sign=1)) Finally, we plot the results. .. code-block:: default plt.figure(2) for mode in range(k_left.shape[0]): plt.plot(omegas,k_right[mode,:],"k") plt.plot(omegas, k_left[mode, :], "k") plt.text(0,0,"m = 0",bbox=dict(boxstyle="round", ec="k",fc="w"),**text_params) plt.text(numpy.max(omegas)*0.95,0,"m = "+str(numpy.max(m)), bbox=dict(boxstyle="round", ec="k",fc="w"),**text_params) plt.text(numpy.max(omegas)*0.5,numpy.max(k_right)*0.2,"cut-on right running", bbox=dict(boxstyle="round", ec="k",fc="w"),**text_params) plt.text(numpy.max(omegas)*0.5,numpy.min(k_left)*0.2,"cut-on left running", bbox=dict(boxstyle="round", ec="k",fc="w"),**text_params) plt.xlabel("$\omega$") plt.ylabel("$Re(k_{m0})$") plt.grid() plt.xlim(0,numpy.max(omegas)) plt.show() .. image:: /auto_examples/images/sphx_glr_plot_RienstraCutOns_002.png :alt: plot RienstraCutOns :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** ( 0 minutes 1.550 seconds) .. _sphx_glr_download_auto_examples_plot_RienstraCutOns.py: .. only :: html .. container:: sphx-glr-footer :class: sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_RienstraCutOns.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_RienstraCutOns.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_