diff --git a/docs/index.rst b/docs/index.rst index 64570468..3f2d702b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -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 diff --git a/docs/scenarios/aeropropulsive.rst b/docs/scenarios/aeropropulsive.rst new file mode 100644 index 00000000..24ae149d --- /dev/null +++ b/docs/scenarios/aeropropulsive.rst @@ -0,0 +1,28 @@ +%%%%%%%%%%%%%%%%%%%%%%% +Aeropropulsive Scenario +%%%%%%%%%%%%%%%%%%%%%%% + +The :class: `ScenarioAeropropulsive ` is for static coupled aerodynamic and propulsion problems. +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 \ No newline at end of file diff --git a/mphys/scenario_aeropropulsive.py b/mphys/scenario_aeropropulsive.py index 5e8fcb29..85158ec5 100644 --- a/mphys/scenario_aeropropulsive.py +++ b/mphys/scenario_aeropropulsive.py @@ -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): @@ -15,7 +16,10 @@ 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", @@ -23,29 +27,32 @@ def initialize(self): 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) @@ -53,19 +60,14 @@ def _mphys_initialize_builders(self, aero_builder, prop_builder, geometry_builde 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 @@ -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) @@ -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)