def SubdivisionCircle(center=(0., 0.), radius=1., nrad=16, ncirc=40, element_type="tri", refinement=False, refinement_level=2): """Creates a mesh on circle using midpoint subdivision. This function is internally called from Mesh.Circle if 'midpoint_subdivision' algorithm is selected """ r = float(radius) h_r = float(radius) / 2. nx = int(ncirc / 4.) ny = int(nrad / 2.) if nx < 3: warn("Number of division in circumferential direction too low") mesh = Mesh() mesh.Rectangle(element_type="quad", lower_left_point=(-1., -1.), upper_right_point=(1., 1.), nx=nx, ny=ny) uv = np.array([ [-1., -1], [1., -1], [1., 1], [-1., 1], ]) t = np.pi / 4 end_points = np.array([ [-h_r * np.cos(t), h_r * np.sin(t)], [h_r * np.cos(t), h_r * np.sin(t)], [r * np.cos(t), r * np.sin(t)], [-r * np.cos(t), r * np.sin(t)], ]) edge_points = mesh.points[np.unique(mesh.edges), :] new_end_points = [] new_end_points.append(end_points[0, :]) new_end_points.append(end_points[1, :]) new_end_points.append(end_points[2, :]) tt = np.linspace(np.pi / 4, 3 * np.pi / 4, nx) x = r * np.cos(tt) y = r * np.sin(tt) interp_p = np.vstack((x, y)).T for i in range(1, len(x) - 1): new_end_points.append([x[i], y[i]]) new_end_points.append(end_points[3, :]) new_end_points = np.array(new_end_points) new_uv = [] new_uv.append(uv[0, :]) new_uv.append(uv[1, :]) new_uv.append(uv[2, :]) L = 0. for i in range(1, interp_p.shape[0]): L += np.linalg.norm(interp_p[i, :] - interp_p[i - 1, :]) interp_uv = [] last_uv = uv[2, :] for i in range(1, interp_p.shape[0] - 1): val = (uv[3, :] - uv[2, :]) * np.linalg.norm( interp_p[i, :] - interp_p[i - 1, :]) / L + last_uv last_uv = np.copy(val) interp_uv.append(val) interp_uv = np.array(interp_uv) new_uv = np.array(new_uv) if interp_uv.shape[0] != 0: new_uv = np.vstack((new_uv, interp_uv)) new_uv = np.vstack((new_uv, uv[3, :])) from Florence.FunctionSpace import MeanValueCoordinateMapping new_points = np.zeros_like(mesh.points) for i in range(mesh.nnode): point = MeanValueCoordinateMapping(mesh.points[i, :], new_uv, new_end_points) new_points[i, :] = point mesh.points = new_points rmesh = deepcopy(mesh) rmesh.points = mesh.Rotate(angle=np.pi / 2., copy=True) mesh += rmesh rmesh.points = rmesh.Rotate(angle=np.pi / 2., copy=True) mesh += rmesh rmesh.points = rmesh.Rotate(angle=np.pi / 2., copy=True) mesh += rmesh mesh.LaplacianSmoothing(niter=10) qmesh = Mesh() qmesh.Rectangle(element_type="quad", lower_left_point=(-h_r * np.cos(t), -h_r * np.sin(t)), upper_right_point=(h_r * np.cos(t), h_r * np.sin(t)), nx=nx, ny=nx) mesh += qmesh mesh.LaplacianSmoothing(niter=20) mesh.points[:, 0] += center[0] mesh.points[:, 1] += center[1] if refinement: mesh.Refine(level=refinement_level) if element_type == "tri": sys.stdout = open(os.devnull, "w") mesh.ConvertQuadsToTris() sys.stdout = sys.__stdout__ return mesh
def SubdivisionArc(center=(0., 0.), radius=1., nrad=16, ncirc=40, start_angle=0., end_angle=np.pi / 2., element_type="tri", refinement=False, refinement_level=2): """Creates a mesh on circle using midpoint subdivision. This function is internally called from Mesh.Circle if 'midpoint_subdivision' algorithm is selected """ if start_angle != 0. and end_angle != np.pi / 2.: raise ValueError( "Subdivision based arc only produces meshes for a quarter-circle arc for now" ) r = float(radius) h_r = float(radius) / 2. nx = int(ncirc / 4.) ny = int(nrad / 2.) if nx < 3: warn("Number of division in circumferential direction too low") mesh = Mesh() mesh.Rectangle(element_type="quad", lower_left_point=(-1., -1.), upper_right_point=(1., 1.), nx=nx, ny=ny) uv = np.array([ [-1., -1], [1., -1], [1., 1], [-1., 1], ]) t = np.pi / 4. end_points = np.array([ [0., h_r * np.sin(t)], [h_r * np.cos(t), h_r * np.sin(t)], [r * np.cos(t), r * np.sin(t)], [0., radius], ]) edge_points = mesh.points[np.unique(mesh.edges), :] new_end_points = [] new_end_points.append(end_points[0, :]) new_end_points.append(end_points[1, :]) new_end_points.append(end_points[2, :]) tt = np.linspace(np.pi / 4, np.pi / 2, nx) x = r * np.cos(tt) y = r * np.sin(tt) interp_p = np.vstack((x, y)).T for i in range(1, len(x) - 1): new_end_points.append([x[i], y[i]]) new_end_points.append(end_points[3, :]) new_end_points = np.array(new_end_points) new_uv = [] new_uv.append(uv[0, :]) new_uv.append(uv[1, :]) new_uv.append(uv[2, :]) L = 0. for i in range(1, interp_p.shape[0]): L += np.linalg.norm(interp_p[i, :] - interp_p[i - 1, :]) interp_uv = [] last_uv = uv[2, :] for i in range(1, interp_p.shape[0] - 1): val = (uv[3, :] - uv[2, :]) * np.linalg.norm( interp_p[i, :] - interp_p[i - 1, :]) / L + last_uv last_uv = np.copy(val) interp_uv.append(val) interp_uv = np.array(interp_uv) new_uv = np.array(new_uv) if interp_uv.shape[0] != 0: new_uv = np.vstack((new_uv, interp_uv)) new_uv = np.vstack((new_uv, uv[3, :])) from Florence.FunctionSpace import MeanValueCoordinateMapping new_points = np.zeros_like(mesh.points) # All nodes barring the ones lying on the arc for i in range(mesh.nnode - nx - 1): point = MeanValueCoordinateMapping(mesh.points[i, :], new_uv, new_end_points) new_points[i, :] = point # The nodes on the arc are not exactly on the arc # so they need to be snapped/clipped tt = np.linspace(np.pi / 4, np.pi / 2, nx + 1)[::-1] x = r * np.cos(tt) y = r * np.sin(tt) new_points[mesh.nnode - nx - 1:, :] = np.vstack((x, y)).T mesh.points = new_points rmesh = deepcopy(mesh) rmesh.points = mesh.Rotate(angle=-np.pi / 2., copy=True) rmesh.points[:, 1] *= -1. mesh += rmesh mesh.LaplacianSmoothing(niter=10) qmesh = Mesh() qmesh.Rectangle(element_type="quad", lower_left_point=(0.0, 0.0), upper_right_point=(h_r * np.cos(t), h_r * np.sin(t)), nx=nx, ny=nx) mesh += qmesh # mesh.LaplacianSmoothing(niter=20) NodeSliderSmootherArc(mesh, niter=20) mesh.points[:, 0] += center[0] mesh.points[:, 1] += center[1] if refinement: mesh.Refine(level=refinement_level) if element_type == "tri": sys.stdout = open(os.devnull, "w") mesh.ConvertQuadsToTris() sys.stdout = sys.__stdout__ return mesh