def test_brachistochrone_backward_shooting(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=(-2.0, -0.5)) phase.set_state_options('x', fix_initial=True) phase.set_state_options('y', fix_initial=True) phase.set_state_options('v', fix_initial=False) 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=0) phase.add_boundary_constraint('y', loc='final', equals=10) phase.add_boundary_constraint('v', loc='final', equals=0) # Minimize time at the end of the phase phase.add_objective('time', loc='final', scaler=-1) p.model.linear_solver = DirectSolver() p.setup(check=True) p['phase0.t_initial'] = 1.8016 p['phase0.t_duration'] = -1.8016 p['phase0.states:x'] = 10 p['phase0.states:y'] = 5 p['phase0.states:v'] = 10 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], 0, tolerance=1.0E-3) assert_rel_error(self, exp_out.get_val('phase0.timeseries.states:y')[-1, 0], 10, tolerance=1.0E-3)
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)
def test_control_rate_path_constraint_gl(self): from openmdao.api import Problem, Group, ScipyOptimizeDriver, DirectSolver from openmdao.utils.assert_utils import assert_rel_error from dymos import Phase, GaussLobatto from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() phase = Phase(ode_class=BrachistochroneODE, transcription=GaussLobatto(num_segments=10)) p.model.add_subsystem('phase0', phase) phase.set_time_options(initial_bounds=(0, 0), 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) phase.add_control('theta', units='deg', rate_continuity=False, 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_path_constraint('theta_rate', lower=0, upper=100, units='deg/s') 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)
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
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()
def setUpClass(cls): import matplotlib matplotlib.use('Agg') from openmdao.api import Problem, Group, ScipyOptimizeDriver, DirectSolver from dymos import Phase, load_simulation_results from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() phase = Phase('gauss-lobatto', ode_class=BrachistochroneODE, num_segments=10) p.model.add_subsystem('phase0', phase) phase.set_time_options(initial_bounds=(0, 0), 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) phase.add_control('theta', units='rad', rate_continuity=False, lower=0.001, upper=3.14) 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) p.model.linear_solver = DirectSolver(assemble_jac=True) p.model.options['assembled_jac_type'] = 'csc' p.setup() p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 2.0 p['phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input') p['phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100.5], nodes='control_input') # Solve for the optimal trajectory p.run_driver() cls.exp_out = phase.simulate( times=100, record_file='phase_simulation_test_sim.db') cls.exp_out_loaded = load_simulation_results( 'phase_simulation_test_sim.db')
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')
def setUpClass(cls): p = cls.p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = 'SNOPT' p.driver.options['dynamic_simul_derivs'] = True p.driver.opt_settings['Major iterations limit'] = 100 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6 p.driver.opt_settings['iSumm'] = 6 phase = Phase('radau-ps', ode_class=CadreOrbitODE, num_segments=10, transcription_order=7, compressed=False) p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(duration, duration)) phase.set_state_options('r_e2b_I', defect_scaler=1000, fix_initial=True, units='km') phase.set_state_options('v_e2b_I', defect_scaler=1000, fix_initial=True, units='km/s') # phase.set_state_options('SOC', defect_scaler=1, fix_initial=True, units=None) # phase.add_design_parameter('P_bat', opt=False, units='W') phase.add_design_parameter('Gamma', opt=False, units='rad') phase.add_objective('time', loc='final', scaler=10) # p.model.options['assembled_jac_type'] = 'csc' # p.model.linear_solver = DirectSolver(assemble_jac=True) p.setup(check=True, force_alloc_complex=True) p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = duration # print(phase.grid_data.num_nodes) # p['phase0.states:r_e2b_I'][:, 0] = rmag p['phase0.states:r_e2b_I'][:, 1] = 0.0 p['phase0.states:r_e2b_I'][:, 2] = 0.0 p['phase0.states:v_e2b_I'][:, 0] = 0.0 p['phase0.states:v_e2b_I'][:, 1] = vcirc p['phase0.states:v_e2b_I'][:, 2] = 0.0 # p['phase0.design_parameters:P_bat'] = 2.0 p['phase0.design_parameters:Gamma'] = 0.0 p.run_model() p.run_driver()
def test_add_existing_control_as_design_parameter(self): p = Phase(ode_class=BrachistochroneODE, transcription=GaussLobatto(num_segments=8, order=3)) p.add_control('theta') with self.assertRaises(ValueError) as e: p.add_design_parameter('theta') expected = 'theta has already been added as a control.' self.assertEqual(str(e.exception), expected)
def test_objective_design_parameter_radau(self): p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() p.driver.options['dynamic_simul_derivs'] = True phase = Phase(ode_class=BrachistochroneODE, transcription=Radau(num_segments=20, order=3, compressed=True)) p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(4, 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) # Minimize time at the end of the phase phase.add_objective('g') p.model.options['assembled_jac_type'] = 'csc' 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'] = 9.80665 p.run_driver() assert_rel_error(self, p['phase0.t_duration'], 10, tolerance=1.0E-3)
def test_add_existing_design_parameter_as_input_parameter(self): p = Phase(ode_class=_A, transcription=GaussLobatto(num_segments=14, order=3, compressed=True)) p.add_design_parameter('theta') with self.assertRaises(ValueError) as e: p.add_input_parameter('theta') expected = 'theta has already been added as a design parameter.' self.assertEqual(str(e.exception), expected)
def test_invalid_design_parameter_name(self): p = Phase('gauss-lobatto', ode_class=BrachistochroneODE, num_segments=8, transcription_order=3) with self.assertRaises(ValueError) as e: p.add_design_parameter('foo') expected = 'foo is not a controllable parameter in the ODE system.' self.assertEqual(str(e.exception), expected)
def test_add_existing_design_parameter_as_input_parameter(self): p = Phase('gauss-lobatto', ode_class=BrachistochroneODE, num_segments=8, transcription_order=3) p.add_design_parameter('theta') with self.assertRaises(ValueError) as e: p.add_input_parameter('theta') expected = 'theta has already been added as a design parameter.' self.assertEqual(str(e.exception), expected)
def test_invalid_options_nonoptimal_design_param(self): p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() p.driver.options['dynamic_simul_derivs'] = True phase = Phase(ode_class=BrachistochroneODE, transcription=GaussLobatto(num_segments=16, order=3, compressed=True)) p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(4, 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, opt=False) phase.add_design_parameter('g', units='m/s**2', opt=False, lower=5, upper=10, ref0=5, ref=10, scaler=1, adder=0) # Minimize time at the end of the phase phase.add_objective('g') p.model.linear_solver = DirectSolver() with warnings.catch_warnings(record=True) as w: warnings.simplefilter('always') p.setup(check=False) print('\n'.join([str(ww.message) for ww in w])) expected = 'Invalid options for non-optimal design_parameter \'g\' in phase \'phase0\': ' \ 'lower, upper, scaler, adder, ref, ref0' self.assertIn(expected, [str(ww.message) for ww in w])
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])
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])
def test_invalid_options_nonoptimal_design_param(self): p = Phase('gauss-lobatto', ode_class=BrachistochroneODE, num_segments=8, transcription_order=3) with warnings.catch_warnings(record=True) as w: warnings.simplefilter('always') p.add_design_parameter('g', opt=False, lower=5, upper=10, ref0=5, ref=10, scaler=1, adder=0) expected = 'Invalid options for non-optimal design parameter "g":' \ 'lower, upper, scaler, adder, ref, ref0' self.assertEqual(len(w), 1) self.assertEqual(str(w[0].message), expected)
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
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
def test_invalid_ode_wrong_class(self): p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() p.driver.options['dynamic_simul_derivs'] = True phase = Phase(ode_class=_A, transcription=GaussLobatto(num_segments=20, order=3, compressed=True)) p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(4, 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, opt=False) phase.add_design_parameter('g', units='m/s**2', opt=True, val=9.80665) # Minimize time at the end of the phase phase.add_objective('g') p.model.linear_solver = DirectSolver() with self.assertRaises(ValueError) as e: p.setup(check=True) self.assertEqual( str(e.exception), 'ode_class must be derived from openmdao.core.System.')
def test_brachistochrone_for_docs_gauss_lobatto_without_simul_derivs(self): from openmdao.api import Problem, Group, pyOptSparseDriver, DirectSolver from openmdao.utils.assert_utils import assert_rel_error from dymos import Phase from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' phase = Phase('gauss-lobatto', ode_class=BrachistochroneODE, num_segments=100, transcription_order=3, compressed=True) p.model.add_subsystem('phase0', phase) phase.set_time_options(initial_bounds=(0, 0), 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) phase.add_control('theta', units='deg', rate_continuity=False, 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) p.model.linear_solver = DirectSolver(assemble_jac=True) p.model.options['assembled_jac_type'] = 'csc' p.setup() p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 2.0 p['phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input') p['phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100.5], nodes='control_input') # Solve for the optimal trajectory p.run_driver() # Test the results assert_rel_error(self, phase.get_values('time')[-1], 1.8016, tolerance=1.0E-3)
def test_two_burn_orbit_raise_gl_rk_gl_constrained(self): import numpy as np import matplotlib.pyplot as plt from openmdao.api import Problem, Group, pyOptSparseDriver, DirectSolver from openmdao.utils.assert_utils import assert_rel_error from openmdao.utils.general_utils import set_pyoptsparse_opt from dymos import Phase, GaussLobatto, RungeKutta, Trajectory from dymos.examples.finite_burn_orbit_raise.finite_burn_eom import FiniteBurnODE traj = Trajectory() p = Problem(model=Group()) p.model.add_subsystem('traj', traj) p.driver = pyOptSparseDriver() _, optimizer = set_pyoptsparse_opt('SNOPT', fallback=True) p.driver.options['optimizer'] = optimizer p.driver.options['dynamic_simul_derivs'] = True traj.add_design_parameter('c', opt=False, val=1.5, units='DU/TU') # First Phase (burn) burn1 = Phase(ode_class=FiniteBurnODE, transcription=GaussLobatto(num_segments=10, order=3, compressed=True)) burn1 = traj.add_phase('burn1', burn1) burn1.set_time_options(fix_initial=True, duration_bounds=(.5, 10)) burn1.set_state_options('r', fix_initial=True, fix_final=False) burn1.set_state_options('theta', fix_initial=True, fix_final=False) burn1.set_state_options('vr', fix_initial=True, fix_final=False) burn1.set_state_options('vt', fix_initial=True, fix_final=False) burn1.set_state_options('accel', fix_initial=True, fix_final=False) burn1.set_state_options('deltav', fix_initial=True, fix_final=False) burn1.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg', scaler=0.01, lower=-30, upper=30) # Second Phase (Coast) coast = Phase(ode_class=FiniteBurnODE, transcription=RungeKutta(num_segments=20, compressed=True)) traj.add_phase('coast', coast) coast.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), duration_ref=10) coast.set_state_options('r', fix_initial=False, fix_final=False) coast.set_state_options('theta', fix_initial=False, fix_final=False) coast.set_state_options('vr', fix_initial=False, fix_final=False) coast.set_state_options('vt', fix_initial=False, fix_final=False) coast.set_state_options('accel', fix_initial=True, fix_final=False) coast.set_state_options('deltav', fix_initial=False, fix_final=False) coast.add_design_parameter('u1', opt=False, val=0.0) # Third Phase (burn) burn2 = Phase(ode_class=FiniteBurnODE, transcription=GaussLobatto(num_segments=10, order=3, compressed=True)) traj.add_phase('burn2', burn2) burn2.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), initial_ref=10) burn2.set_state_options('r', fix_initial=False, fix_final=True) burn2.set_state_options('theta', fix_initial=False, fix_final=False) burn2.set_state_options('vr', fix_initial=False, fix_final=True) burn2.set_state_options('vt', fix_initial=False, fix_final=True) burn2.set_state_options('accel', fix_initial=False, fix_final=False, defect_scaler=1.0) burn2.set_state_options('deltav', fix_initial=False, fix_final=False, defect_scaler=1.0) burn2.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg', scaler=0.01, lower=-30, upper=30) burn2.add_objective('deltav', loc='final', scaler=1.0) burn1.add_timeseries_output('pos_x', units='DU') coast.add_timeseries_output('pos_x', units='DU') burn2.add_timeseries_output('pos_x', units='DU') burn1.add_timeseries_output('pos_y', units='DU') coast.add_timeseries_output('pos_y', units='DU') burn2.add_timeseries_output('pos_y', units='DU') # Link Phases traj.link_phases(phases=['burn1', 'coast', 'burn2'], vars=['time', 'r', 'theta', 'vr', 'vt', 'deltav']) traj.link_phases(phases=['burn1', 'burn2'], vars=['accel']) # Finish Problem Setup p.model.linear_solver = DirectSolver() p.setup(check=True, force_alloc_complex=True) # Set Initial Guesses p.set_val('traj.design_parameters:c', value=1.5) p.set_val('traj.burn1.t_initial', value=0.0) p.set_val('traj.burn1.t_duration', value=2.25) p.set_val('traj.burn1.states:r', value=burn1.interpolate(ys=[1, 1.5], nodes='state_input')) p.set_val('traj.burn1.states:theta', value=burn1.interpolate(ys=[0, 1.7], nodes='state_input')) p.set_val('traj.burn1.states:vr', value=burn1.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('traj.burn1.states:vt', value=burn1.interpolate(ys=[1, 1], nodes='state_input')) p.set_val('traj.burn1.states:accel', value=burn1.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('traj.burn1.states:deltav', value=burn1.interpolate(ys=[0, 0.1], nodes='state_input'), ) p.set_val('traj.burn1.controls:u1', value=burn1.interpolate(ys=[-3.5, 13.0], nodes='control_input')) p.set_val('traj.coast.t_initial', value=2.25) p.set_val('traj.coast.t_duration', value=3.0) p.set_val('traj.coast.states:r', value=coast.interpolate(ys=[1.3, 1.5], nodes='state_input')) p.set_val('traj.coast.states:theta', value=coast.interpolate(ys=[2.1767, 1.7], nodes='state_input')) p.set_val('traj.coast.states:vr', value=coast.interpolate(ys=[0.3285, 0], nodes='state_input')) p.set_val('traj.coast.states:vt', value=coast.interpolate(ys=[0.97, 1], nodes='state_input')) p.set_val('traj.coast.states:accel', value=coast.interpolate(ys=[0, 0], nodes='state_input')) # p.set_val('traj.coast.controls:u1', # value=coast.interpolate(ys=[0, 0], nodes='control_input')) p.set_val('traj.burn2.t_initial', value=5.25) p.set_val('traj.burn2.t_duration', value=1.75) p.set_val('traj.burn2.states:r', value=burn2.interpolate(ys=[1.8, 3], nodes='state_input')) p.set_val('traj.burn2.states:theta', value=burn2.interpolate(ys=[3.2, 4.0], nodes='state_input')) p.set_val('traj.burn2.states:vr', value=burn2.interpolate(ys=[.5, 0], nodes='state_input')) p.set_val('traj.burn2.states:vt', value=burn2.interpolate(ys=[1, np.sqrt(1 / 3)], nodes='state_input')) p.set_val('traj.burn2.states:accel', value=burn2.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('traj.burn2.states:deltav', value=burn2.interpolate(ys=[0.1, 0.2], nodes='state_input')) p.set_val('traj.burn2.controls:u1', value=burn2.interpolate(ys=[1, 1], nodes='control_input')) p.run_driver() assert_rel_error(self, p.get_val('traj.burn2.timeseries.states:deltav')[-1], 0.3995, tolerance=2.0E-3) # Plot results exp_out = traj.simulate() fig = plt.figure(figsize=(8, 4)) fig.suptitle('Two Burn Orbit Raise Solution') ax_u1 = plt.subplot2grid((2, 2), (0, 0)) ax_deltav = plt.subplot2grid((2, 2), (1, 0)) ax_xy = plt.subplot2grid((2, 2), (0, 1), rowspan=2) span = np.linspace(0, 2 * np.pi, 100) ax_xy.plot(np.cos(span), np.sin(span), 'k--', lw=1) ax_xy.plot(3 * np.cos(span), 3 * np.sin(span), 'k--', lw=1) ax_xy.set_xlim(-4.5, 4.5) ax_xy.set_ylim(-4.5, 4.5) ax_xy.set_xlabel('x ($R_e$)') ax_xy.set_ylabel('y ($R_e$)') ax_u1.set_xlabel('time ($TU$)') ax_u1.set_ylabel('$u_1$ ($deg$)') ax_u1.grid(True) ax_deltav.set_xlabel('time ($TU$)') ax_deltav.set_ylabel('${\Delta}v$ ($DU/TU$)') ax_deltav.grid(True) t_sol = dict((phs, p.get_val('traj.{0}.timeseries.time'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) x_sol = dict((phs, p.get_val('traj.{0}.timeseries.pos_x'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) y_sol = dict((phs, p.get_val('traj.{0}.timeseries.pos_y'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) dv_sol = dict((phs, p.get_val('traj.{0}.timeseries.states:deltav'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) u1_sol = dict((phs, p.get_val('traj.{0}.timeseries.controls:u1'.format(phs), units='deg')) for phs in ['burn1', 'burn2']) t_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.time'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) x_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.pos_x'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) y_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.pos_y'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) dv_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.states:deltav'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) u1_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.controls:u1'.format(phs), units='deg')) for phs in ['burn1', 'burn2']) for phs in ['burn1', 'coast', 'burn2']: try: ax_u1.plot(t_sol[phs], u1_sol[phs], 'ro', ms=3) ax_u1.plot(t_exp[phs], u1_exp[phs], 'b-') except KeyError: pass ax_deltav.plot(t_sol[phs], dv_sol[phs], 'ro', ms=3) ax_deltav.plot(t_exp[phs], dv_exp[phs], 'b-') ax_xy.plot(x_sol[phs], y_sol[phs], 'ro', ms=3, label='implicit') ax_xy.plot(x_exp[phs], y_exp[phs], 'b-', label='explicit') plt.show()
def test_timeseries_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=8, 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=False, val=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'] = 9.80665 p.run_driver() gd = phase.options['transcription'].grid_data state_input_idxs = gd.subset_node_indices['state_input'] control_input_idxs = gd.subset_node_indices['control_input'] col_idxs = gd.subset_node_indices['col'] assert_rel_error(self, p.get_val('phase0.time'), p.get_val('phase0.timeseries.time')[:, 0]) assert_rel_error(self, p.get_val('phase0.time_phase'), p.get_val('phase0.timeseries.time_phase')[:, 0]) for state in ('x', 'y', 'v'): assert_rel_error( self, p.get_val('phase0.states:{0}'.format(state)), p.get_val('phase0.timeseries.states:' '{0}'.format(state))[state_input_idxs]) assert_rel_error( self, p.get_val('phase0.state_interp.state_col:{0}'.format(state)), p.get_val('phase0.timeseries.states:' '{0}'.format(state))[col_idxs]) for control in ('theta', ): assert_rel_error( self, p.get_val('phase0.controls:{0}'.format(control)), p.get_val('phase0.timeseries.controls:' '{0}'.format(control))[control_input_idxs]) for dp in ('g', ): for i in range(gd.subset_num_nodes['all']): assert_rel_error( self, p.get_val('phase0.design_parameters:{0}'.format(dp))[0, :], p.get_val('phase0.timeseries.design_parameters:{0}'.format( dp))[i])
def setUpClass(cls): cls.traj = Trajectory() p = Problem(model=cls.traj) # Since we're only testing features like get_values that don't rely on a converged # solution, no driver is attached. We'll just invoke run_model. # First Phase (burn) burn1 = Phase('gauss-lobatto', ode_class=FiniteBurnODE, num_segments=4, transcription_order=3, compressed=True) cls.traj.add_phase('burn1', burn1) burn1.set_time_options(fix_initial=True, duration_bounds=(.5, 10)) burn1.set_state_options('r', fix_initial=True, fix_final=False) burn1.set_state_options('theta', fix_initial=True, fix_final=False) burn1.set_state_options('vr', fix_initial=True, fix_final=False, defect_scaler=0.1) burn1.set_state_options('vt', fix_initial=True, fix_final=False, defect_scaler=0.1) burn1.set_state_options('accel', fix_initial=True, fix_final=False) burn1.set_state_options('deltav', fix_initial=True, fix_final=False) burn1.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg') burn1.add_design_parameter('c', opt=False, val=1.5) # Second Phase (Coast) coast = Phase('gauss-lobatto', ode_class=FiniteBurnODE, num_segments=10, transcription_order=3, compressed=True) cls.traj.add_phase('coast', coast) coast.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10)) coast.set_state_options('r', fix_initial=False, fix_final=False) coast.set_state_options('theta', fix_initial=False, fix_final=False) coast.set_state_options('vr', fix_initial=False, fix_final=False) coast.set_state_options('vt', fix_initial=False, fix_final=False) coast.set_state_options('accel', fix_initial=True, fix_final=True) coast.set_state_options('deltav', fix_initial=False, fix_final=False) coast.add_control('u1', opt=False, val=0.0, units='deg') coast.add_design_parameter('c', opt=False, val=1.5) # Third Phase (burn) burn2 = Phase('gauss-lobatto', ode_class=FiniteBurnODE, num_segments=3, transcription_order=3, compressed=True) cls.traj.add_phase('burn2', burn2) burn2.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10)) burn2.set_state_options('r', fix_initial=False, fix_final=True, defect_scaler=1.0) burn2.set_state_options('theta', fix_initial=False, fix_final=False, defect_scaler=1.0) burn2.set_state_options('vr', fix_initial=False, fix_final=True, defect_scaler=0.1) burn2.set_state_options('vt', fix_initial=False, fix_final=True, defect_scaler=0.1) burn2.set_state_options('accel', fix_initial=False, fix_final=False, defect_scaler=1.0) burn2.set_state_options('deltav', fix_initial=False, fix_final=False, defect_scaler=1.0) burn2.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg', ref0=0, ref=10) burn2.add_design_parameter('c', opt=False, val=1.5) burn2.add_objective('deltav', loc='final') # Link Phases cls.traj.link_phases(phases=['burn1', 'coast', 'burn2'], vars=['time', 'r', 'theta', 'vr', 'vt', 'deltav']) cls.traj.link_phases(phases=['burn1', 'burn2'], vars=['accel']) # Finish Problem Setup p.model.options['assembled_jac_type'] = 'csc' p.model.linear_solver = DirectSolver(assemble_jac=True) p.model.add_recorder(SqliteRecorder('test_trajectory_rec.db')) p.setup(check=True) # Set Initial Guesses p.set_val('burn1.t_initial', value=0.0) p.set_val('burn1.t_duration', value=2.25) p.set_val('burn1.states:r', value=burn1.interpolate(ys=[1, 1.5], nodes='state_input')) p.set_val('burn1.states:theta', value=burn1.interpolate(ys=[0, 1.7], nodes='state_input')) p.set_val('burn1.states:vr', value=burn1.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('burn1.states:vt', value=burn1.interpolate(ys=[1, 1], nodes='state_input')) p.set_val('burn1.states:accel', value=burn1.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('burn1.states:deltav', value=burn1.interpolate(ys=[0, 0.1], nodes='state_input')) p.set_val('burn1.controls:u1', value=burn1.interpolate(ys=[-3.5, 13.0], nodes='control_input')) p.set_val('burn1.design_parameters:c', value=1.5) p.set_val('coast.t_initial', value=2.25) p.set_val('coast.t_duration', value=3.0) p.set_val('coast.states:r', value=coast.interpolate(ys=[1.3, 1.5], nodes='state_input')) p.set_val('coast.states:theta', value=coast.interpolate(ys=[2.1767, 1.7], nodes='state_input')) p.set_val('coast.states:vr', value=coast.interpolate(ys=[0.3285, 0], nodes='state_input')) p.set_val('coast.states:vt', value=coast.interpolate(ys=[0.97, 1], nodes='state_input')) p.set_val('coast.states:accel', value=coast.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('coast.controls:u1', value=coast.interpolate(ys=[0, 0], nodes='control_input')) p.set_val('coast.design_parameters:c', value=1.5) p.set_val('burn2.t_initial', value=5.25) p.set_val('burn2.t_duration', value=1.75) p.set_val('burn2.states:r', value=burn2.interpolate(ys=[1, 3], nodes='state_input')) p.set_val('burn2.states:theta', value=burn2.interpolate(ys=[0, 4.0], nodes='state_input')) p.set_val('burn2.states:vr', value=burn2.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('burn2.states:vt', value=burn2.interpolate(ys=[1, np.sqrt(1 / 3)], nodes='state_input')) p.set_val('burn2.states:accel', value=burn2.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('burn2.states:deltav', value=burn2.interpolate(ys=[0.1, 0.2], nodes='state_input')) p.set_val('burn2.controls:u1', value=burn2.interpolate(ys=[1, 1], nodes='control_input')) p.set_val('burn2.design_parameters:c', value=1.5) p.run_model()
def test_brachistochrone_recording(self): import matplotlib matplotlib.use('Agg') from openmdao.api import Problem, Group, ScipyOptimizeDriver, DirectSolver, \ SqliteRecorder, CaseReader from openmdao.utils.assert_utils import assert_rel_error from dymos import Phase, GaussLobatto from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() phase = Phase(ode_class=BrachistochroneODE, transcription=GaussLobatto(num_segments=10)) p.model.add_subsystem('phase0', phase) phase.set_time_options(initial_bounds=(0, 0), 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) phase.add_control('theta', units='deg', rate_continuity=False, 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) p.model.linear_solver = DirectSolver() # Recording rec = SqliteRecorder('brachistochrone_solution.db') p.driver.recording_options['record_desvars'] = True p.driver.recording_options['record_responses'] = True p.driver.recording_options['record_objectives'] = True p.driver.recording_options['record_constraints'] = True p.model.recording_options['record_metadata'] = True p.driver.add_recorder(rec) p.model.add_recorder(rec) phase.add_recorder(rec) 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) cr = CaseReader('brachistochrone_solution.db') system_cases = cr.list_cases('root') case = cr.get_case(system_cases[-1]) outputs = dict([ (o[0], o[1]) for o in case.list_outputs(units=True, shape=True, out_stream=None) ]) assert_rel_error( self, p['phase0.controls:theta'], outputs['phase0.control_group.indep_controls.controls:theta'] ['value'])
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()
def setUpClass(cls): p = cls.p = Problem(model=Group()) # p.driver = pyOptSparseDriver() # p.driver.options['optimizer'] = 'SNOPT' # p.driver.options['dynamic_simul_derivs'] = True # p.driver.opt_settings['Major iterations limit'] = 1000 # p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-4 # p.driver.opt_settings['Major optimality tolerance'] = 1.0E-4 # p.driver.opt_settings['iSumm'] = 6 NUM_SEG = 10 TRANSCRIPTION_ORDER = 7 orbit_phase = Phase('radau-ps', ode_class=CadreOrbitODE, num_segments=NUM_SEG, transcription_order=TRANSCRIPTION_ORDER, compressed=False) p.model.add_subsystem('orbit_phase', orbit_phase) orbit_phase.set_time_options(fix_initial=True, fix_duration=True) orbit_phase.set_state_options('r_e2b_I', defect_scaler=1000, fix_initial=True, units='km') orbit_phase.set_state_options('v_e2b_I', defect_scaler=1000, fix_initial=True, units='km/s') # orbit_phase.set_state_options('SOC', defect_scaler=1, fix_initial=True, units=None) # orbit_phase.add_design_parameter('P_bat', opt=False, units='W') orbit_phase.add_design_parameter('Gamma', opt=False, units='rad') orbit_phase.add_objective('time', loc='final', scaler=10) # Add a control interp comp to interpolate the rates of O_BI from the orbit phase. faux_control_options = {'O_BI': {'units': None, 'shape': (3, 3)}} p.model.add_subsystem( 'obi_rate_interp_comp', ControlInterpComp(control_options=faux_control_options, time_units='s', grid_data=orbit_phase.grid_data), promotes_outputs=[('control_rates:O_BI_rate', 'Odot_BI')]) control_input_nodes_idxs = orbit_phase.grid_data.subset_node_indices[ 'control_input'] src_idxs = get_src_indices_by_row(control_input_nodes_idxs, shape=(3, 3)) p.model.connect('orbit_phase.rhs_all.O_BI', 'obi_rate_interp_comp.controls:O_BI', src_indices=src_idxs, flat_src_indices=True) p.model.connect( 'orbit_phase.time.dt_dstau', ('obi_rate_interp_comp.dt_dstau', 'w_B_rate_interp_comp.dt_dstau')) # Use O_BI and Odot_BI to compute the angular velocity vector p.model.add_subsystem( 'angular_velocity_comp', AngularVelocityComp(num_nodes=orbit_phase.grid_data.num_nodes)) p.model.connect('orbit_phase.rhs_all.O_BI', 'angular_velocity_comp.O_BI') p.model.connect('Odot_BI', 'angular_velocity_comp.Odot_BI') # Add another interpolation comp to compute the rate of w_B faux_control_options = {'w_B': {'units': '1/s', 'shape': (3, )}} p.model.add_subsystem( 'w_B_rate_interp_comp', ControlInterpComp(control_options=faux_control_options, time_units='s', grid_data=orbit_phase.grid_data), promotes_outputs=[('control_rates:w_B_rate', 'wdot_B')]) src_idxs = get_src_indices_by_row(control_input_nodes_idxs, shape=(3, )) p.model.connect('angular_velocity_comp.w_B', 'w_B_rate_interp_comp.controls:w_B', src_indices=src_idxs, flat_src_indices=True) # Now add the systems phase systems_phase = Phase('radau-ps', ode_class=CadreSystemsODE, num_segments=NUM_SEG, transcription_order=TRANSCRIPTION_ORDER, compressed=False) p.model.add_subsystem('systems_phase', systems_phase) systems_phase.set_time_options(fix_initial=True, fix_duration=True) systems_phase.set_state_options('SOC', defect_ref=1, fix_initial=True, units=None) systems_phase.set_state_options('w_RW', defect_ref=100, fix_initial=True, units='1/s') systems_phase.set_state_options('data', defect_ref=10, fix_initial=True, units='Gibyte') systems_phase.set_state_options('temperature', ref0=273, ref=373, defect_ref=100, fix_initial=True, units='degK') systems_phase.add_design_parameter('LD', opt=False, units='d') systems_phase.add_design_parameter('fin_angle', opt=False, lower=0., upper=np.pi / 2.) systems_phase.add_design_parameter('antAngle', opt=False, lower=-np.pi / 4, upper=np.pi / 4) systems_phase.add_design_parameter('cellInstd', opt=False, lower=0.0, upper=1.0, ref=1.0) # Add r_e2b_I and O_BI as non-optimized controls, allowing them to be connected to external sources systems_phase.add_control('r_e2b_I', opt=False, units='km') systems_phase.add_control('O_BI', opt=False) systems_phase.add_control('w_B', opt=False) systems_phase.add_control('wdot_B', opt=False) systems_phase.add_control('P_comm', opt=False, lower=0.0, upper=30.0, units='W') systems_phase.add_control('Isetpt', opt=False, lower=0.0, upper=0.4, units='A') # Connect r_e2b_I and O_BI values from all nodes in the orbit phase to the input values # in the attitude phase. src_idxs = get_src_indices_by_row(control_input_nodes_idxs, shape=(3, )) p.model.connect('orbit_phase.states:r_e2b_I', 'systems_phase.controls:r_e2b_I', src_indices=src_idxs, flat_src_indices=True) p.model.connect('angular_velocity_comp.w_B', 'systems_phase.controls:w_B', src_indices=src_idxs, flat_src_indices=True) p.model.connect('wdot_B', 'systems_phase.controls:wdot_B', src_indices=src_idxs, flat_src_indices=True) src_idxs = get_src_indices_by_row(control_input_nodes_idxs, shape=(3, 3)) p.model.connect('orbit_phase.rhs_all.O_BI', 'systems_phase.controls:O_BI', src_indices=src_idxs, flat_src_indices=True) p.setup(check=True) # from openmdao.api import view_model # view_model(p.model) # Initialize values in the orbit phase p['orbit_phase.t_initial'] = 0.0 p['orbit_phase.t_duration'] = duration # p['systems_phase.states:w_RW'][:, 0] = 0.0 # p['systems_phase.states:w_RW'][:, 1] = 0.0 # p['systems_phase.states:w_RW'][:, 2] = 0.0 # Default starting orbit # [ 2.89078958e+03 5.69493134e+03 -2.55340189e+03 2.56640460e-01 # 3.00387409e+00 6.99018448e+00] p['orbit_phase.states:r_e2b_I'][:, 0] = 2.89078958e+03 p['orbit_phase.states:r_e2b_I'][:, 1] = 5.69493134e+03 p['orbit_phase.states:r_e2b_I'][:, 2] = -2.55340189e+03 p['orbit_phase.states:v_e2b_I'][:, 0] = 2.56640460e-01 p['orbit_phase.states:v_e2b_I'][:, 1] = 3.00387409e+00 p['orbit_phase.states:v_e2b_I'][:, 2] = 6.99018448e+00 # Initialize values in the systems phase p['systems_phase.t_initial'] = 0.0 p['systems_phase.t_duration'] = duration # p['systems_phase.states:w_RW'][:, 0] = 0.0 # p['systems_phase.states:w_RW'][:, 1] = 0.0 # p['systems_phase.states:w_RW'][:, 2] = 0.0 p['systems_phase.states:SOC'] = 1.0 p['systems_phase.states:w_RW'] = 100.0 p['systems_phase.states:data'] = 0.0 p['systems_phase.states:temperature'] = 273.0 # p['systems_phase.states:v_e2b_I'][:, 0] = 0.0 # p['systems_phase.states:v_e2b_I'][:, 1] = vcirc # p['systems_phase.states:v_e2b_I'][:, 2] = 0.0 p['systems_phase.design_parameters:LD'] = 5233.5 p['systems_phase.design_parameters:fin_angle'] = 70.0 p.run_model()
def test_brachistochrone_integrated_control_radau_ps(self): import numpy as np from openmdao.api import Problem, Group, ScipyOptimizeDriver, DirectSolver from openmdao.utils.assert_utils import assert_rel_error from dymos import Phase, Radau p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() phase = Phase(ode_class=BrachistochroneODE, transcription=Radau(num_segments=10)) p.model.add_subsystem('phase0', phase) phase.set_time_options(initial_bounds=(0, 0), 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) phase.set_state_options('theta', targets='theta', fix_initial=False) phase.add_control('theta_dot', units='deg/s', rate_continuity=True, lower=0, upper=60) 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) p.model.linear_solver = DirectSolver() p.model.options['assembled_jac_type'] = 'csc' p.setup() p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 2.0 p['phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input') p['phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['phase0.states:theta'] = np.radians( phase.interpolate(ys=[0.05, 100.0], nodes='state_input')) p['phase0.controls:theta_dot'] = phase.interpolate( ys=[50, 50], 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) sim_out = phase.simulate(times_per_seg=20) x_sol = p.get_val('phase0.timeseries.states:x') y_sol = p.get_val('phase0.timeseries.states:y') v_sol = p.get_val('phase0.timeseries.states:v') theta_sol = p.get_val('phase0.timeseries.states:theta') theta_dot_sol = p.get_val('phase0.timeseries.controls:theta_dot') time_sol = p.get_val('phase0.timeseries.time') x_sim = sim_out.get_val('phase0.timeseries.states:x') y_sim = sim_out.get_val('phase0.timeseries.states:y') v_sim = sim_out.get_val('phase0.timeseries.states:v') theta_sim = sim_out.get_val('phase0.timeseries.states:theta') theta_dot_sim = sim_out.get_val('phase0.timeseries.controls:theta_dot') time_sim = sim_out.get_val('phase0.timeseries.time') x_interp = interp1d(time_sim[:, 0], x_sim[:, 0]) y_interp = interp1d(time_sim[:, 0], y_sim[:, 0]) v_interp = interp1d(time_sim[:, 0], v_sim[:, 0]) theta_interp = interp1d(time_sim[:, 0], theta_sim[:, 0]) theta_dot_interp = interp1d(time_sim[:, 0], theta_dot_sim[:, 0]) assert_rel_error(self, x_interp(time_sol), x_sol, tolerance=1.0E-5) assert_rel_error(self, y_interp(time_sol), y_sol, tolerance=1.0E-5) assert_rel_error(self, v_interp(time_sol), v_sol, tolerance=1.0E-5) assert_rel_error(self, theta_interp(time_sol), theta_sol, tolerance=1.0E-5) assert_rel_error(self, theta_dot_interp(time_sol), theta_dot_sol, tolerance=1.0E-5)
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) p.model.add_constraint('phase0.rhs_disc.pairwise.dist', lower=20.0) p.setup() phase = p.model.phase0
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