Skip to content

Aeropropulsive scenario and docs update #175

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ They describe physics problem being solved, the standards set by MPhys, requirem
:caption: Multiphysics Scenarios

scenarios/aerostructural.rst
scenarios/aeropropulsive.rst

.. toctree::
:maxdepth: 1
Expand Down
28 changes: 28 additions & 0 deletions docs/scenarios/aeropropulsive.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
%%%%%%%%%%%%%%%%%%%%%%%
Aeropropulsive Scenario
%%%%%%%%%%%%%%%%%%%%%%%

The :class: `ScenarioAeropropulsive <mphys.scenario_aeropropulsive.ScenarioAeropropulsive>` is for static coupled aerodynamic and propulsion problems.
Copy link
Collaborator

Choose a reason for hiding this comment

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

What does the word "static" mean here? Did you want to mean "steady state" or something else?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yup, good catch.

The primary physics modules required for this problem are:
1. The aerodynamics which computes forces and intensive thermodynamic properties given the aerodynamic surface coordinates.
2. The thermodynamic cycle model which computes the effect of the propulsion system on the flowfield.
3. The boundary condition (BC) coupling that enforces the coupling between the aerodynamic and propulsion systems.

Builder Requirements
====================

Propulsion Solver Builder
-------------------------
The propulsion builder constructs the thermodynamic cycle model(s) that are used to compute the effect of the propulsion system on the aerodynamics.

BC Coupling Builder
--------------------
The BC coupling builder implements consistency constraints formulated as residuals between the aerodynamic and propulsion disciplines.
The consistency constraints enforce the aeropropulsive coupling through the optimization problem.

Options
=======
.. embed-options::
mphys.scenario_aeropropulsive
ScenarioAeropropulsive
options
34 changes: 15 additions & 19 deletions mphys/scenario_aeropropulsive.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import openmdao.api as om
from .scenario import Scenario

from .coupling_group import CouplingGroup
from .scenario import Scenario


class ScenarioAeropropulsive(Scenario):
Expand All @@ -15,57 +16,58 @@ def initialize(self):
self.options.declare("aero_builder", recordable=False, desc="The MPhys builder for the aerodynamic solver")
self.options.declare("prop_builder", recordable=False, desc="The MPhys builder for the propulsion model")
self.options.declare(
"balance_builder", recordable=False, desc="The MPhys builder for the balance group", default=None
"bc_coupling_builder",
recordable=False,
desc="The Mphys builder for the boundary condition coupling group",
default=None,
)
self.options.declare(
"in_MultipointParallel",
default=False,
desc="Set to `True` if adding this scenario inside a MultipointParallel Group.",
)
self.options.declare(
"geometry_builder", default=None, recordable=False, desc="The optional MPhys builder for the geometry"
"geometry_builder", default=None, recordable=False, desc="The optional Mphys builder for the geometry"
)

def _mphys_scenario_setup(self):
aero_builder = self.options["aero_builder"]
prop_builder = self.options["prop_builder"]
balance_builder = self.options["balance_builder"]
bc_coupling_builder = self.options["bc_coupling_builder"]
geometry_builder = self.options["geometry_builder"]

if self.options["in_MultipointParallel"]:
self._mphys_initialize_builders(aero_builder, prop_builder, geometry_builder)
self._mphys_add_mesh_and_geometry_subsystems(aero_builder, prop_builder, geometry_builder)
self._mphys_add_mesh_and_geometry_subsystems(aero_builder, geometry_builder)

self._mphys_add_pre_coupling_subsystem_from_builder("aero", aero_builder, self.name)
self._mphys_add_pre_coupling_subsystem_from_builder("prop", prop_builder, self.name)

coupling_group = CouplingAeropropulsive(
aero_builder=aero_builder, prop_builder=prop_builder, balance_builder=balance_builder, scenario_name=self.name
aero_builder=aero_builder, prop_builder=prop_builder, scenario_name=self.name
)
self.mphys_add_subsystem("coupling", coupling_group)

self._mphys_add_post_coupling_subsystem_from_builder("aero", aero_builder, self.name)
self._mphys_add_post_coupling_subsystem_from_builder("prop", prop_builder, self.name)
self._mphys_add_post_coupling_subsystem_from_builder("aero", aero_builder, self.name)

if bc_coupling_builder is not None:
self._mphys_add_post_coupling_subsystem_from_builder("bc_coupling", bc_coupling_builder, self.name)

def _mphys_initialize_builders(self, aero_builder, prop_builder, geometry_builder):
aero_builder.initialize(self.comm)
prop_builder.initialize(self.comm)
if geometry_builder is not None:
geometry_builder.initialize(self.comm)

def _mphys_add_mesh_and_geometry_subsystems(self, aero_builder, prop_builder, geometry_builder):
def _mphys_add_mesh_and_geometry_subsystems(self, aero_builder, geometry_builder):

if geometry_builder is None:
self.mphys_add_subsystem("aero_mesh", aero_builder.get_mesh_coordinate_subsystem(self.name))
# self.mphys_add_subsystem("prop_mesh", prop_builder.get_mesh_coordinate_subsystem(self.name))
else:
self.add_subsystem("aero_mesh", aero_builder.get_mesh_coordinate_subsystem(self.name))
# the propulsion model does not need a mesh with pycycle
# self.add_subsystem("prop_mesh", prop_builder.get_mesh_coordinate_subsystem(self.name))
self.mphys_add_subsystem("geometry", geometry_builder.get_mesh_coordinate_subsystem(self.name))
self.connect("aero_mesh.x_aero0", "geometry.x_aero_in")
# the propulsion model does not need a mesh with pycycle
# self.connect("prop_mesh.x_prop0", "geometry.x_prop_in")

def mphys_make_aeroprop_conn(self, aero2prop_conn, prop2aero_conn):
# TODO automate this with mphys_result or mphys_coupling tags
Expand All @@ -85,13 +87,11 @@ class CouplingAeropropulsive(CouplingGroup):
def initialize(self):
self.options.declare("aero_builder", recordable=False)
self.options.declare("prop_builder", recordable=False)
self.options.declare("balance_builder", recordable=False, default=None)
self.options.declare("scenario_name", recordable=True, default=None)

def setup(self):
aero_builder = self.options["aero_builder"]
prop_builder = self.options["prop_builder"]
balance_builder = self.options["balance_builder"]
scenario_name = self.options["scenario_name"]

aero = aero_builder.get_coupling_group_subsystem(scenario_name)
Expand All @@ -100,9 +100,5 @@ def setup(self):
self.mphys_add_subsystem("aero", aero)
self.mphys_add_subsystem("prop", prop)

if balance_builder is not None:
balance = balance_builder.get_coupling_group_subsystem(scenario_name)
self.mphys_add_subsystem("balance", balance)

self.nonlinear_solver = om.NonlinearBlockGS(maxiter=25, iprint=2, atol=1e-8, rtol=1e-8)
self.linear_solver = om.LinearBlockGS(maxiter=25, iprint=2, atol=1e-8, rtol=1e-8)