BeamC - Consistent Timoshenko 3D beam element (pyfe3d.beamc)#
Defines the two-node beam element BeamC, with six
degrees-of-freedom per node, its probe BeamCProbe and
BeamCData, which gives the number of sparse entries per element of
each structural matrix. The cross-section and material properties are given
by a BeamProp object.
- class pyfe3d.beamc.BeamC#
Timoshenko 3D beam element with consistent shape functions
Nodal connectivity for the beam element:
^ y axis | | ______ --> x axis 1 2
The constructor stores
pinprobe, setseid,pid,n1,n2,c1andc2to-1, and sets theinit_k_*positions,length,vxyi,vxyj,vxykand the rotation matrix to0. The methods use the attributes updated by the others:update_rotation_matrix()readsc1andc2;update_probe_xe()reads the rotation matrix and updateslength; theupdate_K*,update_M()andupdate_probe_finte()methods readlengthand the rotation matrix;update_KG(),update_KCNL()andupdate_probe_finte()also readprobe.ue, updated byupdate_probe_ue().- Parameters:
- p
BeamCProbeobject Probe of the element, stored in
probe. It can be shared with other elements.
- p
- Attributes:
- eid,int
Element identification number.
- pid,int
Property identification number.
- length,double
Element length, dimension length. Updated by
update_length().- r11, r12, r13, r21, r22, r23, r31, r32, r33double
Entries \(T_{ij}\) of the transformation matrix \(\boldsymbol{T}_{3\times 3}\) from element to global coordinates, whose columns are the element axes. Dimensionless.
- vxyi, vxyj, vxykdouble
Components of a vector on the \(XY\) plane of the element coordinate system, defined using global coordinates. Only the direction of the vector is used.
- c1, c2int
Position of each node in the global stiffness matrix, i.e. of the first of its
6degrees-of-freedom. The coordinates of the node are read from the positionc1//2orc2//2of the array of nodal coordinates.- n1, n2int
Node identification number.
- init_k_KC0, init_k_KCNL, init_k_KG, init_k_Mint
Position in the arrays storing the sparse data for the structural matrices, where the entries of this element start, see
BeamCDatafor their number.- probe,
BeamCProbeobject Pointer to the probe.
Methods
update_KC0(self, long[, long[, double[, ...)Update sparse vectors for linear constitutive stiffness matrix KC0
update_KCNL(self, long[, long[, double[, ...)Update sparse vectors for the nonlinear stiffness matrix KCNL
update_KG(self, long[, long[, double[, ...)Update sparse vectors for geometric stiffness matrix KG
update_M(self, long[, long[, double[, ...)Update sparse vectors for mass matrix M
update_fint(self, double[, BeamProp prop, ...)Update the internal force vector
update_length(self)Update element length
update_probe_finte(self, BeamProp prop, ...)Update the internal force vector of the probe
update_probe_ue(self, double[)Update the local displacement vector of the probe of the element
update_probe_xe(self, double[)Update the 3D coordinates of the probe of the element
update_rotation_matrix(self, double vxyi, ...)Update the rotation matrix of the element
Notes
Formulation based on reference [1].
The cross section is rigid. In the element coordinate system, whose \(x\) axis is the beam axis, the displacements of the point \((y, z)\) of the cross section are
\[u_x = u - y r_z + z r_y, \qquad u_y = v - z r_x, \qquad u_z = w + y r_x\]where \(u, v, w, r_x, r_y, r_z\) are the translations and rotations of the beam axis, interpolated from the 12 element displacements
ue. The axial strain, with the curvatures \(\kappa_y\) and \(\kappa_z\), and the transverse shear strains of the beam axis are\[\epsilon_{xx} = u_{,x} + y \kappa_y + z \kappa_z, \qquad \kappa_y = -{r_z}_{,x}, \qquad \kappa_z = {r_y}_{,x}, \qquad \gamma_{xy} = v_{,x} - r_z, \qquad \gamma_{xz} = w_{,x} + r_y\]and, with the twist \(\kappa_x = {r_x}_{,x}\), the linear strain energy is
\[U = \frac{1}{2} \int_0^L \boldsymbol{\epsilon}^\top \boldsymbol{C} \boldsymbol{\epsilon} \, dx, \qquad \boldsymbol{\epsilon} = \{u_{,x}, \gamma_{xy}, \gamma_{xz}, \kappa_x, \kappa_y, \kappa_z\}^\top\]where \(L\) is
lengthand \(\boldsymbol{C}\) is the sectional stiffness matrixCofBeamProp, of entries \(C_{ij}\), \(i, j = 0, \ldots, 5\), in the order of \(\boldsymbol{\epsilon}\), symmetric, with 21 independent entries; seeBeamPropfor its relation to the stiffness matrices ofpyfe3d.vabs. WhenCis not set, it is built from the cross-section integrals ofBeamProp, and\[\begin{split}U = \frac{1}{2} \int_0^L \Big[ E \left( A u_{,x}^2 + I_{zz} \kappa_y^2 + I_{yy} \kappa_z^2 + 2 A_y u_{,x} \kappa_y + 2 A_z u_{,x} \kappa_z + 2 I_{yz} \kappa_y \kappa_z \right) \\ + G_{12} \left( A \gamma_{xy}^2 - 2 A_z \gamma_{xy} {r_x}_{,x} \right) + G_{13} \left( A \gamma_{xz}^2 + 2 A_y \gamma_{xz} {r_x}_{,x} \right) + G J {r_x}_{,x}^2 \Big] dx\end{split}\]where \(G_{12}\) =
G12and \(G_{13}\) =G13are the transverse shear moduli of the planes \(xy\) and \(xz\), and \(G J\) =GJis the torsional stiffness, seeBeamProp. The torsion is of Saint-Venant type, without warping, withGJin place of the torsional stiffness \(G_{12} I_{yy} + G_{13} I_{zz}\) of the rigid cross section, and no shear correction factor is applied. The axial force is the first entry of \(\boldsymbol{C} \boldsymbol{\epsilon}\), \(N = C_{00} u_{,x} + C_{01} \gamma_{xy} + C_{02} \gamma_{xz} + C_{03} \kappa_x + C_{04} \kappa_y + C_{05} \kappa_z\), i.e. \(N = E (A u_{,x} + A_y \kappa_y + A_z \kappa_z)\) withoutC.When the only non-zero off-diagonal entry of \(\boldsymbol{C}\) is the extension-twist coupling \(C_{03}\), e.g. without
Cand withAy,AzandIyzequal to zero, \(u\) and \(r_x\) are interpolated linearly between the nodes, and \(v\) and \(r_z\) are interpolated with the consistent shape functions of [1], cubic for \(v\) and quadratic for \(r_z\), which depend on the parameters\[\alpha_y = -\frac{12 C_{44}}{C_{11} L^2}, \qquad \alpha_z = -\frac{12 C_{55}}{C_{22} L^2}, \qquad \beta_y = \frac{1}{1 - \alpha_y}, \qquad \beta_z = \frac{1}{1 - \alpha_z}\]named
alphay,alphaz,betayandbetazin the code, taken from the diagonal of \(\boldsymbol{C}\); withoutC, \(\alpha_y = -12 E I_{zz}/(G_{12} A L^2)\) and \(\alpha_z = -12 E I_{yy}/(G_{13} A L^2)\). With \(\xi = x/L\) and the nodal values \(v_1, {r_z}_1, v_2, {r_z}_2\):\[\begin{split}v = \left[1 + \beta_y (2\xi^3 - 3\xi^2 + \alpha_y \xi)\right] v_1 + L \beta_y \left(\xi^3 + \frac{\alpha_y - 4}{2} \xi^2 + \left(1 - \frac{\alpha_y}{2}\right) \xi \right) {r_z}_1 \\ + \beta_y (-2\xi^3 + 3\xi^2 - \alpha_y \xi) v_2 + L \beta_y \left(\xi^3 - \frac{\alpha_y + 2}{2} \xi^2 + \frac{\alpha_y}{2} \xi \right) {r_z}_2\end{split}\]\[r_z = \frac{6 \beta_y}{L} (\xi^2 - \xi) (v_1 - v_2) + \left[1 + \beta_y (3\xi^2 + (\alpha_y - 4) \xi)\right] {r_z}_1 + \beta_y (3\xi^2 - (\alpha_y + 2) \xi) {r_z}_2\]\(w\) and \(r_y\) use the same functions, with \(v\) replaced by \(w\), \(r_z\) by \(-r_y\), \(\alpha_y\) by \(\alpha_z\) and \(\beta_y\) by \(\beta_z\). The transverse shear strains are then constant along the element, e.g. \(\gamma_{xy} = \alpha_y \beta_y \left((v_1 - v_2)/L + ({r_z}_1 + {r_z}_2)/2\right)\), and they vanish with \(\alpha_y = 0\), i.e. with an infinite
G12, where the interpolation of \(v\) becomes the cubic Hermite interpolation of the Euler-Bernoulli beam.The parameters \(\alpha_y\) and \(\alpha_z\) are negative. With \(\phi_y = 12 C_{44}/(C_{11} L^2)\), \(\beta_y = 1/(1 + \phi_y)\) and the functions above are the general solution of the homogeneous equilibrium equations of the strain energy above with a diagonal \(\boldsymbol{C}\), \((C_{11} \gamma_{xy})_{,x} = 0\) and \(C_{11} \gamma_{xy} = C_{44} {\kappa_y}_{,x}\), i.e. \(G_{12} A \gamma_{xy} = E I_{zz} {\kappa_y}_{,x}\) (and likewise for \(w\), \(r_y\), with \(C_{22}\) and \(C_{55}\)), which these functions satisfy for any nodal values only with this sign. The same solution is Eq. (17) of [1] and Eq. (3.236) of [2], whose denominator \(1 + 3\beta\), with \(\beta = E I/(\kappa A G a^2)\), where \(\kappa G\) is \(G_{12}\), and \(a = L/2\), is \(1 + \phi_y\); Eq. (21) of [1] gives \(\alpha_y\) and \(\alpha_z\) with the positive sign, inconsistent with its Eqs. (17) and (20), and its Eq. (20) prints the functions of \(w\) and \(r_y\) with the signs of those of \(v\) and \(r_z\), which, with \(\alpha_z = 0\), give \(r_y = w_{,x}\) instead of the \(r_y = -w_{,x}\) of the kinematics above. \(\beta_y\), \(\beta_z\) are finite for any length. The mass and geometric stiffness matrices use the same shape functions.
Shape functions with couplings (derived here). The functions above solve the equilibrium equations for any nodal values only when the only coupling is \(C_{03}\), with which \(u_{,x}\) and \(\kappa_x\) are constant. With any other coupling, including those of
Ay,AzandIyzwhenCis not set, the shape functions are derived from the same equations with the full \(\boldsymbol{C}\). For a prismatic element loaded only at its nodes, the virtual work of the strain energy above gives the equilibrium \(N_{,x} = {V_y}_{,x} = {V_z}_{,x} = {M_x}_{,x} = 0\), \({M_4}_{,x} = V_y\), \({M_5}_{,x} = V_z\) of the sectional forces \(\boldsymbol{C} \boldsymbol{\epsilon} = \{N, V_y, V_z, M_x, M_4, M_5\}^\top\), hence\[\boldsymbol{C} \boldsymbol{\epsilon} = (\boldsymbol{I} + x \boldsymbol{Z}) \boldsymbol{q}, \qquad \boldsymbol{\epsilon} = \boldsymbol{S} (\boldsymbol{I} + x \boldsymbol{Z}) \boldsymbol{q}, \qquad \boldsymbol{q} = \{N, V_y, V_z, M_x, M_4(0), M_5(0)\}^\top\]with \(\boldsymbol{S} = \boldsymbol{C}^{-1}\) and the only non-zero entries \(Z_{41} = Z_{52} = 1\). Integrating the kinematic relations from node 1, \(u = \int \epsilon_0 dx\), \(r_x = \int \epsilon_3 dx\), \(r_z = -\int \epsilon_4 dx\), \(r_y = \int \epsilon_5 dx\), \(v = \int (\epsilon_1 + r_z) dx\) and \(w = \int (\epsilon_2 - r_y) dx\), and adding the rigid-body motion of node 1 gives \(\boldsymbol{d} = \boldsymbol{R}(x) \boldsymbol{u}_1 + \boldsymbol{P}(x) \boldsymbol{q}\), with \(\boldsymbol{d} = \{u, v, w, r_x, r_y, r_z\}^\top\), quadratic in \(x\) for \(u, r_x, r_y, r_z\) and cubic for \(v, w\), with coefficients that depend on all entries of \(\boldsymbol{S}\). The statics of the element clamped at node 1 give \(\boldsymbol{q} = \boldsymbol{T} \boldsymbol{P}_2\) for the loads \(\boldsymbol{P}_2\) at node 2, and \(\boldsymbol{F}_c = \boldsymbol{P}(L) \boldsymbol{T}\) is the flexibility of this cantilever, symmetric and positive definite. With \(\boldsymbol{u}_2 = \boldsymbol{R}(L) \boldsymbol{u}_1 + \boldsymbol{P}(L) \boldsymbol{q}\):
\[\boldsymbol{q} = \boldsymbol{H}_f \boldsymbol{u}_e, \qquad \boldsymbol{H}_f = \boldsymbol{T} \boldsymbol{F}_c^{-1} \boldsymbol{G}, \qquad \boldsymbol{d} = \left( [\boldsymbol{R}(x), \boldsymbol{0}] + \boldsymbol{P}(x) \boldsymbol{H}_f \right) \boldsymbol{u}_e, \qquad \boldsymbol{K}_{C0_e} = \boldsymbol{G}^\top \boldsymbol{F}_c^{-1} \boldsymbol{G}\]where \(\boldsymbol{G} = [-\boldsymbol{R}(L), \boldsymbol{I}]\). \(\boldsymbol{K}_{C0_e}\) is the Hessian of the strain energy with these shape functions, the axial force \(N = q_0\) is uniform along the element, and the mass, geometric and nonlinear matrices are integrated analytically with the same polynomial shape functions. With \(C_{03}\) as the only coupling they are the functions of [1] above, asserted symbolically in
theory/deriving_equations/beamc/derive_beamc_coupled_shape_functions.py, whose closed-form expressions are then used, unchanged. Otherwise \(\boldsymbol{S}\), \(\boldsymbol{F}_c^{-1}\), \(\boldsymbol{H}_f\) and the coefficients of the shape functions are evaluated numerically for each element and call, fromC, which must then be positive definite, otherwise aValueErroris raised. This evaluation reproduces the arrays of the closed-form expressions to 1.3e-14 of their largest entries, seetests/test_beam_sectional_stiffness.py, and costs about 4 to 7 µs more per element and call than the 1.5 to 2 µs ofupdate_KC0,update_M,update_KGandupdate_fintwith the closed-form expressions (measured on 2026-10-31, Windows, calls from Python).The element is therefore exact under nodal loads for any \(\boldsymbol{C}\): one element gives the tip displacements of a cantilever under any tip load, measured in
tests/test_beam_sectional_stiffness.pyto 2.7e-15 of the largest for each single coupling \(C_{ij} = 0.3 \sqrt{C_{ii} C_{jj}}\) of a rectangular section, 50 mm by 30 mm, 0.5 m long, to 2.0e-15 for a \(\boldsymbol{C}\) with 21 non-zero entries and to 5.4e-16 for a composite box beam with extension-twist and bending-shear couplings, against up to 8.9e-2 and 0.42 with the functions of [1] taken from the diagonal of \(\boldsymbol{C}\).BeamLR, whose interpolation does not depend on \(\boldsymbol{C}\), converges as the square of the element length, e.g. 8.3e-2, 5.2e-3 and 3.3e-4 with 1, 4 and 16 elements for the coupling \(C_{15}\) under a transverse tip load.The sign is verified against the literature in
tests/test_timoshenko_beam_literature.py: one element reproduces the cantilever tip deflection \(P L^3/(3 E I_{zz}) + P L/(G A)\) of Eq. (1.2) of [3] (0.053 cm) and, for a cantilever as long as deep, the same formula, where the shear deflection is larger than the bending one; one element reproduces the frequency coefficients3.322and26.569of Example 3.10 of [2], which has the same shape functions and consistent mass matrix with rotary inertia, three elements the errors of Table 3.6 of [2], and refined meshes its exact frequencies. With the positive sign these tests fail, e.g. by -44 % for the deep cantilever and with3.952instead of3.322. Intests/test_beam_shear_moduli.py, with differentG12andG13, the same tip deflection and frequencies are obtained in each plane with its own modulus, \(G = G_{12}\) with \(I_{zz}\) for \(v\) and \(G = G_{13}\) with \(I_{yy}\) for \(w\).With
nonlinear=1inupdate_fint(), the geometric nonlinearity is that of the von Kármán axial strain, with its nonlinear part \((v_{,x}^2 + w_{,x}^2)/2\) replaced by its element mean, Crisfield [4], Section 7.1.3, Eqs. (7.31)-(7.32), and Crisfield [5], Section 17.1.5, Eqs. (17.56a)-(17.56b):\[\epsilon_{xx} = u_{,x} + \bar{\epsilon}_{NL} + y \kappa_y + z \kappa_z, \qquad \bar{\epsilon}_{NL} = \frac{1}{L} \int_0^L \frac{1}{2} \left( v_{,x}^2 + w_{,x}^2 \right) dx\]since the constant \(u_{,x}\) of the linear \(u\) cannot balance the pointwise value, of degree four in \(x\) with the cubic \(v\) and \(w\), which gives membrane locking [4]. The tangent stiffness matrix
KC0 + KCNL + KGis the exact Jacobian of the internal forces, seeupdate_KCNL()andupdate_KG(), whose axial force is the element mean of \(N\).The matrices and the internal forces are computed in element coordinates and transformed to global coordinates with the transformation matrix of the element, e.g. \(\boldsymbol{K} = \boldsymbol{T} \boldsymbol{K}_e \boldsymbol{T}^\top\), where \(\boldsymbol{T}\) is block diagonal with four copies of the matrix \(\boldsymbol{T}_{3\times 3}\) of the entries \(T_{ij}\) stored in
r11, ..., r33, whose columns are the element axes, one for the translations and one for the rotations of each node. The element coordinate system is not updated with the displacements.References
[1] (1,2,3,4,5,6)Luo, Y., 2008, “An Efficient 3D Timoshenko Beam Element with Consistent Shape Functions,” Adv. Theor. Appl. Mech., 1(3), pp. 95–106.
[2] (1,2,3)Petyt, M., 2010, Introduction to Finite Element Vibration Analysis, 2nd ed., Cambridge University Press, Section 3.9. https://doi.org/10.1017/CBO9780511761195
[3]Bathe, K. J., 2014, Finite Element Procedures, 2nd ed., K. J. Bathe, Watertown, MA, ISBN 978-0-9790049-5-7, Section 1.2, p. 5, Eq. (1.2), Fig. 1.2(b).
[4] (1,2)Crisfield, M. A., Non-linear Finite Element Analysis of Solids and Structures, Volume 1: Essentials, John Wiley & Sons, Chichester, 1991.
[5]Crisfield, M. A., Non-linear Finite Element Analysis of Solids and Structures, Volume 2: Advanced Topics, John Wiley & Sons, Chichester, 1997.
- c1#
c1: ‘int’
- c2#
c2: ‘int’
- eid#
eid: ‘int’
- init_k_KC0#
init_k_KC0: ‘int’
- init_k_KCNL#
init_k_KCNL: ‘int’
- init_k_KG#
init_k_KG: ‘int’
- init_k_M#
init_k_M: ‘int’
- length#
length: ‘double’
- n1#
n1: ‘int’
- n2#
n2: ‘int’
- pid#
pid: ‘int’
- probe#
probe: pyfe3d.beamc.BeamCProbe
- r11#
r11: ‘double’
- r12#
r12: ‘double’
- r13#
r13: ‘double’
- r21#
r21: ‘double’
- r22#
r22: ‘double’
- r23#
r23: ‘double’
- r31#
r31: ‘double’
- r32#
r32: ‘double’
- r33#
r33: ‘double’
- update_KC0(self, long[: :1] KC0r, long[: :1] KC0c, double[: :1] KC0v, BeamProp prop, int update_KC0v_only=0) void#
Update sparse vectors for linear constitutive stiffness matrix KC0
The 144 entries of the matrix of the element, in global coordinates, are written at the positions
init_k_KC0toinit_k_KC0 + 143: the row and column indices, built fromc1andc2, are stored inKC0randKC0c, and the values are added to those already inKC0v. The matrix is computed fromlength, the rotation matrix and the sectional stiffness matrixCofprop, seeBeamProp.lengthand the rotation matrix must be updated before, seeupdate_rotation_matrix()andupdate_probe_xe().- Parameters:
- KC0rnp.array
Array to store row positions of sparse values. 1-D array of integers of the C type
long, of size at leastinit_k_KC0 + 144.- KC0cnp.array
Array to store column positions of sparse values. Same type and size as
KC0r.- KC0vnp.array
Array to store sparse values. 1-D array of floats of size at least
init_k_KC0 + 144.- prop
BeamPropobject Beam property object from where the stiffness and mass attributes are read from.
- update_KC0v_onlyint, optional
The default
0means that the row and column indicesKC0randKC0cshould also be updated. Any other value will only update the stiffness matrix valuesKC0v.
Notes
KC0is the Hessian, with respect to the element displacementsue, of the linear strain energy given in the notes ofBeamC, integrated analytically along the element with the consistent shape functions, and transformed to global coordinates as described there. With couplings inCother thanC[0, 3]it is \(\boldsymbol{G}^\top \boldsymbol{F}_c^{-1} \boldsymbol{G}\), from the flexibility of the element clamped at node 1, evaluated numerically, see “Shape functions with couplings” in the notes ofBeamC;Cmust then be positive definite, otherwise aValueErroris raised.
- update_KCNL(self, long[: :1] KCNLr, long[: :1] KCNLc, double[: :1] KCNLv, BeamProp prop, int update_KCNLv_only=0) void#
Update sparse vectors for the nonlinear stiffness matrix KCNL
The matrix, evaluated at the displacements
probe.ue, is computed fromlength, the rotation matrix and the attributes ofpropread by_update_probe_KCNLve(). The tangent stiffness matrix of the internal forces ofupdate_fint()withnonlinear=1isKC0 + KCNL + KG, seeupdate_KC0()andupdate_KG().Before this function is called, the probe
BeamCProbeattribute of theBeamCobject must be updated usingupdate_probe_ue()with the current displacements; andupdate_probe_xe()with the node coordinates.The 144 entries of the matrix of the element, in global coordinates, are written at the positions
init_k_KCNLtoinit_k_KCNL + 143: the row and column indices, built fromc1andc2, are stored inKCNLrandKCNLc, and the values are added to those already inKCNLv. The matrix in element coordinates is also stored inprobe.KCNLve, overwriting it.- Parameters:
- KCNLrnp.array
Array to store row positions of sparse values. 1-D array of integers of the C type
long, of size at leastinit_k_KCNL + 144.- KCNLcnp.array
Array to store column positions of sparse values. Same type and size as
KCNLr.- KCNLvnp.array
Array to store sparse values. 1-D array of floats of size at least
init_k_KCNL + 144.- prop
BeamPropobject Beam property object from where the stiffness and mass attributes are read from.
- update_KCNLv_onlyint, optional
The default
0means that the row and column indicesKCNLrandKCNLcshould also be updated. Any other value will only update the stiffness matrix valuesKCNLv.
Notes
KCNL = KC0L + KCL0 + KCLL + KGNL, that is \(\boldsymbol{K}_{CNL} + \boldsymbol{K}_{GNL}\), the nonlinear constitutive stiffness matrix \(\boldsymbol{K}_{CNL}\) of the terms of the nonlinear axial strain plus the geometric \(\boldsymbol{K}_{GNL}\) of the axial force of the nonlinear axial strain. Crisfield [1], Section 7.1.1, Eq. (7.24), keeps that axial force in the initial-stress matrix instead, that is in \(\boldsymbol{K}_G + \boldsymbol{K}_{GNL}\); the tangent stiffness matrix is the same. The axial strain is that of von Kármán with its nonlinear part replaced by the element mean, Crisfield [1], Section 7.1.3, Eqs. (7.31)-(7.32), and Crisfield [2], Section 17.1.5, Eqs. (17.56a)-(17.56b):
\[\epsilon_{xx} = u_{,x} + \bar{\epsilon}_{NL}, \qquad \bar{\epsilon}_{NL} = \frac{1}{L} \int_0^L \frac{1}{2} \left( v_{,x}^2 + w_{,x}^2 \right) dx = \frac{1}{2} \boldsymbol{u}_e^\top \boldsymbol{H}_m \boldsymbol{u}_e\]with \(\boldsymbol{H}_m\), the gradient \(\bar{\boldsymbol{B}}_{NL} = \boldsymbol{u}_e^\top \boldsymbol{H}_m\) and the row \(\overline{\boldsymbol{EB}}_L\) of the mean axial force of the linear strains given in
_update_means(). With \(\bar{N}_{NL} = C_{00} \bar{\epsilon}_{NL}\), \(C_{00}\) =C[0, 0]ofBeamProp, \(E A\) whenCis not set (own derivation, asserted intheory/deriving_equations/beamc/derive_beamc_KC0L_KCL0_KCLL_KGLL_sparse.py):KC0L = \(L \, \overline{\boldsymbol{EB}}_L^\top \bar{\boldsymbol{B}}_{NL}\)
KCL0 = KC0L`^top`
KCLL = \(L \, C_{00} \, \bar{\boldsymbol{B}}_{NL}^\top \bar{\boldsymbol{B}}_{NL}\)
KGNL = \(L \, \bar{N}_{NL} \boldsymbol{H}_m\)
The first three groups are the constitutive terms coupling the linear and the nonlinear parts of the axial strain. KGNL is geometric, carrying the axial force of the nonlinear axial strain. It is collected here so that
update_KG()stays homogeneous of degree one in the displacements, which is what a linear buckling analysis needs. With it here,\[\boldsymbol{K}_T = \boldsymbol{K}_{C0} + \boldsymbol{K}_{CNL}(\boldsymbol{u}) + \boldsymbol{K}_{GNL}(\boldsymbol{u}) + \boldsymbol{K}_G(\boldsymbol{u})\]is the exact, symmetric Jacobian of the internal forces of
update_fint()withnonlinear=1, and a Newton-Raphson iteration built on them converges quadratically.With \(u\) linear and \(v\), \(w\) cubic, the pointwise \((v_{,x}^2 + w_{,x}^2)/2\) is a polynomial of degree four in \(x\) that the constant \(u_{,x}\) cannot balance, so that the axial strain cannot vanish in inextensional bending and coarse meshes are too stiff (membrane locking, [1], Section 7.1.3). The element mean removes it; [1] justifies it with the Hu-Washizu principle and a constant membrane strain. With zero transverse nodal displacements, as in the local frame of a co-rotational element, and an infinite transverse shear stiffness, \(\bar{\epsilon}_{NL}\) is the term \(\boldsymbol{\theta}_l^\top \boldsymbol{X} \boldsymbol{\theta}_l/60\) of [2], Eq. (17.56a). The slopes \(v_{,x}\) and \(w_{,x}\) include the transverse shear strains, so that \(\alpha_y\), \(\beta_y\), \(\alpha_z\) and \(\beta_z\) enter \(\boldsymbol{H}_m\), or, with couplings in
Cother thanC[0, 3], all entries of \(\boldsymbol{C}^{-1}\), see_update_means(). The von Kármán axial strain is valid for small strains and moderate rotations: the nonlinear axial strain is uniform over the cross section and along the element, the curvatures and the transverse shear strains are linear in the displacements, and the element coordinate system is not updated with the displacements.References
- update_KG(self, long[: :1] KGr, long[: :1] KGc, double[: :1] KGv, BeamProp prop, int update_KGv_only=0) void#
Update sparse vectors for geometric stiffness matrix KG
The 144 entries of the matrix of the element, in global coordinates, are written at the positions
init_k_KGtoinit_k_KG + 143: the row and column indices, built fromc1andc2, are stored inKGrandKGc, and the values are added to those already inKGv. The matrix depends on the axial force computed from the displacementsprobe.ue, fromlengthand from the sectional stiffness matrixCofprop, seeBeamProp: its entriesC[0, 0],C[0, 3],C[1, 1],C[2, 2],C[4, 4]andC[5, 5]without other couplings, all of them otherwise.probe.ue,lengthand the rotation matrix must be updated before, seeupdate_probe_ue()andupdate_probe_xe().- Parameters:
- KGrnp.array
Array to store row positions of sparse values. 1-D array of integers of the C type
long, of size at leastinit_k_KG + 144.- KGcnp.array
Array to store column positions of sparse values. Same type and size as
KGr.- KGvnp.array
Array to store sparse values. 1-D array of floats of size at least
init_k_KG + 144.- prop
BeamPropobject Beam property object from where the stiffness and mass attributes are read from.
- update_KGv_onlyint, optional
The default
0means that the row and column indicesKGrandKGcare also updated. Any other value will only update the stiffness matrix valuesKGv.
Notes
The geometric stiffness matrix is
\[\boldsymbol{K}_G = N_m \int_0^L \left[ \left(\frac{\partial \boldsymbol{S}^v}{\partial x}\right)^\top \frac{\partial \boldsymbol{S}^v}{\partial x} + \left(\frac{\partial \boldsymbol{S}^w}{\partial x}\right)^\top \frac{\partial \boldsymbol{S}^w}{\partial x} \right] dx = L N_m \boldsymbol{H}_m\]the Hessian of \(L N_m \bar{\epsilon}_{NL}\) at a constant \(N_m\), where \(\partial \boldsymbol{S}^v / \partial x\) and \(\partial \boldsymbol{S}^w / \partial x\) give the slopes \(v_{,x}\) and \(w_{,x}\) with the consistent shape functions, \(\bar{\epsilon}_{NL}\) and \(\boldsymbol{H}_m\) are those of
update_KCNL()and\[N_m = \frac{1}{L} \int_0^L N dx\]is the element mean of the axial force of the linear strains, \(N = \boldsymbol{C}_{0,:} \boldsymbol{\epsilon}\), at
probe.ue, with the first row of the sectional stiffness matrix, see the notes ofBeamC. Without couplings inCother thanC[0, 3], \(N_m = (C_{00} (u_2 - u_1) + C_{03} ({r_x}_2 - {r_x}_1))/L\), i.e. \(E A (u_2 - u_1)/L\) whenCis not set andAy,AzandIyzare zero; with other couplings, \(N_m = q_0\), the first entry of \(\boldsymbol{q} = \boldsymbol{H}_f \boldsymbol{u}_e\), see “Shape functions with couplings” in the notes ofBeamC. The mean follows from the mean nonlinear axial strain ofupdate_KCNL(), with which the energy of the axial strain contains \(\int_0^L N dx \, \bar{\epsilon}_{NL}\), such thatKC0 + KCNL + KGis the exact Jacobian of the internal forces ofupdate_fint()withnonlinear=1(own derivation, asserted intheory/deriving_equations/beamc/derive_beamc_KC0L_KCL0_KCLL_KGLL_sparse.py); the geometric matrix of Crisfield [1], Eq. (7.95), also carries an axial force constant along the element. \(N_m\) is the axial force of the nodal internal forces,-finte[0] = finte[6]. Since the shape functions solve the equilibrium equations, \(N\) is uniform along the element for anyCand \(N_m = N\).\(\boldsymbol{K}_G\) is homogeneous of degree one in
probe.ue. Withprobe.uefrom the linear static solution of a reference load, the critical load multipliers \(\lambda\) of the linear buckling analysis solve \((\boldsymbol{K}_{C0} + \lambda \boldsymbol{K}_G) \boldsymbol{u} = \boldsymbol{0}\), seelinear_buckling(). The geometric term of the nonlinear axial strain is inupdate_KCNL().References
[1]Crisfield, M. A., Non-linear Finite Element Analysis of Solids and Structures, Volume 1: Essentials, John Wiley & Sons, Chichester, 1991.
- update_M(self, long[: :1] Mr, long[: :1] Mc, double[: :1] Mv, BeamProp prop, int mtype=0) void#
Update sparse vectors for mass matrix M
The entries of the matrix of the element, in global coordinates, are written from the position
init_k_M: 144 entries withmtype=0and 36 entries withmtype=1. The row and column indices, built fromc1andc2, are stored inMrandMc, and the values are added to those already inMv. The matrix is computed fromlength, the rotation matrix and the attributesintrho,intrhoy,intrhoz,intrhoy2,intrhoz2andintrhoyz, and the diagonal entriesC[1, 1],C[2, 2],C[4, 4]andC[5, 5]of the sectional stiffness matrix ofprop, or all its entries with couplings other thanC[0, 3]andmtype=0.lengthand the rotation matrix must be updated before, seeupdate_rotation_matrix()andupdate_probe_xe().- Parameters:
- Mrnp.array
Array to store row positions of sparse values. 1-D array of integers of the C type
long, of size at leastinit_k_M + 144(init_k_M + 36withmtype=1).- Mcnp.array
Array to store column positions of sparse values. Same type and size as
Mr.- Mvnp.array
Array to store sparse values. 1-D array of floats, of the same size as
Mr.- prop
BeamPropobject Beam property object from where the inertial attributes are read.
- mtypeint, optional
0 for consistent mass matrix, 1 for lumped mass matrix. Default
0. The element has no reduced-integration mass matrix,2.
- Raises:
- ValueError
If
mtypeis not 0 or 1, ifCis not positive semi-definite, seeBeamProp, or if, withmtype=0,Chas couplings other thanC[0, 3]and is not positive definite.
Notes
The mass matrices come from the kinetic energy of the displacement field of the notes of
BeamC, integrated over the cross section with the inertial attributes ofBeamProp:\[T = \frac{1}{2} \int_0^L \Big[ m (\dot{u}^2 + \dot{v}^2 + \dot{w}^2) + m_{yy} \dot{r}_z^2 + m_{zz} \dot{r}_y^2 - 2 m_{yz} \dot{r}_y \dot{r}_z - 2 m_y \dot{u} \dot{r}_z + 2 m_z \dot{u} \dot{r}_y - 2 m_z \dot{v} \dot{r}_x + 2 m_y \dot{w} \dot{r}_x + (m_{yy} + m_{zz}) \dot{r}_x^2 \Big] dx\]with \(m\) =
intrho, \(m_y\) =intrhoy, \(m_z\) =intrhoz, \(m_{yy}\) =intrhoy2, \(m_{zz}\) =intrhoz2and \(m_{yz}\) =intrhoyz.mtype=0gives the consistent mass matrix, the Hessian of \(T\) with respect to the nodal velocities, interpolated with the consistent shape functions ofBeamC, which depend onalphayandalphazand hence onC[1, 1],C[2, 2],C[4, 4]andC[5, 5], i.e. onE,G12,G13,A,IyyandIzzwhenCis not set. With couplings inCother thanC[0, 3], the shape functions depend on all entries ofC, see “Shape functions with couplings” in the notes ofBeamC, andCmust be positive definite. The integral along the element is computed analytically (exactly), and the rotary inertia is included.mtype=1gives the lumped mass matrix, diagonal in element coordinates: at each node, \(L m/2\) for the three translations, \(L (m_{yy} + m_{zz})/2\) for \(r_x\), \(L m_{zz}/2\) for \(r_y\) and \(L m_{yy}/2\) for \(r_z\). It corresponds to the two-point Gauss-Lobatto quadrature of \(T\), whose points are the nodes, without the coupling terms of \(m_y\), \(m_z\) and \(m_{yz}\), which are not included.The lumped mass matrix follows the lumped mass matrix by Lobatto integration of Brockman (1987) [1], p. 2348, adapted to the beam: the two-point Gauss-Lobatto quadrature of \(T\), whose points are the nodes, gives a diagonal matrix only without the first moments of the density, which are therefore dropped. The consistent mass matrix is the classical one, see Petyt (2010) [2]: Sec. 3.3, Eq. (3.59), for the axial terms, Sec. 3.4, Eq. (3.102), with \(m_{yy} + m_{zz}\) in place of \(\rho I_x\), for the torsional terms, and Sec. 3.9, Eqs. (3.234) and (3.237), for the bending terms with the shape functions of static equilibrium and the rotary inertia, which
BeamCreproduces in each plane of bending when \(m_y\), \(m_z\) and \(m_{yz}\) are zero.References
[1]Brockman, R. A., 1987, “Dynamics of the Bilinear Mindlin Plate Element,” Int. J. Numer. Methods Eng., 24(12), pp. 2343–2356. https://onlinelibrary.wiley.com/doi/pdf/10.1002/nme.1620241208
[2]Petyt, M., 2010, Introduction to Finite Element Vibration Analysis, 2nd ed., Cambridge University Press, Cambridge. https://doi.org/10.1017/CBO9780511761195
- update_fint(self, double[: :1] fint, BeamProp prop, int nonlinear=0) void#
Update the internal force vector
Calls
update_probe_finte(prop, nonlinear), transforms the forces and moments ofprobe.finteto global coordinates with the rotation matrix and adds them tofintat the positionsc1toc1 + 5andc2toc2 + 5. The displacementsprobe.uemust be updated before, seeupdate_probe_ue().- Parameters:
- fintnp.array
Array that is updated in place with the internal forces. The internal forces stored in
fintare calculated in global coordinates. Methodupdate_probe_finte()is called to update the parameterfinteof theBeamCProbewith the internal forces in local coordinates. 1-D array of size6*M, for \(M\) nodes in the model.- prop
BeamPropobject Beam property object from where the stiffness and mass attributes are read from.
- nonlinearint, optional
The default
0gives the linear internal forces,KC0*u. Any other value adds the geometrically nonlinear terms, for which the tangent stiffness matrix of the internal forces isKC0 + KCNL + KG, seeupdate_KCNL().
Notes
The nonlinear terms are those of the von Kármán strains, for which the exact Jacobian of the internal forces is
KC0 + KCNL + KG, seeupdate_probe_finte()andupdate_KCNL().
- update_length(self) void#
Update element length
The distance between the two nodes, computed from the coordinates
probe.xein the element coordinate system, is stored in the attributelength. Called byupdate_probe_xe().
- update_probe_finte(self, BeamProp prop, int nonlinear=0) void#
Update the internal force vector of the probe
The attribute
finteis updated with theBeamCProbethe internal forces in local coordinates. While using this function, mind that the probe can be shared amongst more than one finite element, depending how you defined them, meaning that the probe will always safe the values from the last udpate.Note
The
finteattribute of objectBeamCProbeis updated, accessible using.probe.finte.The 12 values of
finteare overwritten. They are computed fromlengthand from the displacementsprobe.ue, which must be updated before, seeupdate_probe_xe()andupdate_probe_ue().- Parameters:
- prop
BeamPropobject Beam property object from where the stiffness and mass attributes are read from.
- nonlinearint, optional
The default
0gives the linear internal forces,KC0*u. Any other value adds the geometrically nonlinear terms, for which the tangent stiffness matrix of the internal forces isKC0 + KCNL + KG, seeupdate_KCNL().
- prop
Notes
The linear internal forces are \(\boldsymbol{K}_{C0_e} \boldsymbol{u}_e\), with the matrix \(\boldsymbol{K}_{C0_e}\) of
update_KC0()in element coordinates. Withnonlineardifferent from0, the terms of the von Kármán strains are added, see_update_probe_finte_nonlinear(), such thatfinteis the gradient of the strain energy with the von Kármán axial strain averaged over the element, seeupdate_KCNL(), for which the exact Jacobian of the internal forces isKC0 + KCNL + KG, seeupdate_KCNL().
- update_probe_ue(self, double[: :1] u) void#
Update the local displacement vector of the probe of the element
Note
The
ueattribute of objectBeamCProbeis updated, accessible using.probe.ue.The translations and rotations of the two nodes, read from
uat the positionsc1toc1 + 5andc2toc2 + 5, are transformed to the element coordinate system with the transpose \(\boldsymbol{T}_{3\times 3}^\top\) of the transformation matrix, which must be updated before, seeupdate_rotation_matrix().- Parameters:
- uarray-like
Array with global displacements, for a total of \(M\) nodes in the model, this array will be arranged as: \(u_1, v_1, w_1, {r_x}_1, {r_y}_1, {r_z}_1, u_2, v_2, w_2, {r_x}_2, {r_y}_2, {r_z}_2, ..., u_M, v_M, w_M, {r_x}_M, {r_y}_M, {r_z}_M\). Translations of dimension length and rotations, 1-D array of size
6*M.
- update_probe_xe(self, double[: :1] x) void#
Update the 3D coordinates of the probe of the element
Note
The
xeattribute of objectBeamCProbeis updated, accessible using.probe.xe.The coordinates of the two nodes, read from
xat the positionsc1//2andc2//2, are transformed to the element coordinate system with the transpose \(\boldsymbol{T}_{3\times 3}^\top\) of the transformation matrix, which must be updated before, seeupdate_rotation_matrix(). Thenupdate_length()is called, updatinglength.- Parameters:
- xarray-like
Array with global nodal coordinates, for a total of \(M\) nodes in the model, this array will be arranged as: \(x_1, y_1, z_1, x_2, y_2, z_2, ..., x_M, y_M, z_M\). Dimension length, 1-D array of size
3*M.
- update_rotation_matrix(self, double vxyi, double vxyj, double vxyk, double[: :1] x) void#
Update the rotation matrix of the element
Attributes
r11,r12,r13,r21,r22,r23,r31,r32,r33are updated, with the entries \(T_{ij}\) of the transformation matrix \(\boldsymbol{T}_{3\times 3}\) from element to global coordinates, whose columns are the element axes.The element attributes
vxyi,vxyjandvxykare also updated when this function is called.The element coordinate system is determined, identifying the \(ijk\) components of each axis: \({x_e}_i, {x_e}_j, {x_e}_k\); \({y_e}_i, {y_e}_j, {y_e}_k\); \({z_e}_i, {z_e}_j, {z_e}_k\).
The element \(x\) axis goes from node 1 to node 2, whose coordinates are read from
xat the positionsc1//2andc2//2. The \(z\) axis is normal to the \(x\) axis and to the vector(vxyi, vxyj, vxyk), the \(y\) axis completes the right-handed system, and the three axes are normalized.- Parameters:
- vxyi, vxyj, vxykdouble
Components of a vector on the \(XY\) plane of the element coordinate system. Only the direction of the vector is used. A vector parallel to the element axis gives a null \(z\) axis and a rotation matrix with
nanentries.- xarray-like
Array with global nodal coordinates, for a total of \(M\) nodes in the model, this array will be arranged as: \(x_1, y_1, z_1, x_2, y_2, z_2, ..., x_M, y_M, z_M\). Dimension length, 1-D array of size
3*M.
- vxyi#
vxyi: ‘double’
- vxyj#
vxyj: ‘double’
- vxyk#
vxyk: ‘double’
- class pyfe3d.beamc.BeamCData#
Used to allocate memory for the sparse matrices.
Each attribute is the number of entries that one
BeamCelement writes in the arrays of rows, columns and values of a sparse matrix, at the consecutive positions that start at itsinit_k_KC0,init_k_KCNL,init_k_KGorinit_k_M. The constructor takes no argument and sets the values below.- Attributes:
- KC0_SPARSE_SIZE,int
KC0_SPARSE_SIZE = 144, written byBeamC.update_KC0().- KCNL_SPARSE_SIZE,int
KCNL_SPARSE_SIZE = 144, written byBeamC.update_KCNL().- KG_SPARSE_SIZE,int
KG_SPARSE_SIZE = 144, written byBeamC.update_KG().- M_SPARSE_SIZE,int
M_SPARSE_SIZE = 144, written byBeamC.update_M()withmtype=0; withmtype=1only the first36are written.
- KC0_SPARSE_SIZE#
KC0_SPARSE_SIZE: ‘int’
- KCNL_SPARSE_SIZE#
KCNL_SPARSE_SIZE: ‘int’
- KG_SPARSE_SIZE#
KG_SPARSE_SIZE: ‘int’
- M_SPARSE_SIZE#
M_SPARSE_SIZE: ‘int’
- class pyfe3d.beamc.BeamCProbe#
Probe used for local coordinates, local displacements, local stresses etc
The idea behind using a probe is to avoid allocating larger memory buffers per finite element. The memory buffers are allocated per probe, and one probe can be shared amongst many finite elements, with the information being updated and retrieved on demand.
Note
The probe can be shared amongst more than one finite element, depending on how you defined them. Mind that the probe will always safe the values from the last udpate.
The constructor takes no argument and allocates the arrays below, filled with zeros.
- Attributes:
- xe,array-like
Array of size
NUM_NODES*DOF//2=6containing the nodal coordinates in the element coordinate system, in the following order \({x_e}_1, {y_e}_1, {z_e}_1, {x_e}_2, {y_e}_2, {z_e}_2\). Dimension length. Updated byBeamC.update_probe_xe().- ue,array-like
Array of size
NUM_NODES*DOF=12containing the element displacements in the following order \(u_{e_1}, v_{e_1}, w_{e_1}, {r_x}_{e_1}, {r_y}_{e_1}, {r_z}_{e_1}, u_{e_2}, v_{e_2}, w_{e_2}, {r_x}_{e_2}, {r_y}_{e_2}, {r_z}_{e_2}\). Translations of dimension length and rotations. Updated byBeamC.update_probe_ue().- finte,array-like
Array of size
NUM_NODES*DOF=12containing the element internal forces corresponding to the degrees-of-freedom described byue, forces and moments. Updated byBeamC.update_probe_finte().KCNLvearray-likeKCNLve: ‘double[::1]’
- KCNLve#
KCNLve: ‘double[::1]’
- finte#
finte: ‘double[::1]’
- ue#
ue: ‘double[::1]’
- xe#
xe: ‘double[::1]’