{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "remove-input",
     "active-ipynb",
     "remove-output"
    ]
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    from openmdao.utils.notebook_utils import notebook_mode\n",
    "except ImportError:\n",
    "    !python -m pip install openmdao[notebooks]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# How OpenMDAO Represents Variables\n",
    "\n",
    "In general, a numerical model can be complex, multidisciplinary, and heterogeneous.\n",
    "It can be decomposed into a series of smaller computations that are chained together by passing variables from one to the next.\n",
    "\n",
    "In OpenMDAO, we perform all these numerical calculations inside a [Component](../../features/core_features/working_with_components/main), which represents the smallest unit of computational work the framework understands. Each component will output its own set of variables. Depending on which type of calculation you're trying to represent, OpenMDAO provides different kinds of components for you to work with.\n",
    "\n",
    "## A Simple Numerical Model\n",
    "\n",
    "In order to understand the different kinds of components in OpenMDAO,\n",
    "let us consider the following numerical model that takes `x` as an input:\n",
    "\n",
    "$$\n",
    "  \\begin{array}{l l}\n",
    "    y \\quad \\text{is computed by solving:} &\n",
    "    \\cos(x \\cdot y) - z \\cdot y = 0  \\\\\n",
    "    z \\quad \\text{is computed by evaluating:} &\n",
    "    z = \\sin(y) .\n",
    "  \\end{array}\n",
    "$$\n",
    "\n",
    "## The Three Types of Components\n",
    "\n",
    "In our numerical model, we have three variables: `x`, `y`, and `z`. Each of these variables needs to be defined as the output of a component. There are three basic types of components in OpenMDAO:\n",
    "\n",
    "\n",
    "1. [IndepVarComp](../../features/core_features/working_with_components/indepvarcomp) : defines independent variables (e.g., x)\n",
    "2. [ExplicitComponent](../../features/core_features/working_with_components/explicit_component) : defines dependent variables that are computed explicitly (e.g., z)\n",
    "3. [ImplicitComponent](../../features/core_features/working_with_components/implicit_component) : defines dependent variables that are computed implicitly (e.g., y)\n",
    "\n",
    "\n",
    "The most straightforward way to implement the numerical model would be to assign each variable its own component, as below.\n",
    "\n",
    "| No. | Component Type    | Inputs | Outputs |\n",
    "|-----|-------------------|--------|---------|\n",
    "| 1   | IndepVarComp      |        | x       |\n",
    "| 2   | ImplicitComponent | x, z   | y       |\n",
    "| 3   | ExplicitComponent | y      | z       |\n",
    "\n",
    "\n",
    "Another way that is also valid would be to have one component compute both y and z explicitly,\n",
    "which would mean that this component solves the implicit equation for y internally.\n",
    "\n",
    "| No. | Component Type    | Inputs | Outputs |\n",
    "|-----|-------------------|--------|---------|\n",
    "| 1   | IndepVarComp      |        | x       |\n",
    "| 2   | ExplicitComponent | x      | y, z    |\n",
    "\n",
    "Both ways would be valid, but the first way is recommended.\n",
    "The second way requires the user to solve y and z together, and computing the derivatives of y and z with respect to x is non-trivial. The first way would also require implicitly solving for y, but an OpenMDAO solver could converge that for you. Moreover, for the first way, OpenMDAO would automatically combine and assemble the derivatives from components 2 and 3."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
