def test_specified_shape(self):
        shape = (3, 2, 4)

        prob = om.Problem(model=om.Group(assembled_jac_type='dense'))

        bal = om.BalanceComp()

        bal.add_balance('x', val=np.ones(shape), use_mult=True)

        tgt = om.IndepVarComp(name='y_tgt', val=4 * np.ones(shape))

        mult_ivc = om.IndepVarComp(name='mult', val=2.0 * np.ones(shape))

        exec_comp = om.ExecComp('y=x**2',
                                x={'value': np.ones(shape)},
                                y={'value': np.ones(shape)})

        prob.model.add_subsystem(name='target',
                                 subsys=tgt,
                                 promotes_outputs=['y_tgt'])
        prob.model.add_subsystem(name='mult_comp',
                                 subsys=mult_ivc,
                                 promotes_outputs=['mult'])

        prob.model.add_subsystem(name='exec', subsys=exec_comp)

        prob.model.add_subsystem(name='balance', subsys=bal)

        prob.model.connect('y_tgt', 'balance.rhs:x')
        prob.model.connect('mult', 'balance.mult:x')
        prob.model.connect('balance.x', 'exec.x')
        prob.model.connect('exec.y', 'balance.lhs:x')

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

        prob.model.nonlinear_solver = om.NewtonSolver(maxiter=100, iprint=0)

        prob.setup()

        prob['balance.x'] = np.random.random(shape)

        prob.run_model()

        assert_almost_equal(prob['balance.x'], np.sqrt(2), decimal=7)

        cpd = prob.check_partials(out_stream=None)

        for (of, wrt) in cpd['balance']:
            assert_almost_equal(cpd['balance'][of, wrt]['abs error'],
                                0.0,
                                decimal=5)
Beispiel #2
0
    def test_vectorized_with_mult(self):

        n = 100

        prob = om.Problem(model=om.Group(assembled_jac_type='dense'))

        bal = om.BalanceComp()

        bal.add_balance('x', val=np.ones(n), use_mult=True)

        tgt = om.IndepVarComp(name='y_tgt', val=4 * np.ones(n))

        mult_ivc = om.IndepVarComp(name='mult', val=2.0 * np.ones(n))

        exec_comp = om.ExecComp('y=x**2',
                                x={'val': np.ones(n)},
                                y={'val': np.ones(n)})

        prob.model.add_subsystem(name='target',
                                 subsys=tgt,
                                 promotes_outputs=['y_tgt'])
        prob.model.add_subsystem(name='mult_comp',
                                 subsys=mult_ivc,
                                 promotes_outputs=['mult'])

        prob.model.add_subsystem(name='exec', subsys=exec_comp)

        prob.model.add_subsystem(name='balance', subsys=bal)

        prob.model.connect('y_tgt', 'balance.rhs:x')
        prob.model.connect('mult', 'balance.mult:x')
        prob.model.connect('balance.x', 'exec.x')
        prob.model.connect('exec.y', 'balance.lhs:x')

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

        prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False,
                                                      maxiter=100,
                                                      iprint=0)

        prob.setup()

        prob['balance.x'] = np.random.rand(n)

        prob.run_model()

        assert_almost_equal(prob['balance.x'], np.sqrt(2), decimal=7)

        cpd = prob.check_partials(out_stream=None)

        assert_check_partials(cpd, atol=1e-5, rtol=1e-5)
Beispiel #3
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', om.Group(), promotes=['*'])
        conv.add_subsystem('fs',
                           FlowStart(thermo_data=thermo_data,
                                     elements=elements),
                           promotes=['Fl_O:*', 'MN', 'W'])
        balance = conv.add_subsystem('balance', om.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 = om.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.options['reraise_child_analysiserror'] = False
        newton.linesearch = om.BoundsEnforceLS()
        newton.linesearch.options['bound_enforcement'] = 'scalar'

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

        conv.linear_solver = om.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')
    def test_vectorized_with_default_mult(self):
        """
        solve:  2 * x**2 = 4
        expected solution:  x=sqrt(2)
        """

        n = 100

        prob = om.Problem(model=om.Group(assembled_jac_type='dense'))

        bal = om.BalanceComp('x', val=np.ones(n), use_mult=True, mult_val=2.0)

        tgt = om.IndepVarComp(name='y_tgt', val=4 * np.ones(n))

        exec_comp = om.ExecComp('y=x**2',
                                x={'value': np.ones(n)},
                                y={'value': np.ones(n)})

        prob.model.add_subsystem(name='target',
                                 subsys=tgt,
                                 promotes_outputs=['y_tgt'])

        prob.model.add_subsystem(name='exec', subsys=exec_comp)

        prob.model.add_subsystem(name='balance', subsys=bal)

        prob.model.connect('y_tgt', 'balance.rhs:x')
        prob.model.connect('balance.x', 'exec.x')
        prob.model.connect('exec.y', 'balance.lhs:x')

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

        prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False,
                                                      maxiter=100,
                                                      iprint=0)

        prob.setup()

        prob['balance.x'] = np.random.rand(n)

        prob.run_model()

        assert_almost_equal(prob['balance.x'], np.sqrt(2), decimal=7)

        cpd = prob.check_partials(out_stream=None)

        for (of, wrt) in cpd['balance']:
            assert_almost_equal(cpd['balance'][of, wrt]['abs error'],
                                0.0,
                                decimal=5)
Beispiel #5
0
    def test_multidimentional_shape_normalize(self):
        prob = om.Problem()

        bal = om.BalanceComp()
        bal.add_balance('x', use_mult=True, shape=(5, 3), normalize=True)
        bal.add_balance('z', val=4 * np.ones(5, ), shape=(5, ), normalize=True)

        exec_comp = om.ExecComp('y=x**2',
                                x={
                                    'val': np.ones((5, 3)),
                                    'shape': (5, 3)
                                },
                                y={
                                    'val': np.ones((5, 3)),
                                    'shape': (5, 3)
                                })
        exec_comp2 = om.ExecComp('y=x**2',
                                 x={
                                     'val': np.ones((5, )),
                                     'shape': (5, )
                                 },
                                 y={
                                     'val': np.ones((5, )),
                                     'shape': (5, )
                                 })

        prob.model.add_subsystem(name='exec', subsys=exec_comp)
        prob.model.add_subsystem(name='exec2', subsys=exec_comp2)
        prob.model.add_subsystem(name='balance', subsys=bal)

        prob.model.connect('balance.x', 'exec.x')
        prob.model.connect('exec.y', 'balance.lhs:x')

        prob.model.connect('balance.z', 'exec2.x')
        prob.model.connect('exec2.y', 'balance.rhs:z')

        prob.model.linear_solver = om.DirectSolver(assemble_jac=True)
        prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False,
                                                      maxiter=100,
                                                      iprint=0)

        prob.setup()

        prob.set_val('balance.rhs:x', np.ones((5, 3)))
        prob.set_val('balance.mult:x', np.ones((5, 3)))

        prob['balance.x'] = 1.0

        prob.run_model()
Beispiel #6
0
    def test_scalar_example(self):

        prob = om.Problem()

        bal = om.BalanceComp()
        bal.add_balance('x', val=1.0)

        tgt = om.IndepVarComp(name='y_tgt', val=2)

        exec_comp = om.ExecComp('y=x**2')

        prob.model.add_subsystem(name='target',
                                 subsys=tgt,
                                 promotes_outputs=['y_tgt'])
        prob.model.add_subsystem(name='exec', subsys=exec_comp)
        prob.model.add_subsystem(name='balance', subsys=bal)

        prob.model.connect('y_tgt', 'balance.rhs:x')
        prob.model.connect('balance.x', 'exec.x')
        prob.model.connect('exec.y', 'balance.lhs:x')

        # do one test in an unconverged state, to capture accuracy of partials
        prob.setup()

        prob[
            'y_tgt'] = 100000  #set rhs and lhs to very different values. Trying to capture some derivatives wrt
        prob['exec.y'] = .001

        prob.run_model()

        cpd = prob.check_partials(out_stream=None)

        assert_check_partials(cpd, atol=2e-5, rtol=2e-5)

        # set an actual solver, and re-setup. Then check derivatives at a converged point
        prob.model.linear_solver = om.DirectSolver()
        prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False)

        prob.setup()

        prob.run_model()

        assert_almost_equal(prob['balance.x'], np.sqrt(2), decimal=7)

        cpd = prob.check_partials(out_stream=None)

        assert_check_partials(cpd, atol=1e-5, rtol=1e-5)
    def test_scalar_with_guess_func(self):

        n = 1

        model = om.Group(assembled_jac_type='dense')

        def guess_function(inputs, outputs, residuals):
            outputs['x'] = np.sqrt(inputs['rhs:x'])

        bal = om.BalanceComp(
            'x', guess_func=guess_function)  # test guess_func as kwarg

        tgt = om.IndepVarComp(name='y_tgt', val=4)

        exec_comp = om.ExecComp('y=x**2', x={'value': 1}, y={'value': 1})

        model.add_subsystem(name='target',
                            subsys=tgt,
                            promotes_outputs=['y_tgt'])
        model.add_subsystem(name='exec', subsys=exec_comp)
        model.add_subsystem(name='balance', subsys=bal)

        model.connect('y_tgt', 'balance.rhs:x')
        model.connect('balance.x', 'exec.x')
        model.connect('exec.y', 'balance.lhs:x')

        model.linear_solver = om.DirectSolver(assemble_jac=True)
        model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False,
                                                 maxiter=100,
                                                 iprint=0)

        prob = om.Problem(model)
        prob.setup()

        prob['balance.x'] = np.random.rand(n)
        prob.run_model()

        assert_almost_equal(prob['balance.x'], 2.0, decimal=7)

        # should converge with no iteration due to the guess function
        self.assertEqual(model.nonlinear_solver._iter_count, 1)

        cpd = prob.check_partials(out_stream=None)
        for (of, wrt) in cpd['balance']:
            assert_almost_equal(cpd['balance'][of, wrt]['abs error'],
                                0.0,
                                decimal=5)
Beispiel #8
0
    def setup(self):
        nn = self.options['num_nodes']
        quasi_steady = self.options['quasi_steady']

        self.add_subsystem(
            'hex',
            BandolierCoolingSystem(
                num_nodes=nn,
                coolant_specific_heat=self.options['coolant_specific_heat'],
                fluid_k=self.options['fluid_k'],
                nusselt=self.options['nusselt'],
                cell_kr=self.options['cell_kr'],
                cell_diameter=self.options['cell_diameter'],
                cell_height=self.options['cell_height'],
                cell_mass=self.options['cell_mass'],
                cell_specific_heat=self.options['cell_specific_heat'],
                battery_weight_fraction=self.options['battery_weight_fraction']
            ),
            promotes_inputs=[
                'q_in', 'mdot_coolant', 'T_in', ('T_battery', 'T'),
                'battery_weight', 'n_cpb', 't_channel'
            ],
            promotes_outputs=['T_core', 'T_surface', 'T_out', 'dTdt'])

        if not quasi_steady:
            ode_integ = self.add_subsystem('ode_integ',
                                           Integrator(num_nodes=nn,
                                                      diff_units='s',
                                                      method='simpson',
                                                      time_setup='duration'),
                                           promotes_outputs=['*'],
                                           promotes_inputs=['*'])
            ode_integ.add_integrand('T',
                                    rate_name='dTdt',
                                    units='K',
                                    lower=1e-10)
        else:
            self.add_subsystem('thermal_bal',
                               om.BalanceComp('T',
                                              eq_units='K/s',
                                              lhs_name='dTdt',
                                              rhs_val=0.0,
                                              units='K',
                                              lower=1.0,
                                              val=299. * np.ones((nn, ))),
                               promotes_inputs=['dTdt'],
                               promotes_outputs=['T'])
Beispiel #9
0
    def test_raise_error_on_singular_with_densejac(self):
        prob = om.Problem()
        model = prob.model

        comp = om.IndepVarComp()
        comp.add_output('dXdt:TAS', val=1.0)
        comp.add_output('accel_target', val=2.0)
        model.add_subsystem('des_vars', comp, promotes=['*'])

        teg = model.add_subsystem('thrust_equilibrium_group',
                                  subsys=om.Group())
        teg.add_subsystem('dynamics',
                          om.ExecComp('z = 2.0*thrust'),
                          promotes=['*'])

        thrust_bal = om.BalanceComp()
        thrust_bal.add_balance(name='thrust',
                               val=1207.1,
                               lhs_name='dXdt:TAS',
                               rhs_name='accel_target',
                               eq_units='m/s**2',
                               lower=-10.0,
                               upper=10000.0)

        teg.add_subsystem(name='thrust_bal',
                          subsys=thrust_bal,
                          promotes_inputs=['dXdt:TAS', 'accel_target'],
                          promotes_outputs=['thrust'])

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

        teg.nonlinear_solver = om.NewtonSolver()
        teg.nonlinear_solver.options['solve_subsystems'] = True
        teg.nonlinear_solver.options['max_sub_solves'] = 1
        teg.nonlinear_solver.options['atol'] = 1e-4

        prob.setup()
        prob.set_solver_print(level=0)

        with self.assertRaises(RuntimeError) as cm:
            prob.run_model()

        expected_msg = "Singular entry found in 'thrust_equilibrium_group' for column associated with state/residual 'thrust'."

        self.assertEqual(expected_msg, str(cm.exception))
Beispiel #10
0
    def test_scalar(self):

        n = 1

        prob = om.Problem(model=om.Group(assembled_jac_type='dense'))

        bal = om.BalanceComp()

        bal.add_balance('x')

        tgt = om.IndepVarComp(name='y_tgt', val=4)

        exec_comp = om.ExecComp('y=x**2', x={'value': 1}, y={'value': 1})

        prob.model.add_subsystem(name='target',
                                 subsys=tgt,
                                 promotes_outputs=['y_tgt'])

        prob.model.add_subsystem(name='exec', subsys=exec_comp)

        prob.model.add_subsystem(name='balance', subsys=bal)

        prob.model.connect('y_tgt', 'balance.rhs:x')
        prob.model.connect('balance.x', 'exec.x')
        prob.model.connect('exec.y', 'balance.lhs:x')

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

        prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False,
                                                      maxiter=100,
                                                      iprint=0)

        prob.setup()

        prob['balance.x'] = np.random.rand(n)

        prob.run_model()

        assert_almost_equal(prob['balance.x'], 2.0, decimal=7)

        cpd = prob.check_partials(out_stream=None)

        for (of, wrt) in cpd['balance']:
            assert_almost_equal(cpd['balance'][of, wrt]['abs error'],
                                0.0,
                                decimal=5)
    def setup(self):
        nn = self.options['num_nodes']

        self.add_subsystem('aero',
                           subsys=AerodynamicsGroup(num_nodes=nn),
                           promotes_inputs=['alt'])

        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=om.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 = om.DirectSolver()
        self.nonlinear_solver = om.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_non_converge'] = 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 = om.BoundsEnforceLS()
        self.nonlinear_solver.linesearch.options['print_bound_enforce'] = True
Beispiel #12
0
    def set_equal(self, lhs_var, rhs_var, solvefor, solveforval=1.):
        lhname, lhseq = find_output_eq(self.eqs, lhs_var)
        rhname, rhseq = find_output_eq(self.eqs, rhs_var)
        model = self.prob.model
        #eq = EqComp(solvefor=solvefor, lhseq=lhseq, rhseq=rhseq)
        
        equality_name = 'h_{}_{}_{}'.format(solvefor, lhs_var, rhs_var)
        bal = om.BalanceComp(solvefor, val=solveforval, rhs_val=solveforval,
            lhs_name=lhs_var, rhs_name=rhs_var)
        self.eqgroup.add_subsystem(name=equality_name, subsys=bal)

        #for inp_eq_name,eq in find_input_eqs(self.eqs, solvefor):
        model.connect('{}.{}'.format(equality_name, solvefor), 
                '{}'.format(solvefor))
        model.connect('{}'.format(lhs_var), 
            '{}.{}'.format(equality_name, lhs_var))
        model.connect('{}'.format(rhs_var), 
            '{}.{}'.format(equality_name, rhs_var))
Beispiel #13
0
    def test_complex_step(self):

        n = 1

        prob = om.Problem(model=om.Group(assembled_jac_type='dense'))

        bal = om.BalanceComp()

        bal.add_balance('x')

        tgt = om.IndepVarComp(name='y_tgt', val=4)

        exec_comp = om.ExecComp('y=x**2', x={'value': 1}, y={'value': 1})

        prob.model.add_subsystem(name='target',
                                 subsys=tgt,
                                 promotes_outputs=['y_tgt'])

        prob.model.add_subsystem(name='exec', subsys=exec_comp)

        prob.model.add_subsystem(name='balance', subsys=bal)

        prob.model.connect('y_tgt', 'balance.rhs:x')
        prob.model.connect('balance.x', 'exec.x')
        prob.model.connect('exec.y', 'balance.lhs:x')

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

        prob.model.nonlinear_solver = om.NewtonSolver(maxiter=100, iprint=0)

        prob.setup(force_alloc_complex=True)

        prob['balance.x'] = np.random.rand(n)

        prob.run_model()

        with warnings.catch_warnings():
            warnings.filterwarnings(action="error", category=np.ComplexWarning)
            cpd = prob.check_partials(out_stream=None, method='cs')

        for (of, wrt) in cpd['balance']:
            assert_almost_equal(cpd['balance'][of, wrt]['abs error'],
                                0.0,
                                decimal=10)
Beispiel #14
0
    def test_feature_scalar(self):
        from numpy.testing import assert_almost_equal
        import openmdao.api as om

        prob = om.Problem()

        bal = om.BalanceComp()
        bal.add_balance('x', use_mult=True)

        tgt = om.IndepVarComp(name='y_tgt', val=4)

        mult_ivc = om.IndepVarComp(name='mult', val=2.0)

        exec_comp = om.ExecComp('y=x**2', x={'value': 1}, y={'value': 1})

        prob.model.add_subsystem(name='target',
                                 subsys=tgt,
                                 promotes_outputs=['y_tgt'])
        prob.model.add_subsystem(name='mult_comp',
                                 subsys=mult_ivc,
                                 promotes_outputs=['mult'])
        prob.model.add_subsystem(name='exec', subsys=exec_comp)
        prob.model.add_subsystem(name='balance', subsys=bal)

        prob.model.connect('y_tgt', 'balance.rhs:x')
        prob.model.connect('mult', 'balance.mult:x')
        prob.model.connect('balance.x', 'exec.x')
        prob.model.connect('exec.y', 'balance.lhs:x')

        prob.model.linear_solver = om.DirectSolver(assemble_jac=True)
        prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False,
                                                      maxiter=100,
                                                      iprint=0)

        prob.setup()

        # A reasonable initial guess to find the positive root.
        prob['balance.x'] = 1.0

        prob.run_model()

        assert_almost_equal(prob['balance.x'], np.sqrt(2), decimal=7)
Beispiel #15
0
    def test_feature_vector(self):
        import numpy as np
        from numpy.testing import assert_almost_equal

        import openmdao.api as om

        n = 100

        prob = om.Problem()

        exec_comp = om.ExecComp(
            'y=b*x+c',
            b={'value': np.random.uniform(0.01, 100, size=n)},
            c={'value': np.random.rand(n)},
            x={'value': np.zeros(n)},
            y={'value': np.ones(n)})

        prob.model.add_subsystem(name='exec', subsys=exec_comp)
        prob.model.add_subsystem(name='balance',
                                 subsys=om.BalanceComp('x', val=np.ones(n)))

        prob.model.connect('balance.x', 'exec.x')
        prob.model.connect('exec.y', 'balance.lhs:x')

        prob.model.linear_solver = om.DirectSolver(assemble_jac=True)
        prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False,
                                                      maxiter=100,
                                                      iprint=0)

        prob.setup()

        prob.set_val('balance.x', np.random.rand(n))

        prob.run_model()

        b = prob.get_val('exec.b')
        c = prob.get_val('exec.c')

        assert_almost_equal(prob.get_val('balance.x'), -c / b, decimal=6)
        assert_almost_equal(-c / b, prob.get_val('balance.x'),
                            decimal=6)  # expected
Beispiel #16
0
    def test_raise_no_error_on_singular(self):
        prob = om.Problem()
        model = prob.model

        comp = om.IndepVarComp()
        comp.add_output('dXdt:TAS', val=1.0)
        comp.add_output('accel_target', val=2.0)
        model.add_subsystem('des_vars', comp, promotes=['*'])

        teg = model.add_subsystem('thrust_equilibrium_group',
                                  subsys=om.Group())
        teg.add_subsystem('dynamics',
                          om.ExecComp('z = 2.0*thrust'),
                          promotes=['*'])

        thrust_bal = om.BalanceComp()
        thrust_bal.add_balance(name='thrust',
                               val=1207.1,
                               lhs_name='dXdt:TAS',
                               rhs_name='accel_target',
                               eq_units='m/s**2',
                               lower=-10.0,
                               upper=10000.0)

        teg.add_subsystem(name='thrust_bal',
                          subsys=thrust_bal,
                          promotes_inputs=['dXdt:TAS', 'accel_target'],
                          promotes_outputs=['thrust'])

        teg.linear_solver = om.DirectSolver(assemble_jac=False)

        teg.nonlinear_solver = om.NewtonSolver()
        teg.nonlinear_solver.options['solve_subsystems'] = True
        teg.nonlinear_solver.options['max_sub_solves'] = 1
        teg.nonlinear_solver.options['atol'] = 1e-4

        prob.setup()
        prob.set_solver_print(level=0)

        teg.linear_solver.options['err_on_singular'] = False
        prob.run_model()
    def test_feature_stall_detection_broyden(self):

        prob = om.Problem()

        prob.model.add_subsystem('comp', om.ExecComp('y=3*x+1'), promotes=['*'])

        balance = prob.model.add_subsystem('balance', om.BalanceComp(),
                                           promotes=['*'])
        balance.add_balance('x', lower=-.1, upper=10, rhs_val=0, lhs_name='y')

        nl_solver = prob.model.nonlinear_solver = om.BroydenSolver()
        nl_solver.options['stall_limit'] = 3
        nl_solver.options['stall_tol'] = 1e-8
        nl_solver.options['maxiter'] = 100

        prob.model.linear_solver = om.DirectSolver()

        prob.setup()
        prob.set_solver_print()

        prob.run_model()
Beispiel #18
0
    def test_create_on_init_no_normalization(self):

        prob = om.Problem()

        bal = om.BalanceComp('x', val=1.0, normalize=False)

        tgt = om.IndepVarComp(name='y_tgt', val=1.5)

        exec_comp = om.ExecComp('y=x**2')

        prob.model.add_subsystem(name='target',
                                 subsys=tgt,
                                 promotes_outputs=['y_tgt'])

        prob.model.add_subsystem(name='exec', subsys=exec_comp)

        prob.model.add_subsystem(name='balance', subsys=bal)

        prob.model.connect('y_tgt', 'balance.rhs:x')
        prob.model.connect('balance.x', 'exec.x')
        prob.model.connect('exec.y', 'balance.lhs:x')

        prob.model.linear_solver = om.DirectSolver()
        prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False,
                                                      iprint=0)

        prob.setup()

        prob.run_model()

        assert_almost_equal(prob['balance.x'], np.sqrt(1.5), decimal=7)

        assert_almost_equal(prob.model.balance._scale_factor, 1.0)

        cpd = prob.check_partials(out_stream=None)

        for (of, wrt) in cpd['balance']:
            assert_almost_equal(cpd['balance'][of, wrt]['abs error'],
                                0.0,
                                decimal=5)
Beispiel #19
0
 def setup(self):
     nn = self.options['num_nodes']
     quasi_steady = self.options['quasi_steady']
     self.add_subsystem(
         'hex',
         MotorCoolingJacket(
             num_nodes=nn,
             coolant_specific_heat=self.options['coolant_specific_heat'],
             motor_specific_heat=self.options['motor_specific_heat'],
             case_cooling_coefficient=self.
             options['case_cooling_coefficient']),
         promotes_inputs=[
             'q_in', 'T_in', 'T', 'power_rating', 'mdot_coolant',
             'motor_weight'
         ],
         promotes_outputs=['T_out', 'dTdt'])
     if not quasi_steady:
         ode_integ = self.add_subsystem('ode_integ',
                                        Integrator(num_nodes=nn,
                                                   diff_units='s',
                                                   method='simpson',
                                                   time_setup='duration'),
                                        promotes_outputs=['*'],
                                        promotes_inputs=['*'])
         ode_integ.add_integrand('T',
                                 rate_name='dTdt',
                                 units='K',
                                 lower=1e-10)
     else:
         self.add_subsystem('thermal_bal',
                            om.BalanceComp('T',
                                           eq_units='K/s',
                                           lhs_name='dTdt',
                                           rhs_val=0.0,
                                           units='K',
                                           lower=1.0,
                                           val=299. * np.ones((nn, ))),
                            promotes_inputs=['dTdt'],
                            promotes_outputs=['T'])
Beispiel #20
0
    def test_rhs_val(self):
        """ Test solution with a default RHS value and no connected RHS variable. """

        n = 1

        prob = om.Problem(model=om.Group(assembled_jac_type='dense'))

        bal = om.BalanceComp('x', rhs_val=4.0)

        exec_comp = om.ExecComp('y=x**2', x={'value': 1}, y={'value': 1})

        prob.model.add_subsystem(name='exec', subsys=exec_comp)

        prob.model.add_subsystem(name='balance', subsys=bal)

        prob.model.connect('balance.x', 'exec.x')
        prob.model.connect('exec.y', 'balance.lhs:x')

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

        prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False,
                                                      maxiter=100,
                                                      iprint=0)

        prob.setup()

        prob['balance.x'] = np.random.rand(n)

        prob.run_model()

        assert_almost_equal(prob['balance.x'], 2.0, decimal=7)

        cpd = prob.check_partials(out_stream=None)

        for (of, wrt) in cpd['balance']:
            assert_almost_equal(cpd['balance'][of, wrt]['abs error'],
                                0.0,
                                decimal=5)
    def test_nonlinear_solver_bounds_stall_warning(self):
        prob = om.Problem()

        prob.model.add_subsystem('comp',
                                 om.ExecComp('y=3*x+1'),
                                 promotes=['*'])

        balance = prob.model.add_subsystem('balance',
                                           om.BalanceComp(),
                                           promotes=['*'])
        balance.add_balance('x', lower=-.1, upper=10, rhs_val=0, lhs_name='y')

        newton = prob.model.nonlinear_solver = om.NewtonSolver()
        newton.options['solve_subsystems'] = True
        newton.options['stall_limit'] = 5
        newton.options['stall_tol'] = 1e-8
        newton.options['maxiter'] = 100
        newton.options['err_on_non_converge'] = False

        prob.model.linear_solver = om.DirectSolver()

        prob.setup()

        msg = (
            f"Your model has stalled three times and may be violating the bounds. "
            f"In the future, turn on print_bound_enforce in your solver options "
            f"here: \nnonlinear_solver.linesearch.options"
            f"['print_bound_enforce']=True. "
            f"\nThe bound(s) being violated now are:\n")
        with assert_warning(UserWarning, msg):
            prob.run_model()

        newton.linesearch.options['print_bound_enforce'] = True

        prob.setup()

        with assert_no_warning(UserWarning, msg):
            prob.run_model()
Beispiel #22
0
    def test_feature_stall_detection_newton(self):
        import openmdao.api as om

        prob = om.Problem()

        prob.model.add_subsystem('comp', om.ExecComp('y=3*x+1'), promotes=['*'])

        balance = prob.model.add_subsystem('balance', om.BalanceComp(),
                                           promotes=['*'])
        balance.add_balance('x', lower=-.1, upper=10, rhs_val=0, lhs_name='y')

        newton = prob.model.nonlinear_solver = om.NewtonSolver()
        newton.options['solve_subsystems'] = True
        newton.options['stall_limit'] = 3
        newton.options['stall_tol'] = 1e-8
        newton.options['maxiter'] = 100

        prob.model.linear_solver = om.DirectSolver()

        prob.setup()
        prob.set_solver_print()

        prob.run_model()
Beispiel #23
0
    def test_balance_comp_record_options(self):

        prob = om.Problem()

        bal = om.BalanceComp()
        bal.add_balance('x', val=1.0)

        prob.model.add_subsystem(name='balance', subsys=bal)

        recorder = om.SqliteRecorder('cases.sql')

        prob.model.add_recorder(recorder)

        prob.model.recording_options['record_inputs'] = True
        prob.model.recording_options['record_outputs'] = True
        prob.model.recording_options['record_residuals'] = True

        prob.setup()

        # there should be no warnings wrt unpicklable 'guess_func' option,
        # since 'recordable' has been set to False
        with assert_no_warning(UserWarning):
            prob.run_model()
Beispiel #24
0
    def test_nonlinear_solver_stall_detection(self):
        prob = om.Problem()

        prob.model.add_subsystem('comp', om.ExecComp('y=3*x+1'), promotes=['*'])

        balance = prob.model.add_subsystem('balance', om.BalanceComp(), promotes=['*'])
        balance.add_balance('x', lower=-.1, upper=10, rhs_val=0, lhs_name='y')

        newton = prob.model.nonlinear_solver = om.NewtonSolver()
        newton.options['solve_subsystems'] = True
        newton.options['stall_limit'] = 3
        newton.options['stall_tol'] = 1e-8
        newton.options['maxiter'] = 100
        newton.options['err_on_non_converge'] = True

        prob.model.linear_solver = om.DirectSolver()

        prob.setup()

        with self.assertRaises(om.AnalysisError) as context:
            prob.run_model()

        msg = "Solver 'NL: Newton' on system '' stalled after 4 iterations."
        self.assertEqual(str(context.exception), msg)
Beispiel #25
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', om.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', om.Group(), promotes=['*'])

        if self.options['internal_solver']:
            newton = conv.nonlinear_solver = om.NewtonSolver()
            newton.options['maxiter'] = 30
            newton.options['atol'] = 1e-2
            newton.options['solve_subsystems'] = True
            newton.options['max_sub_solves'] = 20
            newton.options['reraise_child_analysiserror'] = False
            newton.linesearch = om.BoundsEnforceLS()
            newton.linesearch.options['bound_enforcement'] = 'scalar'
            newton.linesearch.options['iprint'] = -1
            conv.linear_solver = om.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', om.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
Beispiel #26
0
    def setup(self):

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

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

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

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

        # 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')

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

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

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

            balance.add_balance('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')

        else:

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

            balance.add_balance('Nmech',
                                val=1.5,
                                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=168.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', 'nozz',
            'shaft', 'perf'
        ])

        newton = self.nonlinear_solver = om.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 = om.BoundsEnforceLS()
        # newton.linesearch = ArmijoGoldsteinLS()
        # newton.linesearch.options['c'] = .0001
        newton.linesearch.options['bound_enforcement'] = 'scalar'
        newton.linesearch.options['iprint'] = -1

        self.linear_solver = om.DirectSolver(assemble_jac=True)
Beispiel #27
0
        self.nonlinear_solver.options['maxiter'] = 20
        self.linear_solver = om.DirectSolver()


if __name__ == "__main__":
    import openmdao.api as om

    p = om.Problem()
    model = p.model

    model.add_subsystem('ground', om.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', om.IndepVarComp('V', 1.5, units='V'))
    bal = model.add_subsystem('batt_balance', om.BalanceComp())
    bal.add_balance('I', units='A', eq_units='V')

    model.add_subsystem('circuit', Circuit())
    model.add_subsystem(
        'batt_deltaV',
        om.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')
Beispiel #28
0
    def setup(self):

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        else:

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

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

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

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

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

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

            order_add = []

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

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

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

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

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

            order_add = ['hpt_cooling', 'hpt_chargable']

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

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

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

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

        # newton.options['debug_print'] = True

        self.linear_solver = om.DirectSolver(assemble_jac=True)
Beispiel #29
0
    def test_result(self):
        import numpy as np
        from numpy.testing import assert_almost_equal

        import openmdao.api as om

        prob = om.Problem()

        bal = om.BalanceComp()

        bal.add_balance(name='E',
                        val=0.0,
                        units='rad',
                        eq_units='rad',
                        rhs_name='M')

        # Use M (mean anomaly) as the initial guess for E (eccentric anomaly)
        def guess_function(inputs, outputs, residuals):
            if np.abs(residuals['E']) > 1.0E-2:
                outputs['E'] = inputs['M']

        bal.options['guess_func'] = guess_function

        # ExecComp used to compute the LHS of Kepler's equation.
        lhs_comp = om.ExecComp('lhs=E - ecc * sin(E)',
                               lhs={
                                   'value': 0.0,
                                   'units': 'rad'
                               },
                               E={
                                   'value': 0.0,
                                   'units': 'rad'
                               },
                               ecc={'value': 0.0})

        prob.model.add_subsystem(name='balance',
                                 subsys=bal,
                                 promotes_inputs=['M'],
                                 promotes_outputs=['E'])

        prob.model.set_input_defaults('M', 85.0, units='deg')

        prob.model.add_subsystem(name='lhs_comp',
                                 subsys=lhs_comp,
                                 promotes_inputs=['E', 'ecc'])

        # Explicit connections
        prob.model.connect('lhs_comp.lhs', 'balance.lhs:E')

        # Set up solvers
        prob.model.linear_solver = om.DirectSolver()
        prob.model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False,
                                                      maxiter=100,
                                                      iprint=2)

        prob.setup()

        prob.set_val('ecc', 0.6)

        prob.run_model()

        assert_almost_equal(np.degrees(prob.get_val('E')), 115.9, decimal=1)
Beispiel #30
0
    def test_scalar_guess_func_using_outputs(self):

        model = om.Group()

        ind = om.IndepVarComp()
        ind.add_output('a', 1)
        ind.add_output('b', -4)
        ind.add_output('c', 3)

        lhs = om.ExecComp('lhs=-(a*x**2+b*x)')
        bal = om.BalanceComp(name='x', rhs_name='c')

        model.add_subsystem('ind_comp', ind, promotes_outputs=['a', 'b', 'c'])
        model.add_subsystem('lhs_comp', lhs, promotes_inputs=['a', 'b', 'x'])
        model.add_subsystem('bal_comp',
                            bal,
                            promotes_inputs=['c'],
                            promotes_outputs=['x'])

        model.connect('lhs_comp.lhs', 'bal_comp.lhs:x')

        model.linear_solver = om.DirectSolver()
        model.nonlinear_solver = om.NewtonSolver(solve_subsystems=False,
                                                 maxiter=100,
                                                 iprint=0)

        # first verify behavior of the balance comp without the guess function
        # at initial conditions x=5, x=0 and x=-1
        prob = om.Problem(model)
        prob.setup()

        # default solution with initial value of 5 is x=3.
        prob['x'] = 5
        prob.run_model()
        assert_almost_equal(prob['x'], 3.0, decimal=7)

        # default solution with initial value of 0 is x=1.
        prob['x'] = 0
        prob.run_model()
        assert_almost_equal(prob['x'], 1.0, decimal=7)

        # default solution with initial value of -1 is x=1.
        prob['x'] = -1
        prob.run_model()
        assert_almost_equal(prob['x'], 1.0, decimal=7)

        # now use a guess function that steers us to the x=3 solution only
        # if the initial value of x is less than zero
        def guess_function(inputs, outputs, residuals):
            if outputs['x'] < 0:
                outputs['x'] = 3.

        bal.options['guess_func'] = guess_function

        # solution with initial value of 5 is still x=3.
        prob['x'] = 5
        prob.run_model()
        assert_almost_equal(prob['x'], 3.0, decimal=7)

        # solution with initial value of 0 is still x=1.
        prob['x'] = 0
        prob.run_model()
        assert_almost_equal(prob['x'], 1.0, decimal=7)

        # solution with initial value of -1 is now x=3.
        prob['x'] = -1
        prob.run_model()
        assert_almost_equal(prob['x'], 3.0, decimal=7)