예제 #1
0
    def setup(self):

        thermo_spec = pyc.species_data.janaf
        design = self.options['design']
        cooling = self.options['cooling']

        self.pyc_add_element(
            'fc',
            pyc.FlightConditions(thermo_data=thermo_spec,
                                 elements=pyc.AIR_MIX))
        self.pyc_add_element(
            'inlet',
            pyc.Inlet(design=design,
                      thermo_data=thermo_spec,
                      elements=pyc.AIR_MIX))
        self.pyc_add_element('fan',
                             pyc.Compressor(map_data=FanMap,
                                            design=design,
                                            thermo_data=thermo_spec,
                                            elements=pyc.AIR_MIX,
                                            map_extrap=True,
                                            bleed_names=[]),
                             promotes_inputs=[('Nmech', 'Fan_Nmech')])
        self.pyc_add_element(
            'splitter',
            pyc.Splitter(design=design,
                         thermo_data=thermo_spec,
                         elements=pyc.AIR_MIX))
        self.pyc_add_element(
            'duct2',
            pyc.Duct(design=design,
                     expMN=2.0,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_MIX))
        self.pyc_add_element('lpc',
                             pyc.Compressor(map_data=LPCMap,
                                            design=design,
                                            thermo_data=thermo_spec,
                                            elements=pyc.AIR_MIX,
                                            map_extrap=True),
                             promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.pyc_add_element('bld25',
                             pyc.BleedOut(design=design, bleed_names=['sbv']))
        self.pyc_add_element(
            'duct25',
            pyc.Duct(design=design,
                     expMN=2.0,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_MIX))
        self.pyc_add_element(
            'hpc',
            pyc.Compressor(map_data=HPCMap,
                           design=design,
                           thermo_data=thermo_spec,
                           elements=pyc.AIR_MIX,
                           map_extrap=True,
                           bleed_names=['bld_inlet', 'bld_exit', 'cust']),
            promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.pyc_add_element(
            'bld3',
            pyc.BleedOut(design=design, bleed_names=['bld_inlet', 'bld_exit']))
        self.pyc_add_element(
            'burner',
            pyc.Combustor(design=design,
                          thermo_data=thermo_spec,
                          inflow_elements=pyc.AIR_MIX,
                          air_fuel_elements=pyc.AIR_FUEL_MIX,
                          fuel_type='Jet-A(g)'))
        self.pyc_add_element('hpt',
                             pyc.Turbine(map_data=HPTMap,
                                         design=design,
                                         thermo_data=thermo_spec,
                                         elements=pyc.AIR_FUEL_MIX,
                                         map_extrap=True,
                                         bleed_names=['bld_inlet',
                                                      'bld_exit']),
                             promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.pyc_add_element(
            'duct45',
            pyc.Duct(design=design,
                     expMN=2.0,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_FUEL_MIX))
        self.pyc_add_element('lpt',
                             pyc.Turbine(map_data=LPTMap,
                                         design=design,
                                         thermo_data=thermo_spec,
                                         elements=pyc.AIR_FUEL_MIX,
                                         map_extrap=True,
                                         bleed_names=['bld_inlet',
                                                      'bld_exit']),
                             promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.pyc_add_element(
            'duct5',
            pyc.Duct(design=design,
                     expMN=2.0,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_FUEL_MIX))
        self.pyc_add_element(
            'core_nozz',
            pyc.Nozzle(nozzType='CV',
                       lossCoef='Cv',
                       thermo_data=thermo_spec,
                       elements=pyc.AIR_FUEL_MIX))

        self.pyc_add_element(
            'byp_bld', pyc.BleedOut(design=design, bleed_names=['bypBld']))
        self.pyc_add_element(
            'duct17',
            pyc.Duct(design=design,
                     expMN=2.0,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_MIX))
        self.pyc_add_element(
            'byp_nozz',
            pyc.Nozzle(nozzType='CV',
                       lossCoef='Cv',
                       thermo_data=thermo_spec,
                       elements=pyc.AIR_MIX))

        self.pyc_add_element('fan_shaft',
                             pyc.Shaft(num_ports=2),
                             promotes_inputs=[('Nmech', 'Fan_Nmech')])
        self.pyc_add_element('gearbox',
                             pyc.Gearbox(design=design),
                             promotes_inputs=[('N_in', 'LP_Nmech'),
                                              ('N_out', 'Fan_Nmech')])
        self.pyc_add_element('lp_shaft',
                             pyc.Shaft(num_ports=3),
                             promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.pyc_add_element('hp_shaft',
                             pyc.Shaft(num_ports=2),
                             promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.pyc_add_element('perf',
                             pyc.Performance(num_nozzles=2, num_burners=1))

        self.connect('inlet.Fl_O:tot:P', 'perf.Pt2')
        self.connect('hpc.Fl_O:tot:P', 'perf.Pt3')
        self.connect('burner.Wfuel', 'perf.Wfuel_0')
        self.connect('inlet.F_ram', 'perf.ram_drag')
        self.connect('core_nozz.Fg', 'perf.Fg_0')
        self.connect('byp_nozz.Fg', 'perf.Fg_1')

        self.connect('fan.trq', 'fan_shaft.trq_0')
        self.connect('gearbox.trq_out', 'fan_shaft.trq_1')
        self.connect('gearbox.trq_in', 'lp_shaft.trq_0')
        self.connect('lpc.trq', 'lp_shaft.trq_1')
        self.connect('lpt.trq', 'lp_shaft.trq_2')
        self.connect('hpc.trq', 'hp_shaft.trq_0')
        self.connect('hpt.trq', 'hp_shaft.trq_1')
        self.connect('fc.Fl_O:stat:P', 'core_nozz.Ps_exhaust')
        self.connect('fc.Fl_O:stat:P', 'byp_nozz.Ps_exhaust')

        self.add_subsystem(
            'ext_ratio',
            om.ExecComp(
                'ER = core_V_ideal * core_Cv / ( byp_V_ideal *  byp_Cv )',
                core_V_ideal={
                    'value': 1000.0,
                    'units': 'ft/s'
                },
                core_Cv={
                    'value': 0.98,
                    'units': None
                },
                byp_V_ideal={
                    'value': 1000.0,
                    'units': 'ft/s'
                },
                byp_Cv={
                    'value': 0.98,
                    'units': None
                },
                ER={
                    'value': 1.4,
                    'units': None
                }))

        self.connect('core_nozz.ideal_flow.V', 'ext_ratio.core_V_ideal')
        self.connect('byp_nozz.ideal_flow.V', 'ext_ratio.byp_V_ideal')

        main_order = [
            'fc', 'inlet', 'fan', 'splitter', 'duct2', 'lpc', 'bld25',
            'duct25', 'hpc', 'bld3', 'burner', 'hpt', 'duct45', 'lpt', 'duct5',
            'core_nozz', 'byp_bld', 'duct17', 'byp_nozz', 'gearbox',
            'fan_shaft', 'lp_shaft', 'hp_shaft', 'perf', 'ext_ratio'
        ]

        balance = self.add_subsystem('balance', om.BalanceComp())
        if design:

            balance.add_balance('FAR', eq_units='degR', lower=1e-4, val=.017)
            self.connect('balance.FAR', 'burner.Fl_I:FAR')
            self.connect('burner.Fl_O:tot:T', 'balance.lhs:FAR')

            balance.add_balance('lpt_PR',
                                val=10.937,
                                lower=1.001,
                                upper=20,
                                eq_units='hp',
                                rhs_val=0.,
                                res_ref=1e4)
            self.connect('balance.lpt_PR', 'lpt.PR')
            self.connect('lp_shaft.pwr_net', 'balance.lhs:lpt_PR')

            balance.add_balance('hpt_PR',
                                val=4.185,
                                lower=1.001,
                                upper=8,
                                eq_units='hp',
                                rhs_val=0.,
                                res_ref=1e4)
            self.connect('balance.hpt_PR', 'hpt.PR')
            self.connect('hp_shaft.pwr_net', 'balance.lhs:hpt_PR')

            balance.add_balance('gb_trq',
                                val=23928.0,
                                units='ft*lbf',
                                eq_units='hp',
                                rhs_val=0.0)
            self.connect('balance.gb_trq', 'gearbox.trq_base')
            self.connect('fan_shaft.pwr_net', 'balance.lhs:gb_trq')

            balance.add_balance('hpc_PR', val=14.0, units=None, eq_units=None)
            self.connect('balance.hpc_PR', ['hpc.PR', 'opr_calc.HPCPR'])
            # self.connect('perf.OPR', 'balance.lhs:hpc_PR')
            self.connect('opr_calc.OPR_simple', 'balance.lhs:hpc_PR')

            balance.add_balance('fan_eff',
                                val=0.9689,
                                units=None,
                                eq_units=None)
            self.connect('balance.fan_eff', 'fan.eff')
            self.connect('fan.eff_poly', 'balance.lhs:fan_eff')

            balance.add_balance('lpc_eff',
                                val=0.8895,
                                units=None,
                                eq_units=None)
            self.connect('balance.lpc_eff', 'lpc.eff')
            self.connect('lpc.eff_poly', 'balance.lhs:lpc_eff')

            # balance.add_balance('hpc_eff', val=0.8470, units=None, eq_units=None)
            # self.connect('balance.hpc_eff', 'hpc.eff')
            # self.connect('hpc.eff_poly', 'balance.lhs:hpc_eff')

            balance.add_balance('hpt_eff',
                                val=0.9226,
                                units=None,
                                eq_units=None)
            self.connect('balance.hpt_eff', 'hpt.eff')
            self.connect('hpt.eff_poly', 'balance.lhs:hpt_eff')

            balance.add_balance('lpt_eff',
                                val=0.9401,
                                units=None,
                                eq_units=None)
            self.connect('balance.lpt_eff', 'lpt.eff')
            self.connect('lpt.eff_poly', 'balance.lhs:lpt_eff')

            self.add_subsystem(
                'hpc_CS',
                om.ExecComp('CS = Win *(pow(Tout/518.67,0.5)/(Pout/14.696))',
                            Win={
                                'value': 10.0,
                                'units': 'lbm/s'
                            },
                            Tout={
                                'value': 14.696,
                                'units': 'degR'
                            },
                            Pout={
                                'value': 518.67,
                                'units': 'psi'
                            },
                            CS={
                                'value': 10.0,
                                'units': 'lbm/s'
                            }))
            self.connect('duct25.Fl_O:stat:W', 'hpc_CS.Win')
            self.connect('hpc.Fl_O:tot:T', 'hpc_CS.Tout')
            self.connect('hpc.Fl_O:tot:P', 'hpc_CS.Pout')
            self.add_subsystem(
                'hpc_EtaBalance',
                SmallCoreEffBalance(eng_type='large', tech_level=0))
            self.connect('hpc_CS.CS', 'hpc_EtaBalance.CS')
            self.connect('hpc.eff_poly', 'hpc_EtaBalance.eta_p')
            self.connect('hpc_EtaBalance.eta_a', 'hpc.eff')

            self.add_subsystem(
                'fan_dia',
                om.ExecComp('FanDia = 2.0*(area/(pi*(1.0-hub_tip**2.0)))**0.5',
                            area={
                                'value': 7000.0,
                                'units': 'inch**2'
                            },
                            hub_tip={
                                'value': 0.3125,
                                'units': None
                            },
                            FanDia={
                                'value': 100.0,
                                'units': 'inch'
                            }))
            self.connect('inlet.Fl_O:stat:area', 'fan_dia.area')

            self.add_subsystem(
                'opr_calc',
                om.ExecComp('OPR_simple = FPR*LPCPR*HPCPR',
                            FPR={
                                'value': 1.3,
                                'units': None
                            },
                            LPCPR={
                                'value': 3.0,
                                'units': None
                            },
                            HPCPR={
                                'value': 14.0,
                                'units': None
                            },
                            OPR_simple={
                                'value': 55.0,
                                'units': None
                            }))

            # order_add = ['hpc_CS', 'fan_dia', 'opr_calc']
            order_add = ['hpc_CS', 'hpc_EtaBalance', 'fan_dia', 'opr_calc']

        else:

            balance.add_balance('FAR', val=0.017, lower=1e-4, eq_units='lbf')
            self.connect('balance.FAR', 'burner.Fl_I:FAR')
            self.connect('perf.Fn', 'balance.lhs:FAR')
            # self.connect('burner.Fl_O:tot:T', 'balance.lhs:FAR')

            balance.add_balance('W',
                                units='lbm/s',
                                lower=10.,
                                upper=2500.,
                                eq_units='inch**2')
            self.connect('balance.W', 'fc.W')
            self.connect('core_nozz.Throat:stat:area', 'balance.lhs:W')

            balance.add_balance('BPR', lower=15., upper=40.)
            self.connect('balance.BPR', 'splitter.BPR')
            self.connect('fan.map.RlineMap', 'balance.lhs:BPR')

            balance.add_balance('fan_Nmech',
                                val=2000.0,
                                units='rpm',
                                lower=500.,
                                eq_units='hp',
                                rhs_val=0.,
                                res_ref=1e2)
            self.connect('balance.fan_Nmech', 'Fan_Nmech')
            self.connect('fan_shaft.pwr_net', 'balance.lhs:fan_Nmech')

            balance.add_balance('lp_Nmech',
                                val=6000.0,
                                units='rpm',
                                lower=500.,
                                eq_units='hp',
                                rhs_val=0.,
                                res_ref=1e2)
            self.connect('balance.lp_Nmech', 'LP_Nmech')
            self.connect('lp_shaft.pwr_net', 'balance.lhs:lp_Nmech')

            balance.add_balance('hp_Nmech',
                                val=20000.0,
                                units='rpm',
                                lower=500.,
                                eq_units='hp',
                                rhs_val=0.,
                                res_ref=1e2)
            self.connect('balance.hp_Nmech', 'HP_Nmech')
            self.connect('hp_shaft.pwr_net', 'balance.lhs:hp_Nmech')

            order_add = []

        if cooling:
            self.add_subsystem(
                'hpt_cooling',
                pyc.TurbineCooling(n_stages=2,
                                   thermo_data=pyc.species_data.janaf,
                                   T_metal=2460.))
            self.add_subsystem('hpt_chargable', pyc.CombineCooling(n_ins=3))

            self.pyc_connect_flow('bld3.bld_inlet',
                                  'hpt_cooling.Fl_cool',
                                  connect_stat=False)
            self.pyc_connect_flow('burner.Fl_O', 'hpt_cooling.Fl_turb_I')
            self.pyc_connect_flow('hpt.Fl_O', 'hpt_cooling.Fl_turb_O')

            self.connect('hpt_cooling.row_1.W_cool', 'hpt_chargable.W_1')
            self.connect('hpt_cooling.row_2.W_cool', 'hpt_chargable.W_2')
            self.connect('hpt_cooling.row_3.W_cool', 'hpt_chargable.W_3')
            self.connect('hpt.power', 'hpt_cooling.turb_pwr')

            balance.add_balance('hpt_nochrg_cool_frac',
                                val=0.063660111,
                                lower=0.02,
                                upper=.15,
                                eq_units='lbm/s')
            self.connect('balance.hpt_nochrg_cool_frac',
                         'bld3.bld_inlet:frac_W')
            self.connect('bld3.bld_inlet:stat:W',
                         'balance.lhs:hpt_nochrg_cool_frac')
            self.connect('hpt_cooling.row_0.W_cool',
                         'balance.rhs:hpt_nochrg_cool_frac')

            balance.add_balance('hpt_chrg_cool_frac',
                                val=0.07037185,
                                lower=0.02,
                                upper=.15,
                                eq_units='lbm/s')
            self.connect('balance.hpt_chrg_cool_frac', 'bld3.bld_exit:frac_W')
            self.connect('bld3.bld_exit:stat:W',
                         'balance.lhs:hpt_chrg_cool_frac')
            self.connect('hpt_chargable.W_cool',
                         'balance.rhs:hpt_chrg_cool_frac')

            order_add = ['hpt_cooling', 'hpt_chargable']

        self.set_order(main_order + order_add + ['balance'])

        self.pyc_connect_flow('fc.Fl_O', 'inlet.Fl_I')
        self.pyc_connect_flow('inlet.Fl_O', 'fan.Fl_I')
        self.pyc_connect_flow('fan.Fl_O', 'splitter.Fl_I')
        self.pyc_connect_flow('splitter.Fl_O1', 'duct2.Fl_I')
        self.pyc_connect_flow('duct2.Fl_O', 'lpc.Fl_I')
        self.pyc_connect_flow('lpc.Fl_O', 'bld25.Fl_I')
        self.pyc_connect_flow('bld25.Fl_O', 'duct25.Fl_I')
        self.pyc_connect_flow('duct25.Fl_O', 'hpc.Fl_I')
        self.pyc_connect_flow('hpc.Fl_O', 'bld3.Fl_I')
        self.pyc_connect_flow('bld3.Fl_O', 'burner.Fl_I')
        self.pyc_connect_flow('burner.Fl_O', 'hpt.Fl_I')
        self.pyc_connect_flow('hpt.Fl_O', 'duct45.Fl_I')
        self.pyc_connect_flow('duct45.Fl_O', 'lpt.Fl_I')
        self.pyc_connect_flow('lpt.Fl_O', 'duct5.Fl_I')
        self.pyc_connect_flow('duct5.Fl_O', 'core_nozz.Fl_I')
        self.pyc_connect_flow('splitter.Fl_O2', 'byp_bld.Fl_I')
        self.pyc_connect_flow('byp_bld.Fl_O', 'duct17.Fl_I')
        self.pyc_connect_flow('duct17.Fl_O', 'byp_nozz.Fl_I')

        self.pyc_connect_flow('hpc.bld_inlet',
                              'lpt.bld_inlet',
                              connect_stat=False)
        self.pyc_connect_flow('hpc.bld_exit',
                              'lpt.bld_exit',
                              connect_stat=False)
        self.pyc_connect_flow('bld3.bld_inlet',
                              'hpt.bld_inlet',
                              connect_stat=False)
        self.pyc_connect_flow('bld3.bld_exit',
                              'hpt.bld_exit',
                              connect_stat=False)

        newton = self.nonlinear_solver = om.NewtonSolver()
        newton.options['atol'] = 1e-4
        newton.options['rtol'] = 1e-4
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 10
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 10
        newton.options['reraise_child_analysiserror'] = False
        # newton.linesearch = om.BoundsEnforceLS()
        newton.linesearch = om.ArmijoGoldsteinLS()
        # newton.linesearch.options['maxiter'] = 2
        newton.linesearch.options['bound_enforcement'] = 'scalar'
        newton.linesearch.options['iprint'] = -1
        # if design:
        #     newton.linesearch.options['print_bound_enforce'] = True

        # newton.options['debug_print'] = True

        self.linear_solver = om.DirectSolver(assemble_jac=True)
예제 #2
0
    def setup(self):
        thermo_spec = pyc.species_data.janaf
        design = self.options['design']

        self.pyc_add_element(
            'fc',
            pyc.FlightConditions(thermo_data=thermo_spec,
                                 elements=pyc.AIR_ELEMENTS))
        # Inlet Components
        self.pyc_add_element(
            'inlet',
            pyc.Inlet(design=design,
                      thermo_data=thermo_spec,
                      elements=pyc.AIR_ELEMENTS))
        self.pyc_add_element(
            'inlet_duct',
            pyc.Duct(design=design,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_ELEMENTS))
        # Fan Components - Split here for CFD integration Add a CFDStart Compomponent
        self.pyc_add_element('fan',
                             pyc.Compressor(map_data=pyc.AXI5,
                                            design=design,
                                            thermo_data=thermo_spec,
                                            elements=pyc.AIR_ELEMENTS,
                                            map_extrap=True),
                             promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.pyc_add_element(
            'splitter',
            pyc.Splitter(design=design,
                         thermo_data=thermo_spec,
                         elements=pyc.AIR_ELEMENTS))
        # Core Stream components
        self.pyc_add_element(
            'splitter_core_duct',
            pyc.Duct(design=design,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_ELEMENTS))
        self.pyc_add_element('lpc',
                             pyc.Compressor(map_data=pyc.LPCMap,
                                            design=design,
                                            thermo_data=thermo_spec,
                                            elements=pyc.AIR_ELEMENTS,
                                            map_extrap=True),
                             promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.pyc_add_element(
            'lpc_duct',
            pyc.Duct(design=design,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_ELEMENTS))
        self.pyc_add_element('hpc',
                             pyc.Compressor(map_data=pyc.HPCMap,
                                            design=design,
                                            thermo_data=thermo_spec,
                                            elements=pyc.AIR_ELEMENTS,
                                            bleed_names=['cool1'],
                                            map_extrap=True),
                             promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.pyc_add_element(
            'bld3', pyc.BleedOut(design=design, bleed_names=['cool3']))
        self.pyc_add_element(
            'burner',
            pyc.Combustor(design=design,
                          thermo_data=thermo_spec,
                          inflow_elements=pyc.AIR_ELEMENTS,
                          air_fuel_elements=pyc.AIR_FUEL_ELEMENTS,
                          fuel_type='Jet-A(g)'))
        self.pyc_add_element('hpt',
                             pyc.Turbine(map_data=pyc.HPTMap,
                                         design=design,
                                         thermo_data=thermo_spec,
                                         elements=pyc.AIR_FUEL_ELEMENTS,
                                         bleed_names=['cool3'],
                                         map_extrap=True),
                             promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.pyc_add_element(
            'hpt_duct',
            pyc.Duct(design=design,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_FUEL_ELEMENTS))
        self.pyc_add_element('lpt',
                             pyc.Turbine(map_data=pyc.LPTMap,
                                         design=design,
                                         thermo_data=thermo_spec,
                                         elements=pyc.AIR_FUEL_ELEMENTS,
                                         bleed_names=['cool1'],
                                         map_extrap=True),
                             promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.pyc_add_element(
            'lpt_duct',
            pyc.Duct(design=design,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_FUEL_ELEMENTS))
        # Bypass Components
        self.pyc_add_element(
            'bypass_duct',
            pyc.Duct(design=design,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_ELEMENTS))
        # Mixer component
        self.pyc_add_element(
            'mixer',
            pyc.Mixer(design=design,
                      designed_stream=1,
                      Fl_I1_elements=pyc.AIR_FUEL_ELEMENTS,
                      Fl_I2_elements=pyc.AIR_ELEMENTS))
        self.pyc_add_element(
            'mixer_duct',
            pyc.Duct(design=design,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_FUEL_ELEMENTS))
        # Afterburner Components
        self.pyc_add_element(
            'afterburner',
            pyc.Combustor(design=design,
                          thermo_data=thermo_spec,
                          inflow_elements=pyc.AIR_FUEL_ELEMENTS,
                          air_fuel_elements=pyc.AIR_FUEL_ELEMENTS,
                          fuel_type='Jet-A(g)'))
        # End CFD HERE
        # Nozzle
        self.pyc_add_element(
            'mixed_nozz',
            pyc.Nozzle(nozzType='CD',
                       lossCoef='Cfg',
                       thermo_data=thermo_spec,
                       elements=pyc.AIR_FUEL_ELEMENTS))

        # Mechanical components
        self.pyc_add_element('lp_shaft',
                             pyc.Shaft(num_ports=3),
                             promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.pyc_add_element('hp_shaft',
                             pyc.Shaft(num_ports=2),
                             promotes_inputs=[('Nmech', 'HP_Nmech')])

        # Aggregating component
        self.pyc_add_element('perf',
                             pyc.Performance(num_nozzles=1, num_burners=2))

        # Connnect flow path
        self.pyc_connect_flow('fc.Fl_O', 'inlet.Fl_I')
        self.pyc_connect_flow('inlet.Fl_O', 'inlet_duct.Fl_I')
        self.pyc_connect_flow('inlet_duct.Fl_O', 'fan.Fl_I')
        self.pyc_connect_flow('fan.Fl_O', 'splitter.Fl_I')
        # Core connections
        self.pyc_connect_flow('splitter.Fl_O1', 'splitter_core_duct.Fl_I')
        self.pyc_connect_flow('splitter_core_duct.Fl_O', 'lpc.Fl_I')
        self.pyc_connect_flow('lpc.Fl_O', 'lpc_duct.Fl_I')
        self.pyc_connect_flow('lpc_duct.Fl_O', 'hpc.Fl_I')
        self.pyc_connect_flow('hpc.Fl_O', 'bld3.Fl_I')
        self.pyc_connect_flow('bld3.Fl_O', 'burner.Fl_I')
        self.pyc_connect_flow('burner.Fl_O', 'hpt.Fl_I')
        self.pyc_connect_flow('hpt.Fl_O', 'hpt_duct.Fl_I')
        self.pyc_connect_flow('hpt_duct.Fl_O', 'lpt.Fl_I')
        self.pyc_connect_flow('lpt.Fl_O', 'lpt_duct.Fl_I')
        self.pyc_connect_flow('lpt_duct.Fl_O', 'mixer.Fl_I1')
        # Bypass Connections
        self.pyc_connect_flow('splitter.Fl_O2', 'bypass_duct.Fl_I')
        self.pyc_connect_flow('bypass_duct.Fl_O', 'mixer.Fl_I2')

        #Mixer Connections
        self.pyc_connect_flow('mixer.Fl_O', 'mixer_duct.Fl_I')
        # After Burner
        self.pyc_connect_flow('mixer_duct.Fl_O', 'afterburner.Fl_I')

        # Nozzle
        self.pyc_connect_flow('afterburner.Fl_O', 'mixed_nozz.Fl_I')

        # Connect cooling flows
        self.pyc_connect_flow('hpc.cool1', 'lpt.cool1', connect_stat=False)
        self.pyc_connect_flow('bld3.cool3', 'hpt.cool3', connect_stat=False)

        # Make additional model connections
        self.connect('inlet.Fl_O:tot:P', 'perf.Pt2')
        self.connect('hpc.Fl_O:tot:P', 'perf.Pt3')
        self.connect('burner.Wfuel', 'perf.Wfuel_0')
        self.connect('afterburner.Wfuel', 'perf.Wfuel_1')
        self.connect('inlet.F_ram', 'perf.ram_drag')
        self.connect('mixed_nozz.Fg', 'perf.Fg_0')

        self.connect('fan.trq', 'lp_shaft.trq_0')
        self.connect('lpc.trq', 'lp_shaft.trq_1')
        self.connect('lpt.trq', 'lp_shaft.trq_2')
        self.connect('hpc.trq', 'hp_shaft.trq_0')
        self.connect('hpt.trq', 'hp_shaft.trq_1')
        self.connect('fc.Fl_O:stat:P', 'mixed_nozz.Ps_exhaust')

        # Add balence components to close the implicit components
        balance = self.add_subsystem('balance', om.BalanceComp())
        if design:
            balance.add_balance('W',
                                lower=1e-3,
                                upper=200.,
                                units='lbm/s',
                                eq_units='lbf')
            self.connect('balance.W', 'fc.W')
            self.connect('perf.Fn', 'balance.lhs:W')
            # self.add_subsystem('wDV',IndepVarComp('wDes',100,units='lbm/s'))
            # self.connect('wDV.wDes','fc.W')

            balance.add_balance('BPR', eq_units=None, lower=0.25, val=5.0)
            self.connect('balance.BPR', 'splitter.BPR')
            self.connect('mixer.ER', 'balance.lhs:BPR')

            balance.add_balance('FAR_core',
                                eq_units='degR',
                                lower=1e-4,
                                val=.017)
            self.connect('balance.FAR_core', 'burner.Fl_I:FAR')
            self.connect('burner.Fl_O:tot:T', 'balance.lhs:FAR_core')

            balance.add_balance('FAR_ab',
                                eq_units='degR',
                                lower=1e-4,
                                val=.017)
            self.connect('balance.FAR_ab', 'afterburner.Fl_I:FAR')
            self.connect('afterburner.Fl_O:tot:T', 'balance.lhs:FAR_ab')

            balance.add_balance('lpt_PR',
                                val=1.5,
                                lower=1.001,
                                upper=8,
                                eq_units='hp',
                                use_mult=True,
                                mult_val=-1)
            self.connect('balance.lpt_PR', 'lpt.PR')
            self.connect('lp_shaft.pwr_in', 'balance.lhs:lpt_PR')
            self.connect('lp_shaft.pwr_out', 'balance.rhs:lpt_PR')

            balance.add_balance('hpt_PR',
                                val=1.5,
                                lower=1.001,
                                upper=8,
                                eq_units='hp',
                                use_mult=True,
                                mult_val=-1)
            self.connect('balance.hpt_PR', 'hpt.PR')
            self.connect('hp_shaft.pwr_in', 'balance.lhs:hpt_PR')
            self.connect('hp_shaft.pwr_out', 'balance.rhs:hpt_PR')
        else:

            balance.add_balance('W',
                                lower=1e-3,
                                upper=200.,
                                units='lbm/s',
                                eq_units='inch**2')
            self.connect('balance.W', 'fc.W')
            self.connect('mixed_nozz.Throat:stat:area', 'balance.lhs:W')

            balance.add_balance('BPR', lower=0.25, upper=5.0, eq_units='psi')
            self.connect('balance.BPR', 'splitter.BPR')
            self.connect('mixer.Fl_I1_calc:stat:P', 'balance.lhs:BPR')
            self.connect('bypass_duct.Fl_O:stat:P', 'balance.rhs:BPR')

            balance.add_balance('FAR_core',
                                eq_units='degR',
                                lower=1e-4,
                                upper=.06,
                                val=.017)
            self.connect('balance.FAR_core', 'burner.Fl_I:FAR')
            self.connect('burner.Fl_O:tot:T', 'balance.lhs:FAR_core')

            balance.add_balance('FAR_ab',
                                eq_units='degR',
                                lower=1e-4,
                                upper=.06,
                                val=.017)
            self.connect('balance.FAR_ab', 'afterburner.Fl_I:FAR')
            self.connect('afterburner.Fl_O:tot:T', 'balance.lhs:FAR_ab')

            balance.add_balance('LP_Nmech',
                                val=1.,
                                units='rpm',
                                lower=500.,
                                eq_units='hp',
                                use_mult=True,
                                mult_val=-1)
            self.connect('balance.LP_Nmech', 'LP_Nmech')
            self.connect('lp_shaft.pwr_in', 'balance.lhs:LP_Nmech')
            self.connect('lp_shaft.pwr_out', 'balance.rhs:LP_Nmech')

            balance.add_balance('HP_Nmech',
                                val=1.,
                                units='rpm',
                                lower=500.,
                                eq_units='hp',
                                use_mult=True,
                                mult_val=-1)
            self.connect('balance.HP_Nmech', 'HP_Nmech')
            self.connect('hp_shaft.pwr_in', 'balance.lhs:HP_Nmech')
            self.connect('hp_shaft.pwr_out', 'balance.rhs:HP_Nmech')

        # Off design
        newton = self.nonlinear_solver = om.NewtonSolver()
        newton.options['atol'] = 1e-6
        newton.options['rtol'] = 1e-10
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 10
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 100
        newton.options['reraise_child_analysiserror'] = False
        newton.linesearch = om.BoundsEnforceLS()
        newton.linesearch.options['bound_enforcement'] = 'scalar'
        newton.linesearch.options['iprint'] = -1

        self.linear_solver = om.DirectSolver(assemble_jac=True)
예제 #3
0
    def setup(self):
        #Setup the problem by including all the relavant components here - comp, burner, turbine etc

        #Create any relavent short hands here:
        design = self.options['design']

        USE_TABULAR = False
        if USE_TABULAR:
            self.options['thermo_method'] = 'TABULAR'
            self.options['thermo_data'] = pyc.AIR_JETA_TAB_SPEC
            FUEL_TYPE = 'FAR'
        else:
            self.options['thermo_method'] = 'CEA'
            self.options['thermo_data'] = pyc.species_data.janaf
            FUEL_TYPE = 'Jet-A(g)'

        #Add subsystems to build the engine deck:
        self.add_subsystem('fc', pyc.FlightConditions())
        self.add_subsystem('inlet', pyc.Inlet())

        # Note variable promotion for the fan --
        # the LP spool speed and the fan speed are INPUTS that are promoted:
        # Note here that promotion aliases are used. Here Nmech is being aliased to LP_Nmech
        # check out: http://openmdao.org/twodocs/versions/latest/features/core_features/grouping_components/add_subsystem.html?highlight=alias
        self.add_subsystem('fan',
                           pyc.Compressor(map_data=pyc.FanMap,
                                          bleed_names=[],
                                          map_extrap=True),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.add_subsystem('splitter', pyc.Splitter())
        self.add_subsystem('duct4', pyc.Duct())
        self.add_subsystem('lpc',
                           pyc.Compressor(map_data=pyc.LPCMap,
                                          map_extrap=True),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.add_subsystem('duct6', pyc.Duct())
        self.add_subsystem('hpc',
                           pyc.Compressor(
                               map_data=pyc.HPCMap,
                               bleed_names=['cool1', 'cool2', 'cust'],
                               map_extrap=True),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem('bld3',
                           pyc.BleedOut(bleed_names=['cool3', 'cool4']))
        self.add_subsystem('burner', pyc.Combustor(fuel_type=FUEL_TYPE))
        self.add_subsystem('hpt',
                           pyc.Turbine(map_data=pyc.HPTMap,
                                       bleed_names=['cool3', 'cool4'],
                                       map_extrap=True),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem('duct11', pyc.Duct())
        self.add_subsystem('lpt',
                           pyc.Turbine(map_data=pyc.LPTMap,
                                       bleed_names=['cool1', 'cool2'],
                                       map_extrap=True),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.add_subsystem('duct13', pyc.Duct())
        self.add_subsystem('core_nozz', pyc.Nozzle(nozzType='CV',
                                                   lossCoef='Cv'))

        self.add_subsystem('byp_bld', pyc.BleedOut(bleed_names=['bypBld']))
        self.add_subsystem('duct15', pyc.Duct())
        self.add_subsystem('byp_nozz', pyc.Nozzle(nozzType='CV',
                                                  lossCoef='Cv'))

        #Create shaft instances. Note that LP shaft has 3 ports! => no gearbox
        self.add_subsystem('lp_shaft',
                           pyc.Shaft(num_ports=3),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.add_subsystem('hp_shaft',
                           pyc.Shaft(num_ports=2),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem('perf', pyc.Performance(num_nozzles=2,
                                                   num_burners=1))

        # Now use the explicit connect method to make connections -- connect(<from>, <to>)

        #Connect the inputs to perf group
        self.connect('inlet.Fl_O:tot:P', 'perf.Pt2')
        self.connect('hpc.Fl_O:tot:P', 'perf.Pt3')
        self.connect('burner.Wfuel', 'perf.Wfuel_0')
        self.connect('inlet.F_ram', 'perf.ram_drag')
        self.connect('core_nozz.Fg', 'perf.Fg_0')
        self.connect('byp_nozz.Fg', 'perf.Fg_1')

        #LP-shaft connections
        self.connect('fan.trq', 'lp_shaft.trq_0')
        self.connect('lpc.trq', 'lp_shaft.trq_1')
        self.connect('lpt.trq', 'lp_shaft.trq_2')
        #HP-shaft connections
        self.connect('hpc.trq', 'hp_shaft.trq_0')
        self.connect('hpt.trq', 'hp_shaft.trq_1')
        #Ideally expanding flow by conneting flight condition static pressure to nozzle exhaust pressure
        self.connect('fc.Fl_O:stat:P', 'core_nozz.Ps_exhaust')
        self.connect('fc.Fl_O:stat:P', 'byp_nozz.Ps_exhaust')

        #Create a balance component
        # Balances can be a bit confusing, here's some explanation -
        #   State Variables:
        #           (W)        Inlet mass flow rate to implictly balance thrust
        #                      LHS: perf.Fn  == RHS: Thrust requirement (set when TF is instantiated)
        #
        #           (FAR)      Fuel-air ratio to balance Tt4
        #                      LHS: burner.Fl_O:tot:T  == RHS: Tt4 target (set when TF is instantiated)
        #
        #           (lpt_PR)   LPT press ratio to balance shaft power on the low spool
        #           (hpt_PR)   HPT press ratio to balance shaft power on the high spool
        # Ref: look at the XDSM diagrams in the pyCycle paper and this:
        # http://openmdao.org/twodocs/versions/latest/features/building_blocks/components/balance_comp.html

        balance = self.add_subsystem('balance', om.BalanceComp())
        if design:
            balance.add_balance('W', units='lbm/s', eq_units='lbf')
            #Here balance.W is implicit state variable that is the OUTPUT of balance object
            self.connect(
                'balance.W',
                'fc.W')  #Connect the output of balance to the relevant input
            self.connect(
                'perf.Fn', 'balance.lhs:W'
            )  #This statement makes perf.Fn the LHS of the balance eqn.
            self.promotes('balance', inputs=[('rhs:W', 'Fn_DES')])

            balance.add_balance('FAR', eq_units='degR', lower=1e-4, val=.017)
            self.connect('balance.FAR', 'burner.Fl_I:FAR')
            self.connect('burner.Fl_O:tot:T', 'balance.lhs:FAR')
            self.promotes('balance', inputs=[('rhs:FAR', 'T4_MAX')])

            # Note that for the following two balances the mult val is set to -1 so that the NET torque is zero
            balance.add_balance('lpt_PR',
                                val=1.5,
                                lower=1.001,
                                upper=8,
                                eq_units='hp',
                                use_mult=True,
                                mult_val=-1)
            self.connect('balance.lpt_PR', 'lpt.PR')
            self.connect('lp_shaft.pwr_in_real', 'balance.lhs:lpt_PR')
            self.connect('lp_shaft.pwr_out_real', 'balance.rhs:lpt_PR')

            balance.add_balance('hpt_PR',
                                val=1.5,
                                lower=1.001,
                                upper=8,
                                eq_units='hp',
                                use_mult=True,
                                mult_val=-1)
            self.connect('balance.hpt_PR', 'hpt.PR')
            self.connect('hp_shaft.pwr_in_real', 'balance.lhs:hpt_PR')
            self.connect('hp_shaft.pwr_out_real', 'balance.rhs:hpt_PR')

        else:

            #In OFF-DESIGN mode we need to redefine the balances:
            #   State Variables:
            #           (W)        Inlet mass flow rate to balance core flow area
            #                      LHS: core_nozz.Throat:stat:area == Area from DESIGN calculation
            #
            #           (FAR)      Fuel-air ratio to balance Thrust req.
            #                      LHS: perf.Fn  == RHS: Thrust requirement (set when TF is instantiated)
            #
            #           (BPR)      Bypass ratio to balance byp. noz. area
            #                      LHS: byp_nozz.Throat:stat:area == Area from DESIGN calculation
            #
            #           (lp_Nmech)   LP spool speed to balance shaft power on the low spool
            #           (hp_Nmech)   HP spool speed to balance shaft power on the high spool

            if self.options['throttle_mode'] == 'T4':
                balance.add_balance('FAR',
                                    val=0.017,
                                    lower=1e-4,
                                    eq_units='degR')
                self.connect('balance.FAR', 'burner.Fl_I:FAR')
                self.connect('burner.Fl_O:tot:T', 'balance.lhs:FAR')
                self.promotes('balance', inputs=[('rhs:FAR', 'T4_MAX')])

            elif self.options['throttle_mode'] == 'percent_thrust':
                balance.add_balance('FAR',
                                    val=0.017,
                                    lower=1e-4,
                                    eq_units='lbf',
                                    use_mult=True)
                self.connect('balance.FAR', 'burner.Fl_I:FAR')
                self.connect('perf.Fn', 'balance.rhs:FAR')
                self.promotes('balance',
                              inputs=[('mult:FAR', 'PC'),
                                      ('lhs:FAR', 'Fn_max')])

            balance.add_balance('W',
                                units='lbm/s',
                                lower=10.,
                                upper=1000.,
                                eq_units='inch**2')
            self.connect('balance.W', 'fc.W')
            self.connect('core_nozz.Throat:stat:area', 'balance.lhs:W')

            balance.add_balance('BPR', lower=2., upper=10., eq_units='inch**2')
            self.connect('balance.BPR', 'splitter.BPR')
            self.connect('byp_nozz.Throat:stat:area', 'balance.lhs:BPR')

            # Again for the following two balances the mult val is set to -1 so that the NET torque is zero
            balance.add_balance('lp_Nmech',
                                val=1.5,
                                units='rpm',
                                lower=500.,
                                eq_units='hp',
                                use_mult=True,
                                mult_val=-1)
            self.connect('balance.lp_Nmech', 'LP_Nmech')
            self.connect('lp_shaft.pwr_in_real', 'balance.lhs:lp_Nmech')
            self.connect('lp_shaft.pwr_out_real', 'balance.rhs:lp_Nmech')

            balance.add_balance('hp_Nmech',
                                val=1.5,
                                units='rpm',
                                lower=500.,
                                eq_units='hp',
                                use_mult=True,
                                mult_val=-1)
            self.connect('balance.hp_Nmech', 'HP_Nmech')
            self.connect('hp_shaft.pwr_in_real', 'balance.lhs:hp_Nmech')
            self.connect('hp_shaft.pwr_out_real', 'balance.rhs:hp_Nmech')

            # Specify the order in which the subsystems are executed:

            # self.set_order(['balance', 'fc', 'inlet', 'fan', 'splitter', 'duct4', 'lpc', 'duct6', 'hpc', 'bld3', 'burner', 'hpt', 'duct11',
            #                 'lpt', 'duct13', 'core_nozz', 'byp_bld', 'duct15', 'byp_nozz', 'lp_shaft', 'hp_shaft', 'perf'])

        # Set up all the flow connections:
        self.pyc_connect_flow('fc.Fl_O', 'inlet.Fl_I')
        self.pyc_connect_flow('inlet.Fl_O', 'fan.Fl_I')
        self.pyc_connect_flow('fan.Fl_O', 'splitter.Fl_I')
        self.pyc_connect_flow('splitter.Fl_O1', 'duct4.Fl_I')
        self.pyc_connect_flow('duct4.Fl_O', 'lpc.Fl_I')
        self.pyc_connect_flow('lpc.Fl_O', 'duct6.Fl_I')
        self.pyc_connect_flow('duct6.Fl_O', 'hpc.Fl_I')
        self.pyc_connect_flow('hpc.Fl_O', 'bld3.Fl_I')
        self.pyc_connect_flow('bld3.Fl_O', 'burner.Fl_I')
        self.pyc_connect_flow('burner.Fl_O', 'hpt.Fl_I')
        self.pyc_connect_flow('hpt.Fl_O', 'duct11.Fl_I')
        self.pyc_connect_flow('duct11.Fl_O', 'lpt.Fl_I')
        self.pyc_connect_flow('lpt.Fl_O', 'duct13.Fl_I')
        self.pyc_connect_flow('duct13.Fl_O', 'core_nozz.Fl_I')
        self.pyc_connect_flow('splitter.Fl_O2', 'byp_bld.Fl_I')
        self.pyc_connect_flow('byp_bld.Fl_O', 'duct15.Fl_I')
        self.pyc_connect_flow('duct15.Fl_O', 'byp_nozz.Fl_I')

        #Bleed flows:
        self.pyc_connect_flow('hpc.cool1', 'lpt.cool1', connect_stat=False)
        self.pyc_connect_flow('hpc.cool2', 'lpt.cool2', connect_stat=False)
        self.pyc_connect_flow('bld3.cool3', 'hpt.cool3', connect_stat=False)
        self.pyc_connect_flow('bld3.cool4', 'hpt.cool4', connect_stat=False)

        #Specify solver settings:
        newton = self.nonlinear_solver = om.NewtonSolver()
        newton.options['atol'] = 1e-8

        # set this very small, so it never activates and we rely on atol
        newton.options['rtol'] = 1e-99
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 50
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 1000
        newton.options['reraise_child_analysiserror'] = False
        # ls = newton.linesearch = BoundsEnforceLS()
        ls = newton.linesearch = om.ArmijoGoldsteinLS()
        ls.options['maxiter'] = 3
        ls.options['rho'] = 0.75
        # ls.options['print_bound_enforce'] = True

        self.linear_solver = om.DirectSolver()

        super().setup()
예제 #4
0
    def setup(self):

        thermo_spec = pyc.species_data.janaf
        design = self.options['design']

        self.add_subsystem(
            'fc',
            pyc.FlightConditions(thermo_data=thermo_spec,
                                 elements=pyc.AIR_MIX))
        self.add_subsystem(
            'inlet',
            pyc.Inlet(design=design,
                      thermo_data=thermo_spec,
                      elements=pyc.AIR_MIX))
        self.add_subsystem('fan',
                           pyc.Compressor(map_data=pyc.FanMap,
                                          design=design,
                                          thermo_data=thermo_spec,
                                          elements=pyc.AIR_MIX,
                                          bleed_names=[],
                                          map_extrap=True),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.add_subsystem(
            'splitter',
            pyc.Splitter(design=design,
                         thermo_data=thermo_spec,
                         elements=pyc.AIR_MIX))
        self.add_subsystem(
            'duct4',
            pyc.Duct(design=design,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_MIX))
        self.add_subsystem('lpc',
                           pyc.Compressor(map_data=pyc.LPCMap,
                                          design=design,
                                          thermo_data=thermo_spec,
                                          elements=pyc.AIR_MIX,
                                          map_extrap=True),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.add_subsystem(
            'duct6',
            pyc.Duct(design=design,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_MIX))
        self.add_subsystem('hpc',
                           pyc.Compressor(
                               map_data=pyc.HPCMap,
                               design=design,
                               thermo_data=thermo_spec,
                               elements=pyc.AIR_MIX,
                               bleed_names=['cool1', 'cool2', 'cust'],
                               map_extrap=True),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem(
            'bld3', pyc.BleedOut(design=design, bleed_names=['cool3',
                                                             'cool4']))
        self.add_subsystem(
            'burner',
            pyc.Combustor(design=design,
                          thermo_data=thermo_spec,
                          inflow_elements=pyc.AIR_MIX,
                          air_fuel_elements=pyc.AIR_FUEL_MIX,
                          fuel_type='Jet-A(g)'))
        self.add_subsystem('hpt',
                           pyc.Turbine(map_data=pyc.HPTMap,
                                       design=design,
                                       thermo_data=thermo_spec,
                                       elements=pyc.AIR_FUEL_MIX,
                                       bleed_names=['cool3', 'cool4'],
                                       map_extrap=True),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem(
            'duct11',
            pyc.Duct(design=design,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_FUEL_MIX))
        self.add_subsystem('lpt',
                           pyc.Turbine(map_data=pyc.LPTMap,
                                       design=design,
                                       thermo_data=thermo_spec,
                                       elements=pyc.AIR_FUEL_MIX,
                                       bleed_names=['cool1', 'cool2'],
                                       map_extrap=True),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.add_subsystem(
            'duct13',
            pyc.Duct(design=design,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_FUEL_MIX))
        self.add_subsystem(
            'core_nozz',
            pyc.Nozzle(nozzType='CV',
                       lossCoef='Cv',
                       thermo_data=thermo_spec,
                       elements=pyc.AIR_FUEL_MIX))

        self.add_subsystem('byp_bld',
                           pyc.BleedOut(design=design, bleed_names=['bypBld']))
        self.add_subsystem(
            'duct15',
            pyc.Duct(design=design,
                     thermo_data=thermo_spec,
                     elements=pyc.AIR_MIX))
        self.add_subsystem(
            'byp_nozz',
            pyc.Nozzle(nozzType='CV',
                       lossCoef='Cv',
                       thermo_data=thermo_spec,
                       elements=pyc.AIR_MIX))

        self.add_subsystem('lp_shaft',
                           pyc.Shaft(num_ports=3),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.add_subsystem('hp_shaft',
                           pyc.Shaft(num_ports=2),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem('perf', pyc.Performance(num_nozzles=2,
                                                   num_burners=1))

        self.connect('inlet.Fl_O:tot:P', 'perf.Pt2')
        self.connect('hpc.Fl_O:tot:P', 'perf.Pt3')
        self.connect('burner.Wfuel', 'perf.Wfuel_0')
        self.connect('inlet.F_ram', 'perf.ram_drag')
        self.connect('core_nozz.Fg', 'perf.Fg_0')
        self.connect('byp_nozz.Fg', 'perf.Fg_1')

        self.connect('fan.trq', 'lp_shaft.trq_0')
        self.connect('lpc.trq', 'lp_shaft.trq_1')
        self.connect('lpt.trq', 'lp_shaft.trq_2')
        self.connect('hpc.trq', 'hp_shaft.trq_0')
        self.connect('hpt.trq', 'hp_shaft.trq_1')
        self.connect('fc.Fl_O:stat:P', 'core_nozz.Ps_exhaust')
        self.connect('fc.Fl_O:stat:P', 'byp_nozz.Ps_exhaust')

        balance = self.add_subsystem('balance', om.BalanceComp())
        if design:
            balance.add_balance('W', units='lbm/s', eq_units='lbf')
            self.connect('balance.W', 'inlet.Fl_I:stat:W')
            self.connect('perf.Fn', 'balance.lhs:W')

            balance.add_balance('FAR', eq_units='degR', lower=1e-4, val=.017)
            self.connect('balance.FAR', 'burner.Fl_I:FAR')
            self.connect('burner.Fl_O:tot:T', 'balance.lhs:FAR')

            balance.add_balance('lpt_PR',
                                val=1.5,
                                lower=1.001,
                                upper=8,
                                eq_units='hp',
                                use_mult=True,
                                mult_val=-1)
            self.connect('balance.lpt_PR', 'lpt.PR')
            self.connect('lp_shaft.pwr_in_real', 'balance.lhs:lpt_PR')
            self.connect('lp_shaft.pwr_out_real', 'balance.rhs:lpt_PR')

            balance.add_balance('hpt_PR',
                                val=1.5,
                                lower=1.001,
                                upper=8,
                                eq_units='hp',
                                use_mult=True,
                                mult_val=-1)
            self.connect('balance.hpt_PR', 'hpt.PR')
            self.connect('hp_shaft.pwr_in_real', 'balance.lhs:hpt_PR')
            self.connect('hp_shaft.pwr_out_real', 'balance.rhs:hpt_PR')

        else:

            balance.add_balance('FAR', val=0.017, lower=1e-4, eq_units='lbf')
            self.connect('balance.FAR', 'burner.Fl_I:FAR')
            self.connect('perf.Fn', 'balance.lhs:FAR')

            balance.add_balance('W',
                                units='lbm/s',
                                lower=10.,
                                upper=1000.,
                                eq_units='inch**2')
            self.connect('balance.W', 'inlet.Fl_I:stat:W')
            self.connect('core_nozz.Throat:stat:area', 'balance.lhs:W')

            balance.add_balance('BPR', lower=2., upper=10., eq_units='inch**2')
            self.connect('balance.BPR', 'splitter.BPR')
            self.connect('byp_nozz.Throat:stat:area', 'balance.lhs:BPR')

            balance.add_balance('lp_Nmech',
                                val=1.5,
                                units='rpm',
                                lower=500.,
                                eq_units='hp',
                                use_mult=True,
                                mult_val=-1)
            self.connect('balance.lp_Nmech', 'LP_Nmech')
            self.connect('lp_shaft.pwr_in_real', 'balance.lhs:lp_Nmech')
            self.connect('lp_shaft.pwr_out_real', 'balance.rhs:lp_Nmech')

            balance.add_balance('hp_Nmech',
                                val=1.5,
                                units='rpm',
                                lower=500.,
                                eq_units='hp',
                                use_mult=True,
                                mult_val=-1)
            self.connect('balance.hp_Nmech', 'HP_Nmech')
            self.connect('hp_shaft.pwr_in_real', 'balance.lhs:hp_Nmech')
            self.connect('hp_shaft.pwr_out_real', 'balance.rhs:hp_Nmech')

            self.set_order([
                'balance', 'fc', 'inlet', 'fan', 'splitter', 'duct4', 'lpc',
                'duct6', 'hpc', 'bld3', 'burner', 'hpt', 'duct11', 'lpt',
                'duct13', 'core_nozz', 'byp_bld', 'duct15', 'byp_nozz',
                'lp_shaft', 'hp_shaft', 'perf'
            ])

        pyc.connect_flow(self, 'fc.Fl_O', 'inlet.Fl_I', connect_w=False)
        pyc.connect_flow(self, 'inlet.Fl_O', 'fan.Fl_I')
        pyc.connect_flow(self, 'fan.Fl_O', 'splitter.Fl_I')
        pyc.connect_flow(self, 'splitter.Fl_O1', 'duct4.Fl_I')
        pyc.connect_flow(self, 'duct4.Fl_O', 'lpc.Fl_I')
        pyc.connect_flow(self, 'lpc.Fl_O', 'duct6.Fl_I')
        pyc.connect_flow(self, 'duct6.Fl_O', 'hpc.Fl_I')
        pyc.connect_flow(self, 'hpc.Fl_O', 'bld3.Fl_I')
        pyc.connect_flow(self, 'bld3.Fl_O', 'burner.Fl_I')
        pyc.connect_flow(self, 'burner.Fl_O', 'hpt.Fl_I')
        pyc.connect_flow(self, 'hpt.Fl_O', 'duct11.Fl_I')
        pyc.connect_flow(self, 'duct11.Fl_O', 'lpt.Fl_I')
        pyc.connect_flow(self, 'lpt.Fl_O', 'duct13.Fl_I')
        pyc.connect_flow(self, 'duct13.Fl_O', 'core_nozz.Fl_I')
        pyc.connect_flow(self, 'splitter.Fl_O2', 'byp_bld.Fl_I')
        pyc.connect_flow(self, 'byp_bld.Fl_O', 'duct15.Fl_I')
        pyc.connect_flow(self, 'duct15.Fl_O', 'byp_nozz.Fl_I')

        pyc.connect_flow(self, 'hpc.cool1', 'lpt.cool1', connect_stat=False)
        pyc.connect_flow(self, 'hpc.cool2', 'lpt.cool2', connect_stat=False)
        pyc.connect_flow(self, 'bld3.cool3', 'hpt.cool3', connect_stat=False)
        pyc.connect_flow(self, 'bld3.cool4', 'hpt.cool4', connect_stat=False)

        newton = self.nonlinear_solver = om.NewtonSolver()
        newton.options['atol'] = 1e-8
        newton.options['rtol'] = 1e-8
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 50
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 100
        newton.options['reraise_child_analysiserror'] = False
        # ls = newton.linesearch = BoundsEnforceLS()
        ls = newton.linesearch = om.ArmijoGoldsteinLS()
        ls.options['maxiter'] = 3
        ls.options['bound_enforcement'] = 'scalar'
        # ls.options['print_bound_enforce'] = True

        self.linear_solver = om.DirectSolver(assemble_jac=True)