Ejemplo n.º 1
0
def f(x):
    M4, M5 = x
    MFP5 = mach2mfp(M5, gam)
    MFP4 = mach2mfp(M4, gam)

    sqrt_T0_ratio = MFP5 / MFP4 * A_ratio * P0_ratio

    phi4 = MFP4 / M0rotor * (1 + (gam - 1) / 2 * M4**2)**(1 / (gam - 1))
    phi5 = MFP5 / M0rotor * (1 + (gam - 1) / 2 * M5**2)**(
        1 / (gam - 1)) * sqrt_T0_ratio

    psi = 1 + phi5 * tan(beta5) - phi4 * tan(alfa4)

    P0_ratio_new = (1 + (gam - 1) * psi * M0rotor**2)**(gam / (gam - 1))

    err_P0 = P0_ratio_new - P0_ratio
    err_MFP = MFP4 / MFP5 - A_ratio * P0_ratio**((2 * gam - 1) / (gam))

    return P0_ratio_new, err_MFP, psi
Ejemplo n.º 2
0
    def thrust(self, **params):
        gam_t = self.turbine.gam
        R_t = self.R_t
        MFP8 = min(params['MFP5'] * self.turbine.geom['A2'] / self.A8,
                   mach2mfp(1, gam_t))
        mdot = params['MFP5'] * self.turbine.geom['A2'] * params[
            'P05'] * gam_t**0.5 / (params['T05'] * R_t)**0.5
        M8 = mfp2mach(MFP8, gam_t)
        P8 = params['P05'] * (1 + (gam_t - 1) / 2 * M8**2)**(-gam_t /
                                                             (gam_t - 1))
        mdot5 = params['MFP5'] * self.turbine.geom['A2'] * params[
            'P05'] * gam_t**0.5 / (params['T05'] * R_t)**0.5
        T8 = params['T05'] * (1 + (gam_t - 1) / 2 * M8**2)**(-1)

        return mdot * M8 * (gam_t * R_t * T8)**0.5 + (
            P8 - self.P01 /
            (1 + (gam_t - 1) * params['M_flight']**2)**0.5) * self.A8
Ejemplo n.º 3
0
# coding: utf-8
from turbine import *
t = TurbineExtendedMap()
from mfp2mach import mach2mfp
import matplotlib.pyplot as plt
MFP_choke = mach2mfp(1, t.gam)
sol_cr = t.general_explicit_map({'MFP1': MFP_choke, 'MFP2': MFP_choke})
sol_almost_cr = t.general_explicit_map({'MFP1': 0.4, 'MFP2': 0.4})
print(sol_almost_cr)
t.initial_guess = sol_almost_cr.params

fig, (ax1, ax2) = plt.subplots(1, 2)

ax1.plot(sol_cr.params['MFP1'], sol_cr.params['P0_ratio'], 's')

ax1.plot(sol_almost_cr.params['MFP1'], sol_almost_cr.params['P0_ratio'], 's')
assert sol_almost_cr.success
print(sol_cr)

sol = sol_almost_cr
for MbMFP in reversed(np.linspace(0, sol_cr.params['MbMFP'])):
    sol = t.general_explicit_map({
        'MbMFP': MbMFP,
        'MFP1': MFP_choke
    },
                                 initial_guesses=sol.params)
    ax1.plot(sol.params['MbMFP'], 1 / sol.params['P0_ratio'], '+')
    ax2.plot(sol.params['MFP1'], sol.params['MFP2'], '+')
    if not sol.success:
        break
Ejemplo n.º 4
0
import numpy as np
import matplotlib.pyplot as plt

from mfp2mach import mach2mfp
import tccsty

gam = 1.3
mach = np.linspace(0, 4, 100)
mfp = mach2mfp(mach, gam)

plt.rcParams.update({
    'axes.spines.left': True,  # display axis spines
    'axes.spines.bottom': True,
    'axes.spines.top': False,
    'axes.spines.right': False,
    'axes.labelpad': 2,
})

plt.figure(figsize=(2, 1.5))
plt.tick_params(bottom=True, top=False, left=True, right=False)
plt.plot(mach, mfp, 'k', lw=tccsty.thick)
plt.xlim(0, 4)
plt.ylim(0, 0.6)
plt.xlabel('M')
plt.ylabel('MFP')
plt.xticks(range(5))

plt.savefig('mfp_fig.pdf')

plt.plot(2 * [1], [0, mach2mfp(1, gam)], 'r--')
plt.plot([0, 1], 2 * [mach2mfp(1, gam)], 'r--')
Ejemplo n.º 5
0
    def implicit_map(
            self,
            M_flight,  # flight mach number
            MFP,
            MFP3,
            Mb_c,
            T0_ratio_c,
            P0_ratio_c,  # compressor
            mdotf,
            T04,  # burner
            MFP4,
            MFP5,
            Mb_t,
            T0_ratio_t,
            P0_ratio_t  # turbine 
    ):
        """
        This function implements burner, nozzle and spool dynamics and integrates it with
        turbine and compressor maps

        Variable balance: 
            12 variables
          - 11 equations
        --------
             2 free choices (e.g. M_flight and mdotf)
             
        """

        # Expose constants
        A8 = self.A8
        FHV = self.FHV
        eta_combustion = self.eta_combustion
        A5 = self.turbine.geom['A2']
        gam_c = self.compressor.gam
        gam_t = self.turbine.gam
        cpc = self.cpc
        cpt = self.cpt
        T01 = self.T01
        P01 = self.P01
        R_c = self.R_c
        R_t = self.R_t

        ### Dimensionalize everything ###
        dim_params = self.dimensionalize(
            M_flight,  # flight mach number
            MFP,
            MFP3,
            Mb_c,
            T0_ratio_c,
            P0_ratio_c,  # compressor
            mdotf,
            T04,  # burner
            MFP4,
            MFP5,
            Mb_t,
            T0_ratio_t,
            P0_ratio_t  # turbine 
        )
        T02 = dim_params.T02
        T03 = dim_params.T03
        T05 = dim_params.T05
        P02 = dim_params.P02
        P03 = dim_params.P03
        P04 = dim_params.P04
        P05 = dim_params.P05
        omega_c = dim_params.omega_c
        omega_t = dim_params.omega_t
        mdot2 = dim_params.mdot2
        mdot3 = dim_params.mdot3
        mdot4 = dim_params.mdot4
        mdot5 = dim_params.mdot5

        ### CONSTRAINTS ###
        # * Energy addition in ther burner
        res_T04 = T03 + mdotf * FHV * eta_combustion / (mdot3 * cpc) - T04
        # * Spool has constant speed
        res_omega = omega_c - omega_t

        # * Conservation of energy in the spool
        res_energy = mdot2 * cpc * (T03 - T02) - mdot4 * cpt * (T04 - T05)

        # * Consevation of mass in the combustor
        res_mdot = mdot3 + mdotf - mdot4

        # * Nozzle exit is either choked or at ambient pressure
        Pa = P01 / (1 + (gam_c - 1) / 2 * M_flight**2)**(gam_c / (gam_c - 1))
        MFP8 = MFP5 * A5 / A8
        res_MFP_nozzle = (P05 / Pa - 1) * MFP8 - (P05 / Pa - 1) * mach2mfp(
            min(1, (2 / (gam_t - 1) * ((P05 / Pa)**(
                (gam_t - 1) / gam_t) - 1))**0.5) if P05 / Pa > 1 else 0, gam_t)

        ### remove dimensions of residuals ###
        # References for removing dimensions of residuals

        mdotref = (T01 * R_c)**0.5 / (P01 * gam_c**0.5 *
                                      self.compressor.geom['A1'])
        h_ref = cpc * T01
        omega_ref = (gam_c * R_c * T01)**0.5 / self.compressor.geom['D2']

        #remove dimensions
        res_omega /= omega_ref
        res_energy /= h_ref * mdotref
        res_mdot /= mdotref
        res_T04 /= T04

        ### COMPRESSOR MAP ###
        res_MFP_c, res_T0_ratio_c, res_P0_ratio_c = self.compressor.implicit_map(
            MFP, MFP3, Mb_c, T0_ratio_c, P0_ratio_c, tol=1e-13)
        ### TURBINE MAP ###
        res_MFP_t, res_T0_ratio_t, res_P0_ratio_t = self.turbine.implicit_map(
            MFP4, MFP5, Mb_t, T0_ratio_t, P0_ratio_t, tol=1e-13)

        return (res_omega, res_energy, res_mdot, res_MFP_nozzle, res_T04,
                res_MFP_c, res_T0_ratio_c, res_P0_ratio_c, res_MFP_t,
                res_T0_ratio_t, res_P0_ratio_t)
Ejemplo n.º 6
0
    def dimensionalize(
            self,
            M_flight,  # flight mach number
            MFP,
            MFP3,
            Mb_c,
            T0_ratio_c,
            P0_ratio_c,  # compressor
            mdotf,
            T04,  # burner
            MFP4,
            MFP5,
            Mb_t,
            T0_ratio_t,
            P0_ratio_t  # turbine 
    ):
        gam_c = self.compressor.gam
        gam_t = self.turbine.gam
        T01 = self.T01
        P01 = self.P01
        R_c = self.R_c
        R_t = self.R_t

        ### Dimensionalize everything ###
        a01 = (gam_c * R_c * T01)**0.5
        a04 = (gam_t * R_t * T04)**0.5
        T02 = T01
        T03 = T02 * T0_ratio_c
        T04 = T04
        T05 = T04 * T0_ratio_t
        P02 = P01
        P03 = P02 * P0_ratio_c
        P04 = P03
        P05 = P03 * P0_ratio_t
        omega_c = Mb_c * a01 / (self.compressor.geom['D2'] / 2)
        omega_t = Mb_t * a04 / (self.turbine.geom['D1t'] / 2)
        mdot2 = MFP * self.compressor.geom['A1'] * P01 * gam_c**0.5 / (
            T01 * R_c)**0.5
        mdot3 = MFP3 * self.compressor.geom['A2'] * P03 * gam_c**0.5 / (
            T03 * R_c)**0.5
        mdot4 = MFP4 * self.turbine.geom['A1'] * P04 * gam_t**0.5 / (T04 *
                                                                     R_t)**0.5
        mdot5 = MFP5 * self.turbine.geom['A2'] * P05 * gam_t**0.5 / (T05 *
                                                                     R_t)**0.5

        #Nozzle
        MFP8 = min(MFP5 * self.turbine.geom['A2'] / self.A8,
                   mach2mfp(1, gam_t))
        M8 = mfp2mach(MFP8, gam_t)
        P8 = P05 * (1 + (gam_t - 1) / 2 * M8**2)**(-gam_t / (gam_t - 1))
        T8 = T05 * (1 + (gam_t - 1) / 2 * M8**2)**(-1)

        dim_params = DimensionalParameters(T02=T02,
                                           T03=T03,
                                           T04=T04,
                                           T05=T05,
                                           T8=T8,
                                           P02=P02,
                                           P03=P03,
                                           P04=P04,
                                           P05=P05,
                                           P8=P8,
                                           omega_c=omega_c,
                                           omega_t=omega_t,
                                           mdot2=mdot2,
                                           mdot3=mdot3,
                                           mdot4=mdot4,
                                           mdot5=mdot5)

        return dim_params
Ejemplo n.º 7
0
    def plot_map(self,
                 ax,
                 extent=None,
                 samples=25,
                 grid=False,
                 choke_line=True):

        if extent is None:
            xmin, xmax = ax.get_xlim()
            ymin, ymax = ax.get_ylim()
        else:
            xmin, xmax, ymin, ymax = extent

        #Choke line
        if choke_line:
            MFP_choke = mach2mfp(1, self.gam)
            sol = self.general_explicit_map({
                'MFP1': 0.9 * MFP_choke,
                'MFP2': 0.9 * MFP_choke
            })
            MbMFP = np.linspace(sol.params['MbMFP'], xmax, samples * 5)
            pr_choke = np.empty_like(MbMFP)
            for i, MbMFP_ in enumerate(MbMFP):
                if sol.success:
                    old_sol = sol
                sol = self.general_explicit_map(
                    {
                        'MbMFP': MbMFP_,
                        'MFP2': MFP_choke
                    },
                    initial_guesses=old_sol.params)
                pr_choke[i] = sol.params['P0_ratio'] if sol.success else np.nan

            ax.plot(MbMFP, 1 / pr_choke, 'k--', linewidth=0.8)

        #Map

        MbMFP, P0_ratio = np.meshgrid(np.linspace(xmin, xmax, samples),
                                      np.linspace(1 / ymax, 1 / ymin, samples))

        params = gridmap(self, MbMFP, P0_ratio, 'MbMFP')

        params['eff'] = (self.gam - 1) / self.gam * np.log(P0_ratio) / np.log(
            params['T0_ratio'])

        if grid:
            ax.plot(MbMFP, 1 / P0_ratio, 'k,')

        CS = ax.contour(MbMFP,
                        1 / P0_ratio,
                        params['Mb'],
                        levels=np.arange(0, 2, 0.1),
                        colors='k',
                        linewidths=tccsty.thick)
        ax.clabel(CS, CS.levels, fmt='%.1f', rightside_up=False)
        CS.collections[0].set_label('$M_{bt}$')

        #CS2 = ax.contour(MbMFP, 1/P0_ratio, params['eff'], colors='k', linewidths=0.4,
        #                  levels=[0.5,0.8,0.9,0.95])
        #CS2.collections[0].set_label(r'$\eta_p$')
        #ax.clabel(CS2, CS2.levels, fmt='%.2f')

        ax.set_xlabel(r"$M_{bt}\text{MFP}_4$")
        ax.set_ylabel(r"\[\frac{P_{04}}{P_{05}}\]", labelpad=16, rotation=0)
Ejemplo n.º 8
0
    def plot_map(self,
                 ax,
                 P0_min=1,
                 P0_max=4,
                 samples=25,
                 plot=False,
                 grid=False,
                 choke=True):

        MFP_choke = mach2mfp(1, self.gam)
        sol_cr = self.general_explicit_map({
            'MFP1': MFP_choke,
            'MFP2': MFP_choke
        })
        sol_P1 = self.general_explicit_map({
            'MFP2': MFP_choke,
            'P0_ratio': P0_min
        })

        def MFP_max(P0_ratio):
            MFP = np.interp(
                P0_ratio,
                [sol_P1.params['P0_ratio'], sol_cr.params['P0_ratio']],
                [sol_P1.params['MFP1'], sol_cr.params['MFP1']])
            return MFP

        P0_ratio = np.linspace(P0_min, P0_max, samples)
        P0_grid = np.empty((samples, samples))
        MFP_grid = np.empty_like(P0_grid)
        for i, p in enumerate(P0_ratio):
            MFP = np.linspace(1e-6, MFP_max(p), samples)
            MFP_grid[:, i] = MFP
            P0_grid[:, i] = p

        params = gridmap(self, MFP_grid, P0_grid, 'MFP1', plot=plot)
        params['eff'] = (self.gam - 1) / self.gam * np.log(P0_grid) / np.log(
            params['T0_ratio'])

        if grid:
            ax.plot(MFP_grid, P0_grid, 'k,')

        #Add choke 20% before maximum rpm
        if choke:
            index_cr = np.argmin(params['Mb'], axis=0)
            for i, i_cr in enumerate(np.ceil(0.8 * index_cr).astype(int)):
                params['Mb'][:i_cr, i] = np.nan
                params['eff'][:i_cr, i] = np.nan

        CS = ax.contour(MFP_grid,
                        P0_grid,
                        params['Mb'],
                        levels=np.arange(0, 2, 0.1),
                        colors='k',
                        linewidths=tccsty.thick)
        ax.clabel(CS, CS.levels, fmt='%.1f')
        #CS.collections[0].set_label('$M_{bc}$')
        CS2 = ax.contour(MFP_grid,
                         P0_grid,
                         params['eff'],
                         colors='k',
                         linewidths=tccsty.thin,
                         levels=np.arange(0.0, 1.01, 0.05))
        #CS2.collections[0].set_label(r'$\eta_p$')
        ax.clabel(CS2, CS2.levels[-5:], fmt='%.2f')
        ax.plot([MFP_choke, MFP_choke, sol_P1.params['MFP1']],
                [P0_max, sol_cr.params['P0_ratio'], P0_min],
                'k--')  #, label='choke limit')
        ax.set_xlim((0, 0.6))
        ax.set_ylim((1, 4))
        ax.set_xlabel("MFP")
        ax.set_ylabel(r"\[\frac{P_{03}}{P_{02}}\]", labelpad=16, rotation=0)