OpenMDAO / dymos

Open Source Optimization of Dynamic Multidisciplinary Systems
Apache License 2.0
208 stars 66 forks source link

No solution file generated if final_setup is explicitly called before run_problem. #501

Closed robfalck closed 3 years ago

robfalck commented 3 years ago

Summary of Issue

If a user explicitly calls problem.final_setup() before run_problem, the hook system fails to attach a recorder to the problem that records dymos_solution.db.

Issue Type

Description

The hook system is intended to allow the user to run a problem from the command line, but the complex way in which it must be enabled and disabled during operation is likely involved here.

To allow command line operation of Dymos, we may just want to find problems defined in the given run file without relying on the OpenMDAO hook system.

Example

In the example below, commenting out the final_setup line will result in the expected behavior.

    def test_run_problem_with_simulate_explicit_final_setup(self):
        """
        Test that run_problem generates a dymos_solution.db even if final_setup is called
        explicitly beforehand.
        """
        p = om.Problem(model=om.Group())
        p.driver = om.pyOptSparseDriver()
        p.driver.declare_coloring()
        p.driver.options['optimizer'] = 'SLSQP'

        traj = p.model.add_subsystem('traj', dm.Trajectory())
        phase0 = traj.add_phase('phase0', dm.Phase(ode_class=BrachistochroneODE,
                                                   transcription=dm.Radau(num_segments=10,
                                                                          order=3)))
        phase0.set_time_options(fix_initial=True, fix_duration=False)
        phase0.add_state('x', fix_initial=True, fix_final=False)
        phase0.add_state('y', fix_initial=True, fix_final=False)
        phase0.add_state('v', fix_initial=True, fix_final=False)
        phase0.add_control('theta', continuity=True, rate_continuity=True,
                           units='deg', lower=0.01, upper=179.9)
        phase0.add_parameter('g', units='m/s**2', val=9.80665)

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

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

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

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

        p.final_setup()

        dm.run_problem(p, simulate=True)

        self.assertTrue(os.path.exists('dymos_solution.db'))
        self.assertTrue(os.path.exists('dymos_simulation.db'))
        # Assert the results are what we expect.
        cr = om.CaseReader('dymos_solution.db')
        case = cr.get_case('final')
        assert_almost_equal(case.outputs['traj.phase0.timeseries.time'].max(), 1.8016, decimal=4)

Environment

robfalck commented 3 years ago

This issue is related to the post_setup hook which drives the dymos command-line interface. The command-line interface is deprecated and this issue will be resolved with its removal in 1.0.0.

robfalck commented 3 years ago

Resolved by #563