Exemple #1
0
def _run_mass_properties(model2, nnodes, nelements, run_mass_properties=True):
    """helper method"""
    if not (run_mass_properties and nelements):
        return

    if nelements > 1 and nnodes == 0:  # pragma: no cover
        raise RuntimeError('no nodes exist')
    mass1, cg1, inertia1 = mass_properties(model2,
                                           reference_point=None,
                                           sym_axis=None)
    mass2, cg2, inertia2 = mass_properties_nsm(model2,
                                               reference_point=None,
                                               sym_axis=None)
    #if not quiet:
    #if model2.wtmass != 1.0:
    #print('weight = %s' % (mass1 / model2.wtmass))
    #print('mass = %s' % mass1)
    #print('cg   = %s' % cg1)
    #print('Ixx=%s, Iyy=%s, Izz=%s \nIxy=%s, Ixz=%s, Iyz=%s' % tuple(inertia1))
    assert np.allclose(mass1, mass2), 'mass1=%s mass2=%s' % (mass1, mass2)
    assert np.allclose(cg1, cg2), 'mass=%s\ncg1=%s cg2=%s' % (mass1, cg1, cg2)
    if not np.allclose(inertia1, inertia2, atol=1e-5):  # pragma: no cover
        raise ValueError(
            'mass=%s cg=%s\ninertia1=%s\ninertia2=%s\ndinertia=%s' %
            (mass1, cg1, inertia1, inertia2, inertia1 - inertia2))

    unused_mass3, unused_cg3, unused_inertia3 = mass_properties_breakdown(
        model2)[:3]
Exemple #2
0
    def test_nsmadd(self):
        """tests the NSMADD and all NSM cards"""
        eid_quad = 1
        unused_eid_tri = 2
        unused_eid_conrod = 3
        unused_eid_crod = 4
        unused_eid_pbeaml = 5
        unused_eid_pbarl = 6
        unused_pid_pbeaml = 40
        pid_pshell = 10
        unused_pid_pbeaml = 21
        unused_pid_pbarl = 31
        unused_pid_prod = 41
        mid = 100
        E = 3.0e7
        G = None
        nu = 0.3
        nids = [1, 2, 3, 4]

        model = BDF(debug=False)
        model.add_grid(1, [0., 0., 0.])
        model.add_grid(2, [1., 0., 0.])
        model.add_grid(3, [1., 1., 0.])
        model.add_grid(4, [0., 1., 0.])
        model.add_cquad4(eid_quad, pid_pshell, nids)  # area=1.0
        model.add_mat1(mid, E, G, nu, rho=0.0)
        model.add_pshell(pid_pshell, mid1=mid, t=0.1)  #, nsm=None)

        model.add_nsm1(1000, 'PSHELL', 1.0, pid_pshell,
                       comment='nsm1')  # correct; 1.0
        model.add_nsml1(2000, 'PSHELL', 1.0, pid_pshell,
                        comment='nsml1')  # correct; 1.0
        model.add_nsml(3000, 'PSHELL', pid_pshell, 1.0,
                       comment='nsml')  # correct; 1.0
        model.add_nsml(4000, 'PSHELL', pid_pshell, 1.0,
                       comment='nsml')  # correct; 1.0
        model.add_nsmadd(5000, [1000, 2000, 3000, 4000], comment='nsmadd')
        model.add_nsmadd(5000, [1000, 2000, 3000, 4000], comment='nsmadd')
        model.cross_reference()
        model.pop_xref_errors()

        mass, unused_cg, unused_I = mass_properties_nsm(model, nsm_id=5000)
        self.assertAlmostEqual(mass, 8.0)
        model2 = save_load_deck(model)
        mass, unused_cg, unused_I = mass_properties_nsm(model2, nsm_id=5000)
Exemple #3
0
 def check_solid(self, model, eid, etype, pid, ptype, mid, mtype, nsm, rho,
                 V):
     """checks that various solid methods work"""
     mass = rho * V
     element = model.elements[eid]
     assert max(element.node_ids) > 0
     assert pid in model.properties, 'pid is missing for\n%s' % str(element)
     self.assertEqual(element.type, etype)
     self.assertEqual(element.eid, eid)
     self.assertEqual(element.pid_ref.type, ptype)
     self.assertEqual(element.Pid(), pid)
     self.assertEqual(element.pid_ref.mid_ref.type, mtype)
     self.assertEqual(element.Mid(), mid)
     self.assertEqual(element.Volume(), V)
     self.assertEqual(element.Mass(), mass)
     mass_mp = mass_properties(model, element_ids=eid)[0]
     mass_mp_nsm = mass_properties_nsm(model, element_ids=eid)[0]
     assert np.allclose(mass, mass_mp)
     assert np.allclose(mass, mass_mp_nsm)
Exemple #4
0
 def check_solid(self, model, eid, etype, pid, ptype, mid, mtype, nsm, rho,
                 volume):
     """checks that various solid methods work"""
     mass = rho * volume
     element = model.elements[eid]
     assert max(element.node_ids) > 0
     assert pid in model.properties, 'pid is missing for\n%s' % str(element)
     self.assertEqual(element.type, etype)
     self.assertEqual(element.eid, eid)
     self.assertEqual(element.pid_ref.type, ptype)
     self.assertEqual(element.Pid(), pid)
     self.assertEqual(element.pid_ref.mid_ref.type, mtype)
     self.assertEqual(element.Mid(), mid)
     self.assertEqual(element.Volume(), volume)
     self.assertEqual(element.Mass(), mass)
     mass_mp = mass_properties(model, element_ids=eid)[0]
     mass_mp_nsm = mass_properties_nsm(model, element_ids=eid)[0]
     unused_centroid, unused_xe, unused_ye, unused_ze = element.material_coordinate_system(
     )
     assert np.allclose(mass, mass_mp)
     assert np.allclose(mass, mass_mp_nsm)
Exemple #5
0
    def mass_properties_nsm(self,
                            element_ids=None,
                            mass_ids=None,
                            nsm_id=None,
                            reference_point=None,
                            sym_axis=None,
                            scale=None,
                            inertia_reference='cg',
                            xyz_cid0_dict=None,
                            debug=False):
        """
        Calculates mass properties in the global system about the
        reference point.  Considers NSM, NSM1, NSML, NSML1.

        Parameters
        ----------
        model : BDF()
            a BDF object
        element_ids : list[int]; (n, ) ndarray, optional
            An array of element ids.
        mass_ids : list[int]; (n, ) ndarray, optional
            An array of mass ids.
        nsm_id : int
            the NSM id to consider
        reference_point : ndarray/int, optional
            type : ndarray
                An array that defines the origin of the frame.
                default = <0,0,0>.
            type : int
                the node id
        sym_axis : str, optional
            The axis to which the model is symmetric.
            If AERO cards are used, this can be left blank.
            allowed_values = 'no', x', 'y', 'z', 'xy', 'yz', 'xz', 'xyz'
        scale : float, optional
            The WTMASS scaling value.
            default=None -> PARAM, WTMASS is used
            float > 0.0
        inertia_reference : str; default='cg'
            'cg' : inertia is taken about the cg
            'ref' : inertia is about the reference point
        xyz_cid0_dict : dict[nid] : xyz; default=None -> auto-calculate
            mapping of the node id to the global position
        debug : bool; default=False
            developer debug; may be removed in the future

        Returns
        -------
        mass : float
            The mass of the model.
        cg : ndarray
            The cg of the model as an array.
        inertia : ndarray
            Moment of inertia array([Ixx, Iyy, Izz, Ixy, Ixz, Iyz]).

        I = mass * centroid * centroid

        .. math:: I_{xx} = m (dy^2 + dz^2)

        .. math:: I_{yz} = -m * dy * dz

        where:

        .. math:: dx = x_{element} - x_{ref}

        .. seealso:: http://en.wikipedia.org/wiki/Moment_of_inertia#Moment_of_inertia_tensor

        .. note::
           This doesn't use the mass matrix formulation like Nastran.
           It assumes m*r^2 is the dominant term.
           If you're trying to get the mass of a single element, it
           will be wrong, but for real models will be correct.

        Examples
        --------
        **mass properties of entire structure**

        >>> mass, cg, inertia = model.mass_properties()
        >>> Ixx, Iyy, Izz, Ixy, Ixz, Iyz = inertia


        **mass properties of model based on Property ID**
        >>> pids = list(model.pids.keys())
        >>> pid_eids = model.get_element_ids_dict_with_pids(pids)
        >>> for pid, eids in sorted(pid_eids.items()):
        >>>     mass, cg, inertia = mass_properties(model, element_ids=eids)

        Warnings
        --------
         - If eids are requested, but don't exist, no warning is thrown.
           Decide if this is the desired behavior.
         - If the NSMx ALL option is used, the mass from all elements
           will be considered, even if not included in the element set

        """
        self.deprecated(
            'mass, cg, inertia = model.mass_properties_nsm(...)',
            'from pyNastran.bdf.mesh_utils.mass_properties import mass_properties_nsm\n'
            'mass, cg, inertia = mass_properties_nsm(model, ...)', '1.3')
        mass, cg, inertia = mass_properties_nsm(
            self,
            element_ids=element_ids,
            mass_ids=mass_ids,
            nsm_id=nsm_id,
            reference_point=reference_point,
            sym_axis=sym_axis,
            scale=scale,
            inertia_reference=inertia_reference,
            xyz_cid0_dict=xyz_cid0_dict,
            debug=debug)
        return (mass, cg, inertia)
Exemple #6
0
    def test_nsm_cquad4(self):
        eid_quad = 1
        eid_tri = 2
        eid_conrod = 3
        eid_crod = 4
        eid_pbeaml = 5
        eid_pbarl = 6
        pid_pbeaml = 40
        pid_pshell = 10
        pid_pbeaml = 21
        pid_pbarl = 31
        pid_prod = 41
        mid = 100
        E = 3.0e7
        G = None
        nu = 0.3
        nids = [1, 2, 3, 4]
        model = BDF(debug=False)
        model.add_grid(1, [0., 0., 0.])
        model.add_grid(2, [1., 0., 0.])
        model.add_grid(3, [1., 1., 0.])
        model.add_grid(4, [0., 1., 0.])
        model.add_cquad4(eid_quad, pid_pshell, nids)  # area=1.0
        model.add_ctria3(eid_tri, pid_pshell, nids[:-1])  # area=0.5
        model.add_conrod(eid_conrod,
                         mid, [1, 2],
                         A=1.0,
                         j=0.0,
                         c=0.0,
                         nsm=0.0,
                         comment='')

        x = [0., 0., 1.]
        g0 = None
        model.add_cbar(eid_pbarl,
                       pid_pbarl, [1, 2],
                       x,
                       g0,
                       offt='GGG',
                       pa=0,
                       pb=0,
                       wa=None,
                       wb=None,
                       comment='')
        model.add_cbeam(eid_pbeaml,
                        pid_pbeaml,
                        nids,
                        x,
                        g0,
                        offt='GGG',
                        bit=None,
                        pa=0,
                        pb=0,
                        wa=None,
                        wb=None,
                        sa=0,
                        sb=0,
                        comment='')
        model.add_crod(eid_crod, pid_prod, [1, 2])
        model.add_prod(pid_prod, mid, A=0.1)
        model.add_pshell(pid_pshell, mid1=mid, t=0.1)  #, nsm=None)

        bar_type = 'BAR'
        dims = [1., 2.]
        xxb = [0.]
        model.add_pbarl(pid_pbarl,
                        mid,
                        bar_type,
                        dims,
                        group='MSCBML0',
                        nsm=0.,
                        comment='')

        beam_type = 'BAR'
        dims = [[1., 2.]]
        nsm = [0.0]
        model.add_pbeaml(pid_pbeaml,
                         mid,
                         beam_type,
                         xxb,
                         dims,
                         so=None,
                         nsm=nsm,
                         group='MSCBML0',
                         comment='')
        model.add_mat1(mid, E, G, nu, rho=0.0)

        # TODO: these are correct barring incorrect formulas
        model.add_nsm1(1000, 'PSHELL', 1.0, pid_pshell,
                       comment='nsm1')  # correct; 1.5
        model.add_nsm1(1001, 'ELEMENT', 1.0, eid_quad)  # correct; 1.0
        model.add_nsm1(1002, 'ELEMENT', 1.0,
                       [eid_quad, eid_tri])  # correct; 1.5
        model.add_nsm1(1003, 'ELEMENT', 1.0, [eid_pbeaml])  # correct; 1.0
        model.add_nsm1(1004, 'ELEMENT', 1.0, eid_pbarl)  # correct; 1.0
        model.add_nsm1(1005, 'ELEMENT', 1.0,
                       'ALL')  # crash according to QRG b/c mixed type; 2.5
        model.add_nsm1(1006, 'PSHELL', 1.0, 'ALL')  # correct; 1.5
        model.add_nsm1(1007, 'PSHELL', 1.0, [10, 'THRU', 12])  # correct; 1.5
        model.add_nsm1(1008, 'PSHELL', 1.0,
                       [10, 'THRU', 12, 'BY', 2])  # correct; 1.5
        model.add_nsm1(1009, 'PBARL', 1.0, pid_pbarl)  # correct; 1.0
        model.add_nsm1(1010, 'PBEAML', 1.0, pid_pbeaml)  # correct; 1.0
        model.add_nsm1(1011, 'PROD', 1.0, pid_prod)  # correct; 1.0
        model.add_nsm1(1012, 'CONROD', 1.0, eid_conrod)  # correct; 1.0

        #model.add_nsml1(sid, nsm_type, value, ids)
        model.add_nsml1(2000, 'PSHELL', 1.0, pid_pshell,
                        comment='nsml1')  # correct; 1.0
        model.add_nsml1(2001, 'ELEMENT', 1.0, eid_quad)  # correct; 1.0
        model.add_nsml1(2002, 'ELEMENT', 1.0,
                        [eid_quad, eid_tri])  # correct; 1.0
        model.add_nsml1(2003, 'ELEMENT', 1.0, [eid_pbeaml])  # correct; 1.0
        model.add_nsml1(2004, 'ELEMENT', 1.0, eid_pbarl)  # correct; 1.0
        model.add_nsml1(2005, 'ELEMENT', 1.0,
                        'ALL')  # crash according to QRG b/c mixed type; 1.0
        model.add_nsml1(2006, 'PSHELL', 1.0, 'ALL')  # correct; 1.0
        model.add_nsml1(2007, 'PSHELL', 1.0, [10, 'THRU', 12])  # correct; 1.0
        model.add_nsml1(2008, 'PSHELL', 1.0,
                        [10, 'THRU', 12, 'BY', 2])  # correct; 1.0
        model.add_nsml1(2009, 'PBARL', 1.0, pid_pbarl)  # correct; 1.0
        model.add_nsml1(2010, 'PBEAML', 1.0, pid_pbeaml)  # correct; 1.0
        model.add_nsml1(2011, 'PROD', 1.0, pid_prod)  # correct; 1.0
        model.add_nsml1(2012, 'CONROD', 1.0, eid_conrod)  # correct; 1.0

        #model.add_nsml1(2011, 'PSHELL', 1.0, ['1240', 'THRU', '1250', None, None, # correct; 0.0
        #'2567', 'THRU', '2575',
        #'35689', 'THRU', '35700', None, None,
        #'76', 'THRU', '85',])
        #print(model.nsms[2011])

        model.add_nsm(3000, 'PSHELL', pid_pshell, 1.0,
                      comment='nsm')  # correct; 1.5
        model.add_nsm(3001, 'ELEMENT', eid_quad, 1.0)  # correct; 1.0
        model.add_nsm(3003, 'ELEMENT', [eid_pbeaml], 1.0)  # correct; 1.0
        model.add_nsm(3004, 'ELEMENT', eid_pbarl, 1.0)  # correct; 1.0
        model.add_nsm(3009, 'PBARL', pid_pbarl, 1.0)  # correct; 1.0
        model.add_nsm(3010, 'PBEAML', pid_pbeaml, 1.0)  # correct; 1.0
        model.add_nsm(3011, 'PROD', pid_prod, 1.0)  # correct; 1.0
        model.add_nsm(3012, 'CONROD', eid_conrod, 1.0)  # correct; 1.0

        model.add_nsml(4000, 'PSHELL', pid_pshell, 1.0,
                       comment='nsml')  # correct; 1.0
        model.add_nsml(4001, 'ELEMENT', eid_quad, 1.0)  # correct; 1.0
        model.add_nsml(4003, 'ELEMENT', [eid_pbeaml], 1.0)  # correct; 1.0
        model.add_nsml(4004, 'ELEMENT', eid_pbarl, 1.0)  # correct; 1.0
        model.add_nsml(4009, 'PBARL', pid_pbarl, 1.0)  # correct; 1.0
        model.add_nsml(4010, 'PBEAML', pid_pbeaml, 1.0)  # correct; 1.0
        model.add_nsml(4011, 'PROD', pid_prod, 1.0)  # correct; 1.0
        model.add_nsml(4012, 'CONROD', eid_conrod, 1.0)  # correct; 1.0

        model.pop_parse_errors()
        model.cross_reference()
        model.pop_xref_errors()

        expected_dict = {
            # NSM1
            1000: 1.5,
            1001: 1.0,
            1002: 1.5,
            1003: 1.0,
            1004: 1.0,
            1005: -1.0,  # crash
            1006: 1.5,
            1007: 1.5,
            1008: 1.5,
            1009: 1.0,
            1010: 1.0,
            1011: 1.0,
            1012: 1.0,

            #model.add_nsml1(sid, nsm_type, value, ids)
            # NSML1
            2000: 1.0,
            2001: 1.0,
            2002: 1.0,
            2003: 1.0,
            2004: 1.0,
            2005: -1.0,  # crash
            2006: 1.0,
            2007: 1.0,
            2008: 1.0,
            2009: 1.0,
            2010: 1.0,
            2011: 1.0,
            2012: 1.0,

            # NSM
            3000: 1.5,
            3001: 1.0,
            3003: 1.0,
            3004: 1.0,
            3009: 1.0,
            3010: 1.0,
            3011: 1.0,
            3012: 1.0,

            # NSM1
            4000: 1.0,
            4001: 1.0,
            4003: 1.0,
            4004: 1.0,
            4009: 1.0,
            4010: 1.0,
            4011: 1.0,
            4012: 1.0,
        }
        for nsm_id in sorted(model.nsms):
            mass1_expected = expected_dict[nsm_id]
            if mass1_expected == -1.0:
                with self.assertRaises(RuntimeError):
                    mass1, unused_cg, unused_I = mass_properties_nsm(
                        model, nsm_id=nsm_id, debug=False)
            else:
                mass1, unused_cg, unused_I = mass_properties_nsm(model,
                                                                 nsm_id=nsm_id,
                                                                 debug=False)
                if mass1 != mass1_expected:
                    unused_mass2 = mass_properties_nsm(model,
                                                       nsm_id=nsm_id,
                                                       debug=True)[0]
                    raise RuntimeError('nsm_id=%s mass != %s; mass1=%s' %
                                       (nsm_id, mass1_expected, mass1))
            #print('mass[%s] = %s' % (nsm_id, mass))
            #print('----------------------------------------------')

        model2 = save_load_deck(model, run_test_bdf=False)
        model2.reset_rslot_map()
        #print(model2._type_to_slot_map)
        model2.elements = {}

        type_to_id_map = {}
        for card_type, ids in model2._type_to_id_map.items():
            if card_type in [
                    'CQUAD4', 'CTRIA3', 'CBEAM', 'CONROD', 'CBAR', 'CROD'
            ]:
                pass
            elif card_type in [
                    'NSM', 'NSM1', 'NSML', 'NSML1', 'MAT1', 'PBARL', 'PBEAM',
                    'PSHELL', 'PCOMP', 'PROD', 'PBEAML', 'GRID'
            ]:
                type_to_id_map[card_type] = ids
            else:
                raise NotImplementedError(str((card_type, ids)))
        model2._type_to_id_map = type_to_id_map

        model2.log = SimpleLogger(level='error')

        # don't crash on the null case
        for nsm_id in sorted(model2.nsms):
            mass, unused_cg, unused_I = mass_properties_nsm(model2,
                                                            nsm_id=nsm_id,
                                                            debug=False)
            self.assertEqual(mass, 0.0)
Exemple #7
0
    def test_shear(self):
        """tests a CSHEAR, PSHEAR"""
        pid = 10
        pid_pshell = 11

        mid = 100
        log = get_logger(level='warning')
        model = BDF(log=log)
        model.add_grid(1, [0., 0., 0.])
        model.add_grid(2, [1., 0., 0.])
        model.add_grid(3, [1., 1., 0.])
        model.add_grid(4, [0., 1., 0.])
        nsm = 10.0
        t = 1.0
        rho = 1.0
        cshear = model.add_cshear(10, pid, [1, 2, 3, 4],
                                  comment='cshear')

        cquad4 = model.add_cquad4(14, pid_pshell, [1, 2, 3, 4],
                                  comment='cquad4')
        model.add_pshear(pid, mid, t=t,
                         nsm=nsm, f1=0., f2=0., comment='pshear')
        model.add_pshell(pid_pshell, mid1=mid, t=t, mid2=None, twelveIt3=1.0,
                         mid3=None, tst=0.833333,
                         nsm=nsm, z1=None, z2=None,
                         mid4=None, comment='')

        E = 3.0e7
        G = None
        nu = 0.3
        model.add_mat1(mid, E, G, nu, rho=rho)
        model.validate()

        model.cross_reference()
        model.pop_xref_errors()

        area = 1.0
        mass_expected = area * (rho * t + nsm)
        mass = model.mass_properties()[0]
        assert np.allclose(mass, mass_expected*2), 'mass_properties all: mass=%s mass_expected=%s' % (mass, mass_expected*2)

        mass = model.mass_properties(element_ids=10)[0]
        assert np.allclose(mass, mass_expected), 'mass_properties reduced: mass=%s mass_expected=%s' % (mass, mass_expected)

        mass = mass_properties_nsm(model)[0]
        assert np.allclose(mass, mass_expected*2), 'mass_properties_nsm all: mass=%s mass_expected=%s' % (mass, mass_expected*2)

        mass = mass_properties_nsm(model, element_ids=10)[0]
        assert np.allclose(mass, mass_expected), 'mass_properties_nsm reduced: mass=%s mass_expected=%s' % (mass, mass_expected)

        bdf_file = StringIO()
        model.write_bdf(bdf_file)
        model.uncross_reference()
        model.cross_reference()
        model.pop_xref_errors()

        model.get_area_breakdown(property_ids=None, stop_if_no_area=True)
        model.get_mass_breakdown(property_ids=None, stop_if_no_mass=True, detailed=False)
        model.get_mass_breakdown(property_ids=None, stop_if_no_mass=True, detailed=True)
        model.get_volume_breakdown(property_ids=None, stop_if_no_volume=True)

        assert np.allclose(cshear.Mass(), mass_expected), cshear.Mass()

        model.uncross_reference()
        model.safe_cross_reference()
        model.uncross_reference()

        #bdf_file = model.write_bdf(bdf_file)

        save_load_deck(model)