def add_tets_from_mesh(structure, name, mesh, draw_tets=False, volume=None, thermal=False): """ Adds tetrahedron elements from a mesh to the Structure object. Parameters ---------- structure : obj Structure object to update. name : str Name for the element set of tetrahedrons. mesh : obj The Blender mesh representing the outer surface. draw_tets : bool Layer to draw tetrahedrons on. volume : float Maximum volume for tets. thermal : bool Thermal properties on or off. Returns ------- None """ blendermesh = BlenderMesh(mesh) vertices = blendermesh.get_vertices_coordinates().values() faces = blendermesh.get_faces_vertex_indices().values() try: tets_points, tets_elements = tets_from_vertices_faces(vertices=vertices, faces=faces, volume=volume) for point in tets_points: structure.add_node(point) ekeys = [] for element in tets_elements: nodes = [structure.check_node_exists(tets_points[i]) for i in element] ekey = structure.add_element(nodes=nodes, type='TetrahedronElement', thermal=thermal) ekeys.append(ekey) structure.add_set(name=name, type='element', selection=ekeys) if draw_tets: tet_faces = [[0, 1, 2], [1, 3, 2], [1, 3, 0], [0, 2, 3]] for i, points in enumerate(tets_elements): xyz = [tets_points[j] for j in points] draw_mesh(name=str(i), vertices=xyz, faces=tet_faces, layer=draw_tets) print('***** MeshPy (TetGen) successfull *****') except: print('***** Error using MeshPy (TetGen) or drawing Tets *****')
def add_elset_from_bmeshes(structure, name, bmeshes=None, layer=None): """ Adds the Blender meshes' edges and faces as an element set. Parameters ---------- structure : obj Structure object to update. name : str Name of the new element set. bmeshes : list Blender mesh objects to extract edges and faces. layer : int Layer to get bmeshes from if bmeshes are not given. Returns ------- None Notes ----- - Either bmeshes or layer should be given, not both. """ if layer is not None: bmeshes = [ object for object in get_objects(layer=layer) if object.type == 'MESH' ] elements = [] for bmesh in bmeshes: blendermesh = BlenderMesh(bmesh) vertices = blendermesh.get_vertex_coordinates() edges = blendermesh.get_edge_vertex_indices() faces = blendermesh.get_face_vertex_indices() for u, v in edges: sp = structure.check_node_exists(vertices[u]) ep = structure.check_node_exists(vertices[v]) element = structure.check_element_exists([sp, ep]) if element is not None: elements.append(element) for face in faces: nodes = [structure.check_node_exists(vertices[i]) for i in face] element = structure.check_element_exists(nodes) if element is not None: elements.append(element) structure.add_set(name=name, type='element', selection=elements)
def network_from_bmesh(bmesh): """ Create a Network datastructure from a Blender mesh. Parameters: bmesh (obj): Blender mesh object. Returns: obj: Network object. """ blendermesh = BlenderMesh(bmesh) vertices = blendermesh.get_vertex_coordinates() edges = blendermesh.get_edge_vertex_indices() network = Network.from_vertices_and_edges(vertices=vertices, edges=edges) return network
def discretise_mesh(structure, mesh, layer, target, min_angle=15, factor=1): """ Discretise a mesh from an input triangulated coarse mesh into small denser meshes. Parameters ---------- structure : obj Structure object. mesh : obj The object of the Blender input mesh. layer : str Layer name to draw results. target : float Target length of each triangle. min_angle : float Minimum internal angle of triangles. factor : float Factor on the maximum area of each triangle. Returns ------- None """ blendermesh = BlenderMesh(mesh) vertices = list(blendermesh.get_vertices_coordinates().values()) faces = list(blendermesh.get_faces_vertex_indices().values()) try: points, tris = discretise_faces(vertices=vertices, faces=faces, target=target, min_angle=min_angle, factor=factor) for pts, tri in zip(points, tris): bmesh = xdraw_mesh(name='face', vertices=pts, faces=tri, layer=layer) add_nodes_elements_from_bmesh(structure=structure, bmesh=bmesh, mesh_type='ShellElement') except: print('***** Error using MeshPy (Triangle) or drawing faces *****')
def add_nset_from_meshes(structure, layer): """ Adds the Blender meshes' vertices from a layer as a node set. Parameters ---------- structure : obj Structure object to update. layer : str Layer to get meshes. Returns ------- None """ nodes = [] for mesh in get_meshes(layer=layer): for vertex in BlenderMesh(mesh).get_vertices_coordinates().values(): node = structure.check_node_exists(vertex) if node is not None: nodes.append(node) structure.add_set(name=layer, type='node', selection=nodes)
def add_nsets_from_layers(structure, layers): """ Adds node sets from objects in layers. Parameters ---------- structure : obj Structure object to update. layers : list Layers to get objects from. Returns ------- None """ if isinstance(layers, str): layers = [layers] for layer in layers: nodes = [] for point in get_points(layer=layer): nodes.append(structure.check_node_exists(xyz=list(point.location))) for mesh in get_meshes(layer=layer): for vertex in BlenderMesh( mesh).get_vertices_coordinates().values(): node = structure.check_node_exists(xyz=vertex) if node is not None: nodes.append(node) structure.add_set(name=layer, type='node', selection=nodes)
def add_nset_from_bmeshes(structure, name, bmeshes=None, layer=None): """ Adds the Blender meshes' vertices as a node set. Parameters ---------- structure : obj Structure object to update. name : str Name of the new node set. bmeshes : list Blender mesh objects to extract vertices. layer : int Layer to get bmeshes from if bmeshes are not given. Returns ------- None Notes ----- - Either bmeshes or layer should be given, not both. """ if layer is not None: bmeshes = [ object for object in get_objects(layer=layer) if object.type == 'MESH' ] nodes = [] for bmesh in bmeshes: for vertex in BlenderMesh(bmesh).get_vertex_coordinates(): node = structure.check_node_exists(vertex) if node is not None: nodes.append(node) structure.add_set(name=name, type='node', selection=nodes)
def add_nodes_elements_from_bmesh(structure, bmesh, line_type=None, mesh_type=None, thermal=False): """ Adds the Blender mesh's nodes, edges and faces to the Structure object. Parameters ---------- structure : obj Structure object to update. bmesh : obj Blender mesh object. line_type : str Element type for lines (bmesh edges). mesh_type : str Element type for meshes. thermal : bool Thermal properties on or off. Returns ------- list Node keys that were added to the Structure. list Element keys that were added to the Structure. """ blendermesh = BlenderMesh(bmesh) vertices = blendermesh.get_vertices_coordinates() edges = blendermesh.get_edges_vertex_indices() faces = blendermesh.get_faces_vertex_indices() added_nodes = set() added_elements = set() for xyz in vertices.values(): node = structure.add_node(xyz=xyz) added_nodes.add(node) if line_type and edges: ex = get_object_property(object=bmesh, property='ex') ey = get_object_property(object=bmesh, property='ey') axes = {'ex': list(ex) if ex else ex, 'ey': list(ey) if ey else ey} for u, v in edges.values(): sp_xyz = vertices[u] ep_xyz = vertices[v] sp = structure.check_node_exists(sp_xyz) ep = structure.check_node_exists(ep_xyz) ez = subtract_vectors(ep_xyz, sp_xyz) if ex and not ey: ey = cross_vectors(ex, ez) axes['ey'] = ey axes['ez'] = ez ekey = structure.add_element(nodes=[sp, ep], type=line_type, thermal=thermal, axes=axes) if (line_type == 'BeamElement') and (ex is None): if (abs(ez[0]) < 0.0001) and (abs(ez[1]) < 0.0001): print( '***** WARNING: vertical BeamElement with no ex axis, element {0} *****' .format(ekey)) if ekey is not None: added_elements.add(ekey) if mesh_type: if mesh_type in [ 'HexahedronElement', 'TetrahedronElement', 'SolidElement', 'PentahedronElement' ]: nodes = [structure.check_node_exists(i) for i in vertices] ekey = structure.add_element(nodes=nodes, type=mesh_type, thermal=thermal) if ekey is not None: added_elements.add(ekey) else: try: ex = get_object_property(object=bmesh, property='ex') ey = get_object_property(object=bmesh, property='ey') if ex and ey: ez = cross_vectors(ex, ey) else: ez = None except: ex = None ey = None ez = None axes = {'ex': ex, 'ey': ey, 'ez': ez} for face in faces.values(): nodes = [ structure.check_node_exists(vertices[i]) for i in face ] ekey = structure.add_element(nodes=nodes, type=mesh_type, thermal=thermal, axes=axes) if ekey is not None: added_elements.add(ekey) return list(added_nodes), list(added_elements)
def plot_data(structure, step, field='um', layer=None, scale=1.0, radius=0.05, cbar=[None, None], iptype='mean', nodal='mean', mode='', cbar_size=1): """ Plots analysis results on the deformed shape of the Structure. Parameters ---------- structure : obj Structure object. step : str Name of the Step. field : str Field to plot, e.g. 'um', 'sxx', 'sm1'. layer : str Layer name for plotting. scale : float Scale on displacements for the deformed plot. radius : float Radius of the pipe visualisation meshes. cbar : list Minimum and maximum limits on the colorbar. iptype : str 'mean', 'max' or 'min' of an element's integration point data. nodal : str 'mean', 'max' or 'min' for nodal values. mode : int Mode or frequency number to plot, for modal, harmonic or buckling analysis. cbar_size : float Scale on the size of the colorbar. Returns ------- None Notes ----- - Pipe visualisation of line elements is not based on the element section. """ if field in ['smaxp', 'smises']: nodal = 'max' iptype = 'max' elif field in ['sminp']: nodal = 'min' iptype = 'min' # Create and clear Blender layer if not layer: layer = '{0}-{1}{2}'.format(step, field, mode) try: clear_layer(layer) except: create_layer(layer) # Node and element data nodes = structure.nodes_xyz() elements = [ structure.elements[i].nodes for i in sorted(structure.elements, key=int) ] nodal_data = structure.results[step]['nodal'] nkeys = sorted(structure.nodes, key=int) ux = [nodal_data['ux{0}'.format(mode)][i] for i in nkeys] uy = [nodal_data['uy{0}'.format(mode)][i] for i in nkeys] uz = [nodal_data['uz{0}'.format(mode)][i] for i in nkeys] try: data = [nodal_data['{0}{1}'.format(field, mode)][i] for i in nkeys] dtype = 'nodal' except (Exception): data = structure.results[step]['element'][field] dtype = 'element' # Postprocess result = postprocess(nodes, elements, ux, uy, uz, data, dtype, scale, cbar, 1, iptype, nodal) try: toc, U, cnodes, fabs, fscaled, celements, eabs = result U = array(U) print('\n***** Data processed : {0} s *****'.format(toc)) except: print( '\n***** Error encountered during data processing or plotting *****' ) # Plot meshes npts = 8 mesh_faces = [] block_faces = [[0, 1, 2, 3], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [3, 0, 4, 7]] tet_faces = [[0, 2, 1], [1, 2, 3], [1, 3, 0], [0, 3, 2]] pipes = [] mesh_add = [] for element, nodes in enumerate(elements): n = len(nodes) if n == 2: u, v = nodes pipe = draw_cylinder(start=U[u], end=U[v], radius=radius, div=npts, layer=layer) pipes.append(pipe) if dtype == 'element': col1 = col2 = celements[element] elif dtype == 'nodal': col1 = cnodes[u] col2 = cnodes[v] try: blendermesh = BlenderMesh(object=pipe) blendermesh.set_vertices_colors( {i: col1 for i in range(0, 2 * npts, 2)}) blendermesh.set_vertices_colors( {i: col2 for i in range(1, 2 * npts, 2)}) except: pass elif n in [3, 4]: if structure.elements[element].__name__ in [ 'ShellElement', 'MembraneElement' ]: mesh_faces.append(nodes) else: for face in tet_faces: mesh_faces.append([nodes[i] for i in face]) elif n == 8: for block in block_faces: mesh_faces.append([nodes[i] for i in block]) if mesh_faces: bmesh = xdraw_mesh(name='bmesh', vertices=U, faces=mesh_faces, layer=layer) blendermesh = BlenderMesh(bmesh) blendermesh.set_vertices_colors( {i: col for i, col in enumerate(cnodes)}) mesh_add = [bmesh] # Plot colourbar xr, yr, _ = structure.node_bounds() yran = yr[1] - yr[0] if yr[1] - yr[0] else 1 s = yran * 0.1 * cbar_size xmin = xr[1] + 3 * s ymin = yr[0] cmesh = draw_plane(name='colorbar', Lx=s, dx=s, Ly=10 * s, dy=s, layer=layer) set_objects_coordinates(objects=[cmesh], coords=[[xmin, ymin, 0]]) blendermesh = BlenderMesh(object=cmesh) vertices = blendermesh.get_vertices_coordinates().values() y = array(list(vertices))[:, 1] yn = yran * cbar_size colors = colorbar(((y - ymin - 0.5 * yn) * 2 / yn)[:, newaxis], input='array', type=1) blendermesh.set_vertices_colors( {i: j for i, j in zip(range(len(vertices)), colors)}) set_deselect() set_select(objects=pipes + mesh_add + [cmesh]) bpy.context.view_layer.objects.active = cmesh bpy.ops.object.join() h = 0.6 * s for i in range(5): x0 = xmin + 1.2 * s yu = ymin + (5.8 + i) * s yl = ymin + (3.8 - i) * s vu = +max([eabs, fabs]) * (i + 1) / 5. vl = -max([eabs, fabs]) * (i + 1) / 5. draw_text(radius=h, pos=[x0, yu, 0], text='{0:.3g}'.format(vu), layer=layer) draw_text(radius=h, pos=[x0, yl, 0], text='{0:.3g}'.format(vl), layer=layer) draw_text(radius=h, pos=[x0, ymin + 4.8 * s, 0], text='0', layer=layer) draw_text(radius=h, pos=[xmin, ymin + 12 * s, 0], text='Step:{0} Field:{1}'.format(step, field), layer=layer)
__author__ = ['Andrew Liew <*****@*****.**>'] __copyright__ = 'Copyright 2017, BLOCK Research Group - ETH Zurich' __license__ = 'MIT License' __email__ = '*****@*****.**' data = {'numpy': [], 'numba': [], 'nodes': []} for m in range(10, 71, 5): clear_layer(layer=0) # Set-up Network bmesh = draw_plane(dx=1/m, dy=1/m) blendermesh = BlenderMesh(object=bmesh) network = network_from_bmesh(bmesh=bmesh) Pz = 100 / network.number_of_vertices() network.update_default_vertex_attributes({'B': [0, 0, 1], 'P': [0, 0, Pz]}) network.update_default_edge_attributes({'E': 10, 'A': 1, 'ct': 't', 'l0': 1/m}) corners = [key for key in network.vertices() if network.vertex_degree(key) == 2] network.set_vertices_attributes(corners, {'B': [0, 0, 0]}) data['nodes'].append(network.number_of_vertices()) # Numpy-SciPy tic = time() X, f, l = drx_numpy(network=network, tol=0.01) data['numpy'].append(time() - tic)
imp.reload(functions) __author__ = ['Andrew Liew <*****@*****.**>'] __copyright__ = 'Copyright 2018, BLOCK Research Group - ETH Zurich' __license__ = 'MIT License' __email__ = '*****@*****.**' clear_layer(layer=1) # Structure mdl = Structure(name='mesh_tris', path='/home/al/temp/') # Discretise blendermesh = BlenderMesh(get_objects(layer=0)[0]) pts = blendermesh.get_vertex_coordinates() fcs = blendermesh.get_face_vertex_indices() vertices, faces = functions.discretise_faces(vertices=pts, faces=fcs, target=0.1, min_angle=15, factor=1, iterations=50) for pts, fc in zip(vertices, faces): bmesh = xdraw_mesh(name='face', vertices=pts, faces=fc, layer=1, wire=True) blender.add_nodes_elements_from_bmesh(mdl, bmesh=bmesh, mesh_type='ShellElement')
def plot_data(structure, step, field, layer, scale=1.0, radius=0.05, cbar=[None, None], iptype='mean', nodal='mean', mode='', colorbar_size=1): """ Plots analysis results on the deformed shape of the Structure. Parameters ---------- structure : obj Structure object. step : str Name of the Step. field : str Field to plot, e.g. 'um', 'sxx', 'sm1'. layer : int Layer number for plotting. scale : float Scale on displacements for the deformed plot. radius : float Radius of the pipe visualisation meshes. cbar : list Minimum and maximum limits on the colorbar. iptype : str 'mean', 'max' or 'min' of an element's integration point data. nodal : str 'mean', 'max' or 'min' for nodal values. mode : int Mode or frequency number to plot, for modal, harmonic or buckling analysis. colorbar_size : float Scale on the size of the colorbar. Returns ------- None Notes ----- - Pipe visualisation of line elements is not based on the element section. """ clear_layer(layer=layer) # Node and element data nodes = structure.nodes_xyz() elements = [ structure.elements[i].nodes for i in sorted(structure.elements, key=int) ] nodal_data = structure.results[step]['nodal'] nkeys = sorted(structure.nodes, key=int) ux = [nodal_data['ux{0}'.format(mode)][i] for i in nkeys] uy = [nodal_data['uy{0}'.format(mode)][i] for i in nkeys] uz = [nodal_data['uz{0}'.format(mode)][i] for i in nkeys] try: data = [nodal_data['{0}{1}'.format(field, mode)][i] for i in nkeys] dtype = 'nodal' except (Exception): data = structure.results[step]['element'][field] dtype = 'element' # Postprocess result = postprocess(nodes, elements, ux, uy, uz, data, dtype, scale, cbar, 1, iptype, nodal) try: toc, U, cnodes, fabs, fscaled, celements, eabs = result U = array(U) print('\n***** Data processed : {0:.3f} s *****'.format(toc)) except: print( '\n***** Error encountered during data processing or plotting *****' ) # Plot meshes npts = 8 mesh_faces = [] for element, nodes in enumerate(elements): n = len(nodes) if n == 2: u, v = nodes pipe = draw_pipes(start=[U[u]], end=[U[v]], radius=radius, layer=layer)[0] if dtype == 'element': col1 = col2 = [celements[element]] * npts elif dtype == 'nodal': col1 = [cnodes[u]] * npts col2 = [cnodes[v]] * npts blendermesh = BlenderMesh(pipe) blendermesh.set_vertex_colors(vertices=range(0, 2 * npts, 2), colors=col1) blendermesh.set_vertex_colors(vertices=range(1, 2 * npts, 2), colors=col2) elif n in [3, 4]: mesh_faces.append(nodes) if mesh_faces: bmesh = xdraw_mesh(name='bmesh', vertices=U, faces=mesh_faces, layer=layer) blendermesh = BlenderMesh(bmesh) blendermesh.set_vertex_colors(vertices=range(U.shape[0]), colors=cnodes) # Plot colourbar xr, yr, _ = structure.node_bounds() yran = yr[1] - yr[0] if yr[1] - yr[0] else 1 s = yran * 0.1 * colorbar_size xmin = xr[1] + 3 * s ymin = yr[0] cmesh = draw_plane(name='colorbar', Lx=s, dx=s, Ly=10 * s, dy=s, layer=layer) set_object_location(object=cmesh, location=[xmin, ymin, 0]) blendermesh = BlenderMesh(cmesh) verts = blendermesh.get_vertex_coordinates() y = array(verts)[:, 1] yn = yran * colorbar_size colors = colorbar(((y - ymin - 0.5 * yn) * 2 / yn)[:, newaxis], input='array', type=1) blendermesh.set_vertex_colors(vertices=range(len(verts)), colors=colors) h = 0.6 * s texts = [] for i in range(5): x0 = xmin + 1.2 * s yu = ymin + (5.8 + i) * s yl = ymin + (3.8 - i) * s vu = float(+max(eabs, fabs) * (i + 1) / 5.) vl = float(-max(eabs, fabs) * (i + 1) / 5.) texts.extend([{ 'radius': h, 'pos': [x0, yu, 0], 'text': '{0:.3g}'.format(vu), 'layer': layer }, { 'radius': h, 'pos': [x0, yl, 0], 'text': '{0:.3g}'.format(vl), 'layer': layer }]) texts.extend([{ 'radius': h, 'pos': [x0, ymin + 4.8 * s, 0], 'text': '0', 'layer': layer }, { 'radius': h, 'pos': [xmin, ymin + 12 * s, 0], 'text': 'Step:{0} Field:{1}'.format(step, field), 'layer': layer }]) xdraw_texts(texts)
def add_nodes_elements_from_bmesh(structure, bmesh, line_type=None, mesh_type=None, acoustic=False, thermal=False): """ Adds the Blender mesh's nodes, edges and faces to the Structure object. Parameters ---------- structure : obj Structure object to update. bmesh : obj Blender mesh object. line_type : str Element type for lines (bmesh edges). mesh_type : str Element type for meshes. acoustic : bool Acoustic properties on or off. thermal : bool Thermal properties on or off. Returns ------- list Node keys that were added to the Structure. list Element keys that were added to the Structure. """ blendermesh = BlenderMesh(bmesh) vertices = blendermesh.get_vertex_coordinates() edges = blendermesh.get_edge_vertex_indices() faces = blendermesh.get_face_vertex_indices() try: name = blendermesh.guid if name[-5:-3] == '}.': name = name[:-4] except: pass created_nodes = set() created_elements = set() for vertex in vertices: node = structure.add_node(vertex) created_nodes.add(node) if line_type and edges: try: dic = json.loads(name.replace("'", '"')) ex = dic.get('ex', None) ey = dic.get('ey', None) except: ex = None ey = None axes = {'ex': ex, 'ey': ey} for u, v in edges: sp_xyz = vertices[u] ep_xyz = vertices[v] sp = structure.check_node_exists(sp_xyz) ep = structure.check_node_exists(ep_xyz) ez = subtract_vectors(ep_xyz, sp_xyz) if ex and not ey: ey = cross_vectors(ex, ez) axes['ey'] = ey axes['ez'] = ez e = structure.add_element(nodes=[sp, ep], type=line_type, acoustic=acoustic, thermal=thermal, axes=axes) if e is not None: created_elements.add(e) if mesh_type: if mesh_type in [ 'HexahedronElement', 'TetrahedronElement', 'SolidElement', 'PentahedronElement' ]: nodes = [structure.check_node_exists(i) for i in vertices] e = structure.add_element(nodes=nodes, type=mesh_type, acoustic=acoustic, thermal=thermal) if e is not None: created_elements.add(e) else: try: dic = json.loads(name.replace("'", '"')) ex = dic.get('ex', None) ey = dic.get('ey', None) if ex and ey: ez = cross_vectors(ex, ey) else: ez = None except: ex = None ey = None ez = None axes = {'ex': ex, 'ey': ey, 'ez': ez} for face in faces: nodes = [ structure.check_node_exists(vertices[i]) for i in face ] e = structure.add_element(nodes=nodes, type=mesh_type, acoustic=acoustic, thermal=thermal, axes=axes) if e is not None: created_elements.add(e) return list(created_nodes), list(created_elements)
def add_tets_from_bmesh(structure, name, bmesh, draw_tets=False, volume=None, layer=19, acoustic=False, thermal=False): """ Adds tetrahedron elements from a Blender mesh to the Structure object. Parameters ---------- structure : obj Structure object to update. name : str Name for the element set of tetrahedrons. bmesh : obj The Blender mesh representing the outer surface. draw_tets : bool Draw the generated tetrahedrons. volume : float Maximum volume for tets. layer : int Layer to draw tetrahedrons if draw_tets=True. acoustic : bool Acoustic properties on or off. thermal : bool Thermal properties on or off. Returns ------- None """ blendermesh = BlenderMesh(bmesh) vertices = blendermesh.get_vertex_coordinates() faces = blendermesh.get_face_vertex_indices() tets_points, tets_elements = tets_from_vertices_faces(vertices=vertices, faces=faces, volume=volume) for point in tets_points: structure.add_node(point) ekeys = [] for element in tets_elements: nodes = [structure.check_node_exists(tets_points[i]) for i in element] ekey = structure.add_element(nodes=nodes, type='TetrahedronElement', acoustic=acoustic, thermal=thermal) ekeys.append(ekey) structure.add_set(name=name, type='element', selection=ekeys) if draw_tets: tet_faces = [[0, 1, 2], [1, 3, 2], [1, 3, 0], [0, 2, 3]] for i, points in enumerate(tets_elements): xyz = [tets_points[j] for j in points] xdraw_mesh(name=str(i), vertices=xyz, faces=tet_faces, layer=layer)