Linear static analyses#
A linear static analysis solves \(\boldsymbol{K}_{C0} \boldsymbol{u} = \boldsymbol{f}\) for the
dofs whose displacements are unknown, with the matrix KC0 assembled as
in Overview and workflow. This page gives the partition of the dofs, with zero or
prescribed displacements, the reactions, and the solvers.
Partition of the dofs#
At each dof either the load or the displacement is known. The Boolean array
bu marks the free dofs, \(u\), whose displacements are unknown, and its
complement bk = ~bu the known ones, \(k\), with the prescribed
displacements uk[bk], \(\boldsymbol{u}_k\), zero at a fixed support. Bathe (2014,
Sec. 4.2.2, Eqs. (4.42) to (4.45)) writes the same partition with other
subscripts. Without reordering the dofs, the system reads
with \(\boldsymbol{f}_k\) the loads applied at the known dofs and \(\boldsymbol{R}_k\) the unknown reactions. The first row gives the system of the free dofs, where the prescribed displacements act as the forces \(-\boldsymbol{K}_{{C0}_{uk}} \boldsymbol{u}_k\), and the second row the reactions:
which, with SciPy:
KC0uu = KC0[bu, :][:, bu]
KC0uk = KC0[bu, :][:, bk]
u = np.zeros(N)
u[bk] = uk[bk]
u[bu] = solve(KC0uu, f[bu] - KC0uk @ uk[bk])
Rk = KC0[bk, :] @ u - f[bk]
KC0[bk, :] @ u is \(\boldsymbol{K}_{{C0}_{ku}} \boldsymbol{u}_u + \boldsymbol{K}_{{C0}_{kk}}
\boldsymbol{u}_k\), the internal forces at the known dofs, which update_fint of
the elements also gives, \(\boldsymbol{F}_{{int}_k} - \boldsymbol{f}_k\), see step 7 of
Overview and workflow. For fixed supports, uk is zero and the system is
\(\boldsymbol{K}_{{C0}_{uu}} \boldsymbol{u}_u = \boldsymbol{f}_u\). The same partition gives the
matrices of the eigenvalue analyses, see Linear buckling and natural frequencies.
Solvers#
solve()solves a sparse system with an LU factorization and raises an error for a singular matrix, wherescipy.sparse.linalg.spsolve()returns NaN values.linear_static()solvesK @ u = fextof the free dofs, checks that a symmetricKis positive definite and returns[1.]and[u], the outputs ofAnalysis.static().Analysis.static()withNLgeom=Falsesolves the same system from the callables of a model, see Non-linear static analyses, in a single increment. WithAnalysis(..., bu=bu, uk=uk), the callables work with all theNdofs, the system of the free dofs above is formed byFreeDofs.linear_fext(), andcs[0]has sizeN, withuk[bk]at the known dofs; the reactions arecalc_fint(u) - calc_fext()at the known dofs. A configuration-dependent load is corrected by iterations, seeAnalysis.static().
The worked example Tutorial: prescribed displacement at the tip of a cantilever solves a cantilever with a prescribed tip deflection both ways, and Linear static analysis of a plate a plate under a point load.
Errors of the supports#
The solvers of pyfe3d.solver do not remove null rows and columns: a
dof left without stiffness, e.g. an unattached node, an unstiffened
drilling rotation or a missing boundary condition, raises a
numpy.linalg.LinAlgError naming the dofs, see
check_null_rows_cols(). Insufficient boundary conditions, a
mechanism or re-entrant elements leave \(\boldsymbol{K}_{{C0}_{uu}}\) not positive
definite, which linear_static(), linear_buckling() and the
linear Analysis.static() report with a
numpy.linalg.LinAlgError naming the likely causes, see
Linear buckling and natural frequencies. A structure that has no supports, e.g. in
flight, is solved with apply_inertia_relief(), whose reference support is
a set of prescribed null displacements, see Inertia relief.
References#
Bathe, K. J., Finite Element Procedures, 2nd ed., K. J. Bathe, Watertown, MA, 2014.