def brachistochrone_min_time(transcription='gauss-lobatto', num_segments=8, transcription_order=3, compressed=True, optimizer='SLSQP', simul_derivs=True): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=True) p.driver.options['optimizer'] = OPTIMIZER if simul_derivs: p.driver.declare_coloring() if transcription == 'gauss-lobatto': t = dm.GaussLobatto(num_segments=num_segments, order=transcription_order, compressed=compressed) elif transcription == 'radau-ps': t = dm.Radau(num_segments=num_segments, order=transcription_order, compressed=compressed) phase = dm.Phase(ode_class=BrachistochroneODE, transcription=t) p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10), units='s') phase.add_state('x', fix_initial=True, fix_final=False, solve_segments=False, units='m', rate_source='xdot') phase.add_state('y', fix_initial=True, fix_final=False, solve_segments=False, units='m', rate_source='ydot') phase.add_state('v', fix_initial=True, fix_final=False, solve_segments=False, units='m/s', rate_source='vdot') 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, targets=['g']) phase.add_boundary_constraint('x', loc='final', equals=10) phase.add_boundary_constraint('y', loc='final', equals=5) # Minimize time at the end of the phase phase.add_objective('time_phase', loc='final', scaler=10) p.model.linear_solver = om.DirectSolver() p.setup(check=True) p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 2.0 p['phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input') p['phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100], nodes='control_input') p['phase0.parameters:g'] = 9.80665 p.run_driver() return p
def test_run_HS_problem_gl(self): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() _, optimizer = set_pyoptsparse_opt('SNOPT', fallback=True) p.driver.options['optimizer'] = optimizer traj = p.model.add_subsystem('traj', dm.Trajectory()) phase0 = traj.add_phase('phase0', dm.Phase(ode_class=HyperSensitiveODE, transcription=dm.GaussLobatto(num_segments=30, order=3))) phase0.set_time_options(fix_initial=True, fix_duration=True) phase0.add_state('x', fix_initial=True, fix_final=False, rate_source='x_dot', targets=['x']) phase0.add_state('xL', fix_initial=True, fix_final=False, rate_source='L', targets=['xL']) phase0.add_control('u', opt=True, targets=['u'], rate_continuity=False) phase0.add_boundary_constraint('x', loc='final', equals=1) phase0.add_objective('xL', loc='final') phase0.set_refine_options(refine=True) p.setup(check=True) tf = 100 p.set_val('traj.phase0.states:x', phase0.interpolate(ys=[1.5, 1], nodes='state_input')) p.set_val('traj.phase0.states:xL', phase0.interpolate(ys=[0, 1], nodes='state_input')) p.set_val('traj.phase0.t_initial', 0) p.set_val('traj.phase0.t_duration', tf) p.set_val('traj.phase0.controls:u', phase0.interpolate(ys=[-0.6, 2.4], nodes='control_input')) dm.run_problem(p, refine=True) sqrt_two = np.sqrt(2) val = sqrt_two * tf c1 = (1.5 * np.exp(-val) - 1) / (np.exp(-val) - np.exp(val)) c2 = (1 - 1.5 * np.exp(val)) / (np.exp(-val) - np.exp(val)) ui = c1 * (1 + sqrt_two) + c2 * (1 - sqrt_two) uf = c1 * (1 + sqrt_two) * np.exp(val) + c2 * (1 - sqrt_two) * np.exp(-val) J = 0.5 * (c1 ** 2 * (1 + sqrt_two) * np.exp(2 * val) + c2 ** 2 * (1 - sqrt_two) * np.exp(-2 * val) - (1 + sqrt_two) * c1 ** 2 - (1 - sqrt_two) * c2 ** 2) assert_rel_error(self, p.get_val('traj.phase0.timeseries.controls:u')[0], ui, tolerance=1e-2) assert_rel_error(self, p.get_val('traj.phase0.timeseries.controls:u')[-1], uf, tolerance=1e-2) assert_rel_error(self, p.get_val('traj.phase0.timeseries.states:xL')[-1], J, tolerance=5e-4)
def test_ex_two_burn_orbit_raise_connected(self): _, optimizer = set_pyoptsparse_opt('SNOPT', fallback=False) p = two_burn_orbit_raise_problem(transcription='gauss-lobatto', transcription_order=3, compressed=False, optimizer=optimizer, show_output=False, connected=True) if p.model.traj.phases.burn2 in p.model.traj.phases._subsystems_myproc: assert_rel_error(self, p.get_val('traj.burn2.states:deltav')[0], 0.3995, tolerance=4.0E-3)
def make_problem(self, transcription=Radau, optimizer='SLSQP', numseg=30): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.declare_coloring(tol=1.0E-12) OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=False) p.driver.options['optimizer'] = OPTIMIZER if OPTIMIZER == 'SNOPT': p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Verify level'] = 3 elif OPTIMIZER == 'IPOPT': p.driver.opt_settings['max_iter'] = 500 p.driver.opt_settings['print_level'] = 4 p.driver.opt_settings['tol'] = 1.0E-6 p.driver.opt_settings['acceptable_tol'] = 1.0E-5 traj = p.model.add_subsystem('traj', Trajectory()) phase = traj.add_phase('phase', Phase(ode_class=RobotArmODE, transcription=transcription(num_segments=numseg, order=3))) phase.set_time_options(fix_initial=True, fix_duration=False) phase.add_state('x0', fix_initial=True, fix_final=True, rate_source='x0_dot', units='m') phase.add_state('x1', fix_initial=True, fix_final=True, rate_source='x1_dot', units='rad') phase.add_state('x2', fix_initial=True, fix_final=True, rate_source='x2_dot', units='rad') phase.add_state('x3', fix_initial=True, fix_final=True, rate_source='x3_dot', units='m/s') phase.add_state('x4', fix_initial=True, fix_final=True, rate_source='x4_dot', units='rad/s') phase.add_state('x5', fix_initial=True, fix_final=True, rate_source='x5_dot', units='rad/s') phase.add_control('u0', opt=True, lower=-1, upper=1, scaler=0.1, units='m**2/s**2', continuity=False, rate_continuity=False) phase.add_control('u1', opt=True, lower=-1, upper=1, scaler=0.1, units='m**3*rad/s**2', continuity=False, rate_continuity=False) phase.add_control('u2', opt=True, lower=-1, upper=1, scaler=0.1, units='m**3*rad/s**2', continuity=False, rate_continuity=False) phase.add_path_constraint('u0', lower=-1, upper=1, scaler=0.1) phase.add_path_constraint('u1', lower=-1, upper=1, scaler=0.1) phase.add_path_constraint('u2', lower=-1, upper=1, scaler=0.1) phase.add_objective('time', ref=0.1) phase.set_refine_options(refine=True, tol=1e-5, smoothness_factor=1.2) p.setup(check=True, force_alloc_complex=False, mode='auto') p.set_val('traj.phase.t_initial', 0) p.set_val('traj.phase.t_duration', 10) p.set_val('traj.phase.states:x0', phase.interpolate(ys=[4.5, 4.5], nodes='state_input')) p.set_val('traj.phase.states:x1', phase.interpolate(ys=[0.0, 2 * np.pi / 3], nodes='state_input')) p.set_val('traj.phase.states:x2', phase.interpolate(ys=[np.pi / 4, np.pi / 4], nodes='state_input')) p.set_val('traj.phase.states:x3', phase.interpolate(ys=[0.0, 0.0], nodes='state_input')) p.set_val('traj.phase.states:x4', phase.interpolate(ys=[0.0, 0.0], nodes='state_input')) p.set_val('traj.phase.states:x5', phase.interpolate(ys=[0.0, 0.0], nodes='state_input')) return p
def test_ex_two_burn_orbit_raise(self): _, optimizer = set_pyoptsparse_opt('SNOPT', fallback=False) p = two_burn_orbit_raise_problem(transcription='gauss-lobatto', transcription_order=3, compressed=True, show_plots=False, optimizer=optimizer) assert_rel_error(self, p.get_val('burn2.states:deltav')[-1], 0.3995, tolerance=2.0E-3)
def make_problem(self, transcription=GaussLobatto, optimizer='SLSQP', numseg=30): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.declare_coloring() OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=False) p.driver.options['optimizer'] = OPTIMIZER traj = p.model.add_subsystem('traj', Trajectory()) phase0 = traj.add_phase( 'phase0', Phase(ode_class=HyperSensitiveODE, transcription=transcription(num_segments=numseg, order=3))) phase0.set_time_options(fix_initial=True, fix_duration=True) phase0.add_state('x', fix_initial=True, fix_final=False, rate_source='x_dot', targets=['x']) phase0.add_state('xL', fix_initial=True, fix_final=False, rate_source='L', targets=['xL']) phase0.add_control('u', opt=True, targets=['u']) phase0.add_boundary_constraint('x', loc='final', equals=1) phase0.add_objective('xL', loc='final') p.setup(check=True) p.set_val('traj.phase0.states:x', phase0.interpolate(ys=[1.5, 1], nodes='state_input')) p.set_val('traj.phase0.states:xL', phase0.interpolate(ys=[0, 1], nodes='state_input')) p.set_val('traj.phase0.t_initial', 0) p.set_val('traj.phase0.t_duration', tf) p.set_val('traj.phase0.controls:u', phase0.interpolate(ys=[-0.6, 2.4], nodes='control_input')) return p
def test_water_rocket_range_for_docs(self): p = om.Problem(model=om.Group()) traj, phases = new_water_rocket_trajectory(objective='range') traj = p.model.add_subsystem('traj', traj) _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=False) p.driver = om.pyOptSparseDriver(optimizer='IPOPT') p.driver.opt_settings['print_level'] = 5 p.driver.opt_settings['max_iter'] = 1000 p.driver.opt_settings['nlp_scaling_method'] = 'gradient-based' p.driver.declare_coloring(tol=1.0E-12) # Finish Problem Setup p.model.linear_solver = om.DirectSolver() # p.driver.add_recorder(om.SqliteRecorder('ex_water_rocket.db')) p.setup() set_sane_initial_guesses(p, phases) p.run_driver() summary = summarize_results(p) for key, entry in summary.items(): print(f'{key}: {entry.value:6.4f} {entry.unit}') exp_out = traj.simulate(times_per_seg=200) # NOTE: only the last figure is shown in the generated docs plot_propelled_ascent(p, exp_out) plot_trajectory(p, exp_out) plot_states(p, exp_out) plt.show() # Check results (tolerance is relative unless value is zero) assert_near_equal(summary['Launch angle'].value, 46, 0.02) assert_near_equal(summary['Flight angle at end of propulsion'].value, 38, 0.02) assert_near_equal(summary['Empty mass'].value, 0.189, 1e-2) assert_near_equal(summary['Water volume'].value, 1.026, 1e-2) assert_near_equal(summary['Maximum range'].value, 85.11, 1e-2) assert_near_equal(summary['Maximum height'].value, 23.08, 1e-2) assert_near_equal(summary['Maximum velocity'].value, 41.31, 1e-2)
def test_water_rocket_height_for_docs(self): p = om.Problem(model=om.Group()) traj, phases = new_water_rocket_trajectory(objective='height') traj = p.model.add_subsystem('traj', traj) _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=False) p.driver = om.pyOptSparseDriver(optimizer='IPOPT') p.driver.opt_settings['print_level'] = 5 p.driver.opt_settings['max_iter'] = 1000 p.driver.declare_coloring() # Finish Problem Setup p.model.linear_solver = om.DirectSolver() p.setup() set_sane_initial_guesses(p, phases) p.run_driver() summary = summarize_results(p) for key, entry in summary.items(): print(f'{key}: {entry.value:6.4f} {entry.unit}') exp_out = traj.simulate(times_per_seg=200) # NOTE: only the last figure is shown in the generated docs plot_propelled_ascent(p, exp_out) plot_trajectory(p, exp_out) plot_states(p, exp_out) plt.show() # Check results (tolerance is relative unless value is zero) assert_near_equal(summary['Launch angle'].value, 85, .02) assert_near_equal(summary['Flight angle at end of propulsion'].value, 85, .02) assert_near_equal(summary['Empty mass'].value, 0.1425114, 1e-3) assert_near_equal(summary['Water volume'].value, 0.868281, 1e-3) assert_near_equal(summary['Maximum range'].value, 15.78, 5) assert_near_equal(summary['Maximum height'].value, 54.133184, 1e-3) assert_near_equal(summary['Maximum velocity'].value, 47.320298, 1e-3)
import unittest import numpy as np import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.general_utils import set_pyoptsparse_opt _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=True) import dymos as dm from dymos.examples.finite_burn_orbit_raise.finite_burn_eom import FiniteBurnODE from openmdao.utils.testing_utils import use_tempdirs def make_traj(transcription='gauss-lobatto', transcription_order=3, compressed=False, connected=False, param_mode='param_sequence'): t = { 'gauss-lobatto': dm.GaussLobatto(num_segments=5, order=transcription_order, compressed=compressed), 'radau': dm.Radau(num_segments=20, order=transcription_order, compressed=compressed), 'runge-kutta': dm.RungeKutta(num_segments=5, compressed=compressed)
from openmdao.utils.assert_utils import assert_warning from openmdao.utils.general_utils import set_pyoptsparse_opt from openmdao.utils.reports_system import set_default_reports_dir, _reports_dir, register_report, \ list_reports, clear_reports, run_n2_report, setup_default_reports, report_function from openmdao.utils.testing_utils import use_tempdirs from openmdao.utils.mpi import MPI from openmdao.utils.tests.test_hooks import hooks_active from openmdao.visualization.n2_viewer.n2_viewer import _default_n2_filename from openmdao.visualization.scaling_viewer.scaling_report import _default_scaling_filename try: from openmdao.vectors.petsc_vector import PETScVector except ImportError: PETScVector = None OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP') if OPTIMIZER: from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver import dymos as dm from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE @use_tempdirs class TestSubproblemReportToggle(unittest.TestCase): def setUp(self): self.n2_filename = _default_n2_filename self.scaling_filename = _default_scaling_filename # set things to a known initial state for all the test runs
def test_distributed_list_vars(self): from openmdao.utils.general_utils import set_pyoptsparse_opt from openmdao.utils.mpi import MPI if MPI: from openmdao.api import PETScVector vector_class = PETScVector else: PETScVector = None # check that pyoptsparse is installed. if it is, try to use SLSQP. OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP') if OPTIMIZER: from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver else: raise unittest.SkipTest("pyOptSparseDriver is required.") from openmdao.core.parallel_group import ParallelGroup from openmdao.components.exec_comp import ExecComp class Mygroup(Group): def setup(self): self.add_subsystem('indep_var_comp', IndepVarComp('x'), promotes=['*']) self.add_subsystem('Cy', ExecComp('y=2*x'), promotes=['*']) self.add_subsystem('Cc', ExecComp('c=x+2'), promotes=['*']) self.add_design_var('x') self.add_constraint('c', lower=-3.) prob = Problem() prob.model.add_subsystem('par', ParallelGroup()) prob.model.par.add_subsystem('G1', Mygroup()) prob.model.par.add_subsystem('G2', Mygroup()) prob.model.add_subsystem('Obj', ExecComp('obj=y1+y2')) prob.model.connect('par.G1.y', 'Obj.y1') prob.model.connect('par.G2.y', 'Obj.y2') prob.model.add_objective('Obj.obj') prob.driver = pyOptSparseDriver() prob.driver.options['optimizer'] = 'SLSQP' prob.setup(vector_class=PETScVector) prob.run_driver() prob.cleanup() stream = cStringIO() inputs = sorted(prob.model.list_inputs(values=True, print_arrays=True, out_stream=stream)) self.assertEqual(inputs[0][0], 'Obj.y1') self.assertEqual(inputs[1][0], 'Obj.y2') if prob.comm.rank: # Only rank 0 prints self.assertEqual(inputs[2][0], 'par.G2.Cc.x') self.assertEqual(inputs[3][0], 'par.G2.Cy.x') else: self.assertEqual(inputs[2][0], 'par.G1.Cc.x') self.assertEqual(inputs[3][0], 'par.G1.Cy.x') self.assertTrue('value' in inputs[0][1]) self.assertEqual(4, len(inputs)) text = stream.getvalue() if prob.comm.rank: # Only rank 0 prints self.assertEqual(len(text), 0) else: self.assertEqual(1, text.count("6 Input(s) in 'model'"), 1) self.assertEqual(1, text.count('value')) self.assertEqual(1, text.count(' par')) self.assertEqual(1, text.count(' G1')) self.assertEqual(1, text.count(' G2')) self.assertEqual(2, text.count(' Cy')) self.assertEqual(2, text.count(' Cc')) self.assertEqual(4, text.count(' x')) self.assertEqual(1, text.count(' Obj')) self.assertEqual(1, text.count(' y1')) self.assertEqual(1, text.count(' y2')) stream = cStringIO() outputs = sorted(prob.model.list_outputs(values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=True, print_arrays=True, out_stream=stream)) self.assertEqual(outputs[0][0], 'Obj.obj') if prob.comm.rank: # outputs only return what is on their proc self.assertEqual(outputs[1][0], 'par.G2.Cc.c') self.assertEqual(outputs[2][0], 'par.G2.Cy.y') self.assertEqual(outputs[3][0], 'par.G2.indep_var_comp.x') else: self.assertEqual(outputs[1][0], 'par.G1.Cc.c') self.assertEqual(outputs[2][0], 'par.G1.Cy.y') self.assertEqual(outputs[3][0], 'par.G1.indep_var_comp.x') self.assertEqual(4, len(outputs)) self.assertTrue('value' in outputs[0][1]) self.assertTrue('units' in outputs[0][1]) text = stream.getvalue() if prob.comm.rank: # Only rank 0 prints self.assertEqual(len(text), 0) else: self.assertEqual(1, text.count("7 Explicit Output(s) in 'model'")) self.assertEqual(1, text.count('value')) self.assertEqual(1, text.count('units')) self.assertEqual(1, text.count(' par')) self.assertEqual(1, text.count(' G1')) self.assertEqual(1, text.count(' G2')) self.assertEqual(2, text.count(' Cy')) self.assertEqual(2, text.count(' Cc')) self.assertEqual(2, text.count(' indep_var_comp')) self.assertEqual(2, text.count(' x')) self.assertEqual(2, text.count(' y')) self.assertEqual(2, text.count(' c')) self.assertEqual(1, text.count(' Obj')) self.assertEqual(1, text.count(' obj'))
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'], targets=BrachistochroneODE.states['v']['targets'], units=BrachistochroneODE.states['v']['units'], fix_initial=True) phase.add_control( 'theta', targets=BrachistochroneODE.parameters['theta']['targets'], continuity=True, rate_continuity=True, units='deg', lower=0.01, upper=179.9) phase.add_parameter( 'g', targets=BrachistochroneODE.parameters['g']['targets'], 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_distributed_list_vars(self): from openmdao.utils.general_utils import set_pyoptsparse_opt # check that pyoptsparse is installed. if it is, try to use SLSQP. OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP') if OPTIMIZER: from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver else: raise unittest.SkipTest("pyOptSparseDriver is required.") from openmdao.core.parallel_group import ParallelGroup from openmdao.components.exec_comp import ExecComp class Mygroup(Group): def setup(self): self.add_subsystem('indep_var_comp', IndepVarComp('x'), promotes=['*']) self.add_subsystem('Cy', ExecComp('y=2*x'), promotes=['*']) self.add_subsystem('Cc', ExecComp('c=x+2'), promotes=['*']) self.add_design_var('x') self.add_constraint('c', lower=-3.) prob = Problem() prob.model.add_subsystem('par', ParallelGroup()) prob.model.par.add_subsystem('G1', Mygroup()) prob.model.par.add_subsystem('G2', Mygroup()) prob.model.add_subsystem('Obj', ExecComp('obj=y1+y2')) prob.model.connect('par.G1.y', 'Obj.y1') prob.model.connect('par.G2.y', 'Obj.y2') prob.model.add_objective('Obj.obj') prob.driver = pyOptSparseDriver() prob.driver.options['optimizer'] = 'SLSQP' prob.setup() prob.run_driver() prob.cleanup() stream = cStringIO() inputs = sorted(prob.model.list_inputs(values=True, print_arrays=True, out_stream=stream)) self.assertEqual(inputs[0][0], 'Obj.y1') self.assertEqual(inputs[1][0], 'Obj.y2') if prob.comm.rank: # Only rank 0 prints self.assertEqual(inputs[2][0], 'par.G2.Cc.x') self.assertEqual(inputs[3][0], 'par.G2.Cy.x') else: self.assertEqual(inputs[2][0], 'par.G1.Cc.x') self.assertEqual(inputs[3][0], 'par.G1.Cy.x') self.assertTrue('value' in inputs[0][1]) self.assertEqual(4, len(inputs)) text = stream.getvalue() if prob.comm.rank: # Only rank 0 prints self.assertEqual(len(text), 0) else: self.assertEqual(1, text.count("6 Input(s) in 'model'"), 1) self.assertEqual(1, text.count('value')) self.assertEqual(1, text.count(' par')) self.assertEqual(1, text.count(' G1')) self.assertEqual(1, text.count(' G2')) self.assertEqual(2, text.count(' Cy')) self.assertEqual(2, text.count(' Cc')) self.assertEqual(4, text.count(' x')) self.assertEqual(1, text.count(' Obj')) self.assertEqual(1, text.count(' y1')) self.assertEqual(1, text.count(' y2')) stream = cStringIO() outputs = sorted(prob.model.list_outputs(values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=True, print_arrays=True, out_stream=stream)) self.assertEqual(outputs[0][0], 'Obj.obj') if prob.comm.rank: # outputs only return what is on their proc self.assertEqual(outputs[1][0], 'par.G2.Cc.c') self.assertEqual(outputs[2][0], 'par.G2.Cy.y') self.assertEqual(outputs[3][0], 'par.G2.indep_var_comp.x') else: self.assertEqual(outputs[1][0], 'par.G1.Cc.c') self.assertEqual(outputs[2][0], 'par.G1.Cy.y') self.assertEqual(outputs[3][0], 'par.G1.indep_var_comp.x') self.assertEqual(4, len(outputs)) self.assertTrue('value' in outputs[0][1]) self.assertTrue('units' in outputs[0][1]) text = stream.getvalue() if prob.comm.rank: # Only rank 0 prints self.assertEqual(len(text), 0) else: self.assertEqual(1, text.count("7 Explicit Output(s) in 'model'")) self.assertEqual(1, text.count('value')) self.assertEqual(1, text.count('units')) self.assertEqual(1, text.count(' par')) self.assertEqual(1, text.count(' G1')) self.assertEqual(1, text.count(' G2')) self.assertEqual(2, text.count(' Cy')) self.assertEqual(2, text.count(' Cc')) self.assertEqual(2, text.count(' indep_var_comp')) self.assertEqual(2, text.count(' x')) self.assertEqual(2, text.count(' y')) self.assertEqual(2, text.count(' c')) self.assertEqual(1, text.count(' Obj')) self.assertEqual(1, text.count(' obj'))
from openmdao.utils.assert_utils import assert_rel_error, assert_warning from openmdao.utils.general_utils import set_pyoptsparse_opt from openmdao.utils.coloring import get_simul_meta, _solves_info from openmdao.utils.mpi import MPI from openmdao.test_suite.tot_jac_builder import TotJacBuilder import openmdao.test_suite try: from openmdao.vectors.petsc_vector import PETScVector except ImportError: PETScVector = None # check that pyoptsparse is installed OPT, OPTIMIZER = set_pyoptsparse_opt('SNOPT') if OPTIMIZER: from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver class CounterGroup(Group): def __init__(self, *args, **kwargs): self._solve_count = 0 super(CounterGroup, self).__init__(*args, **kwargs) def _solve_linear(self, *args, **kwargs): super(CounterGroup, self)._solve_linear(*args, **kwargs) self._solve_count += 1 # note: size must be an even number
def test_two_burn_orbit_raise_gl_list_add_timeseries_output(self): import numpy as np import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.general_utils import set_pyoptsparse_opt import dymos as dm from dymos.examples.finite_burn_orbit_raise.finite_burn_eom import FiniteBurnODE traj = dm.Trajectory() p = om.Problem(model=om.Group()) p.model.add_subsystem('traj', traj) p.driver = om.pyOptSparseDriver() _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=True) p.driver.options['optimizer'] = optimizer p.driver.declare_coloring() traj.add_parameter('c', opt=False, val=1.5, units='DU/TU', targets={'burn1': ['c'], 'coast': ['c'], 'burn2': ['c']}) # First Phase (burn) burn1 = dm.Phase(ode_class=FiniteBurnODE, transcription=dm.GaussLobatto(num_segments=10, order=3, compressed=True)) burn1 = traj.add_phase('burn1', burn1) burn1.set_time_options(fix_initial=True, duration_bounds=(.5, 10), units='TU') burn1.add_state('r', fix_initial=True, fix_final=False, defect_scaler=100.0, rate_source='r_dot', targets=['r'], units='DU') burn1.add_state('theta', fix_initial=True, fix_final=False, defect_scaler=100.0, rate_source='theta_dot', targets=['theta'], units='rad') burn1.add_state('vr', fix_initial=True, fix_final=False, defect_scaler=100.0, rate_source='vr_dot', targets=['vr'], units='DU/TU') burn1.add_state('vt', fix_initial=True, fix_final=False, defect_scaler=100.0, rate_source='vt_dot', targets=['vt'], units='DU/TU') burn1.add_state('accel', fix_initial=True, fix_final=False, rate_source='at_dot', targets=['accel'], units='DU/TU**2') burn1.add_state('deltav', fix_initial=True, fix_final=False, rate_source='deltav_dot', units='DU/TU') burn1.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg', scaler=0.01, rate_continuity_scaler=0.001, rate2_continuity_scaler=0.001, lower=-30, upper=30, targets=['u1']) # Second Phase (Coast) coast = dm.Phase(ode_class=FiniteBurnODE, transcription=dm.RungeKutta(num_segments=20)) traj.add_phase('coast', coast) coast.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), duration_ref=10, units='TU') coast.add_state('r', fix_initial=False, fix_final=False, defect_scaler=100.0, rate_source='r_dot', targets=['r'], units='DU') coast.add_state('theta', fix_initial=False, fix_final=False, defect_scaler=100.0, units='rad', rate_source='theta_dot', targets=['theta']) coast.add_state('vr', fix_initial=False, fix_final=False, defect_scaler=100.0, rate_source='vr_dot', targets=['vr'], units='DU/TU') coast.add_state('vt', fix_initial=False, fix_final=False, defect_scaler=100.0, rate_source='vt_dot', targets=['vt'], units='DU/TU') coast.add_state('accel', fix_initial=True, fix_final=False, ref=1.0E-12, defect_ref=1.0E-12, rate_source='at_dot', targets=['accel'], units='DU/TU**2') coast.add_state('deltav', fix_initial=False, fix_final=False, rate_source='deltav_dot', units='DU/TU') coast.add_parameter('u1', targets=['u1'], opt=False, val=0.0, units='deg') # Third Phase (burn) burn2 = dm.Phase(ode_class=FiniteBurnODE, transcription=dm.GaussLobatto(num_segments=10, order=3, compressed=True)) traj.add_phase('burn2', burn2) burn2.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), initial_ref=10, units='TU') burn2.add_state('r', fix_initial=False, fix_final=True, rate_source='r_dot', targets=['r'], units='DU') burn2.add_state('theta', fix_initial=False, fix_final=False, rate_source='theta_dot', targets=['theta'], units='rad') burn2.add_state('vr', fix_initial=False, fix_final=True, rate_source='vr_dot', targets=['vr'], units='DU/TU') burn2.add_state('vt', fix_initial=False, fix_final=True, rate_source='vt_dot', targets=['vt'], units='DU/TU') burn2.add_state('accel', fix_initial=False, fix_final=False, defect_ref=1.0E-6, rate_source='at_dot', targets=['accel'], units='DU/TU**2') burn2.add_state('deltav', fix_initial=False, fix_final=False, rate_source='deltav_dot', units='DU/TU') burn2.add_control('u1', targets=['u1'], rate_continuity=True, rate2_continuity=True, units='deg', scaler=0.01, lower=-30, upper=30) burn2.add_objective('deltav', loc='final', scaler=1.0) # demonstrate adding multiple variables at once using list in add_timeseries_output # test dict for units, ignore mismatched unit burn1.add_timeseries_output(['pos_x', 'pos_y'], units={'pos_x': 'm', 'junk': 'lbm'}) coast.add_timeseries_output(['pos_x', 'pos_y']) # test list for units burn2.add_timeseries_output(['pos_x', 'pos_y'], units=['m', 'm']) # Link Phases traj.link_phases(phases=['burn1', 'coast', 'burn2'], vars=['time', 'r', 'vr', 'vt', 'deltav']) traj.link_phases(phases=['burn1', 'burn2'], vars=['accel']) # Finish Problem Setup p.model.linear_solver = om.DirectSolver() p.setup(check=True, force_alloc_complex=True) # Set Initial Guesses p.set_val('traj.parameters:c', value=1.5) p.set_val('traj.burn1.t_initial', value=0.0) p.set_val('traj.burn1.t_duration', value=2.25) p.set_val('traj.burn1.states:r', value=burn1.interpolate(ys=[1, 1.5], nodes='state_input')) p.set_val('traj.burn1.states:theta', value=burn1.interpolate(ys=[0, 1.7], nodes='state_input')) p.set_val('traj.burn1.states:vr', value=burn1.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('traj.burn1.states:vt', value=burn1.interpolate(ys=[1, 1], nodes='state_input')) p.set_val('traj.burn1.states:accel', value=burn1.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('traj.burn1.states:deltav', value=burn1.interpolate(ys=[0, 0.1], nodes='state_input'), ) p.set_val('traj.burn1.controls:u1', value=burn1.interpolate(ys=[-3.5, 13.0], nodes='control_input')) p.set_val('traj.coast.t_initial', value=2.25) p.set_val('traj.coast.t_duration', value=3.0) p.set_val('traj.coast.states:r', value=coast.interpolate(ys=[1.3, 1.5], nodes='state_input')) p.set_val('traj.coast.states:theta', value=coast.interpolate(ys=[2.1767, 1.7], nodes='state_input')) p.set_val('traj.coast.states:vr', value=coast.interpolate(ys=[0.3285, 0], nodes='state_input')) p.set_val('traj.coast.states:vt', value=coast.interpolate(ys=[0.97, 1], nodes='state_input')) p.set_val('traj.coast.states:accel', value=coast.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('traj.burn2.t_initial', value=5.25) p.set_val('traj.burn2.t_duration', value=1.75) p.set_val('traj.burn2.states:r', value=burn2.interpolate(ys=[1.8, 3], nodes='state_input')) p.set_val('traj.burn2.states:theta', value=burn2.interpolate(ys=[3.2, 4.0], nodes='state_input')) p.set_val('traj.burn2.states:vr', value=burn2.interpolate(ys=[.5, 0], nodes='state_input')) p.set_val('traj.burn2.states:vt', value=burn2.interpolate(ys=[1, np.sqrt(1 / 3)], nodes='state_input')) p.set_val('traj.burn2.states:accel', value=burn2.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('traj.burn2.states:deltav', value=burn2.interpolate(ys=[0.1, 0.2], nodes='state_input')) p.set_val('traj.burn2.controls:u1', value=burn2.interpolate(ys=[1, 1], nodes='control_input')) p.run_driver() assert_near_equal(p.get_val('traj.burn2.timeseries.states:deltav')[-1], 0.3995, tolerance=2.0E-3) # check units un = dict(p.model.list_outputs(units=True)) assert(un['traj.phases.burn1.timeseries.pos_x']['units'] == 'm') assert(un['traj.phases.burn1.timeseries.pos_y']['units'] == 'DU') assert(un['traj.phases.burn2.timeseries.pos_x']['units'] == 'm') assert(un['traj.phases.burn2.timeseries.pos_y']['units'] == 'm')
def test_battery_power(self): """ for battery explicit integration testings """ _, local_opt = set_pyoptsparse_opt('SNOPT') if local_opt != 'SNOPT': raise unittest.SkipTest("pyoptsparse is not providing SNOPT") p = om.Problem() p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SNOPT' p.driver.opt_settings['Major iterations limit'] = 100 p.driver.opt_settings['Major optimality tolerance'] = 5.0E-3 p.driver.opt_settings['Major feasibility tolerance'] = 1e-6 p.driver.opt_settings['iSumm'] = 6 transcription = Radau(num_segments=15, order=3, compressed=True) phase0 = Phase(transcription=transcription, ode_class=BatteryGroup) phase0.set_time_options(fix_initial=True, duration_bounds=(30, 30)) p.model.add_subsystem(name='phase0', subsys=phase0) phase0.add_state('SOC', fix_initial=True, rate_source='dXdt:SOC', lower=0.0, upper=1.) phase0.add_state('U_Th', units='V', fix_initial=False, rate_source='dXdt:V_{thev}', lower=0.0, upper=5.0) # phase0.add_parameter('P_out', units='W', opt=False) # phase0.add_boundary_constraint('U_pack', units='V', loc='initial', equals=5100) phase0.add_objective('time', loc='final', ref=1) p.model.linear_solver = om.DirectSolver(assemble_jac=True) phase0.add_timeseries_output('Q_{batt}', output_name='Q_{batt}', units='W') # phase0.add_timeseries_output('U_pack', output_name='V', units='V') p.setup() # p.check_partials() T0 = 10 + 273 p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 30 p['phase0.states:SOC'] = phase0.interpolate(ys=[1.0, 0.0], nodes='state_input') p['phase0.states:U_Th'] = phase0.interpolate(ys=[0.1, 0.1], nodes='state_input') # p['phase0.parameters:P_out'][:] = 72000. p.run_driver() fig, ax = plt.subplots(3, 1, sharex=True) fig.suptitle('Temperature Plots') t_opt = p.get_val('phase0.timeseries.time') SOC_opt = p.get_val('phase0.timeseries.states:SOC', units=None) Q_batt_opt = p.get_val('phase0.timeseries.Q_{batt}', units='kW') ax[1].plot(t_opt, Q_batt_opt * 128 * 40, 'r', label='$Q_{cell}$') ax[2].plot(t_opt, SOC_opt, 'r', label='$SOC$') #spot check final values # assert_rel_error(self, T_batt_opt[-1], 1.25934406, tolerance=1.0E-6) # ax[3].plot(t_opt, V_opt, 'r', label='$Voltage$') # axarr = fig.add_subplot(1, 2, 2) # axarr.plot(sim_out.get_values('time'),sim_out.get_values('electric.battery.I_Li'), 'b') # # # axarr.plot(p['phase0.state_interp.state_col:r'], # # # p['phase0.controls:h'], 'bo', ms=4) # axarr.set_ylabel('I_Li, amps') # axarr.set_xlabel('time, s') # axarr.axes.get_xaxis().set_visible(True) import matplotlib matplotlib.use( 'agg') # <--- comment out if you want to show this plot. plt.show()
def _run_balanced_field_length_problem(tx=dm.GaussLobatto, timeseries=True, sim=True, solvesegs=False): p = om.Problem() _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=True) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() # Use IPOPT if available, with fallback to SLSQP p.driver.options['optimizer'] = optimizer p.driver.options['print_results'] = False if optimizer == 'IPOPT': p.driver.opt_settings['print_level'] = 5 # First Phase: Brake release to V1 - both engines operable br_to_v1 = dm.Phase(ode_class=BalancedFieldODEComp, transcription=tx(num_segments=3, solve_segments=solvesegs), ode_init_kwargs={'mode': 'runway'}) br_to_v1.set_time_options(fix_initial=True, duration_bounds=(1, 1000), duration_ref=10.0) br_to_v1.add_state('r', fix_initial=True, lower=0, ref=1000.0, defect_ref=1000.0) br_to_v1.add_state('v', fix_initial=True, lower=0, ref=100.0, defect_ref=100.0) br_to_v1.add_parameter('alpha', val=0.0, opt=False, units='deg') if timeseries: br_to_v1.add_timeseries_output('*') # Second Phase: Rejected takeoff at V1 - no engines operable rto = dm.Phase(ode_class=BalancedFieldODEComp, transcription=dm.Radau(num_segments=3, solve_segments=solvesegs), ode_init_kwargs={'mode': 'runway'}) rto.set_time_options(fix_initial=False, duration_bounds=(1, 1000), duration_ref=1.0) rto.add_state('r', fix_initial=False, lower=0, ref=1000.0, defect_ref=1000.0) rto.add_state('v', fix_initial=False, lower=0, ref=100.0, defect_ref=100.0) rto.add_parameter('alpha', val=0.0, opt=False, units='deg') if timeseries: rto.add_timeseries_output('*') # Third Phase: V1 to Vr - single engine operable v1_to_vr = dm.Phase(ode_class=BalancedFieldODEComp, transcription=dm.Radau(num_segments=3, solve_segments=solvesegs), ode_init_kwargs={'mode': 'runway'}) v1_to_vr.set_time_options(fix_initial=False, duration_bounds=(1, 1000), duration_ref=1.0) v1_to_vr.add_state('r', fix_initial=False, lower=0, ref=1000.0, defect_ref=1000.0) v1_to_vr.add_state('v', fix_initial=False, lower=0, ref=100.0, defect_ref=100.0) v1_to_vr.add_parameter('alpha', val=0.0, opt=False, units='deg') if timeseries: v1_to_vr.add_timeseries_output('*') # Fourth Phase: Rotate - single engine operable rotate = dm.Phase(ode_class=BalancedFieldODEComp, transcription=dm.Radau(num_segments=3, solve_segments=solvesegs), ode_init_kwargs={'mode': 'runway'}) rotate.set_time_options(fix_initial=False, duration_bounds=(1.0, 5), duration_ref=1.0) rotate.add_state('r', fix_initial=False, lower=0, ref=1000.0, defect_ref=1000.0) rotate.add_state('v', fix_initial=False, lower=0, ref=100.0, defect_ref=100.0) rotate.add_polynomial_control('alpha', order=1, opt=True, units='deg', lower=0, upper=10, ref=10, val=[0, 10]) if timeseries: rotate.add_timeseries_output('*') # Fifth Phase: Climb to target speed and altitude at end of runway. climb = dm.Phase(ode_class=BalancedFieldODEComp, transcription=dm.Radau(num_segments=5), ode_init_kwargs={'mode': 'climb'}) climb.set_time_options(fix_initial=False, duration_bounds=(1, 100), duration_ref=1.0) climb.add_state('r', fix_initial=False, lower=0, ref=1000.0, defect_ref=1000.0) climb.add_state('h', fix_initial=True, lower=0, ref=1.0, defect_ref=1.0) climb.add_state('v', fix_initial=False, lower=0, ref=100.0, defect_ref=100.0) climb.add_state('gam', fix_initial=True, lower=0, ref=0.05, defect_ref=0.05) climb.add_control('alpha', opt=True, units='deg', lower=-10, upper=15, ref=10) if timeseries: climb.add_timeseries_output('*') # Instantiate the trajectory and add phases traj = dm.Trajectory() p.model.add_subsystem('traj', traj) traj.add_phase('br_to_v1', br_to_v1) traj.add_phase('rto', rto) traj.add_phase('v1_to_vr', v1_to_vr) traj.add_phase('rotate', rotate) traj.add_phase('climb', climb) # Add parameters common to multiple phases to the trajectory traj.add_parameter('m', val=174200., opt=False, units='lbm', desc='aircraft mass', targets={'br_to_v1': ['m'], 'v1_to_vr': ['m'], 'rto': ['m'], 'rotate': ['m'], 'climb': ['m']}) traj.add_parameter('T_nominal', val=27000 * 2, opt=False, units='lbf', dynamic=False, desc='nominal aircraft thrust', targets={'br_to_v1': ['T']}) traj.add_parameter('T_engine_out', val=27000, opt=False, units='lbf', dynamic=False, desc='thrust under a single engine', targets={'v1_to_vr': ['T'], 'rotate': ['T'], 'climb': ['T']}) traj.add_parameter('T_shutdown', val=0.0, opt=False, units='lbf', dynamic=False, desc='thrust when engines are shut down for rejected takeoff', targets={'rto': ['T']}) traj.add_parameter('mu_r_nominal', val=0.03, opt=False, units=None, dynamic=False, desc='nominal runway friction coefficient', targets={'br_to_v1': ['mu_r'], 'v1_to_vr': ['mu_r'], 'rotate': ['mu_r']}) traj.add_parameter('mu_r_braking', val=0.3, opt=False, units=None, dynamic=False, desc='runway friction coefficient under braking', targets={'rto': ['mu_r']}) traj.add_parameter('h_runway', val=0., opt=False, units='ft', desc='runway altitude', targets={'br_to_v1': ['h'], 'v1_to_vr': ['h'], 'rto': ['h'], 'rotate': ['h']}) traj.add_parameter('rho', val=1.225, opt=False, units='kg/m**3', dynamic=False, desc='atmospheric density', targets={'br_to_v1': ['rho'], 'v1_to_vr': ['rho'], 'rto': ['rho'], 'rotate': ['rho']}) traj.add_parameter('S', val=124.7, opt=False, units='m**2', dynamic=False, desc='aerodynamic reference area', targets={'br_to_v1': ['S'], 'v1_to_vr': ['S'], 'rto': ['S'], 'rotate': ['S'], 'climb': ['S']}) traj.add_parameter('CD0', val=0.03, opt=False, units=None, dynamic=False, desc='zero-lift drag coefficient', targets={f'{phase}': ['CD0'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb']}) traj.add_parameter('AR', val=9.45, opt=False, units=None, dynamic=False, desc='wing aspect ratio', targets={f'{phase}': ['AR'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb']}) traj.add_parameter('e', val=801, opt=False, units=None, dynamic=False, desc='Oswald span efficiency factor', targets={f'{phase}': ['e'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb']}) traj.add_parameter('span', val=35.7, opt=False, units='m', dynamic=False, desc='wingspan', targets={f'{phase}': ['span'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb']}) traj.add_parameter('h_w', val=1.0, opt=False, units='m', dynamic=False, desc='height of wing above CG', targets={f'{phase}': ['h_w'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb']}) traj.add_parameter('CL0', val=0.5, opt=False, units=None, dynamic=False, desc='zero-alpha lift coefficient', targets={f'{phase}': ['CL0'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb']}) traj.add_parameter('CL_max', val=2.0, opt=False, units=None, dynamic=False, desc='maximum lift coefficient for linear fit', targets={f'{phase}': ['CL_max'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb']}) traj.add_parameter('alpha_max', val=10.0, opt=False, units='deg', dynamic=False, desc='angle of attack at maximum lift', targets={f'{phase}': ['alpha_max'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb']}) # Standard "end of first phase to beginning of second phase" linkages # Alpha changes from being a parameter in v1_to_vr to a polynomial control # in rotate, to a dynamic control in `climb`. traj.link_phases(['br_to_v1', 'v1_to_vr'], vars=['time', 'r', 'v']) traj.link_phases(['v1_to_vr', 'rotate'], vars=['time', 'r', 'v', 'alpha']) traj.link_phases(['rotate', 'climb'], vars=['time', 'r', 'v', 'alpha']) traj.link_phases(['br_to_v1', 'rto'], vars=['time', 'r', 'v']) # Less common "final value of r must be the match at ends of two phases". traj.add_linkage_constraint(phase_a='rto', var_a='r', loc_a='final', phase_b='climb', var_b='r', loc_b='final', ref=1000) # Define the constraints and objective for the optimal control problem v1_to_vr.add_boundary_constraint('v_over_v_stall', loc='final', lower=1.2, ref=100) rto.add_boundary_constraint('v', loc='final', equals=0., ref=100, linear=True) rotate.add_boundary_constraint('F_r', loc='final', equals=0, ref=100000) climb.add_boundary_constraint('h', loc='final', equals=35, ref=35, units='ft', linear=True) climb.add_boundary_constraint('gam', loc='final', equals=5, ref=5, units='deg', linear=True) climb.add_path_constraint('gam', lower=0, upper=5, ref=5, units='deg') climb.add_boundary_constraint('v_over_v_stall', loc='final', lower=1.25, ref=1.25) rto.add_objective('r', loc='final', ref=1000.0) # # Setup the problem and set the initial guess # p.setup(check=True) p.set_val('traj.br_to_v1.t_initial', 0) p.set_val('traj.br_to_v1.t_duration', 35) p.set_val('traj.br_to_v1.states:r', br_to_v1.interpolate(ys=[0, 2500.0], nodes='state_input')) p.set_val('traj.br_to_v1.states:v', br_to_v1.interpolate(ys=[0, 100.0], nodes='state_input')) p.set_val('traj.br_to_v1.parameters:alpha', 0, units='deg') p.set_val('traj.v1_to_vr.t_initial', 35) p.set_val('traj.v1_to_vr.t_duration', 35) p.set_val('traj.v1_to_vr.states:r', v1_to_vr.interpolate(ys=[2500, 300.0], nodes='state_input')) p.set_val('traj.v1_to_vr.states:v', v1_to_vr.interpolate(ys=[100, 110.0], nodes='state_input')) p.set_val('traj.v1_to_vr.parameters:alpha', 0.0, units='deg') p.set_val('traj.rto.t_initial', 35) p.set_val('traj.rto.t_duration', 35) p.set_val('traj.rto.states:r', rto.interpolate(ys=[2500, 5000.0], nodes='state_input')) p.set_val('traj.rto.states:v', rto.interpolate(ys=[110, 0], nodes='state_input')) p.set_val('traj.rto.parameters:alpha', 0.0, units='deg') p.set_val('traj.rotate.t_initial', 70) p.set_val('traj.rotate.t_duration', 5) p.set_val('traj.rotate.states:r', rotate.interpolate(ys=[1750, 1800.0], nodes='state_input')) p.set_val('traj.rotate.states:v', rotate.interpolate(ys=[80, 85.0], nodes='state_input')) p.set_val('traj.rotate.polynomial_controls:alpha', 0.0, units='deg') p.set_val('traj.climb.t_initial', 75) p.set_val('traj.climb.t_duration', 15) p.set_val('traj.climb.states:r', climb.interpolate(ys=[5000, 5500.0], nodes='state_input'), units='ft') p.set_val('traj.climb.states:v', climb.interpolate(ys=[160, 170.0], nodes='state_input'), units='kn') p.set_val('traj.climb.states:h', climb.interpolate(ys=[0, 35.0], nodes='state_input'), units='ft') p.set_val('traj.climb.states:gam', climb.interpolate(ys=[0, 5.0], nodes='state_input'), units='deg') p.set_val('traj.climb.controls:alpha', 5.0, units='deg') dm.run_problem(p, run_driver=True, simulate=sim) # Test this example in Dymos' continuous integration assert_near_equal(p.get_val('traj.rto.states:r')[-1], 2188.2, tolerance=0.01)
def make_problem(self, constrained=True, transcription=GaussLobatto, optimizer='SLSQP', numseg=30): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=False) p.driver.options['optimizer'] = OPTIMIZER traj = p.model.add_subsystem('traj', Trajectory()) phase0 = traj.add_phase( 'phase0', Phase(ode_class=ShuttleODE, transcription=transcription(num_segments=numseg, order=3))) phase0.set_time_options(fix_initial=True, units='s', duration_ref=200) phase0.add_state('h', fix_initial=True, fix_final=True, units='ft', rate_source='hdot', targets=['h'], lower=0, ref0=75000, ref=300000, defect_ref=1000) phase0.add_state('gamma', fix_initial=True, fix_final=True, units='rad', rate_source='gammadot', targets=['gamma'], lower=-89. * np.pi / 180, upper=89. * np.pi / 180) phase0.add_state('phi', fix_initial=True, fix_final=False, units='rad', rate_source='phidot', lower=0, upper=89. * np.pi / 180) phase0.add_state('psi', fix_initial=True, fix_final=False, units='rad', rate_source='psidot', targets=['psi'], lower=0, upper=90. * np.pi / 180) phase0.add_state('theta', fix_initial=True, fix_final=False, units='rad', rate_source='thetadot', targets=['theta'], lower=-89. * np.pi / 180, upper=89. * np.pi / 180) phase0.add_state('v', fix_initial=True, fix_final=True, units='ft/s', rate_source='vdot', targets=['v'], lower=500, ref0=2500, ref=25000) phase0.add_control('alpha', units='rad', opt=True, lower=-np.pi / 2, upper=np.pi / 2, targets=['alpha']) phase0.add_control('beta', units='rad', opt=True, lower=-89 * np.pi / 180, upper=1 * np.pi / 180, targets=['beta']) if constrained: phase0.add_path_constraint('q', lower=0, upper=70, ref=70) phase0.add_objective('theta', loc='final', ref=-0.01) p.setup(check=True, force_alloc_complex=True) p.set_val('traj.phase0.states:h', phase0.interpolate(ys=[260000, 80000], nodes='state_input'), units='ft') p.set_val('traj.phase0.states:gamma', phase0.interpolate(ys=[-1 * np.pi / 180, -5 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:phi', phase0.interpolate(ys=[0, 75 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:psi', phase0.interpolate(ys=[90 * np.pi / 180, 10 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:theta', phase0.interpolate(ys=[0, 25 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:v', phase0.interpolate(ys=[25600, 2500], nodes='state_input'), units='ft/s') p.set_val('traj.phase0.t_initial', 0, units='s') p.set_val('traj.phase0.t_duration', 2000, units='s') p.set_val('traj.phase0.controls:alpha', phase0.interpolate( ys=[17.4 * np.pi / 180, 17.4 * np.pi / 180], nodes='control_input'), units='rad') p.set_val('traj.phase0.controls:beta', phase0.interpolate(ys=[-75 * np.pi / 180, 0 * np.pi / 180], nodes='control_input'), units='rad') return p
def test_distributed_list_vars(self): from openmdao.utils.general_utils import set_pyoptsparse_opt # check that pyoptsparse is installed. if it is, try to use SLSQP. OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP') if OPTIMIZER: from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver else: raise unittest.SkipTest("pyOptSparseDriver is required.") class Mygroup(om.Group): def setup(self): self.add_subsystem('indep_var_comp', om.IndepVarComp('x'), promotes=['*']) self.add_subsystem('Cy', om.ExecComp('y=2*x'), promotes=['*']) self.add_subsystem('Cc', om.ExecComp('c=x+2'), promotes=['*']) self.add_design_var('x') self.add_constraint('c', lower=-3.) prob = om.Problem() prob.model.add_subsystem('par', om.ParallelGroup()) prob.model.par.add_subsystem('G1', Mygroup()) prob.model.par.add_subsystem('G2', Mygroup()) prob.model.add_subsystem('Obj', om.ExecComp('obj=y1+y2')) prob.model.connect('par.G1.y', 'Obj.y1') prob.model.connect('par.G2.y', 'Obj.y2') prob.model.add_objective('Obj.obj') prob.driver = pyOptSparseDriver() prob.driver.options['optimizer'] = 'SLSQP' prob.setup() prob.run_driver() prob.cleanup() stream = StringIO() with multi_proc_exception_check(prob.comm): inputs = sorted(prob.model.list_inputs(values=True, print_arrays=True, out_stream=stream)) if prob.comm.rank: self.assertEqual(inputs, []) else: inames = [t[0] for t in inputs] self.assertEqual(inames, ['Obj.y1', 'Obj.y2', 'par.G1.Cc.x', 'par.G1.Cy.x', 'par.G2.Cc.x', 'par.G2.Cy.x']) self.assertTrue('val' in inputs[0][1]) text = stream.getvalue() if prob.comm.rank: # Only rank 0 prints self.assertEqual(len(text), 0) else: self.assertEqual(1, text.count("6 Input(s) in 'model'"), 1) self.assertEqual(1, text.count('val')) self.assertEqual(1, text.count('par')) self.assertEqual(1, text.count(' G1')) self.assertEqual(1, text.count(' G2')) self.assertEqual(2, text.count(' Cy')) self.assertEqual(2, text.count(' Cc')) self.assertEqual(4, text.count(' x')) self.assertEqual(1, text.count('Obj')) self.assertEqual(1, text.count(' y1')) self.assertEqual(1, text.count(' y2')) stream = StringIO() with multi_proc_exception_check(prob.comm): outputs = sorted(prob.model.list_outputs(values=True, units=True, shape=True, bounds=True, residuals=True, scaling=True, hierarchical=True, print_arrays=True, out_stream=stream)) onames = [t[0] for t in outputs] if prob.comm.rank == 0: self.assertEqual(onames, ['Obj.obj', 'par.G1.Cc.c', 'par.G1.Cy.y', 'par.G1.indep_var_comp.x', 'par.G2.Cc.c', 'par.G2.Cy.y', 'par.G2.indep_var_comp.x']) self.assertTrue('val' in outputs[0][1]) self.assertTrue('units' in outputs[0][1]) else: self.assertEqual(onames, []) text = stream.getvalue() if prob.comm.rank: # Only rank 0 prints self.assertEqual(len(text), 0) else: self.assertEqual(1, text.count("7 Explicit Output(s) in 'model'")) self.assertEqual(1, text.count('val')) self.assertEqual(1, text.count('units')) self.assertEqual(1, text.count('par')) self.assertEqual(1, text.count(' G1')) self.assertEqual(1, text.count(' G2')) self.assertEqual(2, text.count(' Cy')) self.assertEqual(2, text.count(' Cc')) self.assertEqual(2, text.count(' indep_var_comp')) self.assertEqual(2, text.count(' x')) self.assertEqual(2, text.count(' y')) self.assertEqual(2, text.count(' c')) self.assertEqual(1, text.count('Obj')) self.assertEqual(1, text.count(' obj'))
def test_two_burn_orbit_raise_radau_wildcard_add_timeseries_output(self): import numpy as np import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal from openmdao.utils.general_utils import set_pyoptsparse_opt import dymos as dm from dymos.examples.finite_burn_orbit_raise.finite_burn_eom import FiniteBurnODE traj = dm.Trajectory() p = om.Problem(model=om.Group()) p.model.add_subsystem('traj', traj) p.driver = om.pyOptSparseDriver() _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=True) p.driver.options['optimizer'] = optimizer p.driver.declare_coloring() traj.add_parameter('c', opt=False, val=1.5, units='DU/TU', targets={'burn1': ['c'], 'coast': ['c'], 'burn2': ['c']}) # First Phase (burn) burn1 = dm.Phase(ode_class=FiniteBurnODE, transcription=dm.Radau(num_segments=10, order=3, compressed=True)) burn1 = traj.add_phase('burn1', burn1) burn1.set_time_options(fix_initial=True, duration_bounds=(.5, 10), units='TU') burn1.add_state('r', fix_initial=True, fix_final=False, defect_scaler=100.0, rate_source='r_dot', targets=['r'], units='DU') burn1.add_state('theta', fix_initial=True, fix_final=False, defect_scaler=100.0, rate_source='theta_dot', targets=['theta'], units='rad') burn1.add_state('vr', fix_initial=True, fix_final=False, defect_scaler=100.0, rate_source='vr_dot', targets=['vr'], units='DU/TU') burn1.add_state('vt', fix_initial=True, fix_final=False, defect_scaler=100.0, rate_source='vt_dot', targets=['vt'], units='DU/TU') burn1.add_state('accel', fix_initial=True, fix_final=False, rate_source='at_dot', targets=['accel'], units='DU/TU**2') burn1.add_state('deltav', fix_initial=True, fix_final=False, rate_source='deltav_dot', units='DU/TU') burn1.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg', scaler=0.01, rate_continuity_scaler=0.001, rate2_continuity_scaler=0.001, lower=-30, upper=30, targets=['u1']) # Second Phase (Coast) coast = dm.Phase(ode_class=FiniteBurnODE, transcription=dm.RungeKutta(num_segments=20)) traj.add_phase('coast', coast) coast.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), duration_ref=10, units='TU') coast.add_state('r', fix_initial=False, fix_final=False, defect_scaler=100.0, rate_source='r_dot', targets=['r'], units='DU') coast.add_state('theta', fix_initial=False, fix_final=False, defect_scaler=100.0, units='rad', rate_source='theta_dot', targets=['theta']) coast.add_state('vr', fix_initial=False, fix_final=False, defect_scaler=100.0, rate_source='vr_dot', targets=['vr'], units='DU/TU') coast.add_state('vt', fix_initial=False, fix_final=False, defect_scaler=100.0, rate_source='vt_dot', targets=['vt'], units='DU/TU') coast.add_state('accel', fix_initial=True, fix_final=False, ref=1.0E-12, defect_ref=1.0E-12, rate_source='at_dot', targets=['accel'], units='DU/TU**2') coast.add_state('deltav', fix_initial=False, fix_final=False, rate_source='deltav_dot', units='DU/TU') coast.add_parameter('u1', targets=['u1'], opt=False, val=0.0, units='deg') # Third Phase (burn) burn2 = dm.Phase(ode_class=FiniteBurnODE, transcription=dm.Radau(num_segments=10, order=3, compressed=True)) traj.add_phase('burn2', burn2) burn2.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), initial_ref=10, units='TU') burn2.add_state('r', fix_initial=False, fix_final=True, rate_source='r_dot', targets=['r'], units='DU') burn2.add_state('theta', fix_initial=False, fix_final=False, rate_source='theta_dot', targets=['theta'], units='rad') burn2.add_state('vr', fix_initial=False, fix_final=True, rate_source='vr_dot', targets=['vr'], units='DU/TU') burn2.add_state('vt', fix_initial=False, fix_final=True, rate_source='vt_dot', targets=['vt'], units='DU/TU') burn2.add_state('accel', fix_initial=False, fix_final=False, defect_ref=1.0E-6, rate_source='at_dot', targets=['accel'], units='DU/TU**2') burn2.add_state('deltav', fix_initial=False, fix_final=False, rate_source='deltav_dot', units='DU/TU') burn2.add_control('u1', targets=['u1'], rate_continuity=True, rate2_continuity=True, units='deg', scaler=0.01, lower=-30, upper=30) burn2.add_objective('deltav', loc='final', scaler=1.0) # demonstrate adding multiple variables at once using wildcard in add_timeseries_output burn1.add_timeseries_output('pos_*') # match partial variable in ODE outputs (Radau) coast.add_timeseries_output('pos_*') # match partial variable in ODE outputs (Runge Kutta) burn2.add_timeseries_output('*') # add all ODE outputs # Link Phases traj.link_phases(phases=['burn1', 'coast', 'burn2'], vars=['time', 'r', 'vr', 'vt', 'deltav']) traj.link_phases(phases=['burn1', 'burn2'], vars=['accel']) # Finish Problem Setup p.model.linear_solver = om.DirectSolver() p.setup(check=True, force_alloc_complex=True) # Set Initial Guesses p.set_val('traj.parameters:c', value=1.5) p.set_val('traj.burn1.t_initial', value=0.0) p.set_val('traj.burn1.t_duration', value=2.25) p.set_val('traj.burn1.states:r', value=burn1.interpolate(ys=[1, 1.5], nodes='state_input')) p.set_val('traj.burn1.states:theta', value=burn1.interpolate(ys=[0, 1.7], nodes='state_input')) p.set_val('traj.burn1.states:vr', value=burn1.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('traj.burn1.states:vt', value=burn1.interpolate(ys=[1, 1], nodes='state_input')) p.set_val('traj.burn1.states:accel', value=burn1.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('traj.burn1.states:deltav', value=burn1.interpolate(ys=[0, 0.1], nodes='state_input'), ) p.set_val('traj.burn1.controls:u1', value=burn1.interpolate(ys=[-3.5, 13.0], nodes='control_input')) p.set_val('traj.coast.t_initial', value=2.25) p.set_val('traj.coast.t_duration', value=3.0) p.set_val('traj.coast.states:r', value=coast.interpolate(ys=[1.3, 1.5], nodes='state_input')) p.set_val('traj.coast.states:theta', value=coast.interpolate(ys=[2.1767, 1.7], nodes='state_input')) p.set_val('traj.coast.states:vr', value=coast.interpolate(ys=[0.3285, 0], nodes='state_input')) p.set_val('traj.coast.states:vt', value=coast.interpolate(ys=[0.97, 1], nodes='state_input')) p.set_val('traj.coast.states:accel', value=coast.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('traj.burn2.t_initial', value=5.25) p.set_val('traj.burn2.t_duration', value=1.75) p.set_val('traj.burn2.states:r', value=burn2.interpolate(ys=[1.8, 3], nodes='state_input')) p.set_val('traj.burn2.states:theta', value=burn2.interpolate(ys=[3.2, 4.0], nodes='state_input')) p.set_val('traj.burn2.states:vr', value=burn2.interpolate(ys=[.5, 0], nodes='state_input')) p.set_val('traj.burn2.states:vt', value=burn2.interpolate(ys=[1, np.sqrt(1 / 3)], nodes='state_input')) p.set_val('traj.burn2.states:accel', value=burn2.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('traj.burn2.states:deltav', value=burn2.interpolate(ys=[0.1, 0.2], nodes='state_input')) p.set_val('traj.burn2.controls:u1', value=burn2.interpolate(ys=[1, 1], nodes='control_input')) p.run_driver() assert_near_equal(p.get_val('traj.burn2.timeseries.states:deltav')[-1], 0.3995, tolerance=2.0E-3) # test ODE output wildcard matching in solve_ivp exp_out = traj.simulate() for prob in (p, exp_out): # check timeseries: pos_x = r * cos(theta) and pos_y = r * sin(theta) for phs in ['burn1', 'coast', 'burn2']: x = np.array(prob.get_val('traj.{0}.timeseries.pos_x'.format(phs))).flatten() y = np.array(prob.get_val('traj.{0}.timeseries.pos_y'.format(phs))).flatten() t = np.array(prob.get_val('traj.{0}.timeseries.states:theta'.format(phs))).flatten() r = np.array(prob.get_val('traj.{0}.timeseries.states:r'.format(phs))).flatten() xerr = x - r * np.cos(t) yerr = y - r * np.sin(t) assert_near_equal(np.sqrt(np.mean(xerr*xerr)), 0.0) assert_near_equal(np.sqrt(np.mean(yerr*yerr)), 0.0)
def test_distributed_driver_debug_print_options(self): # check that pyoptsparse is installed. if it is, try to use SLSQP. OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP') if OPTIMIZER: from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver else: raise unittest.SkipTest("pyOptSparseDriver is required.") class Mygroup(Group): def setup(self): self.add_subsystem('indep_var_comp', IndepVarComp('x'), promotes=['*']) self.add_subsystem('Cy', ExecComp('y=2*x'), promotes=['*']) self.add_subsystem('Cc', ExecComp('c=x+2'), promotes=['*']) self.add_design_var('x') self.add_constraint('c', lower=-3.) prob = Problem() prob.model.add_subsystem('par', ParallelGroup()) prob.model.par.add_subsystem('G1', Mygroup()) prob.model.par.add_subsystem('G2', Mygroup()) prob.model.add_subsystem('Obj', ExecComp('obj=y1+y2')) prob.model.connect('par.G1.y', 'Obj.y1') prob.model.connect('par.G2.y', 'Obj.y2') prob.model.add_objective('Obj.obj') prob.driver = pyOptSparseDriver() prob.driver.options['optimizer'] = 'SLSQP' prob.driver.options['print_results'] = False prob.driver.options['debug_print'] = [ 'desvars', 'ln_cons', 'nl_cons', 'objs' ] prob.setup() stdout = sys.stdout strout = StringIO() sys.stdout = strout sys.stdout = strout try: prob.run_driver() finally: sys.stdout = stdout output = strout.getvalue().split('\n') if MPI.COMM_WORLD.rank == 0: # Just make sure we have more than one. Not sure we will always have the same number # of iterations self.assertTrue( output.count("Design Vars") > 1, "Should be more than one design vars header printed") self.assertTrue( output.count("Nonlinear constraints") > 1, "Should be more than one nonlinear constraint header printed") self.assertTrue( output.count("Linear constraints") > 1, "Should be more than one linear constraint header printed") self.assertTrue( output.count("Objectives") > 1, "Should be more than one objective header printed") self.assertTrue( len([s for s in output if 'par.G1.indep_var_comp.x' in s]) > 1, "Should be more than one par.G1.indep_var_comp.x printed") self.assertTrue( len([s for s in output if 'par.G2.indep_var_comp.x' in s]) > 1, "Should be more than one par.G2.indep_var_comp.x printed") self.assertTrue( len([s for s in output if 'par.G1.Cc.c' in s]) > 1, "Should be more than one par.G1.Cc.c printed") self.assertTrue( len([s for s in output if 'par.G2.Cc.c' in s]) > 1, "Should be more than one par.G2.Cc.c printed") self.assertTrue( len([s for s in output if s.startswith('None')]) > 1, "Should be more than one None printed") self.assertTrue( len([s for s in output if 'Obj.obj' in s]) > 1, "Should be more than one Obj.obj printed") else: self.assertEqual(output, [''])
def test_balanced_field_length_for_docs(self): import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.general_utils import set_pyoptsparse_opt import dymos as dm from dymos.examples.balanced_field.balanced_field_ode import BalancedFieldODEComp p = om.Problem() _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=True) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() # Use IPOPT if available, with fallback to SLSQP p.driver.options['optimizer'] = optimizer p.driver.options['print_results'] = False if optimizer == 'IPOPT': p.driver.opt_settings['print_level'] = 5 p.driver.opt_settings['derivative_test'] = 'first-order' # First Phase: Brake release to V1 - both engines operable br_to_v1 = dm.Phase(ode_class=BalancedFieldODEComp, transcription=dm.Radau(num_segments=3), ode_init_kwargs={'mode': 'runway'}) br_to_v1.set_time_options(fix_initial=True, duration_bounds=(1, 1000), duration_ref=10.0) br_to_v1.add_state('r', fix_initial=True, lower=0, ref=1000.0, defect_ref=1000.0) br_to_v1.add_state('v', fix_initial=True, lower=0, ref=100.0, defect_ref=100.0) br_to_v1.add_parameter('alpha', val=0.0, opt=False, units='deg') br_to_v1.add_timeseries_output('*') # Second Phase: Rejected takeoff at V1 - no engines operable rto = dm.Phase(ode_class=BalancedFieldODEComp, transcription=dm.Radau(num_segments=3), ode_init_kwargs={'mode': 'runway'}) rto.set_time_options(fix_initial=False, duration_bounds=(1, 1000), duration_ref=1.0) rto.add_state('r', fix_initial=False, lower=0, ref=1000.0, defect_ref=1000.0) rto.add_state('v', fix_initial=False, lower=0, ref=100.0, defect_ref=100.0) rto.add_parameter('alpha', val=0.0, opt=False, units='deg') rto.add_timeseries_output('*') # Third Phase: V1 to Vr - single engine operable v1_to_vr = dm.Phase(ode_class=BalancedFieldODEComp, transcription=dm.Radau(num_segments=3), ode_init_kwargs={'mode': 'runway'}) v1_to_vr.set_time_options(fix_initial=False, duration_bounds=(1, 1000), duration_ref=1.0) v1_to_vr.add_state('r', fix_initial=False, lower=0, ref=1000.0, defect_ref=1000.0) v1_to_vr.add_state('v', fix_initial=False, lower=0, ref=100.0, defect_ref=100.0) v1_to_vr.add_parameter('alpha', val=0.0, opt=False, units='deg') v1_to_vr.add_timeseries_output('*') # Fourth Phase: Rotate - single engine operable rotate = dm.Phase(ode_class=BalancedFieldODEComp, transcription=dm.Radau(num_segments=3), ode_init_kwargs={'mode': 'runway'}) rotate.set_time_options(fix_initial=False, duration_bounds=(1.0, 5), duration_ref=1.0) rotate.add_state('r', fix_initial=False, lower=0, ref=1000.0, defect_ref=1000.0) rotate.add_state('v', fix_initial=False, lower=0, ref=100.0, defect_ref=100.0) rotate.add_polynomial_control('alpha', order=1, opt=True, units='deg', lower=0, upper=10, ref=10, val=[0, 10]) rotate.add_timeseries_output('*') # Fifth Phase: Climb to target speed and altitude at end of runway. climb = dm.Phase(ode_class=BalancedFieldODEComp, transcription=dm.Radau(num_segments=5), ode_init_kwargs={'mode': 'climb'}) climb.set_time_options(fix_initial=False, duration_bounds=(1, 100), duration_ref=1.0) climb.add_state('r', fix_initial=False, lower=0, ref=1000.0, defect_ref=1000.0) climb.add_state('h', fix_initial=True, lower=0, ref=1.0, defect_ref=1.0) climb.add_state('v', fix_initial=False, lower=0, ref=100.0, defect_ref=100.0) climb.add_state('gam', fix_initial=True, lower=0, ref=0.05, defect_ref=0.05) climb.add_control('alpha', opt=True, units='deg', lower=-10, upper=15, ref=10) climb.add_timeseries_output('*') # Instantiate the trajectory and add phases traj = dm.Trajectory() p.model.add_subsystem('traj', traj) traj.add_phase('br_to_v1', br_to_v1) traj.add_phase('rto', rto) traj.add_phase('v1_to_vr', v1_to_vr) traj.add_phase('rotate', rotate) traj.add_phase('climb', climb) # Add parameters common to multiple phases to the trajectory traj.add_parameter('m', val=174200., opt=False, units='lbm', desc='aircraft mass', targets={ 'br_to_v1': ['m'], 'v1_to_vr': ['m'], 'rto': ['m'], 'rotate': ['m'], 'climb': ['m'] }) traj.add_parameter('T_nominal', val=27000 * 2, opt=False, units='lbf', dynamic=False, desc='nominal aircraft thrust', targets={'br_to_v1': ['T']}) traj.add_parameter('T_engine_out', val=27000, opt=False, units='lbf', dynamic=False, desc='thrust under a single engine', targets={ 'v1_to_vr': ['T'], 'rotate': ['T'], 'climb': ['T'] }) traj.add_parameter( 'T_shutdown', val=0.0, opt=False, units='lbf', dynamic=False, desc='thrust when engines are shut down for rejected takeoff', targets={'rto': ['T']}) traj.add_parameter('mu_r_nominal', val=0.03, opt=False, units=None, dynamic=False, desc='nominal runway friction coefficient', targets={ 'br_to_v1': ['mu_r'], 'v1_to_vr': ['mu_r'], 'rotate': ['mu_r'] }) traj.add_parameter('mu_r_braking', val=0.3, opt=False, units=None, dynamic=False, desc='runway friction coefficient under braking', targets={'rto': ['mu_r']}) traj.add_parameter('h_runway', val=0., opt=False, units='ft', desc='runway altitude', targets={ 'br_to_v1': ['h'], 'v1_to_vr': ['h'], 'rto': ['h'], 'rotate': ['h'] }) traj.add_parameter('rho', val=1.225, opt=False, units='kg/m**3', dynamic=False, desc='atmospheric density', targets={ 'br_to_v1': ['rho'], 'v1_to_vr': ['rho'], 'rto': ['rho'], 'rotate': ['rho'] }) traj.add_parameter('S', val=124.7, opt=False, units='m**2', dynamic=False, desc='aerodynamic reference area', targets={ 'br_to_v1': ['S'], 'v1_to_vr': ['S'], 'rto': ['S'], 'rotate': ['S'], 'climb': ['S'] }) traj.add_parameter( 'CD0', val=0.03, opt=False, units=None, dynamic=False, desc='zero-lift drag coefficient', targets={ f'{phase}': ['CD0'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb'] }) traj.add_parameter( 'AR', val=9.45, opt=False, units=None, dynamic=False, desc='wing aspect ratio', targets={ f'{phase}': ['AR'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb'] }) traj.add_parameter( 'e', val=801, opt=False, units=None, dynamic=False, desc='Oswald span efficiency factor', targets={ f'{phase}': ['e'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb'] }) traj.add_parameter( 'span', val=35.7, opt=False, units='m', dynamic=False, desc='wingspan', targets={ f'{phase}': ['span'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb'] }) traj.add_parameter( 'h_w', val=1.0, opt=False, units='m', dynamic=False, desc='height of wing above CG', targets={ f'{phase}': ['h_w'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb'] }) traj.add_parameter( 'CL0', val=0.5, opt=False, units=None, dynamic=False, desc='zero-alpha lift coefficient', targets={ f'{phase}': ['CL0'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb'] }) traj.add_parameter( 'CL_max', val=2.0, opt=False, units=None, dynamic=False, desc='maximum lift coefficient for linear fit', targets={ f'{phase}': ['CL_max'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb'] }) traj.add_parameter( 'alpha_max', val=10.0, opt=False, units='deg', dynamic=False, desc='angle of attack at maximum lift', targets={ f'{phase}': ['alpha_max'] for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate' 'climb'] }) # Standard "end of first phase to beginning of second phase" linkages # Alpha changes from being a parameter in v1_to_vr to a polynomial control # in rotate, to a dynamic control in `climb`. traj.link_phases(['br_to_v1', 'v1_to_vr'], vars=['time', 'r', 'v']) traj.link_phases(['v1_to_vr', 'rotate'], vars=['time', 'r', 'v', 'alpha']) traj.link_phases(['rotate', 'climb'], vars=['time', 'r', 'v', 'alpha']) traj.link_phases(['br_to_v1', 'rto'], vars=['time', 'r', 'v']) # Less common "final value of r must be the match at ends of two phases". traj.add_linkage_constraint(phase_a='rto', var_a='r', loc_a='final', phase_b='climb', var_b='r', loc_b='final', ref=1000) # Define the constraints and objective for the optimal control problem v1_to_vr.add_boundary_constraint('v_over_v_stall', loc='final', lower=1.2, ref=100) rto.add_boundary_constraint('v', loc='final', equals=0., ref=100, linear=True) rotate.add_boundary_constraint('F_r', loc='final', equals=0, ref=100000) climb.add_boundary_constraint('h', loc='final', equals=35, ref=35, units='ft', linear=True) climb.add_boundary_constraint('gam', loc='final', equals=5, ref=5, units='deg', linear=True) climb.add_path_constraint('gam', lower=0, upper=5, ref=5, units='deg') climb.add_boundary_constraint('v_over_v_stall', loc='final', lower=1.25, ref=1.25) rto.add_objective('r', loc='final', ref=1000.0) # # Setup the problem and set the initial guess # p.setup(check=True) p.set_val('traj.br_to_v1.t_initial', 0) p.set_val('traj.br_to_v1.t_duration', 35) p.set_val('traj.br_to_v1.states:r', br_to_v1.interpolate(ys=[0, 2500.0], nodes='state_input')) p.set_val('traj.br_to_v1.states:v', br_to_v1.interpolate(ys=[0, 100.0], nodes='state_input')) p.set_val('traj.br_to_v1.parameters:alpha', 0, units='deg') p.set_val('traj.v1_to_vr.t_initial', 35) p.set_val('traj.v1_to_vr.t_duration', 35) p.set_val('traj.v1_to_vr.states:r', v1_to_vr.interpolate(ys=[2500, 300.0], nodes='state_input')) p.set_val('traj.v1_to_vr.states:v', v1_to_vr.interpolate(ys=[100, 110.0], nodes='state_input')) p.set_val('traj.v1_to_vr.parameters:alpha', 0.0, units='deg') p.set_val('traj.rto.t_initial', 35) p.set_val('traj.rto.t_duration', 35) p.set_val('traj.rto.states:r', rto.interpolate(ys=[2500, 5000.0], nodes='state_input')) p.set_val('traj.rto.states:v', rto.interpolate(ys=[110, 0], nodes='state_input')) p.set_val('traj.rto.parameters:alpha', 0.0, units='deg') p.set_val('traj.rotate.t_initial', 70) p.set_val('traj.rotate.t_duration', 5) p.set_val('traj.rotate.states:r', rotate.interpolate(ys=[1750, 1800.0], nodes='state_input')) p.set_val('traj.rotate.states:v', rotate.interpolate(ys=[80, 85.0], nodes='state_input')) p.set_val('traj.rotate.polynomial_controls:alpha', 0.0, units='deg') p.set_val('traj.climb.t_initial', 75) p.set_val('traj.climb.t_duration', 15) p.set_val('traj.climb.states:r', climb.interpolate(ys=[5000, 5500.0], nodes='state_input'), units='ft') p.set_val('traj.climb.states:v', climb.interpolate(ys=[160, 170.0], nodes='state_input'), units='kn') p.set_val('traj.climb.states:h', climb.interpolate(ys=[0, 35.0], nodes='state_input'), units='ft') p.set_val('traj.climb.states:gam', climb.interpolate(ys=[0, 5.0], nodes='state_input'), units='deg') p.set_val('traj.climb.controls:alpha', 5.0, units='deg') dm.run_problem(p, run_driver=True, simulate=True) sim_case = om.CaseReader('dymos_solution.db').get_case('final') fig, axes = plt.subplots(2, 1, sharex=True, gridspec_kw={'top': 0.92}) for phase in ['br_to_v1', 'rto', 'v1_to_vr', 'rotate', 'climb']: r = sim_case.get_val(f'traj.{phase}.timeseries.states:r', units='ft') v = sim_case.get_val(f'traj.{phase}.timeseries.states:v', units='kn') t = sim_case.get_val(f'traj.{phase}.timeseries.time', units='s') axes[0].plot(t, r, '-', label=phase) axes[1].plot(t, v, '-', label=phase) fig.suptitle('Balanced Field Length') axes[1].set_xlabel('time (s)') axes[0].set_ylabel('range (ft)') axes[1].set_ylabel('airspeed (kts)') axes[0].grid(True) axes[1].grid(True) tv1 = sim_case.get_val('traj.br_to_v1.timeseries.time', units='s')[-1, 0] v1 = sim_case.get_val('traj.br_to_v1.timeseries.states:v', units='kn')[-1, 0] tf_rto = sim_case.get_val('traj.rto.timeseries.time', units='s')[-1, 0] rf_rto = sim_case.get_val('traj.rto.timeseries.states:r', units='ft')[-1, 0] axes[0].annotate(f'field length = {r[-1, 0]:5.1f} ft', xy=(t[-1, 0], r[-1, 0]), xycoords='data', xytext=(0.7, 0.5), textcoords='axes fraction', arrowprops=dict(arrowstyle='->'), horizontalalignment='center', verticalalignment='top') axes[0].annotate(f'', xy=(tf_rto, rf_rto), xycoords='data', xytext=(0.7, 0.5), textcoords='axes fraction', arrowprops=dict(arrowstyle='->'), horizontalalignment='center', verticalalignment='top') axes[1].annotate(f'$v1$ = {v1:5.1f} kts', xy=(tv1, v1), xycoords='data', xytext=(0.5, 0.5), textcoords='axes fraction', arrowprops=dict(arrowstyle='->'), horizontalalignment='center', verticalalignment='top') plt.legend() plt.show()
import os import unittest from numpy.testing import assert_almost_equal import openmdao.api as om import dymos as dm from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE from openmdao.utils.general_utils import set_pyoptsparse_opt from openmdao.utils.testing_utils import use_tempdirs OPT, OPTIMIZER = set_pyoptsparse_opt('SNOPT', fallback=True) @use_tempdirs class TestBrachistochroneRefineGrid(unittest.TestCase): def make_problem(self, transcription='radau-ps', num_segments=5, transcription_order=3, compressed=True): self.p = p = om.Problem(model=om.Group()) p.driver = om.ScipyOptimizeDriver() p.driver.declare_coloring() if transcription == 'gauss-lobatto': t = dm.GaussLobatto(num_segments=num_segments, order=transcription_order, compressed=compressed)
def ex_aircraft_steady_flight(optimizer='SLSQP', solve_segments=False, use_boundary_constraints=False, compressed=False): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() _, optimizer = set_pyoptsparse_opt(optimizer, fallback=False) p.driver.options['optimizer'] = optimizer p.driver.declare_coloring() if optimizer == 'SNOPT': p.driver.opt_settings['Major iterations limit'] = 20 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 if optimizer == 'SLSQP': p.driver.opt_settings['MAXIT'] = 50 num_seg = 15 seg_ends, _ = lgl(num_seg + 1) phase = dm.Phase(ode_class=AircraftODE, transcription=dm.Radau(num_segments=num_seg, segment_ends=seg_ends, order=3, compressed=compressed, solve_segments=solve_segments)) # 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') p.model.add_subsystem('phase0', phase) phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(300, 10000), duration_ref=5600) fix_final = True if use_boundary_constraints: fix_final = False phase.add_boundary_constraint('mass_fuel', loc='final', units='lbm', equals=1e-3, linear=False) phase.add_boundary_constraint('alt', loc='final', units='kft', equals=10.0, linear=False) 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', targets=['mass_comp.mass_fuel'], fix_initial=True, fix_final=fix_final, upper=1.5E5, lower=0.0, ref=1e2, defect_ref=1e2) phase.add_state('alt', units='kft', rate_source='climb_rate', targets=['atmos.h', 'aero.alt', 'propulsion.alt'], fix_initial=True, fix_final=fix_final, 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_input_parameter( 'S', targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'], units='m**2') phase.add_input_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg') phase.add_input_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', '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.0e-4) p.setup() p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 3600.0 p['phase0.states:range'][:] = phase.interpolate(ys=(0, 724.0), nodes='state_input') p['phase0.states:mass_fuel'][:] = phase.interpolate(ys=(30000, 1e-3), nodes='state_input') p['phase0.states:alt'][:] = 10.0 p['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) return p
def test_two_burn_orbit_raise_for_docs(self): import numpy as np import matplotlib.pyplot as plt from openmdao.api import Problem, pyOptSparseDriver, DirectSolver, SqliteRecorder from openmdao.utils.assert_utils import assert_rel_error from openmdao.utils.general_utils import set_pyoptsparse_opt from dymos import Phase, Trajectory from dymos.examples.finite_burn_orbit_raise.finite_burn_eom import FiniteBurnODE traj = Trajectory() p = Problem(model=traj) p.driver = pyOptSparseDriver() _, optimizer = set_pyoptsparse_opt('SNOPT', fallback=False) p.driver.options['optimizer'] = 'SNOPT' p.driver.options['dynamic_simul_derivs'] = True traj.add_design_parameter('c', opt=False, val=1.5) # First Phase (burn) burn1 = Phase('gauss-lobatto', ode_class=FiniteBurnODE, num_segments=10, transcription_order=3, compressed=True) burn1 = traj.add_phase('burn1', burn1) burn1.set_time_options(fix_initial=True, duration_bounds=(.5, 10)) burn1.set_state_options('r', fix_initial=True, fix_final=False, defect_scaler=100.0) burn1.set_state_options('theta', fix_initial=True, fix_final=False, defect_scaler=100.0) burn1.set_state_options('vr', fix_initial=True, fix_final=False, defect_scaler=100.0) burn1.set_state_options('vt', fix_initial=True, fix_final=False, defect_scaler=100.0) burn1.set_state_options('accel', fix_initial=True, fix_final=False) burn1.set_state_options('deltav', fix_initial=True, fix_final=False) burn1.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg', scaler=0.01, rate_continuity_scaler=0.001, rate2_continuity_scaler=0.001, lower=-30, upper=30) # Second Phase (Coast) coast = Phase('gauss-lobatto', ode_class=FiniteBurnODE, num_segments=10, transcription_order=3, compressed=True) traj.add_phase('coast', coast) coast.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), duration_ref=10) coast.set_state_options('r', fix_initial=False, fix_final=False, defect_scaler=100.0) coast.set_state_options('theta', fix_initial=False, fix_final=False, defect_scaler=100.0) coast.set_state_options('vr', fix_initial=False, fix_final=False, defect_scaler=100.0) coast.set_state_options('vt', fix_initial=False, fix_final=False, defect_scaler=100.0) coast.set_state_options('accel', fix_initial=True, fix_final=True) coast.set_state_options('deltav', fix_initial=False, fix_final=False) coast.add_control('u1', opt=False, val=0.0, units='deg') # Third Phase (burn) burn2 = Phase('gauss-lobatto', ode_class=FiniteBurnODE, num_segments=10, transcription_order=3, compressed=True) traj.add_phase('burn2', burn2) burn2.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), initial_ref=10) burn2.set_state_options('r', fix_initial=False, fix_final=True, defect_scaler=100.0) burn2.set_state_options('theta', fix_initial=False, fix_final=False, defect_scaler=100.0) burn2.set_state_options('vr', fix_initial=False, fix_final=True, defect_scaler=100.0) burn2.set_state_options('vt', fix_initial=False, fix_final=True, defect_scaler=100.0) burn2.set_state_options('accel', fix_initial=False, fix_final=False, defect_scaler=1.0) burn2.set_state_options('deltav', fix_initial=False, fix_final=False, defect_scaler=1.0) burn2.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg', scaler=0.01, rate_continuity_scaler=0.001, rate2_continuity_scaler=0.001, lower=-30, upper=30) burn2.add_objective('deltav', loc='final', scaler=1.0) # Link Phases traj.link_phases(phases=['burn1', 'coast', 'burn2'], vars=['time', 'r', 'theta', 'vr', 'vt', 'deltav']) traj.link_phases(phases=['burn1', 'burn2'], vars=['accel']) # Finish Problem Setup p.model.options['assembled_jac_type'] = 'csc' p.model.linear_solver = DirectSolver(assemble_jac=True) p.driver.add_recorder( SqliteRecorder('two_burn_orbit_raise_example_for_docs.db')) p.setup(check=True) # Set Initial Guesses p.set_val('design_parameters:c', value=1.5) p.set_val('burn1.t_initial', value=0.0) p.set_val('burn1.t_duration', value=2.25) p.set_val('burn1.states:r', value=burn1.interpolate(ys=[1, 1.5], nodes='state_input')) p.set_val('burn1.states:theta', value=burn1.interpolate(ys=[0, 1.7], nodes='state_input')) p.set_val('burn1.states:vr', value=burn1.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('burn1.states:vt', value=burn1.interpolate(ys=[1, 1], nodes='state_input')) p.set_val('burn1.states:accel', value=burn1.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val( 'burn1.states:deltav', value=burn1.interpolate(ys=[0, 0.1], nodes='state_input'), ) p.set_val('burn1.controls:u1', value=burn1.interpolate(ys=[-3.5, 13.0], nodes='control_input')) p.set_val('coast.t_initial', value=2.25) p.set_val('coast.t_duration', value=3.0) p.set_val('coast.states:r', value=coast.interpolate(ys=[1.3, 1.5], nodes='state_input')) p.set_val('coast.states:theta', value=coast.interpolate(ys=[2.1767, 1.7], nodes='state_input')) p.set_val('coast.states:vr', value=coast.interpolate(ys=[0.3285, 0], nodes='state_input')) p.set_val('coast.states:vt', value=coast.interpolate(ys=[0.97, 1], nodes='state_input')) p.set_val('coast.states:accel', value=coast.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('coast.controls:u1', value=coast.interpolate(ys=[0, 0], nodes='control_input')) p.set_val('burn2.t_initial', value=5.25) p.set_val('burn2.t_duration', value=1.75) p.set_val('burn2.states:r', value=burn2.interpolate(ys=[1, 3], nodes='state_input')) p.set_val('burn2.states:theta', value=burn2.interpolate(ys=[0, 4.0], nodes='state_input')) p.set_val('burn2.states:vr', value=burn2.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('burn2.states:vt', value=burn2.interpolate(ys=[1, np.sqrt(1 / 3)], nodes='state_input')) p.set_val('burn2.states:accel', value=burn2.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('burn2.states:deltav', value=burn2.interpolate(ys=[0.1, 0.2], nodes='state_input')) p.set_val('burn2.controls:u1', value=burn2.interpolate(ys=[1, 1], nodes='control_input')) p.run_driver() assert_rel_error(self, traj.get_values('deltav', flat=True)[-1], 0.3995, tolerance=2.0E-3) # Plot results exp_out = traj.simulate(times=50, num_procs=3) fig = plt.figure(figsize=(8, 4)) fig.suptitle('Two Burn Orbit Raise Solution') ax_u1 = plt.subplot2grid((2, 2), (0, 0)) ax_deltav = plt.subplot2grid((2, 2), (1, 0)) ax_xy = plt.subplot2grid((2, 2), (0, 1), rowspan=2) span = np.linspace(0, 2 * np.pi, 100) ax_xy.plot(np.cos(span), np.sin(span), 'k--', lw=1) ax_xy.plot(3 * np.cos(span), 3 * np.sin(span), 'k--', lw=1) ax_xy.set_xlim(-4.5, 4.5) ax_xy.set_ylim(-4.5, 4.5) ax_xy.set_xlabel('x ($R_e$)') ax_xy.set_ylabel('y ($R_e$)') ax_u1.set_xlabel('time ($TU$)') ax_u1.set_ylabel('$u_1$ ($deg$)') ax_u1.grid(True) ax_deltav.set_xlabel('time ($TU$)') ax_deltav.set_ylabel('${\Delta}v$ ($DU/TU$)') ax_deltav.grid(True) t_sol = traj.get_values('time') x_sol = traj.get_values('pos_x') y_sol = traj.get_values('pos_y') dv_sol = traj.get_values('deltav') u1_sol = traj.get_values('u1', units='deg') t_exp = exp_out.get_values('time') x_exp = exp_out.get_values('pos_x') y_exp = exp_out.get_values('pos_y') dv_exp = exp_out.get_values('deltav') u1_exp = exp_out.get_values('u1', units='deg') for phase_name in ['burn1', 'coast', 'burn2']: ax_u1.plot(t_sol[phase_name], u1_sol[phase_name], 'ro', ms=3) ax_u1.plot(t_exp[phase_name], u1_exp[phase_name], 'b-') ax_deltav.plot(t_sol[phase_name], dv_sol[phase_name], 'ro', ms=3) ax_deltav.plot(t_exp[phase_name], dv_exp[phase_name], 'b-') ax_xy.plot(x_sol[phase_name], y_sol[phase_name], 'ro', ms=3, label='implicit' if phase_name == 'burn1' else None) ax_xy.plot(x_exp[phase_name], y_exp[phase_name], 'b-', label='explicit' if phase_name == 'burn1' else None) plt.show()
def test_two_burn_orbit_raise_gl_rk_gl_constrained(self): import numpy as np import matplotlib.pyplot as plt from openmdao.api import Problem, Group, pyOptSparseDriver, DirectSolver from openmdao.utils.assert_utils import assert_rel_error from openmdao.utils.general_utils import set_pyoptsparse_opt from dymos import Phase, GaussLobatto, RungeKutta, Trajectory from dymos.examples.finite_burn_orbit_raise.finite_burn_eom import FiniteBurnODE traj = Trajectory() p = Problem(model=Group()) p.model.add_subsystem('traj', traj) p.driver = pyOptSparseDriver() _, optimizer = set_pyoptsparse_opt('SNOPT', fallback=True) p.driver.options['optimizer'] = optimizer p.driver.options['dynamic_simul_derivs'] = True traj.add_design_parameter('c', opt=False, val=1.5, units='DU/TU') # First Phase (burn) burn1 = Phase(ode_class=FiniteBurnODE, transcription=GaussLobatto(num_segments=10, order=3, compressed=True)) burn1 = traj.add_phase('burn1', burn1) burn1.set_time_options(fix_initial=True, duration_bounds=(.5, 10)) burn1.set_state_options('r', fix_initial=True, fix_final=False) burn1.set_state_options('theta', fix_initial=True, fix_final=False) burn1.set_state_options('vr', fix_initial=True, fix_final=False) burn1.set_state_options('vt', fix_initial=True, fix_final=False) burn1.set_state_options('accel', fix_initial=True, fix_final=False) burn1.set_state_options('deltav', fix_initial=True, fix_final=False) burn1.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg', scaler=0.01, lower=-30, upper=30) # Second Phase (Coast) coast = Phase(ode_class=FiniteBurnODE, transcription=RungeKutta(num_segments=20, compressed=True)) traj.add_phase('coast', coast) coast.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), duration_ref=10) coast.set_state_options('r', fix_initial=False, fix_final=False) coast.set_state_options('theta', fix_initial=False, fix_final=False) coast.set_state_options('vr', fix_initial=False, fix_final=False) coast.set_state_options('vt', fix_initial=False, fix_final=False) coast.set_state_options('accel', fix_initial=True, fix_final=False) coast.set_state_options('deltav', fix_initial=False, fix_final=False) coast.add_design_parameter('u1', opt=False, val=0.0) # Third Phase (burn) burn2 = Phase(ode_class=FiniteBurnODE, transcription=GaussLobatto(num_segments=10, order=3, compressed=True)) traj.add_phase('burn2', burn2) burn2.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), initial_ref=10) burn2.set_state_options('r', fix_initial=False, fix_final=True) burn2.set_state_options('theta', fix_initial=False, fix_final=False) burn2.set_state_options('vr', fix_initial=False, fix_final=True) burn2.set_state_options('vt', fix_initial=False, fix_final=True) burn2.set_state_options('accel', fix_initial=False, fix_final=False, defect_scaler=1.0) burn2.set_state_options('deltav', fix_initial=False, fix_final=False, defect_scaler=1.0) burn2.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg', scaler=0.01, lower=-30, upper=30) burn2.add_objective('deltav', loc='final', scaler=1.0) burn1.add_timeseries_output('pos_x', units='DU') coast.add_timeseries_output('pos_x', units='DU') burn2.add_timeseries_output('pos_x', units='DU') burn1.add_timeseries_output('pos_y', units='DU') coast.add_timeseries_output('pos_y', units='DU') burn2.add_timeseries_output('pos_y', units='DU') # Link Phases traj.link_phases(phases=['burn1', 'coast', 'burn2'], vars=['time', 'r', 'theta', 'vr', 'vt', 'deltav']) traj.link_phases(phases=['burn1', 'burn2'], vars=['accel']) # Finish Problem Setup p.model.linear_solver = DirectSolver() p.setup(check=True, force_alloc_complex=True) # Set Initial Guesses p.set_val('traj.design_parameters:c', value=1.5) p.set_val('traj.burn1.t_initial', value=0.0) p.set_val('traj.burn1.t_duration', value=2.25) p.set_val('traj.burn1.states:r', value=burn1.interpolate(ys=[1, 1.5], nodes='state_input')) p.set_val('traj.burn1.states:theta', value=burn1.interpolate(ys=[0, 1.7], nodes='state_input')) p.set_val('traj.burn1.states:vr', value=burn1.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('traj.burn1.states:vt', value=burn1.interpolate(ys=[1, 1], nodes='state_input')) p.set_val('traj.burn1.states:accel', value=burn1.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('traj.burn1.states:deltav', value=burn1.interpolate(ys=[0, 0.1], nodes='state_input'), ) p.set_val('traj.burn1.controls:u1', value=burn1.interpolate(ys=[-3.5, 13.0], nodes='control_input')) p.set_val('traj.coast.t_initial', value=2.25) p.set_val('traj.coast.t_duration', value=3.0) p.set_val('traj.coast.states:r', value=coast.interpolate(ys=[1.3, 1.5], nodes='state_input')) p.set_val('traj.coast.states:theta', value=coast.interpolate(ys=[2.1767, 1.7], nodes='state_input')) p.set_val('traj.coast.states:vr', value=coast.interpolate(ys=[0.3285, 0], nodes='state_input')) p.set_val('traj.coast.states:vt', value=coast.interpolate(ys=[0.97, 1], nodes='state_input')) p.set_val('traj.coast.states:accel', value=coast.interpolate(ys=[0, 0], nodes='state_input')) # p.set_val('traj.coast.controls:u1', # value=coast.interpolate(ys=[0, 0], nodes='control_input')) p.set_val('traj.burn2.t_initial', value=5.25) p.set_val('traj.burn2.t_duration', value=1.75) p.set_val('traj.burn2.states:r', value=burn2.interpolate(ys=[1.8, 3], nodes='state_input')) p.set_val('traj.burn2.states:theta', value=burn2.interpolate(ys=[3.2, 4.0], nodes='state_input')) p.set_val('traj.burn2.states:vr', value=burn2.interpolate(ys=[.5, 0], nodes='state_input')) p.set_val('traj.burn2.states:vt', value=burn2.interpolate(ys=[1, np.sqrt(1 / 3)], nodes='state_input')) p.set_val('traj.burn2.states:accel', value=burn2.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('traj.burn2.states:deltav', value=burn2.interpolate(ys=[0.1, 0.2], nodes='state_input')) p.set_val('traj.burn2.controls:u1', value=burn2.interpolate(ys=[1, 1], nodes='control_input')) p.run_driver() assert_rel_error(self, p.get_val('traj.burn2.timeseries.states:deltav')[-1], 0.3995, tolerance=2.0E-3) # Plot results exp_out = traj.simulate() fig = plt.figure(figsize=(8, 4)) fig.suptitle('Two Burn Orbit Raise Solution') ax_u1 = plt.subplot2grid((2, 2), (0, 0)) ax_deltav = plt.subplot2grid((2, 2), (1, 0)) ax_xy = plt.subplot2grid((2, 2), (0, 1), rowspan=2) span = np.linspace(0, 2 * np.pi, 100) ax_xy.plot(np.cos(span), np.sin(span), 'k--', lw=1) ax_xy.plot(3 * np.cos(span), 3 * np.sin(span), 'k--', lw=1) ax_xy.set_xlim(-4.5, 4.5) ax_xy.set_ylim(-4.5, 4.5) ax_xy.set_xlabel('x ($R_e$)') ax_xy.set_ylabel('y ($R_e$)') ax_u1.set_xlabel('time ($TU$)') ax_u1.set_ylabel('$u_1$ ($deg$)') ax_u1.grid(True) ax_deltav.set_xlabel('time ($TU$)') ax_deltav.set_ylabel('${\Delta}v$ ($DU/TU$)') ax_deltav.grid(True) t_sol = dict((phs, p.get_val('traj.{0}.timeseries.time'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) x_sol = dict((phs, p.get_val('traj.{0}.timeseries.pos_x'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) y_sol = dict((phs, p.get_val('traj.{0}.timeseries.pos_y'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) dv_sol = dict((phs, p.get_val('traj.{0}.timeseries.states:deltav'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) u1_sol = dict((phs, p.get_val('traj.{0}.timeseries.controls:u1'.format(phs), units='deg')) for phs in ['burn1', 'burn2']) t_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.time'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) x_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.pos_x'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) y_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.pos_y'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) dv_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.states:deltav'.format(phs))) for phs in ['burn1', 'coast', 'burn2']) u1_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.controls:u1'.format(phs), units='deg')) for phs in ['burn1', 'burn2']) for phs in ['burn1', 'coast', 'burn2']: try: ax_u1.plot(t_sol[phs], u1_sol[phs], 'ro', ms=3) ax_u1.plot(t_exp[phs], u1_exp[phs], 'b-') except KeyError: pass ax_deltav.plot(t_sol[phs], dv_sol[phs], 'ro', ms=3) ax_deltav.plot(t_exp[phs], dv_exp[phs], 'b-') ax_xy.plot(x_sol[phs], y_sol[phs], 'ro', ms=3, label='implicit') ax_xy.plot(x_exp[phs], y_exp[phs], 'b-', label='explicit') plt.show()
from shutil import rmtree from tempfile import mkdtemp import numpy as np from openmdao.utils.general_utils import set_pyoptsparse_opt from openmdao.utils.mpi import MPI if MPI: from openmdao.api import PETScVector vector_class = PETScVector else: PETScVector = None # check that pyoptsparse is installed. if it is, try to use SLSQP. OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP') if OPTIMIZER: from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver from openmdao.api import ExecComp, ExplicitComponent, Problem, \ Group, ParallelGroup, IndepVarComp, SqliteRecorder from openmdao.utils.array_utils import evenly_distrib_idxs from openmdao.recorders.tests.sqlite_recorder_test_utils import assertDriverIterationDataRecorded from openmdao.recorders.tests.recorder_test_utils import run_driver class DistributedAdder(ExplicitComponent): """ Distributes the work of adding 10 to every item in the param vector """
def test_reentry_mixed_controls(self): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() OPT, OPTIMIZER = set_pyoptsparse_opt('IPOPT', fallback=False) p.driver.options['optimizer'] = OPTIMIZER traj = p.model.add_subsystem('traj', Trajectory()) phase0 = traj.add_phase( 'phase0', Phase(ode_class=ShuttleODE, transcription=GaussLobatto(num_segments=20, order=3))) phase0.set_time_options(fix_initial=True, units='s', duration_ref=200) phase0.add_state('h', fix_initial=True, fix_final=True, units='ft', rate_source='hdot', targets=['h'], lower=0, ref0=75000, ref=300000, defect_ref=1000) phase0.add_state('gamma', fix_initial=True, fix_final=True, units='rad', rate_source='gammadot', targets=['gamma'], lower=-89. * np.pi / 180, upper=89. * np.pi / 180) phase0.add_state('phi', fix_initial=True, fix_final=False, units='rad', rate_source='phidot', lower=0, upper=89. * np.pi / 180) phase0.add_state('psi', fix_initial=True, fix_final=False, units='rad', rate_source='psidot', targets=['psi'], lower=0, upper=90. * np.pi / 180) phase0.add_state('theta', fix_initial=True, fix_final=False, units='rad', rate_source='thetadot', targets=['theta'], lower=-89. * np.pi / 180, upper=89. * np.pi / 180) phase0.add_state('v', fix_initial=True, fix_final=True, units='ft/s', rate_source='vdot', targets=['v'], lower=500, ref0=2500, ref=25000) phase0.add_control('alpha', units='rad', opt=True, lower=-np.pi / 2, upper=np.pi / 2) phase0.add_polynomial_control('beta', order=5, units='rad', opt=True, lower=-89 * np.pi / 180, upper=1 * np.pi / 180) phase0.add_objective('theta', loc='final', ref=-0.01) p.setup(check=True, force_alloc_complex=True) p.set_val('traj.phase0.states:h', phase0.interpolate(ys=[260000, 80000], nodes='state_input'), units='ft') p.set_val('traj.phase0.states:gamma', phase0.interpolate(ys=[-1 * np.pi / 180, -5 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:phi', phase0.interpolate(ys=[0, 75 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:psi', phase0.interpolate(ys=[90 * np.pi / 180, 10 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:theta', phase0.interpolate(ys=[0, 25 * np.pi / 180], nodes='state_input'), units='rad') p.set_val('traj.phase0.states:v', phase0.interpolate(ys=[25600, 2500], nodes='state_input'), units='ft/s') p.set_val('traj.phase0.t_initial', 0, units='s') p.set_val('traj.phase0.t_duration', 2000, units='s') p.set_val('traj.phase0.controls:alpha', phase0.interpolate( ys=[17.4 * np.pi / 180, 17.4 * np.pi / 180], nodes='control_input'), units='rad') p.set_val('traj.phase0.polynomial_controls:beta', np.radians(-75)) p.run_driver() exp_out = traj.simulate() from scipy.interpolate import interp1d t_sol = p.get_val('traj.phase0.timeseries.time') beta_sol = p.get_val('traj.phase0.timeseries.polynomial_controls:beta') t_sim = exp_out.get_val('traj.phase0.timeseries.time') beta_sim = exp_out.get_val( 'traj.phase0.timeseries.polynomial_controls:beta') sol_interp = interp1d(t_sol.ravel(), beta_sol.ravel()) sim_interp = interp1d(t_sim.ravel(), beta_sim.ravel()) t = np.linspace(0, t_sol.ravel()[-1], 100) assert_near_equal(sim_interp(t), sol_interp(t), tolerance=1.0E-3)
def test_distributed_driver_debug_print_options(self): # check that pyoptsparse is installed. if it is, try to use SLSQP. OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP') if OPTIMIZER: from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver else: raise unittest.SkipTest("pyOptSparseDriver is required.") class Mygroup(Group): def setup(self): self.add_subsystem('indep_var_comp', IndepVarComp('x'), promotes=['*']) self.add_subsystem('Cy', ExecComp('y=2*x'), promotes=['*']) self.add_subsystem('Cc', ExecComp('c=x+2'), promotes=['*']) self.add_design_var('x') self.add_constraint('c', lower=-3.) prob = Problem() prob.model.add_subsystem('par', ParallelGroup()) prob.model.par.add_subsystem('G1', Mygroup()) prob.model.par.add_subsystem('G2', Mygroup()) prob.model.add_subsystem('Obj', ExecComp('obj=y1+y2')) prob.model.connect('par.G1.y', 'Obj.y1') prob.model.connect('par.G2.y', 'Obj.y2') prob.model.add_objective('Obj.obj') prob.driver = pyOptSparseDriver() prob.driver.options['optimizer'] = 'SLSQP' prob.driver.options['print_results'] = False prob.driver.options['debug_print'] = ['desvars', 'ln_cons', 'nl_cons', 'objs'] prob.setup() stdout = sys.stdout strout = StringIO() sys.stdout = strout sys.stdout = strout try: prob.run_driver() finally: sys.stdout = stdout output = strout.getvalue().split('\n') if MPI.COMM_WORLD.rank == 0: # Just make sure we have more than one. Not sure we will always have the same number # of iterations self.assertTrue(output.count("Design Vars") > 1, "Should be more than one design vars header printed") self.assertTrue(output.count("Nonlinear constraints") > 1, "Should be more than one nonlinear constraint header printed") self.assertTrue(output.count("Linear constraints") > 1, "Should be more than one linear constraint header printed") self.assertTrue(output.count("Objectives") > 1, "Should be more than one objective header printed") self.assertTrue(len([s for s in output if 'par.G1.indep_var_comp.x' in s]) > 1, "Should be more than one par.G1.indep_var_comp.x printed") self.assertTrue(len([s for s in output if 'par.G2.indep_var_comp.x' in s]) > 1, "Should be more than one par.G2.indep_var_comp.x printed") self.assertTrue(len([s for s in output if 'par.G1.Cc.c' in s]) > 1, "Should be more than one par.G1.Cc.c printed") self.assertTrue(len([s for s in output if 'par.G2.Cc.c' in s]) > 1, "Should be more than one par.G2.Cc.c printed") self.assertTrue(len([s for s in output if s.startswith('None')]) > 1, "Should be more than one None printed") self.assertTrue(len([s for s in output if 'Obj.obj' in s]) > 1, "Should be more than one Obj.obj printed") else: self.assertEqual(output, [''])
import unittest import numpy as np from openmdao.api import Problem, Group, IndepVarComp, ExecComp, AnalysisError, ExplicitComponent from openmdao.devtools.testutil import assert_rel_error from openmdao.test_suite.components.paraboloid import Paraboloid from openmdao.test_suite.components.expl_comp_array import TestExplCompArrayDense from openmdao.test_suite.components.sellar import SellarDerivativesGrouped from openmdao.utils.general_utils import set_pyoptsparse_opt # check that pyoptsparse is installed # if it is, try to use SNOPT but fall back to SLSQP OPT, OPTIMIZER = set_pyoptsparse_opt('SNOPT') if OPTIMIZER: from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver class ParaboloidAE(ExplicitComponent): """ Evaluates the equation f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3 This version raises an analysis error 50% of the time. The AE in ParaboloidAE stands for AnalysisError.""" def __init__(self): super(ParaboloidAE, self).__init__() self.fail_hard = False def setup(self):
def test_promotes_parameter(self): for transcription in ['radau-ps', 'gauss-lobatto']: with self.subTest(msg=transcription): optimizer = 'SLSQP' num_segments = 10 transcription_order = 3 compressed = False p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=True) p.driver.options['optimizer'] = OPTIMIZER p.driver.declare_coloring() if transcription == 'gauss-lobatto': t = dm.GaussLobatto(num_segments=num_segments, order=transcription_order, compressed=compressed) elif transcription == 'radau-ps': t = dm.Radau(num_segments=num_segments, order=transcription_order, compressed=compressed) traj = dm.Trajectory() phase = dm.Phase(ode_class=BrachistochroneODE, transcription=t) traj.add_phase('phase0', phase, promotes_inputs=[ 't_initial', 't_duration', 'parameters:g' ]) p.model.add_subsystem('traj', traj) phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10), units='s') phase.add_state('x', fix_initial=True, fix_final=False, solve_segments=False, units='m', rate_source='xdot') phase.add_state('y', fix_initial=True, fix_final=False, solve_segments=False, units='m', rate_source='ydot') phase.add_state('v', fix_initial=True, fix_final=False, solve_segments=False, units='m/s', rate_source='vdot', targets=['v']) phase.add_control('theta', continuity=True, rate_continuity=True, units='deg', lower=0.01, upper=179.9, targets=['theta']) phase.add_parameter('g', units='m/s**2', val=9.80665, targets=['g']) phase.add_boundary_constraint('x', loc='final', equals=10) phase.add_boundary_constraint('y', loc='final', equals=5) # Minimize time at the end of the phase phase.add_objective('time_phase', loc='final', scaler=10) p.model.linear_solver = om.DirectSolver() p.setup(check=True) p.set_val('traj.t_initial', 0.0) p.set_val('traj.t_duration', 2.0) p.set_val('traj.phase0.states:x', phase.interp('x', ys=[0, 10])) p.set_val('traj.phase0.states:y', phase.interp('y', ys=[10, 5])) p.set_val('traj.phase0.states:v', phase.interp('v', ys=[0, 9.9])) p.set_val('traj.phase0.controls:theta', phase.interp('theta', ys=[5, 100])) p.set_val('traj.parameters:g', 9.80665) p.run_driver() assert_near_equal(p['traj.t_duration'], 1.8016, tolerance=1.0E-4)