def test_remote_voi(self): 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() J = prob.compute_totals(of=['Obj.obj', 'par.G1.c', 'par.G2.c'], wrt=['par.G1.x', 'par.G2.x']) assert_rel_error(self, J['Obj.obj', 'par.G1.x'], np.array([[2.0]]), 1e-6) assert_rel_error(self, J['Obj.obj', 'par.G2.x'], np.array([[2.0]]), 1e-6) assert_rel_error(self, J['par.G1.c', 'par.G1.x'], np.array([[1.0]]), 1e-6) assert_rel_error(self, J['par.G1.c', 'par.G2.x'], np.array([[0.0]]), 1e-6) assert_rel_error(self, J['par.G2.c', 'par.G1.x'], np.array([[0.0]]), 1e-6) assert_rel_error(self, J['par.G2.c', 'par.G2.x'], np.array([[1.0]]), 1e-6)
def set_optimizer(self, optStr): assert type(optStr) == type(''), 'Input optimizer must be a string' self.optimizer = optStr.upper() # Reset all design variables and constraints self.design_variables = [] self.constraints = [] self.objective = None # Establish the optimization driver if self.optimizer in ['SOGA','SOPSO','NM','SUBPLEX']: from openmdao.api import HeuristicDriverParallel self.prob.driver = HeuristicDriverParallel() #elif self.optimizer in ['SUBPLEX']: #from openmdao.api import HeuristicDriver #self.prob.driver = HeuristicDriver() elif self.optimizer in ['COBYLA','SLSQP']: self.prob.driver = ScipyOptimizer() elif self.optimizer in ['CONMIN', 'PSQP','SNOPT','NSGA2','ALPSO']: from openmdao.api import pyOptSparseDriver self.prob.driver = pyOptSparseDriver() else: raise ValueError('Unknown or unworking optimizer. '+self.optimizer) # Set default options self.prob.driver.options['optimizer'] = self.optimizer if self.optimizer == 'CONMIN': self.prob.driver.opt_settings['ITMAX'] = 1000 elif self.optimizer in ['PSQP']: self.prob.driver.opt_settings['MIT'] = 1000 elif self.optimizer in ['SOGA','SOPSO','NM','SUBPLEX']: self.prob.driver.options['population'] = 50 self.prob.driver.options['generations'] = 500 elif self.optimizer in ['NSGA2']: self.prob.driver.opt_settings['PopSize'] = 200 self.prob.driver.opt_settings['maxGen'] = 500 elif self.optimizer in ['SNOPT']: self.prob.driver.opt_settings['Iterations limit'] = 500 self.prob.driver.opt_settings['Major optimality tolerance'] = 1e-4 self.prob.driver.opt_settings['Major feasibility tolerance'] = 1e-6 self.prob.driver.opt_settings['Minor feasibility tolerance'] = 1e-6 self.prob.driver.opt_settings['Function precision'] = 1e-8 elif self.optimizer in ['COBYLA','SLSQP']: self.prob.driver.options['tol'] = 1e-6 self.prob.driver.options['maxiter'] = 1000
def benchmark_mppt(self): model = MPPT_MDP() model.add_design_var('pt0.param.CP_Isetpt', lower=0., upper=0.4) model.add_design_var('pt1.param.CP_Isetpt', lower=0., upper=0.4) model.add_objective('perf.result') # create problem and add optimizer prob = Problem(model) prob.driver = pyOptSparseDriver(optimizer='SNOPT') prob.driver.opt_settings = { 'Major optimality tolerance': 1e-3, 'Major feasibility tolerance': 1.0e-5, 'Iterations limit': 500000000, 'New basis file': 10 } prob.setup() prob.run_driver() assert_rel_error(self, prob['perf.result'], -9.4308562238E+03, 1e-6)
# prob = Problem(model) # prob.setup() # prob.run_model() # print(prob['paraboloid.mean_QoI']) # print(prob['paraboloid.mean_xi']) #------------ Run optimization using SNOPT prob = Problem() indeps = prob.model.add_subsystem('indeps', IndepVarComp(), promotes=['*']) indeps.add_output('mean_xi', 10 * np.ones(3)) prob.model.add_subsystem('paraboloid', Paraboloid(), promotes_inputs=['mean_xi']) # Set up the Optimization prob.driver = pyOptSparseDriver() prob.driver.options['optimizer'] = 'SNOPT' prob.driver.opt_settings['Major optimality tolerance'] = 3e-7 prob.driver.opt_settings['Major feasibility tolerance'] = 3e-7 prob.driver.opt_settings['Major iterations limit'] = 1000 prob.driver.opt_settings['Verify level'] = -1 prob.model.add_design_var('mean_xi', lower=-20 * np.ones(3), upper=20 * np.ones(3)) prob.model.add_objective('paraboloid.mean_QoI') prob.setup() prob.run_driver() print(prob['paraboloid.mean_QoI']) print(prob['paraboloid.mean_xi'])
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'] = 4 # 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='forward'))) # # Set the variables # phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(.5, 10)) phase.add_state('x', fix_initial=True) phase.add_state('y', fix_initial=True) phase.add_state('v', fix_initial=True) phase.add_control('theta', continuity=True, rate_continuity=True, units='deg', lower=0.01, upper=179.9) phase.add_parameter('g', units='m/s**2', val=9.80665) # # Replace state terminal bounds with nonlinear constraints # phase.add_boundary_constraint('x', loc='final', equals=10) phase.add_boundary_constraint('y', loc='final', equals=5) # # Minimize time at the end of the phase # phase.add_objective('time', loc='final', scaler=10) p.model.linear_solver = om.DirectSolver() # # Setup the Problem # p.setup() # # Set the initial values # p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 2.0 p['traj.phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input') p['traj.phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input') p['traj.phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['traj.phase0.controls:theta'] = phase.interpolate(ys=[5, 100.5], nodes='control_input') # # Solve for the optimal trajectory # dm.run_problem(p) # Test the results assert_near_equal(p.get_val('traj.phase0.timeseries.time')[-1], 1.8016, tolerance=1.0E-3) # Generate the explicitly simulated trajectory exp_out = traj.simulate() plot_results([('traj.phase0.timeseries.states:x', 'traj.phase0.timeseries.states:y', 'x (m)', 'y (m)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:theta', 'time (s)', 'theta (deg)')], title='Brachistochrone Solution\nRadau Pseudospectral Method', p_sol=p, p_sim=exp_out) plt.show()
def min_time_climb(optimizer='SLSQP', num_seg=3, transcription='gauss-lobatto', transcription_order=3, force_alloc_complex=False): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = optimizer p.driver.declare_coloring() if optimizer == 'SNOPT': p.driver.opt_settings['Major iterations limit'] = 1000 p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6 p.driver.opt_settings['Function precision'] = 1.0E-12 p.driver.opt_settings['Linesearch tolerance'] = 0.1 p.driver.opt_settings['Major step limit'] = 0.5 t = {'gauss-lobatto': dm.GaussLobatto(num_segments=num_seg, order=transcription_order), 'radau-ps': dm.Radau(num_segments=num_seg, order=transcription_order), 'runge-kutta': dm.RungeKutta(num_segments=num_seg)} traj = dm.Trajectory() phase = dm.Phase(ode_class=MinTimeClimbODE, transcription=t[transcription]) traj.add_phase('phase0', phase) p.model.add_subsystem('traj', traj) phase.set_time_options(fix_initial=True, duration_bounds=(50, 400), duration_ref=100.0) phase.add_state('r', fix_initial=True, lower=0, upper=1.0E6, ref=1.0E3, defect_ref=1.0E3, units='m', rate_source='flight_dynamics.r_dot') phase.add_state('h', fix_initial=True, lower=0, upper=20000.0, ref=1.0E2, defect_ref=1.0E2, units='m', rate_source='flight_dynamics.h_dot', targets=['h']) phase.add_state('v', fix_initial=True, lower=10.0, ref=1.0E2, defect_ref=1.0E2, units='m/s', rate_source='flight_dynamics.v_dot', targets=['v']) phase.add_state('gam', fix_initial=True, lower=-1.5, upper=1.5, ref=1.0, defect_ref=1.0, units='rad', rate_source='flight_dynamics.gam_dot', targets=['gam']) phase.add_state('m', fix_initial=True, lower=10.0, upper=1.0E5, ref=1.0E3, defect_ref=1.0E3, units='kg', rate_source='prop.m_dot', targets=['m']) phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, rate_continuity=True, rate_continuity_scaler=100.0, rate2_continuity=False, targets=['alpha']) phase.add_parameter('S', val=49.2386, units='m**2', opt=False, targets=['S']) phase.add_parameter('Isp', val=1600.0, units='s', opt=False, targets=['Isp']) phase.add_parameter('throttle', val=1.0, opt=False, targets=['throttle']) phase.add_boundary_constraint('h', loc='final', equals=20000, scaler=1.0E-3, units='m') phase.add_boundary_constraint('aero.mach', loc='final', equals=1.0) phase.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad') phase.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000) phase.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8) # Unnecessary but included to test capability phase.add_path_constraint(name='alpha', units='deg', lower=-8, upper=8) phase.add_path_constraint(name='time', lower=0, upper=400) phase.add_path_constraint(name='time_phase', lower=0, upper=400) # Minimize time at the end of the phase phase.add_objective('time', loc='final', ref=1.0) # test mixing wildcard ODE variable expansion and unit overrides phase.add_timeseries_output(['aero.*', 'prop.thrust', 'prop.m_dot'], units={'aero.f_lift': 'lbf', 'prop.thrust': 'lbf'}) p.model.linear_solver = om.DirectSolver() p.setup(check=True, force_alloc_complex=force_alloc_complex) p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 300.0 p['traj.phase0.states:r'] = phase.interpolate(ys=[0.0, 111319.54], nodes='state_input') p['traj.phase0.states:h'] = phase.interpolate(ys=[100.0, 20000.0], nodes='state_input') p['traj.phase0.states:v'] = phase.interpolate(ys=[135.964, 283.159], nodes='state_input') p['traj.phase0.states:gam'] = phase.interpolate(ys=[0.0, 0.0], nodes='state_input') p['traj.phase0.states:m'] = phase.interpolate(ys=[19030.468, 16841.431], nodes='state_input') p['traj.phase0.controls:alpha'] = phase.interpolate(ys=[0.0, 0.0], nodes='control_input') p.run_driver() return p
def test_ex_double_integrator_input_times(self, compressed=True): """ Tests that externally connected t_initial and t_duration function as expected. """ p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() times_ivc = p.model.add_subsystem('times_ivc', om.IndepVarComp(), promotes_outputs=['t0', 'tp']) times_ivc.add_output(name='t0', val=0.0, units='s') times_ivc.add_output(name='tp', val=1.0, units='s') transcription = dm.Radau(num_segments=20, order=3, compressed=compressed) phase = dm.Phase(ode_class=DoubleIntegratorODE, transcription=transcription) p.model.add_subsystem('phase0', phase) p.model.connect('t0', 'phase0.t_initial') p.model.connect('tp', 'phase0.t_duration') phase.set_time_options(input_initial=True, input_duration=True, units='s') phase.add_state('x', fix_initial=True, rate_source='v', units='m') phase.add_state('v', fix_initial=True, fix_final=True, rate_source='u', units='m/s') phase.add_control('u', units='m/s**2', scaler=0.01, continuity=False, rate_continuity=False, rate2_continuity=False, lower=-1.0, upper=1.0) # Maximize distance travelled in one second. phase.add_objective('x', loc='final', scaler=-1) p.model.linear_solver = om.DirectSolver() p.setup(check=True) p['t0'] = 0.0 p['tp'] = 1.0 p['phase0.states:x'] = phase.interpolate(ys=[0, 0.25], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[0, 0], nodes='state_input') p['phase0.controls:u'] = phase.interpolate(ys=[1, -1], nodes='control_input') p.run_driver()
def two_burn_orbit_raise_problem(transcription='gauss-lobatto', optimizer='SLSQP', r_target=3.0, transcription_order=3, compressed=False, show_output=True): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = optimizer p.driver.declare_coloring() if optimizer == 'SNOPT': p.driver.opt_settings['Major iterations limit'] = 100 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6 if show_output: p.driver.opt_settings['iSumm'] = 6 elif optimizer == 'IPOPT': p.driver.opt_settings['hessian_approximation'] = 'limited-memory' p.driver.opt_settings['nlp_scaling_method'] = 'gradient-based' p.driver.opt_settings['print_level'] = 4 p.driver.opt_settings['linear_solver'] = 'mumps' p.driver.opt_settings['mu_strategy'] = 'adaptive' # p.driver.opt_settings['derivative_test'] = 'first-order' traj = make_traj(transcription=transcription, transcription_order=transcription_order, compressed=compressed) p.model.add_subsystem('traj', subsys=traj) # Needed to move the direct solver down into the phases for use with MPI. # - After moving down, used fewer iterations (about 30 less) p.setup(check=True) # Set Initial Guesses p.set_val('traj.parameters:c', value=1.5, units='DU/TU') burn1 = p.model.traj.phases.burn1 burn2 = p.model.traj.phases.burn2 coast = p.model.traj.phases.coast if burn1 in p.model.traj.phases._subsystems_myproc: 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')) if coast in p.model.traj.phases._subsystems_myproc: 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')) if burn2 in p.model.traj.phases._subsystems_myproc: 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, r_target], nodes='state_input')) p.set_val('traj.burn2.states:theta', value=burn2.interpolate(ys=[0, 4.0], nodes='state_input')) p.set_val('traj.burn2.states:vr', value=burn2.interpolate(ys=[0, 0], nodes='state_input')) p.set_val('traj.burn2.states:vt', value=burn2.interpolate(ys=[1, np.sqrt(1 / r_target)], 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.states:accel', value=burn2.interpolate(ys=[0.1, 0], nodes='state_input')) p.set_val('traj.burn2.controls:u1', value=burn2.interpolate(ys=[0, 0], nodes='control_input')) dm.run_problem(p, run_driver=False, simulate=True, make_plots=True) 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 setUp(self): # --- geometry ---- # --- geometry ---- z_param = np.array([0.0, 43.8, 87.6]) d_param = np.array([6.0, 4.935, 3.87]) t_param = np.array([0.027*1.3, 0.023*1.3, 0.019*1.3]) n = 15 z_full = np.linspace(0.0, 87.6, n) L_reinforced = 30.0*np.ones(n) # [m] buckling length theta_stress = 0.0*np.ones(n) yaw = 0.0 # --- material props --- E = 210e9*np.ones(n) G = 80.8e9*np.ones(n) rho = 8500.0*np.ones(n) sigma_y = 450.0e6*np.ones(n) # --- spring reaction data. Use float('inf') for rigid constraints. --- kidx = np.array([0], dtype=int) # applied at base kx = np.array([float('inf')]) ky = np.array([float('inf')]) kz = np.array([float('inf')]) ktx = np.array([float('inf')]) kty = np.array([float('inf')]) ktz = np.array([float('inf')]) nK = len(kidx) # --- extra mass ---- midx = np.array([n-1], dtype=int) # RNA mass at top m = np.array([285598.8]) mIxx = np.array([1.14930678e+08]) mIyy = np.array([2.20354030e+07]) mIzz = np.array([1.87597425e+07]) mIxy = np.array([0.00000000e+00]) mIxz = np.array([5.03710467e+05]) mIyz = np.array([0.00000000e+00]) mrhox = np.array([-1.13197635]) mrhoy = np.array([0.]) mrhoz = np.array([0.50875268]) nMass = len(midx) addGravityLoadForExtraMass = True # ----------- # --- wind --- wind_zref = 90.0 wind_z0 = 0.0 shearExp = 0.2 # --------------- # if addGravityLoadForExtraMass=True be sure not to double count by adding those force here also # # --- loading case 1: max Thrust --- wind_Uref1 = 11.73732 plidx1 = np.array([n-1], dtype=int) # at top Fx1 = np.array([1284744.19620519]) Fy1 = np.array([0.]) Fz1 = np.array([-2914124.84400512]) Mxx1 = np.array([3963732.76208099]) Myy1 = np.array([-2275104.79420872]) Mzz1 = np.array([-346781.68192839]) nPL = len(plidx1) # # --------------- # # --- loading case 2: max wind speed --- wind_Uref2 = 70.0 plidx2 = np.array([n-1], dtype=int) # at top Fx2 = np.array([930198.60063279]) Fy2 = np.array([0.]) Fz2 = np.array([-2883106.12368949]) Mxx2 = np.array([-1683669.22411597]) Myy2 = np.array([-2522475.34625363]) Mzz2 = np.array([147301.97023764]) # # --------------- # --- safety factors --- gamma_f = 1.35 gamma_m = 1.3 gamma_n = 1.0 gamma_b = 1.1 # --------------- # --- fatigue --- z_DEL = np.array([0.000, 1.327, 3.982, 6.636, 9.291, 11.945, 14.600, 17.255, 19.909, 22.564, 25.218, 27.873, 30.527, 33.182, 35.836, 38.491, 41.145, 43.800, 46.455, 49.109, 51.764, 54.418, 57.073, 59.727, 62.382, 65.036, 67.691, 70.345, 73.000, 75.655, 78.309, 80.964, 83.618, 86.273, 87.600]) M_DEL = 1e3*np.array([8.2940E+003, 8.1518E+003, 7.8831E+003, 7.6099E+003, 7.3359E+003, 7.0577E+003, 6.7821E+003, 6.5119E+003, 6.2391E+003, 5.9707E+003, 5.7070E+003, 5.4500E+003, 5.2015E+003, 4.9588E+003, 4.7202E+003, 4.4884E+003, 4.2577E+003, 4.0246E+003, 3.7942E+003, 3.5664E+003, 3.3406E+003, 3.1184E+003, 2.8977E+003, 2.6811E+003, 2.4719E+003, 2.2663E+003, 2.0673E+003, 1.8769E+003, 1.7017E+003, 1.5479E+003, 1.4207E+003, 1.3304E+003, 1.2780E+003, 1.2673E+003, 1.2761E+003]) nDEL = len(z_DEL) gamma_fatigue = 1.35*1.3*1.0 life = 20.0 m_SN = 4 # --------------- # --- constraints --- min_d_to_t = 120.0 min_taper = 0.4 # --------------- # # V_max = 80.0 # tip speed # # D = 126.0 # # .freq1p = V_max / (D/2) / (2*pi) # convert to Hz nPoints = len(z_param) nFull = len(z_full) wind = 'PowerWind' prob = Problem() root = prob.root = Group() prob.driver = pyOptSparseDriver() prob.driver.options['optimizer'] = 'SNOPT' prob.driver.opt_settings['Major iterations limit'] = 1000 root.add('z_param', IndepVarComp('z_param', z_param)) root.add('d_param', IndepVarComp('d_param', d_param)) root.add('t_param', IndepVarComp('t_param', t_param)) root.add('TowerSE', TowerSE(nPoints, nFull, nK, nMass, nPL, nDEL, wind=wind)) prob.driver.add_objective('TowerSE.tower1.mass', scaler=1E-6) prob.driver.add_desvar('z_param.z_param', lower=np.zeros(nPoints), upper=np.ones(nPoints)*1000., scaler=1E-2) prob.driver.add_desvar('t_param.t_param', lower=np.ones(nPoints)*0.001, upper=np.ones(nPoints)*1000., scaler=1E-6) prob.driver.add_desvar('d_param.d_param', np.array([2,2.1,2.2]), upper=np.ones(nPoints)*1000., scaler=1E-6) prob.root.connect('z_param.z_param', 'TowerSE.z_param') prob.root.connect('d_param.d_param', 'TowerSE.d_param') prob.root.connect('t_param.t_param', 'TowerSE.t_param') prob.driver.add_constraint('TowerSE.tower1.stress', upper=np.ones(n)) prob.driver.add_constraint('TowerSE.tower2.stress', upper=np.ones(n)) prob.driver.add_constraint('TowerSE.tower1.global_buckling', upper=np.ones(n)) prob.driver.add_constraint('TowerSE.tower2.global_buckling', upper=np.ones(n)) prob.driver.add_constraint('TowerSE.tower1.shell_buckling', upper=np.ones(n)) prob.driver.add_constraint('TowerSE.tower2.shell_buckling', upper=np.ones(n)) prob.driver.add_constraint('TowerSE.tower1.damage', upper=np.ones(n)*0.8) prob.driver.add_constraint('TowerSE.gc.weldability', upper=np.zeros(n)) prob.driver.add_constraint('TowerSE.gc.manufacturability', upper=np.zeros(n)) freq1p = 0.2 # 1P freq in Hz prob.driver.add_constraint('TowerSE.tower1.f1', lower=1.1*freq1p) prob.driver.add_constraint('TowerSE.tower2.f1', lower=1.1*freq1p) prob.setup() if wind=='PowerWind': prob['TowerSE.wind1.shearExp'] = shearExp prob['TowerSE.wind2.shearExp'] = shearExp # assign values to params # --- geometry ---- #prob['TowerSE.z_param'] = z_param #prob['TowerSE.d_param'] = d_param #prob['TowerSE.t_param'] = t_param prob['TowerSE.z_full'] = z_full prob['TowerSE.tower1.L_reinforced'] = L_reinforced prob['TowerSE.distLoads1.yaw'] = yaw # --- material props --- prob['TowerSE.tower1.E'] = E prob['TowerSE.tower1.G'] = G prob['TowerSE.tower1.rho'] = rho prob['TowerSE.tower1.sigma_y'] = sigma_y # --- spring reaction data. Use float('inf') for rigid constraints. --- prob['TowerSE.tower1.kidx'] = kidx prob['TowerSE.tower1.kx'] = kx prob['TowerSE.tower1.ky'] = ky prob['TowerSE.tower1.kz'] = kz prob['TowerSE.tower1.ktx'] = ktx prob['TowerSE.tower1.kty'] = kty prob['TowerSE.tower1.ktz'] = ktz # --- extra mass ---- prob['TowerSE.tower1.midx'] = midx prob['TowerSE.tower1.m'] = m prob['TowerSE.tower1.mIxx'] = mIxx prob['TowerSE.tower1.mIyy'] = mIyy prob['TowerSE.tower1.mIzz'] = mIzz prob['TowerSE.tower1.mIxy'] = mIxy prob['TowerSE.tower1.mIxz'] = mIxz prob['TowerSE.tower1.mIyz'] = mIyz prob['TowerSE.tower1.mrhox'] = mrhox prob['TowerSE.tower1.mrhoy'] = mrhoy prob['TowerSE.tower1.mrhoz'] = mrhoz prob['TowerSE.tower1.addGravityLoadForExtraMass'] = addGravityLoadForExtraMass # ----------- # --- wind --- prob['TowerSE.wind1.zref'] = wind_zref prob['TowerSE.wind1.z0'] = wind_z0 # --------------- # # --- loading case 1: max Thrust --- prob['TowerSE.wind1.Uref'] = wind_Uref1 prob['TowerSE.tower1.plidx'] = plidx1 prob['TowerSE.tower1.Fx'] = Fx1 prob['TowerSE.tower1.Fy'] = Fy1 prob['TowerSE.tower1.Fz'] = Fz1 prob['TowerSE.tower1.Mxx'] = Mxx1 prob['TowerSE.tower1.Myy'] = Myy1 prob['TowerSE.tower1.Mzz'] = Mzz1 # # --------------- # # --- loading case 2: max Wind Speed --- prob['TowerSE.wind2.Uref'] = wind_Uref2 prob['TowerSE.tower2.plidx'] = plidx2 prob['TowerSE.tower2.Fx'] = Fx2 prob['TowerSE.tower2.Fy'] = Fy2 prob['TowerSE.tower2.Fz'] = Fz2 prob['TowerSE.tower2.Mxx'] = Mxx2 prob['TowerSE.tower2.Myy'] = Myy2 prob['TowerSE.tower2.Mzz'] = Mzz2 # # --------------- # --- safety factors --- prob['TowerSE.tower1.gamma_f'] = gamma_f prob['TowerSE.tower1.gamma_m'] = gamma_m prob['TowerSE.tower1.gamma_n'] = gamma_n prob['TowerSE.tower1.gamma_b'] = gamma_b # --------------- # --- fatigue --- prob['TowerSE.tower1.z_DEL'] = z_DEL prob['TowerSE.tower1.M_DEL'] = M_DEL prob['TowerSE.tower1.gamma_fatigue'] = gamma_fatigue prob['TowerSE.tower1.life'] = life prob['TowerSE.tower1.m_SN'] = m_SN # --------------- # --- constraints --- prob['TowerSE.gc.min_d_to_t'] = min_d_to_t prob['TowerSE.gc.min_taper'] = min_taper # --------------- # # --- run --- prob.run() print prob['TowerSE.gc.weldability'] print prob['TowerSE.gc.manufacturability'] self.J = prob.check_total_derivatives(out_stream=None) """
def _test_integrate_polynomial_control_rate2(self, transcription): # # Define the OpenMDAO problem # p = om.Problem(model=om.Group()) # # Define a Trajectory object # traj = dm.Trajectory() p.model.add_subsystem('traj', subsys=traj) # # Define a Dymos Phase object with GaussLobatto Transcription # phase = dm.Phase(ode_class=BrachistochroneODE, transcription=transcription(num_segments=20, order=3)) traj.add_phase(name='phase0', phase=phase) # # Set the time options # Time has no targets in our ODE. # We fix the initial time so that the it is not a design variable in the optimization. # The duration of the phase is allowed to be optimized, but is bounded on [0.5, 10]. # phase.set_time_options(fix_initial=True, duration_bounds=(1.0, 10.0), units='s') # # Set the time options # Initial values of positions and velocity are all fixed. # The final value of position are fixed, but the final velocity is a free variable. # The equations of motion are not functions of position, so 'x' and 'y' have no targets. # The rate source points to the output in the ODE which provides the time derivative of the # given state. phase.add_state('x', fix_initial=True, fix_final=True) phase.add_state('y', fix_initial=True, fix_final=True) phase.add_state('v', fix_initial=True) phase.add_state('int_theta_dot', fix_initial=False, rate_source='theta_rate2') phase.add_state('int_theta', fix_initial=False, rate_source='int_theta_dot', targets=['theta']) # Define theta as a control. phase.add_polynomial_control(name='theta', order=11, units='rad', shape=(1, ), targets=None) # Force the initial value of the theta polynomial control to equal the initial value of the theta state. traj.add_linkage_constraint(phase_a='phase0', phase_b='phase0', var_a='theta', var_b='int_theta', loc_a='initial', loc_b='initial') traj.add_linkage_constraint(phase_a='phase0', phase_b='phase0', var_a='int_theta_dot', var_b='theta_rate', loc_a='initial', loc_b='initial', units='rad/s') # Minimize final time. phase.add_objective('time', loc='final') # Set the driver. p.driver = om.pyOptSparseDriver(optimizer='SLSQP') # Allow OpenMDAO to automatically determine our sparsity pattern. # Doing so can significant speed up the execution of Dymos. p.driver.declare_coloring() # Setup the problem p.setup(check=True) # Now that the OpenMDAO problem is setup, we can set the values of the states. p.set_val('traj.phase0.t_initial', 0.0, units='s') p.set_val('traj.phase0.t_duration', 5.0, units='s') p.set_val('traj.phase0.states:x', phase.interp('x', [0, 10]), units='m') p.set_val('traj.phase0.states:y', phase.interp('y', [10, 5]), units='m') p.set_val('traj.phase0.states:v', phase.interp('v', [0, 5]), units='m/s') p.set_val('traj.phase0.states:int_theta', phase.interp('int_theta', [0.1, 45]), units='deg') p.set_val('traj.phase0.states:int_theta_dot', phase.interp('int_theta_dot', [0, 0]), units='deg/s') p.set_val('traj.phase0.polynomial_controls:theta', 45.0, units='deg') # Run the driver to solve the problem dm.run_problem(p, simulate=True, make_plots=True) sol = om.CaseReader('dymos_solution.db').get_case('final') sim = om.CaseReader('dymos_simulation.db').get_case('final') t_sol = sol.get_val('traj.phase0.timeseries.time') t_sim = sim.get_val('traj.phase0.timeseries.time') x_sol = sol.get_val('traj.phase0.timeseries.states:x') x_sim = sim.get_val('traj.phase0.timeseries.states:x') y_sol = sol.get_val('traj.phase0.timeseries.states:y') y_sim = sim.get_val('traj.phase0.timeseries.states:y') v_sol = sol.get_val('traj.phase0.timeseries.states:v') v_sim = sim.get_val('traj.phase0.timeseries.states:v') int_theta_sol = sol.get_val('traj.phase0.timeseries.states:int_theta') int_theta_sim = sim.get_val('traj.phase0.timeseries.states:int_theta') theta_sol = sol.get_val( 'traj.phase0.timeseries.polynomial_controls:theta') theta_sim = sim.get_val( 'traj.phase0.timeseries.polynomial_controls:theta') assert_timeseries_near_equal(t_sol, x_sol, t_sim, x_sim, tolerance=1.0E-2) assert_timeseries_near_equal(t_sol, y_sol, t_sim, y_sim, tolerance=1.0E-2) assert_timeseries_near_equal(t_sol, v_sol, t_sim, v_sim, tolerance=1.0E-2) assert_timeseries_near_equal(t_sol, int_theta_sol, t_sim, int_theta_sim, tolerance=1.0E-2)
def hp_transient(transcription='gauss-lobatto', num_segments=5, transcription_order=3, compressed=False, optimizer='SLSQP', run_driver=True, force_alloc_complex=True, solve_segments=False, show_plots=False, save=True, Tf_final=370): p = om.Problem(model=om.Group()) model = p.model nn = 1 p.driver = om.ScipyOptimizeDriver() p.driver = om.pyOptSparseDriver(optimizer=optimizer) p.driver.declare_coloring() traj = p.model.add_subsystem('traj', dm.Trajectory()) phase = traj.add_phase( 'phase', dm.Phase(ode_class=HeatPipeRun, transcription=dm.GaussLobatto(num_segments=num_segments, order=transcription_order, compressed=compressed))) phase.set_time_options(fix_initial=True, fix_duration=False, duration_bounds=(1., 3200.)) phase.add_state( 'T_cond', rate_source='cond.Tdot', targets='cond.T', units='K', # ref=333.15, defect_ref=333.15, fix_initial=True, fix_final=False, solve_segments=solve_segments) phase.add_state( 'T_cond2', rate_source='cond2.Tdot', targets='cond2.T', units='K', # ref=333.15, defect_ref=333.15, fix_initial=True, fix_final=False, solve_segments=solve_segments) phase.add_control('T_evap', targets='evap.Rex.T_in', units='K', opt=False) phase.add_boundary_constraint('T_cond', loc='final', equals=Tf_final) phase.add_objective('time', loc='final', ref=1) phase.add_timeseries_output('evap_bridge.Rv.q', output_name='eRvq', units='W') phase.add_timeseries_output('evap_bridge.Rwa.q', output_name='eRwaq', units='W') phase.add_timeseries_output('evap_bridge.Rwka.q', output_name='eRwkq', units='W') phase.add_timeseries_output('cond_bridge.Rv.q', output_name='cRvq', units='W') phase.add_timeseries_output('cond_bridge.Rwa.q', output_name='cRwaq', units='W') phase.add_timeseries_output('cond_bridge.Rwka.q', output_name='cRwkq', units='W') phase.add_timeseries_output('evap.pcm.PS', output_name='ePS', units=None) phase.add_timeseries_output('cond.pcm.PS', output_name='cPS', units=None) phase.add_timeseries_output('cond2.pcm.PS', output_name='c2PS', units=None) p.model.linear_solver = om.DirectSolver() p.setup(force_alloc_complex=force_alloc_complex) p['traj.phase.t_initial'] = 0.0 p['traj.phase.t_duration'] = 195. p['traj.phase.states:T_cond'] = phase.interpolate(ys=[293.15, 333.15], nodes='state_input') p['traj.phase.states:T_cond2'] = phase.interpolate(ys=[293.15, 333.15], nodes='state_input') p['traj.phase.controls:T_evap'] = phase.interpolate(ys=[333., 338.], nodes='control_input') p.run_model() opt = p.run_driver() # sim = traj.simulate(times_per_seg=10) print('********************************') # save_csv(p, sim, '../../output/output.csv', # y_name=['parameters:T_evap', 'states:T_cond', 'states:T_cond2', # 'eRvq', 'eRwaq', 'eRwkq', 'cRvq', 'cRwaq', 'cRwkq'], # y_units=['K', 'K', 'K', 'W', 'W', 'W', 'W', 'W', 'W']) if show_plots: import matplotlib.pyplot as plt # time = sim.get_val('traj.phase.timeseries.time', units='s') time_opt = p.get_val('traj.phase.timeseries.time', units='s') # T_cond = sim.get_val('traj.phase.timeseries.states:T_cond', units='K') T_cond_opt = p.get_val('traj.phase.timeseries.states:T_cond', units='K') # T_cond2 = sim.get_val('traj.phase.timeseries.states:T_cond2', units='K') T_cond2_opt = p.get_val('traj.phase.timeseries.states:T_cond2', units='K') # T_evap = sim.get_val('traj.phase.timeseries.controls:T_evap', units='K') T_evap_opt = p.get_val('traj.phase.timeseries.controls:T_evap', units='K') ePS_opt = p.get_val('traj.phase.timeseries.ePS') cPS_opt = p.get_val('traj.phase.timeseries.cPS') c2PS_opt = p.get_val('traj.phase.timeseries.c2PS') plt.plot(time_opt, T_cond_opt) # plt.plot(time, T_cond) plt.plot(time_opt, T_cond2_opt) # plt.plot(time, T_cond2) plt.plot(time_opt, T_evap_opt) # plt.plot(time, T_evap) plt.xlabel('time, s') plt.ylabel('T_cond, K') plt.show() plt.plot(time_opt, cPS_opt) # plt.plot(time, EPS) plt.plot(time_opt, c2PS_opt) # plt.plot(time, T_cond2) plt.plot(time_opt, ePS_opt) # plt.plot(time, T_evap) plt.xlabel('time, s') plt.ylabel('percent solid') plt.show() return p
def _run_transcription(self, transcription): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() # # First Phase: Standard Brachistochrone # num_segments = 10 transcription_order = 3 compressed = False if transcription == 'gauss-lobatto': tx0 = dm.GaussLobatto(num_segments=num_segments, order=transcription_order, compressed=compressed) tx1 = dm.GaussLobatto(num_segments=num_segments * 2, order=transcription_order * 3, compressed=compressed) elif transcription == 'radau-ps': tx0 = dm.Radau(num_segments=num_segments, order=transcription_order, compressed=compressed) tx1 = dm.Radau(num_segments=num_segments * 2, order=transcription_order * 3, compressed=compressed) phase0 = dm.Phase(ode_class=BrachistochroneODE, transcription=tx0) p.model.add_subsystem('phase0', phase0) phase0.set_time_options(fix_initial=True, duration_bounds=(.5, 10)) phase0.add_state('x', fix_initial=True, fix_final=False) phase0.add_state('y', fix_initial=True, fix_final=False) phase0.add_state('v', fix_initial=True) phase0.add_parameter('g', units='m/s**2', val=9.80665) phase0.add_control('theta', units='deg', rate_continuity=False, lower=0.01, upper=179.9) phase0.add_boundary_constraint('x', loc='final', equals=10) phase0.add_boundary_constraint('y', loc='final', equals=5) # Add alternative timeseries output to provide control inputs for the next phase phase0.add_timeseries('timeseries2', transcription=tx1, subset='control_input') # # Second Phase: Integration of ArcLength # phase1 = dm.Phase(ode_class=BrachistochroneArclengthODE, transcription=tx1) p.model.add_subsystem('phase1', phase1) phase1.set_time_options(fix_initial=True, input_duration=True) phase1.add_state('S', fix_initial=True, fix_final=False, rate_source='Sdot') phase1.add_control('theta', opt=False, units='deg', targets=['theta']) phase1.add_control('v', opt=False, units='m/s', targets=['v']) # # Connect the two phases # p.model.connect('phase0.t_duration', 'phase1.t_duration') p.model.connect('phase0.timeseries2.controls:theta', 'phase1.controls:theta') p.model.connect('phase0.timeseries2.states:v', 'phase1.controls:v') # Minimize time at the end of the phase # phase1.add_objective('time', loc='final', scaler=1) # phase1.add_boundary_constraint('S', loc='final', upper=12) phase1.add_objective('S', loc='final', ref=1) 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'] = phase0.interpolate(ys=[0, 10], nodes='state_input') p['phase0.states:y'] = phase0.interpolate(ys=[10, 5], nodes='state_input') p['phase0.states:v'] = phase0.interpolate(ys=[0, 9.9], nodes='state_input') p['phase0.controls:theta'] = phase0.interpolate(ys=[5, 100], nodes='control_input') p['phase0.parameters:g'] = 9.80665 p['phase1.states:S'] = 0.0 p.run_driver() expected = np.sqrt((10 - 0)**2 + (10 - 5)**2) assert_near_equal(p['phase1.timeseries.states:S'][-1], expected, tolerance=1.0E-3)
def test_doc_ssto_linear_tangent_guidance(self): import numpy as np import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.plotting import plot_results g = 1.61544 # lunar gravity, m/s**2 class LaunchVehicle2DEOM(om.ExplicitComponent): """ Simple 2D Cartesian Equations of Motion for a launch vehicle subject to thrust and drag. """ def initialize(self): self.options.declare('num_nodes', types=int) def setup(self): nn = self.options['num_nodes'] # Inputs self.add_input('vx', val=np.zeros(nn), desc='x velocity', units='m/s') self.add_input('vy', val=np.zeros(nn), desc='y velocity', units='m/s') self.add_input('m', val=np.zeros(nn), desc='mass', units='kg') self.add_input('theta', val=np.zeros(nn), desc='pitch angle', units='rad') self.add_input('thrust', val=2100000 * np.ones(nn), desc='thrust', units='N') self.add_input('Isp', val=265.2 * np.ones(nn), desc='specific impulse', units='s') # Outputs self.add_output('xdot', val=np.zeros(nn), desc='velocity component in x', units='m/s') self.add_output('ydot', val=np.zeros(nn), desc='velocity component in y', units='m/s') self.add_output('vxdot', val=np.zeros(nn), desc='x acceleration magnitude', units='m/s**2') self.add_output('vydot', val=np.zeros(nn), desc='y acceleration magnitude', units='m/s**2') self.add_output('mdot', val=np.zeros(nn), desc='mass rate of change', units='kg/s') # Setup partials ar = np.arange(self.options['num_nodes']) self.declare_partials(of='xdot', wrt='vx', rows=ar, cols=ar, val=1.0) self.declare_partials(of='ydot', wrt='vy', rows=ar, cols=ar, val=1.0) self.declare_partials(of='vxdot', wrt='vx', rows=ar, cols=ar) self.declare_partials(of='vxdot', wrt='m', rows=ar, cols=ar) self.declare_partials(of='vxdot', wrt='theta', rows=ar, cols=ar) self.declare_partials(of='vxdot', wrt='thrust', rows=ar, cols=ar) self.declare_partials(of='vydot', wrt='m', rows=ar, cols=ar) self.declare_partials(of='vydot', wrt='theta', rows=ar, cols=ar) self.declare_partials(of='vydot', wrt='vy', rows=ar, cols=ar) self.declare_partials(of='vydot', wrt='thrust', rows=ar, cols=ar) self.declare_partials(of='mdot', wrt='thrust', rows=ar, cols=ar) self.declare_partials(of='mdot', wrt='Isp', rows=ar, cols=ar) def compute(self, inputs, outputs): theta = inputs['theta'] cos_theta = np.cos(theta) sin_theta = np.sin(theta) vx = inputs['vx'] vy = inputs['vy'] m = inputs['m'] F_T = inputs['thrust'] Isp = inputs['Isp'] outputs['xdot'] = vx outputs['ydot'] = vy outputs['vxdot'] = F_T * cos_theta / m outputs['vydot'] = F_T * sin_theta / m - g outputs['mdot'] = -F_T / (g * Isp) def compute_partials(self, inputs, jacobian): theta = inputs['theta'] cos_theta = np.cos(theta) sin_theta = np.sin(theta) m = inputs['m'] F_T = inputs['thrust'] Isp = inputs['Isp'] # jacobian['vxdot', 'vx'] = -CDA * rho * vx / m jacobian['vxdot', 'm'] = -(F_T * cos_theta) / m**2 jacobian['vxdot', 'theta'] = -(F_T / m) * sin_theta jacobian['vxdot', 'thrust'] = cos_theta / m # jacobian['vydot', 'vy'] = -CDA * rho * vy / m jacobian['vydot', 'm'] = -(F_T * sin_theta) / m**2 jacobian['vydot', 'theta'] = (F_T / m) * cos_theta jacobian['vydot', 'thrust'] = sin_theta / m jacobian['mdot', 'thrust'] = -1.0 / (g * Isp) jacobian['mdot', 'Isp'] = F_T / (g * Isp**2) class LinearTangentGuidanceComp(om.ExplicitComponent): """ Compute pitch angle from static controls governing linear expression for pitch angle tangent as function of time. """ def initialize(self): self.options.declare('num_nodes', types=int) def setup(self): nn = self.options['num_nodes'] self.add_input('a_ctrl', val=np.zeros(nn), desc='linear tangent slope', units='1/s') self.add_input('b_ctrl', val=np.zeros(nn), desc='tangent of theta at t=0', units=None) self.add_input('time_phase', val=np.zeros(nn), desc='time', units='s') self.add_output('theta', val=np.zeros(nn), desc='pitch angle', units='rad') # Setup partials arange = np.arange(self.options['num_nodes']) self.declare_partials(of='theta', wrt='a_ctrl', rows=arange, cols=arange, val=1.0) self.declare_partials(of='theta', wrt='b_ctrl', rows=arange, cols=arange, val=1.0) self.declare_partials(of='theta', wrt='time_phase', rows=arange, cols=arange, val=1.0) def compute(self, inputs, outputs): a = inputs['a_ctrl'] b = inputs['b_ctrl'] t = inputs['time_phase'] outputs['theta'] = np.arctan(a * t + b) def compute_partials(self, inputs, jacobian): a = inputs['a_ctrl'] b = inputs['b_ctrl'] t = inputs['time_phase'] x = a * t + b denom = x**2 + 1.0 jacobian['theta', 'a_ctrl'] = t / denom jacobian['theta', 'b_ctrl'] = 1.0 / denom jacobian['theta', 'time_phase'] = a / denom class LaunchVehicleLinearTangentODE(om.Group): """ The LaunchVehicleLinearTangentODE for this case consists of a guidance component and the EOM. Guidance is simply an OpenMDAO ExecComp which computes the arctangent of the tan_theta variable. """ def initialize(self): self.options.declare( 'num_nodes', types=int, desc='Number of nodes to be evaluated in the RHS') def setup(self): nn = self.options['num_nodes'] self.add_subsystem('guidance', LinearTangentGuidanceComp(num_nodes=nn)) self.add_subsystem('eom', LaunchVehicle2DEOM(num_nodes=nn)) self.connect('guidance.theta', 'eom.theta') # # Setup and solve the optimal control problem # p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.declare_coloring() traj = dm.Trajectory() p.model.add_subsystem('traj', traj) phase = dm.Phase(ode_class=LaunchVehicleLinearTangentODE, transcription=dm.GaussLobatto(num_segments=10, order=5, compressed=True)) traj.add_phase('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(10, 1000), targets=['guidance.time_phase']) phase.add_state('x', fix_initial=True, lower=0, rate_source='eom.xdot', units='m') phase.add_state('y', fix_initial=True, lower=0, rate_source='eom.ydot', units='m') phase.add_state('vx', fix_initial=True, lower=0, rate_source='eom.vxdot', targets=['eom.vx'], units='m/s') phase.add_state('vy', fix_initial=True, rate_source='eom.vydot', targets=['eom.vy'], units='m/s') phase.add_state('m', fix_initial=True, rate_source='eom.mdot', targets=['eom.m'], units='kg') phase.add_boundary_constraint('y', loc='final', equals=1.85E5, linear=True) phase.add_boundary_constraint('vx', loc='final', equals=1627.0) phase.add_boundary_constraint('vy', loc='final', equals=0) phase.add_parameter('a_ctrl', units='1/s', opt=True, targets=['guidance.a_ctrl']) phase.add_parameter('b_ctrl', units=None, opt=True, targets=['guidance.b_ctrl']) phase.add_parameter('thrust', units='N', opt=False, val=3.0 * 50000.0 * 1.61544, targets=['eom.thrust']) phase.add_parameter('Isp', units='s', opt=False, val=1.0E6, targets=['eom.Isp']) phase.add_objective('time', index=-1, scaler=0.01) p.model.linear_solver = om.DirectSolver() phase.add_timeseries_output('guidance.theta', units='deg') p.setup(check=True) p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 500.0 p['traj.phase0.states:x'] = phase.interpolate(ys=[0, 350000.0], nodes='state_input') p['traj.phase0.states:y'] = phase.interpolate(ys=[0, 185000.0], nodes='state_input') p['traj.phase0.states:vx'] = phase.interpolate(ys=[0, 1627.0], nodes='state_input') p['traj.phase0.states:vy'] = phase.interpolate(ys=[1.0E-6, 0], nodes='state_input') p['traj.phase0.states:m'] = phase.interpolate(ys=[50000, 50000], nodes='state_input') p['traj.phase0.parameters:a_ctrl'] = -0.01 p['traj.phase0.parameters:b_ctrl'] = 3.0 dm.run_problem(p) # # Check the results. # assert_near_equal(p.get_val('traj.phase0.timeseries.time')[-1], 481, tolerance=0.01) # # Get the explitly simulated results # exp_out = traj.simulate() # # Plot the results # plot_results( [('traj.phase0.timeseries.states:x', 'traj.phase0.timeseries.states:y', 'range (m)', 'altitude (m)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.theta', 'range (m)', 'altitude (m)')], title= 'Single Stage to Orbit Solution Using Linear Tangent Guidance', p_sol=p, p_sim=exp_out) plt.show()
def test_tandem_phases_for_docs(self): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() # # First Phase: Standard Brachistochrone # num_segments = 10 transcription_order = 3 compressed = False tx0 = dm.GaussLobatto(num_segments=num_segments, order=transcription_order, compressed=compressed) tx1 = dm.Radau(num_segments=num_segments * 2, order=transcription_order * 3, compressed=compressed) phase0 = dm.Phase(ode_class=BrachistochroneODE, transcription=tx0) p.model.add_subsystem('phase0', phase0) phase0.set_time_options(fix_initial=True, duration_bounds=(.5, 10)) phase0.add_state( 'x', rate_source=BrachistochroneODE.states['x']['rate_source'], units=BrachistochroneODE.states['x']['units'], fix_initial=True, fix_final=False, solve_segments=False) phase0.add_state( 'y', rate_source=BrachistochroneODE.states['y']['rate_source'], units=BrachistochroneODE.states['y']['units'], fix_initial=True, fix_final=False, solve_segments=False) phase0.add_state( 'v', rate_source=BrachistochroneODE.states['v']['rate_source'], targets=BrachistochroneODE.states['v']['targets'], units=BrachistochroneODE.states['v']['units'], fix_initial=True, fix_final=False, solve_segments=False) phase0.add_control( 'theta', continuity=True, rate_continuity=True, targets=BrachistochroneODE.parameters['theta']['targets'], units='deg', lower=0.01, upper=179.9) phase0.add_input_parameter( 'g', targets=BrachistochroneODE.parameters['g']['targets'], units='m/s**2', val=9.80665) phase0.add_boundary_constraint('x', loc='final', equals=10) phase0.add_boundary_constraint('y', loc='final', equals=5) # Add alternative timeseries output to provide control inputs for the next phase phase0.add_timeseries('timeseries2', transcription=tx1, subset='control_input') # # Second Phase: Integration of ArcLength # phase1 = dm.Phase(ode_class=BrachistochroneArclengthODE, transcription=tx1) p.model.add_subsystem('phase1', phase1) phase1.set_time_options(fix_initial=True, input_duration=True) phase1.add_state('S', fix_initial=True, fix_final=False, rate_source='Sdot', units='m') phase1.add_control('theta', opt=False, units='deg', targets='theta') phase1.add_control('v', opt=False, units='m/s', targets='v') # # Connect the two phases # p.model.connect('phase0.t_duration', 'phase1.t_duration') p.model.connect('phase0.timeseries2.controls:theta', 'phase1.controls:theta') p.model.connect('phase0.timeseries2.states:v', 'phase1.controls:v') # Minimize time at the end of the phase # phase1.add_objective('time', loc='final', scaler=1) # phase1.add_boundary_constraint('S', loc='final', upper=12) phase1.add_objective('S', loc='final', ref=1) 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'] = phase0.interpolate(ys=[0, 10], nodes='state_input') p['phase0.states:y'] = phase0.interpolate(ys=[10, 5], nodes='state_input') p['phase0.states:v'] = phase0.interpolate(ys=[0, 9.9], nodes='state_input') p['phase0.controls:theta'] = phase0.interpolate(ys=[5, 100], nodes='control_input') p['phase0.input_parameters:g'] = 9.80665 p['phase1.states:S'] = 0.0 p.run_driver() expected = np.sqrt((10 - 0)**2 + (10 - 5)**2) assert_rel_error(self, p['phase1.timeseries.states:S'][-1], expected, tolerance=1.0E-3) fig, (ax0, ax1) = plt.subplots(2, 1) fig.tight_layout() ax0.plot(p.get_val('phase0.timeseries.states:x'), p.get_val('phase0.timeseries.states:y'), '.') ax0.set_xlabel('x (m)') ax0.set_ylabel('y (m)') ax1.plot(p.get_val('phase1.timeseries.time'), p.get_val('phase1.timeseries.states:S'), '+') ax1.set_xlabel('t (s)') ax1.set_ylabel('S (m)') plt.show()
def _make_problem(transcription='gauss-lobatto', num_segments=8, transcription_order=3, compressed=True, optimizer='SLSQP', force_alloc_complex=False, solve_segments=False, y_bounds=None): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() 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['mu_init'] = 1e-3 p.driver.opt_settings['max_iter'] = 500 p.driver.opt_settings['print_level'] = 5 p.driver.opt_settings['nlp_scaling_method'] = 'gradient-based' # for faster convergence p.driver.opt_settings['alpha_for_y'] = 'safer-min-dual-infeas' p.driver.opt_settings['mu_strategy'] = 'monotone' p.driver.declare_coloring(tol=1.0E-12) 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) p.model.add_subsystem('traj0', traj) traj.add_phase('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10)) phase.add_state('x', fix_initial=False, fix_final=False, solve_segments=solve_segments) phase.add_state('y', fix_initial=False, fix_final=False, solve_segments=solve_segments) if y_bounds is not None: phase.set_state_options('y', lower=y_bounds[0], upper=y_bounds[1]) # Note that by omitting the targets here Dymos will automatically attempt to connect # to a top-level input named 'v' in the ODE, and connect to nothing if it's not found. phase.add_state('v', fix_initial=False, fix_final=False, solve_segments=solve_segments) phase.add_control('theta', continuity=True, rate_continuity=True, units='deg', lower=0.01, upper=179.9) phase.add_parameter('g', targets=['g'], units='m/s**2') phase.add_boundary_constraint('x', loc='initial', equals=0) phase.add_boundary_constraint('y', loc='initial', equals=10) phase.add_boundary_constraint('v', loc='initial', equals=0) 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.set_solver_print(0) p.setup(check=['unconnected_inputs'], force_alloc_complex=force_alloc_complex) p['traj0.phase0.t_initial'] = 0.0 p['traj0.phase0.t_duration'] = 1.5 p['traj0.phase0.states:x'] = phase.interp('x', [0, 10]) p['traj0.phase0.states:y'] = phase.interp('y', [10, 5]) p['traj0.phase0.states:v'] = phase.interp('v', [0, 9.9]) p['traj0.phase0.controls:theta'] = phase.interp('theta', [5, 100]) p['traj0.phase0.parameters:g'] = 9.80665 return p
def make_problem(self, transcription=Radau, 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 if OPTIMIZER == 'SNOPT': p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Verify level'] = 3 elif OPTIMIZER == 'IPOPT': p.driver.opt_settings['nlp_scaling_method'] = 'gradient-based' p.driver.opt_settings['max_iter'] = 500 p.driver.opt_settings['print_level'] = 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, units='m**2/s**2') phase.add_path_constraint('u1', lower=-1, upper=1, scaler=0.1, units='m**3*rad/s**2') phase.add_path_constraint('u2', lower=-1, upper=1, scaler=0.1, units='m**3*rad/s**2') 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_discs(self): OPT, OPTIMIZER = set_pyoptsparse_opt('SNOPT') if OPTIMIZER is not 'SNOPT': raise unittest.SkipTest("pyoptsparse is not providing SNOPT or SLSQP") # So we compare the same starting locations. np.random.seed(123) radius = 1.0 pin = 15.0 n_disc = 7 prob = Problem() prob.root = root = Group() from openmdao.api import pyOptSparseDriver driver = prob.driver = pyOptSparseDriver() driver.options['optimizer'] = 'SNOPT' driver.options['print_results'] = False # Note, active tolerance requires relevance reduction to work. root.ln_solver.options['single_voi_relevance_reduction'] = True # Also, need to be in adjoint root.ln_solver.options['mode'] = 'rev' obj_expr = 'obj = ' sep = '' for i in range(n_disc): dist = "dist_%d" % i x1var = 'x_%d' % i # First disc is pinned if i == 0: root.add('p_%d' % i, IndepVarComp(x1var, pin), promotes=(x1var, )) # The rest are design variables for the optimizer. else: init_val = 5.0*np.random.random() - 5.0 + pin root.add('p_%d' % i, IndepVarComp(x1var, init_val), promotes=(x1var, )) driver.add_desvar(x1var) for j in range(i): x2var = 'x_%d' % j yvar = 'y_%d_%d' % (i, j) name = dist + "_%d" % j expr = '%s= (%s - %s)**2' % (yvar, x1var, x2var) root.add(name, ExecComp(expr), promotes = (x1var, x2var, yvar)) # Constraint (you can experiment with turning on/off the active_tol) #driver.add_constraint(yvar, lower=radius) driver.add_constraint(yvar, lower=radius, active_tol=radius*3.0) # This pair's contribution to objective obj_expr += sep + yvar sep = ' + ' root.add('sum_dist', ExecComp(obj_expr), promotes=('*', )) driver.add_objective('obj') prob.setup(check=False) prob.run()
def setup_problem( trans=dm.GaussLobatto(num_segments=10), polynomial_control=False): from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE from dymos.transcriptions.runge_kutta.runge_kutta import RungeKutta p = om.Problem(model=om.Group()) if isinstance(trans, RungeKutta): p.driver = om.pyOptSparseDriver() else: p.driver = om.ScipyOptimizeDriver() phase = dm.Phase(ode_class=BrachistochroneODE, transcription=trans) p.model.add_subsystem('phase0', phase) phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(.5, 10)) phase.add_state('x', fix_initial=True, fix_final=not isinstance(trans, RungeKutta)) phase.add_state('y', fix_initial=True, fix_final=not isinstance(trans, RungeKutta)) phase.add_state('v', fix_initial=True) if not polynomial_control: phase.add_control('theta', units='deg', rate_continuity=False, lower=0.01, upper=179.9) else: phase.add_polynomial_control('theta', order=1, units='deg', lower=0.01, upper=179.9) phase.add_parameter('g', units='m/s**2', opt=False, val=9.80665) if isinstance(trans, RungeKutta): phase.add_timeseries_output('check', units='m/s', shape=(1, )) 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() p.setup() p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 2.0 p['phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input') p['phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') if not polynomial_control: p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100.5], nodes='control_input') else: p['phase0.polynomial_controls:theta'][:] = 5.0 return p
model.add_constraint('%s.ConS1' % name, upper=0.0, parallel_deriv_color='con4') model.add_constraint('%s_con5.val' % name, equals=0.0) # Add broadcast parameters model.add_design_var('bp.cellInstd', lower=0., upper=1.0) model.add_design_var('bp.finAngle', lower=0., upper=np.pi/2.) model.add_design_var('bp.antAngle', lower=-np.pi/4, upper=np.pi/4) # Add objective model.add_objective('obj.val') # Instantiate Problem with driver (SNOPT) and recorder prob = Problem(model) if 'nopt' not in argv: prob.driver = pyOptSparseDriver(optimizer='SNOPT') prob.driver.opt_settings = { 'Major optimality tolerance': 1e-3, 'Major feasibility tolerance': 1.0e-5, 'Iterations limit': 500000000 } if 'record' in argv: if MPI: print('recording not supported for parallel runs.') else: prob.driver.add_recorder(SqliteRecorder('data.sql')) prob.setup() # For Parallel execution, we must use KSP or LinearGS
def test_double_integrator_for_docs(self): import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.assert_utils import assert_rel_error import dymos as dm from dymos.examples.plotting import plot_results from dymos.examples.double_integrator.double_integrator_ode import DoubleIntegratorODE # Initialize the problem and assign the driver p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() # Setup the trajectory and its phase traj = p.model.add_subsystem('traj', dm.Trajectory()) transcription = dm.Radau(num_segments=30, order=3, compressed=False) phase = traj.add_phase( 'phase0', dm.Phase(ode_class=DoubleIntegratorODE, transcription=transcription)) # # Set the options for our variables. # phase.set_time_options(fix_initial=True, fix_duration=True, units='s') phase.add_state('x', fix_initial=True, rate_source='v', units='m') phase.add_state('v', fix_initial=True, fix_final=True, rate_source='u', units='m/s') phase.add_control('u', units='m/s**2', scaler=0.01, continuity=False, rate_continuity=False, rate2_continuity=False, lower=-1.0, upper=1.0) # # Maximize distance travelled. # phase.add_objective('x', loc='final', scaler=-1) p.model.linear_solver = om.DirectSolver() # # Setup the problem and set our initial values. # p.setup(check=True) p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 1.0 p['traj.phase0.states:x'] = phase.interpolate(ys=[0, 0.25], nodes='state_input') p['traj.phase0.states:v'] = phase.interpolate(ys=[0, 0], nodes='state_input') p['traj.phase0.controls:u'] = phase.interpolate(ys=[1, -1], nodes='control_input') # # Solve the problem. # p.run_driver() # # Verify that the results are correct. # x = p.get_val('traj.phase0.timeseries.states:x') v = p.get_val('traj.phase0.timeseries.states:v') assert_rel_error(self, x[0], 0.0, tolerance=1.0E-4) assert_rel_error(self, x[-1], 0.25, tolerance=1.0E-4) assert_rel_error(self, v[0], 0.0, tolerance=1.0E-4) assert_rel_error(self, v[-1], 0.0, tolerance=1.0E-4) # # Simulate the explicit solution and plot the results. # exp_out = traj.simulate() plot_results( [('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:x', 'time (s)', 'x $(m)$'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:v', 'time (s)', 'v $(m/s)$'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:u', 'time (s)', 'u $(m/s^2)$')], title='Double Integrator Solution\nRadau Pseudospectral Method', p_sol=p, p_sim=exp_out) plt.show()
def flying_robot_direct_collocation(transcription='gauss-lobatto', compressed=True): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() if transcription == 'gauss-lobatto': t = dm.GaussLobatto(num_segments=8, order=5, compressed=compressed) elif transcription == "radau-ps": t = dm.Radau(num_segments=8, order=5, compressed=compressed) else: raise ValueError('invalid transcription') traj = p.model.add_subsystem('traj', dm.Trajectory()) phase = traj.add_phase('phase0', dm.Phase(ode_class=FlyingRobotODE, transcription=t)) phase.set_time_options(fix_initial=True, fix_duration=False, duration_bounds=(0.1, 1E4), units='s') phase.add_state('x', shape=(2, ), fix_initial=True, fix_final=True, rate_source='v', units='m') phase.add_state('v', shape=(2, ), fix_initial=True, fix_final=True, rate_source='u', units='m/s') phase.add_state('J', fix_initial=True, fix_final=False, rate_source='u_mag2', units='m**2/s**3') phase.add_control('u', units='m/s**2', shape=(2, ), scaler=0.01, continuity=False, rate_continuity=False, rate2_continuity=False, lower=-1, upper=1) # Minimize the control effort phase.add_objective('time', loc='final') p.model.linear_solver = om.DirectSolver() p.setup(check=True) p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 1.0 p['traj.phase0.states:x'] = phase.interpolate(ys=[[0.0, 0.0], [-100.0, 100.0]], nodes='state_input') p['traj.phase0.states:v'] = phase.interpolate(ys=[[0.0, 0.0], [0.0, 0.0]], nodes='state_input') p['traj.phase0.controls:u'] = phase.interpolate(ys=[[1, 1], [-1, -1]], nodes='control_input') p.run_driver() return p
def ex_aircraft_steady_flight(optimizer='SLSQP', solve_segments=False, use_boundary_constraints=False, compressed=False): p = Problem(model=Group()) p.driver = pyOptSparseDriver() _, optimizer = set_pyoptsparse_opt(optimizer, fallback=False) p.driver.options['optimizer'] = optimizer p.driver.options['dynamic_simul_derivs'] = True 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', 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.set_state_options('range', units='NM', fix_initial=True, fix_final=False, ref=1e-3, defect_ref=1e-3, lower=0, upper=2000) phase.set_state_options('mass_fuel', units='lbm', fix_initial=True, fix_final=fix_final, upper=1.5E5, lower=0.0, ref=1e2, defect_ref=1e2) phase.set_state_options('alt', units='kft', 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, rate_continuity=True, rate2_continuity=False) phase.add_control('mach', units=None, opt=False) phase.add_input_parameter('S', units='m**2') phase.add_input_parameter('mass_empty', units='kg') phase.add_input_parameter('mass_payload', units='kg') phase.add_path_constraint('propulsion.tau', lower=0.01, upper=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 p.run_driver() return p
def EESG_Opt_example(): opt_problem=Problem(root=EESG_Opt()) #Example optimization of an EESG for costs on a 5 MW reference turbine # add optimizer and set-up problem (using user defined input on objective function) # opt_problem.driver=pyOptSparseDriver() opt_problem.driver.options['optimizer'] = 'CONMIN' opt_problem.driver.add_objective('Costs') # Define Objective opt_problem.driver.opt_settings['IPRINT'] = 4 opt_problem.driver.opt_settings['ITRM'] = 3 opt_problem.driver.opt_settings['ITMAX'] = 10 opt_problem.driver.opt_settings['DELFUN'] = 1e-3 opt_problem.driver.opt_settings['DABFUN'] = 1e-3 opt_problem.driver.opt_settings['IFILE'] = 'CONMIN_EESG.out' opt_problem.root.deriv_options['type']='fd' # Specificiency target efficiency(%) Eta_Target = 93.0 # Set bounds for design variables for an EESG designed for a 5MW turbine opt_problem.driver.add_desvar('r_s',lower=0.5,upper=9.0) opt_problem.driver.add_desvar('l_s', lower=0.5, upper=2.5) opt_problem.driver.add_desvar('h_s', lower=0.06, upper=0.15) opt_problem.driver.add_desvar('tau_p', lower=0.04, upper=0.2) opt_problem.driver.add_desvar('N_f', lower=10, upper=300) opt_problem.driver.add_desvar('I_f', lower=1, upper=500) opt_problem.driver.add_desvar('n_r', lower=5.0, upper=15.0) opt_problem.driver.add_desvar('h_yr', lower=0.01, upper=0.25) opt_problem.driver.add_desvar('h_ys', lower=0.01, upper=0.25) opt_problem.driver.add_desvar('b_r', lower=0.1, upper=1.5) opt_problem.driver.add_desvar('d_r', lower=0.1, upper=1.5) opt_problem.driver.add_desvar('t_wr', lower=0.001, upper=0.2) opt_problem.driver.add_desvar('n_s', lower=5.0, upper=15.0) opt_problem.driver.add_desvar('b_st', lower=0.1, upper=1.5) opt_problem.driver.add_desvar('d_s', lower=0.1, upper=1.5) opt_problem.driver.add_desvar('t_ws', lower=0.001, upper=0.2) # set up constraints for the PMSG_arms generator opt_problem.driver.add_constraint('B_symax',upper=2.0-1.0e-6) #1 opt_problem.driver.add_constraint('B_rymax',upper=2.0-1.0e-6) #2 opt_problem.driver.add_constraint('B_tmax',upper=2.0-1.0e-6) #3 opt_problem.driver.add_constraint('B_gfm',lower=0.617031,upper=1.057768) #4 opt_problem.driver.add_constraint('B_g',lower=0.7,upper=1.2) #5 opt_problem.driver.add_constraint('B_pc',upper=2.0) #6 opt_problem.driver.add_constraint('E_s',lower=500.0,upper=5000.0) #7 opt_problem.driver.add_constraint('con_uAs',lower=0.0+1.0e-6) #8 opt_problem.driver.add_constraint('con_zAs',lower=0.0+1.0e-6) #9 opt_problem.driver.add_constraint('con_yAs',lower=0.0+1.0e-6) #10 opt_problem.driver.add_constraint('con_uAr',lower=0.0+1.0e-6) #11 opt_problem.driver.add_constraint('con_zAr',lower=0.0+1.0e-6) #12 opt_problem.driver.add_constraint('con_yAr',lower=0.0+1.0e-6) #13 opt_problem.driver.add_constraint('con_TC2',lower=0.0+1.0e-6) #14 opt_problem.driver.add_constraint('con_TC3',lower=0.0+1e-6) #15 opt_problem.driver.add_constraint('con_br',lower=0.0+1e-6) #16 opt_problem.driver.add_constraint('con_bst',lower=0.0-1e-6) #17 opt_problem.driver.add_constraint('A_1',upper=60000.0-1e-6) #18 opt_problem.driver.add_constraint('J_s',upper=6.0) #19 opt_problem.driver.add_constraint('J_f',upper=6.0) #20 opt_problem.driver.add_constraint('A_Cuscalc',lower=5.0,upper=300) #22 opt_problem.driver.add_constraint('A_Curcalc',lower=10,upper=300) #23 opt_problem.driver.add_constraint('K_rad',lower=0.2+1e-6,upper=0.27) #24 opt_problem.driver.add_constraint('Slot_aspect_ratio',lower=4.0,upper=10.0)#25 opt_problem.driver.add_constraint('gen_eff',lower=Eta_Target) #26 opt_problem.driver.add_constraint('n_brushes',upper=6) #27 opt_problem.driver.add_constraint('Power_ratio',upper=2-1.0e-6) #28 opt_problem.setup() # Specify Target machine parameters opt_problem['machine_rating']=5000000.0 opt_problem['Torque']=4.143289e6 opt_problem['n_nom']=12.1 # Initial design variables opt_problem['r_s']=3.2 opt_problem['l_s']=1.4 opt_problem['h_s']= 0.060 opt_problem['tau_p']= 0.170 opt_problem['I_f']= 69 opt_problem['N_f']= 100 opt_problem['h_ys']= 0.130 opt_problem['h_yr']= 0.120 opt_problem['n_s']= 5 opt_problem['b_st']= 0.470 opt_problem['n_r']=5 opt_problem['b_r']= 0.480 opt_problem['d_r']= 0.510 opt_problem['d_s']= 0.400 opt_problem['t_wr']=0.140 opt_problem['t_ws']=0.070 opt_problem['R_o']=0.43 #10MW: 0.523950817,#5MW: 0.43, #3MW:0.363882632 #1.5MW: 0.2775 0.75MW: 0.17625 # Costs opt_problem['C_Cu']=4.786 opt_problem['C_Fe']= 0.556 opt_problem['C_Fes']=0.50139 #Material properties opt_problem['rho_Fe']= 7700 #Magnetic Steel/iron density opt_problem['rho_Fes']= 7850 #structural Steel density opt_problem['rho_Copper']=8900 # Kg/m3 copper density opt_problem['main_shaft_cm']=np.array([0.0, 0.0, 0.0]) opt_problem['main_shaft_length'] =2.0 #Run optimization opt_problem.run() """Uncomment to print solution to screen/an excel file
def setup_energy_opt(num_seg, order, Q_env=0., Q_sink=0., Q_out=0., m_flow=0.1, m_burn=0., opt_m_flow=False, opt_m_burn=False): """ Helper function to set up and return a problem instance for an energy minimization of a simple thermal system. Parameters ---------- num_seg : int The number of ODE segments to use when discretizing the problem. order : int The order for the polynomial interpolation for the collocation methods. """ # Instantiate the problem and set the optimizer p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = 'SNOPT' p.driver.opt_settings['Major iterations limit'] = 2000 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-7 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-7 p.driver.opt_settings['Verify level'] = -1 # Set up the phase for the defined ODE function, can be LGR or LGL phase = Phase('gauss-lobatto', ode_class=TankAloneODE, ode_init_kwargs={}, num_segments=num_seg, transcription_order=order, compressed=True) # Do not allow the time to vary during the optimization phase.set_time_options(opt_initial=False, opt_duration=False) # Set the state options for mass, temperature, and energy. phase.set_state_options('m', lower=1., upper=10., fix_initial=False) phase.set_state_options('T', fix_initial=True) phase.set_state_options('energy', fix_initial=True) # Minimize the energy used to pump the fuel # phase.add_objective('energy', loc='final') # phase.add_objective('m', loc='initial') phase.add_objective('time', loc='final') # Allow the optimizer to vary the fuel flow if opt_m_flow: phase.add_control('m_flow', val=m_flow, lower=0.01, opt=True, rate_continuity=True) else: phase.add_control('m_flow', val=m_flow, opt=False) if opt_m_burn: phase.add_control('m_burn', val=m_burn, lower=0.01, opt=True, rate_continuity=True) else: phase.add_control('m_burn', val=m_burn, opt=False) phase.add_control('Q_env', val=Q_env, dynamic=False, opt=False) phase.add_control('Q_sink', val=Q_sink, dynamic=False, opt=False) phase.add_control('Q_out', val=Q_out, dynamic=False, opt=False) # Constrain the temperature, 2nd derivative of fuel mass in the tank, and make # sure that the amount recirculated is at least 0, otherwise we'd burn # more fuel than we pumped. if opt_m_flow: phase.add_path_constraint('T', upper=1.) phase.add_path_constraint('m_flow_rate', upper=0.) phase.add_path_constraint('m_recirculated', lower=0.) phase.add_path_constraint('m_flow', upper=3.) # Add the phase to the problem and set it up p.model.add_subsystem('phase', phase) p.driver.add_recorder(SqliteRecorder('out.db')) p.setup(check=True, force_alloc_complex=True, mode='fwd') # Give initial values for the phase states, controls, and time p['phase.states:m'] = 2. p['phase.states:T'] = 1. p['phase.states:energy'] = 0. p['phase.t_initial'] = 0. p['phase.t_duration'] = 10. p.set_solver_print(level=-1) return p
num_inputs = nn elif 'bandwidth' in varied_term: bandwidth = nn print( f'Running {num_repeats} cases of {num_inputs} num_inputs, {num_outputs} num_outputs, {bandwidth} bandwidth' ) prob = om.Problem() prob.model = MatrixGroup(comp_type=MatrixComp, num_inputs=num_inputs, num_outputs=num_outputs, bandwidth=bandwidth, random_seed=random_seed) prob.driver = om.pyOptSparseDriver() prob.driver.options['optimizer'] = 'SNOPT' prob.driver.opt_settings['Major optimality tolerance'] = 1e-8 prob.driver.opt_settings['Major print level'] = 0 prob.driver.opt_settings['Minor print level'] = 0 prob.driver.opt_settings['iPrint'] = 0 prob.model.add_design_var('x', lower=-10, upper=10) prob.model.add_objective('obj') if 'inputs' in varied_term or 'bandwidth' in varied_term: prob.setup(mode='rev') else: prob.setup(mode='fwd') prob['x'][:] = 2.
def test_ssto_simulate_root_trajectory(self): """ Tests that we can properly simulate a trajectory even if the trajectory is the root group of the model. In this case the name of the trajectory in the output will be 'sim_traj'. """ import numpy as np import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm g = 1.61544 # lunar gravity, m/s**2 class LaunchVehicle2DEOM(om.ExplicitComponent): """ Simple 2D Cartesian Equations of Motion for a launch vehicle subject to thrust and drag. """ def initialize(self): self.options.declare('num_nodes', types=int) def setup(self): nn = self.options['num_nodes'] # Inputs self.add_input('vx', val=np.zeros(nn), desc='x velocity', units='m/s') self.add_input('vy', val=np.zeros(nn), desc='y velocity', units='m/s') self.add_input('m', val=np.zeros(nn), desc='mass', units='kg') self.add_input('theta', val=np.zeros(nn), desc='pitch angle', units='rad') self.add_input('thrust', val=2100000 * np.ones(nn), desc='thrust', units='N') self.add_input('Isp', val=265.2 * np.ones(nn), desc='specific impulse', units='s') # Outputs self.add_output('xdot', val=np.zeros(nn), desc='velocity component in x', units='m/s') self.add_output('ydot', val=np.zeros(nn), desc='velocity component in y', units='m/s') self.add_output('vxdot', val=np.zeros(nn), desc='x acceleration magnitude', units='m/s**2') self.add_output('vydot', val=np.zeros(nn), desc='y acceleration magnitude', units='m/s**2') self.add_output('mdot', val=np.zeros(nn), desc='mass rate of change', units='kg/s') # Setup partials ar = np.arange(self.options['num_nodes']) self.declare_partials(of='xdot', wrt='vx', rows=ar, cols=ar, val=1.0) self.declare_partials(of='ydot', wrt='vy', rows=ar, cols=ar, val=1.0) self.declare_partials(of='vxdot', wrt='vx', rows=ar, cols=ar) self.declare_partials(of='vxdot', wrt='m', rows=ar, cols=ar) self.declare_partials(of='vxdot', wrt='theta', rows=ar, cols=ar) self.declare_partials(of='vxdot', wrt='thrust', rows=ar, cols=ar) self.declare_partials(of='vydot', wrt='m', rows=ar, cols=ar) self.declare_partials(of='vydot', wrt='theta', rows=ar, cols=ar) self.declare_partials(of='vydot', wrt='vy', rows=ar, cols=ar) self.declare_partials(of='vydot', wrt='thrust', rows=ar, cols=ar) self.declare_partials(of='mdot', wrt='thrust', rows=ar, cols=ar) self.declare_partials(of='mdot', wrt='Isp', rows=ar, cols=ar) def compute(self, inputs, outputs): theta = inputs['theta'] cos_theta = np.cos(theta) sin_theta = np.sin(theta) vx = inputs['vx'] vy = inputs['vy'] m = inputs['m'] F_T = inputs['thrust'] Isp = inputs['Isp'] outputs['xdot'] = vx outputs['ydot'] = vy outputs['vxdot'] = F_T * cos_theta / m outputs['vydot'] = F_T * sin_theta / m - g outputs['mdot'] = -F_T / (g * Isp) def compute_partials(self, inputs, jacobian): theta = inputs['theta'] cos_theta = np.cos(theta) sin_theta = np.sin(theta) m = inputs['m'] F_T = inputs['thrust'] Isp = inputs['Isp'] # jacobian['vxdot', 'vx'] = -CDA * rho * vx / m jacobian['vxdot', 'm'] = -(F_T * cos_theta) / m**2 jacobian['vxdot', 'theta'] = -(F_T / m) * sin_theta jacobian['vxdot', 'thrust'] = cos_theta / m # jacobian['vydot', 'vy'] = -CDA * rho * vy / m jacobian['vydot', 'm'] = -(F_T * sin_theta) / m**2 jacobian['vydot', 'theta'] = (F_T / m) * cos_theta jacobian['vydot', 'thrust'] = sin_theta / m jacobian['mdot', 'thrust'] = -1.0 / (g * Isp) jacobian['mdot', 'Isp'] = F_T / (g * Isp**2) class LaunchVehicleLinearTangentODE(om.Group): """ The LaunchVehicleLinearTangentODE for this case consists of a guidance component and the EOM. Guidance is simply an OpenMDAO ExecComp which computes the arctangent of the tan_theta variable. """ def initialize(self): self.options.declare( 'num_nodes', types=int, desc='Number of nodes to be evaluated in the RHS') def setup(self): nn = self.options['num_nodes'] self.add_subsystem( 'guidance', om.ExecComp('theta=arctan(tan_theta)', theta={ 'value': np.ones(nn), 'units': 'rad' }, tan_theta={'value': np.ones(nn)})) self.add_subsystem('eom', LaunchVehicle2DEOM(num_nodes=nn)) self.connect('guidance.theta', 'eom.theta') # # Setup and solve the optimal control problem # traj = dm.Trajectory() p = om.Problem(model=traj) phase = dm.Phase(ode_class=LaunchVehicleLinearTangentODE, transcription=dm.Radau(num_segments=20, order=3, compressed=False)) traj.add_phase('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(10, 1000), units='s') # # Set the state options. We include rate_source, units, and targets here since the ODE # is not decorated with their default values. # phase.add_state('x', fix_initial=True, lower=0, rate_source='eom.xdot') phase.add_state('y', fix_initial=True, lower=0, rate_source='eom.ydot') phase.add_state('vx', fix_initial=True, lower=0, rate_source='eom.vxdot', units='m/s', targets=['eom.vx']) phase.add_state('vy', fix_initial=True, rate_source='eom.vydot', units='m/s', targets=['eom.vy']) phase.add_state('m', fix_initial=True, rate_source='eom.mdot', units='kg', targets=['eom.m']) # # The tangent of theta is modeled as a linear polynomial over the duration of the phase. # phase.add_polynomial_control('tan_theta', order=1, units=None, opt=True, targets=['guidance.tan_theta']) # # Parameters values for thrust and specific impulse are design parameters. They are # provided by an IndepVarComp in the phase, but with opt=False their values are not # design variables in the optimization problem. # phase.add_parameter('thrust', units='N', opt=False, val=3.0 * 50000.0 * 1.61544, targets=['eom.thrust']) phase.add_parameter('Isp', units='s', opt=False, val=1.0E6, targets=['eom.Isp']) # # Set the boundary constraints. These are all states which could also be handled # by setting fix_final=True and including the correct final value in the initial guess. # phase.add_boundary_constraint('y', loc='final', equals=1.85E5, linear=True) phase.add_boundary_constraint('vx', loc='final', equals=1627.0) phase.add_boundary_constraint('vy', loc='final', equals=0) phase.add_objective('time', index=-1, scaler=0.01) # # Add theta as a timeseries output since it's not included by default. # phase.add_timeseries_output('guidance.theta', units='deg') # # Set the optimizer # p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() # # We don't strictly need to define a linear solver here since our problem is entirely # feed-forward with no iterative loops. It's good practice to add one, however, since # failing to do so can cause incorrect derivatives if iterative processes are ever # introduced to the system. # p.model.linear_solver = om.DirectSolver() p.setup(check=True) # # Assign initial guesses for the independent variables in the problem. # p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 500.0 p['phase0.states:x'] = phase.interp('x', [0, 350000.0]) p['phase0.states:y'] = phase.interp('y', [0, 185000.0]) p['phase0.states:vx'] = phase.interp('vx', [0, 1627.0]) p['phase0.states:vy'] = phase.interp('vy', [1.0E-6, 0]) p['phase0.states:m'] = phase.interp('m', [50000, 50000]) p['phase0.polynomial_controls:tan_theta'] = [[0.5 * np.pi], [0.0]] # # Solve the problem. # p.run_driver() # # Check the results. # assert_near_equal(p.get_val('phase0.timeseries.time')[-1], 481, tolerance=0.01) # # Get the explitly simulated results # exp_out = traj.simulate() # # Plot the results # fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(10, 8)) axes[0].plot(p.get_val('phase0.timeseries.states:x'), p.get_val('phase0.timeseries.states:y'), marker='o', ms=4, linestyle='None', label='solution') axes[0].plot(exp_out.get_val('sim_traj.phase0.timeseries.states:x'), exp_out.get_val('sim_traj.phase0.timeseries.states:y'), marker=None, linestyle='-', label='simulation') axes[0].set_xlabel('range (m)') axes[0].set_ylabel('altitude (m)') axes[0].set_aspect('equal') axes[1].plot(p.get_val('phase0.timeseries.time'), p.get_val('phase0.timeseries.theta'), marker='o', ms=4, linestyle='None') axes[1].plot(exp_out.get_val('sim_traj.phase0.timeseries.time'), exp_out.get_val('sim_traj.phase0.timeseries.theta'), linestyle='-', marker=None) axes[1].set_xlabel('time (s)') axes[1].set_ylabel('theta (deg)') plt.suptitle( 'Single Stage to Orbit Solution Using Polynomial Controls') fig.legend(loc='lower center', ncol=2) plt.show()
def test_static_parameter_connections_radau(self): class TrajectoryODE(om.Group): def initialize(self): self.options.declare('num_nodes', types=int) def setup(self): nn = self.options['num_nodes'] self.add_subsystem( 'sum', om.ExecComp('m_tot = sum(m)', m={ 'val': np.zeros((2, 2)), 'units': 'kg' }, m_tot={ 'val': np.zeros(nn), 'units': 'kg' })) self.add_subsystem('eom', FlightPathEOM2D(num_nodes=nn)) self.connect('sum.m_tot', 'eom.m') optimizer = 'SLSQP' num_segments = 1 transcription_order = 5 p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = optimizer p.driver.declare_coloring() seg_ends, _ = lgl(num_segments + 1) phase = dm.Phase(ode_class=TrajectoryODE, transcription=dm.Radau(num_segments=num_segments, order=transcription_order, segment_ends=seg_ends)) p.model.add_subsystem('phase0', phase) phase.set_time_options(initial_bounds=(0.0, 100.0), duration_bounds=(0., 100.)) phase.add_state('h', fix_initial=True, fix_final=True, lower=0.0, units='m', rate_source='eom.h_dot') phase.add_state('v', fix_initial=True, fix_final=False, units='m/s', rate_source='eom.v_dot') phase.add_parameter('m', val=[[1, 2], [3, 4]], units='kg', targets='sum.m', static_target=True) p.model.linear_solver = om.DirectSolver() p.setup(check=True, force_alloc_complex=True) p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 100.0 p['phase0.states:h'] = phase.interp('h', [20, 0]) p['phase0.states:v'] = phase.interp('v', [0, -5]) p.run_model() expected = np.array([[1, 2], [3, 4]]) assert_near_equal(p.get_val('phase0.rhs_all.sum.m'), expected)
def test_steady_aircraft_for_docs(self): import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.aircraft_steady_flight.aircraft_ode import AircraftODE from dymos.examples.plotting import plot_results from dymos.utils.lgl import lgl p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() num_seg = 15 seg_ends, _ = lgl(num_seg + 1) traj = p.model.add_subsystem('traj', dm.Trajectory()) phase = traj.add_phase( 'phase0', dm.Phase(ode_class=AircraftODE, transcription=dm.Radau(num_segments=num_seg, segment_ends=seg_ends, order=3, compressed=False))) # Pass Reference Area from an external source assumptions = p.model.add_subsystem('assumptions', om.IndepVarComp()) assumptions.add_output('S', val=427.8, units='m**2') assumptions.add_output('mass_empty', val=1.0, units='kg') assumptions.add_output('mass_payload', val=1.0, units='kg') phase.set_time_options(fix_initial=True, duration_bounds=(300, 10000), duration_ref=5600) phase.add_state('range', units='NM', rate_source='range_rate_comp.dXdt:range', fix_initial=True, fix_final=False, ref=1e-3, defect_ref=1e-3, lower=0, upper=2000) phase.add_state('mass_fuel', units='lbm', rate_source='propulsion.dXdt:mass_fuel', fix_initial=True, fix_final=True, upper=1.5E5, lower=0.0, ref=1e2, defect_ref=1e2) phase.add_state('alt', units='kft', rate_source='climb_rate', fix_initial=True, fix_final=True, lower=0.0, upper=60, ref=1e-3, defect_ref=1e-3) phase.add_control('climb_rate', units='ft/min', opt=True, lower=-3000, upper=3000, targets=['gam_comp.climb_rate'], rate_continuity=True, rate2_continuity=False) phase.add_control('mach', targets=['tas_comp.mach', 'aero.mach'], units=None, opt=False) phase.add_parameter( 'S', targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'], units='m**2') phase.add_parameter('mass_empty', targets=['mass_comp.mass_empty'], units='kg') phase.add_parameter('mass_payload', targets=['mass_comp.mass_payload'], units='kg') phase.add_path_constraint('propulsion.tau', lower=0.01, upper=2.0, shape=(1, )) p.model.connect('assumptions.S', 'traj.phase0.parameters:S') p.model.connect('assumptions.mass_empty', 'traj.phase0.parameters:mass_empty') p.model.connect('assumptions.mass_payload', 'traj.phase0.parameters:mass_payload') phase.add_objective('range', loc='final', ref=-1.0e-4) phase.add_timeseries_output('aero.CL', units=None, shape=(1, )) phase.add_timeseries_output('aero.CD', units=None, shape=(1, )) p.setup() p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 3600.0 p['traj.phase0.states:range'][:] = phase.interpolate( ys=(0, 724.0), nodes='state_input') p['traj.phase0.states:mass_fuel'][:] = phase.interpolate( ys=(30000, 1e-3), nodes='state_input') p['traj.phase0.states:alt'][:] = 10.0 p['traj.phase0.controls:mach'][:] = 0.8 p['assumptions.S'] = 427.8 p['assumptions.mass_empty'] = 0.15E6 p['assumptions.mass_payload'] = 84.02869 * 400 dm.run_problem(p) assert_near_equal(p.get_val('traj.phase0.timeseries.states:range', units='NM')[-1], 726.85, tolerance=1.0E-2) exp_out = traj.simulate() plot_results( [('traj.phase0.timeseries.states:range', 'traj.phase0.timeseries.states:alt', 'range (NM)', 'altitude (kft)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:mass_fuel', 'time (s)', 'fuel mass (lbm)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.CL', 'time (s)', 'lift coefficient'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.CD', 'time (s)', 'drag coefficient')], title='Commercial Aircraft Optimization', p_sol=p, p_sim=exp_out) plt.show()
def test_min_time_climb_for_docs_partial_coloring(self): import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.min_time_climb.doc.min_time_climb_ode_partial_coloring import MinTimeClimbODE for fd in (False, True): if fd: pc_options = (False, True) else: pc_options = (False, ) for pc in pc_options: with self.subTest( f'Finite Differencing: {fd} Partial Coloring: {pc}'): print(f'Finite Differencing: {fd} Partial Coloring: {pc}') # # Instantiate the problem and configure the optimization driver # p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'IPOPT' p.driver.declare_coloring(tol=1.0E-12) p.driver.opt_settings['max_iter'] = 500 p.driver.opt_settings[ 'alpha_for_y'] = 'safer-min-dual-infeas' # # Instantiate the trajectory and phase # traj = dm.Trajectory() phase = dm.Phase( ode_class=MinTimeClimbODE, ode_init_kwargs={ 'fd': fd, 'partial_coloring': pc }, transcription=dm.GaussLobatto(num_segments=30)) traj.add_phase('phase0', phase) p.model.add_subsystem('traj', traj) # # Set the options on the optimization variables # phase.set_time_options(fix_initial=True, duration_bounds=(50, 400), duration_ref=100.0) phase.add_state('r', fix_initial=True, lower=0, upper=1.0E6, ref=1.0E3, defect_ref=1.0E3, units='m', rate_source='flight_dynamics.r_dot') phase.add_state('h', fix_initial=True, lower=0, upper=20000.0, ref=1.0E2, defect_ref=1.0E2, units='m', rate_source='flight_dynamics.h_dot') phase.add_state('v', fix_initial=True, lower=10.0, ref=1.0E2, defect_ref=1.0E2, units='m/s', rate_source='flight_dynamics.v_dot') phase.add_state('gam', fix_initial=True, lower=-1.5, upper=1.5, ref=1.0, defect_ref=1.0, units='rad', rate_source='flight_dynamics.gam_dot') phase.add_state('m', fix_initial=True, lower=10.0, upper=1.0E5, ref=1.0E3, defect_ref=1.0E3, units='kg', rate_source='prop.m_dot') phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, rate_continuity=True, rate_continuity_scaler=100.0, rate2_continuity=False, targets=['alpha']) phase.add_parameter('S', val=49.2386, units='m**2', opt=False, targets=['S']) phase.add_parameter('Isp', val=1600.0, units='s', opt=False, targets=['Isp']) phase.add_parameter('throttle', val=1.0, opt=False, targets=['throttle']) # # Setup the boundary and path constraints # phase.add_boundary_constraint('h', loc='final', equals=20000, scaler=1.0E-3) phase.add_boundary_constraint('aero.mach', loc='final', equals=1.0) phase.add_boundary_constraint('gam', loc='final', equals=0.0) phase.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000) phase.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8) # Minimize time at the end of the phase phase.add_objective('time', loc='final', ref=100.0) p.model.linear_solver = om.DirectSolver() # # Setup the problem and set the initial guess # p.setup() p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 500 p['traj.phase0.states:r'] = phase.interp( 'r', [0.0, 50000.0]) p['traj.phase0.states:h'] = phase.interp( 'h', [100.0, 20000.0]) p['traj.phase0.states:v'] = phase.interp( 'v', [135.964, 283.159]) p['traj.phase0.states:gam'] = phase.interp( 'gam', [0.0, 0.0]) p['traj.phase0.states:m'] = phase.interp( 'm', [19030.468, 10000.]) p['traj.phase0.controls:alpha'] = phase.interp( 'alpha', [0.0, 0.0]) # # Solve for the optimal trajectory # dm.run_problem(p) # # This code is intended to save the coloring plots for the documentation. # In practice, use the command line interface to view these files instead: # `openmdao view_coloring coloring_files/total_coloring.pkl --view` # stfd = '_fd' if fd else '' stpc = '_pc' if pc else '' coloring_dir = f'coloring_files{stfd}{stpc}' if fd or pc: if os.path.exists(coloring_dir): shutil.rmtree(coloring_dir) shutil.move('coloring_files', coloring_dir) _view_coloring( os.path.join(coloring_dir, 'total_coloring.pkl')) # # Test the results # assert_near_equal(p.get_val('traj.phase0.t_duration'), 321.0, tolerance=1.0E-1)
def setUp(self): solver = 'SLSQP' num_seg = 10 seg_ncn = 2 rel_lengths = 'lgl' # Instantiate a problem and set it's root to an empty Trajectory prob = Problem() prob.add_traj(Trajectory("traj0")) if solver == 'SNOPT' and pyOptSparseDriver is not None: driver = pyOptSparseDriver() driver.options['optimizer'] = solver driver.opt_settings['Major iterations limit'] = 1000 driver.opt_settings['iSumm'] = 6 driver.opt_settings['Major step limit'] = 0.5 driver.opt_settings["Major feasibility tolerance"] = 1.0E-5 driver.opt_settings["Major optimality tolerance"] = 1.0E-5 driver.opt_settings["Minor feasibility tolerance"] = 1.0E-4 driver.opt_settings['Verify level'] = 3 else: driver = ScipyOptimizer() driver.options['tol'] = 1.0E-6 driver.options['disp'] = True driver.options['maxiter'] = 500 prob.driver = driver dynamic_controls = [{'name': 'theta', 'units': 'rad'}, {'name': 'psi', 'units': 'rad'}] static_controls = [{'name': 'mass', 'units': 'kg'}, {'name': 'g', 'units': 'm/s/s'}, {'name': 'Cd', 'units': 'unitless'}, {'name': 'D_magnetic', 'units': 'N'}, {'name': 'R', 'units': 'J/(kg*K)'}, {'name': 'S', 'units': 'm**2'}, {'name': 'T_ambient', 'units': 'K'}, {'name': 'p_tube', 'units': 'Pa'}] phase0 = CollocationPhase(name='phase0', rhs_class=MagnePlaneRHS, num_seg=num_seg, seg_ncn=seg_ncn, rel_lengths=rel_lengths, dynamic_controls=dynamic_controls, static_controls=static_controls) prob.trajectories["traj0"].add_phase(phase0) phase0.set_state_options('x', lower=0, upper=100, ic_val=0, ic_fix=True, fc_val=10, fc_fix=True, scaler=10.0, defect_scaler=0.1) phase0.set_state_options('y', lower=0, upper=0, ic_val=0, ic_fix=True, fc_val=0, fc_fix=True, scaler=10.0, defect_scaler=0.1) phase0.set_state_options('z', lower=-10, upper=10, ic_val=-10, ic_fix=True, fc_val=-5, fc_fix=True, scaler=10.0, defect_scaler=0.1) phase0.set_state_options('v', lower=0, upper=np.inf, ic_val=0.0, ic_fix=True, fc_val=10.0, fc_fix=False, scaler=10.0, defect_scaler=0.1) phase0.set_dynamic_control_options('theta', ic_val=-1.57, fc_val=0.2, opt=True, lower=-1.58, upper=1.58, scaler=0.01) phase0.set_dynamic_control_options('psi', ic_val=0.0, fc_val=0.0, opt=True, lower=0.0, upper=0.0, scaler=0.01) phase0.set_static_control_options(name='g', val=9.80665, opt=False) phase0.set_static_control_options(name='mass', val=1200, opt=False) phase0.set_static_control_options(name='Cd', val=0.0, opt=False) phase0.set_static_control_options(name='S', val=0.0, opt=False) phase0.set_static_control_options(name='p_tube', val=0.0, opt=False) phase0.set_static_control_options(name='T_ambient', val=298.0, opt=False) phase0.set_static_control_options(name='R', val=287.0, opt=False) # Set D_magnetic equal to the thrust value for now, no net forces # on the pod except gravity. phase0.set_static_control_options(name='D_magnetic', val=30000.0, opt=False) phase0.set_time_options(t0_val=0, t0_lower=0, t0_upper=0, tp_val=1.81, tp_lower=0.5, tp_upper=10.0) prob.trajectories["traj0"].add_objective(name="t", phase="phase0", place="end", scaler=1.0) # Do top-level FD prob.root.deriv_options['type'] = 'fd' self.prob = prob
if __name__ == '__main__': # Setup and run the model. from openmdao.core.problem import Problem from openmdao.drivers.scipy_optimizer import ScipyOptimizer from openmdao.api import pyOptSparseDriver from openmdao.api import SqliteRecorder top = Problem() top.root = SellarDerivatives() # top.driver = ScipyOptimizer() # top.driver.options['optimizer'] = 'SLSQP' # top.driver.options['tol'] = 1.0e-8 top.driver = pyOptSparseDriver() top.driver.options['optimizer'] = 'SNOPT' top.driver.add_desvar('z', lower=np.array([-10.0, 0.0]), upper=np.array([10.0, 10.0])) top.driver.add_desvar('x', lower=0.0, upper=10.0) top.driver.add_objective('obj') top.driver.add_constraint('con1', upper=0.0) top.driver.add_constraint('con2', upper=0.0) rec = SqliteRecorder('sellar_snopt.db') top.driver.add_recorder(rec) rec.options['record_derivs'] = True top.setup()
def test_simple_no_exception(self): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() transcription = dm.GaussLobatto(num_segments=3, order=3, compressed=True, solve_segments='forward') fix_final = True traj = dm.Trajectory() phase = dm.Phase(ode_class=BrachistochroneVectorStatesODE, transcription=transcription) traj.add_phase('phase0', phase) p.model.add_subsystem('traj0', traj) phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10), units='s') # can't fix final position if you're solving the segments phase.add_state('pos', rate_source='pos_dot', units='m', fix_initial=True) # test add_boundary_constraint with arrays: expected = np.array([10, 5]) phase.add_boundary_constraint(name='pos', loc='final', lower=expected - 1) phase.add_boundary_constraint(name='pos', loc='final', upper=expected + 1) phase.add_boundary_constraint(name='pos', loc='final', equals=expected) phase.add_state('v', rate_source='vdot', units='m/s', fix_initial=True, fix_final=False) phase.add_control('theta', continuity=True, rate_continuity=True, units='deg', lower=0.01, upper=179.9) phase.add_parameter('g', units='m/s**2', val=9.80665, opt=False) # Minimize time at the end of the phase phase.add_objective('time', loc='final', scaler=10) p.model.linear_solver = om.DirectSolver() p.setup(check=True, force_alloc_complex=True) p.final_setup() p['traj0.phase0.t_initial'] = 0.0 p['traj0.phase0.t_duration'] = 1.8016 pos0 = [0, 10] posf = [10, 5] p['traj0.phase0.states:pos'] = phase.interpolate(ys=[pos0, posf], nodes='state_input') p['traj0.phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input') p['traj0.phase0.controls:theta'] = phase.interpolate( ys=[5, 100], nodes='control_input') p['traj0.phase0.parameters:g'] = 9.80665 p.run_driver()
def test_radau(self): p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() t = dm.Radau(num_segments=20, order=[3, 5] * 10, compressed=True) 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)) phase.add_state( 'x', rate_source=BrachistochroneODE.states['x']['rate_source'], units=BrachistochroneODE.states['x']['units'], fix_initial=True, fix_final=False, solve_segments=False) phase.add_state( 'y', rate_source=BrachistochroneODE.states['y']['rate_source'], units=BrachistochroneODE.states['y']['units'], fix_initial=True, fix_final=False, solve_segments=False) phase.add_state( 'v', rate_source=BrachistochroneODE.states['v']['rate_source'], targets=BrachistochroneODE.states['v']['targets'], units=BrachistochroneODE.states['v']['units'], fix_initial=True, fix_final=False, solve_segments=False) phase.add_control( 'theta', targets=BrachistochroneODE.parameters['theta']['targets'], continuity=True, rate_continuity=True, units='deg', lower=0.01, upper=179.9) phase.add_input_parameter( 'g', targets=BrachistochroneODE.parameters['g']['targets'], units='m/s**2', val=9.80665) 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.input_parameters:g'] = 9.80665 p.run_driver() exp_out = phase.simulate() t_initial = p.get_val('phase0.timeseries.time')[0] tf = p.get_val('phase0.timeseries.time')[-1] x0 = p.get_val('phase0.timeseries.states:x')[0] xf = p.get_val('phase0.timeseries.states:x')[-1] y0 = p.get_val('phase0.timeseries.states:y')[0] yf = p.get_val('phase0.timeseries.states:y')[-1] v0 = p.get_val('phase0.timeseries.states:v')[0] vf = p.get_val('phase0.timeseries.states:v')[-1] g = p.get_val('phase0.timeseries.input_parameters:g')[0] thetaf = exp_out.get_val('phase0.timeseries.controls:theta')[-1] assert_almost_equal(t_initial, 0.0) assert_almost_equal(x0, 0.0) assert_almost_equal(y0, 10.0) assert_almost_equal(v0, 0.0) assert_almost_equal(tf, 1.8016, decimal=3) assert_almost_equal(xf, 10.0, decimal=3) assert_almost_equal(yf, 5.0, decimal=3) assert_almost_equal(vf, 9.902, decimal=3) assert_almost_equal(g, 9.80665, decimal=3) assert_almost_equal(thetaf, 100.12, decimal=0)
def min_time_climb(optimizer='SLSQP', num_seg=3, transcription='gauss-lobatto', transcription_order=3, top_level_jacobian='csc', simul_derivs=True, force_alloc_complex=False): p = Problem(model=Group()) p.driver = pyOptSparseDriver() p.driver.options['optimizer'] = optimizer if simul_derivs: p.driver.options['dynamic_simul_derivs'] = True if optimizer == 'SNOPT': p.driver.opt_settings['Major iterations limit'] = 1000 p.driver.opt_settings['iSumm'] = 6 p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6 p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6 p.driver.opt_settings['Function precision'] = 1.0E-6 p.driver.opt_settings['Linesearch tolerance'] = 0.10 p.driver.opt_settings['Major step limit'] = 0.5 # p.driver.opt_settings['Verify level'] = 3 phase = Phase(transcription, ode_class=MinTimeClimbODE, num_segments=num_seg, compressed=True, transcription_order=transcription_order) p.model.add_subsystem('phase0', phase) phase.set_time_options(fix_initial=True, duration_bounds=(50, 400), duration_ref=100.0) phase.set_state_options('r', fix_initial=True, lower=0, upper=1.0E6, scaler=1.0E-3, defect_scaler=1.0E-2, units='m') phase.set_state_options('h', fix_initial=True, lower=0, upper=20000.0, scaler=1.0E-3, defect_scaler=1.0E-3, units='m') phase.set_state_options('v', fix_initial=True, lower=10.0, scaler=1.0E-2, defect_scaler=1.0E-2, units='m/s') phase.set_state_options('gam', fix_initial=True, lower=-1.5, upper=1.5, ref=1.0, defect_scaler=1.0, units='rad') phase.set_state_options('m', fix_initial=True, lower=10.0, upper=1.0E5, scaler=1.0E-3, defect_scaler=1.0E-3) phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, continuity=True, rate_continuity=True, rate2_continuity=False) phase.add_design_parameter('S', val=49.2386, units='m**2', opt=False) phase.add_design_parameter('Isp', val=1600.0, units='s', opt=False) phase.add_design_parameter('throttle', val=1.0, opt=False) phase.add_boundary_constraint('h', loc='final', equals=20000, scaler=1.0E-3, units='m') phase.add_boundary_constraint('aero.mach', loc='final', equals=1.0, units=None) phase.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad') phase.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000) phase.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8) phase.add_path_constraint(name='alpha', lower=-8, upper=8) # Minimize time at the end of the phase phase.add_objective('time', loc='final') p.model.options['assembled_jac_type'] = top_level_jacobian.lower() p.model.linear_solver = DirectSolver(assemble_jac=True) p.setup(check=True, force_alloc_complex=force_alloc_complex) p['phase0.t_initial'] = 0.0 p['phase0.t_duration'] = 298.46902 p['phase0.states:r'] = phase.interpolate(ys=[0.0, 111319.54], nodes='state_input') p['phase0.states:h'] = phase.interpolate(ys=[100.0, 20000.0], nodes='state_input') p['phase0.states:v'] = phase.interpolate(ys=[135.964, 283.159], nodes='state_input') p['phase0.states:gam'] = phase.interpolate(ys=[0.0, 0.0], nodes='state_input') p['phase0.states:m'] = phase.interpolate(ys=[19030.468, 16841.431], nodes='state_input') p['phase0.controls:alpha'] = phase.interpolate(ys=[0.0, 0.0], nodes='control_input') p.run_driver() if SHOW_PLOTS: exp_out = phase.simulate(times=np.linspace(0, p['phase0.t_duration'], 100)) import matplotlib.pyplot as plt plt.plot(phase.get_values('time'), phase.get_values('h'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('h'), 'b-') plt.xlabel('time (s)') plt.ylabel('altitude (m)') plt.figure() plt.plot(phase.get_values('v'), phase.get_values('h'), 'ro') plt.plot(exp_out.get_values('v'), exp_out.get_values('h'), 'b-') plt.xlabel('airspeed (m/s)') plt.ylabel('altitude (m)') plt.figure() plt.plot(phase.get_values('time'), phase.get_values('alpha'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('alpha'), 'b-') plt.xlabel('time (s)') plt.ylabel('alpha (rad)') plt.figure() plt.plot(phase.get_values('time'), phase.get_values('prop.thrust', units='lbf'), 'ro') plt.plot(exp_out.get_values('time'), exp_out.get_values('prop.thrust', units='lbf'), 'b-') plt.xlabel('time (s)') plt.ylabel('thrust (lbf)') plt.show() return p
import openmdao.api as om from testbed_components import simple_1D_low, simple_1D_high np.random.seed(314) mm = om.MultiFiMetaModelUnStructuredComp(nfi=2) mm.add_input("x", np.zeros((1, ))) mm.add_output("y", np.zeros((1, ))) # Surrrogate model that implements the multifidelity cokriging method. mm.options["default_surrogate"] = om.MultiFiCoKrigingSurrogate(normalize=False) prob = om.Problem() prob.model.add_subsystem("mm", mm, promotes=["*"]) prob.driver = om.pyOptSparseDriver() # om.ScipyOptimizeDriver() # prob.driver.options["optimizer"] = "SNOPT" # prob.driver.opt_settings['Verify level'] = -1 # --- Objective --- prob.model.add_objective("y") prob.model.add_design_var("x", lower=0.0, upper=1.0) prob.setup() prob["x"] = 0.8 s = time() num_high = 5
def test(self): from openaerostruct.geometry.utils import generate_mesh, write_FFD_file from openaerostruct.geometry.geometry_group import Geometry from openaerostruct.transfer.displacement_transfer import DisplacementTransfer from openaerostruct.aerodynamics.aero_groups import AeroPoint from openaerostruct.integration.multipoint_comps import MultiCD from openmdao.api import IndepVarComp, Problem, Group, NewtonSolver, ScipyIterativeSolver, LinearBlockGS, NonlinearBlockGS, DirectSolver, LinearBlockGS, PetscKSP, ScipyOptimizeDriver, ExplicitComponent# TODO, SqliteRecorder, CaseReader, profile from openmdao.devtools import iprofile from openmdao.api import view_model from openmdao.utils.assert_utils import assert_check_partials from pygeo import DVGeometry # Create a dictionary to store options about the surface mesh_dict = {'num_y' : 5, 'num_x' : 3, 'wing_type' : 'CRM', 'symmetry' : True, 'num_twist_cp' : 5, 'span_cos_spacing' : 0.} mesh, _ = generate_mesh(mesh_dict) surf_dict = { # Wing definition 'name' : 'wing', # name of the surface 'type' : 'aero', 'symmetry' : True, # if true, model one half of wing # reflected across the plane y = 0 'S_ref_type' : 'wetted', # how we compute the wing area, # can be 'wetted' or 'projected' 'fem_model_type' : 'tube', 'mesh' : mesh, 'mx' : 2, 'my' : 3, 'geom_manipulator' : 'FFD', # Aerodynamic performance of the lifting surface at # an angle of attack of 0 (alpha=0). # These CL0 and CD0 values are added to the CL and CD # obtained from aerodynamic analysis of the surface to get # the total CL and CD. # These CL0 and CD0 values do not vary wrt alpha. 'CL0' : 0.0, # CL of the surface at alpha=0 'CD0' : 0.015, # CD of the surface at alpha=0 # Airfoil properties for viscous drag calculation 'k_lam' : 0.05, # percentage of chord with laminar # flow, used for viscous drag 't_over_c_cp' : np.array([0.15]), # thickness over chord ratio (NACA0015) 'c_max_t' : .303, # chordwise location of maximum (NACA0015) # thickness 'with_viscous' : True, # if true, compute viscous drag 'with_wave' : False, # if true, compute wave drag } surfaces = [surf_dict] n_points = 2 # Create the problem and the model group prob = Problem() indep_var_comp = IndepVarComp() indep_var_comp.add_output('v', val=248.136, units='m/s') indep_var_comp.add_output('alpha', val=np.ones(n_points)*6.64, units='deg') indep_var_comp.add_output('M', val=0.84) indep_var_comp.add_output('re', val=1.e6, units='1/m') indep_var_comp.add_output('rho', val=0.38, units='kg/m**3') indep_var_comp.add_output('cg', val=np.zeros((3)), units='m') prob.model.add_subsystem('prob_vars', indep_var_comp, promotes=['*']) # Loop through and add a certain number of aero points for i in range(n_points): # Create the aero point group and add it to the model aero_group = AeroPoint(surfaces=surfaces) point_name = 'aero_point_{}'.format(i) prob.model.add_subsystem(point_name, aero_group) # Connect flow properties to the analysis point prob.model.connect('v', point_name + '.v') prob.model.connect('alpha', point_name + '.alpha', src_indices=[i]) prob.model.connect('M', point_name + '.M') prob.model.connect('re', point_name + '.re') prob.model.connect('rho', point_name + '.rho') prob.model.connect('cg', point_name + '.cg') # Connect the parameters within the model for each aero point for surface in surfaces: filename = write_FFD_file(surface, surface['mx'], surface['my']) DVGeo = DVGeometry(filename) geom_group = Geometry(surface=surface, DVGeo=DVGeo) # Add tmp_group to the problem as the name of the surface. # Note that is a group and performance group for each # individual surface. aero_group.add_subsystem(surface['name'] + '_geom', geom_group) name = surface['name'] prob.model.connect(point_name + '.CD', 'multi_CD.' + str(i) + '_CD') # Connect the mesh from the geometry component to the analysis point prob.model.connect(point_name + '.' + name + '_geom.mesh', point_name + '.' + name + '.def_mesh') # Perform the connections with the modified names within the # 'aero_states' group. prob.model.connect(point_name + '.' + name + '_geom.mesh', point_name + '.aero_states.' + name + '_def_mesh') prob.model.connect(point_name + '.' + name + '_geom.t_over_c', point_name + '.' + name + '_perf.' + 't_over_c') prob.model.add_subsystem('multi_CD', MultiCD(n_points=n_points), promotes_outputs=['CD']) from openmdao.api import pyOptSparseDriver prob.driver = pyOptSparseDriver() prob.driver.options['optimizer'] = "SNOPT" prob.driver.opt_settings = {'Major optimality tolerance': 1.0e-5, 'Major feasibility tolerance': 1.0e-5} # # Setup problem and add design variables, constraint, and objective prob.model.add_design_var('alpha', lower=-15, upper=15) prob.model.add_design_var('aero_point_0.wing_geom.shape', lower=-3, upper=2) prob.model.add_constraint('aero_point_0.wing_perf.CL', equals=0.45) prob.model.add_design_var('aero_point_1.wing_geom.shape', lower=-3, upper=2) prob.model.add_constraint('aero_point_1.wing_perf.CL', equals=0.5) prob.model.add_objective('CD', scaler=1e4) # Set up the problem prob.setup() prob.run_model() # Check the partials at this point in the design space data = prob.check_partials(compact_print=True, out_stream=None, method='cs', step=1e-40) assert_check_partials(data, atol=1e20, rtol=1e-6)
def test_min_time_climb_for_docs_gauss_lobatto(self): import matplotlib.pyplot as plt import openmdao.api as om from openmdao.utils.assert_utils import assert_near_equal import dymos as dm from dymos.examples.min_time_climb.min_time_climb_ode import MinTimeClimbODE from dymos.examples.plotting import plot_results # # Instantiate the problem and configure the optimization driver # p = om.Problem(model=om.Group()) p.driver = om.pyOptSparseDriver() p.driver.options['optimizer'] = 'SLSQP' p.driver.declare_coloring() # # Instantiate the trajectory and phase # traj = dm.Trajectory() phase = dm.Phase(ode_class=MinTimeClimbODE, transcription=dm.GaussLobatto(num_segments=15, compressed=False)) traj.add_phase('phase0', phase) p.model.add_subsystem('traj', traj) # # Set the options on the optimization variables # Note the use of explicit state units here since much of the ODE uses imperial units # and we prefer to solve this problem using metric units. # phase.set_time_options(fix_initial=True, duration_bounds=(50, 400), duration_ref=100.0) phase.add_state('r', fix_initial=True, lower=0, upper=1.0E6, units='m', ref=1.0E3, defect_ref=1.0E3, rate_source='flight_dynamics.r_dot') phase.add_state('h', fix_initial=True, lower=0, upper=20000.0, units='m', ref=1.0E2, defect_ref=1.0E2, rate_source='flight_dynamics.h_dot') phase.add_state('v', fix_initial=True, lower=10.0, units='m/s', ref=1.0E2, defect_ref=1.0E2, rate_source='flight_dynamics.v_dot') phase.add_state('gam', fix_initial=True, lower=-1.5, upper=1.5, units='rad', ref=1.0, defect_ref=1.0, rate_source='flight_dynamics.gam_dot') phase.add_state('m', fix_initial=True, lower=10.0, upper=1.0E5, units='kg', ref=1.0E3, defect_ref=1.0E3, rate_source='prop.m_dot') phase.add_control('alpha', units='deg', lower=-8.0, upper=8.0, scaler=1.0, rate_continuity=True, rate_continuity_scaler=100.0, rate2_continuity=False) phase.add_parameter('S', val=49.2386, units='m**2', opt=False, targets=['S']) phase.add_parameter('Isp', val=1600.0, units='s', opt=False, targets=['Isp']) phase.add_parameter('throttle', val=1.0, opt=False, targets=['throttle']) # # Setup the boundary and path constraints # phase.add_boundary_constraint('h', loc='final', equals=20000, scaler=1.0E-3) phase.add_boundary_constraint('aero.mach', loc='final', equals=1.0) phase.add_boundary_constraint('gam', loc='final', equals=0.0) phase.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000) phase.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8) # Minimize time at the end of the phase phase.add_objective('time', loc='final', ref=1.0) p.model.linear_solver = om.DirectSolver() # # Setup the problem and set the initial guess # p.setup(check=True) p['traj.phase0.t_initial'] = 0.0 p['traj.phase0.t_duration'] = 500 p.set_val('traj.phase0.states:r', phase.interp('r', [0.0, 50000.0])) p.set_val('traj.phase0.states:h', phase.interp('h', [100.0, 20000.0])) p.set_val('traj.phase0.states:v', phase.interp('v', [135.964, 283.159])) p.set_val('traj.phase0.states:gam', phase.interp('gam', [0.0, 0.0])) p.set_val('traj.phase0.states:m', phase.interp('m', [19030.468, 10000.])) p.set_val('traj.phase0.controls:alpha', phase.interp('alpha', [0.0, 0.0])) # # Solve for the optimal trajectory # dm.run_problem(p) # # Test the results # assert_near_equal(p.get_val('traj.phase0.t_duration'), 321.0, tolerance=1.0E-1) # # Get the explicitly simulated solution and plot the results # exp_out = traj.simulate() plot_results( [('traj.phase0.timeseries.time', 'traj.phase0.timeseries.states:h', 'time (s)', 'altitude (m)'), ('traj.phase0.timeseries.time', 'traj.phase0.timeseries.controls:alpha', 'time (s)', 'alpha (deg)')], title='Supersonic Minimum Time-to-Climb Solution', p_sol=p, p_sim=exp_out) plt.show()
params_IdepVar_func=add_floris_params_IndepVarComps, params_IndepVar_args={})) jensen_prob = Problem(root=OptAEP(nTurbines=nTurbines, nDirections=nDirections, use_rotor_components=False, wake_model=jensen_wrapper, wake_model_options={'variant': 'CosineYaw_1R', 'radius multiplier': 1.0}, datasize=0, params_IdepVar_func=add_jensen_params_IndepVarComps, params_IndepVar_args={'use_angle': True})) probs = [gauss_prob, floris_prob, jensen_prob] names = ['gauss', 'floris', 'jensen'] for indx, prob in enumerate(probs): # set up optimizer prob.driver = pyOptSparseDriver() prob.driver.options['optimizer'] = 'SNOPT' prob.driver.add_objective('obj', scaler=1E-5) # set optimizer options prob.driver.opt_settings['Verify level'] = 3 prob.driver.opt_settings['Print file'] = 'SNOPT_print_exampleOptYaw_%s.out' % names[indx] prob.driver.opt_settings['Summary file'] = 'SNOPT_summary_exampleOptYaw_%s.out' % names[indx] prob.driver.opt_settings['Major iterations limit'] = 1000 # select design variables for direction_id in range(0, nDirections): prob.driver.add_desvar('yaw%i' % direction_id, lower=-30.0, upper=30.0, scaler=1) prob.setup()
def setup_prob(self): """ Short method to select the optimizer. Uses pyOptSparse if available, or Scipy's SLSQP otherwise. """ try: # Use pyOptSparse optimizer if installed from openmdao.api import pyOptSparseDriver self.prob.driver = pyOptSparseDriver() if self.prob_dict['optimizer'] == 'SNOPT': self.prob.driver.options['optimizer'] = "SNOPT" self.prob.driver.opt_settings = {'Major optimality tolerance': 1.0e-8, 'Major feasibility tolerance': 1.0e-8, 'Major iterations limit':400, 'Minor iterations limit':2000, 'Iterations limit':1000 } elif self.prob_dict['optimizer'] == 'ALPSO': self.prob.driver.options['optimizer'] = 'ALPSO' self.prob.driver.opt_settings = {'SwarmSize': 40, 'maxOuterIter': 200, 'maxInnerIter': 6, 'rtol': 1e-5, 'atol': 1e-5, 'dtol': 1e-5, 'printOuterIters': 1 } elif self.prob_dict['optimizer'] == 'NOMAD': self.prob.driver.options['optimizer'] = 'NOMAD' self.prob.driver.opt_settings = {'maxiter':1000, 'minmeshsize':1e-12, 'minpollsize':1e-12, 'displaydegree':0, 'printfile':1 } elif self.prob_dict['optimizer'] == 'SLSQP': self.prob.driver.options['optimizer'] = 'SLSQP' self.prob.driver.opt_settings = {'ACC' : 1e-10 } except: # Use Scipy SLSQP optimizer if pyOptSparse not installed self.prob.driver = ScipyOptimizer() self.prob.driver.options['optimizer'] = 'SLSQP' self.prob.driver.options['disp'] = True self.prob.driver.options['tol'] = 1.0e-10 # Actually call the OpenMDAO functions to add the design variables, # constraints, and objective. for desvar_name, desvar_data in iteritems(self.desvars): self.prob.driver.add_desvar(desvar_name, **desvar_data) for con_name, con_data in iteritems(self.constraints): self.prob.driver.add_constraint(con_name, **con_data) for obj_name, obj_data in iteritems(self.objective): self.prob.driver.add_objective(obj_name, **obj_data) # Use finite differences over the entire model if user selected it if self.prob_dict['force_fd']: self.prob.root.deriv_options['type'] = 'fd' # Record optimization history to a database. # Data saved here can be examined using `plot_all.py` or `OptView.py` if self.prob_dict['record_db']: recorder = SqliteRecorder(self.prob_dict['prob_name']+".db") recorder.options['record_params'] = True recorder.options['record_derivs'] = True self.prob.driver.add_recorder(recorder) # Profile (time) the problem if self.prob_dict['profile']: profile.setup(self.prob) profile.start() # Set up the problem self.prob.setup() # Use warm start from previous db file if desired. # Note that we only have access to the unknowns, not the gradient history. if self.prob_dict['previous_case_db'] is not None: # Open the previous case and start from the last iteration. # Change the -1 value in get_case() if you want to select a different iteration. cr = CaseReader(self.prob_dict['previous_case_db']) case = cr.get_case(-1) # Loop through the unknowns and set them for this problem. for param_name, param_data in iteritems(case.unknowns): self.prob[param_name] = param_data