Source code for pyNastran.bdf.mesh_utils.get_oml

"""
defines:
 - eids_oml = get_oml_eids(bdf_filename, eid_start, theta_tol=30.,
                           is_symmetric=True, consider_flippped_normals=True)

"""
from io import StringIO
from copy import deepcopy
from typing import Union
from pathlib import PurePath
import numpy as np

from pyNastran.bdf.bdf import BDF
from pyNastran.bdf.mesh_utils.internal_utils import get_bdf_model
#from pyNastran.bdf.bdf_interface.dev_utils import get_free_edges


[docs] def get_oml_eids(bdf_filename: Union[str, BDF, PurePath, StringIO], eid_start: int, theta_tol: float=30., is_symmetric: bool=True, consider_flippped_normals: bool=True) -> tuple[BDF, set[int]]: """ Extracts the OML faces (outer mold line) of a shell model. In other words, find all the shell elements touching the current element without crossing an MPC or rigid element. Parameters ---------- bdf_filename : str or BDF() the bdf filename eid_start : int the element to start from theta_tol : float; default=30. the angular tolerance in degrees is_symmetric : bool; default=True is the y=0 plane considered to be part of the OML consider_flippped_normals : bool; default=True if you extracted the free faces from tets, you can get flipped normals this considers a 180 degree error to be 0.0, which will cause other problems """ #ninety = np.radians(90.) #2810 # start for bwb_saero.bdf #2811 # close #2819 # close #2818 # close #eids_oml = np.array([eid_start]) eids_oml = set([eid_start]) #--------------------------------- theta_tol = np.radians(theta_tol) model = get_bdf_model(bdf_filename, xref=True, log=None, debug=True) maps = model._get_maps( eids=None, map_names=None, consider_0d=False, consider_0d_rigid=False, consider_1d=False, consider_2d=True, consider_3d=False) edge_to_eid_map = maps['edge_to_eid_map'] eid_to_edge_map = maps['eid_to_edge_map'] unused_nid_to_edge_map = maps['nid_to_edge_map'] #free_edges = get_free_edges(model, maps=maps) #--------------------------------- normals = {} etypes_skipped = set() shells = {'CTRIA3', 'CQUAD4', 'CTRIA6', 'CQUAD8', 'CQUAD'} for eid, elem in model.elements.items(): if elem.type in shells: normals[eid] = elem.Normal() else: if elem.type in etypes_skipped: continue model.log.debug(f'elem.type={elem.type!r} is not supported') etypes_skipped.add(elem.type) #eid_starts = eids_oml.tolist() eids_next = set([eid_start]) while eids_next: eid_starts = deepcopy(eids_next) eids_oml_start = deepcopy(eids_oml) model.log.debug(f'nactive_elements = {len(eid_starts)}') while eid_starts: eid_start = eid_starts.pop() normal_start = normals[eid_start] # get the next set of edges edges = eid_to_edge_map[eid_start] #flattened = [] #for row in matrix: #for n in row: #flattened.append(n) # flattened = [n for row in matrix for n in row] #eids_to_consider = [edge_to_eid_map[edge] for edge in edges] list_eids_to_consider = [] for edge in edges: eids_with_edge = edge_to_eid_map[edge] list_eids_to_consider += eids_with_edge #list_eids_to_consider = set([eid for eid in edge_to_eid_map[edge] for edge in edges]) #print('list_eids_to_consider =', list_eids_to_consider) eids_to_consider = set(list_eids_to_consider) # don't do the same element twice; creates an infinite loop if you do #eids_to_check = np.setdiff1d(eids_to_consider, eids_oml) eids_to_check = eids_to_consider.difference(eids_oml) # don't check elements we're checking right now #eids_to_check = np.setdiff1d(eids_to_consider, eid_starts) eids_to_check = eids_to_consider.difference(eid_starts) #print('eids_to_check =', eids_to_check) for eid in eids_to_check: normal = normals[eid] # a o b = a * b * cos(theta) # cos(theta) = (a o b)/ (a b); where |a| = 1; |b| = 1 cos_theta = np.clip(normal @ normal_start, -1.0, 1.0) theta = np.arccos(cos_theta) if theta < theta_tol: eids_next.add(eid) eids_oml.add(eid) elif consider_flippped_normals: # handles flipped normals cos_theta = np.clip(normal @ -normal_start, -1.0, 1.0) theta = np.arccos(cos_theta) if theta < theta_tol: eids_next.add(eid) eids_oml.add(eid) #print('eids_next =', eids_next) eids_next = eids_next.difference(eids_oml_start) #eids_next = eids_next.difference(eid_starts) #print('eids_next =', eids_next) #print('-------------------------------') model.log.debug('done with get_oml_eids') #with open('eids_oml.txt', 'w') as eids_file: #eids_file.write('eids_oml = %s\n' % list(eids_oml)) return model, eids_oml
[docs] def main(): # pragma: no cover """runs the test problem""" bdf_filename = 'bwb_saero.bdf' eid_start = 2810 model, eids_oml = get_oml_eids(bdf_filename, eid_start) del eids_oml
if __name__ == '__main__': # pragma: no cover main()