def get_sh_sections_for_shape_obj(model: gmsh.model, model_obj: Shape, gmsh_data: GmshData, fem: FEM): from ada.core.utils import Counter sides = Counter(1, "S") for dim, ent in gmsh_data.entities: _, tag, _ = model.mesh.getElements(2, ent) _, _, param = model.mesh.getNodes(2, ent, True) elements = [fem.elements.from_id(x) for x in chain.from_iterable(tag)] thickness = 0.0 normal = np.array([ 0.0 if abs(x) == 0.0 else x for x in model.getNormal(ent, param)[:3] ]) s = next(sides) set_name = make_name_fem_ready(f"el{model_obj.name}{s}_sh") fem_sec_name = make_name_fem_ready(f"d{model_obj.name}{s}_sh") add_shell_section(set_name, fem_sec_name, normal, thickness, elements, model_obj, fem, is_rigid=True)
def get_beam_elements(self, li, order): """ :param li: :param order: :return: """ import gmsh from ada.core.utils import make_name_fem_ready model = gmsh.model bm = self._bm_map[li] segments = model.mesh.getElements(1, li)[1][0] fem_nodes = model.mesh.getElements(1, li)[2][0] elem_types, elem_tags, elem_node_tags = gmsh.model.mesh.getElements( 1, li) face, dim, morder, numv, parv, _ = gmsh.model.mesh.getElementProperties( elem_types[0]) set_name = make_name_fem_ready(f"el{bm.name}_set") fem = self._part.fem def make_elem(j): no = [] for i in range(numv): p1 = fem_nodes[numv * j + i] p1_co = gmsh.model.mesh.getNode(p1)[0] no.append(Node(p1_co, p1)) if len(no) == 3: myorder = [0, 2, 1] no = [no[i] for i in myorder] bm_el_type = "B31" if order == 1 else "B32" return Elem(segments[j], no, bm_el_type, parent=self._part.fem) elements = list(map(make_elem, range(len(segments)))) fem_sec_name = make_name_fem_ready(f"d{bm.name}_sec") if set_name in fem.elsets.keys(): fem_set = fem.elsets[set_name] for el in elements: el.fem_sec = fem_set.members[0].fem_sec fem_set.add_members(elements) else: fem_set = FemSet(set_name, elements, "elset", parent=fem) fem.sets.add(fem_set) fem.add_section( FemSection( fem_sec_name, "beam", fem_set, bm.material, bm.section, bm.ori[2], metadata=dict(beam=bm, numel=len(elements)), )) return elements
def get_sh_sections_for_pipe_obj(model: gmsh.model, model_obj: Pipe, gmsh_data: GmshData, fem: FEM): thickness = model_obj.section.wt normal = model_obj.segments[0].zvec for i, (_, ent) in enumerate(gmsh_data.entities): _, tags, _ = model.mesh.getElements(2, ent) set_name = make_name_fem_ready(f"el{model_obj.name}_e{ent}_pipe_sh") fem_sec_name = make_name_fem_ready(f"d{model_obj.name}_e{ent}_pipe_sh") elements = [fem.elements.from_id(x) for x in chain.from_iterable(tags)] add_shell_section(set_name, fem_sec_name, normal, thickness, elements, model_obj, fem)
def create_line_section(fem_sec: FemSection, sec_names: List[str], sec_ids: List[Section]) -> Union[BmSectionStr, None]: from .write_bm_profiles import write_bm_section sec = fem_sec.section if sec in sec_ids: logging.info(f'Skipping already included section "{sec}"') return None sec_ids.append(sec) sec_name = make_name_fem_ready(sec.name, no_dot=True) if sec_name not in sec_names: sec_names.append(sec_name) else: sec_name += next(sec_n) names_str = write_ff( "TDSECT", [ (4, sec.id, 100 + len(sec_name), 0), (sec_name, ), ], ) sec_str = write_bm_section(sec, sec.id) if fem_sec.refs is not None: tdsconc_str, sconcept_str, scon_mesh = create_sconcept_str(fem_sec) else: tdsconc_str, sconcept_str, scon_mesh = "", "", "" return BmSectionStr(sec_str=sec_str, names_str=names_str, tdsconc_str=tdsconc_str, sconcept_str=sconcept_str, scon_mesh=scon_mesh)
def get_sh_sections_for_plate_obj(model: gmsh.model, model_obj: Plate, gmsh_data: GmshData, fem: FEM): tags = [] for dim, ent in gmsh_data.entities: _, tag, _ = model.mesh.getElements(2, ent) tags += tag elements = [fem.elements.from_id(x) for x in chain.from_iterable(tags)] thickness = model_obj.t normal = model_obj.n set_name = make_name_fem_ready(f"el{model_obj.name}_sh") fem_sec_name = make_name_fem_ready(f"d{model_obj.name}_sh") add_shell_section(set_name, fem_sec_name, normal, thickness, elements, model_obj, fem)
def name(self, value): from ada.core.utils import make_name_fem_ready if str.isnumeric(value[0]): raise ValueError("Name cannot start with numeric") if Settings.convert_bad_names_for_fem: self._name = make_name_fem_ready(value) else: self._name = value.strip()
def get_so_sections(model: gmsh.model, solid_object: Beam, gmsh_data: GmshData, fem: FEM): tags = [] for dim, ent in gmsh_data.entities: _, tag, _ = model.mesh.getElements(3, ent) tags += tag elements = [ fem.elements.from_id(elid) for elid in chain.from_iterable(tags) ] set_name = make_name_fem_ready(f"el{solid_object.name}_so") fem_sec_name = make_name_fem_ready(f"d{solid_object.name}_so") fem_set = FemSet(set_name, elements, FemSet.TYPES.ELSET, parent=fem) fem_sec = FemSection(fem_sec_name, ElemType.SOLID, fem_set, solid_object.material) add_sec_to_fem(fem, fem_sec, fem_set)
def get_bm_sections(model: gmsh.model, beam: Beam, gmsh_data, fem: FEM): from ada.core.vector_utils import vector_length tags = [] for dim, ent in gmsh_data.entities: _, tag, _ = model.mesh.getElements(1, ent) tags += tag elements = [ fem.elements.from_id(elid) for elid in chain.from_iterable(tags) ] set_name = make_name_fem_ready(f"el{beam.name}_set_bm") fem_sec_name = make_name_fem_ready(f"d{beam.name}_sec_bm") fem_set = FemSet(set_name, elements, FemSet.TYPES.ELSET, parent=fem) fem_sec = FemSection(fem_sec_name, ElemType.LINE, fem_set, beam.material, beam.section, beam.ori[2], refs=[beam]) add_sec_to_fem(fem, fem_sec, fem_set) if beam.hinge_prop is None: return end1_p = beam.hinge_prop.end1.concept_node.p if beam.hinge_prop.end1 is not None else None end2_p = beam.hinge_prop.end2.concept_node.p if beam.hinge_prop.end2 is not None else None if beam.hinge_prop is not None: for el in elements: n1 = el.nodes[0] n2 = el.nodes[-1] el.hinge_prop = beam.hinge_prop if beam.hinge_prop.end1 is not None and vector_length(end1_p - n1.p) == 0.0: el.hinge_prop.end1.fem_node = n1 if beam.hinge_prop.end2 is not None and vector_length(end2_p - n2.p) == 0.0: el.hinge_prop.end2.fem_node = n2
def get_sh_sections_for_beam_obj(model: gmsh.model, beam: Beam, gmsh_data: GmshData, fem: FEM): from ada.sections.bm_sh_ident import eval_thick_normal_from_cog_of_beam_plate pl1 = Placement(beam.n1.p, beam.yvec, beam.up, beam.xvec) for _, ent in gmsh_data.entities: _, _, param = model.mesh.getNodes(2, ent, True) normal = np.array([ 0.0 if abs(x) == 0.0 else x for x in model.getNormal(ent, param)[:3] ]) cog = model.occ.getCenterOfMass(2, ent) pc = eval_thick_normal_from_cog_of_beam_plate(beam.section, cog, normal, pl1) _, tags, _ = model.mesh.getElements(2, ent) elements = [fem.elements.from_id(x) for x in chain.from_iterable(tags)] set_name = make_name_fem_ready(f"el{beam.name}_e{ent}_{pc.type}_sh") fem_sec_name = make_name_fem_ready(f"d{beam.name}_e{ent}_{pc.type}_sh") add_shell_section(set_name, fem_sec_name, normal, pc.thick, elements, beam, fem)
def create_sconcept_str(fem_sec: FemSection) -> Tuple[str, str, str]: sconcept_str = "" # Give concept relationship based on inputted values beams = [x for x in fem_sec.refs if type(x) is Beam] if len(beams) != 1: raise ValueError("A FemSection cannot be sourced from multiple beams") beam = beams[0] fem_sec.metadata["ircon"] = next(concept_ircon) bm_name = make_name_fem_ready(beam.name, no_dot=True) tdsconc_str = write_ff( "TDSCONC", [(4, fem_sec.metadata["ircon"], 100 + len(bm_name), 0), (bm_name, )], ) sconcept_str += write_ff("SCONCEPT", [(8, next(concept), 7, 0), (0, 1, 0, 2)]) sconc_ref = next(concept) sconcept_str += write_ff("SCONCEPT", [(5, sconc_ref, 2, 4), (1, )]) elids: List[tuple] = [] i = 0 numel = len(beam.elem_refs) elid_bulk = [numel] for el in fem_sec.elset.members: if i == 3: elids.append(tuple(elid_bulk)) elid_bulk = [] i = -1 elid_bulk.append(el.id) i += 1 if len(elid_bulk) != 0: elids.append(tuple(elid_bulk)) mesh_args = [(5 + numel, sconc_ref, 1, 2)] + elids scon_mesh = write_ff("SCONMESH", mesh_args) return tdsconc_str, sconcept_str, scon_mesh
def _sections_str(self): """ 'TDSECT', 'nfield', 'geono', 'codnam', 'codtxt', 'set_name' 'GIORH ', 'geono', 'hz', 'ty', 'bt', 'tt', 'bb', 'tb', 'sfy', 'sfz', 'NLOBYT|', 'NLOBYB|', 'NLOBZ|' :return: """ from ada.core.utils import Counter, make_name_fem_ready from ada.sections import SectionCat sec_str = "" sec_ids = [] names_str = "" concept_str = "" thick_map = dict() c = Counter(1) g = Counter(1) ircon = Counter(1) shid = Counter(1) bmid = Counter(1) for fem_sec in self._gsections: assert isinstance(fem_sec, FemSection) if fem_sec.type == "beam": section = fem_sec.section if section not in sec_ids: secid = next(bmid) sec_name = make_name_fem_ready(fem_sec.section.name, no_dot=True) section.metadata["numid"] = secid names_str += self.write_ff( "TDSECT", [ (4, secid, 100 + len(sec_name), 0), (sec_name, ), ], ) sec_ids.append(fem_sec.section) if "beam" in fem_sec.metadata.keys(): # Give concept relationship based on inputted values beam = fem_sec.metadata["beam"] numel = fem_sec.metadata["numel"] fem_sec.metadata["ircon"] = next(ircon) bm_name = make_name_fem_ready(beam.name, no_dot=True) concept_str += self.write_ff( "TDSCONC", [(4, fem_sec.metadata["ircon"], 100 + len(bm_name), 0), (bm_name, )], ) concept_str += self.write_ff("SCONCEPT", [(8, next(c), 7, 0), (0, 1, 0, 2)]) sconc_ref = next(c) concept_str += self.write_ff("SCONCEPT", [(5, sconc_ref, 2, 4), (1, )]) elids = [] i = 0 elid_bulk = [numel] for el in fem_sec.elset.members: if i == 3: elids.append(tuple(elid_bulk)) elid_bulk = [] i = -1 elid_bulk.append(el.id) i += 1 if len(elid_bulk) != 0: elids.append(tuple(elid_bulk)) elid_bulk = [] mesh_args = [(5 + numel, sconc_ref, 1, 2)] + elids concept_str += self.write_ff("SCONMESH", mesh_args) concept_str += self.write_ff("GUNIVEC", [(next(g), *beam.up)]) section.properties.calculate() p = section.properties sec_str += self.write_ff( "GBEAMG", [ (secid, 0, p.Ax, p.Ix), (p.Iy, p.Iz, p.Iyz, p.Wxmin), (p.Wymin, p.Wzmin, p.Shary, p.Sharz), (p.Scheny, p.Schenz, p.Sy, p.Sz), ], ) if SectionCat.is_i_profile(section.type): sec_str += self.write_ff( "GIORH", [ (secid, section.h, section.t_w, section.w_top), (section.t_ftop, section.w_btn, section.t_fbtn, p.Sfy), (p.Sfz, ), ], ) elif SectionCat.is_hp_profile(section.type): sec_str += self.write_ff( "GLSEC", [ (secid, section.h, section.t_w, section.w_btn), (section.t_fbtn, p.Sfy, p.Sfz, 1), ], ) elif SectionCat.is_box_profile(section.type): sec_str += self.write_ff( "GBOX", [ (secid, section.h, section.t_w, section.t_fbtn), (section.t_ftop, section.w_btn, p.Sfy, p.Sfz), ], ) elif SectionCat.is_tubular_profile(section.type): sec_str += self.write_ff( "GPIPE", [(secid, (section.r - section.wt) * 2, section.r * 2, section.wt), (p.Sfy, p.Sfz)], ) elif SectionCat.is_circular_profile(section.type): sec_str += self.write_ff( "GPIPE", [(secid, (section.r - section.r * 0.99) * 2, section.r * 2, section.wt), (p.Sfy, p.Sfz)], ) elif SectionCat.is_flatbar(section.type): sec_str += self.write_ff( "GBARM", [(secid, section.h, section.w_top, section.w_btn), (p.Sfy, p.Sfz)]) else: logging.error( f'Unable to convert "{section}". This will be exported as general section only' ) elif fem_sec.type == "shell": if fem_sec.thickness not in thick_map.keys(): sh_id = next(shid) thick_map[fem_sec.thickness] = sh_id else: sh_id = thick_map[fem_sec.thickness] sec_str += self.write_ff("GELTH", [(sh_id, fem_sec.thickness, 5)]) else: raise ValueError(f"Unknown type {fem_sec.type}") self._thick_map = thick_map return names_str + sec_str + concept_str