def test_brachistochrone_base_phase_class_gl(self):
        import openmdao.api as om
        from openmdao.utils.assert_utils import assert_near_equal
        import dymos as dm

        class BrachistochronePhase(dm.Phase):
            def setup(self):

                self.options['ode_class'] = BrachistochroneODE
                self.set_time_options(initial_bounds=(0, 0),
                                      duration_bounds=(.5, 10),
                                      units='s')
                self.add_state('x',
                               fix_initial=True,
                               rate_source='xdot',
                               units='m')
                self.add_state('y',
                               fix_initial=True,
                               rate_source='ydot',
                               units='m')
                self.add_state('v',
                               fix_initial=True,
                               rate_source='vdot',
                               targets=['v'],
                               units='m/s')
                self.add_control('theta',
                                 units='deg',
                                 rate_continuity=False,
                                 lower=0.01,
                                 upper=179.9,
                                 targets=['theta'])
                self.add_parameter('g',
                                   units='m/s**2',
                                   opt=False,
                                   val=9.80665,
                                   targets=['g'])

                super(BrachistochronePhase, self).setup()

        p = om.Problem(model=om.Group())
        p.driver = om.ScipyOptimizeDriver()

        phase = BrachistochronePhase(
            transcription=dm.GaussLobatto(num_segments=20, order=3))
        p.model.add_subsystem('phase0', phase)

        phase.add_boundary_constraint('x', loc='final', equals=10)
        phase.add_boundary_constraint('y', loc='final', equals=5)

        # Minimize time at the end of the phase
        phase.add_objective('time', loc='final', scaler=10)

        p.model.linear_solver = om.DirectSolver()

        p.setup()

        p['phase0.t_initial'] = 0.0
        p['phase0.t_duration'] = 2.0

        p['phase0.states:x'] = phase.interpolate(ys=[0, 10],
                                                 nodes='state_input')
        p['phase0.states:y'] = phase.interpolate(ys=[10, 5],
                                                 nodes='state_input')
        p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9],
                                                 nodes='state_input')
        p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100.5],
                                                       nodes='control_input')

        # Solve for the optimal trajectory
        p.run_driver()

        # Test the results
        assert_near_equal(p.get_val('phase0.timeseries.time')[-1],
                          1.8016,
                          tolerance=1.0E-3)

        exp_out = phase.simulate()

        assert_near_equal(exp_out.get_val('phase0.timeseries.states:x')[-1],
                          10,
                          tolerance=1.0E-3)
        assert_near_equal(exp_out.get_val('phase0.timeseries.states:y')[-1],
                          5,
                          tolerance=1.0E-3)
示例#2
0
    def test_propeller_aero4students(self):
        # Copied from CCBlade.jl/test/runtests.jl

        # -------- verification: propellers.  using script at http://www.aerodynamics4students.com/propulsion/blade-element-propeller-theory.php ------
        # I increased their tolerance to 1e-6

        # inputs
        chord = 0.10
        D = 1.6
        RPM = 2100
        rho = 1.225
        pitch = 1.0  # pitch distance in meters.

        # --- rotor definition ---
        turbine = False
        # Rhub = 0.0
        # Rtip = D/2
        Rhub_eff = 1e-6  # something small to eliminate hub effects
        Rtip_eff = 100.0  # something large to eliminate tip effects
        B = 2  # number of blades

        # --- section definitions ---

        num_nodes = 60
        R = D / 2.0
        r = np.linspace(R / 10, R, 11)
        dr = r[1] - r[0]
        r = np.tile(r, (num_nodes, 1))
        theta = np.arctan(pitch / (2 * np.pi * r))

        def affunc(alpha, Re, M):
            cl = 6.2 * alpha
            cd = 0.008 - 0.003 * cl + 0.01 * cl * cl
            return cl, cd

        prob = om.Problem()
        num_radial = r.shape[-1]

        comp = om.IndepVarComp()
        comp.add_output('v', val=np.arange(1, 60 + 1)[:num_nodes], units='m/s')
        comp.add_output('omega', val=np.tile(RPM, num_nodes), units='rpm')
        comp.add_output('radii', val=r, units='m')
        comp.add_output('chord',
                        val=chord,
                        shape=(num_nodes, num_radial),
                        units='m')
        comp.add_output('theta',
                        val=theta,
                        shape=(num_nodes, num_radial),
                        units='rad')
        comp.add_output('precone', val=0., shape=num_nodes, units='rad')
        comp.add_output('rho', val=rho, shape=(num_nodes, 1), units='kg/m**3')
        comp.add_output('mu', val=1.0, shape=(num_nodes, 1), units='N/m**2*s')
        comp.add_output('asound', val=1.0, shape=(num_nodes, 1), units='m/s')
        comp.add_output('hub_radius', val=Rhub_eff, shape=num_nodes, units='m')
        comp.add_output('prop_radius',
                        val=Rtip_eff,
                        shape=num_nodes,
                        units='m')
        comp.add_output('pitch', val=0.0, shape=num_nodes, units='rad')
        prob.model.add_subsystem('ivc', comp, promotes_outputs=['*'])

        comp = SimpleInflow(num_nodes=num_nodes, num_radial=num_radial)
        prob.model.add_subsystem(
            "simple_inflow",
            comp,
            promotes_inputs=["v", "omega", "radii", "precone"],
            promotes_outputs=["Vx", "Vy"])

        comp = ccb.LocalInflowAngleComp(num_nodes=num_nodes,
                                        num_radial=num_radial,
                                        num_blades=B,
                                        airfoil_interp=affunc,
                                        turbine=turbine,
                                        debug_print=False)
        comp.linear_solver = om.DirectSolver(assemble_jac=True)
        prob.model.add_subsystem('ccblade',
                                 comp,
                                 promotes_inputs=[
                                     'radii', 'chord', 'theta', 'Vx', 'Vy',
                                     'rho', 'mu', 'asound', 'hub_radius',
                                     'prop_radius', 'precone', 'pitch'
                                 ],
                                 promotes_outputs=['Np', 'Tp'])

        prob.setup()
        prob.final_setup()
        prob.run_model()

        Np = prob.get_val('Np', units='N/m')
        Tp = prob.get_val('Tp', units='N/m')
        T = np.sum(Np * dr, axis=1) * B
        Q = np.sum(r * Tp * dr, axis=1) * B

        tsim = 1e3 * np.array([
            1.045361193032356, 1.025630300048415, 1.005234466788998,
            0.984163367036026, 0.962407923825140, 0.939960208707079,
            0.916813564966455, 0.892962691000145, 0.868403981825492,
            0.843134981103815, 0.817154838249790, 0.790463442573673,
            0.763063053839278, 0.734956576558370, 0.706148261507327,
            0.676643975451150, 0.646450304160057, 0.615575090105131,
            0.584027074365864, 0.551815917391907, 0.518952127358381,
            0.485446691671386, 0.451311288662196, 0.416557935286392,
            0.381199277009438, 0.345247916141561, 0.308716772800348,
            0.271618894441869, 0.233967425339051, 0.195775319296371,
            0.157055230270717, 0.117820154495231, 0.078082266879117,
            0.037854059197644, -0.002852754149850, -0.044026182837742,
            -0.085655305814570, -0.127728999394140, -0.170237722799272,
            -0.213169213043848, -0.256515079286031, -0.300266519551194,
            -0.344414094748869, -0.388949215983616, -0.433863576642539,
            -0.479150401337354, -0.524801553114807, -0.570810405128802,
            -0.617169893200684, -0.663873474163182, -0.710915862524620,
            -0.758291877949762, -0.805995685105502, -0.854022273120508,
            -0.902366919041604, -0.951025170820984, -0.999992624287163,
            -1.049265666456123, -1.098840222937414, -1.148712509929845
        ])
        qsim = 1e2 * np.array([
            0.803638686218187, 0.806984572453978, 0.809709290183008,
            0.811743686838315, 0.813015017103876, 0.813446921530685,
            0.812959654049620, 0.811470393912576, 0.808893852696513,
            0.805141916379142, 0.800124489784850, 0.793748780791057,
            0.785921727832179, 0.776548246109426, 0.765532528164390,
            0.752778882688809, 0.738190986274448, 0.721673076180745,
            0.703129918771009, 0.682467282681955, 0.659592296506578,
            0.634413303042323, 0.606840565246423, 0.576786093366321,
            0.544164450503912, 0.508891967461804, 0.470887571011192,
            0.430072787279711, 0.386371788290446, 0.339711042057184,
            0.290019539402947, 0.237229503458026, 0.181274942660876,
            0.122093307308376, 0.059623821454727, -0.006190834182631,
            -0.075406684829235, -0.148076528546541, -0.224253047813501,
            -0.303980950928302, -0.387309291734422, -0.474283793689904,
            -0.564946107631716, -0.659336973911858, -0.757495165410553,
            -0.859460291551374, -0.965266648683888, -1.074949504731187,
            -1.188540970723477, -1.306072104649531, -1.427575034895290,
            -1.553080300508925, -1.682614871422754, -1.816205997296014,
            -1.953879956474228, -2.095662107769925, -2.241576439746701,
            -2.391647474158875, -2.545897099743367, -2.704346566395035
        ])

        assert_rel_error(self, T, tsim[:num_nodes], 1e-5)
        assert_rel_error(self, Q, qsim[:num_nodes], 1e-5)

        # Run with v = 20.0 m/s.
        prob.set_val('v', 20.0, units='m/s', indices=0)
        prob.run_model()

        Vhub = prob.get_val('v', units='m/s', indices=0)
        omega = prob.get_val('omega', units='rad/s', indices=0)
        Np = prob.get_val('Np', units='N/m', indices=0)
        Tp = prob.get_val('Tp', units='N/m', indices=0)
        T = np.sum(Np * dr) * B
        Q = np.sum(r[0, :] * Tp * dr) * B

        P = Q * omega
        n = omega / (2 * np.pi)
        CT = T / (rho * n**2 * D**4)
        CQ = Q / (rho * n**2 * D**5)
        eff = T * Vhub / P

        assert_rel_error(self, CT, 0.056110238632657, 1e-6)
        assert_rel_error(self, CQ, 0.004337202960642, 1e-6)
        assert_rel_error(self, eff, 0.735350632777002, 1e-5)
示例#3
0
    def test_multiple_adv_ratios(self):
        # num_nodes = 20
        nstart = 0
        nend = 19
        num_nodes = nend - nstart + 1

        r = 0.0254 * np.array([
            0.7526, 0.7928, 0.8329, 0.8731, 0.9132, 0.9586, 1.0332, 1.1128,
            1.1925, 1.2722, 1.3519, 1.4316, 1.5114, 1.5911, 1.6708, 1.7505,
            1.8302, 1.9099, 1.9896, 2.0693, 2.1490, 2.2287, 2.3084, 2.3881,
            2.4678, 2.5475, 2.6273, 2.7070, 2.7867, 2.8661, 2.9410
        ]).reshape(1, -1)
        num_radial = r.shape[-1]
        r = np.tile(r, (num_nodes, 1))

        chord = 0.0254 * np.array([
            0.6270, 0.6255, 0.6231, 0.6199, 0.6165, 0.6125, 0.6054, 0.5973,
            0.5887, 0.5794, 0.5695, 0.5590, 0.5479, 0.5362, 0.5240, 0.5111,
            0.4977, 0.4836, 0.4689, 0.4537, 0.4379, 0.4214, 0.4044, 0.3867,
            0.3685, 0.3497, 0.3303, 0.3103, 0.2897, 0.2618, 0.1920
        ]).reshape((1, num_radial))
        chord = np.tile(chord, (num_nodes, 1))

        theta = np.pi / 180.0 * np.array([
            40.2273, 38.7657, 37.3913, 36.0981, 34.8803, 33.5899, 31.6400,
            29.7730, 28.0952, 26.5833, 25.2155, 23.9736, 22.8421, 21.8075,
            20.8586, 19.9855, 19.1800, 18.4347, 17.7434, 17.1005, 16.5013,
            15.9417, 15.4179, 14.9266, 14.4650, 14.0306, 13.6210, 13.2343,
            12.8685, 12.5233, 12.2138
        ]).reshape((1, num_radial))
        theta = np.tile(theta, (num_nodes, 1))

        rho = 1.225
        Rhub = 0.0254 * .5
        Rtip = 0.0254 * 3.0
        B = 2  # number of blades
        turbine = False

        J = np.linspace(0.1, 0.9, 20)[nstart:nend + 1]  # advance ratio
        # J = np.linspace(0.1, 0.9, 20)

        omega = 8000.0 * np.pi / 30

        n = omega / (2 * np.pi)
        D = 2 * Rtip

        Vinf = J * D * n
        dr = r[0, 1] - r[0, 0]

        # Airfoil interpolator.
        af = af_from_files(["airfoils/NACA64_A17.dat"])[0]

        prob = om.Problem()

        comp = om.IndepVarComp()
        comp.add_output('v', val=Vinf, units='m/s')
        comp.add_output('omega', val=np.tile(omega, num_nodes), units='rad/s')
        comp.add_output('radii',
                        val=r,
                        shape=(num_nodes, num_radial),
                        units='m')
        comp.add_output('dradii',
                        val=dr,
                        shape=(num_nodes, num_radial),
                        units='m')
        comp.add_output('chord',
                        val=chord,
                        shape=(num_nodes, num_radial),
                        units='m')
        comp.add_output('theta',
                        val=theta,
                        shape=(num_nodes, num_radial),
                        units='rad')
        comp.add_output('precone', val=0., shape=num_nodes, units='rad')
        comp.add_output('rho', val=rho, shape=(num_nodes, 1), units='kg/m**3')
        comp.add_output('mu', val=1.0, shape=(num_nodes, 1), units='N/m**2*s')
        comp.add_output('asound', val=1.0, shape=(num_nodes, 1), units='m/s')
        comp.add_output('hub_radius', val=Rhub, shape=num_nodes, units='m')
        comp.add_output('prop_radius', val=Rtip, shape=num_nodes, units='m')
        comp.add_output('pitch', val=0.0, shape=num_nodes, units='rad')
        prob.model.add_subsystem('ivc', comp, promotes_outputs=['*'])

        comp = SimpleInflow(num_nodes=num_nodes, num_radial=num_radial)
        prob.model.add_subsystem(
            "simple_inflow",
            comp,
            promotes_inputs=["v", "omega", "radii", "precone"],
            promotes_outputs=["Vx", "Vy"])

        comp = ccb.LocalInflowAngleComp(num_nodes=num_nodes,
                                        num_radial=num_radial,
                                        num_blades=B,
                                        airfoil_interp=af,
                                        turbine=turbine,
                                        debug_print=False)
        comp.linear_solver = om.DirectSolver(assemble_jac=True)
        prob.model.add_subsystem('ccblade',
                                 comp,
                                 promotes_inputs=[
                                     'radii', 'chord', 'theta', 'Vx', 'Vy',
                                     'rho', 'mu', 'asound', 'hub_radius',
                                     'prop_radius', 'precone', 'pitch'
                                 ],
                                 promotes_outputs=['Np', 'Tp'])

        comp = ccb.FunctionalsComp(num_nodes=num_nodes,
                                   num_radial=num_radial,
                                   num_blades=B)
        prob.model.add_subsystem(
            'ccblade_torquethrust_comp',
            comp,
            promotes_inputs=[
                'hub_radius', 'prop_radius', 'radii', 'Np', 'Tp', 'v', 'omega'
            ],
            promotes_outputs=['thrust', 'torque', 'efficiency'])

        prob.setup()
        prob.final_setup()
        prob.run_model()

        etatest = np.array([
            0.24598190455626265, 0.3349080300487075, 0.4155652767326253,
            0.48818637673414306, 0.5521115225679999, 0.6089123481436948,
            0.6595727776885079, 0.7046724703349897, 0.7441662053086512,
            0.7788447616541276, 0.8090611349633181, 0.8347808848055981,
            0.8558196582739432, 0.8715046719672315, 0.8791362131978436,
            0.8670633642311274, 0.7974063895510229, 0.2715632768892098, 0.0,
            0.0
        ])[nstart:nend + 1]

        thrust = prob.get_val('thrust', units='N')
        eff = prob.get_val('efficiency')
        assert_array_almost_equal(eff[thrust > 0.0],
                                  etatest[thrust > 0.0],
                                  decimal=2)
    p = om.Problem()

    dvs = p.model.add_subsystem('dvs', om.IndepVarComp(), promotes=['*'])
    dvs.add_output('h', val=np.ones(NUM_ELEMENTS)*1.0) 
    p.model.add_subsystem('FEM', FEMBeam(E=1, L=1, b=0.1, 
                                         num_elements=NUM_ELEMENTS),
                          promotes_inputs=['h'], 
                          promotes_outputs=['compliance', 'volume'])


    p.driver = om.ScipyOptimizeDriver()
    p.driver.options['tol'] = 1e-4
    p.driver.options['disp'] = True
    p.model.add_design_var('h', lower=0.01, upper=10.0)
    p.model.add_objective('compliance')
    p.model.add_constraint('volume', equals=0.01)

    # p.model.approx_totals(method='fd', step=1e-4, step_calc='abs')

    p.model.linear_solver = om.DirectSolver()

    p.setup()

    # p['h'] = [0.14007896, 0.12362061, 0.1046475 , 0.08152954, 0.05012339]

    p.run_driver()

    p.model.list_outputs(print_arrays=True)


示例#5
0
    def test_parameter_boundary_constraint(self):
        p = om.Problem(model=om.Group())

        p.driver = om.ScipyOptimizeDriver()
        p.driver.declare_coloring()

        phase = dm.Phase(ode_class=BrachistochroneODE,
                         transcription=dm.GaussLobatto(num_segments=20,
                                                       order=3,
                                                       compressed=True))

        p.model.add_subsystem('phase0', phase)

        phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10))

        phase.add_state('x', fix_initial=True, fix_final=True)

        phase.add_state('y', fix_initial=True, fix_final=True)

        phase.add_state('v', fix_initial=True, fix_final=False)

        phase.add_control('theta',
                          continuity=True,
                          rate_continuity=True,
                          rate2_continuity=True,
                          units='deg',
                          lower=0.01,
                          upper=179.9)

        phase.add_parameter('g', opt=True, units='m/s**2', val=9.80665)

        # We'll let g vary, but make sure it hits the desired value.
        # It's a static parameter, so it shouldn't matter whether we enforce it
        # at the start or the end of the phase, so here we'll do both.
        # Note if we make these equality constraints, some optimizers (SLSQP) will
        # see the problem as infeasible.
        phase.add_boundary_constraint('g',
                                      loc='initial',
                                      units='m/s**2',
                                      upper=9.80665)
        phase.add_boundary_constraint('g',
                                      loc='final',
                                      units='m/s**2',
                                      upper=9.80665)

        # Minimize time at the end of the phase
        phase.add_objective('time_phase', loc='final', scaler=10)

        p.model.linear_solver = om.DirectSolver()
        p.setup(check=True)

        p['phase0.t_initial'] = 0.0
        p['phase0.t_duration'] = 2.0

        p['phase0.states:x'] = phase.interp('x', [0, 10])
        p['phase0.states:y'] = phase.interp('y', [10, 5])
        p['phase0.states:v'] = phase.interp('v', [0, 9.9])
        p['phase0.controls:theta'] = phase.interp('theta', [5, 100])
        p['phase0.parameters:g'] = 5

        p.run_driver()

        assert_near_equal(p.get_val('phase0.timeseries.time')[-1],
                          1.8016,
                          tolerance=1.0E-4)
        assert_near_equal(p.get_val('phase0.timeseries.parameters:g')[0],
                          9.80665,
                          tolerance=1.0E-6)
        assert_near_equal(p.get_val('phase0.timeseries.parameters:g')[-1],
                          9.80665,
                          tolerance=1.0E-6)
示例#6
0
    def setup(self):
        thermo_data = self.options['thermo_data']
        elements = self.options['elements']
        nozzType = self.options['nozzType']
        lossCoef = self.options['lossCoef']

        num_element = len(elements)

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

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

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

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

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

        # Calculate throat total flow properties
        throat_total = Thermo(mode='total_hP',
                              fl_name='Fl_O:tot',
                              method='CEA',
                              thermo_kwargs={
                                  'elements': elements,
                                  'spec': thermo_data
                              })
        prom_in = [('h', 'Fl_I:tot:h'),
                   ('composition', 'Fl_I:tot:composition')]
        self.add_subsystem('throat_total',
                           throat_total,
                           promotes_inputs=prom_in,
                           promotes_outputs=['Fl_O:*'])
        self.connect('press_calcs.Pt_th', 'throat_total.P')

        # Calculate static properties for sonic flow
        throat_static_MN = Thermo(mode='static_MN',
                                  method='CEA',
                                  thermo_kwargs={
                                      'elements': elements,
                                      'spec': thermo_data
                                  })
        prom_in = [('ht', 'Fl_I:tot:h'), ('W', 'Fl_I:stat:W'),
                   ('composition', 'Fl_I:tot:composition')]
        self.add_subsystem('staticMN',
                           throat_static_MN,
                           promotes_inputs=prom_in)
        self.connect('throat_total.S', 'staticMN.S')
        self.connect('mach_choked.MN', 'staticMN.MN')
        self.connect('press_calcs.Pt_th', 'staticMN.guess:Pt')
        self.connect('throat_total.gamma', 'staticMN.guess:gamt')
        # self.connect('Fl_I.flow:flow_products','staticMN.init_prod_amounts')

        # Calculate static properties based on exit static pressure
        throat_static_Ps = Thermo(mode='static_Ps',
                                  method='CEA',
                                  thermo_kwargs={
                                      'elements': elements,
                                      'spec': thermo_data
                                  })
        prom_in = [('ht', 'Fl_I:tot:h'), ('W', 'Fl_I:stat:W'),
                   ('Ps', 'Ps_calc'), ('composition', 'Fl_I:tot:composition')]
        self.add_subsystem('staticPs',
                           throat_static_Ps,
                           promotes_inputs=prom_in)
        self.connect('throat_total.S', 'staticPs.S')
        # self.connect('press_calcs.Ps_calc', 'staticPs.Ps')
        # self.connect('Fl_I.flow:flow_products','staticPs.init_prod_amounts')

        # Calculate ideal exit flow properties
        ideal_flow = Thermo(mode='static_Ps',
                            method='CEA',
                            thermo_kwargs={
                                'elements': elements,
                                'spec': thermo_data
                            })
        prom_in = [('ht', 'Fl_I:tot:h'), ('S', 'Fl_I:tot:S'),
                   ('W', 'Fl_I:stat:W'), ('Ps', 'Ps_calc'),
                   ('composition', 'Fl_I:tot:composition')]
        self.add_subsystem('ideal_flow', ideal_flow, promotes_inputs=prom_in)
        # self.connect('press_calcs.Ps_calc', 'ideal_flow.Ps')
        # self.connect('Fl_I.flow:flow_products','ideal_flow.init_prod_amounts')

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

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

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

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

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

            newton.linesearch.options['iprint'] = -1
            self.linear_solver = om.DirectSolver(assemble_jac=True)
示例#7
0
    def test_double_integrator_for_docs(self):
        import matplotlib.pyplot as plt
        import openmdao.api as om
        from openmdao.utils.assert_utils import assert_near_equal
        import dymos as dm
        from dymos.examples.plotting import plot_results
        from dymos.examples.double_integrator.double_integrator_ode import DoubleIntegratorODE

        # Initialize the problem and assign the driver
        p = om.Problem(model=om.Group())
        p.driver = om.pyOptSparseDriver()
        p.driver.options['optimizer'] = 'SLSQP'
        p.driver.declare_coloring()

        # Setup the trajectory and its phase
        traj = p.model.add_subsystem('traj', dm.Trajectory())

        transcription = dm.Radau(num_segments=30, order=3, compressed=False)

        phase = traj.add_phase(
            'phase0',
            dm.Phase(ode_class=DoubleIntegratorODE,
                     transcription=transcription))

        #
        # Set the options for our variables.
        #
        phase.set_time_options(fix_initial=True, fix_duration=True, units='s')
        phase.add_state('v',
                        fix_initial=True,
                        fix_final=True,
                        rate_source='u',
                        units='m/s')
        phase.add_state('x', fix_initial=True, rate_source='v', units='m')

        phase.add_control('u',
                          units='m/s**2',
                          scaler=0.01,
                          continuity=False,
                          rate_continuity=False,
                          rate2_continuity=False,
                          shape=(1, ),
                          lower=-1.0,
                          upper=1.0)

        #
        # Maximize distance travelled.
        #
        phase.add_objective('x', loc='final', scaler=-1)

        p.model.linear_solver = om.DirectSolver()

        #
        # Setup the problem and set our initial values.
        #
        p.setup(check=True)

        p['traj.phase0.t_initial'] = 0.0
        p['traj.phase0.t_duration'] = 1.0

        p['traj.phase0.states:x'] = phase.interpolate(ys=[0, 0.25],
                                                      nodes='state_input')
        p['traj.phase0.states:v'] = phase.interpolate(ys=[0, 0],
                                                      nodes='state_input')
        p['traj.phase0.controls:u'] = phase.interpolate(ys=[1, -1],
                                                        nodes='control_input')

        #
        # Solve the problem.
        #
        dm.run_problem(p)

        #
        # Verify that the results are correct.
        #
        x = p.get_val('traj.phase0.timeseries.states:x')
        v = p.get_val('traj.phase0.timeseries.states:v')

        assert_near_equal(x[0], 0.0, tolerance=1.0E-4)
        assert_near_equal(x[-1], 0.25, tolerance=1.0E-4)

        assert_near_equal(v[0], 0.0, tolerance=1.0E-4)
        assert_near_equal(v[-1], 0.0, tolerance=1.0E-4)

        #
        # Simulate the explicit solution and plot the results.
        #
        exp_out = traj.simulate()

        plot_results(
            [('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:x',
              'time (s)', 'x $(m)$'),
             ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:v',
              'time (s)', 'v $(m/s)$'),
             ('traj.phase0.timeseries.time',
              'traj.phase0.timeseries.controls:u', 'time (s)', 'u $(m/s^2)$')],
            title='Double Integrator Solution\nRadau Pseudospectral Method',
            p_sol=p,
            p_sim=exp_out)

        plt.show()
def main(a):
    prob = om.Problem()

    ivc = om.IndepVarComp()
    ivc.add_output("x", 2.0)
    ivc.add_output("y", 3.0)
    prob.model.add_subsystem("ivc", ivc, promotes=["*"])

    comp = make_component(julia.SimpleExplicit(a))
    prob.model.add_subsystem("square_it_comp0",
                             comp,
                             promotes_inputs=['x', 'y'],
                             promotes_outputs=[('z1', 'z1_0'), ('z2', 'z2_0')])

    comp = make_component(julia.SimpleExplicit(a + 1))
    prob.model.add_subsystem("square_it_comp1",
                             comp,
                             promotes_inputs=['x', 'y'],
                             promotes_outputs=[('z1', 'z1_1'), ('z2', 'z2_1')])

    comp = make_component(julia.SimpleExplicit(a + 2))
    prob.model.add_subsystem("square_it_comp2",
                             comp,
                             promotes_inputs=['x', 'y'],
                             promotes_outputs=[('z1', 'z1_2'), ('z2', 'z2_2')])

    comp = make_component(julia.SimpleImplicit(a))
    comp.linear_solver = om.DirectSolver(assemble_jac=True)
    comp.nonlinear_solver = om.NewtonSolver(solve_subsystems=True,
                                            iprint=0,
                                            err_on_non_converge=True)
    prob.model.add_subsystem("square_it_comp3",
                             comp,
                             promotes_inputs=["x", "y"],
                             promotes_outputs=[("z1", "z1_3"), ("z2", "z2_3")])

    comp = make_component(julia.SimpleImplicit(a + 1))
    comp.linear_solver = om.DirectSolver(assemble_jac=True)
    comp.nonlinear_solver = om.NewtonSolver(solve_subsystems=True,
                                            iprint=0,
                                            err_on_non_converge=True)
    prob.model.add_subsystem("square_it_comp4",
                             comp,
                             promotes_inputs=["x", "y"],
                             promotes_outputs=[("z1", "z1_4"), ("z2", "z2_4")])

    comp = make_component(julia.SimpleImplicit(a + 2))
    comp.linear_solver = om.DirectSolver(assemble_jac=True)
    comp.nonlinear_solver = om.NewtonSolver(solve_subsystems=True,
                                            iprint=0,
                                            err_on_non_converge=True)
    prob.model.add_subsystem("square_it_comp5",
                             comp,
                             promotes_inputs=["x", "y"],
                             promotes_outputs=[("z1", "z1_5"), ("z2", "z2_5")])

    prob.setup()
    prob.run_model()

    prob.get_val("z1_0")
    prob.get_val("z2_0")
    prob.get_val("z1_1")
    prob.get_val("z2_1")
    prob.get_val("z1_2")
    prob.get_val("z2_2")
    prob.compute_totals(of=["z1_0", "z2_0"], wrt=["x", "y"])
    prob.compute_totals(of=["z1_1", "z2_1"], wrt=["x", "y"])
    prob.compute_totals(of=["z1_2", "z2_2"], wrt=["x", "y"])
示例#9
0
    def test_control_rate2_path_constraint_gl(self):
        import openmdao.api as om
        from openmdao.utils.assert_utils import assert_near_equal
        import dymos as dm
        from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE

        p = om.Problem(model=om.Group())
        p.driver = om.ScipyOptimizeDriver()

        phase = dm.Phase(ode_class=BrachistochroneODE,
                         transcription=dm.GaussLobatto(num_segments=10,
                                                       order=5))

        p.model.add_subsystem('phase0', phase)

        phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(.5, 10))

        phase.add_state(
            'x',
            fix_initial=True,
            fix_final=True,
            rate_source=BrachistochroneODE.states['x']['rate_source'])
        phase.add_state(
            'y',
            fix_initial=True,
            fix_final=True,
            rate_source=BrachistochroneODE.states['y']['rate_source'])
        phase.add_state(
            'v',
            fix_initial=True,
            rate_source=BrachistochroneODE.states['v']['rate_source'])

        phase.add_control('theta',
                          units='deg',
                          rate_continuity=False,
                          lower=0.01,
                          upper=179.9)

        phase.add_parameter('g', units='m/s**2', opt=False, val=9.80665)

        # Minimize time at the end of the phase
        phase.add_objective('time', loc='final', scaler=10)

        phase.add_path_constraint('theta_rate2',
                                  lower=-200,
                                  upper=200,
                                  units='rad/s**2')

        p.model.linear_solver = om.DirectSolver()
        p.model.options['assembled_jac_type'] = 'csc'

        p.setup()

        p['phase0.t_initial'] = 0.0
        p['phase0.t_duration'] = 2.0

        p['phase0.states:x'] = phase.interpolate(ys=[0, 10],
                                                 nodes='state_input')
        p['phase0.states:y'] = phase.interpolate(ys=[10, 5],
                                                 nodes='state_input')
        p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9],
                                                 nodes='state_input')
        p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100.5],
                                                       nodes='control_input')

        # Solve for the optimal trajectory
        p.run_driver()

        # Test the results
        assert_near_equal(p.get_val('phase0.timeseries.time')[-1],
                          1.8016,
                          tolerance=1.0E-3)
示例#10
0
    def test_sellar_specify_linear_direct_solver(self):

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

        model.add_subsystem('px', om.IndepVarComp('x', 1.0), promotes=['x'])
        model.add_subsystem('pz',
                            om.IndepVarComp('z', np.array([5.0, 2.0])),
                            promotes=['z'])

        proms = [
            'x', 'z', 'y1', 'state_eq.y2_actual', 'state_eq.y2_command',
            'd1.y2', 'd2.y2'
        ]
        sub = model.add_subsystem('sub', om.Group(), promotes=proms)

        subgrp = sub.add_subsystem(
            'state_eq_group',
            om.Group(),
            promotes=['state_eq.y2_actual', 'state_eq.y2_command'])
        subgrp.linear_solver = om.ScipyKrylov()
        subgrp.add_subsystem('state_eq', StateConnection())

        sub.add_subsystem('d1',
                          SellarDis1withDerivatives(),
                          promotes=['x', 'z', 'y1'])
        sub.add_subsystem('d2',
                          SellarDis2withDerivatives(),
                          promotes=['z', 'y1'])

        model.connect('state_eq.y2_command', 'd1.y2')
        model.connect('d2.y2', 'state_eq.y2_actual')

        model.add_subsystem('obj_cmp',
                            om.ExecComp('obj = x**2 + z[1] + y1 + exp(-y2)',
                                        z=np.array([0.0, 0.0]),
                                        x=0.0,
                                        y1=0.0,
                                        y2=0.0),
                            promotes=['x', 'z', 'y1', 'obj'])
        model.connect('d2.y2', 'obj_cmp.y2')

        model.add_subsystem('con_cmp1',
                            om.ExecComp('con1 = 3.16 - y1'),
                            promotes=['con1', 'y1'])
        model.add_subsystem('con_cmp2',
                            om.ExecComp('con2 = y2 - 24.0'),
                            promotes=['con2'])
        model.connect('d2.y2', 'con_cmp2.y2')

        model.nonlinear_solver = om.NewtonSolver()

        # Use bad settings for this one so that problem doesn't converge.
        # That way, we test that we are really using Newton's Lin Solver
        # instead.
        sub.linear_solver = om.ScipyKrylov()
        sub.linear_solver.options['maxiter'] = 1

        # The good solver
        model.nonlinear_solver.linear_solver = om.DirectSolver()

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

        assert_rel_error(self, prob['y1'], 25.58830273, .00001)
        assert_rel_error(self, prob['state_eq.y2_command'], 12.05848819,
                         .00001)

        # Make sure we aren't iterating like crazy
        self.assertLess(model.nonlinear_solver._iter_count, 8)
        self.assertEqual(model.linear_solver._iter_count, 0)
示例#11
0
    def test_solve_subsystems_internals(self):
        # Here we test that this feature is doing what it should do by counting the
        # number of calls in various places.

        class CountNewton(om.NewtonSolver):
            """ This version of Newton also counts how many times it runs in total."""
            def __init__(self, **kwargs):
                super(CountNewton, self).__init__(**kwargs)
                self.total_count = 0

            def _single_iteration(self):
                super(CountNewton, self)._single_iteration()
                self.total_count += 1

        class CountDS(om.DirectSolver):
            """ This version of Newton also counts how many times it linearizes"""
            def __init__(self, **kwargs):
                super(CountDS, self).__init__(**kwargs)
                self.lin_count = 0

            def _linearize(self):
                super(CountDS, self)._linearize()
                self.lin_count += 1

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

        # each SubSellar group converges itself
        g1 = model.g1
        g1.nonlinear_solver = CountNewton()
        g1.nonlinear_solver.options['rtol'] = 1.0e-5
        g1.linear_solver = CountDS()  # used for derivatives

        g2 = model.g2
        g2.nonlinear_solver = CountNewton()
        g2.nonlinear_solver.options['rtol'] = 1.0e-5
        g2.linear_solver = om.DirectSolver()

        # Converge the outer loop with Gauss Seidel, with a looser tolerance.
        model.nonlinear_solver = om.NewtonSolver()
        model.linear_solver = om.ScipyKrylov()

        # Enfore behavior: max_sub_solves = 0 means we run once during init

        model.nonlinear_solver.options['maxiter'] = 5
        model.nonlinear_solver.options['solve_subsystems'] = True
        model.nonlinear_solver.options['max_sub_solves'] = 0
        prob.set_solver_print(level=0)

        prob.setup()
        prob.run_model()

        # Verifying subsolvers ran
        self.assertEqual(g1.nonlinear_solver.total_count, 2)
        self.assertEqual(g2.nonlinear_solver.total_count, 2)
        self.assertEqual(g1.linear_solver.lin_count, 2)

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

        # each SubSellar group converges itself
        g1 = model.g1
        g1.nonlinear_solver = CountNewton()
        g1.nonlinear_solver.options['rtol'] = 1.0e-5
        g1.linear_solver = CountDS()  # used for derivatives

        g2 = model.g2
        g2.nonlinear_solver = CountNewton()
        g2.nonlinear_solver.options['rtol'] = 1.0e-5
        g2.linear_solver = om.DirectSolver()

        # Converge the outer loop with Gauss Seidel, with a looser tolerance.
        model.nonlinear_solver = om.NewtonSolver()
        model.linear_solver = om.ScipyKrylov()

        # Enforce Behavior: baseline

        model.nonlinear_solver.options['maxiter'] = 5
        model.nonlinear_solver.options['solve_subsystems'] = True
        model.nonlinear_solver.options['max_sub_solves'] = 5
        prob.set_solver_print(level=0)

        prob.setup()
        prob.run_model()

        # Verifying subsolvers ran
        self.assertEqual(g1.nonlinear_solver.total_count, 5)
        self.assertEqual(g2.nonlinear_solver.total_count, 5)
        self.assertEqual(g1.linear_solver.lin_count, 5)

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

        # each SubSellar group converges itself
        g1 = model.g1
        g1.nonlinear_solver = CountNewton()
        g1.nonlinear_solver.options['rtol'] = 1.0e-5
        g1.linear_solver = CountDS()  # used for derivatives

        g2 = model.g2
        g2.nonlinear_solver = CountNewton()
        g2.nonlinear_solver.options['rtol'] = 1.0e-5
        g2.linear_solver = om.DirectSolver()

        # Converge the outer loop with Gauss Seidel, with a looser tolerance.
        model.nonlinear_solver = om.NewtonSolver()
        model.linear_solver = om.ScipyKrylov()

        # Enfore behavior: max_sub_solves = 1 means we run during init and first iteration of iter_execute

        model.nonlinear_solver.options['maxiter'] = 5
        model.nonlinear_solver.options['solve_subsystems'] = True
        model.nonlinear_solver.options['max_sub_solves'] = 1
        prob.set_solver_print(level=0)

        prob.setup()
        prob.run_model()

        # Verifying subsolvers ran
        self.assertEqual(g1.nonlinear_solver.total_count, 4)
        self.assertEqual(g2.nonlinear_solver.total_count, 4)
        self.assertEqual(g1.linear_solver.lin_count, 4)
    def test_brachistochrone_vector_boundary_constraints_radau_partial_indices(
            self):

        p = om.Problem(model=om.Group())
        p.driver = om.ScipyOptimizeDriver()
        p.driver.declare_coloring()

        phase = dm.Phase(ode_class=BrachistochroneVectorStatesODE,
                         transcription=dm.Radau(num_segments=20, order=3))

        p.model.add_subsystem('phase0', phase)

        phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10))

        phase.add_state(
            'pos',
            shape=(2, ),
            rate_source=BrachistochroneVectorStatesODE.states['pos']
            ['rate_source'],
            units=BrachistochroneVectorStatesODE.states['pos']['units'],
            fix_initial=True,
            fix_final=[True, False])
        phase.add_state(
            'v',
            rate_source=BrachistochroneVectorStatesODE.states['v']
            ['rate_source'],
            targets=BrachistochroneVectorStatesODE.states['v']['targets'],
            units=BrachistochroneVectorStatesODE.states['v']['units'],
            fix_initial=True,
            fix_final=False)

        phase.add_control(
            'theta',
            units='deg',
            targets=BrachistochroneVectorStatesODE.parameters['theta']
            ['targets'],
            rate_continuity=False,
            lower=0.01,
            upper=179.9)

        phase.add_design_parameter(
            'g',
            targets=BrachistochroneVectorStatesODE.parameters['g']['targets'],
            units='m/s**2',
            opt=False,
            val=9.80665)

        phase.add_boundary_constraint('pos',
                                      loc='final',
                                      equals=5,
                                      indices=[1])

        # Minimize time at the end of the phase
        phase.add_objective('time', loc='final', scaler=10)

        p.model.linear_solver = om.DirectSolver()
        p.setup(check=True, force_alloc_complex=True)

        p['phase0.t_initial'] = 0.0
        p['phase0.t_duration'] = 2.0

        pos0 = [0, 10]
        posf = [10, 5]

        p['phase0.states:pos'] = phase.interpolate(ys=[pos0, posf],
                                                   nodes='state_input')
        p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9],
                                                 nodes='state_input')
        p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100],
                                                       nodes='control_input')
        p['phase0.design_parameters:g'] = 9.80665

        p.run_driver()

        assert_rel_error(self,
                         p.get_val('phase0.time')[-1],
                         1.8016,
                         tolerance=1.0E-3)

        # Plot results
        if SHOW_PLOTS:
            p.run_driver()
            exp_out = phase.simulate(times_per_seg=20)

            fig, ax = plt.subplots()
            fig.suptitle('Brachistochrone Solution')

            x_imp = p.get_val('phase0.timeseries.states:pos')[:, 0]
            y_imp = p.get_val('phase0.timeseries.states:pos')[:, 1]

            x_exp = exp_out.get_val('phase0.timeseries.states:pos')[:, 0]
            y_exp = exp_out.get_val('phase0.timeseries.states:pos')[:, 1]

            ax.plot(x_imp, y_imp, 'ro', label='implicit')
            ax.plot(x_exp, y_exp, 'b-', label='explicit')

            ax.set_xlabel('x (m)')
            ax.set_ylabel('y (m)')
            ax.grid(True)
            ax.legend(loc='upper right')

            fig, ax = plt.subplots()
            fig.suptitle('Brachistochrone Solution')

            x_imp = p.get_val('phase0.timeseries.time')
            y_imp = p.get_val('phase0.timeseries.control_rates:theta_rate2')

            x_exp = exp_out.get_val('phase0.timeseries.time')
            y_exp = exp_out.get_val(
                'phase0.timeseries.control_rates:theta_rate2')

            ax.plot(x_imp, y_imp, 'ro', label='implicit')
            ax.plot(x_exp, y_exp, 'b-', label='explicit')

            ax.set_xlabel('time (s)')
            ax.set_ylabel('theta rate2 (rad/s**2)')
            ax.grid(True)
            ax.legend(loc='lower right')

            plt.show()

        return p
示例#13
0
    def setup(self):

        design = self.options['design']

        # NOTE: DEFAULT TABULAR thermo doesn't include WAR, so must use CEA here
        # (or build your own thermo tables)

        self.options['thermo_method'] = 'CEA'
        self.options['thermo_data'] = pyc.species_data.wet_air

        # Add engine elements
        self.add_subsystem('fc', pyc.FlightConditions(composition=pyc.CEA_AIR_COMPOSITION, 
                                                      reactant='Water',
                                                      mix_ratio_name='WAR')) 

        self.add_subsystem('inlet', pyc.Inlet())
        self.add_subsystem('comp', pyc.Compressor(map_data=pyc.AXI5),
                                    promotes_inputs=['Nmech'])

        self.add_subsystem('burner', pyc.Combustor(fuel_type='JP-7'))
        self.add_subsystem('turb', pyc.Turbine(map_data=pyc.LPT2269),
                                    promotes_inputs=['Nmech'])
        self.add_subsystem('nozz', pyc.Nozzle(nozzType='CD', lossCoef='Cv'))
        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
        self.pyc_connect_flow('fc.Fl_O', 'inlet.Fl_I', connect_w=False)
        self.pyc_connect_flow('inlet.Fl_O', 'comp.Fl_I')
        self.pyc_connect_flow('comp.Fl_O', 'burner.Fl_I')
        self.pyc_connect_flow('burner.Fl_O', 'turb.Fl_I')
        self.pyc_connect_flow('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.options['reraise_child_analysiserror'] = False
        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)

        super().setup()
    def test_brachistochrone_undecorated_ode_gl(self):
        import numpy as np
        import matplotlib
        matplotlib.use('Agg')
        import matplotlib.pyplot as plt
        import openmdao.api as om
        from openmdao.utils.assert_utils import assert_near_equal
        import dymos as dm

        p = om.Problem(model=om.Group())
        p.driver = om.ScipyOptimizeDriver()

        phase = dm.Phase(ode_class=BrachistochroneODE,
                         transcription=dm.GaussLobatto(num_segments=10))

        p.model.add_subsystem('phase0', phase)

        phase.set_time_options(initial_bounds=(0, 0),
                               duration_bounds=(.5, 10),
                               units='s')

        phase.add_state('x',
                        fix_initial=True,
                        fix_final=True,
                        rate_source='xdot',
                        units='m')
        phase.add_state('y',
                        fix_initial=True,
                        fix_final=True,
                        rate_source='ydot',
                        units='m')
        phase.add_state('v',
                        fix_initial=True,
                        rate_source='vdot',
                        targets=['v'],
                        units='m/s')

        phase.add_control('theta',
                          units='deg',
                          rate_continuity=False,
                          lower=0.01,
                          upper=179.9,
                          targets=['theta'])

        phase.add_parameter('g',
                            units='m/s**2',
                            opt=False,
                            val=9.80665,
                            targets=['g'])

        # Minimize time at the end of the phase
        phase.add_objective('time', loc='final', scaler=10)

        p.model.linear_solver = om.DirectSolver()

        p.setup()

        p['phase0.t_initial'] = 0.0
        p['phase0.t_duration'] = 2.0

        p['phase0.states:x'] = phase.interpolate(ys=[0, 10],
                                                 nodes='state_input')
        p['phase0.states:y'] = phase.interpolate(ys=[10, 5],
                                                 nodes='state_input')
        p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9],
                                                 nodes='state_input')
        p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100.5],
                                                       nodes='control_input')

        # Solve for the optimal trajectory
        p.run_driver()

        # Test the results
        assert_near_equal(p.get_val('phase0.timeseries.time')[-1],
                          1.8016,
                          tolerance=1.0E-3)
示例#15
0
def brachistochrone_min_time(transcription='gauss-lobatto',
                             num_segments=8,
                             transcription_order=3,
                             compressed=True,
                             optimizer='SLSQP'):
    p = om.Problem(model=om.Group())

    p.driver = om.pyOptSparseDriver()
    p.driver.options['optimizer'] = optimizer
    p.driver.declare_coloring()

    if transcription == 'gauss-lobatto':
        t = dm.GaussLobatto(num_segments=num_segments,
                            order=transcription_order,
                            compressed=compressed)
    elif transcription == 'radau-ps':
        t = dm.Radau(num_segments=num_segments,
                     order=transcription_order,
                     compressed=compressed)
    elif transcription == 'runge-kutta':
        t = dm.RungeKutta(num_segments=num_segments,
                          order=transcription_order,
                          compressed=compressed)

    phase = dm.Phase(ode_class=BrachistochroneODE, transcription=t)

    p.model.add_subsystem('phase0', phase)

    phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10))

    phase.add_state('x',
                    rate_source=BrachistochroneODE.states['x']['rate_source'],
                    units=BrachistochroneODE.states['x']['units'],
                    fix_initial=True,
                    fix_final=False,
                    solve_segments=False)
    phase.add_state('y',
                    rate_source=BrachistochroneODE.states['y']['rate_source'],
                    units=BrachistochroneODE.states['y']['units'],
                    fix_initial=True,
                    fix_final=False,
                    solve_segments=False)
    phase.add_state('v',
                    rate_source=BrachistochroneODE.states['v']['rate_source'],
                    targets=BrachistochroneODE.states['v']['targets'],
                    units=BrachistochroneODE.states['v']['units'],
                    fix_initial=True,
                    fix_final=False,
                    solve_segments=False)

    phase.add_control(
        'theta',
        targets=BrachistochroneODE.parameters['theta']['targets'],
        continuity=True,
        rate_continuity=True,
        units='deg',
        lower=0.01,
        upper=179.9)

    phase.add_input_parameter(
        'g',
        targets=BrachistochroneODE.parameters['g']['targets'],
        units='m/s**2',
        val=9.80665)

    phase.add_timeseries('timeseries2',
                         transcription=dm.Radau(num_segments=num_segments * 5,
                                                order=transcription_order,
                                                compressed=compressed),
                         subset='control_input')

    phase.add_boundary_constraint('x', loc='final', equals=10)
    phase.add_boundary_constraint('y', loc='final', equals=5)
    # Minimize time at the end of the phase
    phase.add_objective('time_phase', loc='final', scaler=10)

    p.model.linear_solver = om.DirectSolver()
    p.setup(check=['unconnected_inputs'])

    p['phase0.t_initial'] = 0.0
    p['phase0.t_duration'] = 2.0

    p['phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input')
    p['phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input')
    p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input')
    p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100],
                                                   nodes='control_input')
    p['phase0.input_parameters:g'] = 9.80665

    p.run_driver()

    # Plot results
    if SHOW_PLOTS:
        exp_out = phase.simulate()

        fig, ax = plt.subplots()
        fig.suptitle('Brachistochrone Solution')

        x_imp = p.get_val('phase0.timeseries.states:x')
        y_imp = p.get_val('phase0.timeseries.states:y')

        x_exp = exp_out.get_val('phase0.timeseries.states:x')
        y_exp = exp_out.get_val('phase0.timeseries.states:y')

        ax.plot(x_imp, y_imp, 'ro', label='implicit')
        ax.plot(x_exp, y_exp, 'b-', label='explicit')

        ax.set_xlabel('x (m)')
        ax.set_ylabel('y (m)')
        ax.grid(True)
        ax.legend(loc='upper right')

        fig, ax = plt.subplots()
        fig.suptitle('Brachistochrone Solution')

        x_imp = p.get_val('phase0.timeseries.time_phase')
        y_imp = p.get_val('phase0.timeseries.controls:theta')

        x_exp = exp_out.get_val('phase0.timeseries.time_phase')
        y_exp = exp_out.get_val('phase0.timeseries.controls:theta')

        ax.plot(x_imp, y_imp, 'ro', label='implicit')
        ax.plot(x_exp, y_exp, 'b-', label='explicit')

        ax.set_xlabel('time (s)')
        ax.set_ylabel('theta (rad)')
        ax.grid(True)
        ax.legend(loc='lower right')

        plt.show()

    return p
示例#16
0
    def test_brachistochrone_integrated_parameter_radau_ps(self):
        import numpy as np
        import openmdao.api as om
        from openmdao.utils.assert_utils import assert_near_equal
        import dymos as dm

        p = om.Problem(model=om.Group())
        p.driver = om.pyOptSparseDriver()
        p.driver.options['optimizer'] = 'SLSQP'
        p.driver.declare_coloring()

        phase = dm.Phase(ode_class=BrachistochroneODE,
                         transcription=dm.Radau(num_segments=10))

        p.model.add_subsystem('phase0', phase)

        phase.set_time_options(initial_bounds=(0, 0),
                               duration_bounds=(.5, 10),
                               units='s')

        phase.add_state('x',
                        fix_initial=True,
                        fix_final=True,
                        rate_source='xdot',
                        units='m')
        phase.add_state('y',
                        fix_initial=True,
                        fix_final=True,
                        rate_source='ydot',
                        units='m')
        phase.add_state('v', fix_initial=True, rate_source='vdot', units='m/s')
        phase.add_state('theta',
                        fix_initial=False,
                        rate_source='theta_dot',
                        lower=1E-3)

        # theta_dot has no target, therefore we need to explicitly set the units and shape.
        phase.add_parameter('theta_dot',
                            units='deg/s',
                            shape=(1, ),
                            opt=True,
                            lower=0,
                            upper=100)

        phase.add_parameter('g', units='m/s**2', opt=False, val=9.80665)

        # Minimize time at the end of the phase
        phase.add_objective('time', loc='final', scaler=10)

        p.model.linear_solver = om.DirectSolver()

        p.setup()

        p['phase0.t_initial'] = 0.0
        p['phase0.t_duration'] = 2.0

        p['phase0.states:x'] = phase.interpolate(ys=[0, 10],
                                                 nodes='state_input')
        p['phase0.states:y'] = phase.interpolate(ys=[10, 5],
                                                 nodes='state_input')
        p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9],
                                                 nodes='state_input')
        p['phase0.states:theta'] = np.radians(
            phase.interpolate(ys=[0.05, 100.0], nodes='state_input'))
        p['phase0.parameters:theta_dot'] = 60.0

        # Solve for the optimal trajectory
        dm.run_problem(p, refine_iteration_limit=5)

        # Test the results
        assert_near_equal(p.get_val('phase0.timeseries.time')[-1],
                          1.8016,
                          tolerance=1.0E-3)

        sim_out = phase.simulate(times_per_seg=20)

        t_sol = p.get_val('phase0.timeseries.time')
        x_sol = p.get_val('phase0.timeseries.states:x')
        y_sol = p.get_val('phase0.timeseries.states:y')
        v_sol = p.get_val('phase0.timeseries.states:v')
        theta_sol = p.get_val('phase0.timeseries.states:theta')

        t_sim = sim_out.get_val('phase0.timeseries.time')
        x_sim = sim_out.get_val('phase0.timeseries.states:x')
        y_sim = sim_out.get_val('phase0.timeseries.states:y')
        v_sim = sim_out.get_val('phase0.timeseries.states:v')
        theta_sim = sim_out.get_val('phase0.timeseries.states:theta')

        assert_timeseries_near_equal(t_sol,
                                     x_sol,
                                     t_sim,
                                     x_sim,
                                     tolerance=1.0E-3,
                                     num_points=10)
        assert_timeseries_near_equal(t_sol,
                                     y_sol,
                                     t_sim,
                                     y_sim,
                                     tolerance=1.0E-3,
                                     num_points=10)
        assert_timeseries_near_equal(t_sol,
                                     v_sol,
                                     t_sim,
                                     v_sim,
                                     tolerance=1.0E-3,
                                     num_points=10)
        assert_timeseries_near_equal(t_sol,
                                     theta_sol,
                                     t_sim,
                                     theta_sim,
                                     tolerance=1.0E-3,
                                     num_points=10)
示例#17
0
    def test_radau(self):
        p = om.Problem(model=om.Group())

        p.driver = om.pyOptSparseDriver()
        p.driver.options['optimizer'] = 'SLSQP'
        p.driver.declare_coloring()

        t = dm.Radau(num_segments=20,
                     order=[3, 5]*10,
                     compressed=True)

        phase = dm.Phase(ode_class=BrachistochroneODE, transcription=t)

        p.model.add_subsystem('phase0', phase)

        phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10))

        phase.add_state('x', rate_source=BrachistochroneODE.states['x']['rate_source'],
                        units=BrachistochroneODE.states['x']['units'],
                        fix_initial=True, fix_final=False, solve_segments=False)
        phase.add_state('y', rate_source=BrachistochroneODE.states['y']['rate_source'],
                        units=BrachistochroneODE.states['y']['units'],
                        fix_initial=True, fix_final=False, solve_segments=False)
        phase.add_state('v', rate_source=BrachistochroneODE.states['v']['rate_source'],
                        targets=BrachistochroneODE.states['v']['targets'],
                        units=BrachistochroneODE.states['v']['units'],
                        fix_initial=True, fix_final=False, solve_segments=False)

        phase.add_control('theta', targets=BrachistochroneODE.parameters['theta']['targets'],
                          continuity=True, rate_continuity=True,
                          units='deg', lower=0.01, upper=179.9)

        phase.add_parameter('g', targets=BrachistochroneODE.parameters['g']['targets'],
                            units='m/s**2', val=9.80665)

        phase.add_boundary_constraint('x', loc='final', equals=10)
        phase.add_boundary_constraint('y', loc='final', equals=5)
        # Minimize time at the end of the phase
        phase.add_objective('time_phase', loc='final', scaler=10)

        p.model.linear_solver = om.DirectSolver()
        p.setup(check=True)

        p['phase0.t_initial'] = 0.0
        p['phase0.t_duration'] = 2.0

        p['phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input')
        p['phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input')
        p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input')
        p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100], nodes='control_input')
        p['phase0.parameters:g'] = 9.80665

        p.run_driver()

        exp_out = phase.simulate()

        t_initial = p.get_val('phase0.timeseries.time')[0]
        tf = p.get_val('phase0.timeseries.time')[-1]

        x0 = p.get_val('phase0.timeseries.states:x')[0]
        xf = p.get_val('phase0.timeseries.states:x')[-1]

        y0 = p.get_val('phase0.timeseries.states:y')[0]
        yf = p.get_val('phase0.timeseries.states:y')[-1]

        v0 = p.get_val('phase0.timeseries.states:v')[0]
        vf = p.get_val('phase0.timeseries.states:v')[-1]

        g = p.get_val('phase0.timeseries.parameters:g')[0]

        thetaf = exp_out.get_val('phase0.timeseries.controls:theta')[-1]

        assert_almost_equal(t_initial, 0.0)
        assert_almost_equal(x0, 0.0)
        assert_almost_equal(y0, 10.0)
        assert_almost_equal(v0, 0.0)

        assert_almost_equal(tf, 1.8016, decimal=3)
        assert_almost_equal(xf, 10.0, decimal=3)
        assert_almost_equal(yf, 5.0, decimal=3)
        assert_almost_equal(vf, 9.902, decimal=3)
        assert_almost_equal(g, 9.80665, decimal=3)

        assert_almost_equal(thetaf, 100.12, decimal=0)
示例#18
0
    def test_simulate_array_param(self):
        #
        # Initialize the Problem and the optimization driver
        #
        p = om.Problem(model=om.Group())
        p.driver = om.ScipyOptimizeDriver()
        p.driver.declare_coloring()

        #
        # Create a trajectory and add a phase to it
        #
        traj = p.model.add_subsystem('traj', dm.Trajectory())

        phase = traj.add_phase(
            'phase0',
            dm.Phase(ode_class=BrachistochroneODE,
                     transcription=dm.GaussLobatto(num_segments=10)))

        #
        # Set the variables
        #
        phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10))

        phase.add_state('x',
                        fix_initial=True,
                        fix_final=True,
                        rate_source='xdot')

        phase.add_state('y',
                        fix_initial=True,
                        fix_final=True,
                        rate_source='ydot')

        phase.add_state('v',
                        fix_initial=True,
                        fix_final=False,
                        rate_source='vdot')

        phase.add_control('theta',
                          continuity=True,
                          rate_continuity=True,
                          units='deg',
                          lower=0.01,
                          upper=179.9)

        phase.add_parameter('g', units='m/s**2', val=9.80665)
        phase.add_parameter('array',
                            units=None,
                            shape=(10, ),
                            static_target=True)

        # dummy array of data
        indeps = p.model.add_subsystem('indeps',
                                       om.IndepVarComp(),
                                       promotes=['*'])
        indeps.add_output('array', np.linspace(1, 10, 10), units=None)
        # add dummy array as a parameter and connect it
        p.model.connect('array', 'traj.phase0.parameters:array')

        #
        # Minimize time at the end of the phase
        #
        phase.add_objective('time', loc='final', scaler=10)

        p.model.linear_solver = om.DirectSolver()

        #
        # Setup the Problem
        #
        p.setup()

        #
        # Set the initial values
        #
        p['traj.phase0.t_initial'] = 0.0
        p['traj.phase0.t_duration'] = 2.0

        p['traj.phase0.states:x'] = phase.interp('x', [0, 10])
        p['traj.phase0.states:y'] = phase.interp('y', [10, 5])
        p['traj.phase0.states:v'] = phase.interp('v', [0, 9.9])
        p['traj.phase0.controls:theta'] = phase.interp('theta', [5, 100.5])

        #
        # Solve for the optimal trajectory
        #
        dm.run_problem(p, simulate=True)

        # Test the results
        sol_results = om.CaseReader('dymos_solution.db').get_case('final')
        sim_results = om.CaseReader('dymos_solution.db').get_case('final')

        sol = sol_results.get_val('traj.phase0.timeseries.parameters:array')
        sim = sim_results.get_val('traj.phase0.timeseries.parameters:array')

        assert_near_equal(sol - sim, np.zeros_like(sol))

        # Test that the parameter is available in the solution and simulation files
        sol = sol_results.get_val('traj.phase0.parameters:array')
        sim = sim_results.get_val('traj.phase0.parameters:array')

        assert_near_equal(sol - sim, np.zeros_like(sol))
    def test_connect_control_to_parameter(self):
        """ Test that the final value of a control in one phase can be connected as the value
        of a parameter in a subsequent phase. """
        import openmdao.api as om
        from openmdao.utils.assert_utils import assert_near_equal

        import dymos as dm
        from dymos.examples.cannonball.size_comp import CannonballSizeComp
        from dymos.examples.cannonball.cannonball_phase import CannonballPhase

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

        p.driver = om.pyOptSparseDriver()
        p.driver.options['optimizer'] = 'SLSQP'
        p.driver.declare_coloring()

        external_params = p.model.add_subsystem('external_params',
                                                om.IndepVarComp())

        external_params.add_output('radius', val=0.10, units='m')
        external_params.add_output('dens', val=7.87, units='g/cm**3')

        external_params.add_design_var('radius',
                                       lower=0.01,
                                       upper=0.10,
                                       ref0=0.01,
                                       ref=0.10)

        p.model.add_subsystem('size_comp', CannonballSizeComp())

        traj = p.model.add_subsystem('traj', dm.Trajectory())

        transcription = dm.Radau(num_segments=5, order=3, compressed=True)
        ascent = CannonballPhase(transcription=transcription)

        ascent = traj.add_phase('ascent', ascent)

        # All initial states except flight path angle are fixed
        # Final flight path angle is fixed (we will set it to zero so that the phase ends at apogee)
        ascent.set_time_options(fix_initial=True,
                                duration_bounds=(1, 100),
                                duration_ref=100,
                                units='s')
        ascent.set_state_options('r', fix_initial=True, fix_final=False)
        ascent.set_state_options('h', fix_initial=True, fix_final=False)
        ascent.set_state_options('gam', fix_initial=False, fix_final=True)
        ascent.set_state_options('v', fix_initial=False, fix_final=False)

        ascent.add_parameter('S', targets=['aero.S'], units='m**2')
        ascent.add_parameter('mass',
                             targets=['eom.m', 'kinetic_energy.m'],
                             units='kg')

        ascent.add_control('CD', targets=['aero.CD'], opt=False, val=0.05)

        # Limit the muzzle energy
        ascent.add_boundary_constraint('kinetic_energy.ke',
                                       loc='initial',
                                       upper=400000,
                                       lower=0,
                                       ref=100000)

        # Second Phase (descent)
        transcription = dm.GaussLobatto(num_segments=5,
                                        order=3,
                                        compressed=True)
        descent = CannonballPhase(transcription=transcription)

        traj.add_phase('descent', descent)

        # All initial states and time are free (they will be linked to the final states of ascent.
        # Final altitude is fixed (we will set it to zero so that the phase ends at ground impact)
        descent.set_time_options(initial_bounds=(.5, 100),
                                 duration_bounds=(.5, 100),
                                 duration_ref=100,
                                 units='s')
        descent.add_state('r', )
        descent.add_state('h', fix_initial=False, fix_final=True)
        descent.add_state('gam', fix_initial=False, fix_final=False)
        descent.add_state('v', fix_initial=False, fix_final=False)

        descent.add_parameter('S', targets=['aero.S'], units='m**2')
        descent.add_parameter('mass',
                              targets=['eom.m', 'kinetic_energy.m'],
                              units='kg')
        descent.add_parameter('CD', targets=['aero.CD'], val=0.01)

        descent.add_objective('r', loc='final', scaler=-1.0)

        # Add internally-managed design parameters to the trajectory.
        traj.add_parameter('CL',
                           targets={
                               'ascent': ['aero.CL'],
                               'descent': ['aero.CL']
                           },
                           val=0.0,
                           units=None,
                           opt=False)
        traj.add_parameter('T',
                           targets={
                               'ascent': ['eom.T'],
                               'descent': ['eom.T']
                           },
                           val=0.0,
                           units='N',
                           opt=False)
        traj.add_parameter('alpha',
                           targets={
                               'ascent': ['eom.alpha'],
                               'descent': ['eom.alpha']
                           },
                           val=0.0,
                           units='deg',
                           opt=False)

        # Add externally-provided design parameters to the trajectory.
        # In this case, we connect 'm' to pre-existing input parameters named 'mass' in each phase.
        traj.add_parameter('m',
                           units='kg',
                           val=1.0,
                           targets={
                               'ascent': 'mass',
                               'descent': 'mass'
                           })

        # In this case, by omitting targets, we're connecting these parameters to parameters
        # with the same name in each phase.
        traj.add_parameter('S', units='m**2', val=0.005)

        # Link Phases (link time and all state variables)
        traj.link_phases(phases=['ascent', 'descent'], vars=['*'])

        # Issue Connections
        p.model.connect('external_params.radius', 'size_comp.radius')
        p.model.connect('external_params.dens', 'size_comp.dens')

        p.model.connect('size_comp.mass', 'traj.parameters:m')
        p.model.connect('size_comp.S', 'traj.parameters:S')

        traj.connect('ascent.timeseries.controls:CD',
                     'descent.parameters:CD',
                     src_indices=[-1])

        # A linear solver at the top level can improve performance.
        p.model.linear_solver = om.DirectSolver()

        # Finish Problem Setup
        p.setup()

        # Set Initial Guesses
        p.set_val('external_params.radius', 0.05, units='m')
        p.set_val('external_params.dens', 7.87, units='g/cm**3')

        p.set_val('traj.ascent.controls:CD', 0.5)
        p.set_val('traj.parameters:CL', 0.0)
        p.set_val('traj.parameters:T', 0.0)

        p.set_val('traj.ascent.t_initial', 0.0)
        p.set_val('traj.ascent.t_duration', 10.0)

        p.set_val('traj.ascent.states:r',
                  ascent.interpolate(ys=[0, 100], nodes='state_input'))
        p.set_val('traj.ascent.states:h',
                  ascent.interpolate(ys=[0, 100], nodes='state_input'))
        p.set_val('traj.ascent.states:v',
                  ascent.interpolate(ys=[200, 150], nodes='state_input'))
        p.set_val('traj.ascent.states:gam',
                  ascent.interpolate(ys=[25, 0], nodes='state_input'),
                  units='deg')

        p.set_val('traj.descent.t_initial', 10.0)
        p.set_val('traj.descent.t_duration', 10.0)

        p.set_val('traj.descent.states:r',
                  descent.interpolate(ys=[100, 200], nodes='state_input'))
        p.set_val('traj.descent.states:h',
                  descent.interpolate(ys=[100, 0], nodes='state_input'))
        p.set_val('traj.descent.states:v',
                  descent.interpolate(ys=[150, 200], nodes='state_input'))
        p.set_val('traj.descent.states:gam',
                  descent.interpolate(ys=[0, -45], nodes='state_input'),
                  units='deg')

        dm.run_problem(p, simulate=True)

        assert_near_equal(p.get_val('traj.descent.states:r')[-1],
                          3183.25,
                          tolerance=1.0E-2)
        assert_near_equal(
            p.get_val('traj.ascent.timeseries.controls:CD')[-1],
            p.get_val('traj.descent.timeseries.parameters:CD')[0])
示例#20
0
def flying_robot_direct_collocation(transcription='gauss-lobatto',
                                    compressed=True):

    p = om.Problem(model=om.Group())
    p.driver = om.pyOptSparseDriver()
    p.driver.options['optimizer'] = 'SLSQP'
    p.driver.declare_coloring()

    if transcription == 'gauss-lobatto':
        t = dm.GaussLobatto(num_segments=8, order=5, compressed=compressed)
    elif transcription == "radau-ps":
        t = dm.Radau(num_segments=8, order=5, compressed=compressed)
    else:
        raise ValueError('invalid transcription')

    traj = p.model.add_subsystem('traj', dm.Trajectory())

    phase = traj.add_phase('phase0',
                           dm.Phase(ode_class=FlyingRobotODE, transcription=t))

    phase.set_time_options(fix_initial=True,
                           fix_duration=False,
                           duration_bounds=(0.1, 1E4),
                           units='s')

    phase.add_state('x',
                    shape=(2, ),
                    fix_initial=True,
                    fix_final=True,
                    rate_source='v',
                    units='m')
    phase.add_state('v',
                    shape=(2, ),
                    fix_initial=True,
                    fix_final=True,
                    rate_source='u',
                    units='m/s')
    phase.add_state('J',
                    fix_initial=True,
                    fix_final=False,
                    rate_source='u_mag2',
                    units='m**2/s**3')

    phase.add_control('u',
                      units='m/s**2',
                      shape=(2, ),
                      scaler=0.01,
                      continuity=False,
                      rate_continuity=False,
                      rate2_continuity=False,
                      lower=-1,
                      upper=1)

    # Minimize the control effort
    phase.add_objective('time', loc='final')

    p.model.linear_solver = om.DirectSolver()

    p.setup(check=True)

    p['traj.phase0.t_initial'] = 0.0
    p['traj.phase0.t_duration'] = 1.0

    p['traj.phase0.states:x'] = phase.interp('x',
                                             [[0.0, 0.0], [-100.0, 100.0]])
    p['traj.phase0.states:v'] = phase.interp('v', [[0.0, 0.0], [0.0, 0.0]])
    p['traj.phase0.controls:u'] = phase.interp('u', [[1, 1], [-1, -1]])

    p.run_driver()

    return p
示例#21
0
文件: N3_MDP.py 项目: will214/pyCycle
newton.options['iprint'] = 2
newton.options['maxiter'] = 20
newton.options['solve_subsystems'] = True
newton.options['max_sub_solves'] = 10
newton.options['err_on_non_converge'] = True
newton.options['reraise_child_analysiserror'] = False
# newton.linesearch =  om.ArmijoGoldsteinLS()
newton.linesearch =  om.BoundsEnforceLS()
# newton.linesearch.options['maxiter'] = 2
newton.linesearch.options['bound_enforcement'] = 'scalar'
# newton.linesearch.options['print_bound_enforce'] = True
newton.linesearch.options['iprint'] = -1
# newton.linesearch.options['print_bound_enforce'] = False
# newton.linesearch.options['alpha'] = 0.5

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


# setup the optimization
prob.driver = om.pyOptSparseDriver()
prob.driver.options['optimizer'] = 'SNOPT'
prob.driver.options['debug_print'] = ['desvars', 'nl_cons', 'objs']
prob.driver.opt_settings={'Major step limit': 0.05}

prob.model.add_design_var('fan:PRdes', lower=1.20, upper=1.4)
prob.model.add_design_var('lpc:PRdes', lower=2.0, upper=4.0)
prob.model.add_design_var('OPR', lower=40.0, upper=70.0, ref0=40.0, ref=70.0)
prob.model.add_design_var('RTO:T4max', lower=3000.0, upper=3600.0, ref0=3000.0, ref=3600.0)
prob.model.add_design_var('CRZ:VjetRatio', lower=1.35, upper=1.45, ref0=1.35, ref=1.45)
prob.model.add_design_var('TR', lower=0.5, upper=0.95, ref0=0.5, ref=0.95)
示例#22
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,
                                          map_extrap=True),
                           promotes_inputs=[('Nmech', 'HP_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,
                                       map_extrap=True),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem('pt',
                           pyc.Turbine(map_data=pyc.LPT2269,
                                       design=design,
                                       thermo_data=thermo_spec,
                                       elements=pyc.AIR_FUEL_MIX,
                                       map_extrap=True),
                           promotes_inputs=[('Nmech', 'LP_Nmech')])
        self.add_subsystem(
            'nozz',
            pyc.Nozzle(nozzType='CV',
                       lossCoef='Cv',
                       thermo_data=thermo_spec,
                       elements=pyc.AIR_FUEL_MIX))
        self.add_subsystem('HP_shaft',
                           pyc.Shaft(num_ports=2),
                           promotes_inputs=[('Nmech', 'HP_Nmech')])
        self.add_subsystem('LP_shaft',
                           pyc.Shaft(num_ports=1),
                           promotes_inputs=[('Nmech', 'LP_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', 'pt.Fl_I')
        pyc.connect_flow(self, 'pt.Fl_O', 'nozz.Fl_I')

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

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

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

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

            balance.add_balance('W', val=27.0, units='lbm/s', eq_units=None)
            self.connect('balance.W', 'inlet.Fl_I:stat:W')
            self.connect('nozz.PR', 'balance.lhs:W')

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

            balance.add_balance('turb_PR',
                                val=3.0,
                                lower=1.001,
                                upper=8,
                                eq_units='hp',
                                rhs_val=0.)
            self.connect('balance.turb_PR', 'turb.PR')
            self.connect('HP_shaft.pwr_net', 'balance.lhs:turb_PR')

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

        else:

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

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

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

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

        newton = self.nonlinear_solver = 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 = om.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)
示例#23
0
    def test_control_rate2_boundary_constraint_gl(self):
        p = om.Problem(model=om.Group())

        p.driver = om.ScipyOptimizeDriver()

        p.driver.declare_coloring()

        phase = dm.Phase(ode_class=BrachistochroneODE,
                         transcription=dm.GaussLobatto(num_segments=20,
                                                       order=3,
                                                       compressed=True))

        p.model.add_subsystem('phase0', phase)

        phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10))

        phase.add_state('x', fix_initial=True, fix_final=False)

        phase.add_state('y', fix_initial=True, fix_final=False)

        phase.add_state('v', fix_initial=True, fix_final=False)

        phase.add_control('theta',
                          continuity=True,
                          rate_continuity=True,
                          rate2_continuity=True,
                          units='deg',
                          lower=0.01,
                          upper=179.9)

        phase.add_parameter('g', opt=False, units='m/s**2', val=9.80665)

        phase.add_boundary_constraint('theta_rate2',
                                      loc='final',
                                      equals=0.0,
                                      units='deg/s**2')

        # Minimize time at the end of the phase
        phase.add_objective('time')

        p.model.linear_solver = om.DirectSolver()
        p.setup(check=True)

        p['phase0.t_initial'] = 0.0
        p['phase0.t_duration'] = 2.0

        p['phase0.states:x'] = phase.interp('x', [0, 10])
        p['phase0.states:y'] = phase.interp('y', [10, 5])
        p['phase0.states:v'] = phase.interp('v', [0, 9.9])
        p['phase0.controls:theta'] = phase.interp('theta', [5, 100])
        p['phase0.parameters:g'] = 8

        p.run_driver()

        plt.plot(p.get_val('phase0.timeseries.states:x'),
                 p.get_val('phase0.timeseries.states:y'), 'ko')

        plt.figure()

        plt.plot(p.get_val('phase0.timeseries.time'),
                 p.get_val('phase0.timeseries.controls:theta'), 'ro')

        plt.plot(p.get_val('phase0.timeseries.time'),
                 p.get_val('phase0.timeseries.control_rates:theta_rate'), 'bo')

        plt.plot(p.get_val('phase0.timeseries.time'),
                 p.get_val('phase0.timeseries.control_rates:theta_rate2'),
                 'go')
        plt.show()

        assert_near_equal(
            p.get_val('phase0.timeseries.control_rates:theta_rate2')[-1],
            0,
            tolerance=1.0E-6)
示例#24
0
def min_time_climb(optimizer='SLSQP',
                   num_seg=3,
                   transcription='gauss-lobatto',
                   transcription_order=3,
                   force_alloc_complex=False):

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

    p.driver = om.pyOptSparseDriver()
    p.driver.options['optimizer'] = optimizer
    p.driver.declare_coloring()

    if optimizer == 'SNOPT':
        p.driver.opt_settings['Major iterations limit'] = 1000
        p.driver.opt_settings['iSumm'] = 6
        p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6
        p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6
        p.driver.opt_settings['Function precision'] = 1.0E-12
        p.driver.opt_settings['Linesearch tolerance'] = 0.1
        p.driver.opt_settings['Major step limit'] = 0.5

    t = {
        'gauss-lobatto':
        dm.GaussLobatto(num_segments=num_seg, order=transcription_order),
        'radau-ps':
        dm.Radau(num_segments=num_seg, order=transcription_order)
    }

    traj = dm.Trajectory()

    phase = dm.Phase(ode_class=_TestODE, transcription=t[transcription])
    traj.add_phase('phase0', phase)

    p.model.add_subsystem('traj', traj)

    phase.set_time_options(fix_initial=True,
                           duration_bounds=(50, 400),
                           duration_ref=100.0)

    phase.add_state('r',
                    fix_initial=True,
                    lower=0,
                    upper=1.0E6,
                    ref=1.0E3,
                    defect_ref=1.0E3,
                    units='m',
                    rate_source='flight_dynamics.r_dot')

    phase.add_state('h',
                    fix_initial=True,
                    lower=0,
                    upper=20000.0,
                    ref=1.0E2,
                    defect_ref=1.0E2,
                    units='m',
                    rate_source='flight_dynamics.h_dot',
                    targets=['h'])

    phase.add_state('v',
                    fix_initial=True,
                    lower=10.0,
                    ref=1.0E2,
                    defect_ref=1.0E2,
                    units='m/s',
                    rate_source='flight_dynamics.v_dot',
                    targets=['v'])

    phase.add_state('gam',
                    fix_initial=True,
                    lower=-1.5,
                    upper=1.5,
                    ref=1.0,
                    defect_ref=1.0,
                    units='rad',
                    rate_source='flight_dynamics.gam_dot',
                    targets=['gam'])

    phase.add_state('m',
                    fix_initial=True,
                    lower=10.0,
                    upper=1.0E5,
                    ref=1.0E3,
                    defect_ref=1.0E3,
                    units='kg',
                    rate_source='prop.m_dot',
                    targets=['m'])

    phase.add_control('alpha',
                      units='deg',
                      lower=-8.0,
                      upper=8.0,
                      scaler=1.0,
                      rate_continuity=True,
                      rate_continuity_scaler=100.0,
                      rate2_continuity=False,
                      targets=['alpha'])

    phase.add_parameter('S',
                        val=49.2386,
                        units='m**2',
                        opt=False,
                        targets=['S'])
    phase.add_parameter('Isp',
                        val=1600.0,
                        units='s',
                        opt=False,
                        targets=['Isp'])
    phase.add_parameter('throttle', val=1.0, opt=False, targets=['throttle'])
    phase.add_parameter('test',
                        val=40 * [1],
                        opt=False,
                        static_target=True,
                        targets=['test'])

    phase.add_boundary_constraint('h',
                                  loc='final',
                                  equals=20000,
                                  scaler=1.0E-3)
    phase.add_boundary_constraint('aero.mach', loc='final', equals=1.0)
    phase.add_boundary_constraint('gam', loc='final', equals=0.0)

    phase.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000)
    phase.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8)

    # Unnecessary but included to test capability
    phase.add_path_constraint(name='alpha', lower=-8, upper=8, units='deg')

    # Minimize time at the end of the phase
    phase.add_objective('time', loc='final', ref=1.0)

    # test mixing wildcard ODE variable expansion and unit overrides
    phase.add_timeseries_output(['aero.*', 'prop.thrust', 'prop.m_dot'],
                                units={
                                    'aero.f_lift': 'lbf',
                                    'prop.thrust': 'lbf'
                                })

    phase.set_refine_options(max_order=5)

    p.model.linear_solver = om.DirectSolver()

    p.setup(check=True, force_alloc_complex=force_alloc_complex)

    p['traj.phase0.t_initial'] = 0.0
    p['traj.phase0.t_duration'] = 300.0

    p['traj.phase0.states:r'] = phase.interp('r', [0.0, 111319.54])
    p['traj.phase0.states:h'] = phase.interp('h', [100.0, 20000.0])
    p['traj.phase0.states:v'] = phase.interp('v', [135.964, 283.159])
    p['traj.phase0.states:gam'] = phase.interp('gam', [0.0, 0.0])
    p['traj.phase0.states:m'] = phase.interp('m', [19030.468, 16841.431])
    p['traj.phase0.controls:alpha'] = phase.interp('alpha', [0.0, 0.0])

    dm.run_problem(p, refine_iteration_limit=1)

    return p
示例#25
0
    def test_propeller_example(self):
        # Example from the tutorial in the CCBlade documentation.

        num_nodes = 1
        turbine = False

        Rhub = np.array([0.5 * 0.0254]).reshape((1, 1))
        Rtip = np.array([3.0 * 0.0254]).reshape((1, 1))
        num_blades = 2
        precone = np.array([0.0]).reshape((1, 1))

        r = 0.0254 * np.array([
            0.7526, 0.7928, 0.8329, 0.8731, 0.9132, 0.9586, 1.0332, 1.1128,
            1.1925, 1.2722, 1.3519, 1.4316, 1.5114, 1.5911, 1.6708, 1.7505,
            1.8302, 1.9099, 1.9896, 2.0693, 2.1490, 2.2287, 2.3084, 2.3881,
            2.4678, 2.5475, 2.6273, 2.7070, 2.7867, 2.8661, 2.9410
        ]).reshape(1, -1)
        num_radial = r.shape[-1]

        chord = 0.0254 * np.array([
            0.6270, 0.6255, 0.6231, 0.6199, 0.6165, 0.6125, 0.6054, 0.5973,
            0.5887, 0.5794, 0.5695, 0.5590, 0.5479, 0.5362, 0.5240, 0.5111,
            0.4977, 0.4836, 0.4689, 0.4537, 0.4379, 0.4214, 0.4044, 0.3867,
            0.3685, 0.3497, 0.3303, 0.3103, 0.2897, 0.2618, 0.1920
        ]).reshape((1, num_radial))

        theta = np.pi / 180.0 * np.array([
            40.2273, 38.7657, 37.3913, 36.0981, 34.8803, 33.5899, 31.6400,
            29.7730, 28.0952, 26.5833, 25.2155, 23.9736, 22.8421, 21.8075,
            20.8586, 19.9855, 19.1800, 18.4347, 17.7434, 17.1005, 16.5013,
            15.9417, 15.4179, 14.9266, 14.4650, 14.0306, 13.6210, 13.2343,
            12.8685, 12.5233, 12.2138
        ]).reshape((1, num_radial))

        rho = np.array([1.225]).reshape((num_nodes, 1))
        Vinf = np.array([10.0]).reshape((num_nodes, 1))
        omega = np.array([8000.0 * (2 * np.pi / 60.0)]).reshape((num_nodes, 1))

        Vy = omega * r * np.cos(precone)
        Vx = np.tile(Vinf * np.cos(precone), (1, num_radial))
        mu = np.array([1.]).reshape((num_nodes, 1))
        asound = np.array([1.]).reshape((num_nodes, 1))
        pitch = np.array([0.0]).reshape((num_nodes, 1))

        # Airfoil interpolator.
        af = af_from_files(["airfoils/NACA64_A17.dat"])[0]

        prob = om.Problem()

        comp = ccb.LocalInflowAngleComp(num_nodes=num_nodes,
                                        num_radial=num_radial,
                                        num_blades=num_blades,
                                        airfoil_interp=af,
                                        turbine=turbine,
                                        debug_print=False)
        comp.linear_solver = om.DirectSolver(assemble_jac=True)

        prob.model.add_subsystem('ccblade', comp)

        prob.setup()
        prob.final_setup()

        prob['ccblade.phi'] = 1.
        prob['ccblade.radii'] = r
        prob['ccblade.chord'] = chord
        prob['ccblade.theta'] = theta
        prob['ccblade.Vx'] = Vx
        prob['ccblade.Vy'] = Vy
        prob['ccblade.rho'] = rho
        prob['ccblade.mu'] = mu
        prob['ccblade.asound'] = asound
        prob['ccblade.hub_radius'] = Rhub
        prob['ccblade.prop_radius'] = Rtip
        prob['ccblade.precone'] = precone
        prob['ccblade.pitch'] = pitch

        prob.run_model()

        Nptest = np.array([
            1.8660880922356378, 2.113489633244873, 2.35855792055661,
            2.60301402945597, 2.844874233881403, 3.1180230827072126,
            3.560077224628854, 4.024057801497014, 4.480574891998562,
            4.9279550384928275, 5.366395080074933, 5.79550918136406,
            6.21594163851808, 6.622960527391846, 7.017012349498324,
            7.3936834781240774, 7.751945902955048, 8.086176029603802,
            8.393537672577372, 8.67090062789216, 8.912426896510306,
            9.111379449026037, 9.264491105426602, 9.361598738055728,
            9.397710628068818, 9.360730779314666, 9.236967116872792,
            9.002418776792911, 8.617229305924996, 7.854554211296309,
            5.839491141636506
        ])
        Tptest = np.array([
            1.481919153409856, 1.5816880353415623, 1.6702432911163534,
            1.7502397903925069, 1.822089134395204, 1.8965254874252537,
            2.0022647148294554, 2.097706171361262, 2.178824887386094,
            2.2475057498944886, 2.3058616094094666, 2.355253913018444,
            2.3970643308370168, 2.4307239254050717, 2.4574034513165794,
            2.4763893383410522, 2.488405728268889, 2.492461784055084,
            2.4887264544021237, 2.4772963155708783, 2.457435891854637,
            2.4282986089025607, 2.3902927838322237, 2.3418848562229155,
            2.283388513786012, 2.2134191689454954, 2.130781255778788,
            2.0328865955896, 1.9153448642630952, 1.7308451522888118,
            1.2736544011110416
        ])
        unormtest = np.array([
            0.1138639166930624, 0.1215785884908478, 0.12836706426605704,
            0.13442694075150818, 0.13980334658952898, 0.14527249541450538,
            0.15287706861957473, 0.15952130275430465, 0.16497198426904225,
            0.16942902209255595, 0.17308482185019125, 0.17607059901193356,
            0.17850357997819633, 0.1803781237713692, 0.18177831882512596,
            0.18267665167815783, 0.18311924527883217, 0.18305367052760668,
            0.182487470134022, 0.1814205780851561, 0.17980424363698078,
            0.1775794222894007, 0.1747493664535781, 0.1712044765873724,
            0.1669243629724566, 0.16177907188793106, 0.155616714947619,
            0.14815634397029886, 0.13888287431637295, 0.12464247057085576,
            0.09292645450646951
        ])
        vnormtest = np.array([
            0.09042291182918308, 0.090986677078917, 0.09090479653774426,
            0.09038728871285233, 0.08954144817337718, 0.08836143378908702,
            0.08598138211326231, 0.08315706129440237, 0.08022297890584436,
            0.07727195122065926, 0.07437202068064472, 0.07155384528141737,
            0.06883664444997291, 0.0662014244622726, 0.06365995181515205,
            0.061184457505937574, 0.05878201223442723, 0.056423985398129595,
            0.05410845965501752, 0.05183227774671869, 0.04957767474023305,
            0.04732717658478895, 0.04508635659098153, 0.04282827989707323,
            0.04055808783300249, 0.03825394697198818, 0.0358976247398962,
            0.033456013675480394, 0.030869388594900515, 0.027466462150913407,
            0.020268236545135546
        ])

        assert_array_almost_equal(prob.get_val('ccblade.Np',
                                               units='N/m')[0, :],
                                  Nptest,
                                  decimal=2)
        assert_array_almost_equal(prob.get_val('ccblade.Tp',
                                               units='N/m')[0, :],
                                  Tptest,
                                  decimal=2)
        assert_array_almost_equal(
            (prob.get_val('ccblade.u', units='m/s') / Vinf)[0, :],
            unormtest,
            decimal=2)
        assert_array_almost_equal(
            (prob.get_val('ccblade.v', units='m/s') / Vinf)[0, :],
            vnormtest,
            decimal=2)
    def test_brachistochrone_for_docs_coloring_demo_solve_segments(self):
        import openmdao.api as om
        from openmdao.utils.assert_utils import assert_near_equal
        import dymos as dm
        from dymos.examples.plotting import plot_results
        from dymos.examples.brachistochrone import BrachistochroneODE

        #
        # Initialize the Problem and the optimization driver
        #
        p = om.Problem(model=om.Group())
        p.driver = om.pyOptSparseDriver(optimizer='IPOPT')
        p.driver.opt_settings['print_level'] = 4
        # p.driver.declare_coloring()

        #
        # Create a trajectory and add a phase to it
        #
        traj = p.model.add_subsystem('traj', dm.Trajectory())

        #
        # In this case the phase has many segments to demonstrate the impact of coloring.
        #
        phase = traj.add_phase(
            'phase0',
            dm.Phase(ode_class=BrachistochroneODE,
                     transcription=dm.Radau(num_segments=100,
                                            solve_segments='forward')))

        #
        # Set the variables
        #
        phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10))

        phase.add_state('x', fix_initial=True)

        phase.add_state('y', fix_initial=True)

        phase.add_state('v', fix_initial=True)

        phase.add_control('theta',
                          continuity=True,
                          rate_continuity=True,
                          units='deg',
                          lower=0.01,
                          upper=179.9)

        phase.add_parameter('g', units='m/s**2', val=9.80665)

        #
        # Replace state terminal bounds with nonlinear constraints
        #
        phase.add_boundary_constraint('x', loc='final', equals=10)
        phase.add_boundary_constraint('y', loc='final', equals=5)

        #
        # Minimize time at the end of the phase
        #
        phase.add_objective('time', loc='final', scaler=10)

        p.model.linear_solver = om.DirectSolver()

        #
        # Setup the Problem
        #
        p.setup()

        #
        # Set the initial values
        #
        p['traj.phase0.t_initial'] = 0.0
        p['traj.phase0.t_duration'] = 2.0

        p.set_val('traj.phase0.states:x', phase.interp('x', ys=[0, 10]))
        p.set_val('traj.phase0.states:y', phase.interp('y', ys=[10, 5]))
        p.set_val('traj.phase0.states:v', phase.interp('v', ys=[0, 9.9]))
        p.set_val('traj.phase0.controls:theta',
                  phase.interp('theta', ys=[5, 100.5]))

        #
        # Solve for the optimal trajectory
        #
        dm.run_problem(p)

        # Test the results
        assert_near_equal(p.get_val('traj.phase0.timeseries.time')[-1],
                          1.8016,
                          tolerance=1.0E-3)

        # Generate the explicitly simulated trajectory
        exp_out = traj.simulate()

        plot_results(
            [('traj.phase0.timeseries.states:x',
              'traj.phase0.timeseries.states:y', 'x (m)', 'y (m)'),
             ('traj.phase0.timeseries.time',
              'traj.phase0.timeseries.controls:theta', 'time (s)',
              'theta (deg)')],
            title='Brachistochrone Solution\nRadau Pseudospectral Method',
            p_sol=p,
            p_sim=exp_out)

        plt.show()
示例#27
0
    def test_camber(self):
        # Copied from CCBlade.jl/test/runtests.jl

        # inputs
        chord = 0.10
        D = 1.6
        RPM = 2100
        rho = 1.225
        pitch = 1.0  # pitch distance in meters.

        # --- rotor definition ---
        turbine = False
        Rhub = 0.0
        Rtip = D / 2
        Rhub_eff = 1e-6  # something small to eliminate hub effects
        Rtip_eff = 100.0  # something large to eliminate tip effects
        B = 2  # number of blades

        # --- section definitions ---

        num_nodes = 1
        R = D / 2.0
        r = np.linspace(R / 10, R, 11)
        dr = r[1] - r[0]
        r = np.tile(r, (num_nodes, 1))
        dr = np.tile(dr, r.shape)
        theta = np.arctan(pitch / (2 * np.pi * r))

        def affunc(alpha, Re, M):
            alpha0 = -3 * np.pi / 180
            cl = 6.2 * (alpha - alpha0)
            cd = 0.008 - 0.003 * cl + 0.01 * cl * cl
            return cl, cd

        prob = om.Problem()
        num_radial = r.shape[-1]

        comp = om.IndepVarComp()
        comp.add_output('v', val=[5.0], units='m/s')
        comp.add_output('omega', val=np.tile(RPM, num_nodes), units='rpm')
        comp.add_output('radii', val=r, units='m')
        comp.add_output('dradii', val=dr, units='m')
        comp.add_output('chord',
                        val=chord,
                        shape=(num_nodes, num_radial),
                        units='m')
        comp.add_output('theta',
                        val=theta,
                        shape=(num_nodes, num_radial),
                        units='rad')
        comp.add_output('precone', val=0., shape=num_nodes, units='rad')
        comp.add_output('rho', val=rho, shape=(num_nodes, 1), units='kg/m**3')
        comp.add_output('mu', val=1.0, shape=(num_nodes, 1), units='N/m**2*s')
        comp.add_output('asound', val=1.0, shape=(num_nodes, 1), units='m/s')
        comp.add_output('hub_radius_eff',
                        val=Rhub_eff,
                        shape=num_nodes,
                        units='m')
        comp.add_output('prop_radius_eff',
                        val=Rtip_eff,
                        shape=num_nodes,
                        units='m')
        comp.add_output('hub_radius', val=Rhub, shape=num_nodes, units='m')
        comp.add_output('prop_radius', val=Rtip, shape=num_nodes, units='m')
        comp.add_output('pitch', val=0.0, shape=num_nodes, units='rad')
        prob.model.add_subsystem('ivc', comp, promotes_outputs=['*'])

        comp = SimpleInflow(num_nodes=num_nodes, num_radial=num_radial)
        prob.model.add_subsystem(
            "simple_inflow",
            comp,
            promotes_inputs=["v", "omega", "radii", "precone"],
            promotes_outputs=["Vx", "Vy"])

        comp = ccb.LocalInflowAngleComp(num_nodes=num_nodes,
                                        num_radial=num_radial,
                                        num_blades=B,
                                        airfoil_interp=affunc,
                                        turbine=turbine,
                                        debug_print=False)
        comp.linear_solver = om.DirectSolver(assemble_jac=True)
        prob.model.add_subsystem('ccblade',
                                 comp,
                                 promotes_inputs=[
                                     'radii', 'chord', 'theta', 'Vx', 'Vy',
                                     'rho', 'mu', 'asound',
                                     ('hub_radius', 'hub_radius_eff'),
                                     ('prop_radius', 'prop_radius_eff'),
                                     'precone', 'pitch'
                                 ],
                                 promotes_outputs=['Np', 'Tp'])

        prob.setup()
        prob.final_setup()
        prob.run_model()

        Np = prob.get_val('Np', units='N/m')
        Tp = prob.get_val('Tp', units='N/m')
        T = np.sum(Np * dr) * B
        Q = np.sum(r * Tp * dr) * B

        assert_rel_error(self, 1223.0506862888788, T, 1e-9)
        assert_rel_error(self, 113.79919472569034, Q, 1e-10)

        assert_rel_error(self,
                         prob.get_val('Np', units='N/m')[0, 3],
                         427.3902632382494, 1e-10)
        assert_rel_error(self,
                         prob.get_val('Tp', units='N/m')[0, 3],
                         122.38414345762305, 1e-10)
        assert_rel_error(self,
                         prob.get_val('ccblade.a')[0, 3], 2.2845512476210943,
                         1e-8)
        assert_rel_error(self,
                         prob.get_val('ccblade.ap')[0, 3], 0.05024950801920044,
                         1e-8)
        assert_rel_error(self,
                         prob.get_val('ccblade.u', units='m/s')[0, 3],
                         11.422756238105471, 1e-8)
        assert_rel_error(self,
                         prob.get_val('ccblade.v', units='m/s')[0, 3],
                         3.2709314141649575, 1e-8)
        assert_rel_error(self,
                         prob.get_val('ccblade.phi', units='rad')[0, 3],
                         0.2596455971546484, 1e-8)
        assert_rel_error(self,
                         prob.get_val('ccblade.alpha', units='rad')[0, 3],
                         0.23369406105568025, 1e-8)
        assert_rel_error(self,
                         prob.get_val('ccblade.W', units='m/s')[0, 3],
                         63.96697566502531, 1e-8)
        assert_rel_error(self,
                         prob.get_val('ccblade.cl')[0, 3], 1.773534419416163,
                         1e-8)
        assert_rel_error(self,
                         prob.get_val('ccblade.cd')[0, 3], 0.03413364011028978,
                         1e-8)
        assert_rel_error(self,
                         prob.get_val('ccblade.cn')[0, 3], 1.7053239640124302,
                         1e-8)
        assert_rel_error(self,
                         prob.get_val('ccblade.ct')[0, 3], 0.48832327407767123,
                         1e-8)
        assert_rel_error(self, prob.get_val('ccblade.F')[0, 3], 1.0, 1e-8)
        assert_rel_error(self, prob.get_val('ccblade.G')[0, 3], 1.0, 1e-8)

        theta = np.arctan(pitch / (2 * np.pi * r)) - 3 * np.pi / 180
        prob.set_val('theta', theta, units='rad')
        prob.run_model()

        Np = prob.get_val('Np', units='N/m')
        Tp = prob.get_val('Tp', units='N/m')
        T = np.sum(Np * dr) * B
        Q = np.sum(r * Tp * dr) * B

        assert_rel_error(self, T, 1e3 * 0.962407923825140, 1e-6)
        assert_rel_error(self, Q, 1e2 * 0.813015017103876, 1e-6)
    def test_brachistochrone_for_docs_gauss_lobatto(self):
        import openmdao.api as om
        from openmdao.utils.assert_utils import assert_near_equal
        import dymos as dm
        from dymos.examples.plotting import plot_results
        from dymos.examples.brachistochrone import BrachistochroneODE
        import matplotlib.pyplot as plt

        #
        # Initialize the Problem and the optimization driver
        #
        p = om.Problem(model=om.Group())
        p.driver = om.ScipyOptimizeDriver()
        p.driver.declare_coloring()

        #
        # Create a trajectory and add a phase to it
        #
        traj = p.model.add_subsystem('traj', dm.Trajectory())

        phase = traj.add_phase(
            'phase0',
            dm.Phase(ode_class=BrachistochroneODE,
                     transcription=dm.GaussLobatto(num_segments=10)))

        #
        # Set the variables
        #
        phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10))

        phase.add_state('x', fix_initial=True, fix_final=True)

        phase.add_state('y', fix_initial=True, fix_final=True)

        phase.add_state('v', fix_initial=True, fix_final=False)

        phase.add_control('theta',
                          continuity=True,
                          rate_continuity=True,
                          units='deg',
                          lower=0.01,
                          upper=179.9)

        phase.add_parameter('g', units='m/s**2', val=9.80665)
        #
        # Minimize time at the end of the phase
        #
        phase.add_objective('time', loc='final', scaler=10)

        p.model.linear_solver = om.DirectSolver()

        #
        # Setup the Problem
        #
        p.setup()

        #
        # Set the initial values
        #
        p['traj.phase0.t_initial'] = 0.0
        p['traj.phase0.t_duration'] = 2.0

        p.set_val('traj.phase0.states:x', phase.interp('x', ys=[0, 10]))
        p.set_val('traj.phase0.states:y', phase.interp('y', ys=[10, 5]))
        p.set_val('traj.phase0.states:v', phase.interp('v', ys=[0, 9.9]))
        p.set_val('traj.phase0.controls:theta',
                  phase.interp('theta', ys=[5, 100.5]))

        #
        # Solve for the optimal trajectory
        #
        dm.run_problem(p)

        # Test the results
        assert_near_equal(p.get_val('traj.phase0.timeseries.time')[-1],
                          1.8016,
                          tolerance=1.0E-3)

        # Generate the explicitly simulated trajectory
        exp_out = traj.simulate()

        plot_results(
            [('traj.phase0.timeseries.states:x',
              'traj.phase0.timeseries.states:y', 'x (m)', 'y (m)'),
             ('traj.phase0.timeseries.time',
              'traj.phase0.timeseries.controls:theta', 'time (s)',
              'theta (deg)')],
            title='Brachistochrone Solution\nHigh-Order Gauss-Lobatto Method',
            p_sol=p,
            p_sim=exp_out)

        plt.show()
示例#29
0
    def test_hover(self):
        # num_nodes = 40
        nstart = 0
        nend = 39
        num_nodes = nend - nstart + 1
        chord = 0.060
        theta = 0.0
        Rtip = 0.656
        Rhub = 0.19 * Rtip
        rho = 1.225
        omega = 800.0 * np.pi / 30
        Vinf = 0.0
        turbine = False
        B = 3

        r = np.linspace(Rhub + 0.01 * Rtip, Rtip - 0.01 * Rtip, 30)
        num_radial = r.shape[-1]
        r = np.tile(r, (num_nodes, 1))

        chord = np.tile(chord, (num_nodes, num_radial))
        theta = np.tile(theta, (num_nodes, num_radial))

        # Airfoil interpolator.
        af = af_from_files(["airfoils/naca0012v2.txt"])[0]

        pitch = np.linspace(1e-4, 20 * np.pi / 180, 40)[nstart:nend + 1]
        prob = om.Problem()

        comp = om.IndepVarComp()
        comp.add_output('v', val=Vinf, shape=num_nodes, units='m/s')
        comp.add_output('omega', val=np.tile(omega, num_nodes), units='rad/s')
        comp.add_output('radii',
                        val=r,
                        shape=(num_nodes, num_radial),
                        units='m')
        comp.add_output('chord',
                        val=chord,
                        shape=(num_nodes, num_radial),
                        units='m')
        comp.add_output('theta',
                        val=theta,
                        shape=(num_nodes, num_radial),
                        units='rad')
        comp.add_output('precone', val=0., shape=num_nodes, units='rad')
        comp.add_output('rho', val=rho, shape=(num_nodes, 1), units='kg/m**3')
        comp.add_output('mu', val=1.0, shape=(num_nodes, 1), units='N/m**2*s')
        comp.add_output('asound', val=1.0, shape=(num_nodes, 1), units='m/s')
        comp.add_output('hub_radius', val=Rhub, shape=num_nodes, units='m')
        comp.add_output('prop_radius', val=Rtip, shape=num_nodes, units='m')
        comp.add_output('pitch', val=pitch, shape=num_nodes, units='rad')
        prob.model.add_subsystem('ivc', comp, promotes_outputs=['*'])

        comp = SimpleInflow(num_nodes=num_nodes, num_radial=num_radial)
        prob.model.add_subsystem(
            "simple_inflow",
            comp,
            promotes_inputs=["v", "omega", "radii", "precone"],
            promotes_outputs=["Vx", "Vy"])

        comp = ccb.LocalInflowAngleComp(num_nodes=num_nodes,
                                        num_radial=num_radial,
                                        num_blades=B,
                                        airfoil_interp=af,
                                        turbine=turbine,
                                        debug_print=False)
        comp.linear_solver = om.DirectSolver(assemble_jac=True)
        prob.model.add_subsystem('ccblade',
                                 comp,
                                 promotes_inputs=[
                                     'radii', 'chord', 'theta', 'Vx', 'Vy',
                                     'rho', 'mu', 'asound', 'hub_radius',
                                     'prop_radius', 'precone', 'pitch'
                                 ],
                                 promotes_outputs=['Np', 'Tp'])

        comp = ccb.FunctionalsComp(num_nodes=num_nodes,
                                   num_radial=num_radial,
                                   num_blades=B)
        prob.model.add_subsystem(
            'ccblade_torquethrust_comp',
            comp,
            promotes_inputs=[
                'hub_radius', 'prop_radius', 'radii', 'Np', 'Tp', 'v', 'omega'
            ],
            promotes_outputs=['thrust', 'torque', 'efficiency'])

        prob.setup()
        prob.final_setup()
        prob.run_model()

        # these are not directly from the experimental data, but have been compared to the experimental data and compare favorably.
        # this is more of a regression test on the Vx=0 case
        CTcomp = np.array([
            9.452864991304056e-9, 6.569947366946672e-5, 0.00022338783939012262,
            0.0004420355541809959, 0.0007048495858030926,
            0.0010022162314665929, 0.0013268531109981317,
            0.0016736995380106938, 0.0020399354072946035,
            0.0024223576277264307, 0.0028189858460418893,
            0.0032281290309981213, 0.003649357660426685, 0.004081628946214875,
            0.004526034348853718, 0.004982651929181267, 0.0054553705714941,
            0.005942700094508395, 0.006447634897014323, 0.006963626871239654,
            0.007492654931894796, 0.00803866268066438, 0.008597914974368199,
            0.009163315934297088, 0.00973817187875574, 0.010309276997090536,
            0.010827599471613264, 0.011322361524464346, 0.01180210507896255,
            0.012276543435307877, 0.012749323136224754, 0.013223371028562213,
            0.013697833731701945, 0.01417556699620018, 0.014646124777465859,
            0.015112116772851365, 0.015576452747370885, 0.01602507607909594,
            0.016461827164870473, 0.016880126012974343
        ])
        CQcomp = np.array([
            0.000226663607327854, 0.0002270862930229147, 0.0002292742856722754,
            0.00023412703235791698, 0.00024192624628054639,
            0.0002525855612031453, 0.00026638347417704255,
            0.00028314784456601373, 0.00030299181501156373,
            0.0003259970210015136, 0.00035194661281707764,
            0.00038102864688744595, 0.0004132249034847219,
            0.00044859355432807347, 0.0004873204055790553,
            0.0005293656187218555, 0.0005753409000182888,
            0.0006250099998058788, 0.0006788861946930185,
            0.0007361096750412038, 0.0007970800153713466,
            0.0008624036743669367, 0.0009315051772818803,
            0.0010035766105979213, 0.0010791941808362153,
            0.0011566643573792704, 0.001229236439467123, 0.0013007334425769355,
            0.001372124993921022, 0.0014449961686871802, 0.0015197156782734364,
            0.0015967388663224156, 0.0016761210460920718,
            0.0017578748614666766, 0.0018409716992061841,
            0.0019248522013432586, 0.0020103360819251357, 0.002096387027559033,
            0.002182833604491109, 0.0022686470790128036
        ])
        T = prob.get_val('thrust', units='N')
        Q = prob.get_val('torque', units='N*m')
        A = np.pi * Rtip**2
        CT = T / (rho * A * (omega * Rtip)**2)
        CQ = Q / (rho * A * (omega * Rtip)**2 * Rtip)

        assert_array_almost_equal(CT, CTcomp[nstart:nend + 1], decimal=3)
        assert_array_almost_equal(CQ, CQcomp[nstart:nend + 1], decimal=3)
示例#30
0
    def test_control_boundary_constraint_gl(self):
        p = om.Problem(model=om.Group())

        p.driver = om.ScipyOptimizeDriver()

        p.driver.declare_coloring()

        phase = dm.Phase(ode_class=BrachistochroneODE,
                         transcription=dm.GaussLobatto(num_segments=20,
                                                       order=3,
                                                       compressed=True))

        p.model.add_subsystem('phase0', phase)

        phase.set_time_options(initial_bounds=(0, 0),
                               duration_bounds=(.5, 10),
                               units='s')

        phase.add_state(
            'x',
            rate_source=BrachistochroneODE.states['x']['rate_source'],
            units=BrachistochroneODE.states['x']['units'],
            fix_initial=True,
            fix_final=False,
            solve_segments=False)

        phase.add_state(
            'y',
            rate_source=BrachistochroneODE.states['y']['rate_source'],
            units=BrachistochroneODE.states['y']['units'],
            fix_initial=True,
            fix_final=False,
            solve_segments=False)

        phase.add_state(
            'v',
            rate_source=BrachistochroneODE.states['v']['rate_source'],
            targets=BrachistochroneODE.states['v']['targets'],
            units=BrachistochroneODE.states['v']['units'],
            fix_initial=True,
            fix_final=False,
            solve_segments=False)

        phase.add_control(
            'theta',
            targets=BrachistochroneODE.parameters['theta']['targets'],
            units='deg',
            lower=0.01,
            upper=179.9)

        phase.add_parameter(
            'g',
            targets=BrachistochroneODE.parameters['g']['targets'],
            opt=False,
            units='m/s**2',
            val=9.80665)

        phase.add_boundary_constraint('theta',
                                      loc='final',
                                      lower=90.0,
                                      upper=90.0,
                                      units='deg')

        # Minimize time at the end of the phase
        phase.add_objective('time')

        p.model.linear_solver = om.DirectSolver()
        p.setup(check=True)

        p['phase0.t_initial'] = 0.0
        p['phase0.t_duration'] = 2.0

        p['phase0.states:x'] = phase.interpolate(ys=[0, 10],
                                                 nodes='state_input')
        p['phase0.states:y'] = phase.interpolate(ys=[10, 5],
                                                 nodes='state_input')
        p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9],
                                                 nodes='state_input')
        p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100],
                                                       nodes='control_input')
        p['phase0.parameters:g'] = 8

        p.run_driver()

        assert_near_equal(
            p.get_val('phase0.timeseries.controls:theta', units='deg')[-1],
            90.0)