Пример #1
0
class NLP:
    """NLP class transcribes a continuous-time optimal control problem in trajectory optimization into
    a Non Linear Programming Problem (NLP) using the OpenMDAO and dymos libraries.

    Parameters
    ----------
    body : Primary
        Instance of `Primary` class representing the central attracting body
    sc : Spacecraft
        Instance of `Spacecraft` class representing the spacecraft
    method : str
        Transcription method used to discretize the continuous time trajectory into a finite set of nodes,
        allowed ``gauss-lobatto``, ``radau-ps`` and ``runge-kutta``
    nb_seg : int or tuple
        Number of segments in which each phase is discretized
    order : int or tuple
        Transcription order within each phase, must be odd
    solver : str
        NLP solver, must be supported by OpenMDAO
    snopt_opts : dict or None, optional
        SNOPT optional settings expressed as key-value pairs. Refer to the SNOPT User Guide [1]_ for more details.
        Default is None
    rec_file : str or None, optional
        Name of the file in which the computed solution is recorded or None. Default is None

    Attributes
    ----------
    body : Primary
        Instance of `Primary` class representing the central attracting body
    sc : Spacecraft
        Instance of `Spacecraft` class representing the spacecraft
    method : str
        Transcription method used to discretize the continuous time trajectory into a finite set of nodes,
        allowed ``gauss-lobatto``, ``radau-ps`` and ``runge-kutta``
    nb_seg : int or tuple
        Number of segments in which each phase is discretized
    order : int or tuple
        Transcription order within each phase, must be odd
    solver : str
        NLP solver, must be supported by OpenMDAO
    snopt_opts : dict or None
        SNOPT optional settings expressed as key-value pairs. Refer to the SNOPT User Guide [1]_ for more details.
    rec_file : str or None
        Name of the file in which the computed solution is recorded or None
    p : Problem
        OpenMDAO `Problem` class instance representing the NLP
    trajectory : Trajectory
        Dymos `Trajectory` class instance representing the spacecraft trajectory
    p_exp : Problem
        OpenMDAO `Problem` class instance representing the explicitly simulated trajectory

    References
    ----------
    .. [1] Gill, Philip E., et al. User’s Guide for SNOPT Version 7.7: Software for Large-Scale Nonlinear Programming,
        Feb. 2019, p. 126.

    """

    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 setup(self):
        """Set up the Jacobian type, linear solver and derivatives type. """

        self.p.model.options['assembled_jac_type'] = 'csc'
        self.p.model.linear_solver = DirectSolver()
        self.p.setup(check=True, force_alloc_complex=True, derivatives=True)

    def exp_sim(self, rec_file=None):
        """Explicitly simulate the implicitly obtained optimal solution using Scipy `solve_ivp` method. """

        if rec_file is not None:
            self.p_exp = self.trajectory.simulate(atol=1e-12, rtol=1e-12, record_file=rec_file)
        else:
            self.p_exp = self.trajectory.simulate(atol=1e-12, rtol=1e-12)

        self.cleanup()

    def cleanup(self):
        """Clean up resources. """

        self.trajectory.cleanup()
        self.p.driver.cleanup()
        self.p.cleanup()

    def __str__(self):
        """Prints info on the NLP.

        Returns
        -------
        s : str
            Info on the NLP

        """

        lines = ['\n{:^40s}'.format('NLP characteristics:'),
                 '\n{:<25s}{:<15s}'.format('Solver:', self.solver),
                 '{:<25s}{:<15s}'.format('Transcription method:', str(self.method)),
                 '{:<25s}{:<15s}'.format('Number of segments:', str(self.nb_seg)),
                 '{:<25s}{:<15s}'.format('Transcription order:', str(self.order))]

        s = '\n'.join(lines)

        return s
    def test_recording_remote_voi(self):
        # Create a parallel model
        model = Group()

        model.add_subsystem('par', ParallelGroup())
        model.par.add_subsystem('G1', Mygroup())
        model.par.add_subsystem('G2', Mygroup())
        model.connect('par.G1.y', 'Obj.y1')
        model.connect('par.G2.y', 'Obj.y2')

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

        # Configure driver to record VOIs on both procs
        driver = ScipyOptimizeDriver(disp=False)

        driver.recording_options['record_desvars'] = True
        driver.recording_options['record_responses'] = True
        driver.recording_options['record_objectives'] = True
        driver.recording_options['record_constraints'] = True
        driver.recording_options['includes'] = ['par.G1.y', 'par.G2.y']

        driver.add_recorder(self.recorder)

        # Create problem and run driver
        prob = Problem(model, driver)
        prob.add_recorder(self.recorder)
        prob.setup()

        t0, t1 = run_driver(prob)
        prob.record_iteration('final')
        t2 = time()

        prob.cleanup()

        # Since the test will compare the last case recorded, just check the
        # current values in the problem. This next section is about getting those values

        # These involve collective gathers so all ranks need to run this
        expected_outputs = driver.get_design_var_values()
        expected_outputs.update(driver.get_objective_values())
        expected_outputs.update(driver.get_constraint_values())

        # includes for outputs are specified as promoted names but we need absolute names
        prom2abs = model._var_allprocs_prom2abs_list['output']
        abs_includes = [prom2abs[n][0] for n in prob.driver.recording_options['includes']]

        # Absolute path names of includes on this rank
        rrank = model.comm.rank
        rowned = model._owning_rank
        local_includes = [n for n in abs_includes if rrank == rowned[n]]

        # Get values for all vars on this rank
        inputs, outputs, residuals = model.get_nonlinear_vectors()

        # Get values for includes on this rank
        local_vars = {n: outputs[n] for n in local_includes}

        # Gather values for includes on all ranks
        all_vars = model.comm.gather(local_vars, root=0)

        if prob.comm.rank == 0:
            # Only on rank 0 do we have all the values. The all_vars variable is a list of
            # dicts from all ranks 0,1,... In this case, just ranks 0 and 1
            dct = all_vars[-1]
            for d in all_vars[:-1]:
                dct.update(d)

            expected_includes = {
                'par.G1.Cy.y': dct['par.G1.Cy.y'],
                'par.G2.Cy.y': dct['par.G2.Cy.y'],
            }

            expected_outputs.update(expected_includes)

            coordinate = [0, 'ScipyOptimize_SLSQP', (driver.iter_count-1,)]

            expected_data = ((coordinate, (t0, t1), expected_outputs, None),)
            assertDriverIterDataRecorded(self, expected_data, self.eps)

            expected_data = (('final', (t1, t2), expected_outputs),)
            assertProblemDataRecorded(self, expected_data, self.eps)
    def test_recording_remote_voi(self):
        # Create a parallel model
        model = Group()

        model.add_subsystem('par', ParallelGroup())
        model.par.add_subsystem('G1', Mygroup())
        model.par.add_subsystem('G2', Mygroup())
        model.connect('par.G1.y', 'Obj.y1')
        model.connect('par.G2.y', 'Obj.y2')

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

        # Configure driver to record VOIs on both procs
        driver = ScipyOptimizeDriver(disp=False)

        driver.recording_options['record_desvars'] = True
        driver.recording_options['record_responses'] = True
        driver.recording_options['record_objectives'] = True
        driver.recording_options['record_constraints'] = True
        driver.recording_options['includes'] = ['par.G1.y', 'par.G2.y']

        driver.add_recorder(self.recorder)

        # Create problem and run driver
        prob = Problem(model, driver)
        prob.add_recorder(self.recorder)
        prob.setup()

        t0, t1 = run_driver(prob)
        prob.record_iteration('final')
        t2 = time()

        prob.cleanup()

        # Since the test will compare the last case recorded, just check the
        # current values in the problem. This next section is about getting those values

        # These involve collective gathers so all ranks need to run this
        expected_outputs = driver.get_design_var_values()
        expected_outputs.update(driver.get_objective_values())
        expected_outputs.update(driver.get_constraint_values())

        # includes for outputs are specified as promoted names but we need absolute names
        prom2abs = model._var_allprocs_prom2abs_list['output']
        abs_includes = [
            prom2abs[n][0] for n in prob.driver.recording_options['includes']
        ]

        # Absolute path names of includes on this rank
        rrank = model.comm.rank
        rowned = model._owning_rank
        local_includes = [n for n in abs_includes if rrank == rowned[n]]

        # Get values for all vars on this rank
        inputs, outputs, residuals = model.get_nonlinear_vectors()

        # Get values for includes on this rank
        local_vars = {n: outputs[n] for n in local_includes}

        # Gather values for includes on all ranks
        all_vars = model.comm.gather(local_vars, root=0)

        if prob.comm.rank == 0:
            # Only on rank 0 do we have all the values. The all_vars variable is a list of
            # dicts from all ranks 0,1,... In this case, just ranks 0 and 1
            dct = all_vars[-1]
            for d in all_vars[:-1]:
                dct.update(d)

            expected_includes = {
                'par.G1.Cy.y': dct['par.G1.Cy.y'],
                'par.G2.Cy.y': dct['par.G2.Cy.y'],
            }

            expected_outputs.update(expected_includes)

            coordinate = [0, 'ScipyOptimize_SLSQP', (driver.iter_count - 1, )]

            expected_data = ((coordinate, (t0, t1), expected_outputs, None), )
            assertDriverIterDataRecorded(self, expected_data, self.eps)

            expected_data = (('final', (t1, t2), expected_outputs), )
            assertProblemDataRecorded(self, expected_data, self.eps)
Пример #4
0
    #Optimization Set-Up
    p.driver = ScipyOptimizeDriver()
    p.driver.options['optimizer'] = 'SLSQP'
    # p.driver.options['optimizer'] = 'COBYLA'
    p.driver.options
    model.linear_solver = DirectSolver(iprint=2)

    # model.add_design_var('eta_sa', lower = 0.01, upper=1)
    model.add_design_var('M_ps', lower=0.01, upper=100)
    model.add_constraint('con1',)
    model.add_objective('t_tot')

    #Case Recorder Setting
    recorder = SqliteRecorder('test.sql')
    p.driver.add_recorder(recorder)
    p.add_recorder(recorder)

    #Set-up and Run
    p.setup()
    p.set_solver_print(2)
    p.run_driver()
    # view_model(p)
    p.record_iteration('final')
    p.cleanup()

    cr = CaseReader('test.sql')
    drivercases = cr.list_cases('driver')
    case = cr.get_case(drivercases[0])
    print(sorted(case.outputs.keys()))

    print('P_req',['P_req'])