def test_cubic_interpolation(permute): # we need more points for cubic interpolation coords = np.array([[0.0, 0.0 + np.random.random() * 1.0e-16], [0.0, 1.0 + np.random.random() * 1.0e-16], [1.0, 0.0 + np.random.random() * 1.0e-16], [1.0, 1.0 + np.random.random() * 1.0e-16], [0.1, 0.1 + np.random.random() * 1.0e-16], [0.1, 0.9 + np.random.random() * 1.0e-16], [0.9, 0.1 + np.random.random() * 1.0e-16], [0.9, 0.9 + np.random.random() * 1.0e-16]]) x, y = coords[:, 0], coords[:, 1] mesh = stripy.Triangulation(x, y, permute=permute) Z = mesh.x**2 npts = 7 xi = np.linspace(0.0, 1.0, npts) yi = np.zeros(npts) Zi_linear, ierr = mesh.interpolate_linear(xi, yi, Z) Zi_cubic, ierr = mesh.interpolate_cubic(xi, yi, Z) diff_linear = np.abs(Zi_linear - xi**2).sum() diff_cubic = np.abs(Zi_cubic - xi**2).sum() # check if cubic interpolation is more accurate than linear if diff_cubic < diff_linear: print("PASS! (Interpolation - cubic") else: assert False, "FAIL! (Interpolation - cubic)"
def test_linear_interpolation(permute): coords = np.array([[0.0, 0.0 + np.random.random() * 1.0e-16], [0.0, 1.0 + np.random.random() * 1.0e-16], [1.0, 0.0 + np.random.random() * 1.0e-16], [1.0, 1.0 + np.random.random() * 1.0e-16], [0.5, 0.5 + np.random.random() * 1.0e-16]]) x, y = coords[:, 0], coords[:, 1] mesh = stripy.Triangulation(x, y, permute=permute) Z = mesh.x npts = 5 ix = np.linspace(0.0, 1.0, npts) iy = np.zeros(npts) Zi, ierr = mesh.interpolate_linear(ix, iy, Z) # this should be true # but machine precision may differ so we don't test it # print((Zi == ix).all()) bounded = Zi[0] == ix[0] and Zi[-1] == ix[-1] ascending = (np.diff(Zi) > 0).all() if bounded and ascending: print("PASS! (Interpolation - linear") else: assert False, "FAIL! (Interpolation - linear)"
def test_cubic_interpolation(): # we need more points for cubic interpolation coords = np.array([[0.0, 0.0], \ [0.0, 1.0], \ [1.0, 0.0], \ [1.0, 1.0], \ [0.1, 0.1], \ [0.1, 0.9], \ [0.9, 0.1], \ [0.9, 0.9]]) x, y = coords[:, 0], coords[:, 1] mesh = stripy.Triangulation(x, y) Z = mesh.x**2 npts = 7 ilons = np.linspace(0.0, 1.0, npts) ilats = np.zeros(npts) Zi_linear, ierr = mesh.interpolate_linear(ilons, ilats, Z) Zi_cubic, ierr = mesh.interpolate_cubic(ilons, ilats, Z) diff_linear = np.abs(Zi_linear - ilons**2).sum() diff_cubic = np.abs(Zi_cubic - ilons**2).sum() # check if cubic interpolation is more accurate than linear if diff_cubic < diff_linear: print("PASS! (Interpolation - cubic") else: assert False, "FAIL! (Interpolation - cubic)"
def test_smoothing(permute): # we need more points for cubic interpolation coords = np.array([[0.0, 0.0 + np.random.random() * 1.0e-16], [0.0, 1.0 + np.random.random() * 1.0e-16], [1.0, 0.0 + np.random.random() * 1.0e-16], [1.0, 1.0 + np.random.random() * 1.0e-16], [0.1, 0.1 + np.random.random() * 1.0e-16], [0.1, 0.9 + np.random.random() * 1.0e-16], [0.9, 0.1 + np.random.random() * 1.0e-16], [0.9, 0.9 + np.random.random() * 1.0e-16]]) x, y = coords[:, 0], coords[:, 1] mesh = stripy.Triangulation(x, y, permute=permute) Z = np.ones_like(x) Z[-1] = 0.0 weights = np.ones_like(x) f_smooth, f_derivatives, ierr = mesh.smoothing(Z, weights, 0.05, 1e-2, 1e-5) if (f_smooth.max() - f_smooth.min()) < 1.0: print("PASS! (Smoothing)") else: assert False, "FAIL! (Smoothing)"
def _phiStar_stripy(self, dt, smooth=0.9): import stripy import numpy as np from scipy.spatial import cKDTree import time if self._mswarm == None: self._build_phiStar_swarm(ratio=smooth) mesh = self.phiField.mesh phiStar = mesh.add_variable(dataType="double", nodeDofCount=1) phiNorm = mesh.add_variable(dataType="double", nodeDofCount=1) mswarm_phiStar = self._mswarm_phiStar mswarm = self._mswarm if self._mesh_interpolator_stripy == None: self._mesh_interpolator_stripy = stripy.Triangulation(mesh.data[:, 0], mesh.data[:, 1], permute=True) mesh_interpolator = self._mesh_interpolator_stripy # Consider doing this in 2 half steps ... self._mswarm_advector.integrate(-dt, update_owners=True) mswarm_phiStar.data[:, 0], err = mesh_interpolator.interpolate_cubic( mswarm.particleCoordinates.data[:, 0], mswarm.particleCoordinates.data[:, 1], self.phiField.data) # Restore self._reset_phiStar_swarm() phiStar.data[:] = 0.0 phiNorm.data[:] = 0.0 # Surely this can be optimised (maybe the kdTree (cached) would be quicker / less storage ?) for i, gnode in enumerate(self._mswarm_map.data[:, 0]): node = np.where(mesh.data_nodegId == gnode)[0] phiStar.data[node] += mswarm_phiStar.data[i] phiNorm.data[node] += 1.0 if uw.mpi.size > 1: mswarm.shadow_particles_fetch() for i, gnode in enumerate(self._mswarm_map.data_shadow[:, 0]): node = np.where(mesh.data_nodegId == gnode)[0] phiStar.data[node] += mswarm_phiStar.data_shadow[i, 0] phiNorm.data[node] += 1.0 phiStar.data[np.where(phiNorm.data > 0.0)] /= phiNorm.data[np.where( phiNorm.data > 0.0)] self._phiStar_dirichlet_conditions(phiStar) return phiStar
def test_cartesian_triangulation(): # Create some (semi) random points np.random.seed(0) x = np.random.random(npoints) y = np.random.random(npoints) # interpolation data xi = np.random.random(100) yi = np.random.random(100) rint = np.random.randint(0, len(xi), len(xi)) # triangulation tri = stripy.Triangulation(x, y) assert tri.npoints == npoints return (tri, x, y, xi, yi)
def test_cubic_interpolation_tension(permute): # we need more points for cubic interpolation coords = np.array([[0.0, 0.0 + np.random.random() * 1.0e-16], [0.0, 1.0 + np.random.random() * 1.0e-16], [1.0, 0.0 + np.random.random() * 1.0e-16], [1.0, 1.0 + np.random.random() * 1.0e-16], [0.1, 0.1 + np.random.random() * 1.0e-16], [0.1, 0.9 + np.random.random() * 1.0e-16], [0.9, 0.1 + np.random.random() * 1.0e-16], [0.9, 0.9 + np.random.random() * 1.0e-16]]) x, y = coords[:, 0], coords[:, 1] mesh = stripy.Triangulation(x, y, permute=permute) Z = mesh.x**2 npts = 7 xi = np.linspace(0.0, 1.0, npts) yi = np.zeros(npts) Zi_linear, ierr = mesh.interpolate_linear(xi, yi, Z) Zi_cubic, ierr = mesh.interpolate_cubic(xi, yi, Z) sigma = mesh.get_spline_tension_factors(Z) Zi_cubicT, ierr = mesh.interpolate_cubic(xi, yi, Z, sigma=sigma) sigma.fill(45.) Zi_cubicTmax, ierr = mesh.interpolate_cubic(xi, yi, Z, sigma=sigma) diff_linear = np.abs(Zi_linear - xi**2).sum() diff_cubic = np.abs(Zi_cubic - xi**2).sum() if np.abs(Zi_cubicT - Zi_cubic).any(): print("PASS! (Interpolation - cubic tensioned splines") # check if cubic interpolation with max tension is like linear interpolation elif np.abs(Zi_linear - Zi_cubicTmax).sum() < np.abs(Zi_cubic - Zi_cubicTmax).sum(): print("PASS! (Interpolation - cubic tensioned splines") else: assert False, "FAIL! (Interpolation - cubic tensioned splines)"
def test_derivative(permute): p0 = 0.0 p1 = 1.0 p2 = 2.0 coords = np.array([[p0, -p2 + np.random.random() * 1.0e-16], [-p2, p0 + np.random.random() * 1.0e-16], [p0, p2 + np.random.random() * 1.0e-16], [p2, p0 + np.random.random() * 1.0e-16], [p0, -p1 + np.random.random() * 1.0e-16], [-p1, p0 + np.random.random() * 1.0e-16], [p0, p1 + np.random.random() * 1.0e-16], [p1, p0 + np.random.random() * 1.0e-16], [-p1, -p1 + np.random.random() * 1.0e-16], [-p1, p1 + np.random.random() * 1.0e-16], [p1, p1 + np.random.random() * 1.0e-16], [p1, -p1 + np.random.random() * 1.0e-16], [p0, p0 + np.random.random() * 1.0e-16]]) x, y = coords[:, 0], coords[:, 1] mesh = stripy.Triangulation(x, y, permute=permute) # create a soup bowl Z = mesh.x**2 + mesh.y**2 # derivatives will have a constant gradient dZdx, dZdy = mesh.gradient(Z, nit=10, tol=1e-12) # interpolate onto a straight line ipts = np.linspace(-p2, p2, 5) dZdx_interp, ierr = mesh.interpolate_linear(ipts, ipts * 0, dZdx) dZdy_interp, ierr = mesh.interpolate_linear(ipts * 0, ipts, dZdy) ascending_xi = (np.diff(dZdx_interp) > 0).all() ascending_yi = (np.diff(dZdy_interp) > 0).all() if ascending_xi and ascending_yi: print("PASS! (Derivatives)") else: assert False, "FAIL! (Derivatives)"
def test_nearest_nd_interpolation(permute): coords = np.array([[0.0, 0.0 + np.random.random() * 1.0e-16], [0.0, 1.0 + np.random.random() * 1.0e-16], [1.0, 0.0 + np.random.random() * 1.0e-16], [1.0, 1.0 + np.random.random() * 1.0e-16]]) x, y = coords[:, 0], coords[:, 1] mesh = stripy.Triangulation(x, y, permute=permute) Z = np.linspace(0.0, 10.0, mesh.npoints) ix = x[0] + 0.001 iy = y[0] + 0.001 Zi, ierr = mesh.interpolate_nearest(ix, iy, Z) if Zi == Z[0]: print("PASS! (Interpolation - nearest neighbour)") else: assert False, "FAIL! (Interpolation - nearest neighbour)"
def test_smoothing(): coords = np.array([[0.0, 0.0], \ [0.0, 1.0], \ [1.0, 0.0], \ [1.0, 1.0], \ [0.5, 0.5]]) x, y = coords[:,0], coords[:,1] mesh = stripy.Triangulation(x, y) Z = np.ones_like(x) Z[-1] = 0.0 weights = np.ones_like(x) f_smooth, f_derivatives, ierr = mesh.smoothing(Z, weights, 0.05, 1e-2, 1e-5) if (f_smooth.max() - f_smooth.min()) < 1.0: print("PASS! (Smoothing)") else: assert False, "FAIL! (Smoothing)"
def test_cubic_interpolation_grid(permute): # we need more points for cubic interpolation coords = np.array([[0.0, 0.0 + np.random.random() * 1.0e-16], [0.0, 1.0 + np.random.random() * 1.0e-16], [1.0, 0.0 + np.random.random() * 1.0e-16], [1.0, 1.0 + np.random.random() * 1.0e-16], [0.1, 0.1 + np.random.random() * 1.0e-16], [0.1, 0.9 + np.random.random() * 1.0e-16], [0.9, 0.1 + np.random.random() * 1.0e-16], [0.9, 0.9 + np.random.random() * 1.0e-16]]) x, y = coords[:, 0], coords[:, 1] mesh = stripy.Triangulation(x, y, permute=permute) Z = mesh.x**2 npts = 7 xi = np.linspace(-0.1, 1.1, npts) yi = np.linspace(-0.1, 1.1, npts) xq, yq = np.meshgrid(xi, yi) shape = (npts, npts) Zi_cubic, ierr = mesh.interpolate_cubic(xq.ravel(), yq.ravel(), Z) Zi_cubic_grid = mesh.interpolate_to_grid(xi, yi, Z) sigma = mesh.get_spline_tension_factors(Z, tol=1e-5) Zi_cubic_grid_S = mesh.interpolate_to_grid(xi, yi, Z, sigma=sigma) err_msg = "Interpolate to grid - cubic tensioned splines" np.testing.assert_allclose(Zi_cubic.reshape(shape), Zi_cubic_grid, atol=0.1, err_msg=err_msg) np.testing.assert_allclose(Zi_cubic_grid_S, Zi_cubic_grid, atol=0.5, err_msg=err_msg) assert (Zi_cubic_grid_S != Zi_cubic_grid).any(), err_msg
def test_cubic_interpolation_grid(): # we need more points for cubic interpolation coords = np.array([[0.0, 0.0], \ [0.0, 1.0], \ [1.0, 0.0], \ [1.0, 1.0], \ [0.1, 0.1], \ [0.1, 0.9], \ [0.9, 0.1], \ [0.9, 0.9]]) x, y = coords[:,0], coords[:,1] mesh = stripy.Triangulation(x, y) Z = mesh.x**2 npts = 7 xi = np.linspace(0.0, 1.0, npts) yi = np.linspace(0.0, 1.0, npts) xq, yq = np.meshgrid(xi,yi) shape = (npts, npts) Zi_cubic, ierr = mesh.interpolate_cubic(xq.ravel(), yq.ravel(), Z) Zi_cubic_grid = mesh.interpolate_to_grid(xi, yi, Z) sigma = mesh.get_spline_tension_factors(Z) Zi_cubic_grid_S = mesh.interpolate_to_grid(xi, yi, Z, sigma=sigma) if np.abs(Zi_cubic.reshape(shape) - Zi_cubic_grid).sum() < \ np.abs(Zi_cubic.reshape(shape) - Zi_cubic_grid_S).sum(): # unstructured and grid interpolation works # and applying tension alters the result print("PASS! (Interpolate to grid - cubic tensioned splines") else: assert False, "FAIL! (Interpolate to grid - cubic tensioned splines)"
""" Test Triangulation routines """ print("==========\nTriangulation routines\n==========") # Create some (semi) random points np.random.seed(0) x = np.random.random(npoints) y = np.random.random(npoints) xi = np.random.random(100) yi = np.random.random(100) rint = np.random.randint(0, len(xi), len(xi)) # triangulation tri = stripy.Triangulation(x, y) for refine in range(max_refinements): print("\nrefinement = {}\n".format(refine)) time_routine(tri.__init__, x, y, refine, permute) z = np.hypot(tri.x, tri.y) time_routine(tri.areas) time_routine(tri.convex_hull) time_routine(tri.gradient, z) time_routine(tri.gradient_local, z, 0) time_routine(tri.interpolate_nearest, xi, yi, z) time_routine(tri.interpolate_linear, xi, yi, z) time_routine(tri.interpolate_cubic, xi, yi, z) time_routine(tri.nearest_vertex, xi, yi)
def _phiStar_stripy_old(self, dt): import stripy import numpy as np from scipy.spatial import cKDTree mesh = self.phiField.mesh surface = mesh.specialSets["surface_VertexSet"] phiStar = mesh.add_variable(dataType="double", nodeDofCount=1) phiNorm = mesh.add_variable(dataType="double", nodeDofCount=1) if self._mesh_interpolator_stripy == None: self._mesh_interpolator_stripy = stripy.Triangulation(mesh.data[:, 0], mesh.data[:, 1], permute=True) mesh_interpolator = self._mesh_interpolator_stripy # The swarm info can also be cached ! mswarm = uw.swarm.Swarm(mesh, particleEscape=True) mswarm_map = mswarm.add_variable(dataType="int", count=1) mswarm_home_pts = mswarm.add_variable(dataType="double", count=mesh.dim) mcoords = mesh.data.copy() # layout = uw.swarm.layouts.PerCellGaussLayout(mswarm, gaussPointCount=5) # mswarm.populate_using_layout(layout) local_nId = -1 * np.ones(mesh.nodesGlobal, dtype=np.int) for i, gId in enumerate(mesh.data_nodegId): local_nId[gId] = i element_centroids = mesh.data[local_nId[mesh.data_elementNodes]].mean( axis=1) element_centroids2 = element_centroids.reshape( tuple((*element_centroids.shape, 1))) element_coords = mesh.data[local_nId[ mesh.data_elementNodes]].transpose(0, 2, 1) swarm_coords = (element_coords - element_centroids2) * 0.8 + element_centroids2 swarm_coords2 = swarm_coords.transpose(0, 2, 1).reshape(-1, 2) localID = mswarm.add_particles_with_coordinates(swarm_coords2) accepted = np.where(localID != -1) mswarm_map.data[:] = mesh.data_elementNodes.reshape(-1, 1)[accepted] mswarm_home_pts.data[:] = mswarm.particleCoordinates.data[accepted] # mcoords[surface,:] *= 0.9999 # localID = mswarm.add_particles_with_coordinates(mcoords) # not_accepted = np.where(localID == -1) print("A{}: mswarm has {} particles ({} local)".format( uw.mpi.rank, mswarm.particleGlobalCount, mswarm.particleLocalCount)) morig_coords = mswarm.add_variable("double", mesh.dim) morig_coords.data[...] = mswarm.particleCoordinates.data[...] mswarm_Tstar = mswarm.add_variable(dataType="float", count=1) madvector = uw.systems.SwarmAdvector(velocityField=self.vField, swarm=mswarm) madvector.integrate(-dt, update_owners=True) # madvector.integrate(-dt*0.5, update_owners=True) print("B{}: mswarm has {} particles ({} local)".format( uw.mpi.rank, mswarm.particleGlobalCount, mswarm.particleLocalCount)) # mswarm_Tstar.data[:,0], err = mesh_interpolator.interpolate_cubic(mswarm.particleCoordinates.data[:,0], # mswarm.particleCoordinates.data[:,1], # self.phiField.data) # mswarm_Tstar.data[:] = self.phiField.evaluate(mswarm) ## mswarm_Tstar.data[:,0] = mswarm.particleCoordinates.data[:,0] # Restore with mswarm.deform_swarm(): mswarm.particleCoordinates.data[:] = mswarm_home_pts.data[:] phiStar.data[:] = 0.0 phiNorm.data[:] = 0.0 # Surely this can be optimised (maybe the kdTree (cached) would be quicker / less storage ?) for i, gnode in enumerate(mswarm_map.data[:, 0]): node = np.where(mesh.data_nodegId == gnode)[0] phiStar.data[node] += mswarm_Tstar.data[i] phiNorm.data[node] += 1.0 if uw.mpi.size > 1: mswarm.shadow_particles_fetch() for i, gnode in enumerate(mswarm_map.data_shadow[:, 0]): node = np.where(mesh.data_nodegId == gnode)[0] phiStar.data[node] += mswarm_Tstar.data_shadow[i, 0] phiNorm.data[node] += 1.0 phiStar.data[np.where(phiNorm.data > 0.0)] /= phiNorm.data[np.where( phiNorm.data > 0.0)] return phiStar