{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Simple beam - Geometry\n", "In this first notebook, the geometry of a simple beam with rectangular section is explored. The correlated mechanical parameters are also visualized." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# Import the packages needed\n", "import math\n", "import numpy as np \n", "from bokeh.layouts import layout, column\n", "from bokeh.models import Div, CustomJS, Slider, Spacer\n", "from bokeh.models.tickers import SingleIntervalTicker\n", "from bokeh.plotting import figure, show, ColumnDataSource\n", "from bokeh.io import output_notebook\n", "from cienpy import simplebeam as sb\n", "from cienpy import rectangular_section as beam_section\n", "from cienpy import models\n", "\n", "# output_notebook()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define the geometry:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# Choose the dimensions\n", "L = 6 # [m]\n", "h = 200 # [mm]\n", "b = 100 # [mm]\n", "\n", "# compute the parameters\n", "A = beam_section.compute_area(b, h) # [mm2]\n", "Iy = beam_section.compute_inertia_y(b, h) # [mm4] strong axis\n", "Iz = beam_section.compute_inertia_z(b, h) # [mm4] weak axis\n", "\n", "# constants for the visualisation\n", "MAX_B = 3*b\n", "MAX_H = 3*h\n", "\n", "# store the values in a specific format\n", "data_beam = dict(\n", " x=[0, L],\n", " y=[0, 0]\n", ")\n", "\n", "initial_position = L\n", "data = dict( # stores every useful single variable\n", " L=[L],\n", " b=[b],\n", " h=[h],\n", " A=[A],\n", " Iy=[Iy],\n", " Iz=[Iz],\n", " x=[initial_position],\n", " y=[0]\n", ")\n", "\n", "source_beam = ColumnDataSource(data_beam)\n", "source = ColumnDataSource(data)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now define the new figures, renderers and widgets:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
GlyphRenderer(
id = '1829', …)
coordinates = None,
data_source = ColumnDataSource(id='1825', ...),
glyph = Text(id='1826', ...),
group = None,
hover_glyph = None,
js_event_callbacks = {},
js_property_callbacks = {},
level = 'glyph',
muted = False,
muted_glyph = Text(id='1828', ...),
name = None,
nonselection_glyph = Text(id='1827', ...),
selection_glyph = 'auto',
subscribed_events = [],
syncable = True,
tags = [],
view = CDSView(id='1830', ...),
visible = True,
x_range_name = 'default',
y_range_name = 'default')
\n", "\n" ], "text/plain": [ "GlyphRenderer(id='1829', ...)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "FIG_H_B = 200 # height figure beam\n", "FIG_B_B = 700 # width figure beam\n", "FIG_H_SEC = 600 # height figure section\n", "\n", "paddingx = 0.2*L\n", "options = dict(\n", " toolbar_location=None\n", ")\n", "\n", "fig_beam = figure(**options,\n", " x_axis_label=\"Position [m]\",\n", " plot_height=200,\n", " plot_width=700,\n", " x_range=(0-paddingx, L+paddingx),\n", " y_range=(-1, 1),\n", " title=\"Simple supported beam\"\n", ")\n", "fig_beam.xgrid.grid_line_alpha = 0\n", "fig_beam.ygrid.grid_line_alpha = 0\n", "fig_beam.yaxis.visible = False\n", "\n", "fig_section = figure(**options,\n", " x_axis_label=\"Width b [mm]\",\n", " y_axis_label=\"Height h [mm]\",\n", " plot_height=int(MAX_H*0.9),\n", " plot_width=int(MAX_B),\n", " match_aspect=True,\n", " title=\"Cross-section of the beam\"\n", ")\n", "fig_section.rect([0], [0], width=MAX_B, height=MAX_H, alpha=0, fill_alpha=0) # transparent rect\n", "fig_section.axis.ticker = SingleIntervalTicker(interval=50, num_minor_ticks=5)\n", "\n", "\n", "# beam\n", "beam = fig_beam.line('x', 'y', source=source_beam, line_width=6, color='black')\n", "b_supp = 0.3\n", "supp_opt = dict(\n", " fill_color='white',\n", " line_color='black'\n", ")\n", "support_l = fig_beam.patch([0, b_supp/2, -b_supp/2],\n", " [0, -b_supp/2*math.sqrt(3), -b_supp/2*math.sqrt(3)],\n", " **supp_opt)\n", "support_r = fig_beam.circle([L], [-b_supp/2], radius=b_supp/2, **supp_opt)\n", "\n", "\n", "# section\n", "section = fig_section.rect([0], [0], width=b, height=h, fill_color='white',\n", " color='black', line_width=3, hatch_pattern='/', hatch_color='black')\n", "\n", "\n", "# show mechanical parameters\n", "div_text = lambda h, b, L, A, Iy, Iz : f\"\"\"

Geometrical and mechanical parameters:

\n", " h = {round(h)} mm
\n", " b = {round(b)} mm
\n", " L = {round(L)} m
\n", " A = {\"{:.2e}\".format(A)} mm2
\n", " Iy = {\"{:.2e}\".format(Iy)} mm4
\n", " Iz = {\"{:.2e}\".format(Iz)} mm4\"\"\"\n", "\n", "div = Div(\n", " text=div_text(h, b, L, A, Iy, Iz),\n", " width=300,\n", " height=300\n", ")\n", "\n", "\n", "# change geometry\n", "slider_b = Slider(\n", " title=\"Change the width b [mm]\",\n", " start=10,\n", " end=MAX_B,\n", " step=10,\n", " value=b\n", ")\n", "slider_h = Slider(\n", " title=\"Change the height h [mm]\",\n", " start=20,\n", " end=MAX_H,\n", " step=20,\n", " value=h\n", ")\n", "slider_L = Slider(\n", " title=\"Change the length L [m]\",\n", " start=1,\n", " end=L+1,\n", " step=0.1,\n", " value=L\n", ")\n", "\n", "# reference system\n", "axis_arrow_length = 0.8\n", "axis_arrow_scale = 100\n", "x_axis_arrow = models.force_vector(fig_beam, axis_arrow_length, L, L+axis_arrow_length, 0, 0, 'gray')\n", "x_axis_label = fig_beam.text(x=[L+axis_arrow_length/2], y=[0.1], text=[\"x axis\"], text_color='gray', text_baseline='bottom')\n", "models.force_vector(fig_section, axis_arrow_length*10, 0, 0, 0, axis_arrow_length*axis_arrow_scale*1.6, 'gray') # y axis\n", "fig_section.text(x=[0], y=[axis_arrow_length*axis_arrow_scale*1.7], text=[\"y axis\"], text_color='gray', text_baseline='middle', angle=math.pi/2)\n", "models.force_vector(fig_section, axis_arrow_length*10, 0, -axis_arrow_length*axis_arrow_scale, 0, 0, 'gray') # z axis\n", "fig_section.text(x=[-axis_arrow_length*axis_arrow_scale*1.1], y=[0], text=[\"z axis\"], text_color='gray', text_align='right', text_baseline='middle')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Configure the logics:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "code_slider = lambda var, L_code, b_code, h_code, x_axis_code=\"\" : f\"\"\"\n", " // retrieve data used\n", " const data_b = s_b.data\n", " const data_s = s_s.data\n", " // retrieve the var from the object that uses callback\n", " const f = cb_obj.value // value of the slider\n", " // compute the parameters and dimensions\n", " const L = Math.round({L_code}*10)/10\n", " const b = Math.round({b_code})\n", " const h = Math.round({h_code})\n", " const A = b*h\n", " const Iy = Math.round(Math.pow(h, 3)*b/12)\n", " const Iz = Math.round(Math.pow(b, 3)*h/12)\n", " div.text = \"

Geometrical and mechanical parameters:

h = \"+h+\n", " \" mm
b = \"+b+\n", " \" mm
L = \"+L+\n", " \" m
A = \"+A.toExponential()+\n", " \" mm2
Iy = \"+Iy.toExponential()+\n", " \" mm4
Iz = \"+Iz.toExponential()+\n", " \" mm4\"\n", " // change the plot of the section\n", " section.glyph.width = b\n", " section.glyph.height = h\n", " // change the plot of the beam\n", " data_b['x'][1] = L\n", " support_r.glyph.x = L\n", " {x_axis_code}\n", " // apply the changes\n", " data_s['{var}'] = f\n", " data_s['A'] = A\n", " data_s['Iy'] = Iy\n", " data_s['Iz'] = Iz\n", " s_s.change.emit()\n", " s_b.change.emit()\n", "\"\"\"\n", "\n", "x_axis_code = f\"\"\"\n", "// change the position of the x axis arrow and text\n", "x_axis_arrow.x_start = L\n", "x_axis_arrow.x_end = L+{axis_arrow_length}\n", "x_axis_label.glyph.x = L+{axis_arrow_length}/2\n", "\"\"\"\n", "\n", "# logic for slider_L\n", "update_L = CustomJS(args=dict(s_b=source_beam, s_s=source, div=div, section=section, support_r=support_r,\n", " x_axis_arrow=x_axis_arrow, x_axis_label=x_axis_label),\n", " code=code_slider(\"L\", \"f\", \"data_s['b']\", \"data_s['h']\", x_axis_code))\n", "\n", "slider_L.js_on_change('value', update_L)\n", "\n", "# logic for slider_b\n", "update_b = CustomJS(args=dict(s_b=source_beam, s_s=source, div=div, section=section, support_r=support_r),\n", " code=code_slider(\"b\", \"data_s['L']\", \"f\", \"data_s['h']\"))\n", "\n", "slider_b.js_on_change('value', update_b)\n", "\n", "# logic for slider_h\n", "update_h = CustomJS(args=dict(s_b=source_beam, s_s=source, div=div, section=section, support_r=support_r),\n", " code=code_slider(\"h\", \"data_s['L']\", \"data_s['b']\", \"f\"))\n", "\n", "slider_h.js_on_change('value', update_h)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Build the layout and show the figures:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "layout1 = layout([\n", " [fig_beam],\n", " [fig_section, Spacer(width=20), column([Spacer(height=50), slider_L, slider_b, slider_h, Spacer(height=50), div])] \n", "])\n", "\n", "show(layout1)" ] } ], "metadata": { "interpreter": { "hash": "f29f3a16a5c47811d2900cf82e6584cc83572ddcd5db25d9cf9bef77823b3d45" }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.10" } }, "nbformat": 4, "nbformat_minor": 2 }