Пример #1
0
    def make_problem(self,
                     transcription=GaussLobatto,
                     optimizer='SLSQP',
                     numseg=30):
        p = Problem(model=Group())
        p.driver = pyOptSparseDriver()
        p.driver.declare_coloring()
        p.driver.options['optimizer'] = optimizer

        if optimizer == 'SNOPT':
            p.driver.declare_coloring()
            p.driver.opt_settings['Major iterations limit'] = 100
            p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6
            p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6
        elif optimizer == 'IPOPT':
            p.driver.opt_settings['hessian_approximation'] = 'limited-memory'
            # p.driver.opt_settings['nlp_scaling_method'] = 'user-scaling'
            p.driver.opt_settings['print_level'] = 5
            p.driver.opt_settings['linear_solver'] = 'mumps'
            p.driver.declare_coloring()
        else:
            p.driver.declare_coloring()

        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')

        phase0.set_refine_options(refine=True, tol=1e-6, max_order=14)

        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
Пример #2
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
Пример #3
0
    def __init__(self, body, sc, method, nb_seg, order, solver, snopt_opts=None, rec_file=None):
        """Initializes NLP class. """

        # input parameters
        self.body = body
        self.sc = sc
        self.method = method
        self.nb_seg = nb_seg
        self.order = order
        self.solver = solver

        if self.solver == 'SNOPT':
            self.snopt_opts = snopt_opts
        else:
            self.snopt_opts = None

        self.rec_file = rec_file

        # Problem object
        self.p = Problem(model=Group())

        # Problem Driver
        self.p.driver = pyOptSparseDriver()
        self.p.driver.options['optimizer'] = self.solver
        self.p.driver.options['print_results'] = False
        self.p.driver.options['dynamic_derivs_sparsity'] = True

        if self.snopt_opts is not None:
            for k in self.snopt_opts.keys():
                self.p.driver.opt_settings[k] = self.snopt_opts[k]

        self.p.driver.declare_coloring(show_summary=True, show_sparsity=False)

        # Problem Recorder
        if rec_file is not None:

            recorder = SqliteRecorder(rec_file)
            opts = ['record_objectives', 'record_constraints', 'record_desvars']

            self.p.add_recorder(recorder)

            for opt in opts:
                self.p.recording_options[opt] = False

            self.p.recording_options['excludes'] = rec_excludes

        self.rec_file = rec_file

        # Trajectory object
        self.trajectory = self.p.model.add_subsystem('traj', Trajectory())

        # Problem object for explicit simulation
        self.p_exp = None
    def test_solver_defects_reverse_propagation(self):
        prob = Problem()

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

        traj = prob.model.add_subsystem('traj', Trajectory())

        # First phase: normal operation.
        transcription = Radau(num_segments=5,
                              order=5,
                              segment_ends=seg_ends,
                              compressed=True)
        phase0 = Phase(ode_class=BatteryODE, transcription=transcription)
        traj_p0 = traj.add_phase('phase0', phase0)

        traj_p0.set_time_options(fix_initial=True, fix_duration=True)
        traj_p0.set_state_options('state_of_charge',
                                  fix_initial=True,
                                  fix_final=False,
                                  solve_segments=True)

        # Second phase: normal operation.
        phase1 = Phase(ode_class=BatteryODE, transcription=transcription)
        traj_p1 = traj.add_phase('phase1', phase1)

        traj_p1.set_time_options(fix_initial=False, fix_duration=True)
        traj_p1.set_state_options('state_of_charge',
                                  fix_initial=False,
                                  fix_final=False,
                                  solve_segments=True)
        traj_p1.add_objective('time', loc='final')

        traj.link_phases(phases=['phase0', 'phase1'],
                         vars=['state_of_charge', 'time'],
                         connected=True)

        prob.setup()

        prob['traj.phase0.t_initial'] = 0
        prob['traj.phase0.t_duration'] = -1.0 * 3600
        prob['traj.phase0.states:state_of_charge'][:] = 0.23794217

        prob['traj.phase1.t_initial'] = 0
        prob['traj.phase1.t_duration'] = -1.0 * 3600

        prob.set_solver_print(level=0)
        prob.run_model()

        soc1 = prob['traj.phase1.states:state_of_charge']
        assert_rel_error(self, soc1[-1], 1.0, 1e-6)
Пример #5
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
Пример #6
0
def make_problem(transcription=GaussLobatto, num_segments=10, order=3, compressed=True):
    p = om.Problem(model=om.Group())
    p.driver = om.pyOptSparseDriver()
    p.driver.declare_coloring()

    traj = p.model.add_subsystem('traj', Trajectory())
    phase = traj.add_phase('phase', Phase(ode_class=crtbp_ode, transcription=transcription(num_segments=num_segments,
                                                                                           order=order,
                                                                                           compressed=compressed)))

    phase.set_time_options(fix_initial=True, fix_duration=True)
    phase.add_state('x', rate_source='vx', )
    phase.add_state('y', rate_source='vz', fix_initial=True)
    phase.add_state('z', rate_source='vz')
    phase.add_state('x_dot', rate_source='vx_dot', fix_initial=True, units=None)
    phase.add_state('y_dot', rate_source='vy_dot', units=None)
    phase.add_state('z_dot', rate_source='vz_dot', fix_initial=True, units=None)

    p.model.add_subsystem('x_periodic_bc', om.ExecComp('bc_defect=final-initial'))
    p.model.connect('traj.phase.timeseries.states:x', 'x_periodic_bc.initial', src_indices=0)
    p.model.connect('traj.phase.timeseries.states:x', 'x_periodic_bc.final', src_indices=-1)

    p.model.add_constraint('x_periodic_bc.bc_defect', equals=0)

    p.model.add_subsystem('z_periodic_bc', om.ExecComp('bc_defect=final-initial'))
    p.model.connect('traj.phase.timeseries.states:z', 'z_periodic_bc.initial', src_indices=0)
    p.model.connect('traj.phase.timeseries.states:z', 'z_periodic_bc.final', src_indices=-1)

    p.model.add_constraint('z_periodic_bc.bc_defect', equals=0)

    p.model.add_subsystem('vy_periodic_bc', om.ExecComp('bc_defect=final-initial'))
    p.model.connect('traj.phase.timeseries.states:y_dot', 'vy_periodic_bc.initial', src_indices=0)
    p.model.connect('traj.phase.timeseries.states:y_dot', 'vy_periodic_bc.final', src_indices=-1)

    p.model.add_constraint('vy_periodic_bc.bc_defect', equals=0)

    phase.add_objective('time', loc='final')

    p.setup(check=True)
    return p
Пример #7
0
    def test_reentry_mixed_controls(self):

        p = om.Problem(model=om.Group())
        p.driver = om.pyOptSparseDriver()
        p.driver.declare_coloring(tol=1.0E-12)
        p.driver.options['optimizer'] = 'IPOPT'
        p.driver.opt_settings['alpha_for_y'] = 'safer-min-dual-infeas'
        p.driver.opt_settings['print_level'] = 5
        p.driver.opt_settings['nlp_scaling_method'] = 'gradient-based'
        p.driver.opt_settings['mu_strategy'] = 'monotone'

        traj = p.model.add_subsystem('traj', Trajectory())
        phase0 = traj.add_phase(
            'phase0',
            Phase(ode_class=ShuttleODE,
                  transcription=Radau(num_segments=30, 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=9,
                                      units='rad',
                                      opt=True,
                                      lower=-89 * np.pi / 180,
                                      upper=1 * np.pi / 180)

        phase0.add_objective('theta', loc='final', ref=-0.01)
        phase0.add_path_constraint('q', lower=0, upper=70, ref=70)

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

        p.set_val('traj.phase0.states:h',
                  phase0.interp('h', [260000, 80000]),
                  units='ft')
        p.set_val('traj.phase0.states:gamma',
                  phase0.interp('gamma', [-1 * np.pi / 180, -5 * np.pi / 180]),
                  units='rad')
        p.set_val('traj.phase0.states:phi',
                  phase0.interp('phi', [0, 75 * np.pi / 180]),
                  units='rad')
        p.set_val('traj.phase0.states:psi',
                  phase0.interp('psi', [90 * np.pi / 180, 10 * np.pi / 180]),
                  units='rad')
        p.set_val('traj.phase0.states:theta',
                  phase0.interp('theta', [0, 25 * np.pi / 180]),
                  units='rad')
        p.set_val('traj.phase0.states:v',
                  phase0.interp('v', [25600, 2500]),
                  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.interp('alpha', [17.4, 17.4]),
                  units='deg')
        p.set_val('traj.phase0.polynomial_controls:beta',
                  phase0.interp('beta', [-20, 0]),
                  units='deg')

        run_problem(p, simulate=True)

        sol = om.CaseReader('dymos_solution.db').get_case('final')
        sim = om.CaseReader('dymos_simulation.db').get_case('final')

        from scipy.interpolate import interp1d

        t_sol = sol.get_val('traj.phase0.timeseries.time')
        beta_sol = sol.get_val(
            'traj.phase0.timeseries.polynomial_controls:beta', units='deg')

        t_sim = sim.get_val('traj.phase0.timeseries.time')
        beta_sim = sim.get_val(
            'traj.phase0.timeseries.polynomial_controls:beta', units='deg')

        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], 1000)

        assert_near_equal(sim_interp(t), sol_interp(t), tolerance=0.01)

        assert_near_equal(p.get_val('traj.phase0.timeseries.time')[-1],
                          expected_results['constrained']['time'],
                          tolerance=1e-2)

        assert_near_equal(p.get_val('traj.phase0.timeseries.states:theta',
                                    units='deg')[-1],
                          expected_results['constrained']['theta'],
                          tolerance=1e-2)
Пример #8
0
import numpy as np 
import matplotlib.pyplot as plt 
from openmdao.api import Problem, Group, ScipyOptimizeDriver, SqliteRecorder, CaseReader, IndepVarComp
from dymos import Trajectory, GaussLobatto, Phase, Radau
from shuttle_ode import ShuttleODE

prob = Problem(model=Group())

traj = prob.model.add_subsystem("traj", Trajectory())

phase0 = Phase(ode_class=ShuttleODE, transcription=Radau(num_segments=20, order=3))
traj.add_phase(name="phase0", phase=phase0)

phase0.set_time_options(fix_initial=True, units="s", duration_ref=200)#, duration_ref=2000, duration_bounds=(50, 3000)

phase0.set_state_options("h", fix_initial=True, fix_final=True, units="ft", rate_source="hdot", targets=["h"], lower=0)#, ref=260000, defect_ref=260000, ref0=80000
phase0.set_state_options("gamma", fix_initial=True, fix_final=True, units="rad", rate_source="gammadot", targets=["gamma"], lower=-89.*np.pi/180, upper=89.*np.pi/180)
phase0.set_state_options("phi", fix_initial=True, fix_final=False, units="rad", rate_source="phidot", lower=0, upper=89.*np.pi/180)
phase0.set_state_options("psi", fix_initial=True, fix_final=False, units="rad", rate_source="psidot", targets=["psi"], lower=0, upper=90.*np.pi/180)
phase0.set_state_options("theta", fix_initial=True, fix_final=False, units="rad", rate_source="thetadot", targets=["theta"], lower=-89.*np.pi/180, upper=89.*np.pi/180)
phase0.set_state_options("v", fix_initial=True, fix_final=True, units="ft/s", rate_source="vdot", targets=["v"], lower=0)#, ref=25600, defect_ref=25600, ref0=2500

phase0.add_control("alpha", units="rad", opt=True, lower=-np.pi/2, upper=np.pi/2, targets=["alpha"])
phase0.add_control("beta", units="rad", opt=True, lower=-89*np.pi/180, upper=1*np.pi/180, targets=["beta"])

phase0.add_path_constraint("q", lower=0, upper=70, units="Btu/ft**2/s", ref=70)#

phase0.add_objective("theta", loc="final", ref=-1)

prob.driver = ScipyOptimizeDriver()
prob.driver.declare_coloring()
Пример #9
0
def two_burn_orbit_raise_problem(transcription='gauss-lobatto',
                                 optimizer='SNOPT',
                                 transcription_order=3,
                                 compressed=True,
                                 show_plots=False):

    traj = Trajectory()
    p = Problem(model=traj)

    if optimizer == 'SNOPT':
        p.driver = pyOptSparseDriver()
        p.driver.options['optimizer'] = optimizer
        p.driver.options['dynamic_simul_derivs'] = True
        p.driver.opt_settings['Major iterations limit'] = 100
        p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-6
        p.driver.opt_settings['Major optimality tolerance'] = 1.0E-6
        p.driver.opt_settings['iSumm'] = 6
    else:
        p.driver = pyOptSparseDriver()
        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(transcription,
                  ode_class=FiniteBurnODE,
                  num_segments=10,
                  transcription_order=transcription_order,
                  compressed=compressed)

    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(transcription,
                  ode_class=FiniteBurnODE,
                  num_segments=10,
                  transcription_order=transcription_order,
                  compressed=compressed)

    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(transcription,
                  ode_class=FiniteBurnODE,
                  num_segments=10,
                  transcription_order=transcription_order,
                  compressed=compressed)

    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=-10,
                      upper=10)

    burn2.add_objective('deltav', loc='final', scaler=100.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.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()

    # 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', flat=True)
    x_sol = traj.get_values('pos_x', flat=True)
    y_sol = traj.get_values('pos_y', flat=True)
    dv_sol = traj.get_values('deltav', flat=True)
    u1_sol = traj.get_values('u1', units='deg', flat=True)

    t_exp = exp_out.get_values('time', flat=True)
    x_exp = exp_out.get_values('pos_x', flat=True)
    y_exp = exp_out.get_values('pos_y', flat=True)
    dv_exp = exp_out.get_values('deltav', flat=True)
    u1_exp = exp_out.get_values('u1', units='deg', flat=True)

    ax_u1.plot(t_sol, u1_sol, 'ro', ms=3)
    ax_u1.plot(t_exp, u1_exp, 'b-')

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

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

    if show_plots:
        plt.show()

    return p
    def test_two_phase_cannonball_for_docs(self):
        from openmdao.api import Problem, Group, IndepVarComp, DirectSolver, SqliteRecorder, \
            pyOptSparseDriver
        from openmdao.utils.assert_utils import assert_rel_error

        from dymos import Phase, Trajectory, Radau, GaussLobatto
        from dymos.examples.cannonball.cannonball_ode import CannonballODE

        from dymos.examples.cannonball.size_comp import CannonballSizeComp

        p = Problem(model=Group())

        p.driver = pyOptSparseDriver()
        p.driver.options['optimizer'] = 'SLSQP'
        p.driver.options['dynamic_simul_derivs'] = True

        external_params = p.model.add_subsystem('external_params', IndepVarComp())

        external_params.add_output('radius', val=0.10, units='m')
        external_params.add_output('dens', val=7.87, units='g/cm**3')

        external_params.add_design_var('radius', lower=0.01, upper=0.10, ref0=0.01, ref=0.10)

        p.model.add_subsystem('size_comp', CannonballSizeComp())

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

        transcription = Radau(num_segments=5, order=3, compressed=True)
        ascent = Phase(ode_class=CannonballODE, transcription=transcription)

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

        # All initial states except flight path angle are fixed
        # Final flight path angle is fixed (we will set it to zero so that the phase ends at apogee)
        ascent.set_time_options(fix_initial=True, duration_bounds=(1, 100),
                                duration_ref=100, units='s')
        ascent.set_state_options('r', fix_initial=True, fix_final=False)
        ascent.set_state_options('h', fix_initial=True, fix_final=False)
        ascent.set_state_options('gam', fix_initial=False, fix_final=True)
        ascent.set_state_options('v', fix_initial=False, fix_final=False)

        # Limit the muzzle energy
        ascent.add_boundary_constraint('kinetic_energy.ke', loc='initial', units='J',
                                       upper=400000, lower=0, ref=100000, shape=(1,))

        # Second Phase (descent)
        transcription = GaussLobatto(num_segments=5, order=3, compressed=True)
        descent = Phase(ode_class=CannonballODE, transcription=transcription)

        traj.add_phase('descent', descent)

        # All initial states and time are free (they will be linked to the final states of ascent.
        # Final altitude is fixed (we will set it to zero so that the phase ends at ground impact)
        descent.set_time_options(initial_bounds=(.5, 100), duration_bounds=(.5, 100),
                                 duration_ref=100)
        descent.set_state_options('r', fix_initial=False, fix_final=False)
        descent.set_state_options('h', fix_initial=False, fix_final=True)
        descent.set_state_options('gam', fix_initial=False, fix_final=False)
        descent.set_state_options('v', fix_initial=False, fix_final=False)

        descent.add_objective('r', loc='final', scaler=-1.0)

        # Add internally-managed design parameters to the trajectory.
        traj.add_design_parameter('CD', val=0.5, units=None, opt=False)
        traj.add_design_parameter('CL', val=0.0, units=None, opt=False)
        traj.add_design_parameter('T', val=0.0, units='N', opt=False)
        traj.add_design_parameter('alpha', val=0.0, units='deg', opt=False)

        # Add externally-provided design parameters to the trajectory.
        traj.add_input_parameter('mass',
                                 target_params={'ascent': 'm', 'descent': 'm'},
                                 val=1.0)

        traj.add_input_parameter('S', val=0.005)

        # Link Phases (link time and all state variables)
        traj.link_phases(phases=['ascent', 'descent'], vars=['*'])

        # Issue Connections
        p.model.connect('external_params.radius', 'size_comp.radius')
        p.model.connect('external_params.dens', 'size_comp.dens')

        p.model.connect('size_comp.mass', 'traj.input_parameters:mass')
        p.model.connect('size_comp.S', 'traj.input_parameters:S')

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

        p.driver.add_recorder(SqliteRecorder('ex_two_phase_cannonball.db'))

        p.setup(check=True)

        # Set Initial Guesses
        p.set_val('external_params.radius', 0.05, units='m')
        p.set_val('external_params.dens', 7.87, units='g/cm**3')

        p.set_val('traj.design_parameters:CD', 0.5)
        p.set_val('traj.design_parameters:CL', 0.0)
        p.set_val('traj.design_parameters:T', 0.0)

        p.set_val('traj.ascent.t_initial', 0.0)
        p.set_val('traj.ascent.t_duration', 10.0)

        p.set_val('traj.ascent.states:r', ascent.interpolate(ys=[0, 100], nodes='state_input'))
        p.set_val('traj.ascent.states:h', ascent.interpolate(ys=[0, 100], nodes='state_input'))
        p.set_val('traj.ascent.states:v', ascent.interpolate(ys=[200, 150], nodes='state_input'))
        p.set_val('traj.ascent.states:gam', ascent.interpolate(ys=[25, 0], nodes='state_input'),
                  units='deg')

        p.set_val('traj.descent.t_initial', 10.0)
        p.set_val('traj.descent.t_duration', 10.0)

        p.set_val('traj.descent.states:r', descent.interpolate(ys=[100, 200], nodes='state_input'))
        p.set_val('traj.descent.states:h', descent.interpolate(ys=[100, 0], nodes='state_input'))
        p.set_val('traj.descent.states:v', descent.interpolate(ys=[150, 200], nodes='state_input'))
        p.set_val('traj.descent.states:gam', descent.interpolate(ys=[0, -45], nodes='state_input'),
                  units='deg')

        p.run_driver()

        assert_rel_error(self, p.get_val('traj.descent.states:r')[-1],
                         3183.25, tolerance=1.0E-2)

        exp_out = traj.simulate()

        print('optimal radius: {0:6.4f} m '.format(p.get_val('external_params.radius',
                                                             units='m')[0]))
        print('cannonball mass: {0:6.4f} kg '.format(p.get_val('size_comp.mass',
                                                               units='kg')[0]))
        print('launch angle: {0:6.4f} '
              'deg '.format(p.get_val('traj.ascent.timeseries.states:gam',  units='deg')[0, 0]))
        print('maximum range: {0:6.4f} '
              'm '.format(p.get_val('traj.descent.timeseries.states:r')[-1, 0]))

        fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(10, 6))

        time_imp = {'ascent': p.get_val('traj.ascent.timeseries.time'),
                    'descent': p.get_val('traj.descent.timeseries.time')}

        time_exp = {'ascent': exp_out.get_val('traj.ascent.timeseries.time'),
                    'descent': exp_out.get_val('traj.descent.timeseries.time')}

        r_imp = {'ascent': p.get_val('traj.ascent.timeseries.states:r'),
                 'descent': p.get_val('traj.descent.timeseries.states:r')}

        r_exp = {'ascent': exp_out.get_val('traj.ascent.timeseries.states:r'),
                 'descent': exp_out.get_val('traj.descent.timeseries.states:r')}

        h_imp = {'ascent': p.get_val('traj.ascent.timeseries.states:h'),
                 'descent': p.get_val('traj.descent.timeseries.states:h')}

        h_exp = {'ascent': exp_out.get_val('traj.ascent.timeseries.states:h'),
                 'descent': exp_out.get_val('traj.descent.timeseries.states:h')}

        axes.plot(r_imp['ascent'], h_imp['ascent'], 'bo')

        axes.plot(r_imp['descent'], h_imp['descent'], 'ro')

        axes.plot(r_exp['ascent'], h_exp['ascent'], 'b--')

        axes.plot(r_exp['descent'], h_exp['descent'], 'r--')

        axes.set_xlabel('range (m)')
        axes.set_ylabel('altitude (m)')

        fig, axes = plt.subplots(nrows=4, ncols=1, figsize=(10, 6))
        states = ['r', 'h', 'v', 'gam']
        for i, state in enumerate(states):
            x_imp = {'ascent': p.get_val('traj.ascent.timeseries.states:{0}'.format(state)),
                     'descent': p.get_val('traj.descent.timeseries.states:{0}'.format(state))}

            x_exp = {'ascent': exp_out.get_val('traj.ascent.timeseries.states:{0}'.format(state)),
                     'descent': exp_out.get_val('traj.descent.timeseries.states:{0}'.format(state))}

            axes[i].set_ylabel(state)

            axes[i].plot(time_imp['ascent'], x_imp['ascent'], 'bo')
            axes[i].plot(time_imp['descent'], x_imp['descent'], 'ro')
            axes[i].plot(time_exp['ascent'], x_exp['ascent'], 'b--')
            axes[i].plot(time_exp['descent'], x_exp['descent'], 'r--')

        params = ['CL', 'CD', 'T', 'alpha', 'm', 'S']
        fig, axes = plt.subplots(nrows=6, ncols=1, figsize=(12, 6))
        for i, param in enumerate(params):
            p_imp = {
                'ascent': p.get_val('traj.ascent.timeseries.traj_parameters:{0}'.format(param)),
                'descent': p.get_val('traj.descent.timeseries.traj_parameters:{0}'.format(param))}

            p_exp = {'ascent': exp_out.get_val('traj.ascent.timeseries.'
                                               'traj_parameters:{0}'.format(param)),
                     'descent': exp_out.get_val('traj.descent.timeseries.'
                                                'traj_parameters:{0}'.format(param))}

            axes[i].set_ylabel(param)

            axes[i].plot(time_imp['ascent'], p_imp['ascent'], 'bo')
            axes[i].plot(time_imp['descent'], p_imp['descent'], 'ro')
            axes[i].plot(time_exp['ascent'], p_exp['ascent'], 'b--')
            axes[i].plot(time_exp['descent'], p_exp['descent'], 'r--')

        plt.show()
Пример #11
0
    def test_basic(self):
        import matplotlib.pyplot as plt

        from openmdao.api import Problem, ScipyOptimizeDriver, DirectSolver
        from openmdao.utils.assert_utils import assert_rel_error

        from dymos import Trajectory, Phase, Radau
        from dymos.examples.battery_multibranch.battery_multibranch_ode import BatteryODE
        from dymos.utils.lgl import lgl

        prob = Problem()

        opt = prob.driver = ScipyOptimizeDriver()
        opt.options['dynamic_simul_derivs'] = True
        opt.options['optimizer'] = 'SLSQP'

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

        traj = prob.model.add_subsystem('traj', Trajectory())

        # First phase: normal operation.
        transcription = Radau(num_segments=num_seg,
                              order=5,
                              segment_ends=seg_ends,
                              compressed=False)
        phase0 = Phase(ode_class=BatteryODE, transcription=transcription)
        traj_p0 = traj.add_phase('phase0', phase0)

        traj_p0.set_time_options(fix_initial=True, fix_duration=True)
        traj_p0.set_state_options('state_of_charge',
                                  fix_initial=True,
                                  fix_final=False)

        # Second phase: normal operation.

        phase1 = Phase(ode_class=BatteryODE, transcription=transcription)
        traj_p1 = traj.add_phase('phase1', phase1)

        traj_p1.set_time_options(fix_initial=False, fix_duration=True)
        traj_p1.set_state_options('state_of_charge',
                                  fix_initial=False,
                                  fix_final=False)
        traj_p1.add_objective('time', loc='final')

        # Second phase, but with battery failure.

        phase1_bfail = Phase(ode_class=BatteryODE,
                             ode_init_kwargs={'num_battery': 2},
                             transcription=transcription)
        traj_p1_bfail = traj.add_phase('phase1_bfail', phase1_bfail)

        traj_p1_bfail.set_time_options(fix_initial=False, fix_duration=True)
        traj_p1_bfail.set_state_options('state_of_charge',
                                        fix_initial=False,
                                        fix_final=False)

        # Second phase, but with motor failure.

        phase1_mfail = Phase(ode_class=BatteryODE,
                             ode_init_kwargs={'num_motor': 2},
                             transcription=transcription)
        traj_p1_mfail = traj.add_phase('phase1_mfail', phase1_mfail)

        traj_p1_mfail.set_time_options(fix_initial=False, fix_duration=True)
        traj_p1_mfail.set_state_options('state_of_charge',
                                        fix_initial=False,
                                        fix_final=False)

        traj.link_phases(phases=['phase0', 'phase1'],
                         vars=['state_of_charge', 'time'])
        traj.link_phases(phases=['phase0', 'phase1_bfail'],
                         vars=['state_of_charge', 'time'])
        traj.link_phases(phases=['phase0', 'phase1_mfail'],
                         vars=['state_of_charge', 'time'])

        prob.model.options['assembled_jac_type'] = 'csc'
        prob.model.linear_solver = DirectSolver(assemble_jac=True)

        prob.setup()

        prob['traj.phase0.t_initial'] = 0
        prob['traj.phase0.t_duration'] = 1.0 * 3600

        prob['traj.phase1.t_initial'] = 1.0 * 3600
        prob['traj.phase1.t_duration'] = 1.0 * 3600

        prob['traj.phase1_bfail.t_initial'] = 1.0 * 3600
        prob['traj.phase1_bfail.t_duration'] = 1.0 * 3600

        prob['traj.phase1_mfail.t_initial'] = 1.0 * 3600
        prob['traj.phase1_mfail.t_duration'] = 1.0 * 3600

        prob.set_solver_print(level=0)
        prob.run_driver()

        soc0 = prob['traj.phase0.states:state_of_charge']
        soc1 = prob['traj.phase1.states:state_of_charge']
        soc1b = prob['traj.phase1_bfail.states:state_of_charge']
        soc1m = prob['traj.phase1_mfail.states:state_of_charge']

        # Final value for State of Chrage in each segment should be a good test.
        print('State of Charge after 1 hour')
        assert_rel_error(self, soc0[-1], 0.63464982, 1e-6)
        print('State of Charge after 2 hours')
        assert_rel_error(self, soc1[-1], 0.23794217, 1e-6)
        print('State of Charge after 2 hours, battery fails at 1 hour')
        assert_rel_error(self, soc1b[-1], 0.0281523, 1e-6)
        print('State of Charge after 2 hours, motor fails at 1 hour')
        assert_rel_error(self, soc1m[-1], 0.18625395, 1e-6)

        # Plot Results
        t0 = prob['traj.phases.phase0.time.time'] / 3600
        t1 = prob['traj.phases.phase1.time.time'] / 3600
        t1b = prob['traj.phases.phase1_bfail.time.time'] / 3600
        t1m = prob['traj.phases.phase1_mfail.time.time'] / 3600

        plt.subplot(2, 1, 1)
        plt.plot(t0, soc0, 'b')
        plt.plot(t1, soc1, 'b')
        plt.plot(t1b, soc1b, 'r')
        plt.plot(t1m, soc1m, 'c')
        plt.xlabel('Time (hour)')
        plt.ylabel('State of Charge (percent)')

        I_Li0 = prob['traj.phases.phase0.rhs_all.pwr_balance.I_Li']
        I_Li1 = prob['traj.phases.phase1.rhs_all.pwr_balance.I_Li']
        I_Li1b = prob['traj.phases.phase1_bfail.rhs_all.pwr_balance.I_Li']
        I_Li1m = prob['traj.phases.phase1_mfail.rhs_all.pwr_balance.I_Li']

        plt.subplot(2, 1, 2)
        plt.plot(t0, I_Li0, 'b')
        plt.plot(t1, I_Li1, 'b')
        plt.plot(t1b, I_Li1b, 'r')
        plt.plot(t1m, I_Li1m, 'c')
        plt.xlabel('Time (hour)')
        plt.ylabel('Line Current (A)')

        plt.legend([
            'Phase 1', 'Phase 2', 'Phase 2 Battery Fail', 'Phase 2 Motor Fail'
        ],
                   loc=2)

        plt.show()
Пример #12
0
    def instantiate_problem(self, idx):

        traj = Trajectory()
        p = Problem(model=traj)

        # First Phase (burn)

        burn1 = Phase('gauss-lobatto',
                      ode_class=FiniteBurnODE,
                      num_segments=4,
                      transcription_order=3,
                      compressed=True)

        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,
                                defect_scaler=0.1)
        burn1.set_state_options('vt',
                                fix_initial=True,
                                fix_final=False,
                                defect_scaler=0.1)
        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')
        burn1.add_design_parameter('c', opt=False, val=1.5)

        # 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))
        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=True)
        coast.set_state_options('deltav', fix_initial=False, fix_final=False)
        coast.add_control('u1', opt=False, val=0.0, units='deg')
        coast.add_design_parameter('c', opt=False, val=1.5)

        # Third Phase (burn)

        burn2 = Phase('gauss-lobatto',
                      ode_class=FiniteBurnODE,
                      num_segments=3,
                      transcription_order=3,
                      compressed=True)

        traj.add_phase('burn2', burn2)

        burn2.set_time_options(initial_bounds=(0.5, 20),
                               duration_bounds=(.5, 10))
        burn2.set_state_options('r',
                                fix_initial=False,
                                fix_final=True,
                                defect_scaler=1.0)
        burn2.set_state_options('theta',
                                fix_initial=False,
                                fix_final=False,
                                defect_scaler=1.0)
        burn2.set_state_options('vr',
                                fix_initial=False,
                                fix_final=True,
                                defect_scaler=0.1)
        burn2.set_state_options('vt',
                                fix_initial=False,
                                fix_final=True,
                                defect_scaler=0.1)
        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',
                          ref0=0,
                          ref=10)
        burn2.add_design_parameter('c', opt=False, val=1.5)

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

        # 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)

        rec_file = 'two_burn_orbit_raise_example_{0}.db'.format(idx)
        p.driver.add_recorder(SqliteRecorder(rec_file))

        p.setup(check=True)

        # Set Initial Guesses

        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('burn1.design_parameters:c', value=1.5)

        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('coast.design_parameters:c', value=1.5)

        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.set_val('burn2.design_parameters:c', value=1.5)

        p.run_model()

        # Plot results
        sim_rec_file = 'traj_sim_{0}.db'.format(idx)
        exp_out = traj.simulate(times=50, record_file=sim_rec_file)

        loaded_exp_out = load_simulation_results(sim_rec_file)

        return exp_out, loaded_exp_out, rec_file, sim_rec_file
Пример #13
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)
Пример #14
0
    def test_reentry_gauss_lobatto_dymos(self):

        p = Problem(model=Group())
        p.driver = pyOptSparseDriver()
        p.driver.declare_coloring()

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

        phase0.set_time_options(fix_initial=True, units="s", duration_ref=200)
        phase0.set_state_options("h",
                                 fix_initial=True,
                                 fix_final=True,
                                 units="ft",
                                 rate_source="hdot",
                                 targets=["h"],
                                 lower=0,
                                 ref0=75000,
                                 ref=300000,
                                 defect_ref=1000)
        phase0.set_state_options("gamma",
                                 fix_initial=True,
                                 fix_final=True,
                                 units="rad",
                                 rate_source="gammadot",
                                 targets=["gamma"],
                                 lower=-89. * np.pi / 180,
                                 upper=89. * np.pi / 180)
        phase0.set_state_options("phi",
                                 fix_initial=True,
                                 fix_final=False,
                                 units="rad",
                                 rate_source="phidot",
                                 lower=0,
                                 upper=89. * np.pi / 180)
        phase0.set_state_options("psi",
                                 fix_initial=True,
                                 fix_final=False,
                                 units="rad",
                                 rate_source="psidot",
                                 targets=["psi"],
                                 lower=0,
                                 upper=90. * np.pi / 180)
        phase0.set_state_options("theta",
                                 fix_initial=True,
                                 fix_final=False,
                                 units="rad",
                                 rate_source="thetadot",
                                 targets=["theta"],
                                 lower=-89. * np.pi / 180,
                                 upper=89. * np.pi / 180)
        phase0.set_state_options("v",
                                 fix_initial=True,
                                 fix_final=True,
                                 units="ft/s",
                                 rate_source="vdot",
                                 targets=["v"],
                                 lower=0,
                                 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"])
        phase0.add_path_constraint("q",
                                   lower=0,
                                   upper=70,
                                   units="Btu/ft**2/s",
                                   ref=70)
        phase0.add_objective("theta", loc="final", ref=-0.01)

        p.driver.options["optimizer"] = 'SNOPT'
        p.driver.opt_settings["iSumm"] = 6

        p.setup(check=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")

        p.run_driver()

        print(p.get_val("traj.phase0.timeseries.time")[-1])
        print(p.get_val("traj.phase0.timeseries.states:theta")[-1])
        assert_rel_error(self,
                         p.get_val("traj.phase0.timeseries.time")[-1],
                         2181.88191719,
                         tolerance=1e-3)
        assert_rel_error(self,
                         p.get_val("traj.phase0.timeseries.states:theta")[-1],
                         .53440955,
                         tolerance=1e-3)
Пример #15
0
    def setUpClass(cls):

        cls.traj = Trajectory()
        p = Problem(model=cls.traj)

        # Since we're only testing features like get_values that don't rely on a converged
        # solution, no driver is attached.  We'll just invoke run_model.

        # First Phase (burn)
        burn1 = Phase('gauss-lobatto',
                      ode_class=FiniteBurnODE,
                      num_segments=4,
                      transcription_order=3,
                      compressed=True)

        cls.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,
                                defect_scaler=0.1)
        burn1.set_state_options('vt',
                                fix_initial=True,
                                fix_final=False,
                                defect_scaler=0.1)
        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')
        burn1.add_design_parameter('c', opt=False, val=1.5)

        # Second Phase (Coast)

        coast = Phase('gauss-lobatto',
                      ode_class=FiniteBurnODE,
                      num_segments=10,
                      transcription_order=3,
                      compressed=True)

        cls.traj.add_phase('coast', coast)

        coast.set_time_options(initial_bounds=(0.5, 20),
                               duration_bounds=(.5, 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=True)
        coast.set_state_options('deltav', fix_initial=False, fix_final=False)
        coast.add_control('u1', opt=False, val=0.0, units='deg')
        coast.add_design_parameter('c', opt=False, val=1.5)

        # Third Phase (burn)

        burn2 = Phase('gauss-lobatto',
                      ode_class=FiniteBurnODE,
                      num_segments=3,
                      transcription_order=3,
                      compressed=True)

        cls.traj.add_phase('burn2', burn2)

        burn2.set_time_options(initial_bounds=(0.5, 20),
                               duration_bounds=(.5, 10))
        burn2.set_state_options('r',
                                fix_initial=False,
                                fix_final=True,
                                defect_scaler=1.0)
        burn2.set_state_options('theta',
                                fix_initial=False,
                                fix_final=False,
                                defect_scaler=1.0)
        burn2.set_state_options('vr',
                                fix_initial=False,
                                fix_final=True,
                                defect_scaler=0.1)
        burn2.set_state_options('vt',
                                fix_initial=False,
                                fix_final=True,
                                defect_scaler=0.1)
        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',
                          ref0=0,
                          ref=10)
        burn2.add_design_parameter('c', opt=False, val=1.5)

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

        # Link Phases
        cls.traj.link_phases(phases=['burn1', 'coast', 'burn2'],
                             vars=['time', 'r', 'theta', 'vr', 'vt', 'deltav'])
        cls.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.model.add_recorder(SqliteRecorder('test_trajectory_rec.db'))

        p.setup(check=True)

        # Set Initial Guesses

        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('burn1.design_parameters:c', value=1.5)

        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('coast.design_parameters:c', value=1.5)

        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.set_val('burn2.design_parameters:c', value=1.5)

        p.run_model()
Пример #16
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()
Пример #17
0
    def test_invalid_linkage_phase(self):
        p = Problem(model=Group())

        traj = Trajectory()
        p.model.add_subsystem('traj', subsys=traj)

        # Since we're only testing features like get_values that don't rely on a converged
        # solution, no driver is attached.  We'll just invoke run_model.

        # First Phase (burn)
        burn1 = Phase(ode_class=FiniteBurnODE, transcription=GaussLobatto(num_segments=4, order=3))

        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, defect_scaler=0.1)
        burn1.set_state_options('vt', fix_initial=True, fix_final=False, defect_scaler=0.1)
        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')
        burn1.add_design_parameter('c', opt=False, val=1.5)

        # Second Phase (Coast)

        coast = Phase(ode_class=FiniteBurnODE, transcription=GaussLobatto(num_segments=10, order=3))

        traj.add_phase('coast', coast)

        coast.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 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=True)
        coast.set_state_options('deltav', fix_initial=False, fix_final=False)
        coast.add_control('u1', opt=False, val=0.0, units='deg')
        coast.add_design_parameter('c', opt=False, val=1.5)

        # Third Phase (burn)

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

        traj.add_phase('burn2', burn2)

        burn2.set_time_options(initial_bounds=(0.5, 20), duration_bounds=(.5, 10))
        burn2.set_state_options('r', fix_initial=False, fix_final=True, defect_scaler=1.0)
        burn2.set_state_options('theta', fix_initial=False, fix_final=False, defect_scaler=1.0)
        burn2.set_state_options('vr', fix_initial=False, fix_final=True, defect_scaler=0.1)
        burn2.set_state_options('vt', fix_initial=False, fix_final=True, defect_scaler=0.1)
        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',
                          ref0=0, ref=10)
        burn2.add_design_parameter('c', opt=False, val=1.5)

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

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

        traj.link_phases(phases=['burn1', 'foo'], vars=['u1', 'u1'])

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

        p.model.add_recorder(SqliteRecorder('test_trajectory_rec.db'))

        with self.assertRaises(ValueError) as e:
            p.setup(check=True)

        self.assertEqual(str(e.exception), 'Invalid linkage.  Phase \'foo\' does not exist in '
                                           'trajectory \'traj\'.')
    def test_connected_linkages_rk(self):
        prob = Problem()

        if optimizer == 'SNOPT':
            opt = prob.driver = pyOptSparseDriver()
            opt.options['optimizer'] = optimizer
            opt.options['dynamic_simul_derivs'] = True

            opt.opt_settings['Major iterations limit'] = 1000
            opt.opt_settings['Major feasibility tolerance'] = 1.0E-6
            opt.opt_settings['Major optimality tolerance'] = 1.0E-6
            opt.opt_settings["Linesearch tolerance"] = 0.10
            opt.opt_settings['iSumm'] = 6

        else:
            opt = prob.driver = ScipyOptimizeDriver()
            opt.options['dynamic_simul_derivs'] = True

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

        traj = prob.model.add_subsystem('traj', Trajectory())

        # First phase: normal operation.

        transcription = RungeKutta(num_segments=num_seg)
        phase0 = Phase(ode_class=BatteryODE, transcription=transcription)
        traj_p0 = traj.add_phase('phase0', phase0)

        traj_p0.set_time_options(fix_initial=True, fix_duration=True)
        traj_p0.set_state_options('state_of_charge',
                                  fix_initial=True,
                                  fix_final=False)

        # Second phase: normal operation.

        phase1 = Phase(ode_class=BatteryODE, transcription=transcription)
        traj_p1 = traj.add_phase('phase1', phase1)

        traj_p1.set_time_options(fix_initial=False, fix_duration=True)
        traj_p1.set_state_options('state_of_charge',
                                  fix_initial=False,
                                  fix_final=False)
        traj_p1.add_objective('time', loc='final')

        # Second phase, but with battery failure.

        phase1_bfail = Phase(ode_class=BatteryODE,
                             ode_init_kwargs={'num_battery': 2},
                             transcription=transcription)
        traj_p1_bfail = traj.add_phase('phase1_bfail', phase1_bfail)

        traj_p1_bfail.set_time_options(fix_initial=False, fix_duration=True)
        traj_p1_bfail.set_state_options('state_of_charge',
                                        fix_initial=False,
                                        fix_final=False)

        # Second phase, but with motor failure.
        phase1_mfail = Phase(ode_class=BatteryODE,
                             ode_init_kwargs={'num_motor': 2},
                             transcription=transcription)
        traj_p1_mfail = traj.add_phase('phase1_mfail', phase1_mfail)

        traj_p1_mfail.set_time_options(fix_initial=False, fix_duration=True)
        traj_p1_mfail.set_state_options('state_of_charge',
                                        fix_initial=False,
                                        fix_final=False)

        traj.link_phases(phases=['phase0', 'phase1'],
                         vars=['state_of_charge', 'time'],
                         connected=True)
        traj.link_phases(phases=['phase0', 'phase1_bfail'],
                         vars=['state_of_charge', 'time'],
                         connected=True)
        traj.link_phases(phases=['phase0', 'phase1_mfail'],
                         vars=['state_of_charge', 'time'],
                         connected=True)

        prob.model.options['assembled_jac_type'] = 'csc'
        prob.model.linear_solver = DirectSolver(assemble_jac=True)

        prob.setup()

        prob['traj.phase0.t_initial'] = 0
        prob['traj.phase0.t_duration'] = 1.0 * 3600

        prob['traj.phase1.t_initial'] = 1.0 * 3600
        prob['traj.phase1.t_duration'] = 1.0 * 3600

        prob['traj.phase1_bfail.t_initial'] = 1.0 * 3600
        prob['traj.phase1_bfail.t_duration'] = 1.0 * 3600

        prob['traj.phase1_mfail.t_initial'] = 1.0 * 3600
        prob['traj.phase1_mfail.t_duration'] = 1.0 * 3600

        prob.set_solver_print(level=0)
        prob.run_driver()

        soc0 = prob['traj.phase0.states:state_of_charge']
        soc1 = prob['traj.phase1.states:state_of_charge']
        soc1b = prob['traj.phase1_bfail.states:state_of_charge']
        soc1m = prob['traj.phase1_mfail.states:state_of_charge']

        # Final value for State of Chrage in each segment should be a good test.
        assert_rel_error(self, soc0[-1], 0.63464982, 5e-5)
        assert_rel_error(self, soc1[-1], 0.23794217, 5e-5)
        assert_rel_error(self, soc1b[-1], 0.0281523, 5e-5)
        assert_rel_error(self, soc1m[-1], 0.18625395, 5e-5)
    def test_solver_defects(self):
        prob = Problem()

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

        traj = prob.model.add_subsystem('traj', Trajectory())

        # First phase: normal operation.

        transcription = Radau(num_segments=5,
                              order=5,
                              segment_ends=seg_ends,
                              compressed=True)
        phase0 = Phase(ode_class=BatteryODE, transcription=transcription)
        traj_p0 = traj.add_phase('phase0', phase0)

        traj_p0.set_time_options(fix_initial=True, fix_duration=True)
        traj_p0.set_state_options('state_of_charge',
                                  fix_initial=True,
                                  fix_final=False,
                                  solve_segments=True)

        # Second phase: normal operation.
        phase1 = Phase(ode_class=BatteryODE, transcription=transcription)
        traj_p1 = traj.add_phase('phase1', phase1)

        traj_p1.set_time_options(fix_initial=False, fix_duration=True)
        traj_p1.set_state_options('state_of_charge',
                                  fix_initial=False,
                                  fix_final=False,
                                  solve_segments=True)
        traj_p1.add_objective('time', loc='final')

        # Second phase, but with battery failure.
        phase1_bfail = Phase(ode_class=BatteryODE,
                             ode_init_kwargs={'num_battery': 2},
                             transcription=transcription)
        traj_p1_bfail = traj.add_phase('phase1_bfail', phase1_bfail)

        traj_p1_bfail.set_time_options(fix_initial=False, fix_duration=True)
        traj_p1_bfail.set_state_options('state_of_charge',
                                        fix_initial=False,
                                        fix_final=False,
                                        solve_segments=True)

        # Second phase, but with motor failure.
        phase1_mfail = Phase(ode_class=BatteryODE,
                             ode_init_kwargs={'num_motor': 2},
                             transcription=transcription)
        traj_p1_mfail = traj.add_phase('phase1_mfail', phase1_mfail)

        traj_p1_mfail.set_time_options(fix_initial=False, fix_duration=True)
        traj_p1_mfail.set_state_options('state_of_charge',
                                        fix_initial=False,
                                        fix_final=False,
                                        solve_segments=True)

        traj.link_phases(phases=['phase0', 'phase1'],
                         vars=['state_of_charge', 'time'],
                         connected=True)
        traj.link_phases(phases=['phase0', 'phase1_bfail'],
                         vars=['state_of_charge', 'time'],
                         connected=True)
        traj.link_phases(phases=['phase0', 'phase1_mfail'],
                         vars=['state_of_charge', 'time'],
                         connected=True)

        prob.setup()

        prob['traj.phase0.t_initial'] = 0
        prob['traj.phase0.t_duration'] = 1.0 * 3600

        prob['traj.phase1.t_initial'] = 1.0 * 3600
        prob['traj.phase1.t_duration'] = 1.0 * 3600

        prob['traj.phase1_bfail.t_initial'] = 1.0 * 3600
        prob['traj.phase1_bfail.t_duration'] = 1.0 * 3600

        prob['traj.phase1_mfail.t_initial'] = 1.0 * 3600
        prob['traj.phase1_mfail.t_duration'] = 1.0 * 3600

        prob['traj.phase0.states:state_of_charge'][:] = 1.0

        prob.set_solver_print(level=0)
        prob.run_model()

        soc0 = prob['traj.phase0.states:state_of_charge']
        soc1 = prob['traj.phase1.states:state_of_charge']
        soc1b = prob['traj.phase1_bfail.states:state_of_charge']
        soc1m = prob['traj.phase1_mfail.states:state_of_charge']

        # Final value for State of Charge in each segment should be a good test.
        assert_rel_error(self, soc0[-1], 0.63464982, 1e-6)
        assert_rel_error(self, soc1[-1], 0.23794217, 1e-6)
        assert_rel_error(self, soc1b[-1], 0.0281523, 1e-6)
        assert_rel_error(self, soc1m[-1], 0.18625395, 1e-6)
Пример #20
0
    def make_problem(self,
                     constrained=True,
                     transcription=GaussLobatto,
                     optimizer='SLSQP',
                     numseg=50):
        p = om.Problem(model=om.Group())
        p.driver = om.pyOptSparseDriver(optimizer=optimizer)
        p.driver.declare_coloring()

        if optimizer == 'IPOPT':
            p.driver.opt_settings['max_iter'] = 500
            p.driver.opt_settings['alpha_for_y'] = 'safer-min-dual-infeas'
            p.driver.opt_settings['print_level'] = 5
            p.driver.opt_settings['nlp_scaling_method'] = 'gradient-based'
            p.driver.opt_settings['tol'] = 1.0E-7
            p.driver.opt_settings['mu_strategy'] = 'monotone'

        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.interp('h', [260000, 80000]),
                  units='ft')
        p.set_val('traj.phase0.states:gamma',
                  phase0.interp('gamma', [-1 * np.pi / 180, -5 * np.pi / 180]),
                  units='rad')
        p.set_val('traj.phase0.states:phi',
                  phase0.interp('phi', [0, 75 * np.pi / 180]),
                  units='rad')
        p.set_val('traj.phase0.states:psi',
                  phase0.interp('psi', [90 * np.pi / 180, 10 * np.pi / 180]),
                  units='rad')
        p.set_val('traj.phase0.states:theta',
                  phase0.interp('theta', [0, 25 * np.pi / 180]),
                  units='rad')
        p.set_val('traj.phase0.states:v',
                  phase0.interp('v', [25600, 2500]),
                  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.interp('alpha',
                                [17.4 * np.pi / 180, 17.4 * np.pi / 180]),
                  units='rad')
        p.set_val('traj.phase0.controls:beta',
                  phase0.interp('beta', [-75 * np.pi / 180, 0 * np.pi / 180]),
                  units='rad')

        return p
Пример #21
0
    def test_two_phase_cannonball_for_docs(self):
        from openmdao.api import Problem, Group, IndepVarComp, DirectSolver, SqliteRecorder, \
            pyOptSparseDriver
        from openmdao.utils.assert_utils import assert_rel_error

        from dymos import Phase, Trajectory, load_simulation_results
        from dymos.examples.cannonball.cannonball_ode import CannonballODE

        from dymos.examples.cannonball.size_comp import CannonballSizeComp

        p = Problem(model=Group())

        p.driver = pyOptSparseDriver()
        p.driver.options['optimizer'] = 'SLSQP'
        p.driver.options['dynamic_simul_derivs'] = True

        external_params = p.model.add_subsystem('external_params',
                                                IndepVarComp())

        external_params.add_output('radius', val=0.10, units='m')
        external_params.add_output('dens', val=7.87, units='g/cm**3')

        external_params.add_design_var('radius',
                                       lower=0.01,
                                       upper=0.10,
                                       ref0=0.01,
                                       ref=0.10)

        p.model.add_subsystem('size_comp', CannonballSizeComp())

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

        # First Phase (ascent)
        ascent = Phase('radau-ps',
                       ode_class=CannonballODE,
                       num_segments=5,
                       transcription_order=3,
                       compressed=True)

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

        # All initial states except flight path angle are fixed
        # Final flight path angle is fixed (we will set it to zero so that the phase ends at apogee)
        ascent.set_time_options(fix_initial=True,
                                duration_bounds=(1, 100),
                                duration_ref=100)
        ascent.set_state_options('r', fix_initial=True, fix_final=False)
        ascent.set_state_options('h', fix_initial=True, fix_final=False)
        ascent.set_state_options('gam', fix_initial=False, fix_final=True)
        ascent.set_state_options('v', fix_initial=False, fix_final=False)

        # Limit the muzzle energy
        ascent.add_boundary_constraint('kinetic_energy.ke',
                                       loc='initial',
                                       units='J',
                                       upper=400000,
                                       lower=0,
                                       ref=100000)

        # Second Phase (descent)
        descent = Phase('gauss-lobatto',
                        ode_class=CannonballODE,
                        num_segments=5,
                        transcription_order=3,
                        compressed=True)

        traj.add_phase('descent', descent)

        # All initial states and time are free (they will be linked to the final states of ascent.
        # Final altitude is fixed (we will set it to zero so that the phase ends at ground impact)
        descent.set_time_options(initial_bounds=(.5, 100),
                                 duration_bounds=(.5, 100),
                                 duration_ref=100)
        descent.set_state_options('r', fix_initial=False, fix_final=False)
        descent.set_state_options('h', fix_initial=False, fix_final=True)
        descent.set_state_options('gam', fix_initial=False, fix_final=False)
        descent.set_state_options('v', fix_initial=False, fix_final=False)

        descent.add_objective('r', loc='final', scaler=-1.0)

        # Add internally-managed design parameters to the trajectory.
        traj.add_design_parameter('CD', val=0.5, units=None, opt=False)
        traj.add_design_parameter('CL', val=0.0, units=None, opt=False)
        traj.add_design_parameter('T', val=0.0, units='N', opt=False)
        traj.add_design_parameter('alpha', val=0.0, units='deg', opt=False)

        # Add externally-provided design parameters to the trajectory.
        traj.add_input_parameter('mass',
                                 targets={
                                     'ascent': 'm',
                                     'descent': 'm'
                                 },
                                 val=1.0,
                                 units='kg')

        traj.add_input_parameter('S', val=0.005, units='m**2')

        # Link Phases (link time and all state variables)
        traj.link_phases(phases=['ascent', 'descent'], vars=['*'])

        # Issue Connections
        p.model.connect('external_params.radius', 'size_comp.radius')
        p.model.connect('external_params.dens', 'size_comp.dens')

        p.model.connect('size_comp.mass', 'traj.input_parameters:mass')
        p.model.connect('size_comp.S', 'traj.input_parameters:S')

        # Finish Problem Setup
        p.model.options['assembled_jac_type'] = 'csc'
        p.model.linear_solver = DirectSolver(assemble_jac=True)

        p.driver.add_recorder(SqliteRecorder('ex_two_phase_cannonball.db'))

        p.setup(check=True)

        # Set Initial Guesses
        p.set_val('external_params.radius', 0.05, units='m')
        p.set_val('external_params.dens', 7.87, units='g/cm**3')

        p.set_val('traj.design_parameters:CD', 0.5)
        p.set_val('traj.design_parameters:CL', 0.0)
        p.set_val('traj.design_parameters:T', 0.0)

        p.set_val('traj.ascent.t_initial', 0.0)
        p.set_val('traj.ascent.t_duration', 10.0)

        p.set_val('traj.ascent.states:r',
                  ascent.interpolate(ys=[0, 100], nodes='state_input'))
        p.set_val('traj.ascent.states:h',
                  ascent.interpolate(ys=[0, 100], nodes='state_input'))
        p.set_val('traj.ascent.states:v',
                  ascent.interpolate(ys=[200, 150], nodes='state_input'))
        p.set_val('traj.ascent.states:gam',
                  ascent.interpolate(ys=[25, 0], nodes='state_input'),
                  units='deg')

        p.set_val('traj.descent.t_initial', 10.0)
        p.set_val('traj.descent.t_duration', 10.0)

        p.set_val('traj.descent.states:r',
                  descent.interpolate(ys=[100, 200], nodes='state_input'))
        p.set_val('traj.descent.states:h',
                  descent.interpolate(ys=[100, 0], nodes='state_input'))
        p.set_val('traj.descent.states:v',
                  descent.interpolate(ys=[150, 200], nodes='state_input'))
        p.set_val('traj.descent.states:gam',
                  descent.interpolate(ys=[0, -45], nodes='state_input'),
                  units='deg')

        p.run_driver()

        assert_rel_error(self,
                         traj.get_values('r')['descent'][-1],
                         3191.83945861,
                         tolerance=1.0E-2)

        exp_out = traj.simulate(times=100,
                                record_file='ex_two_phase_cannonball_sim.db')

        # exp_out_loaded = load_simulation_results('ex_two_phase_cannonball_sim.db')

        print('optimal radius: {0:6.4f} m '.format(
            p.get_val('external_params.radius', units='m')[0]))
        print('cannonball mass: {0:6.4f} kg '.format(
            p.get_val('size_comp.mass', units='kg')[0]))

        fig, axes = plt.subplots(nrows=3, ncols=1, figsize=(8, 6))

        axes[0].plot(
            traj.get_values('r')['ascent'],
            traj.get_values('h')['ascent'], 'bo')

        axes[0].plot(
            traj.get_values('r')['descent'],
            traj.get_values('h')['descent'], 'ro')

        axes[0].plot(
            exp_out.get_values('r')['ascent'],
            exp_out.get_values('h')['ascent'], 'b--')

        axes[0].plot(
            exp_out.get_values('r')['descent'],
            exp_out.get_values('h')['descent'], 'r--')

        axes[0].set_xlabel('range (m)')
        axes[0].set_ylabel('altitude (m)')

        # plt.suptitle('Kinetic Energy vs Time')

        axes[1].plot(
            traj.get_values('time')['ascent'],
            traj.get_values('kinetic_energy.ke')['ascent'], 'bo')

        axes[1].plot(
            traj.get_values('time')['descent'],
            traj.get_values('kinetic_energy.ke')['descent'], 'ro')

        axes[1].plot(
            exp_out.get_values('time')['ascent'],
            exp_out.get_values('kinetic_energy.ke')['ascent'], 'b--')

        axes[1].plot(
            exp_out.get_values('time')['descent'],
            exp_out.get_values('kinetic_energy.ke')['descent'], 'r--')

        # axes[1].plot(exp_out_loaded.get_values('time')['ascent'],
        #              exp_out_loaded.get_values('kinetic_energy.ke')['ascent'],
        #              'b--')
        #
        # axes[1].plot(exp_out_loaded.get_values('time')['descent'],
        #              exp_out_loaded.get_values('kinetic_energy.ke')['descent'],
        #              'r--')

        axes[1].set_xlabel('time (s)')
        axes[1].set_ylabel(r'kinetic energy (J)')

        # plt.figure()

        axes[2].plot(
            traj.get_values('time')['ascent'],
            traj.get_values('gam', units='deg')['ascent'], 'bo')
        axes[2].plot(
            traj.get_values('time')['descent'],
            traj.get_values('gam', units='deg')['descent'], 'ro')

        axes[2].plot(
            exp_out.get_values('time')['ascent'],
            exp_out.get_values('gam', units='deg')['ascent'], 'b--')

        axes[2].plot(
            exp_out.get_values('time')['descent'],
            exp_out.get_values('gam', units='deg')['descent'], 'r--')

        axes[2].set_xlabel('time (s)')
        axes[2].set_ylabel(r'flight path angle (deg)')

        plt.show()
Пример #22
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()
Пример #23
0
    def test_dynamic_input_params(self):
        prob = Problem(model=Group())

        traj = prob.model.add_subsystem('traj', Trajectory())

        # First phase: normal operation.
        # NOTE: using RK4 integration here

        P_DEMAND = 2.0

        phase0 = Phase(ode_class=BatteryODE, transcription=RungeKutta(num_segments=200))
        phase0.set_time_options(fix_initial=True, fix_duration=True)
        phase0.set_state_options('state_of_charge', fix_initial=True, fix_final=False)
        phase0.add_timeseries_output('battery.V_oc', output_name='V_oc', units='V')
        phase0.add_timeseries_output('battery.V_pack', output_name='V_pack', units='V')
        phase0.add_timeseries_output('pwr_balance.I_Li', output_name='I_Li', units='A')
        phase0.add_input_parameter('P_demand', val=P_DEMAND, units='W')
        traj.add_phase('phase0', phase0)

        # Second phase: normal operation.

        transcription = Radau(num_segments=5, order=5, compressed=True)
        phase1 = Phase(ode_class=BatteryODE, transcription=transcription)
        phase1.set_time_options(fix_initial=False, fix_duration=True)
        phase1.set_state_options('state_of_charge', fix_initial=False, fix_final=False, solve_segments=True)
        phase1.add_timeseries_output('battery.V_oc', output_name='V_oc', units='V')
        phase1.add_timeseries_output('battery.V_pack', output_name='V_pack', units='V')
        phase1.add_timeseries_output('pwr_balance.I_Li', output_name='I_Li', units='A')
        phase1.add_input_parameter('P_demand', val=P_DEMAND, units='W')
        traj.add_phase('phase1', phase1)

        # Second phase, but with battery failure.

        phase1_bfail = Phase(ode_class=BatteryODE, ode_init_kwargs={'num_battery': 2},
                             transcription=transcription)
        phase1_bfail.set_time_options(fix_initial=False, fix_duration=True)
        phase1_bfail.set_state_options('state_of_charge', fix_initial=False, fix_final=False, solve_segments=True)
        phase1_bfail.add_timeseries_output('battery.V_oc', output_name='V_oc', units='V')
        phase1_bfail.add_timeseries_output('battery.V_pack', output_name='V_pack', units='V')
        phase1_bfail.add_timeseries_output('pwr_balance.I_Li', output_name='I_Li', units='A')
        phase1_bfail.add_input_parameter('P_demand', val=P_DEMAND, units='W')
        traj.add_phase('phase1_bfail', phase1_bfail)

        # Second phase, but with motor failure.

        phase1_mfail = Phase(ode_class=BatteryODE, ode_init_kwargs={'num_motor': 2},
                             transcription=transcription)
        phase1_mfail.set_time_options(fix_initial=False, fix_duration=True)
        phase1_mfail.set_state_options('state_of_charge', fix_initial=False, fix_final=False, solve_segments=True)
        phase1_mfail.add_timeseries_output('battery.V_oc', output_name='V_oc', units='V')
        phase1_mfail.add_timeseries_output('battery.V_pack', output_name='V_pack', units='V')
        phase1_mfail.add_timeseries_output('pwr_balance.I_Li', output_name='I_Li', units='A')
        phase1_mfail.add_input_parameter('P_demand', val=P_DEMAND, units='W')
        traj.add_phase('phase1_mfail', phase1_mfail)

        traj.link_phases(phases=['phase0', 'phase1'], vars=['state_of_charge', 'time'], connected=True)
        traj.link_phases(phases=['phase0', 'phase1_bfail'], vars=['state_of_charge', 'time'], connected=True)
        traj.link_phases(phases=['phase0', 'phase1_mfail'], vars=['state_of_charge', 'time'], connected=True)

        # prob.model.linear_solver = DirectSolver(assemble_jac=True)

        prob.setup()
        prob.final_setup()

        prob['traj.phases.phase0.time_extents.t_initial'] = 0
        prob['traj.phases.phase0.time_extents.t_duration'] = 1.0*3600

        # prob['traj.phases.phase1.time_extents.t_initial'] = 1.0*3600
        prob['traj.phases.phase1.time_extents.t_duration'] = 1.0*3600

        # prob['traj.phases.phase1_bfail.time_extents.t_initial'] = 1.0*3600
        prob['traj.phases.phase1_bfail.time_extents.t_duration'] = 1.0*3600

        # prob['traj.phases.phase1_mfail.time_extents.t_initial'] = 1.0*3600
        prob['traj.phases.phase1_mfail.time_extents.t_duration'] = 1.0*3600

        prob.set_solver_print(level=0)
        prob.run_model()

        plot = True
        if plot:
            import matplotlib
            matplotlib.use('Agg')
            import matplotlib.pyplot as plt

            t0 = prob['traj.phase0.timeseries.time']
            t1 = prob['traj.phase1.timeseries.time']
            t1b = prob['traj.phase1_bfail.timeseries.time']
            t1m = prob['traj.phase1_mfail.timeseries.time']
            soc0 = prob['traj.phase0.timeseries.states:state_of_charge']
            soc1 = prob['traj.phase1.timeseries.states:state_of_charge']
            soc1b = prob['traj.phase1_bfail.timeseries.states:state_of_charge']
            soc1m = prob['traj.phase1_mfail.timeseries.states:state_of_charge']

            plt.subplot(2, 2, 1)
            plt.plot(t0, soc0, 'b')
            plt.plot(t1, soc1, 'b')
            plt.plot(t1b, soc1b, 'r')
            plt.plot(t1m, soc1m, 'c')
            plt.xlabel('Time (hour)')
            plt.ylabel('State of Charge (percent)')

            V_oc0 = prob['traj.phase0.timeseries.V_oc']
            V_oc1 = prob['traj.phase1.timeseries.V_oc']
            V_oc1b = prob['traj.phase1_bfail.timeseries.V_oc']
            V_oc1m = prob['traj.phase1_mfail.timeseries.V_oc']

            plt.subplot(2, 2, 2)
            plt.plot(t0, V_oc0, 'b')
            plt.plot(t1, V_oc1, 'b')
            plt.plot(t1b, V_oc1b, 'r')
            plt.plot(t1m, V_oc1m, 'c')
            plt.xlabel('Time (hour)')
            plt.ylabel('Open Circuit Voltage (V)')

            V_pack0 = prob['traj.phase0.timeseries.V_pack']
            V_pack1 = prob['traj.phase1.timeseries.V_pack']
            V_pack1b = prob['traj.phase1_bfail.timeseries.V_pack']
            V_pack1m = prob['traj.phase1_mfail.timeseries.V_pack']

            plt.subplot(2, 2, 3)
            plt.plot(t0, V_pack0, 'b')
            plt.plot(t1, V_pack1, 'b')
            plt.plot(t1b, V_pack1b, 'r')
            plt.plot(t1m, V_pack1m, 'c')
            plt.xlabel('Time (hour)')
            plt.ylabel('Terminal Voltage (V)')

            I_Li0 = prob['traj.phase0.timeseries.I_Li']
            I_Li1 = prob['traj.phase1.timeseries.I_Li']
            I_Li1b = prob['traj.phase1_bfail.timeseries.I_Li']
            I_Li1m = prob['traj.phase1_mfail.timeseries.I_Li']

            plt.subplot(2, 2, 4)
            plt.plot(t0, I_Li0, 'b')
            plt.plot(t1, I_Li1, 'b')
            plt.plot(t1b, I_Li1b, 'r')
            plt.plot(t1m, I_Li1m, 'c')
            plt.xlabel('Time (hour)')
            plt.ylabel('Line Current (A)')

            plt.show()
Пример #24
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
Пример #25
0
def thermal_mission_trajectory(num_seg=5,
                               transcription_order=3,
                               meeting_altitude=20000.,
                               Q_env=0.,
                               Q_sink=0.,
                               Q_out=0.,
                               m_recirculated=0.,
                               opt_m_recirculated=False,
                               opt_m_burn=False,
                               opt_throttle=True,
                               engine_heat_coeff=0.,
                               pump_heat_coeff=0.,
                               T=None,
                               T_o=None,
                               opt_m=False,
                               m_initial=20.e3,
                               transcription='gauss-lobatto'):

    p = Problem(model=Group())

    p.driver = pyOptSparseDriver()
    p.driver.options['optimizer'] = 'SNOPT'
    p.driver.opt_settings['Major iterations limit'] = 50  #00
    p.driver.opt_settings['Iterations limit'] = 5000000000000000
    p.driver.opt_settings['iSumm'] = 6
    p.driver.opt_settings['Major feasibility tolerance'] = 1.0E-8
    p.driver.opt_settings['Major optimality tolerance'] = 1.0E-8
    p.driver.opt_settings['Verify level'] = -1
    p.driver.opt_settings['Linesearch tolerance'] = .1
    p.driver.opt_settings['Major step limit'] = .05
    p.driver.options['dynamic_simul_derivs'] = True

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

    ascent = Phase(transcription,
                   ode_class=ThermalMissionODE,
                   ode_init_kwargs={
                       'engine_heat_coeff': engine_heat_coeff,
                       'pump_heat_coeff': pump_heat_coeff
                   },
                   num_segments=num_seg,
                   transcription_order=transcription_order)

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

    ascent.set_time_options(opt_initial=False,
                            duration_bounds=(50, 400),
                            duration_ref=100.0)

    ascent.set_state_options('r',
                             fix_initial=True,
                             lower=0,
                             upper=1.0E6,
                             scaler=1.0E-3,
                             defect_scaler=1.0E-2,
                             units='m')

    ascent.set_state_options('h',
                             fix_initial=True,
                             lower=0,
                             upper=20000.0,
                             scaler=1.0E-3,
                             defect_scaler=1.0E-3,
                             units='m')

    ascent.set_state_options('v',
                             fix_initial=True,
                             lower=10.0,
                             scaler=1.0E-2,
                             defect_scaler=5.0E-0,
                             units='m/s')

    ascent.set_state_options('gam',
                             fix_initial=True,
                             lower=-1.5,
                             upper=1.5,
                             ref=1.0,
                             defect_scaler=1.0,
                             units='rad')

    ascent.set_state_options('m',
                             fix_initial=not opt_m,
                             lower=15.e3,
                             upper=80e3,
                             scaler=1.0E-3,
                             defect_scaler=1.0E-3,
                             units='kg')

    ascent.add_control('alpha',
                       units='deg',
                       lower=-8.0,
                       upper=8.0,
                       scaler=1.0,
                       rate_continuity=True)

    ascent.add_design_parameter('S', val=1., units='m**2', opt=False)

    if opt_throttle:
        ascent.add_control('throttle',
                           val=1.0,
                           lower=0.0,
                           upper=1.0,
                           opt=True,
                           rate_continuity=True)
    else:
        ascent.add_design_parameter('throttle', val=1.0, opt=False)

    ascent.add_design_parameter('W0', val=10.5e3, opt=False, units='kg')

    ascent.add_boundary_constraint('h',
                                   loc='final',
                                   equals=meeting_altitude,
                                   scaler=1.0E-3,
                                   units='m')
    ascent.add_boundary_constraint('aero.mach',
                                   loc='final',
                                   equals=1.,
                                   units=None)
    ascent.add_boundary_constraint('gam', loc='final', equals=0.0, units='rad')

    ascent.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000)
    ascent.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8)
    # ascent.add_path_constraint(name='time', upper=110.)

    # Minimize time at the end of the ascent
    ascent.add_objective('time', loc='final', ref=100.0)
    # ascent.add_objective('energy', loc='final', ref=100.0)
    # ascent.add_objective('m', loc='final', ref=-10000.0)

    # Set the state options for mass, temperature, and energy.
    ascent.set_state_options('T',
                             fix_initial=True,
                             ref=300,
                             defect_scaler=1e-2)
    ascent.set_state_options('energy',
                             fix_initial=True,
                             ref=10e3,
                             defect_scaler=1e-4)

    # Allow the optimizer to vary the fuel flow
    if opt_m_recirculated:
        ascent.add_control('m_recirculated',
                           val=m_recirculated,
                           lower=0.,
                           opt=True,
                           rate_continuity=True,
                           ref=20.)
    else:
        ascent.add_control('m_recirculated', val=m_recirculated, opt=False)

    ascent.add_design_parameter('Q_env', val=Q_env, opt=False)
    ascent.add_design_parameter('Q_sink', val=Q_sink, opt=False)
    ascent.add_design_parameter('Q_out', val=Q_out, opt=False)

    # Constrain the temperature, 2nd derivative of fuel mass in the tank, and make
    # sure that the amount recirculated is at least 0, otherwise we'd burn
    # more fuel than we pumped.
    if opt_m_recirculated:
        ascent.add_path_constraint('m_flow',
                                   lower=0.,
                                   upper=50.,
                                   units='kg/s',
                                   ref=10.)

    if T is not None:
        ascent.add_path_constraint('T', upper=T, units='K')

    if T_o is not None:
        ascent.add_path_constraint('T_o', upper=T_o, units='K', ref=300.)

    cruise = Phase(transcription,
                   ode_class=ThermalMissionODE,
                   ode_init_kwargs={
                       'engine_heat_coeff': engine_heat_coeff,
                       'pump_heat_coeff': pump_heat_coeff
                   },
                   num_segments=num_seg,
                   transcription_order=transcription_order)

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

    cruise.set_time_options(opt_initial=False,
                            duration_bounds=(50, 1e4),
                            duration_ref=100.0)

    cruise.set_state_options('r',
                             lower=0,
                             upper=1.0E6,
                             scaler=1.0E-3,
                             defect_scaler=1.0E-2,
                             units='m')

    cruise.set_state_options('h',
                             lower=0,
                             upper=20000.0,
                             scaler=1.0E-3,
                             defect_scaler=1.0E-3,
                             units='m')

    cruise.set_state_options('v',
                             lower=10.0,
                             scaler=1.0E-2,
                             defect_scaler=5.0E-0,
                             units='m/s')

    cruise.set_state_options('gam',
                             lower=-1.5,
                             upper=1.5,
                             ref=1.0,
                             defect_scaler=1.0,
                             units='rad')

    cruise.set_state_options('m',
                             lower=15.e3,
                             upper=80e3,
                             scaler=1.0E-3,
                             defect_scaler=1.0E-3,
                             units='kg')

    cruise.add_control('alpha',
                       units='deg',
                       lower=-8.0,
                       upper=8.0,
                       scaler=1.0,
                       rate_continuity=True)

    cruise.add_design_parameter('S', val=1., units='m**2', opt=False)

    if opt_throttle:
        cruise.add_control('throttle',
                           val=1.0,
                           lower=0.0,
                           upper=1.0,
                           opt=True,
                           rate_continuity=True)
    else:
        cruise.add_design_parameter('throttle', val=1.0, opt=False)

    cruise.add_design_parameter('W0', val=10.5e3, opt=False, units='kg')

    # Set the state options for mass, temperature, and energy.
    cruise.set_state_options('T',
                             fix_initial=True,
                             ref=300,
                             defect_scaler=1e-2)
    cruise.set_state_options('energy',
                             fix_initial=True,
                             ref=10e3,
                             defect_scaler=1e-4)

    # Allow the optimizer to vary the fuel flow
    if opt_m_recirculated:
        cruise.add_control('m_recirculated',
                           val=m_recirculated,
                           lower=0.,
                           opt=True,
                           rate_continuity=True,
                           ref=20.)
    else:
        cruise.add_control('m_recirculated', val=m_recirculated, opt=False)

    cruise.add_design_parameter('Q_env', val=Q_env, opt=False)
    cruise.add_design_parameter('Q_sink', val=Q_sink, opt=False)
    cruise.add_design_parameter('Q_out', val=Q_out, opt=False)

    cruise.add_path_constraint(name='h', lower=100.0, upper=20000, ref=20000)
    cruise.add_path_constraint(name='aero.mach', lower=0.1, upper=1.8)

    # Link Phases (link time and all state variables)
    traj.link_phases(phases=['ascent', 'cruise'], vars=['*'])

    p.setup(mode='fwd', check=True)

    p['traj.ascent.t_initial'] = 0.0
    p['traj.ascent.t_duration'] = 200.
    p['traj.ascent.states:r'] = ascent.interpolate(ys=[0.0, 111319.54],
                                                   nodes='state_input')
    p['traj.ascent.states:h'] = ascent.interpolate(
        ys=[100.0, meeting_altitude], nodes='state_input')
    # p['traj.ascent.states:h'][:] = 10000.

    p['traj.ascent.states:v'] = ascent.interpolate(ys=[135.964, 283.159],
                                                   nodes='state_input')
    # p['traj.ascent.states:v'][:] = 200.
    p['traj.ascent.states:gam'] = ascent.interpolate(ys=[0.0, 0.0],
                                                     nodes='state_input')
    p['traj.ascent.states:m'] = ascent.interpolate(ys=[m_initial, 20.e3],
                                                   nodes='state_input')
    p['traj.ascent.controls:alpha'] = ascent.interpolate(ys=[1., 1.],
                                                         nodes='control_input')

    # Give initial values for the ascent states, controls, and time
    p['traj.ascent.states:T'] = 310.

    p['traj.cruise.t_initial'] = 200
    p['traj.cruise.t_duration'] = 1000.
    p['traj.cruise.states:r'] = cruise.interpolate(ys=[111319.54, 2e6],
                                                   nodes='state_input')
    p['traj.cruise.states:h'] = cruise.interpolate(
        ys=[meeting_altitude, meeting_altitude], nodes='state_input')
    # p['traj.cruise.states:h'][:] = 10000.

    p['traj.cruise.states:v'] = cruise.interpolate(ys=[283.159, 283.159],
                                                   nodes='state_input')
    # p['traj.cruise.states:v'][:] = 200.
    p['traj.cruise.states:gam'] = cruise.interpolate(ys=[0.0, 0.0],
                                                     nodes='state_input')
    p['traj.cruise.states:m'] = cruise.interpolate(ys=[14e3, 12.e3],
                                                   nodes='state_input')
    p['traj.cruise.controls:alpha'] = cruise.interpolate(ys=[1., 1.],
                                                         nodes='control_input')

    # Give initial values for the cruise states, controls, and time
    p['traj.cruise.states:T'] = 310.

    return p