{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Contenido bajo licencia Creative Commons BY 4.0 y código bajo licencia MIT. © Juan Gómez y Nicolás Guarín-Zapata 2020. Este material es parte del curso Modelación Computacional en el programa de Ingeniería Civil de la Universidad EAFIT." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Ensamblaje paso a paso" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Este notebook presenta de manera automática las matrices de rigidez locales para cada elemento y la matriz de rigidez global luego de ensamblar el elemento correspondiente. Se sugiere usar este notebook para verificar el proceso de ensamblaje hecho a mano. Adicionalmente, se sugiere no usarse para sistemas con más de 10 elementos ya que requeriría de matrices muy grandes para resultar práctico.\n", "\n", "\n", "Este notebok está acompañado de un [notebook auxiliar](./06b_ensamblaje.ipynb) que explica cómo construir el sistema de ecuaciones para un sistema de masas y resortes con un ejemplo paso a paso.\n", "\n", "**Nota:** Este notebook utiliza los mismos archivos de texto del sistema de resortes del notebook principal y disponibles en la carpeta `files` del repositorio. Para poder continuar con el resto del notebook es necesario que estos archivos esten disponibles en memoria." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from IPython.display import display, Markdown\n", "import pandas as pd" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def readin():\n", " nodes = np.loadtxt('files/sprnodes.txt', ndmin=2)\n", " mats = np.loadtxt('files/sprmater.txt', ndmin=2)\n", " elements = np.loadtxt('files/spreles.txt', ndmin=2, dtype=np.int)\n", " loads = np.loadtxt('files/sprloads.txt', ndmin=2)\n", " return nodes, mats, elements, loads" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def eqcounter(nodes):\n", " nn = nodes.shape[0]\n", " IBC = np.zeros((nn, 1), dtype=np.integer)\n", " neq = 0\n", " for cont in range(nn):\n", " IBC[cont] = int(nodes[cont, 2])\n", " if IBC[cont] == 0:\n", " IBC[cont] = neq\n", " neq = neq + 1\n", " return neq, IBC" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def DME(nodes, elements):\n", " nels = elements.shape[0]\n", " DME_mat = np.zeros((nels, 2), dtype=np.integer)\n", " neq, IBC = eqcounter(nodes)\n", " ndof = 2\n", " nnodes = 2\n", " for ele in range(nels):\n", " for node in range(nnodes):\n", " pos = elements[ele, node + 3]\n", " DME_mat[ele, node] = IBC[pos]\n", " return DME_mat, IBC, neq" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def uelspring(kcof):\n", " \"\"\"\n", " Esta rutina calcula la matriz de rigidez para\n", " un elemento tipo resorte conformado por 2 nodos.\n", "\n", " Parámetros\n", " ----------\n", " kcof : float\n", " Coeficiente de rigidez del resorte (>0).\n", "\n", " Retorna\n", " -------\n", " kloc : ndarray\n", " Matriz de coeficientes de rigidez local para\n", " el elemento tipo resorte (2, 2).\n", "\n", "\n", " \"\"\"\n", " kloc = np.array([\n", " [kcof, -kcof],\n", " [-kcof, kcof]])\n", " return kloc" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def assem_msg(el, kloc, kglob):\n", " \"\"\"Muestra la matriz local y global para un elemento dado\"\"\"\n", " display(Markdown(\"### Elemento {:d}\".format(el)))\n", " display(Markdown(\"Matriz local\"))\n", " display(pd.DataFrame(kloc))\n", " display(Markdown(\"Matriz global luego de ensamblar\"))\n", " display(pd.DataFrame(kglob))\n", " return None" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "def assembly(elements, mats, nodes, neq, DME_mat, steps=True):\n", " IELCON = np.zeros([2], dtype=np.integer)\n", " KG = np.zeros((neq, neq))\n", " nels = elements.shape[0]\n", " nnodes = 2\n", " ndof = 2\n", " for el in range(nels):\n", " elcoor = np.zeros((nnodes))\n", " im = np.int(elements[el, 2])\n", " par = mats[im]\n", " for j in range(nnodes):\n", " IELCON[j] = elements[el, j+3]\n", " elcoor[j] = nodes[IELCON[j], 1]\n", " kloc = uelspring(par[0])\n", " dme = DME_mat[el, :ndof]\n", " for row in range(ndof):\n", " glob_row = dme[row]\n", " if glob_row != -1:\n", " for col in range(ndof):\n", " glob_col = dme[col]\n", " if glob_col != -1:\n", " KG[glob_row, glob_col] = KG[glob_row, glob_col] +\\\n", " kloc[row, col]\n", " if steps:\n", " assem_msg(el, kloc, KG)\n", " return KG" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "def loadasem(loads, IBC, neq, nl):\n", " \"\"\"\n", " Ensambla el vector de cargas o de valores conocidos\n", " en el sistema global de ecuaciones.\n", "\n", " Parámetros\n", " ----------\n", " loads : ndarray\n", " Arreglo con las cargas impuestas a las partículas.\n", " IBC : ndarray (int)\n", " Arreglo que almacena el identificador de grado de libertad\n", " a cada partícula.\n", " neq : int\n", " Numero de ecuaciones en el sistema.\n", " nl : int\n", " Numero de cargas en el sistema.\n", "\n", " Retorna\n", " -------\n", " rhs_glob : ndarray\n", " Arreglo con las cargas impuestas a las partículas,\n", " rhs se refiere a lado derecho (del inglés right-hand-side).\n", "\n", " \"\"\"\n", " rhs_glob = np.zeros((neq))\n", " for cont in range(nl):\n", " il = int(loads[cont, 0])\n", " ilx = IBC[il]\n", " if ilx != -1:\n", " rhs_glob[ilx] = loads[cont, 1]\n", " return rhs_glob" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "nodes, mats, elements, loads = readin()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La siguiente celda ensambla el sistema de ecuaciones y muestra cada uno de los pasos." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/markdown": [ "### Elemento 0" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "Matriz local" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>0</th>\n", " <th>1</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>1000.0</td>\n", " <td>-1000.0</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>-1000.0</td>\n", " <td>1000.0</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " 0 1\n", "0 1000.0 -1000.0\n", "1 -1000.0 1000.0" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "Matriz global luego de ensamblar" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>0</th>\n", " <th>1</th>\n", " <th>2</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>1000.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " 0 1 2\n", "0 1000.0 0.0 0.0\n", "1 0.0 0.0 0.0\n", "2 0.0 0.0 0.0" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "### Elemento 1" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "Matriz local" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>0</th>\n", " <th>1</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>1000.0</td>\n", " <td>-1000.0</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>-1000.0</td>\n", " <td>1000.0</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " 0 1\n", "0 1000.0 -1000.0\n", "1 -1000.0 1000.0" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "Matriz global luego de ensamblar" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>0</th>\n", " <th>1</th>\n", " <th>2</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>2000.0</td>\n", " <td>-1000.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>-1000.0</td>\n", " <td>1000.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " 0 1 2\n", "0 2000.0 -1000.0 0.0\n", "1 -1000.0 1000.0 0.0\n", "2 0.0 0.0 0.0" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "### Elemento 2" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "Matriz local" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>0</th>\n", " <th>1</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>1000.0</td>\n", " <td>-1000.0</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>-1000.0</td>\n", " <td>1000.0</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " 0 1\n", "0 1000.0 -1000.0\n", "1 -1000.0 1000.0" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "Matriz global luego de ensamblar" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>0</th>\n", " <th>1</th>\n", " <th>2</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>3000.0</td>\n", " <td>-2000.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>-2000.0</td>\n", " <td>2000.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " 0 1 2\n", "0 3000.0 -2000.0 0.0\n", "1 -2000.0 2000.0 0.0\n", "2 0.0 0.0 0.0" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "### Elemento 3" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "Matriz local" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>0</th>\n", " <th>1</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>1000.0</td>\n", " <td>-1000.0</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>-1000.0</td>\n", " <td>1000.0</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " 0 1\n", "0 1000.0 -1000.0\n", "1 -1000.0 1000.0" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "Matriz global luego de ensamblar" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "<div>\n", "<style scoped>\n", " .dataframe tbody tr th:only-of-type {\n", " vertical-align: middle;\n", " }\n", "\n", " .dataframe tbody tr th {\n", " vertical-align: top;\n", " }\n", "\n", " .dataframe thead th {\n", " text-align: right;\n", " }\n", "</style>\n", "<table border=\"1\" class=\"dataframe\">\n", " <thead>\n", " <tr style=\"text-align: right;\">\n", " <th></th>\n", " <th>0</th>\n", " <th>1</th>\n", " <th>2</th>\n", " </tr>\n", " </thead>\n", " <tbody>\n", " <tr>\n", " <th>0</th>\n", " <td>3000.0</td>\n", " <td>-2000.0</td>\n", " <td>0.0</td>\n", " </tr>\n", " <tr>\n", " <th>1</th>\n", " <td>-2000.0</td>\n", " <td>3000.0</td>\n", " <td>-1000.0</td>\n", " </tr>\n", " <tr>\n", " <th>2</th>\n", " <td>0.0</td>\n", " <td>-1000.0</td>\n", " <td>1000.0</td>\n", " </tr>\n", " </tbody>\n", "</table>\n", "</div>" ], "text/plain": [ " 0 1 2\n", "0 3000.0 -2000.0 0.0\n", "1 -2000.0 3000.0 -1000.0\n", "2 0.0 -1000.0 1000.0" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "DME_mat, IBC, neq = DME(nodes, elements)\n", "KG = assembly(elements, mats, nodes, neq, DME_mat)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0.002 0.0025 0.0045]\n" ] } ], "source": [ "RHSG = loadasem(loads, IBC, neq, 3)\n", "UG = np.linalg.solve(KG, RHSG)\n", "print(UG)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Formato del notebook" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La siguiente celda cambia el formato del Notebook." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "<link href='http://fonts.googleapis.com/css?family=Fenix' rel='stylesheet' type='text/css'>\n", "<link href='http://fonts.googleapis.com/css?family=Alegreya+Sans:100,300,400,500,700,800,900,100italic,300italic,400italic,500italic,700italic,800italic,900italic' rel='stylesheet' type='text/css'>\n", "<link href='http://fonts.googleapis.com/css?family=Source+Code+Pro:300,400' rel='stylesheet' type='text/css'>\n", "\n", "<style>\n", "\n", "/*\n", "Template for Notebooks for Modelación computacional.\n", "\n", "Based on Lorena Barba template available at:\n", "\n", " https://github.com/barbagroup/AeroPython/blob/master/styles/custom.css\n", "*/\n", "\n", "/* Fonts */\n", "@font-face {\n", "font-family: \"Computer Modern\";\n", "src: url('http://mirrors.ctan.org/fonts/cm-unicode/fonts/otf/cmunss.otf');\n", "}\n", "\n", "/* Text */\n", "div.cell{\n", "width:800px;\n", "margin-left:16% !important;\n", "margin-right:auto;\n", "}\n", "h1 {\n", "font-family: 'Alegreya Sans', sans-serif;\n", "}\n", "h2 {\n", "font-family: 'Fenix', serif;\n", "}\n", "h3{\n", "font-family: 'Fenix', serif;\n", "margin-top:12px;\n", "margin-bottom: 3px;\n", "}\n", "h4{\n", "font-family: 'Fenix', serif;\n", "}\n", "h5 {\n", "font-family: 'Alegreya Sans', sans-serif;\n", "}\t\n", "div.text_cell_render{\n", "font-family: 'Alegreya Sans',Computer Modern, \"Helvetica Neue\", Arial, Helvetica, Geneva, sans-serif;\n", "line-height: 135%;\n", "font-size: 120%;\n", "width:600px;\n", "margin-left:auto;\n", "margin-right:auto;\n", "}\n", ".CodeMirror{\n", "font-family: \"Source Code Pro\";\n", "font-size: 90%;\n", "}\n", "/* .prompt{\n", "display: None;\n", "}*/\n", ".text_cell_render h1 {\n", "font-weight: 200;\n", "font-size: 50pt;\n", "line-height: 100%;\n", "color:#CD2305;\n", "margin-bottom: 0.5em;\n", "margin-top: 0.5em;\n", "display: block;\n", "}\t\n", ".text_cell_render h5 {\n", "font-weight: 300;\n", "font-size: 16pt;\n", "color: #CD2305;\n", "font-style: italic;\n", "margin-bottom: .5em;\n", "margin-top: 0.5em;\n", "display: block;\n", "}\n", ".warning{\n", "color: rgb( 240, 20, 20 )\n", "}\n", "</style>\n", "\n", "<script>\n", "/* Equations */\n", "\n", "MathJax.Hub.Config({\n", "TeX: {\n", "extensions: [\"AMSmath.js\"]\n", "},\n", "tex2jax: {\n", "inlineMath: [ ['$','$'], [\"\\\\(\",\"\\\\)\"] ],\n", "displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"] ]\n", "},\n", "displayAlign: 'center', // Change this to 'center' to center equations.\n", "\"HTML-CSS\": {\n", "styles: {'.MathJax_Display': {\"margin\": 4}}\n", "}\n", "});\n", "</script>\n", "\n", "\n" ], "text/plain": [ "<IPython.core.display.HTML object>" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.core.display import HTML\n", "def css_styling():\n", " styles = open('./nb_style.css', 'r').read()\n", " return HTML(styles)\n", "css_styling()" ] } ], "metadata": { "celltoolbar": "Raw Cell Format", "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.7.3" }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 1 }