def test_ex_double_integrator_deprecated_time_options( self, transcription='radau-ps'): """ 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()) phase = Phase(transcription, ode_class=DoubleIntegratorODE, num_segments=20, transcription_order=3, compressed=True) p.model.add_subsystem('phase0', phase) with warnings.catch_warnings(record=True) as ctx: warnings.simplefilter('always') phase.set_time_options(opt_initial=False, initial_bounds=(-5, 5), initial_ref0=1, initial_ref=10, initial_adder=0, initial_scaler=1, opt_duration=False, duration_bounds=(-5, 5), duration_ref0=1, duration_ref=10, duration_adder=0, duration_scaler=1) self.assertTrue(len(ctx) == 4, msg='Expected 4 warnings, got {0}'.format(len(ctx))) self.assertEqual( str(ctx[0].message), 'opt_initial has been deprecated in favor of ' 'fix_initial, which has the opposite meaning. ' 'If the user desires to input the initial ' 'phase time from an exterior source, set ' 'input_initial=True.') self.assertEqual( str(ctx[1].message), 'opt_duration has been deprecated in favor ' 'of fix_duration, which has the opposite ' 'meaning. If the user desires to input the ' 'phase duration from an exterior source, ' 'set input_duration=True.') self.assertEqual( str(ctx[2].message), 'Phase time options have no effect because fix_initial=True for phase ' '"phase0": initial_bounds, initial_scaler, initial_adder, initial_ref, ' 'initial_ref0') self.assertEqual( str(ctx[3].message), 'Phase time options have no effect because fix_duration=True for phase ' '"phase0": duration_bounds, duration_scaler, duration_adder, duration_ref,' ' duration_ref0')
def test_ex_double_integrator_input_times_warns(self, transcription='radau-ps'): """ 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()) times_ivc = p.model.add_subsystem('times_ivc', IndepVarComp(), promotes_outputs=['t0', 'tp']) times_ivc.add_output(name='t0', val=0.0, units='s') times_ivc.add_output(name='tp', val=1.0, units='s') phase = Phase(transcription, ode_class=DoubleIntegratorODE, num_segments=20, transcription_order=3, compressed=True) p.model.add_subsystem('phase0', phase) p.model.connect('t0', 'phase0.t_initial') p.model.connect('tp', 'phase0.t_duration') with warnings.catch_warnings(record=True) as ctx: warnings.simplefilter('always') phase.set_time_options(input_initial=True, initial_bounds=(-5, 5), initial_ref0=1, initial_ref=10, initial_adder=0, initial_scaler=1, input_duration=True, duration_bounds=(-5, 5), duration_ref0=1, duration_ref=10, duration_adder=0, duration_scaler=1) self.assertTrue(len(ctx) == 2, msg='Expected 2 warnings, got {0}'.format(len(ctx))) self.assertEqual( str(ctx[0].message), 'Phase time options have no effect because input_initial=True for phase ' '"phase0": initial_bounds, initial_scaler, initial_adder, initial_ref, ' 'initial_ref0') self.assertEqual( str(ctx[1].message), 'Phase time options have no effect because input_duration=True for phase ' '"phase0": duration_bounds, duration_scaler, duration_adder, duration_ref,' ' duration_ref0')
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)
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_solver_defects_reverse_propagation(self): prob = Problem() num_seg = 5 seg_ends, _ = lgl(num_seg + 1) traj = prob.model.add_subsystem('traj', Trajectory()) # First phase: normal operation. transcription = Radau(num_segments=5, order=5, segment_ends=seg_ends, compressed=True) phase0 = Phase(ode_class=BatteryODE, transcription=transcription) traj_p0 = traj.add_phase('phase0', phase0) traj_p0.set_time_options(fix_initial=True, fix_duration=True) traj_p0.set_state_options('state_of_charge', fix_initial=True, fix_final=False, solve_segments=True) # Second phase: normal operation. phase1 = Phase(ode_class=BatteryODE, transcription=transcription) traj_p1 = traj.add_phase('phase1', phase1) traj_p1.set_time_options(fix_initial=False, fix_duration=True) traj_p1.set_state_options('state_of_charge', fix_initial=False, fix_final=False, solve_segments=True) traj_p1.add_objective('time', loc='final') traj.link_phases(phases=['phase0', 'phase1'], vars=['state_of_charge', 'time'], connected=True) prob.setup() prob['traj.phase0.t_initial'] = 0 prob['traj.phase0.t_duration'] = -1.0 * 3600 prob['traj.phase0.states:state_of_charge'][:] = 0.23794217 prob['traj.phase1.t_initial'] = 0 prob['traj.phase1.t_duration'] = -1.0 * 3600 prob.set_solver_print(level=0) prob.run_model() soc1 = prob['traj.phase1.states:state_of_charge'] assert_rel_error(self, soc1[-1], 1.0, 1e-6)
def __init__(self, body, sc, method, nb_seg, order, solver, ode_class, ode_kwargs, ph_name, snopt_opts=None, rec_file=None): NLP.__init__(self, body, sc, method, nb_seg, order, solver, snopt_opts=snopt_opts, rec_file=rec_file) # Transcription object if self.method == 'gauss-lobatto': self.transcription = GaussLobatto(num_segments=self.nb_seg, order=self.order, compressed=True) elif self.method == 'radau-ps': self.transcription = Radau(num_segments=self.nb_seg, order=self.order, compressed=True) elif self.method == 'runge-kutta': self.transcription = RungeKutta(num_segments=self.nb_seg, order=self.order, compressed=True) else: raise ValueError('method must be either gauss-lobatto or radau-ps') # Phase object self.phase = self.trajectory.add_phase(ph_name, Phase(ode_class=ode_class, ode_init_kwargs=ode_kwargs, transcription=self.transcription)) self.phase_name = ''.join(['traj.', ph_name]) # discretization nodes self.state_nodes = None self.control_nodes = None self.t_all = None self.t_state = None self.t_control = None self.idx_state_control = None # time of flight self.tof = None
def test_single_phase_reverse_propagation_rk(self): prob = Problem() num_seg = 10 seg_ends, _ = lgl(num_seg + 1) # First phase: normal operation. transcription = RungeKutta(num_segments=num_seg) phase0 = Phase(ode_class=BatteryODE, transcription=transcription) traj_p0 = prob.model.add_subsystem('phase0', phase0) traj_p0.set_time_options(fix_initial=True, fix_duration=True) traj_p0.set_state_options('state_of_charge', fix_initial=True, fix_final=False) prob.setup() prob['phase0.t_initial'] = 0 prob['phase0.t_duration'] = -1.0 * 3600 prob['phase0.states:state_of_charge'][:] = 0.63464982 prob.set_solver_print(level=0) prob.run_model() soc0 = prob['phase0.states:state_of_charge'] assert_rel_error(self, soc0[-1], 1.0, 1e-6)
def __init__(self, body, sc, method, nb_seg, order, solver, ode_class, ode_kwargs, ph_name, snopt_opts=None, rec_file=None): if isinstance(order, int): order = tuple(order for _ in range(len(nb_seg))) if isinstance(method, str): method = tuple(method for _ in range(len(nb_seg))) NLP.__init__(self, body, sc, method, nb_seg, order, solver, snopt_opts=snopt_opts, rec_file=rec_file) # Transcription objects list self.transcription = [] for i in range(len(self.nb_seg)): if self.method[i] == 'gauss-lobatto': t = GaussLobatto(num_segments=self.nb_seg[i], order=self.order[i], compressed=True) elif self.method[i] == 'radau-ps': t = Radau(num_segments=self.nb_seg[i], order=self.order[i], compressed=True) elif self.method[i] == 'runge-kutta': t = RungeKutta(num_segments=self.nb_seg[i], order=self.order[i], compressed=True) else: raise ValueError('method must be either gauss-lobatto, radau-ps or runge-kutta') self.transcription.append(t) # Phase objects list self.phase = [] self.phase_name = [] for i in range(len(self.nb_seg)): ph = self.trajectory.add_phase(ph_name[i], Phase(ode_class=ode_class[i], ode_init_kwargs=ode_kwargs[i], transcription=self.transcription[i])) self.phase.append(ph) self.phase_name.append(''.join(['traj.', ph_name[i]]))
def make_problem(self, transcription=GaussLobatto, optimizer='SLSQP', numseg=30): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.declare_coloring() p.driver.options['optimizer'] = optimizer if optimizer == 'SNOPT': p.driver.declare_coloring() 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 elif optimizer == 'IPOPT': p.driver.opt_settings['hessian_approximation'] = 'limited-memory' # p.driver.opt_settings['nlp_scaling_method'] = 'user-scaling' p.driver.opt_settings['print_level'] = 5 p.driver.opt_settings['linear_solver'] = 'mumps' p.driver.declare_coloring() else: p.driver.declare_coloring() traj = p.model.add_subsystem('traj', Trajectory()) phase0 = traj.add_phase( 'phase0', Phase(ode_class=HyperSensitiveODE, transcription=transcription(num_segments=numseg, order=3))) phase0.set_time_options(fix_initial=True, fix_duration=True) phase0.add_state('x', fix_initial=True, fix_final=False, rate_source='x_dot', targets=['x']) phase0.add_state('xL', fix_initial=True, fix_final=False, rate_source='L', targets=['xL']) phase0.add_control('u', opt=True, targets=['u']) phase0.add_boundary_constraint('x', loc='final', equals=1) phase0.add_objective('xL', loc='final') phase0.set_refine_options(refine=True, tol=1e-6, max_order=14) p.setup(check=True) p.set_val('traj.phase0.states:x', phase0.interpolate(ys=[1.5, 1], nodes='state_input')) p.set_val('traj.phase0.states:xL', phase0.interpolate(ys=[0, 1], nodes='state_input')) p.set_val('traj.phase0.t_initial', 0) p.set_val('traj.phase0.t_duration', tf) p.set_val('traj.phase0.controls:u', phase0.interpolate(ys=[-0.6, 2.4], nodes='control_input')) return p
def test_invalid_options_nonoptimal_control(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_control('theta', opt=False, lower=5, upper=10, ref0=5, ref=10, scaler=1, adder=0) expected = 'Invalid options for non-optimal control "theta":' \ 'lower, upper, scaler, adder, ref, ref0' self.assertEqual(len(w), 1) self.assertEqual(str(w[0].message), expected)
def test_invalid_ode_class_wrong_class(self): with self.assertRaises(ValueError) as e: phase = Phase('gauss-lobatto', ode_class=_A, num_segments=8, transcription_order=3) self.assertEqual(str(e.exception), 'ode_class must be derived from openmdao.core.System.')
def test_invalid_ode_class_instance(self): with self.assertRaises(ValueError) as e: Phase('gauss-lobatto', ode_class=BrachistochroneODE(), num_segments=8, transcription_order=3) self.assertEqual(str(e.exception), 'ode_class must be a class, not an instance.')
def test_gauss_lobatto(self): p = Problem(model=Group()) phase = Phase(ode_class=MyODE, ode_init_kwargs={'n_traj': n_traj}, transcription=GaussLobatto(num_segments=25, order=3, compressed=True)) p.model.add_subsystem('phase0', phase) phase.add_input_parameter('alpha', val=np.ones((n_traj, 2)), units='m') try: p.setup() except Exception as e: self.fail('Exception encountered in setup:\n' + str(e))
def test_invalid_ode_class_invalid_metadata(self): with self.assertRaises(ValueError) as e: Phase('gauss-lobatto', ode_class=_D, num_segments=8, transcription_order=3) self.assertEqual(str(e.exception), 'ode_class has no ODE metadata. ' 'Use @declare_time, @declare_stateand @declare_control ' 'to assign ODE metadata.')
def test_ex_double_integrator_input_and_fixed_times_warns( self, transcription='radau-ps'): """ 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()) times_ivc = p.model.add_subsystem('times_ivc', IndepVarComp(), promotes_outputs=['t0', 'tp']) times_ivc.add_output(name='t0', val=0.0, units='s') times_ivc.add_output(name='tp', val=1.0, units='s') phase = Phase(transcription, ode_class=DoubleIntegratorODE, num_segments=20, transcription_order=3, compressed=True) p.model.add_subsystem('phase0', phase) p.model.connect('t0', 'phase0.t_initial') p.model.connect('tp', 'phase0.t_duration') with warnings.catch_warnings(record=True) as ctx: warnings.simplefilter('always') phase.set_time_options(input_initial=True, fix_initial=True, input_duration=True, fix_duration=True) self.assertTrue( len(ctx) == 2, 'Expected 2 warnings, got {0}'.format(len(ctx))) expected = 'Phase "phase0" initial time is an externally-connected input, therefore ' \ 'fix_initial has no effect.' self.assertEqual(str(ctx[0].message), expected) expected = 'Phase "phase0" time duration is an externally-connected input, ' \ 'therefore fix_duration has no effect.' self.assertEqual(str(ctx[1].message), expected)
def make_problem(self, transcription=Radau, optimizer='SLSQP', numseg=30): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.declare_coloring(tol=1.0E-12) OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=False) p.driver.options['optimizer'] = OPTIMIZER if OPTIMIZER == 'SNOPT': p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Verify level'] = 3 elif OPTIMIZER == 'IPOPT': p.driver.opt_settings['max_iter'] = 500 p.driver.opt_settings['print_level'] = 4 p.driver.opt_settings['tol'] = 1.0E-6 p.driver.opt_settings['acceptable_tol'] = 1.0E-5 traj = p.model.add_subsystem('traj', Trajectory()) phase = traj.add_phase('phase', Phase(ode_class=RobotArmODE, transcription=transcription(num_segments=numseg, order=3))) phase.set_time_options(fix_initial=True, fix_duration=False) phase.add_state('x0', fix_initial=True, fix_final=True, rate_source='x0_dot', units='m') phase.add_state('x1', fix_initial=True, fix_final=True, rate_source='x1_dot', units='rad') phase.add_state('x2', fix_initial=True, fix_final=True, rate_source='x2_dot', units='rad') phase.add_state('x3', fix_initial=True, fix_final=True, rate_source='x3_dot', units='m/s') phase.add_state('x4', fix_initial=True, fix_final=True, rate_source='x4_dot', units='rad/s') phase.add_state('x5', fix_initial=True, fix_final=True, rate_source='x5_dot', units='rad/s') phase.add_control('u0', opt=True, lower=-1, upper=1, scaler=0.1, units='m**2/s**2', continuity=False, rate_continuity=False) phase.add_control('u1', opt=True, lower=-1, upper=1, scaler=0.1, units='m**3*rad/s**2', continuity=False, rate_continuity=False) phase.add_control('u2', opt=True, lower=-1, upper=1, scaler=0.1, units='m**3*rad/s**2', continuity=False, rate_continuity=False) phase.add_path_constraint('u0', lower=-1, upper=1, scaler=0.1) phase.add_path_constraint('u1', lower=-1, upper=1, scaler=0.1) phase.add_path_constraint('u2', lower=-1, upper=1, scaler=0.1) phase.add_objective('time', ref=0.1) phase.set_refine_options(refine=True, tol=1e-5, smoothness_factor=1.2) p.setup(check=True, force_alloc_complex=False, mode='auto') p.set_val('traj.phase.t_initial', 0) p.set_val('traj.phase.t_duration', 10) p.set_val('traj.phase.states:x0', phase.interpolate(ys=[4.5, 4.5], nodes='state_input')) p.set_val('traj.phase.states:x1', phase.interpolate(ys=[0.0, 2 * np.pi / 3], nodes='state_input')) p.set_val('traj.phase.states:x2', phase.interpolate(ys=[np.pi / 4, np.pi / 4], nodes='state_input')) p.set_val('traj.phase.states:x3', phase.interpolate(ys=[0.0, 0.0], nodes='state_input')) p.set_val('traj.phase.states:x4', phase.interpolate(ys=[0.0, 0.0], nodes='state_input')) p.set_val('traj.phase.states:x5', phase.interpolate(ys=[0.0, 0.0], nodes='state_input')) return p
def test_invalid_options(self, transcription='gauss-lobatto'): p = Problem(model=Group()) phase = Phase(transcription, ode_class=BrachistochroneODE, num_segments=8, transcription_order=3) p.model.add_subsystem('phase0', phase) 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') 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) self.assertEqual(len(ctx), 2, msg='set_time_options failed to raise two warnings') self.assertEqual(str(ctx[0].message), expected_msg0) self.assertEqual(str(ctx[1].message), expected_msg1)
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_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 make_problem(self, transcription=GaussLobatto, optimizer='SLSQP', numseg=30): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.declare_coloring() OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=False) p.driver.options['optimizer'] = OPTIMIZER traj = p.model.add_subsystem('traj', Trajectory()) phase0 = traj.add_phase( 'phase0', Phase(ode_class=HyperSensitiveODE, transcription=transcription(num_segments=numseg, order=3))) phase0.set_time_options(fix_initial=True, fix_duration=True) phase0.add_state('x', fix_initial=True, fix_final=False, rate_source='x_dot', targets=['x']) phase0.add_state('xL', fix_initial=True, fix_final=False, rate_source='L', targets=['xL']) phase0.add_control('u', opt=True, targets=['u']) phase0.add_boundary_constraint('x', loc='final', equals=1) phase0.add_objective('xL', loc='final') p.setup(check=True) p.set_val('traj.phase0.states:x', phase0.interpolate(ys=[1.5, 1], nodes='state_input')) p.set_val('traj.phase0.states:xL', phase0.interpolate(ys=[0, 1], nodes='state_input')) p.set_val('traj.phase0.t_initial', 0) p.set_val('traj.phase0.t_duration', tf) p.set_val('traj.phase0.controls:u', phase0.interpolate(ys=[-0.6, 2.4], nodes='control_input')) return p
def test_add_existing_input_parameter_as_input_parameter(self): p = Phase('gauss-lobatto', ode_class=BrachistochroneODE, num_segments=8, transcription_order=3) p.add_input_parameter('theta') with self.assertRaises(ValueError) as e: p.add_input_parameter('theta') expected = 'theta has already been added as an input parameter.' self.assertEqual(str(e.exception), expected)
def setup(self, problem, ndv, nstate, nproc, flag): simul_derivs = flag num_segments = nstate transcription = 'radau-ps' top_level_jacobian = 'csc' transcription_order = 3 force_alloc_complex = False p = problem self.phase = phase = Phase(transcription, ode_class=BrachistochroneODE, num_segments=num_segments, transcription_order=transcription_order, compressed=False) 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', loc='final', scaler=10) p.model.options['assembled_jac_type'] = top_level_jacobian.lower() p.model.linear_solver = DirectSolver(assemble_jac=True) p.driver = ColoringOnly() p.driver.options['dynamic_simul_derivs'] = simul_derivs
def make_problem(transcription=GaussLobatto, num_segments=10, order=3, compressed=True): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() traj = p.model.add_subsystem('traj', Trajectory()) phase = traj.add_phase('phase', Phase(ode_class=crtbp_ode, transcription=transcription(num_segments=num_segments, order=order, compressed=compressed))) phase.set_time_options(fix_initial=True, fix_duration=True) phase.add_state('x', rate_source='vx', ) phase.add_state('y', rate_source='vz', fix_initial=True) phase.add_state('z', rate_source='vz') phase.add_state('x_dot', rate_source='vx_dot', fix_initial=True, units=None) phase.add_state('y_dot', rate_source='vy_dot', units=None) phase.add_state('z_dot', rate_source='vz_dot', fix_initial=True, units=None) p.model.add_subsystem('x_periodic_bc', om.ExecComp('bc_defect=final-initial')) p.model.connect('traj.phase.timeseries.states:x', 'x_periodic_bc.initial', src_indices=0) p.model.connect('traj.phase.timeseries.states:x', 'x_periodic_bc.final', src_indices=-1) p.model.add_constraint('x_periodic_bc.bc_defect', equals=0) p.model.add_subsystem('z_periodic_bc', om.ExecComp('bc_defect=final-initial')) p.model.connect('traj.phase.timeseries.states:z', 'z_periodic_bc.initial', src_indices=0) p.model.connect('traj.phase.timeseries.states:z', 'z_periodic_bc.final', src_indices=-1) p.model.add_constraint('z_periodic_bc.bc_defect', equals=0) p.model.add_subsystem('vy_periodic_bc', om.ExecComp('bc_defect=final-initial')) p.model.connect('traj.phase.timeseries.states:y_dot', 'vy_periodic_bc.initial', src_indices=0) p.model.connect('traj.phase.timeseries.states:y_dot', 'vy_periodic_bc.final', src_indices=-1) p.model.add_constraint('vy_periodic_bc.bc_defect', equals=0) phase.add_objective('time', loc='final') p.setup(check=True) return p
from __future__ import print_function, division, absolute_import import numpy as np import matplotlib.pyplot as plt from openmdao.api import Problem, Group from dymos import Phase from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE p = Problem(model=Group()) phase = Phase('radau-ps', ode_class=BrachistochroneODE, num_segments=4, transcription_order=[3, 5, 3, 5]) p.model.add_subsystem('phase0', phase) p.setup() p['phase0.t_initial'] = 1.0 p['phase0.t_duration'] = 9.0 p.run_model() t_disc = phase.get_values('time', nodes='state_disc') t_col = phase.get_values('time', nodes='col') t_all = phase.get_values('time', nodes='all') def f(x): return np.sin(x) / x + 1 def fu(x): return (np.cos(x) * x - np.sin(x))/x**2
def make_problem(self, constrained=True, transcription=GaussLobatto, optimizer='SLSQP', numseg=30): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=False) p.driver.options['optimizer'] = OPTIMIZER traj = p.model.add_subsystem('traj', Trajectory()) phase0 = traj.add_phase( 'phase0', Phase(ode_class=ShuttleODE, transcription=transcription(num_segments=numseg, order=3))) phase0.set_time_options(fix_initial=True, units='s', duration_ref=200) phase0.add_state('h', fix_initial=True, fix_final=True, units='ft', rate_source='hdot', targets=['h'], lower=0, ref0=75000, ref=300000, defect_ref=1000) phase0.add_state('gamma', fix_initial=True, fix_final=True, units='rad', rate_source='gammadot', targets=['gamma'], lower=-89. * np.pi / 180, upper=89. * np.pi / 180) phase0.add_state('phi', fix_initial=True, fix_final=False, units='rad', rate_source='phidot', lower=0, upper=89. * np.pi / 180) phase0.add_state('psi', fix_initial=True, fix_final=False, units='rad', rate_source='psidot', targets=['psi'], lower=0, upper=90. * np.pi / 180) phase0.add_state('theta', fix_initial=True, fix_final=False, units='rad', rate_source='thetadot', targets=['theta'], lower=-89. * np.pi / 180, upper=89. * np.pi / 180) phase0.add_state('v', fix_initial=True, fix_final=True, units='ft/s', rate_source='vdot', targets=['v'], lower=500, ref0=2500, ref=25000) phase0.add_control('alpha', units='rad', opt=True, lower=-np.pi / 2, upper=np.pi / 2, targets=['alpha']) phase0.add_control('beta', units='rad', opt=True, lower=-89 * np.pi / 180, upper=1 * np.pi / 180, targets=['beta']) if constrained: phase0.add_path_constraint('q', lower=0, upper=70, ref=70) phase0.add_objective('theta', loc='final', ref=-0.01) p.setup(check=True, force_alloc_complex=True) p.set_val('traj.phase0.states:h', phase0.interpolate(ys=[260000, 80000], nodes='state_input'), units='ft') p.set_val('traj.phase0.states:gamma', phase0.interpolate(ys=[-1 * np.pi / 180, -5 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:phi', phase0.interpolate(ys=[0, 75 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:psi', phase0.interpolate(ys=[90 * np.pi / 180, 10 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:theta', phase0.interpolate(ys=[0, 25 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:v', phase0.interpolate(ys=[25600, 2500], nodes='state_input'), units='ft/s') p.set_val('traj.phase0.t_initial', 0, units='s') p.set_val('traj.phase0.t_duration', 2000, units='s') p.set_val('traj.phase0.controls:alpha', phase0.interpolate( ys=[17.4 * np.pi / 180, 17.4 * np.pi / 180], nodes='control_input'), units='rad') p.set_val('traj.phase0.controls:beta', phase0.interpolate(ys=[-75 * np.pi / 180, 0 * np.pi / 180], nodes='control_input'), units='rad') return p
def test_reentry_mixed_controls(self): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() OPT, OPTIMIZER = set_pyoptsparse_opt('IPOPT', fallback=False) p.driver.options['optimizer'] = OPTIMIZER traj = p.model.add_subsystem('traj', Trajectory()) phase0 = traj.add_phase( 'phase0', Phase(ode_class=ShuttleODE, transcription=GaussLobatto(num_segments=20, order=3))) phase0.set_time_options(fix_initial=True, units='s', duration_ref=200) phase0.add_state('h', fix_initial=True, fix_final=True, units='ft', rate_source='hdot', targets=['h'], lower=0, ref0=75000, ref=300000, defect_ref=1000) phase0.add_state('gamma', fix_initial=True, fix_final=True, units='rad', rate_source='gammadot', targets=['gamma'], lower=-89. * np.pi / 180, upper=89. * np.pi / 180) phase0.add_state('phi', fix_initial=True, fix_final=False, units='rad', rate_source='phidot', lower=0, upper=89. * np.pi / 180) phase0.add_state('psi', fix_initial=True, fix_final=False, units='rad', rate_source='psidot', targets=['psi'], lower=0, upper=90. * np.pi / 180) phase0.add_state('theta', fix_initial=True, fix_final=False, units='rad', rate_source='thetadot', targets=['theta'], lower=-89. * np.pi / 180, upper=89. * np.pi / 180) phase0.add_state('v', fix_initial=True, fix_final=True, units='ft/s', rate_source='vdot', targets=['v'], lower=500, ref0=2500, ref=25000) phase0.add_control('alpha', units='rad', opt=True, lower=-np.pi / 2, upper=np.pi / 2) phase0.add_polynomial_control('beta', order=5, units='rad', opt=True, lower=-89 * np.pi / 180, upper=1 * np.pi / 180) phase0.add_objective('theta', loc='final', ref=-0.01) p.setup(check=True, force_alloc_complex=True) p.set_val('traj.phase0.states:h', phase0.interpolate(ys=[260000, 80000], nodes='state_input'), units='ft') p.set_val('traj.phase0.states:gamma', phase0.interpolate(ys=[-1 * np.pi / 180, -5 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:phi', phase0.interpolate(ys=[0, 75 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:psi', phase0.interpolate(ys=[90 * np.pi / 180, 10 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:theta', phase0.interpolate(ys=[0, 25 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:v', phase0.interpolate(ys=[25600, 2500], nodes='state_input'), units='ft/s') p.set_val('traj.phase0.t_initial', 0, units='s') p.set_val('traj.phase0.t_duration', 2000, units='s') p.set_val('traj.phase0.controls:alpha', phase0.interpolate( ys=[17.4 * np.pi / 180, 17.4 * np.pi / 180], nodes='control_input'), units='rad') p.set_val('traj.phase0.polynomial_controls:beta', np.radians(-75)) p.run_driver() exp_out = traj.simulate() from scipy.interpolate import interp1d t_sol = p.get_val('traj.phase0.timeseries.time') beta_sol = p.get_val('traj.phase0.timeseries.polynomial_controls:beta') t_sim = exp_out.get_val('traj.phase0.timeseries.time') beta_sim = exp_out.get_val( 'traj.phase0.timeseries.polynomial_controls:beta') sol_interp = interp1d(t_sol.ravel(), beta_sol.ravel()) sim_interp = interp1d(t_sim.ravel(), beta_sim.ravel()) t = np.linspace(0, t_sol.ravel()[-1], 100) assert_near_equal(sim_interp(t), sol_interp(t), tolerance=1.0E-3)
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 double_integrator_direct_collocation(transcription='gauss-lobatto', top_level_jacobian='csc', compressed=True): p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() p.driver.options['dynamic_simul_derivs'] = True phase = Phase(transcription, ode_class=DoubleIntegratorODE, num_segments=20, transcription_order=3, compressed=compressed) p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, fix_duration=True) phase.set_state_options('x', fix_initial=True) phase.set_state_options('v', fix_initial=True, fix_final=True) phase.add_control('u', units='m/s**2', scaler=0.01, continuity=False, rate_continuity=False, rate2_continuity=False, lower=-1.0, upper=1.0) # Maximize distance travelled in one second. phase.add_objective('x', loc='final', scaler=-1) p.model.linear_solver = DirectSolver(assemble_jac=True) p.model.options['assembled_jac_type'] = top_level_jacobian.lower() p.setup(check=True) p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 1.0 p['phase0.states:x'] = phase.interpolate(ys=[0, 0.25], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[0, 0], nodes='state_input') p['phase0.controls:u'] = phase.interpolate(ys=[1, -1], nodes='control_input') p.run_driver() return p
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 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