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]:
CD_Conical_Nozzle?
Init signature:
CD_Conical_Nozzle(
    Ri=0.4,
    Re=1.2,
    Rt=0.2,
    Rj=0.1,
    R0=0,
    theta_c=40,
    theta_N=15,
    **params,
)
Docstring:
    Convergent-Divergent nozzle with conical divergent.

    Examples
    --------

    Compute the length of a conical nozzle:

    >>> from pygasflow.nozzles import CD_Conical_Nozzle
    >>> Ri, Re, Rt = 0.4, 1.2, 0.2
    >>> nozzle = CD_Conical_Nozzle(Ri, Re, Rt, theta_c=30, theta_N=25)
    >>> nozzle.length
    np.float64(2.53988146753074)

    Change the angle of the divergent section and retrieve the new length
    of the nozzle:

    >>> nozzle.theta_N = 60
    >>> nozzle.length
    np.float64(1.0082903768654763)

    Visualize the nozzle:

    .. bokeh-plot::
        :source-position: above

        from pygasflow.nozzles import CD_Conical_Nozzle
        Ri, Re, Rt = 0.4, 1.2, 0.2
        nozzle = CD_Conical_Nozzle(Ri, Re, Rt, theta_c=30, theta_N=25)
        nozzle.plot(interactive=False)


Parameters of 'CD_Conical_Nozzle'
=================================

Parameters changed from their default values are marked in red.
Soft bound values are marked in cyan.
C/V= Constant/Variable, RO/RW = ReadOnly/ReadWrite, AN=Allow None

Name                     Value         Type      Bounds      Mode  

inlet_radius              0.4         Number     (0, 3)      V RW
outlet_radius             1.2         Number     (0, 3)      V RW
throat_radius             0.2         Number     (0, 3)      V RW
junction_radius_j         0.1         Number    (0, 0.5)     V RW
junction_radius_0          0          Number    (0, 0.5)     V RW
theta_c                    40         Number    (0, 90)      V RW
theta_N                    15         Number    (0, 90)      V RW
theta_e                    15         Number                 C RW
fractional_length         0.8         Number    (0.6, 1)     V RW
geometry_type        'axisymmetric'  Selector                V RW
N                         200        Integer   (10, 1000)    V RW
error_log                  ''         String                 V RW
is_interactive_app       False       Boolean                 V RW
title                      ''         String                 V RW
gamma                     1.4         Number     (1, 2)      V RW
n_lines                    10        Integer   (3, None)     V RW
inlet_area                0.0         Number   (0, None)     C RW
outlet_area               0.0         Number   (0, None)     C RW
throat_area               0.0         Number   (0, None)     C RW
length_convergent         0.0         Number               V RW AN
length_divergent          0.0         Number               V RW AN
length                    0.0         Number   (0, None)     V RW
length_array              None        Array                C RW AN
wall_radius_array         None        Array                C RW AN
area_ratio_array          None        Array                C RW AN
shockwave_location    (None, None)    Tuple                  C RW

Parameter docstrings:
=====================

inlet_radius:       Alias ``Ri`` in the constructor.
outlet_radius:      Alias ``Re`` in the constructor.
throat_radius:      Alias ``Rt`` in the constructor.
junction_radius_j:  Radius of the junction between convergent and divergent.
                    Alias ``Rj`` in the constructor.
junction_radius_0:  Radius of the junction between combustion chamber and convergent.
                    Alias ``R0`` in the constructor.
theta_c:            Half angle [degrees] of the convergent
theta_N:            Half angle [degrees] of the conical divergent
theta_e:            Half angle [degrees] of the conical divergent at the exit section.
fractional_length:  Fractional Length of the nozzle with respect to a same exit
                    area ratio conical nozzle with 15 deg half-cone angle.
                    Alias ``K`` in the constructor.
geometry_type:      Specify the geometry type of the nozzle:
                    
                    * ``"planar"``: the radius indicates the distance from the line
                      of symmetry and the nozzle wall. The area is computed with
                      ``A = 2 * r``. Note the lack of depth in the formula: this is
                      because it simplifies.
                    * ``"axisymmetric"``: the area is computed with
                      ``A = pi * r**2``.
N:                  Number of discretization elements along the length of the nozzle.
error_log:          Visualize on the interactive application any error that raises
                    from the computation.
is_interactive_app: If True, exceptions are going to be intercepted and shown on
                    error_log, otherwise fall back to the standard behaviour.
title:              < No docstring available >
gamma:              Ratio of specific heats, γ = Cp / Cv
n_lines:            < No docstring available >
inlet_area:         < No docstring available >
outlet_area:        < No docstring available >
throat_area:        < No docstring available >
length_convergent:  < No docstring available >
length_divergent:   < No docstring available >
length:             Total length of the nozzle, convergent + divergent.
length_array:       < No docstring available >
wall_radius_array:  < No docstring available >
area_ratio_array:   < No docstring available >
shockwave_location: Location of the shockwave in the divergent: (loc, radius).
Init docstring:
Parameters
----------
Ri : float
    Inlet radius.
Re : float
    Exit (outlet) radius.
Rt : float
    Throat radius.
R0 : float
    Radius of the junction between combustion chamber and convergent.
Rj : float
    Radius of the junction between convergent and divergent.
File:           ~/Documents/Development/pygasflow/pygasflow/nozzles/cd_conical.py
Type:           ParameterizedMetaclass
Subclasses:
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.

Axisymmetric nozzles

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

[3]:
Ri = 0.4         # inlet radius of the convergent section
Rt = 0.2         # throat radius
Re = 1.2         # exit (outlet) radius of the divergent section
Rj = 0.1         # junction radius between the convergent and divergent at
                 # the throat section. Used in the conical nozzle.
R0 = 0           # junction radius between the combustion chamber and the convergent
theta_c = 40     # half cone angle of the convergent section
theta_N = 15     # half cone angle of the divergent section
# 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_c, theta_N=theta_N, geometry_type=geom_type))
for k in K:
    nozzles.append(CD_TOP_Nozzle(Ri, Rt, R0, theta_c, k, geometry_type=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.27474774194546225
        Ld      3.7452160573276165
        L       4.019963799273079
Angles:
        theta_c 40
        theta_N 15

Here I plot the different nozzles for comparison.

[6]:
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()
    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-1_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

With planar nozzles the width is constant along the length of the nozzle. 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_c, theta_N=theta_N, geometry_type=geom_type)

# fractional length of the TOP nozzle
K = 0.7
top = CD_TOP_Nozzle(Ri, Rt, R0, theta_c, 0.7, geometry_type=geom_type)
print(top)
C-D TOP Nozzle
Radius:
        Ri      0.4
        Re      1.2000000000000002
        Rt      0.2
Areas:
        Ai      0.8
        Ae      2.4000000000000004
        At      0.4
Lengths:
        Lc      0.3475417887987028
        Ld      2.619476340869189
        L       2.967018129667892
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]:
x1, y1 = conical.build_geometry()
x2, y2 = top.build_geometry()
x3, y3 = moc.build_geometry()
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-1_19_0.png
[ ]: