{ "cells": [ { "cell_type": "markdown", "id": "f17a116a", "metadata": {}, "source": [ "# Replacing a group with a component\n", "In this demonstration we show how we can replace a group of components with a single component by using the functionality implemented in the `standard_evaluator` library.\n", "\n", "\n", "\n", "We first load all required libraries and methods." ] }, { "cell_type": "code", "execution_count": 1, "id": "acef51ce-e90f-43a3-9716-ecb16167b371", "metadata": { "metadata": {} }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "matlabengine not available.\n" ] } ], "source": [ "import typing\n", "import openmdao.api as om\n", "import openmdao.core.system as oms\n", "\n", "from standard_evaluator import get_interface, show_structure, create_problem, get_state, set_state, load_state, save_state\n", "from standard_evaluator import load_assembly, save_assembly, convert_om_var, get_opt_problem, set_opt_problem\n", "from standard_evaluator import Variable, FloatVariable, IntVariable, ArrayVariable, OptProblem" ] }, { "cell_type": "markdown", "id": "763bdf4f-e824-456c-898f-1513dcff5e7c", "metadata": {}, "source": [ "## Creating the OpenMDAO assembly\n", "\n", "Next we generate an OpenMDAO assembly with wo sub-groups, one of which represents an aero analyses with two components. The first component is a stand-in for a geometry builder, and the second component is a stand-in for a Computational Fluid Dynamics (CFD) component. There is a link between those two components which can be thought of as a large, multi-dimensional grid. In this example we are just using a 1-D array, but this can be thought of as a large three dimensional grid.\n", "\n", "The idea is that the geometry builder takes as inputs a small number of geometry parameters (in this case all individual floats), and produces a large, even multi-dimensional output. The CFD component takes that output from the geometry builder and some parameters and performs calculations that together with a post-processing step (which we did not model) creates a small number of outputs (in this example we only use a single float output).\n", "\n", "After building the assembly we add optimization design variables, objectives, and constraints, run the assembly, and show the values of all inputs and outputs." ] }, { "cell_type": "code", "execution_count": 2, "id": "d9bdb3c0", "metadata": { "metadata": {} }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "14 Input(s) in 'model'\n", "\n", "varname val shape prom_name \n", "---------- ------------------ ----- -------------\n", "sub1\n", " z1\n", " a [1.] (1,) a \n", " b [1.] (1,) sub1.my_alias\n", " c [1.] (1,) sub1.z1.c \n", " d [1.] (1,) sub1.d \n", " z2\n", " a [1.] (1,) sub1.z2.a \n", " b [1.] (1,) sub1.z2.b \n", " c [4.] (1,) sub1.c \n", " d [1.] (1,) sub1.d \n", "aero\n", " geometry\n", " l [1.] (1,) aero.l \n", " q [1.] (1,) aero.q \n", " z [1.] (1,) aero.z \n", " cfd\n", " grid |8.94427191| (20,) aero.cfd.grid\n", " k [7.] (1,) aero.k \n", " r [1.] (1,) aero.r \n", "\n", "\n", "5 Explicit Output(s) in 'model'\n", "\n", "varname val shape prom_name \n", "---------- ------------------ -------- ------------------\n", "sub1\n", " z1\n", " y [4.] (1,) sub1.z1.y \n", " z2\n", " v [7.] (1,) sub1.v \n", "aero\n", " geometry\n", " bla |20.0| (20, 20) aero.geometry.bla \n", " grid |8.94427191| (20,) aero.geometry.grid\n", " cfd\n", " drag [0.047] (1,) aero.drag \n", "\n", "\n", "0 Implicit Output(s) in 'model'\n", "\n", "\n" ] } ], "source": [ "grid_size = 20\n", "\n", "class Sub1(om.Group):\n", " def setup(self):\n", " self.add_subsystem('z1', om.ExecComp(\"y = a + b + c + d\",\n", " ),\n", " promotes_inputs=[\n", " 'a',\n", " ('b', 'my_alias'),\n", " 'd',\n", " ])\n", "\n", " self.add_subsystem('z2', om.ExecComp(\"v = a + b + c + d\",\n", " ),\n", " promotes_inputs=['c', 'd'],\n", " promotes_outputs=['*'])\n", " self.connect('z1.y', 'c')\n", "\n", "class Aero(om.Group):\n", " def setup(self):\n", " self.add_subsystem('geometry', om.ExecComp([f\"grid = (q + z *l)*ones({grid_size})\", f\"bla = outer(ones({grid_size}), ones({grid_size}))\"], \n", " grid={'tags': 'internal', 'shape': (grid_size)},\n", " bla ={'tags': 'internal', 'shape': (grid_size, grid_size)}\n", " ),\n", " promotes_inputs=['q', 'z', 'l'])\n", " self.add_subsystem('cfd', om.ExecComp(f\"drag = (inner(grid, ones({grid_size})) + r * k)/1000\", \n", " grid={'tags': 'internal', 'shape_by_conn': True},\n", " drag={'units': 'N'}),\n", " promotes_inputs=['r', 'k'],\n", " promotes_outputs=['drag'])\n", " self.connect('geometry.grid', 'cfd.grid')\n", "\n", "\n", "class Intermediate3(om.Group):\n", " def setup(self):\n", " self.add_subsystem('sub1', Sub1(),\n", " promotes_inputs=['a'])\n", "\n", " self.add_subsystem('aero', Aero())\n", " self.connect('sub1.v', 'aero.k')\n", "\n", "prob = om.Problem(model=Intermediate3())\n", "\n", "# Define an optimization problem\n", "prob.model.add_design_var('a', lower=-50, upper=50, scaler= .1, adder=30.)\n", "prob.model.add_design_var('sub1.my_alias', lower=-50, upper=50)\n", "prob.model.add_objective('aero.drag')\n", "prob.model.add_constraint('sub1.v', lower=0, upper=10.)\n", "prob.model.add_constraint('sub1.z1.y', lower=-32.32, upper=1829.)\n", "\n", "prob.setup()\n", "prob.final_setup()\n", "\n", "prob.run_model()\n", "_ = prob.model.list_inputs(shape=True)\n", "_ = prob.model.list_outputs(shape=True)" ] }, { "cell_type": "markdown", "id": "079c55d7", "metadata": {}, "source": [ "Next we look at the N2 diagram of this assembly. Note that the grid output from the `geometry` component only goes to the `cfd` component, which means we can mark it as an internal variable.\n", "\n", "