Source code for pyNastran.bdf.mesh_utils.remove_unused

"""
defines some methods for cleaning up a model
 - model = remove_unused(bdf_filename, remove_nids=True, remove_cids=True,
                         remove_pids=True, remove_mids=True)

"""
import numpy as np
from pyNastran.bdf.bdf import BDF, read_bdf
#from pyNastran.bdf.mesh_utils.bdf_renumber import bdf_renumber

[docs] def remove_unused(bdf_filename: str, remove_nids: bool=True, remove_cids: bool=True, remove_pids: bool=True, remove_mids: bool=True, remove_spcs: bool=True, remove_mpcs: bool=True, remove_optimization: bool=True, reset_type_to_id_map: bool=False) -> BDF: """ Takes an uncross-referenced bdf and removes unused data removes unused: - nodes - properties - materials - coords - spcs - mpcs cannot be removed: - loads """ if isinstance(bdf_filename, BDF): model = bdf_filename else: model = read_bdf(bdf_filename, xref=False) #nids = model.nodes.keys() #cids = #nids = set(list(model.nodes.keys())) #cids = set(list(model.coords.keys())) #pids = set(list(model.properties.keys())) nids_used = set() cids_used = set() eids_used = set() pids_used = set() pids_mass_used = set() mids_used = set() mids_thermal_used = set() sets_used = set() desvars_used = set() dresps_used = set([]) mpcs_used = set() spcs_used = set() #nsms_used = set() aecomps_used = set() #card_types = list(model.card_count.keys()) #card_map = model.get_card_ids_by_card_types( #card_types=card_types, #reset_type_to_slot_map=False, #stop_on_missing_card=True) #for nid, node in model.nodes.items(): #cids_used.update([node.Cp(), node.Cd()]) unreferenced_types_quiet = { 'ENDDATA', 'PARAM', 'PAERO1', 'PAERO2', #'PAERO3', 'PAERO5', } unreferenced_types_case_control = { 'EIGR', 'EIGRL', 'EIGB', 'EIGP', 'EIGC', 'FREQ', 'FREQ1', 'FREQ2', 'TSTEP', 'TSTEPNL', 'NLPCI', 'NLPARM', # aero 'TRIM', 'TRIM2', 'DIVERG', 'GUST', 'FLUTTER', } # ureferenced types aren't referenced by any card # (but may be referenced by the case control deck) unreferenced_types = { 'SPOINT', 'EPOINT', 'DESVAR', 'ROTORG', 'ROTORD', 'DAREA', 'DEQATN', 'DMIG', 'DMI', 'DMIJ', 'DMIK', 'DMIJI', 'DMIAX', 'POINT', 'EPOINT', 'DELAY', 'DPHASE', 'CBARAO', 'AEPARM', # properties 'PELAS', 'PDAMP', 'PBUSH', 'PELAST', 'PDAMPT', 'PBUSHT', 'PGAP', 'PBUSH1D', 'PFAST', 'PVISC', 'PMASS', 'FLFACT', 'DLINK', 'DDVAL', 'AELINK', 'AELIST', 'AEFACT', 'AESTAT', # contact 'BCTPARA', 'BCRPARA', 'BSURF', 'BSURFS', 'BCTADD', 'BCTSET', 'BFRIC', 'TABRNDG', 'DTI', 'TABLEH1', } # this are things that haven't been referenced yet not_implemented_types = { # not checked------------------------------------------ 'PHBDY', 'CHBDYG', 'CHBDYP', 'CHBDYE', 'RADBC', # 'CONV', 'QVOL', 'PCONVM', # 'PCONV', #'PBCOMP', 'PDAMP5', 'CFAST', 'AECOMP', 'CAERO2', 'CAERO3', 'CAERO4', 'CAERO5', 'PAERO2', 'PAERO3', 'PAERO4', 'PAERO5', 'DCONADD', #'GMCORD', 'MONPNT1', 'MONPNT2', 'MONPNT3', 'DSCREEN', 'DTI', 'NSMADD', 'AESURFS', 'CSSCHD', 'CGEN', 'NXSTRAT', # axisymmetric 'FORCEAX', # acoustic 'PACABS', 'PMIC', 'MATPOR', 'AMLREG', 'CAABSF', 'MICPNT', # superelements 'SELOC', 'SEEXCLD', 'SENQSET', # parametric 'FEEDGE', 'FEFACE', # contact 'BGSET', # nx bolts 'BOLT', 'BOLTFOR', 'BOLTLD', 'BOLTSEQ', 'BOLTFRC', } set_types_simple = [ 'SET1', # handled elsewhere (e.g,. by SPLINEx) 'SET3', ] set_types = { 'ASET', 'ASET1', 'BSET', 'BSET1', 'CSET', 'CSET1', 'QSET', 'QSET1', 'USET', 'USET1', 'OMIT', 'OMIT1', } #seset_types = { #'SESET', #} load_types = { 'GRAV', 'RANDPS', 'FORCE', 'FORCE1', 'FORCE2', 'MOMENT', 'MOMENT1', 'MOMENT2', 'PLOAD', 'PLOAD1', 'PLOAD2', 'PLOAD4', 'SPCD', 'RFORCE', 'RFORCE1', 'TEMP', 'QBDY1', 'QBDY2', 'QBDY3', 'QHBDY', 'ACCEL', 'PLOADX1', 'SLOAD', 'ACCEL1', 'LOADCYN', 'LOAD', 'CLOAD', 'LSEQ', 'DLOAD', 'QVECT', 'RADM', 'TEMPAX', 'DEFORM', # msgmesh #'GMLOAD', } masses = {'CONM1', 'CONM2', 'CMASS1', 'CMASS2', 'CMASS3', 'CMASS4'} elements = { 'CELAS1', 'CELAS2', 'CELAS3', 'CELAS4', 'CDAMP1', 'CDAMP2', 'CDAMP3', 'CDAMP4', 'CDAMP5', 'CGAP', 'CBUSH', 'CBUSH1D', 'CBUSH2D', 'CFAST', 'CVISC', 'CSHEAR', 'CTUBE', 'GENEL', 'CTRIA3', 'CQUAD4', 'CTRIA6', 'CTRIAR', 'CQUAD8', 'CQUADR', 'CTRIAX', 'CQUADX', 'CQUAD', 'CPLSTN3', 'CPLSTN4', 'CPLSTN6', 'CPLSTN8', 'CPLSTS3', 'CPLSTS4', 'CPLSTS6', 'CPLSTS8', 'CQUADX4', 'CQUADX8', 'CTRIAX6', 'CTRAX3', 'CTRAX6', 'CTRIAX6', 'CTETRA', 'CHEXA', 'CPENTA', 'CPYRAM', 'CROD', 'CRAC2D', 'CRAC3D', 'CONROD', 'CCONEAX', 'CBAR', 'CBEAM', 'CBEND', 'CBEAM3', # acoustic 'CHACAB', } dvprel_properties = { 'PELAS', 'PELAST', 'PDAMP', 'PVISC', 'PGAP', 'PBUSH', 'PBUSH1D', 'PBUSHT', 'PROD', 'PTUBE', 'PBAR', 'PBARL', 'PBEAM', 'PBEAML', 'PSHEAR', 'PSHELL', 'PCOMP', 'PCOMPG', 'PMASS', } tableht_used = set([]) tableh1_used = set([]) pconv_used = set([]) friction_ids_used = set([]) spline_set_nodes = set([]) log = model.log for key, subcase in model.subcases.items(): #print(key) #print(subcase) if 'SPC' in subcase: spc_id, options = subcase['SPC'] spcs_used.add(spc_id) if 'MPC' in subcase: mpc_id, options = subcase['MPC'] mpcs_used.add(mpc_id) if 'DESSUB' in subcase: dconstr_id, options = subcase['DESSUB'] #dconstrs_used.add(dconstr_id) if 'DESOBJ' in subcase: dresp_id, options = subcase['DESOBJ'] dresps_used.add(dresp_id) #log.info(f'found DESOBJ={dresp_id}') # could remove some if we look at the rid_trace #for cid, coord in model.coords.items(): #if coord.type in ['CORD1R', 'CORD1C', 'CORD1S']: #nids_used.update(node_ids) #elif coord.type in ['CORD1R', 'CORD1C', 'CORD1S']: #cids_used.update(coord.Rid()) #else: #raise NotImplementedError(coord) for card_type, ids in model._type_to_id_map.items(): #print(card_type, ids) #for card_type, ids in card_map.items(): if card_type in ['CORD1R', 'CORD1C', 'CORD1S']: for cid in ids: coord = model.coords[cid] nids_used.update(coord.node_ids) elif card_type in ['CORD2R', 'CORD2C', 'CORD2S']: for cid in ids: coord = model.coords[cid] cids_used.add(coord.Rid()) elif card_type in ['MAT1', 'MAT2', 'MAT3', 'MAT4', 'MAT5', 'MAT8', 'MAT9', 'MAT10', 'MAT11']: # todo: MATS1, MATT1, etc. pass elif card_type in ['MATS1', 'MATT1', 'MATT2', 'MATT3', 'MATT4', 'MATT5', 'MATT8', 'MATT9', 'MATHE', 'MATHP', 'CREEP']: mids_used.update(ids) elif card_type in masses: _store_masses(card_type, model, ids, nids_used, pids_mass_used, cids_used) elif card_type in elements: _store_elements(card_type, model, ids, nids_used, pids_used, mids_used, cids_used) elif card_type == 'PLPLANE': for pid in ids: prop = model.properties[pid] cids_used.add(prop.cid) mids_used.add(prop.Mid()) elif card_type == 'PPLANE': for pid in ids: prop = model.properties[pid] mids_used.add(prop.Mid()) elif card_type == 'PLOTEL': for eid in ids: elem = model.plotels[eid] nids_used.update(elem.node_ids) elif card_type in ['PSOLID', 'PLSOLID', 'PIHEX']: for pid in ids: prop = model.properties[pid] mids_used.add(prop.Mid()) elif card_type == 'PDAMP5': for pid in ids: prop = model.properties[pid] mids_thermal_used.add(prop.Mid()) elif card_type in ['PBAR', 'PBARL', 'PROD', 'PTUBE', 'PBEAM', 'PBEAML', 'PBEAM3', 'PSHEAR', 'PRAC2D', 'PRAC3D', 'PBEND']: for pid in ids: prop = model.properties[pid] mids_used.add(prop.Mid()) elif card_type == 'PSHELL': for pid in ids: prop = model.properties[pid] mids = [mid for mid in prop.material_ids if mid is not None] mids_used.update(mids) elif card_type in ['PCOMP', 'PCOMPG']: for pid in ids: prop = model.properties[pid] mids = prop.material_ids mids_used.update(mids) elif card_type in ['PBCOMP']: for pid in ids: prop = model.properties[pid] mids = prop.Mids() mids_used.add(prop.Mid()) mids_used.update(mids) elif card_type in ['PCOMPS', 'PCOMPLS']: for pid in ids: prop = model.properties[pid] mids = prop.Mids() mids_used.update(mids) cids_used.add(prop.cordm) elif card_type == 'PCONEAX': for pid in ids: # MID1 T1 MID2 I MID3 T2 NSM prop = model.properties[pid] #print(prop.object_methods()) mids = [mid for mid in prop.Mids() if mid not in (0, None)] prop = model.properties[pid] mids_used.update(mids) elif card_type in ['RBAR', 'RBAR1', 'RBE1', 'RBE2', 'RBE3', 'RROD', 'RSPLINE', 'RSSCON']: for eid in ids: elem = model.rigid_elements[eid] #print(elem.object_attributes()) #print(elem.object_methods()) nids_used.update(elem.independent_nodes) nids_used.update(elem.dependent_nodes) elif card_type in ['TLOAD1', 'TLOAD2', 'RLOAD1', 'RLOAD2', 'ACSRCE']: pass elif card_type in load_types: _store_loads(model, card_type, ids, nids_used, eids_used, cids_used) elif card_type == 'TEMPD': pass #for temp_id in ids: #tempd = self.tempds[temp_id] elif card_type == 'MPCADD': for mpcadds in model.mpcadds.values(): for mpcadd in mpcadds: mpcs_used.update(mpcadd.mpc_ids) elif card_type == 'MPC': for mpcs in model.mpcs.values(): for mpc in mpcs: nids_used.update(mpc.node_ids) elif card_type == 'SPCADD': for spcadds in model.spcadds.values(): for spcadd in spcadds: spcs_used.update(spcadd.spc_ids) elif card_type in ['SPC1', 'SPC', 'GMSPC', 'SPCAX']: for spcs in model.spcs.values(): for spc in spcs: if spc.type in ['GMSPC', 'SPCAX']: pass elif spc.type in ['SPC1', 'SPC']: nids_used.update(spc.node_ids) else: raise NotImplementedError(spc) elif card_type in {'TABLED1', 'TABLED2', 'TABLED3', 'TABLED4', 'TABLEM1', 'TABLEM2', 'TABLEM3', 'TABLEM4', 'TABDMP1', 'TABRND1', 'TABLES1',}: pass elif card_type == 'SUPORT': for suport in model.suport: nids_used.update(suport.node_ids) elif card_type == 'SUPORT1': for suport1 in model.suport1.values(): nids_used.update(suport1.node_ids) elif card_type == 'TIC': for tic in model.tics.values(): nids_used.update(tic.node_ids) elif card_type == 'GRID': for unused_nid, node in model.nodes.items(): cids_used.update([node.Cp(), node.Cd()]) elif card_type in ['PBUSH']: pass #for pid in ids: #prop = model.properties[pid] #raise RuntimeError(prop) elif card_type == 'PBUSHT': # tables pass elif card_type == 'AESURF': #CID1 | ALID1 | CID2 | ALID2 for aesurf in model.aesurf.values(): cids_used.add(aesurf.Cid1()) cid2 = aesurf.Cid2() if cid2 is not None: cids_used.add(cid2) elif card_type in {'SPLINE1', 'SPLINE2', 'SPLINE3', 'SPLINE4', 'SPLINE5'}: _store_splines(model, card_type, ids, nids_used, sets_used, spline_set_nodes) elif card_type == 'CAERO1': for eid in ids: caero = model.caeros[eid] # PID, LSPAN, LCHORD cids_used.add(caero.Cp()) elif card_type in set_types_simple: # handled based on context in other blocks pass elif card_type in unreferenced_types_quiet: pass elif card_type in unreferenced_types_case_control: log.debug(f'{card_type} (case control) is unreferenced') elif card_type in unreferenced_types: log.debug(f'{card_type} is unreferenced') elif card_type in {'USET', 'USET1'}: for set_cards in model.usets.values(): for set_card in set_cards: nids_used.update(set_card.ids) elif card_type in set_types: obj = card_type[:4].lower() + 's' sets = getattr(model, obj) # list of SETs for set_card in sets: nids_used.update(set_card.ids) elif card_type == 'SESET': sets = model.se_sets # list of SETs for unused_id, set_card in sorted(sets.items()): nids_used.update(set_card.ids) elif card_type == 'DCONSTR': for dconstr_id, dconstrs in model.dconstrs.items(): for dconstr in dconstrs: if dconstr.type == 'DCONADD': log.error(f'skipping DCONADD, which is referenced by a DCONSTR?\n{dconstr}') continue dresps_used.add(dconstr.dresp_id) elif card_type == 'DRESP1': _store_dresp1(model, ids, nids_used, pids_used, dresps_used) elif card_type == 'DRESP2': for dresp_id in ids: dresp = model.dresps[dresp_id] for idi_type, values in dresp.params.items(): idi, dresp_type = idi_type if dresp_type in {'DRESP1', 'DRESP2'}: #params : {(0, 'DRESP1'): [3000, 3001, 3002]} log.debug(f'DRESP2={dresp_id}: {dresp_type}={values}') dresps_used.update(values) elif dresp_type == 'DESVAR': desvars_used.update(values) elif dresp_type == 'DTABLE': pass elif dresp_type == 'DNODE': log.warning(f'DRESP2={dresp_id}: skipping DNODE') else: print(dresp.get_stats()) raise NotImplementedError(dresp_type) #dresp.deqatn #if dresp.property_type in ['PSHELL', 'PCOMP', 'PBAR', 'PBARL', 'PBEAM', 'PROD']: #pids_used.update(dresp.atti_values()) #elif dresp.property_type is None: #if dresp.response_type in ['WEIGHT', 'EIGN', 'VOLUME']: #pass #elif dresp.response_type in ['DISP']: #nids_used.update(dresp.atti) #else: #msg = str(dresp) + 'response_type=%r' % dresp.response_type #raise NotImplementedError(msg) #else: #raise NotImplementedError(dresp) #msg = str(dresp) + 'response_type=%r' % dresp.response_type #raise NotImplementedError(msg) elif card_type == 'DRESP3': pass elif card_type in {'DVPREL1', 'DVPREL2'}: for dvprel_id in ids: dvprel = model.dvprels[dvprel_id] desvars_used.update(dvprel.desvar_ids) if dvprel.prop_type in dvprel_properties: pids_used.add(dvprel.Pid()) elif dvprel.prop_type in ['DISP']: msg = str(dvprel) + 'dvprel.prop_type=%r' % dvprel.prop_type raise NotImplementedError(msg) else: raise NotImplementedError(dvprel) elif card_type in ['DVCREL1', 'DVCREL2']: for dvcrel_id in ids: dvcrel = model.dvcrels[dvcrel_id] desvars_used.update(dvcrel.desvar_ids) if dvcrel.element_type in ['CMASS2', 'CMASS4', 'CONM1', 'CONM2', 'CELAS2', 'CELAS4', 'CBUSH', 'CDAMP2', 'CQUAD4', 'CGAP', 'CBAR']: #eids_used.add(dvcrel.Eid()) # we don't remove elements...for now pass else: msg = str(dvcrel) + 'element_type=%r' % dvcrel.element_type raise NotImplementedError(msg) elif card_type in ['DVMREL1', 'DVMREL2']: for dvmrel_id in ids: dvmrel = model.dvmrels[dvmrel_id] desvars_used.update(dvmrel.desvar_ids) if dvmrel.mat_type in ['MAT1', 'MAT2', 'MAT8', 'MAT9', 'MAT10', 'MAT11']: mids_used.add(dvmrel.Mid()) else: msg = str(dvmrel) + 'mat_type=%r' % dvmrel.mat_type raise NotImplementedError(msg) elif card_type == 'DVGRID': for dvgrid_id in ids: dvgrids = model.dvgrids[dvgrid_id] for dvgrid in dvgrids: desvars_used.add(dvgrid.desvar_id) nids_used.add(dvgrid.nid) cids_used.add(dvgrid.cid) elif card_type == 'TF': for tf_id in ids: tfs = model.transfer_functions[tf_id] for transfer_function in tfs: nids_used.update(transfer_function.nids) elif card_type in ['NSM', 'NSM1', 'NSML', 'NSML1']: _store_nsm(model, ids, pids_used) elif card_type in ['POINTAX', 'AXIC', 'RINGAX']: pass #for eid in ids: #elem = model.plotels[eid] #nids_used.update(elem.node_ids) elif card_type in ['PBRSECT', 'PBMSECT']: for pid in ids: prop = model.properties[pid] if prop.outp: sets_used.add(prop.outp) if prop.brps: for unused_key, value in prop.brps.items(): sets_used.add(value) #if prop.cores: #for key, value in prop.cores.items(): #pids_used.add(value) elif card_type == 'CYJOIN': for idi in ids: cyjoin = model.cyjoin[idi] nids_used.update(cyjoin.nids) elif card_type == 'TABLEHT': for idi in ids: table = model.tables[idi] tableh1_ids = table.y.tolist() tableh1_used.update(tableh1_ids) del tableh1_ids elif card_type == 'PCONV': for idi in ids: pconv = model.convection_properties[idi] if pconv.tid is not None: tableht_used.add(pconv.tid) elif card_type == 'CONV': for idi in ids: bcs = model.bcs[idi] for conv in bcs: if conv.type != 'CONV': continue pconv_used.add(conv.pconid) elif card_type == 'BLSEG': for idi in ids: blseg = model.blseg[idi] # line_id nids_used.update(blseg.nodes) #print(blseg.get_stats()) elif card_type == 'BCONP': for idi in ids: bconp = model.bconp[idi] # master # slave # ??? #print(bconp.get_stats()) cids_used.add(bconp.cid) friction_ids_used.add(bconp.friction_id) #elif card_type == 'FORCEAX': #pass #ring_id #sid elif card_type == 'MONPNT1': for idi in ids: monpnt = model.monitor_points[idi] #print(monpnt.get_stats()) cids_used.add(monpnt.cd) cids_used.add(monpnt.cp) aecomp_name = monpnt.comp aecomps_used.add(aecomp_name) elif card_type == 'AECOMP': for aecomp_name in ids: aecomp = model.aecomps[aecomp_name] if aecomp.list_type == 'SET1': spline_set_nodes.update(aecomp.lists) elif aecomp.list_type == 'AELIST': #print(aecomp.get_stats()) log.warning('skipping AELIST in MONPNT1/AECOMP') elif aecomp.list_type == 'CAERO': log.warning('skipping CAERO in MONPNT1/AECOMP') else: raise NotImplementedError(aecomp) elif card_type in {'FREQ', 'FREQ1', 'FREQ2', 'FREQ3', 'FREQ4', 'FREQ5'}: # freq_id exists, but we shouldn't be getting rid of it pass # for freq_id, elif card_type in not_implemented_types: model.log.warning(f'skipping {card_type}') else: raise NotImplementedError(card_type) #for pid, prop in model.properties.items(): #prop = model.properties[pid] #if prop.type in no_materials: #continue #elif prop.type == 'PSHELL': #mids_used.extend([mid for mid in prop.material_ids if mid is not None]) #elif prop.type == 'PCONEAX': #mids_used.extend([mid for mid in model.Mids() if mid is not None]) #elif prop.type in prop_mid: #mids_used.append(prop.Mid()) #elif prop.type in ['PCOMP', 'PCOMPG', 'PCOMPS', 'PCOMPLS']: #mids_used.extend(prop.Mids()) #elif prop.type == 'PBCOMP': #mids_used.append(prop.Mid()) #mids_used.extend(prop.Mids()) #else: #raise NotImplementedError(prop) _store_aero(model, spline_set_nodes, nids_used, cids_used) remove_desvars = False _remove( model, nids_used, cids_used, pids_used, pids_mass_used, mids_used, spcs_used, mpcs_used, pconv_used, tableht_used, tableh1_used, desvars_used, dresps_used, remove_nids=remove_nids, remove_cids=remove_cids, remove_pids=remove_pids, remove_mids=remove_mids, remove_spcs=remove_spcs, remove_mpcs=remove_mpcs, remove_desvars=remove_desvars, ) return model
[docs] def _store_splines(model: BDF, card_type: str, ids: np.ndarray, nids_used: set[int], sets_used: set[int], spline_set_nodes: set[int]): for spline_id in ids: spline = model.splines[spline_id] if card_type in ['SPLINE1', 'SPLINE2', 'SPLINE4', 'SPLINE5']: set_id = spline.Set() sets_used.add(set_id) spline_set_nodes.add(set_id) else: #print(' spline.node_ids =', spline.node_ids) nids_used.update(spline.node_ids)
#print(spline.get_stats())
[docs] def _store_aero(model: BDF, spline_set_nodes: set[int], nids_used: set[int], cids_used: set[int]) -> None: for set_id in spline_set_nodes: set_card = model.sets[set_id] nids_used.update(set_card.ids) aeros = model.aeros if aeros is not None: cids_used.update([aeros.acsid, aeros.rcsid]) aero = model.aero if aero is not None: cids_used.add(aero.acsid)
[docs] def _store_elements(card_type, model, ids, nids_used, pids_used, mids_used, cids_used): if card_type in ['CTETRA', 'CPENTA', 'CPYRAM', 'CHEXA', 'CHACAB']: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) pids_used.add(elem.Pid()) elif card_type in ['CELAS1', 'CDAMP1', 'CVISC', 'CDAMP5']: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) pids_used.add(elem.Pid()) elif card_type in ['CELAS2', 'CDAMP2']: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) elif card_type in ['CELAS3', 'CDAMP3']: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) pids_used.add(elem.Pid()) elif card_type in ['CELAS4', 'CDAMP4', 'GENEL']: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) elif card_type in ['CTRIA3', 'CQUAD4', 'CTRIA6', 'CTRIAR', 'CQUAD8', 'CQUADR', 'CTRIAX', 'CQUADX', 'CQUAD']: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) pids_used.add(elem.Pid()) if isinstance(elem.theta_mcid, int): cids_used.add(elem.theta_mcid) elif card_type in ['CTRIAX6', ]: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) mids_used.add(elem.Mid()) elif card_type in ['CSHEAR', 'CTUBE']: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) pids_used.add(elem.Pid()) elif card_type in ['CPLSTN3', 'CPLSTN4', 'CPLSTN6', 'CPLSTN8', 'CPLSTS3', 'CPLSTS4', 'CPLSTS6', 'CPLSTS8', 'CQUADX4', 'CQUADX8', 'CTRIAX6', 'CTRAX3', 'CTRAX6']: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) pids_used.add(elem.Pid()) elif card_type in ['CROD', 'CRAC2D', 'CRAC3D']: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) pids_used.add(elem.Pid()) elif card_type in ['CONROD']: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) pids_used.add(elem.Mid()) elif card_type == 'CCONEAX': for eid in ids: elem = model.elements[eid] pids_used.add(elem.Pid()) elif card_type in ['CBAR', 'CBEAM', 'CBEND']: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) pids_used.add(elem.Pid()) if elem.g0 is not None: assert isinstance(elem.g0, int), elem.g0 nids_used.add(elem.g0) elif card_type == 'CBEAM3': for eid in ids: elem = model.elements[eid] nids_used.add(elem.Ga()) nids_used.add(elem.Gb()) if elem.gc is not None: nids_used.add(elem.gc) pids_used.add(elem.Pid()) if elem.g0 is not None: assert isinstance(elem.g0, int), elem.g0 elif card_type == 'CFAST': for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) pids_used.add(elem.Pid()) elif card_type == 'CGAP': for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) pids_used.add(elem.Pid()) if elem.g0 is not None: assert isinstance(elem.g0, int), elem.g0 nids_used.add(elem.G0()) elif card_type == 'CBUSH': for eid in ids: elem = model.elements[eid] elem = model.elements[eid] nids_used.update(elem.node_ids) if elem.g0 is not None: assert isinstance(elem.g0, int), elem.g0 nids_used.add(elem.G0()) pids_used.add(elem.Pid()) if elem.cid is not None: cids_used.add(elem.Cid()) elif card_type in ['CBUSH1D', 'CBUSH2D']: for eid in ids: elem = model.elements[eid] nids_used.update(elem.node_ids) pids_used.add(elem.Pid()) cids_used.add(elem.Cid()) else: raise NotImplementedError(card_type)
[docs] def _store_nsm(model, ids, pids_used): """helper for ``remove_unused``""" for nsm_id in ids: nsms = model.nsms[nsm_id] for nsm in nsms: idsi = nsm.ids if nsm.nsm_type in ['PROD', 'PBARL', 'PBEAML', 'PSHELL', 'PCOMP', ]: if len(idsi) == 1 and idsi[0] == 'ALL': idsi = list(model.properties.keys()) #raise NotImplementedError('found ALL...\n%s' % str(nsm)) pids_used.update(idsi) elif nsm.nsm_type in ['CONROD', 'ELEMENT']: # we skip this because we assume all elements are used #if len(idsi) == 1 and idsi[0] == 'ALL': #raise NotImplementedError('found ALL...\n%s' % str(nsm)) #eids_used.update(idsi) pass else: msg = 'found nsm_type=%r...\n%s' % (nsm.nsm_type, str(nsm)) raise NotImplementedError(msg)
[docs] def _store_loads(model, unused_card_type, unused_ids, nids_used, eids_used, cids_used): """helper for ``remove_unused``""" for loads in model.loads.values(): for load in loads: if load.type in ['FORCE', 'MOMENT']: nids_used.add(load.node_id) cids_used.add(load.Cid()) elif load.type in ['FORCE1', 'FORCE2', 'MOMENT1', 'MOMENT2']: nids_used.update(load.node_ids) elif load.type == 'GRAV': cids_used.add(load.Cid()) elif load.type == 'RANDPS': pass elif load.type == 'PLOAD': nids_used.update(load.node_ids) elif load.type == 'PLOAD1': #eid = integer(card, 2, 'eid') pass elif load.type == 'PLOAD2': #eids_used.update(load.element_ids) pass elif load.type == 'PLOAD4': # eids, g1, g34 cids_used.add(load.Cid()) elif load.type == 'DEFORM': eids_used.add(load.Eid()) elif load.type == 'SPCD': nids_used.update(load.node_ids) #elif load.type == 'GMLOAD': #cids_used.add(load.Cid()) elif load.type in ['RFORCE', 'RFORCE1']: nids_used.add(load.node_id) cids_used.add(load.Cid()) elif load.type == 'TEMP': nids_used.update(list(load.temperatures.keys())) elif load.type == 'ACCEL': # nids? cids_used.add(load.Cid()) elif load.type == 'ACCEL1': # nids? cids_used.add(load.Cid()) elif load.type in ['QBDY1', 'QBDY2', 'QBDY3', 'QHBDY']: pass #'QBDY1', 'QBDY2', 'QBDY3', 'QHBDY', 'PLOADX1 elif load.type in ['PLOADX1']: nids_used.update(load.node_ids) elif load.type in ['SLOAD']: nids_used.update(load.node_ids) elif load.type in ['LOAD', 'LSEQ', 'LOADCYN']: pass elif load.type in ['QVOL', 'TEMPRB']: # eids pass elif load.type in ['TEMPAX']: pass # not done... else: raise NotImplementedError(load)
[docs] def _store_dresp1(model: BDF, ids, nids_used, pids_used, dresps_used): """helper for ``remove_unused``""" log = model.log for dresp_id in ids: dresp = model.dresps[dresp_id] if dresp.property_type in {'PSHELL', 'PCOMP', 'PCOMPG', 'PBAR', 'PBARL', 'PBEAM', 'PROD', 'PDAMP', 'PVISC', 'PTUBE', 'PSHEAR', 'PELAS', 'PSOLID', 'PBEAML'}: values = dresp.atti_values() pids_found = [] for pid in values: if pid in model.properties: pids_used.add(pid) pids_found.append(pid) log.info(f'found {dresp.type}={dresp_id}: pids={pids_found}') elif dresp.property_type == 'ELEM': if dresp.response_type in ['STRESS', 'FRSTRE', 'CFAILURE', 'TFORC', 'FRFORC']: #eids_used.update(dresp.atti_values()) pass else: msg = ( str(dresp) + 'region=%r property_type=%r response_type=%r, ' 'atta=%r attb=%s atti=%s' % ( dresp.region, dresp.property_type, dresp.response_type, dresp.atta, dresp.attb, dresp.atti)) raise NotImplementedError(msg) #elif dresp.property_type == 'STRESS': elif dresp.property_type is None: if dresp.response_type in {'WEIGHT', 'EIGN', 'VOLUME', 'LAMA', 'CEIG', 'FREQ', 'STABDER'}: #dresps_used.add(dresp_id) pass elif dresp.response_type in ['DISP', 'FRDISP', 'TDISP', 'RMSDISP', 'PSDDISP', 'TVELO', 'FRVELO', 'RMSVELO', 'TACCL', 'FRACCL', 'RMSACCL', 'SPCFORCE', 'TSPCF', 'FRSPCF', 'FORCE', 'TFORC', 'FRFORC']: nids_used.update(dresp.atti) elif dresp.response_type in ['FLUTTER', 'TRIM', 'DIVERG']: # flutter_id / trim_id pass elif dresp.response_type in {'CMPLNCE', 'DWEIGHT'}: pass else: msg = ( str(dresp) + 'region=%r property_type=%r response_type=%r ' 'atta=%r attb=%s atti=%s' % ( dresp.region, dresp.property_type, dresp.response_type, dresp.atta, dresp.attb, dresp.atti)) raise NotImplementedError(msg) else: msg = ( str(dresp) + 'region=%r property_type=%r response_type=%r ' 'atta=%r attb=%s atti=%s' % ( dresp.region, dresp.property_type, dresp.response_type, dresp.atta, dresp.attb, dresp.atti)) raise NotImplementedError(msg)
[docs] def _store_masses(card_type, model, ids, nids_used, pids_mass_used, cids_used) -> None: """handles masses""" if card_type in ['CONM1', 'CONM2']: for eid in ids: elem = model.masses[eid] nids_used.add(elem.Nid()) cids_used.add(elem.Cid()) elif card_type in ['CMASS1', 'CMASS3']: for eid in ids: elem = model.masses[eid] pids_mass_used.add(elem.Pid()) nids_used.update(elem.node_ids) elif card_type in ['CMASS2', 'CMASS4']: for eid in ids: elem = model.masses[eid] nids_used.update(elem.node_ids) else: raise NotImplementedError(card_type)
[docs] def _remove(model: BDF, nids_used: set[int], cids_used: set[int], pids_used: set[int], pids_mass_used: set[int], mids_used: set[int], spcs_used: set[int], mpcs_used: set[int], pconv_used: set[int], tableht_used: set[int], tableh1_used: set[int], desvars_used: set[int], dresps_used: set[int], remove_nids: bool=True, remove_cids: bool=True, remove_pids: bool=True, remove_mids: bool=True, remove_spcs: bool=True, remove_mpcs: bool=True, remove_desvars: bool=True, remove_optimization: bool=True) -> None: """actually removes the cards""" nids = set(model.nodes.keys()) pids = set(model.properties.keys()) pids_mass = set(model.properties_mass.keys()) cids = set(model.coords.keys()) mids = set(model.materials.keys()) spcs = set(model.spcs.keys()) # spcadds? mpcs = set(model.mpcs.keys()) # mpcadds? dresps = set(model.dresps.keys()) desvars = set(model.desvars.keys()) nids_to_remove = list(nids - nids_used) pids_to_remove = list(pids - pids_used) pids_mass_to_remove = list(pids_mass - pids_mass_used) mids_to_remove = list(mids - mids_used) cids_to_remove = list(cids - cids_used) #for subcase in model.subcases: # if 'SPC' in subcase: # value = subcase['SPC'] # spcs_used.add(value) # if 'MPC' in subcase: # value = subcase['MPC'] # mpcs_used.add(value) # #if 'LOAD' in subcase: # #value = subcase['LOAD'] # #loads_used.add(value) spcs_to_remove = list(spcs - spcs_used) mpcs_to_remove = list(mpcs - mpcs_used) desvars_to_remove = list(desvars - desvars_used) dresps_to_remove = list(dresps - dresps_used) if 0 in cids_to_remove: cids_to_remove.remove(0) if remove_nids and nids_to_remove: for nid in nids_to_remove: del model.nodes[nid] nids_to_remove.sort() if nids_to_remove: nodes_array = np.array(nids_to_remove) model.log.debug(f'removed nodes {nodes_array}; n={len(nodes_array)}') if remove_cids and cids_to_remove: for cid in cids_to_remove: del model.coords[cid] cids_to_remove.sort() if cids_to_remove: model.log.debug('removing coords %s' % cids_to_remove) if remove_pids and pids_to_remove: for pid in pids_mass_to_remove: del model.properties_mass[pid] pids_mass_to_remove.sort() if pids_mass_to_remove: model.log.debug('removing properties_mass %s' % pids_mass_to_remove) for pid in pids_to_remove: del model.properties[pid] pids_to_remove.sort() if pids_to_remove: model.log.debug('removing properties %s' % pids_to_remove) if remove_mids and mids_to_remove: for mid in mids_to_remove: del model.materials[mid] mids_to_remove.sort() if mids_to_remove: model.log.debug('removing materials %s' % mids_to_remove) #if remove_spcs and spcs_to_remove: # for spc_id in spcs_to_remove: # del model.spcs[spc_id] # spcs_to_remove.sort() # model.log.debug('removed spcs %s' % spcs_to_remove) #if remove_mpcs and mpcs_to_remove: # for mpc_id in mpcs_to_remove: # del model.mpcs[mpc_id] # mpcs_to_remove.sort() # model.log.debug('removed mpcs %s' % mpcs_to_remove) _remove_thermal(model, pconv_used, tableht_used, tableh1_used) if remove_optimization: _remove_optimization(model, pids_to_remove, desvars_to_remove, dresps_to_remove)
[docs] def _remove_optimization(model: BDF, pids_to_remove: list[int], desvars_to_remove: list[int], dresps_to_remove: list[int]) -> None: for desvar_id in desvars_to_remove: del model.desvars[desvar_id] if desvars_to_remove: model.log.debug('removing DESVAR %s' % desvars_to_remove) for dresp_id in dresps_to_remove: del model.dresps[dresp_id] if dresps_to_remove: model.log.debug('removing DRESPx %s' % dresps_to_remove) dvprels_ids_to_remove = [] dvprels_to_remove = [] for dvprel_id, dvprel in model.dvprels.items(): pid = dvprel.Pid() if pid in pids_to_remove: dvprels_ids_to_remove.append(dvprel_id) dvprels_to_remove.append((dvprel_id, f'removing DVPRELx={dvprel_id} because pid={pid} does not exist')) if dvprels_ids_to_remove: model.log.debug('removing DVPRELx %s' % dvprels_ids_to_remove) _remove_dict(model.dvprels, dvprels_to_remove, model.log)
#for dvprel_id, msg in dvprels_to_remove: #del model.dvprels[dvprel_id] #model.log.debug(msg)
[docs] def _remove_dict(mydict, keys_msg, log): for key, msg in keys_msg: del mydict[key] log.debug(msg)
[docs] def _remove_thermal(model: BDF, pconv_used, tableht_used, tableh1_used) -> None: """removes some thermal cards""" pconv = {pid for pid, prop in model.convection_properties.items() if prop.type == 'PCONV'} tableht = {tid for tid, table in model.tables.items() if table.type == 'TABLEHT'} tableh1 = {tid for tid, table in model.tables.items() if table.type == 'TABLEH1'} pconv_to_remove = list(pconv - pconv_used) tableht_to_remove = list(tableht - tableht_used) tableh1_to_remove = list(tableh1 - tableh1_used) remove_pconv = True if remove_pconv and pconv_to_remove: for pid in pconv_to_remove: del model.convection_properties[pid] pconv_to_remove.sort() model.log.debug('removing convection_properties %s' % pconv_to_remove) remove_tableh1 = True remove_tableht = True if remove_tableh1 and tableh1_to_remove: for pid in tableh1_to_remove: del model.tables[pid] tableh1_to_remove.sort() model.log.debug('removing TABLEH1 %s' % tableh1_to_remove) if remove_tableht and tableht_to_remove: for pid in tableht_to_remove: del model.tables[pid] tableht_to_remove.sort() model.log.debug('removing TABLEH1 %s' % tableht_to_remove) return