Ejemplo n.º 1
0
    def test_record_line_search_armijo_goldstein(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 = ArmijoGoldsteinLS(
            bound_enforcement='vector')

        # This is pretty bogus, but it ensures that we get a few LS iterations.
        ls.options['c'] = 100.0
        ls.add_recorder(recorder)

        self.prob.setup(check=False)

        t0, t1 = run_driver(self.prob)

        self.prob.cleanup()

        expected_abs_error = 3.49773898733e-9
        expected_rel_error = expected_abs_error / 2.9086436370499857e-08

        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'], [])
Ejemplo n.º 2
0
    def setup(self):
        nn = self.options['num_nodes']

        self.add_subsystem(name='pack',
                           subsys=packSize(num_nodes=nn),
                           promotes_inputs=['*'],
                           promotes_outputs=['*'])

        self.add_subsystem(name='pcm',
                           subsys=pcmSize(num_nodes=nn),
                           promotes_inputs=['*'],
                           promotes_outputs=['*'])

        self.add_subsystem(name='ohp',
                           subsys=OHP(num_nodes=nn),
                           promotes_inputs=['*'],
                           promotes_outputs=['*'])

        self.add_subsystem(name='mass',
                           subsys=packMass(num_nodes=nn),
                           promotes_inputs=['*'],
                           promotes_outputs=['*'])

        self.set_input_defaults('frame_mass', 0.01, units='kg')

        self.nonlinear_solver = NewtonSolver(maxiter=30,
                                             atol=1e-10,
                                             rtol=1e-100)
        self.nonlinear_solver.options['solve_subsystems'] = True
        self.nonlinear_solver.options['max_sub_solves'] = 500
        self.nonlinear_solver.linesearch = ArmijoGoldsteinLS()
        self.linear_solver = DirectSolver()
        self.nonlinear_solver.options['err_on_non_converge'] = True
Ejemplo n.º 3
0
            def setup(self):
                self.add_subsystem('n1',
                                   Node(n_in=1, n_out=2),
                                   promotes_inputs=[('I_in:0', 'I_in')])
                self.add_subsystem('n2', Node())  # leaving defaults

                self.add_subsystem('R1',
                                   Resistor(R=100.),
                                   promotes_inputs=[('V_out', 'Vg')])
                self.add_subsystem('R2', Resistor(R=10000.))
                self.add_subsystem('D1',
                                   Diode(),
                                   promotes_inputs=[('V_out', 'Vg')])

                self.connect('n1.V', ['R1.V_in', 'R2.V_in'])
                self.connect('R1.I', 'n1.I_out:0')
                self.connect('R2.I', 'n1.I_out:1')

                self.connect('n2.V', ['R2.V_out', 'D1.V_in'])
                self.connect('R2.I', 'n2.I_in:0')
                self.connect('D1.I', 'n2.I_out:0')

                self.nonlinear_solver = NewtonSolver()
                self.linear_solver = DirectSolver()

                self.nonlinear_solver.options['iprint'] = 2
                self.nonlinear_solver.options['maxiter'] = 10
                self.nonlinear_solver.options['solve_subsystems'] = True
                self.nonlinear_solver.linesearch = ArmijoGoldsteinLS()
                self.nonlinear_solver.linesearch.options['maxiter'] = 10
                self.nonlinear_solver.linesearch.options['iprint'] = 2
Ejemplo n.º 4
0
    def test_record_line_search_armijo_goldstein(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 = ArmijoGoldsteinLS(bound_enforcement='vector')

        # This is pretty bogus, but it ensures that we get a few LS iterations.
        ls.options['c'] = 100.0
        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 = 3.49773898733e-9
        expected_rel_error = expected_abs_error / 2.9086436370499857e-08

        solver_iteration = json.loads(self.solver_iterations)
        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]}
        ]

        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'])
Ejemplo n.º 5
0
    def test_circuit_advanced_newton(self):
        from openmdao.api import ArmijoGoldsteinLS, Problem, IndepVarComp

        from openmdao.test_suite.scripts.circuit_analysis import Circuit

        p = Problem()
        model = p.model

        model.add_subsystem('ground', IndepVarComp('V', 0., units='V'))
        model.add_subsystem('source', IndepVarComp('I', 0.1, units='A'))
        model.add_subsystem('circuit', Circuit())

        model.connect('source.I', 'circuit.I_in')
        model.connect('ground.V', 'circuit.Vg')

        p.setup()

        # you can change the NewtonSolver settings in circuit after setup is called
        newton = p.model.circuit.nonlinear_solver
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 10
        newton.options['solve_subsystems'] = True
        newton.linesearch = ArmijoGoldsteinLS()
        newton.linesearch.options['maxiter'] = 10
        newton.linesearch.options['iprint'] = 2

        # set some initial guesses
        p['circuit.n1.V'] = 10.
        p['circuit.n2.V'] = 1e-3

        p.run_model()

        assert_rel_error(self, p['circuit.n1.V'], 9.90830282, 1e-5)
        assert_rel_error(self, p['circuit.n2.V'], 0.73858486, 1e-5)
        assert_rel_error(self, p['circuit.R1.I'], 0.09908303, 1e-5)
        assert_rel_error(self, p['circuit.R2.I'], 0.00091697, 1e-5)
        assert_rel_error(self, p['circuit.D1.I'], 0.00091697, 1e-5)

        # sanity check: should sum to .1 Amps
        assert_rel_error(self, p['circuit.R1.I'] + p['circuit.D1.I'], .1, 1e-6)
Ejemplo n.º 6
0
    def test_circuit_voltage_source(self):
        from openmdao.api import ArmijoGoldsteinLS, Problem, IndepVarComp, BalanceComp, ExecComp
        from openmdao.api import NewtonSolver, DirectSolver, NonlinearRunOnce, LinearRunOnce

        from openmdao.test_suite.scripts.circuit_analysis import Circuit

        p = Problem()
        model = p.model

        model.add_subsystem('ground', IndepVarComp('V', 0., units='V'))

        # replacing the fixed current source with a BalanceComp to represent a fixed Voltage source
        # model.add_subsystem('source', IndepVarComp('I', 0.1, units='A'))
        model.add_subsystem('batt', IndepVarComp('V', 1.5, units='V'))
        bal = model.add_subsystem('batt_balance', BalanceComp())
        bal.add_balance('I', units='A', eq_units='V')

        model.add_subsystem('circuit', Circuit())
        model.add_subsystem(
            'batt_deltaV',
            ExecComp('dV = V1 - V2',
                     V1={'units': 'V'},
                     V2={'units': 'V'},
                     dV={'units': 'V'}))

        # current into the circuit is now the output state from the batt_balance comp
        model.connect('batt_balance.I', 'circuit.I_in')
        model.connect('ground.V', ['circuit.Vg', 'batt_deltaV.V2'])
        model.connect('circuit.n1.V', 'batt_deltaV.V1')

        # set the lhs and rhs for the battery residual
        model.connect('batt.V', 'batt_balance.rhs:I')
        model.connect('batt_deltaV.dV', 'batt_balance.lhs:I')

        p.setup()

        ###################
        # Solver Setup
        ###################

        # change the circuit solver to RunOnce because we're
        # going to converge at the top level of the model with newton instead
        p.model.circuit.nonlinear_solver = NonlinearRunOnce()
        p.model.circuit.linear_solver = LinearRunOnce()

        # Put Newton at the top so it can also converge the new BalanceComp residual
        newton = p.model.nonlinear_solver = NewtonSolver()
        p.model.linear_solver = DirectSolver()
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 20
        newton.options['solve_subsystems'] = True
        newton.linesearch = ArmijoGoldsteinLS()
        newton.linesearch.options['maxiter'] = 10
        newton.linesearch.options['iprint'] = 2

        # set initial guesses from the current source problem
        p['circuit.n1.V'] = 9.8
        p['circuit.n2.V'] = .7

        p.run_model()

        assert_rel_error(self, p['circuit.n1.V'], 1.5, 1e-5)
        assert_rel_error(self, p['circuit.n2.V'], 0.676232, 1e-5)
        assert_rel_error(self, p['circuit.R1.I'], 0.015, 1e-5)
        assert_rel_error(self, p['circuit.R2.I'], 8.23767999e-05, 1e-5)
        assert_rel_error(self, p['circuit.D1.I'], 8.23767999e-05, 1e-5)
Ejemplo n.º 7
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('fan', Compressor(map_data=FanMap, design=design, thermo_data=thermo_spec, elements=AIR_MIX,
                                        bleed_names=[], statics=statics, map_extrap=True), promotes_inputs=[('Nmech','LP_Nmech')])
        self.add_subsystem('splitter', Splitter(design=design, thermo_data=thermo_spec, elements=AIR_MIX, statics=statics))
        self.add_subsystem('duct4', 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, map_extrap=True),promotes_inputs=[('Nmech','LP_Nmech')])
        self.add_subsystem('duct6', Duct(design=design, thermo_data=thermo_spec, elements=AIR_MIX, statics=statics))
        self.add_subsystem('hpc', Compressor(map_data=HPCmap, design=design, thermo_data=thermo_spec, elements=AIR_MIX,
                                        bleed_names=['cool1','cool2','cust'], statics=statics, map_extrap=True),promotes_inputs=[('Nmech','HP_Nmech')])
        self.add_subsystem('bld3', BleedOut(design=design, statics=statics, bleed_names=['cool3','cool4']))
        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, map_extrap=True),promotes_inputs=[('Nmech','HP_Nmech')])
        self.add_subsystem('duct11', 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, map_extrap=True),promotes_inputs=[('Nmech','LP_Nmech')])
        self.add_subsystem('duct13', Duct(design=design, thermo_data=thermo_spec, elements=AIR_FUEL_MIX, statics=statics))
        self.add_subsystem('core_nozz', Nozzle(nozzType='CV', lossCoef='Cv', thermo_data=thermo_spec, elements=AIR_FUEL_MIX))

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

        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')])
        self.add_subsystem('perf', Performance(num_nozzles=2, num_burners=1))

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

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

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

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

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

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

        else:

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

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

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

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

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

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

        connect_flow(self, 'fc.Fl_O', 'inlet.Fl_I', connect_w=False)
        connect_flow(self, 'inlet.Fl_O', 'fan.Fl_I')
        connect_flow(self, 'fan.Fl_O', 'splitter.Fl_I')
        connect_flow(self, 'splitter.Fl_O1', 'duct4.Fl_I')
        connect_flow(self, 'duct4.Fl_O', 'lpc.Fl_I')
        connect_flow(self, 'lpc.Fl_O', 'duct6.Fl_I')
        connect_flow(self, 'duct6.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', 'duct11.Fl_I')
        connect_flow(self, 'duct11.Fl_O', 'lpt.Fl_I')
        connect_flow(self, 'lpt.Fl_O', 'duct13.Fl_I')
        connect_flow(self, 'duct13.Fl_O','core_nozz.Fl_I')
        connect_flow(self, 'splitter.Fl_O2', 'byp_bld.Fl_I')
        connect_flow(self, 'byp_bld.Fl_O', 'duct15.Fl_I')
        connect_flow(self, 'duct15.Fl_O', 'byp_nozz.Fl_I')
       

        connect_flow(self, 'hpc.cool1', 'lpt.cool1', connect_stat=False)
        connect_flow(self, 'hpc.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-8
        newton.options['rtol'] = 1e-8
        newton.options['iprint'] = 2
        newton.options['maxiter'] = 50
        newton.options['solve_subsystems'] = True
        newton.options['max_sub_solves'] = 100

        
        # ls = newton.linesearch = BoundsEnforceLS()
        ls = newton.linesearch = ArmijoGoldsteinLS()
        ls.options['maxiter'] = 3
        ls.options['bound_enforcement'] = 'scalar'
        # ls.options['print_bound_enforce'] = True

        self.linear_solver = DirectSolver(assemble_jac=True)
Ejemplo n.º 8
0
    # set the lhs and rhs for the battery residual
    model.connect('batt.V', 'batt_balance.rhs:I')
    model.connect('batt_deltaV.dV', 'batt_balance.lhs:I')

    p.setup()

    ###################
    # Solver Setup
    ###################

    # change the circuit solver to RunOnce because we're
    # going to converge at the top level of the model with newton instead
    p.model.circuit.nonlinear_solver = NonlinearRunOnce()
    p.model.circuit.linear_solver = LinearRunOnce()

    # Put Newton at the top so it can also converge the new BalanceComp residual
    newton = p.model.nonlinear_solver = NewtonSolver()
    p.model.linear_solver = DirectSolver()
    newton.options['iprint'] = 2
    newton.options['maxiter'] = 20
    newton.options['solve_subsystems'] = True
    newton.linesearch = ArmijoGoldsteinLS()
    newton.linesearch.options['maxiter'] = 10
    newton.linesearch.options['iprint'] = 2

    # set initial guesses from the current source problem
    p['circuit.n1.V'] = 9.8
    p['circuit.n2.V'] = .7

    p.run_model()
Ejemplo n.º 9
0
    def setup(self):

        newton = self.nonlinear_solver = NewtonSolver()
        newton.options['maxiter'] = 100
        newton.options['iprint'] = 2
        newton.options['atol'] = 1e-10
        newton.options['rtol'] = 1e-10

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

        # ln_bt = newton.linesearch = BoundsEnforceLS()
        ln_bt = newton.linesearch = ArmijoGoldsteinLS()
        ln_bt.options['maxiter'] = 2
        ln_bt.options['bound_enforcement'] = 'scalar'
        ln_bt.options['iprint'] = -1
        #ln_bt.options['maxiter'] = 1

        # Once the concentration of a species reaches its minimum, we
        # can essentially remove it from the problem. This switch controls
        # whether to do this.
        self.remove_trace_species = False

        # multiply a damping function that scales down the residual for trace species
        self.use_trace_damping = True

        thermo = self.options['thermo']
        mode = self.options['mode']

        num_prod = thermo.num_prod
        num_element = thermo.num_element

        # Input vars
        self.add_input('init_prod_amounts', val=thermo.init_prod_amounts, shape=(num_prod,),
                       desc="initial mass fractions of products, before equilibrating")

        self.add_input('P', val=1.0, units="bar", desc="Pressure")

        if mode == "T":  # T is an input
            self.add_input('T', val=400., units="degK", desc="Temperature")
        elif mode == "h" or mode == "S":  # T becomes another state variable
            if mode == "h":  # hP solve
                self.add_input('h', val=0., units="cal/g",
                               desc="Enthalpy")
            elif mode == "S":  # SP solve
                self.add_input('S', val=0., units="cal/(g*degK)",
                               desc="Entropy")

            self.T_idx = num_prod + num_element
            self.add_output('T', val=400., units="degK", desc="Temperature",
                            lower=1.,
                            res_ref=100
                            )

        # State vars
        self.n_init = np.ones(num_prod) / num_prod / 10  # initial guess for n

        # for a known solution, these are the orders of magnitude of the variables.
        # We'll try setting scaling to +/1 1 order around thee values

        mag = np.array([3.23319258e-04, 1.00000000e-10, 1.10131241e-05, 1.00000000e-10,
                        1.15755853e-08, 2.95692989e-09, 1.00000000e-10, 2.69578794e-02,
                        1.00000000e-10, 7.23198523e-03])

        #mag = np.ones(num_prod)
        self.add_output('n', shape=num_prod,
                        val=self.n_init,
                        desc="mole fractions of the mixture",
                        lower=1e-10,
                        res_ref=10000.
                        )

        self.add_output('pi', val=np.ones(num_element),
                        desc="modified lagrange multipliers from the Gibbs lagrangian")

        # Explicit Outputs
        self.add_output('b0', shape=num_element,  # when converged, b0=b
                        desc='assigned kg-atoms of element i per total kg of reactant '
                             'for the initial prod amounts')
        self.add_output('n_moles', lower=1e-10, val=0.034, shape=1,
                        desc="1/molecular weight of gas")

        # allocate the newton Jacobian
        self.size = size = num_prod + num_element
        if mode != "T":
            size += 1  # added T as a state variable

        self._dRdy = np.zeros((size, size))
        self._rhs = np.zeros(size)  # used for solve_linear

        # Cached stuff for speed
        self.H0_T = None
        self.S0_T = None
        self.dH0_dT = None
        self.dS0_dT = None
        self.sum_n_H0_T = None

        # self.deriv_options['check_type'] = 'cs'
        # self.deriv_options['check_step_size'] = 1e-50
        # self.deriv_options['type'] = 'fd'
        # self.deriv_options['step_size'] = 1e-5

        self.declare_partials('n', ['n', 'pi', 'P', 'T'])
        self.declare_partials('pi', ['n', 'init_prod_amounts'])
        self.declare_partials('b0', ['b0', 'init_prod_amounts'])
        self.declare_partials('n_moles', 'n')
        self.declare_partials('n_moles', 'n_moles', val=-1)

        if mode == 'h':
            self.declare_partials('T', ['n', 'h', 'T'])
        elif mode == 'S':
            self.declare_partials('T', ['n', 'S', 'T', 'P'])
Ejemplo n.º 10
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('comp', Compressor(map_data=AXI5, design=design, thermo_data=thermo_spec, elements=AIR_MIX,
                                        bleed_names=['cool1','cool2'], statics=statics, map_extrap=True),promotes_inputs=['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', statics=statics))
        self.add_subsystem('turb', Turbine(map_data=LPT2269, design=design, thermo_data=thermo_spec, elements=AIR_FUEL_MIX,
                                        bleed_names=['cool1','cool2'], statics=statics, map_extrap=True),promotes_inputs=['Nmech'])
        self.add_subsystem('ab', Combustor(design=design,thermo_data=thermo_spec,
                                        inflow_elements=AIR_FUEL_MIX,
                                        air_fuel_elements=AIR_FUEL_MIX,
                                        fuel_type='JP-7', statics=statics))
        self.add_subsystem('nozz', Nozzle(nozzType='CD', lossCoef='Cv', thermo_data=thermo_spec, elements=AIR_FUEL_MIX, internal_solver=True))
        self.add_subsystem('shaft', Shaft(num_ports=2),promotes_inputs=['Nmech'])
        self.add_subsystem('perf', Performance(num_nozzles=1, num_burners=2))

        self.connect('duct1.Fl_O:tot:P', 'perf.Pt2')
        self.connect('comp.Fl_O:tot:P', 'perf.Pt3')
        self.connect('burner.Wfuel', 'perf.Wfuel_0')
        self.connect('ab.Wfuel', 'perf.Wfuel_1')
        self.connect('inlet.F_ram', 'perf.ram_drag')
        self.connect('nozz.Fg', 'perf.Fg_0')

        self.connect('comp.trq', 'shaft.trq_0')
        self.connect('turb.trq', 'shaft.trq_1')
        # self.connect('shaft.Nmech', 'comp.Nmech')
        # self.connect('shaft.Nmech', 'turb.Nmech')
        self.connect('fc.Fl_O:stat:P', 'nozz.Ps_exhaust')

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

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

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

            balance.add_balance('turb_PR', val=1.5, lower=1.001, upper=8, eq_units='hp', rhs_val=0.)
            self.connect('balance.turb_PR', 'turb.PR')
            self.connect('shaft.pwr_net', 'balance.lhs:turb_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:

            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('Nmech', val=8000., units='rpm', lower=500., eq_units='hp', rhs_val=0.)
            self.connect('balance.Nmech', 'Nmech')
            self.connect('shaft.pwr_net', 'balance.lhs:Nmech')

            balance.add_balance('W', val=100.0, units='lbm/s', eq_units=None, rhs_val=2.0)
            self.connect('balance.W', 'inlet.Fl_I:stat:W')
            self.connect('comp.map.RlineMap', 'balance.lhs:W')

            self.set_order(['balance', 'fc', 'inlet', 'duct1', 'comp', 'burner', 'turb', 'ab', 'nozz', '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', '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', 'ab.Fl_I')
            connect_flow(self, 'ab.Fl_O', 'nozz.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', 'comp.Fl_I', connect_stat=False)
            connect_flow(self, 'comp.Fl_O', 'burner.Fl_I', connect_stat=False)
            connect_flow(self, 'burner.Fl_O', 'turb.Fl_I', connect_stat=False)
            connect_flow(self, 'turb.Fl_O', 'ab.Fl_I', connect_stat=False)
            connect_flow(self, 'ab.Fl_O', 'nozz.Fl_I', connect_stat=False)

        connect_flow(self, 'comp.cool1', 'turb.cool1', connect_stat=False)
        connect_flow(self, 'comp.cool2', 'turb.cool2', 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'] = 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)
Ejemplo n.º 11
0
def run_a320_analysis():
    # Set up OpenMDAO to analyze the airplane
    num_nodes = 9
    prob = Problem()
    prob.model = A320AnalysisGroup()

    prob.model.nonlinear_solver = NewtonSolver(iprint=2)
    # prob.model.nonlinear_solver = NonlinearBlockGS(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'] = 50
    prob.model.nonlinear_solver.options['atol'] = 1e-7
    prob.model.nonlinear_solver.options['rtol'] = 1e-7
    prob.model.nonlinear_solver.linesearch = ArmijoGoldsteinLS(bound_enforcement='vector', maxiter=5, print_bound_enforce=False)
    prob.setup(check=True, mode='fwd')

    # set some (required) mission parameters. Each phase needs a vertical and air-speed
    # the entire mission needs a cruise altitude and range
    # U_EAS = equivalent air speed
    # VS = vertical speed = Rate of Climb
    ones_nn = np.ones((num_nodes,))

    #"""
    # climb 1: initial climb to 5000 ft
    prob.set_val('climb1.fltcond|vs', 2500*ones_nn, units='ft/min')
    prob.set_val('climb1.fltcond|Ueas', 175*ones_nn, units='kn')
    # climb 2: 5000 to 15000 ft
    prob.set_val('climb2|h0', 5000,  units='ft')
    prob.set_val('climb2.fltcond|vs', 2000*ones_nn, units='ft/min')
    prob.set_val('climb2.fltcond|Ueas', 290*ones_nn, units='kn')
    # climb 3: 15000 to 24000 ft
    prob.set_val('climb3|h0', 15000,  units='ft')
    prob.set_val('climb3.fltcond|vs', 1400*ones_nn, units='ft/min')
    prob.set_val('climb3.fltcond|Ueas', 290*ones_nn, units='kn')
    # climb 4 (Mach climb): 24000 ft to cruise
    prob.set_val('climb4|h0', 24000,  units='ft')
    prob.set_val('climb4.fltcond|vs', 1000*ones_nn, units='ft/min')
    prob.set_val('climb4.fltcond|Ueas', 240*ones_nn, units='kn')
    # cruise. M=0.78 at 37000 ft. U_tas = 450 kn, U_eas = 240 kn
    prob.set_val('cruise|h0', 37000,  units='ft')
    prob.set_val('cruise.fltcond|vs', 0.1*ones_nn, units='ft/min')  # horizontal cruise
    prob.set_val('cruise.fltcond|Ueas', 240*ones_nn, units='kn')
    # descent 1: initial descent to 24000 ft
    prob.set_val('descent1.fltcond|vs', -500*ones_nn, units='ft/min')   # 1000
    prob.set_val('descent1.fltcond|Ueas', 240*ones_nn, units='kn')  
    # descent 2: 24000 to 10000 ft
    prob.set_val('descent2|h0', 24000,  units='ft')
    prob.set_val('descent2.fltcond|vs', -1000*ones_nn, units='ft/min')  # 3500 too steep?
    prob.set_val('descent2.fltcond|Ueas', 290*ones_nn, units='kn')
    # descent 3: approach
    prob.set_val('descent3|h0', 10000,  units='ft')
    prob.set_val('descent3.fltcond|vs', -500*ones_nn, units='ft/min')  # 1500
    prob.set_val('descent3.fltcond|Ueas', 250*ones_nn, units='kn')
    """
    prob.set_val('climb1.fltcond|vs', 1000*ones_nn, units='ft/min')
    prob.set_val('climb1.fltcond|Ueas', 70*ones_nn, units='kn')
    # cruise. M=0.78 at 37000 ft. U_tas = 450 kn, U_eas = 240 kn
    prob.set_val('cruise|h0', 20000,  units='ft')
    prob.set_val('cruise.fltcond|vs', 0.1*ones_nn, units='ft/min')  # horizontal cruise
    prob.set_val('cruise.fltcond|Ueas', 150*ones_nn, units='kn')
    # descent 1: initial descent to 24000 ft
    prob.set_val('descent1.fltcond|vs', -800*ones_nn, units='ft/min')   # 1000
    prob.set_val('descent1.fltcond|Ueas', 100*ones_nn, units='kn')  
    """

    prob.set_val('mission_range', 2200, units='NM')  # see Airbus AC-A320 pp 143 for payload-range chart

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

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

    prob.run_model()
    return prob