Note
Go to the end to download the full example code.
Beam3#
A bi-fixed beam undergoing bending deformation.
Beam: section uses linear TRI3 elements — _Get_shear_correction_factor converges at O(h²). Use TRI6 / QUAD8 (or finer mesh) for accurate k.
err uy: 1.99e-11%
err Mz : 1.17e-11 %
err Ty : 1.43e-11 %
==================== Mesh ====================
Element type: SEG3
Ne = 10, Nn = 21
==================== Model ====================
<EasyFEA.Models.Beam._beam.BeamStructure object at 0x70da16ec4890>
solver:scipy
============= Boundary Conditions =============
Unspecified.
=================== Results ===================
Ux max = -0.00e+00
Ux min = -0.00e+00
Uy max = 0.00e+00
Uy min = -3.61e-03
=================== TicTac ===================
Mesh: 43.347 ms
Boundary Conditions: 32.187 µs
Matrix: 26.042 ms
Solver: 3.408 ms
Display: 54.334 ms
13 import matplotlib.pyplot as plt
14 import numpy as np
15
16 from EasyFEA import Display, Models, Mesher, ElemType, Simulations
17 from EasyFEA.Geoms import Line, Point, Points
18
19 if __name__ == "__main__":
20 Display.Clear()
21
22 # ----------------------------------------------
23 # Configuration
24 # ----------------------------------------------
25
26 # geom
27 L = 120
28 h = 20
29 b = 13
30 e = 2
31
32 # model
33 E = 210000
34 v = 0.3
35 beamDim = 2 # must be >= 2
36
37 # load
38 F = -800
39
40 # ----------------------------------------------
41 # Section
42 # ----------------------------------------------
43
44 def DoSym(p: Point, n: np.ndarray) -> Point:
45 pc = p.copy()
46 pc.Symmetry(n=n)
47 return pc
48
49 p1 = Point(-b / 2, -h / 2)
50 p2 = Point(b / 2, -h / 2)
51 p3 = Point(b / 2, -h / 2 + e)
52 p4 = Point(e / 2, -h / 2 + e, r=e)
53 p5 = DoSym(p4, (0, 1))
54 p6 = DoSym(p3, (0, 1))
55 p7 = DoSym(p2, (0, 1))
56 p8 = DoSym(p1, (0, 1))
57 p9 = DoSym(p6, (1, 0))
58 p10 = DoSym(p5, (1, 0))
59 p11 = DoSym(p4, (1, 0))
60 p12 = DoSym(p3, (1, 0))
61 contour = Points([p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12], e / 3)
62 section = Mesher().Mesh_2D(contour, elemType=ElemType.TRI3)
63
64 # ----------------------------------------------
65 # Mesh
66 # ----------------------------------------------
67
68 p1 = Point()
69 pL = Point(x=L * 0.75)
70 p2 = Point(x=L)
71 line = Line(p1, p2, L / 9)
72 beam = Models.Beam.Isotropic(beamDim, line, section, E, v)
73
74 mesh = Mesher().Mesh_Beams([beam], additionalPoints=[pL])
75
76 # ----------------------------------------------
77 # Simulation
78 # ----------------------------------------------
79
80 # Initialize the beam structure with the defined beam segments
81 beamStructure = Models.Beam.BeamStructure([beam])
82
83 # Create the beam simulation
84 simu = Simulations.Beam(mesh, beamStructure)
85 dof_n = simu.Get_dof_n()
86
87 # Apply boundary conditions
88 simu.add_dirichlet(mesh.Nodes_Point(p1), [0] * dof_n, simu.Get_unknowns())
89 simu.add_dirichlet(mesh.Nodes_Point(p2), [0] * dof_n, simu.Get_unknowns())
90 simu.add_neumann(mesh.Nodes_Point(pL), [F], ["y"])
91
92 # Solve the beam problem and get displacement results
93 sol = simu.Solve()
94 simu.Save_Iter()
95
96 # ----------------------------------------------
97 # Results
98 # ----------------------------------------------
99
100 Display.Plot_Mesh(simu, L / 20 / sol.min())
101 ax = Display.Plot_Mesh(section)
102 ax.set_title("Section")
103 Display.Plot_BoundaryConditions(simu)
104 Display.Plot_Result(simu, "uy", L / 20 / sol.min())
105
106 # ------------------------
107 # uy
108 # ------------------------
109
110 # beam properties
111 Iz = beam.Iz
112 G = beam.mu
113 A = section.area
114
115 # general reactions and fixed-end moment (valid for arbitrary pL.x)
116 a = pL.x
117 b = L - a
118 Ra = -F * b**2 * (3 * a + b) / L**3 # upward reaction at x=0
119 Rb = -F * a**2 * (a + 3 * b) / L**3 # upward reaction at x=L
120 Ma = F * a * b**2 / L**2 # fixed-end moment at x=0
121
122 x = np.linspace(0, L, 100)
123 x_n = mesh.coord[:, 0]
124 x_e = x_n[mesh.connect].mean(1) # element centroid x-coords
125
126 def uy_x(x):
127 x = np.asarray(x)
128 macaulay = np.where(x > a, (x - a) ** 3 / 6, 0.0)
129 return (Ma / 2 * x**2 + Ra / 6 * x**3 + F * macaulay) / (E * Iz)
130
131 uy = simu.Result("uy")
132 err_uy = np.abs(uy_x(x_n) - uy).max() / np.abs(uy_x(a))
133 Display.MyPrint(f"\nerr uy: {err_uy * 100:.2e}%")
134
135 ax_uy = Display.Init_Axes()
136 ax_uy.plot(x, uy_x(x), label="Analytical", c="blue")
137 ax_uy.scatter(x_n, uy, label="FE", c="red", marker="x", zorder=2)
138 ax_uy.set_title("$u_y(x)$")
139 ax_uy.legend()
140
141 # ------------------------
142 # Mz
143 # ------------------------
144
145 def Mz_x(x):
146 x = np.asarray(x)
147 Ma_plus_Ra_x = Ma + Ra * x
148 return np.where(x <= a, Ma_plus_Ra_x, Ma_plus_Ra_x + F * (x - a))
149
150 Mz = simu.Result("Mz", nodeValues=False)
151 err_Mz = np.abs(Mz_x(x_e) - Mz).max() / np.abs(Mz_x(x_e)).max()
152 Display.MyPrint(f"\nerr Mz : {err_Mz * 100:.2e} %")
153
154 axMz = Display.Init_Axes()
155 axMz.plot(x, Mz_x(x), label="Analytical", c="blue")
156 axMz.scatter(x_e, Mz, label="FE", c="red", marker="x", zorder=2)
157 axMz.set_title("$M_z(x)$")
158 axMz.legend()
159
160 # ------------------------
161 # Ty
162 # ------------------------
163
164 def Ty_x(x):
165 x = np.asarray(x)
166 return np.where(x < a, -Ra, Rb)
167
168 Ty = simu.Result("Ty", nodeValues=False)
169 err_Ty = np.abs(Ty_x(x_e) - Ty).max() / max(Ra, Rb)
170 Display.MyPrint(f"\nerr Ty : {err_Ty * 100:.2e} %")
171
172 ax_Ty = Display.Init_Axes()
173 ax_Ty.step(x, Ty_x(x), label="Analytical", c="blue", where="mid")
174 ax_Ty.scatter(x_e, Ty, label="FE", c="red", marker="x", zorder=2)
175 ax_Ty.set_title("$T_y(x)$")
176 ax_Ty.legend()
177
178 print(simu)
179
180 plt.show()
Total running time of the script: (0 minutes 0.565 seconds)






