Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove FLOPS based mission method #53

Merged
merged 27 commits into from
Jan 19, 2024

Conversation

johnjasa
Copy link
Member

@johnjasa johnjasa commented Jan 9, 2024

Summary

I've modified all run scripts, tests, benchmarks, and docs to use the simple mission method and removed the FLOPS mission method.
This is probably the crux of my work this jog.
This PR dramatically simplifies the FLOPS-based mission logic and run scripts.

Related Issues

  • Resolves #

Backwards incompatibilities

None

New Dependencies

None

@johnjasa johnjasa changed the title Removed FLOPS based mission method Remove FLOPS based mission method Jan 9, 2024
@Kenneth-T-Moore
Copy link
Member

I am a little nervous about completely removing the old method. We might want it to be able to build off of legacy results using the new aviary, or we might want to do some testing with it.

@johnjasa
Copy link
Member Author

johnjasa commented Jan 9, 2024

I am a little nervous about completely removing the old method. We might want it to be able to build off of legacy results using the new aviary, or we might want to do some testing with it.

Can you tell me more about the use cases you'd want to keep it around for? The underlying physics of the simple height energy equations of motion are the same as in FLOPS. Would you ever want new users to use the older mission method or just keep it around for comparisons?

@Kenneth-T-Moore
Copy link
Member

I am a little nervous about completely removing the old method. We might want it to be able to build off of legacy results using the new aviary, or we might want to do some testing with it.

Can you tell me more about the use cases you'd want to keep it around for? The underlying physics of the simple height energy equations of motion are the same as in FLOPS. Would you ever want new users to use the older mission method or just keep it around for comparisons?

I am mostly thinking in terms of the MBSAE published work, and being able to reproduce it exactly as we migrate all of that to Aviary 0.9.x.

@johnjasa
Copy link
Member Author

johnjasa commented Jan 10, 2024

Ken and I had a great conversation about this and established this path forward:

  • Irian will convert the MBSA&E models to use Aviary 0.9.1+
  • Ken and John will help convert this to the simple mission
  • This PR can come in and when it does and with all added features we should increment to Aviary 0.9.2

Copy link
Contributor

@jkirk5 jkirk5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stuff! I have a ton of little nitpicks about some changes, especially instances where simple was being brought back to name or label things.

Copy link
Contributor

@jkirk5 jkirk5 Jan 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change height_energy to simple? And phase info paths are wrong. I guess this whole file needs to get updated, seems like it is very out-of-date on how to set up mission & phase info. If you don't want to deal with it for this PR we can make it a task for someone to tackle.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your comments, Jason -- anything where simple snuck back in was just an artifact of this branch being out-of-date with main. I was waiting for Ken's assessment for MBSA&E work. I've worked through the merge conflicts now; I'll update any remaining notions of simple as you pointed out.

@@ -694,7 +691,7 @@ def _add_groundroll_eq_constraint(self, phase):
promotes_inputs=["t_init_gear", "t_init_flaps"],
)

def _get_height_energy_phase(self, phase_name, phase_idx):
def _get_simple_phase(self, phase_name, phase_idx):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change from height_energy to simple?

for phase_idx, phase_name in enumerate(phases):
phase = traj.add_phase(
phase_name, self._get_height_energy_phase(phase_name, phase_idx))
phase_name, self._get_simple_phase(phase_name, phase_idx))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question here, why bring back simple

@@ -11,7 +11,7 @@


class TestCheckInputs(unittest.TestCase):
def test_correct_input_flops(self):
def test_correct_input_simple(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More simple! FLOPS -> height_energy

@@ -11,7 +11,7 @@


class TestCheckInputs(unittest.TestCase):
def test_correct_input_flops(self):
def test_correct_input_simple(self):
# This should pass without any issue as it's the same valid dict as before
self.assertTrue(check_phase_info(phase_info_flops, mission_method=HEIGHT_ENERGY))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flops & gasp in this file should get changed to height_energy and 2dof

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can delete this file - it should be an exact copy of FwFm.csv now

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

def test_height_energy_zero_iters(self):
local_phase_info = deepcopy(height_energy_phase_info)
self.build_and_run_problem('models/test_aircraft/aircraft_for_bench_FwFm.csv',
def test_simple_zero_iters(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here too

@@ -5,7 +5,7 @@

from aviary.interface.methods_for_level2 import AviaryProblem
from aviary.interface.default_phase_info.two_dof import phase_info as two_dof_phase_info
from aviary.interface.default_phase_info.height_energy import phase_info as height_energy_phase_info
from aviary.interface.default_phase_info.height_energy import phase_info as simple_phase_info
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more height_energy reverted to simple

'subsystem_options': {
'core_aerodynamics': {'method': 'solved_alpha', 'aero_data': aero_data, 'training_data': False}
},
"subsystem_options": {"core_aerodynamics": {"method": "computed"}},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was aero method changed? It should be mission agnostic (and if it is somehow not, then we need a bug report!)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed for no particular reason; I copied-pasted this phase_info from another place. It is indeed mission agnostic

TWO_DEGREES_OF_FREEDOM = '2DOF'
# TODO these are a little out of place atm
SIMPLE = 'simple'
HEIGHT_ENERGY = 'height_energy'
Copy link
Contributor

@jkirk5 jkirk5 Jan 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You made them non-alphabetical! Plus the TODO is implied to apply to height_energy now, but that one's fine

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

order moved and comment removed

@jkirk5
Copy link
Contributor

jkirk5 commented Jan 17, 2024

I am mostly thinking in terms of the MBSAE published work, and being able to reproduce it exactly as we migrate all of that to Aviary 0.9.x.

I don't think its reasonable to always expect identical results moving to a new version of Aviary, especially as the code is rapidly evolving. Long term best practice will be archiving the environment used to run final results in case replication is needed.

},
}

prob = run_aviary(
'models/test_aircraft/aircraft_for_bench_FwFm_simple.csv', phase_info)
'models/test_aircraft/aircraft_for_bench_FwFm.csv', phase_info, max_iter=50)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we hitting maxiter on this benchmark? It is the FLOPS/FLOPS test, so I would expect it to converge more quickly.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not hitting max_iter; I added it during debugging


traj = setup_trajectory_params(prob.model, traj, aviary_inputs)

##################################
# Connect in Takeoff and Landing #
##################################

prob.model.add_subsystem(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is interesting that this benchmark used slack variables instead of a connection for the takeoff to climb connection. (even more interesting since I wrote this benchmark, but I must have copied from a different benchmark that is long gone.)

I guess that removing the slack variables makes it more like how we currently do it in level 2.

@@ -63,6 +63,4 @@ def test_zero_iters_solved(self):


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep these.

Note: testflo doesn't require unittest.main(). We only need that if we run with unittest, or if we want the test for run with python test_0_iters.py. You can't debug through unittest though, which is why I like to keep the other lines.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed back!

prob = AviaryProblem(reports=False)

# Load aircraft and options data from user
# Allow for user overrides here
prob.load_inputs(csv_path, phase_info, engine_builder=SimpleTestEngine())
prob.load_inputs("models/test_aircraft/aircraft_for_bench_GwFm.csv",
phase_info, engine_builder=SimpleTestEngine())


# Preprocess inputs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, fixed

for var_name in expected_var_names:
self.assertIn(var_name, design_vars_dict)

# Check values
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why were these asserts all removed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not important for testing if the custom engine model was used correctly; I had to update their names and realized there was no reason for them to be there

@@ -279,6 +349,4 @@ def build_pre_mission(self, aviary_inputs):


if __name__ == "__main__":
# unittest.main()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please restore these.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

restored

assert_near_equal(CL_pass, CL_base, 1e-6)
assert_near_equal(CD_pass, CD_base, 1e-6)

def test_solved_aero_pass_polar_unique_abscissa(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this test deleted in a regression, or was it moved from elsewhere? I remember writing this, but it appears as new in this diff.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch, it was unnecessarily duplicated in this PR, I fixed that now

@@ -152,3 +196,12 @@ def setup(self):
('mass', Dynamic.Mission.MASS)
],
promotes_outputs=['initial_mass_residual'])

self.nonlinear_solver = om.NewtonSolver(solve_subsystems=True,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the solver has some ramifications. I wondered if you could confine it to a subsystem, but looks like that subsystem would need to contain at least the engine, and that's in the external subsystem group, so there probably isn't anything else we can do.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree about the ramifications and lack of potential simplification with the current setup. Is there something you'd like to see different here in the PR or are you simply noting this consideration?

@@ -125,46 +121,6 @@ def test_phase_info_parameterization_gasp(self):
assert_near_equal(prob.get_val("traj.cruise.rhs.mach")[0],
0.6)

def test_phase_info_parameterization_flops(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than deleting this test, I think the right thing would be to convert the parameterizing method from the old height_energy phase info so that it works on the new one. This was added to support the level 1 command line interface, when you run it on an aircraft that is not the single-aisle-transport.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood, Ken, thanks for explaining! I've updated this and pushed up.

},
}


def phase_info_parameterization(phase_info, aviary_inputs):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in earlier comment, this needs to be migrated to not lose a command line feature that was essential to the release.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, added back now.

# self.model.connect(Mission.Takeoff.FINAL_ALTITUDE,
# 'traj.climb.controls:altitude')

# Create an ExecComp to compute the difference in mach
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, we do have a slack variable! (Mostly because mach isn't a state any more.)
I wonder if we should name the component more descriptively -- mach_resid_takeoff_cruise or maybe you have some other ideas?

Same with altitude.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went with mach_resid_for_connecting_takeoff and altitude_resid_for_connecting_takeoff, thanks!

self.model.connect('traj.descent.control_values:altitude', Mission.Landing.INITIAL_ALTITUDE,
src_indices=[0])
self.model.connect('traj.descent.control_values:altitude', Mission.Landing.INITIAL_ALTITUDE,
src_indices=[0])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you take a look at an n2 of one of the FLOPS models and make sure that none of the component changes are producing any cycles (i.e., everything is in the correct order)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done this and confirmed that the only cycle introduced is the solver-based throttle loop, as expected. Thanks!

Copy link
Member

@Kenneth-T-Moore Kenneth-T-Moore left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments to address.

@johnjasa
Copy link
Member Author

Thanks for these comments, @Kenneth-T-Moore! Please let me know if you'd like to see any other changes. I'm working on the docs failures now.

@johnjasa johnjasa added this pull request to the merge queue Jan 19, 2024
Merged via the queue into OpenMDAO:main with commit 4f0b3e7 Jan 19, 2024
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants