Source code for pyNastran.op2.result_objects.grid_point_weight

"""defines the GridPointWeight class"""
from __future__ import print_function
from six import StringIO

from numpy import zeros

from pyNastran.utils import object_attributes, object_methods


[docs]class GridPointWeight(object): def __init__(self): """ .. seealso:: http://www.6dof.com/index.php?option=com_content&view=article&id=298:output-from-the-grid-point-weight-generator&catid=178:courses-and-trainings&Itemid=61 """ # The Grid Point Weight Generator (GPWG) module computes the rigid body # mass properties of an entire structure with respect to a user specified point and with # respect to the center of mass. Output from the module is requested by a PARAM # GRDPNT card in the Bulk Data Deck which specifies from which grid point mass # computations are to be referenced. Optionally, the absence of a specific grid point # (i.e. PARAM, GRDPNT, 0) automatically causes the origin of the basic # coordinate system to be utilized as a reference. The mass properties are initially # defined in the basic coordinate system. Subsequently, the mass properties are # transformed to principal mass axes and to principal inertia axes. The actual printout # is composed of several elements. These are: self.reference_point = None # M0 RIGID BODY MASS MATRIX IN BASIC COORDINATE SYSTEM # This is the rigid body mass matrix of the entire structure in the basic coordinate # system with respect to a reference point chosen by the analyst. self.MO = None # S TRANSFORMATION MATRIX FOR SCALAR MASS PARTITION # S is the transformation from the basic coordinate system to the set of principal axes # for the 3 x 3 scalar mass partition of the 6 x 6 mass matrix. The principal axes for # just the scalar partition are known as the principal mass axes. self.S = None self.mass = None # XC.G. YC.G. ZC.G. # It is possible in NASTRAN to assemble a structural model having different values of # mass in each coordinate direction at a grid point. This can arise, for example, by # assembling scalar mass components or from omitting some components by means of bar # element pin flags. Consequently three distinct mass systems are assembled one in each of # the three directions of the principal mass axes (the S system). This third tabulation # has five columns. The first column lists the axis direction in the S coordinates. The # second column lists the mass associated with the appropriate axis direction. The final # three columns list the x, y, and z coordinate distances from the reference point to the # center of mass for each of the three mass systems. self.cg = None # I(S) INERTIAS RELATIVE TO C.G. # This is the 3 x 3 mass moment of inertia partition with respect to the center of # gravity referred to the principal mass axes (the S system). This is not necessarily a # diagonal matrix because the determination of the S system does not involve second # moments. The values of inertias at the center of gravity are found from the values at # the reference point employing the parallel axes rule. self.IS = None # I(Q) PRINCIPAL INERTIAS # The principal moments of inertia at the center of gravity are displayed in matrix # form with reference to the Q system of axes. The Q system is obtained from an eigenvalue # analysis of the I(S) matrix. self.IQ = None # Q TRANSFORMATION MATRIX I(Q) = QT*IBAR(S)*Q # Q is the coordinate transformation between the S axes and the Q axes. IBAR(S) is the # same as I(s) except that the signs of the offdiagonal terms are reversed. self.Q = None
[docs] def object_attributes(self, mode='public', keys_to_skip=None): if keys_to_skip is None: keys_to_skip = [] my_keys_to_skip = [ 'object_methods', 'object_attributes', ] return object_attributes(self, mode=mode, keys_to_skip=keys_to_skip+my_keys_to_skip)
[docs] def object_methods(self, mode='public', keys_to_skip=None): if keys_to_skip is None: keys_to_skip = [] my_keys_to_skip = [] my_keys_to_skip = [ 'object_methods', 'object_attributes', ] return object_methods(self, mode=mode, keys_to_skip=keys_to_skip+my_keys_to_skip)
[docs] def set_grid_point_weight(self, reference_point, MO, S, mass, cg, IS, IQ, Q): self.reference_point = reference_point self.MO = MO self.S = S self.mass = mass self.cg = cg self.IS = IS self.IQ = IQ self.Q = Q
[docs] def get_stats(self, short=True): if self.reference_point is None: return '' if short: msg = ('GridPointWeight: ref_point=%s mass=%g; ' '[reference_point, M0, S, mass, cg, IS, IQ, Q]\n' % ( self.reference_point, self.mass.max())) else: msg = ( 'GridPointWeight:' ' reference_point=%s\n' ' mass=[%10g %10g %10g]\n' ' cg =[%10g %10g %10g]\n' ' [%10g %10g %10g]\n' ' [%10g %10g %10g]\n\n' ' IS =[%10g %10g %10g]\n' ' [%10g %10g %10g]\n' ' [%10g %10g %10g]\n\n' ' IQ =[%10g %10s %10s]\n' ' [%10s %10g %10s]\n' ' [%10s %10s %10g]\n\n' ' Q = [%10g %10g %10g]\n' ' [%10g %10g %10g]\n' ' [%10g %10g %10g]\n' % ( self.reference_point, self.mass[0], self.mass[1], self.mass[2], self.cg[0, 0], self.cg[0, 1], self.cg[0, 2], self.cg[1, 0], self.cg[1, 1], self.cg[1, 2], self.cg[2, 0], self.cg[2, 1], self.cg[2, 2], self.IS[0, 0], self.IS[0, 1], self.IS[0, 2], self.IS[1, 0], self.IS[1, 1], self.IS[1, 2], self.IS[2, 0], self.IS[2, 1], self.IS[2, 2], self.IQ[0], '', '', '', self.IQ[1], '', '', '', self.IQ[2], self.Q[0, 0], self.Q[0, 1], self.Q[0, 2], self.Q[1, 0], self.Q[1, 1], self.Q[1, 2], self.Q[2, 0], self.Q[2, 1], self.Q[2, 2], ) ) return msg
def __repr__(self): f = StringIO() page_stamp = 'PAGE %i' page_num = 1 self.write_f06(f, page_stamp, page_num) msg = f.getvalue() return msg
[docs] def read_grid_point_weight(self, lines): """ 0- REFERENCE POINT = 0 1- M O 2- * 2.338885E+05 2.400601E-13 -7.020470E-15 -1.909968E-11 2.851745E+06 -5.229834E+07 * 3- * 2.400601E-13 2.338885E+05 -2.520547E-13 -2.851745E+06 2.151812E-10 2.098475E+08 * 4- * -7.020470E-15 -2.520547E-13 2.338885E+05 5.229834E+07 -2.098475E+08 -1.960403E-10 * 5- * -1.909968E-11 -2.851745E+06 5.229834E+07 2.574524E+10 -5.566238E+10 -4.054256E+09 * 6- * 2.851745E+06 2.151812E-10 -2.098475E+08 -5.566238E+10 2.097574E+11 -2.060162E+09 * 7- * -5.229834E+07 2.098475E+08 -1.960403E-10 -4.054256E+09 -2.060162E+09 2.336812E+11 * 8- S 9- * 1.000000E+00 0.000000E+00 0.000000E+00 * 10- * 0.000000E+00 1.000000E+00 0.000000E+00 * 11- * 0.000000E+00 0.000000E+00 1.000000E+00 * 12- DIRECTION 13- MASS AXIS SYSTEM (S) MASS X-C.G. Y-C.G. Z-C.G. 14- X 2.338885E+05 -8.166148E-17 2.236038E+02 1.219276E+01 15- Y 2.338885E+05 8.972118E+02 9.200164E-16 1.219276E+01 16- Z 2.338885E+05 8.972118E+02 2.236038E+02 -8.381786E-16 17- I(S) 18- * 1.401636E+10 8.739690E+09 1.495636E+09 * * 8.739690E+09 2.144496E+10 1.422501E+09 * * 1.495636E+09 1.422501E+09 3.370946E+10 * I(Q) * 3.389001E+10 * * 8.073297E+09 * * 2.720748E+10 * Q * -3.599259E-02 -8.305739E-01 5.557441E-01 * * -8.850329E-02 -5.512702E-01 -8.296194E-01 * * 9.954254E-01 -7.904533E-02 -5.366689E-02 * .. note:: pyNastran's BDF mass_properties method uses the following (not totally correct as there technically isn't one xcg): DIRECTION MASS AXIS SYSTEM (S) MASS X-C.G. Y-C.G. Z-C.G. X mass 0.000000E+00 ycg zcg Y mass xcg 0.000000E+00 zcg Z nass xcg ycg 0.000000E+00 The inertias are close to I(S), but not exact as the method doesn't use the mass matrix, but is close for sufficiently complex models. The terms are: * Ixx Ixy Ixz * * Iyx Iyy Iyz * * Izz Izy Izz * or inertia = [Ixx, Iyy, Izz, Ixy, Ixz, Iyz] """ self.reference_point = int(lines[0].split('=')[1]) assert lines[1] == 'M O', lines[1] self.MO = zeros((6, 6), dtype='float64') self.S = zeros((3, 3), dtype='float64') self.mass = zeros(3, dtype='float64') self.cg = zeros((6, 6), dtype='float64') self.IS = zeros((3, 3), dtype='float64') self.IQ = zeros(3, dtype='float64') self.Q = zeros((3, 3), dtype='float64') #======================================== # MO n = 2 for i in range(6): line = lines[n + i][1:-1] # get rid of the * characters sline = line.split() for j in range(6): self.MO[i, j] = sline[j] #print("MO =", self.MO) n += i + 1 #======================================== # S assert lines[n] == 'S', lines[n] n += 1 for i in range(3): line = lines[n + i][1:-1] # get rid of the * characters sline = line.split() for j in range(3): self.S[i, j] = sline[j] #print("S =", self.S) n += i + 1 #======================================== assert lines[n] == 'DIRECTION', lines[n] n += 2 for i in range(3): line = lines[n + i][1:] # get rid of the * characters sline = line.split() self.mass[i] = sline[0] for j in range(3): self.cg[i, j] = sline[j + 1] #print("mass =", self.mass) #print("mass =", self.cg) n += 3 #======================================== assert lines[n] == 'I(S)', lines[n] n += 1 for i in range(3): line = lines[n + i][1:-1] # get rid of the * characters sline = line.split() for j in range(3): self.IS[i, j] = sline[j] #print("IS =", self.IS) n += i + 1 #======================================== assert lines[n] == 'I(Q)', lines[n] n += 1 for i in range(3): sline = lines[n + i][1:-1].strip().split() # get rid of the * characters self.IQ[i] = sline[0] #print("IQ =", self.IQ) n += i + 1 #======================================== # S assert lines[n] == 'Q', lines[n] n += 1 for i in range(3): line = lines[n + i][1:-1] # get rid of the * characters sline = line.split() for j in range(3): self.Q[i, j] = sline[j] #print("Q =", self.Q) n += i
[docs] def write_f06(self, f06_file, page_stamp, page_num): """ writes the f06 Parameters ---------- f06_file : file / StringIO a file-like object page_stamp : str the page formatter (e.g., 'PAGE %i') page_num : int the active page number Returns ------- page_num : int the new page number """ if self.reference_point is None: return page_num msg = [' O U T P U T F R O M G R I D P O I N T W E I G H T G E N E R A T O R'] msg.append('0 REFERENCE POINT = %i' % self.reference_point) # MO msg.append(' M O') for i in range(6): msg.append(' * %13.6E %13.6E %13.6E %13.6E %13.6E %13.6E *' % tuple(self.MO[i, :])) msg.append(' S') for i in range(3): msg.append(' * %13.6E %13.6E %13.6E *' % tuple(self.S[i, :])) msg.append(' DIRECTION') msg.append(' MASS AXIS SYSTEM (S) MASS X-C.G. Y-C.G. Z-C.G.') msg.append(' X %12.6E %13.6E %13.6E %13.6E' % (self.mass[0], self.cg[0, 0], self.cg[0, 1], self.cg[0, 2])) msg.append(' Y %12.6E %13.6E %13.6E %13.6E' % (self.mass[1], self.cg[1, 0], self.cg[1, 1], self.cg[1, 2])) msg.append(' Z %12.6E %13.6E %13.6E %13.6E' % (self.mass[2], self.cg[2, 0], self.cg[2, 1], self.cg[2, 2])) msg.append(' I(S)') for i in range(3): msg.append(' * %13.6E %13.6E %13.6E *' % tuple(self.IS[i, :])) msg.append(' I(Q)') msg.append(' * %13.6E %13s %13s *' % (self.IQ[0], '', '')) msg.append(' * %13s %13.6E %13s *' % ('', self.IQ[1], '')) msg.append(' * %13s %13s %13.6E *' % ('', '', self.IQ[2])) msg.append(' Q') for i in range(3): msg.append(' * %13.6E %13.6E %13.6E *' % tuple(self.Q[i, :])) msg.append('\n' + page_stamp % page_num + '\n') f06_file.write('\n'.join(msg)) #print('\n'.join(msg)) return page_num + 1