def _mirror_aero(model: BDF, nid_offset: int, plane: str = 'xz'): """ Mirrors the aero cards Considers: - AEROS - doesn't consider sideslip - CAERO1 - doesn't consider sideslip - considers Cp - considers lchord/lspan/nchord/nspan - SPLINE1 - handle boxes - SET1 - handle nodes - AELIST - handle boxes - AESURF - only supports names of length 7 or less (appends an M to the name) - handles AELIST - doesn't handle coords well - doesn't handle second AESURF Doesnt consider: - AERO - AEFORCE - AEPRES - CAERO2/3/4/5 - PAERO1/2/3/4/5 - AESURFS """ is_aero = False aero_cids_set = set([]) if model.aeros is not None: is_aero = True aeros = model.aeros # The ACSID must be a rectangular coordinate system. # Flow is in the positive x-direction (T1). if aeros.acsid > 0: model.log.error( 'Sideslip coordinate system (ACSID) mirroring is not supported' ) # REFB should be full span, even on half-span models # REFS should be half area on half-span models aeros.sref *= 2. if plane == 'xz': aeros.sym_xz = 0 elif plane == 'yz': aeros.sym_yz = 0 else: model.log.error('not mirroring plane %r; only xz, yz' % plane) caero_id_offset = 0 if len(model.caeros): is_aero = True caero_id_max = max(model.caero_ids) caero_id_offset = np.max(model.caeros[caero_id_max].box_ids.flat) caeros = [] for unused_caero_id, caero in model.caeros.items(): if caero.type == 'CAERO1': # the AEFACTs are assumed to be the same on the left and right side # I think the spanwise direction will be fine lchord = caero.lchord nchord = caero.nchord lspan = caero.lspan nspan = caero.nspan p1, p4 = caero.get_leading_edge_points() p1 = p1.copy() p4 = p4.copy() x12 = caero.x12 x43 = caero.x43 if plane == 'xz': # flip the y p1[1] *= -1. p4[1] *= -1. elif plane == 'xy': p1[2] *= -1. p4[2] *= -1. else: # pragma: no cover raise NotImplementedError( 'plane=%r not supported in CAERO1' % plane) eid2 = caero.eid + caero_id_offset caero_new = CAERO1(eid2, caero.pid, caero.igroup, p1, x12, p4, x43, cp=0, nspan=nspan, lspan=lspan, nchord=nchord, lchord=lchord, comment='') # we flip the normal so if we ever use W2GJ it's going to be consistent caero_new.flip_normal() caeros.append(caero_new) else: # pragma: no cover model.log.error('skipping (only supports CAERO1):\n%s' % caero.rstrip()) for caero in caeros: model._add_caero_object(caero) nsplines = len(model.splines) sets_max = max(model.sets) if len(model.sets) else 0 if caero_id_offset == 0 and nsplines: model.log.error("cant mirror splines because CAEROs don't exist...") elif nsplines and sets_max == 0: model.log.error("cant mirror splines because SET1/3 don't exist...") elif nsplines: is_aero = True splines = [] spline_sets_to_duplicate = [] spline_max = max(model.splines) for unused_spline_id, spline in model.splines.items(): if spline.type == 'SPLINE1': eid = spline.eid + spline_max caero = spline.caero + caero_id_offset method = spline.method usage = spline.usage box1 = spline.box1 + caero_id_offset box2 = spline.box2 + caero_id_offset setg = spline.setg + sets_max dz = spline.dz melements = spline.melements nelements = spline.nelements spline_new = SPLINE1(eid, caero, box1, box2, setg, dz=dz, method=method, usage=usage, nelements=nelements, melements=melements, comment='') splines.append(spline_new) spline_sets_to_duplicate.append(spline.setg) else: # pragma: no cover model.log.error('skipping (only support SPLINE1):\n%s' % spline.rstrip()) #print("spline_sets_to_duplicate =", spline_sets_to_duplicate) msg = ', which is required to mirror:\n%s' % spline.rstrip() sets_to_add = [] for set_id in spline_sets_to_duplicate: set_card = model.Set(set_id, msg=msg) if set_card.type == 'SET1': sid = set_card.sid + sets_max ids = [nid + nid_offset for nid in set_card.ids] is_skin = set_card.is_skin set_card = SET1(sid, ids, is_skin=is_skin, comment='') sets_to_add.append(set_card) else: # pragma: no cover model.log.error('skipping (only support SET1):\n%s' % set_card.rstrip()) for spline in splines: model._add_spline_object(spline) for set_card in sets_to_add: model._add_set_object(set_card) aelist_id_offset = 0 if len(model.aelists): is_aero = True aelist_id_offset = max(model.aelists) cid_offset = max(model.coords) if len(model.coords) > 1 else 0 if len(model.aesurf): is_aero = True aesurf_id_offset = max(model.aesurf) for aelist_id, aelist in sorted(model.aelists.items()): aelist_id_new = aelist_id + aelist_id_offset elements = [eid + caero_id_offset for eid in aelist.elements] model.add_aelist(aelist_id_new, elements, comment='') for aesurf_id, aesurf in sorted(model.aesurf.items()): # TODO: doesn't handle cid2/aelist2 aesurf_id_new = aesurf_id + aesurf_id_offset label = aesurf.label + 'M' cid1 = aesurf.cid1 + cid_offset alid1 = aesurf.alid1 + aelist_id_offset if cid_offset > 0: aero_cids_set.add(aesurf.cid1) cid2 = None alid2 = None if aesurf.cid2: model.log.warning( "skipping aesurf='{aesurf.label}' second cid/aelist") # combine this into the first coordinate system # # don't mirror the coordinate system because it's antisymmetric? #cid2 = aesurf.cid1 + cid_offset * 2 # how is the second coord and aelist made? #aero_cids_set.add(aesurf.cid1) #alid2 = aesurf.alid1 + aelist_id_offset * 2 model.add_aesurf(aesurf_id_new, label, cid1, alid1, cid2=None, alid2=None, eff=aesurf.eff, ldw=aesurf.ldw, crefc=aesurf.crefc, crefs=aesurf.crefs, pllim=aesurf.pllim, pulim=aesurf.pulim, hmllim=aesurf.hmllim, hmulim=aesurf.hmulim, tqllim=aesurf.tqllim, tqulim=aesurf.tqulim, comment='') if is_aero: _asymmetrically_mirror_aero_coords(model, aero_cids_set, cid_offset, plane) model.pop_parse_errors()
def _mirror_aero(model, nid_offset, plane): """ Mirrors the aero elements Considers: - AEROS - doesn't consider sideslip - CAERO1 - doesn't consider sideslip - doesn't consider lspan/lchord - SPLINE1 - SET1 """ if model.aeros is not None: aeros = model.aeros aeros.sref *= 2. if plane == 'xz': aeros.sym_xz = 0 elif plane == 'yz': aeros.sym_yz = 0 else: model.log.error('not mirroring plane %r; only xz, yz' % plane) caero_id_offset = 0 if len(model.caeros): caero_id_max = max(model.caero_ids) caero_id_offset = np.max(model.caeros[caero_id_max].box_ids.flat) caeros = [] for unused_caero_id, caero in model.caeros.items(): if caero.type == 'CAERO1': assert caero.lspan == 0, caero assert caero.lchord == 0, caero lchord = caero.lchord nchord = caero.nchord lspan = caero.lspan nspan = caero.nspan p1 = caero.p1.copy() p1[1] *= -1. x12 = caero.x12 p4 = caero.p4.copy() p4[1] *= -1. x43 = caero.x43 eid2 = caero.eid + caero_id_offset caero_new = CAERO1(eid2, caero.pid, caero.igroup, p1, x12, p4, x43, cp=caero.cp, nspan=nspan, lspan=lspan, nchord=nchord, lchord=lchord, comment='') # we flip the normal so if we ever use W2GJ it's going to be consistent caero_new.flip_normal() caeros.append(caero_new) #print(caero) else: # pragma: no cover model.log.error('skipping (only support CAERO1):\n%s' % caero.rstrip()) for caero in caeros: model._add_caero_object(caero) nsplines = len(model.splines) sets_max = max(model.sets) if len(model.sets) else 0 if caero_id_offset == 0 and nsplines: model.log.error("cant mirror splines because CAEROs don't exist...") elif nsplines and sets_max == 0: model.log.error("cant mirror splines because SET1/3 don't exist...") elif nsplines: splines = [] spline_sets_to_duplicate = [] spline_max = max(model.splines) for unused_spline_id, spline in model.splines.items(): if spline.type == 'SPLINE1': #spline = SPLINE1(eid, caero, box1, box2, setg) eid = spline.eid + spline_max caero = spline.caero + caero_id_offset method = spline.method usage = spline.usage box1 = spline.box1 + caero_id_offset box2 = spline.box2 + caero_id_offset setg = spline.setg + sets_max dz = spline.dz melements = spline.melements nelements = spline.nelements spline_new = SPLINE1(eid, caero, box1, box2, setg, dz=dz, method=method, usage=usage, nelements=nelements, melements=melements, comment='') splines.append(spline_new) spline_sets_to_duplicate.append(spline.setg) else: # pragma: no cover model.log.error('skipping (only support SPLINE1):\n%s' % spline.rstrip()) #print("spline_sets_to_duplicate =", spline_sets_to_duplicate) msg = ', which is required to mirror:\n%s' % spline.rstrip() sets_to_add = [] for set_id in spline_sets_to_duplicate: set_card = model.Set(set_id, msg=msg) if set_card.type == 'SET1': sid = set_card.sid + sets_max ids = [nid + nid_offset for nid in set_card.ids] is_skin = set_card.is_skin set_card = SET1(sid, ids, is_skin=is_skin, comment='') sets_to_add.append(set_card) else: # pragma: no cover model.log.error('skipping (only support SET1):\n%s' % set_card.rstrip()) for spline in splines: model._add_spline_object(spline) for set_card in sets_to_add: model._add_set_object(set_card) model.pop_parse_errors()