Frequency analysis (structsolve.freq)#
- structsolve.freq(K, M, tol=0, sparse_solver=True, silent=False, sort=True, num_eigvalues=25, num_eigvalues_print=5, skip_null_cols=False, symmetric=False, check_rtol=1e-06, max_dense_size=2000)#
Frequency analysis
Calculates the eigenvalues \(\lambda^2\) and eigenvectors \(\{u\}\) of the free-vibration eigenvalue problem:
\[([K] + \lambda^2 [M])\{u\} = \{0\}\]where \(\lambda^2 = -\omega_n^2\) and \(\omega_n\) is the natural frequency in rad/s. The null rows and columns of
Kare removed from both matrices before solving the eigenvalue problem, unlessskip_null_cols=True.- Parameters:
- Ksparse_matrix
Stiffness matrix. Should include initial stress stiffness matrix, aerodynamic matrix and so forth when applicable.
- Msparse_matrix
Mass matrix.
- tolfloat, optional
A tolerance value passed to
scipy.sparse.linalg.eigs()andscipy.sparse.linalg.eigsh().- sparse_solverbool, optional
With
True, the default, the sparse solver always runs first, whatever the size of the problem:scipy.sparse.linalg.eigs(), orscipy.sparse.linalg.eigsh()withsymmetric=True, in shift-invert mode with a negative shift estimated from the matrices, calculating thenum_eigvalueseigenvalues closest to the shift. Its eigenpairs are verified, and a dense solver is only used as a last resort, see the Notes. WithFalse, the full problem is explicitly solved with a dense solver,scipy.linalg.eig(), orscipy.linalg.eigh()withsymmetric=True, without trying the sparse solver, which calculates all eigenvalues, e.g. for the kinetic criterion of stability, and is a reference for validations.- silentbool, optional
A boolean to tell whether the log messages should be printed.
- sortbool, optional
Sort the eigenvectors by increasing natural frequency, keeping only those with a natural frequency larger than
1e-6rad/s. The returned eigenvalues are not affected by this option.- num_eigvaluesint, optional
Number of calculated eigenvalues with the sparse solver, limited to the size of
Mminus 2.- num_eigvalues_printint, optional
Number of eigenvalues to print.
- skip_null_colsbool, optional
If True, skip the removal of null columns from the matrices. Use only when
KandMare known to be non-singular.- symmetricbool or None, optional
False, the default, uses the general solvers described above, valid for unsymmetric matrices, e.g.Kwith an aerodynamic matrix or with the load stiffness of follower loads.Trueuses the solvers of symmetric matrices,scipy.sparse.linalg.eigsh()in shift-invert mode orscipy.linalg.eigh(), which require symmetricKandMand a positive definiteM, and return real eigenvalues and eigenvectors normalized with respect toM.Noneselects them whenlinear_buckling.is_symmetric()is true for both matrices.- check_rtolfloat or None, optional
Maximum relative residual of an eigenpair, \(||K u + \lambda^2 M u||/(||K u|| + |\lambda^2| ||M u||)\). A larger residual of the sparse solver is a failed verification, see the Notes. For
sparse_solver=False, a warning is issued.Noneskips the check.- max_dense_sizeint, optional
Maximum size of the dense problem solved as a last resort when the sparse solver failed, see the Notes. Larger problems raise a
RuntimeErrorinstead, and0disables the dense fallback.
- Returns:
- lambda2ndarray
Complex array with the eigenvalues \(\lambda^2 = -\omega_n^2\), in the order returned by the eigenvalue solver, real with
symmetric=True.- eigvecsndarray
The \(i^{th}\) eigenvector is
eigvecs[:, i], with the size of the original matrices. The sparse solver returns eigenvectors normalized with respect toM, the dense solver returns eigenvectors with unit Euclidean norm. Ifsort=Truethe columns are sorted and filtered as described above, in which case they correspond to the eigenvalues inlambda2only if the solver already returned them in the order of increasing natural frequency.
- Raises:
- RuntimeError
When the sparse solver failed and the dense fallback was not possible or failed too, listing the attempted solvers and their failures.
- Warns:
- .linear_buckling.DenseFallbackWarning
When the sparse solver failed and the dense solver was used.
Notes
Solver policy. As in
lb(), withsparse_solver=Truethe sparse solver runs first for every problem size, and its eigenpairs are verified:the relative residual of each eigenpair must not be larger than
check_rtol;with
symmetric=True, no eigenvalue \(\omega_n^2\) lower than the highest one returned may be missing: the number of negative pivots of \([K] - s [M]\), for \(s\) slightly lower than this eigenvalue, is the number of eigenvalues below \(s\) (Sylvester’s law of inertia).
When the verification fails or the sparse solver raises an error, e.g. ARPACK did not converge, the dense solver is used as a last resort if the problem has at most
max_dense_sizedofs, with alinear_buckling.DenseFallbackWarninggiving the reasons. It returns thenum_eigvalueslowest eigenvalues withsymmetric=True, otherwise thenum_eigvalueseigenvalues closest to the shift, as the sparse solver, and its eigenpairs are verified as well. Otherwise aRuntimeErroris raised. Until version 0.5.3, the sparse solver only issued a warning when the residual check failed.scipy.sparse.linalg.eigsh()uses ARPACK’s symmetric drivers, which return wrong eigenpairs when linked against Intel MKL 2024.2.0 to 2025.0.0 andncv > 32, seelb()andstructsolve.arpackutils, wherencvis capped accordingly.Non-conservative systems, e.g. under follower loads, may lose stability by flutter, which the static criterion of
lb()does not detect: withKthe tangent stiffness matrix at a load level, including the load stiffness, the eigenvalues \(\lambda^2\) of the general solvers are real and negative below the flutter load and become complex conjugate pairs above it, when two natural frequencies coalesce (the kinetic criterion). A real positive \(\lambda^2\) indicates divergence.
See also Eigenvalue solvers for the solver policy.