def MATERIAL_ID(self): self._dict["material_id"] = gen_std_mat_id(self.ELEMENTS)
def convert_meshio( mesh, ignore_unknown=False, import_dim=(1, 2, 3), element_id_name="element_id", material_id_name="material_id", ): """ Convert points and cells from meshio to ogs format. Parameters ---------- mesh : meshio mesh class The given mesh by meshio ignore_unknown : bool, optional Unknown data in the file will be ignored. Default: False import_dim : iterable of int or single int, optional State which elements should be imported by dimensionality. Default: (1, 2, 3) element_id_name : str, optional The name of the cell-data containing the element IDs if present. Default: "element_id" material_id_name : str, optional The name of the cell-data containing the material IDs if present. Default: "material_id" Returns ------- out : dict dictionary contains one '#FEM_MSH' block of the mesh file with the following information mesh_data : dictionary containing information about Is empty by default and can be filled later. nodes : ndarray Array with all node postions elements : dictionary contains array of nodes for elements sorted by element types material_id : dictionary contains material ids for each element sorted by element types element_id : dictionary contains element ids for each element sorted by element types Notes ----- This routine uses the meshio data structure. (see here: https://github.com/nschloe/meshio) If there is any "vertex" in the element data, it will be removed. """ nodes = mesh.points cells = mesh.cells_dict cell_data = mesh.cell_data_dict print(cells) print(cell_data) if not isinstance(import_dim, (set, list, tuple)): import_dim = [import_dim] # remove 0D elements if "vertex" in cells: del cells["vertex"] # check if element types are supported keylist = np.array(list(cells)) keys = [key in MESHIO_NAMES for key in keylist] valid = all(keys) if not valid: print("Some element types in the file are not supported by OGS:") print(keylist[np.logical_not(keys)]) if ignore_unknown: print("... but they will be ignored") else: raise ValueError("import_mesh: Unsupported element types") elements = {} material_id = {} element_id = {} for elm_i, elm_e in enumerate(MESHIO_NAMES): if elm_e not in cells: continue elements[ELEM_NAMES[elm_i]] = cells[elm_e] if material_id_name in cell_data: material_id[ELEM_NAMES[elm_i]] = cell_data[material_id_name][elm_e] if element_id_name in cell_data: element_id[ELEM_NAMES[elm_i]] = cell_data[element_id_name][elm_e] if not material_id: material_id = gen_std_mat_id(elements) if not element_id: element_id = gen_std_elem_id(elements) out = { "mesh_data": {}, "nodes": nodes, "elements": elements, "material_id": material_id, "element_id": element_id, } rem_dim = {1, 2, 3} - set(import_dim) remove_dim(out, rem_dim) return out
def MATERIAL_ID(self, value): if isinstance(value, int): self._dict["material_id"] = gen_std_mat_id(self.ELEMENTS, value) else: self._dict["material_id"] = value
def grid_adapter3D( out_dim=(100.0, 100.0), in_dim=(50.0, 50.0), z_dim=-10.0, out_res=(10.0, 10.0, 10.0), in_res=(5.0, 5.0, 5.0), out_pos=(0.0, 0.0), in_pos=(25.0, 25.0), z_pos=0.0, in_mat=0, out_mat=0, fill=False, ): """ Generate a grid adapter. 3D adapter from an outer grid resolution to an inner grid resolution with gmsh. Parameters ---------- out_dim : list of 2 float xy-Dimension of the outer block in_dim : list of 2 float xy-Dimension of the inner block z_dim : float z-Dimension of the whole block out_res : list of 3 float Grid resolution of the outer block in_res : list of 3 float Grid resolution of the inner block out_pos : list of 2 float xy-Position of the origin of the outer block in_pos : list of 2 float xy-Position of the origin of the inner block z_dim : float z-Position of the origin of the whole block in_mat : integer Material-ID of the inner block out_mat : integer Material-ID of the outer block fill : bool, optional State if the inner block should be filled with a rectangular mesh. Default: False. Returns ------- result : dictionary Result contains one '#FEM_MSH' block of the OGS mesh file with the following information (sorted by keys): mesh_data : dict dictionary containing information about - AXISYMMETRY (bool) - CROSS_SECTION (bool) - PCS_TYPE (str) - GEO_TYPE (str) - GEO_NAME (str) - LAYER (int) nodes : ndarray Array with all node postions elements : dict contains nodelists for elements sorted by element types material_id : dict contains material ids for each element sorted by element types element_id : dict contains element ids for each element sorted by element types """ out = gmsh( gmsh_grid_adapt3D(out_dim, in_dim, z_dim, out_res, in_res, out_pos, in_pos, z_pos), import_dim=3, ) out["material_id"] = gen_std_mat_id(out["elements"], out_mat) if fill: element_no = [ int(in_dim[0] / in_res[0]), int(in_dim[1] / in_res[1]), int(abs(z_dim) / in_res[2]), ] mesh_in = rectangular( dim=3, mesh_origin=in_pos + (z_pos + min(z_dim, 0.0), ), element_no=element_no, element_size=in_res, ) mesh_in["material_id"] = gen_std_mat_id(mesh_in["elements"], in_mat) dec = int(np.ceil(-np.log10(min(min(in_res), min(out_res)))) + 2.0) * 2 out = combine(mesh_in, out, dec) return out
def rectangular( dim=2, mesh_origin=(0.0, 0.0, 0.0), element_no=(10, 10, 10), element_size=(1.0, 1.0, 1.0), ): """ Generate a rectangular grid in 2D or 3D. Parameters ---------- dim : int, optional Dimension of the resulting mesh, either 2 or 3. Default: 3 mesh_origin : list of float, optional Origin of the mesh Default: [0.0, 0.0, 0.0] element_no : list of int, optional Number of elements in each direction. Default: [10, 10, 10] element_size : list of float, optional Size of an element in each direction. Default: [1.0 ,1.0 ,1.0] Returns ------- result : dictionary Result contains one '#FEM_MSH' block of the OGS mesh file with the following information (sorted by keys): mesh_data : dict dictionary containing information about - AXISYMMETRY (bool) - CROSS_SECTION (bool) - PCS_TYPE (str) - GEO_TYPE (str) - GEO_NAME (str) - LAYER (int) nodes : ndarray Array with all node postions elements : dict contains nodelists for elements sorted by element types material_id : dict contains material ids for each element sorted by element types element_id : dict contains element ids for each element sorted by element types """ x_no = element_no[0] dx = element_size[0] x0 = mesh_origin[0] y_no = element_no[1] dy = element_size[1] y0 = mesh_origin[1] if len(mesh_origin) > 2: z0 = mesh_origin[2] else: z0 = 0.0 if dim == 2: z_no = 0 dz = 0.0 node_no = (x_no + 1) * (y_no + 1) node_per_elem = 4 element_no = x_no * y_no elif dim == 3: z_no = element_no[2] dz = element_size[2] node_no = (x_no + 1) * (y_no + 1) * (z_no + 1) node_per_elem = 8 element_no = x_no * y_no * z_no else: raise ValueError("generator.rectangular: dim has to be either 2 or 3") node_arr = np.zeros((node_no, 3)) element_arr = np.zeros((element_no, node_per_elem), dtype=int) node_arr[:, 0] = (dx * ((np.arange(node_no) % ((x_no + 1) * (y_no + 1))) % (x_no + 1)) + x0) node_arr[:, 1] = (dy * ((np.arange(node_no) % ((x_no + 1) * (y_no + 1))) // (x_no + 1)) + y0) node_arr[:, 2] = (dz * (np.arange(node_no) // ((x_no + 1) * (y_no + 1))) + z0) if dim == 2: element_arr[:, 0] = np.arange(element_no) element_arr[:, 0] += np.arange(element_no) // (x_no) element_arr[:, 1] = element_arr[:, 0] + 1 element_arr[:, 2] = element_arr[:, 0] element_arr[:, 2] += 2 + x_no element_arr[:, 3] = element_arr[:, 2] - 1 element_dict = {"quad": element_arr} else: element_arr[:, 0] = np.arange(element_no) element_arr[:, 0] += (x_no + y_no + 1) * (np.arange(element_no) // (x_no * y_no)) element_arr[:, 0] += (np.arange(element_no) % (x_no * y_no)) // (x_no) element_arr[:, 1] = element_arr[:, 0] + 1 element_arr[:, 2] = element_arr[:, 0] element_arr[:, 2] += 2 + x_no element_arr[:, 3] = element_arr[:, 2] - 1 element_arr[:, 4] = element_arr[:, 0] element_arr[:, 4] += (1 + x_no) * (1 + y_no) element_arr[:, 5] = element_arr[:, 4] + 1 element_arr[:, 6] = element_arr[:, 4] element_arr[:, 6] += 2 + x_no element_arr[:, 7] = element_arr[:, 6] - 1 element_dict = {"hex": element_arr} out = { "mesh_data": {}, "nodes": node_arr, "elements": element_dict, "material_id": gen_std_mat_id(element_dict), "element_id": gen_std_elem_id(element_dict), } return out
def radial( dim=3, mesh_origin=(0.0, 0.0, 0.0), angles=16, rad=np.arange(11), z_arr=-np.arange(2), ): """ Generate a radial grid in 2D or 3D. Parameters ---------- dim : int, optional Dimension of the resulting mesh, either 2 or 3. Default: 3 mesh_origin : list of float, optional Origin of the mesh Default: [0.0, 0.0, 0.0] angles : int, optional Number of elements in each direction. Default: [10, 10, 10] rad : array, optional array of radii to set in the mesh z_arr : array, optional array of z values to set the layers in the mesh (only needed for dim=3) needs to be sorted in negative z direction Returns ------- result : dictionary Result contains one '#FEM_MSH' block of the OGS mesh file with the following information (sorted by keys): mesh_data : dict dictionary containing information about - AXISYMMETRY (bool) - CROSS_SECTION (bool) - PCS_TYPE (str) - GEO_TYPE (str) - GEO_NAME (str) - LAYER (int) nodes : ndarray Array with all node postions elements : dict contains nodelists for elements sorted by element types material_id : dict contains material ids for each element sorted by element types element_id : dict contains element ids for each element sorted by element types """ if z_arr is not None and dim > 2: assert (all(z_arr[i] > z_arr[i + 1] for i in range(len(z_arr) - 1))) or (all( z_arr[i] < z_arr[i + 1] for i in range(len(z_arr) - 1))), "The z-array needs to be sorted" # flip the z_array if it is sorted downwards if all(z_arr[i] > z_arr[i + 1] for i in range(len(z_arr) - 1)): z_arr = z_arr[::-1] assert all(rad[i] < rad[i + 1] for i in range(len(rad) - 1)), "The radii need to be sorted" if len(mesh_origin) > 2: x0, y0, z0 = mesh_origin else: x0, y0, z0 = mesh_origin + (0.0, ) if float(rad[0]) == 0.0: closed = True rad = rad[1:] else: closed = False r_no = len(rad) if z_arr is not None and dim > 2: z_no = len(z_arr) else: z_no = 0 lay_no = r_no * angles if dim == 2: node_no = angles * r_no element_no = angles * (r_no - 1) if closed: node_no += 1 elem_mid_arr = np.zeros((angles, 3), dtype=np.int) element_arr = np.zeros((element_no, 4), dtype=np.int) node_arr = np.zeros((node_no, 3)) for ri, re in enumerate(rad): for n in range(angles): no = n + ri * angles node_arr[no, :] = [ x0 + re * np.cos(n / angles * 2 * np.pi), y0 + re * np.sin(n / angles * 2 * np.pi), z0, ] if closed: node_arr[-1, :] = [x0, y0, z0] element_arr[:, 0] = np.arange(element_no) element_arr[:, 3] = np.arange(element_no) // angles * angles element_arr[:, 3] += (np.arange(element_no) % angles + 1) % angles element_arr[:, 2] = element_arr[:, 3] + angles element_arr[:, 1] = element_arr[:, 0] + angles element_dict = {"quad": element_arr} if len(rad) > 1 else {} if closed: elem_mid_arr[:, 0] = np.arange(angles) elem_mid_arr[:, 1] = (np.arange(angles) + 1) % angles elem_mid_arr[:, 2] = node_no - 1 element_dict["tri"] = elem_mid_arr elif dim == 3: node_no = angles * r_no * z_no element_no = angles * (r_no - 1) * (z_no - 1) if closed: node_no += z_no elem_mid_arr = np.zeros((angles * (z_no - 1), 6), dtype=np.int) element_arr = np.zeros((element_no, 8), dtype=np.int) node_arr = np.zeros((node_no, 3)) # write nodes for z in range(z_no): for ri, re in enumerate(rad): for n in range(angles): no = n + ri * angles + z * r_no * angles node_arr[no, :] = [ x0 + re * np.cos(n / angles * 2 * np.pi), y0 + re * np.sin(n / angles * 2 * np.pi), z0 + z_arr[z], ] # add center as last points if closed: node_arr[-z_no:, 0] = x0 node_arr[-z_no:, 1] = y0 node_arr[-z_no:, 2] = z_arr # write elements for z in range(z_no - 1): for r in range(r_no - 1): for n in range(angles): no = n + r * angles + z * (r_no - 1) * angles no1 = n + r * angles + z * r_no * angles no2 = no1 + angles no4 = (n + 1) % angles + r * angles + z * r_no * angles no3 = no4 + angles element_arr[no, :] = [ no1, no2, no3, no4, no1 + lay_no, no2 + lay_no, no3 + lay_no, no4 + lay_no, ] element_dict = {"hex": element_arr} if len(rad) > 1 else {} # add the center pris if closed: for z in range(z_no - 1): for n in range(angles): no = n + z * angles no1 = n + z * r_no * angles no2 = node_no - z_no + z no3 = (n + 1) % angles + z * r_no * angles elem_mid_arr[no, :] = [ no1 + lay_no, no2 + 1, no3 + lay_no, no1, no2, no3, ] element_dict["pris"] = elem_mid_arr out = { "mesh_data": {}, "nodes": node_arr, "elements": element_dict, "material_id": gen_std_mat_id(element_dict), "element_id": gen_std_elem_id(element_dict), } return out
def grid_adapter2D( out_dim=(100.0, 100.0), in_dim=(50.0, 50.0), out_res=(10.0, 10.0), in_res=(1.0, 1.0), out_pos=(0.0, 0.0), in_pos=(25.0, 25.0), z_pos=0.0, in_mat=0, out_mat=0, fill=False, ): """ generate a grid adapter in 2D from an outer grid resolution to an inner grid resolution with gmsh. Parameters ---------- out_dim : list of 2 float xy-Dimension of the outer block in_dim : list of 2 float xy-Dimension of the inner block out_res : list of 2 float Grid resolution of the outer block in_res : list of 2 float Grid resolution of the inner block out_pos : list of 2 float xy-Position of the origin of the outer block in_pos : list of 2 float xy-Position of the origin of the inner block z_pos : float z-Position of the origin of the whole block in_mat : integer Material-ID of the inner block out_mat : integer Material-ID of the outer block fill : bool, optional State if the inner block should be filled with a rectangular mesh. Default: False. Returns ------- result : dictionary Result contains one '#FEM_MSH' block of the OGS mesh file with the following information (sorted by keys): mesh_data : dict dictionary containing information about - AXISYMMETRY (bool) - CROSS_SECTION (bool) - PCS_TYPE (str) - GEO_TYPE (str) - GEO_NAME (str) - LAYER (int) nodes : ndarray Array with all node postions elements : dict contains nodelists for elements sorted by element types material_id : dict contains material ids for each element sorted by element types element_id : dict contains element ids for each element sorted by element types """ import pygmsh as pg geo = gmsh_grid_adapt2D( out_dim, in_dim, out_res, in_res, out_pos, in_pos, z_pos ) points, cells, __, __, __ = pg.generate_mesh( geo, # num_lloyd_steps=0, # num_quad_lloyd_steps=0, dim=2, ) out = convert_meshio(points, cells, import_dim=2) out["material_id"] = gen_std_mat_id(out["elements"], out_mat) if fill: element_no = [int(in_dim[0] / in_res[0]), int(in_dim[1] / in_res[1])] mesh_in = rectangular( dim=2, mesh_origin=in_pos + (z_pos,), element_no=element_no, element_size=in_res, ) mesh_in["material_id"] = gen_std_mat_id(mesh_in["elements"], in_mat) out = combine(mesh_in, out) return out