#
##
## SPDX-FileCopyrightText: © 2007-2024 Benedict Verhegghe <bverheg@gmail.com>
## SPDX-License-Identifier: GPL-3.0-or-later
##
## This file is part of pyFormex 3.5 (Thu Feb 8 19:11:13 CET 2024)
## pyFormex is a tool for generating, manipulating and transforming 3D
## geometrical models by sequences of mathematical operations.
## Home page: https://pyformex.org
## Project page: https://savannah.nongnu.org/projects/pyformex/
## Development: https://gitlab.com/bverheg/pyformex
## Distributed under the GNU General Public License version 3 or later.
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see http://www.gnu.org/licenses/.
##
"""beam2d: A 2d beam finite element
"""
import numpy as np
class Beam2d:
@staticmethod
def mass(rho, A, l):
l = float(l)
l2 = l*l
M = np.array([
[ 156 , 22*l , 54 , -13*l ], # noqa: 201,203
[ 22*l, 4*l2, 13*l, -3*l2 ], # noqa: 201,203
[ 54 , 13*l , 156 , -22*l ], # noqa: 201,203
[ -13*l, -3*l2, -22*l, 4*l2 ]]) # noqa: 201,203
M *= rho * A * l / 420
return M
@staticmethod
def stiff(E, I, l):
l = float(l)
EIl = E*I/l
b4 = 2 * EIl
b3 = 2 * b4
b2 = 3 * b4 / l
b1 = 2 * b2 / l
K = np.array([
[ b1, b2, -b1, b2 ], # noqa: 201,203
[ b2, b3, -b2, b4 ], # noqa: 201,203
[ -b1, -b2, b1, -b2 ], # noqa: 201,203
[ b2, b4, -b2, b3 ]]) # noqa: 201,203
return K
# units are N, m, kg, s
class steel():
E = 210.e9
class IPE100():
rho = 8.26 # kg/m
A = 1032.e-6
I = 171.e-12
[docs]def cantilever_frequencies(rho, A, l, E, I):
"""First 6 eigenfrequencies of cantilever beam
These are high precision results from analytical formulas.
"""
c = np.sqrt(E*I/(rho*A)) / (l*l)
coeffs = np.array([
1.875104069,
4.694091133,
7.854757438,
10.99554073,
14.13716839,
17.27875953])
return c * coeffs**2 / 2 / np.pi
[docs]def assemble(Ke, Me, ne):
"""Assemble beam of ne identical elements Ke, Me"""
n = 2*(ne+1)
K = np.zeros((n, n))
M = np.zeros((n, n))
for ie in range(ne):
i = 2*ie
K[i:i+4, i:i+4] += Ke
M[i:i+4, i:i+4] += Me
return K, M
[docs]def createBeam(lt, nel, addbc=True):
"""Create stiffness and mass matrices of a simple beam.
lt: length of the beam (m)
nel: number of element to use along the beam length
addbc: if True, add cantilever boundary conditions
"""
# element length
l = lt / nel
# create element stiffness and mass matrix
Ke = Beam2d.stiff(steel.E, IPE100.I, l)
Me = Beam2d.mass(IPE100.rho, IPE100.A, l)
# assemble the global stiffness and mass matrix
K, M = assemble(Ke, Me, nel)
if addbc:
# Impose cantilever boundary conditions
# This is done by adding a very stiff translational
# and rotational spring to the first node:
VERY_STIFF = 1.e4
K[0, 0] *= (1.+VERY_STIFF)
K[1, 1] *= (1.+VERY_STIFF)
return K, M
# End