Exemplo n.º 1
0
    def test_specify_precon(self):
        import numpy as np

        from openmdao.api import Problem, ScipyKrylov, NewtonSolver, LinearBlockGS, \
             DirectSolver

        from openmdao.test_suite.components.double_sellar import DoubleSellar

        prob = Problem(model=DoubleSellar())
        model = prob.model

        model.nonlinear_solver = NewtonSolver()
        model.nonlinear_solver.linesearch = BoundsEnforceLS()
        model.linear_solver = ScipyKrylov()
        model.g1.linear_solver = DirectSolver()
        model.g2.linear_solver = DirectSolver()

        model.linear_solver.precon = LinearBlockGS()
        # TODO: This should work with 1 iteration.
        #model.linear_solver.precon.options['maxiter'] = 1

        prob.setup()
        prob.set_solver_print(level=2)
        prob.run_model()

        assert_rel_error(self, prob['g1.y1'], 0.64, .00001)
        assert_rel_error(self, prob['g1.y2'], 0.80, .00001)
        assert_rel_error(self, prob['g2.y1'], 0.64, .00001)
        assert_rel_error(self, prob['g2.y2'], 0.80, .00001)
    def setup(self):
        nn = self.options['num_nodes']

        self.add_subsystem('aero', subsys=AerodynamicsGroup(num_nodes=nn))

        self.add_subsystem(
            'thrust_eq_comp',
            subsys=ThrustEquilibriumComp(num_nodes=nn),
            promotes_inputs=['q', 'S', 'gam', 'alpha', 'W_total'],
            promotes_outputs=['CT'])

        self.add_subsystem(
            'lift_eq_comp',
            subsys=LiftEquilibriumComp(num_nodes=nn),
            promotes_inputs=['q', 'S', 'gam', 'alpha', 'W_total', 'CT'],
            promotes_outputs=['CL_eq'])

        bal = self.add_subsystem(name='alpha_eta_balance',
                                 subsys=BalanceComp(),
                                 promotes_outputs=['alpha', 'eta'])

        self.connect('alpha', ('aero.alpha'))
        self.connect('eta', ('aero.eta'))

        bal.add_balance('alpha',
                        units='rad',
                        eq_units=None,
                        lhs_name='CL_eq',
                        rhs_name='CL',
                        val=0.01 * np.ones(nn),
                        lower=-20,
                        upper=30,
                        res_ref=1.0)

        bal.add_balance('eta',
                        units='rad',
                        val=0.01 * np.ones(nn),
                        eq_units=None,
                        lhs_name='CM',
                        lower=-30,
                        upper=30,
                        res_ref=1.0)

        self.connect('aero.CL', 'alpha_eta_balance.CL')
        self.connect('aero.CD', 'thrust_eq_comp.CD')
        self.connect('aero.CM', 'alpha_eta_balance.CM')
        self.connect('CL_eq', ('alpha_eta_balance.CL_eq'))

        self.linear_solver = DirectSolver()
        self.nonlinear_solver = NewtonSolver()
        self.nonlinear_solver.options['atol'] = 1e-14
        self.nonlinear_solver.options['rtol'] = 1e-14
        self.nonlinear_solver.options['solve_subsystems'] = True
        self.nonlinear_solver.options['err_on_maxiter'] = True
        self.nonlinear_solver.options['max_sub_solves'] = 10
        self.nonlinear_solver.options['maxiter'] = 150
        self.nonlinear_solver.options['iprint'] = -1
        # self.nonlinear_solver.linesearch = ArmijoGoldsteinLS()
        self.nonlinear_solver.linesearch = BoundsEnforceLS()
        self.nonlinear_solver.linesearch.options['print_bound_enforce'] = True
Exemplo n.º 3
0
    def test_backtracking(self):
        top = Problem()
        top.model.add_subsystem('px', IndepVarComp('x', 1.0))
        top.model.add_subsystem('comp', ImplCompTwoStates())
        top.model.connect('px.x', 'comp.x')

        top.model.nonlinear_solver = BroydenSolver()
        top.model.nonlinear_solver.options['maxiter'] = 25
        top.model.nonlinear_solver.options['diverge_limit'] = 0.5
        top.model.nonlinear_solver.options['state_vars'] = ['comp.y', 'comp.z']

        top.model.linear_solver = DirectSolver()

        top.setup(check=False)
        top.model.nonlinear_solver.linesearch = BoundsEnforceLS(
            bound_enforcement='vector')

        # Setup again because we assigned a new linesearch
        top.setup(check=False)

        top.set_solver_print(level=2)
        # Test lower bound: should go to the lower bound and stall
        top['px.x'] = 2.0
        top['comp.y'] = 0.0
        top['comp.z'] = 1.6
        top.run_model()
        assert_rel_error(self, top['comp.z'], 1.5, 1e-8)

        # Test upper bound: should go to the upper bound and stall
        top['px.x'] = 0.5
        top['comp.y'] = 0.0
        top['comp.z'] = 2.4
        top.run_model()
        assert_rel_error(self, top['comp.z'], 2.5, 1e-8)
Exemplo n.º 4
0
    def setUp(self):
        self.prob = Problem()

        self.prob.model.add_subsystem('map',
                                      CompressorMap(map_data=AXI5,
                                                    design=False),
                                      promotes=['*'])

        self.prob.model.set_input_defaults('Wc',
                                           322.60579101811692,
                                           units='lbm/s')
        self.prob.model.set_input_defaults('Nc',
                                           172.11870165984794,
                                           units='rpm')
        self.prob.model.set_input_defaults('alphaMap', 1.0)
        self.prob.model.set_input_defaults('s_Nc', 1.721074624)
        self.prob.model.set_input_defaults('s_PR', 0.147473296)
        self.prob.model.set_input_defaults('s_Wc', 2.152309293)
        self.prob.model.set_input_defaults('s_eff', 0.9950409659)

        newton = self.prob.model.nonlinear_solver = NewtonSolver()
        newton.options['atol'] = 1e-8
        newton.options['rtol'] = 1e-8
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 10
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 10
        newton.linesearch = BoundsEnforceLS()
        newton.linesearch.options['bound_enforcement'] = 'scalar'
        newton.linesearch.options['iprint'] = -1

        self.prob.model.linear_solver = DirectSolver(assemble_jac=True)

        self.prob.setup(check=False)
Exemplo n.º 5
0
    def test_implicit_cycle_precon(self):
        prob = Problem()
        model = prob.model = Group()

        model.add_subsystem('p1', IndepVarComp('x', 1.0))
        model.add_subsystem('d1', SellarImplicitDis1())
        model.add_subsystem('d2', SellarImplicitDis2())
        model.connect('d1.y1', 'd2.y1')
        model.connect('d2.y2', 'd1.y2')

        model.nonlinear_solver = NewtonSolver()
        model.nonlinear_solver.options['maxiter'] = 5
        model.nonlinear_solver.linesearch = BoundsEnforceLS()
        model.linear_solver = ScipyKrylov()
        model.linear_solver.precon = self.linear_solver_class()

        prob.setup(check=False)

        prob['d1.y1'] = 4.0
        prob.set_solver_print()
        prob.run_model()
        res = model._residuals.get_norm()

        # Newton is kinda slow on this for some reason, this is how far it gets with directsolver too.
        self.assertLess(res, 2.0e-2)
Exemplo n.º 6
0
 def setup_solvers(self, phase):
     if self.any_solved_segs:
         newton = phase.nonlinear_solver = NewtonSolver()
         newton.options['solve_subsystems'] = True
         newton.options['iprint'] = -1
         newton.linesearch = BoundsEnforceLS()
         phase.linear_solver = DirectSolver()
Exemplo n.º 7
0
    def test_record_line_search_bounds_enforce(self, m):
        self.setup_endpoints(m)
        recorder = WebRecorder(self._accepted_token, suppress_output=True)
        self.setup_sellar_model()

        model = self.prob.model
        model.nonlinear_solver = NewtonSolver()
        model.linear_solver = ScipyIterativeSolver()

        model.nonlinear_solver.options['solve_subsystems'] = True
        model.nonlinear_solver.options['max_sub_solves'] = 4
        ls = model.nonlinear_solver.linesearch = BoundsEnforceLS(
            bound_enforcement='vector')

        ls.add_recorder(recorder)

        self.prob.setup(check=False)

        t0, t1 = run_driver(self.prob)

        self.prob.cleanup()

        expected_abs_error = 7.02783609310096e-10
        expected_rel_error = 8.078674883382422e-07

        solver_iteration = json.loads(self.solver_iterations)
        self.assertAlmostEqual(solver_iteration['abs_err'], expected_abs_error)
        self.assertAlmostEqual(solver_iteration['rel_err'], expected_rel_error)
        self.assertEqual(solver_iteration['solver_output'], [])
        self.assertEqual(solver_iteration['solver_residuals'], [])
Exemplo n.º 8
0
    def setup(self):

        thermo_spec = species_data.janaf

        self.add_subsystem(
            'fc', FlightConditions(thermo_data=thermo_spec, elements=AIR_MIX))

        self.add_subsystem(
            'inlet',
            Inlet(design=True, thermo_data=thermo_spec, elements=AIR_MIX))
        self.add_subsystem(
            'fan',
            Compressor(thermo_data=thermo_spec, elements=AIR_MIX, design=True))
        self.add_subsystem('nozz',
                           Nozzle(thermo_data=thermo_spec, elements=AIR_MIX))
        self.add_subsystem('perf', Performance(num_nozzles=1, num_burners=0))

        self.add_subsystem('shaft', IndepVarComp('Nmech', 1., units='rpm'))

        self.add_subsystem('pwr_balance',
                           BalanceComp('W',
                                       units='lbm/s',
                                       eq_units='hp',
                                       val=50.,
                                       lower=1.,
                                       upper=500.),
                           promotes_inputs=[('rhs:W', 'pwr_target')])

        # self.set_order(['pwr_balance', 'pwr_target', 'fc', 'inlet', 'shaft', 'fan', 'nozz', 'perf'])

        connect_flow(self, 'fc.Fl_O', 'inlet.Fl_I')
        connect_flow(self, 'inlet.Fl_O', 'fan.Fl_I')
        connect_flow(self, 'fan.Fl_O', 'nozz.Fl_I')

        self.connect('shaft.Nmech', 'fan.Nmech')

        self.connect('fc.Fl_O:stat:P', 'nozz.Ps_exhaust')
        self.connect('inlet.Fl_O:tot:P', 'perf.Pt2')
        self.connect('fan.Fl_O:tot:P', 'perf.Pt3')
        self.connect('inlet.F_ram', 'perf.ram_drag')
        self.connect('nozz.Fg', 'perf.Fg_0')

        self.connect('pwr_balance.W', 'fc.W')
        self.connect('fan.power', 'pwr_balance.lhs:W')

        newton = self.nonlinear_solver = NewtonSolver()
        newton.options['atol'] = 1e-12
        newton.options['rtol'] = 1e-12
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 10
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 10
        #
        newton.linesearch = BoundsEnforceLS()
        newton.linesearch.options['bound_enforcement'] = 'scalar'
        # newton.linesearch.options['print_bound_enforce'] = True
        # newton.linesearch.options['iprint'] = -1
        #
        self.linear_solver = DirectSolver(assemble_jac=True)
Exemplo n.º 9
0
    def setUp(self):

        self.prob = Problem()

        des_vars = self.prob.model.add_subsystem('des_vars',
                                                 IndepVarComp(),
                                                 promotes=['*'])
        des_vars.add_output('P', 17., units='psi')
        des_vars.add_output('T', 500., units='degR')
        des_vars.add_output('W', 0., units='lbm/s')
        des_vars.add_output('Nmech', 0., units='rpm')
        des_vars.add_output('area_targ', 50., units='inch**2')

        des_vars.add_output('s_PR', val=1.)
        des_vars.add_output('s_eff', val=1.)
        des_vars.add_output('s_Wc', val=1.)
        des_vars.add_output('s_Nc', val=1.)
        des_vars.add_output('alphaMap', val=0.)

        self.prob.model.connect("P", "flow_start.P")
        self.prob.model.connect("T", "flow_start.T")
        self.prob.model.connect("W", "flow_start.W")
        self.prob.model.connect("Nmech", "compressor.Nmech")
        self.prob.model.connect("area_targ", "compressor.area")

        self.prob.model.connect("s_PR", "compressor.s_PR")
        self.prob.model.connect("s_eff", "compressor.s_eff")
        self.prob.model.connect("s_Wc", "compressor.s_Wc")
        self.prob.model.connect("s_Nc", "compressor.s_Nc")
        self.prob.model.connect('alphaMap', 'compressor.map.alphaMap')

        self.prob.model.add_subsystem(
            'flow_start', FlowStart(thermo_data=janaf, elements=AIR_MIX))
        self.prob.model.add_subsystem(
            'compressor',
            Compressor(map_data=AXI5,
                       design=False,
                       elements=AIR_MIX,
                       map_extrap=False))

        connect_flow(self.prob.model, "flow_start.Fl_O", "compressor.Fl_I")

        newton = self.prob.model.nonlinear_solver = NewtonSolver()
        newton.options['atol'] = 1e-8
        newton.options['rtol'] = 1e-8
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 10
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 10
        newton.linesearch = BoundsEnforceLS()
        newton.linesearch.options['bound_enforcement'] = 'scalar'
        newton.linesearch.options['iprint'] = -1

        self.prob.model.linear_solver = DirectSolver(assemble_jac=True)

        self.prob.set_solver_print(level=-1)
        self.prob.setup(check=False)
Exemplo n.º 10
0
def run_tbm_analysis():
    # Set up OpenMDAO to analyze the airplane
    num_nodes = 11
    prob = Problem()
    prob.model = TBMAnalysisGroup()
    prob.model.nonlinear_solver = NewtonSolver(iprint=2)
    prob.model.options['assembled_jac_type'] = 'csc'
    prob.model.linear_solver = DirectSolver(assemble_jac=True)
    prob.model.nonlinear_solver.options['solve_subsystems'] = True
    prob.model.nonlinear_solver.options['maxiter'] = 10
    prob.model.nonlinear_solver.options['atol'] = 1e-6
    prob.model.nonlinear_solver.options['rtol'] = 1e-6
    prob.model.nonlinear_solver.linesearch = BoundsEnforceLS(
        bound_enforcement='scalar', print_bound_enforce=False)
    prob.setup(check=True, mode='fwd')

    # set some (required) mission parameters. Each pahse needs a vertical and air-speed
    # the entire mission needs a cruise altitude and range
    prob.set_val('climb.fltcond|vs',
                 np.ones((num_nodes, )) * 1500,
                 units='ft/min')
    prob.set_val('climb.fltcond|Ueas',
                 np.ones((num_nodes, )) * 124,
                 units='kn')
    prob.set_val('cruise.fltcond|vs',
                 np.ones((num_nodes, )) * 0.01,
                 units='ft/min')
    prob.set_val('cruise.fltcond|Ueas',
                 np.ones((num_nodes, )) * 201,
                 units='kn')
    prob.set_val('descent.fltcond|vs',
                 np.ones((num_nodes, )) * (-600),
                 units='ft/min')
    prob.set_val('descent.fltcond|Ueas',
                 np.ones((num_nodes, )) * 140,
                 units='kn')

    prob.set_val('cruise|h0', 28000., units='ft')
    prob.set_val('mission_range', 1250, units='NM')

    # (optional) guesses for takeoff speeds may help with convergence
    prob.set_val('v0v1.fltcond|Utrue', np.ones((num_nodes)) * 50, units='kn')
    prob.set_val('v1vr.fltcond|Utrue', np.ones((num_nodes)) * 85, units='kn')
    prob.set_val('v1v0.fltcond|Utrue', np.ones((num_nodes)) * 85, units='kn')

    # set some airplane-specific values. The throttle edits are to derate the takeoff power of the PT6A
    prob['climb.OEW.structural_fudge'] = 1.67
    prob['v0v1.throttle'] = np.ones((num_nodes)) / 1.21
    prob['v1vr.throttle'] = np.ones((num_nodes)) / 1.21
    prob['rotate.throttle'] = np.ones((num_nodes)) / 1.21

    prob.run_model()
    return prob
def configure_problem():
    prob = Problem()
    prob.model = ElectricTwinAnalysisGroup()
    prob.model.nonlinear_solver = NewtonSolver(iprint=2)
    prob.model.options['assembled_jac_type'] = 'csc'
    prob.model.linear_solver = DirectSolver(assemble_jac=True)
    prob.model.nonlinear_solver.options['solve_subsystems'] = True
    prob.model.nonlinear_solver.options['maxiter'] = 10
    prob.model.nonlinear_solver.options['atol'] = 1e-8
    prob.model.nonlinear_solver.options['rtol'] = 1e-8
    prob.model.nonlinear_solver.linesearch = BoundsEnforceLS()
    # prob.model.nonlinear_solver.linesearch.options['print_bound_enforce'] = True
    return prob
Exemplo n.º 12
0
    def setup(self):
        thermo_data = self.options['thermo_data']
        elements = self.options['elements']

        self.add_subsystem('ambient', Ambient(),
                           promotes=('alt', 'dTs'))  # inputs

        conv = self.add_subsystem('conv', Group(), promotes=['*'])
        conv.add_subsystem('fs',
                           FlowStart(thermo_data=thermo_data,
                                     elements=elements),
                           promotes=['Fl_O:*', 'MN', 'W'])
        balance = conv.add_subsystem('balance', BalanceComp())
        balance.add_balance('Tt',
                            val=500.0,
                            lower=1e-4,
                            units='degR',
                            desc='Total temperature',
                            eq_units='degR')
        balance.add_balance('Pt',
                            val=14.696,
                            lower=1e-4,
                            units='psi',
                            desc='Total pressure',
                            eq_units='psi')
        # sub.set_order(['fs','balance'])

        newton = conv.nonlinear_solver = NewtonSolver()
        newton.options['atol'] = 1e-10
        newton.options['rtol'] = 1e-10
        newton.options['maxiter'] = 10
        newton.options['iprint'] = -1
        newton.options['solve_subsystems'] = True
        newton.linesearch = BoundsEnforceLS()
        newton.linesearch.options['bound_enforcement'] = 'scalar'

        newton.linesearch.options['iprint'] = -1
        # newton.linesearch.options['solve_subsystems'] = True

        conv.linear_solver = DirectSolver(assemble_jac=True)

        self.connect('ambient.Ps', 'balance.rhs:Pt')
        self.connect('ambient.Ts', 'balance.rhs:Tt')

        self.connect('balance.Pt', 'fs.P')
        self.connect('balance.Tt', 'fs.T')

        self.connect('Fl_O:stat:P', 'balance.lhs:Pt')
        self.connect('Fl_O:stat:T', 'balance.lhs:Tt')
Exemplo n.º 13
0
    def setUp(self):

        thermo = Thermo(janaf, constants.AIR_MIX)

        self.prob = Problem()

        self.prob.model.add_subsystem(
            'flow_start', FlowStart(thermo_data=janaf, elements=AIR_MIX))
        self.prob.model.add_subsystem(
            'compressor',
            Compressor(map_data=AXI5,
                       design=False,
                       elements=AIR_MIX,
                       map_extrap=False))

        self.prob.model.set_input_defaults('compressor.s_PR', val=1.)
        self.prob.model.set_input_defaults('compressor.s_eff', val=1.)
        self.prob.model.set_input_defaults('compressor.s_Wc', val=1.)
        self.prob.model.set_input_defaults('compressor.s_Nc', val=1.)
        self.prob.model.set_input_defaults('compressor.map.alphaMap', val=0.)
        self.prob.model.set_input_defaults('compressor.Nmech', 0., units='rpm')
        self.prob.model.set_input_defaults('flow_start.P', 17., units='psi')
        self.prob.model.set_input_defaults('flow_start.T', 500., units='degR')
        self.prob.model.set_input_defaults('flow_start.W', 0., units='lbm/s')
        self.prob.model.set_input_defaults('compressor.area',
                                           50.,
                                           units='inch**2')

        connect_flow(self.prob.model, "flow_start.Fl_O", "compressor.Fl_I")

        newton = self.prob.model.nonlinear_solver = NewtonSolver()
        newton.options['atol'] = 1e-8
        newton.options['rtol'] = 1e-8
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 10
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 10
        newton.linesearch = BoundsEnforceLS()
        newton.linesearch.options['bound_enforcement'] = 'scalar'
        newton.linesearch.options['iprint'] = -1

        self.prob.model.linear_solver = DirectSolver(assemble_jac=True)

        self.prob.set_solver_print(level=-1)
        self.prob.setup(check=False)
Exemplo n.º 14
0
    def setup_solvers(self, phase):
        """
        Add a NewtonSolver to converge continuity errors in the state between steps.

        Parameters
        ----------
        phase
            The phase to which this transcription instance applies.

        Returns
        -------

        """
        phase.nonlinear_solver = NewtonSolver()
        phase.nonlinear_solver.options['iprint'] = -1
        phase.nonlinear_solver.options['solve_subsystems'] = True
        phase.nonlinear_solver.options['err_on_maxiter'] = True
        phase.nonlinear_solver.linesearch = BoundsEnforceLS()
Exemplo n.º 15
0
    def setUp(self):

        self.prob = Problem()
        cycle = self.prob.model = Cycle()
        cycle.options['design'] = False
        cycle.options['thermo_method'] = 'CEA'
        cycle.options['thermo_data'] = species_data.janaf

        cycle.add_subsystem('flow_start', FlowStart())
        cycle.add_subsystem(
            'compressor',
            Compressor(map_data=AXI5, design=False, map_extrap=False))

        cycle.set_input_defaults('compressor.s_PR', val=1.)
        cycle.set_input_defaults('compressor.s_eff', val=1.)
        cycle.set_input_defaults('compressor.s_Wc', val=1.)
        cycle.set_input_defaults('compressor.s_Nc', val=1.)
        cycle.set_input_defaults('compressor.map.alphaMap', val=0.)
        cycle.set_input_defaults('compressor.Nmech', 0., units='rpm')
        cycle.set_input_defaults('flow_start.P', 17., units='psi')
        cycle.set_input_defaults('flow_start.T', 500., units='degR')
        cycle.set_input_defaults('flow_start.W', 0., units='lbm/s')
        cycle.set_input_defaults('compressor.area', 50., units='inch**2')

        cycle.pyc_connect_flow("flow_start.Fl_O", "compressor.Fl_I")

        newton = self.prob.model.nonlinear_solver = NewtonSolver()
        newton.options['atol'] = 1e-8
        newton.options['rtol'] = 1e-8
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 10
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 10
        newton.linesearch = BoundsEnforceLS()
        newton.linesearch.options['bound_enforcement'] = 'scalar'
        newton.linesearch.options['iprint'] = -1

        self.prob.model.linear_solver = DirectSolver(assemble_jac=True)

        self.prob.set_solver_print(level=-1)
        self.prob.setup(check=False, force_alloc_complex=True)
Exemplo n.º 16
0
def configure_problem():
    prob = Problem()
    prob.model = ElectricTBMAnalysisGroup()

    prob.model.nonlinear_solver = NewtonSolver(iprint=2)
    prob.model.options['assembled_jac_type'] = 'csc'
    prob.model.linear_solver = DirectSolver(assemble_jac=True)
    prob.model.nonlinear_solver.options['solve_subsystems'] = True
    prob.model.nonlinear_solver.options['maxiter'] = 20
    prob.model.nonlinear_solver.options['atol'] = 1e-8
    prob.model.nonlinear_solver.options['rtol'] = 1e-8
    prob.model.nonlinear_solver.linesearch = BoundsEnforceLS(
        bound_enforcement='scalar', print_bound_enforce=False)
    prob.model.add_design_var('mission_range',
                              lower=100,
                              upper=300,
                              scaler=1e-2)
    prob.model.add_constraint('descent.propmodel.batt1.SOC_final', lower=0.0)
    prob.model.add_objective('mission_range', scaler=-1.0)
    prob.driver = ScipyOptimizeDriver()
    return prob
Exemplo n.º 17
0
    def test_record_line_search_bounds_enforce(self, m):
        self.setup_endpoints(m)
        self.setup_sellar_model()

        model = self.prob.model
        model.nonlinear_solver = NewtonSolver()
        model.linear_solver = ScipyKrylov()

        model.nonlinear_solver.options['solve_subsystems'] = True
        model.nonlinear_solver.options['max_sub_solves'] = 4
        ls = model.nonlinear_solver.linesearch = BoundsEnforceLS(bound_enforcement='vector')

        ls.add_recorder(self.recorder)

        self.prob.setup(check=False)

        t0, t1 = run_driver(self.prob)

        self.prob.cleanup()
        upload(self.filename, self._accepted_token)

        expected_abs_error = 7.02783609310096e-10
        expected_rel_error = 8.078674883382422e-07
        expected_solver_output = [
            {'name': 'con_cmp1.con1', 'values': [-22.42830237]},
            {'name': 'd1.y1', 'values': [25.58830237]},
            {'name': 'con_cmp2.con2', 'values': [-11.941511849]},
            {'name': 'pz.z', 'values': [5.0, 2.0]},
            {'name': 'obj_cmp.obj', 'values': [28.588308165]},
            {'name': 'd2.y2', 'values': [12.058488150]},
            {'name': 'px.x', 'values': [1.0]}
        ]

        solver_iteration = json.loads(self.solver_iterations)
        self.assertAlmostEqual(solver_iteration['abs_err'], expected_abs_error)
        self.assertAlmostEqual(solver_iteration['rel_err'], expected_rel_error)
        self.assertEqual(solver_iteration['solver_residuals'], [])
        for o in expected_solver_output:
            self.assert_array_close(o, solver_iteration['solver_output'])
Exemplo n.º 18
0
    def configure(self):

        for_statics = self.options['for_statics']
        if for_statics and for_statics != 'Ps':

            self.ceq.nonlinear_solver.options['atol'] = 1e-10
            self.ceq.nonlinear_solver.options['rtol'] = 1e-6

            # statics need an newton solver to converge the outer loop with Ps
            newton = self.nonlinear_solver = NewtonSolver()
            newton.options['atol'] = 1e-10
            newton.options['rtol'] = 1e-10
            newton.options['maxiter'] = 50
            newton.options['iprint'] = 2
            newton.options['solve_subsystems'] = True
            newton.options['max_sub_solves'] = 50

            self.options['assembled_jac_type'] = 'dense'
            newton.linear_solver = DirectSolver(assemble_jac=True)

            ln_bt = newton.linesearch = BoundsEnforceLS()
            ln_bt.options['bound_enforcement'] = 'scalar'
            ln_bt.options['iprint'] = -1
Exemplo n.º 19
0
                                      promotes_inputs=['*'],
                                      promotes_outputs=['*'])


if __name__ == "__main__":
    num_nodes = 11
    prob = Problem()
    prob.model = KingAirAnalysisGroup()
    prob.model.nonlinear_solver = NewtonSolver(iprint=2)
    prob.model.options['assembled_jac_type'] = 'csc'
    prob.model.linear_solver = DirectSolver(assemble_jac=True)
    prob.model.nonlinear_solver.options['solve_subsystems'] = True
    prob.model.nonlinear_solver.options['maxiter'] = 10
    prob.model.nonlinear_solver.options['atol'] = 1e-6
    prob.model.nonlinear_solver.options['rtol'] = 1e-6
    prob.model.nonlinear_solver.linesearch = BoundsEnforceLS(
        bound_enforcement='scalar', print_bound_enforce=True)
    prob.setup(check=True, mode='fwd')

    # set some (required) mission parameters. Each pahse needs a vertical and air-speed
    # the entire mission needs a cruise altitude and range
    prob.set_val('climb.fltcond|vs',
                 np.ones((num_nodes, )) * 1500,
                 units='ft/min')
    prob.set_val('climb.fltcond|Ueas',
                 np.ones((num_nodes, )) * 124,
                 units='kn')
    prob.set_val('cruise.fltcond|vs',
                 np.ones((num_nodes, )) * 0.01,
                 units='ft/min')
    prob.set_val('cruise.fltcond|Ueas',
                 np.ones((num_nodes, )) * 170,
Exemplo n.º 20
0
    def setup(self):

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

        self.add_subsystem(
            'fc', FlightConditions(thermo_data=thermo_spec, elements=AIR_MIX))
        self.add_subsystem(
            'inlet',
            Inlet(design=design, thermo_data=thermo_spec, elements=AIR_MIX))
        self.add_subsystem(
            'duct1',
            Duct(design=design,
                 thermo_data=thermo_spec,
                 elements=AIR_MIX,
                 statics=statics))
        self.add_subsystem('lpc',
                           Compressor(map_data=LPCmap,
                                      design=design,
                                      thermo_data=thermo_spec,
                                      elements=AIR_MIX,
                                      statics=statics),
                           promotes_inputs=[('Nmech', 'IP_Nmech')])
        self.add_subsystem(
            'icduct',
            Duct(design=design,
                 thermo_data=thermo_spec,
                 elements=AIR_MIX,
                 statics=statics))
        self.add_subsystem('hpc_axi',
                           Compressor(map_data=HPCmap,
                                      design=design,
                                      thermo_data=thermo_spec,
                                      elements=AIR_MIX,
                                      statics=statics),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem(
            'bld25',
            BleedOut(design=design,
                     statics=statics,
                     bleed_names=['cool1', 'cool2']))
        self.add_subsystem('hpc_centri',
                           Compressor(map_data=HPCmap,
                                      design=design,
                                      thermo_data=thermo_spec,
                                      elements=AIR_MIX,
                                      statics=statics),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem(
            'bld3',
            BleedOut(design=design,
                     statics=statics,
                     bleed_names=['cool3', 'cool4']))
        self.add_subsystem(
            'duct6',
            Duct(design=design,
                 thermo_data=thermo_spec,
                 elements=AIR_MIX,
                 statics=statics))
        self.add_subsystem(
            'burner',
            Combustor(design=design,
                      thermo_data=thermo_spec,
                      inflow_elements=AIR_MIX,
                      air_fuel_elements=AIR_FUEL_MIX,
                      fuel_type='Jet-A(g)',
                      statics=statics))
        self.add_subsystem('hpt',
                           Turbine(map_data=HPTmap,
                                   design=design,
                                   thermo_data=thermo_spec,
                                   elements=AIR_FUEL_MIX,
                                   bleed_names=['cool3', 'cool4'],
                                   statics=statics),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem(
            'duct43',
            Duct(design=design,
                 thermo_data=thermo_spec,
                 elements=AIR_FUEL_MIX,
                 statics=statics))
        self.add_subsystem('lpt',
                           Turbine(map_data=LPTmap,
                                   design=design,
                                   thermo_data=thermo_spec,
                                   elements=AIR_FUEL_MIX,
                                   bleed_names=['cool1', 'cool2'],
                                   statics=statics),
                           promotes_inputs=[('Nmech', 'IP_Nmech')])
        self.add_subsystem(
            'itduct',
            Duct(design=design,
                 thermo_data=thermo_spec,
                 elements=AIR_FUEL_MIX,
                 statics=statics))
        self.add_subsystem('pt',
                           Turbine(map_data=LPTmap,
                                   design=design,
                                   thermo_data=thermo_spec,
                                   elements=AIR_FUEL_MIX,
                                   statics=statics),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.add_subsystem(
            'duct12',
            Duct(design=design,
                 thermo_data=thermo_spec,
                 elements=AIR_FUEL_MIX,
                 statics=statics))
        self.add_subsystem(
            'nozzle',
            Nozzle(nozzType='CV',
                   lossCoef='Cv',
                   thermo_data=thermo_spec,
                   elements=AIR_FUEL_MIX))

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

        self.connect('duct1.Fl_O:tot:P', 'perf.Pt2')
        self.connect('hpc_centri.Fl_O:tot:P', 'perf.Pt3')
        self.connect('burner.Wfuel', 'perf.Wfuel_0')
        self.connect('inlet.F_ram', 'perf.ram_drag')
        self.connect('nozzle.Fg', 'perf.Fg_0')
        self.connect('lp_shaft.pwr_in', 'perf.power')

        self.connect('pt.trq', 'lp_shaft.trq_0')
        self.connect('lpc.trq', 'ip_shaft.trq_0')
        self.connect('lpt.trq', 'ip_shaft.trq_1')
        self.connect('hpc_axi.trq', 'hp_shaft.trq_0')
        self.connect('hpc_centri.trq', 'hp_shaft.trq_1')
        self.connect('hpt.trq', 'hp_shaft.trq_2')
        self.connect('fc.Fl_O:stat:P', 'nozzle.Ps_exhaust')

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

            balance.add_balance('W', units='lbm/s', eq_units=None)
            self.connect('balance.W', 'inlet.Fl_I:stat:W')
            self.connect('nozzle.PR', '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',
                                rhs_val=0.)
            self.connect('balance.lpt_PR', 'lpt.PR')
            self.connect('ip_shaft.pwr_net', 'balance.lhs:lpt_PR')

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

            balance.add_balance('pt_PR',
                                val=1.5,
                                lower=1.001,
                                upper=8,
                                eq_units='hp',
                                rhs_val=0.)
            self.connect('balance.pt_PR', 'pt.PR')
            self.connect('lp_shaft.pwr_net', 'balance.lhs:pt_PR')

            # self.set_order(['fc', 'inlet', 'duct1', 'comp', 'burner', 'turb', 'ab', 'nozz', 'shaft', 'perf', 'thrust_balance', 'temp_balance', 'shaft_balance'])
            # self.set_order(['balance', 'fc', 'inlet', 'duct1', 'comp', 'burner', 'turb', 'ab', 'nozz', 'shaft', 'perf'])

        else:

            # Need to check all these balances once power turbine map is updated
            balance.add_balance('FAR', eq_units='lbf', lower=1e-4, val=.017)
            self.connect('balance.FAR', 'burner.Fl_I:FAR')
            self.connect('perf.Fn', 'balance.lhs:FAR')

            balance.add_balance('W', units='lbm/s', eq_units=None)
            self.connect('balance.W', 'inlet.Fl_I:stat:W')
            self.connect('nozzle.Throat:stat:area', 'balance.lhs:W')

            balance.add_balance('IP_Nmech',
                                val=12000.0,
                                units='rpm',
                                lower=1.001,
                                eq_units='hp',
                                rhs_val=0.)
            self.connect('balance.IP_Nmech', 'IP_Nmech')
            self.connect('ip_shaft.pwr_net', 'balance.lhs:IP_Nmech')

            balance.add_balance('HP_Nmech',
                                val=14800.0,
                                units='rpm',
                                lower=1.001,
                                eq_units='hp',
                                rhs_val=0.)
            self.connect('balance.HP_Nmech', 'HP_Nmech')
            self.connect('hp_shaft.pwr_net', 'balance.lhs:HP_Nmech')

            balance.add_balance('LP_Nmech',
                                val=1800.0,
                                units='rpm',
                                lower=1.001,
                                eq_units='hp',
                                rhs_val=0.)
            self.connect('balance.LP_Nmech', 'LP_Nmech')
            self.connect('lp_shaft.pwr_net', 'balance.lhs:LP_Nmech')

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

        if statics:
            connect_flow(self, 'fc.Fl_O', 'inlet.Fl_I', connect_w=False)
            connect_flow(self, 'inlet.Fl_O', 'duct1.Fl_I')
            connect_flow(self, 'duct1.Fl_O', 'lpc.Fl_I')
            connect_flow(self, 'lpc.Fl_O', 'icduct.Fl_I')
            connect_flow(self, 'icduct.Fl_O', 'hpc_axi.Fl_I')
            connect_flow(self, 'hpc_axi.Fl_O', 'bld25.Fl_I')
            connect_flow(self, 'bld25.Fl_O', 'hpc_centri.Fl_I')
            connect_flow(self, 'hpc_centri.Fl_O', 'bld3.Fl_I')
            connect_flow(self, 'bld3.Fl_O', 'duct6.Fl_I')
            connect_flow(self, 'duct6.Fl_O', 'burner.Fl_I')
            connect_flow(self, 'burner.Fl_O', 'hpt.Fl_I')
            connect_flow(self, 'hpt.Fl_O', 'duct43.Fl_I')
            connect_flow(self, 'duct43.Fl_O', 'lpt.Fl_I')
            connect_flow(self, 'lpt.Fl_O', 'itduct.Fl_I')
            connect_flow(self, 'itduct.Fl_O', 'pt.Fl_I')
            connect_flow(self, 'pt.Fl_O', 'duct12.Fl_I')
            connect_flow(self, 'duct12.Fl_O', 'nozzle.Fl_I')
        else:
            connect_flow(self, 'fc.Fl_O', 'inlet.Fl_I', connect_w=False)
            connect_flow(self, 'inlet.Fl_O', 'duct1.Fl_I', connect_stat=False)
            connect_flow(self, 'duct1.Fl_O', 'lpc.Fl_I', connect_stat=False)
            connect_flow(self, 'lpc.Fl_O', 'icduct.Fl_I', connect_stat=False)
            connect_flow(self,
                         'icduct.Fl_O',
                         'hpc_axi.Fl_I',
                         connect_stat=False)
            connect_flow(self,
                         'hpc_axi.Fl_O',
                         'bld25.Fl_I',
                         connect_stat=False)
            connect_flow(self,
                         'bld25.Fl_O',
                         'hpc_centri.Fl_I',
                         connect_stat=False)
            connect_flow(self,
                         'hpc_centri.Fl_O',
                         'bld3.Fl_I',
                         connect_stat=False)
            connect_flow(self, 'bld3.Fl_O', 'duct6.Fl_I', connect_stat=False)
            connect_flow(self, 'duct6.Fl_O', 'burner.Fl_I', connect_stat=False)
            connect_flow(self, 'burner.Fl_O', 'hpt.Fl_I', connect_stat=False)
            connect_flow(self, 'hpt.Fl_O', 'duct43.Fl_I', connect_stat=False)
            connect_flow(self, 'duct43.Fl_O', 'lpt.Fl_I', connect_stat=False)
            connect_flow(self, 'lpt.Fl_O', 'itduct.Fl_I', connect_stat=False)
            connect_flow(self, 'itduct.Fl_O', 'pt.Fl_I', connect_stat=False)
            connect_flow(self, 'pt.Fl_O', 'duct12.Fl_I', connect_stat=False)
            connect_flow(self,
                         'duct12.Fl_O',
                         'nozzle.Fl_I',
                         connect_stat=False)

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

        newton = self.nonlinear_solver = NewtonSolver()
        newton.options['atol'] = 1e-6
        newton.options['rtol'] = 1e-6
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 10
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 100
        newton.linesearch = BoundsEnforceLS()
        # newton.linesearch = ArmijoGoldsteinLS()
        # newton.linesearch.options['c'] = .0001
        newton.linesearch.options['bound_enforcement'] = 'scalar'
        newton.linesearch.options['iprint'] = -1

        self.linear_solver = DirectSolver(assemble_jac=True)
Exemplo n.º 21
0
    def setup(self):
        thermo_data = self.options['thermo_data']
        elements = self.options['elements']
        nozzType = self.options['nozzType']
        lossCoef = self.options['lossCoef']

        gas_thermo = species_data.Thermo(thermo_data, init_reacts=elements)
        self.gas_prods = gas_thermo.products

        num_prod = len(self.gas_prods)

        self.add_subsystem('mach_choked', IndepVarComp(
            'MN',
            1.000,
        ))

        # Create inlet flow station
        in_flow = FlowIn(fl_name="Fl_I", num_prods=num_prod)
        self.add_subsystem('in_flow', in_flow, promotes_inputs=['Fl_I:*'])

        # PR_bal = self.add_subsystem('PR_bal', BalanceComp())
        # PR_bal.add_balance('PR', units=None, eq_units='lbf/inch**2', lower=1.001)
        # self.connect('PR_bal.PR', 'PR')
        # self.connect('Ps_exhaust', 'PR_bal.lhs:PR')
        # self.connect('Ps_calc', 'PR_bal.rhs:PR')

        self.add_subsystem('PR_bal',
                           PR_bal(),
                           promotes_inputs=['*'],
                           promotes_outputs=['*'])

        # Calculate pressure at the throat
        prom_in = [('Pt_in', 'Fl_I:tot:P'), 'PR', 'dPqP']
        self.add_subsystem('press_calcs',
                           PressureCalcs(),
                           promotes_inputs=prom_in,
                           promotes_outputs=['Ps_calc'])

        # Calculate throat total flow properties
        throat_total = SetTotal(thermo_data=thermo_data,
                                mode="h",
                                init_reacts=elements,
                                fl_name="Fl_O:tot")
        prom_in = [('h', 'Fl_I:tot:h'), ('init_prod_amounts', 'Fl_I:tot:n')]
        self.add_subsystem('throat_total',
                           throat_total,
                           promotes_inputs=prom_in,
                           promotes_outputs=['Fl_O:*'])
        self.connect('press_calcs.Pt_th', 'throat_total.P')

        # Calculate static properties for sonic flow
        prom_in = [('ht', 'Fl_I:tot:h'), ('W', 'Fl_I:stat:W'),
                   ('init_prod_amounts', 'Fl_I:tot:n')]
        self.add_subsystem('staticMN',
                           SetStatic(mode="MN",
                                     thermo_data=thermo_data,
                                     init_reacts=elements),
                           promotes_inputs=prom_in)
        self.connect('throat_total.S', 'staticMN.S')
        self.connect('mach_choked.MN', 'staticMN.MN')
        self.connect('press_calcs.Pt_th', 'staticMN.guess:Pt')
        self.connect('throat_total.gamma', 'staticMN.guess:gamt')
        # self.connect('Fl_I.flow:flow_products','staticMN.init_prod_amounts')

        # Calculate static properties based on exit static pressure
        prom_in = [('ht', 'Fl_I:tot:h'), ('W', 'Fl_I:stat:W'),
                   ('Ps', 'Ps_calc'), ('init_prod_amounts', 'Fl_I:tot:n')]
        self.add_subsystem('staticPs',
                           SetStatic(mode="Ps",
                                     thermo_data=thermo_data,
                                     init_reacts=elements),
                           promotes_inputs=prom_in)
        self.connect('throat_total.S', 'staticPs.S')
        # self.connect('press_calcs.Ps_calc', 'staticPs.Ps')
        # self.connect('Fl_I.flow:flow_products','staticPs.init_prod_amounts')

        # Calculate ideal exit flow properties
        prom_in = [('ht', 'Fl_I:tot:h'), ('S', 'Fl_I:tot:S'),
                   ('W', 'Fl_I:stat:W'), ('Ps', 'Ps_calc'),
                   ('init_prod_amounts', 'Fl_I:tot:n')]
        self.add_subsystem('ideal_flow',
                           SetStatic(mode="Ps",
                                     thermo_data=thermo_data,
                                     init_reacts=elements),
                           promotes_inputs=prom_in)
        # self.connect('press_calcs.Ps_calc', 'ideal_flow.Ps')
        # self.connect('Fl_I.flow:flow_products','ideal_flow.init_prod_amounts')

        # Determine throat and exit flow properties based on nozzle type and exit static pressure
        mux = Mux(nozzType=nozzType, fl_out_name='Fl_O')
        prom_in = [('Ps:W', 'Fl_I:stat:W'), ('MN:W', 'Fl_I:stat:W'),
                   ('Ps:P', 'Ps_calc'), 'Ps_calc']
        self.add_subsystem('mux',
                           mux,
                           promotes_inputs=prom_in,
                           promotes_outputs=['*:stat:*'])
        self.connect('throat_total.S', 'mux.S')
        self.connect('staticPs.h', 'mux.Ps:h')
        self.connect('staticPs.T', 'mux.Ps:T')
        self.connect('staticPs.rho', 'mux.Ps:rho')
        self.connect('staticPs.gamma', 'mux.Ps:gamma')
        self.connect('staticPs.Cp', 'mux.Ps:Cp')
        self.connect('staticPs.Cv', 'mux.Ps:Cv')
        self.connect('staticPs.V', 'mux.Ps:V')
        self.connect('staticPs.Vsonic', 'mux.Ps:Vsonic')
        self.connect('staticPs.MN', 'mux.Ps:MN')
        self.connect('staticPs.area', 'mux.Ps:area')

        self.connect('staticMN.h', 'mux.MN:h')
        self.connect('staticMN.T', 'mux.MN:T')
        self.connect('staticMN.Ps', 'mux.MN:P')
        self.connect('staticMN.rho', 'mux.MN:rho')
        self.connect('staticMN.gamma', 'mux.MN:gamma')
        self.connect('staticMN.Cp', 'mux.MN:Cp')
        self.connect('staticMN.Cv', 'mux.MN:Cv')
        self.connect('staticMN.V', 'mux.MN:V')
        self.connect('staticMN.Vsonic', 'mux.MN:Vsonic')
        self.connect('mach_choked.MN', 'mux.MN:MN')
        self.connect('staticMN.area', 'mux.MN:area')

        # Calculate nozzle performance paramters based on
        perf_calcs = PerformanceCalcs(lossCoef=lossCoef)
        if lossCoef == "Cv":
            other_inputs = ['Cv', 'Ps_calc']
        else:
            other_inputs = ['Cfg', 'Ps_calc']
        prom_in = [('W_in', 'Fl_I:stat:W')] + other_inputs
        self.add_subsystem('perf_calcs',
                           perf_calcs,
                           promotes_inputs=prom_in,
                           promotes_outputs=['Fg'])
        self.connect('ideal_flow.V', 'perf_calcs.V_ideal')
        # self.connect('ideal_flow.area', 'perf_calcs.A_ideal')

        if lossCoef == 'Cv':
            self.connect('Fl_O:stat:V', 'perf_calcs.V_actual')
            self.connect('Fl_O:stat:area', 'perf_calcs.A_actual')
            self.connect('Fl_O:stat:P', 'perf_calcs.Ps_actual')

        if self.options['internal_solver']:
            newton = self.nonlinear_solver = NewtonSolver()
            newton.options['atol'] = 1e-10
            newton.options['rtol'] = 1e-10
            newton.options['maxiter'] = 20
            newton.options['iprint'] = 2
            newton.options['solve_subsystems'] = True
            newton.linesearch = BoundsEnforceLS()
            newton.linesearch.options['bound_enforcement'] = 'scalar'

            newton.linesearch.options['iprint'] = -1
            self.linear_solver = DirectSolver(assemble_jac=True)
    def setup(self):
        thermo_spec = species_data.janaf
        design = self.options['design']

        ##########################################
        # Elements
        ##########################################

        self.add_subsystem(
            'fc', FlightConditions(thermo_data=thermo_spec, elements=AIR_MIX))
        # Inlet Components
        self.add_subsystem('mil_spec', MilSpecRecovery())
        self.add_subsystem(
            'inlet',
            Inlet(design=design, thermo_data=thermo_spec, elements=AIR_MIX))

        # Fan Components - Split here for CFD integration Add a CFDStart Compomponent
        self.add_subsystem('fan',
                           Compressor(map_data=AXI5,
                                      design=design,
                                      thermo_data=thermo_spec,
                                      elements=AIR_MIX,
                                      map_extrap=True),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])

        self.add_subsystem(
            'splitter',
            Splitter(design=design, thermo_data=thermo_spec, elements=AIR_MIX))

        # Bypass Stream
        ###################
        self.add_subsystem(
            'bypass_duct',
            Duct(design=design, thermo_data=thermo_spec, elements=AIR_MIX))

        # Core Stream
        ##############
        self.add_subsystem(
            'ic_duct',
            Duct(design=design, thermo_data=thermo_spec, elements=AIR_MIX))

        self.add_subsystem('hpc',
                           Compressor(map_data=HPCmap,
                                      design=design,
                                      thermo_data=thermo_spec,
                                      elements=AIR_MIX,
                                      bleed_names=['cool1', 'cool2'],
                                      map_extrap=True),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])

        self.add_subsystem(
            'duct_3',
            Duct(design=design, thermo_data=thermo_spec, elements=AIR_MIX))

        self.add_subsystem('bleed_3',
                           BleedOut(design=design, bleed_names=['cust_bleed']))

        self.add_subsystem(
            'burner',
            Combustor(design=design,
                      thermo_data=thermo_spec,
                      inflow_elements=AIR_MIX,
                      air_fuel_elements=AIR_FUEL_MIX,
                      fuel_type='Jet-A(g)'))
        self.add_subsystem('hpt',
                           Turbine(map_data=HPTmap,
                                   design=design,
                                   thermo_data=thermo_spec,
                                   elements=AIR_FUEL_MIX,
                                   bleed_names=['chargable', 'non_chargable'],
                                   map_extrap=True),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])

        self.add_subsystem(
            'it_duct',
            Duct(design=design, thermo_data=thermo_spec,
                 elements=AIR_FUEL_MIX))

        # uncooled lpt
        self.add_subsystem('lpt',
                           Turbine(map_data=LPTmap,
                                   design=design,
                                   thermo_data=thermo_spec,
                                   elements=AIR_FUEL_MIX,
                                   map_extrap=True),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])

        if not design:
            self.add_subsystem(
                'vabi',
                ExecComp('Fl1_area = Fl1_area_des*fact',
                         Fl1_area_des={'units': 'inch**2'},
                         Fl1_area={
                             'units': 'inch**2',
                             'value': 164.
                         }))

        self.add_subsystem(
            'mixer',
            Mixer(design=design,
                  designed_stream=1,
                  Fl_I1_elements=AIR_FUEL_MIX,
                  Fl_I2_elements=AIR_MIX))

        # augmentor Components
        self.add_subsystem(
            'augmentor',
            Combustor(design=design,
                      thermo_data=thermo_spec,
                      inflow_elements=AIR_FUEL_MIX,
                      air_fuel_elements=AIR_FUEL_MIX,
                      fuel_type='Jet-A(g)'))
        # End CFD HERE
        # Nozzle
        self.add_subsystem(
            'nozzle',
            Nozzle(nozzType='CD',
                   lossCoef='Cfg',
                   thermo_data=thermo_spec,
                   elements=AIR_FUEL_MIX))

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

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

        ##########################################
        #  Connecting the Flow Path
        ##########################################
        connect_flow(self, 'fc.Fl_O', 'inlet.Fl_I')
        connect_flow(self, 'inlet.Fl_O', 'fan.Fl_I')
        connect_flow(self, 'fan.Fl_O', 'splitter.Fl_I')

        # Bypass Connections
        connect_flow(self, 'splitter.Fl_O2', 'bypass_duct.Fl_I')
        connect_flow(self, 'bypass_duct.Fl_O', 'mixer.Fl_I2')

        # Core connections
        connect_flow(self, 'splitter.Fl_O1', 'ic_duct.Fl_I')
        connect_flow(self, 'ic_duct.Fl_O', 'hpc.Fl_I')
        connect_flow(self, 'hpc.Fl_O', 'duct_3.Fl_I')
        connect_flow(self, 'duct_3.Fl_O', 'bleed_3.Fl_I')
        connect_flow(self, 'bleed_3.Fl_O', 'burner.Fl_I')
        connect_flow(self, 'burner.Fl_O', 'hpt.Fl_I')
        connect_flow(self, 'hpt.Fl_O', 'it_duct.Fl_I')
        connect_flow(self, 'it_duct.Fl_O', 'lpt.Fl_I')
        connect_flow(self, 'lpt.Fl_O', 'mixer.Fl_I1')

        connect_flow(self, 'mixer.Fl_O', 'augmentor.Fl_I')
        connect_flow(self, 'augmentor.Fl_O', 'nozzle.Fl_I')

        # Connect cooling flows
        connect_flow(self,
                     'hpc.cool1',
                     'hpt.non_chargable',
                     connect_stat=False)
        connect_flow(self, 'hpc.cool2', 'hpt.chargable', connect_stat=False)

        ##########################################
        #  Additional Connections
        ##########################################
        # Make additional model connections
        self.connect('fc.Fl_O:stat:MN', 'mil_spec.MN')
        self.connect('mil_spec.ram_recovery', 'inlet.ram_recovery')
        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('augmentor.Wfuel', 'perf.Wfuel_1')
        self.connect('inlet.F_ram', 'perf.ram_drag')
        self.connect('nozzle.Fg', 'perf.Fg_0')

        self.connect('fan.trq', 'lp_shaft.trq_0')
        self.connect('lpt.trq', 'lp_shaft.trq_1')

        self.connect('hpc.trq', 'hp_shaft.trq_0')
        self.connect('hpt.trq', 'hp_shaft.trq_1')

        self.connect('fc.Fl_O:stat:P', 'nozzle.Ps_exhaust')

        if not design:
            self.connect('vabi.Fl1_area', 'mixer.Fl_I1_stat_calc.area')

        ##########################################
        #  Balances to define cycle convergence
        ##########################################
        balance = self.add_subsystem('balance', BalanceComp())
        if design:
            balance.add_balance('W',
                                lower=1e-3,
                                upper=200.,
                                units='lbm/s',
                                eq_units='lbf')
            self.connect('balance.W', 'fc.fs.W')
            self.connect('perf.Fn', 'balance.lhs:W')
            # self.add_subsystem('wDV',IndepVarComp('wDes',100,units='lbm/s'))
            # self.connect('wDV.wDes','fc.fs.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', 'augmentor.Fl_I:FAR')
            self.connect('augmentor.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:  # off design
            balance.add_balance('W',
                                lower=1e-3,
                                upper=400.,
                                units='lbm/s',
                                eq_units='inch**2')
            self.connect('balance.W', 'fc.fs.W')
            self.connect('nozzle.Throat:stat:area', 'balance.lhs:W')

            balance.add_balance('BPR', lower=0.25, upper=3.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=.045, 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=.045,
                                val=.017)
            self.connect('balance.FAR_ab', 'augmentor.Fl_I:FAR')
            self.connect('augmentor.Fl_O:tot:T', 'balance.lhs:FAR_ab')

            far_core_bal = ConstrainedTempBalance()
            self.add_subsystem('far_core_bal', far_core_bal)
            self.connect('far_core_bal.FAR', 'burner.Fl_I:FAR')
            self.connect('burner.Fl_O:tot:T', 'far_core_bal.T_computed')
            self.connect('fan.map.shaftNc.NcMap', 'far_core_bal.Nc_computed')

            balance.add_balance('LP_Nmech',
                                val=1.,
                                units='rpm',
                                lower=0.5,
                                upper=2.,
                                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=0.5,
                                upper=2.,
                                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')

        newton = self.nonlinear_solver = NewtonSolver()
        newton.options['atol'] = 1e-6
        newton.options['rtol'] = 1e-10
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 30
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 10
        newton.linesearch = BoundsEnforceLS()
        newton.linesearch.options['bound_enforcement'] = 'scalar'
        # newton.linesearch.options['print_bound_enforce'] = True
        newton.linesearch.options['iprint'] = -1

        # newton.linesearch = ArmijoGoldsteinLS()
        # newton.linesearch.options['c'] = -.1

        self.linear_solver = DirectSolver(assemble_jac=True)

        # TODO: re-factor pycycle so this block isn't needed in default use case!!!
        if design:
            ##########################################
            #  Model Parameters
            ##########################################
            element_params = self.add_subsystem('element_params',
                                                IndepVarComp(),
                                                promotes=["*"])
            # element_params.add_output('inlet:ram_recovery', 0.9990)
            element_params.add_output('inlet:MN_out', 0.65)
            # self.connect('inlet:ram_recovery', 'inlet.ram_recovery')
            self.connect('inlet:MN_out', 'inlet.MN')

            element_params.add_output('fan:effDes', 0.8700)
            element_params.add_output('fan:MN_out', 0.4578)
            self.connect('fan:effDes', 'fan.map.effDes')
            self.connect('fan:MN_out', 'fan.MN')

            element_params.add_output('splitter:MN_out1', 0.3104)
            element_params.add_output('splitter:MN_out2', 0.4518)
            self.connect('splitter:MN_out1', 'splitter.MN1')
            self.connect('splitter:MN_out2', 'splitter.MN2')

            element_params.add_output('ic_duct:dPqP', 0.0048)
            element_params.add_output('ic_duct:MN_out', 0.3121)
            self.connect('ic_duct:dPqP', 'ic_duct.dPqP')
            self.connect('ic_duct:MN_out', 'ic_duct.MN')

            element_params.add_output('hpc:effDes', 0.8707)
            element_params.add_output('hpc:MN_out', 0.2442)
            self.connect('hpc:effDes', 'hpc.map.effDes')
            self.connect('hpc:MN_out', 'hpc.MN')

            element_params.add_output('hpc:cool1:frac_W', 0.09)
            element_params.add_output('hpc:cool1:frac_P', 1.0)
            element_params.add_output('hpc:cool1:frac_work', 1.0)
            self.connect('hpc:cool1:frac_W', 'hpc.cool1:frac_W')
            self.connect('hpc:cool1:frac_P', 'hpc.cool1:frac_P')
            self.connect('hpc:cool1:frac_work', 'hpc.cool1:frac_work')

            element_params.add_output('hpc:cool2:frac_W', 0.07)
            element_params.add_output('hpc:cool2:frac_P', 0.5)
            element_params.add_output('hpc:cool2:frac_work', 0.5)
            self.connect('hpc:cool2:frac_W', 'hpc.cool2:frac_W')
            self.connect('hpc:cool2:frac_P', 'hpc.cool2:frac_P')
            self.connect('hpc:cool2:frac_work', 'hpc.cool2:frac_work')

            element_params.add_output('duct_3:dPqP', 0.0048)
            element_params.add_output('duct_3:MN_out', 0.2)
            self.connect('duct_3:dPqP', 'duct_3.dPqP')
            self.connect('duct_3:MN_out', 'duct_3.MN')

            element_params.add_output('bleed_3:MN_out', 0.3000)
            element_params.add_output('bleed_3:cust_bleed:frac_W', 0.07)
            self.connect('bleed_3:MN_out', 'bleed_3.MN')
            self.connect('bleed_3:cust_bleed:frac_W',
                         'bleed_3.cust_bleed:frac_W')

            element_params.add_output('burner:dPqP', 0.0540)
            element_params.add_output('burner:MN_out', 0.1025)
            self.connect('burner:dPqP', 'burner.dPqP')
            self.connect('burner:MN_out', 'burner.MN')

            element_params.add_output('hpt:effDes', 0.8888)
            element_params.add_output('hpt:MN_out', 0.3650)
            element_params.add_output('hpt:chargable:frac_P', 0.0)
            element_params.add_output('hpt:non_chargable:frac_P', 1.0)
            self.connect('hpt:effDes', 'hpt.map.effDes')
            self.connect('hpt:MN_out', 'hpt.MN')
            self.connect('hpt:chargable:frac_P', 'hpt.chargable:frac_P')
            self.connect('hpt:non_chargable:frac_P',
                         'hpt.non_chargable:frac_P')

            element_params.add_output('it_duct:dPqP', 0.0051)
            element_params.add_output('it_duct:MN_out', 0.3063)
            self.connect('it_duct:dPqP', 'it_duct.dPqP')
            self.connect('it_duct:MN_out', 'it_duct.MN')

            element_params.add_output('lpt:effDes', 0.8996)
            element_params.add_output('lpt:MN_out', 0.4127)
            self.connect('lpt:effDes', 'lpt.map.effDes')
            self.connect('lpt:MN_out', 'lpt.MN')

            element_params.add_output('bypass_duct:dPqP', 0.0107)
            element_params.add_output('bypass_duct:MN_out', 0.4463)
            self.connect('bypass_duct:dPqP', 'bypass_duct.dPqP')
            self.connect('bypass_duct:MN_out', 'bypass_duct.MN')

            # No params for mixer

            element_params.add_output('augmentor:dPqP', 0.0540)
            element_params.add_output('augmentor:MN_out', 0.1025)
            self.connect('augmentor:dPqP', 'augmentor.dPqP')
            self.connect('augmentor:MN_out', 'augmentor.MN')

            element_params.add_output('nozzle:Cfg', 0.9933)
            self.connect('nozzle:Cfg', 'nozzle.Cfg')

            element_params.add_output('lp_shaft:Nmech', 1, units='rpm')
            element_params.add_output('hp_shaft:Nmech', 1, units='rpm')
            element_params.add_output('hp_shaft:HPX', 250.0, units='hp')
            self.connect('lp_shaft:Nmech', 'LP_Nmech')
            self.connect('hp_shaft:Nmech', 'HP_Nmech')
            self.connect('hp_shaft:HPX', 'hp_shaft.HPX')
Exemplo n.º 23
0
    def setup(self):

        design = self.options['design']
        thermo_data = self.options['thermo_data']

        flow1_elements = self.options['Fl_I1_elements']
        flow1_thermo = Thermo(thermo_data, init_reacts=flow1_elements)
        n_flow1_prods = len(flow1_thermo.products)
        in_flow = FlowIn(fl_name='Fl_I1', num_prods=n_flow1_prods)
        self.add_subsystem('in_flow1', in_flow, promotes=['Fl_I1:*'])

        flow2_elements = self.options['Fl_I2_elements']
        flow2_thermo = Thermo(thermo_data, init_reacts=flow2_elements)
        n_flow2_prods = len(flow2_thermo.products)
        in_flow = FlowIn(fl_name='Fl_I2', num_prods=n_flow2_prods)
        self.add_subsystem('in_flow2', in_flow, promotes=['Fl_I2:*'])

        if design:
            # internal flow station to compute the area that is needed to match the static pressures
            if self.options['designed_stream'] == 1:
                Fl1_stat = SetStatic(mode="Ps",
                                     thermo_data=thermo_data,
                                     init_reacts=flow1_elements,
                                     fl_name="Fl_I1_calc:stat")
                self.add_subsystem('Fl_I1_stat_calc',
                                   Fl1_stat,
                                   promotes_inputs=[('init_prod_amounts',
                                                     'Fl_I1:stat:n'),
                                                    ('S', 'Fl_I1:tot:S'),
                                                    ('ht', 'Fl_I1:tot:h'),
                                                    ('W', 'Fl_I1:stat:W'),
                                                    ('Ps', 'Fl_I2:stat:P')],
                                   promotes_outputs=['Fl_I1_calc:stat*'])

                self.add_subsystem('area_calc',
                                   AreaSum(),
                                   promotes_inputs=['Fl_I2:stat:area'],
                                   promotes_outputs=[('area_sum', 'area')])
                self.connect('Fl_I1_calc:stat:area',
                             'area_calc.Fl_I1:stat:area')
            else:
                Fl2_stat = SetStatic(mode="Ps",
                                     thermo_data=thermo_data,
                                     init_reacts=flow2_elements,
                                     fl_name="Fl_I2_calc:stat")
                self.add_subsystem('Fl_I2_stat_calc',
                                   Fl2_stat,
                                   promotes_inputs=[('init_prod_amounts',
                                                     'Fl_I2:tot:n'),
                                                    ('S', 'Fl_I2:tot:S'),
                                                    ('ht', 'Fl_I2:tot:h'),
                                                    ('W', 'Fl_I2:stat:W'),
                                                    ('Ps', 'Fl_I1:stat:P')],
                                   promotes_outputs=['Fl_I2_calc:stat:*'])

                self.add_subsystem('area_calc',
                                   AreaSum(),
                                   promotes_inputs=['Fl_I1:stat:area'],
                                   promotes_outputs=[('area_sum', 'area')])
                self.connect('Fl_I2_calc:stat:area',
                             'area_calc.Fl_I2:stat:area')

        else:
            if self.options['designed_stream'] == 1:
                Fl1_stat = SetStatic(mode="area",
                                     thermo_data=thermo_data,
                                     init_reacts=flow1_elements,
                                     fl_name="Fl_I1_calc:stat")
                self.add_subsystem('Fl_I1_stat_calc',
                                   Fl1_stat,
                                   promotes_inputs=[
                                       ('init_prod_amounts', 'Fl_I1:tot:n'),
                                       ('S', 'Fl_I1:tot:S'),
                                       ('ht', 'Fl_I1:tot:h'),
                                       ('W', 'Fl_I1:stat:W'),
                                       ('guess:Pt', 'Fl_I1:tot:P'),
                                       ('guess:gamt', 'Fl_I1:tot:gamma')
                                   ],
                                   promotes_outputs=['Fl_I1_calc:stat*'])
            else:
                Fl2_stat = SetStatic(mode="area",
                                     thermo_data=thermo_data,
                                     init_reacts=flow2_elements,
                                     fl_name="Fl_I2_calc:stat")
                self.add_subsystem('Fl_I2_stat_calc',
                                   Fl2_stat,
                                   promotes_inputs=[
                                       ('init_prod_amounts', 'Fl_I2:tot:n'),
                                       ('S', 'Fl_I2:tot:S'),
                                       ('ht', 'Fl_I2:tot:h'),
                                       ('W', 'Fl_I2:stat:W'),
                                       ('guess:Pt', 'Fl_I2:tot:P'),
                                       ('guess:gamt', 'Fl_I2:tot:gamma')
                                   ],
                                   promotes_outputs=['Fl_I2_calc:stat*'])

        self.add_subsystem('extraction_ratio',
                           ExecComp('ER=Pt1/Pt2',
                                    Pt1={'units': 'Pa'},
                                    Pt2={'units': 'Pa'}),
                           promotes_inputs=[('Pt1', 'Fl_I1:tot:P'),
                                            ('Pt2', 'Fl_I2:tot:P')],
                           promotes_outputs=['ER'])

        mix_flow = MixFlow(thermo_data=thermo_data,
                           Fl_I1_elements=self.options['Fl_I1_elements'],
                           Fl_I2_elements=self.options['Fl_I2_elements'])
        if self.options['designed_stream'] == 1:
            self.add_subsystem('mix_flow',
                               mix_flow,
                               promotes_inputs=[
                                   'Fl_I1:tot:h', 'Fl_I1:tot:n',
                                   ('Fl_I1:stat:W', 'Fl_I1_calc:stat:W'),
                                   ('Fl_I1:stat:P', 'Fl_I1_calc:stat:P'),
                                   ('Fl_I1:stat:V', 'Fl_I1_calc:stat:V'),
                                   ('Fl_I1:stat:area', 'Fl_I1_calc:stat:area'),
                                   'Fl_I2:tot:h', 'Fl_I2:tot:n',
                                   'Fl_I2:stat:W', 'Fl_I2:stat:P',
                                   'Fl_I2:stat:V', 'Fl_I2:stat:area'
                               ])
        else:
            self.add_subsystem('mix_flow',
                               mix_flow,
                               promotes_inputs=[
                                   'Fl_I1:tot:h', 'Fl_I1:tot:n',
                                   'Fl_I1:stat:W', 'Fl_I1:stat:P',
                                   'Fl_I1:stat:V', 'Fl_I1:stat:area',
                                   'Fl_I2:tot:h', 'Fl_I2:tot:n',
                                   ('Fl_I2:stat:W', 'Fl_I2_calc:stat:W'),
                                   ('Fl_I2:stat:P', 'Fl_I2_calc:stat:P'),
                                   ('Fl_I2:stat:V', 'Fl_I2_calc:stat:V'),
                                   ('Fl_I2:stat:area', 'Fl_I2_calc:stat:area')
                               ])

        # group to converge for the impulse balance
        conv = self.add_subsystem('impulse_converge', Group(), promotes=['*'])

        if self.options['internal_solver']:
            newton = conv.nonlinear_solver = NewtonSolver()
            newton.options['maxiter'] = 30
            newton.options['atol'] = 1e-2
            newton.options['solve_subsystems'] = True
            newton.options['max_sub_solves'] = 20
            newton.linesearch = BoundsEnforceLS()
            newton.linesearch.options['bound_enforcement'] = 'scalar'
            newton.linesearch.options['iprint'] = -1
            conv.linear_solver = DirectSolver(assemble_jac=True)

        out_tot = SetTotal(thermo_data=thermo_data,
                           mode='h',
                           init_reacts=self.options['Fl_I1_elements'],
                           fl_name="Fl_O:tot")
        conv.add_subsystem('out_tot', out_tot, promotes_outputs=['Fl_O:tot:*'])
        self.connect('mix_flow.n_mix', 'out_tot.init_prod_amounts')
        self.connect('mix_flow.ht_mix', 'out_tot.h')
        # note: gets Pt from the balance comp

        out_stat = SetStatic(mode="area",
                             thermo_data=thermo_data,
                             init_reacts=self.options['Fl_I1_elements'],
                             fl_name="Fl_O:stat")
        conv.add_subsystem('out_stat',
                           out_stat,
                           promotes_outputs=['Fl_O:stat:*'],
                           promotes_inputs=[
                               'area',
                           ])
        self.connect('mix_flow.n_mix', 'out_stat.init_prod_amounts')
        self.connect('mix_flow.W_mix', 'out_stat.W')
        conv.connect('Fl_O:tot:S', 'out_stat.S')
        self.connect('mix_flow.ht_mix', 'out_stat.ht')
        conv.connect('Fl_O:tot:P', 'out_stat.guess:Pt')
        conv.connect('Fl_O:tot:gamma', 'out_stat.guess:gamt')

        conv.add_subsystem('imp_out', Impulse())
        conv.connect('Fl_O:stat:P', 'imp_out.P')
        conv.connect('Fl_O:stat:area', 'imp_out.area')
        conv.connect('Fl_O:stat:V', 'imp_out.V')
        conv.connect('Fl_O:stat:W', 'imp_out.W')

        balance = conv.add_subsystem('balance', BalanceComp())
        balance.add_balance('P_tot',
                            val=100,
                            units='psi',
                            eq_units='N',
                            lower=1e-3,
                            upper=10000)
        conv.connect('balance.P_tot', 'out_tot.P')
        conv.connect('imp_out.impulse', 'balance.lhs:P_tot')
        self.connect(
            'mix_flow.impulse_mix', 'balance.rhs:P_tot'
        )  #note that this connection comes from outside the convergence group
Exemplo n.º 24
0
    def setup(self):

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

        # Add engine elements
        self.add_subsystem(
            'fc', FlightConditions(thermo_data=thermo_spec, elements=AIR_MIX))
        self.add_subsystem(
            'inlet',
            Inlet(design=design, thermo_data=thermo_spec, elements=AIR_MIX))
        self.add_subsystem('comp',
                           Compressor(
                               map_data=AXI5,
                               design=design,
                               thermo_data=thermo_spec,
                               elements=AIR_MIX,
                           ),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem(
            'burner',
            Combustor(design=design,
                      thermo_data=thermo_spec,
                      inflow_elements=AIR_MIX,
                      air_fuel_elements=AIR_FUEL_MIX,
                      fuel_type='JP-7'))
        self.add_subsystem('turb',
                           Turbine(
                               map_data=LPT2269,
                               design=design,
                               thermo_data=thermo_spec,
                               elements=AIR_FUEL_MIX,
                           ),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem('pt',
                           Turbine(
                               map_data=LPT2269,
                               design=design,
                               thermo_data=thermo_spec,
                               elements=AIR_FUEL_MIX,
                           ),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.add_subsystem(
            'nozz',
            Nozzle(nozzType='CV',
                   lossCoef='Cv',
                   thermo_data=thermo_spec,
                   elements=AIR_FUEL_MIX))
        self.add_subsystem('HP_shaft',
                           Shaft(num_ports=2),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem('LP_shaft',
                           Shaft(num_ports=1),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.add_subsystem('perf', Performance(num_nozzles=1, num_burners=1))

        # Connect flow stations
        connect_flow(self, 'fc.Fl_O', 'inlet.Fl_I', connect_w=False)
        connect_flow(self, 'inlet.Fl_O', 'comp.Fl_I')
        connect_flow(self, 'comp.Fl_O', 'burner.Fl_I')
        connect_flow(self, 'burner.Fl_O', 'turb.Fl_I')
        connect_flow(self, 'turb.Fl_O', 'pt.Fl_I')
        connect_flow(self, 'pt.Fl_O', 'nozz.Fl_I')

        # Connect turbomachinery elements to shaft
        self.connect('comp.trq', 'HP_shaft.trq_0')
        self.connect('turb.trq', 'HP_shaft.trq_1')
        self.connect('pt.trq', 'LP_shaft.trq_0')

        # Connnect nozzle exhaust to freestream static conditions
        self.connect('fc.Fl_O:stat:P', 'nozz.Ps_exhaust')

        # Connect outputs to pefromance element
        self.connect('inlet.Fl_O:tot:P', 'perf.Pt2')
        self.connect('comp.Fl_O:tot:P', 'perf.Pt3')
        self.connect('burner.Wfuel', 'perf.Wfuel_0')
        self.connect('inlet.F_ram', 'perf.ram_drag')
        self.connect('nozz.Fg', 'perf.Fg_0')
        self.connect('LP_shaft.pwr_net', 'perf.power')

        # Add balances for design and off-design
        balance = self.add_subsystem('balance', BalanceComp())
        if design:

            balance.add_balance('W', val=27.0, units='lbm/s', eq_units=None)
            self.connect('balance.W', 'inlet.Fl_I:stat:W')
            self.connect('nozz.PR', '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('turb_PR',
                                val=3.0,
                                lower=1.001,
                                upper=8,
                                eq_units='hp',
                                rhs_val=0.)
            self.connect('balance.turb_PR', 'turb.PR')
            self.connect('HP_shaft.pwr_net', 'balance.lhs:turb_PR')

            balance.add_balance('pt_PR',
                                val=3.0,
                                lower=1.001,
                                upper=8,
                                eq_units='hp')
            self.connect('balance.pt_PR', 'pt.PR')
            self.connect('LP_shaft.pwr_net', 'balance.lhs:pt_PR')

        else:

            balance.add_balance('FAR', eq_units='hp', lower=1e-4, val=.3)
            self.connect('balance.FAR', 'burner.Fl_I:FAR')
            self.connect('LP_shaft.pwr_net', 'balance.lhs:FAR')

            balance.add_balance('HP_Nmech',
                                val=1.5,
                                units='rpm',
                                lower=500.,
                                eq_units='hp',
                                rhs_val=0.)
            self.connect('balance.HP_Nmech', 'HP_Nmech')
            self.connect('HP_shaft.pwr_net', 'balance.lhs:HP_Nmech')

            balance.add_balance('W',
                                val=27.0,
                                units='lbm/s',
                                eq_units='inch**2')
            self.connect('balance.W', 'inlet.Fl_I:stat:W')
            self.connect('nozz.Throat:stat:area', 'balance.lhs:W')

        # Setup solver to converge engine
        self.set_order([
            'balance', 'fc', 'inlet', 'comp', 'burner', 'turb', 'pt', 'nozz',
            'HP_shaft', 'LP_shaft', 'perf'
        ])

        newton = self.nonlinear_solver = NewtonSolver()
        newton.options['atol'] = 1e-6
        newton.options['rtol'] = 1e-6
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 15
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 100
        newton.linesearch = BoundsEnforceLS()
        # newton.linesearch = ArmijoGoldsteinLS()
        # newton.linesearch.options['c'] = .0001
        newton.linesearch.options['bound_enforcement'] = 'scalar'
        newton.linesearch.options['iprint'] = -1

        self.linear_solver = DirectSolver(assemble_jac=True)
Exemplo n.º 25
0
def main():

    num_nodes = 1
    num_blades = 10
    num_radial = 15
    num_cp = 6

    af_filename = 'airfoils/mh117.dat'
    chord = 20.
    theta = 5.0*np.pi/180.0
    pitch = 0.

    # Numbers taken from the Aviary group's study of the RVLT tiltwing
    # turboelectric concept vehicle.
    n_props = 4
    hub_diameter = 30.  # cm
    prop_diameter = 15*30.48  # 15 ft in cm
    c0 = np.sqrt(1.4*287.058*300.)  # meters/second
    rho0 = 1.4*98600./(c0*c0)  # kg/m^3
    omega = 236.  # rad/s

    # Find the thrust per rotor from the vehicle's mass.
    m_full = 6367  # kg
    g = 9.81  # m/s**2
    thrust_vtol = m_full*g/n_props

    prob = Problem()

    comp = IndepVarComp()
    comp.add_output('rho', val=rho0, shape=num_nodes, units='kg/m**3')
    comp.add_output('mu', val=1., shape=num_nodes, units='N/m**2*s')
    comp.add_output('asound', val=c0, shape=num_nodes, units='m/s')
    comp.add_output('v', val=2., shape=num_nodes, units='m/s')
    comp.add_output('alpha', val=0., shape=num_nodes, units='rad')
    comp.add_output('incidence', val=0., shape=num_nodes, units='rad')
    comp.add_output('precone', val=0., units='deg')
    comp.add_output('hub_diameter', val=hub_diameter, shape=num_nodes, units='cm')
    comp.add_output('prop_diameter', val=prop_diameter, shape=num_nodes, units='cm')
    comp.add_output('pitch', val=pitch, shape=num_nodes, units='rad')
    comp.add_output('chord_dv', val=chord, shape=num_cp, units='cm')
    comp.add_output('theta_dv', val=theta, shape=num_cp, units='rad')
    comp.add_output('thrust_vtol', val=thrust_vtol, shape=num_nodes, units='N')
    prob.model.add_subsystem('indep_var_comp', comp, promotes=['*'])

    comp = GeometryGroup(num_nodes=num_nodes, num_cp=num_cp,
                         num_radial=num_radial)
    prob.model.add_subsystem(
        'geometry_group', comp,
        promotes_inputs=['hub_diameter', 'prop_diameter', 'chord_dv',
                         'theta_dv', 'pitch'],
        promotes_outputs=['radii', 'dradii', 'chord', 'theta'])

    balance_group = Group()

    comp = CCBladeGroup(num_nodes=num_nodes, num_radial=num_radial,
                        num_blades=num_blades, af_filename=af_filename,
                        turbine=False)
    balance_group.add_subsystem(
        'ccblade_group', comp,
        promotes_inputs=['radii', 'dradii', 'chord', 'theta', 'rho', 'mu',
                         'asound', 'v', 'precone', 'omega', 'hub_diameter',
                         'prop_diameter'],
        promotes_outputs=['thrust', 'torque', 'efficiency'])

    comp = BalanceComp()
    comp.add_balance(
        name='omega',
        eq_units='N', lhs_name='thrust', rhs_name='thrust_vtol',
        val=omega, units='rad/s',
        lower=0.)
    balance_group.add_subsystem('thrust_balance_comp', comp, promotes=['*'])

    balance_group.linear_solver = DirectSolver(assemble_jac=True)
    # balance_group.nonlinear_solver = NewtonSolver(maxiter=20, iprint=2)
    # balance_group.nonlinear_solver.options['solve_subsystems'] = True
    # balance_group.nonlinear_solver.options['atol'] = 1e-9

    prob.model.add_subsystem('thrust_balance_group', balance_group,
                             promotes=['*'])

    prob.model.nonlinear_solver = NewtonSolver(maxiter=20, iprint=2)
    prob.model.nonlinear_solver.options['solve_subsystems'] = True
    prob.model.nonlinear_solver.options['atol'] = 1e-9
    prob.model.nonlinear_solver.linesearch = BoundsEnforceLS()
    prob.model.nonlinear_solver.linesearch.options['iprint'] = 2
    prob.setup()
    prob.final_setup()

    # Calculate the induced axial velocity at the rotor for hover, used for
    # non-diminsionalation.
    rho = prob.get_val('rho', units='kg/m**3')[0]
    hub_diameter = prob.get_val('hub_diameter', units='m')[0]
    prop_diameter = prob.get_val('prop_diameter', units='m')[0]
    thrust_vtol = prob.get_val('thrust_vtol', units='N')[0]
    A_rotor = 0.25*np.pi*(prop_diameter**2 - hub_diameter**2)
    v_h = np.sqrt(thrust_vtol/(2*rho*A_rotor))

    # Climb:
    climb_velocity_nondim = np.linspace(0.1, 2., 10)
    induced_velocity_nondim = np.zeros_like(climb_velocity_nondim)
    for vc, vi in np.nditer(
            [climb_velocity_nondim, induced_velocity_nondim],
            op_flags=[['readonly'], ['writeonly']]):

        # Run the model with the requested climb velocity.
        prob.set_val('v', vc*v_h, units='m/s')
        print(f"v = {prob.get_val('v', units='m/s')}")
        prob.run_model()

        # Calculate the area-weighted average induced velocity at the rotor.
        # Need the area of each blade section.
        radii = prob.get_val('radii',
                             units='m')
        dradii = prob.get_val('dradii',
                              units='m')
        dArea = 2*np.pi*radii*dradii

        # Get the induced velocity at the rotor plane for each blade section.
        Vx = prob.get_val('ccblade_group.Vx', units='m/s')
        a = prob.get_val('ccblade_group.ccblade_comp.a')

        # Get the area-weighted average of the induced velocity.
        vi[...] = np.sum(a*Vx*dArea/A_rotor)/v_h

    # Induced velocity from plain old momentum theory (for climb).
    induced_velocity_mt = (
        -0.5*climb_velocity_nondim + np.sqrt((0.5*climb_velocity_nondim)**2 + 1.))

    fig, ax = plt.subplots()
    ax.plot(climb_velocity_nondim, -induced_velocity_nondim,
            label='CCBlade.jl (climb)')
    ax.plot(climb_velocity_nondim, induced_velocity_mt,
            label='Momentum Theory (climb)')

    # Descent:
    climb_velocity_nondim = np.linspace(-4., -2.5, 10)
    induced_velocity_nondim = np.zeros_like(climb_velocity_nondim)
    for vc, vi in np.nditer(
            [climb_velocity_nondim, induced_velocity_nondim],
            op_flags=[['readonly'], ['writeonly']]):

        # Run the model with the requested climb velocity.
        prob.set_val('v', vc*v_h, units='m/s')
        print(f"vc = {vc}, v = {prob.get_val('v', units='m/s')}")
        prob.run_model()

        # Calculate the area-weighted average induced velocity at the rotor.
        # Need the area of each blade section.
        radii = prob.get_val('radii',
                             units='m')
        dradii = prob.get_val('dradii',
                              units='m')
        dArea = 2*np.pi*radii*dradii

        # Get the induced velocity at the rotor plane for each blade section.
        Vx = prob.get_val('ccblade_group.Vx', units='m/s')
        a = prob.get_val('ccblade_group.ccblade_comp.a')

        # Get the area-weighted average of the induced velocity.
        vi[...] = np.sum(a*Vx*dArea/A_rotor)/v_h

    # Induced velocity from plain old momentum theory (for descent).
    induced_velocity_mt = (
        -0.5*climb_velocity_nondim - np.sqrt((0.5*climb_velocity_nondim)**2 - 1.))

    # Plot the induced velocity for descent.
    ax.plot(climb_velocity_nondim, -induced_velocity_nondim,
            label='CCBlade.jl (descent)')
    ax.plot(climb_velocity_nondim, induced_velocity_mt,
            label='Momentum Theory (descent)')

    # # Empirical region:
    # climb_velocity_nondim = np.linspace(-1.9, -1.5, 5)
    # induced_velocity_nondim = np.zeros_like(climb_velocity_nondim)
    # for vc, vi in np.nditer(
    #         [climb_velocity_nondim, induced_velocity_nondim],
    #         op_flags=[['readonly'], ['writeonly']]):

    #     # Run the model with the requested climb velocity.
    #     prob.set_val('v', vc*v_h, units='m/s')
    #     print(f"vc = {vc}, v = {prob.get_val('v', units='m/s')}")
    #     prob.run_model()

    #     # Calculate the area-weighted average induced velocity at the rotor.
    #     # Need the area of each blade section.
    #     radii = prob.get_val('radii',
    #                          units='m')
    #     dradii = prob.get_val('dradii',
    #                           units='m')
    #     dArea = 2*np.pi*radii*dradii

    #     # Get the induced velocity at the rotor plane for each blade section.
    #     Vx = prob.get_val('ccblade_group.Vx', units='m/s')
    #     a = prob.get_val('ccblade_group.ccblade_comp.a')

    #     # Get the area-weighted average of the induced velocity.
    #     vi[...] = np.sum(a*Vx*dArea/A_rotor)/v_h

    # # Plot the induced velocity for the empirical region.
    # ax.plot(climb_velocity_nondim, -induced_velocity_nondim,
    #         label='CCBlade.jl (empirical region)')

    ax.set_xlabel('Vc/vh')
    ax.set_ylabel('Vi/vh')
    ax.legend()
    fig.savefig('induced_velocity.png')
Exemplo n.º 26
0
prob.model.connect('T4_ratio.TOC_T4', 'TOC.balance.rhs:FAR')
prob.model.connect('TR', 'T4_ratio.TR')
prob.model.set_order(['des_vars', 'T4_ratio', 'TOC', 'RTO', 'SLS', 'CRZ', 'bal'])


newton = prob.model.nonlinear_solver = NewtonSolver()
newton.options['atol'] = 1e-6
newton.options['rtol'] = 1e-6
newton.options['iprint'] = 2
newton.options['maxiter'] = 20
newton.options['solve_subsystems'] = True
newton.options['max_sub_solves'] = 10
newton.options['err_on_non_converge'] = True
newton.options['reraise_child_analysiserror'] = False
# newton.linesearch =  ArmijoGoldsteinLS()
newton.linesearch =  BoundsEnforceLS()
# newton.linesearch.options['maxiter'] = 2
newton.linesearch.options['bound_enforcement'] = 'scalar'
# newton.linesearch.options['print_bound_enforce'] = True
newton.linesearch.options['iprint'] = -1
# newton.linesearch.options['print_bound_enforce'] = False
# newton.linesearch.options['alpha'] = 0.5

prob.model.linear_solver = DirectSolver(assemble_jac=True)
# prob.model.jacobian = CSCJacobian()

# recorder = SqliteRecorder('N3_MDP.sql')

# prob.model.linear_solver = PETScKrylov()
# prob.model.linear_solver.options['iprint'] = 2
# prob.model.linear_solver.precon = DirectSolver()
Exemplo n.º 27
0
    def setup(self):
        thermo_spec = species_data.janaf
        design = self.options['design']

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

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

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

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

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

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

        # Connect cooling flows
        connect_flow(self, 'hpc.cool1', 'lpt.cool1', connect_stat=False)
        connect_flow(self, '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', 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 = 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.linesearch = BoundsEnforceLS()
        newton.linesearch.options['bound_enforcement'] = 'scalar'
        newton.linesearch.options['iprint'] = -1


        self.linear_solver = DirectSolver(assemble_jac=True)