pyyeti.cla.DR_Results.solvepsd¶
- DR_Results.solvepsd(nas, case, DR, fs, forcepsd, t_frc, freq, *, use_apply_uf=False, verbose=False, allow_force_trimming=False, **kwargs)[source]¶
Solve equations of motion in frequency domain with PSD forces
See also
pyyeti.ode.solvepsd()for a very similar routine, but one that is independent of theclamodule.- Parameters:
nas (dictionary) – Typically, this is the nas2cam dictionary:
nas = pyyeti.nastran.op2.rdnas2cam(). However, only the “nrb” member is needed directly by this routine (for uncertainty factor application). It is also passed to the data recovery routines (the drfunc setting inDR_Def.add()).case (string) – Unique string identifying the case; stored in, for example, the
self['SC_atm'].casesand the .mincase and .maxcase lists. Also used to index the temporary dictionaryself['SC_atm']._psd(see Notes below).DR (instance of
DR_Event) – Defines data recovery for an event simulation (and is created in the simulation script viaDR = cla.DR_Event()). It is an event specific version of all combinedDR_Defobjects with all ULVS matrices applied.fs (class instance) – An instance of
pyyeti.ode.SolveUncorpyyeti.ode.FreqDirect(or similar … must have.fsolvemethod)forcepsd (2d array_like) – Matrix of force psds; each row is a force
t_frc (2d array_like) – Transform to put forcepsd into the coordinates of the equations of motion:
t_frc @ forcepsd. Commonly, t_frc is simply the transpose of a row-partition of the mode shape matrix (phi) and the conversion of forcepsd is from physical space to modal space. In that case, the row-partition is from the full set down to just the forced DOF. However, t_frc can also have force mappings (as from the TLOAD capability in Nastran); in that case,t_frc = phi.T @ mapping_vectors. In any case, the number of columns in t_frc is the number of rows in forcepsd:t_frc.shape[1] == forcepsd.shape[0]freq (1d array_like) – Frequency vector at which solution will be computed
use_apply_uf (bool; optional) – If True, use
DR_Event.apply_uf()instead ofDR_Event.frf_apply_uf()to apply the uncertainty factors.Added in version 1.4.1.3.
The primary difference is in the handling of displacements. Specifically,
DR_Event.apply_uf()does the following things whileDR_Event.frf_apply_uf()does not:Breaks the elastic displacements are broken into static and dynamic parts for uncertainty factor application.
Zeros out the rigid-body displacements. This means that the displacement setting in incrb irrelevant for
DR_Event.apply_uf()(as if “d” is not present in incrb).Handles residual flexibility responses statically.
verbose (bool; optional) – If True, print status messages and timer results.
allow_force_trimming (bool; optional) – If True, zero forces will be trimmed off to save time. Since this can cause trouble during data recovery if you have any force-dependent data recovery matrices (“drmf”), the default is False. It is advisable to trim off zero forces before calling this routine and trim the corresponding columns off any “drmf” matrices.
**kwargs (keyword arguments for
fs.fsolve; optional) – Currently, there are two arguments available:argument
brief description
incrb
specifies how to handle rigid-body responses
rf_disp_only
specifies how to handle residual-flexibility modes
See, for example,
pyyeti.ode.SolveUnc.fsolve().
Notes
The self results dictionary is updated (see
DR_Resultsfor an example).This routine calls
DR_Event.frf_apply_uf()orDR_Event.apply_uf()to apply the uncertainty factors (see use_apply_uf above).The response PSDs are stored in a temporary dictionary index by the case; eg:
self['SC_atm'][case]._psd. The routinepsd_data_recovery()operates on this variable and deletes it after processing that last case. Note that some or all rows of this variable might be saved inself['SC_atm'].psd; this is determined according to the histpv setting defined through the call toDR_Def.add().The solution loop is essentially as follows, written in a python-like pseudo-code:
for cat in categories: cat[case]._psd = 0.0 for i in range(forcepsd.shape[0]): # solve for unit frequency response function for i'th # force: genforce = t_frc[:, [i]] @ unitforce; sol = fs.fsolve(genforce, freq, **kwargs) sol.pg[:] = 0.0 sol.pg[i] = unitforce sol = DR.frf_apply_uf(sol, nas["nrb"]) # compute the unit frf's for all categories: for cat in categories: # call the drfunc set in cla.DR_Def.add for # current category resp = cat_drfunc(sol[uf_reds], nas, DR.Vars, se) # ex: resp = (ltma @ sol.a + ltmd @ sol.d # + ltmf @ sol.pg) # compute psd response and add it on: cat._psd[case] += forcepsd[i] * abs(resp) ** 2
Note
If you have force-dependent data recovery matrices (which is typically from using the mode-acceleration method of data recovery for fundamentally displacement-based quantities), you may need to trim/reorder its columns to match forcepsd. Note that while looping over each PSD in forcepsd, this routine creates
sol.pgsized compatibly with forcepsd and has only one row of 1.0 values. See also allow_force_trimming above.