def test_brachistochrone_forward_shooting_path_constrained_ode_output(self): from openmdao.api import Problem, Group, ScipyOptimizeDriver, DirectSolver from openmdao.utils.assert_utils import assert_rel_error from dymos import Phase, RungeKutta from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() p.driver.options['dynamic_simul_derivs'] = True phase = Phase(ode_class=BrachistochroneODE, transcription=RungeKutta(num_segments=20)) p.model.add_subsystem('phase0', phase) phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(0.5, 2.0)) phase.set_state_options('x', fix_initial=True) phase.set_state_options('y', fix_initial=True) phase.set_state_options('v', fix_initial=True) phase.add_control('theta', units='deg', lower=0.01, upper=179.9, ref0=0, ref=180.0, rate_continuity=True, rate2_continuity=True) phase.add_design_parameter('g', units='m/s**2', opt=False, val=9.80665) # Final state values can't be controlled with simple bounds in ExplicitPhase, # so use nonlinear boundary constraints instead. phase.add_boundary_constraint('x', loc='final', equals=10) phase.add_boundary_constraint('y', loc='final', equals=5) phase.add_path_constraint('check', lower=-500, upper=500, shape=(1,), units='m/s') # Minimize time at the end of the phase phase.add_objective('time_phase', loc='final', scaler=1) p.model.linear_solver = DirectSolver() p.setup(check=True) p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 2.0 p['phase0.states:x'] = 0 p['phase0.states:y'] = 10 p['phase0.states:v'] = 0 p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100.5], nodes='control_input') # Solve for the optimal trajectory p.run_driver() # Test the results assert_rel_error(self, p['phase0.time'][-1], 1.8016, tolerance=1.0E-3) # Generate the explicitly simulated trajectory exp_out = phase.simulate() assert_rel_error(self, exp_out.get_val('phase0.timeseries.states:x')[-1, 0], 10, tolerance=1.0E-3) assert_rel_error(self, exp_out.get_val('phase0.timeseries.states:y')[-1, 0], 5, tolerance=1.0E-3)
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 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()
phase0 = Phase(ode_class=ShuttleODE, transcription=Radau(num_segments=20, order=3)) traj.add_phase(name="phase0", phase=phase0) phase0.set_time_options(fix_initial=True, units="s", duration_ref=200)#, duration_ref=2000, duration_bounds=(50, 3000) phase0.set_state_options("h", fix_initial=True, fix_final=True, units="ft", rate_source="hdot", targets=["h"], lower=0)#, ref=260000, defect_ref=260000, ref0=80000 phase0.set_state_options("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.set_state_options("phi", fix_initial=True, fix_final=False, units="rad", rate_source="phidot", lower=0, upper=89.*np.pi/180) phase0.set_state_options("psi", fix_initial=True, fix_final=False, units="rad", rate_source="psidot", targets=["psi"], lower=0, upper=90.*np.pi/180) phase0.set_state_options("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.set_state_options("v", fix_initial=True, fix_final=True, units="ft/s", rate_source="vdot", targets=["v"], lower=0)#, ref=25600, defect_ref=25600, ref0=2500 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"]) phase0.add_path_constraint("q", lower=0, upper=70, units="Btu/ft**2/s", ref=70)# phase0.add_objective("theta", loc="final", ref=-1) prob.driver = ScipyOptimizeDriver() prob.driver.declare_coloring() prob.driver.options["maxiter"] = 100 prob.setup(check=True) prob.set_val("traj.phase0.states:h", phase0.interpolate(ys=[260000, 80000], nodes="state_input"), units="ft") prob.set_val("traj.phase0.states:gamma", phase0.interpolate(ys=[-1*np.pi/180, -5*np.pi/180], nodes="state_input"), units="rad") prob.set_val("traj.phase0.states:phi", phase0.interpolate(ys=[0, 75*np.pi/180], nodes="state_input"), units="rad") prob.set_val("traj.phase0.states:psi", phase0.interpolate(ys=[90*np.pi/180, 10*np.pi/180], nodes="state_input"), units="rad") prob.set_val("traj.phase0.states:theta", phase0.interpolate(ys=[0, 25*np.pi/180], nodes="state_input"), units="rad") prob.set_val("traj.phase0.states:v", phase0.interpolate(ys=[25600, 2500], nodes="state_input"), units="ft/s")
def ex_aircraft_steady_flight(optimizer='SLSQP', transcription='gauss-lobatto'): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = optimizer p.driver.options['dynamic_simul_derivs'] = True if optimizer == 'SNOPT': p.driver.opt_settings['Major iterations limit'] = 1000 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6 p.driver.opt_settings["Linesearch tolerance"] = 0.10 p.driver.opt_settings['iSumm'] = 6 num_seg = 15 seg_ends, _ = lgl(num_seg + 1) phase = Phase(transcription, ode_class=AircraftODE, num_segments=num_seg, segment_ends=seg_ends, transcription_order=5, compressed=False) # Pass Reference Area from an external source assumptions = p.model.add_subsystem('assumptions', IndepVarComp()) assumptions.add_output('S', val=427.8, units='m**2') assumptions.add_output('mass_empty', val=1.0, units='kg') assumptions.add_output('mass_payload', val=1.0, units='kg') p.model.add_subsystem('phase0', phase) phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(300, 10000), duration_ref=3600) phase.set_state_options('range', units='NM', fix_initial=True, fix_final=False, scaler=0.001, defect_scaler=1.0E-2) phase.set_state_options('mass_fuel', units='lbm', fix_initial=True, fix_final=True, upper=1.5E5, lower=0.0, scaler=1.0E-5, defect_scaler=1.0E-1) phase.add_control('alt', units='kft', opt=True, lower=0.0, upper=50.0, rate_param='climb_rate', rate_continuity=True, rate_continuity_scaler=1.0, rate2_continuity=True, rate2_continuity_scaler=1.0, ref=1.0, fix_initial=True, fix_final=True) phase.add_control('mach', units=None, opt=False) phase.add_input_parameter('S', units='m**2') phase.add_input_parameter('mass_empty', units='kg') phase.add_input_parameter('mass_payload', units='kg') phase.add_path_constraint('propulsion.tau', lower=0.01, upper=1.0) phase.add_path_constraint('alt_rate', units='ft/min', lower=-3000, upper=3000, ref=3000) p.model.connect('assumptions.S', 'phase0.input_parameters:S') p.model.connect('assumptions.mass_empty', 'phase0.input_parameters:mass_empty') p.model.connect('assumptions.mass_payload', 'phase0.input_parameters:mass_payload') phase.add_objective('range', loc='final', ref=-1.0) p.model.linear_solver = DirectSolver(assemble_jac=True) p.setup() p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 3600.0 p['phase0.states:range'] = phase.interpolate(ys=(0, 1000.0), nodes='state_input') p['phase0.states:mass_fuel'] = phase.interpolate(ys=(30000, 0), nodes='state_input') p['phase0.controls:mach'][:] = 0.8 p['phase0.controls:alt'][:] = 10.0 p['assumptions.S'] = 427.8 p['assumptions.mass_empty'] = 0.15E6 p['assumptions.mass_payload'] = 84.02869 * 400 p.run_driver() exp_out = phase.simulate( times=np.linspace(0, p['phase0.t_duration'], 500), record=True, record_file='test_ex_aircraft_steady_flight_rec.db') plt.plot(phase.get_values('time', nodes='all'), phase.get_values('alt', nodes='all'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('alt'), 'b-') plt.suptitle('altitude vs time') plt.figure() plt.plot(phase.get_values('time', nodes='all'), phase.get_values('alt_rate', nodes='all', units='ft/min'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('alt_rate', units='ft/min'), 'b-') plt.suptitle('altitude rate vs time') plt.figure() plt.plot(phase.get_values('time', nodes='all'), phase.get_values('mass_fuel', nodes='all'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('mass_fuel'), 'b-') plt.suptitle('fuel mass vs time') plt.figure() plt.plot(phase.get_values('time', nodes='all'), phase.get_values('propulsion.dXdt:mass_fuel', nodes='all'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('propulsion.dXdt:mass_fuel'), 'b-') plt.suptitle('fuel mass flow rate vs time') plt.figure() plt.plot(phase.get_values('time', nodes='all'), phase.get_values('mach', nodes='all'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('mach'), 'b-') plt.suptitle('mach vs time') plt.figure() plt.plot(phase.get_values('time', nodes='all'), phase.get_values('mach_rate', nodes='all'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('mach_rate'), 'b-') plt.suptitle('mach rate vs time') print('time') print(phase.get_values('time', nodes='all').T) print('alt') print(phase.get_values('alt', nodes='all').T) print('alt_rate') print(phase.get_values('alt_rate', nodes='all').T) print('alt_rate2') print(phase.get_values('alt_rate2', nodes='all').T) print('range') print(phase.get_values('range', nodes='all').T) print('flight path angle') print(phase.get_values('gam_comp.gam').T) print('true airspeed') print(phase.get_values('tas_comp.TAS', units='m/s').T) print('coef of lift') print(phase.get_values('aero.CL').T) print('coef of drag') print(phase.get_values('aero.CD').T) print('atmos density') print(phase.get_values('atmos.rho').T) print('alpha') print(phase.get_values('flight_equilibrium.alpha', units='rad').T) print('coef of thrust') print(phase.get_values('flight_equilibrium.CT').T) print('fuel flow rate') print(phase.get_values('propulsion.dXdt:mass_fuel').T) print('max_thrust') print(phase.get_values('propulsion.max_thrust', units='N').T) print('tau') print(phase.get_values('propulsion.tau').T) print('dynamic pressure') print(phase.get_values('q_comp.q', units='Pa').T) print('S') print(phase.get_values('S', units='m**2').T) plt.show() return p
def setup_energy_opt(num_seg, order, q_tank, q_hx1, q_hx2, opt_burn=False): """ Helper function to set up and return a problem instance for an energy minimization of a simple thermal system. Parameters ---------- num_seg : int The number of ODE segments to use when discretizing the problem. order : int The order for the polynomial interpolation for the collocation methods. q_tank : float The amount of inputted heat to the fuel tank. Positive is heat inputted to the fuel tank. q_hx1 : float A measure of the amount of heat added to the fuel at the first heat exchanger. This mimics the fuel handling the heat generated from a thermal load, such as avionicsc or air conditioners. q_hx2 : float A measure of the amount of heat added to the fuel at the second heat exchanger. This may be a negative number, which means that heat is being taken out of the fuel in some way. opt_burn : boolean If true, we allow the optimizer to control the amount of fuel burned in the system. This mimics the cost of the fuel needed in the plane to provide thrust. """ # Instantiate the problem and set the optimizer p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = 'SNOPT' p.driver.opt_settings['Major iterations limit'] = 2000 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-7 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-7 p.driver.opt_settings['Verify level'] = -1 # Set up the phase for the defined ODE function, can be LGR or LGL phase = Phase('gauss-lobatto', ode_class=SimpleHeatODE, ode_init_kwargs={ 'q_tank': q_tank, 'q_hx1': q_hx1, 'q_hx2': q_hx2 }, num_segments=num_seg, transcription_order=order) # Do not allow the time to vary during the optimization phase.set_time_options(opt_initial=False, opt_duration=False) # Set the state options for mass, temperature, and energy. phase.set_state_options('m', lower=1., upper=10., fix_initial=True) phase.set_state_options('T', fix_initial=True, defect_scaler=.01) phase.set_state_options('energy', fix_initial=True) # Minimize the energy used to pump the fuel phase.set_objective('energy', loc='final') # Allow the optimizer to vary the fuel flow phase.add_control('m_flow', opt=True, lower=0., upper=5., rate_continuity=True) # Optimize the burned fuel amount, if selected if opt_burn: phase.add_control('m_burn', opt=opt_burn, lower=.2, upper=5., dynamic=False) else: phase.add_control('m_burn', opt=opt_burn) # 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. phase.add_path_constraint('T', upper=1.) phase.add_path_constraint('m_flow_rate', upper=0.) phase.add_path_constraint('m_flow', upper=1.) phase.add_path_constraint('fuel_burner.m_recirculated', lower=0.) # Add the phase to the problem and set it up p.model.add_subsystem('phase', phase) p.driver.add_recorder(SqliteRecorder('out.db')) p.setup(check=True, force_alloc_complex=True) # Give initial values for the phase states, controls, and time p['phase.states:m'] = 10. p['phase.states:T'] = 1. p['phase.states:energy'] = 0. p['phase.controls:m_flow'] = .5 p['phase.controls:m_burn'] = .1 p['phase.t_initial'] = 0. p['phase.t_duration'] = 2. return p
phase.set_state_options('gam', fix_initial=True, lower=-1.5, upper=1.5, ref=1.0, defect_scaler=1.0, units='rad') phase.set_state_options('m', fix_initial=True, lower=1e3, upper=1.0E6, scaler=1.0E-3, defect_scaler=1.0E-3) phase.add_control('alpha', units='rad', lower=-8. * np.pi/180., upper=8. * np.pi/180., scaler=1, rate_continuity=True) phase.add_control('throttle', val=1.0, lower=0., upper=1., opt=True, rate_continuity=True) phase.add_boundary_constraint('h', loc='final', equals=100., scaler=1.0E-3, units='m') phase.add_boundary_constraint('r', loc='final', equals=1500., units='km') # phase.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad') phase.add_path_constraint(name='aero.mach', lower=0.01, upper=.9) # phase.add_path_constraint(name='prop.m_dot', upper=0.) # phase.add_path_constraint(name='flight_dynamics.r_dot', lower=0.) # phase.add_path_constraint(name='m', lower=1e4) phase.add_path_constraint(name='h', lower=0.) # phase.set_objective('time', loc='final', ref=10.0) phase.add_objective('m', loc='final', ref=-10000.0) # phase.set_objective('r', loc='final', ref=-100000.0) p.model.linear_solver = DirectSolver(assemble_jac=True) p.model.options['assembled_jac_type'] = 'csc' # p.driver.add_recorder(SqliteRecorder('out.db')) p.setup(mode='fwd', check=True) # from openmdao.api import view_model
def escort_problem(optimizer='SLSQP', num_seg=3, transcription_order=5, transcription='gauss-lobatto', meeting_altitude=14000., climb_time=350., starting_mass=19030.468): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = optimizer if optimizer == 'SNOPT': p.driver.opt_settings['Major iterations limit'] = 1000 p.driver.opt_settings['Iterations limit'] = 100000000 p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-5 p.driver.opt_settings['Verify level'] = -1 p.driver.opt_settings['Function precision'] = 1.0E-6 p.driver.opt_settings['Linesearch tolerance'] = 0.10 p.driver.opt_settings['Major step limit'] = 0.5 phase_class = _phase_map[transcription] climb = Phase('gauss-lobatto', ode_class=MinTimeClimbODE, num_segments=num_seg, transcription_order=transcription_order) climb.set_time_options(duration_bounds=(50, climb_time), duration_ref=100.0) climb.set_state_options('r', fix_initial=True, lower=0, upper=1.0E6, scaler=1.0E-3, defect_scaler=1.0E-2, units='m') climb.set_state_options('h', fix_initial=True, lower=0, upper=20000.0, scaler=1.0E-3, defect_scaler=1.0E-3, units='m') climb.set_state_options('v', fix_initial=True, lower=10.0, scaler=1.0E-2, defect_scaler=1.0E-2, units='m/s') climb.set_state_options('gam', fix_initial=True, lower=-1.5, upper=1.5, ref=1.0, defect_scaler=1.0, units='rad') climb.set_state_options('m', fix_initial=True, lower=10.0, upper=1.0E5, scaler=1.0E-3, defect_scaler=1.0E-3) climb.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, rate_continuity=True) climb.add_control('S', val=49.2386, units='m**2', dynamic=False, opt=False) climb.add_control('Isp', val=5000.0, units='s', dynamic=False, opt=False) climb.add_control('throttle', val=1.0, dynamic=False, opt=False) climb.add_boundary_constraint('h', loc='final', equals=meeting_altitude, scaler=1.0E-3, units='m') climb.add_boundary_constraint('aero.mach', loc='final', equals=1.0, units=None) climb.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad') # climb.add_boundary_constraint('time', loc='final', upper=climb_time, units='s') climb.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000) climb.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8) # Minimize time at the end of the climb climb.set_objective('time', loc='final', ref=100.0) p.model.add_subsystem('climb', climb) escort = Phase('gauss-lobatto', ode_class=MinTimeClimbODE, num_segments=num_seg * 2, transcription_order=transcription_order) escort.set_time_options(duration_bounds=(50, 10000), opt_initial=True, duration_ref=100.0) escort.set_state_options('r', lower=0, upper=1.0E6, scaler=1.0E-3, defect_scaler=1.0E-2, units='m') escort.set_state_options('h', lower=0, upper=20000.0, scaler=1.0E-3, defect_scaler=1.0E-3, units='m') escort.set_state_options('v', lower=10.0, scaler=1.0E-2, defect_scaler=1.0E-2, units='m/s') escort.set_state_options('gam', lower=-1.5, upper=1.5, ref=1.0, defect_scaler=1.0, units='rad') escort.set_state_options('m', lower=10.0, upper=1.0E5, scaler=1.0E-3, defect_scaler=1.0E-3) escort.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, rate_continuity=True) escort.add_control('S', val=49.2386, units='m**2', dynamic=False, opt=False) escort.add_control('Isp', val=1600.0, units='s', dynamic=False, opt=False) escort.add_control('throttle', val=1.0, lower=0., upper=1., opt=True) # escort.add_control('throttle', val=1.0, dynamic=False, opt=False) # escort.add_boundary_constraint('h', loc='final', equals=20000, scaler=1.0E-3, units='m') # escort.add_boundary_constraint('aero.mach', loc='final', equals=1.0, units=None) # escort.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad') escort.add_boundary_constraint('m', loc='final', equals=15000.0, units='kg') escort.add_path_constraint(name='h', lower=meeting_altitude, upper=meeting_altitude, ref=meeting_altitude) escort.add_path_constraint(name='aero.mach', equals=1.0) # Maximize distance at the end of the escort # escort.set_objective('r', loc='final', ref=-1e5) p.model.add_subsystem('escort', escort) # Connect the phases linkage_comp = PhaseLinkageComp() linkage_comp.add_linkage(name='L01', vars=['t'], units='s', equals=0.0, linear=True) linkage_comp.add_linkage(name='L01', vars=['r'], units='m', equals=0.0, linear=True) linkage_comp.add_linkage(name='L01', vars=['h'], units='m', equals=0.0, linear=True) linkage_comp.add_linkage(name='L01', vars=['v'], units='m/s', equals=0.0, linear=True) linkage_comp.add_linkage(name='L01', vars=['gam'], units='rad', equals=0.0, linear=True) linkage_comp.add_linkage(name='L01', vars=['m'], units='kg', equals=0.0, linear=True) linkage_comp.add_linkage(name='L01', vars=['alpha'], units='rad', equals=0.0, linear=True) linkage_comp.add_linkage(name='L01', vars=['throttle'], equals=0.0, linear=True) p.model.connect('climb.time++', 'linkages.L01_t:lhs') p.model.connect('escort.time--', 'linkages.L01_t:rhs') p.model.connect('climb.states:r++', 'linkages.L01_r:lhs') p.model.connect('escort.states:r--', 'linkages.L01_r:rhs') p.model.connect('climb.states:h++', 'linkages.L01_h:lhs') p.model.connect('escort.states:h--', 'linkages.L01_h:rhs') # p.model.connect('climb.states:v++', 'linkages.L01_v:lhs') p.model.connect('escort.states:v--', 'linkages.L01_v:rhs') # p.model.connect('climb.states:gam++', 'linkages.L01_gam:lhs') p.model.connect('escort.states:gam--', 'linkages.L01_gam:rhs') p.model.connect('climb.states:m++', 'linkages.L01_m:lhs') p.model.connect('escort.states:m--', 'linkages.L01_m:rhs') p.model.connect('climb.controls:alpha++', 'linkages.L01_alpha:lhs') p.model.connect('escort.controls:alpha--', 'linkages.L01_alpha:rhs') p.model.connect('climb.controls:throttle++', 'linkages.L01_throttle:lhs') p.model.connect('escort.controls:throttle--', 'linkages.L01_throttle:rhs') p.model.add_subsystem('linkages', linkage_comp) p.model.linear_solver = DirectSolver(assemble_jac=True) p.model.options['assembled_jac_type'] = 'csc' # p.driver.add_recorder(SqliteRecorder('escort.db')) p.setup(mode='fwd', check=True) p['climb.t_initial'] = 0.0 p['climb.t_duration'] = 200. p['climb.states:r'] = climb.interpolate(ys=[0.0, 111319.54], nodes='disc') p['climb.states:h'] = climb.interpolate(ys=[100.0, 20000.0], nodes='disc') p['climb.states:v'] = climb.interpolate(ys=[135.964, 283.159], nodes='disc') p['climb.states:gam'] = climb.interpolate(ys=[0.0, 0.0], nodes='disc') p['climb.states:m'] = climb.interpolate(ys=[starting_mass, 16841.431], nodes='disc') p['climb.controls:alpha'] = climb.interpolate(ys=[0.0, 0.0], nodes='all') p['escort.t_initial'] = 200. p['escort.t_duration'] = 1000. p['escort.states:r'] = escort.interpolate(ys=[111319.54, 400000.], nodes='disc') p['escort.states:h'] = escort.interpolate( ys=[meeting_altitude, meeting_altitude], nodes='disc') p['escort.states:v'] = escort.interpolate(ys=[250., 250.], nodes='disc') p['escort.states:gam'] = escort.interpolate(ys=[0.0, 0.0], nodes='disc') p['escort.states:m'] = escort.interpolate(ys=[17000., 15000.], nodes='disc') p['escort.controls:alpha'] = escort.interpolate(ys=[0.0, 0.0], nodes='all') return p
def thermal_mission_problem(num_seg=5, transcription_order=3, meeting_altitude=20000., Q_env=0., Q_sink=0., Q_out=0., m_recirculated=0., opt_m_recirculated=False, opt_m_burn=False, opt_throttle=True, engine_heat_coeff=0., pump_heat_coeff=0., T=None, T_o=None, opt_m=False, m_initial=20.e3, transcription='gauss-lobatto'): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = 'SNOPT' p.driver.opt_settings['Major iterations limit'] = 5000 p.driver.opt_settings['Iterations limit'] = 5000000000000000 p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-8 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-8 p.driver.opt_settings['Verify level'] = -1 p.driver.opt_settings['Linesearch tolerance'] = .1 p.driver.opt_settings['Major step limit'] = .1 p.driver.options['dynamic_simul_derivs'] = True phase = Phase(transcription, ode_class=ThermalMissionODE, ode_init_kwargs={'engine_heat_coeff':engine_heat_coeff, 'pump_heat_coeff':pump_heat_coeff}, num_segments=num_seg, transcription_order=transcription_order) p.model.add_subsystem('phase', phase) phase.set_time_options(opt_initial=False, duration_bounds=(50, 400), duration_ref=100.0) phase.set_state_options('r', fix_initial=True, lower=0, upper=1.0E6, scaler=1.0E-3, defect_scaler=1.0E-2, units='m') phase.set_state_options('h', fix_initial=True, lower=0, upper=20000.0, scaler=1.0E-3, defect_scaler=1.0E-3, units='m') phase.set_state_options('v', fix_initial=True, lower=10.0, scaler=1.0E-2, defect_scaler=5.0E-0, units='m/s') phase.set_state_options('gam', fix_initial=True, lower=-1.5, upper=1.5, ref=1.0, defect_scaler=1.0, units='rad') phase.set_state_options('m', fix_initial=not opt_m, lower=15.e3, upper=80e3, scaler=1.0E-3, defect_scaler=1.0E-3, units='kg') phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, rate_continuity=True) phase.add_design_parameter('S', val=1., units='m**2', opt=False) if opt_throttle: phase.add_control('throttle', val=1.0, lower=0.0, upper=1.0, opt=True, rate_continuity=True) else: phase.add_design_parameter('throttle', val=1.0, opt=False) phase.add_design_parameter('W0', val=10.5e3, opt=False, units='kg') phase.add_boundary_constraint('h', loc='final', equals=meeting_altitude, scaler=1.0E-3, units='m') phase.add_boundary_constraint('aero.mach', loc='final', equals=1., units=None) phase.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad') phase.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000) phase.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8) # phase.add_path_constraint(name='time', upper=110.) # Minimize time at the end of the phase phase.add_objective('time', loc='final', ref=100.0) # phase.add_objective('energy', loc='final', ref=100.0) # phase.add_objective('m', loc='final', ref=-10000.0) # Set the state options for mass, temperature, and energy. phase.set_state_options('T', fix_initial=True, ref=300, defect_scaler=1e-2) phase.set_state_options('energy', fix_initial=True, ref=10e3, defect_scaler=1e-4) # Allow the optimizer to vary the fuel flow if opt_m_recirculated: phase.add_control('m_recirculated', val=m_recirculated, lower=0., opt=True, rate_continuity=True, ref=20.) else: phase.add_control('m_recirculated', val=m_recirculated, opt=False) phase.add_design_parameter('Q_env', val=Q_env, opt=False) phase.add_design_parameter('Q_sink', val=Q_sink, opt=False) phase.add_design_parameter('Q_out', val=Q_out, opt=False) # Constrain the temperature, 2nd derivative of fuel mass in the tank, and make # sure that the amount recirculated is at least 0, otherwise we'd burn # more fuel than we pumped. if opt_m_recirculated: phase.add_path_constraint('m_flow', lower=0., upper=50., units='kg/s', ref=10.) if T is not None: phase.add_path_constraint('T', upper=T, units='K') if T_o is not None: phase.add_path_constraint('T_o', upper=T_o, units='K', ref=300.) # phase.add_path_constraint('m_flow', lower=0., upper=20., units='kg/s', ref=10.) p.setup(mode='fwd', check=True) p['phase.t_initial'] = 0.0 p['phase.t_duration'] = 200. p['phase.states:r'] = phase.interpolate(ys=[0.0, 111319.54], nodes='state_input') p['phase.states:h'] = phase.interpolate(ys=[100.0, meeting_altitude], nodes='state_input') # p['phase.states:h'][:] = 10000. p['phase.states:v'] = phase.interpolate(ys=[135.964, 283.159], nodes='state_input') # p['phase.states:v'][:] = 200. p['phase.states:gam'] = phase.interpolate(ys=[0.0, 0.0], nodes='state_input') p['phase.states:m'] = phase.interpolate(ys=[m_initial, 12.e3], nodes='state_input') p['phase.controls:alpha'] = phase.interpolate(ys=[1., 1.], nodes='control_input') # Give initial values for the phase states, controls, and time p['phase.states:T'] = 310. return p
def min_time_climb_problem(num_seg=3, transcription_order=5, transcription='gauss-lobatto', top_level_densejacobian=True): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = 'SNOPT' p.driver.opt_settings['Major iterations limit'] = 500 p.driver.opt_settings['Iterations limit'] = 1000000000 p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-10 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-10 p.driver.opt_settings['Verify level'] = 1 p.driver.opt_settings['Function precision'] = 1.0E-6 p.driver.opt_settings['Linesearch tolerance'] = .1 p.driver.options['dynamic_simul_derivs'] = True phase = Phase(transcription, ode_class=MinTimeClimbODE, num_segments=num_seg, transcription_order=transcription_order) p.model.add_subsystem('phase', phase) phase.set_time_options(opt_initial=False, duration_bounds=(100, 100), duration_ref=100.0) phase.set_state_options('r', fix_initial=True, lower=0, upper=1.0E8, scaler=1.0E-4, defect_scaler=1.0E-3, units='m') phase.set_state_options('h', lower=0, upper=20000.0, scaler=1.0E-3, defect_scaler=1.0E-3, units='m') phase.set_state_options('v', lower=10.0, upper=500., scaler=1.0E-2, defect_scaler=1.0E-2, units='m/s') phase.set_state_options('gam', lower=-1.5, upper=1.5, ref=1.0, defect_scaler=1.0, units='rad') phase.set_state_options('m', fix_initial=True, lower=10.0, upper=1.0E5, scaler=1.0E-3, defect_scaler=1.0E-3, units='kg') phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, rate_continuity=True) phase.add_control('S', val=49.2386, units='m**2', dynamic=False, opt=False) phase.add_control('throttle', val=1.0, opt=True, lower=0., upper=1., rate_continuity=False) phase.add_path_constraint(name='h', lower=1e4, upper=1e4, ref=20000, units='m') phase.add_path_constraint(name='aero.mach', lower=1.2, upper=1.2) phase.add_objective('time', loc='final', ref=-100.0) p.model.linear_solver = DirectSolver(assemble_jac=True) p.model.options['assembled_jac_type'] = 'csc' p.setup(mode='fwd', check=True) p['phase.t_initial'] = 0.0 p['phase.t_duration'] = 2000. p['phase.states:r'] = phase.interpolate(ys=[0.0, 1e6], nodes='disc') p['phase.states:h'][:] = 1e4 p['phase.states:v'][:] = 250. p['phase.states:gam'][:] = 0. p['phase.states:m'] = phase.interpolate(ys=[50e3, 49e3], nodes='disc') return p
def test_cruise_results_gl(self): 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['Major step limit'] = 0.05 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6 p.driver.opt_settings["Linesearch tolerance"] = 0.10 p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Verify level'] = 3 else: p.driver = ScipyOptimizeDriver() p.driver.options['dynamic_simul_derivs'] = True transcription = GaussLobatto(num_segments=1, order=13, compressed=False) phase = Phase(ode_class=AircraftODE, transcription=transcription) p.model.add_subsystem('phase0', phase) # Pass Reference Area from an external source assumptions = p.model.add_subsystem('assumptions', IndepVarComp()) assumptions.add_output('S', val=427.8, units='m**2') assumptions.add_output('mass_empty', val=1.0, units='kg') assumptions.add_output('mass_payload', val=1.0, units='kg') phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(3600, 3600), duration_ref=3600) phase.set_state_options('range', units='km', fix_initial=True, fix_final=False, scaler=0.01, defect_scaler=0.01) phase.set_state_options('mass_fuel', fix_final=True, upper=20000.0, lower=0.0, scaler=1.0E-4, defect_scaler=1.0E-2) phase.set_state_options('alt', units='km', fix_initial=True) phase.add_control('mach', units=None, opt=False) phase.add_control('climb_rate', units='m/s', opt=False) phase.add_input_parameter('S', units='m**2') phase.add_input_parameter('mass_empty', units='kg') phase.add_input_parameter('mass_payload', units='kg') phase.add_path_constraint('propulsion.tau', lower=0.01, upper=1.0, shape=(1, )) phase.add_timeseries_output('tas_comp.TAS', units='m/s') p.model.connect('assumptions.S', 'phase0.input_parameters:S') p.model.connect('assumptions.mass_empty', 'phase0.input_parameters:mass_empty') p.model.connect('assumptions.mass_payload', 'phase0.input_parameters:mass_payload') phase.add_objective('time', loc='final', ref=3600) p.model.linear_solver = DirectSolver() p.setup() p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 1.515132 * 3600.0 p['phase0.states:range'] = phase.interpolate(ys=(0, 1296.4), nodes='state_input') p['phase0.states:mass_fuel'] = phase.interpolate(ys=(12236.594555, 0), nodes='state_input') p['phase0.states:alt'] = 5.0 p['phase0.controls:mach'] = 0.8 p['phase0.controls:climb_rate'] = 0.0 p['assumptions.S'] = 427.8 p['assumptions.mass_empty'] = 0.15E6 p['assumptions.mass_payload'] = 84.02869 * 400 p.run_driver() time = p.get_val('phase0.timeseries.time') tas = p.get_val('phase0.timeseries.TAS', units='km/s') range = p.get_val('phase0.timeseries.states:range') assert_rel_error(self, range, tas * time, tolerance=1.0E-4)
def setup_energy_opt(num_seg, order, Q_env=0., Q_sink=0., Q_out=0., m_flow=0.1, m_burn=0., opt_m_flow=False, opt_m_burn=False): """ Helper function to set up and return a problem instance for an energy minimization of a simple thermal system. Parameters ---------- num_seg : int The number of ODE segments to use when discretizing the problem. order : int The order for the polynomial interpolation for the collocation methods. """ # Instantiate the problem and set the optimizer p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = 'SNOPT' p.driver.opt_settings['Major iterations limit'] = 2000 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-10 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-10 p.driver.opt_settings['Verify level'] = -1 # Set up the phase for the defined ODE function, can be LGR or LGL phase = Phase('gauss-lobatto', ode_class=TankAloneODE, ode_init_kwargs={}, num_segments=num_seg, transcription_order=order, compressed=True) # Do not allow the time to vary during the optimization phase.set_time_options(opt_initial=False, opt_duration=False) # Set the state options for mass, temperature, and energy. phase.set_state_options('m', units='kg', lower=1e2, upper=1e5, fix_initial=True) phase.set_state_options('T', units='K', fix_initial=True) phase.set_state_options('energy', fix_initial=True) # Minimize the energy used to pump the fuel phase.add_objective('energy', loc='final', ref=10e2) # phase.add_objective('m', loc='initial') # phase.add_objective('time', loc='final') # Allow the optimizer to vary the fuel flow if opt_m_flow: phase.add_control('m_flow', val=m_flow, lower=0.01, opt=True, rate_continuity=True) else: phase.add_control('m_flow', val=m_flow, opt=False) if opt_m_burn: phase.add_control('m_burn', val=m_burn, lower=0.01, opt=True, rate_continuity=True) else: phase.add_control('m_burn', val=m_burn, opt=False) phase.add_control('Q_env', val=Q_env, dynamic=False, opt=False) phase.add_control('Q_sink', val=Q_sink, dynamic=False, opt=False) phase.add_control('Q_out', val=Q_out, dynamic=False, 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_flow: phase.add_path_constraint('T', lower=0.) phase.add_path_constraint('T', upper=333.) phase.add_path_constraint('T_o', lower=0., units='K') phase.add_path_constraint('T_o', upper=333., units='K') # phase.add_path_constraint('m_flow_rate', upper=0.) phase.add_path_constraint('m_recirculated', lower=0., units='kg/s') phase.add_path_constraint('m_flow', lower=0., upper=50.) # Add the phase to the problem and set it up p.model.add_subsystem('phase', phase) p.driver.add_recorder(SqliteRecorder('out.db')) p.setup(check=True, force_alloc_complex=True, mode='fwd') # Give initial values for the phase states, controls, and time p['phase.states:m'] = 6000 p['phase.states:T'] = 300. p['phase.states:energy'] = 0. # p['phase.controls:m_burn'][:10] = np.atleast_2d(np.linspace(2., .5, num_seg*order)[:10]).T**2 # p['phase.controls:m_burn'][10:] = 2.2 p['phase.t_initial'] = 0. p['phase.t_duration'] = 9000 p.set_solver_print(level=-1) return p
def test_brachistochrone_vector_ode_path_constraints_rk_partial_indices( self): p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() p.driver.options['dynamic_simul_derivs'] = True phase = Phase(ode_class=BrachistochroneVectorStatesODE, transcription=RungeKutta(num_segments=20)) p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10)) phase.set_state_options('pos', fix_initial=True, fix_final=False) phase.set_state_options('v', fix_initial=True, fix_final=False) phase.add_control('theta', continuity=True, rate_continuity=True, units='deg', lower=0.01, upper=179.9) phase.add_design_parameter('g', units='m/s**2', opt=False, val=9.80665) phase.add_boundary_constraint('pos', loc='final', equals=[10, 5]) phase.add_path_constraint('pos_dot', shape=(2, ), units='m/s', indices=[1], lower=-4, upper=4) phase.add_timeseries_output('pos_dot', shape=(2, ), units='m/s') # Minimize time at the end of the phase phase.add_objective('time', loc='final', scaler=10) p.model.linear_solver = DirectSolver() p.setup(check=True, force_alloc_complex=True) p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 2.0 pos0 = [0, 10] posf = [10, 5] p['phase0.states:pos'] = phase.interpolate(ys=[pos0, posf], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100], nodes='control_input') p['phase0.design_parameters:g'] = 9.80665 p.run_driver() assert_rel_error(self, np.min(p.get_val('phase0.timeseries.pos_dot')[:, -1]), -4, tolerance=1.0E-2) # Plot results if SHOW_PLOTS: exp_out = phase.simulate(times_per_seg=20) fig, ax = plt.subplots() fig.suptitle('Brachistochrone Solution') x_imp = p.get_val('phase0.timeseries.states:pos')[:, 0] y_imp = p.get_val('phase0.timeseries.states:pos')[:, 1] x_exp = exp_out.get_val('phase0.timeseries.states:pos')[:, 0] y_exp = exp_out.get_val('phase0.timeseries.states:pos')[:, 1] ax.plot(x_imp, y_imp, 'ro', label='implicit') ax.plot(x_exp, y_exp, 'b-', label='explicit') ax.set_xlabel('x (m)') ax.set_ylabel('y (m)') ax.grid(True) ax.legend(loc='upper right') fig, ax = plt.subplots() fig.suptitle('Brachistochrone Solution\nVelocity') t_imp = p.get_val('phase0.timeseries.time') t_exp = exp_out.get_val('phase0.timeseries.time') xdot_imp = p.get_val('phase0.timeseries.pos_dot')[:, 0] ydot_imp = p.get_val('phase0.timeseries.pos_dot')[:, 1] xdot_exp = exp_out.get_val('phase0.timeseries.pos_dot')[:, 0] ydot_exp = exp_out.get_val('phase0.timeseries.pos_dot')[:, 1] ax.plot(t_imp, xdot_imp, 'bo', label='implicit') ax.plot(t_exp, xdot_exp, 'b-', label='explicit') ax.plot(t_imp, ydot_imp, 'ro', label='implicit') ax.plot(t_exp, ydot_exp, 'r-', label='explicit') ax.set_xlabel('t (s)') ax.set_ylabel('v (m/s)') ax.grid(True) ax.legend(loc='upper right') fig, ax = plt.subplots() fig.suptitle('Brachistochrone Solution') x_imp = p.get_val('phase0.timeseries.time') y_imp = p.get_val('phase0.timeseries.control_rates:theta_rate2') x_exp = exp_out.get_val('phase0.timeseries.time') y_exp = exp_out.get_val( 'phase0.timeseries.control_rates:theta_rate2') ax.plot(x_imp, y_imp, 'ro', label='implicit') ax.plot(x_exp, y_exp, 'b-', label='explicit') ax.set_xlabel('time (s)') ax.set_ylabel('theta rate2 (rad/s**2)') ax.grid(True) ax.legend(loc='lower right') plt.show() return p
upper=10, lower=-10.0, scaler=200.0, adder=-10) phase.add_control('vy%d' % i, rate_continuity=False, units='m/s', opt=True, upper=10, lower=-10.0, scaler=200.0, adder=-10) #phase.add_control('chi%d' % i, units='deg', opt=True, upper=180, lower=-180) phase.add_path_constraint(name='schedule%d.err_d' % i, constraint_name='schedule_err%d' % i, scaler=100.0, upper=10.0, units='m') phase.add_path_constraint(name='keepout%d.dist' % i, constraint_name='keepout%d' % i, scaler=0.1, lower=keepout_radius, units='m') for i, j in combinations([i for i in range(n_traj)], 2): phase.add_path_constraint(name='distance_%d_%d.dist' % (i, j), constraint_name='distance_%d_%d' % (i, j), scaler=0.1, lower=personal_zone, units='m') # Minimize time to target
def min_time_climb(optimizer='SLSQP', num_seg=3, transcription='gauss-lobatto', transcription_order=3, top_level_jacobian='csc', simul_derivs=True, force_alloc_complex=False): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = optimizer if simul_derivs: p.driver.options['dynamic_simul_derivs'] = True if optimizer == 'SNOPT': p.driver.opt_settings['Major iterations limit'] = 1000 p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6 p.driver.opt_settings['Function precision'] = 1.0E-6 p.driver.opt_settings['Linesearch tolerance'] = 0.10 p.driver.opt_settings['Major step limit'] = 0.5 # p.driver.opt_settings['Verify level'] = 3 phase = Phase(transcription, ode_class=MinTimeClimbODE, num_segments=num_seg, compressed=True, transcription_order=transcription_order) p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(50, 400), duration_ref=100.0) phase.set_state_options('r', fix_initial=True, lower=0, upper=1.0E6, scaler=1.0E-3, defect_scaler=1.0E-2, units='m') phase.set_state_options('h', fix_initial=True, lower=0, upper=20000.0, scaler=1.0E-3, defect_scaler=1.0E-3, units='m') phase.set_state_options('v', fix_initial=True, lower=10.0, scaler=1.0E-2, defect_scaler=1.0E-2, units='m/s') phase.set_state_options('gam', fix_initial=True, lower=-1.5, upper=1.5, ref=1.0, defect_scaler=1.0, units='rad') phase.set_state_options('m', fix_initial=True, lower=10.0, upper=1.0E5, scaler=1.0E-3, defect_scaler=1.0E-3) phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, continuity=True, rate_continuity=True, rate2_continuity=False) phase.add_design_parameter('S', val=49.2386, units='m**2', opt=False) phase.add_design_parameter('Isp', val=1600.0, units='s', opt=False) phase.add_design_parameter('throttle', val=1.0, opt=False) phase.add_boundary_constraint('h', loc='final', equals=20000, scaler=1.0E-3, units='m') phase.add_boundary_constraint('aero.mach', loc='final', equals=1.0, units=None) phase.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad') phase.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000) phase.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8) phase.add_path_constraint(name='alpha', lower=-8, upper=8) # Minimize time at the end of the phase phase.add_objective('time', loc='final') p.model.options['assembled_jac_type'] = top_level_jacobian.lower() p.model.linear_solver = DirectSolver(assemble_jac=True) p.setup(check=True, force_alloc_complex=force_alloc_complex) p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 298.46902 p['phase0.states:r'] = phase.interpolate(ys=[0.0, 111319.54], nodes='state_input') p['phase0.states:h'] = phase.interpolate(ys=[100.0, 20000.0], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[135.964, 283.159], nodes='state_input') p['phase0.states:gam'] = phase.interpolate(ys=[0.0, 0.0], nodes='state_input') p['phase0.states:m'] = phase.interpolate(ys=[19030.468, 16841.431], nodes='state_input') p['phase0.controls:alpha'] = phase.interpolate(ys=[0.0, 0.0], nodes='control_input') p.run_driver() if SHOW_PLOTS: exp_out = phase.simulate(times=np.linspace(0, p['phase0.t_duration'], 100)) import matplotlib.pyplot as plt plt.plot(phase.get_values('time'), phase.get_values('h'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('h'), 'b-') plt.xlabel('time (s)') plt.ylabel('altitude (m)') plt.figure() plt.plot(phase.get_values('v'), phase.get_values('h'), 'ro') plt.plot(exp_out.get_values('v'), exp_out.get_values('h'), 'b-') plt.xlabel('airspeed (m/s)') plt.ylabel('altitude (m)') plt.figure() plt.plot(phase.get_values('time'), phase.get_values('alpha'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('alpha'), 'b-') plt.xlabel('time (s)') plt.ylabel('alpha (rad)') plt.figure() plt.plot(phase.get_values('time'), phase.get_values('prop.thrust', units='lbf'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('prop.thrust', units='lbf'), 'b-') plt.xlabel('time (s)') plt.ylabel('thrust (lbf)') plt.show() return p
def test_steady_aircraft_for_docs(self): import numpy as np import matplotlib.pyplot as plt from openmdao.api import Problem, Group, pyOptSparseDriver, DirectSolver, IndepVarComp from openmdao.utils.assert_utils import assert_rel_error from dymos import Phase from dymos.examples.aircraft_steady_flight.aircraft_ode import AircraftODE from dymos.utils.lgl import lgl p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.options['dynamic_simul_derivs'] = True num_seg = 15 seg_ends, _ = lgl(num_seg + 1) phase = Phase('gauss-lobatto', ode_class=AircraftODE, num_segments=num_seg, segment_ends=seg_ends, transcription_order=5, compressed=False) # Pass design parameters in externally from an external source assumptions = p.model.add_subsystem('assumptions', IndepVarComp()) assumptions.add_output('mach', val=0.8, units=None) assumptions.add_output('S', val=427.8, units='m**2') assumptions.add_output('mass_empty', val=1.0, units='kg') assumptions.add_output('mass_payload', val=1.0, units='kg') p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(300, 10000), duration_ref=3600) phase.set_state_options('range', units='NM', fix_initial=True, fix_final=False, scaler=0.001, defect_scaler=1.0E-2) phase.set_state_options('mass_fuel', units='lbm', fix_initial=True, fix_final=True, upper=1.5E5, lower=0.0, scaler=1.0E-5, defect_scaler=1.0E-1) phase.add_control('alt', units='kft', opt=True, lower=0.0, upper=50.0, rate_param='climb_rate', rate_continuity=True, rate_continuity_scaler=1.0, rate2_continuity=True, rate2_continuity_scaler=1.0, ref=1.0, fix_initial=True, fix_final=True) phase.add_input_parameter('mach', units=None) phase.add_input_parameter('S', units='m**2') phase.add_input_parameter('mass_empty', units='kg') phase.add_input_parameter('mass_payload', units='kg') phase.add_path_constraint('propulsion.tau', lower=0.01, upper=1.0) phase.add_path_constraint('alt_rate', units='ft/min', lower=-3000, upper=3000, ref=3000) p.model.connect('assumptions.mach', 'phase0.input_parameters:mach') p.model.connect('assumptions.S', 'phase0.input_parameters:S') p.model.connect('assumptions.mass_empty', 'phase0.input_parameters:mass_empty') p.model.connect('assumptions.mass_payload', 'phase0.input_parameters:mass_payload') phase.add_objective('range', loc='final', ref=-1.0) p.model.linear_solver = DirectSolver(assemble_jac=True) p.setup() p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 3600.0 p['phase0.states:range'] = phase.interpolate(ys=(0, 1000.0), nodes='state_input') p['phase0.states:mass_fuel'] = phase.interpolate(ys=(30000, 0), nodes='state_input') p['phase0.controls:alt'][:] = 10.0 p['assumptions.mach'][:] = 0.8 p['assumptions.S'] = 427.8 p['assumptions.mass_empty'] = 0.15E6 p['assumptions.mass_payload'] = 84.02869 * 400 p.run_driver() exp_out = phase.simulate(times=np.linspace(0, p['phase0.t_duration'], 500), record=True, record_file='test_doc_aircraft_steady_flight_rec.db') assert_rel_error(self, phase.get_values('range', units='NM')[-1], 726.7, tolerance=1.0E-2) plt.figure() plt.plot(phase.get_values('time', nodes='all'), phase.get_values('alt', nodes='all', units='ft'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('alt', units='ft'), 'b-') plt.suptitle('Altitude vs Time') plt.xlabel('Time (s)') plt.ylabel('Altitude (ft)') plt.figure() plt.plot(phase.get_values('time', nodes='all'), phase.get_values('alt_rate', nodes='all', units='ft/min'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('alt_rate', units='ft/min'), 'b-') plt.suptitle('Climb Rate vs Time') plt.xlabel('Time (s)') plt.ylabel('Climb Rate (ft/min)') plt.figure() plt.plot(phase.get_values('time', nodes='all'), phase.get_values('mass_fuel', nodes='all', units='lbm'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('mass_fuel', units='lbm'), 'b-') plt.suptitle('Fuel Mass vs Time') plt.xlabel('Time (s)') plt.ylabel('Fuel Mass (lbm)') plt.show()