Source code for pyNastran.bdf.mesh_utils.extract_bodies
"""
defines:
- extract_bodies(bdf_filename)
"""
from __future__ import print_function
from collections import defaultdict
from six import iterkeys
import numpy as np
from pyNastran.bdf.bdf import BDF, read_bdf, print_card_16
[docs]def extract_bodies(bdf_filename, mpc_id=0):
"""
Finds the isolated bodies
Parameters
----------
bdf_filename : str/BDF
str : the path the the *.bdf file
BDF : a BDF() boject
mpc_id : int; default=0
0 : consider all MPCs
>0 : use this MPC set
not supported
Considers:
- elements
- rigid_elements
Doesn't consider:
- elements_mass
- MPC
- MPCADD
- DMIx
Doesn't support:
- xref
- duplicate element ids
- large values
"""
if isinstance(bdf_filename, BDF):
model = bdf_filename
else:
model = read_bdf(bdf_filename, xref=False)
debug = False
nnodes = len(model.nodes)
nspoints = 0
nepoints = 0
if model.spoints:
nspoints = len(model.spoints)
if model.epoints:
nepoints = len(model.epoints)
npoints = nnodes + nspoints + nepoints
nelements = len(model.elements) + len(model.rigid_elements) + len(model.masses)
if npoints == 0 or nelements == 0:
return {}
nid_to_eid_map = defaultdict(list)
eid_to_nid_map = defaultdict(list)
for eid, elem in model.elements.items():
if debug: # pragma: no cover
print(print_card_16(elem.repr_fields()))
node_ids = elem.node_ids
eid_to_nid_map[eid] = node_ids
for nid in node_ids:
if nid is None:
continue
nid_to_eid_map[nid].append(eid)
rigid_offset = 0
if len(model.elements):
rigid_offset = max(model.elements)
for eid, elem in model.rigid_elements.items():
if debug: # pragma: no cover
print(print_card_16(elem.repr_fields()))
eid += rigid_offset
assert eid not in model.elements, 'eid=%s cannot be used twice' % eid
#node_ids = elem.node_ids
node_ids = elem.independent_nodes + elem.dependent_nodes
eid_to_nid_map[eid] = node_ids
for nid in node_ids:
if nid is None:
raise RuntimeError(elem)
nid_to_eid_map[nid].append(eid)
#mpc_offset = rigid_offset + max(model.rigid_elements)
if len(nid_to_eid_map) == 0:
raise RuntimeError(model.get_bdf_stats())
#return {}
nids_used = set()
eids_used = set()
ibody = 0
all_nids_to_check = set(list(nid_to_eid_map.keys()))
nids_to_check = set([next(iterkeys(nid_to_eid_map))])
if debug: # pragma: no cover
print('all_nids_to_check= ', all_nids_to_check)
body_eids = {ibody : set()}
nbodies_max = 3
while all_nids_to_check:
if debug: # pragma: no cover
print(all_nids_to_check)
while nids_to_check:
#if len(nids_to_check) < 10:
#print('nids_to_check =', nids_to_check)
nid = nids_to_check.pop()
if debug: # pragma: no cover
print('nid = ', nid)
print('all_nids_to_check =', all_nids_to_check)
if nid not in all_nids_to_check:
msg = 'nids_to_check = %s' % nids_to_check
raise RuntimeError(msg)
if debug: # pragma: no cover
print('nids_used =', nids_used)
print('all_nids_to_check =', all_nids_to_check)
nids_used.add(nid)
if debug: # pragma: no cover
print(' adding nid=%s' % nid)
all_nids_to_check.remove(nid)
if debug: # pragma: no cover
print(' nids_used =', nids_used)
print(' all_nids_to_check =', all_nids_to_check)
eids = nid_to_eid_map[nid]
if debug: # pragma: no cover
print(' eids = %s' % eids)
for eidi in eids:
if eidi in eids_used:
continue
eids_used.add(eidi)
try:
elem = model.elements[eidi]
except KeyError:
elem = model.rigid_elements[eidi - rigid_offset]
if debug: # pragma: no cover
print(print_card_16(elem.repr_fields()))
print('adding eidi=%s' % eidi)
body_eids[ibody].add(eidi)
nidsi = eid_to_nid_map[eidi]
for nidi in nidsi:
if nidi not in nids_used:
nids_to_check.add(nidi)
if debug: # pragma: no cover
print(' adding nid=%s' % nidi)
del nidsi # , elem
if debug: # pragma: no cover
print('next eid\n')
print('---------------------------')
del nid, eids
if len(body_eids[ibody]) == 0:
return body_eids
# unused node
#try:
#nid = nids_to_check.pop()
#except KeyError:
#break
#continue
#msg = 'cannot find a new body...nbodies=%s\nelements:' % ibody
#for nid, eids in sorted(nid_to_eid_map.items()):
#msg += ' nid=%r eids=%s\n' % (nid, eids)
#for eid in eids:
#try:
#elem = model.elements[eid]
#except KeyError:
#elem = model.rigid_elements[eid - rigid_offset]
#msg += print_card_16(elem.repr_fields())
#msg += 'eid=%s used=%s\n\n' % (eid, eid in eids_used)
#msg += '----------------\n'
#msg += ''
#raise RuntimeError(msg + model.get_bdf_stats())
ibody += 1
if ibody > nbodies_max:
raise RuntimeError('Too many bodies...\n' + model.get_bdf_stats())
body_eids[ibody] = set()
#print('--------------------------------------')
if len(body_eids[ibody]) == 0:
del body_eids[ibody]
body_eids2 = {}
for ibody, body in sorted(body_eids.items()):
abody = np.unique(np.array(list(body), dtype='int64'))
ielem = np.where(abody <= rigid_offset)
irigid = np.where(abody > rigid_offset)
#ielem = np.asarray(ielem, dtype='int32')
#ielem = np.asarray(ielem, dtype='int32')
body_eids2[ibody] = [
np.asarray(abody[ielem], dtype='int32'),
np.asarray(abody[irigid], dtype='int32')
]
#print('body_eids = %s' % body_eids2)
nbodies = len(body_eids2)
if nbodies > 1:
print('nbodies = %i' % nbodies)
return body_eids2