Beispiel #1
0
def calcAM(S, freq):
    """
    Calculate apparent mass

    Parameters
    ----------
    S : list/tuple
        Contains: ``[mass, damp, stiff, bdof]`` for structure. These
        are the source mass, damping, and stiffness matrices (see
        :class:`pyyeti.ode.SolveUnc`) and `bdof`, which is described
        below.
    freq : 1d array_like
        Frequency vector (Hz)

    Returns
    -------
    AM : 3d ndarray
        Apparent mass matrix in a 3d array:

        .. code-block:: none

            boundary DOF x Frequencies x boundary DOF
             (response)                   (input)

    Notes
    -----
    The `bdof` input defines boundary DOF in one of two ways as
    follows. Let `N` be total number of DOF in mass, damping, &
    stiffness.

       1.  If `bdof` is a 2d array_like, it is interpreted to be a
           data recovery matrix to the b-set (number b-set =
           ``bdof.shape[0]``). Structure is treated generically (uses
           :class:`pyyeti.ode.SolveUnc` with ``pre_eig=True`` to
           compute apparent mass).
       2.  Otherwise, `bdof` is assumed to be a 1d partition vector
           from full `N` size to b-set and structure is assumed to be
           in Craig-Bampton form (uses :func:`pyyeti.cb.cbtf` to
           compute apparent mass).

    The routine :func:`ntfl` example demonstrates this function.

    See also
    --------
    :func:`ntfl`.
    """
    lf = len(freq)
    m = S[0]
    b = S[1]
    k = S[2]
    bdof = np.atleast_1d(S[3])

    if bdof.ndim == 2:  # bdof is treated as a drm
        r = bdof.shape[0]
        T = bdof
        Frc = np.zeros((r, lf))
        Acc = np.empty((r, lf, r), dtype=complex)
        fs = ode.SolveUnc(m, b, k, pre_eig=True)
        for direc in range(r):
            Frc[direc, :] = 1.0
            sol = fs.fsolve(T.T @ Frc, freq)
            Acc[:, :, direc] = T @ sol.a
            Frc[direc, :] = 0.0
        AM = np.empty((r, lf, r), dtype=complex)
        for j in range(lf):
            AM[:, j, :] = la.inv(Acc[:, j, :])
    else:  # bdof treated as a partition vector for CB model
        r = len(bdof)
        acce = np.eye(r)
        # Perform Baseshake
        # cbtf = craig bampton transfer function; this will genenerate
        # the corresponding interface force required to meet imposed
        # acceleration
        AM = np.empty((r, lf, r), dtype=complex)
        save = {}
        for direc in range(r):
            tf = cb.cbtf(m, b, k, acce[direc, :], freq, bdof, save)
            AM[:, :, direc] = tf.frc
    return AM
Beispiel #2
0
def test_cbtf():
    nas = op2.rdnas2cam("tests/nas2cam_csuper/nas2cam")
    maa = nas["maa"][102]
    kaa = nas["kaa"][102]
    uset = nas["uset"][102]
    b = n2p.mksetpv(uset, "a", "b")
    q = ~b
    b = np.nonzero(b)[0]

    rb = n2p.rbgeom_uset(uset.iloc[b], 3)
    freq = np.arange(1.0, 80.0, 1.0)
    a = rb[:, :1]
    a2 = a.dot(np.ones((1, len(freq))))
    a3 = rb[:, 0]

    pv = np.any(maa, axis=0)
    q = q[pv]
    pv = np.ix_(pv, pv)
    maa = maa[pv]
    kaa = kaa[pv]
    baa1 = np.zeros_like(maa)
    baa1[q, q] = 2 * 0.05 * np.sqrt(kaa[q, q])
    baa2 = 0.1 * np.random.randn(*maa.shape)
    baa2 = baa2.dot(baa2.T)

    bb = np.ix_(b, b)

    for baa in [baa1, baa2]:
        for delq in [False, True]:
            if delq:
                m = maa[bb]
                c = baa[bb]
                k = kaa[bb]
            else:
                m = maa
                c = baa
                k = kaa

            tf = cb.cbtf(m, c, k, a, freq, b)
            tf2 = cb.cbtf(m, c, k, a2, freq, b)
            save = {}
            tf3 = cb.cbtf(m, c, k, a3, freq, b, save)
            tf4 = cb.cbtf(m, c, k, a2, freq, b, save)

            assert np.all(freq == tf.freq)
            assert np.all(freq == tf2.freq)
            assert np.all(freq == tf3.freq)
            assert np.all(freq == tf4.freq)

            assert np.allclose(tf.frc, tf2.frc)
            assert np.allclose(tf.a, tf2.a)
            assert np.allclose(tf.d, tf2.d)
            assert np.allclose(tf.v, tf2.v)

            assert np.allclose(tf.frc, tf3.frc)
            assert np.allclose(tf.a, tf3.a)
            assert np.allclose(tf.d, tf3.d)
            assert np.allclose(tf.v, tf3.v)

            assert np.allclose(tf.frc, tf4.frc)
            assert np.allclose(tf.a, tf4.a)
            assert np.allclose(tf.d, tf4.d)
            assert np.allclose(tf.v, tf4.v)

            # confirm proper solution:
            O = 2 * np.pi * freq
            velo = 1j * O * tf.d
            acce = 1j * O * velo
            f = m.dot(acce) + c.dot(velo) + k.dot(tf.d)
            assert np.allclose(acce, tf.a)
            assert np.allclose(velo, tf.v)
            assert np.allclose(f[b], tf.frc)
            if not delq:
                assert np.allclose(f[q], 0)

    assert_raises(ValueError, cb.cbtf, maa, baa1, kaa, a2[:, :3], freq, b)

    assert_raises(ValueError, cb.cbtf, maa, baa1, kaa, a2[:3, :], freq, b)