def __design_angelino_nozzle(self, design_alt, truncate_ratio, CEA, r_e):
        """ Can be a class function, will edit going forwards
		"""
        (p_atm, T_atm, rho_atm) = gd.standard_atmosphere([design_alt])

        PR = CEA.p_c / p_atm

        M_e = gd.PR_expansion_mach(PR, CEA.gamma)

        expansion_ratio = gd.expansion_ratio(1, M_e, CEA.gamma)  #6.64 #8.1273
        # print('Exp. ratio: ' + str(expansion_ratio))
        # print('PR: ' + str(PR))

        A_t = r_e**2 * np.pi / expansion_ratio  # max expansion (r_b = 0, r_e**2 >= A_t*expansion_ratio/np.pi)

        return plug_nozzle(expansion_ratio,
                           A_t,
                           r_e,
                           CEA.gamma,
                           CEA.T_c,
                           CEA.p_c,
                           CEA.a_c,
                           CEA.rho_c,
                           1500,
                           truncate_ratio=truncate_ratio)
    def __init__(self,
                 design_alt,
                 r_e,
                 gamma,
                 T_c,
                 p_c,
                 a_c,
                 rho_c,
                 n,
                 truncate_ratio=1):
        # input design parameters

        (p_atm, T_atm, rho_atm) = gd.standard_atmosphere([design_alt])

        PR = p_c / p_atm

        M_e = gd.PR_expansion_mach(PR, gamma)

        expansion_ratio = gd.expansion_ratio(1, M_e, gamma)
        print('Expansion ratio: ' + str(expansion_ratio))

        self.expansion_ratio = expansion_ratio
        self.A_t = r_e**2 * np.pi / expansion_ratio
        self.r_e = r_e
        self.gamma = gamma
        self.n = n
        self.truncate_ratio = truncate_ratio

        self.T_c = T_c
        self.p_c = p_c
        self.a_c = a_c
        self.rho_c = rho_c

        # calculated design parameters
        self.A_e = self.A_t * self.expansion_ratio
        self.r_b = np.sqrt(-self.A_e / np.pi + self.r_e**2)
        self.M_e = optimize.fsolve(
            lambda M: gd.expansion_ratio_zero(1, M, self.gamma, self.
                                              expansion_ratio), 5)

        # DESIGN OF NOZZLE, FUNCTION ORDER IS IMPORTANT
        # NON-OPTIONAL FUNCTION RUNS
        self.design_nozzle()

        self.truncate_nozzle()

        self.calc_flow_properties()

        self.arc_length_coord()

        # OPTIONAL FUNCTION CONSTANTS
        self.converge_section = 0  # whether the converging section has been designed
    def update_contour(self, x, y, M, x_centre_spike=0):
        # Updates the spike contour with new (x,y) points with known values of M at each point
        self.x = x
        self.y = y
        self.M = M

        # optionally centre spike about x-axis
        if (x_centre_spike):
            self.centre_spike()

        # update flow properties based on isentropic expansion
        self.calc_flow_properties()

        # update arc length coordinates
        self.arc_length_coord()

        # update exit mach number
        self.M_e = M[-1]

        # update expansion ratio
        self.expansion_ratio = gd.expansion_ratio(1, self.M_e)

        self.A_t = self.r_e**2 * np.pi / self.expansion_ratio
        print(
            "Warning, throat area update not complete, assumes perfect isentropic expansion from throat to exit"
        )

        # update area estimation
        self.A = self.A_t * gd.expansion_ratio(1, self.M, self.gamma)
        # update base radius
        self.r_b = self.y[-1]

        # update exit area
        self.A_e = np.pi * (self.r_e**2 - self.r_b**2)

        if (self.converge_section):
            print(
                "Warning, congerence section not updated. Run self.converge_section(args) again to define a new convergence section."
            )
    def design_nozzle(self):
        # discrete contour design variables
        self.M = np.linspace(1, self.M_e, self.n)
        self.A = self.A_t * gd.expansion_ratio(1, self.M, self.gamma)
        self.alpha = gd.prandtl_meyer(self.M_e, self.gamma) - gd.prandtl_meyer(
            self.M, self.gamma) + gd.mach_angle(self.M)
        self.l = (self.r_e - np.sqrt(
            np.abs(self.r_e**2 -
                   (self.A * self.M * np.sin(self.alpha) / np.pi)))) / np.sin(
                       self.alpha)

        self.x = self.l * np.cos(self.alpha)
        self.y = self.l * np.sin(self.alpha)

        self.centre_spike()

        self.length = self.x.max()
def COST_FNC(design_alt, truncate_ratio, T_w, CEA, r_e, alpha, beta, n):

    ### DESIGNING NOZZLE
    (p_atm, T_atm, rho_atm) = gd.standard_atmosphere([design_alt])

    PR = CEA.p_c / p_atm

    M_e = gd.PR_expansion_mach(PR, CEA.gamma)

    expansion_ratio = gd.expansion_ratio(1, M_e, CEA.gamma)  #6.64 #8.1273
    # print('Exp. ratio: ' + str(expansion_ratio))
    # print('PR: ' + str(PR))

    A_t = r_e**2 * np.pi / expansion_ratio  # max expansion (r_b = 0, r_e**2 >= A_t*expansion_ratio/np.pi)

    spike = plug_nozzle(expansion_ratio,
                        A_t,
                        r_e,
                        CEA.gamma,
                        CEA.T_c,
                        CEA.p_c,
                        CEA.a_c,
                        CEA.rho_c,
                        n,
                        truncate_ratio=truncate_ratio)

    ### CALCULATING COST
    ##	thurst estimation over altitude
    alt_range = np.linspace(0, 12000, 30)
    (p_atm_r, T_atm_r, rho_atm_r) = gd.standard_atmosphere(alt_range)
    #print(CEA.p_c/p_atm_r)
    thrust_range = np.zeros(alt_range.shape)
    for i in range(alt_range.shape[0]):
        if i == 10:
            MOC_mesh = MOC.chr_mesh(spike,
                                    gamma,
                                    alt_range[i],
                                    50,
                                    downstream_factor=1.2,
                                    plot_chr=0)
        else:
            MOC_mesh = MOC.chr_mesh(spike,
                                    gamma,
                                    alt_range[i],
                                    50,
                                    downstream_factor=1.2,
                                    plot_chr=0)

        thrust_range[i] = MOC_mesh.compute_thrust('nearest', 10)

    work = np.trapz(thrust_range, alt_range)
    plt.plot(alt_range, thrust_range, 'o')
    plt.show()
    ## heat transfer required

    total_heat_flux = heat_flux(CEA.Pr, CEA.cp, CEA.gamma, CEA.c, CEA.w,
                                CEA.T_c, T_w, spike)

    # print('Work*alpha: ' + str(work*alpha))
    # print('Heat flux*beta: ' + str(total_heat_flux*beta))
    return -alpha * work + total_heat_flux * beta
    design_alt = 9144
    truncate_ratio = 1  # bounds on truncate < 0.1425

    gamma = 1.237  #np.mean([1.2534,1.2852])
    T_c = 2831.47  # combustion chamber temperature
    p_c = 3102640.8  # combustion chamber pressure
    rho_c = 3.3826  # combustion chamber density
    a_c = np.sqrt(gamma * (1 - 1 / gamma) * 200.07 *
                  T_c)  # combustion chamber sound speed
    (p_atm, T_atm, rho_atm) = gd.standard_atmosphere([design_alt])

    PR = p_c / p_atm

    M_e = gd.PR_expansion_mach(PR, gamma)

    expansion_ratio = gd.expansion_ratio(1, M_e, gamma)  #6.64 #8.1273
    # print('Exp. ratio: ' + str(expansion_ratio))
    # print('PR: ' + str(PR))

    A_t = r_e**2 * np.pi / expansion_ratio  # max expansion (r_b = 0, r_e**2 >= A_t*expansion_ratio/np.pi)

    plug1 = plug_nozzle(expansion_ratio,
                        A_t,
                        r_e,
                        gamma,
                        T_c,
                        p_c,
                        a_c,
                        rho_c,
                        1000,
                        truncate_ratio=1)