def test_vanderpol_for_docs_optimize_refine(self): import dymos as dm from dymos.examples.plotting import plot_results from dymos.examples.vanderpol.vanderpol_dymos import vanderpol # Create the Dymos problem instance p = vanderpol(transcription='gauss-lobatto', num_segments=15, transcription_order=3, compressed=True, optimizer='SLSQP') # Enable grid refinement and find optimal control solution to stop oscillation p.model.traj.phases.phase0.set_refine_options(refine=True) dm.run_problem(p, refine=True, refine_iteration_limit=10) # check validity by using scipy.integrate.solve_ivp to integrate the solution exp_out = p.model.traj.simulate() # Display the results plot_results([ ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:x1', 'time (s)', 'x1 (V)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:x0', 'time (s)', 'x0 (V/s)'), ('traj.phase0.timeseries.states:x0', 'traj.phase0.timeseries.states:x1', 'x0 vs x1', 'x0 vs x1'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:u', 'time (s)', 'control u'), ], title='Van Der Pol Optimization with Grid Refinement', p_sol=p, p_sim=exp_out) plt.show()
def test_vanderpol_for_docs_simulation(self): from dymos.examples.plotting import plot_results from dymos.examples.vanderpol.vanderpol_dymos import vanderpol # Create the Dymos problem instance p = vanderpol(transcription='gauss-lobatto', num_segments=75) # Run the problem (simulate only) p.run_model() # check validity by using scipy.integrate.solve_ivp to integrate the solution exp_out = p.model.traj.simulate() # Display the results plot_results([ ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:x1', 'time (s)', 'x1 (V)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:x0', 'time (s)', 'x0 (V/s)'), ('traj.phase0.timeseries.states:x0', 'traj.phase0.timeseries.states:x1', 'x0 vs x1', 'x0 vs x1'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:u', 'time (s)', 'control u'), ], title='Van Der Pol Simulation', p_sol=p, p_sim=exp_out) plt.show()
def test_doc_ssto_linear_tangent_guidance(self): import numpy as np import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.assert_utils import assert_rel_error import dymos as dm from dymos.examples.plotting import plot_results g = 1.61544 # lunar gravity, m/s**2 class LaunchVehicle2DEOM(om.ExplicitComponent): """ Simple 2D Cartesian Equations of Motion for a launch vehicle subject to thrust and drag. """ def initialize(self): self.options.declare('num_nodes', types=int) def setup(self): nn = self.options['num_nodes'] # Inputs self.add_input('vx', val=np.zeros(nn), desc='x velocity', units='m/s') self.add_input('vy', val=np.zeros(nn), desc='y velocity', units='m/s') self.add_input('m', val=np.zeros(nn), desc='mass', units='kg') self.add_input('theta', val=np.zeros(nn), desc='pitch angle', units='rad') self.add_input('thrust', val=2100000 * np.ones(nn), desc='thrust', units='N') self.add_input('Isp', val=265.2 * np.ones(nn), desc='specific impulse', units='s') # Outputs self.add_output('xdot', val=np.zeros(nn), desc='velocity component in x', units='m/s') self.add_output('ydot', val=np.zeros(nn), desc='velocity component in y', units='m/s') self.add_output('vxdot', val=np.zeros(nn), desc='x acceleration magnitude', units='m/s**2') self.add_output('vydot', val=np.zeros(nn), desc='y acceleration magnitude', units='m/s**2') self.add_output('mdot', val=np.zeros(nn), desc='mass rate of change', units='kg/s') # Setup partials ar = np.arange(self.options['num_nodes']) self.declare_partials(of='xdot', wrt='vx', rows=ar, cols=ar, val=1.0) self.declare_partials(of='ydot', wrt='vy', rows=ar, cols=ar, val=1.0) self.declare_partials(of='vxdot', wrt='vx', rows=ar, cols=ar) self.declare_partials(of='vxdot', wrt='m', rows=ar, cols=ar) self.declare_partials(of='vxdot', wrt='theta', rows=ar, cols=ar) self.declare_partials(of='vxdot', wrt='thrust', rows=ar, cols=ar) self.declare_partials(of='vydot', wrt='m', rows=ar, cols=ar) self.declare_partials(of='vydot', wrt='theta', rows=ar, cols=ar) self.declare_partials(of='vydot', wrt='vy', rows=ar, cols=ar) self.declare_partials(of='vydot', wrt='thrust', rows=ar, cols=ar) self.declare_partials(of='mdot', wrt='thrust', rows=ar, cols=ar) self.declare_partials(of='mdot', wrt='Isp', rows=ar, cols=ar) def compute(self, inputs, outputs): theta = inputs['theta'] cos_theta = np.cos(theta) sin_theta = np.sin(theta) vx = inputs['vx'] vy = inputs['vy'] m = inputs['m'] F_T = inputs['thrust'] Isp = inputs['Isp'] outputs['xdot'] = vx outputs['ydot'] = vy outputs['vxdot'] = F_T * cos_theta / m outputs['vydot'] = F_T * sin_theta / m - g outputs['mdot'] = -F_T / (g * Isp) def compute_partials(self, inputs, jacobian): theta = inputs['theta'] cos_theta = np.cos(theta) sin_theta = np.sin(theta) m = inputs['m'] F_T = inputs['thrust'] Isp = inputs['Isp'] # jacobian['vxdot', 'vx'] = -CDA * rho * vx / m jacobian['vxdot', 'm'] = -(F_T * cos_theta) / m**2 jacobian['vxdot', 'theta'] = -(F_T / m) * sin_theta jacobian['vxdot', 'thrust'] = cos_theta / m # jacobian['vydot', 'vy'] = -CDA * rho * vy / m jacobian['vydot', 'm'] = -(F_T * sin_theta) / m**2 jacobian['vydot', 'theta'] = (F_T / m) * cos_theta jacobian['vydot', 'thrust'] = sin_theta / m jacobian['mdot', 'thrust'] = -1.0 / (g * Isp) jacobian['mdot', 'Isp'] = F_T / (g * Isp**2) class LinearTangentGuidanceComp(om.ExplicitComponent): """ Compute pitch angle from static controls governing linear expression for pitch angle tangent as function of time. """ def initialize(self): self.options.declare('num_nodes', types=int) def setup(self): nn = self.options['num_nodes'] self.add_input('a_ctrl', val=np.zeros(nn), desc='linear tangent slope', units='1/s') self.add_input('b_ctrl', val=np.zeros(nn), desc='tangent of theta at t=0', units=None) self.add_input('time_phase', val=np.zeros(nn), desc='time', units='s') self.add_output('theta', val=np.zeros(nn), desc='pitch angle', units='rad') # Setup partials arange = np.arange(self.options['num_nodes']) self.declare_partials(of='theta', wrt='a_ctrl', rows=arange, cols=arange, val=1.0) self.declare_partials(of='theta', wrt='b_ctrl', rows=arange, cols=arange, val=1.0) self.declare_partials(of='theta', wrt='time_phase', rows=arange, cols=arange, val=1.0) def compute(self, inputs, outputs): a = inputs['a_ctrl'] b = inputs['b_ctrl'] t = inputs['time_phase'] outputs['theta'] = np.arctan(a * t + b) def compute_partials(self, inputs, jacobian): a = inputs['a_ctrl'] b = inputs['b_ctrl'] t = inputs['time_phase'] x = a * t + b denom = x**2 + 1.0 jacobian['theta', 'a_ctrl'] = t / denom jacobian['theta', 'b_ctrl'] = 1.0 / denom jacobian['theta', 'time_phase'] = a / denom @dm.declare_time(units='s', targets=['guidance.time_phase']) @dm.declare_state('x', rate_source='eom.xdot', units='m') @dm.declare_state('y', rate_source='eom.ydot', units='m') @dm.declare_state('vx', rate_source='eom.vxdot', targets=['eom.vx'], units='m/s') @dm.declare_state('vy', rate_source='eom.vydot', targets=['eom.vy'], units='m/s') @dm.declare_state('m', rate_source='eom.mdot', targets=['eom.m'], units='kg') @dm.declare_parameter('thrust', targets=['eom.thrust'], units='N') @dm.declare_parameter('a_ctrl', targets=['guidance.a_ctrl'], units='1/s') @dm.declare_parameter('b_ctrl', targets=['guidance.b_ctrl'], units=None) @dm.declare_parameter('Isp', targets=['eom.Isp'], units='s') class LaunchVehicleLinearTangentODE(om.Group): """ The LaunchVehicleLinearTangentODE for this case consists of a guidance component and the EOM. Guidance is simply an OpenMDAO ExecComp which computes the arctangent of the tan_theta variable. """ def initialize(self): self.options.declare( 'num_nodes', types=int, desc='Number of nodes to be evaluated in the RHS') def setup(self): nn = self.options['num_nodes'] self.add_subsystem('guidance', LinearTangentGuidanceComp(num_nodes=nn)) self.add_subsystem('eom', LaunchVehicle2DEOM(num_nodes=nn)) self.connect('guidance.theta', 'eom.theta') # # Setup and solve the optimal control problem # p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() traj = dm.Trajectory() p.model.add_subsystem('traj', traj) phase = dm.Phase(ode_class=LaunchVehicleLinearTangentODE, transcription=dm.GaussLobatto(num_segments=10, order=5, compressed=True)) traj.add_phase('phase0', phase) phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(10, 1000)) phase.add_state('x', fix_initial=True, lower=0) phase.add_state('y', fix_initial=True, lower=0) phase.add_state('vx', fix_initial=True, lower=0) phase.add_state('vy', fix_initial=True) phase.add_state('m', fix_initial=True) phase.add_boundary_constraint('y', loc='final', equals=1.85E5, linear=True) phase.add_boundary_constraint('vx', loc='final', equals=1627.0) phase.add_boundary_constraint('vy', loc='final', equals=0) phase.add_design_parameter('a_ctrl', units='1/s', opt=True) phase.add_design_parameter('b_ctrl', units=None, opt=True) phase.add_design_parameter('thrust', units='N', opt=False, val=3.0 * 50000.0 * 1.61544) phase.add_design_parameter('Isp', units='s', opt=False, val=1.0E6) phase.add_objective('time', index=-1, scaler=0.01) p.model.linear_solver = om.DirectSolver() phase.add_timeseries_output('guidance.theta', units='deg') p.setup(check=True) p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 500.0 p['traj.phase0.states:x'] = phase.interpolate(ys=[0, 350000.0], nodes='state_input') p['traj.phase0.states:y'] = phase.interpolate(ys=[0, 185000.0], nodes='state_input') p['traj.phase0.states:vx'] = phase.interpolate(ys=[0, 1627.0], nodes='state_input') p['traj.phase0.states:vy'] = phase.interpolate(ys=[1.0E-6, 0], nodes='state_input') p['traj.phase0.states:m'] = phase.interpolate(ys=[50000, 50000], nodes='state_input') p['traj.phase0.design_parameters:a_ctrl'] = -0.01 p['traj.phase0.design_parameters:b_ctrl'] = 3.0 p.run_driver() # # Check the results. # assert_rel_error(self, p.get_val('traj.phase0.timeseries.time')[-1], 481, tolerance=0.01) # # Get the explitly simulated results # exp_out = traj.simulate() # # Plot the results # plot_results( [('traj.phase0.timeseries.states:x', 'traj.phase0.timeseries.states:y', 'range (m)', 'altitude (m)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.theta', 'range (m)', 'altitude (m)')], title= 'Single Stage to Orbit Solution Using Linear Tangent Guidance', p_sol=p, p_sim=exp_out) plt.show()
def test_hyper_sensitive_for_docs(self): import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.plotting import plot_results from dymos.examples.hyper_sensitive.hyper_sensitive_ode import HyperSensitiveODE # Initialize the problem and assign the driver p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() # Setup the trajectory and its phase traj = p.model.add_subsystem('traj', dm.Trajectory()) transcription = dm.Radau(num_segments=30, order=3, compressed=False) phase = traj.add_phase('phase0', dm.Phase(ode_class=HyperSensitiveODE, transcription=transcription)) phase.set_time_options(fix_initial=True, fix_duration=True) phase.add_state('x', fix_initial=True, fix_final=False, rate_source='x_dot', targets=['x']) phase.add_state('xL', fix_initial=True, fix_final=False, rate_source='L', targets=['xL']) phase.add_control('u', opt=True, targets=['u']) phase.add_boundary_constraint('x', loc='final', equals=1) phase.add_objective('xL', loc='final') p.setup(check=True) p.set_val('traj.phase0.states:x', phase.interpolate(ys=[1.5, 1], nodes='state_input')) p.set_val('traj.phase0.states:xL', phase.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', phase.interpolate(ys=[-0.6, 2.4], nodes='control_input')) # # Solve the problem. # dm.run_problem(p) # # Verify that the results are correct. # ui, uf, J = solution() assert_near_equal(p.get_val('traj.phase0.timeseries.controls:u')[0], ui, tolerance=1.5e-2) assert_near_equal(p.get_val('traj.phase0.timeseries.controls:u')[-1], uf, tolerance=1.5e-2) assert_near_equal(p.get_val('traj.phase0.timeseries.states:xL')[-1], J, tolerance=1e-2) # # Simulate the explicit solution and plot the results. # exp_out = traj.simulate() plot_results([('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:x', 'time (s)', 'x $(m)$'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:u', 'time (s)', 'u $(m/s^2)$')], title='Hyper Sensitive Problem Solution\nRadau Pseudospectral Method', p_sol=p, p_sim=exp_out) plt.show()
def test_brachistochrone_for_docs_coloring_demo_solve_segments(self): import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.plotting import plot_results from dymos.examples.brachistochrone import BrachistochroneODE from openmdao.utils.general_utils import set_pyoptsparse_opt # # Initialize the Problem and the optimization driver # p = om.Problem(model=om.Group()) _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=True) p.driver = om.pyOptSparseDriver(optimizer=optimizer) p.driver.opt_settings['print_level'] = 5 # p.driver.declare_coloring() # # Create a trajectory and add a phase to it # traj = p.model.add_subsystem('traj', dm.Trajectory()) # # In this case the phase has many segments to demonstrate the impact of coloring. # phase = traj.add_phase( 'phase0', dm.Phase(ode_class=BrachistochroneODE, transcription=dm.Radau(num_segments=100, solve_segments=True))) # # Set the variables # phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(.5, 10)) phase.add_state( 'x', rate_source=BrachistochroneODE.states['x']['rate_source'], units=BrachistochroneODE.states['x']['units'], fix_initial=True) phase.add_state( 'y', rate_source=BrachistochroneODE.states['y']['rate_source'], units=BrachistochroneODE.states['y']['units'], fix_initial=True) phase.add_state( 'v', rate_source=BrachistochroneODE.states['v']['rate_source'], units=BrachistochroneODE.states['v']['units'], fix_initial=True) phase.add_control('theta', continuity=True, rate_continuity=True, units='deg', lower=0.01, upper=179.9) phase.add_parameter('g', units='m/s**2', val=9.80665) # # Replace state terminal bounds with nonlinear constraints # phase.add_boundary_constraint('x', loc='final', equals=10) phase.add_boundary_constraint('y', loc='final', equals=5) # # Minimize time at the end of the phase # phase.add_objective('time', loc='final', scaler=10) p.model.linear_solver = om.DirectSolver() # # Setup the Problem # p.setup() # # Set the initial values # p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 2.0 p['traj.phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input') p['traj.phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input') p['traj.phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['traj.phase0.controls:theta'] = phase.interpolate( ys=[5, 100.5], nodes='control_input') # # Solve for the optimal trajectory # dm.run_problem(p) # Test the results assert_near_equal(p.get_val('traj.phase0.timeseries.time')[-1], 1.8016, tolerance=1.0E-3) # Generate the explicitly simulated trajectory exp_out = traj.simulate() plot_results( [('traj.phase0.timeseries.states:x', 'traj.phase0.timeseries.states:y', 'x (m)', 'y (m)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:theta', 'time (s)', 'theta (deg)')], title='Brachistochrone Solution\nRadau Pseudospectral Method', p_sol=p, p_sim=exp_out) plt.show()
def test_brachistochrone_for_docs_gauss_lobatto(self): import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.plotting import plot_results from dymos.examples.brachistochrone import BrachistochroneODE # # Initialize the Problem and the optimization driver # p = om.Problem(model=om.Group()) p.driver = om.ScipyOptimizeDriver() p.driver.declare_coloring() # # Create a trajectory and add a phase to it # traj = p.model.add_subsystem('traj', dm.Trajectory()) phase = traj.add_phase( 'phase0', dm.Phase(ode_class=BrachistochroneODE, transcription=dm.GaussLobatto(num_segments=10))) # # Set the variables # phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(.5, 10)) phase.add_state( 'x', rate_source=BrachistochroneODE.states['x']['rate_source'], units=BrachistochroneODE.states['x']['units'], fix_initial=True, fix_final=True, solve_segments=False) phase.add_state( 'y', rate_source=BrachistochroneODE.states['y']['rate_source'], units=BrachistochroneODE.states['y']['units'], fix_initial=True, fix_final=True, solve_segments=False) phase.add_state( 'v', rate_source=BrachistochroneODE.states['v']['rate_source'], targets=BrachistochroneODE.states['v']['targets'], units=BrachistochroneODE.states['v']['units'], fix_initial=True, fix_final=False, solve_segments=False) phase.add_control( 'theta', targets=BrachistochroneODE.parameters['theta']['targets'], continuity=True, rate_continuity=True, units='deg', lower=0.01, upper=179.9) phase.add_input_parameter( 'g', targets=BrachistochroneODE.parameters['g']['targets'], units='m/s**2', val=9.80665) # # Minimize time at the end of the phase # phase.add_objective('time', loc='final', scaler=10) p.model.linear_solver = om.DirectSolver() # # Setup the Problem # p.setup() # # Set the initial values # p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 2.0 p['traj.phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input') p['traj.phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input') p['traj.phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['traj.phase0.controls:theta'] = phase.interpolate( ys=[5, 100.5], nodes='control_input') # # Solve for the optimal trajectory # dm.run_problem(p) # Test the results assert_near_equal(p.get_val('traj.phase0.timeseries.time')[-1], 1.8016, tolerance=1.0E-3) # Generate the explicitly simulated trajectory exp_out = traj.simulate() plot_results( [('traj.phase0.timeseries.states:x', 'traj.phase0.timeseries.states:y', 'x (m)', 'y (m)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:theta', 'time (s)', 'theta (deg)')], title='Brachistochrone Solution\nHigh-Order Gauss-Lobatto Method', p_sol=p, p_sim=exp_out) plt.show()
def test_double_integrator_for_docs(self): import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.plotting import plot_results from dymos.examples.double_integrator.double_integrator_ode import DoubleIntegratorODE # Initialize the problem and assign the driver p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() # Setup the trajectory and its phase traj = p.model.add_subsystem('traj', dm.Trajectory()) transcription = dm.Radau(num_segments=30, order=3, compressed=False) phase = traj.add_phase( 'phase0', dm.Phase(ode_class=DoubleIntegratorODE, transcription=transcription)) # # Set the options for our variables. # phase.set_time_options(fix_initial=True, fix_duration=True, units='s') phase.add_state('x', fix_initial=True, rate_source='v', units='m') phase.add_state('v', fix_initial=True, fix_final=True, rate_source='u', units='m/s') 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. # phase.add_objective('x', loc='final', scaler=-1) p.model.linear_solver = om.DirectSolver() # # Setup the problem and set our initial values. # p.setup(check=True) p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 1.0 p['traj.phase0.states:x'] = phase.interpolate(ys=[0, 0.25], nodes='state_input') p['traj.phase0.states:v'] = phase.interpolate(ys=[0, 0], nodes='state_input') p['traj.phase0.controls:u'] = phase.interpolate(ys=[1, -1], nodes='control_input') # # Solve the problem. # dm.run_problem(p) # # Verify that the results are correct. # x = p.get_val('traj.phase0.timeseries.states:x') v = p.get_val('traj.phase0.timeseries.states:v') assert_near_equal(x[0], 0.0, tolerance=1.0E-4) assert_near_equal(x[-1], 0.25, tolerance=1.0E-4) assert_near_equal(v[0], 0.0, tolerance=1.0E-4) assert_near_equal(v[-1], 0.0, tolerance=1.0E-4) # # Simulate the explicit solution and plot the results. # exp_out = traj.simulate() plot_results( [('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:x', 'time (s)', 'x $(m)$'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:v', 'time (s)', 'v $(m/s)$'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:u', 'time (s)', 'u $(m/s^2)$')], title='Double Integrator Solution\nRadau Pseudospectral Method', p_sol=p, p_sim=exp_out) plt.show()
def test_steady_aircraft_for_docs(self): import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.aircraft_steady_flight.aircraft_ode import AircraftODE from dymos.examples.plotting import plot_results from dymos.utils.lgl import lgl p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() num_seg = 15 seg_ends, _ = lgl(num_seg + 1) traj = p.model.add_subsystem('traj', dm.Trajectory()) phase = traj.add_phase( 'phase0', dm.Phase(ode_class=AircraftODE, transcription=dm.Radau(num_segments=num_seg, segment_ends=seg_ends, order=3, compressed=False))) # Pass Reference Area from an external source assumptions = p.model.add_subsystem('assumptions', om.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(fix_initial=True, duration_bounds=(300, 10000), duration_ref=5600) phase.add_state('range', units='NM', rate_source='range_rate_comp.dXdt:range', fix_initial=True, fix_final=False, ref=1e-3, defect_ref=1e-3, lower=0, upper=2000) phase.add_state('mass_fuel', units='lbm', rate_source='propulsion.dXdt:mass_fuel', fix_initial=True, fix_final=True, upper=1.5E5, lower=0.0, ref=1e2, defect_ref=1e2) phase.add_state('alt', units='kft', rate_source='climb_rate', fix_initial=True, fix_final=True, lower=0.0, upper=60, ref=1e-3, defect_ref=1e-3) phase.add_control('climb_rate', units='ft/min', opt=True, lower=-3000, upper=3000, targets=['gam_comp.climb_rate'], rate_continuity=True, rate2_continuity=False) phase.add_control('mach', targets=['tas_comp.mach', 'aero.mach'], units=None, opt=False) phase.add_parameter( 'S', targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'], units='m**2') phase.add_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg') phase.add_parameter('mass_payload', targets=['mass_comp.mass_payload'], units='kg') phase.add_path_constraint('propulsion.tau', lower=0.01, upper=2.0, shape=(1, )) p.model.connect('assumptions.S', 'traj.phase0.parameters:S') p.model.connect('assumptions.mass_empty', 'traj.phase0.parameters:mass_empty') p.model.connect('assumptions.mass_payload', 'traj.phase0.parameters:mass_payload') phase.add_objective('range', loc='final', ref=-1.0e-4) phase.add_timeseries_output('aero.CL') phase.add_timeseries_output('aero.CD') p.setup() p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 3600.0 p['traj.phase0.states:range'][:] = phase.interpolate( ys=(0, 724.0), nodes='state_input') p['traj.phase0.states:mass_fuel'][:] = phase.interpolate( ys=(30000, 1e-3), nodes='state_input') p['traj.phase0.states:alt'][:] = 10.0 p['traj.phase0.controls:mach'][:] = 0.8 p['assumptions.S'] = 427.8 p['assumptions.mass_empty'] = 0.15E6 p['assumptions.mass_payload'] = 84.02869 * 400 dm.run_problem(p) assert_near_equal(p.get_val('traj.phase0.timeseries.states:range', units='NM')[-1], 726.85, tolerance=1.0E-2) exp_out = traj.simulate() assert_near_equal(p.get_val('traj.phase0.timeseries.CL')[0], exp_out.get_val('traj.phase0.timeseries.CL')[0], tolerance=1.0E-9) assert_near_equal(p.get_val('traj.phase0.timeseries.CD')[0], exp_out.get_val('traj.phase0.timeseries.CD')[0], tolerance=1.0E-9) plot_results( [('traj.phase0.timeseries.states:range', 'traj.phase0.timeseries.states:alt', 'range (NM)', 'altitude (kft)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:mass_fuel', 'time (s)', 'fuel mass (lbm)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.CL', 'time (s)', 'lift coefficient'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.CD', 'time (s)', 'drag coefficient')], title='Commercial Aircraft Optimization', p_sol=p, p_sim=exp_out) plt.show()
p['traj.phase0.states:fuel_burnt'][:] = 0 p['traj.phase0.controls:P_gen1'][:] = 1 p['traj.phase0.controls:P_gen2'][:] = 1 # Solve for the optimal trajectory dm.run_problem(p) # Test the results print(p.get_val('traj.phase0.timeseries.states:fuel_burnt')[-1]) # # generate the explicitly simulated trajectory exp_out = traj.simulate() fig, axs = plot_results([ ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:P_gen1', 'time (s)', 'P1 (kW)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:P_gen2', 'time (s)', 'P2 (kW)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:fuel_burnt', 'time (s)', 'fuel burnt (kg)') ], title='Twin Turboelectric Test Case', p_sol=p, p_sim=exp_out) axs[0].set_ylim(0, 1.1) axs[1].set_ylim(0, 1.1) plt.show() print(p.get_val('traj.phase0.timeseries.states:fuel_burnt')[-1])
def test_reentry(self): import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.shuttle_reentry.shuttle_ode import ShuttleODE from dymos.examples.plotting import plot_results # Instantiate the problem, add the driver, and allow it to use coloring p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() p.driver.options['optimizer'] = 'SLSQP' # Instantiate the trajectory and add a phase to it traj = p.model.add_subsystem('traj', dm.Trajectory()) phase0 = traj.add_phase('phase0', dm.Phase(ode_class=ShuttleODE, transcription=dm.Radau(num_segments=15, 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', lower=0, ref0=75000, ref=300000, defect_ref=1000) phase0.add_state('gamma', fix_initial=True, fix_final=True, units='rad', rate_source='gammadot', 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', lower=0, upper=90. * np.pi / 180) phase0.add_state('theta', fix_initial=True, fix_final=False, units='rad', rate_source='thetadot', 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', lower=0, ref0=2500, ref=25000) phase0.add_control('alpha', units='rad', opt=True, lower=-np.pi / 2, upper=np.pi / 2, ) phase0.add_control('beta', units='rad', opt=True, lower=-89 * np.pi / 180, upper=1 * np.pi / 180, ) # The original implementation by Betts includes a heating rate path constraint. # This will work with the SNOPT optimizer but SLSQP has difficulty converging the solution. # phase0.add_path_constraint('q', lower=0, upper=70, ref=70) phase0.add_timeseries_output('q', shape=(1,)) phase0.add_objective('theta', loc='final', ref=-0.01) p.setup(check=True) 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.states:h', phase0.interp('h', [260000, 80000]), units='ft') p.set_val('traj.phase0.states:gamma', phase0.interp('gamma', [-1, -5]), units='deg') p.set_val('traj.phase0.states:phi', phase0.interp('phi', [0, 75]), units='deg') p.set_val('traj.phase0.states:psi', phase0.interp('psi', [90, 10]), units='deg') p.set_val('traj.phase0.states:theta', phase0.interp('theta', [0, 25]), units='deg') p.set_val('traj.phase0.states:v', phase0.interp('v', [25600, 2500]), units='ft/s') p.set_val('traj.phase0.controls:alpha', phase0.interp('alpha', ys=[17.4, 17.4]), units='deg') p.set_val('traj.phase0.controls:beta', phase0.interp('beta', ys=[-75, 0]), units='deg') # Run the driver dm.run_problem(p) # Check the validity of the solution assert_near_equal(p.get_val('traj.phase0.timeseries.time')[-1], 2008.59, tolerance=1e-3) assert_near_equal(p.get_val('traj.phase0.timeseries.states:theta', units='deg')[-1], 34.1412, tolerance=1e-3) # Run the simulation to check if the model is physically valid sim_out = traj.simulate() # Plot the results plot_results([('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:alpha', 'time (s)', 'alpha (rad)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:beta', 'time (s)', 'beta (rad)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:theta', 'time (s)', 'theta (rad)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.q', 'time (s)', 'q (btu/ft/ft/s')], title='Reentry Solution', p_sol=p, p_sim=sim_out) plt.show()
def test_min_time_climb_for_docs_gauss_lobatto(self): import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.min_time_climb.min_time_climb_ode import MinTimeClimbODE from dymos.examples.plotting import plot_results # # Instantiate the problem and configure the optimization driver # p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() # # Instantiate the trajectory and phase # traj = dm.Trajectory() phase = dm.Phase(ode_class=MinTimeClimbODE, transcription=dm.GaussLobatto(num_segments=15, compressed=False)) traj.add_phase('phase0', phase) p.model.add_subsystem('traj', traj) # # Set the options on the optimization variables # Note the use of explicit state units here since much of the ODE uses imperial units # and we prefer to solve this problem using metric units. # phase.set_time_options(fix_initial=True, duration_bounds=(50, 400), duration_ref=100.0) phase.add_state('r', fix_initial=True, lower=0, upper=1.0E6, units='m', ref=1.0E3, defect_ref=1.0E3, rate_source='flight_dynamics.r_dot') phase.add_state('h', fix_initial=True, lower=0, upper=20000.0, units='m', ref=1.0E2, defect_ref=1.0E2, rate_source='flight_dynamics.h_dot') phase.add_state('v', fix_initial=True, lower=10.0, units='m/s', ref=1.0E2, defect_ref=1.0E2, rate_source='flight_dynamics.v_dot') phase.add_state('gam', fix_initial=True, lower=-1.5, upper=1.5, units='rad', ref=1.0, defect_ref=1.0, rate_source='flight_dynamics.gam_dot') phase.add_state('m', fix_initial=True, lower=10.0, upper=1.0E5, units='kg', ref=1.0E3, defect_ref=1.0E3, rate_source='prop.m_dot') phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, rate_continuity=True, rate_continuity_scaler=100.0, rate2_continuity=False) phase.add_parameter('S', val=49.2386, units='m**2', opt=False, targets=['S']) phase.add_parameter('Isp', val=1600.0, units='s', opt=False, targets=['Isp']) phase.add_parameter('throttle', val=1.0, opt=False, targets=['throttle']) # # Setup the boundary and path constraints # 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, shape=(1, )) 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, shape=(1, )) # Minimize time at the end of the phase phase.add_objective('time', loc='final', ref=1.0) p.model.linear_solver = om.DirectSolver() # # Setup the problem and set the initial guess # p.setup(check=True) p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 500 p['traj.phase0.states:r'] = phase.interpolate(ys=[0.0, 50000.0], nodes='state_input') p['traj.phase0.states:h'] = phase.interpolate(ys=[100.0, 20000.0], nodes='state_input') p['traj.phase0.states:v'] = phase.interpolate(ys=[135.964, 283.159], nodes='state_input') p['traj.phase0.states:gam'] = phase.interpolate(ys=[0.0, 0.0], nodes='state_input') p['traj.phase0.states:m'] = phase.interpolate(ys=[19030.468, 10000.], nodes='state_input') p['traj.phase0.controls:alpha'] = phase.interpolate( ys=[0.0, 0.0], nodes='control_input') # # Solve for the optimal trajectory # dm.run_problem(p) # # Test the results # assert_near_equal(p.get_val('traj.phase0.t_duration'), 321.0, tolerance=1.0E-1) # # Get the explicitly simulated solution and plot the results # exp_out = traj.simulate() plot_results( [('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:h', 'time (s)', 'altitude (m)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:alpha', 'time (s)', 'alpha (deg)')], title='Supersonic Minimum Time-to-Climb Solution', p_sol=p, p_sim=exp_out) plt.show()
def test_brachistochrone_for_docs_runge_kutta_polynomial_controls(self): import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.plotting import plot_results from dymos.examples.brachistochrone import BrachistochroneODE # # Initialize the Problem and the optimization driver # p = om.Problem(model=om.Group()) p.driver = om.ScipyOptimizeDriver() p.driver.declare_coloring() # # Create a trajectory and add a phase to it # traj = p.model.add_subsystem('traj', dm.Trajectory()) phase = traj.add_phase('phase0', dm.Phase(ode_class=BrachistochroneODE, transcription=dm.RungeKutta(num_segments=10))) # # Set the variables # phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(.5, 10)) phase.add_state('x', fix_initial=True, fix_final=False) phase.add_state('y', fix_initial=True, fix_final=False) phase.add_state('v', fix_initial=True, fix_final=False) phase.add_polynomial_control('theta', order=1, units='deg', lower=0.01, upper=179.9) phase.add_parameter('g', units='m/s**2', val=9.80665) # # Final state values are not optimization variables, so we must enforce final values # with boundary constraints, not simple bounds. # phase.add_boundary_constraint('x', loc='final', equals=10) phase.add_boundary_constraint('y', loc='final', equals=5) # # Minimize time at the end of the phase # phase.add_objective('time', loc='final', scaler=10) p.model.linear_solver = om.DirectSolver() # # Setup the Problem # p.setup() # # Set the initial values # p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 2.0 p['traj.phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input') p['traj.phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input') p['traj.phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['traj.phase0.polynomial_controls:theta'][:] = 5.0 # # Solve for the optimal trajectory # dm.run_problem(p) # Test the results assert_near_equal(p.get_val('traj.phase0.timeseries.time')[-1], 1.8016, tolerance=1.0E-3) # Generate the explicitly simulated trajectory exp_out = traj.simulate() plot_results([('traj.phase0.timeseries.states:x', 'traj.phase0.timeseries.states:y', 'x (m)', 'y (m)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.polynomial_controls:theta', 'time (s)', 'theta (deg)')], title='Brachistochrone Solution\nRK4 Shooting and Polynomial Controls', p_sol=p, p_sim=exp_out) plt.show()
def test_brachistochrone_for_docs_radau(self): from openmdao.api import Problem, Group, ScipyOptimizeDriver, DirectSolver, SqliteRecorder from openmdao.utils.assert_utils import assert_rel_error import dymos as dm from dymos.examples.plotting import plot_results from dymos.examples.brachistochrone import BrachistochroneODE # # Initialize the Problem and the optimization driver # p = Problem(model=Group()) p.driver = ScipyOptimizeDriver() p.driver.options['dynamic_simul_derivs'] = True # # Create a trajectory and add a phase to it # traj = p.model.add_subsystem('traj', dm.Trajectory()) phase = traj.add_phase( 'phase0', dm.Phase(ode_class=BrachistochroneODE, transcription=dm.Radau(num_segments=10))) # # Set the variables # 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', lower=0.01, upper=179.9) phase.add_design_parameter('g', units='m/s**2', opt=False, val=9.80665) # # Minimize time at the end of the phase # phase.add_objective('time', loc='final', scaler=10) p.model.linear_solver = DirectSolver() # # Setup the Problem # p.setup() # # Set the initial values # p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 2.0 p['traj.phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input') p['traj.phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input') p['traj.phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['traj.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('traj.phase0.timeseries.time')[-1], 1.8016, tolerance=1.0E-3) # Generate the explicitly simulated trajectory exp_out = traj.simulate() plot_results( [('traj.phase0.timeseries.states:x', 'traj.phase0.timeseries.states:y', 'x (m)', 'y (m)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:theta', 'time (s)', 'theta (deg)')], title='Brachistochrone Solution\nRadau Pseudospectral Method', p_sol=p, p_sim=exp_out) plt.show()
loc='final', units='K', upper=60, lower=20, shape=(1, )) phase.add_parameter('d', opt=True, lower=0.00001, upper=0.1) phase.add_objective('d', loc='final', scaler=1) p.model.linear_solver = om.DirectSolver() p.setup() p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.states:T'] = phase.interpolate(ys=[20, 60], nodes='state_input') dm.run_problem(p) exp_out = traj.simulate() plot_results([('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:T', 'time (s)', 'temp (K)')], title='Temps', p_sol=p, p_sim=exp_out) plt.show() # t = np.linspace(0, 45, 101) # def dT_calc(Ts,t): # Tf = Ts[0] # Tc = Ts[1] # K = 0.03 # W/mk # A = .102*.0003 # m^2 # d = 0.003 #m # m = 0.06 #kg # Cp = 3.58 #kJ/kgK
p.model.linear_solver = om.DirectSolver() # Setup the Problem p.setup() # Set the initial values p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 2.0 p['traj.phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input') p['traj.phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input') p['traj.phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['traj.phase0.controls:theta'] = phase.interpolate(ys=[5, 100.5], nodes='control_input') # Solve for the optimal trajectory dm.run_problem(p) # Test the results assert_near_equal(p.get_val('traj.phase0.timeseries.time')[-1], 1.8016, tolerance=1.0E-3) # Generate the explicitly simulated trajectory exp_out = traj.simulate() plot_results([('traj.phase0.timeseries.states:x', 'traj.phase0.timeseries.states:y', 'x (m)', 'y (m)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:theta', 'time (s)', 'theta (deg)')], title='Brachistochrone Solution\nHigh-Order Gauss-Lobatto Method', p_sol=p, p_sim=exp_out) plt.show()