def test_barycentric_weights_1d(self): eps = 1e-12 # test barycentric weights for uniform points using direct calculation abscissa = np.linspace( -1, 1., 5 ) weights = compute_barycentric_weights_1d( abscissa,normalize_weights=False) n = abscissa.shape[0]-1 h = 2. / n true_weights = np.empty( ( n+1 ), np.double ) for j in range( n+1 ): true_weights[j] = (-1.)**(n-j)*nchoosek(n,j)/( h**n*factorial(n) ) assert np.allclose( true_weights, weights, eps ) # test barycentric weights for uniform points using analytical formula # and with scaling on weights = compute_barycentric_weights_1d( abscissa, interval_length=1,normalize_weights=False) weights_analytical = equidistant_barycentric_weights( 5 ) ratio = weights / weights_analytical; # assert the two weights array differ by only a constant factor assert np.allclose( np.min( ratio ), np.max( ratio ) ) # test barycentric weights for clenshaw curtis points level = 7 abscissa, tmp = clenshaw_curtis_pts_wts_1D( level ) n = abscissa.shape[0] weights = compute_barycentric_weights_1d( abscissa,normalize_weights=False,interval_length=2) true_weights = np.empty( ( n ), np.double ) true_weights[0] = true_weights[n-1] = 0.5 true_weights[1:n-1]=[(-1)**ii for ii in range(1,n-1)] factor = true_weights[1]/weights[1] assert np.allclose( true_weights/factor, weights, atol=eps ) # check barycentric weights are correctly computed regardless of # order of points. Eventually ordering can effect numerical stability # but not until very high level abscissa, tmp = clenshaw_curtis_in_polynomial_order(level) I = np.argsort(abscissa) n = abscissa.shape[0] weights = compute_barycentric_weights_1d( abscissa,normalize_weights=False, interval_length=abscissa.max()-abscissa.min()) true_weights = np.empty( ( n ), np.double ) true_weights[0] = true_weights[n-1] = 0.5 true_weights[1:n-1]=[(-1)**ii for ii in range(1,n-1)] factor = true_weights[1]/weights[I][1] assert np.allclose( true_weights/factor, weights[I], eps ) from pyapprox.univariate_quadrature import gauss_hermite_pts_wts_1D num_samples = 65 abscissa, tmp = gauss_hermite_pts_wts_1D(num_samples) weights = compute_barycentric_weights_1d( abscissa,normalize_weights=False, interval_length=abscissa.max()-abscissa.min()) print(weights) print(np.absolute(weights).max(),np.absolute(weights).min()) print(np.absolute(weights).max()/np.absolute(weights).min())
def test_multivariate_barycentric_lagrange_interpolation(self): def f(x): return np.sum(x**2, axis=0) eps = 1e-14 # test 1d barycentric lagrange interpolation level = 5 #abscissa, __ = clenshaw_curtis_pts_wts_1D( level ) #barycentric_weights_1d = [clenshaw_curtis_barycentric_weights(level)] abscissa, __ = clenshaw_curtis_in_polynomial_order(level, False) abscissa_1d = [abscissa] barycentric_weights_1d = [ compute_barycentric_weights_1d(abscissa_1d[0]) ] fn_vals = f(np.array(abscissa).reshape(1, abscissa.shape[0]))[:, np.newaxis] pts = np.linspace(-1., 1., 3).reshape(1, 3) poly_vals = multivariate_barycentric_lagrange_interpolation( pts, abscissa_1d, barycentric_weights_1d, fn_vals, np.array([0])) #import pylab # print poly_vals.squeeze().shape # pylab.plot(pts[0,:],poly_vals.squeeze()) # pylab.plot(abscissa_1d[0],fn_vals.squeeze(),'ro') # print np.linalg.norm( poly_vals - f( pts ) ) # pylab.show() assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps) # test 2d barycentric lagrange interpolation # with the same abscissa in each dimension a = -3.0 b = 3.0 x = np.linspace(a, b, 21) [X, Y] = np.meshgrid(x, x) pts = np.vstack((X.reshape((1, X.shape[0] * X.shape[1])), Y.reshape((1, Y.shape[0] * Y.shape[1])))) num_abscissa = [10, 10] abscissa_1d = [ np.linspace(a, b, num_abscissa[0]), np.linspace(a, b, num_abscissa[1]) ] abscissa = cartesian_product(abscissa_1d, 1) fn_vals = f(abscissa) barycentric_weights_1d = [ compute_barycentric_weights_1d(abscissa_1d[0]), compute_barycentric_weights_1d(abscissa_1d[1]) ] poly_vals = multivariate_barycentric_lagrange_interpolation( pts, abscissa_1d, barycentric_weights_1d, fn_vals[:, np.newaxis], np.array([0, 1])) assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps) # test 2d barycentric lagrange interpolation # with different abscissa in each dimension a = -1.0 b = 1.0 x = np.linspace(a, b, 21) [X, Y] = np.meshgrid(x, x) pts = np.vstack((X.reshape((1, X.shape[0] * X.shape[1])), Y.reshape((1, Y.shape[0] * Y.shape[1])))) level = [1, 2] nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0]) nodes_1, tmp = clenshaw_curtis_pts_wts_1D(level[1]) abscissa_1d = [nodes_0, nodes_1] barycentric_weights_1d = [ clenshaw_curtis_barycentric_weights(level[0]), clenshaw_curtis_barycentric_weights(level[1]) ] abscissa = cartesian_product(abscissa_1d, 1) fn_vals = f(abscissa) poly_vals = multivariate_barycentric_lagrange_interpolation( pts, abscissa_1d, barycentric_weights_1d, fn_vals[:, np.newaxis], np.array([0, 1])) assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps) # test 3d barycentric lagrange interpolation # with different abscissa in each dimension num_dims = 3 a = -1.0 b = 1.0 pts = np.random.uniform(-1., 1., (num_dims, 10)) level = [1, 1, 1] nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0]) nodes_1, tmp = clenshaw_curtis_pts_wts_1D(level[1]) nodes_2, tmp = clenshaw_curtis_pts_wts_1D(level[2]) abscissa_1d = [nodes_0, nodes_1, nodes_2] barycentric_weights_1d = [ clenshaw_curtis_barycentric_weights(level[0]), clenshaw_curtis_barycentric_weights(level[1]), clenshaw_curtis_barycentric_weights(level[2]) ] abscissa = cartesian_product(abscissa_1d, 1) fn_vals = f(abscissa) poly_vals = multivariate_barycentric_lagrange_interpolation( pts, abscissa_1d, barycentric_weights_1d, fn_vals[:, np.newaxis], np.array([0, 1, 2])) assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps) # test 3d barycentric lagrange interpolation # with different abscissa in each dimension # and only two active dimensions (0 and 2) num_dims = 3 a = -1.0 b = 1.0 pts = np.random.uniform(-1., 1., (num_dims, 5)) level = [2, 0, 1] # to get fn_vals we must specify abscissa for all three dimensions # but only the abscissa of the active dimensions should get passed # to the interpolation function nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0]) nodes_1, tmp = clenshaw_curtis_pts_wts_1D(level[1]) nodes_2, tmp = clenshaw_curtis_pts_wts_1D(level[2]) abscissa_1d = [nodes_0, nodes_1, nodes_2] abscissa = cartesian_product(abscissa_1d, 1) abscissa_1d = [nodes_0, nodes_2] barycentric_weights_1d = [ clenshaw_curtis_barycentric_weights(level[0]), clenshaw_curtis_barycentric_weights(level[2]) ] fn_vals = f(abscissa) poly_vals = multivariate_barycentric_lagrange_interpolation( pts, abscissa_1d, barycentric_weights_1d, fn_vals[:, np.newaxis], np.array([0, 2])) pts[1, :] = 0. assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps) # test 3d barycentric lagrange interpolation # with different abscissa in each dimension # and only two active dimensions (0 and 1) num_dims = 3 a = -1.0 b = 1.0 pts = np.random.uniform(-1., 1., (num_dims, 5)) level = [2, 3, 0] # to get fn_vals we must specify abscissa for all three dimensions # but only the abscissa of the active dimensions should get passed # to the interpolation function nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0]) nodes_1, tmp = clenshaw_curtis_pts_wts_1D(level[1]) nodes_2, tmp = clenshaw_curtis_pts_wts_1D(level[2]) abscissa_1d = [nodes_0, nodes_1, nodes_2] abscissa = cartesian_product(abscissa_1d, 1) abscissa_1d = [nodes_0, nodes_1] barycentric_weights_1d = [ clenshaw_curtis_barycentric_weights(level[0]), clenshaw_curtis_barycentric_weights(level[1]) ] fn_vals = f(abscissa) poly_vals = multivariate_barycentric_lagrange_interpolation( pts, abscissa_1d, barycentric_weights_1d, fn_vals[:, np.newaxis], np.array([0, 1])) # The interpolant will only be correct on the plane involving # the active dimensions so we must set the coordinate of the inactive # dimension to the abscissa coordinate of the inactive dimension. # The interpoolation algorithm is efficient in the sense that it # ignores all dimensions involving only one point because the # interpolant will be a constant in that direction pts[2, :] = 0. assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps) # test 3d barycentric lagrange interpolation # with different abscissa in each dimension # and only two active dimensions (1 and 2) num_dims = 3 a = -1.0 b = 1.0 pts = np.random.uniform(-1., 1., (num_dims, 5)) level = [0, 2, 4] # to get fn_vals we must specify abscissa for all three dimensions # but only the abscissa of the active dimensions should get passed # to the interpolation function nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0]) nodes_1, tmp = clenshaw_curtis_pts_wts_1D(level[1]) nodes_2, tmp = clenshaw_curtis_pts_wts_1D(level[2]) abscissa_1d = [nodes_0, nodes_1, nodes_2] abscissa = cartesian_product(abscissa_1d, 1) abscissa_1d = [nodes_1, nodes_2] barycentric_weights_1d = [ clenshaw_curtis_barycentric_weights(level[1]), clenshaw_curtis_barycentric_weights(level[2]) ] fn_vals = f(abscissa) poly_vals = multivariate_barycentric_lagrange_interpolation( pts, abscissa_1d, barycentric_weights_1d, fn_vals[:, np.newaxis], np.array([1, 2])) pts[0, :] = 0. assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps) # test 2d barycentric lagrange interpolation # with different abscissa in each dimension and only some of # the coefficients of the basis terms being non-zero. This situation # arises in hierarchical interpolation. In these cases we need # to construct the basis functions on all abscissa but we only # need to add the basis functions that are one at the hierachical # nodes a = -1.0 b = 1.0 #x = np.linspace( a, b, 21 ) x = np.linspace(a, b, 5) [X, Y] = np.meshgrid(x, x) pts = np.vstack((X.reshape((1, X.shape[0] * X.shape[1])), Y.reshape((1, Y.shape[0] * Y.shape[1])))) poly_vals = np.ones((pts.shape[1], 1), np.double) * \ f(np.array([[0.0, 0.0]]).T)[:, np.newaxis] level = [1] nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0]) abscissa_1d = [nodes_0] barycentric_weights_1d = [ compute_barycentric_weights_1d(abscissa_1d[0]) ] sets = copy.copy(abscissa_1d) sets.append(np.array([0.0])) abscissa = cartesian_product(sets, 1) hier_indices = np.array([[0, 2]], np.int32) abscissa = abscissa[:, hier_indices[0]] fn_vals = f(abscissa) poly_vals_increment = \ multivariate_hierarchical_barycentric_lagrange_interpolation( pts, abscissa_1d, barycentric_weights_1d, (fn_vals - np.ones((abscissa.shape[1]), np.double) * f( np.array([0.0, 0.0])))[:, np.newaxis], np.array([0]), hier_indices) poly_vals += poly_vals_increment level = [1] nodes_0, tmp = clenshaw_curtis_pts_wts_1D(level[0]) abscissa_1d = [nodes_0] # barycentric_weights_1d = [barycentric_weights( np.array( [0.0] ) ), # barycentric_weights( abscissa_1d[0] )] barycentric_weights_1d = [ compute_barycentric_weights_1d(abscissa_1d[0]) ] sets = [np.array([0.0])] sets.append(nodes_0) abscissa = cartesian_product(sets, 1) hier_indices = np.array([[0, 2]], np.int32) abscissa = abscissa[:, hier_indices[0]] fn_vals = f(abscissa) poly_vals += \ multivariate_hierarchical_barycentric_lagrange_interpolation( pts, abscissa_1d, barycentric_weights_1d, (fn_vals - np.ones((abscissa.shape[1]), np.double) * f( np.array([[0.0, 0.0]]).T))[:, np.newaxis], np.array([1]), hier_indices) assert np.allclose(poly_vals, f(pts)[:, np.newaxis], eps)