C-D Nozzles

pygasflow comes with a nozzle subpackage, aimed to build and visuale different nozzle designs.

At the time of writing, three different nozzles are implemented: 1. CD_Conical_Nozzle: the nozzle’s divergent is conical. Support both planar and axisymmetric geometry. 2. CD_TOP_Nozzle: Thrust Optimized Parabolic, based on Rao’s parabolic approximation. Support both planar and axisymmetric geometry. 3. CD_Min_Length_Nozzle: Minimum Length Nozzle built with the Method of Characteristics where the expansion takes place through a centered Prandtl-Meyer wave emanating from a sharp corner throat. Support only planar geometry.

[1]:
import numpy as np
import matplotlib.pyplot as plt
from pygasflow.nozzles import (
    CD_Conical_Nozzle,
    CD_TOP_Nozzle,
    CD_Min_Length_Nozzle
)

Let’s look at the help, for example about the CD_Conical_Nozzle:

[2]:
help(CD_Conical_Nozzle)
Help on class CD_Conical_Nozzle in module pygasflow.nozzles.cd_conical:

class CD_Conical_Nozzle(pygasflow.nozzles.nozzle_geometry.Nozzle_Geometry)
 |  CD_Conical_Nozzle(Ri, Re, Rt, Rj, R0, theta_c, theta_N=15, geometry_type='axisymmetric', N=100)
 |
 |  Convergent-Divergent nozzle with conical divergent.
 |
 |  Examples
 |  --------
 |
 |  .. plot::
 |     :context: reset
 |     :format: python
 |     :include-source: True
 |
 |     from pygasflow import CD_Conical_Nozzle
 |     import matplotlib.pyplot as plt
 |     Ri = 0.4
 |     Re = 1.2
 |     Rt = 0.2
 |     geom = CD_Conical_Nozzle(Ri, Re, Rt, 0.15, 1, 30, 25)
 |     x, y = geom.build_geometry(100)
 |     plt.figure()
 |     plt.plot(x, y)
 |     plt.xlabel("Length")
 |     plt.ylabel("Radius")
 |     plt.grid()
 |     plt.axis('equal')
 |     plt.show()
 |
 |  Method resolution order:
 |      CD_Conical_Nozzle
 |      pygasflow.nozzles.nozzle_geometry.Nozzle_Geometry
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __init__(self, Ri, Re, Rt, Rj, R0, theta_c, theta_N=15, geometry_type='axisymmetric', N=100)
 |      Parameters
 |      ----------
 |      Ri : float
 |          Inlet radius.
 |      Re : float
 |          Exit (outlet) radius.
 |      Rt : float
 |          Throat radius.
 |      Rj : float
 |          Radius of the junction between convergent and divergent.
 |      R0 : float
 |          Radius of the junction between combustion chamber and convergent.
 |      theta_c : float
 |          Half angle [degrees] of the convergent.
 |      theta_N : float
 |          Half angle [degrees] of the conical divergent. Default to 15 deg.
 |      geometry_type : string
 |          Specify the geometry type of the nozzle. Can be either
 |          ``'axisymmetric'`` or ``'planar'``.
 |          If ``'planar'`` is specified, Ri, Re, Rt will be considered as
 |          half of the height of the respective sections (therefore, R is the
 |          distance from the line of symmetry and the nozzle wall).
 |          To compute the cross section area, "axisymmetric" uses the formula
 |          A = pi * r**2, whereas "planar" uses the formula A = 2 * r. Note
 |          the lack of width in the planar formula, this is because in the
 |          area ratios it simplifies, hence it is not considere here.
 |      N : int
 |          Number of discretization elements along the length of the nozzle.
 |          Default to 100.
 |
 |  __str__(self)
 |      Return str(self).
 |
 |  build_geometry(self, N)
 |      Discretize the length of the nozzle and compute the nozzle profile.
 |
 |      Parameters
 |      ----------
 |      N : int
 |          Number of discretization elements along the length of the nozzle. Default to 100.
 |
 |      Returns
 |      -------
 |      x : array_like
 |          x-coordinate along the nozzle length.
 |      y : array_like
 |          y_coordinate of the nozzle wall.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  intersection_points
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from pygasflow.nozzles.nozzle_geometry.Nozzle_Geometry:
 |
 |  get_points(self, area_ratio=False, offset=1.2)
 |      Helper function used to construct a matrix of points representing
 |      the nozzle for visualization purposes.
 |
 |      Parameters
 |      ----------
 |      area_ratio : Boolean
 |          If True, represents the area ratio A/A*. Otherwise, represents
 |          the radius. Default to False.
 |      offset : float
 |          Used to construct the container (or the walls) of the nozzle.
 |          The container radius is equal to offset * max_nozzle_radius.
 |
 |      Returns
 |      -------
 |          points_top : np.ndarray [Nx2]
 |              Matrix representing the wall at the top of the nozzle.
 |          points_mid : np.ndarray [Nx2]
 |              Matrix representing the flow area.
 |          points_bottom : np.ndarray [Nx2]
 |              Matrix representing the wall at the bottom of the nozzle.
 |
 |  location_divergent_from_area_ratio(self, A_ratio)
 |      Given an area ratio, compute the location on the divergent where
 |      this area ratio is located.
 |
 |      Parameters
 |      ----------
 |      A_ratio : float
 |          A / At
 |
 |      Returns
 |      -------
 |      x : float
 |          x-coordinate along the divergent length.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from pygasflow.nozzles.nozzle_geometry.Nozzle_Geometry:
 |
 |  area_ratio_array
 |
 |  critical_area
 |
 |  critical_radius
 |
 |  inlet_area
 |
 |  inlet_radius
 |
 |  length
 |
 |  length_array
 |
 |  length_convergent
 |
 |  length_divergent
 |
 |  outlet_area
 |
 |  outlet_radius
 |
 |  wall_radius_array
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from pygasflow.nozzles.nozzle_geometry.Nozzle_Geometry:
 |
 |  __dict__
 |      dictionary for instance variables (if defined)
 |
 |  __weakref__
 |      list of weak references to the object (if defined)

We can see that to construct a nozzle we need to use a bunch of radius for different sections and junctions.
We can specify the geometry type (axisymmetric or planar), from which the nozzle will compute the areas. With axisymmetric geometry, the nozzle uses a circular cross section. With planar nozzle, the radius is defined as half height of the nozzle section.

We can also see a bunch of methods, that can get us the respective nozzle values (like Critical_Radius, Inlet_Radius, ….)

Axisymmetric nozzles

Axisymmetric nozzles use a circular cross section. Let’s define the important parameters:

[3]:
# inlet radius of the convergent section
Ri = 0.4
# throat radius
Rt = 0.2
# exit (outlet) radius of the divergent section
Re = 1.2
# junction radius between the convergent and divergent at the throat section. Used in the conical nozzle.
Rj = 0.1
# junction radius between the combustion chamber and the convergent
R0 = 0.2
# half cone angle of the convergent section
theta_c = 40
# half cone angle of the divergent section
theta_N = 15
# fractional lengths. Used to construct TOP nozzles.
K = [0.6, 0.7, 0.8, 0.9, 1]

Here I create a nozzles list for convenience. The different nozzles will be appended to this list. Note that I also specify the geometry type to be axisymmetric.

[4]:
geom_type = "axisymmetric"
nozzles = []
nozzles.append(CD_Conical_Nozzle(Ri, Re, Rt, Rj, R0, theta_c, theta_N, geom_type))
for k in K:
    nozzles.append(CD_TOP_Nozzle(Ri, Re, Rt, R0, theta_c, k, geom_type))

I can print the nozzle object to get a textual description. We can notice that the areas have been computed using the circular area formula. I can access the different values with the methods seen above.

[5]:
print(nozzles[0])
C-D Conical Nozzle
Radius:
        Ri      0.4
        Re      1.2
        Rt      0.2
Areas:
        Ai      0.5026548245743669
        Ae      4.523893421169302
        At      0.12566370614359174
Lengths:
        Lc      0.3475417887987027
        Ld      3.7452160573276165
        L       4.092757846126319
Angles:
        theta_c 40
        theta_N 15

Here I plot the different nozzles for comparison.

[6]:
# number of discretization points along the nozzle length
N = 1000
plt.figure()

for i, g in enumerate(nozzles):
    lbl = "Conical"
    if i != 0:
        lbl = "TOP: K = {}".format(K[i-1])
    x, y = g.build_geometry(N)
    plt.plot(x, y, label=lbl)
plt.legend()
plt.xlabel("Length")
plt.ylabel("Radius")
plt.title("Axisymmetric")
plt.minorticks_on()
plt.grid(which='major', linestyle='-', alpha=0.7)
plt.grid(which='minor', linestyle=':', alpha=0.5)
plt.axis('equal')
plt.show()
../_images/examples_tut-7_13_0.png

The difference in the convergent’s length between conical and TOP nozzles is due to the different throat junction radius. Rao’s TOP nozzle uses a prescribed radius, whereas in the conical nozzle we can specify the radius we’d like.

From this picture we can also appreciate the Fractional Length of the nozzle with respect to a same exit area ratio conical nozzle with 15 deg half-cone angle.

Planar Nozzles

Planar nozzles do not use a circular cross section. Think of them having a rectangular cross section: the width is constant along the length of the nozzle, therefore in the area ratios the width simplify. For this reason, we can discard the width, and think about the area as a unit area.

In this case, the radius corresponds to half height of the cross section (the distance from the line of symmetry of the planar nozzle, to the wall).

[7]:
geom_type = "planar"

conical = CD_Conical_Nozzle(Ri, Re, Rt, Rj, R0, theta_c, theta_N, geom_type)

# fractional length of the TOP nozzle
K = 0.7
top = CD_TOP_Nozzle(Ri, Re, Rt, R0, theta_c, 0.7, geom_type)
print(top)
C-D TOP Nozzle
Radius:
        Ri      0.4
        Re      1.2
        Rt      0.2
Areas:
        Ai      0.8
        Ae      2.4
        At      0.4
Lengths:
        Lc      0.4203358356519432
        Ld      2.6194763408691877
        L       3.039812176521131
Angles:
        theta_c 40
        theta_N 29.526881404482012
        theta_e 14.248957413040683

For the CD_Min_Length_Nozzle we also need to specify the specific heats ratio of the gas and the number of characteristics lines to use.

[8]:
# number of characteristics
n = 15
# specific heats ratio
gamma = 1.4

moc = CD_Min_Length_Nozzle(Ri, Re, Rt, Rj, R0, theta_c, n, gamma)
[9]:
N = 1000
x1, y1 = conical.build_geometry(N)
x2, y2 = top.build_geometry(N)
x3, y3 = moc.build_geometry(N)
plt.figure()
plt.plot(x1, y1, label="conical")
plt.plot(x2, y2, label="TOP: K = {}".format(top.Fractional_Length))
plt.plot(x3, y3, label="MOC")
plt.legend()
plt.xlabel("Length")
plt.ylabel("Half Height")
plt.title("Planar")
plt.minorticks_on()
plt.grid(which='major', linestyle='-', alpha=0.7)
plt.grid(which='minor', linestyle=':', alpha=0.5)
plt.axis('equal')
plt.show()
../_images/examples_tut-7_19_0.png
[ ]: