예제 #1
0
 def setup(self):
     super(IntegratorTestValLimits, self).setup()
     nn = self.options['num_nodes']
     ec2 = self.add_subsystem(
         'ec2',
         om.ExecComp(
             ['df2 = 5.1*x**2 +0.5*x-7.2'],
             df2={
                 'val':
                 1.0 * np.ones((nn, )),
                 'units':
                 'W',
                 'tags': [
                     'integrate', 'state_name:f2', 'state_units:J',
                     'state_upper:1e20', 'state_lower:-1e20',
                     'state_val:np.linspace(0,5,' + str(nn) + ')'
                 ]
             },
             x={
                 'val': 1.0 * np.ones((nn, )),
                 'units': 's'
             }))
     self.connect('iv.x', 'ec2.x')
     self.set_order(['iv', 'ec', 'ec2', 'ode_integ'])
    def test_driver_options(self):
        """Tests if F and Pc options can be set."""
        prob = om.Problem()

        indeps = prob.model.add_subsystem('indeps',
                                          om.IndepVarComp(),
                                          promotes=['*'])
        indeps.add_output('x', 1.)

        prob.model.add_subsystem('model',
                                 om.ExecComp('y=x**2'),
                                 promotes=['*'])

        prob.driver = GenericDriver(
            algorithm=DifferentialEvolution(F=.123, Pc=.0123, max_gen=5))
        # prob.driver.options['F'] = 0.123
        # prob.driver.options['Pc'] = 0.0123
        # prob.driver.options['max_gen'] = 5

        prob.model.add_design_var('x', lower=-10., upper=10.)
        prob.model.add_objective('y')

        prob.setup()
        prob.run_driver()
예제 #3
0
    def test_feature_scalar_with_default_mult(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, mult_val=2.0)

        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()

        # 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)
예제 #4
0
    def test_lower_flag(self):
        import numpy as np

        import openmdao.api as om

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

        model.add_subsystem('comp',
                            om.ExecComp('y = 3.0*x',
                                        x=np.zeros((2, )),
                                        y=np.zeros((2, ))),
                            promotes_inputs=['x'])

        model.add_subsystem('ks', om.KSComp(width=2))

        model.connect('comp.y', 'ks.g')

        model.ks.options['lower_flag'] = True
        prob.setup()
        prob.set_val('x', np.array([5.0, 4.0]))
        prob.run_model()

        assert_near_equal(prob.get_val('ks.KS'), [[-12.0]])
예제 #5
0
    def test_remote_distrib(self):
        # this test has remote distributed components (distributed comps under parallel groups)
        p = om.Problem()
        indep = p.model.add_subsystem('indep', om.IndepVarComp())
        indep.add_output('x1', shape_by_conn=True)

        par = p.model.add_subsystem('par', om.ParallelGroup())
        G1 = par.add_subsystem('G1',
                               DynShapeGroupSeries(2, 1, DistribDynShapeComp))
        G2 = par.add_subsystem('G2',
                               DynShapeGroupSeries(2, 1, DistribDynShapeComp))

        # 'sink' has a defined shape and dyn shapes propagate in reverse from there.
        p.model.add_subsystem('sink', om.ExecComp(['y1=x1+x2'], shape=(8, )))
        p.model.connect('indep.x1', ['par.G1.C1.x1', 'par.G2.C1.x1'])
        p.model.connect('par.G1.C2.y1', 'sink.x1', src_indices=om.slicer[:])
        p.model.connect('par.G2.C2.y1', 'sink.x2', src_indices=om.slicer[:])

        with self.assertRaises(RuntimeError) as cm:
            p.setup()

        cname = 'G1' if p.model.comm.rank <= 1 else 'G2'
        msg = f"'par.{cname}.C1' <class DistribDynShapeComp>: Can't determine src_indices automatically for input 'par.{cname}.C1.x1'. They must be supplied manually."
        self.assertEqual(str(cm.exception), msg)
예제 #6
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
예제 #7
0
    def test_units_compute_totals(self):
        p = om.Problem()

        p.model.add_subsystem('stuff',
                              om.ExecComp(['y = x', 'cy = x'],
                                          x={'units': 'inch'},
                                          y={'units': 'kg'},
                                          cy={'units': 'kg'}),
                              promotes=['*'])

        p.model.add_design_var('x', units='ft')
        p.model.add_objective('y', units='lbm')
        p.model.add_constraint('cy', units='lbm', lower=0)

        p.setup()

        p['x'] = 1.0
        p.run_model()

        J_driver = p.driver._compute_totals()

        fact = convert_units(1.0, 'kg/inch', 'lbm/ft')
        assert_near_equal(J_driver['stuff.y', 'x'][0, 0], fact, 1e-5)
        assert_near_equal(J_driver['stuff.cy', 'x'][0, 0], fact, 1e-5)
예제 #8
0
    def test_auto_ivc(self):
        """
        Tests a model with automatically added IndepVarComp.
        """

        filename = 'xdsm_auto_ivc'

        p = om.Problem()

        p.model.add_subsystem('paraboloid',
                              om.ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'),
                              promotes_inputs=['x', 'y'])

        # setup the optimization
        p.driver = om.ScipyOptimizeDriver()
        p.driver.options['optimizer'] = 'SLSQP'

        p.model.add_design_var('x', lower=-50, upper=50)
        p.model.add_design_var('y', lower=-50, upper=50)
        p.model.add_objective('paraboloid.f')

        p.setup()
        p.final_setup()

        # Write output
        write_xdsm(p, filename=filename, out_format=PYXDSM_OUT, show_browser=SHOW, quiet=QUIET,
                   include_indepvarcomps=False)  # Not showing the Auto IVC

        # Check if file was created
        self.assertTrue(os.path.isfile(filename + '.tex'))

        write_xdsm(p, filename=filename + '2', out_format=PYXDSM_OUT, show_browser=SHOW, quiet=QUIET,
                   include_indepvarcomps=True)  # Showing the Auto IVC

        # Check if file was created
        self.assertTrue(os.path.isfile(filename + '2.tex'))
예제 #9
0
    def test_execcomp(self):
        filename = 'pyxdsm_execcomp'
        out_format = PYXDSM_OUT
        p = om.Problem()
        indeps = p.model.add_subsystem('indeps', om.IndepVarComp(), promotes=['*'])
        indeps.add_output('x')
        p.model.add_subsystem('C1', om.ExecComp(['y=2.0*x+1.'], x=2.0), promotes=['*'])
        p.driver = om.ScipyOptimizeDriver()
        p.model.add_design_var('x', lower=0.0, upper=10.0)
        p.model.add_objective('y')
        p.setup()

        # Conclude setup but don't run model.
        p.final_setup()

        write_xdsm(p, filename=filename, out_format=out_format, quiet=QUIET, show_browser=SHOW, show_parallel=True)
        # Check if file was created
        self.assertTrue(os.path.isfile(filename + '.' + out_format))

        # Including the expression from the ExecComp formatted in LaTeX
        write_xdsm(p, filename=filename + "2", out_format=out_format, quiet=QUIET, show_browser=SHOW,
                   show_parallel=True, equations=True)
        # Check if file was created
        self.assertTrue(os.path.isfile(filename + '.' + out_format))
예제 #10
0
    def test_vectorized(self):
        import numpy as np

        import openmdao.api as om

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

        model.add_subsystem(
            'px', om.IndepVarComp('x', val=np.array([[5.0, 4.0], [10.0,
                                                                  8.0]])))
        model.add_subsystem(
            'comp',
            om.ExecComp('y = 3.0*x', x=np.zeros((2, 2)), y=np.zeros((2, 2))))
        model.add_subsystem('ks', om.KSComp(width=2, vec_size=2))

        model.connect('px.x', 'comp.x')
        model.connect('comp.y', 'ks.g')

        prob.setup()
        prob.run_model()

        assert_rel_error(self, prob['ks.KS'][0], 15.0)
        assert_rel_error(self, prob['ks.KS'][1], 30.0)
예제 #11
0
    def test_reraise_analylsis_error(self):
        prob = om.Problem()
        model = prob.model

        model.add_subsystem('p1', om.IndepVarComp('x', 0.5))
        model.add_subsystem('p2', om.IndepVarComp('x', 3.0))
        sub = model.add_subsystem('sub', om.ParallelGroup())

        sub.add_subsystem('c1', AEComp())
        sub.add_subsystem('c2', AEComp())

        model.add_subsystem('obj', om.ExecComp(['val = x1 + x2']))

        model.connect('p1.x', 'sub.c1.x')
        model.connect('p2.x', 'sub.c2.x')
        model.connect('sub.c1.y', 'obj.x1')
        model.connect('sub.c2.y', 'obj.x2')

        prob.driver = AEDriver()

        prob.setup()

        handled = prob.run_driver()
        self.assertTrue(handled)
예제 #12
0
    def test_broadcast_scalar_connection(self):
        """
        OpenMDAO should allow promotion to an input that appears to have a certain shape.
        Users should be allowed to connect an arbitrary variable with compatible src_indices to that input.
        """
        p = om.Problem()

        # c1 contains scalar calculations
        ivc = p.model.add_subsystem('ivc', om.IndepVarComp())
        ivc.add_output('y', val=5.0*np.ones(4,))
        ivc.add_output('x', val=np.arange(4, dtype=float) + 1)

        g1 = p.model.add_subsystem('g1', om.Group())
        # c2 is vectorized calculations
        c2 = g1.add_subsystem('c2', om.ExecComp('z = a * y', shape=(4,)))

        # The ultimate source of a and y may be scalar, or have some other arbitrary shape
        g1.promotes('c2', inputs=['a'], src_indices=[0, 0, 0, 0], src_shape=(1,))
        g1.promotes('c2', inputs=['y'], src_indices=[0, 0, 0, 0], src_shape=(4,))

        p.model.connect('ivc.y', 'g1.y')

        # Now connect only a portion of some other output to a, which appears as a scalar input
        p.model.connect('ivc.x', 'g1.a', src_indices=[-1])

        p.setup()

        p.run_model()

        assert_near_equal(p['g1.a'], 4.)
        assert_near_equal(p.model.g1.get_val('a'), 4.)
        assert_near_equal(p['g1.y'], [5., 5., 5., 5.])
        assert_near_equal(p.model.g1.get_val('y'), [5., 5., 5., 5.])
        assert_near_equal(p['g1.c2.y'], [5., 5., 5., 5.])
        assert_near_equal(p['g1.c2.a'], [4., 4., 4., 4.])
        assert_near_equal(p['g1.c2.z'], [20., 20., 20., 20.])
예제 #13
0
 def test_cycle_rev(self):
     # now put the DynShapeGroupSeries in a cycle (sink.y2 feeds back into Gdyn.C1.x2), but here,
     # only the sink outputs are known and inputs are coming from auto_ivcs.
     p = om.Problem()
     p.model.add_subsystem('Gdyn', DynShapeGroupSeries(3, 2, DynShapeComp))
     p.model.add_subsystem(
         'sink',
         om.ExecComp('y1, y2 = x1*2, x2*2',
                     x1=np.ones((2, 3)),
                     x2=np.ones((4, 2)),
                     y1=np.ones((2, 3)),
                     y2=np.ones((4, 2))))
     p.model.connect('Gdyn.C3.y1', 'sink.x1')
     p.model.connect('Gdyn.C3.y2', 'sink.x2')
     p.model.connect('sink.y2', 'Gdyn.C1.x2')
     p.setup()
     p.run_model()
     np.testing.assert_allclose(p['sink.y1'], np.ones((2, 3)) * 16)
     np.testing.assert_allclose(p['sink.y2'], np.ones((4, 2)) * 16)
     p.run_model()
     np.testing.assert_allclose(p['sink.y1'], np.ones((2, 3)) * 16)
     # each time we run_model, the value of sink.y2 will be multiplied by 16
     # because of the feedback
     np.testing.assert_allclose(p['sink.y2'], np.ones((4, 2)) * 256)
예제 #14
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(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)
예제 #15
0
    def test_feature_has_diag_partials(self):
        import numpy as np
        import openmdao.api as om

        p = om.Problem()
        model = p.model
        model.add_subsystem('indep', om.IndepVarComp('x', val=np.ones(5)))

        model.add_subsystem(
            'comp',
            om.ExecComp('y=3.0*x + 2.5',
                        has_diag_partials=True,
                        x=np.ones(5),
                        y=np.ones(5)))
        model.connect('indep.x', 'comp.x')

        p.setup()
        p.run_model()

        J = p.compute_totals(of=['comp.y'],
                             wrt=['indep.x'],
                             return_format='array')

        assert_almost_equal(J, np.eye(5) * 3., decimal=6)
예제 #16
0
    def test_multi_dim_src_indices(self):
        prob = om.Problem()
        model = prob.model
        size = 5

        model.add_subsystem(
            'indeps', om.IndepVarComp('x',
                                      np.arange(5).reshape((1, size, 1))))
        model.add_subsystem(
            'comp',
            om.ExecComp('y = x * 2.',
                        x=np.zeros((size, )),
                        y=np.zeros((size, ))))
        src_indices = [[0, i, 0] for i in range(size)]
        model.connect('indeps.x', 'comp.x', src_indices=src_indices)

        model.linear_solver = om.DirectSolver()
        prob.setup()
        prob.run_model()

        J = prob.compute_totals(wrt=['indeps.x'],
                                of=['comp.y'],
                                return_format='array')
        np.testing.assert_almost_equal(J, np.eye(size) * 2.)
예제 #17
0
    def test_abs_array_complex_step(self):
        prob = om.Problem()
        C1 = prob.model.add_subsystem(
            'C1',
            om.ExecComp('y=2.0*abs(x)', x=np.ones(3) * -2.0, y=np.zeros(3)))

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

        assert_rel_error(self, C1._outputs['y'], np.ones(3) * 4.0, 0.00001)

        # any positive C1.x should give a 2.0 derivative for dy/dx
        C1._inputs['x'] = np.ones(3) * 1.0e-10
        C1._linearize()
        assert_rel_error(self, C1._jacobian['y', 'x'],
                         np.eye(3) * 2.0, 0.00001)

        C1._inputs['x'] = np.ones(3) * -3.0
        C1._linearize()
        assert_rel_error(self, C1._jacobian['y', 'x'],
                         np.eye(3) * -2.0, 0.00001)

        C1._inputs['x'] = np.zeros(3)
        C1._linearize()
        assert_rel_error(self, C1._jacobian['y', 'x'],
                         np.eye(3) * 2.0, 0.00001)

        C1._inputs['x'] = np.array([1.5, -0.6, 2.4])
        C1._linearize()
        expect = np.zeros((3, 3))
        expect[0, 0] = 2.0
        expect[1, 1] = -2.0
        expect[2, 2] = 2.0

        assert_rel_error(self, C1._jacobian['y', 'x'], expect, 0.00001)
예제 #18
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)
예제 #19
0
 def test_cycle_fwd_rev(self):
     # now put the DynShapeGroupSeries in a cycle (sink.y2 feeds back into Gdyn.C1.x2). Sizes are known
     # at both ends of the model (the IVC and at the sink)
     p = om.Problem()
     indep = p.model.add_subsystem('indep', om.IndepVarComp('x1', val=np.ones((2,3))))
     p.model.add_subsystem('Gdyn', DynShapeGroupSeries(3,2, DynShapeComp))
     p.model.add_subsystem('sink', om.ExecComp('y1, y2 = x1*2, x2*2',
                                               x1=np.ones((2,3)),
                                               x2=np.ones((4,2)),
                                               y1=np.ones((2,3)),
                                               y2=np.ones((4,2))))
     p.model.connect('Gdyn.C3.y1', 'sink.x1')
     p.model.connect('Gdyn.C3.y2', 'sink.x2')
     p.model.connect('sink.y2', 'Gdyn.C1.x2')
     p.model.connect('indep.x1', 'Gdyn.C1.x1')
     p.setup()
     p.run_model()
     np.testing.assert_allclose(p['sink.y1'], np.ones((2,3))*16)
     np.testing.assert_allclose(p['sink.y2'], np.ones((4,2))*16)
     p.run_model()
     np.testing.assert_allclose(p['sink.y1'], np.ones((2,3))*16)
     # each time we run_model, the value of sink.y2 will be multiplied by 16
     # because of the feedback
     np.testing.assert_allclose(p['sink.y2'], np.ones((4,2))*256)
예제 #20
0
    def test_raise_error_on_singular_with_sparsejac(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.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' <class Group> for row associated with state/residual 'thrust' ('thrust_equilibrium_group.thrust_bal.thrust') index 0."

        self.assertEqual(expected_msg, str(cm.exception))
예제 #21
0
    def __init__(self):
        super(ConvergeDivergeGroups, self).__init__()

        self.add_subsystem('iv', om.IndepVarComp('x', 2.0))

        g1 = self.add_subsystem('g1', om.ParallelGroup())
        g1.add_subsystem('c1', om.ExecComp(['y1 = 2.0*x1**2',
                                            'y2 = 3.0*x1'
                                            ]))

        g2 = g1.add_subsystem('g2', om.ParallelGroup())
        g2.add_subsystem('c2', om.ExecComp('y1 = 0.5*x1'))
        g2.add_subsystem('c3', om.ExecComp('y1 = 3.5*x1'))

        g1.add_subsystem('c4', om.ExecComp(['y1 = x1 + 2.0*x2',
                                            'y2 = 3.0*x1 - 5.0*x2'
                                            ]))

        g3 = self.add_subsystem('g3', om.ParallelGroup())
        g3.add_subsystem('c5', om.ExecComp('y1 = 0.8*x1'))
        g3.add_subsystem('c6', om.ExecComp('y1 = 0.5*x1'))

        self.add_subsystem('c7', om.ExecComp('y1 = x1 + 3.0*x2'))

        # make connections
        self.connect('iv.x', 'g1.c1.x1')

        g1.connect('c1.y1', 'g2.c2.x1')
        g1.connect('c1.y2', 'g2.c3.x1')

        self.connect('g1.g2.c2.y1', 'g1.c4.x1')
        self.connect('g1.g2.c3.y1', 'g1.c4.x2')

        self.connect('g1.c4.y1', 'g3.c5.x1')
        self.connect('g1.c4.y2', 'g3.c6.x1')

        self.connect('g3.c5.y1', 'c7.x1')
        self.connect('g3.c6.y1', 'c7.x2')
예제 #22
0
    def test_parallel_group_order(self):
        prob = om.Problem()
        model = prob.model

        model.add_subsystem('p1', om.IndepVarComp('x', 1.0))
        model.add_subsystem('p2', om.IndepVarComp('x', 1.0))

        parallel = model.add_subsystem('parallel', om.ParallelGroup())
        parallel.add_subsystem('c1', om.ExecComp(['y=-2.0*x']))
        parallel.add_subsystem('c2', om.ExecComp(['y=5.0*x']))
        parallel.connect('c1.y', 'c2.x')

        parallel = model.add_subsystem('parallel_copy', om.ParallelGroup())
        parallel.add_subsystem('comp1', om.ExecComp(['y=-2.0*x']))
        parallel.add_subsystem('comp2', om.ExecComp(['y=5.0*x']))
        parallel.connect('comp1.y', 'comp2.x')

        model.add_subsystem('c3', om.ExecComp(['y=3.0*x1+7.0*x2']))
        model.add_subsystem('c4', om.ExecComp(['y=3.0*x_copy_1+7.0*x_copy_2']))

        model.connect("parallel.c1.y", "c3.x1")
        model.connect("parallel.c2.y", "c3.x2")
        model.connect("parallel_copy.comp1.y", "c4.x_copy_1")
        model.connect("parallel_copy.comp2.y", "c4.x_copy_2")

        model.connect("p1.x", "parallel.c1.x")
        model.connect("p1.x", "parallel_copy.comp1.x")

        testlogger = TestLogger()
        prob.setup(check=True, mode='fwd', logger=testlogger)

        msg = "Need to attach NonlinearBlockJac, NewtonSolver, or BroydenSolver to 'parallel' when " \
              "connecting components inside parallel groups"

        with assert_warning(UserWarning, msg):
            prob.run_model()

        expected_warning = ("The following systems are executed out-of-order:\n"
                            "   System 'parallel.c2' executes out-of-order with respect to its source systems ['parallel.c1']\n"
                            "   System 'parallel_copy.comp2' executes out-of-order with respect to its source systems ['parallel_copy.comp1']\n")

        testlogger.find_in('warning', expected_warning)
예제 #23
0
    def setup(self):
        E = self.options['E']
        L = self.options['L']
        b = self.options['b']
        volume = self.options['volume']
        num_elements = self.options['num_elements']
        num_nodes = num_elements + 1
        num_cp = self.options['num_cp']
        num_load_cases = self.options['num_load_cases']

        inputs_comp = om.IndepVarComp()
        inputs_comp.add_output('h_cp', shape=num_cp)
        self.add_subsystem('inputs_comp', inputs_comp)

        comp = om.BsplinesComp(num_control_points=num_cp,
                               num_points=num_elements,
                               in_name='h_cp',
                               out_name='h')
        self.add_subsystem('interp', comp)

        I_comp = MomentOfInertiaComp(num_elements=num_elements, b=b)
        self.add_subsystem('I_comp', I_comp)

        comp = LocalStiffnessMatrixComp(num_elements=num_elements, E=E, L=L)
        self.add_subsystem('local_stiffness_matrix_comp', comp)

        # Parallel Subsystem for load cases.
        par = self.add_subsystem('parallel', om.ParallelGroup())

        # Determine how to split cases up over the available procs.
        nprocs = self.comm.size
        divide = divide_cases(num_load_cases, nprocs)

        obj_srcs = []
        for j, this_proc in enumerate(divide):
            num_rhs = len(this_proc)

            name = 'sub_%d' % j
            sub = par.add_subsystem(name, om.Group())

            # Load is a sinusoidal distributed force of varying spatial frequency.
            force_vector = np.zeros((2 * num_nodes, num_rhs))
            for i, k in enumerate(this_proc):

                end = 1.5 * np.pi
                if num_load_cases > 1:
                    end += k * 0.5 * np.pi / (num_load_cases - 1)

                x = np.linspace(0, end, num_nodes)
                f = -np.sin(x)
                force_vector[0:-1:2, i] = f

            comp = MultiStatesComp(num_elements=num_elements,
                                   force_vector=force_vector,
                                   num_rhs=num_rhs)
            sub.add_subsystem('states_comp', comp)

            comp = MultiDisplacementsComp(num_elements=num_elements,
                                          num_rhs=num_rhs)
            sub.add_subsystem('displacements_comp', comp)

            comp = MultiComplianceComp(num_elements=num_elements,
                                       force_vector=force_vector,
                                       num_rhs=num_rhs)
            sub.add_subsystem('compliance_comp', comp)

            self.connect('local_stiffness_matrix_comp.K_local',
                         'parallel.%s.states_comp.K_local' % name)

            for k in range(num_rhs):
                sub.connect('states_comp.d_%d' % k,
                            'displacements_comp.d_%d' % k)
                sub.connect('displacements_comp.displacements_%d' % k,
                            'compliance_comp.displacements_%d' % k)

                obj_srcs.append('parallel.%s.compliance_comp.compliance_%d' %
                                (name, k))

        comp = VolumeComp(num_elements=num_elements, b=b, L=L)
        self.add_subsystem('volume_comp', comp)

        comp = om.ExecComp([
            'obj = ' +
            ' + '.join(['compliance_%d' % i for i in range(num_load_cases)])
        ])
        self.add_subsystem('obj_sum', comp)

        for j, src in enumerate(obj_srcs):
            self.connect(src, 'obj_sum.compliance_%d' % j)

        self.connect('inputs_comp.h_cp', 'interp.h_cp')
        self.connect('interp.h', 'I_comp.h')
        self.connect('I_comp.I', 'local_stiffness_matrix_comp.I')
        self.connect('interp.h', 'volume_comp.h')

        self.add_design_var('inputs_comp.h_cp', lower=1e-2, upper=10.)
        self.add_constraint('volume_comp.volume', equals=volume)
        self.add_objective('obj_sum.obj')
예제 #24
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
예제 #25
0
def _make_tree_model():
    p = om.Problem()
    model = p.model

    units1 = units2 = 'ft'

    val = 1.0

    g1 = model.add_subsystem("G1", om.Group(), promotes_inputs=['x'])

    g2 = g1.add_subsystem("G2", om.Group(), promotes_inputs=['x'])
    g2.add_subsystem("C1",
                     om.ExecComp("y = 2. * x",
                                 x={
                                     'val': val,
                                     'units': units2
                                 },
                                 y={
                                     'val': 1.0,
                                     'units': units2
                                 }),
                     promotes_inputs=['x'])
    g2.add_subsystem("C2",
                     om.ExecComp("y = 3. * x",
                                 x={
                                     'val': val,
                                     'units': units1
                                 },
                                 y={
                                     'val': 1.0,
                                     'units': units1
                                 }),
                     promotes_inputs=['x'])

    g3 = model.add_subsystem("G3", om.Group(), promotes_inputs=['x'])
    g3.add_subsystem("C3",
                     om.ExecComp("y = 4. * x",
                                 x={
                                     'val': val,
                                     'units': units1
                                 },
                                 y={
                                     'val': 1.0,
                                     'units': units1
                                 }),
                     promotes_inputs=['x'])
    g3.add_subsystem("C4",
                     om.ExecComp("y = 5. * x",
                                 x={
                                     'val': val,
                                     'units': units2
                                 },
                                 y={
                                     'val': 1.0,
                                     'units': units2
                                 }),
                     promotes_inputs=['x'])

    par = model.add_subsystem("par", om.ParallelGroup(), promotes_inputs=['x'])

    g4 = par.add_subsystem("G4", om.Group(), promotes_inputs=['x'])
    g4.add_subsystem("C5",
                     om.ExecComp("y = 6. * x",
                                 x={
                                     'val': val,
                                     'units': units2
                                 },
                                 y={
                                     'val': 1.0,
                                     'units': units2
                                 }),
                     promotes_inputs=['x'])
    g4.add_subsystem("C6",
                     om.ExecComp("y = 7. * x",
                                 x={
                                     'val': val,
                                     'units': units1
                                 },
                                 y={
                                     'val': 1.0,
                                     'units': units1
                                 }),
                     promotes_inputs=['x'])

    g5 = par.add_subsystem("G5", om.Group(), promotes_inputs=['x'])
    g5.add_subsystem("C7",
                     om.ExecComp("y = 8. * x",
                                 x={
                                     'val': val,
                                     'units': units1
                                 },
                                 y={
                                     'val': 1.0,
                                     'units': units1
                                 }),
                     promotes_inputs=['x'])
    g5.add_subsystem("C8",
                     om.ExecComp("y = 9. * x",
                                 x={
                                     'val': val,
                                     'units': units2
                                 },
                                 y={
                                     'val': 1.0,
                                     'units': units2
                                 }),
                     promotes_inputs=['x'])

    model.add_subsystem("C9",
                        om.ExecComp("y = 10. * x",
                                    x={
                                        'val': val,
                                        'units': units2
                                    },
                                    y={
                                        'val': 1.0,
                                        'units': units2
                                    }),
                        promotes_inputs=['x'])

    return p
예제 #26
0
    def test(self):
        """
        This is an opt problem that tests the wingbox model with wave drag and the fuel vol constraint
        """

        # Create a dictionary to store options about the surface
        mesh_dict = {
            'num_y': 7,
            'num_x': 2,
            'wing_type': 'CRM',
            'symmetry': True,
            'num_twist_cp': 6,
            'chord_cos_spacing': 0,
            'span_cos_spacing': 0,
        }

        mesh, twist_cp = generate_mesh(mesh_dict)

        surf_dict = {
            # Wing definition
            'name':
            'wing',  # name of the surface
            'symmetry':
            True,  # if true, model one half of wing
            # reflected across the plane y = 0
            'S_ref_type':
            'wetted',  # how we compute the wing area,
            # can be 'wetted' or 'projected'
            'fem_model_type':
            'wingbox',
            'spar_thickness_cp':
            np.array([0.004, 0.005, 0.005, 0.008, 0.008, 0.01]),  # [m]
            'skin_thickness_cp':
            np.array([0.005, 0.01, 0.015, 0.020, 0.025, 0.026]),
            'twist_cp':
            np.array([4., 5., 8., 8., 8., 9.]),
            'mesh':
            mesh,
            'data_x_upper':
            upper_x,
            'data_x_lower':
            lower_x,
            'data_y_upper':
            upper_y,
            'data_y_lower':
            lower_y,
            'strength_factor_for_upper_skin':
            1.,

            # Aerodynamic performance of the lifting surface at
            # an angle of attack of 0 (alpha=0).
            # These CL0 and CD0 values are added to the CL and CD
            # obtained from aerodynamic analysis of the surface to get
            # the total CL and CD.
            # These CL0 and CD0 values do not vary wrt alpha.
            'CL0':
            0.0,  # CL of the surface at alpha=0
            'CD0':
            0.0078,  # CD of the surface at alpha=0

            # Airfoil properties for viscous drag calculation
            'k_lam':
            0.05,  # percentage of chord with laminar
            # flow, used for viscous drag
            't_over_c_cp':
            np.array([0.08, 0.08, 0.08, 0.10, 0.10, 0.08]),
            'original_wingbox_airfoil_t_over_c':
            0.12,
            'c_max_t':
            .38,  # chordwise location of maximum thickness
            'with_viscous':
            True,
            'with_wave':
            True,  # if true, compute wave drag

            # Structural values are based on aluminum 7075
            'E':
            73.1e9,  # [Pa] Young's modulus
            'G': (
                73.1e9 / 2 / 1.33
            ),  # [Pa] shear modulus (calculated using E and the Poisson's ratio here)
            'yield': (420.e6 / 1.5),  # [Pa] allowable yield stress
            'mrho':
            2.78e3,  # [kg/m^3] material density
            'strength_factor_for_upper_skin':
            1.0,  # the yield stress is multiplied by this factor for the upper skin
            # 'fem_origin' : 0.35,    # normalized chordwise location of the spar
            'wing_weight_ratio':
            1.25,
            'struct_weight_relief':
            True,
            'distributed_fuel_weight':
            True,
            # Constraints
            'exact_failure_constraint':
            False,  # if false, use KS function
            'fuel_density':
            803.,  # [kg/m^3] fuel density (only needed if the fuel-in-wing volume constraint is used)
            'Wf_reserve':
            15000.,  # [kg] reserve fuel mass
        }

        surfaces = [surf_dict]

        # Create the problem and assign the model group
        prob = om.Problem()

        # Add problem information as an independent variables component
        indep_var_comp = om.IndepVarComp()
        indep_var_comp.add_output('v', val=.85 * 295.07, units='m/s')
        indep_var_comp.add_output('alpha', val=0., units='deg')
        indep_var_comp.add_output('Mach_number', val=0.85)
        indep_var_comp.add_output('re',
                                  val=0.348 * 295.07 * .85 * 1. /
                                  (1.43 * 1e-5),
                                  units='1/m')
        indep_var_comp.add_output('rho', val=0.348, units='kg/m**3')
        indep_var_comp.add_output('CT', val=0.53 / 3600, units='1/s')
        indep_var_comp.add_output('R', val=14.307e6, units='m')
        indep_var_comp.add_output('W0',
                                  val=148000 + surf_dict['Wf_reserve'],
                                  units='kg')
        indep_var_comp.add_output('speed_of_sound', val=295.07, units='m/s')
        indep_var_comp.add_output('load_factor', val=1.)
        indep_var_comp.add_output('empty_cg', val=np.zeros((3)), units='m')
        indep_var_comp.add_output('fuel_mass', val=10000., units='kg')

        prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*'])

        # Loop over each surface in the surfaces list
        for surface in surfaces:

            # Get the surface name and create a group to contain components
            # only for this surface
            name = surface['name']

            aerostruct_group = AerostructGeometry(surface=surface)

            # Add tmp_group to the problem with the name of the surface.
            prob.model.add_subsystem(name, aerostruct_group)

        # Loop through and add a certain number of aero points
        for i in range(1):

            point_name = 'AS_point_{}'.format(i)
            # Connect the parameters within the model for each aero point

            # Create the aero point group and add it to the model
            AS_point = AerostructPoint(surfaces=surfaces)

            prob.model.add_subsystem(point_name, AS_point)

            # Connect flow properties to the analysis point
            prob.model.connect('v', point_name + '.v')
            prob.model.connect('alpha', point_name + '.alpha')
            prob.model.connect('Mach_number', point_name + '.Mach_number')
            prob.model.connect('re', point_name + '.re')
            prob.model.connect('rho', point_name + '.rho')
            prob.model.connect('CT', point_name + '.CT')
            prob.model.connect('R', point_name + '.R')
            prob.model.connect('W0', point_name + '.W0')
            prob.model.connect('speed_of_sound',
                               point_name + '.speed_of_sound')
            prob.model.connect('empty_cg', point_name + '.empty_cg')
            prob.model.connect('load_factor', point_name + '.load_factor')

            for surface in surfaces:

                prob.model.connect('load_factor',
                                   point_name + '.coupled.load_factor')

                com_name = point_name + '.' + name + '_perf.'
                prob.model.connect(
                    name + '.local_stiff_transformed', point_name +
                    '.coupled.' + name + '.local_stiff_transformed')

                # Connect aerodyamic mesh to coupled group mesh
                prob.model.connect(name + '.mesh',
                                   point_name + '.coupled.' + name + '.mesh')
                prob.model.connect(
                    name + '.element_mass',
                    point_name + '.coupled.' + name + '.element_mass')
                prob.model.connect(name + '.nodes',
                                   point_name + '.coupled.' + name + '.nodes')

                # Connect performance calculation variables
                prob.model.connect(name + '.nodes', com_name + 'nodes')
                prob.model.connect(
                    name + '.cg_location',
                    point_name + '.' + 'total_perf.' + name + '_cg_location')
                prob.model.connect(
                    name + '.structural_mass', point_name + '.' +
                    'total_perf.' + name + '_structural_mass')

                # Connect wingbox properties to von Mises stress calcs
                prob.model.connect(name + '.Qz', com_name + 'Qz')
                prob.model.connect(name + '.J', com_name + 'J')
                prob.model.connect(name + '.A_enc', com_name + 'A_enc')
                prob.model.connect(name + '.htop', com_name + 'htop')
                prob.model.connect(name + '.hbottom', com_name + 'hbottom')
                prob.model.connect(name + '.hfront', com_name + 'hfront')
                prob.model.connect(name + '.hrear', com_name + 'hrear')

                prob.model.connect(name + '.spar_thickness',
                                   com_name + 'spar_thickness')
                prob.model.connect(name + '.t_over_c', com_name + 't_over_c')

            #=======================================================================================
            # Here we add the fuel volume constraint componenet to the model
            #=======================================================================================
            prob.model.add_subsystem('fuel_vol_delta',
                                     WingboxFuelVolDelta(surface=surface))
            prob.model.connect('AS_point_0.fuelburn',
                               'fuel_vol_delta.fuelburn')
            prob.model.connect('wing.struct_setup.fuel_vols',
                               'fuel_vol_delta.fuel_vols')
            prob.model.connect(
                'wing.struct_setup.fuel_vols',
                'AS_point_0.coupled.wing.struct_states.fuel_vols')
            prob.model.connect(
                'fuel_mass', 'AS_point_0.coupled.wing.struct_states.fuel_mass')

            comp = om.ExecComp('fuel_diff = (fuel_mass - fuelburn) / fuelburn',
                               units='kg')
            prob.model.add_subsystem('fuel_diff',
                                     comp,
                                     promotes_inputs=['fuel_mass'],
                                     promotes_outputs=['fuel_diff'])
            prob.model.connect('AS_point_0.fuelburn', 'fuel_diff.fuelburn')
            #=======================================================================================
            #=======================================================================================

        prob.driver = om.ScipyOptimizeDriver()
        prob.driver.options['tol'] = 1e-9

        # prob.driver = om.pyOptSparseDriver()
        # prob.driver.add_recorder(om.SqliteRecorder("cases.sql"))
        # prob.driver.options['optimizer'] = "SNOPT"
        # prob.driver.opt_settings['Major optimality tolerance'] = 1e-6
        # prob.driver.opt_settings['Major feasibility tolerance'] = 1e-8
        # prob.driver.opt_settings['Major iterations limit'] = 200

        prob.model.add_objective('AS_point_0.fuelburn', scaler=1e-5)

        prob.model.add_design_var('wing.twist_cp',
                                  lower=-15.,
                                  upper=15.,
                                  scaler=0.1)
        prob.model.add_design_var('wing.spar_thickness_cp',
                                  lower=0.003,
                                  upper=0.1,
                                  scaler=1e2)
        prob.model.add_design_var('wing.skin_thickness_cp',
                                  lower=0.003,
                                  upper=0.1,
                                  scaler=1e2)
        prob.model.add_design_var('wing.geometry.t_over_c_cp',
                                  lower=0.07,
                                  upper=0.2,
                                  scaler=10.)
        prob.model.add_design_var('fuel_mass',
                                  lower=0.,
                                  upper=2e5,
                                  scaler=1e-5)

        prob.model.add_constraint('AS_point_0.CL', equals=0.5)
        prob.model.add_constraint('AS_point_0.wing_perf.failure', upper=0.)

        #=======================================================================================
        # Here we add the fuel volume constraint
        #=======================================================================================
        prob.model.add_constraint('fuel_vol_delta.fuel_vol_delta', lower=0.)
        prob.model.add_constraint('fuel_diff', equals=0.)
        #=======================================================================================
        #=======================================================================================

        # Set up the problem
        prob.setup()

        # om.view_model(prob)

        prob.run_driver()

        # prob.check_partials(form='central', compact_print=True)

        print(prob['AS_point_0.fuelburn'][0])
        print(prob['wing.structural_mass'][0] / 1.25)

        assert_rel_error(self, prob['AS_point_0.fuelburn'][0], 80758.28839215,
                         1e-5)
        assert_rel_error(self, prob['wing.structural_mass'][0] / 1.25,
                         12330.193521430, 1e-5)
예제 #27
0
    def setup(self):
        num_nodes = self.options['num_nodes']
        num_radial = self.options['num_radial']
        num_blades = self.options['num_blades']
        af_filename = self.options['af_filename']
        turbine = self.options['turbine']
        installed_thrust_loss = self.options['installed_thrust_loss']

        comp = om.ExecComp([
            'hub_radius = 0.5*hub_diameter', 'prop_radius = 0.5*prop_diameter'
        ],
                           shape=num_nodes,
                           has_diag_partials=True,
                           hub_radius={'units': 'm'},
                           hub_diameter={'units': 'm'},
                           prop_radius={'units': 'm'},
                           prop_diameter={'units': 'm'})
        self.add_subsystem('hub_prop_radius_comp', comp, promotes=['*'])

        # Stole this from John Hwang's OpenBEMT code.
        this_dir = os.path.split(__file__)[0]
        file_path = os.path.join(this_dir, 'airfoils', af_filename)
        af = af_from_files([file_path])

        comp = make_component(
            CCBladeResidualComp(num_nodes=num_nodes,
                                num_radial=num_radial,
                                af=af,
                                B=num_blades,
                                turbine=turbine))
        comp.linear_solver = om.DirectSolver(assemble_jac=True)
        self.add_subsystem('ccblade_comp',
                           comp,
                           promotes_inputs=[("r", "radii"), "chord", "theta",
                                            "Vx", "Vy", "rho", "mu", "asound",
                                            ("Rhub", "hub_radius"),
                                            ("Rtip", "prop_radius"), "precone",
                                            "pitch"],
                           promotes_outputs=['Np', 'Tp'])

        comp = FunctionalsComp(num_nodes=num_nodes,
                               num_radial=num_radial,
                               num_blades=num_blades)
        if installed_thrust_loss:
            promotes_outputs = [('thrust', 'uninstalled_thrust'), 'torque',
                                'power', 'efficiency']
        else:
            promotes_outputs = ['thrust', 'torque', 'power', 'efficiency']

        self.add_subsystem('ccblade_torquethrust_comp',
                           comp,
                           promotes_inputs=[
                               'hub_radius', 'prop_radius', 'radii', 'Np',
                               'Tp', 'v', 'omega'
                           ],
                           promotes_outputs=promotes_outputs)

        if installed_thrust_loss:
            comp = BertonInstalledThrustLossInputComp(num_nodes=num_nodes)
            self.add_subsystem('installed_thrust_loss_inputs_comp',
                               comp,
                               promotes_inputs=['omega', 'v', 'prop_diameter'],
                               promotes_outputs=['sqa', 'zje'])

            comp = om.MetaModelStructuredComp(vec_size=num_nodes)
            comp.add_input('sqa',
                           val=0.0,
                           training_data=sqa_training,
                           units=None)
            comp.add_input('zje',
                           val=0.0,
                           training_data=zje_training,
                           units=None)
            comp.add_output('fb',
                            val=1.0,
                            training_data=fb_training,
                            units=None)
            self.add_subsystem('installed_thrust_loss_mm_comp',
                               comp,
                               promotes_inputs=['sqa', 'zje'],
                               promotes_outputs=['fb'])

            comp = om.ExecComp('thrust = fb*uninstalled_thrust',
                               has_diag_partials=True,
                               uninstalled_thrust={
                                   'units': 'N',
                                   'shape': num_nodes
                               },
                               fb={
                                   'units': None,
                                   'shape': num_nodes
                               },
                               thrust={
                                   'units': 'N',
                                   'shape': num_nodes
                               })
            self.add_subsystem('installed_thrust_loss_comp',
                               comp,
                               promotes_inputs=['fb', 'uninstalled_thrust'],
                               promotes_outputs=['thrust'])
예제 #28
0
    comp = om.MetaModelStructuredComp(vec_size=nn)
    comp.add_input('sqa', val=0.0, training_data=sqa_training, units=None)
    comp.add_input('zje', val=0.0, training_data=zje_training, units=None)
    comp.add_output('fb', val=1.0, training_data=fb_training, units=None)
    prob.model.add_subsystem('installed_thrust_loss_mm_comp',
                             comp,
                             promotes_inputs=['sqa', 'zje'],
                             promotes_outputs=['fb'])

    comp = om.ExecComp('installed_thrust = fb*bemt_thrust',
                       has_diag_partials=True,
                       bemt_thrust={
                           'units': 'N',
                           'shape': nn
                       },
                       fb={
                           'units': None,
                           'shape': nn
                       },
                       installed_thrust={
                           'units': 'N',
                           'shape': nn
                       })
    prob.model.add_subsystem('installed_thrust_loss_comp',
                             comp,
                             promotes_inputs=['fb', 'bemt_thrust'],
                             promotes_outputs=['installed_thrust'])

    prob.setup()
    prob.run_model()
    print(f"sqa = {prob.get_val('sqa')}")
    print(f"zje = {prob.get_val('zje')}")
예제 #29
0
 def test_dangling_input_w_units(self):
     prob = om.Problem()
     prob.model.add_subsystem(
         'C1', om.ExecComp('y=x', x={'units': 'ft'}, y={'units': 'm'}))
     prob.setup()
     prob.run_model()
예제 #30
0
    def test_pyxdsm_pdf(self):
        """
        Makes an XDSM of the Sphere test case. It also adds a design variable, constraint and
        objective.
        """
        class Rosenbrock(om.ExplicitComponent):
            def __init__(self, problem):
                super(Rosenbrock, self).__init__()
                self.problem = problem
                self.counter = 0

            def setup(self):
                self.add_input('x', np.array([1.5, 1.5]))
                self.add_output('f', 0.0)
                self.declare_partials('f',
                                      'x',
                                      method='fd',
                                      form='central',
                                      step=1e-4)

            def compute(self,
                        inputs,
                        outputs,
                        discrete_inputs=None,
                        discrete_outputs=None):
                x = inputs['x']
                outputs['f'] = sum(x**2)

        x0 = np.array([1.2, 1.5])
        filename = 'xdsm2'

        prob = om.Problem()
        indeps = prob.model.add_subsystem('indeps',
                                          om.IndepVarComp(problem=prob),
                                          promotes=['*'])
        indeps.add_output('x', list(x0))

        prob.model.add_subsystem('sphere',
                                 Rosenbrock(problem=prob),
                                 promotes=['*'])
        prob.model.add_subsystem('con',
                                 om.ExecComp('c=sum(x)', x=np.ones(2)),
                                 promotes=['*'])
        prob.driver = om.ScipyOptimizeDriver()
        prob.model.add_design_var('x')
        prob.model.add_objective('f')
        prob.model.add_constraint('c', lower=1.0)

        prob.setup()
        prob.final_setup()

        # requesting 'pdf', but if 'pdflatex' is not found we will only get 'tex'
        pdflatex = find_executable('pdflatex')

        # Write output
        om.write_xdsm(prob,
                      filename=filename,
                      out_format='pdf',
                      show_browser=SHOW,
                      quiet=QUIET)

        # Check if file was created
        self.assertTrue(os.path.isfile('.'.join([filename, 'tex'])))
        # Check if PDF was created (only if pdflatex is installed)
        self.assertTrue(not pdflatex
                        or os.path.isfile('.'.join([filename, 'pdf'])))