def brachistochrone_min_time(transcription='gauss-lobatto', num_segments=8, transcription_order=3,
                             compressed=True, optimizer='SLSQP', simul_derivs=True):
    p = om.Problem(model=om.Group())

    p.driver = om.pyOptSparseDriver()
    OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=True)
    p.driver.options['optimizer'] = OPTIMIZER

    if simul_derivs:
        p.driver.declare_coloring()

    if transcription == 'gauss-lobatto':
        t = dm.GaussLobatto(num_segments=num_segments,
                            order=transcription_order,
                            compressed=compressed)
    elif transcription == 'radau-ps':
        t = dm.Radau(num_segments=num_segments,
                     order=transcription_order,
                     compressed=compressed)

    phase = dm.Phase(ode_class=BrachistochroneODE, transcription=t)

    p.model.add_subsystem('phase0', phase)

    phase.set_time_options(fix_initial=True, duration_bounds=(.5, 10), units='s')

    phase.add_state('x', fix_initial=True, fix_final=False, solve_segments=False,
                    units='m', rate_source='xdot')
    phase.add_state('y', fix_initial=True, fix_final=False, solve_segments=False,
                    units='m', rate_source='ydot')
    phase.add_state('v', fix_initial=True, fix_final=False, solve_segments=False,
                    units='m/s', rate_source='vdot')

    phase.add_control('theta', continuity=True, rate_continuity=True,
                      units='deg', lower=0.01, upper=179.9)

    phase.add_parameter('g', units='m/s**2', val=9.80665, targets=['g'])

    phase.add_boundary_constraint('x', loc='final', equals=10)
    phase.add_boundary_constraint('y', loc='final', equals=5)
    # Minimize time at the end of the phase
    phase.add_objective('time_phase', loc='final', scaler=10)

    p.model.linear_solver = om.DirectSolver()
    p.setup(check=True)

    p['phase0.t_initial'] = 0.0
    p['phase0.t_duration'] = 2.0

    p['phase0.states:x'] = phase.interpolate(ys=[0, 10], nodes='state_input')
    p['phase0.states:y'] = phase.interpolate(ys=[10, 5], nodes='state_input')
    p['phase0.states:v'] = phase.interpolate(ys=[0, 9.9], nodes='state_input')
    p['phase0.controls:theta'] = phase.interpolate(ys=[5, 100], nodes='control_input')
    p['phase0.parameters:g'] = 9.80665

    p.run_driver()

    return p
Example #2
0
    def test_run_HS_problem_gl(self):
        p = om.Problem(model=om.Group())
        p.driver = om.pyOptSparseDriver()
        p.driver.declare_coloring()
        _, optimizer = set_pyoptsparse_opt('SNOPT', fallback=True)
        p.driver.options['optimizer'] = optimizer

        traj = p.model.add_subsystem('traj', dm.Trajectory())
        phase0 = traj.add_phase('phase0', dm.Phase(ode_class=HyperSensitiveODE,
                                                   transcription=dm.GaussLobatto(num_segments=30, order=3)))
        phase0.set_time_options(fix_initial=True, fix_duration=True)
        phase0.add_state('x', fix_initial=True, fix_final=False, rate_source='x_dot', targets=['x'])
        phase0.add_state('xL', fix_initial=True, fix_final=False, rate_source='L', targets=['xL'])
        phase0.add_control('u', opt=True, targets=['u'], rate_continuity=False)

        phase0.add_boundary_constraint('x', loc='final', equals=1)

        phase0.add_objective('xL', loc='final')

        phase0.set_refine_options(refine=True)

        p.setup(check=True)

        tf = 100

        p.set_val('traj.phase0.states:x', phase0.interpolate(ys=[1.5, 1], nodes='state_input'))
        p.set_val('traj.phase0.states:xL', phase0.interpolate(ys=[0, 1], nodes='state_input'))
        p.set_val('traj.phase0.t_initial', 0)
        p.set_val('traj.phase0.t_duration', tf)
        p.set_val('traj.phase0.controls:u', phase0.interpolate(ys=[-0.6, 2.4],
                                                               nodes='control_input'))
        dm.run_problem(p, refine=True)

        sqrt_two = np.sqrt(2)
        val = sqrt_two * tf
        c1 = (1.5 * np.exp(-val) - 1) / (np.exp(-val) - np.exp(val))
        c2 = (1 - 1.5 * np.exp(val)) / (np.exp(-val) - np.exp(val))

        ui = c1 * (1 + sqrt_two) + c2 * (1 - sqrt_two)
        uf = c1 * (1 + sqrt_two) * np.exp(val) + c2 * (1 - sqrt_two) * np.exp(-val)
        J = 0.5 * (c1 ** 2 * (1 + sqrt_two) * np.exp(2 * val) + c2 ** 2 * (1 - sqrt_two) * np.exp(-2 * val) -
                   (1 + sqrt_two) * c1 ** 2 - (1 - sqrt_two) * c2 ** 2)

        assert_rel_error(self,
                         p.get_val('traj.phase0.timeseries.controls:u')[0],
                         ui,
                         tolerance=1e-2)

        assert_rel_error(self,
                         p.get_val('traj.phase0.timeseries.controls:u')[-1],
                         uf,
                         tolerance=1e-2)

        assert_rel_error(self,
                         p.get_val('traj.phase0.timeseries.states:xL')[-1],
                         J,
                         tolerance=5e-4)
    def test_ex_two_burn_orbit_raise_connected(self):
        _, optimizer = set_pyoptsparse_opt('SNOPT', fallback=False)

        p = two_burn_orbit_raise_problem(transcription='gauss-lobatto', transcription_order=3,
                                         compressed=False, optimizer=optimizer,
                                         show_output=False, connected=True)

        if p.model.traj.phases.burn2 in p.model.traj.phases._subsystems_myproc:
            assert_rel_error(self, p.get_val('traj.burn2.states:deltav')[0], 0.3995,
                             tolerance=4.0E-3)
Example #4
0
    def make_problem(self, transcription=Radau, optimizer='SLSQP', numseg=30):
        p = Problem(model=Group())
        p.driver = pyOptSparseDriver()
        p.driver.declare_coloring(tol=1.0E-12)
        OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=False)
        p.driver.options['optimizer'] = OPTIMIZER
        if OPTIMIZER == 'SNOPT':
            p.driver.opt_settings['iSumm'] = 6
            p.driver.opt_settings['Verify level'] = 3
        elif OPTIMIZER == 'IPOPT':
            p.driver.opt_settings['max_iter'] = 500
            p.driver.opt_settings['print_level'] = 4
            p.driver.opt_settings['tol'] = 1.0E-6
            p.driver.opt_settings['acceptable_tol'] = 1.0E-5
        traj = p.model.add_subsystem('traj', Trajectory())

        phase = traj.add_phase('phase', Phase(ode_class=RobotArmODE,
                                              transcription=transcription(num_segments=numseg, order=3)))
        phase.set_time_options(fix_initial=True, fix_duration=False)

        phase.add_state('x0', fix_initial=True, fix_final=True, rate_source='x0_dot', units='m')
        phase.add_state('x1', fix_initial=True, fix_final=True, rate_source='x1_dot', units='rad')
        phase.add_state('x2', fix_initial=True, fix_final=True, rate_source='x2_dot', units='rad')
        phase.add_state('x3', fix_initial=True, fix_final=True, rate_source='x3_dot', units='m/s')
        phase.add_state('x4', fix_initial=True, fix_final=True, rate_source='x4_dot', units='rad/s')
        phase.add_state('x5', fix_initial=True, fix_final=True, rate_source='x5_dot', units='rad/s')

        phase.add_control('u0', opt=True, lower=-1, upper=1, scaler=0.1, units='m**2/s**2',
                          continuity=False, rate_continuity=False)
        phase.add_control('u1', opt=True, lower=-1, upper=1, scaler=0.1, units='m**3*rad/s**2',
                          continuity=False, rate_continuity=False)
        phase.add_control('u2', opt=True, lower=-1, upper=1, scaler=0.1, units='m**3*rad/s**2',
                          continuity=False, rate_continuity=False)

        phase.add_path_constraint('u0', lower=-1, upper=1, scaler=0.1)
        phase.add_path_constraint('u1', lower=-1, upper=1, scaler=0.1)
        phase.add_path_constraint('u2', lower=-1, upper=1, scaler=0.1)

        phase.add_objective('time', ref=0.1)

        phase.set_refine_options(refine=True, tol=1e-5, smoothness_factor=1.2)

        p.setup(check=True, force_alloc_complex=False, mode='auto')

        p.set_val('traj.phase.t_initial', 0)
        p.set_val('traj.phase.t_duration', 10)
        p.set_val('traj.phase.states:x0', phase.interpolate(ys=[4.5, 4.5], nodes='state_input'))
        p.set_val('traj.phase.states:x1', phase.interpolate(ys=[0.0, 2 * np.pi / 3], nodes='state_input'))
        p.set_val('traj.phase.states:x2', phase.interpolate(ys=[np.pi / 4, np.pi / 4], nodes='state_input'))
        p.set_val('traj.phase.states:x3', phase.interpolate(ys=[0.0, 0.0], nodes='state_input'))
        p.set_val('traj.phase.states:x4', phase.interpolate(ys=[0.0, 0.0], nodes='state_input'))
        p.set_val('traj.phase.states:x5', phase.interpolate(ys=[0.0, 0.0], nodes='state_input'))

        return p
    def test_ex_two_burn_orbit_raise(self):
        _, optimizer = set_pyoptsparse_opt('SNOPT', fallback=False)

        p = two_burn_orbit_raise_problem(transcription='gauss-lobatto',
                                         transcription_order=3,
                                         compressed=True,
                                         show_plots=False,
                                         optimizer=optimizer)

        assert_rel_error(self,
                         p.get_val('burn2.states:deltav')[-1],
                         0.3995,
                         tolerance=2.0E-3)
Example #6
0
    def make_problem(self,
                     transcription=GaussLobatto,
                     optimizer='SLSQP',
                     numseg=30):
        p = Problem(model=Group())
        p.driver = pyOptSparseDriver()
        p.driver.declare_coloring()
        OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=False)
        p.driver.options['optimizer'] = OPTIMIZER

        traj = p.model.add_subsystem('traj', Trajectory())
        phase0 = traj.add_phase(
            'phase0',
            Phase(ode_class=HyperSensitiveODE,
                  transcription=transcription(num_segments=numseg, order=3)))
        phase0.set_time_options(fix_initial=True, fix_duration=True)
        phase0.add_state('x',
                         fix_initial=True,
                         fix_final=False,
                         rate_source='x_dot',
                         targets=['x'])
        phase0.add_state('xL',
                         fix_initial=True,
                         fix_final=False,
                         rate_source='L',
                         targets=['xL'])
        phase0.add_control('u', opt=True, targets=['u'])

        phase0.add_boundary_constraint('x', loc='final', equals=1)

        phase0.add_objective('xL', loc='final')

        p.setup(check=True)

        p.set_val('traj.phase0.states:x',
                  phase0.interpolate(ys=[1.5, 1], nodes='state_input'))
        p.set_val('traj.phase0.states:xL',
                  phase0.interpolate(ys=[0, 1], nodes='state_input'))
        p.set_val('traj.phase0.t_initial', 0)
        p.set_val('traj.phase0.t_duration', tf)
        p.set_val('traj.phase0.controls:u',
                  phase0.interpolate(ys=[-0.6, 2.4], nodes='control_input'))

        return p
    def test_water_rocket_range_for_docs(self):
        p = om.Problem(model=om.Group())

        traj, phases = new_water_rocket_trajectory(objective='range')
        traj = p.model.add_subsystem('traj', traj)

        _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=False)
        p.driver = om.pyOptSparseDriver(optimizer='IPOPT')
        p.driver.opt_settings['print_level'] = 5
        p.driver.opt_settings['max_iter'] = 1000
        p.driver.opt_settings['nlp_scaling_method'] = 'gradient-based'
        p.driver.declare_coloring(tol=1.0E-12)

        # Finish Problem Setup
        p.model.linear_solver = om.DirectSolver()
        # p.driver.add_recorder(om.SqliteRecorder('ex_water_rocket.db'))

        p.setup()
        set_sane_initial_guesses(p, phases)

        p.run_driver()

        summary = summarize_results(p)
        for key, entry in summary.items():
            print(f'{key}: {entry.value:6.4f} {entry.unit}')

        exp_out = traj.simulate(times_per_seg=200)

        # NOTE: only the last figure is shown in the generated docs
        plot_propelled_ascent(p, exp_out)
        plot_trajectory(p, exp_out)
        plot_states(p, exp_out)

        plt.show()

        # Check results (tolerance is relative unless value is zero)
        assert_near_equal(summary['Launch angle'].value, 46, 0.02)
        assert_near_equal(summary['Flight angle at end of propulsion'].value,
                          38, 0.02)
        assert_near_equal(summary['Empty mass'].value, 0.189, 1e-2)
        assert_near_equal(summary['Water volume'].value, 1.026, 1e-2)
        assert_near_equal(summary['Maximum range'].value, 85.11, 1e-2)
        assert_near_equal(summary['Maximum height'].value, 23.08, 1e-2)
        assert_near_equal(summary['Maximum velocity'].value, 41.31, 1e-2)
    def test_water_rocket_height_for_docs(self):
        p = om.Problem(model=om.Group())

        traj, phases = new_water_rocket_trajectory(objective='height')
        traj = p.model.add_subsystem('traj', traj)

        _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=False)
        p.driver = om.pyOptSparseDriver(optimizer='IPOPT')
        p.driver.opt_settings['print_level'] = 5
        p.driver.opt_settings['max_iter'] = 1000
        p.driver.declare_coloring()

        # Finish Problem Setup
        p.model.linear_solver = om.DirectSolver()

        p.setup()
        set_sane_initial_guesses(p, phases)

        p.run_driver()

        summary = summarize_results(p)
        for key, entry in summary.items():
            print(f'{key}: {entry.value:6.4f} {entry.unit}')

        exp_out = traj.simulate(times_per_seg=200)

        # NOTE: only the last figure is shown in the generated docs
        plot_propelled_ascent(p, exp_out)
        plot_trajectory(p, exp_out)
        plot_states(p, exp_out)

        plt.show()

        # Check results (tolerance is relative unless value is zero)
        assert_near_equal(summary['Launch angle'].value, 85, .02)
        assert_near_equal(summary['Flight angle at end of propulsion'].value,
                          85, .02)
        assert_near_equal(summary['Empty mass'].value, 0.1425114, 1e-3)
        assert_near_equal(summary['Water volume'].value, 0.868281, 1e-3)
        assert_near_equal(summary['Maximum range'].value, 15.78, 5)
        assert_near_equal(summary['Maximum height'].value, 54.133184, 1e-3)
        assert_near_equal(summary['Maximum velocity'].value, 47.320298, 1e-3)
Example #9
0
import unittest

import numpy as np

import openmdao.api as om
from openmdao.utils.assert_utils import assert_near_equal
from openmdao.utils.general_utils import set_pyoptsparse_opt
_, optimizer = set_pyoptsparse_opt('IPOPT', fallback=True)

import dymos as dm
from dymos.examples.finite_burn_orbit_raise.finite_burn_eom import FiniteBurnODE
from openmdao.utils.testing_utils import use_tempdirs


def make_traj(transcription='gauss-lobatto',
              transcription_order=3,
              compressed=False,
              connected=False,
              param_mode='param_sequence'):

    t = {
        'gauss-lobatto':
        dm.GaussLobatto(num_segments=5,
                        order=transcription_order,
                        compressed=compressed),
        'radau':
        dm.Radau(num_segments=20,
                 order=transcription_order,
                 compressed=compressed),
        'runge-kutta':
        dm.RungeKutta(num_segments=5, compressed=compressed)
Example #10
0
from openmdao.utils.assert_utils import assert_warning
from openmdao.utils.general_utils import set_pyoptsparse_opt
from openmdao.utils.reports_system import set_default_reports_dir, _reports_dir, register_report, \
    list_reports, clear_reports, run_n2_report, setup_default_reports, report_function
from openmdao.utils.testing_utils import use_tempdirs
from openmdao.utils.mpi import MPI
from openmdao.utils.tests.test_hooks import hooks_active
from openmdao.visualization.n2_viewer.n2_viewer import _default_n2_filename
from openmdao.visualization.scaling_viewer.scaling_report import _default_scaling_filename

try:
    from openmdao.vectors.petsc_vector import PETScVector
except ImportError:
    PETScVector = None

OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP')

if OPTIMIZER:
    from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver

import dymos as dm
from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE


@use_tempdirs
class TestSubproblemReportToggle(unittest.TestCase):
    def setUp(self):
        self.n2_filename = _default_n2_filename
        self.scaling_filename = _default_scaling_filename

        # set things to a known initial state for all the test runs
    def test_distributed_list_vars(self):

        from openmdao.utils.general_utils import set_pyoptsparse_opt
        from openmdao.utils.mpi import MPI

        if MPI:
            from openmdao.api import PETScVector
            vector_class = PETScVector
        else:
            PETScVector = None

        # check that pyoptsparse is installed. if it is, try to use SLSQP.
        OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP')

        if OPTIMIZER:
            from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver
        else:
            raise unittest.SkipTest("pyOptSparseDriver is required.")
            
        from openmdao.core.parallel_group import ParallelGroup
        from openmdao.components.exec_comp import ExecComp

        class Mygroup(Group):

            def setup(self):
                self.add_subsystem('indep_var_comp', IndepVarComp('x'), promotes=['*'])
                self.add_subsystem('Cy', ExecComp('y=2*x'), promotes=['*'])
                self.add_subsystem('Cc', ExecComp('c=x+2'), promotes=['*'])

                self.add_design_var('x')
                self.add_constraint('c', lower=-3.)

        prob = Problem()

        prob.model.add_subsystem('par', ParallelGroup())

        prob.model.par.add_subsystem('G1', Mygroup())
        prob.model.par.add_subsystem('G2', Mygroup())

        prob.model.add_subsystem('Obj', ExecComp('obj=y1+y2'))

        prob.model.connect('par.G1.y', 'Obj.y1')
        prob.model.connect('par.G2.y', 'Obj.y2')

        prob.model.add_objective('Obj.obj')

        prob.driver = pyOptSparseDriver()
        prob.driver.options['optimizer'] = 'SLSQP'

        prob.setup(vector_class=PETScVector)
        prob.run_driver()
        prob.cleanup()

        stream = cStringIO()
        inputs = sorted(prob.model.list_inputs(values=True, print_arrays=True, out_stream=stream))
        self.assertEqual(inputs[0][0], 'Obj.y1')
        self.assertEqual(inputs[1][0], 'Obj.y2')
        if prob.comm.rank: # Only rank 0 prints
            self.assertEqual(inputs[2][0], 'par.G2.Cc.x')
            self.assertEqual(inputs[3][0], 'par.G2.Cy.x')
        else:
            self.assertEqual(inputs[2][0], 'par.G1.Cc.x')
            self.assertEqual(inputs[3][0], 'par.G1.Cy.x')
        self.assertTrue('value' in inputs[0][1])
        self.assertEqual(4, len(inputs))

        text = stream.getvalue()
        if prob.comm.rank: # Only rank 0 prints
            self.assertEqual(len(text), 0)
        else:
            self.assertEqual(1, text.count("6 Input(s) in 'model'"), 1)
            self.assertEqual(1, text.count('value'))
            self.assertEqual(1, text.count('  par'))
            self.assertEqual(1, text.count('    G1'))
            self.assertEqual(1, text.count('    G2'))
            self.assertEqual(2, text.count('      Cy'))
            self.assertEqual(2, text.count('      Cc'))
            self.assertEqual(4, text.count('        x'))
            self.assertEqual(1, text.count('  Obj'))
            self.assertEqual(1, text.count('    y1'))
            self.assertEqual(1, text.count('    y2'))

        stream = cStringIO()
        outputs = sorted(prob.model.list_outputs(values=True,
                                          units=True,
                                          shape=True,
                                          bounds=True,
                                          residuals=True,
                                          scaling=True,
                                          hierarchical=True,
                                          print_arrays=True,
                                          out_stream=stream))
        self.assertEqual(outputs[0][0], 'Obj.obj')
        if prob.comm.rank: # outputs only return what is on their proc
            self.assertEqual(outputs[1][0], 'par.G2.Cc.c')
            self.assertEqual(outputs[2][0], 'par.G2.Cy.y')
            self.assertEqual(outputs[3][0], 'par.G2.indep_var_comp.x')
        else:
            self.assertEqual(outputs[1][0], 'par.G1.Cc.c')
            self.assertEqual(outputs[2][0], 'par.G1.Cy.y')
            self.assertEqual(outputs[3][0], 'par.G1.indep_var_comp.x')
        self.assertEqual(4, len(outputs))
        self.assertTrue('value' in outputs[0][1])
        self.assertTrue('units' in outputs[0][1])

        text = stream.getvalue()
        if prob.comm.rank: # Only rank 0 prints
            self.assertEqual(len(text), 0)
        else:
            self.assertEqual(1, text.count("7 Explicit Output(s) in 'model'"))
            self.assertEqual(1, text.count('value'))
            self.assertEqual(1, text.count('units'))
            self.assertEqual(1, text.count('  par'))
            self.assertEqual(1, text.count('    G1'))
            self.assertEqual(1, text.count('    G2'))
            self.assertEqual(2, text.count('      Cy'))
            self.assertEqual(2, text.count('      Cc'))
            self.assertEqual(2, text.count('      indep_var_comp'))
            self.assertEqual(2, text.count('        x'))
            self.assertEqual(2, text.count('        y'))
            self.assertEqual(2, text.count('        c'))
            self.assertEqual(1, text.count('  Obj'))
            self.assertEqual(1, text.count('    obj'))
    def test_brachistochrone_for_docs_coloring_demo_solve_segments(self):
        import openmdao.api as om
        from openmdao.utils.assert_utils import assert_near_equal
        import dymos as dm
        from dymos.examples.plotting import plot_results
        from dymos.examples.brachistochrone import BrachistochroneODE
        from openmdao.utils.general_utils import set_pyoptsparse_opt

        #
        # Initialize the Problem and the optimization driver
        #
        p = om.Problem(model=om.Group())
        _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=True)
        p.driver = om.pyOptSparseDriver(optimizer=optimizer)
        p.driver.opt_settings['print_level'] = 5
        # p.driver.declare_coloring()

        #
        # Create a trajectory and add a phase to it
        #
        traj = p.model.add_subsystem('traj', dm.Trajectory())

        #
        # In this case the phase has many segments to demonstrate the impact of coloring.
        #
        phase = traj.add_phase(
            'phase0',
            dm.Phase(ode_class=BrachistochroneODE,
                     transcription=dm.Radau(num_segments=100,
                                            solve_segments=True)))

        #
        # Set the variables
        #
        phase.set_time_options(initial_bounds=(0, 0), duration_bounds=(.5, 10))

        phase.add_state(
            'x',
            rate_source=BrachistochroneODE.states['x']['rate_source'],
            units=BrachistochroneODE.states['x']['units'],
            fix_initial=True)

        phase.add_state(
            'y',
            rate_source=BrachistochroneODE.states['y']['rate_source'],
            units=BrachistochroneODE.states['y']['units'],
            fix_initial=True)

        phase.add_state(
            'v',
            rate_source=BrachistochroneODE.states['v']['rate_source'],
            targets=BrachistochroneODE.states['v']['targets'],
            units=BrachistochroneODE.states['v']['units'],
            fix_initial=True)

        phase.add_control(
            'theta',
            targets=BrachistochroneODE.parameters['theta']['targets'],
            continuity=True,
            rate_continuity=True,
            units='deg',
            lower=0.01,
            upper=179.9)

        phase.add_parameter(
            'g',
            targets=BrachistochroneODE.parameters['g']['targets'],
            units='m/s**2',
            val=9.80665)

        #
        # Replace state terminal bounds with nonlinear constraints
        #
        phase.add_boundary_constraint('x', loc='final', equals=10)
        phase.add_boundary_constraint('y', loc='final', equals=5)

        #
        # Minimize time at the end of the phase
        #
        phase.add_objective('time', loc='final', scaler=10)

        p.model.linear_solver = om.DirectSolver()

        #
        # Setup the Problem
        #
        p.setup()

        #
        # Set the initial values
        #
        p['traj.phase0.t_initial'] = 0.0
        p['traj.phase0.t_duration'] = 2.0

        p['traj.phase0.states:x'] = phase.interpolate(ys=[0, 10],
                                                      nodes='state_input')
        p['traj.phase0.states:y'] = phase.interpolate(ys=[10, 5],
                                                      nodes='state_input')
        p['traj.phase0.states:v'] = phase.interpolate(ys=[0, 9.9],
                                                      nodes='state_input')
        p['traj.phase0.controls:theta'] = phase.interpolate(
            ys=[5, 100.5], nodes='control_input')

        #
        # Solve for the optimal trajectory
        #
        dm.run_problem(p)

        # Test the results
        assert_near_equal(p.get_val('traj.phase0.timeseries.time')[-1],
                          1.8016,
                          tolerance=1.0E-3)

        # Generate the explicitly simulated trajectory
        exp_out = traj.simulate()

        plot_results(
            [('traj.phase0.timeseries.states:x',
              'traj.phase0.timeseries.states:y', 'x (m)', 'y (m)'),
             ('traj.phase0.timeseries.time',
              'traj.phase0.timeseries.controls:theta', 'time (s)',
              'theta (deg)')],
            title='Brachistochrone Solution\nRadau Pseudospectral Method',
            p_sol=p,
            p_sim=exp_out)

        plt.show()
    def test_distributed_list_vars(self):

        from openmdao.utils.general_utils import set_pyoptsparse_opt

        # check that pyoptsparse is installed. if it is, try to use SLSQP.
        OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP')

        if OPTIMIZER:
            from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver
        else:
            raise unittest.SkipTest("pyOptSparseDriver is required.")

        from openmdao.core.parallel_group import ParallelGroup
        from openmdao.components.exec_comp import ExecComp

        class Mygroup(Group):

            def setup(self):
                self.add_subsystem('indep_var_comp', IndepVarComp('x'), promotes=['*'])
                self.add_subsystem('Cy', ExecComp('y=2*x'), promotes=['*'])
                self.add_subsystem('Cc', ExecComp('c=x+2'), promotes=['*'])

                self.add_design_var('x')
                self.add_constraint('c', lower=-3.)

        prob = Problem()

        prob.model.add_subsystem('par', ParallelGroup())

        prob.model.par.add_subsystem('G1', Mygroup())
        prob.model.par.add_subsystem('G2', Mygroup())

        prob.model.add_subsystem('Obj', ExecComp('obj=y1+y2'))

        prob.model.connect('par.G1.y', 'Obj.y1')
        prob.model.connect('par.G2.y', 'Obj.y2')

        prob.model.add_objective('Obj.obj')

        prob.driver = pyOptSparseDriver()
        prob.driver.options['optimizer'] = 'SLSQP'

        prob.setup()
        prob.run_driver()
        prob.cleanup()

        stream = cStringIO()
        inputs = sorted(prob.model.list_inputs(values=True, print_arrays=True, out_stream=stream))
        self.assertEqual(inputs[0][0], 'Obj.y1')
        self.assertEqual(inputs[1][0], 'Obj.y2')
        if prob.comm.rank:  # Only rank 0 prints
            self.assertEqual(inputs[2][0], 'par.G2.Cc.x')
            self.assertEqual(inputs[3][0], 'par.G2.Cy.x')
        else:
            self.assertEqual(inputs[2][0], 'par.G1.Cc.x')
            self.assertEqual(inputs[3][0], 'par.G1.Cy.x')
        self.assertTrue('value' in inputs[0][1])
        self.assertEqual(4, len(inputs))

        text = stream.getvalue()
        if prob.comm.rank:  # Only rank 0 prints
            self.assertEqual(len(text), 0)
        else:
            self.assertEqual(1, text.count("6 Input(s) in 'model'"), 1)
            self.assertEqual(1, text.count('value'))
            self.assertEqual(1, text.count('  par'))
            self.assertEqual(1, text.count('    G1'))
            self.assertEqual(1, text.count('    G2'))
            self.assertEqual(2, text.count('      Cy'))
            self.assertEqual(2, text.count('      Cc'))
            self.assertEqual(4, text.count('        x'))
            self.assertEqual(1, text.count('  Obj'))
            self.assertEqual(1, text.count('    y1'))
            self.assertEqual(1, text.count('    y2'))

        stream = cStringIO()
        outputs = sorted(prob.model.list_outputs(values=True,
                                                 units=True,
                                                 shape=True,
                                                 bounds=True,
                                                 residuals=True,
                                                 scaling=True,
                                                 hierarchical=True,
                                                 print_arrays=True,
                                                 out_stream=stream))
        self.assertEqual(outputs[0][0], 'Obj.obj')
        if prob.comm.rank:  # outputs only return what is on their proc
            self.assertEqual(outputs[1][0], 'par.G2.Cc.c')
            self.assertEqual(outputs[2][0], 'par.G2.Cy.y')
            self.assertEqual(outputs[3][0], 'par.G2.indep_var_comp.x')
        else:
            self.assertEqual(outputs[1][0], 'par.G1.Cc.c')
            self.assertEqual(outputs[2][0], 'par.G1.Cy.y')
            self.assertEqual(outputs[3][0], 'par.G1.indep_var_comp.x')
        self.assertEqual(4, len(outputs))
        self.assertTrue('value' in outputs[0][1])
        self.assertTrue('units' in outputs[0][1])

        text = stream.getvalue()
        if prob.comm.rank:  # Only rank 0 prints
            self.assertEqual(len(text), 0)
        else:
            self.assertEqual(1, text.count("7 Explicit Output(s) in 'model'"))
            self.assertEqual(1, text.count('value'))
            self.assertEqual(1, text.count('units'))
            self.assertEqual(1, text.count('  par'))
            self.assertEqual(1, text.count('    G1'))
            self.assertEqual(1, text.count('    G2'))
            self.assertEqual(2, text.count('      Cy'))
            self.assertEqual(2, text.count('      Cc'))
            self.assertEqual(2, text.count('      indep_var_comp'))
            self.assertEqual(2, text.count('        x'))
            self.assertEqual(2, text.count('        y'))
            self.assertEqual(2, text.count('        c'))
            self.assertEqual(1, text.count('  Obj'))
            self.assertEqual(1, text.count('    obj'))
Example #14
0
from openmdao.utils.assert_utils import assert_rel_error, assert_warning
from openmdao.utils.general_utils import set_pyoptsparse_opt
from openmdao.utils.coloring import get_simul_meta, _solves_info
from openmdao.utils.mpi import MPI
from openmdao.test_suite.tot_jac_builder import TotJacBuilder

import openmdao.test_suite

try:
    from openmdao.vectors.petsc_vector import PETScVector
except ImportError:
    PETScVector = None


# check that pyoptsparse is installed
OPT, OPTIMIZER = set_pyoptsparse_opt('SNOPT')
if OPTIMIZER:
    from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver


class CounterGroup(Group):
    def __init__(self, *args, **kwargs):
        self._solve_count = 0
        super(CounterGroup, self).__init__(*args, **kwargs)

    def _solve_linear(self, *args, **kwargs):
        super(CounterGroup, self)._solve_linear(*args, **kwargs)
        self._solve_count += 1


# note: size must be an even number
    def test_two_burn_orbit_raise_gl_list_add_timeseries_output(self):
        import numpy as np

        import matplotlib.pyplot as plt

        import openmdao.api as om
        from openmdao.utils.assert_utils import assert_near_equal
        from openmdao.utils.general_utils import set_pyoptsparse_opt

        import dymos as dm
        from dymos.examples.finite_burn_orbit_raise.finite_burn_eom import FiniteBurnODE

        traj = dm.Trajectory()
        p = om.Problem(model=om.Group())
        p.model.add_subsystem('traj', traj)

        p.driver = om.pyOptSparseDriver()
        _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=True)
        p.driver.options['optimizer'] = optimizer

        p.driver.declare_coloring()

        traj.add_parameter('c', opt=False, val=1.5, units='DU/TU',
                           targets={'burn1': ['c'], 'coast': ['c'], 'burn2': ['c']})

        # First Phase (burn)
        burn1 = dm.Phase(ode_class=FiniteBurnODE,
                         transcription=dm.GaussLobatto(num_segments=10, order=3, compressed=True))

        burn1 = traj.add_phase('burn1', burn1)

        burn1.set_time_options(fix_initial=True, duration_bounds=(.5, 10), units='TU')
        burn1.add_state('r', fix_initial=True, fix_final=False, defect_scaler=100.0,
                        rate_source='r_dot', targets=['r'], units='DU')
        burn1.add_state('theta', fix_initial=True, fix_final=False, defect_scaler=100.0,
                        rate_source='theta_dot', targets=['theta'], units='rad')
        burn1.add_state('vr', fix_initial=True, fix_final=False, defect_scaler=100.0,
                        rate_source='vr_dot', targets=['vr'], units='DU/TU')
        burn1.add_state('vt', fix_initial=True, fix_final=False, defect_scaler=100.0,
                        rate_source='vt_dot', targets=['vt'], units='DU/TU')
        burn1.add_state('accel', fix_initial=True, fix_final=False,
                        rate_source='at_dot', targets=['accel'], units='DU/TU**2')
        burn1.add_state('deltav', fix_initial=True, fix_final=False,
                        rate_source='deltav_dot', units='DU/TU')
        burn1.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg',
                          scaler=0.01,
                          rate_continuity_scaler=0.001, rate2_continuity_scaler=0.001,
                          lower=-30, upper=30, targets=['u1'])

        # Second Phase (Coast)
        coast = dm.Phase(ode_class=FiniteBurnODE,
                         transcription=dm.RungeKutta(num_segments=20))

        traj.add_phase('coast', coast)

        coast.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), duration_ref=10, units='TU')

        coast.add_state('r', fix_initial=False, fix_final=False, defect_scaler=100.0,
                        rate_source='r_dot', targets=['r'], units='DU')
        coast.add_state('theta', fix_initial=False, fix_final=False, defect_scaler=100.0,
                        units='rad', rate_source='theta_dot', targets=['theta'])
        coast.add_state('vr', fix_initial=False, fix_final=False, defect_scaler=100.0,
                        rate_source='vr_dot', targets=['vr'], units='DU/TU')
        coast.add_state('vt', fix_initial=False, fix_final=False, defect_scaler=100.0,
                        rate_source='vt_dot', targets=['vt'], units='DU/TU')
        coast.add_state('accel', fix_initial=True, fix_final=False, ref=1.0E-12, defect_ref=1.0E-12,
                        rate_source='at_dot', targets=['accel'], units='DU/TU**2')
        coast.add_state('deltav', fix_initial=False, fix_final=False,
                        rate_source='deltav_dot', units='DU/TU')
        coast.add_parameter('u1', targets=['u1'], opt=False, val=0.0, units='deg')

        # Third Phase (burn)
        burn2 = dm.Phase(ode_class=FiniteBurnODE,
                         transcription=dm.GaussLobatto(num_segments=10, order=3, compressed=True))

        traj.add_phase('burn2', burn2)

        burn2.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), initial_ref=10, units='TU')
        burn2.add_state('r', fix_initial=False, fix_final=True,
                        rate_source='r_dot', targets=['r'], units='DU')
        burn2.add_state('theta', fix_initial=False, fix_final=False,
                        rate_source='theta_dot', targets=['theta'], units='rad')
        burn2.add_state('vr', fix_initial=False, fix_final=True,
                        rate_source='vr_dot', targets=['vr'], units='DU/TU')
        burn2.add_state('vt', fix_initial=False, fix_final=True,
                        rate_source='vt_dot', targets=['vt'], units='DU/TU')
        burn2.add_state('accel', fix_initial=False, fix_final=False, defect_ref=1.0E-6,
                        rate_source='at_dot', targets=['accel'], units='DU/TU**2')
        burn2.add_state('deltav', fix_initial=False, fix_final=False,
                        rate_source='deltav_dot', units='DU/TU')
        burn2.add_control('u1', targets=['u1'], rate_continuity=True, rate2_continuity=True,
                          units='deg', scaler=0.01, lower=-30, upper=30)

        burn2.add_objective('deltav', loc='final', scaler=1.0)

        # demonstrate adding multiple variables at once using list in add_timeseries_output
        # test dict for units, ignore mismatched unit
        burn1.add_timeseries_output(['pos_x', 'pos_y'], units={'pos_x': 'm', 'junk': 'lbm'})
        coast.add_timeseries_output(['pos_x', 'pos_y'])
        # test list for units
        burn2.add_timeseries_output(['pos_x', 'pos_y'], units=['m', 'm'])

        # Link Phases
        traj.link_phases(phases=['burn1', 'coast', 'burn2'],
                         vars=['time', 'r', 'vr', 'vt', 'deltav'])
        traj.link_phases(phases=['burn1', 'burn2'], vars=['accel'])

        # Finish Problem Setup
        p.model.linear_solver = om.DirectSolver()

        p.setup(check=True, force_alloc_complex=True)

        # Set Initial Guesses
        p.set_val('traj.parameters:c', value=1.5)

        p.set_val('traj.burn1.t_initial', value=0.0)
        p.set_val('traj.burn1.t_duration', value=2.25)

        p.set_val('traj.burn1.states:r',
                  value=burn1.interpolate(ys=[1, 1.5], nodes='state_input'))
        p.set_val('traj.burn1.states:theta',
                  value=burn1.interpolate(ys=[0, 1.7], nodes='state_input'))
        p.set_val('traj.burn1.states:vr',
                  value=burn1.interpolate(ys=[0, 0], nodes='state_input'))
        p.set_val('traj.burn1.states:vt',
                  value=burn1.interpolate(ys=[1, 1], nodes='state_input'))
        p.set_val('traj.burn1.states:accel',
                  value=burn1.interpolate(ys=[0.1, 0], nodes='state_input'))
        p.set_val('traj.burn1.states:deltav',
                  value=burn1.interpolate(ys=[0, 0.1], nodes='state_input'), )
        p.set_val('traj.burn1.controls:u1',
                  value=burn1.interpolate(ys=[-3.5, 13.0], nodes='control_input'))

        p.set_val('traj.coast.t_initial', value=2.25)
        p.set_val('traj.coast.t_duration', value=3.0)

        p.set_val('traj.coast.states:r',
                  value=coast.interpolate(ys=[1.3, 1.5], nodes='state_input'))
        p.set_val('traj.coast.states:theta',
                  value=coast.interpolate(ys=[2.1767, 1.7], nodes='state_input'))
        p.set_val('traj.coast.states:vr',
                  value=coast.interpolate(ys=[0.3285, 0], nodes='state_input'))
        p.set_val('traj.coast.states:vt',
                  value=coast.interpolate(ys=[0.97, 1], nodes='state_input'))
        p.set_val('traj.coast.states:accel',
                  value=coast.interpolate(ys=[0, 0], nodes='state_input'))

        p.set_val('traj.burn2.t_initial', value=5.25)
        p.set_val('traj.burn2.t_duration', value=1.75)

        p.set_val('traj.burn2.states:r',
                  value=burn2.interpolate(ys=[1.8, 3], nodes='state_input'))
        p.set_val('traj.burn2.states:theta',
                  value=burn2.interpolate(ys=[3.2, 4.0], nodes='state_input'))
        p.set_val('traj.burn2.states:vr',
                  value=burn2.interpolate(ys=[.5, 0], nodes='state_input'))
        p.set_val('traj.burn2.states:vt',
                  value=burn2.interpolate(ys=[1, np.sqrt(1 / 3)], nodes='state_input'))
        p.set_val('traj.burn2.states:accel',
                  value=burn2.interpolate(ys=[0.1, 0], nodes='state_input'))
        p.set_val('traj.burn2.states:deltav',
                  value=burn2.interpolate(ys=[0.1, 0.2], nodes='state_input'))
        p.set_val('traj.burn2.controls:u1',
                  value=burn2.interpolate(ys=[1, 1], nodes='control_input'))

        p.run_driver()

        assert_near_equal(p.get_val('traj.burn2.timeseries.states:deltav')[-1],
                          0.3995,
                          tolerance=2.0E-3)

        # check units
        un = dict(p.model.list_outputs(units=True))
        assert(un['traj.phases.burn1.timeseries.pos_x']['units'] == 'm')
        assert(un['traj.phases.burn1.timeseries.pos_y']['units'] == 'DU')
        assert(un['traj.phases.burn2.timeseries.pos_x']['units'] == 'm')
        assert(un['traj.phases.burn2.timeseries.pos_y']['units'] == 'm')
Example #16
0
    def test_battery_power(self):
        """
            for battery explicit integration testings
        """
        _, local_opt = set_pyoptsparse_opt('SNOPT')
        if local_opt != 'SNOPT':
            raise unittest.SkipTest("pyoptsparse is not providing SNOPT")

        p = om.Problem()

        p.driver = om.pyOptSparseDriver()
        p.driver.options['optimizer'] = 'SNOPT'
        p.driver.opt_settings['Major iterations limit'] = 100
        p.driver.opt_settings['Major optimality tolerance'] = 5.0E-3
        p.driver.opt_settings['Major feasibility tolerance'] = 1e-6
        p.driver.opt_settings['iSumm'] = 6

        transcription = Radau(num_segments=15, order=3, compressed=True)

        phase0 = Phase(transcription=transcription, ode_class=BatteryGroup)

        phase0.set_time_options(fix_initial=True, duration_bounds=(30, 30))

        p.model.add_subsystem(name='phase0', subsys=phase0)

        phase0.add_state('SOC',
                         fix_initial=True,
                         rate_source='dXdt:SOC',
                         lower=0.0,
                         upper=1.)
        phase0.add_state('U_Th',
                         units='V',
                         fix_initial=False,
                         rate_source='dXdt:V_{thev}',
                         lower=0.0,
                         upper=5.0)

        # phase0.add_parameter('P_out', units='W', opt=False)

        # phase0.add_boundary_constraint('U_pack', units='V', loc='initial', equals=5100)

        phase0.add_objective('time', loc='final', ref=1)

        p.model.linear_solver = om.DirectSolver(assemble_jac=True)

        phase0.add_timeseries_output('Q_{batt}',
                                     output_name='Q_{batt}',
                                     units='W')
        # phase0.add_timeseries_output('U_pack', output_name='V', units='V')

        p.setup()

        # p.check_partials()

        T0 = 10 + 273

        p['phase0.t_initial'] = 0.0
        p['phase0.t_duration'] = 30

        p['phase0.states:SOC'] = phase0.interpolate(ys=[1.0, 0.0],
                                                    nodes='state_input')
        p['phase0.states:U_Th'] = phase0.interpolate(ys=[0.1, 0.1],
                                                     nodes='state_input')
        # p['phase0.parameters:P_out'][:] = 72000.

        p.run_driver()

        fig, ax = plt.subplots(3, 1, sharex=True)
        fig.suptitle('Temperature Plots')

        t_opt = p.get_val('phase0.timeseries.time')
        SOC_opt = p.get_val('phase0.timeseries.states:SOC', units=None)

        Q_batt_opt = p.get_val('phase0.timeseries.Q_{batt}', units='kW')

        ax[1].plot(t_opt, Q_batt_opt * 128 * 40, 'r', label='$Q_{cell}$')

        ax[2].plot(t_opt, SOC_opt, 'r', label='$SOC$')

        #spot check final values
        # assert_rel_error(self, T_batt_opt[-1], 1.25934406, tolerance=1.0E-6)

        # ax[3].plot(t_opt, V_opt, 'r', label='$Voltage$')

        # axarr = fig.add_subplot(1, 2, 2)
        # axarr.plot(sim_out.get_values('time'),sim_out.get_values('electric.battery.I_Li'), 'b')
        # # # axarr.plot(p['phase0.state_interp.state_col:r'],
        # # #            p['phase0.controls:h'], 'bo', ms=4)
        # axarr.set_ylabel('I_Li, amps')
        # axarr.set_xlabel('time, s')
        # axarr.axes.get_xaxis().set_visible(True)

        import matplotlib
        matplotlib.use(
            'agg')  # <--- comment out if you want to show this plot.
        plt.show()
def _run_balanced_field_length_problem(tx=dm.GaussLobatto, timeseries=True, sim=True, solvesegs=False):
    p = om.Problem()

    _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=True)

    p.driver = om.pyOptSparseDriver()
    p.driver.declare_coloring()

    # Use IPOPT if available, with fallback to SLSQP
    p.driver.options['optimizer'] = optimizer
    p.driver.options['print_results'] = False
    if optimizer == 'IPOPT':
        p.driver.opt_settings['print_level'] = 5

    # First Phase: Brake release to V1 - both engines operable
    br_to_v1 = dm.Phase(ode_class=BalancedFieldODEComp,
                        transcription=tx(num_segments=3, solve_segments=solvesegs),
                        ode_init_kwargs={'mode': 'runway'})
    br_to_v1.set_time_options(fix_initial=True, duration_bounds=(1, 1000), duration_ref=10.0)
    br_to_v1.add_state('r', fix_initial=True, lower=0, ref=1000.0, defect_ref=1000.0)
    br_to_v1.add_state('v', fix_initial=True, lower=0, ref=100.0, defect_ref=100.0)
    br_to_v1.add_parameter('alpha', val=0.0, opt=False, units='deg')

    if timeseries:
        br_to_v1.add_timeseries_output('*')

    # Second Phase: Rejected takeoff at V1 - no engines operable
    rto = dm.Phase(ode_class=BalancedFieldODEComp,
                   transcription=dm.Radau(num_segments=3, solve_segments=solvesegs),
                   ode_init_kwargs={'mode': 'runway'})
    rto.set_time_options(fix_initial=False, duration_bounds=(1, 1000), duration_ref=1.0)
    rto.add_state('r', fix_initial=False, lower=0, ref=1000.0, defect_ref=1000.0)
    rto.add_state('v', fix_initial=False, lower=0, ref=100.0, defect_ref=100.0)
    rto.add_parameter('alpha', val=0.0, opt=False, units='deg')

    if timeseries:
        rto.add_timeseries_output('*')

    # Third Phase: V1 to Vr - single engine operable
    v1_to_vr = dm.Phase(ode_class=BalancedFieldODEComp,
                        transcription=dm.Radau(num_segments=3, solve_segments=solvesegs),
                        ode_init_kwargs={'mode': 'runway'})
    v1_to_vr.set_time_options(fix_initial=False, duration_bounds=(1, 1000), duration_ref=1.0)
    v1_to_vr.add_state('r', fix_initial=False, lower=0, ref=1000.0, defect_ref=1000.0)
    v1_to_vr.add_state('v', fix_initial=False, lower=0, ref=100.0, defect_ref=100.0)
    v1_to_vr.add_parameter('alpha', val=0.0, opt=False, units='deg')

    if timeseries:
        v1_to_vr.add_timeseries_output('*')

    # Fourth Phase: Rotate - single engine operable
    rotate = dm.Phase(ode_class=BalancedFieldODEComp,
                      transcription=dm.Radau(num_segments=3, solve_segments=solvesegs),
                      ode_init_kwargs={'mode': 'runway'})
    rotate.set_time_options(fix_initial=False, duration_bounds=(1.0, 5), duration_ref=1.0)
    rotate.add_state('r', fix_initial=False, lower=0, ref=1000.0, defect_ref=1000.0)
    rotate.add_state('v', fix_initial=False, lower=0, ref=100.0, defect_ref=100.0)
    rotate.add_polynomial_control('alpha', order=1, opt=True, units='deg', lower=0, upper=10,
                                  ref=10, val=[0, 10])

    if timeseries:
        rotate.add_timeseries_output('*')

    # Fifth Phase: Climb to target speed and altitude at end of runway.
    climb = dm.Phase(ode_class=BalancedFieldODEComp, transcription=dm.Radau(num_segments=5),
                     ode_init_kwargs={'mode': 'climb'})
    climb.set_time_options(fix_initial=False, duration_bounds=(1, 100), duration_ref=1.0)
    climb.add_state('r', fix_initial=False, lower=0, ref=1000.0, defect_ref=1000.0)
    climb.add_state('h', fix_initial=True, lower=0, ref=1.0, defect_ref=1.0)
    climb.add_state('v', fix_initial=False, lower=0, ref=100.0, defect_ref=100.0)
    climb.add_state('gam', fix_initial=True, lower=0, ref=0.05, defect_ref=0.05)
    climb.add_control('alpha', opt=True, units='deg', lower=-10, upper=15, ref=10)

    if timeseries:
        climb.add_timeseries_output('*')

    # Instantiate the trajectory and add phases
    traj = dm.Trajectory()
    p.model.add_subsystem('traj', traj)
    traj.add_phase('br_to_v1', br_to_v1)
    traj.add_phase('rto', rto)
    traj.add_phase('v1_to_vr', v1_to_vr)
    traj.add_phase('rotate', rotate)
    traj.add_phase('climb', climb)

    # Add parameters common to multiple phases to the trajectory
    traj.add_parameter('m', val=174200., opt=False, units='lbm',
                       desc='aircraft mass',
                       targets={'br_to_v1': ['m'], 'v1_to_vr': ['m'], 'rto': ['m'],
                                'rotate': ['m'], 'climb': ['m']})

    traj.add_parameter('T_nominal', val=27000 * 2, opt=False, units='lbf', dynamic=False,
                       desc='nominal aircraft thrust',
                       targets={'br_to_v1': ['T']})

    traj.add_parameter('T_engine_out', val=27000, opt=False, units='lbf', dynamic=False,
                       desc='thrust under a single engine',
                       targets={'v1_to_vr': ['T'], 'rotate': ['T'], 'climb': ['T']})

    traj.add_parameter('T_shutdown', val=0.0, opt=False, units='lbf', dynamic=False,
                       desc='thrust when engines are shut down for rejected takeoff',
                       targets={'rto': ['T']})

    traj.add_parameter('mu_r_nominal', val=0.03, opt=False, units=None, dynamic=False,
                       desc='nominal runway friction coefficient',
                       targets={'br_to_v1': ['mu_r'], 'v1_to_vr': ['mu_r'], 'rotate': ['mu_r']})

    traj.add_parameter('mu_r_braking', val=0.3, opt=False, units=None, dynamic=False,
                       desc='runway friction coefficient under braking',
                       targets={'rto': ['mu_r']})

    traj.add_parameter('h_runway', val=0., opt=False, units='ft',
                       desc='runway altitude',
                       targets={'br_to_v1': ['h'], 'v1_to_vr': ['h'], 'rto': ['h'],
                                'rotate': ['h']})

    traj.add_parameter('rho', val=1.225, opt=False, units='kg/m**3', dynamic=False,
                       desc='atmospheric density',
                       targets={'br_to_v1': ['rho'], 'v1_to_vr': ['rho'], 'rto': ['rho'],
                                'rotate': ['rho']})

    traj.add_parameter('S', val=124.7, opt=False, units='m**2', dynamic=False,
                       desc='aerodynamic reference area',
                       targets={'br_to_v1': ['S'], 'v1_to_vr': ['S'], 'rto': ['S'],
                                'rotate': ['S'], 'climb': ['S']})

    traj.add_parameter('CD0', val=0.03, opt=False, units=None, dynamic=False,
                       desc='zero-lift drag coefficient',
                       targets={f'{phase}': ['CD0'] for phase in ['br_to_v1', 'v1_to_vr',
                                                                  'rto', 'rotate' 'climb']})

    traj.add_parameter('AR', val=9.45, opt=False, units=None, dynamic=False,
                       desc='wing aspect ratio',
                       targets={f'{phase}': ['AR'] for phase in ['br_to_v1', 'v1_to_vr',
                                                                 'rto', 'rotate' 'climb']})

    traj.add_parameter('e', val=801, opt=False, units=None, dynamic=False,
                       desc='Oswald span efficiency factor',
                       targets={f'{phase}': ['e'] for phase in ['br_to_v1', 'v1_to_vr',
                                                                'rto', 'rotate' 'climb']})

    traj.add_parameter('span', val=35.7, opt=False, units='m', dynamic=False,
                       desc='wingspan',
                       targets={f'{phase}': ['span'] for phase in ['br_to_v1', 'v1_to_vr',
                                                                   'rto', 'rotate' 'climb']})

    traj.add_parameter('h_w', val=1.0, opt=False, units='m', dynamic=False,
                       desc='height of wing above CG',
                       targets={f'{phase}': ['h_w'] for phase in ['br_to_v1', 'v1_to_vr',
                                                                  'rto', 'rotate' 'climb']})

    traj.add_parameter('CL0', val=0.5, opt=False, units=None, dynamic=False,
                       desc='zero-alpha lift coefficient',
                       targets={f'{phase}': ['CL0'] for phase in ['br_to_v1', 'v1_to_vr',
                                                                  'rto', 'rotate' 'climb']})

    traj.add_parameter('CL_max', val=2.0, opt=False, units=None, dynamic=False,
                       desc='maximum lift coefficient for linear fit',
                       targets={f'{phase}': ['CL_max'] for phase in ['br_to_v1', 'v1_to_vr',
                                                                     'rto', 'rotate' 'climb']})

    traj.add_parameter('alpha_max', val=10.0, opt=False, units='deg', dynamic=False,
                       desc='angle of attack at maximum lift',
                       targets={f'{phase}': ['alpha_max'] for phase in ['br_to_v1', 'v1_to_vr',
                                                                        'rto', 'rotate' 'climb']})

    # Standard "end of first phase to beginning of second phase" linkages
    # Alpha changes from being a parameter in v1_to_vr to a polynomial control
    # in rotate, to a dynamic control in `climb`.
    traj.link_phases(['br_to_v1', 'v1_to_vr'], vars=['time', 'r', 'v'])
    traj.link_phases(['v1_to_vr', 'rotate'], vars=['time', 'r', 'v', 'alpha'])
    traj.link_phases(['rotate', 'climb'], vars=['time', 'r', 'v', 'alpha'])
    traj.link_phases(['br_to_v1', 'rto'], vars=['time', 'r', 'v'])

    # Less common "final value of r must be the match at ends of two phases".
    traj.add_linkage_constraint(phase_a='rto', var_a='r', loc_a='final',
                                phase_b='climb', var_b='r', loc_b='final',
                                ref=1000)

    # Define the constraints and objective for the optimal control problem
    v1_to_vr.add_boundary_constraint('v_over_v_stall', loc='final', lower=1.2, ref=100)

    rto.add_boundary_constraint('v', loc='final', equals=0., ref=100, linear=True)

    rotate.add_boundary_constraint('F_r', loc='final', equals=0, ref=100000)

    climb.add_boundary_constraint('h', loc='final', equals=35, ref=35, units='ft', linear=True)
    climb.add_boundary_constraint('gam', loc='final', equals=5, ref=5, units='deg', linear=True)
    climb.add_path_constraint('gam', lower=0, upper=5, ref=5, units='deg')
    climb.add_boundary_constraint('v_over_v_stall', loc='final', lower=1.25, ref=1.25)

    rto.add_objective('r', loc='final', ref=1000.0)

    #
    # Setup the problem and set the initial guess
    #
    p.setup(check=True)

    p.set_val('traj.br_to_v1.t_initial', 0)
    p.set_val('traj.br_to_v1.t_duration', 35)
    p.set_val('traj.br_to_v1.states:r', br_to_v1.interpolate(ys=[0, 2500.0], nodes='state_input'))
    p.set_val('traj.br_to_v1.states:v', br_to_v1.interpolate(ys=[0, 100.0], nodes='state_input'))
    p.set_val('traj.br_to_v1.parameters:alpha', 0, units='deg')

    p.set_val('traj.v1_to_vr.t_initial', 35)
    p.set_val('traj.v1_to_vr.t_duration', 35)
    p.set_val('traj.v1_to_vr.states:r', v1_to_vr.interpolate(ys=[2500, 300.0], nodes='state_input'))
    p.set_val('traj.v1_to_vr.states:v', v1_to_vr.interpolate(ys=[100, 110.0], nodes='state_input'))
    p.set_val('traj.v1_to_vr.parameters:alpha', 0.0, units='deg')

    p.set_val('traj.rto.t_initial', 35)
    p.set_val('traj.rto.t_duration', 35)
    p.set_val('traj.rto.states:r', rto.interpolate(ys=[2500, 5000.0], nodes='state_input'))
    p.set_val('traj.rto.states:v', rto.interpolate(ys=[110, 0], nodes='state_input'))
    p.set_val('traj.rto.parameters:alpha', 0.0, units='deg')

    p.set_val('traj.rotate.t_initial', 70)
    p.set_val('traj.rotate.t_duration', 5)
    p.set_val('traj.rotate.states:r', rotate.interpolate(ys=[1750, 1800.0], nodes='state_input'))
    p.set_val('traj.rotate.states:v', rotate.interpolate(ys=[80, 85.0], nodes='state_input'))
    p.set_val('traj.rotate.polynomial_controls:alpha', 0.0, units='deg')

    p.set_val('traj.climb.t_initial', 75)
    p.set_val('traj.climb.t_duration', 15)
    p.set_val('traj.climb.states:r', climb.interpolate(ys=[5000, 5500.0], nodes='state_input'),
              units='ft')
    p.set_val('traj.climb.states:v', climb.interpolate(ys=[160, 170.0], nodes='state_input'),
              units='kn')
    p.set_val('traj.climb.states:h', climb.interpolate(ys=[0, 35.0], nodes='state_input'),
              units='ft')
    p.set_val('traj.climb.states:gam', climb.interpolate(ys=[0, 5.0], nodes='state_input'),
              units='deg')
    p.set_val('traj.climb.controls:alpha', 5.0, units='deg')

    dm.run_problem(p, run_driver=True, simulate=sim)

    # Test this example in Dymos' continuous integration
    assert_near_equal(p.get_val('traj.rto.states:r')[-1], 2188.2, tolerance=0.01)
Example #18
0
    def make_problem(self,
                     constrained=True,
                     transcription=GaussLobatto,
                     optimizer='SLSQP',
                     numseg=30):
        p = om.Problem(model=om.Group())
        p.driver = om.pyOptSparseDriver()
        p.driver.declare_coloring()
        OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=False)
        p.driver.options['optimizer'] = OPTIMIZER

        traj = p.model.add_subsystem('traj', Trajectory())
        phase0 = traj.add_phase(
            'phase0',
            Phase(ode_class=ShuttleODE,
                  transcription=transcription(num_segments=numseg, order=3)))

        phase0.set_time_options(fix_initial=True, units='s', duration_ref=200)
        phase0.add_state('h',
                         fix_initial=True,
                         fix_final=True,
                         units='ft',
                         rate_source='hdot',
                         targets=['h'],
                         lower=0,
                         ref0=75000,
                         ref=300000,
                         defect_ref=1000)
        phase0.add_state('gamma',
                         fix_initial=True,
                         fix_final=True,
                         units='rad',
                         rate_source='gammadot',
                         targets=['gamma'],
                         lower=-89. * np.pi / 180,
                         upper=89. * np.pi / 180)
        phase0.add_state('phi',
                         fix_initial=True,
                         fix_final=False,
                         units='rad',
                         rate_source='phidot',
                         lower=0,
                         upper=89. * np.pi / 180)
        phase0.add_state('psi',
                         fix_initial=True,
                         fix_final=False,
                         units='rad',
                         rate_source='psidot',
                         targets=['psi'],
                         lower=0,
                         upper=90. * np.pi / 180)
        phase0.add_state('theta',
                         fix_initial=True,
                         fix_final=False,
                         units='rad',
                         rate_source='thetadot',
                         targets=['theta'],
                         lower=-89. * np.pi / 180,
                         upper=89. * np.pi / 180)
        phase0.add_state('v',
                         fix_initial=True,
                         fix_final=True,
                         units='ft/s',
                         rate_source='vdot',
                         targets=['v'],
                         lower=500,
                         ref0=2500,
                         ref=25000)
        phase0.add_control('alpha',
                           units='rad',
                           opt=True,
                           lower=-np.pi / 2,
                           upper=np.pi / 2,
                           targets=['alpha'])
        phase0.add_control('beta',
                           units='rad',
                           opt=True,
                           lower=-89 * np.pi / 180,
                           upper=1 * np.pi / 180,
                           targets=['beta'])

        if constrained:
            phase0.add_path_constraint('q', lower=0, upper=70, ref=70)

        phase0.add_objective('theta', loc='final', ref=-0.01)

        p.setup(check=True, force_alloc_complex=True)

        p.set_val('traj.phase0.states:h',
                  phase0.interpolate(ys=[260000, 80000], nodes='state_input'),
                  units='ft')
        p.set_val('traj.phase0.states:gamma',
                  phase0.interpolate(ys=[-1 * np.pi / 180, -5 * np.pi / 180],
                                     nodes='state_input'),
                  units='rad')
        p.set_val('traj.phase0.states:phi',
                  phase0.interpolate(ys=[0, 75 * np.pi / 180],
                                     nodes='state_input'),
                  units='rad')
        p.set_val('traj.phase0.states:psi',
                  phase0.interpolate(ys=[90 * np.pi / 180, 10 * np.pi / 180],
                                     nodes='state_input'),
                  units='rad')
        p.set_val('traj.phase0.states:theta',
                  phase0.interpolate(ys=[0, 25 * np.pi / 180],
                                     nodes='state_input'),
                  units='rad')
        p.set_val('traj.phase0.states:v',
                  phase0.interpolate(ys=[25600, 2500], nodes='state_input'),
                  units='ft/s')
        p.set_val('traj.phase0.t_initial', 0, units='s')
        p.set_val('traj.phase0.t_duration', 2000, units='s')
        p.set_val('traj.phase0.controls:alpha',
                  phase0.interpolate(
                      ys=[17.4 * np.pi / 180, 17.4 * np.pi / 180],
                      nodes='control_input'),
                  units='rad')
        p.set_val('traj.phase0.controls:beta',
                  phase0.interpolate(ys=[-75 * np.pi / 180, 0 * np.pi / 180],
                                     nodes='control_input'),
                  units='rad')

        return p
Example #19
0
    def test_distributed_list_vars(self):

        from openmdao.utils.general_utils import set_pyoptsparse_opt

        # check that pyoptsparse is installed. if it is, try to use SLSQP.
        OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP')

        if OPTIMIZER:
            from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver
        else:
            raise unittest.SkipTest("pyOptSparseDriver is required.")

        class Mygroup(om.Group):

            def setup(self):
                self.add_subsystem('indep_var_comp', om.IndepVarComp('x'), promotes=['*'])
                self.add_subsystem('Cy', om.ExecComp('y=2*x'), promotes=['*'])
                self.add_subsystem('Cc', om.ExecComp('c=x+2'), promotes=['*'])

                self.add_design_var('x')
                self.add_constraint('c', lower=-3.)

        prob = om.Problem()

        prob.model.add_subsystem('par', om.ParallelGroup())

        prob.model.par.add_subsystem('G1', Mygroup())
        prob.model.par.add_subsystem('G2', Mygroup())

        prob.model.add_subsystem('Obj', om.ExecComp('obj=y1+y2'))

        prob.model.connect('par.G1.y', 'Obj.y1')
        prob.model.connect('par.G2.y', 'Obj.y2')

        prob.model.add_objective('Obj.obj')

        prob.driver = pyOptSparseDriver()
        prob.driver.options['optimizer'] = 'SLSQP'

        prob.setup()
        prob.run_driver()
        prob.cleanup()

        stream = StringIO()
        with multi_proc_exception_check(prob.comm):
            inputs = sorted(prob.model.list_inputs(values=True, print_arrays=True, out_stream=stream))
            if prob.comm.rank:
                self.assertEqual(inputs, [])
            else:
                inames = [t[0] for t in inputs]
                self.assertEqual(inames, ['Obj.y1', 'Obj.y2', 'par.G1.Cc.x', 'par.G1.Cy.x', 'par.G2.Cc.x', 'par.G2.Cy.x'])
                self.assertTrue('val' in inputs[0][1])

            text = stream.getvalue()
            if prob.comm.rank:  # Only rank 0 prints
                self.assertEqual(len(text), 0)
            else:
                self.assertEqual(1, text.count("6 Input(s) in 'model'"), 1)
                self.assertEqual(1, text.count('val'))
                self.assertEqual(1, text.count('par'))
                self.assertEqual(1, text.count('  G1'))
                self.assertEqual(1, text.count('  G2'))
                self.assertEqual(2, text.count('    Cy'))
                self.assertEqual(2, text.count('    Cc'))
                self.assertEqual(4, text.count('      x'))
                self.assertEqual(1, text.count('Obj'))
                self.assertEqual(1, text.count('  y1'))
                self.assertEqual(1, text.count('  y2'))

        stream = StringIO()
        with multi_proc_exception_check(prob.comm):
            outputs = sorted(prob.model.list_outputs(values=True,
                                                     units=True,
                                                     shape=True,
                                                     bounds=True,
                                                     residuals=True,
                                                     scaling=True,
                                                     hierarchical=True,
                                                     print_arrays=True,
                                                     out_stream=stream))
            onames = [t[0] for t in outputs]
            if prob.comm.rank == 0:
                self.assertEqual(onames, ['Obj.obj', 'par.G1.Cc.c', 'par.G1.Cy.y', 'par.G1.indep_var_comp.x', 'par.G2.Cc.c', 'par.G2.Cy.y', 'par.G2.indep_var_comp.x'])
                self.assertTrue('val' in outputs[0][1])
                self.assertTrue('units' in outputs[0][1])
            else:
                self.assertEqual(onames, [])

            text = stream.getvalue()
            if prob.comm.rank:  # Only rank 0 prints
                self.assertEqual(len(text), 0)
            else:
                self.assertEqual(1, text.count("7 Explicit Output(s) in 'model'"))
                self.assertEqual(1, text.count('val'))
                self.assertEqual(1, text.count('units'))
                self.assertEqual(1, text.count('par'))
                self.assertEqual(1, text.count('  G1'))
                self.assertEqual(1, text.count('  G2'))
                self.assertEqual(2, text.count('    Cy'))
                self.assertEqual(2, text.count('    Cc'))
                self.assertEqual(2, text.count('    indep_var_comp'))
                self.assertEqual(2, text.count('      x'))
                self.assertEqual(2, text.count('      y'))
                self.assertEqual(2, text.count('      c'))
                self.assertEqual(1, text.count('Obj'))
                self.assertEqual(1, text.count('  obj'))
    def test_two_burn_orbit_raise_radau_wildcard_add_timeseries_output(self):
        import numpy as np

        import matplotlib.pyplot as plt

        import openmdao.api as om
        from openmdao.utils.assert_utils import assert_near_equal
        from openmdao.utils.general_utils import set_pyoptsparse_opt

        import dymos as dm
        from dymos.examples.finite_burn_orbit_raise.finite_burn_eom import FiniteBurnODE

        traj = dm.Trajectory()
        p = om.Problem(model=om.Group())
        p.model.add_subsystem('traj', traj)

        p.driver = om.pyOptSparseDriver()
        _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=True)
        p.driver.options['optimizer'] = optimizer

        p.driver.declare_coloring()

        traj.add_parameter('c', opt=False, val=1.5, units='DU/TU',
                           targets={'burn1': ['c'], 'coast': ['c'], 'burn2': ['c']})

        # First Phase (burn)
        burn1 = dm.Phase(ode_class=FiniteBurnODE,
                         transcription=dm.Radau(num_segments=10, order=3, compressed=True))

        burn1 = traj.add_phase('burn1', burn1)

        burn1.set_time_options(fix_initial=True, duration_bounds=(.5, 10), units='TU')
        burn1.add_state('r', fix_initial=True, fix_final=False, defect_scaler=100.0,
                        rate_source='r_dot', targets=['r'], units='DU')
        burn1.add_state('theta', fix_initial=True, fix_final=False, defect_scaler=100.0,
                        rate_source='theta_dot', targets=['theta'], units='rad')
        burn1.add_state('vr', fix_initial=True, fix_final=False, defect_scaler=100.0,
                        rate_source='vr_dot', targets=['vr'], units='DU/TU')
        burn1.add_state('vt', fix_initial=True, fix_final=False, defect_scaler=100.0,
                        rate_source='vt_dot', targets=['vt'], units='DU/TU')
        burn1.add_state('accel', fix_initial=True, fix_final=False,
                        rate_source='at_dot', targets=['accel'], units='DU/TU**2')
        burn1.add_state('deltav', fix_initial=True, fix_final=False,
                        rate_source='deltav_dot', units='DU/TU')
        burn1.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg',
                          scaler=0.01,
                          rate_continuity_scaler=0.001, rate2_continuity_scaler=0.001,
                          lower=-30, upper=30, targets=['u1'])

        # Second Phase (Coast)
        coast = dm.Phase(ode_class=FiniteBurnODE,
                         transcription=dm.RungeKutta(num_segments=20))

        traj.add_phase('coast', coast)

        coast.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), duration_ref=10, units='TU')

        coast.add_state('r', fix_initial=False, fix_final=False, defect_scaler=100.0,
                        rate_source='r_dot', targets=['r'], units='DU')
        coast.add_state('theta', fix_initial=False, fix_final=False, defect_scaler=100.0,
                        units='rad', rate_source='theta_dot', targets=['theta'])
        coast.add_state('vr', fix_initial=False, fix_final=False, defect_scaler=100.0,
                        rate_source='vr_dot', targets=['vr'], units='DU/TU')
        coast.add_state('vt', fix_initial=False, fix_final=False, defect_scaler=100.0,
                        rate_source='vt_dot', targets=['vt'], units='DU/TU')
        coast.add_state('accel', fix_initial=True, fix_final=False, ref=1.0E-12, defect_ref=1.0E-12,
                        rate_source='at_dot', targets=['accel'], units='DU/TU**2')
        coast.add_state('deltav', fix_initial=False, fix_final=False,
                        rate_source='deltav_dot', units='DU/TU')
        coast.add_parameter('u1', targets=['u1'], opt=False, val=0.0, units='deg')

        # Third Phase (burn)
        burn2 = dm.Phase(ode_class=FiniteBurnODE,
                         transcription=dm.Radau(num_segments=10, order=3, compressed=True))

        traj.add_phase('burn2', burn2)

        burn2.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), initial_ref=10, units='TU')
        burn2.add_state('r', fix_initial=False, fix_final=True,
                        rate_source='r_dot', targets=['r'], units='DU')
        burn2.add_state('theta', fix_initial=False, fix_final=False,
                        rate_source='theta_dot', targets=['theta'], units='rad')
        burn2.add_state('vr', fix_initial=False, fix_final=True,
                        rate_source='vr_dot', targets=['vr'], units='DU/TU')
        burn2.add_state('vt', fix_initial=False, fix_final=True,
                        rate_source='vt_dot', targets=['vt'], units='DU/TU')
        burn2.add_state('accel', fix_initial=False, fix_final=False, defect_ref=1.0E-6,
                        rate_source='at_dot', targets=['accel'], units='DU/TU**2')
        burn2.add_state('deltav', fix_initial=False, fix_final=False,
                        rate_source='deltav_dot', units='DU/TU')
        burn2.add_control('u1', targets=['u1'], rate_continuity=True, rate2_continuity=True,
                          units='deg', scaler=0.01, lower=-30, upper=30)

        burn2.add_objective('deltav', loc='final', scaler=1.0)

        # demonstrate adding multiple variables at once using wildcard in add_timeseries_output
        burn1.add_timeseries_output('pos_*')  # match partial variable in ODE outputs (Radau)
        coast.add_timeseries_output('pos_*')  # match partial variable in ODE outputs (Runge Kutta)
        burn2.add_timeseries_output('*')      # add all ODE outputs

        # Link Phases
        traj.link_phases(phases=['burn1', 'coast', 'burn2'],
                         vars=['time', 'r', 'vr', 'vt', 'deltav'])
        traj.link_phases(phases=['burn1', 'burn2'], vars=['accel'])

        # Finish Problem Setup
        p.model.linear_solver = om.DirectSolver()

        p.setup(check=True, force_alloc_complex=True)

        # Set Initial Guesses
        p.set_val('traj.parameters:c', value=1.5)

        p.set_val('traj.burn1.t_initial', value=0.0)
        p.set_val('traj.burn1.t_duration', value=2.25)

        p.set_val('traj.burn1.states:r',
                  value=burn1.interpolate(ys=[1, 1.5], nodes='state_input'))
        p.set_val('traj.burn1.states:theta',
                  value=burn1.interpolate(ys=[0, 1.7], nodes='state_input'))
        p.set_val('traj.burn1.states:vr',
                  value=burn1.interpolate(ys=[0, 0], nodes='state_input'))
        p.set_val('traj.burn1.states:vt',
                  value=burn1.interpolate(ys=[1, 1], nodes='state_input'))
        p.set_val('traj.burn1.states:accel',
                  value=burn1.interpolate(ys=[0.1, 0], nodes='state_input'))
        p.set_val('traj.burn1.states:deltav',
                  value=burn1.interpolate(ys=[0, 0.1], nodes='state_input'), )
        p.set_val('traj.burn1.controls:u1',
                  value=burn1.interpolate(ys=[-3.5, 13.0], nodes='control_input'))

        p.set_val('traj.coast.t_initial', value=2.25)
        p.set_val('traj.coast.t_duration', value=3.0)

        p.set_val('traj.coast.states:r',
                  value=coast.interpolate(ys=[1.3, 1.5], nodes='state_input'))
        p.set_val('traj.coast.states:theta',
                  value=coast.interpolate(ys=[2.1767, 1.7], nodes='state_input'))
        p.set_val('traj.coast.states:vr',
                  value=coast.interpolate(ys=[0.3285, 0], nodes='state_input'))
        p.set_val('traj.coast.states:vt',
                  value=coast.interpolate(ys=[0.97, 1], nodes='state_input'))
        p.set_val('traj.coast.states:accel',
                  value=coast.interpolate(ys=[0, 0], nodes='state_input'))

        p.set_val('traj.burn2.t_initial', value=5.25)
        p.set_val('traj.burn2.t_duration', value=1.75)

        p.set_val('traj.burn2.states:r',
                  value=burn2.interpolate(ys=[1.8, 3], nodes='state_input'))
        p.set_val('traj.burn2.states:theta',
                  value=burn2.interpolate(ys=[3.2, 4.0], nodes='state_input'))
        p.set_val('traj.burn2.states:vr',
                  value=burn2.interpolate(ys=[.5, 0], nodes='state_input'))
        p.set_val('traj.burn2.states:vt',
                  value=burn2.interpolate(ys=[1, np.sqrt(1 / 3)], nodes='state_input'))
        p.set_val('traj.burn2.states:accel',
                  value=burn2.interpolate(ys=[0.1, 0], nodes='state_input'))
        p.set_val('traj.burn2.states:deltav',
                  value=burn2.interpolate(ys=[0.1, 0.2], nodes='state_input'))
        p.set_val('traj.burn2.controls:u1',
                  value=burn2.interpolate(ys=[1, 1], nodes='control_input'))

        p.run_driver()

        assert_near_equal(p.get_val('traj.burn2.timeseries.states:deltav')[-1],
                          0.3995,
                          tolerance=2.0E-3)

        # test ODE output wildcard matching in solve_ivp
        exp_out = traj.simulate()

        for prob in (p, exp_out):
            # check timeseries: pos_x = r * cos(theta) and pos_y = r * sin(theta)
            for phs in ['burn1', 'coast', 'burn2']:
                x = np.array(prob.get_val('traj.{0}.timeseries.pos_x'.format(phs))).flatten()
                y = np.array(prob.get_val('traj.{0}.timeseries.pos_y'.format(phs))).flatten()
                t = np.array(prob.get_val('traj.{0}.timeseries.states:theta'.format(phs))).flatten()
                r = np.array(prob.get_val('traj.{0}.timeseries.states:r'.format(phs))).flatten()

                xerr = x - r * np.cos(t)
                yerr = y - r * np.sin(t)

                assert_near_equal(np.sqrt(np.mean(xerr*xerr)), 0.0)
                assert_near_equal(np.sqrt(np.mean(yerr*yerr)), 0.0)
    def test_distributed_driver_debug_print_options(self):

        # check that pyoptsparse is installed. if it is, try to use SLSQP.
        OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP')

        if OPTIMIZER:
            from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver
        else:
            raise unittest.SkipTest("pyOptSparseDriver is required.")

        class Mygroup(Group):
            def setup(self):
                self.add_subsystem('indep_var_comp',
                                   IndepVarComp('x'),
                                   promotes=['*'])
                self.add_subsystem('Cy', ExecComp('y=2*x'), promotes=['*'])
                self.add_subsystem('Cc', ExecComp('c=x+2'), promotes=['*'])

                self.add_design_var('x')
                self.add_constraint('c', lower=-3.)

        prob = Problem()

        prob.model.add_subsystem('par', ParallelGroup())

        prob.model.par.add_subsystem('G1', Mygroup())
        prob.model.par.add_subsystem('G2', Mygroup())

        prob.model.add_subsystem('Obj', ExecComp('obj=y1+y2'))

        prob.model.connect('par.G1.y', 'Obj.y1')
        prob.model.connect('par.G2.y', 'Obj.y2')

        prob.model.add_objective('Obj.obj')

        prob.driver = pyOptSparseDriver()
        prob.driver.options['optimizer'] = 'SLSQP'
        prob.driver.options['print_results'] = False

        prob.driver.options['debug_print'] = [
            'desvars', 'ln_cons', 'nl_cons', 'objs'
        ]

        prob.setup()

        stdout = sys.stdout
        strout = StringIO()
        sys.stdout = strout
        sys.stdout = strout
        try:
            prob.run_driver()
        finally:
            sys.stdout = stdout

        output = strout.getvalue().split('\n')
        if MPI.COMM_WORLD.rank == 0:
            # Just make sure we have more than one. Not sure we will always have the same number
            #    of iterations
            self.assertTrue(
                output.count("Design Vars") > 1,
                "Should be more than one design vars header printed")
            self.assertTrue(
                output.count("Nonlinear constraints") > 1,
                "Should be more than one nonlinear constraint header printed")
            self.assertTrue(
                output.count("Linear constraints") > 1,
                "Should be more than one linear constraint header printed")
            self.assertTrue(
                output.count("Objectives") > 1,
                "Should be more than one objective header printed")

            self.assertTrue(
                len([s for s in output if 'par.G1.indep_var_comp.x' in s]) > 1,
                "Should be more than one par.G1.indep_var_comp.x printed")
            self.assertTrue(
                len([s for s in output if 'par.G2.indep_var_comp.x' in s]) > 1,
                "Should be more than one par.G2.indep_var_comp.x printed")
            self.assertTrue(
                len([s for s in output if 'par.G1.Cc.c' in s]) > 1,
                "Should be more than one par.G1.Cc.c printed")
            self.assertTrue(
                len([s for s in output if 'par.G2.Cc.c' in s]) > 1,
                "Should be more than one par.G2.Cc.c printed")
            self.assertTrue(
                len([s for s in output if s.startswith('None')]) > 1,
                "Should be more than one None printed")
            self.assertTrue(
                len([s for s in output if 'Obj.obj' in s]) > 1,
                "Should be more than one Obj.obj printed")
        else:
            self.assertEqual(output, [''])
Example #22
0
    def test_balanced_field_length_for_docs(self):
        import matplotlib.pyplot as plt
        import openmdao.api as om
        from openmdao.utils.general_utils import set_pyoptsparse_opt
        import dymos as dm
        from dymos.examples.balanced_field.balanced_field_ode import BalancedFieldODEComp

        p = om.Problem()

        _, optimizer = set_pyoptsparse_opt('IPOPT', fallback=True)

        p.driver = om.pyOptSparseDriver()
        p.driver.declare_coloring()

        # Use IPOPT if available, with fallback to SLSQP
        p.driver.options['optimizer'] = optimizer
        p.driver.options['print_results'] = False
        if optimizer == 'IPOPT':
            p.driver.opt_settings['print_level'] = 5
            p.driver.opt_settings['derivative_test'] = 'first-order'

        # First Phase: Brake release to V1 - both engines operable
        br_to_v1 = dm.Phase(ode_class=BalancedFieldODEComp,
                            transcription=dm.Radau(num_segments=3),
                            ode_init_kwargs={'mode': 'runway'})
        br_to_v1.set_time_options(fix_initial=True,
                                  duration_bounds=(1, 1000),
                                  duration_ref=10.0)
        br_to_v1.add_state('r',
                           fix_initial=True,
                           lower=0,
                           ref=1000.0,
                           defect_ref=1000.0)
        br_to_v1.add_state('v',
                           fix_initial=True,
                           lower=0,
                           ref=100.0,
                           defect_ref=100.0)
        br_to_v1.add_parameter('alpha', val=0.0, opt=False, units='deg')
        br_to_v1.add_timeseries_output('*')

        # Second Phase: Rejected takeoff at V1 - no engines operable
        rto = dm.Phase(ode_class=BalancedFieldODEComp,
                       transcription=dm.Radau(num_segments=3),
                       ode_init_kwargs={'mode': 'runway'})
        rto.set_time_options(fix_initial=False,
                             duration_bounds=(1, 1000),
                             duration_ref=1.0)
        rto.add_state('r',
                      fix_initial=False,
                      lower=0,
                      ref=1000.0,
                      defect_ref=1000.0)
        rto.add_state('v',
                      fix_initial=False,
                      lower=0,
                      ref=100.0,
                      defect_ref=100.0)
        rto.add_parameter('alpha', val=0.0, opt=False, units='deg')
        rto.add_timeseries_output('*')

        # Third Phase: V1 to Vr - single engine operable
        v1_to_vr = dm.Phase(ode_class=BalancedFieldODEComp,
                            transcription=dm.Radau(num_segments=3),
                            ode_init_kwargs={'mode': 'runway'})
        v1_to_vr.set_time_options(fix_initial=False,
                                  duration_bounds=(1, 1000),
                                  duration_ref=1.0)
        v1_to_vr.add_state('r',
                           fix_initial=False,
                           lower=0,
                           ref=1000.0,
                           defect_ref=1000.0)
        v1_to_vr.add_state('v',
                           fix_initial=False,
                           lower=0,
                           ref=100.0,
                           defect_ref=100.0)
        v1_to_vr.add_parameter('alpha', val=0.0, opt=False, units='deg')
        v1_to_vr.add_timeseries_output('*')

        # Fourth Phase: Rotate - single engine operable
        rotate = dm.Phase(ode_class=BalancedFieldODEComp,
                          transcription=dm.Radau(num_segments=3),
                          ode_init_kwargs={'mode': 'runway'})
        rotate.set_time_options(fix_initial=False,
                                duration_bounds=(1.0, 5),
                                duration_ref=1.0)
        rotate.add_state('r',
                         fix_initial=False,
                         lower=0,
                         ref=1000.0,
                         defect_ref=1000.0)
        rotate.add_state('v',
                         fix_initial=False,
                         lower=0,
                         ref=100.0,
                         defect_ref=100.0)
        rotate.add_polynomial_control('alpha',
                                      order=1,
                                      opt=True,
                                      units='deg',
                                      lower=0,
                                      upper=10,
                                      ref=10,
                                      val=[0, 10])
        rotate.add_timeseries_output('*')

        # Fifth Phase: Climb to target speed and altitude at end of runway.
        climb = dm.Phase(ode_class=BalancedFieldODEComp,
                         transcription=dm.Radau(num_segments=5),
                         ode_init_kwargs={'mode': 'climb'})
        climb.set_time_options(fix_initial=False,
                               duration_bounds=(1, 100),
                               duration_ref=1.0)
        climb.add_state('r',
                        fix_initial=False,
                        lower=0,
                        ref=1000.0,
                        defect_ref=1000.0)
        climb.add_state('h',
                        fix_initial=True,
                        lower=0,
                        ref=1.0,
                        defect_ref=1.0)
        climb.add_state('v',
                        fix_initial=False,
                        lower=0,
                        ref=100.0,
                        defect_ref=100.0)
        climb.add_state('gam',
                        fix_initial=True,
                        lower=0,
                        ref=0.05,
                        defect_ref=0.05)
        climb.add_control('alpha',
                          opt=True,
                          units='deg',
                          lower=-10,
                          upper=15,
                          ref=10)
        climb.add_timeseries_output('*')

        # Instantiate the trajectory and add phases
        traj = dm.Trajectory()
        p.model.add_subsystem('traj', traj)
        traj.add_phase('br_to_v1', br_to_v1)
        traj.add_phase('rto', rto)
        traj.add_phase('v1_to_vr', v1_to_vr)
        traj.add_phase('rotate', rotate)
        traj.add_phase('climb', climb)

        # Add parameters common to multiple phases to the trajectory
        traj.add_parameter('m',
                           val=174200.,
                           opt=False,
                           units='lbm',
                           desc='aircraft mass',
                           targets={
                               'br_to_v1': ['m'],
                               'v1_to_vr': ['m'],
                               'rto': ['m'],
                               'rotate': ['m'],
                               'climb': ['m']
                           })

        traj.add_parameter('T_nominal',
                           val=27000 * 2,
                           opt=False,
                           units='lbf',
                           dynamic=False,
                           desc='nominal aircraft thrust',
                           targets={'br_to_v1': ['T']})

        traj.add_parameter('T_engine_out',
                           val=27000,
                           opt=False,
                           units='lbf',
                           dynamic=False,
                           desc='thrust under a single engine',
                           targets={
                               'v1_to_vr': ['T'],
                               'rotate': ['T'],
                               'climb': ['T']
                           })

        traj.add_parameter(
            'T_shutdown',
            val=0.0,
            opt=False,
            units='lbf',
            dynamic=False,
            desc='thrust when engines are shut down for rejected takeoff',
            targets={'rto': ['T']})

        traj.add_parameter('mu_r_nominal',
                           val=0.03,
                           opt=False,
                           units=None,
                           dynamic=False,
                           desc='nominal runway friction coefficient',
                           targets={
                               'br_to_v1': ['mu_r'],
                               'v1_to_vr': ['mu_r'],
                               'rotate': ['mu_r']
                           })

        traj.add_parameter('mu_r_braking',
                           val=0.3,
                           opt=False,
                           units=None,
                           dynamic=False,
                           desc='runway friction coefficient under braking',
                           targets={'rto': ['mu_r']})

        traj.add_parameter('h_runway',
                           val=0.,
                           opt=False,
                           units='ft',
                           desc='runway altitude',
                           targets={
                               'br_to_v1': ['h'],
                               'v1_to_vr': ['h'],
                               'rto': ['h'],
                               'rotate': ['h']
                           })

        traj.add_parameter('rho',
                           val=1.225,
                           opt=False,
                           units='kg/m**3',
                           dynamic=False,
                           desc='atmospheric density',
                           targets={
                               'br_to_v1': ['rho'],
                               'v1_to_vr': ['rho'],
                               'rto': ['rho'],
                               'rotate': ['rho']
                           })

        traj.add_parameter('S',
                           val=124.7,
                           opt=False,
                           units='m**2',
                           dynamic=False,
                           desc='aerodynamic reference area',
                           targets={
                               'br_to_v1': ['S'],
                               'v1_to_vr': ['S'],
                               'rto': ['S'],
                               'rotate': ['S'],
                               'climb': ['S']
                           })

        traj.add_parameter(
            'CD0',
            val=0.03,
            opt=False,
            units=None,
            dynamic=False,
            desc='zero-lift drag coefficient',
            targets={
                f'{phase}': ['CD0']
                for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate'
                              'climb']
            })

        traj.add_parameter(
            'AR',
            val=9.45,
            opt=False,
            units=None,
            dynamic=False,
            desc='wing aspect ratio',
            targets={
                f'{phase}': ['AR']
                for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate'
                              'climb']
            })

        traj.add_parameter(
            'e',
            val=801,
            opt=False,
            units=None,
            dynamic=False,
            desc='Oswald span efficiency factor',
            targets={
                f'{phase}': ['e']
                for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate'
                              'climb']
            })

        traj.add_parameter(
            'span',
            val=35.7,
            opt=False,
            units='m',
            dynamic=False,
            desc='wingspan',
            targets={
                f'{phase}': ['span']
                for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate'
                              'climb']
            })

        traj.add_parameter(
            'h_w',
            val=1.0,
            opt=False,
            units='m',
            dynamic=False,
            desc='height of wing above CG',
            targets={
                f'{phase}': ['h_w']
                for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate'
                              'climb']
            })

        traj.add_parameter(
            'CL0',
            val=0.5,
            opt=False,
            units=None,
            dynamic=False,
            desc='zero-alpha lift coefficient',
            targets={
                f'{phase}': ['CL0']
                for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate'
                              'climb']
            })

        traj.add_parameter(
            'CL_max',
            val=2.0,
            opt=False,
            units=None,
            dynamic=False,
            desc='maximum lift coefficient for linear fit',
            targets={
                f'{phase}': ['CL_max']
                for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate'
                              'climb']
            })

        traj.add_parameter(
            'alpha_max',
            val=10.0,
            opt=False,
            units='deg',
            dynamic=False,
            desc='angle of attack at maximum lift',
            targets={
                f'{phase}': ['alpha_max']
                for phase in ['br_to_v1', 'v1_to_vr', 'rto', 'rotate'
                              'climb']
            })

        # Standard "end of first phase to beginning of second phase" linkages
        # Alpha changes from being a parameter in v1_to_vr to a polynomial control
        # in rotate, to a dynamic control in `climb`.
        traj.link_phases(['br_to_v1', 'v1_to_vr'], vars=['time', 'r', 'v'])
        traj.link_phases(['v1_to_vr', 'rotate'],
                         vars=['time', 'r', 'v', 'alpha'])
        traj.link_phases(['rotate', 'climb'], vars=['time', 'r', 'v', 'alpha'])
        traj.link_phases(['br_to_v1', 'rto'], vars=['time', 'r', 'v'])

        # Less common "final value of r must be the match at ends of two phases".
        traj.add_linkage_constraint(phase_a='rto',
                                    var_a='r',
                                    loc_a='final',
                                    phase_b='climb',
                                    var_b='r',
                                    loc_b='final',
                                    ref=1000)

        # Define the constraints and objective for the optimal control problem
        v1_to_vr.add_boundary_constraint('v_over_v_stall',
                                         loc='final',
                                         lower=1.2,
                                         ref=100)

        rto.add_boundary_constraint('v',
                                    loc='final',
                                    equals=0.,
                                    ref=100,
                                    linear=True)

        rotate.add_boundary_constraint('F_r',
                                       loc='final',
                                       equals=0,
                                       ref=100000)

        climb.add_boundary_constraint('h',
                                      loc='final',
                                      equals=35,
                                      ref=35,
                                      units='ft',
                                      linear=True)
        climb.add_boundary_constraint('gam',
                                      loc='final',
                                      equals=5,
                                      ref=5,
                                      units='deg',
                                      linear=True)
        climb.add_path_constraint('gam', lower=0, upper=5, ref=5, units='deg')
        climb.add_boundary_constraint('v_over_v_stall',
                                      loc='final',
                                      lower=1.25,
                                      ref=1.25)

        rto.add_objective('r', loc='final', ref=1000.0)

        #
        # Setup the problem and set the initial guess
        #
        p.setup(check=True)

        p.set_val('traj.br_to_v1.t_initial', 0)
        p.set_val('traj.br_to_v1.t_duration', 35)
        p.set_val('traj.br_to_v1.states:r',
                  br_to_v1.interpolate(ys=[0, 2500.0], nodes='state_input'))
        p.set_val('traj.br_to_v1.states:v',
                  br_to_v1.interpolate(ys=[0, 100.0], nodes='state_input'))
        p.set_val('traj.br_to_v1.parameters:alpha', 0, units='deg')

        p.set_val('traj.v1_to_vr.t_initial', 35)
        p.set_val('traj.v1_to_vr.t_duration', 35)
        p.set_val('traj.v1_to_vr.states:r',
                  v1_to_vr.interpolate(ys=[2500, 300.0], nodes='state_input'))
        p.set_val('traj.v1_to_vr.states:v',
                  v1_to_vr.interpolate(ys=[100, 110.0], nodes='state_input'))
        p.set_val('traj.v1_to_vr.parameters:alpha', 0.0, units='deg')

        p.set_val('traj.rto.t_initial', 35)
        p.set_val('traj.rto.t_duration', 35)
        p.set_val('traj.rto.states:r',
                  rto.interpolate(ys=[2500, 5000.0], nodes='state_input'))
        p.set_val('traj.rto.states:v',
                  rto.interpolate(ys=[110, 0], nodes='state_input'))
        p.set_val('traj.rto.parameters:alpha', 0.0, units='deg')

        p.set_val('traj.rotate.t_initial', 70)
        p.set_val('traj.rotate.t_duration', 5)
        p.set_val('traj.rotate.states:r',
                  rotate.interpolate(ys=[1750, 1800.0], nodes='state_input'))
        p.set_val('traj.rotate.states:v',
                  rotate.interpolate(ys=[80, 85.0], nodes='state_input'))
        p.set_val('traj.rotate.polynomial_controls:alpha', 0.0, units='deg')

        p.set_val('traj.climb.t_initial', 75)
        p.set_val('traj.climb.t_duration', 15)
        p.set_val('traj.climb.states:r',
                  climb.interpolate(ys=[5000, 5500.0], nodes='state_input'),
                  units='ft')
        p.set_val('traj.climb.states:v',
                  climb.interpolate(ys=[160, 170.0], nodes='state_input'),
                  units='kn')
        p.set_val('traj.climb.states:h',
                  climb.interpolate(ys=[0, 35.0], nodes='state_input'),
                  units='ft')
        p.set_val('traj.climb.states:gam',
                  climb.interpolate(ys=[0, 5.0], nodes='state_input'),
                  units='deg')
        p.set_val('traj.climb.controls:alpha', 5.0, units='deg')

        dm.run_problem(p, run_driver=True, simulate=True)

        sim_case = om.CaseReader('dymos_solution.db').get_case('final')

        fig, axes = plt.subplots(2, 1, sharex=True, gridspec_kw={'top': 0.92})
        for phase in ['br_to_v1', 'rto', 'v1_to_vr', 'rotate', 'climb']:
            r = sim_case.get_val(f'traj.{phase}.timeseries.states:r',
                                 units='ft')
            v = sim_case.get_val(f'traj.{phase}.timeseries.states:v',
                                 units='kn')
            t = sim_case.get_val(f'traj.{phase}.timeseries.time', units='s')
            axes[0].plot(t, r, '-', label=phase)
            axes[1].plot(t, v, '-', label=phase)
        fig.suptitle('Balanced Field Length')
        axes[1].set_xlabel('time (s)')
        axes[0].set_ylabel('range (ft)')
        axes[1].set_ylabel('airspeed (kts)')
        axes[0].grid(True)
        axes[1].grid(True)

        tv1 = sim_case.get_val('traj.br_to_v1.timeseries.time', units='s')[-1,
                                                                           0]
        v1 = sim_case.get_val('traj.br_to_v1.timeseries.states:v',
                              units='kn')[-1, 0]

        tf_rto = sim_case.get_val('traj.rto.timeseries.time', units='s')[-1, 0]
        rf_rto = sim_case.get_val('traj.rto.timeseries.states:r',
                                  units='ft')[-1, 0]

        axes[0].annotate(f'field length = {r[-1, 0]:5.1f} ft',
                         xy=(t[-1, 0], r[-1, 0]),
                         xycoords='data',
                         xytext=(0.7, 0.5),
                         textcoords='axes fraction',
                         arrowprops=dict(arrowstyle='->'),
                         horizontalalignment='center',
                         verticalalignment='top')

        axes[0].annotate(f'',
                         xy=(tf_rto, rf_rto),
                         xycoords='data',
                         xytext=(0.7, 0.5),
                         textcoords='axes fraction',
                         arrowprops=dict(arrowstyle='->'),
                         horizontalalignment='center',
                         verticalalignment='top')

        axes[1].annotate(f'$v1$ = {v1:5.1f} kts',
                         xy=(tv1, v1),
                         xycoords='data',
                         xytext=(0.5, 0.5),
                         textcoords='axes fraction',
                         arrowprops=dict(arrowstyle='->'),
                         horizontalalignment='center',
                         verticalalignment='top')

        plt.legend()
        plt.show()
import os
import unittest
from numpy.testing import assert_almost_equal

import openmdao.api as om

import dymos as dm
from dymos.examples.brachistochrone.brachistochrone_ode import BrachistochroneODE

from openmdao.utils.general_utils import set_pyoptsparse_opt
from openmdao.utils.testing_utils import use_tempdirs
OPT, OPTIMIZER = set_pyoptsparse_opt('SNOPT', fallback=True)


@use_tempdirs
class TestBrachistochroneRefineGrid(unittest.TestCase):
    def make_problem(self,
                     transcription='radau-ps',
                     num_segments=5,
                     transcription_order=3,
                     compressed=True):

        self.p = p = om.Problem(model=om.Group())

        p.driver = om.ScipyOptimizeDriver()
        p.driver.declare_coloring()

        if transcription == 'gauss-lobatto':
            t = dm.GaussLobatto(num_segments=num_segments,
                                order=transcription_order,
                                compressed=compressed)
def ex_aircraft_steady_flight(optimizer='SLSQP',
                              solve_segments=False,
                              use_boundary_constraints=False,
                              compressed=False):
    p = om.Problem(model=om.Group())
    p.driver = om.pyOptSparseDriver()
    _, optimizer = set_pyoptsparse_opt(optimizer, fallback=False)
    p.driver.options['optimizer'] = optimizer
    p.driver.declare_coloring()
    if optimizer == 'SNOPT':
        p.driver.opt_settings['Major iterations limit'] = 20
        p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6
        p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6
        p.driver.opt_settings["Linesearch tolerance"] = 0.10
        p.driver.opt_settings['iSumm'] = 6
    if optimizer == 'SLSQP':
        p.driver.opt_settings['MAXIT'] = 50

    num_seg = 15
    seg_ends, _ = lgl(num_seg + 1)

    phase = dm.Phase(ode_class=AircraftODE,
                     transcription=dm.Radau(num_segments=num_seg,
                                            segment_ends=seg_ends,
                                            order=3,
                                            compressed=compressed,
                                            solve_segments=solve_segments))

    # Pass Reference Area from an external source
    assumptions = p.model.add_subsystem('assumptions', om.IndepVarComp())
    assumptions.add_output('S', val=427.8, units='m**2')
    assumptions.add_output('mass_empty', val=1.0, units='kg')
    assumptions.add_output('mass_payload', val=1.0, units='kg')

    p.model.add_subsystem('phase0', phase)

    phase.set_time_options(initial_bounds=(0, 0),
                           duration_bounds=(300, 10000),
                           duration_ref=5600)

    fix_final = True
    if use_boundary_constraints:
        fix_final = False
        phase.add_boundary_constraint('mass_fuel',
                                      loc='final',
                                      units='lbm',
                                      equals=1e-3,
                                      linear=False)
        phase.add_boundary_constraint('alt',
                                      loc='final',
                                      units='kft',
                                      equals=10.0,
                                      linear=False)

    phase.add_state('range',
                    units='NM',
                    rate_source='range_rate_comp.dXdt:range',
                    fix_initial=True,
                    fix_final=False,
                    ref=1e-3,
                    defect_ref=1e-3,
                    lower=0,
                    upper=2000)

    phase.add_state('mass_fuel',
                    units='lbm',
                    rate_source='propulsion.dXdt:mass_fuel',
                    targets=['mass_comp.mass_fuel'],
                    fix_initial=True,
                    fix_final=fix_final,
                    upper=1.5E5,
                    lower=0.0,
                    ref=1e2,
                    defect_ref=1e2)

    phase.add_state('alt',
                    units='kft',
                    rate_source='climb_rate',
                    targets=['atmos.h', 'aero.alt', 'propulsion.alt'],
                    fix_initial=True,
                    fix_final=fix_final,
                    lower=0.0,
                    upper=60,
                    ref=1e-3,
                    defect_ref=1e-3)

    phase.add_control('climb_rate',
                      units='ft/min',
                      opt=True,
                      lower=-3000,
                      upper=3000,
                      targets=['gam_comp.climb_rate'],
                      rate_continuity=True,
                      rate2_continuity=False)

    phase.add_control('mach',
                      targets=['tas_comp.mach', 'aero.mach'],
                      units=None,
                      opt=False)

    phase.add_input_parameter(
        'S',
        targets=['aero.S', 'flight_equilibrium.S', 'propulsion.S'],
        units='m**2')

    phase.add_input_parameter('mass_empty',
                              targets=['mass_comp.mass_empty'],
                              units='kg')
    phase.add_input_parameter('mass_payload',
                              targets=['mass_comp.mass_payload'],
                              units='kg')

    phase.add_path_constraint('propulsion.tau',
                              lower=0.01,
                              upper=2.0,
                              shape=(1, ))

    p.model.connect('assumptions.S', 'phase0.input_parameters:S')
    p.model.connect('assumptions.mass_empty',
                    'phase0.input_parameters:mass_empty')
    p.model.connect('assumptions.mass_payload',
                    'phase0.input_parameters:mass_payload')

    phase.add_objective('range', loc='final', ref=-1.0e-4)

    p.setup()

    p['phase0.t_initial'] = 0.0
    p['phase0.t_duration'] = 3600.0
    p['phase0.states:range'][:] = phase.interpolate(ys=(0, 724.0),
                                                    nodes='state_input')
    p['phase0.states:mass_fuel'][:] = phase.interpolate(ys=(30000, 1e-3),
                                                        nodes='state_input')
    p['phase0.states:alt'][:] = 10.0

    p['phase0.controls:mach'][:] = 0.8

    p['assumptions.S'] = 427.8
    p['assumptions.mass_empty'] = 0.15E6
    p['assumptions.mass_payload'] = 84.02869 * 400

    dm.run_problem(p)

    return p
Example #25
0
    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()
Example #26
0
    def test_two_burn_orbit_raise_gl_rk_gl_constrained(self):
        import numpy as np

        import matplotlib.pyplot as plt

        from openmdao.api import Problem, Group, pyOptSparseDriver, DirectSolver
        from openmdao.utils.assert_utils import assert_rel_error
        from openmdao.utils.general_utils import set_pyoptsparse_opt

        from dymos import Phase, GaussLobatto, RungeKutta, Trajectory
        from dymos.examples.finite_burn_orbit_raise.finite_burn_eom import FiniteBurnODE

        traj = Trajectory()
        p = Problem(model=Group())
        p.model.add_subsystem('traj', traj)

        p.driver = pyOptSparseDriver()
        _, optimizer = set_pyoptsparse_opt('SNOPT', fallback=True)
        p.driver.options['optimizer'] = optimizer

        p.driver.options['dynamic_simul_derivs'] = True

        traj.add_design_parameter('c', opt=False, val=1.5, units='DU/TU')

        # First Phase (burn)

        burn1 = Phase(ode_class=FiniteBurnODE,
                      transcription=GaussLobatto(num_segments=10, order=3, compressed=True))

        burn1 = traj.add_phase('burn1', burn1)

        burn1.set_time_options(fix_initial=True, duration_bounds=(.5, 10))
        burn1.set_state_options('r', fix_initial=True, fix_final=False)
        burn1.set_state_options('theta', fix_initial=True, fix_final=False)
        burn1.set_state_options('vr', fix_initial=True, fix_final=False)
        burn1.set_state_options('vt', fix_initial=True, fix_final=False)
        burn1.set_state_options('accel', fix_initial=True, fix_final=False)
        burn1.set_state_options('deltav', fix_initial=True, fix_final=False)
        burn1.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg',
                          scaler=0.01, lower=-30, upper=30)

        # Second Phase (Coast)
        coast = Phase(ode_class=FiniteBurnODE,
                      transcription=RungeKutta(num_segments=20, compressed=True))

        traj.add_phase('coast', coast)

        coast.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), duration_ref=10)
        coast.set_state_options('r', fix_initial=False, fix_final=False)
        coast.set_state_options('theta', fix_initial=False, fix_final=False)
        coast.set_state_options('vr', fix_initial=False, fix_final=False)
        coast.set_state_options('vt', fix_initial=False, fix_final=False)
        coast.set_state_options('accel', fix_initial=True, fix_final=False)
        coast.set_state_options('deltav', fix_initial=False, fix_final=False)
        coast.add_design_parameter('u1', opt=False, val=0.0)

        # Third Phase (burn)

        burn2 = Phase(ode_class=FiniteBurnODE,
                      transcription=GaussLobatto(num_segments=10, order=3, compressed=True))

        traj.add_phase('burn2', burn2)

        burn2.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10), initial_ref=10)
        burn2.set_state_options('r', fix_initial=False, fix_final=True)
        burn2.set_state_options('theta', fix_initial=False, fix_final=False)
        burn2.set_state_options('vr', fix_initial=False, fix_final=True)
        burn2.set_state_options('vt', fix_initial=False, fix_final=True)
        burn2.set_state_options('accel', fix_initial=False, fix_final=False, defect_scaler=1.0)
        burn2.set_state_options('deltav', fix_initial=False, fix_final=False, defect_scaler=1.0)
        burn2.add_control('u1', rate_continuity=True, rate2_continuity=True, units='deg',
                          scaler=0.01, lower=-30, upper=30)

        burn2.add_objective('deltav', loc='final', scaler=1.0)

        burn1.add_timeseries_output('pos_x', units='DU')
        coast.add_timeseries_output('pos_x', units='DU')
        burn2.add_timeseries_output('pos_x', units='DU')

        burn1.add_timeseries_output('pos_y', units='DU')
        coast.add_timeseries_output('pos_y', units='DU')
        burn2.add_timeseries_output('pos_y', units='DU')

        # Link Phases
        traj.link_phases(phases=['burn1', 'coast', 'burn2'],
                         vars=['time', 'r', 'theta', 'vr', 'vt', 'deltav'])
        traj.link_phases(phases=['burn1', 'burn2'], vars=['accel'])

        # Finish Problem Setup
        p.model.linear_solver = DirectSolver()

        p.setup(check=True, force_alloc_complex=True)

        # Set Initial Guesses
        p.set_val('traj.design_parameters:c', value=1.5)

        p.set_val('traj.burn1.t_initial', value=0.0)
        p.set_val('traj.burn1.t_duration', value=2.25)

        p.set_val('traj.burn1.states:r',
                  value=burn1.interpolate(ys=[1, 1.5], nodes='state_input'))
        p.set_val('traj.burn1.states:theta',
                  value=burn1.interpolate(ys=[0, 1.7], nodes='state_input'))
        p.set_val('traj.burn1.states:vr',
                  value=burn1.interpolate(ys=[0, 0], nodes='state_input'))
        p.set_val('traj.burn1.states:vt',
                  value=burn1.interpolate(ys=[1, 1], nodes='state_input'))
        p.set_val('traj.burn1.states:accel',
                  value=burn1.interpolate(ys=[0.1, 0], nodes='state_input'))
        p.set_val('traj.burn1.states:deltav',
                  value=burn1.interpolate(ys=[0, 0.1], nodes='state_input'), )
        p.set_val('traj.burn1.controls:u1',
                  value=burn1.interpolate(ys=[-3.5, 13.0], nodes='control_input'))

        p.set_val('traj.coast.t_initial', value=2.25)
        p.set_val('traj.coast.t_duration', value=3.0)

        p.set_val('traj.coast.states:r',
                  value=coast.interpolate(ys=[1.3, 1.5], nodes='state_input'))
        p.set_val('traj.coast.states:theta',
                  value=coast.interpolate(ys=[2.1767, 1.7], nodes='state_input'))
        p.set_val('traj.coast.states:vr',
                  value=coast.interpolate(ys=[0.3285, 0], nodes='state_input'))
        p.set_val('traj.coast.states:vt',
                  value=coast.interpolate(ys=[0.97, 1], nodes='state_input'))
        p.set_val('traj.coast.states:accel',
                  value=coast.interpolate(ys=[0, 0], nodes='state_input'))
        # p.set_val('traj.coast.controls:u1',
        #           value=coast.interpolate(ys=[0, 0], nodes='control_input'))

        p.set_val('traj.burn2.t_initial', value=5.25)
        p.set_val('traj.burn2.t_duration', value=1.75)

        p.set_val('traj.burn2.states:r',
                  value=burn2.interpolate(ys=[1.8, 3], nodes='state_input'))
        p.set_val('traj.burn2.states:theta',
                  value=burn2.interpolate(ys=[3.2, 4.0], nodes='state_input'))
        p.set_val('traj.burn2.states:vr',
                  value=burn2.interpolate(ys=[.5, 0], nodes='state_input'))
        p.set_val('traj.burn2.states:vt',
                  value=burn2.interpolate(ys=[1, np.sqrt(1 / 3)], nodes='state_input'))
        p.set_val('traj.burn2.states:accel',
                  value=burn2.interpolate(ys=[0.1, 0], nodes='state_input'))
        p.set_val('traj.burn2.states:deltav',
                  value=burn2.interpolate(ys=[0.1, 0.2], nodes='state_input'))
        p.set_val('traj.burn2.controls:u1',
                  value=burn2.interpolate(ys=[1, 1], nodes='control_input'))

        p.run_driver()

        assert_rel_error(self,
                         p.get_val('traj.burn2.timeseries.states:deltav')[-1],
                         0.3995,
                         tolerance=2.0E-3)

        # Plot results
        exp_out = traj.simulate()

        fig = plt.figure(figsize=(8, 4))
        fig.suptitle('Two Burn Orbit Raise Solution')
        ax_u1 = plt.subplot2grid((2, 2), (0, 0))
        ax_deltav = plt.subplot2grid((2, 2), (1, 0))
        ax_xy = plt.subplot2grid((2, 2), (0, 1), rowspan=2)

        span = np.linspace(0, 2 * np.pi, 100)
        ax_xy.plot(np.cos(span), np.sin(span), 'k--', lw=1)
        ax_xy.plot(3 * np.cos(span), 3 * np.sin(span), 'k--', lw=1)
        ax_xy.set_xlim(-4.5, 4.5)
        ax_xy.set_ylim(-4.5, 4.5)

        ax_xy.set_xlabel('x ($R_e$)')
        ax_xy.set_ylabel('y ($R_e$)')

        ax_u1.set_xlabel('time ($TU$)')
        ax_u1.set_ylabel('$u_1$ ($deg$)')
        ax_u1.grid(True)

        ax_deltav.set_xlabel('time ($TU$)')
        ax_deltav.set_ylabel('${\Delta}v$ ($DU/TU$)')
        ax_deltav.grid(True)

        t_sol = dict((phs, p.get_val('traj.{0}.timeseries.time'.format(phs)))
                     for phs in ['burn1', 'coast', 'burn2'])
        x_sol = dict((phs, p.get_val('traj.{0}.timeseries.pos_x'.format(phs)))
                     for phs in ['burn1', 'coast', 'burn2'])
        y_sol = dict((phs, p.get_val('traj.{0}.timeseries.pos_y'.format(phs)))
                     for phs in ['burn1', 'coast', 'burn2'])
        dv_sol = dict((phs, p.get_val('traj.{0}.timeseries.states:deltav'.format(phs)))
                      for phs in ['burn1', 'coast', 'burn2'])
        u1_sol = dict((phs, p.get_val('traj.{0}.timeseries.controls:u1'.format(phs), units='deg'))
                      for phs in ['burn1', 'burn2'])

        t_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.time'.format(phs)))
                     for phs in ['burn1', 'coast', 'burn2'])
        x_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.pos_x'.format(phs)))
                     for phs in ['burn1', 'coast', 'burn2'])
        y_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.pos_y'.format(phs)))
                     for phs in ['burn1', 'coast', 'burn2'])
        dv_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.states:deltav'.format(phs)))
                      for phs in ['burn1', 'coast', 'burn2'])
        u1_exp = dict((phs, exp_out.get_val('traj.{0}.timeseries.controls:u1'.format(phs),
                                            units='deg'))
                      for phs in ['burn1', 'burn2'])

        for phs in ['burn1', 'coast', 'burn2']:
            try:
                ax_u1.plot(t_sol[phs], u1_sol[phs], 'ro', ms=3)
                ax_u1.plot(t_exp[phs], u1_exp[phs], 'b-')
            except KeyError:
                pass

            ax_deltav.plot(t_sol[phs], dv_sol[phs], 'ro', ms=3)
            ax_deltav.plot(t_exp[phs], dv_exp[phs], 'b-')

            ax_xy.plot(x_sol[phs], y_sol[phs], 'ro', ms=3, label='implicit')
            ax_xy.plot(x_exp[phs], y_exp[phs], 'b-', label='explicit')

        plt.show()
from shutil import rmtree
from tempfile import mkdtemp

import numpy as np

from openmdao.utils.general_utils import set_pyoptsparse_opt
from openmdao.utils.mpi import MPI

if MPI:
    from openmdao.api import PETScVector
    vector_class = PETScVector
else:
    PETScVector = None

# check that pyoptsparse is installed. if it is, try to use SLSQP.
OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP')

if OPTIMIZER:
    from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver

from openmdao.api import ExecComp, ExplicitComponent, Problem, \
    Group, ParallelGroup, IndepVarComp, SqliteRecorder
from openmdao.utils.array_utils import evenly_distrib_idxs
from openmdao.recorders.tests.sqlite_recorder_test_utils import assertDriverIterationDataRecorded
from openmdao.recorders.tests.recorder_test_utils import run_driver

class DistributedAdder(ExplicitComponent):
    """
    Distributes the work of adding 10 to every item in the param vector
    """
Example #28
0
    def test_reentry_mixed_controls(self):

        p = om.Problem(model=om.Group())
        p.driver = om.pyOptSparseDriver()
        p.driver.declare_coloring()
        OPT, OPTIMIZER = set_pyoptsparse_opt('IPOPT', fallback=False)
        p.driver.options['optimizer'] = OPTIMIZER

        traj = p.model.add_subsystem('traj', Trajectory())
        phase0 = traj.add_phase(
            'phase0',
            Phase(ode_class=ShuttleODE,
                  transcription=GaussLobatto(num_segments=20, order=3)))

        phase0.set_time_options(fix_initial=True, units='s', duration_ref=200)
        phase0.add_state('h',
                         fix_initial=True,
                         fix_final=True,
                         units='ft',
                         rate_source='hdot',
                         targets=['h'],
                         lower=0,
                         ref0=75000,
                         ref=300000,
                         defect_ref=1000)
        phase0.add_state('gamma',
                         fix_initial=True,
                         fix_final=True,
                         units='rad',
                         rate_source='gammadot',
                         targets=['gamma'],
                         lower=-89. * np.pi / 180,
                         upper=89. * np.pi / 180)
        phase0.add_state('phi',
                         fix_initial=True,
                         fix_final=False,
                         units='rad',
                         rate_source='phidot',
                         lower=0,
                         upper=89. * np.pi / 180)
        phase0.add_state('psi',
                         fix_initial=True,
                         fix_final=False,
                         units='rad',
                         rate_source='psidot',
                         targets=['psi'],
                         lower=0,
                         upper=90. * np.pi / 180)
        phase0.add_state('theta',
                         fix_initial=True,
                         fix_final=False,
                         units='rad',
                         rate_source='thetadot',
                         targets=['theta'],
                         lower=-89. * np.pi / 180,
                         upper=89. * np.pi / 180)
        phase0.add_state('v',
                         fix_initial=True,
                         fix_final=True,
                         units='ft/s',
                         rate_source='vdot',
                         targets=['v'],
                         lower=500,
                         ref0=2500,
                         ref=25000)
        phase0.add_control('alpha',
                           units='rad',
                           opt=True,
                           lower=-np.pi / 2,
                           upper=np.pi / 2)
        phase0.add_polynomial_control('beta',
                                      order=5,
                                      units='rad',
                                      opt=True,
                                      lower=-89 * np.pi / 180,
                                      upper=1 * np.pi / 180)

        phase0.add_objective('theta', loc='final', ref=-0.01)

        p.setup(check=True, force_alloc_complex=True)

        p.set_val('traj.phase0.states:h',
                  phase0.interpolate(ys=[260000, 80000], nodes='state_input'),
                  units='ft')
        p.set_val('traj.phase0.states:gamma',
                  phase0.interpolate(ys=[-1 * np.pi / 180, -5 * np.pi / 180],
                                     nodes='state_input'),
                  units='rad')
        p.set_val('traj.phase0.states:phi',
                  phase0.interpolate(ys=[0, 75 * np.pi / 180],
                                     nodes='state_input'),
                  units='rad')
        p.set_val('traj.phase0.states:psi',
                  phase0.interpolate(ys=[90 * np.pi / 180, 10 * np.pi / 180],
                                     nodes='state_input'),
                  units='rad')
        p.set_val('traj.phase0.states:theta',
                  phase0.interpolate(ys=[0, 25 * np.pi / 180],
                                     nodes='state_input'),
                  units='rad')
        p.set_val('traj.phase0.states:v',
                  phase0.interpolate(ys=[25600, 2500], nodes='state_input'),
                  units='ft/s')
        p.set_val('traj.phase0.t_initial', 0, units='s')
        p.set_val('traj.phase0.t_duration', 2000, units='s')
        p.set_val('traj.phase0.controls:alpha',
                  phase0.interpolate(
                      ys=[17.4 * np.pi / 180, 17.4 * np.pi / 180],
                      nodes='control_input'),
                  units='rad')
        p.set_val('traj.phase0.polynomial_controls:beta', np.radians(-75))

        p.run_driver()

        exp_out = traj.simulate()

        from scipy.interpolate import interp1d

        t_sol = p.get_val('traj.phase0.timeseries.time')
        beta_sol = p.get_val('traj.phase0.timeseries.polynomial_controls:beta')

        t_sim = exp_out.get_val('traj.phase0.timeseries.time')
        beta_sim = exp_out.get_val(
            'traj.phase0.timeseries.polynomial_controls:beta')

        sol_interp = interp1d(t_sol.ravel(), beta_sol.ravel())
        sim_interp = interp1d(t_sim.ravel(), beta_sim.ravel())

        t = np.linspace(0, t_sol.ravel()[-1], 100)

        assert_near_equal(sim_interp(t), sol_interp(t), tolerance=1.0E-3)
    def test_distributed_driver_debug_print_options(self):

        # check that pyoptsparse is installed. if it is, try to use SLSQP.
        OPT, OPTIMIZER = set_pyoptsparse_opt('SLSQP')

        if OPTIMIZER:
            from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver
        else:
            raise unittest.SkipTest("pyOptSparseDriver is required.")

        class Mygroup(Group):

            def setup(self):
                self.add_subsystem('indep_var_comp', IndepVarComp('x'), promotes=['*'])
                self.add_subsystem('Cy', ExecComp('y=2*x'), promotes=['*'])
                self.add_subsystem('Cc', ExecComp('c=x+2'), promotes=['*'])

                self.add_design_var('x')
                self.add_constraint('c', lower=-3.)

        prob = Problem()

        prob.model.add_subsystem('par', ParallelGroup())

        prob.model.par.add_subsystem('G1', Mygroup())
        prob.model.par.add_subsystem('G2', Mygroup())

        prob.model.add_subsystem('Obj', ExecComp('obj=y1+y2'))

        prob.model.connect('par.G1.y', 'Obj.y1')
        prob.model.connect('par.G2.y', 'Obj.y2')

        prob.model.add_objective('Obj.obj')

        prob.driver = pyOptSparseDriver()
        prob.driver.options['optimizer'] = 'SLSQP'
        prob.driver.options['print_results'] = False

        prob.driver.options['debug_print'] = ['desvars', 'ln_cons', 'nl_cons', 'objs']

        prob.setup()

        stdout = sys.stdout
        strout = StringIO()
        sys.stdout = strout
        sys.stdout = strout
        try:
            prob.run_driver()
        finally:
            sys.stdout = stdout

        output = strout.getvalue().split('\n')
        if MPI.COMM_WORLD.rank == 0:
            # Just make sure we have more than one. Not sure we will always have the same number
            #    of iterations
            self.assertTrue(output.count("Design Vars") > 1,
                            "Should be more than one design vars header printed")
            self.assertTrue(output.count("Nonlinear constraints") > 1,
                            "Should be more than one nonlinear constraint header printed")
            self.assertTrue(output.count("Linear constraints") > 1,
                            "Should be more than one linear constraint header printed")
            self.assertTrue(output.count("Objectives") > 1,
                            "Should be more than one objective header printed")

            self.assertTrue(len([s for s in output if 'par.G1.indep_var_comp.x' in s]) > 1,
                            "Should be more than one par.G1.indep_var_comp.x printed")
            self.assertTrue(len([s for s in output if 'par.G2.indep_var_comp.x' in s]) > 1,
                            "Should be more than one par.G2.indep_var_comp.x printed")
            self.assertTrue(len([s for s in output if 'par.G1.Cc.c' in s]) > 1,
                            "Should be more than one par.G1.Cc.c printed")
            self.assertTrue(len([s for s in output if 'par.G2.Cc.c' in s]) > 1,
                            "Should be more than one par.G2.Cc.c printed")
            self.assertTrue(len([s for s in output if s.startswith('None')]) > 1,
                            "Should be more than one None printed")
            self.assertTrue(len([s for s in output if 'Obj.obj' in s]) > 1,
                            "Should be more than one Obj.obj printed")
        else:
            self.assertEqual(output, [''])
Example #30
0
import unittest

import numpy as np

from openmdao.api import Problem, Group, IndepVarComp, ExecComp, AnalysisError, ExplicitComponent
from openmdao.devtools.testutil import assert_rel_error
from openmdao.test_suite.components.paraboloid import Paraboloid
from openmdao.test_suite.components.expl_comp_array import TestExplCompArrayDense
from openmdao.test_suite.components.sellar import SellarDerivativesGrouped
from openmdao.utils.general_utils import set_pyoptsparse_opt


# check that pyoptsparse is installed
# if it is, try to use SNOPT but fall back to SLSQP
OPT, OPTIMIZER = set_pyoptsparse_opt('SNOPT')

if OPTIMIZER:
    from openmdao.drivers.pyoptsparse_driver import pyOptSparseDriver


class ParaboloidAE(ExplicitComponent):
    """ Evaluates the equation f(x,y) = (x-3)^2 + xy + (y+4)^2 - 3
    This version raises an analysis error 50% of the time.
    The AE in ParaboloidAE stands for AnalysisError."""

    def __init__(self):
        super(ParaboloidAE, self).__init__()
        self.fail_hard = False

    def setup(self):
Example #31
0
    def test_promotes_parameter(self):

        for transcription in ['radau-ps', 'gauss-lobatto']:
            with self.subTest(msg=transcription):
                optimizer = 'SLSQP'
                num_segments = 10
                transcription_order = 3
                compressed = False

                p = om.Problem(model=om.Group())

                p.driver = om.pyOptSparseDriver()
                OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=True)
                p.driver.options['optimizer'] = OPTIMIZER
                p.driver.declare_coloring()

                if transcription == 'gauss-lobatto':
                    t = dm.GaussLobatto(num_segments=num_segments,
                                        order=transcription_order,
                                        compressed=compressed)
                elif transcription == 'radau-ps':
                    t = dm.Radau(num_segments=num_segments,
                                 order=transcription_order,
                                 compressed=compressed)

                traj = dm.Trajectory()
                phase = dm.Phase(ode_class=BrachistochroneODE, transcription=t)

                traj.add_phase('phase0',
                               phase,
                               promotes_inputs=[
                                   't_initial', 't_duration', 'parameters:g'
                               ])

                p.model.add_subsystem('traj', traj)

                phase.set_time_options(fix_initial=True,
                                       duration_bounds=(.5, 10),
                                       units='s')

                phase.add_state('x',
                                fix_initial=True,
                                fix_final=False,
                                solve_segments=False,
                                units='m',
                                rate_source='xdot')
                phase.add_state('y',
                                fix_initial=True,
                                fix_final=False,
                                solve_segments=False,
                                units='m',
                                rate_source='ydot')
                phase.add_state('v',
                                fix_initial=True,
                                fix_final=False,
                                solve_segments=False,
                                units='m/s',
                                rate_source='vdot',
                                targets=['v'])

                phase.add_control('theta',
                                  continuity=True,
                                  rate_continuity=True,
                                  units='deg',
                                  lower=0.01,
                                  upper=179.9,
                                  targets=['theta'])

                phase.add_parameter('g',
                                    units='m/s**2',
                                    val=9.80665,
                                    targets=['g'])

                phase.add_boundary_constraint('x', loc='final', equals=10)
                phase.add_boundary_constraint('y', loc='final', equals=5)
                # Minimize time at the end of the phase
                phase.add_objective('time_phase', loc='final', scaler=10)

                p.model.linear_solver = om.DirectSolver()
                p.setup(check=True)

                p.set_val('traj.t_initial', 0.0)
                p.set_val('traj.t_duration', 2.0)

                p.set_val('traj.phase0.states:x', phase.interp('x', ys=[0,
                                                                        10]))
                p.set_val('traj.phase0.states:y', phase.interp('y', ys=[10,
                                                                        5]))
                p.set_val('traj.phase0.states:v', phase.interp('v',
                                                               ys=[0, 9.9]))
                p.set_val('traj.phase0.controls:theta',
                          phase.interp('theta', ys=[5, 100]))
                p.set_val('traj.parameters:g', 9.80665)

                p.run_driver()

                assert_near_equal(p['traj.t_duration'],
                                  1.8016,
                                  tolerance=1.0E-4)