MDO Structure
Extracted documentation from src/mdotoolbox/core/mdo.py.
Discipline
Attributes
name (str): Unique identifier for this discipline (e.g., "aerodynamics", "structures", "propulsion"). outputs (Function): Function that computes discipline outputs. Takes concatenated inputs [z_under_i, x_under_i, y_bar_coupled] and returns output array. constraints (List[Constraint], optional): Discipline-level constraints that must be satisfied. Defaults to empty list. shared_var_indices (np.ndarray, optional): Indices into the global shared variable vector (z_bar) that this discipline uses. Defaults to empty array. local_var_indices (np.ndarray, optional): Indices into the global local variable vector (x_bar) that this discipline owns. Defaults to empty array. coupling_output_indices (np.ndarray, optional): Indices into the global coupling variable vector (y_bar) that this discipline produces. Defaults to empty array. coupling_input_indices (List[np.ndarray], optional): List of index arrays, one per upstream discipline, specifying which coupling outputs from those disciplines are inputs to this discipline. Defaults to empty list.
Examples
Aerodynamics discipline
>>> def aero_analysis(mach, altitude, angle_of_attack, structural_deflection): ... # Compute lift and drag ... lift = ... ... drag = ... ... return np.array([lift, drag]) >>> >>> aero = Discipline( ... name="aerodynamics", ... outputs=Function( ... func=aero_analysis, ... x=['mach', 'altitude', 'aoa', 'deflection'] ... ), ... shared_var_indices=[0, 1], # mach, altitude ... local_var_indices=[2], # angle_of_attack ... coupling_output_indices=[0, 1], # lift, drag (outputs) ... coupling_input_indices=[[2]] # structural_deflection (input from structures) ... )
Notes
- Variable indices refer to positions in global vectors (z_bar, x_bar, y_bar)
- The outputs function receives: [z_under_i, x_under_i, y_bar_coupled]
- Coupling creates interdependencies between disciplines
evaluate
Examples
z_under = np.array([0.8, 10000.0]) # mach, altitude >>> x_under = np.array([5.0]) # angle of attack >>> y_bar_coupled = np.array([0.1]) # structural deflection >>> outputs = aero.evaluate(z_under, x_under, y_bar_coupled) >>> print(outputs) # [lift, drag] [15000.0, 1200.0]
Notes
- Internally builds input as [z_under_local, x_under_local, y_bar_coupled]
- The output function is called with unpacked inputs
evaluate_constraints
Examples
Discipline with stress constraint
>>> c_vals = structure.evaluate_constraints(z_under, x_under, y_bar_coupled) >>> print(c_vals) # [stress_margin] [0.15] # Positive means constraint is satisfied
Notes
- Returns empty array if self.constraints is empty
- Constraint functions receive same input format as outputs function
MDOProblem
Attributes
system_objective (Function): System-level objective function to minimize (or maximize if maximize=True). Takes all variables [z_bar, x_bar, y_bar]. disciplines (List[Discipline]): List of coupled discipline objects. Each discipline analyzes part of the system. n_shared (int): Number of shared design variables (z_bar) that affect multiple disciplines. n_local (List[int]): Number of local design variables (x_bar_i) for each discipline. Length must match len(disciplines). n_coupling (List[int]): Number of coupling variables (y_bar_i) output by each discipline. Length must match len(disciplines). shared_bounds (np.ndarray): Bounds for shared variables, shape (n_shared, 2) where each row is [lower_bound, upper_bound]. local_bounds (List[np.ndarray]): Bounds for local variables of each discipline. Each element has shape (n_local[i], 2). system_constraints (List[Constraint], optional): System-level constraints that involve variables from multiple disciplines. Defaults to empty list. maximize (bool, optional): If True, maximize the objective instead of minimizing. Defaults to False. tol (float, optional): Numerical tolerance for comparisons. Defaults to 1e-6. name (str, optional): Descriptive name for the problem. Defaults to "".
Examples
Two-discipline problem (e.g., aerodynamics + structures)
>>> problem = MDOProblem( ... system_objective=Function(func=total_weight, x=['z', 'x1', 'x2', 'y1', 'y2']), ... disciplines=[aero_discipline, structure_discipline], ... n_shared=2, # e.g., mach number, altitude ... n_local=[1, 2], # aero has 1 local, structure has 2 ... n_coupling=[2, 1], # aero outputs 2, structure outputs 1 ... shared_bounds=np.array([[0.5, 0.9], [0, 15000]]), ... local_bounds=[ ... np.array([[0, 10]]), # aero local bounds ... np.array([[0, 1], [0, 100]]) # structure local bounds ... ], ... system_constraints=[weight_constraint], ... name="aircraft_design" ... )
Notes
- Variable ordering: z_bar (shared), x_bar (concatenated local), y_bar (coupling)
- Disciplines are evaluated in sequence to resolve coupling
- System-level optimization coordinates discipline-level optimizations
Raises: TypeError: If inputs are not of the correct type. ValueError: If dimensions are inconsistent (e.g., len(n_local) != len(disciplines)).