### Install and Run Code Formatting Tools Source: https://github.com/openmdao/mphys/blob/main/README.md Install flake8, black, and isort, then run them to check code formatting compliance. A specific flake8 configuration for mdolab is downloaded and used. ```bash pip install flake8 black isort ``` ```bash wget https://raw.githubusercontent.com/mdolab/.github/main/.flake8 -O .flake8_mdolab # download flake8 configuration for mdolab ``` ```bash python -m flake8 . --append-config .flake8_mdolab --count --show-source --statistics ``` ```bash python -m black . --check --diff ``` ```bash python -m isort . --check-only --diff ``` -------------------------------- ### Install MPhys (Developer Mode) Source: https://github.com/openmdao/mphys/blob/main/README.md For developers, clone the repository and install MPhys in editable mode for active development. ```bash pip install -e . ``` -------------------------------- ### Install MPhys (Latest Release) Source: https://github.com/openmdao/mphys/blob/main/README.md Use this command to install the latest stable version of MPhys from PyPI. ```bash pip install mphys ``` -------------------------------- ### Setup Single-Discipline Aerodynamic Scenario Source: https://context7.com/openmdao/mphys/llms.txt Assembles aerodynamic subsystems for a single analysis. Requires an aerodynamic builder and optionally a geometry builder. ```python from mphys.scenarios.aerodynamic import ScenarioAerodynamic from mphys import Multipoint import openmdao.api as om class AeroModel(Multipoint): def setup(self): aero_builder = MyAeroBuilder({"mesh_file": "wing.cgns"}) aero_builder.initialize(self.comm) geo_builder = MyGeoBuilder({"ffd_file": "ffd.xyz"}) # optional geo_builder.initialize(self.comm) self.add_subsystem("ivc", om.IndepVarComp(), promotes=["*"]) self.ivc.add_output("angle_of_attack", val=2.0, units="deg") self.ivc.add_output("mach_number", val=0.8) self.mphys_add_scenario( "cruise", ScenarioAerodynamic( aero_builder=aero_builder, geometry_builder=geo_builder, # optional geometry parameterization run_directory="./cruise", ), ) self.connect("angle_of_attack", "cruise.angle_of_attack") self.connect("mach_number", "cruise.mach_number") prob = om.Problem() prob.model = AeroModel() prob.setup(mode="rev") prob.run_model() print(prob["cruise.C_L"]) prob.compute_totals(of=["cruise.C_L", "cruise.C_D"], wrt=["angle_of_attack"]) ``` -------------------------------- ### Setup Single-Discipline Structural Scenario Source: https://context7.com/openmdao/mphys/llms.txt Assembles a structural analysis scenario where the structural solver computes its own loads. Requires a structural builder. ```python from mphys.scenarios.structural import ScenarioStructural from mphys import Multipoint import openmdao.api as om import numpy as np class StructuralModel(Multipoint): def setup(self): struct_builder = MyStructBuilder({"bdf": "wingbox.bdf"}) struct_builder.initialize(self.comm) self.add_subsystem("ivc", om.IndepVarComp(), promotes=["*"]) self.ivc.add_output("dv_struct", val=0.003 * np.ones(50)) self.mphys_add_scenario( "load_case_1", ScenarioStructural(struct_builder=struct_builder), ) self.connect("dv_struct", "load_case_1.dv_struct") prob = om.Problem() prob.model = StructuralModel() prob.setup(mode="rev") prob.run_model() print(prob["load_case_1.func_struct"]) ``` -------------------------------- ### Setup Coupled Aerostructural Scenario Source: https://context7.com/openmdao/mphys/llms.txt Performs full aerostructural coupling, iterating between aerodynamic and structural solves. Requires aero, structural, and load transfer builders. ```python from mphys.scenarios.aerostructural import ScenarioAeroStructural from mphys import Multipoint, MPhysVariables import openmdao.api as om import numpy as np class AerostructuralModel(Multipoint): def setup(self): N_struct = 20 aero_builder = MyAeroBuilder({"mesh": "wing.cgns"}) struct_builder = MyStructBuilder({"bdf": "wingbox.bdf", "n_el": N_struct}) xfer_builder = MyXferBuilder(aero_builder=aero_builder, struct_builder=struct_builder) for b in [aero_builder, struct_builder, xfer_builder]: b.initialize(self.comm) self.add_subsystem("ivc", om.IndepVarComp(), promotes=["*"]) self.ivc.add_output("angle_of_attack", val=3.0, units="deg") self.ivc.add_output("dv_struct", val=0.001 * np.ones(N_struct)) self.mphys_add_scenario( "cruise", ScenarioAeroStructural( aero_builder=aero_builder, struct_builder=struct_builder, ldxfer_builder=xfer_builder, coupling_group_type="full_coupling", # or "aerodynamics_only" pre_coupling_order=["aero", "struct", "ldxfer"], post_coupling_order=["ldxfer", "aero", "struct"], ), coupling_nonlinear_solver=om.NonlinearBlockGS( maxiter=100, use_aitken=True, aitken_initial_factor=0.5 ), coupling_linear_solver=om.LinearBlockGS(maxiter=40, use_aitken=True), ) self.connect("angle_of_attack", "cruise.angle_of_attack") self.connect("dv_struct", "cruise.dv_struct") prob = om.Problem() prob.model = AerostructuralModel() prob.setup(mode="rev") prob.run_model() print(prob["cruise.mass"]) print(prob["cruise.C_L"]) prob.check_totals( of=["cruise.mass", "cruise.C_L"], wrt=["angle_of_attack", "dv_struct"], compact_print=True, ) ``` -------------------------------- ### Define MPhys Model with Scenarios Source: https://github.com/openmdao/mphys/blob/main/docs/basics/model_assembly.rst This snippet demonstrates the setup of a custom MPhys model using the Multipoint class. It includes adding independent variables, initializing an AeroBuilder, adding a mesh coordinate subsystem, creating an Aerodynamic scenario, and connecting inputs. ```python import openmdao.api as om from mphys import Multipoint, MPhysVariables from mphys.scenarios import ScenarioAerodynamic from my_aero_code import AeroBuilder # Step 1 class MyMPhysModel(Multipoint): def setup(self): dvs = self.add_subsystem('dvs', om.IndepVarComp()) dvs.add_output('aoa', val=0.0, units='deg') # Step 2 aero_builder = AeroBuilder(mesh="naca0012.ugrid") # Step 3 aero_builder.initialize(self.comm) # Step 4 self.add_subsystem("aero_mesh", aero_builder.get_mesh_coordinate_subsystem()) # Step 5 scenario = ScenarioAerodynamic(aero_builder=aero_builder) # Step 6 self.mphys_add_scenario("cruise", scenario) # Step 7 self.connect("dvs.aoa", "cruise.aoa") self.connect(MPhysVariables.Aerodynamics.Mesh.COORDINATES, MPhysVariables.Aerodynamics.Surface.COORDINATES) ``` -------------------------------- ### Run MPhys Integration Tests Source: https://github.com/openmdao/mphys/blob/main/README.md Execute integration tests for MPhys using the testflo framework. Ensure all required Python packages and input files are installed and available. ```bash testflo -v tests ``` -------------------------------- ### MPhysZeroMQServer Source: https://github.com/openmdao/mphys/blob/main/docs/basics/remote_components.rst A specialized Server for MPhys that utilizes ZeroMQ for communication. ```APIDOC ## Class: MPhysZeroMQServer ### Description This class extends the base `Server` class to provide MPhys-specific functionality for ZeroMQ-based servers. It handles the execution of MPhys models and components on the server side. ### Methods - **__init__(self, **kwargs)**: Initializes the MPhys ZeroMQ server. ``` -------------------------------- ### Configure AeroThermal Scenario in MPhys Source: https://context7.com/openmdao/mphys/llms.txt Sets up a conjugate heat transfer scenario by coupling aerodynamics and thermal solvers. Requires initialization of builders before adding the scenario. ```python from mphys.scenarios.aerothermal import ScenarioAeroThermal from mphys import Multipoint import openmdao.api as om class AeroThermalModel(Multipoint): def setup(self): aero_builder = MyAeroBuilder() thermal_builder = MyThermalBuilder() thermalxfer_builder = MyThermalXferBuilder( aero_builder=aero_builder, thermal_builder=thermal_builder ) for b in [aero_builder, thermal_builder, thermalxfer_builder]: b.initialize(self.comm) self.mphys_add_scenario( "hot_section", ScenarioAeroThermal( aero_builder=aero_builder, thermal_builder=thermal_builder, thermalxfer_builder=thermalxfer_builder, ), ) prob = om.Problem() prob.model = AeroThermalModel() prob.setup(mode="rev") prob.run_model() ``` -------------------------------- ### Connect MPhys Variables Source: https://context7.com/openmdao/mphys/llms.txt Demonstrates connecting MPhys variables within OpenMDAO. ```python self.connect( MPhysVariables.Aerodynamics.Surface.Mesh.COORDINATES, MPhysVariables.Aerodynamics.Surface.COORDINATES_INITIAL, ) ``` -------------------------------- ### MPhysZeroMQServerManager Source: https://github.com/openmdao/mphys/blob/main/docs/basics/remote_components.rst A specialized ServerManager for MPhys that uses ZeroMQ for communication. ```APIDOC ## Class: MPhysZeroMQServerManager ### Description This class extends `ServerManager` and is specifically designed for MPhys applications using ZeroMQ for inter-process communication. It integrates with the MPhys workflow for managing remote servers. ### Methods - **__init__(self, **kwargs)**: Initializes the MPhys ZeroMQ server manager. ``` -------------------------------- ### Implement a Custom Aerodynamics Builder in MPhys Source: https://context7.com/openmdao/mphys/llms.txt Subclasses of Builder define solver-specific OpenMDAO subsystems. Implement factory methods to provide components for mesh coordinates, coupling groups, and pre/post-coupling phases. Ensure the solver is initialized with the correct MPI communicator. ```python from mphys.core import Builder import openmdao.api as om class MyAeroBuilder(Builder): def __init__(self, options): self.options = options def initialize(self, comm): # Initialize the solver with the MPI communicator self.solver = MyAeroSolver(options=self.options, comm=comm) def get_mesh_coordinate_subsystem(self, scenario_name=None): # Returns an OM component that outputs mesh coordinates return MyAeroMesh(solver=self.solver) def get_coupling_group_subsystem(self, scenario_name=None): # Returns the OM group that performs the actual aerodynamic solve return MyAeroCouplingGroup(solver=self.solver) def get_pre_coupling_subsystem(self, scenario_name=None): # Optional: return a group executed before the coupling loop return MyAeroPreCoupling(solver=self.solver) def get_post_coupling_subsystem(self, scenario_name=None): # Optional: return a group executed after the coupling loop return MyAeroPostCoupling(solver=self.solver) def get_number_of_nodes(self): return self.solver.n_nodes def get_ndof(self): return 3 # x, y, z displacements per node def get_tagged_indices(self, tags): return self.solver.get_surface_ids(tags) ``` -------------------------------- ### Scenario for Analysis Points Source: https://context7.com/openmdao/mphys/llms.txt Base class for multiphysics analysis points, managing ordered execution of subsystems. Use mphys_add_post_subsystem() to add user-defined components after builder subsystems. ```python from mphys.core import Scenario import openmdao.api as om class MyCustomScenario(Scenario): def initialize(self): super().initialize() self.options.declare("my_builder", recordable=False) def _mphys_scenario_setup(self): builder = self.options["my_builder"] self._mphys_add_pre_coupling_subsystem_from_builder("discipline", builder, self.name) self.mphys_add_subsystem("coupling", builder.get_coupling_group_subsystem(self.name)) self._mphys_add_post_coupling_subsystem_from_builder("discipline", builder, self.name) # Add user-defined post-processing after builder subsystems scenario = MyCustomScenario(my_builder=my_builder, run_directory="./run_pt1") scenario.mphys_add_post_subsystem( "obj_func", MyObjectiveComponent(), promotes_inputs=["C_L", "mass"], promotes_outputs=["objective"], ) ``` -------------------------------- ### HPC Remote Component Evaluation with ZeroMQ Source: https://context7.com/openmdao/mphys/llms.txt Enable local OpenMDAO optimization drivers to offload physics evaluations to separate HPC jobs using ZeroMQ. The client manages PBS jobs, while the server runs the MPhys problem on HPC nodes. ```python # --- CLIENT SIDE (top-level optimizer script) --- from mphys.network.zmq_pbs import RemoteZeroMQComp from pbs4py import PBS import openmdao.api as om pbs = PBS.k4(time="2:00:00", ncpus_per_node=40) prob = om.Problem() prob.model.add_subsystem( "aero", RemoteZeroMQComp( run_server_filename="mphys_server.py", pbs=pbs, port=5081, time_estimate_multiplier=2.0, dump_json=True, ), promotes=["*"], ) prob.driver = om.ScipyOptimizeDriver(optimizer="SLSQP") prob.setup() prob.run_driver() prob.model.aero.stop_server() ``` ```python # --- SERVER SIDE (mphys_server.py, runs on HPC compute nodes) --- from mphys.network.zmq_pbs import MPhysZeroMQServer, get_default_zmq_pbs_argparser from my_model import get_model # returns an om.Group parser = get_default_zmq_pbs_argparser() args = parser.parse_args() server = MPhysZeroMQServer( port=args.port, get_om_group_function_pointer=get_model, ignore_setup_warnings=False, rerun_initial_design=True, # warm-start with baseline before accepting connections write_n2=True, ) server.run() ``` -------------------------------- ### Server Source: https://github.com/openmdao/mphys/blob/main/docs/basics/remote_components.rst The core server class that listens for and processes requests from remote components. ```APIDOC ## Class: Server ### Description This is the main server class that runs on the remote machine. It listens for incoming connections from `RemoteZeroMQComp` instances, processes their requests, and sends back results. ### Methods - **__init__(self, **kwargs)**: Initializes the server. ``` -------------------------------- ### MPhysGroup Methods Source: https://github.com/openmdao/mphys/blob/main/docs/developers/mphys_group.rst This section details the key methods of the MPhysGroup class that users can interact with. ```APIDOC ## MPhysGroup ### Description The MPhysGroup is the base class for implementing mechanics of promoting MPhys variables by tags. Subsystems with tagged variables to be promoted are added using `mphys_add_subsystem`. ### Methods #### `mphys_add_subsystem(subsystem)` Adds a subsystem to the MPhysGroup. This method is specifically designed for subsystems whose variables will be promoted by tags. #### `configure()` Configures the MPhysGroup. If using `configure` in a CouplingGroup or Scenario group, ensure to call the parent's configure with `super().configure()`. ``` -------------------------------- ### Multipoint for Sequential Scenarios Source: https://context7.com/openmdao/mphys/llms.txt Collects multiple analysis scenarios for sequential evaluation. Use mphys_add_scenario() to register each scenario and optionally specify custom coupling solvers. ```python import openmdao.api as om from mphys import Multipoint, MultipointParallel from mphys.scenarios.aerodynamic import ScenarioAerodynamic class MyModel(Multipoint): def setup(self): aero_builder = MyAeroBuilder(options) aero_builder.initialize(self.comm) # Sequential evaluation: two flight points self.mphys_add_scenario( "cruise", ScenarioAerodynamic(aero_builder=aero_builder), coupling_nonlinear_solver=om.NewtonSolver(solve_subsystems=True), coupling_linear_solver=om.LinearBlockGS(maxiter=20), ) self.mphys_add_scenario( "maneuver", ScenarioAerodynamic(aero_builder=aero_builder), ) ``` -------------------------------- ### ServerManager Source: https://github.com/openmdao/mphys/blob/main/docs/basics/remote_components.rst Manages the lifecycle of the server process for remote components. ```APIDOC ## Class: ServerManager ### Description This class is responsible for managing the server-side process that executes remote components. It handles the setup and teardown of the server environment. ### Methods - **__init__(self, **kwargs)**: Initializes the server manager. ``` -------------------------------- ### Builder Class Source: https://github.com/openmdao/mphys/blob/main/docs/basics/builders.rst The `Builder` class serves as the base for integrating custom code into MPhys. Developers should subclass this class and implement the necessary methods for their specific integration needs. ```APIDOC ## Class: Builder ### Description Base class for MPhys builders. Developers wishing to integrate their code to MPhys should subclass the builder and implement the methods relevant to their code. ### Methods Developers should implement methods relevant to their specific integration. Not all methods need to be implemented by every builder. For example, a transfer scheme builder may not need a precoupling post coupling subsystem in the scenario. ``` -------------------------------- ### Time-Domain Integration with Integrator Source: https://context7.com/openmdao/mphys/llms.txt Use the Integrator base class for unsteady time-domain simulations. Subclass it and implement `_get_timestep_group()` and `_get_builder_list()` to define per-step physics. ```python from mphys.time_domain.integrator import Integrator from mphys.time_domain.time_domain_builder import TimeDomainBuilder import openmdao.api as om class MyIntegrator(Integrator): def initialize(self): super().initialize() self.options.declare("struct_builder") self.options.declare("aero_builder") def _get_builder_list(self): return [self.options["struct_builder"], self.options["aero_builder"]] def _get_timestep_group(self): from mphys.time_domain.timestep_aerostructural import TimestepAeroStructural return TimestepAeroStructural( aero_builder=self.options["aero_builder"], struct_builder=self.options["struct_builder"], ) prob = om.Problem() prob.model.add_subsystem( "integrator", MyIntegrator( nsteps=100, dt=0.01, struct_builder=struct_builder, aero_builder=aero_builder, ), ) prob.setup() prob.run_model() ``` -------------------------------- ### RemoteZeroMQComp Source: https://github.com/openmdao/mphys/blob/main/docs/basics/remote_components.rst Represents a remote component that communicates over ZeroMQ. It allows for running components on a separate server, potentially on an HPC environment. ```APIDOC ## Class: RemoteZeroMQComp ### Description This class provides the interface for a remote component that communicates via ZeroMQ. It enables the execution of OpenMDAO components on a remote server. ### Methods - **__init__(self, **kwargs)**: Initializes the remote component. - **stop_server()**: Stops the remote server process and associated SSH port forwarding. - **dump_json**: If set to True, writes input and output JSON files for each design evaluation. - **dump_separate_json**: If set to True, writes separate JSON files for each design evaluation. ``` -------------------------------- ### MPhysGroup for Auto-Promotion Source: https://context7.com/openmdao/mphys/llms.txt Extends OpenMDAO's Group for automatic promotion of MPhys-tagged variables. Use mphys_add_subsystem() to register components for this feature. ```python from mphys.core import MPhysGroup import openmdao.api as om class MyCustomGroup(MPhysGroup): def setup(self): # mphys_add_subsystem registers the component for automatic variable promotion self.mphys_add_subsystem("solver_a", MySolverA()) self.mphys_add_subsystem("solver_b", MySolverB()) # Variables tagged mphys_coupling, mphys_input, mphys_coordinates, # mphys_result are automatically promoted at configure() time # In components, tag variables to participate in auto-promotion: class MySolverA(om.ExplicitComponent): def setup(self): self.add_input("x_aero", shape_by_conn=True, distributed=True, tags=["mphys_coordinates"]) self.add_output("f_aero", shape_by_conn=True, distributed=True, tags=["mphys_coupling"]) self.add_output("C_L", tags=["mphys_result"]) ``` -------------------------------- ### Integrate Surface Forces with OpenMDAO Source: https://context7.com/openmdao/mphys/llms.txt An OpenMDAO component to calculate total aerodynamic forces and moments from distributed surface loads. Supports forward and reverse adjoints. ```python from mphys.integrated_forces import IntegratedSurfaceForces from mphys import MPhysVariables import openmdao.api as om import numpy as np nnodes = 500 prob = om.Problem() ivc = om.IndepVarComp() ivc.add_output(MPhysVariables.Aerodynamics.FlowConditions.ANGLE_OF_ATTACK, val=2.0, units="deg") ivc.add_output(MPhysVariables.Aerodynamics.FlowConditions.YAW_ANGLE, val=0.0, units="deg") ivc.add_output(MPhysVariables.Aerodynamics.FlowConditions.DYNAMIC_PRESSURE, val=6125.0) ivc.add_output(MPhysVariables.Aerodynamics.ReferenceGeometry.REF_AREA, val=45.5) ivc.add_output(MPhysVariables.Aerodynamics.ReferenceGeometry.MOMENT_CENTER, shape=3, val=[10.0, 0.0, 0.0]) ivc.add_output(MPhysVariables.Aerodynamics.ReferenceGeometry.REF_LENGTH_X, val=3.5) ivc.add_output(MPhysVariables.Aerodynamics.ReferenceGeometry.REF_LENGTH_Y, val=13.0) ivc.add_output(MPhysVariables.Aerodynamics.Surface.COORDINATES, shape=3*nnodes, distributed=True) ivc.add_output(MPhysVariables.Aerodynamics.Surface.LOADS, shape=3*nnodes, distributed=True) prob.model.add_subsystem("ivc", ivc, promotes_outputs=["*"]) prob.model.add_subsystem("forces", IntegratedSurfaceForces(), promotes_inputs=["*"]) prob.setup(force_alloc_complex=True) prob.run_model() print("C_L =", prob["forces.C_L"]) print("C_D =", prob["forces.C_D"]) print("Lift =", prob["forces.Lift"]) print("CM_Y =", prob["forces.CM_Y"]) prob.check_partials(compact_print=True, method="cs") ``` -------------------------------- ### Builder Base Class Source: https://context7.com/openmdao/mphys/llms.txt The Builder base class defines the interface for physics solver integration with MPhys. Subclasses implement factory methods to provide OpenMDAO components for different phases of the simulation. ```APIDOC ## Builder ### Description The `Builder` base class defines the interface that every physics solver must implement to integrate with MPhys. Subclasses provide solver-specific OpenMDAO subsystems through factory methods; `Scenario` classes call these methods during `setup()` to assemble the full model. ### Methods - `initialize(comm)`: Initializes the solver with the MPI communicator. - `get_mesh_coordinate_subsystem(scenario_name=None)`: Returns an OpenMDAO component that outputs mesh coordinates. - `get_coupling_group_subsystem(scenario_name=None)`: Returns the OpenMDAO group that performs the actual solve. - `get_pre_coupling_subsystem(scenario_name=None)`: Optional: Returns a group executed before the coupling loop. - `get_post_coupling_subsystem(scenario_name=None)`: Optional: Returns a group executed after the coupling loop. - `get_number_of_nodes()`: Returns the number of nodes for the solver. - `get_ndof()`: Returns the number of degrees of freedom per node. - `get_tagged_indices(tags)`: Returns indices associated with given tags. ``` -------------------------------- ### MultipointParallel for Parallel Scenarios Source: https://context7.com/openmdao/mphys/llms.txt Manages multiple analysis scenarios for parallel evaluation across MPI processes. Use mphys_add_scenario() to register scenarios; in_MultipointParallel=True triggers builder initialization within each scenario. ```python # For parallel evaluation across MPI processes: class MyParallelModel(MultipointParallel): def setup(self): aero_builder = MyAeroBuilder(options) # in_MultipointParallel=True triggers builder initialization inside each scenario for name in ["cruise", "maneuver", "climb"]: self.mphys_add_scenario( name, ScenarioAerodynamic( aero_builder=aero_builder, in_MultipointParallel=True, ), ) prob = om.Problem() prob.model = MyParallelModel() prob.setup(mode="rev") prob.run_model() ``` -------------------------------- ### Access MPhys Variables in Python Source: https://github.com/openmdao/mphys/blob/main/docs/basics/naming_conventions.rst Demonstrates how to import and access MPhys variable names from the MPhysVariables class. These variables are used when defining inputs and outputs for OpenMDAO components. ```python import openmdao.api as om from mphys import MPhysVariables X_AERO0 = MPhysVariables.Aerodynamics.Surface.COORDINATES_INITIAL U_AERO = MPhysVariables.Aerodynamics.Surface.DISPLACEMENTS F_AERO = MPhysVariables.Aerodynamics.Surface.LOADS class AeroSolver(om.ImplicitComponent): def setup(self): self.add_input(X_AERO0, shape=5, distributed=True, tags=['mphys_coordinates']) self.add_input(U_AERO0, shape=5, distributed=True, tags=['mphys_coupling']) self.add_output(F_AERO0, shape=3, distributed=True, tags=['mphys_coupling']) ``` -------------------------------- ### Configure Aeropropulsive Scenario in MPhys Source: https://context7.com/openmdao/mphys/llms.txt Couples aerodynamic and propulsion cycle models for aeropropulsive simulations. Defines cross-discipline connections for data transfer between solvers. ```python from mphys.scenarios.aeropropulsive import ScenarioAeropropulsive from mphys import Multipoint import openmdao.api as om class AeropropulsiveModel(Multipoint): def setup(self): aero_builder = MyAeroBuilder() prop_builder = MyPropBuilder() for b in [aero_builder, prop_builder]: b.initialize(self.comm) scenario = ScenarioAeropropulsive( aero_builder=aero_builder, prop_builder=prop_builder, ) self.mphys_add_scenario("cruise", scenario) # Define cross-discipline connections (aero outputs → prop inputs, vice versa) aero2prop = {"mach": "flight_mach", "altitude": "alt"} prop2aero = {"net_thrust": "thrust_bc"} self.cruise.mphys_make_aeroprop_conn(aero2prop, prop2aero) ``` -------------------------------- ### Distributed Vector Summation with DistributedSummer Source: https://context7.com/openmdao/mphys/llms.txt Use DistributedSummer to sum multiple distributed vectors element-wise. It ensures correct adjoint derivatives for coupled analyses. ```python from mphys.core.distributed_summer import DistributedSummer from mphys.core.distributed_converter import DistributedVariableDescription import openmdao.api as om summer = DistributedSummer( inputs=[ DistributedVariableDescription("f_aero_wing", shape=(900,), tags=["mphys_coupling"]), DistributedVariableDescription("f_aero_tail", shape=(900,), tags=["mphys_coupling"]), ], output=DistributedVariableDescription("f_aero_total", shape=(900,), tags=["mphys_coupling"]), ) prob = om.Problem() prob.model.add_subsystem("summer", summer, promotes=["*"]) prob.setup() prob.run_model() ``` -------------------------------- ### MPhysVariables Source: https://context7.com/openmdao/mphys/llms.txt MPhysVariables provides a nested class hierarchy for standardized canonical string names for all inter-disciplinary coupling variables, ensuring correct variable connections between solvers. ```APIDOC ## MPhysVariables ### Description `MPhysVariables` is a nested class hierarchy that provides canonical string names for all inter-disciplinary coupling variables. Using these constants instead of hard-coded strings guarantees correct variable connections between solvers. ### Examples #### Aerodynamic Surface Variables - `MPhysVariables.Aerodynamics.Surface.COORDINATES` - `MPhysVariables.Aerodynamics.Surface.COORDINATES_INITIAL` - `MPhysVariables.Aerodynamics.Surface.LOADS` - `MPhysVariables.Aerodynamics.Surface.DISPLACEMENTS` - `MPhysVariables.Aerodynamics.Surface.Mesh.COORDINATES` - `MPhysVariables.Aerodynamics.Surface.Geometry.COORDINATES_INPUT` - `MPhysVariables.Aerodynamics.Surface.Geometry.COORDINATES_OUTPUT` #### Flow Condition Variables - `MPhysVariables.Aerodynamics.FlowConditions.ANGLE_OF_ATTACK` - `MPhysVariables.Aerodynamics.FlowConditions.MACH_NUMBER` - `MPhysVariables.Aerodynamics.FlowConditions.DYNAMIC_PRESSURE` #### Reference Geometry - `MPhysVariables.Aerodynamics.ReferenceGeometry.REF_AREA` #### Structural Variables - `MPhysVariables.Structures.DISPLACEMENTS` - `MPhysVariables.Structures.COORDINATES` - `MPhysVariables.Structures.Loads.AERODYNAMIC` #### Thermal Variables - `MPhysVariables.Thermal.TEMPERATURE` - `MPhysVariables.Thermal.COORDINATES` - `MPhysVariables.Thermal.HeatFlow.AERODYNAMIC` ``` -------------------------------- ### Access Standardized MPhys Variable Names Source: https://context7.com/openmdao/mphys/llms.txt Use MPhysVariables constants for inter-disciplinary coupling variables to ensure consistency. This avoids hard-coded strings and guarantees correct connections between solvers. ```python from mphys.core import MPhysVariables # Aerodynamic surface variables print(MPhysVariables.Aerodynamics.Surface.COORDINATES) # "x_aero" print(MPhysVariables.Aerodynamics.Surface.COORDINATES_INITIAL) # "x_aero0" print(MPhysVariables.Aerodynamics.Surface.LOADS) # "f_aero" print(MPhysVariables.Aerodynamics.Surface.DISPLACEMENTS) # "u_aero" print(MPhysVariables.Aerodynamics.Surface.Mesh.COORDINATES) # "x_aero0_mesh" print(MPhysVariables.Aerodynamics.Surface.Geometry.COORDINATES_INPUT) # "x_aero0_geometry_input" print(MPhysVariables.Aerodynamics.Surface.Geometry.COORDINATES_OUTPUT) # "x_aero0_geometry_output" # Flow condition variables print(MPhysVariables.Aerodynamics.FlowConditions.ANGLE_OF_ATTACK) # "angle_of_attack" print(MPhysVariables.Aerodynamics.FlowConditions.MACH_NUMBER) # "mach_number" print(MPhysVariables.Aerodynamics.FlowConditions.DYNAMIC_PRESSURE) # "dynamic_pressure" # Reference geometry for force nondimensionalization print(MPhysVariables.Aerodynamics.ReferenceGeometry.REF_AREA) # "ref_area" # Structural variables print(MPhysVariables.Structures.DISPLACEMENTS) # "u_struct" print(MPhysVariables.Structures.COORDINATES) # "x_struct0" print(MPhysVariables.Structures.Loads.AERODYNAMIC) # "f_aero_struct" # Thermal variables print(MPhysVariables.Thermal.TEMPERATURE) # "T_thermal" print(MPhysVariables.Thermal.COORDINATES) # "x_thermal0" print(MPhysVariables.Thermal.HeatFlow.AERODYNAMIC) # "q_aero_thermal" ``` -------------------------------- ### Convert Distributed to Serial Variables in MPhys Source: https://context7.com/openmdao/mphys/llms.txt Converts between distributed MPI variables and serial (replicated) variables. Useful for connecting non-parallel solvers to MPhys coupling variables. ```python from mphys.core import DistributedConverter, DistributedVariableDescription import openmdao.api as om # Convert distributed input → serial output, and serial input → distributed output converter = DistributedConverter( distributed_inputs=[ DistributedVariableDescription( name="f_aero_struct", shape=(300,), tags=["mphys_coupling"], ) ], distributed_outputs=[ DistributedVariableDescription( name="u_struct", shape=(300,), tags=["mphys_coupling"], ) ], ) prob = om.Problem() prob.model.add_subsystem("converter", converter) prob.setup() # Now connect "f_aero_struct_serial" to a serial structural solver ``` -------------------------------- ### MPhys BibTeX Citation Source: https://github.com/openmdao/mphys/blob/main/docs/references/citing_mphys.rst Use this BibTeX entry to cite the MPhys library in your academic work. Ensure it is correctly formatted within your bibliography. ```text @article{mphys_2025, author = {Yildirim, Anil and Jacobson, Kevin E. and Anibal, Joshua L. and Stanford, Bret K. and Gray, Justin S. and Mader, Charles A. and Martins, Joaquim R. R. A. and Kennedy, Graeme J.}, date = {2025/01/08}, doi = {10.1007/s00158-024-03900-0}, isbn = {1615-1488}, journal = {Structural and Multidisciplinary Optimization}, number = {1}, pages = {15}, title = {{MPhys}: a Modular Multiphysics Library for Coupled Simulation and Adjoint Derivative Computation}, url = {https://doi.org/10.1007/s00158-024-03900-0}, volume = {68}, year = {2025} } ``` -------------------------------- ### MultipointParallel Class Members Source: https://github.com/openmdao/mphys/blob/main/docs/basics/model_hierarchy.rst The MultipointParallel class provides functionality for managing multipoint analyses in parallel. The following members are available for direct use by the user, excluding the 'configure' method which is for internal use. ```APIDOC ## MultipointParallel This class is designed to handle multipoint analyses in a parallel computing environment within the mPhys framework. ### Methods - **__init__(self, **kwargs)**: Initializes the MultipointParallel object. - **add_subsystem(self, name, subsys, promotes=None)**: Adds a subsystem to the model. - **compute(self, inputs, outputs, **kwargs)**: Computes the model's outputs from its inputs. - **compute_jacvec_product(self, inputs, outputs, jacvec_ందో)**: Computes the Jacobian-vector product. - **declare_input(self, name, val=None, units=None, desc='')**: Declares an input variable. - **declare_output(self, name, val=None, units=None, desc='')**: Declares an output variable. - **get_io_metadata(self, name)**: Retrieves metadata for a given input or output. - **list_inputs(self, iotype='all', out_stream=None)**: Lists all input variables. - **list_outputs(self, iotype='all', out_stream=None)**: Lists all output variables. - **load(self, filename, reload_if_needed=False)**: Loads model data from a file. - **msg_push(self, msg_type, data)**: Pushes a message to the message queue. - **options_apply(self, options)**: Applies a dictionary of options to the model. - **options_get(self, name)**: Gets the value of a specific option. - **options_set(self, name, value)**: Sets the value of a specific option. - **record_desvars(self, record_options=None)**: Records design variables. - **record_responses(self, record_options=None)**: Records responses. - **save(self, filename, format='auto', overwrite=False)**: Saves model data to a file. - **set_input_defaults(self, **kwargs)**: Sets default values for input variables. - **setup(self)**: Sets up the model structure. - **solve_nonlinear(self, **kwargs)**: Solves the nonlinear system. - **solve_linear(self, **kwargs)**: Solves the linear system. - **update(self)**: Updates the model state. ### Attributes - **comm**: The communicator associated with this component. - **name**: The name of the component. - **parent**: The parent component of this component. - **pathname**: The full pathname of the component. - **prom_names**: List of promoted variable names. - **ref**: Reference value for scaling. - **ref0**: Reference value for scaling. - **supports**: Indicates whether the component supports certain features. - **units**: Units of the component's primary variable. Note: The `configure` method is excluded as it is intended for internal use. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.