def add(self, node: Node, point_tol: float = Settings.point_tol, allow_coincident: bool = False) -> Node: """Insert node into sorted list""" def insert_node(n, i): new_id = int(self._maxid + 1) if len(self._nodes) > 0 else 1 if n.id in self._idmap.keys() or n.id is None: n.id = new_id self._nodes.insert(i, n) self._idmap[n.id] = n self._bbox = None self._maxid = n.id if n.id > self._maxid else self._maxid index = bisect_left(self._nodes, node) if (len(self._nodes) != 0) and allow_coincident is False: res = self.get_by_volume(node.p, tol=point_tol) if len(res) == 1: nearest_node = res[0] vlen = vector_length(nearest_node.p - node.p) if vlen < point_tol: logging.debug( f'Replaced new node with node id "{nearest_node.id}" found within point tolerances' ) return nearest_node insert_node(node, index) if node.parent is None: node.parent = self.parent return node
def add_rp(self, name: str, node: Node): """Adds a reference point in assembly with a specific name""" node.parent = self node_ = self.ref_points.add(node) fem_set = self.ref_sets.add(FemSet(name, [node_], "nset", parent=self)) fem_set.metadata["internal"] = True return node_, fem_set
def getnodes(m): d = m.groupdict() res = np.fromstring(list_cleanup(d["members"]), sep=",", dtype=np.float64) res_ = res.reshape(int(res.size / 4), 4) members = [Node(n[1:4], int(n[0]), parent=parent) for n in res_] if d["nset"] is not None: parent.sets.add(FemSet(d["nset"], members, "nset", parent=parent)) return members
def to_fem_obj( self, mesh_size: float, bm_repr=ElemType.LINE, pl_repr=ElemType.SHELL, shp_repr=ElemType.SOLID, options: GmshOptions = None, silent=True, interactive=False, use_quads=False, use_hex=False, ) -> FEM: from ada import Beam, Plate, Shape from ada.fem.meshing import GmshOptions, GmshSession options = GmshOptions(Mesh_Algorithm=8) if options is None else options masses: List[Shape] = [] with GmshSession(silent=silent, options=options) as gs: for obj in self.get_all_physical_objects(sub_elements_only=False): if type(obj) is Beam: gs.add_obj(obj, geom_repr=bm_repr.upper(), build_native_lines=False) elif type(obj) is Plate: gs.add_obj(obj, geom_repr=pl_repr.upper()) elif issubclass(type(obj), Shape) and obj.mass is not None: masses.append(obj) elif issubclass(type(obj), Shape): gs.add_obj(obj, geom_repr=shp_repr.upper()) else: logger.error( f'Unsupported object type "{obj}". Should be either plate or beam objects' ) # if interactive is True: # gs.open_gui() gs.split_plates_by_beams() gs.mesh(mesh_size, use_quads=use_quads, use_hex=use_hex) if interactive is True: gs.open_gui() fem = gs.get_fem() for mass_shape in masses: cog_absolute = mass_shape.placement.absolute_placement( ) + mass_shape.cog n = fem.nodes.add(Node(cog_absolute)) fem.add_mass(Mass(f"{mass_shape.name}_mass", [n], mass_shape.mass)) return fem
def add(self, joint: JointBase, point_tol=Settings.point_tol): if joint.name is None: raise Exception("Name is not allowed to be None.") if joint.name in self._dmap.keys(): raise ValueError("Joint Exists with same name") new_node = Node(joint.centre) node = self._joint_centre_nodes.add(new_node, point_tol=point_tol) if node != new_node: return self._nmap[node] else: self._nmap[node] = joint joint.parent = self self._dmap[joint.name] = joint self._connections.append(joint)
def get_node(m, parent): d = m.groupdict() return Node([float(d["x"]), float(d["y"]), float(d["z"])], str_to_int(d["id"]), parent=parent)
def get_nodes_from_cache(node_group, parent): points_in = node_group[()] points = [Node(n[1:], n[0]) for n in points_in] return Nodes(points, parent=parent)
def __init__( self, name, n1: Union[Node, Iterable] = None, n2: Union[Node, Iterable] = None, sec: Union[str, Section] = None, mat: Union[str, Material] = None, tap: Union[str, Section] = None, jusl=JUSL_TYPES.NA, up=None, angle=0.0, curve: Union[CurvePoly, CurveRevolve] = None, e1=None, e2=None, colour=None, parent: Part = None, metadata=None, opacity=1.0, units="m", ifc_elem=None, guid=None, placement=Placement(), ifc_ref: IfcRef = None, ): super().__init__( name, metadata=metadata, units=units, guid=guid, ifc_elem=ifc_elem, placement=placement, ifc_ref=ifc_ref, colour=colour, opacity=opacity, ) if curve is not None: curve.parent = self if type(curve) is CurvePoly: n1 = curve.points3d[0] n2 = curve.points3d[-1] elif type(curve) is CurveRevolve: n1 = curve.p1 n2 = curve.p2 else: raise ValueError(f'Unsupported curve type "{type(curve)}"') self._curve = curve self._n1 = n1 if type(n1) is Node else Node(n1[:3], units=units) self._n2 = n2 if type(n2) is Node else Node(n2[:3], units=units) self._jusl = jusl self._connected_to = [] self._connected_end1 = None self._connected_end2 = None self._tos = None self._e1 = e1 self._e2 = e2 self._hinge_prop = None self._parent = parent self._bbox = None # Section and Material setup self._section, self._taper = get_section(sec) self._section.refs.append(self) self._taper.refs.append(self) self._material = get_material(mat) self._material.refs.append(self) if tap is not None: self._taper, _ = get_section(tap) self._section.parent = self self._taper.parent = self # Define orientations self._init_orientation(angle, up) self.add_beam_to_node_refs()
def n2(self, new_node: Node): self._n2.remove_obj_from_refs(self) self._n2 = new_node.get_main_node_at_point() self._n2.add_obj_to_refs(self)
def get_by_volume(self, p=None, vol_box=None, vol_cyl=None, tol=Settings.point_tol) -> List[Node]: """ :param p: Point :param vol_box: Additional point to find nodes inside a rectangular box :param vol_cyl: (radius, height, cylinder thickness). Note! Radius is measured to outside of cylinder wall :param tol: Point tolerance :return: """ p = np.array(p) if type(p) is (list, tuple) else p if p is not None and vol_cyl is None and vol_box is None: vol = [(coord - tol, coord + tol) for coord in p] elif vol_box is not None: vol = list(zip(p, vol_box)) elif vol_cyl is not None and p is not None: r, h, t = vol_cyl vol = [ (p[0] - r - tol, p[0] + r + tol), (p[1] - r - tol, p[1] + r + tol), (p[2] - tol, p[2] + tol + h), ] else: raise Exception("No valid search input provided. None is returned") vol_min, vol_max = zip(*vol) xmin = bisect_left(self._nodes, Node(vol_min)) xmax = bisect_right(self._nodes, Node(vol_max)) xlist = sorted(self._nodes[xmin:xmax], key=attrgetter("y")) ysorted = [n.y for n in xlist] ymin = bisect_left(ysorted, vol_min[1]) ymax = bisect_right(ysorted, vol_max[1]) ylist = sorted(xlist[ymin:ymax], key=attrgetter("z")) zsorted = [n.z for n in ylist] zmin = bisect_left(zsorted, vol_min[2]) zmax = bisect_right(zsorted, vol_max[2]) simplesearch = ylist[zmin:zmax] if vol_cyl is not None: r, h, t = vol_cyl pt1_ = p + np.array([0, 0, -h]) pt2_ = p + np.array([0, 0, +h]) def eval_p_in_cyl(no): if t == r: if points_in_cylinder(pt1_, pt2_, r, no.p) is True: return no else: eval1 = points_in_cylinder(pt1_, pt2_, r + t, no.p) eval2 = points_in_cylinder(pt1_, pt2_, r - t, no.p) if eval1 is True and eval2 is False: return no return None return list(filter(None, [eval_p_in_cyl(q) for q in simplesearch])) else: return list(simplesearch)
def _np_array_to_nlist(self, np_array): from ada import Node return [ Node(row[1:], int(row[0]), parent=self._parent) for row in np_array ]
def to_node(data): return Node(data[1], data[0])