示例#1
0
def test_cbcheck_determinate():
    nas = op2.rdnas2cam("tests/nas2cam_csuper/nas2cam")
    se = 101
    maa = nas["maa"][se]
    kaa = nas["kaa"][se]
    pv = np.any(maa, axis=0)
    pv = np.ix_(pv, pv)
    maa = maa[pv]
    kaa = kaa[pv]

    uset = nas["uset"][se]
    bset = n2p.mksetpv(uset, "p", "b")
    usetb = nas["uset"][se].iloc[bset]
    b = n2p.mksetpv(uset, "a", "b")

    q = ~b
    b = np.nonzero(b)[0]
    q = np.nonzero(q)[0]

    center = np.mean(usetb.iloc[::6, 1:], axis=0)
    rb = n2p.rbgeom_uset(usetb, center.values)

    # transform to single pt on centerline:
    # [b, q]_old = T*[b, q]_new
    #            = [[rb, 0], [0, I]] * [b, q]_new
    T = np.zeros((len(b) + len(q), 6 + len(q)))
    T[:len(b), :6] = rb
    T[len(b):, 6:] = np.eye(len(q))

    kaa = T.T @ kaa @ T
    maa = T.T @ maa @ T
    b = np.arange(6)

    # write to a string:
    with StringIO() as f:
        out = cb.cbcheck(f, maa, kaa, b, b[:6], em_filt=2)
        s = f.getvalue()

    s = s.splitlines()
    with open("tests/nas2cam_csuper/yeti_outputs/cbcheck_yeti_101_single.out"
              ) as f:
        sy = f.read().splitlines()

    assert s[0] == "Mass matrix is symmetric."
    assert s[1] == "Mass matrix is positive definite."
    assert s[2] == "Warning: stiffness matrix is not symmetric."

    j = [10]
    jy = [10]
    assert comptable(s, sy, j, jy, label="KBB =", skip=1)
    compare_cbcheck_output(s, sy)
示例#2
0
def relative_displacement_dtm(nas, node_pairs):
    """
    Form relative displacements data recovery matrix

    Parameters
    ----------
    nas : dictionary
        This is the nas2cam dictionary: ``nas = op2.rdnas2cam()``. For
        a Craig-Bampton component, `nas` will also need to have `mug1`
        and `tug1` entries as shown in the example usage below. The
        matrix `mug1` is a data recovery matrix (to recover the
        displacements) and `tug1` is the DOF map to `mug1`: ``[node,
        dof]``. These get created during an "EXTSEOUT" Nastran run.
        The naming convention is::

            tug1 --> nas['tug1'][se]
            mug1 --> nas['extse'][se]['mug1']

    node_pairs : 2d array_like
        Four column matrix where each row contains the superelement ID
        and node ID for two non-coincident nodes: ``[SE1, Node1, SE2,
        Node2]``. The relative displacement between each node pair is
        computed along a vector from Node1 to Node2 with positive
        meaning increased distance.

    Returns
    -------
    reldtm : 2d ndarray
        This is the displacement-dependent relative displacement
        recovery matrix. There is one row per node pair and the order
        given in `node_pairs` is preserved.
    dist : 1d ndarray
        Vector of distances between node pairs.
    labels : list
        List of labels briefly describing each row in `reldtm`. For
        example, if one row in `node_pairs` is: ``[101, 3, 102, 30]``,
        the label for that row would be: 'SE102,30 - SE101,3'.

    Notes
    -----
    The algorithm works as follows:

      1. Forms two data recovery matrices for the X, Y and Z DOF of
         each node listed in `node_pairs`. One (`DTMG`) recovers from
         residual g-set DOF and the other (`DTMQ`) recovers from the
         residual q-set.

      2. Multiplies `DTMG` by the g-set residual rigid-body modes. The
         resulting 6-column matrix is passed to
         :func:`pyyeti.nastran.n2p.find_xyz_triples` which calculates
         the location of each node and applies coordinated transforms
         to `DTMQ` such that it recovers in the basic coordinate
         system for all nodes.

      3. For each pair of nodes in `node_pairs`:

         a. Form a new rectangular coordinate system based at Node1
            with the z-axis pointing to Node2.

         b. Transform the Node1 and Node2 rows of `DTMQ` to output in
            the new coordinate system.

         c. Form a single row of the final `reldtm` by subtracting the
            Node1 Z recovery from the Node2 Z recovery: ``dtm2[2] -
            dtm1[2]``. This means that a positive relative
            displacement corresponds to an increased distance between
            the two nodes.

    As a final check, the magnitude of the rigid-body part of
    `reldtm` is examined. If the largest value is greater than 1e-6 a
    warning message is printed.

    Example usage::

        # load nastran data:
        nas = op2.rdnas2cam('nas2cam')

        SC = 101
        n2p.addulvs(nas, SC)

        # read in more data for SC since it is a Craig-Bampton model:
        if 'tug1' not in nas:
            nas['tug1'] = {}
        nas['tug1'][SC] = nastran.rddtipch('outboard.pch')

        if 'extse' not in nas:
            nas['extse'] = {}
        nas['extse'][SC] = nastran.op4.read('outboard.op4')

        node_pairs = [
            [SC,  3,   SC, 10],
            [ 0, 11,   SC, 18],
        ]

        reldtm, dist, lbls = relative_displacement_dtm(
            nas, node_pairs)

        # add the above items to the data recovery:
        drdefs = cla.DR_Def({'se': 0})

        @cla.DR_Def.addcat
        def _():
            name = 'reldisp'
            desc = 'Relative Displacements'
            units = 'in'
            labels = lbls
            drms = {name: reldtm}
            drfunc = f"Vars[se]['{name}'] @ sol.d"
            histpv = 'all'
            drdefs.add(**locals())

        # prepare spacecraft data recovery matrices
        DR = cla.DR_Event()
        DR.add(nas, drdefs)

        # initialize results (ext, mnc, mxc for all drms)
        results = DR.prepare_results(mission, event)

        # solve equations of motion:
        ts = ode.SolveUnc(*mbk, h)
        sol = ts.tsolve(genforce, static_ic=1)
        sol.t = t
        sol = DR.apply_uf(sol, *mbk, nas['nrb'], rfmodes)
        results.time_data_recovery(sol, nas['nrb'],
                                   caseid, DR, LC, j)

        # write report of results:
        results.rpttab()

    Raises
    ------
    ValueError
        When Node1 and Node2 of any node pair are coincident.
    """
    # to get locations in basic, need rb modes relative to origin:
    rbg = n2p.rbgeom_uset(nas["uset"][0])

    # call formdrm only once per superelement:
    node_pairs = np.atleast_2d(node_pairs)
    nrel = node_pairs.shape[0]
    dtmq = np.empty((nrel * 6, nas["lambda"][0].shape[0]))
    dtmg = np.empty((nrel * 6, 6))

    senodes = np.vstack((node_pairs[:, :2], node_pairs[:, 2:]))
    senodesdof = np.array([[se, n, i] for se, n in senodes
                           for i in range(1, 4)])

    for se in set(senodes[:, 0]):
        pvd = senodesdof[:, 0] == se
        dof = senodesdof[pvd, 1:]
        try:
            tq = n2p.formdrm(nas, se, dof)[0]
            tx = n2p.formdrm(nas, se, dof, gset=True)[0]
        except ValueError:
            u1x = n2p.formulvs(nas, se, gset=True)
            pv = n2p.mkdofpv(nas["tug1"][se], "p", dof)[0]
            tq = nas["extse"][se]["mug1"][pv] @ nas["ulvs"][se]
            tx = nas["extse"][se]["mug1"][pv] @ u1x
        dtmq[pvd] = tq
        dtmg[pvd] = tx @ rbg

    mats = {"dtmq": dtmq}
    xyz = n2p.find_xyz_triples(dtmg, mats=mats, inplace=True)

    reldtm = np.empty((nrel, dtmq.shape[1]))
    dist = np.empty(nrel)

    ext_coords = xyz.coords.max(axis=0)
    for i in range(nrel):
        n1 = slice(i * 3, i * 3 + 3)
        n2 = slice((nrel + i) * 3, (nrel + i) * 3 + 3)

        # make transform from basic to C:
        a = xyz.coords[i * 3]
        b = xyz.coords[(i + nrel) * 3]

        # check for coincident nodes:
        if la.norm((b - a) / ext_coords) < 1e-5:
            raise ValueError(f"coincident nodes detected at index {i} of "
                             f"`node_pairs`: {node_pairs[i]}")

        c = a + (b - a)[[1, 2, 0]]
        C = np.array([[1, 1, 0], a, b, c])
        To_local = n2p.mkusetcoordinfo(C, None, {})[2:].T
        dtm1 = To_local @ dtmq[n1]
        dtm2 = To_local @ dtmq[n2]

        # positive for moving apart (b - a > 0):
        reldtm[i] = dtm2[2] - dtm1[2]
        dist[i] = la.norm(b - a)

    labels = [
        f"SE{se2},{n2} - SE{se1},{n1}" for se1, n1, se2, n2 in node_pairs
    ]
    return reldtm, dist, labels
示例#3
0
def test_mk_net_drms():
    pth = os.path.dirname(inspect.getfile(cb))
    pth = os.path.join(pth, "..")
    pth = os.path.join(pth, "tests")
    pth = os.path.join(pth, "nas2cam_csuper")

    # Load the mass and stiffness from the .op4 file
    # This loads the data into a dict:
    mk = op4.load(os.path.join(pth, "inboard.op4"))
    maa = mk["mxx"][0]
    kaa = mk["kxx"][0]

    # Get the USET table The USET table has the boundary DOF
    # information (id, location, coordinate system). This is needed
    # for superelements with an indeterminate interface. The nastran
    # module has the function bulk2uset which is handy for forming the
    # USET table from bulk data.

    uset, coords = nastran.bulk2uset(os.path.join(pth, "inboard.asm"))

    # uset[::6, [0, 3, 4, 5]]
    # array([[   3.,  600.,    0.,  300.],
    #        [  11.,  600.,  300.,  300.],
    #        [  19.,  600.,  300.,    0.],
    #        [  27.,  600.,    0.,    0.]])

    # x s/c is axial (see figure in cbtf or cbcheck tutorial)
    # - make z l/v axial, but pointing down

    # z s/c  ^ y l/v
    #    \   |   / y s/c
    #       \|/
    #  <------
    # x l/v

    sccoord = [
        [900, 1, 0],
        [0, 0, 0],
        [1, 1, 0],  # z is 45 deg between x & y of l/v
        [0, 0, -1],
    ]  # x is -z l/v
    c = np.cos(45 / 180 * np.pi)
    Tl2s = np.array([[0, 0, -1.0], [-c, c, 0], [c, c, 0]])

    # Form b-set partition vector into a-set
    # In this case, we already know the b-set are first:

    n = uset.shape[0]
    b = np.arange(n)

    # array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
    #        16, 17, 18, 19, 20, 21, 22, 23])

    # convert s/c from mm, kg --> m, kg
    ref = [600, 150, 150]
    conv = (0.001, 1.0)
    g = 9.80665

    u = n2p.addgrid(None, 1, "b", sccoord, [0, 0, 0], sccoord)
    Tsc2lv = np.zeros((6, 6))
    T = u.iloc[3:, 1:]
    Tsc2lv[:3, :3] = T
    Tsc2lv[3:, 3:] = T
    assert np.allclose(Tl2s.T, Tsc2lv[:3, :3])

    net = cb.mk_net_drms(
        maa, kaa, b, uset=uset, ref=ref, sccoord=sccoord, conv=conv, g=g
    )

    usetbq, c, bset = nastran.asm2uset(os.path.join(pth, "inboard.asm"))
    with assert_raises(ValueError) as cm:
        cb.mk_net_drms(
            maa, kaa, b[:3], uset=usetbq, ref=ref, sccoord=Tl2s, conv=conv, g=g
        )
    the_msg = str(cm.exception)
    assert 0 == the_msg.find(
        f"number of rows in `uset` is {uset.shape[0]}, but must "
        f"equal len(b-set) (3)"
    )

    net2 = cb.mk_net_drms(
        maa, kaa, b, uset=usetbq, ref=ref, sccoord=Tl2s, conv=conv, g=g
    )

    # rb modes in system units:
    uset2, ref2 = cb.uset_convert(uset, ref, conv)
    rb = n2p.rbgeom_uset(uset2, ref2)
    l_sc = net.ifltma_sc[:, :n] @ rb
    l_lv = net.ifltma_lv[:, :n] @ rb
    l_scd = net.ifltmd_sc[:, :n] @ rb
    l_lvd = net.ifltmd_lv[:, :n] @ rb
    a_sc = net.ifatm_sc[:, :n] @ rb
    a_lv = net.ifatm_lv[:, :n] @ rb
    c_sc = net.cgatm_sc[:, :n] @ rb
    c_lv = net.cgatm_lv[:, :n] @ rb

    sbe = np.eye(6)
    sbe[:3] *= 1 / g
    assert np.allclose(a_sc, sbe)

    # calc what the interface forces should be:
    # - acceleration = 1 m/s**2 = 1000 mm/s**2
    # - the forces should be very similar to the 6x6 mass
    #   matrix at the reference point ... which, conveniently,
    #   is provided in the cbtf tutorial:
    mass = np.array(
        [
            [1.755, 0.0, -0.0, 0.0, 0.0, 0.0],
            [0.0, 1.755, -0.0, -0.0, 0.0, 772.22],
            [-0.0, -0.0, 1.755, 0.0, -772.22, -0.0],
            [0.0, -0.0, 0.0, 35905.202, -0.0, -0.0],
            [0.0, 0.0, -772.22, -0.0, 707976.725, 109.558],
            [0.0, 772.22, -0.0, -0.0, 109.558, 707976.725],
        ]
    )
    sbe = mass
    sbe[:, :3] *= 1000  # scale up translations
    assert abs(sbe - l_sc).max() < 0.5

    assert np.allclose(Tsc2lv @ a_sc, a_lv)
    assert np.allclose(Tsc2lv @ c_sc, c_lv)
    assert abs(l_scd).max() < 1e-6 * abs(l_sc).max()
    assert abs(l_lvd).max() < 1e-6 * abs(l_lv).max()
    scale = np.array([[1000], [1000], [1000], [1000000], [1000000], [1000000]])
    assert np.allclose((1 / scale) * (Tsc2lv @ l_sc), l_lv)

    # height and mass values from cbcheck tutorial (and then refined):
    m_kg = 1.75505183
    h_m = 1.039998351 - 0.6
    assert abs(net.height_lv - h_m) < 0.000001
    assert abs(net.weight_lv - m_kg * g) < 0.000001
    assert abs(net.height_sc - 1000 * h_m) < 0.000001 * 1000
    assert abs(net.weight_sc - 1000 * m_kg * g) < 0.000001 * 1000
    assert net.scaxial_sc == 0
    assert net.scaxial_lv == 2

    compare_nets(net, net2)

    # check the natural unit output:
    net3 = cb.mk_net_drms(
        maa, kaa, b, uset=uset, ref=ref, sccoord=Tl2s, conv=conv, g=g, tau=("mm", "m")
    )
    for drm in ("ifatm", "cgatm"):
        if drm == "ifatm":
            # only ifatm has 12 rows
            drm1 = getattr(net, drm)
            drm3 = getattr(net3, drm)
            assert np.allclose(drm3[:3], drm1[:3] * g * 1000)
            assert np.allclose(drm3[3:6], drm1[3:6])
            assert np.allclose(drm3[6:9], drm1[6:9] * g)
            assert np.allclose(drm3[9:], drm1[9:])
        for ext, factor in (("_sc", 1000), ("_lv", 1)):
            drm1 = getattr(net, drm + ext)
            drm3 = getattr(net3, drm + ext)
            assert np.allclose(drm3[:3], drm1[:3] * g * factor)
            assert np.allclose(drm3[3:], drm1[3:])

    labels3 = [i.replace("g", "mm/s^2") for i in net.ifatm_labels[:6]] + [
        i.replace("g", "m/s^2") for i in net.ifatm_labels[6:]
    ]
    print(labels3)
    print()
    print(net3.ifatm_labels)
    assert labels3 == net3.ifatm_labels

    net4 = cb.mk_net_drms(
        maa, kaa, b, uset=uset, ref=ref, sccoord=Tl2s, conv=conv, g=g, tau=("g", "m")
    )
    for drm in ("ifatm", "cgatm"):
        if drm == "ifatm":
            # only ifatm has 12 rows
            drm1 = getattr(net, drm)
            drm3 = getattr(net3, drm)
            drm4 = getattr(net4, drm)
            assert np.allclose(drm4[:3], drm1[:3])
            assert np.allclose(drm4[3:6], drm1[3:6])
            assert np.allclose(drm4[6:9], drm3[6:9])
            assert np.allclose(drm4[9:], drm3[9:])
        for ext, net_ in (("_sc", net), ("_lv", net3)):
            drm1 = getattr(net_, drm + ext)
            drm4 = getattr(net4, drm + ext)
            assert np.allclose(drm4[:3], drm1[:3])
            assert np.allclose(drm4[3:], drm1[3:])

    labels4 = net.ifatm_labels[:6] + net3.ifatm_labels[6:]
    assert labels4 == net4.ifatm_labels

    # test mixed b-set/q-set:
    na = maa.shape[0]
    q = np.r_[n:na]
    newb = np.r_[0:12, na - 12 : na]
    newq = np.r_[12 : na - 12]
    kaa_newb = np.empty((na, na))
    maa_newb = np.empty((na, na))
    for newr, oldr in [(newb, b), (newq, q)]:
        for newc, oldc in [(newb, b), (newq, q)]:
            maa_newb[np.ix_(newr, newc)] = maa[np.ix_(oldr, oldc)]
            kaa_newb[np.ix_(newr, newc)] = kaa[np.ix_(oldr, oldc)]

    net5 = cb.mk_net_drms(
        maa_newb,
        kaa_newb,
        newb,
        uset=uset,
        ref=ref,
        sccoord=sccoord,
        conv=conv,
        g=g,
        reorder=False,
    )

    assert np.allclose(net5.ifltma[:, newb], net.ifltma[:, b])
    assert np.allclose(net5.ifltma[:, newq], net.ifltma[:, q])

    net6 = cb.mk_net_drms(
        maa_newb,
        kaa_newb,
        newb,
        uset=uset,
        ref=ref,
        sccoord=sccoord,
        conv=conv,
        g=g,
        reorder=False,
        rbe3_indep_dof=123456,
    )

    assert np.allclose(net6.ifltma, net5.ifltma)
    # translations match:
    assert np.allclose(net6.ifatm_sc[:3], net5.ifatm_sc[:3])
    # rotations do not:
    assert not np.allclose(net6.ifatm_sc[3:], net5.ifatm_sc[3:])
    vec = ytools.mkpattvec([3, 4, 5], len(newb), 6).ravel()
    assert (net5.ifatm_sc[:, newb[vec]] == 0.0).all()
    assert not (net6.ifatm_sc[:, newb[vec]] == 0.0).all()
示例#4
0
def test_rbmultchk():
    nas = op2.rdnas2cam("tests/nas2cam_csuper/nas2cam")
    se = 101
    maa = nas["maa"][se]
    kaa = nas["kaa"][se]
    pv = np.any(maa, axis=0)
    pv = np.ix_(pv, pv)
    maa = maa[pv]
    kaa = kaa[pv]

    uset = nas["uset"][se]
    bset = n2p.mksetpv(uset, "p", "b")
    usetb = nas["uset"][se].iloc[bset]
    b = n2p.mksetpv(uset, "a", "b")
    q = ~b
    b = np.nonzero(b)[0]

    grids = [[11, 123456], [45, 123456], [60, 123456]]
    drm101, dof101 = n2p.formtran(nas, 101, grids)

    # write and read a file:
    f = tempfile.NamedTemporaryFile(delete=False)
    name = f.name
    f.close()

    rb = n2p.rbgeom_uset(usetb)
    cb.rbmultchk(name, drm101, "DRM101", rb)
    with open(name) as f:
        sfile = f.read()
    os.remove(name)

    # test rbscale and unit scale:
    with StringIO() as f:
        cb.rbmultchk(f, 0.00259 * drm101, "DRM101", 100 * rb)
        s = f.getvalue()

    pos = s.find(" which is: ")
    pos2 = s[pos:].find("\n")
    assert math.isclose(float(s[pos + 10 : pos + pos2]), 100)
    s = s.splitlines()
    table, nj1 = gettable(s, 15, 0, "Absolute Maximums", 3)
    sbe = np.array(
        [
            [600, 300, 300, 0.00259],
            [600, 300, 300, 0.00259],
            [600, 300, 300, 0.00259],
            [150, -930, 150, 0.00259],
            [600, 300, 300, 0.00259],
            [150, -930, 150, 0.00259],
        ]
    )

    assert np.allclose(table[:, 1:5], sbe)

    # write to a string:
    with StringIO() as f:
        cb.rbmultchk(f, drm101, "DRM101", rb)
        s = f.getvalue()
    assert sfile == s

    # add q-set rows to rb:
    nq = np.count_nonzero(q)
    rb2 = np.vstack((rb, np.zeros((nq, 6))))
    with StringIO() as f:
        cb.rbmultchk(f, drm101, "DRM101", rb2)
        s2 = f.getvalue()
    assert s2 == s

    # check results when b-set are last:
    drm101_last = np.hstack((drm101[:, q], drm101[:, b]))
    with StringIO() as f:
        cb.rbmultchk(f, drm101_last, "DRM101", rb, bset="last")
        s2 = f.getvalue()
    assert s2 == s

    # check results when b-set are last ... using pv:
    with StringIO() as f:
        bsetpv = np.zeros((len(b) + nq), bool)
        bsetpv[-len(b) :] = True
        cb.rbmultchk(f, drm101_last, "DRM101", rb, bset=bsetpv)
        s2 = f.getvalue()
    assert s2 == s

    with StringIO() as f:
        assert_raises(
            ValueError, cb.rbmultchk, f, drm101, "asdf", rb, bset="bad string"
        )

    # trim q-set columns out of drm:
    labels = [str(i[0]) + "  " + str(i[1]) for i in dof101]
    with StringIO() as f:
        cb.rbmultchk(
            f,
            drm101[:, b],
            "DRM101",
            rb,
            drm2=drm101[:, b],
            prtnullrows=True,
            labels=labels,
        )
        s2 = f.getvalue()

    # row 16 is now all zeros ... not comparable
    drm2 = drm101.copy()
    drm2[15] = 0
    with StringIO() as f:
        cb.rbmultchk(f, drm2, "DRM101", rb, drm2=drm2, prtnullrows=True, labels=labels)
        s3 = f.getvalue()
    assert s2 == s3

    s = s.splitlines()
    with open("tests/nas2cam_csuper/yeti_outputs/rbmultchk_yeti_101.out") as f:
        sy = f.read().splitlines()

    j = [2]
    jy = [2]
    assert comptable(s, sy, j, jy, label="Extreme ", skip=3, col=11)
    assert comptable(s, sy, j, jy, label=" Row ", skip=2, col=68)
    assert comptable(s, sy, j, jy, label=" Row ", skip=2)
    assert comptable(s, sy, j, jy, label=" Row ", skip=2)
示例#5
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)
示例#6
0
def test_cbcheck_determinate():
    nas = op2.rdnas2cam("tests/nas2cam_csuper/nas2cam")
    se = 101
    maa = nas["maa"][se]
    kaa = nas["kaa"][se]
    pv = np.any(maa, axis=0)
    pv = np.ix_(pv, pv)
    maa = maa[pv]
    kaa = kaa[pv]

    uset = nas["uset"][se]
    bset = n2p.mksetpv(uset, "p", "b")
    usetb = nas["uset"][se].iloc[bset]
    b = n2p.mksetpv(uset, "a", "b")

    q = ~b
    b = np.nonzero(b)[0]
    q = np.nonzero(q)[0]

    center = np.mean(usetb.iloc[::6, 1:], axis=0)
    rb = n2p.rbgeom_uset(usetb, center.values)

    # transform to single pt on centerline:
    # [b, q]_old = T*[b, q]_new
    #            = [[rb, 0], [0, I]] * [b, q]_new
    T = np.zeros((len(b) + len(q), 6 + len(q)))
    T[: len(b), :6] = rb
    T[len(b) :, 6:] = np.eye(len(q))

    kaa = T.T @ kaa @ T
    maa = T.T @ maa @ T
    b = np.arange(6)

    # write to a string:
    with StringIO() as f:
        out = cb.cbcheck(f, maa, kaa, b, b[:6], em_filt=2)
        s = f.getvalue()

    s = s.splitlines()
    with open("tests/nas2cam_csuper/yeti_outputs/cbcheck_yeti_101_single.out") as f:
        sy = f.read().splitlines()

    assert s[0] == "Mass matrix is symmetric."
    assert s[1] == "Mass matrix is positive definite."
    assert s[2] == "Warning: stiffness matrix is not symmetric."

    j = [10]
    jy = [10]
    assert comptable(s, sy, j, jy, label="KBB =", skip=1)
    compare_cbcheck_output(s, sy)

    # check with no em filter:
    with StringIO() as f:
        out2 = cb.cbcheck(f, maa, kaa, b, b[:6])
        s2 = f.getvalue()
    s2 = s2.splitlines()

    s_unique = [i for i in s if i not in s2]
    # ['Printing only the modes with at least 2.0% effective mass.',
    #  'The sum includes all modes.']

    s2_unique = [i for i in s2 if i not in s]
    # ['     5          7.025        0.00    0.00    0.00    0.00    0.88    0.00',
    #  '     6          7.025        0.00    0.00    0.00    0.00    0.00    0.00',
    #  '     7         10.913        0.00    0.00    0.00    0.00    0.00    1.52',
    #  '    11         25.135        0.00    0.00    0.00    0.00    0.00    0.42',
    #  '    12         25.140        1.03    0.00    0.00    0.00    0.00    0.00',
    #  '    13         42.173        0.00    0.00    0.00    0.51    0.00    0.00',
    #  '    14         42.193        0.00    0.00    1.04    0.00    1.02    0.00',
    #  '    16         46.895        0.00    0.00    0.00    0.00    0.00    0.00',
    #  '    17         69.173        0.00    0.13    0.00    0.00    0.00    0.99']

    assert len(s2) > len(s)
    assert len(s_unique) == 2
    assert len(s2_unique) == 9
示例#7
0
def test_cbcheck_indeterminate():
    nas = op2.rdnas2cam("tests/nas2cam_csuper/nas2cam")
    se = 101
    maa = nas["maa"][se]
    kaa = nas["kaa"][se]
    pv = np.any(maa, axis=0)
    pv = np.ix_(pv, pv)
    maa = maa[pv]
    kaa = kaa[pv]

    uset = nas["uset"][se]
    bset = n2p.mksetpv(uset, "p", "b")
    usetb = nas["uset"][se].iloc[bset]
    b = n2p.mksetpv(uset, "a", "b")
    q = ~b
    b = np.nonzero(b)[0]

    # write and read a file:
    f = tempfile.NamedTemporaryFile(delete=False)
    name = f.name
    f.close()
    # m, k, bset, rbs, rbg, rbe, usetconv = cb.cbcheck(
    out = cb.cbcheck(name, maa, kaa, b, b[:6], uset, em_filt=2)
    with open(name) as f:
        sfile = f.read()
    os.remove(name)
    assert (out.m == maa).all()
    assert (out.k == kaa).all()
    assert out.uset.equals(usetb)

    rbg = n2p.rbgeom_uset(out.uset)
    assert np.allclose(rbg, out.rbg)
    rbg_s = np.vstack((la.solve(rbg[:6].T, rbg.T).T, np.zeros((q[q].size, 6))))
    assert abs(out.rbs - rbg_s).max() < 1e-5
    assert abs(out.rbe - rbg_s).max() < 1e-5

    # write to a string:
    with StringIO() as f:
        out = cb.cbcheck(f, maa, kaa, b, b[:6], usetb, em_filt=2)
        s = f.getvalue()

    assert sfile == s
    s = s.splitlines()

    with open("tests/nas2cam_csuper/yeti_outputs/cbcheck_yeti_101.out") as f:
        sy = f.read().splitlines()

    assert s[0] == "Mass matrix is symmetric."
    assert s[1] == "Mass matrix is positive definite."
    assert s[2] == "Stiffness matrix is symmetric."

    compare_cbcheck_output(s, sy)

    with StringIO() as f:
        out = cb.cbcheck(f, maa, kaa, b, b[:6], usetb, em_filt=2, conv="e2m")
        out2 = cb.cbcheck(f, out.m, out.k, b, b[:6], out.uset, em_filt=2, conv="m2e")
        assert np.allclose(out2.uset, usetb)
        assert np.allclose(maa, out2.m)
        assert np.allclose(kaa, out2.k)

    # check for error catches:
    with StringIO() as f:
        assert_raises(
            ValueError, cb.cbcheck, f, maa, kaa, b, b[:6], usetb.iloc[:-6], em_filt=2
        )
示例#8
0
def test_cglf_moment_signs():
    pth = os.path.dirname(inspect.getfile(cb))
    pth = os.path.join(pth, "..")
    pth = os.path.join(pth, "tests")
    pth = os.path.join(pth, "cla_test_data")

    se = 101
    uset, coords = nastran.bulk2uset(os.path.join(pth, "outboard.asm"))
    dct = op4.read(os.path.join(pth, "outboard.op4"))
    maa = dct["mxx"]
    kaa = dct["kxx"]
    atm = dct["mug1"]
    ltm = dct["mef1"]
    pch = os.path.join(pth, "outboard.pch")
    atm_labels = [
        "Grid {:4d}-{:1d}".format(grid, dof) for grid, dof in nastran.rddtipch(pch)
    ]
    ltm_labels = [
        "CBAR {:4d}-{:1d}".format(cbar, arg)
        for cbar, arg in nastran.rddtipch(pch, "tef1")
    ]

    nb = uset.shape[0]
    nq = maa.shape[0] - nb
    bset = np.arange(nb)
    qset = np.arange(nq) + nb
    ref = [600.0, 150.0, 150.0]
    g = 9806.65

    # use addgrid to get coordinate transformations from lv to sc:
    cid = [1, 0, 0]
    A = [0, 0, 0]
    # define sc in terms of lv coords:
    # (all drawn out by hand)
    BC = [
        [[0, 0, 1.0], [1.0, 0, 0]],  # lv x is up
        [[0, 0, -1.0], [0, 1.0, 0]],  # lv y is up
        [[-1.0, 0, 0.0], [0, 0, 1.0]],  # lv z is up
        [[0, 0, -1.0], [-1.0, 0, 0]],  # lv x is down
        [[0, 0, 1.0], [0, -1.0, 0]],  # lv y is down
        [[0, -1.0, 0], [0, 0, -1.0]],  # lv z is down
    ]
    Ts = []
    nets = []
    rb = n2p.rbgeom_uset(uset, ref)
    rbcglfa = []
    for bc in BC:
        CI = n2p.mkusetcoordinfo([cid, A, *bc], None, {})
        T = CI[2:]
        Ts.append(T)
        net = cb.mk_net_drms(maa, kaa, bset, uset=uset, ref=ref, g=g, sccoord=T)
        nets.append(net)
        rba = net.cglfa[:, :24] @ rb
        rbcglfa.append(rba)
        # sc rows:
        assert np.all(np.sign(rba[1, [1, 5]]) == np.sign(rba[3, [1, 5]]))
        assert np.all(np.sign(rba[2, [2, 4]]) == np.sign(rba[4, [2, 4]]))
        # lv rows:
        assert np.all(np.sign(rba[6, [1, 5]]) == np.sign(rba[8, [1, 5]]))
        assert np.all(np.sign(rba[7, [2, 4]]) == np.sign(rba[9, [2, 4]]))

    wh_sc = nets[0].weight_sc * nets[0].height_sc
    wh_lv = nets[0].weight_lv * nets[0].height_lv
    n = nets[0].cgatm_sc.shape[1]
    # x is down:
    cgdrm = np.vstack(
        (
            # 5 s/c rows
            nets[0].cgatm_sc[:3],
            -nets[0].ifltma_sc[5] / wh_sc,
            nets[0].ifltma_sc[4] / wh_sc,
            # 5 l/v rows
            nets[0].cgatm_lv[:3],
            -nets[0].ifltma_lv[5] / wh_lv,
            nets[0].ifltma_lv[4] / wh_lv,
            # 4 RSS rows ... filled in during data recovery
            np.zeros((4, n)),
        )
    )
    assert np.allclose(cgdrm, nets[0].cglfa)
示例#9
0
def test_mk_net_drms_6dof():
    # same as above, but reduced to single point interface
    pth = os.path.dirname(inspect.getfile(cb))
    pth = os.path.join(pth, "..")
    pth = os.path.join(pth, "tests")
    pth = os.path.join(pth, "nas2cam_csuper")
    mk = op4.load(os.path.join(pth, "inboard.op4"))
    maa = mk["mxx"][0]
    kaa = mk["kxx"][0]
    uset, coords = nastran.bulk2uset(os.path.join(pth, "inboard.asm"))
    n = uset.shape[0]
    b = np.arange(n)
    q = np.arange(n, maa.shape[0])
    ttl = maa.shape[0]

    # reduce to single point interface:
    rb = n2p.rbgeom_uset(uset, [600, 150, 150])

    # old = {b_24} = {rb.T @ b_6}  = [rb.T  0_6?] {b_6}
    #       {q_?}    {q_?}           [0_?6   I??] {q_?}
    trans = np.zeros((len(q) + 6, ttl))
    trans[:6, :n] = rb.T
    trans[6:, n:] = np.eye(len(q))
    maa = trans @ maa @ trans.T
    kaa = trans @ kaa @ trans.T

    # no conversion, no coordinate change:
    g = 9.80665
    n = 6
    b = np.arange(n)
    net = cb.mk_net_drms(maa, kaa, b, g=g)
    net2 = cb.mk_net_drms(maa, kaa, b, g=g, bsubset=b)
    l_sc = net.ifltma_sc[:, :n]
    l_lv = net.ifltma_lv[:, :n]
    l_scd = net.ifltmd_sc[:, :n]
    l_lvd = net.ifltmd_lv[:, :n]
    a_sc = net.ifatm_sc[:, :n]
    a_lv = net.ifatm_lv[:, :n]
    c_sc = net.cgatm_sc[:, :n]
    c_lv = net.cgatm_lv[:, :n]

    sbe = np.eye(6)
    sbe[:3] *= 1 / g
    assert np.allclose(a_sc, sbe)
    mass = np.array(
        [
            [1.755, 0.0, -0.0, 0.0, 0.0, 0.0],
            [0.0, 1.755, -0.0, -0.0, 0.0, 772.22],
            [-0.0, -0.0, 1.755, 0.0, -772.22, -0.0],
            [0.0, -0.0, 0.0, 35905.202, -0.0, -0.0],
            [0.0, 0.0, -772.22, -0.0, 707976.725, 109.558],
            [0.0, 772.22, -0.0, -0.0, 109.558, 707976.725],
        ]
    )
    sbe = mass
    assert abs(sbe - l_sc).max() < 0.0005

    Tsc2lv = np.eye(6)
    assert np.allclose(Tsc2lv @ a_sc, a_lv)
    assert np.allclose(Tsc2lv @ c_sc, c_lv)
    assert abs(l_scd).max() < 1e-6 * abs(l_sc).max()
    assert abs(l_lvd).max() < 1e-6 * abs(l_lv).max()
    assert np.allclose((Tsc2lv @ l_sc), l_lv)

    # height and mass values from cbcheck tutorial (and then refined):
    m_kg = 1.75505183
    h_m = 1039.998351 - 600
    assert abs(net.height_lv - h_m) < 0.0001
    assert abs(net.weight_lv - m_kg * g) < 0.0001
    assert abs(net.height_sc - h_m) < 0.0001
    assert abs(net.weight_sc - m_kg * g) < 0.0001
    assert net.scaxial_sc == 0
    assert net.scaxial_lv == 0

    compare_nets(net, net2)