def safe_cross_reference(self, model: BDF, xref_errors): """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by CGAP eid=%s' % self.eid self.ga_ref = model.Node(self.ga, msg=msg) self.gb_ref = model.Node(self.gb, msg=msg) if self.g0: self.g0_ref = model.Node(self.g0, msg=msg) self.x = self.g0_ref.get_position() self.pid_ref = model.safe_property(self.pid, self.eid, xref_errors, msg=msg) if self.cid is not None: self.cid_ref = model.safe_coord(self.cid, self.eid, xref_errors, msg=msg)
def getNodes(self, grids, grids_expected, coords, debug=False): model = BDF(debug=False) for (nid, grid) in enumerate(grids): (cid, x, y, z) = grid model.add_card(['GRID', nid + 1, cid, x, y, z], 'GRID') gridObj = model.Node(nid + 1) if debug: print(gridObj) for (cid, coord) in enumerate(coords): #print coord (rid, x, y, z) = coord model.add_card(['CORD2R', cid + 1, rid] + x + y + z, 'CORD2R') coordObj = model.Coord(cid + 1) if debug: print(coordObj) model.cross_reference() for (i, grid) in enumerate(grids_expected): (cid, x, y, z) = grid node = model.Node(i + 1) pos = node.Position() n = array([x, y, z]) msg = 'expected=%s actual=%s\n' % (n, pos) msg += 'n=%s grid=\n%s' % (i + 1, node) coord = node.cp msg += 'n=%s coord=\n%s' % (node.nid, coord) while coord.rid: msg += 'n=%s rcoord=\n%s' % (node.nid, coord.rid) coord = coord.rid assert allclose(n, pos), msg
def test_cord2_rcs_01(self): """ all points are located at <30,40,50> """ model = BDF(debug=False) cards = [ [#'$ Femap with NX Nastran Coordinate System 10 : rectangular defined in a rectangular', 'CORD2R* 10 0 10. 5.', '* 3. 10.3420201433 4.53015368961 3.81379768136* ', '* 10.7198463104 5.68767171433 3.09449287122',], [#'$ Femap with NX Nastran Coordinate System 11 : cylindrical defined in rectangular', 'CORD2C* 11 0 7. 3.', '* 9. 7.64278760969 2.73799736977 9.71984631039* ', '* 7.75440650673 3.37968226211 8.46454486422',], [#'$ Femap with NX Nastran Coordinate System 12 : spherical defined in rectangular', 'CORD2S* 12 0 12. 8.', '* 5. 12.6427876097 7.86697777844 5.75440650673* ', '* 12.6634139482 8.58906867688 4.53861076379',], ['GRID* 10 10 42.9066011565 34.2422137135', '* 28.6442730262 0',], ['GRID* 11 11 48.8014631871 78.8394787869', '* 34.6037164304 0',], ['GRID* 12 12 58.0775343829 44.7276544324', '* 75.7955331161 0',], ] for lines in cards: card = model.process_card(lines) model.add_card(card, card[0]) model.cross_reference() for nid in model.nodes: a = array([30.,40.,50.]) b = model.Node(nid).Position() self.assertTrue(allclose(array([30.,40.,50.]), model.Node(nid).Position()), str(a-b))
def test_cord2_rcs_03(self): """ all points are located at <30,40,50> """ model = BDF(debug=False) cards = [ [ 'CORD2S* 2 0 0. 0.', '* 0. 0. 0. 1.* ', '* 1. 0. 1.', ], [ #'$ Femap with NX Nastran Coordinate System 30 : rectangular in spherical', 'CORD2R* 30 2 14. 30.', '* 70. 13.431863852 32.1458443949 75.2107442927* ', '* 14.4583462334 33.4569982885 68.2297989286', ], [ #'$ Femap with NX Nastran Coordinate System 31 : cylindrical in spherical', 'CORD2C* 31 2 3. 42.', '* -173. 2.86526881213 45.5425615252 159.180363517* ', '* 3.65222385965 29.2536614627 -178.631312271', ], [ #'$ Femap with NX Nastran Coordinate System 32 : spherical in spherical', 'CORD2S* 32 2 22. 14.', '* 85. 22.1243073983 11.9537753718 77.9978191005* ', '* 21.0997242967 13.1806120497 88.4824763008', ], [ 'GRID* 30 30 40.7437952957 -23.6254877994', '* -33.09784854 0', ], [ 'GRID* 31 31 62.9378078196 15.9774797923', '* 31.0484428362 0', ], [ 'GRID* 32 32 53.8270847449 95.8215692632', '* 159.097767463 0', ], ] for lines in cards: card = model._process_card(lines) model.add_card(card, card[0]) model.cross_reference() for nid in model.nodes: a = array([30., 40., 50.]) b = model.Node(nid).Position() self.assertTrue( allclose(array([30., 40., 50.]), model.Node(nid).Position()), str(a - b))
def test_cord2_rcs_02(self): """ all points are located at <30,40,50> """ model = BDF(debug=False) cards = [ [ 'CORD2C* 1 0 0. 0.', '* 0. 0. 0. 1.* ', '* 1. 0. 1.', ], [ #'$ Femap with NX Nastran Coordinate System 20 : rectangular defined in cylindrical', 'CORD2R* 20 1 7. 20.', '* -6. 7.07106781187 28.1301023542 -6.* ', '* 7.70710678119 20. -5.29289321881', ], [ #'$ Femap with NX Nastran Coordinate System 21 : cylindrical defined in cylindrical', 'CORD2C* 21 1 15. -30.', '* 12. 14.6565766735 -30.3177805524 12.9355733712* ', '* 14.6234241583 -26.4257323272 11.9304419665', ], [ #'$ Femap with NX Nastran Coordinate System 22 : spherical defined in cylindrical', 'CORD2S* 22 1 5. -75.', '* 20. 5.66032384035 -82.9319986389 19.8502545865* ', '* 4.88876051026 -73.8006653677 19.0116094889', ], [ 'GRID* 20 20 64.2559135157 -14.9400459772', '* 27.3271005317 0', ], [ 'GRID* 21 21 52.8328862418 -28.8729017195', '* 34.615939507 0', ], [ 'GRID* 22 22 61.1042111232 158.773483595', '* -167.4951724 0', ], ] for lines in cards: card = model._process_card(lines) model.add_card(card, card[0]) model.cross_reference() for nid in model.nodes: a = array([30., 40., 50.]) b = model.Node(nid).Position() self.assertTrue( allclose(array([30., 40., 50.]), model.Node(nid).Position()), str(a - b))
def test_cord2r_02(self): grid = ['GRID 20143 7 -9.31-4 .11841 .028296'] coord = [ 'CORD2R 7 1.135 .089237 -.0676 .135 .089237 -.0676', ' 1.135 .089237 .9324' ] model = BDF(debug=False) card = model._process_card(grid) model.add_card(card, card[0]) card = model._process_card(coord) model.add_card(card, card[0]) model.cross_reference() coord = model.Coord(7) #print(coord.origin) #print(coord.i, coord.j, coord.k) node = model.Node(20143) xyzp1 = Position(node.xyz, node.cp, model) xyzp2 = Position(node.xyz, node.cp_ref, model) xyz = node.get_position() assert np.array_equal(xyz, xyzp1) assert np.array_equal(xyz, xyzp2) xyz_same = PositionWRT([1., 2., 3.], 100, 100, model) assert np.array_equal(xyz_same, [1., 2., 3.]) xyz_wrt_p1 = PositionWRT(node.xyz, node.cp, 0, model) xyz_wrt_p2 = PositionWRT(node.xyz, node.cp_ref, 0, model) xyz_wrt = node.get_position_wrt(model, 0) assert np.array_equal(xyz, xyz_wrt_p1) assert np.array_equal(xyz, xyz_wrt_p2) assert np.array_equal(xyz, xyz_wrt) # by running it through Patran... #GRID 20143 1.1067 .207647 -.068531 expected = array([1.106704, .207647, -0.068531]) diff = xyz - expected msg = '\nexpected=%s \nactual =%s \ndiff =%s' % (expected, xyz, diff) assert allclose(diff, 0.), msg coord = model.Coord(7) coord.beta_n(1) coord.beta_n(2) coord.beta_n(3) coord.beta_n(6) with self.assertRaises(AttributeError): self.assertTrue(array_equal(coord.T(), coord.beta_n(2))) #with self.assertRaises(NotImplementedError): #self.assertTrue(array_equal(coord.T(), coord.beta_n(2))) model2 = BDF(debug=False) cid = 7 origin = [1.135, .089237, -.0676] zaxis = [.135, .089237, -.0676] xzplane = [1.135, .089237, .9324] coord2 = model2.add_cord2r(cid, origin, zaxis, xzplane, rid=0, comment='cord2r') coord2.comment = '' assert coord == coord2, 'coord:\n%r\ncoord2:\n%r' % (str(coord), str(coord2))
def _get_nodes(self, grids, grids_expected, coords): model = BDF(debug=False) for grid in grids: (nid, cid, x, y, z) = grid model.add_card(['GRID', nid, cid, x, y, z], 'GRID') for coord in coords: (cid, rid, x, y, z) = coord model.add_card(['CORD2R', cid, rid] + x + y + z, 'CORD2R') coord_obj = model.Coord(cid) model.cross_reference() for i, grid in enumerate(grids_expected): nid, cid, x, y, z = grid node = model.Node(nid) pos = node.get_position() n = array([x, y, z]) msg = 'i=%s expected=%s actual=%s\n' % (i, n, pos) msg += 'n=%s grid=\n%s' % (nid, node) coord = node.cp msg += 'n=%s coord=\n%s' % (node.nid, coord) while coord.rid: msg += 'n=%s rcoord=\n%s' % (node.nid, coord.rid) coord = coord.rid assert allclose(n, pos), msg
def test_cord2r_1(self): grid = ['GRID 20143 7 -9.31-4 .11841 .028296'] coord = ['CORD2R 7 1.135 .089237 -.0676 .135 .089237 -.0676', ' 1.135 .089237 .9324'] model = BDF(debug=False) card = model.process_card(grid) model.add_card(card, card[0]) card = model.process_card(coord) model.add_card(card, card[0]) model.cross_reference() g = model.Node(20143) #print(g.Position(debug=False)) # by running it through Patran... #GRID 20143 1.1067 .207647 -.068531 diff = g.Position() - array([1.106704, .207647, -0.068531]) msg = 'diff=%s' % diff assert allclose(diff, 0.), msg coord = model.Coord(7) coord.T() self.assertTrue(array_equal(coord.T(), coord.beta_n(2)))
def test_cord2r_02(self): grid = ['GRID 20143 7 -9.31-4 .11841 .028296'] coord = ['CORD2R 7 1.135 .089237 -.0676 .135 .089237 -.0676', ' 1.135 .089237 .9324'] model = BDF(debug=False) card = model.process_card(grid) model.add_card(card, card[0]) card = model.process_card(coord) model.add_card(card, card[0]) model.cross_reference() coord = model.Coord(7) #print(coord.origin) #print(coord.i, coord.j, coord.k) g = model.Node(20143) #print(g.Position(debug=False)) xyz = g.Position() # by running it through Patran... #GRID 20143 1.1067 .207647 -.068531 expected = array([1.106704, .207647, -0.068531]) diff = xyz - expected msg = '\nexpected=%s \nactual =%s \ndiff =%s' % (expected, xyz, diff) assert allclose(diff, 0.), msg coord = model.Coord(7) coord.T() self.assertTrue(array_equal(coord.T(), coord.beta_n(2)))
def cross_reference(self, model: BDF) -> None: """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by CBUSH1D eid=%s' % self.eid self.ga_ref = model.Node(self.ga, msg=msg) if self.gb: self.gb_ref = model.Node(self.gb, msg=msg) self.pid_ref = model.Property(self.pid, msg=msg) if self.cid is not None: self.cid_ref = model.Coord(self.cid)
def cross_reference(self, model: BDF) -> None: """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by CFAST eid=%s' % self.eid self.pid_ref = model.Property(self.Pid(), msg=msg) if self.gs: self.gs_ref = model.Node(self.Gs(), msg=msg) if self.ga: self.ga_ref = model.Node(self.Ga(), msg=msg) if self.gb: self.gb_ref = model.Node(self.Gb(), msg=msg)
def get_nodes(grids, grids_expected, coords): """ Create each input grid/coord Loop over the expected grids, use the provided coordinate system and verify that the xyz location is correct. Parameters ---------- grids : List[grid] the grids grid : List[nid, cp, x, y, z] the GRID fields coords : List[coord] coord : List[int cid, rid, origin, zaxis, xaxis] the coordinate system to add to the model grids_expected : List[grid] the expected grids grid : List[nid, cp, x, y, z] the GRID fields """ model = BDF(debug=False) for grid in grids: (nid, cid, x, y, z) = grid model.add_card(['GRID', nid, cid, x, y, z], 'GRID') for coord in coords: (cid, rid, x, y, z) = coord model.add_card(['CORD2R', cid, rid] + x + y + z, 'CORD2R') #coord_obj = model.Coord(cid) model.cross_reference() save_load_deck(model, run_remove_unused=False, run_convert=False, run_save_load_hdf5=True) for (i, grid) in enumerate(grids_expected): (nid, cid, x, y, z) = grid node = model.Node(nid) xyz_actual = node.get_position() xyz = array([x, y, z]) msg = 'i=%s expected=%s actual=%s\n' % (i, xyz, xyz_actual) msg += 'n=%s grid=\n%s' % (nid, node) coord_ref = node.cp_ref msg += 'n=%s coord=\n%s' % (node.nid, coord_ref) if not allclose(xyz, xyz_actual): # TODO: this used to work, but the changing xref broke it somehow # this block probably needs to be slightly updated while coord_ref.rid: msg += 'xyz=%s rcoord=\n%s' % (node.nid, coord_ref.rid) coord_ref = coord_ref.rid assert allclose(xyz, xyz_actual), msg
def cross_reference(self, model: BDF) -> None: """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by CGAP eid=%s' % self.eid self.ga_ref = model.Node(self.ga, msg=msg) self.gb_ref = model.Node(self.gb, msg=msg) if self.g0: self.g0_ref = model.Node(self.g0, msg=msg) self.x = self.g0_ref.get_position() self.pid_ref = model.Property(self.pid, msg=msg) if self.cid: self.cid_ref = model.Coord(self.cid, msg=msg)
def safe_cross_reference(self, model: BDF, xref_errors): """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by CONM1 eid=%s' % self.eid self.nid_ref = model.Node(self.nid, msg=msg) self.cid_ref = model.safe_coord(self.cid, self.eid, xref_errors, msg='')
def cross_reference(self, model: BDF) -> None: """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by CONM1 eid=%s' % self.eid self.nid_ref = model.Node(self.nid, msg=msg) self.cid_ref = model.Coord(self.cid, msg=msg)
def get_node_positions_no_xref(self, model: BDF, nodes: List[Any]=None) -> np.ndarray: """returns the positions of multiple node objects""" if not nodes: nodes = self.nodes nnodes = len(nodes) positions = np.empty((nnodes, 3), dtype='float64') positions.fill(np.nan) for i, nid in enumerate(nodes): if nid is not None: node = model.Node(nid) positions[i, :] = node.get_position_no_xref(model) return positions
def cross_reference(self, model: BDF) -> None: """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by PLOADX1 lid=%s' % self.sid self.eid_ref = model.Element(self.eid, msg=msg) self.ga_ref = model.Node(self.ga, msg=msg) self.gb_ref = model.Node(self.gb, msg=msg)
def cross_reference(self, model: BDF) -> None: """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by PLOTEL eid=%s' % self.eid self.nodes_ref = [ model.Node(self.nodes[0], msg=msg), model.Node(self.nodes[1], msg=msg), ]
def safe_cross_reference(self, model: BDF, xref_errors): msg = ', which is required by CBEAM eid=%s' % (self.eid) self.nodes_ref = [ model.Node(self.ga, msg=msg), model.Node(self.gb, msg=msg), ] self.nodes_ref = [self.ga_ref, self.gb_ref] self.pid_ref = model.safe_property(self.pid, self.eid, xref_errors, msg=msg) if self.g0: try: self.g0_ref = model.nodes[self.g0] ga_ref = self.nodes_ref[0] self.g0_vector = self.g0_ref.get_position() - ga_ref.get_position() except KeyError: model.log.warning('Node=%s%s' % (self.g0, msg)) else: self.g0_vector = self.x
def cross_reference(self, model: BDF) -> None: """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by CBUSH eid=%s' % self.eid self.nodes_ref = model.EmptyNodes(self.node_ids, msg=msg) self.pid_ref = model.Property(self.pid, msg=msg) if self.g0 is not None: self.g0_ref = model.Node(self.g0, msg=msg) if self.cid is not None: self.cid_ref = model.Coord(self.cid, msg=msg) if self.ocid is not None and self.ocid != -1: self.ocid_ref = model.Coord(self.ocid, msg=msg)
def test_cord2r_1(self): grid = ['GRID 20143 7 -9.31-4 .11841 .028296'] coord = [ 'CORD2R 7 1.135 .089237 -.0676 .135 .089237 -.0676', ' 1.135 .089237 .9324' ] model = BDF() card = model.process_card(grid) model.add_card(card, card[0]) card = model.process_card(coord) model.add_card(card, card[0]) model.cross_reference() g = model.Node(20143) #print(g.Position(debug=False)) diff = g.Position() - array([1.106704, .207647, -0.068531]) assert allclose(diff, 0.)
def test_grid_01(self): model = BDF(debug=False) cards = [ #['CORD1R', 1, 1, 2, 3], # fails on self.k ['GRID', 1, 0, 0., 0., 0.], ['GRID', 2, 0, 1., 0., 0.], ['GRID', 4, 0, 1., 2., 3.], ] for card in cards: model.add_card(card, card[0], comment='comment', is_list=True) #+------+-----+----+----+----+----+----+----+------+ #| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | #+======+=====+====+====+====+====+====+====+======+ #| GRID | NID | CP | X1 | X2 | X3 | CD | PS | SEID | #+------+-----+----+----+----+----+----+----+------+ node = model.Node(4) self.assertEqual(node.get_field(1), 4) self.assertEqual(node.get_field(2), 0) self.assertEqual(node.get_field(3), 1.) self.assertEqual(node.get_field(4), 2.) self.assertEqual(node.get_field(5), 3.) node.update_field(1, 5) node.update_field(2, 6) node.update_field(3, 7.) node.update_field(4, 8.) node.update_field(5, 9.) with self.assertRaises(KeyError): node.update_field(9, 'dummy') self.assertEqual(node.get_field(1), 5) self.assertEqual(node.get_field(2), 6) self.assertEqual(node.get_field(3), 7.) self.assertEqual(node.get_field(4), 8.) self.assertEqual(node.get_field(5), 9.) with self.assertRaises(KeyError): node.get_field(9)
def cross_reference(self, model: BDF) -> None: """ Cross links the card so referenced cards can be extracted directly Parameters ---------- model : BDF() the BDF object """ msg = ', which is required by CBEAM eid=%s' % (self.eid) self.ga_ref = model.Node(self.ga, msg=msg) self.gb_ref = model.Node(self.gb, msg=msg) self.nodes_ref = [self.ga_ref, self.gb_ref] self.pid_ref = model.Property(self.pid, msg=msg) if self.g0: self.g0_ref = model.nodes[self.g0] self.g0_vector = self.g0_ref.get_position( ) - self.ga_ref.get_position() else: self.g0_vector = self.x if model.is_nx: assert self.offt == 'GGG', 'NX only support offt=GGG; offt=%r' % self.offt
model_output = BDF() pid_pbush = 99000000 prop_pbush_k =[1.0e+8,1.0e+8,1.0e+8,1.0e+12,1.0e+12,1.0e+12] model_output.add_pbush(pid_pbush,prop_pbush_k,'','') list_len = int(len(list_input_node) / 2 ) count = -1 for ta in range(list_len): count = count + 1 id_grid_new = int(list_input_node[count]) count = count + 1 id_grid_input = int(list_input_node[count]) grid_input = model_input.Node(id_grid_input) grid_input_pos = grid_input.get_position() model_output.add_grid(id_grid_new,grid_input_pos) list_node_pair = [id_grid_new,id_grid_input] model_output.add_cbush(id_grid_new,pid_pbush,list_node_pair,'','',0) model_output.write_bdf('cbush.bdf')
def test_cord2_rcs_03(self): """ all points are located at <30,40,50> """ model = BDF(debug=False) cards = [ [ 'CORD2S* 2 0 0. 0.', '* 0. 0. 0. 1.* ', '* 1. 0. 1.', ], [ #'$ Coordinate System 30 : rectangular in spherical', 'CORD2R* 30 2 14. 30.', '* 70. 13.431863852 32.1458443949 75.2107442927* ', '* 14.4583462334 33.4569982885 68.2297989286', ], [ #'$ Coordinate System 31 : cylindrical in spherical', 'CORD2C* 31 2 3. 42.', '* -173. 2.86526881213 45.5425615252 159.180363517* ', '* 3.65222385965 29.2536614627 -178.631312271', ], [ #'$ Coordinate System 32 : spherical in spherical', 'CORD2S* 32 2 22. 14.', '* 85. 22.1243073983 11.9537753718 77.9978191005* ', '* 21.0997242967 13.1806120497 88.4824763008', ], [ 'GRID* 30 30 40.7437952957 -23.6254877994', '* -33.09784854 0', ], [ 'GRID* 31 31 62.9378078196 15.9774797923', '* 31.0484428362 0', ], [ 'GRID* 32 32 53.8270847449 95.8215692632', '* 159.097767463 0', ], ] for lines in cards: card = model.process_card(lines) model.add_card(card, card[0]) xyz_cid0b = model.get_xyz_in_coord_no_xref(cid=0, fdtype='float64') xyz_cid0c = model.get_xyz_in_coord_no_xref(cid=32, fdtype='float64') model.cross_reference() xyz_cid0_actual = array([ [30., 40., 50.], [30., 40., 50.], [30., 40., 50.], ], dtype='float64') for nid in model.nodes: a = array([30., 40., 50.]) b = model.Node(nid).get_position() self.assertTrue( allclose(array([30., 40., 50.]), model.Node(nid).get_position()), str(a - b)) xyz_cid0 = model.get_xyz_in_coord(cid=0, fdtype='float64') array_equal(xyz_cid0_actual, xyz_cid0) icd_transform, icp_transform, xyz_cp, nid_cp_cd = model.get_displacement_index_xyz_cp_cd( ) xyz_cid0_xform = model.transform_xyzcp_to_xyz_cid(xyz_cp, icp_transform, cid=0) array_equal(xyz_cid0_actual, xyz_cid0_xform) assert array_equal(nid_cp_cd[:, 0], array([30, 31, 32])) xyz_cid_30 = model.transform_xyzcp_to_xyz_cid(xyz_cp, icp_transform, cid=30) xyz_cid_31 = model.transform_xyzcp_to_xyz_cid(xyz_cp, icp_transform, cid=31) xyz_cid_32 = model.transform_xyzcp_to_xyz_cid(xyz_cp, icp_transform, cid=32)
def test_cord2_rcs_02(self): """ all points are located at <30,40,50> """ model = BDF(debug=False) cards = [ [ 'CORD2C* 1 0 0. 0.', '* 0. 0. 0. 1.* ', '* 1. 0. 1.',], [ #'$ Coordinate System 20 : rectangular defined in cylindrical', 'CORD2R* 20 1 7. 20.', '* -6. 7.07106781187 28.1301023542 -6.* ', '* 7.70710678119 20. -5.29289321881',], [ #'$ Coordinate System 21 : cylindrical defined in cylindrical', 'CORD2C* 21 1 15. -30.', '* 12. 14.6565766735 -30.3177805524 12.9355733712* ', '* 14.6234241583 -26.4257323272 11.9304419665',], [ #'$ Coordinate System 22 : spherical defined in cylindrical', 'CORD2S* 22 1 5. -75.', '* 20. 5.66032384035 -82.9319986389 19.8502545865* ', '* 4.88876051026 -73.8006653677 19.0116094889',], [ 'GRID* 20 20 64.2559135157 -14.9400459772', '* 27.3271005317 0',], [ 'GRID* 21 21 52.8328862418 -28.8729017195', '* 34.615939507 0',], [ 'GRID* 22 22 61.1042111232 158.773483595', '* -167.4951724 0',], ] for lines in cards: card = model._process_card(lines) model.add_card(card, card[0]) unused_xyz_cid0b = model.get_xyz_in_coord_no_xref(cid=0, fdtype='float64') unused_xyz_cid0c = model.get_xyz_in_coord_no_xref(cid=22, fdtype='float64') model.cross_reference() xyz_cid0_actual = array([ [30., 40., 50.], [30., 40., 50.], [30., 40., 50.], ], dtype='float64') for nid in model.nodes: a = array([30., 40., 50.]) b = model.Node(nid).get_position() self.assertTrue(allclose(array([30., 40., 50.]), model.Node(nid).get_position()), str(a - b)) xyz_cid0 = model.get_xyz_in_coord(cid=0, fdtype='float64') array_equal(xyz_cid0_actual, xyz_cid0) unused_icd_transform, icp_transform, xyz_cp, nid_cp_cd = model.get_displacement_index_xyz_cp_cd() xyz_cid0_xform = model.transform_xyzcp_to_xyz_cid( xyz_cp, nid_cp_cd[:, 0], icp_transform, cid=0) array_equal(xyz_cid0_actual, xyz_cid0_xform) assert array_equal(nid_cp_cd[:, 0], array([20, 21, 22])) unused_xyz_cid_20 = model.transform_xyzcp_to_xyz_cid( xyz_cp, nid_cp_cd[:, 0], icp_transform, cid=20) unused_xyz_cid_21 = model.transform_xyzcp_to_xyz_cid( xyz_cp, nid_cp_cd[:, 0], icp_transform, cid=21) unused_xyz_cid_22 = model.transform_xyzcp_to_xyz_cid( xyz_cp, nid_cp_cd[:, 0], icp_transform, cid=22)
def test_cord2_rcs_01(self): """ all points are located at <30,40,50> """ model = BDF(debug=False) cards = [ [ #'$ Coordinate System 10 : rectangular defined in a rectangular', 'CORD2R* 10 0 10. 5.', '* 3. 10.3420201433 4.53015368961 3.81379768136* ', '* 10.7198463104 5.68767171433 3.09449287122',], [ #'$ Coordinate System 11 : cylindrical defined in rectangular', 'CORD2C* 11 0 7. 3.', '* 9. 7.64278760969 2.73799736977 9.71984631039* ', '* 7.75440650673 3.37968226211 8.46454486422',], [ #'$ Coordinate System 12 : spherical defined in rectangular', 'CORD2S* 12 0 12. 8.', '* 5. 12.6427876097 7.86697777844 5.75440650673* ', '* 12.6634139482 8.58906867688 4.53861076379',], [ 'GRID* 10 10 42.9066011565 34.2422137135', '* 28.6442730262 0',], [ 'GRID* 11 11 48.8014631871 78.8394787869', '* 34.6037164304 0',], [ 'GRID* 12 12 58.0775343829 44.7276544324', '* 75.7955331161 0',], ] for lines in cards: card = model._process_card(lines) model.add_card(card, card[0]) unused_xyz_cid0b = model.get_xyz_in_coord_no_xref(cid=0, fdtype='float64') unused_xyz_cid0c = model.get_xyz_in_coord_no_xref(cid=12, fdtype='float64') model.cross_reference() xyz_cid0_actual = array([ [30., 40., 50.], [30., 40., 50.], [30., 40., 50.], ], dtype='float64') for nid in model.nodes: node = model.Node(nid) a = array([30., 40., 50.]) b = node.get_position() self.assertTrue(allclose(array([30., 40., 50.]), node.get_position()), str(a - b)) xyz_cid0 = model.get_xyz_in_coord(cid=0, fdtype='float64') array_equal(xyz_cid0_actual, xyz_cid0) unused_icd_transform, icp_transform, xyz_cp, nid_cp_cd = model.get_displacement_index_xyz_cp_cd() xyz_cid0_xform = model.transform_xyzcp_to_xyz_cid( xyz_cp, nid_cp_cd[:, 0], icp_transform, cid=0) array_equal(xyz_cid0_actual, xyz_cid0_xform) assert array_equal(nid_cp_cd[:, 0], array([10, 11, 12])) unused_xyz_cid_10 = model.transform_xyzcp_to_xyz_cid( xyz_cp, nid_cp_cd[:, 0], icp_transform, cid=10) unused_xyz_cid_11 = model.transform_xyzcp_to_xyz_cid( xyz_cp, nid_cp_cd[:, 0], icp_transform, cid=11) unused_xyz_cid_12 = model.transform_xyzcp_to_xyz_cid( xyz_cp, nid_cp_cd[:, 0], icp_transform, cid=12)
def sum_forces_moments(model: BDF, p0: np.ndarray, loadcase_id: int, cid: int=0, include_grav: bool=False, xyz_cid0: Optional[Dict[int, NDArray3float]]=None, ) -> Tuple[NDArray3float, NDArray3float]: """ Sums applied forces & moments about a reference point p0 for all load cases. Considers: - FORCE, FORCE1, FORCE2 - MOMENT, MOMENT1, MOMENT2 - PLOAD, PLOAD2, PLOAD4 - LOAD Parameters ---------- model : BDF() a BDF object p0 : NUMPY.NDARRAY shape=(3,) or integer (node ID) the reference point loadcase_id : int the LOAD=ID to analyze cid : int; default=0 the coordinate system for the summation include_grav : bool; default=False includes gravity in the summation (not supported) xyz_cid0 : None / Dict[int] = (3, ) ndarray the nodes in the global coordinate system Returns ------- forces : NUMPY.NDARRAY shape=(3,) the forces moments : NUMPY.NDARRAY shape=(3,) the moments .. warning:: not full validated .. todo:: It's super slow for cid != 0. We can speed this up a lot if we calculate the normal, area, centroid based on precomputed node locations. Pressure acts in the normal direction per model/real/loads.bdf and loads.f06 """ if not isinstance(loadcase_id, integer_types): raise RuntimeError('loadcase_id must be an integer; loadcase_id=%r' % loadcase_id) p = _get_load_summation_point(model, p0, cid=0) loads, scale_factors, unused_is_grav = model.get_reduced_loads( loadcase_id, skip_scale_factor0=True) F = array([0., 0., 0.]) M = array([0., 0., 0.]) xyz = get_xyz_cid0_dict(model, xyz_cid0=xyz_cid0) unsupported_types = set() for load, scale in zip(loads, scale_factors): #if load.type not in ['FORCE1']: #continue if load.type == 'FORCE': if load.Cid() != 0: cp_ref = load.cid_ref #from pyNastran.bdf.bdf import CORD2R #cp_ref = CORD2R() f = load.mag * cp_ref.transform_vector_to_global(load.xyz) * scale else: f = load.mag * load.xyz * scale node = model.Node(load.node_id) r = xyz[node.nid] - p m = cross(r, f) F += f M += m elif load.type == 'FORCE1': f = load.mag * load.xyz * scale node = model.Node(load.node_id) r = xyz[node.nid] - p m = cross(r, f) F += f M += m elif load.type == 'FORCE2': f = load.mag * load.xyz * scale node = model.Node(load.node_id) r = xyz[node.nid] - p m = cross(r, f) F += f M += m elif load.type == 'MOMENT': if load.Cid() != 0: cp = load.cid_ref #from pyNastran.bdf.bdf import CORD2R #cp = CORD2R() m = load.mag * cp.transform_vector_to_global(load.xyz) * scale else: m = load.mag * load.xyz * scale M += m elif load.type == 'MOMENT1': m = load.mag * load.xyz * scale M += m elif load.type == 'MOMENT2': m = load.mag * load.xyz * scale M += m elif load.type == 'PLOAD': nodes = load.node_ids nnodes = len(nodes) if nnodes == 3: n1, n2, n3 = xyz[nodes[0]], xyz[nodes[1]], xyz[nodes[2]] axb = cross(n1 - n2, n1 - n3) centroid = (n1 + n2 + n3) / 3. elif nnodes == 4: n1, n2, n3, n4 = xyz[nodes[0]], xyz[nodes[1]], xyz[nodes[2]], xyz[nodes[3]] axb = cross(n1 - n3, n2 - n4) centroid = (n1 + n2 + n3 + n4) / 4. else: msg = 'invalid number of nodes on PLOAD card; nodes=%s' % str(nodes) raise RuntimeError(msg) area, normal = _get_area_normal(axb, nodes, xyz) r = centroid - p f = load.pressure * area * normal * scale m = cross(r, f) F += f M += m elif load.type == 'PLOAD1': _pload1_total(model, loadcase_id, load, scale, xyz, F, M, p) elif load.type == 'PLOAD2': pressure = load.pressure * scale for eid in load.element_ids: elem = model.elements[eid] if elem.type in ['CTRIA3', 'CQUAD4', 'CSHEAR', 'CQUADR', 'CTRIAR']: n = elem.Normal() area = elem.Area() f = pressure * n * area r = elem.Centroid() - p m = cross(r, f) F += f M += m else: model.log.warning('case=%s etype=%r loadtype=%r not supported' % ( loadcase_id, elem.type, load.type)) elif load.type == 'PLOAD4': _pload4_total(loadcase_id, load, scale, xyz, F, M, p) elif load.type == 'GRAV': if include_grav: # this will be super slow gravity = load.GravityVector() * scale for eid, elem in model.elements.items(): centroid = elem.Centroid() mass = elem.Mass() r = centroid - p f = mass * gravity m = cross(r, f) F += f M += m else: # we collect them so we only get one print unsupported_types.add(load.type) for load_type in unsupported_types: model.log.warning('case=%s loadtype=%r not supported' % (loadcase_id, load_type)) #forces, moments = sum_forces_moments(self, p0, loadcase_id, #include_grav=include_grav, xyz_cid0=xyz_cid0) if cid == 0: return F, M cid0 = 0 F2, M2 = transform_load(F, M, cid0, cid, model) return F2, M2
def test_cord2_rcs_03(self): """ all points are located at <30,40,50> """ model = BDF(debug=False) cards = [ [ 'CORD2S* 2 0 0. 0.', '* 0. 0. 0. 1.* ', '* 1. 0. 1.',], [ #'$ Coordinate System 30 : rectangular in spherical', 'CORD2R* 30 2 14. 30.', '* 70. 13.431863852 32.1458443949 75.2107442927* ', '* 14.4583462334 33.4569982885 68.2297989286',], [ #'$ Coordinate System 31 : cylindrical in spherical', 'CORD2C* 31 2 3. 42.', '* -173. 2.86526881213 45.5425615252 159.180363517* ', '* 3.65222385965 29.2536614627 -178.631312271',], [ #'$ Coordinate System 32 : spherical in spherical', 'CORD2S* 32 2 22. 14.', '* 85. 22.1243073983 11.9537753718 77.9978191005* ', '* 21.0997242967 13.1806120497 88.4824763008',], [ 'GRID* 30 30 40.7437952957 -23.6254877994', '* -33.09784854 0',], [ 'GRID* 31 31 62.9378078196 15.9774797923', '* 31.0484428362 0',], [ 'GRID* 32 32 53.8270847449 95.8215692632', '* 159.097767463 0',], ] for lines in cards: card = model._process_card(lines) model.add_card(card, card[0]) unused_xyz_cid0b = model.get_xyz_in_coord_no_xref(cid=0, fdtype='float64') unused_xyz_cid0c = model.get_xyz_in_coord_no_xref(cid=32, fdtype='float64') bdf_file = StringIO() model.write_bdf(bdf_file, close=False) bdf_file.seek(0) #------------------------------------------------- model.cross_reference() model2 = BDFv(debug=False) model2.read_bdf(bdf_file, punch=True, xref=False, save_file_structure=False) bdf_file.seek(0) #------------------------------------------------- xyz_cid0_actual = array([ [30., 40., 50.], [30., 40., 50.], [30., 40., 50.], ], dtype='float64') for nid in model.nodes: node = model.Node(nid) a = array([30., 40., 50.]) b = node.get_position() self.assertTrue(allclose(array([30., 40., 50.]), node.get_position()), str(a - b)) xyz_cid0 = model.get_xyz_in_coord(cid=0, fdtype='float64') assert np.allclose(xyz_cid0_actual, xyz_cid0), '%s' % (xyz_cid0_actual - xyz_cid0) out = model.get_displacement_index_xyz_cp_cd() unused_icd_transform, icp_transform, xyz_cp, nid_cp_cd = out nids = nid_cp_cd[:, 0] xyz_cid0_xform = model.transform_xyzcp_to_xyz_cid( xyz_cp, nids, icp_transform, cid=0) array_equal(xyz_cid0_actual, xyz_cid0_xform) assert array_equal(nids, array([30, 31, 32])) model2.nodes.nids = nid_cp_cd[:, 0] for cid in [30, 31, 32]: unused_xyz_cid_a = model.transform_xyzcp_to_xyz_cid( xyz_cp, nids, icp_transform, cid=cid) unused_xyz_cid_b = model2.transform_xyzcp_to_xyz_cid( xyz_cp, nids, icp_transform, cid=cid, atol=None) #assert np.allclose(xyz_cid_a, xyz_cid_b), '%s' % np.isclose(xyz_cid_a, xyz_cid_b) #print(xyz_cid_a) #print(xyz_cid_b) #print(xyz_cid_a - xyz_cid_b) #print('-------------') #assert array_equal(xyz_cid_a, xyz_cid_b), 'error=%s' % ( #xyz_cid_a - xyz_cid_b) #--------------------------------------------- xyz_cid0 = model.transform_xyzcp_to_xyz_cid( xyz_cp, nids, icp_transform, cid=0, atol=None) array_equal(xyz_cid0_actual, xyz_cid0) model.write_bdf(bdf_file, close=False) model3 = BDF(debug=False) origin = [14., 30., 70.] zaxis = [13.431863852, 32.1458443949, 75.2107442927] xzplane = [14.4583462334, 33.4569982885, 68.2297989286] cord2r = model3.add_cord2r(30, origin, zaxis, xzplane, rid=2, comment='') origin = [3., 42., -173.] zaxis = [2.86526881213, 45.5425615252, 159.180363517] xzplane = [3.65222385965, 29.2536614627, -178.631312271] cord2c = model3.add_cord2c(31, origin, zaxis, xzplane, rid=2, comment='') origin = [22., 14., 85.] zaxis = [22.1243073983, 11.9537753718, 77.9978191005] xzplane = [21.0997242967, 13.1806120497, 88.4824763008] cord2s = model3.add_cord2s(32, origin, zaxis, xzplane, rid=2, comment='') assert cord2r == model.coords[cord2r.cid], 'cord2r:\n%r\ncord2r[cid]:\n%r' % (str(cord2r), str(model.coords[cord2r.cid])) assert cord2c == model.coords[cord2c.cid], 'cord2c:\n%r\ncord2c[cid]:\n%r' % (str(cord2c), str(model.coords[cord2c.cid])) assert cord2s == model.coords[cord2s.cid], 'cord2s:\n%r\ncord2s[cid]:\n%r' % (str(cord2s), str(model.coords[cord2s.cid]))
def sum_forces_moments_elements(model: BDF, p0: int, loadcase_id: int, eids: List[int], nids: List[int], cid: int=0, include_grav: bool=False, xyz_cid0: Optional[Dict[int, NDArray3float]]=None, ) -> Tuple[NDArray3float, NDArray3float]: """ Sum the forces/moments based on a list of nodes and elements. Parameters ---------- model : BDF() a BDF object eids : List[int] the list of elements to include (e.g. the loads due to a PLOAD4) nids : List[int] the list of nodes to include (e.g. the loads due to a FORCE card) p0 : int; (3,) ndarray the point to sum moments about type = int sum moments about the specified grid point type = (3, ) ndarray/list (e.g. [10., 20., 30]): the x, y, z location in the global frame loadcase_id : int the LOAD=ID to analyze include_grav : bool; default=False includes gravity in the summation (not supported) xyz_cid0 : None / Dict[int] = (3, ) ndarray the nodes in the global coordinate system Returns ------- forces : NUMPY.NDARRAY shape=(3,) the forces moments : NUMPY.NDARRAY shape=(3,) the moments Nodal Types : FORCE, FORCE1, FORCE2, MOMENT, MOMENT1, MOMENT2, PLOAD Element Types: PLOAD1, PLOAD2, PLOAD4, GRAV If you have a CQUAD4 (eid=3) with a PLOAD4 (sid=3) and a FORCE card (nid=5) acting on it, you can incldue the PLOAD4, but not the FORCE card by using: For just pressure: .. code-block:: python eids = [3] nids = [] For just force: .. code-block:: python eids = [] nids = [5] or both: .. code-block:: python eids = [3] nids = [5] .. note:: If you split the model into sections and sum the loads on each section, you may not get the same result as if you summed the loads on the total model. This is due to the fact that nodal loads on the boundary are double/triple/etc. counted depending on how many breaks you have. .. todo:: not done... """ if not isinstance(loadcase_id, integer_types): raise RuntimeError('loadcase_id must be an integer; loadcase_id=%r' % loadcase_id) p = _get_load_summation_point(model, p0, cid=0) if eids is None: eids = list(model.element_ids) if nids is None: nids = list(model.node_ids) #for (key, load_case) in model.loads.items(): #if key != loadcase_id: #continue loads, scale_factors, unused_is_grav = model.get_reduced_loads( loadcase_id, skip_scale_factor0=True) F = array([0., 0., 0.]) M = array([0., 0., 0.]) xyz = get_xyz_cid0_dict(model, xyz_cid0) unsupported_types = set() shell_elements = { 'CTRIA3', 'CQUAD4', 'CTRIAR', 'CQUADR', 'CTRIA6', 'CQUAD8', 'CQUAD', 'CSHEAR'} skip_loads = {'QVOL'} for load, scale in zip(loads, scale_factors): #if load.type not in ['FORCE1']: #continue #print(load.type) loadtype = load.type if loadtype == 'FORCE': if load.node_id not in nids: continue if load.Cid() != 0: cp_ref = load.cid_ref #from pyNastran.bdf.bdf import CORD2R #cp = CORD2R() f = load.mag * cp_ref.transform_vector_to_global(load.xyz) * scale else: f = load.mag * load.xyz * scale node = model.Node(load.node_id) r = xyz[node.nid] - p m = cross(r, f) F += f M += m elif load.type == 'FORCE1': not_found_nid = False for nid in load.node_ids: if nid not in nids: not_found_nid = True break if not_found_nid: continue f = load.mag * load.xyz * scale node = model.Node(load.node_id) r = xyz[node.nid] - p m = cross(r, f) F += f M += m elif load.type == 'FORCE2': not_found_nid = False for nid in load.node_ids: if nid not in nids: not_found_nid = True break if not_found_nid: continue f = load.mag * load.xyz * scale node = model.Node(load.node_id) r = xyz[node.nid] - p m = cross(r, f) F += f M += m elif load.type == 'MOMENT': not_found_nid = False for nid in load.node_ids: if nid not in nids: not_found_nid = True break if not_found_nid: continue if load.Cid() != 0: cp_ref = load.cid_ref m = cp_ref.transform_vector_to_global(load.xyz) else: m = load.xyz M += load.mag * m * scale elif load.type == 'MOMENT1': not_found_nid = False for nid in load.node_ids: if nid not in nids: not_found_nid = True break if not_found_nid: continue m = load.mag * load.xyz * scale M += m elif loadtype == 'MOMENT2': not_found_nid = False for nid in load.node_ids: if nid not in nids: not_found_nid = True break if not_found_nid: continue m = load.mag * load.xyz * scale M += m elif loadtype == 'PLOAD': nodes = load.node_ids nnodes = len(nodes) nodesi = 0 if nnodes == 3: n1, n2, n3 = xyz[nodes[0]], xyz[nodes[1]], xyz[nodes[2]] axb = cross(n1 - n2, n1 - n3) centroid = (n1 + n2 + n3) / 3. elif nnodes == 4: n1, n2, n3, n4 = xyz[nodes[0]], xyz[nodes[1]], xyz[nodes[2]], xyz[nodes[3]] axb = cross(n1 - n3, n2 - n4) centroid = (n1 + n2 + n3 + n4) / 4. if nodes[3] in nids: nodesi += 1 else: raise RuntimeError('invalid number of nodes on PLOAD card; ' 'nodes=%s' % str(nodes)) if nodes[0] in nids: nodesi += 1 if nodes[1] in nids: nodesi += 1 if nodes[2] in nids: nodesi += 1 area, normal = _get_area_normal(axb, nodes, xyz) r = centroid - p f = load.pressure * area * normal * scale m = cross(r, f) node_scale = nodesi / float(nnodes) F += f * node_scale M += m * node_scale elif loadtype == 'PLOAD1': _pload1_elements(model, loadcase_id, load, scale, eids, xyz, F, M, p) elif loadtype == 'PLOAD2': pressure = load.pressure * scale for eid in load.element_ids: if eid not in eids: continue elem = model.elements[eid] if elem.type in shell_elements: normal = elem.Normal() area = elem.Area() f = pressure * normal * area r = elem.Centroid() - p m = cross(r, f) F += f M += m else: #model.log.warning('case=%s etype=%r loadtype=%r not supported' % ( #loadcase_id, elem.type, loadtype)) raise NotImplementedError('case=%s etype=%r loadtype=%r not supported' % ( loadcase_id, elem.type, loadtype)) elif loadtype == 'PLOAD4': _pload4_elements(loadcase_id, load, scale, eids, xyz, F, M, p) elif loadtype == 'GRAV': if include_grav: # this will be super slow g = load.GravityVector() * scale for eid, elem in model.elements.items(): if eid not in eids: continue centroid = elem.Centroid() mass = elem.Mass() r = centroid - p f = mass * g m = cross(r, f) F += f M += m elif loadtype in skip_loads: continue else: # we collect them so we only get one print unsupported_types.add(loadtype) for loadtype in unsupported_types: model.log.warning('case=%s loadtype=%r not supported' % (loadcase_id, loadtype)) #model.log.info("case=%s F=%s M=%s\n" % (loadcase_id, F, M)) if cid == 0: return F, M cid0 = 0 F2, M2 = transform_load(F, M, cid0, cid, model) return F2, M2