{ "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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "Matriz local" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
01000.0-1000.0
1-1000.01000.0
\n", "
" ], "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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
01000.00.00.0
10.00.00.0
20.00.00.0
\n", "
" ], "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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "Matriz local" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
01000.0-1000.0
1-1000.01000.0
\n", "
" ], "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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
02000.0-1000.00.0
1-1000.01000.00.0
20.00.00.0
\n", "
" ], "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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "Matriz local" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
01000.0-1000.0
1-1000.01000.0
\n", "
" ], "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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
03000.0-2000.00.0
1-2000.02000.00.0
20.00.00.0
\n", "
" ], "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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "Matriz local" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
01
01000.0-1000.0
1-1000.01000.0
\n", "
" ], "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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
03000.0-2000.00.0
1-2000.03000.0-1000.0
20.0-1000.01000.0
\n", "
" ], "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", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "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 }