bcam.indar.ema.ComplexModes¶
- class bcam.indar.ema.ComplexModes(poles: array - like, amps: array - like, ns: int, fs: float = 1.0, coords: array - like | None = None, response: str = 'a')¶
Fit mode shapes with non-proportional damping.
After estimating the amplitudes \(A^l_{ij}\) with
Amplitudes, this class can be used to fit mode shapes assuming non-proportional damping. The algorithm needs an initial guess, which may be taken from the fitted mode shapes by the classRealModes. The complex mode shapes are stored as an array \(\varphi\) of shape (n_outputs, dof), and they satisfy\[A^l_{ij} \approx \varphi_{il} \varphi_{jl},\]where \(i=0, \ldots, n_\mathrm{out}-1\), \(j=0, \ldots, n_\mathrm{in}-1\), and \(l=0, \ldots, \mathrm{dof}-1\).
- Parameters:
- polesarray-like, shape (dof,)
Natural frequencies.
- ampsarray-like, shape (n_outputs, n_inputs, dof)
Amplitudes for each measured output-input pair and mode.
- nsint
Number of time samples in the fitted IRF.
- fsfloat, default 1.
Sampling frequency (\(1/dt\)) of the IRF.
- coordsarray-like, shape (n_out,), optional
To solve the minimization problem, the space of (partial) mode shapes is decomposed through the grassmannian space \(\mathrm{Gr}(n_\mathrm{out}, \mathrm{dof})\) over the real field. To parameterize the grassmannian, we use a coordinate subspace \(\{e_{i_1}, \ldots, e_{i_{n_\mathrm{out}}}\}\), so the array coords is
np.array([i_1, \ldots, i_{out}]). If None, the first n_out standard basis vectors are used.- responsestr, default ‘a’
Type of response. Must be one of ‘a’, ‘v’, or ‘d’, for accelerance, velocity, or displacement, respectively.
- Attributes:
- modes_np.ndarray, shape (n_outputs, dof)
Fitted (partial) mode shapes.
- success_bool
Whether the optimization was successful.
- message_str
Description of the cause of the termination.
Methods
fit(x0[, options, maxiter])Fit the mode shapes.
predict(X)Predict the impulse response function (IRF).
Notes
We use a loss-function based on the Hilbert–Schmidt norm
\[L(\varphi) = \sum_{i,j}\sum_{k=0}^{N-1} (N - k)\Big\lvert \im\Big(\sum_l(A^l_{ij}-\varphi_{il} \varphi_{jl})\lambda_l^\nu s_l^k\Big) \Big\rvert^2,\]subject to the constraints
\[\begin{split}\begin{split} \im(\sum_l \varphi_{il} \varphi_{jl}) = 0, \quad\text{for each } i = 0, \ldots, n_\mathrm{out}-1 \text{ and } j = 0, \ldots, n_\mathrm{in}-1, \\ \im(\sum_l \lambda_l\varphi_{il} \varphi_{jl}) > 0, \text{ and } -\im(\sum_l \lambda_l^2\varphi_{il} \varphi_{jl}) > 0 \text{ for } i, j = 0, \ldots, n_\mathrm{in}-1. \end{split}\end{split}\]Here, \(N\) is the number of time samples, \(s_l = e^{\lambda_l\,dt}\) are the poles of the structure, and the exponent \(\nu\) depends on the type of IRF (accelerance (2), velocity (1), or displacement (0)). The inequality constraints are to be understood as positive-definite matrices.
The optimization is performed by a local search with the minimizer
scipy.optimize.minimize()using the method trust-constr. To speed up computations, the exact jacobian and hessian are passed, and the functions are optimized to avoid redundant computations.- fit(x0: array - like | tuple[array - like, array - like], options: dict | None = None, maxiter: int = 1000) ComplexModes¶
Fit the mode shapes.
- Parameters:
- x0array-like or 2-tuple of arrays with shape (n_outputs, dof)
Initial guess for the optimization. If a single array is given, it is interpreted as real mode shapes. If a tuple of two arrays is given, the arrays represent a parameterization of the mode shapes, where the first array is the real part, and the second array has the same shape but the left-most \((n_\mathrm{out}\times n_\mathrm{out})\)-submatrix is antisymmetric.
- optionsdict, optional
Options for the optimization by trust-constr.
- maxiterint, optional
Maximum number of iterations for the optimization. Default is 1000.
- Returns:
- selfComplexModes
Fitted model.