def test_eq4(self): r""" 5 6 *-------* 40 | \ | | \ | | \ | *-------* 3 1 20 """ log = SimpleLogger(level='error') msg = 'CEND\n' msg += 'BEGIN BULK\n' msg += 'GRID,1, , 0., 0., 0.\n' msg += 'GRID,20,, 1., 0., 0.\n' msg += 'GRID,3, , 1.01, 0., 0.\n' msg += 'GRID,41,, 1., 1., 0.\n' # eq msg += 'GRID,4,, 1., 1., 0.\n' # eq msg += 'GRID,40,, 1., 1., 0.\n' # eq msg += 'GRID,4,, 1., 1., 0.\n' # eq msg += 'GRID,5, , 0., 1., 0.\n' msg += 'GRID,6, , 0., 1.01, 0.\n' msg += 'CTRIA3,1, 100,1,20,6\n' msg += 'CTRIA3,10,100,3,40,5\n' msg += 'PSHELL,100,1000,0.1\n' msg += 'MAT1,1000,3.0,, 0.3\n' msg += 'ENDDATA' bdf_filename = 'nonunique.bdf' bdf_filename_out = 'unique.bdf' with open(bdf_filename, 'w') as bdf_file: bdf_file.write(msg) tol = 0.2 node_set = [4, 40, 41] # Collapse 5/6 and 20/3; Put a 40 and 20 to test non-sequential IDs bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=node_set, crash_on_collapse=False, log=log, debug=False) model = BDF(log=log, debug=False) model.read_bdf(bdf_filename_out) nids = model.nodes.keys() assert len(model.nodes) == 6, 'nnodes=%s nodes=%s' % (len(model.nodes), nids) assert 1 in nids, nids assert 20 in nids, nids assert 3 in nids, nids assert 4 in nids, nids assert 5 in nids, nids assert 6 in nids, nids assert 40 not in nids, nids assert 41 not in nids, nids #print(nids) os.remove(bdf_filename) os.remove(bdf_filename_out)
def test_eq4(self): r""" 5 6 *-------* 40 | \ | | \ | | \ | *-------* 3 1 20 """ msg = 'CEND\n' msg += 'BEGIN BULK\n' msg += 'GRID,1, , 0., 0., 0.\n' msg += 'GRID,20,, 1., 0., 0.\n' msg += 'GRID,3, , 1.01, 0., 0.\n' msg += 'GRID,41,, 1., 1., 0.\n' # eq msg += 'GRID,4,, 1., 1., 0.\n' # eq msg += 'GRID,40,, 1., 1., 0.\n' # eq msg += 'GRID,4,, 1., 1., 0.\n' # eq msg += 'GRID,5, , 0., 1., 0.\n' msg += 'GRID,6, , 0., 1.01, 0.\n' msg += 'CTRIA3,1, 100,1,20,6\n' msg += 'CTRIA3,10,100,3,40,5\n' msg += 'PSHELL,100,1000,0.1\n' msg += 'MAT1,1000,3.0,, 0.3\n' msg += 'ENDDATA' bdf_filename = 'nonunique.bdf' bdf_filename_out = 'unique.bdf' with codec_open(bdf_filename, 'w') as bdf_file: bdf_file.write(msg) tol = 0.2 node_set = [4, 40, 41] # Collapse 5/6 and 20/3; Put a 40 and 20 to test non-sequential IDs bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=node_set, crash_on_collapse=False, log=log, debug=False) model = BDF(log=log, debug=False) model.read_bdf(bdf_filename_out) nids = model.nodes.keys() assert len(model.nodes) == 6, 'nnodes=%s nodes=%s' % (len(model.nodes), nids) assert 1 in nids, nids assert 20 in nids, nids assert 3 in nids, nids assert 4 in nids, nids assert 5 in nids, nids assert 6 in nids, nids assert 40 not in nids, nids assert 41 not in nids, nids #print(nids) os.remove(bdf_filename) os.remove(bdf_filename_out)
def cmd_line_equivalence(argv=None, quiet=False): """command line interface to bdf_equivalence_nodes""" if argv is None: argv = sys.argv from docopt import docopt import pyNastran msg = ( "Usage:\n" " bdf equivalence IN_BDF_FILENAME EQ_TOL [-o OUT_BDF_FILENAME]\n" ' bdf equivalence -h | --help\n' ' bdf equivalence -v | --version\n' '\n' "Positional Arguments:\n" " IN_BDF_FILENAME path to input BDF/DAT/NAS file\n" " EQ_TOL the spherical equivalence tolerance\n" #" OUT_BDF_FILENAME path to output BDF/DAT/NAS file\n" '\n' 'Options:\n' " -o OUT, --output OUT_BDF_FILENAME path to output BDF/DAT/NAS file\n\n" 'Info:\n' ' -h, --help show this help message and exit\n' " -v, --version show program's version number and exit\n") if len(argv) == 1: sys.exit(msg) ver = str(pyNastran.__version__) #type_defaults = { # '--nerrors' : [int, 100], #} data = docopt(msg, version=ver, argv=argv[1:]) if not quiet: # pragma: no cover print(data) bdf_filename = data['IN_BDF_FILENAME'] bdf_filename_out = data['--output'] if bdf_filename_out is None: bdf_filename_out = 'merged.bdf' tol = data['EQ_TOL'] size = 16 from pyNastran.bdf.mesh_utils.bdf_equivalence import bdf_equivalence_nodes level = 'debug' if not quiet else 'warning' log = SimpleLogger(level=level, encoding='utf-8', log_func=None) bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=10, xref=True, node_set=None, size=size, is_double=False, remove_collapsed_elements=False, avoid_collapsed_elements=False, crash_on_collapse=False, log=log, debug=True)
def cmd_line_equivalence(): # pragma: no cover """command line interface to bdf_equivalence_nodes""" import sys from docopt import docopt import pyNastran msg = "Usage:\n" msg += " bdf equivalence IN_BDF_FILENAME EQ_TOL [-o OUT_BDF_FILENAME]\n" msg += ' bdf equivalence -h | --help\n' msg += ' bdf equivalence -v | --version\n' msg += '\n' msg += "Positional Arguments:\n" msg += " IN_BDF_FILENAME path to input BDF/DAT/NAS file\n" msg += " EQ_TOL the spherical equivalence tolerance\n\n" #msg += " OUT_BDF_FILENAME path to output BDF/DAT/NAS file\n" msg += '\n' msg += 'Options:\n' msg += " -o OUT, --output OUT_BDF_FILENAME path to output BDF/DAT/NAS file\n\n" msg += 'Info:\n' msg += ' -h, --help show this help message and exit\n' msg += " -v, --version show program's version number and exit\n" if len(sys.argv) == 1: sys.exit(msg) ver = str(pyNastran.__version__) #type_defaults = { # '--nerrors' : [int, 100], #} data = docopt(msg, version=ver) print(data) size = 16 bdf_filename = data['IN_BDF_FILENAME'] bdf_filename_out = data['--output'] if bdf_filename_out is None: bdf_filename_out = 'merged.bdf' tol = data['EQ_TOL'] size = 16 from pyNastran.bdf.mesh_utils.bdf_equivalence import bdf_equivalence_nodes bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=10, xref=True, node_set=None, size=size, is_double=False, remove_collapsed_elements=False, avoid_collapsed_elements=False, crash_on_collapse=False, debug=True)
def cmd_line_equivalence(): # pragma: no cover """command line interface to bdf_equivalence_nodes""" import sys from docopt import docopt import pyNastran msg = "Usage:\n" msg += " bdf equivalence IN_BDF_FILENAME EQ_TOL [-o OUT_BDF_FILENAME]\n" msg += ' bdf equivalence -h | --help\n' msg += ' bdf equivalence -v | --version\n' msg += '\n' msg += "Positional Arguments:\n" msg += " IN_BDF_FILENAME path to input BDF/DAT/NAS file\n" msg += " EQ_TOL the spherical equivalence tolerance\n\n" #msg += " OUT_BDF_FILENAME path to output BDF/DAT/NAS file\n" msg += '\n' msg += 'Options:\n' msg += " -o OUT, --output OUT_BDF_FILENAME path to output BDF/DAT/NAS file\n\n" msg += 'Info:\n' msg += ' -h, --help show this help message and exit\n' msg += " -v, --version show program's version number and exit\n" if len(sys.argv) == 1: sys.exit(msg) ver = str(pyNastran.__version__) #type_defaults = { # '--nerrors' : [int, 100], #} data = docopt(msg, version=ver) print(data) size = 16 bdf_filename = data['IN_BDF_FILENAME'] bdf_filename_out = data['--output'] if bdf_filename_out is None: bdf_filename_out = 'merged.bdf' tol = data['EQ_TOL'] size = 16 from pyNastran.bdf.mesh_utils.bdf_equivalence import bdf_equivalence_nodes bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=10, xref=True, node_set=None, size=size, is_double=False, remove_collapsed_elements=False, avoid_collapsed_elements=False, crash_on_collapse=False, debug=True)
def test_eq1(self): """ Collapse nodes 2 and 3; consider 1-3 """ log = SimpleLogger(level='error') msg = ('CEND\n' 'BEGIN BULK\n' 'GRID,1,,0.,0.,0.\n' 'GRID,2,,0.,0.,0.5\n' 'GRID,3,,0.,0.,0.51\n' 'GRID,10,,0.,0.,1.\n' 'GRID,11,,0.,0.,1.\n' 'CTRIA3,1,1,1,2,11\n' 'CTRIA3,3,1,2,3,11\n' 'CTRIA3,4,1,1,2,10\n' 'PSHELL,1,1,0.1\n' 'MAT1,1,3.0,, 0.3\n' 'ENDDATA') bdf_filename = 'nonunique.bdf' bdf_filename_out = 'unique.bdf' with open(bdf_filename, 'w') as bdf_file: bdf_file.write(msg) tol = 0.2 bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=None, crash_on_collapse=False, log=log, debug=False) # model = BDF(debug=False) # model.read_bdf(bdf_filename_out) # assert len(model.nodes) == 3, len(model.nodes) os.remove(bdf_filename) os.remove(bdf_filename_out)
def test_eq1(self): """ Collapse nodes 2 and 3; consider 1-3 """ msg = ( 'CEND\n' 'BEGIN BULK\n' 'GRID,1,,0.,0.,0.\n' 'GRID,2,,0.,0.,0.5\n' 'GRID,3,,0.,0.,0.51\n' 'GRID,10,,0.,0.,1.\n' 'GRID,11,,0.,0.,1.\n' 'CTRIA3,1,1,1,2,11\n' 'CTRIA3,3,1,2,3,11\n' 'CTRIA3,4,1,1,2,10\n' 'PSHELL,1,1,0.1\n' 'MAT1,1,3.0,, 0.3\n' 'ENDDATA' ) bdf_filename = 'nonunique.bdf' bdf_filename_out = 'unique.bdf' with codec_open(bdf_filename, 'w') as bdf_file: bdf_file.write(msg) tol = 0.2 bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=None, crash_on_collapse=False, log=log, debug=False) # model = BDF(debug=False) # model.read_bdf(bdf_filename_out) # assert len(model.nodes) == 3, len(model.nodes) os.remove(bdf_filename) os.remove(bdf_filename_out)
def test_eq2(self): r""" 5 6 *-------* 40 | \ | | \ | | \ | *-------* 3 1 20 """ log = SimpleLogger(level='error') msg = ( 'CEND\n' 'BEGIN BULK\n' 'GRID,1, , 0., 0., 0.\n' 'GRID,20,, 1., 0., 0.\n' 'GRID,3, , 1.01, 0., 0.\n' 'GRID,40,, 1., 1., 0.\n' 'GRID,5, , 0., 1., 0.\n' 'GRID,6, , 0., 1.01, 0.\n' 'CTRIA3,1, 100,1,20,6\n' 'CTRIA3,10,100,3,40,5\n' 'PSHELL,100,1000,0.1\n' 'MAT1,1000,3.0,, 0.3\n' 'ENDDATA' ) bdf_filename = 'nonunique.bdf' bdf_filename_out = 'unique.bdf' with open(bdf_filename, 'w') as bdf_file: bdf_file.write(msg) tol = 0.2 # Collapse 5/6 and 20/3; Put a 40 and 20 to test non-sequential IDs bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=None, crash_on_collapse=False, log=log, debug=False) model = BDF(log=log, debug=False) model.read_bdf(bdf_filename_out) msg = 'nnodes=%s\n' % len(model.nodes) for nid, node in sorted(model.nodes.items()): msg += 'nid=%s xyz=%s\n' % (nid, node.xyz) assert len(model.nodes) == 4, msg #os.remove(bdf_filename) os.remove(bdf_filename_out) tol = 0.009 # Don't collapse anything because the tolerance is too small bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=None, crash_on_collapse=False, log=log, debug=False) model = BDF(log=log, debug=False) model.read_bdf(bdf_filename_out) assert len(model.nodes) == 6, len(model.nodes) os.remove(bdf_filename_out) tol = 0.2 node_set = [2, 3] # Node 2 is not defined, so crash with self.assertRaises(RuntimeError): # node 2 is not defined because it should be node 20 bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=node_set, crash_on_collapse=False, log=log, debug=False) tol = 0.2 node_list = [20, 3] # Only collpase 2 nodes bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=node_list, crash_on_collapse=False, log=log, debug=False) model = BDF(log=log, debug=False) model.read_bdf(bdf_filename_out) assert len(model.nodes) == 5, len(model.nodes) os.remove(bdf_filename_out) tol = 0.2 node_set = {20, 3} # Only collpase 2 nodes bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=node_set, crash_on_collapse=False, log=log, debug=False) model = BDF(log=log, debug=False) model.read_bdf(bdf_filename_out) assert len(model.nodes) == 5, len(model.nodes) os.remove(bdf_filename_out) tol = 0.2 aset = np.array([20, 3, 4], dtype='int32') bset = np.array([20, 3], dtype='int32') node_set = np.intersect1d(aset, bset) assert len(node_set) > 0, node_set # Only collpase 2 nodes bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=node_set, crash_on_collapse=False, debug=False) model = BDF(debug=False) model.read_bdf(bdf_filename_out) assert len(model.nodes) == 5, len(model.nodes) os.remove(bdf_filename_out)
def test_eq3(self): """node_set=None""" log = SimpleLogger(level='error') lines = [ '$pyNastran: version=msc', '$pyNastran: punch=True', '$pyNastran: encoding=ascii', '$NODES', '$ Nodes to merge:', '$ 5987 10478', '$ GRID 5987 35.46 -6. 0.', '$ GRID 10478 35.46 -6. 0.', '$ 5971 10479', '$ GRID 5971 34.92 -6. 0.', '$ GRID 10479 34.92 -6. 0.', '$ 6003 10477', '$ GRID 6003 36. -6. 0.', '$ GRID 10477 36. -6. 0.', 'GRID 5971 34.92 -6. 0.', 'GRID 5972 34.92-5.73333 0.', 'GRID 5973 34.92-5.46667 0.', 'GRID 5987 35.46 -6. 0.', 'GRID 5988 35.46-5.73333 0.', 'GRID 5989 35.46-5.46667 0.', 'GRID 6003 36. -6. 0.', 'GRID 6004 36.-5.73333 0.', 'GRID 6005 36.-5.46667 0.', 'GRID 10476 36. -6. -1.5', 'GRID 10477 36. -6. 0.', 'GRID 10478 35.46 -6. 0.', 'GRID 10479 34.92 -6. 0.', 'GRID 10561 34.92 -6. -.54', '$ELEMENTS_WITH_PROPERTIES', 'PSHELL 1 1 .1', 'CQUAD4 5471 1 5971 5987 5988 5972', 'CQUAD4 5472 1 5972 5988 5989 5973', 'CQUAD4 5486 1 5987 6003 6004 5988', 'CQUAD4 5487 1 5988 6004 6005 5989', 'PSHELL 11 1 .1', 'CTRIA3 9429 11 10561 10476 10478', 'CTRIA3 9439 11 10478 10479 10561', 'CTRIA3 9466 11 10476 10477 10478', '$MATERIALS', 'MAT1 1 3. .3', ] bdf_filename = 'nonunique2.bdf' bdf_filename_out = 'unique2.bdf' with open(bdf_filename, 'w') as bdf_file: bdf_file.write('\n'.join(lines)) tol = 0.01 bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=None, crash_on_collapse=False, log=log, debug=False) model = BDF(debug=False) model.read_bdf(bdf_filename_out) assert len(model.nodes) == 11, len(model.nodes) os.remove(bdf_filename) os.remove(bdf_filename_out)
def cmd_line_mirror(): # pragma: no cover """command line interface to write_bdf_symmetric""" from docopt import docopt import pyNastran msg = ( "Usage:\n" " bdf mirror IN_BDF_FILENAME [-o OUT_BDF_FILENAME] [--plane PLANE] [--tol TOL]\n" " bdf mirror IN_BDF_FILENAME [-o OUT_BDF_FILENAME] [--plane PLANE] [--noeq]\n" ' bdf mirror -h | --help\n' ' bdf mirror -v | --version\n' '\n' "Positional Arguments:\n" " IN_BDF_FILENAME path to input BDF/DAT/NAS file\n" #" OUT_BDF_FILENAME path to output BDF/DAT/NAS file\n" '\n' 'Options:\n' " -o OUT, --output OUT_BDF_FILENAME path to output BDF/DAT/NAS file\n" " --plane PLANE the symmetry plane (xz, yz, xy); default=xz\n" ' --tol TOL the spherical equivalence tolerance; default=1e-6\n' ' --noeq disable equivalencing\n' "\n" # (default=0.000001) 'Info:\n' ' -h, --help show this help message and exit\n' " -v, --version show program's version number and exit\n" ) if len(sys.argv) == 1: sys.exit(msg) ver = str(pyNastran.__version__) #type_defaults = { # '--nerrors' : [int, 100], #} data = docopt(msg, version=ver) if data['--tol'] is None: data['TOL'] = 0.000001 tol = data['TOL'] if data['--noeq'] is not None: tol = -1. plane = 'xz' if data['--plane'] is not None: plane = data['--plane'] print(data) size = 16 bdf_filename = data['IN_BDF_FILENAME'] bdf_filename_out = data['--output'] if bdf_filename_out is None: bdf_filename_out = 'mirrored.bdf' from pyNastran.bdf.bdf import read_bdf from pyNastran.bdf.mesh_utils.bdf_equivalence import bdf_equivalence_nodes model = read_bdf(bdf_filename) size = 16 bdf_filename_temp = '__temp.bdf__' write_bdf_symmetric(model, bdf_filename_temp, encoding=None, size=size, is_double=False, enddata=None, close=True, plane=plane) bdf_equivalence_nodes(bdf_filename_temp, bdf_filename_out, tol, renumber_nodes=False, neq_max=10, xref=True, node_set=None, size=size, is_double=False, remove_collapsed_elements=False, avoid_collapsed_elements=False, crash_on_collapse=False, debug=True) os.remove(bdf_filename_temp)
def equivalence_ugrid3d_and_bdf_to_bdf(ugrid_filename, bdf_filename, pshell_pids_to_remove, tol=0.01, renumber=True): """ Merges a UGRID3D (*.ugrid) with a BDF and exports a BDF that is equivalenced and renumbered. Parameters ---------- ugrid_filename : str the AFLR3/UGrid3d filename bdf_filename : str the BDF filename pshell_pids_to_remove : List[int, ...] tol : float; default=0.01 the equivalence tolerance renumber : bool; default=True calls ``bdf_renumber`` to renumber the output BDF model Returns ------- out_bdf_filename : str the output BDF filename """ print('equivalence_ugrid3d_and_bdf_to_bdf - bdf_filename=%s' % bdf_filename) print('equivalence_ugrid3d_and_bdf_to_bdf - ugrid_filename=%s' % ugrid_filename) check_path(ugrid_filename, 'ugrid_filename') base = os.path.splitext(bdf_filename)[0] #bdf_merged_filename = base + '_merged.bdf' bdf_equivalence_filename = base + '_equivalence.bdf' bdf_renumber_filename = base + '_renumber.bdf' update_merge = True if update_merge: ugrid_model = UGRID(log=None, debug=False) ugrid_model.read_ugrid(ugrid_filename) bdf_model = read_bdf(bdf_filename, xref=False) #bdf_model.write_bdf(bdf_merged_filename, interspersed=False, enddata=False) tol = 0.01 nid0 = max(bdf_model.nodes) + 1 # new node ids start at max+1 nid_offset = nid0 - 1 # node_ids are 1-based, so we must offset them eid = max(bdf_model.elements) + 1 cp = None for nid, node in enumerate(ugrid_model.nodes): #assert len(node) == 3, node card = ['GRID', nid + nid0, cp] + list(node) bdf_model.add_card(card, 'GRID', is_list=True) #f.write(print_card_double(card)) pid_solid = 100 mid = 1 pids = unique(ugrid_model.pids) for pidi in pids: if pidi not in pshell_pids_to_remove: card = ['PSHELL', pidi, mid, 0.1] bdf_model.add_card(card, 'PSHELL', is_list=True) card = ['PSOLID', pid_solid, mid] bdf_model.add_card(card, 'PSOLID', is_list=True) card = ['MAT1', mid, 3.0e7, None, 0.3] bdf_model.add_card(card, 'MAT1', is_list=True) shells = [ ('CQUAD4', ugrid_model.quads), ('CTRIA3', ugrid_model.tris), ] for card_type, card_nodes in shells: if card_nodes.shape[0]: for pid, nodes in zip(ugrid_model.pids, card_nodes + nid_offset): if pid not in pshell_pids_to_remove: card = [ card_type, eid, pid, ] + list(nodes) bdf_model.add_card(card, card_type, is_list=True) eid += 1 solids = [ ('CTETRA', ugrid_model.tets), ('CPYRAM', ugrid_model.penta5s), ('CPENTA', ugrid_model.penta6s), ('CHEXA', ugrid_model.hexas), ] for card_type, card_nodes in solids: if card_nodes.shape[0]: for nodes in card_nodes + nid_offset: card = [ card_type, eid, pid_solid, ] + list(nodes) bdf_model.add_card(card, card_type, is_list=True) eid += 1 # tol = min_edge_length / 2.0 # TODO: remove this... bdf_model.write_bdf('model_join.bdf', interspersed=False) bdf_model.cross_reference() bdf_equivalence_nodes(bdf_model, bdf_equivalence_filename, tol, renumber_nodes=False, neq_max=10, xref=False) if renumber: starting_ids_dict = { 'cid': 1, 'nid': 1, 'eid': 1, 'pid': 1, 'mid': 1, } bdf_renumber(bdf_equivalence_filename, bdf_renumber_filename, size=16, is_double=False, starting_id_dict=starting_ids_dict) #os.remove(bdf_equivalence_filename) out_bdf_filename = bdf_renumber_filename else: out_bdf_filename = bdf_equivalence_filename #os.remove(bdf_merged_filename) #os.remove(bdf_renumber_filename) return out_bdf_filename
def main(): # pragma: no cover """docopt interface""" encoding = sys.getdefaultencoding() import pyNastran from docopt import docopt msg = "Usage:\n" msg += " extract_free_faces [-d] [-f] [--encoding ENCODE] BDF_FILENAME SKIN_FILENAME\n" msg += " extract_free_faces [-l] [-f] [--encoding ENCODE] BDF_FILENAME SKIN_FILENAME\n" msg += ' extract_free_faces -h | --help\n' msg += ' extract_free_faces -v | --version\n' msg += '\n' msg += "Positional Arguments:\n" msg += " BDF_FILENAME path to input BDF/DAT/NAS file\n" msg += " SKIN_FILENAME path to output BDF/DAT/NAS file\n" msg += '\n' msg += 'Options:\n' msg += ' -l, --large writes the BDF in large field, single precision format (default=False)\n' msg += ' -d, --double writes the BDF in large field, double precision format (default=False)\n' msg += ' --encoding ENCODE the encoding method (default=None -> %r)\n' % encoding msg += "\n" msg += "Developer:\n" msg += ' -f, --profile Profiles the code (default=False)\n' msg += "\n" msg += "Info:\n" msg += ' -h, --help show this help message and exit\n' msg += " -v, --version show program's version number and exit\n" if len(sys.argv) == 1: sys.exit(msg) ver = str(pyNastran.__version__) data = docopt(msg, version=ver) #data['--xref'] = not data['--xref'] if not data['--encoding']: data['--encoding'] = None for key, value in sorted(iteritems(data)): print("%-12s = %r" % (key.strip('--'), value)) import time time0 = time.time() #is_double = False if data['--double']: size = 16 #is_double = True elif data['--large']: size = 16 else: size = 8 bdf_filename = data['BDF_FILENAME'] skin_filename = data['SKIN_FILENAME'] from pyNastran.bdf.mesh_utils.bdf_equivalence import bdf_equivalence_nodes tol = 1e-005 bdf_filename_merged = 'merged.bdf' bdf_equivalence_nodes(bdf_filename, bdf_filename_merged, tol, renumber_nodes=False, neq_max=10, xref=True, node_set=None, size=8, is_double=False, remove_collapsed_elements=False, avoid_collapsed_elements=False, crash_on_collapse=False, debug=True) print('done with equivalencing') write_skin_solid_faces( bdf_filename_merged, skin_filename, write_solids=False, write_shells=True, size=size, is_double=False, encoding=None, ) print("total time: %.2f sec" % (time.time() - time0))
def main(): """docopt interface""" encoding = sys.getdefaultencoding() import pyNastran from docopt import docopt msg = "Usage:\n" msg += " extract_free_faces [-d] [-f] [--encoding ENCODE] BDF_FILENAME SKIN_FILENAME\n" msg += " extract_free_faces [-l] [-f] [--encoding ENCODE] BDF_FILENAME SKIN_FILENAME\n" msg += " extract_free_faces -h | --help\n" msg += " extract_free_faces -v | --version\n" msg += "\n" msg += "Positional Arguments:\n" msg += " BDF_FILENAME path to input BDF/DAT/NAS file\n" msg += " SKIN_FILENAME path to output BDF/DAT/NAS file\n" msg += "\n" msg += "Options:\n" msg += " -l, --large writes the BDF in large field, single precision format (default=False)\n" msg += " -d, --double writes the BDF in large field, double precision format (default=False)\n" msg += " --encoding ENCODE the encoding method (default=None -> %r)\n" % encoding msg += "\n" msg += "Developer:\n" msg += " -f, --profile Profiles the code (default=False)\n" msg += "\n" msg += "Info:\n" msg += " -h, --help show this help message and exit\n" msg += " -v, --version show program's version number and exit\n" if len(sys.argv) == 1: sys.exit(msg) ver = str(pyNastran.__version__) data = docopt(msg, version=ver) # data['--xref'] = not data['--xref'] if not data["--encoding"]: data["--encoding"] = None for key, value in sorted(iteritems(data)): print("%-12s = %r" % (key.strip("--"), value)) import time time0 = time.time() # is_double = False if data["--double"]: size = 16 # is_double = True elif data["--large"]: size = 16 else: size = 8 bdf_filename = data["BDF_FILENAME"] skin_filename = data["SKIN_FILENAME"] from pyNastran.bdf.mesh_utils.bdf_equivalence import bdf_equivalence_nodes tol = 1e-005 bdf_filename_merged = "merged.bdf" bdf_equivalence_nodes( bdf_filename, bdf_filename_merged, tol, renumber_nodes=False, neq_max=10, xref=True, node_set=None, size=8, is_double=False, remove_collapsed_elements=False, avoid_collapsed_elements=False, crash_on_collapse=False, debug=True, ) print("done with equivalencing") write_skin_solid_faces( bdf_filename_merged, skin_filename, write_solids=False, write_shells=True, size=size, is_double=False, encoding=None, ) print("total time: %.2f sec" % (time.time() - time0))
def cmd_line_free_faces(argv=None, quiet=False): """command line interface to bdf free_faces""" if argv is None: argv = sys.argv encoding = sys.getdefaultencoding() import pyNastran usage = ( 'Usage:\n' ' bdf free_faces BDF_FILENAME SKIN_FILENAME [-d] [-l] [-f] [--encoding ENCODE]\n' ' bdf free_faces -h | --help\n' ' bdf free_faces -v | --version\n' '\n') arg_msg = ( "Positional Arguments:\n" " BDF_FILENAME path to input BDF/DAT/NAS file\n" " SKIN_FILENAME path to output BDF/DAT/NAS file\n" '\n' 'Options:\n' ' -l, --large writes the BDF in large field, single precision format (default=False)\n' ' -d, --double writes the BDF in large field, double precision format (default=False)\n' ' --encoding ENCODE the encoding method (default=None -> %r)\n' '\n' 'Developer:\n' ' -f, --profile Profiles the code (default=False)\n' '\n' "Info:\n" ' -h, --help show this help message and exit\n' " -v, --version show program's version number and exit\n" % encoding) if len(argv) == 1: sys.exit(arg_msg) arg_msg += '\n' examples = ('Examples\n' '--------\n' ' bdf free_faces solid.bdf skin.bdf\n' ' bdf free_faces solid.bdf skin.bdf --large\n') import argparse parent_parser = argparse.ArgumentParser() # positional arguments parent_parser.add_argument('BDF_FILENAME', help='path to input BDF/DAT/NAS file', type=str) parent_parser.add_argument('SKIN_FILENAME', help='path to output BDF/DAT/NAS file', type=str) size_group = parent_parser.add_mutually_exclusive_group() size_group.add_argument( '-d', '--double', help='writes the BDF in large field, single precision format', action='store_true') size_group.add_argument( '-l', '--large', help='writes the BDF in large field, double precision format', action='store_true') size_group.add_argument( '--encoding', help='the encoding method (default=None -> {repr(encoding)})', type=str) parent_parser.add_argument('--profile', help='Profiles the code', action='store_true') parent_parser.add_argument('-v', '--version', action='version', version=pyNastran.__version__) from pyNastran.utils.arg_handling import argparse_to_dict, update_message update_message(parent_parser, usage, arg_msg, examples) print(argv) args = parent_parser.parse_args(args=argv[2:]) data = argparse_to_dict(args) if not quiet: # pragma: no cover for key, value in sorted(data.items()): print("%-12s = %r" % (key.strip('--'), value)) import time time0 = time.time() is_double = False if data['double']: size = 16 is_double = True elif data['large']: size = 16 else: size = 8 bdf_filename = data['BDF_FILENAME'] skin_filename = data['SKIN_FILENAME'] from pyNastran.bdf.mesh_utils.bdf_equivalence import bdf_equivalence_nodes tol = 1e-005 bdf_filename_merged = 'merged.bdf' level = 'debug' if not quiet else 'warning' log = SimpleLogger(level=level, encoding='utf-8', log_func=None) bdf_equivalence_nodes(bdf_filename, bdf_filename_merged, tol, renumber_nodes=False, neq_max=10, xref=True, node_set=None, size=8, is_double=is_double, remove_collapsed_elements=False, avoid_collapsed_elements=False, crash_on_collapse=False, log=log, debug=True) if not quiet: # pragma: no cover print('done with equivalencing') write_skin_solid_faces( bdf_filename_merged, skin_filename, write_solids=False, write_shells=True, size=size, is_double=is_double, encoding=None, log=log, ) if not quiet: # pragma: no cover print("total time: %.2f sec" % (time.time() - time0))
def cmd_line_mirror(): # pragma: no cover """command line interface to write_bdf_symmetric""" import sys from docopt import docopt import pyNastran msg = "Usage:\n" msg += " bdf mirror IN_BDF_FILENAME [-o OUT_BDF_FILENAME] [--plane PLANE] [--tol TOL]\n" msg += ' bdf mirror -h | --help\n' msg += ' bdf mirror -v | --version\n' msg += '\n' msg += "Positional Arguments:\n" msg += " IN_BDF_FILENAME path to input BDF/DAT/NAS file\n" #msg += " OUT_BDF_FILENAME path to output BDF/DAT/NAS file\n" msg += '\n' msg += 'Options:\n' msg += " -o OUT, --output OUT_BDF_FILENAME path to output BDF/DAT/NAS file\n\n" msg += " --plane PLANE the symmetry plane (xz, ???)\n\n" msg += " --tol TOL the spherical equivalence tolerance (default=0.000001)\n\n" msg += 'Info:\n' msg += ' -h, --help show this help message and exit\n' msg += " -v, --version show program's version number and exit\n" if len(sys.argv) == 1: sys.exit(msg) ver = str(pyNastran.__version__) #type_defaults = { # '--nerrors' : [int, 100], #} data = docopt(msg, version=ver) if data['--tol'] is None: data['--tol'] = 0.000001 print(data) size = 16 bdf_filename = data['IN_BDF_FILENAME'] bdf_filename_out = data['--output'] if bdf_filename_out is None: bdf_filename_out = 'mirrored.bdf' from pyNastran.bdf.bdf import read_bdf from pyNastran.bdf.mesh_utils.bdf_equivalence import bdf_equivalence_nodes model = read_bdf(bdf_filename) size = 16 bdf_filename_temp = '__temp.bdf__' model.write_bdf_symmetric(bdf_filename_temp, encoding=None, size=size, is_double=False, enddata=None, close=True, plane='xz') tol = 0.000001 bdf_equivalence_nodes(bdf_filename_temp, bdf_filename_out, tol, renumber_nodes=False, neq_max=10, xref=True, node_set=None, size=size, is_double=False, remove_collapsed_elements=False, avoid_collapsed_elements=False, crash_on_collapse=False, debug=True) os.remove(bdf_filename_temp)
def test_eq2(self): r""" 5 6 *-------* 40 | \ | | \ | | \ | *-------* 3 1 20 """ msg = ( 'CEND\n' 'BEGIN BULK\n' 'GRID,1, , 0., 0., 0.\n' 'GRID,20,, 1., 0., 0.\n' 'GRID,3, , 1.01, 0., 0.\n' 'GRID,40,, 1., 1., 0.\n' 'GRID,5, , 0., 1., 0.\n' 'GRID,6, , 0., 1.01, 0.\n' 'CTRIA3,1, 100,1,20,6\n' 'CTRIA3,10,100,3,40,5\n' 'PSHELL,100,1000,0.1\n' 'MAT1,1000,3.0,, 0.3\n' 'ENDDATA' ) bdf_filename = 'nonunique.bdf' bdf_filename_out = 'unique.bdf' with codec_open(bdf_filename, 'w') as bdf_file: bdf_file.write(msg) tol = 0.2 # Collapse 5/6 and 20/3; Put a 40 and 20 to test non-sequential IDs bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=None, crash_on_collapse=False, debug=False) model = BDF(debug=False) model.read_bdf(bdf_filename_out) msg = 'nnodes=%s\n' % len(model.nodes) for nid, node in sorted(iteritems(model.nodes)): msg += 'nid=%s xyz=%s\n' % (nid, node.xyz) assert len(model.nodes) == 4, msg # os.remove(bdf_filename) os.remove(bdf_filename_out) tol = 0.009 # Don't collapse anything because the tolerance is too small bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=None, crash_on_collapse=False, debug=False) model = BDF(debug=False) model.read_bdf(bdf_filename_out) assert len(model.nodes) == 6, len(model.nodes) os.remove(bdf_filename_out) tol = 0.2 node_set = [2, 3] # Node 2 is not defined, so crash with self.assertRaises(RuntimeError): # node 2 is not defined because it should be node 20 bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=node_set, crash_on_collapse=False, debug=False) tol = 0.2 node_set = [20, 3] # Only collpase 2 nodes bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=node_set, crash_on_collapse=False, debug=False) model = BDF(debug=False) model.read_bdf(bdf_filename_out) assert len(model.nodes) == 5, len(model.nodes) os.remove(bdf_filename_out) tol = 0.2 node_set = set([20, 3]) # Only collpase 2 nodes bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=node_set, crash_on_collapse=False, debug=False) model = BDF(debug=False) model.read_bdf(bdf_filename_out) assert len(model.nodes) == 5, len(model.nodes) os.remove(bdf_filename_out) tol = 0.2 aset = np.array([20, 3, 4], dtype='int32') bset = np.array([20, 3], dtype='int32') node_set = np.intersect1d(aset, bset) assert len(node_set) > 0, node_set # Only collpase 2 nodes bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=node_set, crash_on_collapse=False, debug=False) model = BDF(debug=False) model.read_bdf(bdf_filename_out) assert len(model.nodes) == 5, len(model.nodes) os.remove(bdf_filename_out)
def test_eq3(self): """node_set=None""" lines = [ '$pyNastran: version=msc', '$pyNastran: punch=True', '$pyNastran: encoding=ascii', '$NODES', '$ Nodes to merge:', '$ 5987 10478', '$ GRID 5987 35.46 -6. 0.', '$ GRID 10478 35.46 -6. 0.', '$ 5971 10479', '$ GRID 5971 34.92 -6. 0.', '$ GRID 10479 34.92 -6. 0.', '$ 6003 10477', '$ GRID 6003 36. -6. 0.', '$ GRID 10477 36. -6. 0.', 'GRID 5971 34.92 -6. 0.', 'GRID 5972 34.92-5.73333 0.', 'GRID 5973 34.92-5.46667 0.', 'GRID 5987 35.46 -6. 0.', 'GRID 5988 35.46-5.73333 0.', 'GRID 5989 35.46-5.46667 0.', 'GRID 6003 36. -6. 0.', 'GRID 6004 36.-5.73333 0.', 'GRID 6005 36.-5.46667 0.', 'GRID 10476 36. -6. -1.5', 'GRID 10477 36. -6. 0.', 'GRID 10478 35.46 -6. 0.', 'GRID 10479 34.92 -6. 0.', 'GRID 10561 34.92 -6. -.54', '$ELEMENTS_WITH_PROPERTIES', 'PSHELL 1 1 .1', 'CQUAD4 5471 1 5971 5987 5988 5972', 'CQUAD4 5472 1 5972 5988 5989 5973', 'CQUAD4 5486 1 5987 6003 6004 5988', 'CQUAD4 5487 1 5988 6004 6005 5989', 'PSHELL 11 1 .1', 'CTRIA3 9429 11 10561 10476 10478', 'CTRIA3 9439 11 10478 10479 10561', 'CTRIA3 9466 11 10476 10477 10478', '$MATERIALS', 'MAT1 1 3. .3', ] bdf_filename = 'nonunique2.bdf' bdf_filename_out = 'unique2.bdf' with codec_open(bdf_filename, 'w') as bdf_file: bdf_file.write('\n'.join(lines)) tol = 0.01 bdf_equivalence_nodes(bdf_filename, bdf_filename_out, tol, renumber_nodes=False, neq_max=4, xref=True, node_set=None, crash_on_collapse=False, debug=False) model = BDF(debug=False) model.read_bdf(bdf_filename_out) assert len(model.nodes) == 11, len(model.nodes) os.remove(bdf_filename) os.remove(bdf_filename_out)
def equivalence_ugrid3d_and_bdf_to_bdf(ugrid_filename: str, bdf_filename: str, pshell_pids_to_remove: List[int], tol: float = 0.01, renumber: bool = True, log: Optional[SimpleLogger] = None): """ Merges a UGRID3D (*.ugrid) with a BDF and exports a BDF that is equivalenced and renumbered. Parameters ---------- ugrid_filename : str the AFLR3/UGrid3d filename bdf_filename : str the BDF filename pshell_pids_to_remove : List[int, ...] tol : float; default=0.01 the equivalence tolerance renumber : bool; default=True calls ``bdf_renumber`` to renumber the output BDF model Returns ------- out_bdf_filename : str the output BDF filename """ log = get_logger2(log, debug=True) log.info( f'equivalence_ugrid3d_and_bdf_to_bdf - bdf_filename={bdf_filename}') log.info( f'equivalence_ugrid3d_and_bdf_to_bdf - ugrid_filename={ugrid_filename}' ) check_path(ugrid_filename, 'ugrid_filename') base = os.path.splitext(bdf_filename)[0] #bdf_merged_filename = base + '_merged.bdf' bdf_equivalence_filename = base + '_equivalence.bdf' bdf_renumber_filename = base + '_renumber.bdf' update_merge = True if update_merge: bdf_model = _update_merge(ugrid_filename, bdf_filename, pshell_pids_to_remove, tol=tol, log=log) bdf_equivalence_nodes(bdf_model, bdf_equivalence_filename, tol, renumber_nodes=False, neq_max=10, xref=False, log=log) if renumber: starting_ids_dict = { 'cid': 1, 'nid': 1, 'eid': 1, 'pid': 1, 'mid': 1, } bdf_renumber(bdf_equivalence_filename, bdf_renumber_filename, size=16, is_double=False, starting_id_dict=starting_ids_dict, log=log) #os.remove(bdf_equivalence_filename) out_bdf_filename = bdf_renumber_filename else: out_bdf_filename = bdf_equivalence_filename #os.remove(bdf_merged_filename) #os.remove(bdf_renumber_filename) os.remove('model_join.bdf') return out_bdf_filename
def clear_out_solids(bdf_filename, bdf_filename_out=None, equivalence=True, renumber=True, equivalence_tol=0.01): """removes solid elements""" if bdf_filename_out is None: if renumber or equivalence: msg = ('bdf_filename_out=%s must be specified if renumber=%s ' 'or equivalence=%s are True' % (bdf_filename_out, renumber, equivalence)) raise RuntimeError(msg) print('clearing out solids from %s' % bdf_filename) model = read_bdf(bdf_filename, xref=False) #nodes2 = {nid, node for nid, node in iteritems(model.nodes)} #elements2 = {eid, element for eid, element in iteritems(model.elements) #if element.type in ['CTRIA3', 'CQUAD4']} out_dict = model.get_card_ids_by_card_types( card_types=['CTRIA3', 'CQUAD4']) save_eids = set(out_dict['CTRIA3'] + out_dict['CQUAD4']) all_eids = set(model.element_ids) print('all_eids =', all_eids) print('save_eids =', save_eids) remove_eids = all_eids - save_eids print('remove_eids =', remove_eids) for eid in remove_eids: print('eid =', eid) del model.elements[eid] # TODO: seems like we could be more efficient... #nids = unique(hstack([model.elements[eid].node_ids for eid in save_eids])) nids = set([]) elements2 = {} print(model.elements) for eid, element in iteritems(model.elements): #if element.type not in ['CTRIA3', 'CQUAD4']: #continue #elements2[eid] = element nids.update(element.node_ids) nids = list(nids) nids.sort() #print('nids = ', nids) #print('eids = ', eids) nodes2 = {nid: node for nid, node in iteritems(model.nodes) if nid in nids} properties2 = { pid: prop for pid, prop in iteritems(model.properties) if prop.type == 'PSHELL' } model.nodes = nodes2 #model.elements = elements2 model.properties = properties2 # already equivalenced? #remove_unassociated_nodes(bdf_filename, bdf_filename_out, renumber=False) #bdf_filename_out = 'equivalence.bdf' starting_id_dict = { 'cid': 1, 'nid': 1, 'eid': 1, 'pid': 1, 'mid': 1, } if equivalence: if renumber: bdf_equivalenced_filename = 'equivalence.bdf' else: bdf_equivalenced_filename = bdf_filename_out model.write_bdf('remove_unused_nodes.bdf') bdf_equivalence_nodes(model, bdf_equivalenced_filename, equivalence_tol, renumber_nodes=False, neq_max=4, xref=True) if renumber: bdf_renumber(bdf_equivalenced_filename, bdf_filename_out, size=8, is_double=False, starting_id_dict=starting_id_dict) elif renumber: bdf_renumber(model, bdf_filename_out, size=8, is_double=False, starting_id_dict=starting_id_dict) return model
def cmd_line_mirror(argv=None, quiet=False): """command line interface to write_bdf_symmetric""" if argv is None: argv = sys.argv from docopt import docopt import pyNastran msg = ( "Usage:\n" " bdf mirror IN_BDF_FILENAME [-o OUT_BDF_FILENAME] [--plane PLANE] [--tol TOL]\n" " bdf mirror IN_BDF_FILENAME [-o OUT_BDF_FILENAME] [--plane PLANE] [--noeq]\n" ' bdf mirror -h | --help\n' ' bdf mirror -v | --version\n' '\n' "Positional Arguments:\n" " IN_BDF_FILENAME path to input BDF/DAT/NAS file\n" #" OUT_BDF_FILENAME path to output BDF/DAT/NAS file\n" '\n' 'Options:\n' " -o OUT, --output OUT_BDF_FILENAME path to output BDF/DAT/NAS file\n" " --plane PLANE the symmetry plane (xz, yz, xy); default=xz\n" ' --tol TOL the spherical equivalence tolerance; default=1e-6\n' ' --noeq disable equivalencing\n' "\n" # (default=0.000001) 'Info:\n' ' -h, --help show this help message and exit\n' " -v, --version show program's version number and exit\n") if len(argv) == 1: sys.exit(msg) ver = str(pyNastran.__version__) #type_defaults = { # '--nerrors' : [int, 100], #} data = docopt(msg, version=ver, argv=argv[1:]) if data['--tol'] is None: data['TOL'] = 0.000001 if isinstance(data['TOL'], str): data['TOL'] = float(data['TOL']) tol = data['TOL'] assert data['--noeq'] in [True, False] if data['--noeq']: tol = -1. plane = 'xz' if data['--plane'] is not None: # None or str plane = data['--plane'] if not quiet: # pragma: no cover print(data) size = 16 bdf_filename = data['IN_BDF_FILENAME'] bdf_filename_out = data['--output'] if bdf_filename_out is None: bdf_filename_out = 'mirrored.bdf' #from io import StringIO from pyNastran.bdf.bdf import read_bdf from pyNastran.bdf.mesh_utils.bdf_equivalence import bdf_equivalence_nodes level = 'debug' if not quiet else 'warning' log = SimpleLogger(level=level, encoding='utf-8', log_func=None) model = read_bdf(bdf_filename, log=log) bdf_filename_stringio = StringIO() write_bdf_symmetric(model, bdf_filename_stringio, encoding=None, size=size, is_double=False, enddata=None, close=False, plane=plane, log=log) bdf_filename_stringio.seek(0) if tol >= 0.0: bdf_equivalence_nodes(bdf_filename_stringio, bdf_filename_out, tol, renumber_nodes=False, neq_max=10, xref=True, node_set=None, size=size, is_double=False, remove_collapsed_elements=False, avoid_collapsed_elements=False, crash_on_collapse=False, debug=True, log=log) else: model.log.info('writing mirrored model %s without equivalencing' % bdf_filename_out) with open(bdf_filename_out, 'w') as bdf_file: bdf_file.write(bdf_filename_stringio.getvalue())