def QuadBallSphericalArc(center=(0., 0., 0.), inner_radius=9., outer_radius=10., n=10, nthick=1, element_type="hex", cut_threshold=None, portion=1. / 8.): """Similar to QuadBall but hollow and creates only 1/8th or 1/4th or 1/2th of the sphere. Starting and ending angles are not supported. Radial division (nthick: to be consistent with SphericalArc method of Mesh class) is supported input: cut_threshold [float] cutting threshold for element removal since this function is based QuadBall. Ideal value is zero, so prescribe a value as close to zero as possible, however that might not always be possible as the cut might take remove some wanted elements [default = -0.01] portion [float] portion of the sphere to take. Can only be 1/8., 1/4., 1/2. """ assert inner_radius < outer_radius mm = QuadBallSurface(n=n, element_type=element_type) offset = outer_radius * 2. if cut_threshold is None: cut_threshold = -0.01 if portion == 1. / 8.: mm.RemoveElements( np.array([[cut_threshold, cut_threshold, cut_threshold], [offset, offset, offset]])) elif portion == 1. / 4.: mm.RemoveElements( np.array([[cut_threshold, cut_threshold, -offset], [offset, offset, offset]])) elif portion == 1. / 2.: mm.RemoveElements( np.array([[cut_threshold, -offset, -offset], [offset, offset, offset]])) else: raise ValueError("The value of portion can only be 1/8., 1/4. or 1/2.") radii = np.linspace(inner_radius, outer_radius, nthick + 1) mesh = Mesh() mesh.element_type = "hex" mesh.nelem = 0 mesh.nnode = 0 for i in range(nthick): mm1, mm2 = deepcopy(mm), deepcopy(mm) if not np.isclose(radii[i], 1): mm1.points *= radii[i] if not np.isclose(radii[i + 1], 1): mm2.points *= radii[i + 1] if i == 0: elements = np.hstack( (mm1.elements, mm1.nnode + mm2.elements)).astype(np.int64) mesh.elements = np.copy(elements) mesh.points = np.vstack((mm1.points, mm2.points)) else: elements = np.hstack( (mesh.elements[(i - 1) * mm2.nelem:i * mm2.nelem, 4:], mesh.nnode + mm2.elements)).astype(np.int64) mesh.elements = np.vstack((mesh.elements, elements)) mesh.points = np.vstack((mesh.points, mm2.points)) mesh.nelem = mesh.elements.shape[0] mesh.nnode = mesh.points.shape[0] mesh.elements = np.ascontiguousarray(mesh.elements, dtype=np.int64) mesh.nelem = mesh.elements.shape[0] mesh.nnode = mesh.points.shape[0] mesh.GetBoundaryFaces() mesh.GetBoundaryEdges() mesh.points[:, 0] += center[0] mesh.points[:, 1] += center[1] mesh.points[:, 2] += center[2] return mesh
print("The problem requires 2D analyses. Solving", number_of_planar_surfaces, "2D problems") for niter in range(number_of_planar_surfaces): pmesh = Mesh() if mesh.element_type == "tet": pmesh.element_type = "tri" no_face_vertices = 3 elif mesh.element_type == "hex": pmesh.element_type = "quad" no_face_vertices = 4 else: raise ValueError("Curvilinear mesher for element type {} not yet implemented".format(mesh.element_type)) pmesh.elements = mesh.faces[planar_mesh_faces[planar_mesh_faces[:,1]==surface_flags[niter,0],0],:] pmesh.nelem = np.int64(surface_flags[niter,1]) pmesh.GetBoundaryEdges() unique_edges = np.unique(pmesh.edges).astype(nodesDBC.dtype) # Dirichlet2D = np.zeros((unique_edges.shape[0],3)) # nodesDBC2D = np.zeros(unique_edges.shape[0]).astype(np.int64) unique_elements, inv = np.unique(pmesh.elements, return_inverse=True) unique_elements = unique_elements.astype(nodesDBC.dtype) aranger = np.arange(unique_elements.shape[0],dtype=np.uint64) pmesh.elements = aranger[inv].reshape(pmesh.elements.shape) # counter = 0 # for i in unique_edges: # nodesDBC2D[counter] = np.where(nodesDBC==i)[0][0] # Dirichlet2D[counter,:] = Dirichlet[nodesDBC2D[counter],:] # counter += 1 # nodesDBC2D = nodesDBC2D.astype(np.int64)