예제 #1
0
    def test_initial_val_and_final_val_stick(self):
        p = Problem(model=Group())

        p.driver = ScipyOptimizeDriver()
        p.driver.options['dynamic_simul_derivs'] = True

        phase = Phase(ode_class=BrachistochroneODE,
                      transcription=GaussLobatto(num_segments=8, order=3))

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

        phase.set_time_options(fix_initial=False, fix_duration=False,
                               initial_val=0.01, duration_val=1.9)

        phase.set_state_options('x', fix_initial=True, fix_final=True)
        phase.set_state_options('y', fix_initial=True, fix_final=True)
        phase.set_state_options('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_design_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_boundary_constraint('time', loc='initial', equals=0)

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

        assert_rel_error(self, p['phase0.t_initial'], 0.01)
        assert_rel_error(self, p['phase0.t_duration'], 1.9)
예제 #2
0
    def test_brachistochrone_forward_shooting_path_constrained_ode_output(self):
        from openmdao.api import Problem, Group, ScipyOptimizeDriver, DirectSolver
        from openmdao.utils.assert_utils import assert_rel_error
        from dymos import Phase, RungeKutta
        from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE

        p = Problem(model=Group())
        p.driver = ScipyOptimizeDriver()
        p.driver.options['dynamic_simul_derivs'] = True

        phase = Phase(ode_class=BrachistochroneODE,
                      transcription=RungeKutta(num_segments=20))

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

        phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(0.5, 2.0))

        phase.set_state_options('x', fix_initial=True)
        phase.set_state_options('y', fix_initial=True)
        phase.set_state_options('v', fix_initial=True)

        phase.add_control('theta', units='deg', lower=0.01, upper=179.9, ref0=0, ref=180.0,
                          rate_continuity=True, rate2_continuity=True)

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

        # Final state values can't be controlled with simple bounds in ExplicitPhase,
        # so use nonlinear boundary constraints instead.
        phase.add_boundary_constraint('x', loc='final', equals=10)
        phase.add_boundary_constraint('y', loc='final', equals=5)
        phase.add_path_constraint('check', lower=-500, upper=500, shape=(1,), units='m/s')

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

        p.model.linear_solver = DirectSolver()

        p.setup(check=True)

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

        p['phase0.states:x'] = 0
        p['phase0.states:y'] = 10
        p['phase0.states:v'] = 0
        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_rel_error(self, p['phase0.time'][-1], 1.8016, tolerance=1.0E-3)

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

        assert_rel_error(self, exp_out.get_val('phase0.timeseries.states:x')[-1, 0], 10,
                         tolerance=1.0E-3)
        assert_rel_error(self, exp_out.get_val('phase0.timeseries.states:y')[-1, 0], 5,
                         tolerance=1.0E-3)
예제 #3
0
    def test_ex_brachistochrone_vs_rungekutta_compressed(self):
        from openmdao.api import Problem, Group, ScipyOptimizeDriver, DirectSolver
        from dymos import Phase, RungeKutta
        from dymos.examples.brachistochrone.brachistochrone_vector_states_ode import \
            BrachistochroneVectorStatesODE

        p = Problem(model=Group())

        p.driver = ScipyOptimizeDriver()

        p.driver.options['dynamic_simul_derivs'] = True

        phase = Phase(ode_class=BrachistochroneVectorStatesODE,
                      transcription=RungeKutta(num_segments=20,
                                               compressed=True))

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

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

        phase.set_state_options('pos', fix_initial=True, fix_final=False)
        phase.set_state_options('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_design_parameter('g', units='m/s**2', opt=False, val=9.80665)

        phase.add_boundary_constraint('pos', loc='final', lower=[10, 5])

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

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

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

        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=[0.46, 100.22900215],
                                                       nodes='control_input')
        p['phase0.design_parameters:g'] = 9.80665

        p.run_driver()

        self.assert_results(p)
        self.tearDown()
예제 #4
0
    def test_unbounded_time(self):
        p = Problem(model=Group())

        p.driver = ScipyOptimizeDriver()
        p.driver.options['dynamic_simul_derivs'] = True

        phase = Phase('gauss-lobatto',
                      ode_class=BrachistochroneODE,
                      num_segments=8,
                      transcription_order=3)

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

        phase.set_time_options(fix_initial=False, fix_duration=False)

        phase.set_state_options('x', fix_initial=True, fix_final=True)
        phase.set_state_options('y', fix_initial=True, fix_final=True)
        phase.set_state_options('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_design_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_boundary_constraint('time', loc='initial', equals=0)

        p.model.options['assembled_jac_type'] = 'csc'
        p.model.linear_solver = DirectSolver(assemble_jac=True)
        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.design_parameters:g'] = 9.80665

        p.run_driver()

        self.assertTrue(p.driver.result.success,
                        msg='Brachistochrone with outbounded times has failed')
예제 #5
0
    def test_invalid_boundary_loc(self):

        p = Phase(ode_class=BrachistochroneODE,
                  transcription=GaussLobatto(num_segments=8,
                                             order=3,
                                             compressed=True))

        with self.assertRaises(ValueError) as e:
            p.add_boundary_constraint('x', loc='foo')

        expected = 'Invalid boundary constraint location "foo". Must be "initial" or "final".'
        self.assertEqual(str(e.exception), expected)
예제 #6
0
def ssto_moon(transcription='gauss-lobatto',
              num_seg=10,
              optimizer='SLSQP',
              top_level_jacobian='csc',
              transcription_order=5,
              compressed=False):

    p = Problem(model=Group())

    if optimizer == 'SNOPT':
        p.driver = pyOptSparseDriver()
        p.driver.options['optimizer'] = optimizer
        p.driver.options['dynamic_simul_derivs'] = True
        p.driver.opt_settings['Major iterations limit'] = 100
        p.driver.opt_settings['iSumm'] = 6
        p.driver.opt_settings['Verify level'] = 3
    else:
        p.driver = ScipyOptimizeDriver()
        p.driver.options['dynamic_simul_derivs'] = True

    phase = Phase(transcription,
                  ode_class=LaunchVehicleODE,
                  ode_init_kwargs={'central_body': 'moon'},
                  num_segments=num_seg,
                  compressed=compressed,
                  transcription_order=3)

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

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

    phase.set_state_options('x', fix_initial=True, scaler=1.0E-5, lower=0)
    phase.set_state_options('y', fix_initial=True, scaler=1.0E-5, lower=0)
    phase.set_state_options('vx', fix_initial=True, scaler=1.0E-3, lower=0)
    phase.set_state_options('vy', fix_initial=True, scaler=1.0E-3)
    phase.set_state_options('m', fix_initial=True, scaler=1.0E-3)

    phase.add_boundary_constraint('y', loc='final', equals=1.85E5, linear=True)
    phase.add_boundary_constraint('vx', loc='final', equals=1627.0)
    phase.add_boundary_constraint('vy', loc='final', equals=0)

    if transcription == 'radau-ps':
        # This constraint is necessary using the Radau-Pseudospectral method since the
        # last value of the control does not impact the collocation defects.
        phase.add_boundary_constraint('theta_rate2', loc='final', equals=0)

    phase.add_control('theta', units='rad', lower=-1.57, upper=1.57)
    phase.add_design_parameter('thrust',
                               units='N',
                               opt=False,
                               val=3.0 * 50000.0 * 1.61544)
    phase.add_design_parameter('Isp', units='s', opt=False, val=1.0E6)

    phase.add_objective('time', index=-1, scaler=0.01)

    p.model.options['assembled_jac_type'] = top_level_jacobian.lower()
    p.model.linear_solver = DirectSolver(assemble_jac=True)

    return p
예제 #7
0
    def test_fixed_time_invalid_options(self):
        p = Problem(model=Group())

        p.driver = ScipyOptimizeDriver()
        p.driver.options['dynamic_simul_derivs'] = True

        phase = Phase(ode_class=BrachistochroneODE,
                      transcription=GaussLobatto(num_segments=8, order=3))

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

        phase.set_time_options(fix_initial=True, fix_duration=True,
                               initial_bounds=(1.0, 5.0), initial_adder=0.0,
                               initial_scaler=1.0, initial_ref0=0.0,
                               initial_ref=1.0, duration_bounds=(1.0, 5.0),
                               duration_adder=0.0, duration_scaler=1.0,
                               duration_ref0=0.0, duration_ref=1.0)

        phase.set_state_options('x', fix_initial=True, fix_final=True)
        phase.set_state_options('y', fix_initial=True, fix_final=True)
        phase.set_state_options('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_design_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_boundary_constraint('time', loc='initial', equals=0)

        p.model.linear_solver = DirectSolver()

        expected_msg0 = 'Phase time options have no effect because fix_initial=True for ' \
                        'phase \'phase0\': initial_bounds, initial_scaler, initial_adder, ' \
                        'initial_ref, initial_ref0'

        expected_msg1 = 'Phase time options have no effect because fix_duration=True for' \
                        ' phase \'phase0\': duration_bounds, duration_scaler, ' \
                        'duration_adder, duration_ref, duration_ref0'

        with warnings.catch_warnings(record=True) as ctx:
            warnings.simplefilter('always')
            p.setup(check=True)

        self.assertIn(expected_msg0, [str(w.message) for w in ctx])
        self.assertIn(expected_msg1, [str(w.message) for w in ctx])
예제 #8
0
    def test_ex_double_integrator_input_and_fixed_times_warns(self):
        """
        Tests that time optimization options cause a ValueError to be raised when t_initial and
        t_duration are connected to external sources.
        """
        p = Problem(model=Group())

        p.driver = ScipyOptimizeDriver()
        p.driver.options['dynamic_simul_derivs'] = True

        phase = Phase(ode_class=BrachistochroneODE,
                      transcription=GaussLobatto(num_segments=8, order=3))

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

        phase.set_time_options(input_initial=True, fix_initial=True,
                               input_duration=True, fix_duration=True)

        phase.set_state_options('x', fix_initial=True, fix_final=True)
        phase.set_state_options('y', fix_initial=True, fix_final=True)
        phase.set_state_options('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_design_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_boundary_constraint('time', loc='initial', equals=0)

        p.model.linear_solver = DirectSolver()

        with warnings.catch_warnings(record=True) as ctx:
            warnings.simplefilter('always')
            p.setup(check=True)

        expected_msg0 = 'Phase \'phase0\' initial time is an externally-connected input, therefore ' \
                        'fix_initial has no effect.'

        expected_msg1 = 'Phase \'phase0\' time duration is an externally-connected input, ' \
                        'therefore fix_duration has no effect.'

        self.assertIn(expected_msg0, [str(w.message) for w in ctx])
        self.assertIn(expected_msg1, [str(w.message) for w in ctx])
예제 #9
0
    def _make_problem(self, transcription, num_seg, transcription_order=3):
        p = Problem(model=Group())

        p.driver = ScipyOptimizeDriver()

        # Compute sparsity/coloring when run_driver is called
        p.driver.options['dynamic_simul_derivs'] = True

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

        phase = Phase(ode_class=_BrachistochroneTestODE, transcription=t[transcription])

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

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

        phase.set_state_options('x', fix_initial=True)
        phase.set_state_options('y', fix_initial=True)
        phase.set_state_options('v', fix_initial=True)

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

        phase.add_design_parameter('g', units='m/s**2', opt=False, 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', loc='final', scaler=10)

        p.model.linear_solver = DirectSolver()

        p.setup()

        p['phase0.t_initial'] = 1.0
        p['phase0.t_duration'] = 3.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')

        return p
예제 #10
0
def ssto_earth(transcription='gauss-lobatto', num_seg=10, transcription_order=5,
               top_level_jacobian='csc', optimizer='SLSQP', compressed=False):
    p = Problem(model=Group())
    if optimizer == 'SNOPT':
        p.driver = pyOptSparseDriver()
        p.driver.options['optimizer'] = optimizer
        p.driver.options['dynamic_simul_derivs'] = True
        p.driver.opt_settings['Major iterations limit'] = 100
        p.driver.opt_settings['iSumm'] = 6
        p.driver.opt_settings['Verify level'] = 3
    else:
        p.driver = ScipyOptimizeDriver()
        p.driver.options['dynamic_simul_derivs'] = True

    phase = Phase(transcription,
                  ode_class=LaunchVehicleODE,
                  ode_init_kwargs={'central_body': 'earth'},
                  num_segments=num_seg,
                  transcription_order=transcription_order,
                  compressed=compressed)

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

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

    phase.set_state_options('x', fix_initial=True, scaler=1.0E-5)
    phase.set_state_options('y', fix_initial=True, scaler=1.0E-5)
    phase.set_state_options('vx', fix_initial=True, scaler=1.0E-3)
    phase.set_state_options('vy', fix_initial=True, scaler=1.0E-3)
    phase.set_state_options('m', fix_initial=True, scaler=1.0E-3)

    phase.add_boundary_constraint('y', loc='final', equals=1.85E5, linear=True)
    phase.add_boundary_constraint('vx', loc='final', equals=7796.6961)
    phase.add_boundary_constraint('vy', loc='final', equals=0)

    phase.add_control('theta', units='rad', lower=-1.57, upper=1.57)
    phase.add_design_parameter('thrust', units='N', opt=False, val=2100000.0)

    phase.add_objective('time', loc='final', scaler=0.01)

    p.model.options['assembled_jac_type'] = top_level_jacobian.lower()
    p.model.linear_solver = DirectSolver(assemble_jac=True)

    return p
예제 #11
0
def min_time_climb_problem(num_seg=3, transcription_order=5,
                           transcription='gauss-lobatto',
                           top_level_densejacobian=True):

    p = Problem(model=Group())

    p.driver = pyOptSparseDriver()
    p.driver.options['optimizer'] = 'SNOPT'
    p.driver.opt_settings['Major iterations limit'] = 500
    p.driver.opt_settings['Iterations limit'] = 1000000000
    p.driver.opt_settings['iSumm'] = 6
    p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-10
    p.driver.opt_settings['Major optimality tolerance'] = 1.0E-10
    p.driver.opt_settings['Verify level'] = 1
    p.driver.opt_settings['Function precision'] = 1.0E-6
    p.driver.opt_settings['Linesearch tolerance'] = .1
    p.driver.opt_settings['Major step limit'] = .1
    p.driver.options['dynamic_simul_derivs'] = True


    phase = Phase(transcription, ode_class=MinTimeClimbODE,
                        num_segments=num_seg,
                        transcription_order=transcription_order)

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

    phase.set_time_options(opt_initial=False, duration_bounds=(50, 1e8),
                           duration_ref=100.0)

    phase.set_state_options('r', fix_initial=True, lower=0, upper=1.0E8,
                            scaler=1.0E-4, defect_scaler=1.0E-3, units='m')

    phase.set_state_options('h', fix_initial=True, lower=0, upper=20000.0,
                            scaler=1.0E-3, defect_scaler=1.0E-3, units='m')

    phase.set_state_options('v', fix_initial=True, lower=10.0, upper=500.,
                            scaler=1.0E-2, defect_scaler=1.0E-2, units='m/s')

    phase.set_state_options('gam', fix_initial=True, lower=-1.5, upper=1.5,
                            ref=1.0, defect_scaler=1.0, units='rad')

    phase.set_state_options('m', fix_initial=True, lower=10.0, upper=1.0E5,
                            scaler=1.0E-3, defect_scaler=1.0E-3, units='kg')

    phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0,
                      rate_continuity=True)

    phase.add_design_parameter('S', val=49.2386, units='m**2', opt=False)
    # phase.add_design_parameter('throttle', val=1.0, opt=False)
    phase.add_control('throttle', val=1.0, opt=True, lower=0., upper=1., rate_continuity=False)

    phase.add_boundary_constraint('h', loc='final', equals=100., scaler=1.0E-3, units='m')
    # phase.add_boundary_constraint('aero.mach', loc='final', equals=1., units=None)
    # phase.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad')
    phase.add_boundary_constraint('r', loc='final', equals=1e6, units='m')

    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)
    phase.add_path_constraint(name='prop.m_dot', upper=0.)
    # phase.add_path_constraint(name='flight_dynamics.r_dot', lower=0.)

    # Minimize time at the end of the phase
    # phase.add_objective('time', loc='final', ref=100.0)
    phase.add_objective('m', loc='final', ref=-1000.0)

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

    p.setup(mode='fwd', check=True)

    p['phase.t_initial'] = 0.0
    p['phase.t_duration'] = 2000.
    p['phase.states:r'] = phase.interpolate(ys=[0.0, 1e6], nodes='state_input')
    p['phase.states:h'] = phase.interpolate(ys=[100.0, 1e4], nodes='state_input')
    p['phase.states:v'] = phase.interpolate(ys=[135.964, 283.159], nodes='state_input')
    p['phase.states:gam'] = phase.interpolate(ys=[0.0, 0.0], nodes='state_input')
    p['phase.states:m'] = phase.interpolate(ys=[30e3, 29e3], nodes='state_input')
    # p['phase.controls:alpha'] = phase.interpolate(ys=[0.50, 0.50], nodes='all')

    return p
예제 #12
0
def brachistochrone_min_time(transcription='gauss-lobatto',
                             num_segments=8,
                             transcription_order=3,
                             run_driver=True,
                             compressed=True,
                             optimizer='SLSQP'):
    p = Problem(model=Group())

    # if optimizer == 'SNOPT':
    p.driver = pyOptSparseDriver()
    p.driver.options['optimizer'] = optimizer
    p.driver.options['dynamic_simul_derivs'] = True

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

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

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

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

    phase.set_state_options('x',
                            fix_initial=True,
                            fix_final=False,
                            solve_segments=False)
    phase.set_state_options('y',
                            fix_initial=True,
                            fix_final=False,
                            solve_segments=False)
    phase.set_state_options('v',
                            fix_initial=True,
                            fix_final=False,
                            solve_segments=False)

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

    phase.add_input_parameter('g', 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 = 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.input_parameters:g'] = 9.80665

    p.run_model()

    if run_driver:
        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
예제 #13
0
    def test_min_time_climb_for_docs_gauss_lobatto(self):
        import numpy as np

        import matplotlib
        matplotlib.use('Agg')
        import matplotlib.pyplot as plt

        from openmdao.api import Problem, Group, pyOptSparseDriver, DirectSolver
        from openmdao.utils.assert_utils import assert_rel_error

        from dymos import Phase
        from dymos.examples.min_time_climb.min_time_climb_ode import MinTimeClimbODE

        p = Problem(model=Group())

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

        # Compute sparsity/coloring when run_driver is called
        p.driver.options['dynamic_simul_derivs'] = True

        phase = Phase('gauss-lobatto',
                      ode_class=MinTimeClimbODE,
                      num_segments=12,
                      compressed=True,
                      transcription_order=3)

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

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

        phase.set_state_options('r',
                                fix_initial=True,
                                lower=0,
                                upper=1.0E6,
                                ref=1.0E3,
                                defect_ref=1000.0,
                                units='m')

        phase.set_state_options('h',
                                fix_initial=True,
                                lower=0,
                                upper=20000.0,
                                ref=1.0E2,
                                defect_ref=100.0,
                                units='m')

        phase.set_state_options('v',
                                fix_initial=True,
                                lower=10.0,
                                ref=1.0E2,
                                defect_ref=0.1,
                                units='m/s')

        phase.set_state_options('gam',
                                fix_initial=True,
                                lower=-1.5,
                                upper=1.5,
                                ref=1.0,
                                defect_scaler=1.0,
                                units='rad')

        phase.set_state_options('m',
                                fix_initial=True,
                                lower=10.0,
                                upper=1.0E5,
                                ref=1.0E3,
                                defect_ref=0.1)

        rate_continuity = True

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

        phase.add_design_parameter('S', val=49.2386, units='m**2', opt=False)
        phase.add_design_parameter('Isp', val=1600.0, units='s', opt=False)
        phase.add_design_parameter('throttle', val=1.0, opt=False)

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

        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)
        phase.add_path_constraint(name='alpha', lower=-8, upper=8)

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

        p.driver.options['dynamic_simul_derivs'] = True
        p.model.options['assembled_jac_type'] = 'csc'
        p.model.linear_solver = DirectSolver(assemble_jac=True)

        p.setup(check=True)

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

        p['phase0.states:r'] = phase.interpolate(ys=[0.0, 50000.0],
                                                 nodes='state_input')
        p['phase0.states:h'] = phase.interpolate(ys=[100.0, 20000.0],
                                                 nodes='state_input')
        p['phase0.states:v'] = phase.interpolate(ys=[135.964, 283.159],
                                                 nodes='state_input')
        p['phase0.states:gam'] = phase.interpolate(ys=[0.0, 0.0],
                                                   nodes='state_input')
        p['phase0.states:m'] = phase.interpolate(ys=[19030.468, 10000.],
                                                 nodes='state_input')
        p['phase0.controls:alpha'] = phase.interpolate(ys=[0.0, 0.0],
                                                       nodes='control_input')

        # Solve for the optimal trajectory
        p.run_driver()

        # Test the results
        assert_rel_error(self,
                         p.model.phase0.get_values('time')[-1],
                         321.0,
                         tolerance=2)

        exp_out = phase.simulate(times=50)

        fig, axes = plt.subplots(2, 1, sharex=True)

        axes[0].plot(phase.get_values('time'), phase.get_values('h'), 'ro')
        axes[0].plot(exp_out.get_values('time'), exp_out.get_values('h'), 'b-')
        axes[0].set_xlabel('time (s)')
        axes[0].set_ylabel('altitude (m)')

        axes[1].plot(phase.get_values('time'),
                     phase.get_values('alpha', units='deg'), 'ro')
        axes[1].plot(exp_out.get_values('time'),
                     exp_out.get_values('alpha', units='deg'), 'b-')
        axes[1].set_xlabel('time (s)')
        axes[1].set_ylabel('alpha (deg)')

        plt.show()
예제 #14
0
    def test_brachistochrone_undecorated_ode_rk(self):
        import numpy as np
        import matplotlib
        matplotlib.use('Agg')
        import matplotlib.pyplot as plt
        from openmdao.api import Problem, Group, ScipyOptimizeDriver, DirectSolver
        from openmdao.utils.assert_utils import assert_rel_error
        from dymos import Phase, RungeKutta

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

        phase = Phase(ode_class=BrachistochroneODE,
                      transcription=RungeKutta(num_segments=20))

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

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

        phase.set_state_options('x',
                                fix_initial=True,
                                rate_source='xdot',
                                units='m')
        phase.set_state_options('y',
                                fix_initial=True,
                                rate_source='ydot',
                                units='m')
        phase.set_state_options('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_design_parameter('g',
                                   units='m/s**2',
                                   opt=False,
                                   val=9.80665,
                                   targets=['g'])

        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 = 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_rel_error(self,
                         p.get_val('phase0.timeseries.time')[-1],
                         1.8016,
                         tolerance=1.0E-3)
예제 #15
0
                            defect_scaler=0.01,
                            fix_initial=True,
                            fix_final=False)
    phase.set_state_options('p%dy' % i,
                            scaler=0.1,
                            defect_scaler=0.01,
                            fix_initial=True,
                            fix_final=False)
    # phase.set_state_options('p%dmass' % i,
    #                         scaler=0.01, defect_scaler=0.1, fix_initial=True,
    #                         lower=0.0)
    # phase.set_state_options('p%dimpulse' % i,
    #                         scaler=0.01, defect_scaler=0.1, fix_initial=True)

    phase.add_boundary_constraint('space%d.err_space_dist' % i,
                                  constraint_name='space%d_err_space_dist' % i,
                                  loc='final',
                                  lower=0.0)

    phase.add_design_parameter('speed%d' % i,
                               opt=True,
                               val=1.0,
                               upper=20,
                               lower=1e-9,
                               units='m/s')

    phase.add_design_parameter('heading%d' % i,
                               opt=False,
                               val=heading,
                               units='rad')

phase.add_objective('time', loc='final', scaler=1.0)
    def test_two_phase_cannonball_for_docs(self):
        from openmdao.api import Problem, Group, IndepVarComp, DirectSolver, SqliteRecorder, \
            pyOptSparseDriver
        from openmdao.utils.assert_utils import assert_rel_error

        from dymos import Phase, Trajectory, Radau, GaussLobatto
        from dymos.examples.cannonball.cannonball_ode import CannonballODE

        from dymos.examples.cannonball.size_comp import CannonballSizeComp

        p = Problem(model=Group())

        p.driver = pyOptSparseDriver()
        p.driver.options['optimizer'] = 'SLSQP'
        p.driver.options['dynamic_simul_derivs'] = True

        external_params = p.model.add_subsystem('external_params', 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', Trajectory())

        transcription = Radau(num_segments=5, order=3, compressed=True)
        ascent = Phase(ode_class=CannonballODE, 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)

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

        # Second Phase (descent)
        transcription = GaussLobatto(num_segments=5, order=3, compressed=True)
        descent = Phase(ode_class=CannonballODE, 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)
        descent.set_state_options('r', fix_initial=False, fix_final=False)
        descent.set_state_options('h', fix_initial=False, fix_final=True)
        descent.set_state_options('gam', fix_initial=False, fix_final=False)
        descent.set_state_options('v', fix_initial=False, fix_final=False)

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

        # Add internally-managed design parameters to the trajectory.
        traj.add_design_parameter('CD', val=0.5, units=None, opt=False)
        traj.add_design_parameter('CL', val=0.0, units=None, opt=False)
        traj.add_design_parameter('T', val=0.0, units='N', opt=False)
        traj.add_design_parameter('alpha', val=0.0, units='deg', opt=False)

        # Add externally-provided design parameters to the trajectory.
        traj.add_input_parameter('mass',
                                 target_params={'ascent': 'm', 'descent': 'm'},
                                 val=1.0)

        traj.add_input_parameter('S', 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.input_parameters:mass')
        p.model.connect('size_comp.S', 'traj.input_parameters:S')

        # Finish Problem Setup
        p.model.linear_solver = DirectSolver()

        p.driver.add_recorder(SqliteRecorder('ex_two_phase_cannonball.db'))

        p.setup(check=True)

        # 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.design_parameters:CD', 0.5)
        p.set_val('traj.design_parameters:CL', 0.0)
        p.set_val('traj.design_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')

        p.run_driver()

        assert_rel_error(self, p.get_val('traj.descent.states:r')[-1],
                         3183.25, tolerance=1.0E-2)

        exp_out = traj.simulate()

        print('optimal radius: {0:6.4f} m '.format(p.get_val('external_params.radius',
                                                             units='m')[0]))
        print('cannonball mass: {0:6.4f} kg '.format(p.get_val('size_comp.mass',
                                                               units='kg')[0]))
        print('launch angle: {0:6.4f} '
              'deg '.format(p.get_val('traj.ascent.timeseries.states:gam',  units='deg')[0, 0]))
        print('maximum range: {0:6.4f} '
              'm '.format(p.get_val('traj.descent.timeseries.states:r')[-1, 0]))

        fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(10, 6))

        time_imp = {'ascent': p.get_val('traj.ascent.timeseries.time'),
                    'descent': p.get_val('traj.descent.timeseries.time')}

        time_exp = {'ascent': exp_out.get_val('traj.ascent.timeseries.time'),
                    'descent': exp_out.get_val('traj.descent.timeseries.time')}

        r_imp = {'ascent': p.get_val('traj.ascent.timeseries.states:r'),
                 'descent': p.get_val('traj.descent.timeseries.states:r')}

        r_exp = {'ascent': exp_out.get_val('traj.ascent.timeseries.states:r'),
                 'descent': exp_out.get_val('traj.descent.timeseries.states:r')}

        h_imp = {'ascent': p.get_val('traj.ascent.timeseries.states:h'),
                 'descent': p.get_val('traj.descent.timeseries.states:h')}

        h_exp = {'ascent': exp_out.get_val('traj.ascent.timeseries.states:h'),
                 'descent': exp_out.get_val('traj.descent.timeseries.states:h')}

        axes.plot(r_imp['ascent'], h_imp['ascent'], 'bo')

        axes.plot(r_imp['descent'], h_imp['descent'], 'ro')

        axes.plot(r_exp['ascent'], h_exp['ascent'], 'b--')

        axes.plot(r_exp['descent'], h_exp['descent'], 'r--')

        axes.set_xlabel('range (m)')
        axes.set_ylabel('altitude (m)')

        fig, axes = plt.subplots(nrows=4, ncols=1, figsize=(10, 6))
        states = ['r', 'h', 'v', 'gam']
        for i, state in enumerate(states):
            x_imp = {'ascent': p.get_val('traj.ascent.timeseries.states:{0}'.format(state)),
                     'descent': p.get_val('traj.descent.timeseries.states:{0}'.format(state))}

            x_exp = {'ascent': exp_out.get_val('traj.ascent.timeseries.states:{0}'.format(state)),
                     'descent': exp_out.get_val('traj.descent.timeseries.states:{0}'.format(state))}

            axes[i].set_ylabel(state)

            axes[i].plot(time_imp['ascent'], x_imp['ascent'], 'bo')
            axes[i].plot(time_imp['descent'], x_imp['descent'], 'ro')
            axes[i].plot(time_exp['ascent'], x_exp['ascent'], 'b--')
            axes[i].plot(time_exp['descent'], x_exp['descent'], 'r--')

        params = ['CL', 'CD', 'T', 'alpha', 'm', 'S']
        fig, axes = plt.subplots(nrows=6, ncols=1, figsize=(12, 6))
        for i, param in enumerate(params):
            p_imp = {
                'ascent': p.get_val('traj.ascent.timeseries.traj_parameters:{0}'.format(param)),
                'descent': p.get_val('traj.descent.timeseries.traj_parameters:{0}'.format(param))}

            p_exp = {'ascent': exp_out.get_val('traj.ascent.timeseries.'
                                               'traj_parameters:{0}'.format(param)),
                     'descent': exp_out.get_val('traj.descent.timeseries.'
                                                'traj_parameters:{0}'.format(param))}

            axes[i].set_ylabel(param)

            axes[i].plot(time_imp['ascent'], p_imp['ascent'], 'bo')
            axes[i].plot(time_imp['descent'], p_imp['descent'], 'ro')
            axes[i].plot(time_exp['ascent'], p_exp['ascent'], 'b--')
            axes[i].plot(time_exp['descent'], p_exp['descent'], 'r--')

        plt.show()
                        scaler=1.0E-3, defect_scaler=1.0E-3, units='m')

phase.set_state_options('v', fix_initial=True, lower=0.01,
                        scaler=1.0E-2, defect_scaler=1.0E-2, units='m/s')

phase.set_state_options('gam', fix_initial=True, lower=-1.5, upper=1.5,
                        ref=1.0, defect_scaler=1.0, units='rad')

phase.set_state_options('m', fix_initial=True, lower=1e3, upper=1.0E6,
                        scaler=1.0E-3, defect_scaler=1.0E-3)

phase.add_control('alpha', units='rad', lower=-8. * np.pi/180., upper=8. * np.pi/180., scaler=1, rate_continuity=True)

phase.add_control('throttle', val=1.0, lower=0., upper=1., opt=True, rate_continuity=True)

phase.add_boundary_constraint('h', loc='final', equals=100., scaler=1.0E-3, units='m')
phase.add_boundary_constraint('r', loc='final', equals=1500., units='km')
# phase.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad')

phase.add_path_constraint(name='aero.mach', lower=0.01, upper=.9)
# phase.add_path_constraint(name='prop.m_dot', upper=0.)
# phase.add_path_constraint(name='flight_dynamics.r_dot', lower=0.)
# phase.add_path_constraint(name='m', lower=1e4)
phase.add_path_constraint(name='h', lower=0.)

# phase.set_objective('time', loc='final', ref=10.0)
phase.add_objective('m', loc='final', ref=-10000.0)
# phase.set_objective('r', loc='final', ref=-100000.0)

p.model.linear_solver = DirectSolver(assemble_jac=True)
p.model.options['assembled_jac_type'] = 'csc'
예제 #18
0
def escort_problem(optimizer='SLSQP',
                   num_seg=3,
                   transcription_order=5,
                   transcription='gauss-lobatto',
                   meeting_altitude=14000.,
                   climb_time=350.,
                   starting_mass=19030.468):

    p = Problem(model=Group())

    p.driver = pyOptSparseDriver()
    p.driver.options['optimizer'] = optimizer
    if optimizer == 'SNOPT':
        p.driver.opt_settings['Major iterations limit'] = 1000
        p.driver.opt_settings['Iterations limit'] = 100000000
        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-5
        p.driver.opt_settings['Verify level'] = -1
        p.driver.opt_settings['Function precision'] = 1.0E-6
        p.driver.opt_settings['Linesearch tolerance'] = 0.10
        p.driver.opt_settings['Major step limit'] = 0.5

    phase_class = _phase_map[transcription]

    climb = Phase('gauss-lobatto',
                  ode_class=MinTimeClimbODE,
                  num_segments=num_seg,
                  transcription_order=transcription_order)

    climb.set_time_options(duration_bounds=(50, climb_time),
                           duration_ref=100.0)

    climb.set_state_options('r',
                            fix_initial=True,
                            lower=0,
                            upper=1.0E6,
                            scaler=1.0E-3,
                            defect_scaler=1.0E-2,
                            units='m')

    climb.set_state_options('h',
                            fix_initial=True,
                            lower=0,
                            upper=20000.0,
                            scaler=1.0E-3,
                            defect_scaler=1.0E-3,
                            units='m')

    climb.set_state_options('v',
                            fix_initial=True,
                            lower=10.0,
                            scaler=1.0E-2,
                            defect_scaler=1.0E-2,
                            units='m/s')

    climb.set_state_options('gam',
                            fix_initial=True,
                            lower=-1.5,
                            upper=1.5,
                            ref=1.0,
                            defect_scaler=1.0,
                            units='rad')

    climb.set_state_options('m',
                            fix_initial=True,
                            lower=10.0,
                            upper=1.0E5,
                            scaler=1.0E-3,
                            defect_scaler=1.0E-3)

    climb.add_control('alpha',
                      units='deg',
                      lower=-8.0,
                      upper=8.0,
                      scaler=1.0,
                      rate_continuity=True)

    climb.add_control('S', val=49.2386, units='m**2', dynamic=False, opt=False)
    climb.add_control('Isp', val=5000.0, units='s', dynamic=False, opt=False)
    climb.add_control('throttle', val=1.0, dynamic=False, opt=False)

    climb.add_boundary_constraint('h',
                                  loc='final',
                                  equals=meeting_altitude,
                                  scaler=1.0E-3,
                                  units='m')
    climb.add_boundary_constraint('aero.mach',
                                  loc='final',
                                  equals=1.0,
                                  units=None)
    climb.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad')

    # climb.add_boundary_constraint('time', loc='final', upper=climb_time, units='s')

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

    # Minimize time at the end of the climb
    climb.set_objective('time', loc='final', ref=100.0)

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

    escort = Phase('gauss-lobatto',
                   ode_class=MinTimeClimbODE,
                   num_segments=num_seg * 2,
                   transcription_order=transcription_order)

    escort.set_time_options(duration_bounds=(50, 10000),
                            opt_initial=True,
                            duration_ref=100.0)

    escort.set_state_options('r',
                             lower=0,
                             upper=1.0E6,
                             scaler=1.0E-3,
                             defect_scaler=1.0E-2,
                             units='m')

    escort.set_state_options('h',
                             lower=0,
                             upper=20000.0,
                             scaler=1.0E-3,
                             defect_scaler=1.0E-3,
                             units='m')

    escort.set_state_options('v',
                             lower=10.0,
                             scaler=1.0E-2,
                             defect_scaler=1.0E-2,
                             units='m/s')

    escort.set_state_options('gam',
                             lower=-1.5,
                             upper=1.5,
                             ref=1.0,
                             defect_scaler=1.0,
                             units='rad')

    escort.set_state_options('m',
                             lower=10.0,
                             upper=1.0E5,
                             scaler=1.0E-3,
                             defect_scaler=1.0E-3)

    escort.add_control('alpha',
                       units='deg',
                       lower=-8.0,
                       upper=8.0,
                       scaler=1.0,
                       rate_continuity=True)

    escort.add_control('S',
                       val=49.2386,
                       units='m**2',
                       dynamic=False,
                       opt=False)
    escort.add_control('Isp', val=1600.0, units='s', dynamic=False, opt=False)

    escort.add_control('throttle', val=1.0, lower=0., upper=1., opt=True)
    # escort.add_control('throttle', val=1.0, dynamic=False, opt=False)

    # escort.add_boundary_constraint('h', loc='final', equals=20000, scaler=1.0E-3, units='m')
    # escort.add_boundary_constraint('aero.mach', loc='final', equals=1.0, units=None)
    # escort.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad')
    escort.add_boundary_constraint('m',
                                   loc='final',
                                   equals=15000.0,
                                   units='kg')

    escort.add_path_constraint(name='h',
                               lower=meeting_altitude,
                               upper=meeting_altitude,
                               ref=meeting_altitude)
    escort.add_path_constraint(name='aero.mach', equals=1.0)

    # Maximize distance at the end of the escort
    # escort.set_objective('r', loc='final', ref=-1e5)

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

    # Connect the phases
    linkage_comp = PhaseLinkageComp()
    linkage_comp.add_linkage(name='L01',
                             vars=['t'],
                             units='s',
                             equals=0.0,
                             linear=True)
    linkage_comp.add_linkage(name='L01',
                             vars=['r'],
                             units='m',
                             equals=0.0,
                             linear=True)
    linkage_comp.add_linkage(name='L01',
                             vars=['h'],
                             units='m',
                             equals=0.0,
                             linear=True)
    linkage_comp.add_linkage(name='L01',
                             vars=['v'],
                             units='m/s',
                             equals=0.0,
                             linear=True)
    linkage_comp.add_linkage(name='L01',
                             vars=['gam'],
                             units='rad',
                             equals=0.0,
                             linear=True)
    linkage_comp.add_linkage(name='L01',
                             vars=['m'],
                             units='kg',
                             equals=0.0,
                             linear=True)
    linkage_comp.add_linkage(name='L01',
                             vars=['alpha'],
                             units='rad',
                             equals=0.0,
                             linear=True)
    linkage_comp.add_linkage(name='L01',
                             vars=['throttle'],
                             equals=0.0,
                             linear=True)

    p.model.connect('climb.time++', 'linkages.L01_t:lhs')
    p.model.connect('escort.time--', 'linkages.L01_t:rhs')

    p.model.connect('climb.states:r++', 'linkages.L01_r:lhs')
    p.model.connect('escort.states:r--', 'linkages.L01_r:rhs')

    p.model.connect('climb.states:h++', 'linkages.L01_h:lhs')
    p.model.connect('escort.states:h--', 'linkages.L01_h:rhs')
    #
    p.model.connect('climb.states:v++', 'linkages.L01_v:lhs')
    p.model.connect('escort.states:v--', 'linkages.L01_v:rhs')
    #
    p.model.connect('climb.states:gam++', 'linkages.L01_gam:lhs')
    p.model.connect('escort.states:gam--', 'linkages.L01_gam:rhs')

    p.model.connect('climb.states:m++', 'linkages.L01_m:lhs')
    p.model.connect('escort.states:m--', 'linkages.L01_m:rhs')

    p.model.connect('climb.controls:alpha++', 'linkages.L01_alpha:lhs')
    p.model.connect('escort.controls:alpha--', 'linkages.L01_alpha:rhs')

    p.model.connect('climb.controls:throttle++', 'linkages.L01_throttle:lhs')
    p.model.connect('escort.controls:throttle--', 'linkages.L01_throttle:rhs')

    p.model.add_subsystem('linkages', linkage_comp)

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

    # p.driver.add_recorder(SqliteRecorder('escort.db'))

    p.setup(mode='fwd', check=True)

    p['climb.t_initial'] = 0.0
    p['climb.t_duration'] = 200.
    p['climb.states:r'] = climb.interpolate(ys=[0.0, 111319.54], nodes='disc')
    p['climb.states:h'] = climb.interpolate(ys=[100.0, 20000.0], nodes='disc')
    p['climb.states:v'] = climb.interpolate(ys=[135.964, 283.159],
                                            nodes='disc')
    p['climb.states:gam'] = climb.interpolate(ys=[0.0, 0.0], nodes='disc')
    p['climb.states:m'] = climb.interpolate(ys=[starting_mass, 16841.431],
                                            nodes='disc')
    p['climb.controls:alpha'] = climb.interpolate(ys=[0.0, 0.0], nodes='all')

    p['escort.t_initial'] = 200.
    p['escort.t_duration'] = 1000.
    p['escort.states:r'] = escort.interpolate(ys=[111319.54, 400000.],
                                              nodes='disc')
    p['escort.states:h'] = escort.interpolate(
        ys=[meeting_altitude, meeting_altitude], nodes='disc')
    p['escort.states:v'] = escort.interpolate(ys=[250., 250.], nodes='disc')
    p['escort.states:gam'] = escort.interpolate(ys=[0.0, 0.0], nodes='disc')
    p['escort.states:m'] = escort.interpolate(ys=[17000., 15000.],
                                              nodes='disc')
    p['escort.controls:alpha'] = escort.interpolate(ys=[0.0, 0.0], nodes='all')

    return p
def thermal_mission_problem(num_seg=5, transcription_order=3, meeting_altitude=20000., Q_env=0., Q_sink=0., Q_out=0., m_recirculated=0., opt_m_recirculated=False, opt_m_burn=False, opt_throttle=True, engine_heat_coeff=0., pump_heat_coeff=0., T=None, T_o=None, opt_m=False, m_initial=20.e3, transcription='gauss-lobatto'):

    p = Problem(model=Group())

    p.driver = pyOptSparseDriver()
    p.driver.options['optimizer'] = 'SNOPT'
    p.driver.opt_settings['Major iterations limit'] = 5000
    p.driver.opt_settings['Iterations limit'] = 5000000000000000
    p.driver.opt_settings['iSumm'] = 6
    p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-8
    p.driver.opt_settings['Major optimality tolerance'] = 1.0E-8
    p.driver.opt_settings['Verify level'] = -1
    p.driver.opt_settings['Linesearch tolerance'] = .1
    p.driver.opt_settings['Major step limit'] = .1
    p.driver.options['dynamic_simul_derivs'] = True

    phase = Phase(transcription, ode_class=ThermalMissionODE,
                        ode_init_kwargs={'engine_heat_coeff':engine_heat_coeff, 'pump_heat_coeff':pump_heat_coeff}, num_segments=num_seg,
                        transcription_order=transcription_order)

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

    phase.set_time_options(opt_initial=False, duration_bounds=(50, 400),
                           duration_ref=100.0)

    phase.set_state_options('r', fix_initial=True, lower=0, upper=1.0E6,
                            scaler=1.0E-3, defect_scaler=1.0E-2, units='m')

    phase.set_state_options('h', fix_initial=True, lower=0, upper=20000.0,
                            scaler=1.0E-3, defect_scaler=1.0E-3, units='m')

    phase.set_state_options('v', fix_initial=True, lower=10.0,
                            scaler=1.0E-2, defect_scaler=5.0E-0, units='m/s')

    phase.set_state_options('gam', fix_initial=True, lower=-1.5, upper=1.5,
                            ref=1.0, defect_scaler=1.0, units='rad')

    phase.set_state_options('m', fix_initial=not opt_m, lower=15.e3, upper=80e3,
                            scaler=1.0E-3, defect_scaler=1.0E-3, units='kg')

    phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0,
                      rate_continuity=True)

    phase.add_design_parameter('S', val=1., units='m**2', opt=False)

    if opt_throttle:
        phase.add_control('throttle', val=1.0, lower=0.0, upper=1.0, opt=True, rate_continuity=True)
    else:
        phase.add_design_parameter('throttle', val=1.0, opt=False)

    phase.add_design_parameter('W0', val=10.5e3, opt=False, units='kg')

    phase.add_boundary_constraint('h', loc='final', equals=meeting_altitude, scaler=1.0E-3, units='m')
    phase.add_boundary_constraint('aero.mach', loc='final', equals=1., units=None)
    phase.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad')

    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)
    # phase.add_path_constraint(name='time', upper=110.)

    # Minimize time at the end of the phase
    phase.add_objective('time', loc='final', ref=100.0)
    # phase.add_objective('energy', loc='final', ref=100.0)
    # phase.add_objective('m', loc='final', ref=-10000.0)

    # Set the state options for mass, temperature, and energy.
    phase.set_state_options('T', fix_initial=True, ref=300, defect_scaler=1e-2)
    phase.set_state_options('energy', fix_initial=True, ref=10e3, defect_scaler=1e-4)

    # Allow the optimizer to vary the fuel flow
    if opt_m_recirculated:
        phase.add_control('m_recirculated', val=m_recirculated, lower=0., opt=True, rate_continuity=True, ref=20.)
    else:
        phase.add_control('m_recirculated', val=m_recirculated, opt=False)

    phase.add_design_parameter('Q_env', val=Q_env, opt=False)
    phase.add_design_parameter('Q_sink', val=Q_sink, opt=False)
    phase.add_design_parameter('Q_out', val=Q_out, opt=False)

    # Constrain the temperature, 2nd derivative of fuel mass in the tank, and make
    # sure that the amount recirculated is at least 0, otherwise we'd burn
    # more fuel than we pumped.
    if opt_m_recirculated:
        phase.add_path_constraint('m_flow', lower=0., upper=50., units='kg/s', ref=10.)

    if T is not None:
        phase.add_path_constraint('T', upper=T, units='K')

    if T_o is not None:
        phase.add_path_constraint('T_o', upper=T_o, units='K', ref=300.)

    # phase.add_path_constraint('m_flow', lower=0., upper=20., units='kg/s', ref=10.)

    p.setup(mode='fwd', check=True)

    p['phase.t_initial'] = 0.0
    p['phase.t_duration'] = 200.
    p['phase.states:r'] = phase.interpolate(ys=[0.0, 111319.54], nodes='state_input')
    p['phase.states:h'] = phase.interpolate(ys=[100.0, meeting_altitude], nodes='state_input')
    # p['phase.states:h'][:] = 10000.

    p['phase.states:v'] = phase.interpolate(ys=[135.964, 283.159], nodes='state_input')
    # p['phase.states:v'][:] = 200.
    p['phase.states:gam'] = phase.interpolate(ys=[0.0, 0.0], nodes='state_input')
    p['phase.states:m'] = phase.interpolate(ys=[m_initial, 12.e3], nodes='state_input')
    p['phase.controls:alpha'] = phase.interpolate(ys=[1., 1.], nodes='control_input')

    # Give initial values for the phase states, controls, and time
    p['phase.states:T'] = 310.

    return p
예제 #20
0
    def test_control_rate2_boundary_constraint_gl(self):
        p = Problem(model=Group())

        p.driver = ScipyOptimizeDriver()

        p.driver.options['dynamic_simul_derivs'] = True

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

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

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

        phase.set_state_options('x', fix_initial=True, fix_final=True)
        phase.set_state_options('y', fix_initial=True, fix_final=True)
        phase.set_state_options('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_design_parameter('g', units='m/s**2', opt=False, 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 = 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.design_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_rel_error(
            self,
            p.get_val('phase0.timeseries.control_rates:theta_rate2')[-1],
            0,
            tolerance=1.0E-6)
예제 #21
0
    def test_two_phase_cannonball_for_docs(self):
        from openmdao.api import Problem, Group, IndepVarComp, DirectSolver, SqliteRecorder, \
            pyOptSparseDriver
        from openmdao.utils.assert_utils import assert_rel_error

        from dymos import Phase, Trajectory, load_simulation_results
        from dymos.examples.cannonball.cannonball_ode import CannonballODE

        from dymos.examples.cannonball.size_comp import CannonballSizeComp

        p = Problem(model=Group())

        p.driver = pyOptSparseDriver()
        p.driver.options['optimizer'] = 'SLSQP'
        p.driver.options['dynamic_simul_derivs'] = True

        external_params = p.model.add_subsystem('external_params',
                                                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', Trajectory())

        # First Phase (ascent)
        ascent = Phase('radau-ps',
                       ode_class=CannonballODE,
                       num_segments=5,
                       transcription_order=3,
                       compressed=True)

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

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

        # Second Phase (descent)
        descent = Phase('gauss-lobatto',
                        ode_class=CannonballODE,
                        num_segments=5,
                        transcription_order=3,
                        compressed=True)

        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)
        descent.set_state_options('r', fix_initial=False, fix_final=False)
        descent.set_state_options('h', fix_initial=False, fix_final=True)
        descent.set_state_options('gam', fix_initial=False, fix_final=False)
        descent.set_state_options('v', fix_initial=False, fix_final=False)

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

        # Add internally-managed design parameters to the trajectory.
        traj.add_design_parameter('CD', val=0.5, units=None, opt=False)
        traj.add_design_parameter('CL', val=0.0, units=None, opt=False)
        traj.add_design_parameter('T', val=0.0, units='N', opt=False)
        traj.add_design_parameter('alpha', val=0.0, units='deg', opt=False)

        # Add externally-provided design parameters to the trajectory.
        traj.add_input_parameter('mass',
                                 targets={
                                     'ascent': 'm',
                                     'descent': 'm'
                                 },
                                 val=1.0,
                                 units='kg')

        traj.add_input_parameter('S', val=0.005, units='m**2')

        # 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.input_parameters:mass')
        p.model.connect('size_comp.S', 'traj.input_parameters:S')

        # Finish Problem Setup
        p.model.options['assembled_jac_type'] = 'csc'
        p.model.linear_solver = DirectSolver(assemble_jac=True)

        p.driver.add_recorder(SqliteRecorder('ex_two_phase_cannonball.db'))

        p.setup(check=True)

        # 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.design_parameters:CD', 0.5)
        p.set_val('traj.design_parameters:CL', 0.0)
        p.set_val('traj.design_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')

        p.run_driver()

        assert_rel_error(self,
                         traj.get_values('r')['descent'][-1],
                         3191.83945861,
                         tolerance=1.0E-2)

        exp_out = traj.simulate(times=100,
                                record_file='ex_two_phase_cannonball_sim.db')

        # exp_out_loaded = load_simulation_results('ex_two_phase_cannonball_sim.db')

        print('optimal radius: {0:6.4f} m '.format(
            p.get_val('external_params.radius', units='m')[0]))
        print('cannonball mass: {0:6.4f} kg '.format(
            p.get_val('size_comp.mass', units='kg')[0]))

        fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(8, 6))

        axes[0].plot(
            traj.get_values('r')['ascent'],
            traj.get_values('h')['ascent'], 'bo')

        axes[0].plot(
            traj.get_values('r')['descent'],
            traj.get_values('h')['descent'], 'ro')

        axes[0].plot(
            exp_out.get_values('r')['ascent'],
            exp_out.get_values('h')['ascent'], 'b--')

        axes[0].plot(
            exp_out.get_values('r')['descent'],
            exp_out.get_values('h')['descent'], 'r--')

        axes[0].set_xlabel('range (m)')
        axes[0].set_ylabel('altitude (m)')

        # plt.suptitle('Kinetic Energy vs Time')

        axes[1].plot(
            traj.get_values('time')['ascent'],
            traj.get_values('kinetic_energy.ke')['ascent'], 'bo')

        axes[1].plot(
            traj.get_values('time')['descent'],
            traj.get_values('kinetic_energy.ke')['descent'], 'ro')

        axes[1].plot(
            exp_out.get_values('time')['ascent'],
            exp_out.get_values('kinetic_energy.ke')['ascent'], 'b--')

        axes[1].plot(
            exp_out.get_values('time')['descent'],
            exp_out.get_values('kinetic_energy.ke')['descent'], 'r--')

        # axes[1].plot(exp_out_loaded.get_values('time')['ascent'],
        #              exp_out_loaded.get_values('kinetic_energy.ke')['ascent'],
        #              'b--')
        #
        # axes[1].plot(exp_out_loaded.get_values('time')['descent'],
        #              exp_out_loaded.get_values('kinetic_energy.ke')['descent'],
        #              'r--')

        axes[1].set_xlabel('time (s)')
        axes[1].set_ylabel(r'kinetic energy (J)')

        # plt.figure()

        axes[2].plot(
            traj.get_values('time')['ascent'],
            traj.get_values('gam', units='deg')['ascent'], 'bo')
        axes[2].plot(
            traj.get_values('time')['descent'],
            traj.get_values('gam', units='deg')['descent'], 'ro')

        axes[2].plot(
            exp_out.get_values('time')['ascent'],
            exp_out.get_values('gam', units='deg')['ascent'], 'b--')

        axes[2].plot(
            exp_out.get_values('time')['descent'],
            exp_out.get_values('gam', units='deg')['descent'], 'r--')

        axes[2].set_xlabel('time (s)')
        axes[2].set_ylabel(r'flight path angle (deg)')

        plt.show()
    def test_brachistochrone_vector_ode_path_constraints_rk_partial_indices(
            self):

        p = Problem(model=Group())

        p.driver = ScipyOptimizeDriver()
        p.driver.options['dynamic_simul_derivs'] = True

        phase = Phase(ode_class=BrachistochroneVectorStatesODE,
                      transcription=RungeKutta(num_segments=20))

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

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

        phase.set_state_options('pos', fix_initial=True, fix_final=False)
        phase.set_state_options('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_design_parameter('g', units='m/s**2', opt=False, val=9.80665)

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

        phase.add_path_constraint('pos_dot',
                                  shape=(2, ),
                                  units='m/s',
                                  indices=[1],
                                  lower=-4,
                                  upper=4)

        phase.add_timeseries_output('pos_dot', shape=(2, ), units='m/s')

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

        p.model.linear_solver = 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,
                         np.min(p.get_val('phase0.timeseries.pos_dot')[:, -1]),
                         -4,
                         tolerance=1.0E-2)

        # Plot results
        if SHOW_PLOTS:
            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\nVelocity')

            t_imp = p.get_val('phase0.timeseries.time')
            t_exp = exp_out.get_val('phase0.timeseries.time')

            xdot_imp = p.get_val('phase0.timeseries.pos_dot')[:, 0]
            ydot_imp = p.get_val('phase0.timeseries.pos_dot')[:, 1]

            xdot_exp = exp_out.get_val('phase0.timeseries.pos_dot')[:, 0]
            ydot_exp = exp_out.get_val('phase0.timeseries.pos_dot')[:, 1]

            ax.plot(t_imp, xdot_imp, 'bo', label='implicit')
            ax.plot(t_exp, xdot_exp, 'b-', label='explicit')

            ax.plot(t_imp, ydot_imp, 'ro', label='implicit')
            ax.plot(t_exp, ydot_exp, 'r-', label='explicit')

            ax.set_xlabel('t (s)')
            ax.set_ylabel('v (m/s)')
            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
예제 #23
0
    def test_design_parameter_boundary_constraint(self):
        p = Problem(model=Group())

        p.driver = ScipyOptimizeDriver()
        p.driver.options['dynamic_simul_derivs'] = True

        phase = Phase(ode_class=BrachistochroneODE,
                      transcription=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.set_state_options('x', fix_initial=True, fix_final=True)
        phase.set_state_options('y', fix_initial=True, fix_final=True)
        phase.set_state_options('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_design_parameter('g', units='m/s**2', opt=True, val=9.80665)

        # We'll let g vary, but make sure it hits the desired value.
        # It's a static design 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 = 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.design_parameters:g'] = 5

        p.run_driver()

        assert_rel_error(self,
                         p.get_val('phase0.timeseries.time')[-1],
                         1.8016,
                         tolerance=1.0E-4)
        assert_rel_error(self,
                         p.get_val('phase0.timeseries.design_parameters:g')[0],
                         9.80665,
                         tolerance=1.0E-6)
        assert_rel_error(
            self,
            p.get_val('phase0.timeseries.design_parameters:g')[-1],
            9.80665,
            tolerance=1.0E-6)
예제 #24
0
    end_y = center_y + r * np.sin(theta + theta2)

    locations.append([start_x, end_x, start_y, end_y])
    #print("location", i, locations[-1])
    phase.add_input_parameter('sx%d' % i, val=start_x, units='m')
    phase.add_input_parameter('sy%d' % i, val=start_y, units='m')
    phase.add_input_parameter('ex%d' % i, val=end_x, units='m')
    phase.add_input_parameter('ey%d' % i, val=end_y, units='m')

    phase.add_input_parameter('ts%d' % i, val=t_start, units='s')
    phase.add_input_parameter('te%d' % i, val=t_end, units='s')

    phase.set_state_options('x%d' % i, scaler=0.01, defect_scaler=0.1)
    phase.set_state_options('y%d' % i, scaler=0.01, defect_scaler=0.1)

    phase.add_boundary_constraint('x%d' % i, loc='initial', equals=start_x)
    phase.add_boundary_constraint('y%d' % i, loc='initial', equals=start_y)
    phase.add_boundary_constraint('x%d' % i, loc='final', equals=end_x)
    phase.add_boundary_constraint('y%d' % i, loc='final', equals=end_y)
    # phase.set_state_options('v%d' % i, fix_initial=False, fix_final=False,
    #                     scaler=0.01, defect_scaler=0.01, lower=0.0)

    phase.add_control('vx%d' % i,
                      rate_continuity=False,
                      units='m/s',
                      opt=True,
                      upper=10,
                      lower=-10.0,
                      scaler=200.0,
                      adder=-10)
    phase.add_control('vy%d' % i,
예제 #25
0
def min_time_climb(optimizer='SLSQP', num_seg=3, transcription='gauss-lobatto',
                   transcription_order=3, top_level_jacobian='csc', simul_derivs=True,
                   force_alloc_complex=False):

    p = Problem(model=Group())

    p.driver = pyOptSparseDriver()
    p.driver.options['optimizer'] = optimizer
    if simul_derivs:
        p.driver.options['dynamic_simul_derivs'] = True

    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-6
        p.driver.opt_settings['Linesearch tolerance'] = 0.10
        p.driver.opt_settings['Major step limit'] = 0.5
        # p.driver.opt_settings['Verify level'] = 3

    phase = Phase(transcription,
                  ode_class=MinTimeClimbODE,
                  num_segments=num_seg,
                  compressed=True,
                  transcription_order=transcription_order)

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

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

    phase.set_state_options('r', fix_initial=True, lower=0, upper=1.0E6,
                            scaler=1.0E-3, defect_scaler=1.0E-2, units='m')

    phase.set_state_options('h', fix_initial=True, lower=0, upper=20000.0,
                            scaler=1.0E-3, defect_scaler=1.0E-3, units='m')

    phase.set_state_options('v', fix_initial=True, lower=10.0,
                            scaler=1.0E-2, defect_scaler=1.0E-2, units='m/s')

    phase.set_state_options('gam', fix_initial=True, lower=-1.5, upper=1.5,
                            ref=1.0, defect_scaler=1.0, units='rad')

    phase.set_state_options('m', fix_initial=True, lower=10.0, upper=1.0E5,
                            scaler=1.0E-3, defect_scaler=1.0E-3)

    phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0,
                      continuity=True, rate_continuity=True, rate2_continuity=False)

    phase.add_design_parameter('S', val=49.2386, units='m**2', opt=False)
    phase.add_design_parameter('Isp', val=1600.0, units='s', opt=False)
    phase.add_design_parameter('throttle', val=1.0, opt=False)

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

    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)
    phase.add_path_constraint(name='alpha', lower=-8, upper=8)

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

    p.model.options['assembled_jac_type'] = top_level_jacobian.lower()
    p.model.linear_solver = DirectSolver(assemble_jac=True)

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

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

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

    p.run_driver()

    if SHOW_PLOTS:
        exp_out = phase.simulate(times=np.linspace(0, p['phase0.t_duration'], 100))

        import matplotlib.pyplot as plt
        plt.plot(phase.get_values('time'), phase.get_values('h'), 'ro')
        plt.plot(exp_out.get_values('time'), exp_out.get_values('h'), 'b-')
        plt.xlabel('time (s)')
        plt.ylabel('altitude (m)')

        plt.figure()
        plt.plot(phase.get_values('v'), phase.get_values('h'), 'ro')
        plt.plot(exp_out.get_values('v'), exp_out.get_values('h'), 'b-')
        plt.xlabel('airspeed (m/s)')
        plt.ylabel('altitude (m)')

        plt.figure()
        plt.plot(phase.get_values('time'), phase.get_values('alpha'), 'ro')
        plt.plot(exp_out.get_values('time'), exp_out.get_values('alpha'), 'b-')
        plt.xlabel('time (s)')
        plt.ylabel('alpha (rad)')

        plt.figure()
        plt.plot(phase.get_values('time'), phase.get_values('prop.thrust', units='lbf'), 'ro')
        plt.plot(exp_out.get_values('time'), exp_out.get_values('prop.thrust', units='lbf'), 'b-')
        plt.xlabel('time (s)')
        plt.ylabel('thrust (lbf)')

        plt.show()

    return p