Resonances of a beam clamped at one end
Eigenmodes
3D
Comparison with beam theory
This example is adapted from (legacy Fenics):
where extensive explanations are given. Here we show how
elastodynamicsx
can be used to reproduce it.It is also inspired from (Fenicsx):
[1]:
import numpy as np
from dolfinx import mesh, fem, default_scalar_type
from mpi4py import MPI
from elastodynamicsx.pde import material, boundarycondition, PDE
from elastodynamicsx.solvers import EigenmodesSolver
from elastodynamicsx.utils import make_facet_tags
FE domain
[2]:
L_, B_, H_ = 20., 0.5, 1. # Lengths
# Nb of elts.
Nx = 20
Ny = int(B_ / L_ * Nx) + 1
Nz = int(H_ / L_ * Nx) + 1
extent = [[0., 0., 0.], [L_, B_, H_]]
# create the mesh
domain = mesh.create_box(MPI.COMM_WORLD, extent, [Nx, Ny, Nz])
# create the function space
V = fem.functionspace(domain, ("Lagrange", 2, (domain.geometry.dim,)))
# define some tags
tag_left, tag_top, tag_right, tag_bottom, tag_back, tag_front = 1, 2, 3, 4, 5, 6
boundaries = [(tag_left , lambda x: np.isclose(x[0], 0.)),
(tag_right , lambda x: np.isclose(x[0], L_)),
(tag_bottom, lambda x: np.isclose(x[1], 0.)),
(tag_top , lambda x: np.isclose(x[1], B_)),
(tag_back , lambda x: np.isclose(x[2], 0.)),
(tag_front , lambda x: np.isclose(x[2], H_))]
facet_tags = make_facet_tags(domain, boundaries)
Boundary condition
Clamp the left face of the beam
[3]:
bc_clamp = boundarycondition((V, facet_tags, tag_left), 'Clamp')
Define the material law
isotropic elasticity
[4]:
# Parameters here...
E, nu = 1e5, 0.
rho = 1e-3
# ... end
# Scaling
scaleRHO = 1e6 # a scaling factor to avoid blowing the solver
scaleFREQ = np.sqrt(scaleRHO) # the frequencies must be scaled accordingly
rho *= scaleRHO
# Convert Young & Poisson to Lamé's constants
lambda_ = E * nu / (1 + nu) / (1 - 2 * nu)
mu = E / 2 / (1 + nu)
# Convert floats to fem.Constant
rho = fem.Constant(domain, default_scalar_type(rho))
lambda_ = fem.Constant(domain, default_scalar_type(lambda_))
mu = fem.Constant(domain, default_scalar_type(mu))
material = material(V, 'isotropic', rho, lambda_, mu)
Assemble the PDE
[5]:
pde = PDE(V, materials=[material], bodyforces=[], bcs=[bc_clamp])
Solve
[6]:
# ## Initialize the solver; prepare to solve for 6 eigenvalues
M = pde.M() # mass matrix (PETSc)
C = None # None to ensure no damping
K = pde.K() # stiffness matrix (PETSc)
eps = EigenmodesSolver(V.mesh.comm, M, C, K, nev=6)
[7]:
# ## Run the big calculation!
eps.solve()
# ## End of big calc.
[8]:
# ## Get the result
# eps.printEigenvalues()
eigenfreqs = eps.getEigenfrequencies()
# eigenmodes = eps.getEigenmodes()
eps.plot(V, wireframe=True, factor=50)
Compare with beam theory
\(\omega_n = \alpha_n^2 \sqrt{\frac{E I}{\rho S L^4}}\), with \(S\) the cross section, \(I\) the bending inertia, and \(\alpha_n\) the \(n^\mathrm{th}\) solution of \(\cos\alpha \cosh\alpha +1 =0\).
[9]:
# Exact solution computation
from scipy.optimize import root
from math import cos, cosh
falpha = lambda x: cos(x) * cosh(x) + 1
alpha = lambda n: root(falpha, (2 * n + 1) * np.pi / 2)['x'][0]
[10]:
nev = eigenfreqs.size
I_bend = H_ * B_**3 / 12 * (np.arange(nev) % 2 == 0) + B_ * H_**3 / 12 * (np.arange(nev) % 2 == 1)
freq_beam = np.array([alpha(i // 2) for i in range(nev)])**2 \
* np.sqrt(E * I_bend / (rho.value * B_ * H_ * L_**4)) / 2 / np.pi
[11]:
print('Eigenfrequencies: comparison with beam theory\n')
print('mode || FE (Hz)\t|| Beam theory (Hz)\t|| Difference (%)')
for n in range(len(eigenfreqs)):
fe = eigenfreqs[n] * scaleFREQ
bt = freq_beam[n] * scaleFREQ
print(f'{n+1} || {fe:.4f}\t|| {bt:.4f} \t|| {100*(fe-bt)/fe:.1f}')
Eigenfrequencies: comparison with beam theory
mode || FE (Hz) || Beam theory (Hz) || Difference (%)
1 || 2.0190 || 2.0193 || -0.0
2 || 4.0324 || 4.0385 || -0.2
3 || 12.6452 || 12.6544 || -0.1
4 || 25.0451 || 25.3089 || -1.1
5 || 35.3717 || 35.4328 || -0.2
6 || 68.8365 || 70.8655 || -2.9