{ "cells": [ { "cell_type": "markdown", "metadata": { "raw_mimetype": "text/latex" }, "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": [ "# Pórticos planos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Introducción" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En este Notebook se agrega un elemento adicional al programa de análisis estructural, iniciado con el problema simple de resortes unidimesionales y extendido para considerar armaduras planas. En particular, ahora se adicionan elementos tipo viga para abordar problemas en los cuales los elementos funcionen principalmente a flexión. Adicionalmente, en una implementación independiente, es posible acoplar el comportamiento a carga axial de la cercha con el comportamiento a flexión de la viga.\n", "\n", "El modelo de viga que se discute en este notebook corresponde a un modelo de Euler-Bernoulli en el cual se desprecian las deformaciones por cortante y por lo tanto válido para elementos con secciones transversales de baja esbeltez.\n", "\n", "**Al completar este notebook usted debería estar en la capacidad de:**\n", "\n", "* Reconocer las modificaciones necesarias para convertir un programa fundamental de ensamblaje de resortes en uno para estructuras conformadas por vigas.\n", "\n", "* Resolver problemas simples de estructuras conformadas por vigas sometidas a cargas puntuales." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ensamblaje de elementos tipo viga" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Consideremos un elemento tipo viga en su sistema local de referencia como el mostrado en la figura. En el sistema local el elemento tiene 2 grados de libertad por nodo, correspondientes al desplazamiento transversal y una rotación con respecto a un eje perpendicular al plano de la imagen.\n", "\n", "<center>\n", " <img src=\"img/viga_local.svg\"\n", " alt=\"Viga en el sistema de referencia local\"\n", " style=\"width:400px\">\n", "</center>\n", "\n", "El vector de grados de libertad (o desplazamientos generalizados) del elemento es:\n", "\n", "$$\n", "u^T=\\begin{bmatrix}v_1 &\\theta_1 &v_2 &\\theta_2\\end{bmatrix}\n", "$$\n", "\n", "mientras que el vector de fuerza (momentos y cortantes) esta dado por:\n", "\n", "$$\n", "f^T=\\begin{bmatrix}f_1 &m_1 &f_2 &m_2\\end{bmatrix}\n", "$$\n", "\n", "\n", "En el sistema de referencia local la matriz de rigidez relacionando fuerzas con desplazamientos es:\n", "\n", "$$\n", "\\begin{Bmatrix} f_1\\\\ m_1\\\\ f_2\\\\ m_2\\end{Bmatrix} =\n", "\\begin{bmatrix}\n", "12\\frac{EI}{\\mathcal l^3} &6\\frac{EI}{\\mathcal l^3} &-12\\frac{EI}{\\mathcal l^3} &6\\frac{EI}{\\mathcal l^2}\\\\\n", "6\\frac{EI}{\\mathcal l^3}&4\\frac{EI}{\\mathcal l}&-6\\frac{EI}{\\mathcal l^2}&2\\frac{EI}{\\mathcal l}\\\\\n", "12\\frac{EI}{\\mathcal l^3}&-6\\frac{EI}{\\mathcal l^2}&12\\frac{EI}{\\mathcal l^3}&-6\\frac{EI}{\\mathcal l^2}\\\\\n", "6\\frac{EI}{\\mathcal l^2}&2\\frac{EI}{\\mathcal l}&-6\\frac{EI}{\\mathcal l^2}&4\\frac{EI}{\\mathcal l}\n", "\\end{bmatrix}\n", "\\begin{Bmatrix} v_1\\\\ \\theta_1\\\\ v_2\\\\ \\theta_2\\end{Bmatrix}\n", "$$\n", "\n", "\n", "\n", "\n", "<div class=\"alert alert-warning\">\n", "\n", "**Nota:** La matriz de rigidez puede formularse por diferentes métodos que serán cubiertos en el curso de Análisis de Estructuras.\n", "\n", "</div>\n", "\n", "Para obtener la matriz de rigidez global de la estructura es necesario considerar nuevamente la contribución de todos los elementos en el sistema **global** de referencia. Con ese propósito procedemos como con el problema de la cercha. Usando la matriz de transformación bajo rotación $\\lambda$ se tiene que:\n", "\n", "$$K = \\lambda^T k\\lambda$$\n", "\n", "donde $K$ es la matriz de rigidez para el elemento tipo viga en el sistema global de referencia. Note que en este sistema el elemento tiene ahora 3 grados de libertad por nodo." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Estructura aporticada simple" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Considere el siguiente modelo simple conformado por un ensamblaje de 3 elementos. (Los archivos de datos de entrada están disponibles en la carpeta `files`).\n", "\n", "<center>\n", " <img src=\"img/portico_ejemplo.svg\"\n", " alt=\"Esquema de la estructura del ejemplo.\"\n", " style=\"width:500px\">\n", "</center>\n", "\n", "Se requiere determinar el desplazamiento lateral de la estructura cuando es sometida a la carga lateral $P$.\n", "\n", "<div class=\"alert alert-warning\">\n", "\n", "Encuentre la matriz de transformación bajo rotación $\\lambda$ requerida para la formulación de la matriz de rigidez en el sistema de referencia global.\n", "\n", "</div>" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Las modificacions que se deben aplicar al código de resortes (o al de cerchas) solo estan relacionadas con el hecho de que ahora hay 3 grados de libertad en cada nodo." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import sympy as sym" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lea los archivos de entrada de la carpeta `files`." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def readin():\n", " nodes = np.loadtxt('files/Fnodes.txt', ndmin=2)\n", " mats = np.loadtxt('files/Fmater.txt', ndmin=2)\n", " elements = np.loadtxt('files/Feles.txt', ndmin=2)\n", " loads = np.loadtxt('files/Floads.txt', ndmin=2)\n", " return nodes, mats, elements, loads" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La función `eqcounter` cuenta ecuaciones y genera el arreglo de condiciones de frontera." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def eqcounter(nodes):\n", " nnodes = nodes.shape[0]\n", " IBC = np.zeros([nnodes, 3], dtype=np.integer)\n", " for i in range(nnodes):\n", " for k in range(3):\n", " IBC[i, k] = int(nodes[i, k+3])\n", " neq = 0\n", " for i in range(nnodes):\n", " for j in range(3):\n", " if IBC[i, j] == 0:\n", " IBC[i, j] = neq\n", " neq = neq + 1\n", " return neq, IBC" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ahora, la función `DME` calcula la matriz de ensamblaje de ecuaciones." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def DME(nodes, elements):\n", "\n", " nels = elements.shape[0]\n", " IELCON = np.zeros([nels, 2], dtype=np.integer)\n", " DME_mat = np.zeros([nels, 6], dtype=np.integer)\n", " neq, IBC = eqcounter(nodes)\n", " ndof = 6\n", " nnodes = 2\n", " for i in range(nels):\n", " for j in range(nnodes):\n", " IELCON[i, j] = elements[i, j+3]\n", " kk = IELCON[i, j]\n", " for l in range(3):\n", " DME_mat[i, 3*j+l] = IBC[kk, l]\n", " return DME_mat, IBC, neq" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La función `assembly` usa el modelo y la matriz `DME_mat` para calcular la matriz de rigidez global." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def assembly(elements, mats, nodes, neq, DME_mat):\n", " IELCON = np.zeros([2], dtype=np.integer)\n", " KG = np.zeros((neq, neq))\n", " nels = elements.shape[0]\n", " nnodes = 2\n", " ndof = 6\n", " for el in range(nels):\n", " elcoor = np.zeros([nnodes, 2])\n", " im = np.int(elements[el, 2])\n", " par0 = mats[im, 0]\n", " par1 = mats[im, 1]\n", " for j in range(nnodes):\n", " IELCON[j] = elements[el, j+3]\n", " elcoor[j, 0] = nodes[IELCON[j], 1]\n", " elcoor[j, 1] = nodes[IELCON[j], 2]\n", " kloc = uelbeam2DU(elcoor, par0, par1)\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", " return KG" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La función `uelbeam2D` usa las coordenadas de los nodos y los parámetros de material para calcular la matriz de rigidez local ya transformada al sistema de referencia global.\n", "\n", "\n", "<div class=\"alert alert-warning\">\n", " \n", "Agregue un comentario a cada línea relevante de los códigos de las siguientes funciones y úselos para escribir los pseudocódigos correspondientes. En particular identifique el calculo de la matriz de transformación bajo rotación $\\lambda$.\n", "\n", "</div>" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "def uelbeam2DU(coord, I, Emod):\n", " \"\"\"2D-2-noded beam element\n", " without axial deformation\n", "\n", " Parametros\n", " ----------\n", " coord : ndarray\n", " Cordenadas nodales (2, 2).\n", " A : float\n", " Area de la seccion transversal.\n", " Emod : float\n", " Modulo de elasticidad (>0).\n", "\n", " Returna\n", " -------\n", " kl : ndarray\n", " Matriz de rigidez local para el elemento (4, 4).\n", "\n", " \"\"\"\n", " vec = coord[1, :] - coord[0, :]\n", " nx = vec[0]/np.linalg.norm(vec)\n", " ny = vec[1]/np.linalg.norm(vec)\n", " L = np.linalg.norm(vec)\n", " Q = np.array([\n", " [-ny, nx, 0, 0, 0, 0],\n", " [0, 0, 1.0, 0, 0, 0],\n", " [0, 0, 0, -ny, nx, 0],\n", " [0, 0, 0, 0, 0, 1.0]])\n", " kl = (I*Emod/(L*L*L)) * np.array([\n", " [12.0, 6, -12.0, 6*L],\n", " [6, 4*L*L, -6*L, 2*L*L],\n", " [-12.0, -6*L, 12.0, -6*L],\n", " [6*L, 2*L*L, -6*L, 4*L*L]])\n", " kG = np.dot(np.dot(Q.T, kl), Q)\n", " return kG" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La rutina `loadassem` forma el vector de cargas en los nodos." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "def loadasem(loads, IBC, neq, nl):\n", " RHSG = np.zeros([neq])\n", " for i in range(nl):\n", " il = int(loads[i, 0])\n", " ilx = IBC[il, 0]\n", " ily = IBC[il, 1]\n", " ilT = IBC[il, 2]\n", " if ilx != -1:\n", " RHSG[ilx] = loads[i, 1]\n", " if ily != -1:\n", " RHSG[ily] = loads[i, 2]\n", " if ilT != -1:\n", " RHSG[ilT] = loads[i, 3]\n", " return RHSG" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "El programa principal mantiene la misma estructura que el programa de resortes, es decir, se tienen siguientes pasos:\n", "\n", "* Lee el modelo.\n", "\n", "* Determina la matriz de ensamblaje `DME_mat`.\n", "\n", "* Ensambla el sistema global de ecuaciones.\n", "\n", "* Determina los desplazamientos globales `UG` tras resolver el sistema global." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 2.25000000e+01 2.00000000e+01 1.27557539e-16 -1.25918779e-15\n", " 2.00000000e+01 4.88970566e-16]\n" ] } ], "source": [ "nodes, mats, elements, loads = readin()\n", "DME_mat, IBC, neq = DME(nodes, elements)\n", "KG = assembly(elements, mats, nodes, neq, DME_mat)\n", "RHSG = loadasem(loads, IBC, neq, 1)\n", "UG = np.linalg.solve(KG, RHSG)\n", "print(UG)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<div class=\"alert alert-warning\">\n", " \n", "### Problemas propuestos\n", "\n", "#### Problema 1\n", "\n", "Implemente una función que calcule las fuerzas nodales en cada elemento y que verifique el equilibrio del sistema.\n", "\n", "#### Problema 2\n", "\n", "Determine la rigidez lateral de la estructura usando la siguiente expresión:\n", "\n", "$$k = \\frac{P}{\\delta}\\, .$$\n", "\n", "#### Problema 3\n", "\n", "Repotencie la estructura de tal forma que la rigidez lateral se incremente por un factor de 2.0\n", "\n", "#### Problema 4\n", "\n", "Repare el pórtico mostrado en la figura adicionando elementos y/o imponiendo restricciones apropiadas a los desplazamientos. (Cree un nuevo paquete de archivos de datos).\n", "\n", "#### Problema 5\n", "\n", "Para el portico de la figura asuma que la conexión del nudo 5 es articulada e indique como esta condición cambia los resultados.\n", "\n", "<center>\n", " <img src=\"img/portico_ejercicio.svg\"\n", " alt=\"Esquema del pórtico para el ejercicio propuesto.\"\n", " style=\"width:500px\">\n", "</center>\n", "\n", "</div>" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Referencias" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Bathe, Klaus-Jürgen. (2006) Finite element procedures. Klaus-Jurgen Bathe. Prentice Hall International.\n", "\n", "* Juan Gómez, Nicolás Guarín-Zapata (2018). SolidsPy: 2D-Finite Element Analysis with Python, <https://github.com/AppliedMechanics-EAFIT/SolidsPy>." ] }, { "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": 10, "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": 10, "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 }