.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "gallery/analyses/static/example_cantilever_plate.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_gallery_analyses_static_example_cantilever_plate.py: .. _ref_solid185_static_cantilever_example: SOLID185 — cantilever plate static analysis =========================================== Static analysis of a cantilever plate under a distributed tip load. This example walks through the full :meth:`femorph_solver.Model.solve` → :class:`StaticResult` → :func:`femorph_solver.io.static_result_to_grid` → pyvista rendering loop and checks static equilibrium via :attr:`StaticResult.reaction`. Euler–Bernoulli beam theory is included as a back-of-envelope reference; SOLID185 is a first-order hex with full 2 × 2 × 2 Gauss integration, which exhibits well-known shear locking in thin-bending problems unless many elements are used through the thickness. The difference between the two is a feature of the element, not a bug — swap in ``SOLID186`` (quadratic) to recover EB to a few percent with the same mesh. .. GENERATED FROM PYTHON SOURCE LINES 21-29 .. code-block:: Python from __future__ import annotations import numpy as np import pyvista as pv import femorph_solver .. GENERATED FROM PYTHON SOURCE LINES 30-34 Geometry + material ------------------- Steel cantilever, 1 m × 0.1 m × 0.05 m, meshed 40 × 4 × 4 hex (640 SOLID185 elements, 1 025 nodes). .. GENERATED FROM PYTHON SOURCE LINES 34-69 .. code-block:: Python E = 2.0e11 # Pa NU = 0.30 RHO = 7850.0 LX, LY, LZ = 1.0, 0.1, 0.05 NX, NY, NZ = 40, 4, 4 F_TIP = -5.0e3 # N (downward) xs = np.linspace(0.0, LX, NX + 1) ys = np.linspace(0.0, LY, NY + 1) zs = np.linspace(0.0, LZ, NZ + 1) xx, yy, zz = np.meshgrid(xs, ys, zs, indexing="ij") points = np.stack([xx.ravel(), yy.ravel(), zz.ravel()], axis=1) def _node_id(i: int, j: int, k: int) -> int: return (i * (NY + 1) + j) * (NZ + 1) + k + 1 cells = [] for i in range(NX): for j in range(NY): for k in range(NZ): cells.append( [ _node_id(i, j, k), _node_id(i + 1, j, k), _node_id(i + 1, j + 1, k), _node_id(i, j + 1, k), _node_id(i, j, k + 1), _node_id(i + 1, j, k + 1), _node_id(i + 1, j + 1, k + 1), _node_id(i, j + 1, k + 1), ] ) .. GENERATED FROM PYTHON SOURCE LINES 70-72 Build the model --------------- .. GENERATED FROM PYTHON SOURCE LINES 72-94 .. code-block:: Python m = femorph_solver.Model() m.et(1, "SOLID185") m.mp("EX", 1, E) m.mp("PRXY", 1, NU) m.mp("DENS", 1, RHO) for nn, (x, y, z) in enumerate(points, start=1): m.n(nn, x, y, z) for conn in cells: m.e(*conn) # Clamp the ``x = 0`` face in all 3 DOFs. x0_nodes = [nn for nn, p in enumerate(points, start=1) if p[0] < 1e-9] for nn in x0_nodes: m.d(nn, "UX") m.d(nn, "UY") m.d(nn, "UZ") # Distributed downward tip load. tip_nodes = [nn for nn, p in enumerate(points, start=1) if p[0] > LX - 1e-9] for nn in tip_nodes: m.f(nn, "FZ", F_TIP / len(tip_nodes)) .. rst-class:: sphx-glr-script-out .. code-block:: none /home/runner/_work/solver/solver/examples/analyses/static/example_cantilever_plate.py:73: DeprecationWarning: Model.et(...) is a MAPDL-dialect shortcut and has moved off the Model public surface. Use `APDL(model).et(et_id, name)` for line-by-line APDL deck porting, or the native `Model.assign("HEX8", material)` for new code. m.et(1, "SOLID185") /home/runner/_work/solver/solver/examples/analyses/static/example_cantilever_plate.py:74: DeprecationWarning: Model.mp(...) is a MAPDL-dialect shortcut and has moved off the Model public surface. Use `APDL(model).mp(prop, mat_id, value)` for line-by-line APDL deck porting, or the native `Model.assign(element, {prop: value, ...})` for new code. m.mp("EX", 1, E) /home/runner/_work/solver/solver/examples/analyses/static/example_cantilever_plate.py:75: DeprecationWarning: Model.mp(...) is a MAPDL-dialect shortcut and has moved off the Model public surface. Use `APDL(model).mp(prop, mat_id, value)` for line-by-line APDL deck porting, or the native `Model.assign(element, {prop: value, ...})` for new code. m.mp("PRXY", 1, NU) /home/runner/_work/solver/solver/examples/analyses/static/example_cantilever_plate.py:76: DeprecationWarning: Model.mp(...) is a MAPDL-dialect shortcut and has moved off the Model public surface. Use `APDL(model).mp(prop, mat_id, value)` for line-by-line APDL deck porting, or the native `Model.assign(element, {prop: value, ...})` for new code. m.mp("DENS", 1, RHO) /home/runner/_work/solver/solver/examples/analyses/static/example_cantilever_plate.py:78: DeprecationWarning: Model.n(...) is a MAPDL-dialect shortcut and has moved off the Model public surface. Use `APDL(model).n(num, x, y, z)` for line-by-line APDL deck porting, or the native `Model.from_grid(pv_grid)` for new code. m.n(nn, x, y, z) /home/runner/_work/solver/solver/examples/analyses/static/example_cantilever_plate.py:80: DeprecationWarning: Model.e(...) is a MAPDL-dialect shortcut and has moved off the Model public surface. Use `APDL(model).e(*node_nums)` for line-by-line APDL deck porting, or the native `Model.from_grid(pv_grid)` for new code. m.e(*conn) /home/runner/_work/solver/solver/examples/analyses/static/example_cantilever_plate.py:85: DeprecationWarning: Model.d(...) is a MAPDL-dialect shortcut and has moved off the Model public surface. Use `APDL(model).d(node, label, value)` for line-by-line APDL deck porting, or the native `Model.fix(nodes=..., where=..., dof=...)` for new code. m.d(nn, "UX") /home/runner/_work/solver/solver/examples/analyses/static/example_cantilever_plate.py:86: DeprecationWarning: Model.d(...) is a MAPDL-dialect shortcut and has moved off the Model public surface. Use `APDL(model).d(node, label, value)` for line-by-line APDL deck porting, or the native `Model.fix(nodes=..., where=..., dof=...)` for new code. m.d(nn, "UY") /home/runner/_work/solver/solver/examples/analyses/static/example_cantilever_plate.py:87: DeprecationWarning: Model.d(...) is a MAPDL-dialect shortcut and has moved off the Model public surface. Use `APDL(model).d(node, label, value)` for line-by-line APDL deck porting, or the native `Model.fix(nodes=..., where=..., dof=...)` for new code. m.d(nn, "UZ") /home/runner/_work/solver/solver/examples/analyses/static/example_cantilever_plate.py:92: DeprecationWarning: Model.f(...) is a MAPDL-dialect shortcut and has moved off the Model public surface. Use `APDL(model).f(node, label, value)` for line-by-line APDL deck porting, or the native `Model.apply_force(node, fx=..., fy=..., fz=...)` for new code. m.f(nn, "FZ", F_TIP / len(tip_nodes)) .. GENERATED FROM PYTHON SOURCE LINES 95-101 Solve + reaction check ---------------------- :meth:`Model.solve` returns a :class:`StaticResult` with ``displacement``, ``reaction``, and ``free_mask``. Reactions are nonzero only at constrained DOFs; summing ``FZ`` at the clamp must equal ``-F_TIP`` to machine precision for a well-posed static solve. .. GENERATED FROM PYTHON SOURCE LINES 101-111 .. code-block:: Python res = m.solve() dof = m.dof_map() fz_clamp = 0.0 for nn in x0_nodes: rows = np.where((dof[:, 0] == nn) & (dof[:, 1] == 2))[0] for r in rows: fz_clamp += float(res.reaction[r]) print(f"Σ FZ reaction at clamp = {fz_clamp:.4e} N (expected {-F_TIP:.4e})") .. rst-class:: sphx-glr-script-out .. code-block:: none Σ FZ reaction at clamp = 5.0000e+03 N (expected 5.0000e+03) .. GENERATED FROM PYTHON SOURCE LINES 112-119 Tip deflection vs Euler–Bernoulli --------------------------------- :math:`\\delta_\\mathrm{EB} = F L^3 / (3 E I)` with :math:`I = b h^3 / 12` is the slender-beam estimate. With 4 elements through the thickness, SOLID185's shear locking gives a few percent error — swap in ``SOLID186`` (see :ref:`ref_solid186_example`) to remove it entirely. .. GENERATED FROM PYTHON SOURCE LINES 119-131 .. code-block:: Python I_y = LY * LZ**3 / 12.0 delta_eb = F_TIP * LX**3 / (3.0 * E * I_y) grid = femorph_solver.io.static_result_to_grid(m, res) tip_mask = grid.points[:, 0] > LX - 1e-9 w_tip_femorph_solver = grid.point_data["displacement"][tip_mask, 2].min() print(f"Euler-Bernoulli tip deflection = {delta_eb:.3e} m") print(f"femorph-solver tip deflection (min UZ) = {w_tip_femorph_solver:.3e} m") print( f"relative error = {abs(w_tip_femorph_solver - delta_eb) / abs(delta_eb):.2%}" ) .. rst-class:: sphx-glr-script-out .. code-block:: none Euler-Bernoulli tip deflection = -8.000e-03 m femorph-solver tip deflection (min UZ) = -7.348e-03 m relative error = 8.15% .. GENERATED FROM PYTHON SOURCE LINES 132-134 Render the deformed plate, coloured by displacement magnitude ------------------------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 134-156 .. code-block:: Python warped = grid.warp_by_vector("displacement", factor=20.0) plotter = pv.Plotter(off_screen=True) plotter.add_mesh( m.grid, style="wireframe", color="gray", opacity=0.35, label="undeformed", ) plotter.add_mesh( warped, scalars="displacement_magnitude", show_edges=True, cmap="viridis", scalar_bar_args={"title": "|u| [m]"}, label="deformed ×20", ) plotter.add_legend() plotter.add_axes() plotter.camera_position = [(2.4, -1.6, 1.0), (0.5, 0.05, 0.0), (0.0, 0.0, 1.0)] plotter.show() .. image-sg:: /gallery/analyses/static/images/sphx_glr_example_cantilever_plate_001.png :alt: example cantilever plate :srcset: /gallery/analyses/static/images/sphx_glr_example_cantilever_plate_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.376 seconds) .. _sphx_glr_download_gallery_analyses_static_example_cantilever_plate.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: example_cantilever_plate.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: example_cantilever_plate.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: example_cantilever_plate.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_