def example5(): """ Example 5: Get Elements by Node ID - Level 2 """ # this example will demonstate: # - getting the list of elements that share a certain node # our model import pyNastran pkg_path = pyNastran.__path__[0] test_path = os.path.join(pkg_path, '..', 'models', 'solid_bending') bdf_filename = os.path.join(test_path, 'solid_bending.bdf') # instantiate the model from pyNastran.bdf.bdf import BDF model = BDF() model.read_bdf(bdf_filename, xref=True) f = open('junk.out', 'w') # given a Node, get the Elements Attached to that Node # assume node 55 # doesnt support 0d/1d elements yet nid_to_eids_map = model.get_node_id_to_element_ids_map() eids = nid_to_eids_map[55] # convert to elements instead of element IDs elements = [] for eid in eids: elements.append(model.Element(eid)) print("eids = %s" % eids) print("elements =\n %s" % elements)
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 QBDY2 sid=%s' % self.sid self.eid_ref = model.Element(self.eid, 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 QBDY3 sid=%s' % self.sid eids = [] for eid in self.eids: eids.append(model.Element(eid, msg=msg)) self.eids_ref = eids
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 RADBC pid=%s' % self.nodamb elems = [] for eid in self.eids: elem = model.Element(eid, msg=msg) elems.append(elem) self.eids_ref = elems
def test_cbeam_05(self): # modification of test_pbeam_05 model = BDF(debug=False) lines = [ 'PBEAM,3,6,2.9,3.5,5.97,0.4,3.14', ' , , ,2.0,-4.0', ] card = model.add_card(lines, 'PBEAM', is_list=False) lines = [ 'CBEAM 10 3 1 2 0.01.000000 0.0' ] model.add_card(lines, 'CBEAM', is_list=False) lines = ['MAT1, 6, 1.0e7,,0.3'] model.add_card(lines, 'MAT1', is_list=False) lines = ['GRID,1,,0.,0.,0.'] model.add_card(lines, 'GRID', is_list=False) lines = ['GRID,2,,0.,0.,0.'] model.add_card(lines, 'GRID', is_list=False) model.cross_reference() cbeam = model.Element(10) #cbeam = model.elements[10] #print("Area = ", cbeam.Area()) #print("I11 = ", cbeam.I11()) #print("I22 = ", cbeam.I22()) #print("I12 = ", cbeam.I12()) #print("J = ", cbeam.J()) #print("Area = ", cbeam.Area()) #print("I11 = ", cbeam.I1()) #print("I22 = ", cbeam.I2()) #print("I12 = ", cbeam.I12()) #print("J = ", cbeam.J()) node_ids = cbeam.node_ids assert node_ids == [1, 2], node_ids self.assertEqual(cbeam.Area(), 2.9) self.assertEqual(cbeam.I11(), 3.5) self.assertEqual(cbeam.I22(), 5.97) self.assertEqual(cbeam.I12(), 0.4) self.assertEqual(cbeam.J(), 3.14)
def test_cbeam_01(self): """modification of test_pbeam_05""" model = BDF(debug=False) lines = [ 'PBEAM,3,6,2.9,3.5,5.97,0.4,3.14', ' , , ,2.0,-4.0', ] model.add_card(lines, 'PBEAM', is_list=False) lines = [ 'CBEAM 10 3 1 2 0.01.000000 0.0' ] model.add_card(lines, 'CBEAM', is_list=False) mid = 6 E = 1.0e7 G = None nu = 0.3 model.add_mat1(mid, E, G, nu) model.add_grid(1, [0., 0., 0.]) model.add_grid(2, [0., 0., 0.]) model.cross_reference() cbeam = model.Element(10) #cbeam = model.elements[10] #print("Area = ", cbeam.Area()) #print("I11 = ", cbeam.I11()) #print("I22 = ", cbeam.I22()) #print("I12 = ", cbeam.I12()) #print("J = ", cbeam.J()) #print("Area = ", cbeam.Area()) #print("I11 = ", cbeam.I1()) #print("I22 = ", cbeam.I2()) #print("I12 = ", cbeam.I12()) print("J = ", cbeam.J()) node_ids = cbeam.node_ids assert node_ids == [1, 2], node_ids self.assertEqual(cbeam.Area(), 2.9) self.assertEqual(cbeam.I11(), 3.5) self.assertEqual(cbeam.I22(), 5.97) self.assertEqual(cbeam.I12(), 0.4) self.assertEqual(cbeam.J(), 3.14)
def example7(): """ Example 7: Get Elements by Material ID - Level 2 """ # this example will demonstate: # - getting a list of elements that have a certain material # our model import pyNastran pkg_path = pyNastran.__path__[0] test_path = os.path.join(pkg_path, '..', 'models', 'sol_101_elements') bdf_filename = os.path.join(test_path, 'static_solid_shell_bar.bdf') # instantiate the model from pyNastran.bdf.bdf import BDF model = BDF() model.read_bdf(bdf_filename, xref=True) f = open('junk.out', 'w') # assume you want the eids for material 10 pid_to_eids_map = model.get_property_id_to_element_ids_map() mid_to_pids_map = model.get_material_id_to_property_ids_map() pids1 = mid_to_pids_map[1] print('pids1 = %s' % pids1) ## pids1 = [1, 2, 3, 4, 5] eids = [] for pid in pids1: eids += pid_to_eids_map[pid] # convert to elements instead of element IDs elements = [] for eid in eids: element = model.Element(eid) elements.append(element) print(str(element).rstrip())
def example6(): """ Example 6: Get Elements by Property ID - Level 2 """ # this example will demonstate: # - getting a list of elements that have a certain property # our model import pyNastran pkg_path = pyNastran.__path__[0] test_path = os.path.join(pkg_path, '..', 'models', 'sol_101_elements') bdf_filename = os.path.join(test_path, 'static_solid_shell_bar.bdf') # instantiate the model from pyNastran.bdf.bdf import BDF model = BDF() model.read_bdf(bdf_filename, xref=True) f = open('junk.out', 'w') # Creating a List of Elements based on a Property ID # assume pid=1 pid_to_eids_map = model.get_property_id_to_element_ids_map() eids4 = pid_to_eids_map[4] # PSHELL print("eids4 = %s" % eids4) ## eids4 = [6, 7, 8, 9, 10, 11] # convert to elements instead of element IDs elements4 = [] for eid in eids4: elements4.append(model.Element(eid)) # just to verify elem = model.elements[eids4[0]] print(elem.pid)
class FEMModel: """ Class representing a FEM model which is based on a Nastran bdf file and which needs to be converted to a Modelica lumped element model. From the Nastran bdf file only CTRIA3 triangular plate elements, CQUAD4 quadrilateral plate elements and CTETRA four-Sided solid Element are imported. The corresponding Modelica lumped element models are CTRIA3.mo, CQUAD4.mo and CTETRA.mo """ count = 0 # How many FEMModel objects are there? def __init__(self, NastranFile, meshfile): """ Extend `FEMModel.__init__()` to append required input and output data. Keyword arguments: NastranFile -- Nastran input filename """ self.NastranFile = NastranFile self.model = None self.conv_el = [] self.maxelid = None self.NCTRIA3 = None self.NCQUAD4 = None self.NCTETRA = None self.NCHEXA8 = None self.IFdict = {} self._readNas() self._getIF() self.con_mat = np.zeros((self.maxelid, self.maxelid)) self.vol = np.zeros(self.maxelid) self.F_mat = np.zeros((self.maxelid, self.maxelid)) self.meshfile = meshfile self.calc_vol() self.PlatingT = None print "\nTotal volume of nastran file: %3.3e m^3" % np.sum(self.vol) FEMModel.count += 1 def _readNas(self): """ Read the nastran file and extract the elements. """ 'Create the BDF object' print "Start reading Nastran file:" print "%s" % os.path.abspath(self.NastranFile) self.model = BDF(debug=False) self.model.read_bdf(self.NastranFile, xref=True) self.conv_el = [(eid, el) for (eid, el) in sorted(self.model.elements.items()) if el.type in ['CTRIA3', 'CQUAD4', 'CTETRA', 'CHEXA8']] self.maxelid = np.max(self.model.element_ids) self.NCTRIA3 = len([(eid, el) for (eid, el) in self.conv_el if el.type == 'CTRIA3']) self.NCQUAD4 = len([(eid, el) for (eid, el) in self.conv_el if el.type == 'CQUAD4']) self.NCTETRA = len([(eid, el) for (eid, el) in self.conv_el if el.type == 'CTETRA']) self.NCHEXA8 = len([(eid, el) for (eid, el) in self.conv_el if el.type == 'CHEXA8']) print '-------------------------------' print '%-4i elements found in file which can be converted:' % len( self.conv_el) print '-------------------------------' print "%-4i CTRIA3 elements" % self.NCTRIA3 print "%-4i CQUAD4 elements" % self.NCQUAD4 print "%-4i CTETRA elements" % self.NCTETRA print "%-4i CHEXA8 elements" % self.NCHEXA8 print '-------------------------------' print "Finished reading Nastran file." print '-------------------------------\n' def _getIF(self): """ Get interfaces. """ for spc in self.model.spcs: for node in self.model.SPC(spc): s1 = str(node).split("SPC")[1] nid = int(s1.split()[1]) ngid = s1.split()[3].rstrip('.') if ngid in self.IFdict: self.IFdict[ngid]['nodes'].append(nid) else: self.IFdict[ngid] = {'nodes': [nid], 'elements': {}} for key in self.IFdict: for nid in self.IFdict[key]['nodes']: tmp = self.model.get_node_id_to_element_ids_map()[nid] for i in tmp: inodes = [node.nid for node in self.model.Element(i).nodes] if np.sum( [inodes.count(x) for x in self.IFdict[key]['nodes']]) > 1: if i not in self.IFdict[key]['elements']: self.IFdict[key]['elements'].setdefault(i, []) for eid in self.IFdict[key]['elements']: el = self.model.Element(eid) elnodes = [node.nid for node in el.nodes] if el.type == 'CTRIA3': sides = [[0, 1], [1, 2], [2, 0]] if el.type == 'CQUAD4': sides = [[0, 1], [1, 2], [2, 3], [3, 0]] for i in range(len(sides)): v1 = elnodes[sides[i][0]] v2 = elnodes[sides[i][1]] if (v1 in self.IFdict[key]['nodes']) and ( v2 in self.IFdict[key]['nodes']): self.IFdict[key]['elements'][eid].append([[v1, v2], 0]) print self.IFdict def _connected(self, el_type_1, el_nodes_1, el_type_2, el_nodes_2): """ """ comb = { 'CTRIA3CTRIA3': 2, 'CTRIA3CQUAD4': 2, 'CTRIA3CTETRA': 2, 'CTRIA3CHEXA8': 2, 'CQUAD4CTRIA3': 2, 'CQUAD4CQUAD4': 2, 'CQUAD4CTETRA': 2, 'CQUAD4CHEXA8': 2, 'CTETRACTRIA3': 2, 'CTETRACQUAD4': 2, 'CTETRACTETRA': 3, 'CTETRACHEXA8': -1, 'CHEXA8CTRIA3': 2, 'CHEXA8CQUAD4': 2, 'CHEXA8CTETRA': -1, 'CHEXA8CHEXA8': 4, } mask = el_type_1 + el_type_2 inters = len(np.intersect1d(el_nodes_1, el_nodes_2)) if inters == comb[mask]: value = True else: value = False return value def _get_con(self): """ """ nid_to_eids_map = self.model.get_node_id_to_element_ids_map() for (eid, el) in sorted(self.model.elements.items()): con_el = [] el_type_1 = el.type el_nodes_1 = el.node_ids con_el_node = [] for elid in el.node_ids: [con_el_node.append(i) for i in nid_to_eids_map[elid]] for eid2 in set(con_el_node): el_type_2 = self.model.Element(eid2).type el_nodes_2 = self.model.Element(eid2).node_ids if self._connected(el_type_1, el_nodes_1, el_type_2, el_nodes_2): con_el.append(eid2) for con in con_el: self.con_mat[con - 1][eid - 1] = 1 self.con_mat[eid - 1][con - 1] = 1 self.ncon = np.count_nonzero(np.triu(self.con_mat)) print "\nTotal number of internal connections: %i" % (np.count_nonzero( self.con_mat)) def calc_vol(self): """ """ for (eid, el) in sorted(self.model.elements.items()): v, lcar = self._calc_el_vol(el, eid) self.vol[eid - 1] = v def _calc_el_vol(self, el, eid): """ """ if (el.type == 'CTRIA3') or (el.type == 'CQUAD4'): a = el.Area() t = el.Thickness() v = a * t * 1e-9 lcar = np.sqrt((4. / 3.) * np.sqrt(3.) * (a * 1 / 115.)) if el.type == 'CTETRA': v = el.Volume() * 1e-9 lcar = (v * 3e6 * np.sqrt(2))**(1. / 3.) if el.type == 'CHEXA8': v = el.Volume() * 1e-9 lcar = (v * 1.5e6 * np.sqrt(2))**(1. / 3.) self.vol[eid - 1] = v return (v, lcar) def convert(self, verbose=False, PlatingT=None): """ """ if PlatingT is not None: self.PlatingT = PlatingT self.Fpl_mat = np.zeros((self.maxelid, self.maxelid)) print "Adding data for plating thickness of %3.3e" % self.PlatingT self._get_con() nF = 0 for (eid1, el1) in self.conv_el: if eid1: el1 = self.model.elements[eid1] (vol, lcar) = self._calc_el_vol(el1, eid1) print "\nElement %i evaluated: type=%s, lcar=%f, vol=%e" % ( eid1, el1.type, lcar, vol) points = self.model.elements[eid1].get_node_positions() if (el1.type == "CTRIA3") or (el1.type == "CQUAD4"): points = _rotate_2D(points) if (el1.type == "CTETRA") or (el1.type == "CHEXA8"): el13d = True t = None else: el13d = False t = el1.Thickness() print "Creating mesh..." mesh_el(el1.type, points, lcar=lcar, filename=self.meshfile) for eid2 in np.arange(1, self.maxelid + 1): if eid2: if self.con_mat[eid1 - 1][eid2 - 1] != 0: n_ids_1 = self.model.elements[eid1].node_ids n_ids_2 = self.model.elements[eid2].node_ids el2 = self.model.elements[eid2] boundary = np.in1d(n_ids_1, n_ids_2) if (el2.type == "CTRIA3") or (el2.type == "CQUAD4"): el22d = True else: el22d = False if el13d and el22d: print "3D to 2D connection detected, adjusting boundary." nodes = [] for node in n_ids_1: if node not in n_ids_2: nodes.append(node) Ftot = 0 for node in nodes: for i in range(len(boundary)): if n_ids_1[i] == node: boundary[i] = True try: F = FarField(el1.type, points, boundary, lcar, 0.005, self.meshfile, thickness=t, verbose=verbose) print "Handling element %i, node %i added, F=%f" % ( eid2, node, F) Ftot += F except Exception as e: print "Handling element %i, F determination failed!" % ( eid2) print(e) Favg = Ftot / len(nodes) self.F_mat[eid1 - 1][eid2 - 1] = Favg nF += 1 print "Handling element %i, done, Favg=%f" % ( eid2, Favg) try: F = FarField(el1.type, points, boundary, lcar, 0.005, self.meshfile, thickness=t, verbose=verbose) self.F_mat[eid1 - 1][eid2 - 1] = F nF += 1 print "Step %i, handling element %i, F=%f" % ( nF, eid2, F) if self.PlatingT is not None: self.Fpl_mat[eid1 - 1][eid2 - 1] = (self.PlatingT / t) * F print "Step %i, handling plating element %i, Fpl=%f" % ( nF, eid2, self.Fpl_mat[eid1 - 1][eid2 - 1]) except Exception as e: print "Handling element %i, F determination failed!" % ( eid2) print(e) for key in self.IFdict: if eid1 in self.IFdict[key]['elements']: IFbound = self.IFdict[key]['elements'][eid1] for IF in IFbound: edge = IF[0] boundary = np.in1d(n_ids_1, edge) try: F = FarField(el1.type, points, boundary, lcar, 0.005, self.meshfile, thickness=t, verbose=verbose) IF[1] = F print "Handling element %i interface, F=%f" % ( eid1, F) if self.PlatingT is not None: IF[2] = (self.PlatingT / t) * F print "Plating element %i interface, Fpl=%f" % ( eid1, IF[2]) except Exception as e: print "Handling element %i, interface failed!" % ( eid1) print(e) self.vtotal = np.sum(self.vol) print '\nTotal converted volume: %e\n' % self.vtotal def ExportModelicaFile(self, FileName, WithinStr=None, MaterialStr=None, IFnamedict=None, DiagramStr=None, PlatingStr=None): """ """ print "Start writing Modelica file:" print "%s" % os.path.abspath(FileName) 'Open the Modelica file buffer for writing' f = open(FileName, 'w') self.modelname = ntpath.basename(FileName)[:-3] 'Write Modelica file header' if WithinStr is None: header = "model %s\n" % self.modelname else: header = "within %s;\n\n" % WithinStr header += "model %s\n" % self.modelname header += " /*\n" header += " This Modelica file is created using the FarFieldConvert python script.\n" header += " Nastran input file: %s\n" % os.path.abspath( self.NastranFile) header += " Exported on %s, at %s\n" % ( datetime.datetime.now().strftime("%d/%m/%Y"), datetime.datetime.now().strftime("%H:%M:%S")) header += " The file Contains the following mesh elements converted into lumped elements:\n" header += " %-5i CTRIA3 elements\n" % self.NCTRIA3 header += " %-5i CQUAD4 elements\n" % self.NCQUAD4 header += " %-5i CTETRA elements\n" % self.NCTETRA header += " %-5i CHEXA8 elements\n\n" % self.NCHEXA8 header += " The following %i IF groups were converted from SPC temperature BC's:\n" % len( self.IFdict) sortedkeys = sorted(map(int, list(self.IFdict.keys()))) for id in sortedkeys: key = str(id) if IFnamedict is None: header += " %s: %s \n" % (key, str(self.IFdict[key])) else: header += " %s: nodes: %s \n" % (IFnamedict[key]['name'], self.IFdict[key]['nodes']) if self.PlatingT is not None: header += " A plating is added to the model with a thickness of %f mm\n" % self.PlatingT header += " The heat capacity of this plating is neglected, while parallel conductances are added to the base material.\n" header += " */\n" f.write(header) f.write("\n") 'Create material declaration and start temperature statement:' Strmat = " /* Material declaration: */\n" if MaterialStr is None: Strmat += " replaceable package Material = ThermalCryogenics.Materials.Unity\n" Strmat += " constrainedby Modelica.ThermalCryogenics.Interfaces.PartialMaterial;\n" else: if self.PlatingT is None: Strmat += " replaceable package Material = %s\n" % MaterialStr Strmat += " constrainedby Modelica.ThermalCryogenics.Interfaces.PartialMaterial;\n" else: Strmat += " replaceable package Material = %s\n" % MaterialStr Strmat += " constrainedby Modelica.ThermalCryogenics.Interfaces.PartialMaterial;\n" Strmat += " replaceable package Plating = %s\n" % PlatingStr Strmat += " constrainedby Modelica.ThermalCryogenics.Interfaces.PartialMaterial;\n" f.write(Strmat) StrTstart = " parameter Modelica.SIunits.Temperature Tstart(displayUnit=\"K\") \"Start temperature of part\";\n" f.write(StrTstart) f.write("\n") 'Create component statements in mo file' f.write(' /* Component section: */\n') IFStr = _interfacesection(self, IFnamedict) f.write(IFStr) ModelStr = _modelsection(self) f.write(ModelStr) 'Create connection equations in mo file' f.write('\n') self.ConnectStr = _connectsection(self, IFnamedict) f.write(self.ConnectStr) 'Add footer in mo file' if DiagramStr is None: l = len(self.IFdict) * 50. footer = "\n" footer += "annotation(Icon(coordinateSystem(initialScale = 0.1),\n" footer += " graphics={\n" footer += " Text(\n" footer += " origin = {0, 0},\n" footer += " lineColor = {0, 0, 255},\n" footer += " extent = {{-150, 140}, {150, 100}},\n" footer += " textString = \"%name\"),\n" footer += " Rectangle(\n" footer += " origin = {0, 0},\n" footer += " extent = {{-100, %.0f}, {100, %.0f}})}),\n" % ( l, -l) footer += " uses(Modelica(version = \"3.2.2\")));\n" else: footer = DiagramStr footer += "\nend %s;" % self.modelname f.write(footer) 'Close the mo file buffer' f.close() print "Finished"
def cross_reference(self, model: BDF) -> None: self.eid_ref = model.Element(self.eid) self.eids_ref = model.Elements(self.eids)
x = float(gpos[0]) y = float(gpos[1]) z = float(gpos[2]) Coord.append(x) Coord.append(y) Coord.append(z) test = points.InsertNextPoint(*Coord) Color.InsertTuple1(test, 0) nidMap[nid] = i i = i + 1 grid.SetPoints(points) for (eid, element) in model.elements.iteritems(): if isinstance(element, CONM2): exmcon = model.Element(eid) val = str(exmcon) val.strip() mcon = val.strip().split() g = (int(mcon[2])) mconvert = vtk.vtkVertex() mconvert.GetPointIds().SetId(0, nidMap[g]) Mconcell = grid.InsertNextCell(mconvert.GetCellType(), mconvert.GetPointIds()) Color.InsertTuple1(Mconcell, 1) k = 0 for (eid, element) in model.elements.iteritems(): EidMap[eid] = k if isinstance(element, CBUSH) or isinstance(element, CBEAM): exbar = model.Element(eid)