pyyeti.ode.getmodepart¶
- pyyeti.ode.getmodepart(h_or_frq, sols, mfreq, factor=0.6666666666666666, helpmsg=True, ylog=False, auto=None, idlabel='', frf_ttl='')[source]¶
Get modal participation from frequency response plots.
- Parameters:
h_or_frq (list/tuple or 1d ndarray) – Plot line handles or frequency vector:
If list/tuple, it contains the plot line handles to the FRF curves; in this case, the analysis frequency is retrieved from the plot.
If it is a 1d ndarray, it is the frequency vector; in this case, a plot of FRFs (from sols) is generated in figure ‘FRF’ (or ‘FRF - ‘+idlabel)
sols (list/tuple of lists/tuples) –
Contains info to determine modal particpation:
sols = [[Trecover1, accel1, Trecover1_row_labels], [Trecover2, accel2, Trecover2_row_labels], ... ]
each Trecover matrix is: any number x modes
each accel matrix is: modes x frequencies
each row_labels entry is a list/tuple: len = # rows in corresponding Trecover (if Trecover only has 1 row, then row_labels may be just a string)
The FRFs are recovered by:
FRFs1 = Trecover1*accel1 FRFs2 = Trecover2*accel2 ...
accel1, accel2, etc are the complex modal acceleration (or displacement or velocity) frequency responses; normally output by, for example,
SolveUnc.fsolve()mfreq (array_like) – Vector of modal frequencies (Hz)
factor (scalar; optional) – From 0 to 1 for setting the criteria for choosing secondary modes: if mode participation of secondary mode(s) >= factor * max_participation, include it.
helpmsg (bool; optional) – If True, print brief message explaining the mouse buttons before plotting anything
ylog (bool; optional) – If True, y-axis will be log
auto (list/tuple or None; optional) –
If None, operate interactively.
If a 2 element vector, it specifies an item in sols and a Trecover row (0-offset) that this routine will automatically (non-interactively) use to select modes. It will select the peak of the specified response and, based on mode participation, return the results. In other words, it acts as if you picked the peak of the specified curve and then hit ‘t’. The 1st element of auto selects which sols entry to use and the 2nd selects the matrix row. For example, to choose the 12th row of Trecover3, set auto to [2, 11].
idlabel (string; optional If not ‘’, it will be) – used in the figure name. This allows multiple getmodepart()’s to be run with the same model, each using its own FRF and MP windows. The figure names will be:
'FRF - '+idlabel <-- used only if h_or_frq is freq 'MP - '+idlabel
frf_ttl (string; optional) – Title used for FRF plot
- Returns:
modes (list) – List of selected mode numbers; 0-offset
freqs (1d ndarray) – Vector of frequencies in Hz corresponding to modes.
Notes
FRF peaks can only be selected in range of the analysis frequency, but modes outside this range may be selected based on modal participation.
This routine will echo modal participation factors to the screen and plot them in figure ‘MP’ (or ‘MP - ‘+idlabel).
If auto is None (or some other non-2-element object), this routine works as follows:
If h is frequency vector, plot FRFs from sols in figure ‘FRF’ or ‘FRF - ‘+idlabel
Repeat:
Waits for user to select response. Mouse/key commands:
Left - select response point; valid only in the FRF figure Right - erase last selected mode(s) 't' - done
Plots mode participation bar graph in figure ‘MP’ (or ‘MP - ‘+idlabel) showing the frequency(s) of modes selected.
If using auto, no plots are generated (see auto description above).
See also
Examples
>>> import numpy as np >>> import matplotlib.pyplot as plt >>> from pyyeti.ode import SolveUnc >>> from pyyeti.ode import getmodepart >>> import scipy.linalg as la >>> rng = np.random.default_rng() >>> K = 40*rng.normal(size=(5, 5)) >>> K = K @ K.T # pos-definite K matrix, M is identity >>> M = None >>> w2, phi = la.eigh(K) >>> mfreq = np.sqrt(w2)/2/np.pi >>> zetain = np.array([ .02, .02, .05, .02, .05 ]) >>> Z = np.diag(2*zetain*np.sqrt(w2)) >>> freq = np.arange(0.1, 15.05, .1) >>> f = np.ones((1, len(freq))) >>> Tbot = phi[0:1, :] >>> Tmid = phi[2:3, :] >>> Ttop = phi[4:5, :] >>> fs = SolveUnc(M, Z, w2) >>> sol_bot = fs.fsolve(Tbot.T @ f, freq) >>> sol_mid = fs.fsolve(Tmid.T @ f, freq)
Prepare transforms and solutions for
getmodepart(): (Note: the top 2 items in sols could be combined since they both use the same acceleration)>>> sols = [[Tmid, sol_bot.a, 'Bot to Mid'], ... [Ttop, sol_bot.a, 'Bot to Top'], ... [Ttop, sol_mid.a, 'Mid to Top']]
Approach 1: let
getmodepart()do the FRF plotting:>>> lbl = 'getmodepart demo 1' >>> mds, frqs = getmodepart(freq, sols, ... mfreq, ylog=1, ... idlabel=lbl) >>> print('modes =', mds) >>> print('freqs =', frqs)
Approach 2: plot FRFs first, then call
getmodepart():>>> fig = plt.figure('approach 2 FRFs') >>> fig.clf() >>> for s in sols: ... plt.plot(freq, abs(s[0] @ s[1]).T, ... label=s[2]) >>> _ = plt.xlabel('Frequency (Hz)') >>> plt.yscale('log') >>> _ = plt.legend(loc='best') >>> h = plt.gca().lines >>> lbl = 'getmodepart demo 2' >>> modes, freqs = getmodepart(h, sols, ... mfreq, ... idlabel=lbl) >>> print('modes =', modes) >>> print('freqs =', freqs)