def test_roots_legendre(): weightf = orth.legendre(5).weight_func verify_gauss_quad(sc.roots_legendre, orth.eval_legendre, weightf, -1., 1., 5) verify_gauss_quad(sc.roots_legendre, orth.eval_legendre, weightf, -1., 1., 25, atol=1e-13) verify_gauss_quad(sc.roots_legendre, orth.eval_legendre, weightf, -1., 1., 100, atol=1e-12) x, w = sc.roots_legendre(5, False) y, v, m = sc.roots_legendre(5, True) assert_allclose(x, y, 1e-14, 1e-14) assert_allclose(w, v, 1e-14, 1e-14) muI, muI_err = integrate.quad(weightf, -1, 1) assert_allclose(m, muI, rtol=muI_err) assert_raises(ValueError, sc.roots_legendre, 0) assert_raises(ValueError, sc.roots_legendre, 3.3)
def __init__(self, lm, nphi=None, ntheta=None): self.lmax = lm self.plm = AssocLegendre(lm) if nphi is None: self.nphi = _closest_int_with_only_prime_factors_up_to_fmax(2 * lm + 1) else: self.nphi = nphi # avoid the poles self.phi = np.arange(0, self.nphi) * 2 * np.pi / self.nphi if ntheta is None: n = self.lmax + 1 n += (n & 1) n = ((n + 7) // 8) * 8 self.ntheta = n else: self.ntheta = ntheta self.cos_theta, self.weights, self.total_weight = roots_legendre( self.ntheta, mu=True) self.weights *= 4 * np.pi / self.total_weight self.theta = np.arccos(self.cos_theta) self.fft_work_array = np.empty(self.nphi, dtype=np.complex128) self.plm_work_array = np.empty(self.nplm()) self._grid = None self._grid_cartesian = None
def legendre(function, a, b, order, *args, **kwargs): """ Evaluate integral of <function> object, of 1 variable and parameters: Args: :function <function> f(x, *args, **kwargs) :a <float> lower limit :b <float> upper limit :order <int> order of the quadrature *args and **kwargs will be passed to the function (check argument introduction in case of several function management) """ A = (b - a) / 2 B = (b + a) / 2 if not order in GaussianQuadrature._roots_weights_Legendre: x_i, w_i = roots_legendre(order, mu=False) GaussianQuadrature._roots_weights_Legendre[order] = (x_i, w_i) else: x_i, w_i = GaussianQuadrature._roots_weights_Legendre.get(order) x_i_aux = A*x_i + B #integral = A * sum(w_i * function(x_i, *args, **kwargs)) #return integral integral = 0.0 for i in range(len(x_i)): integral += w_i[i] * function(x_i_aux[i], *args, **kwargs) #print("order", order, "=",integral) return A * integral
def gauss1d(fun, x0, x1, n): """Gauss quadrature in 1D Parameters ---------- fun : callable Function to integrate. x0 : float Initial point for the integration interval. x1 : float End point for the integration interval. n : int Number of points to take in the interval. Returns ------- inte : float Approximation of the integral """ xi, wi = roots_legendre(n) inte = 0 h = 0.5 * (x1 - x0) xm = 0.5 * (x0 + x1) for cont in range(n): inte = inte + h * fun(h * xi[cont] + xm) * wi[cont] return inte
def __init__(self, polygon, center=0, n_node=8, method='krylov'): """ polygon = target polygon of SC transformation center = point in polygon where disk center is mapped to n_node = number of nodes for gaussian quadrature method = used for root finding """ p = polygon.copy() p.roll() w = p.vertex beta = p.angle n = len(w) k_rat = p.FiniteEdge([0, n - 1], n - 3) k_fix = p.InfVertex() if len(k_fix) == 0: k_fix = [1] node = np.empty([n + 1, n_node]) weight = np.empty_like(node) for k in range(n): if np.isinf(w[k]): continue (node[k], weight[k]) = roots_jacobi(n_node, 0, -beta[k]) (node[n], weight[n]) = roots_legendre(n_node) self.prevertex = np.empty(n, dtype=np.complex) self.vertex = w self.angle = beta self.node = node self.weight = weight self.A = center self.map = np.vectorize(self.map) self.invmap = np.vectorize(self.invmap) y = np.zeros(n - 1) f = np.empty_like(y) def scfun(y): z = self.yztran(y) C = (center - w[-1]) / self.zquad(1, 0, n - 1) i = 0 for k in k_fix: q = w[k - 1] - center + C * self.zquad(z[k - 1], 0, k - 1) f[i] = np.real(q) f[i + 1] = np.imag(q) i += 2 for k in k_rat: q = self.zquad(z[k], z[k + 1], k, k + 1) f[i] = np.abs(w[k + 1] - w[k]) - np.abs(C * q) i += 1 self.C = C return f sol = root(scfun, y, method=method, options={'disp': True}) self.yztran(sol.x)
def _get_quadrature_points(n, a, b): """ Quadrature points needed for gauss-legendre integration. Utility function to get the legendre points, shifted from [-1, 1] to [a, b] Args: n: number of quadrature_points a: lower bound of integration b: upper bound of integration Returns: quadrature_points: (1d array) quadrature_points for numerical integration weights: (1d array) quadrature weights Notes: A local function of the based fixed_quad found in scipy, this is done for processing optimization """ x, w = roots_legendre(n) x = np.real(x) # Legendre domain is [-1, 1], convert to [a, b] scalar = (b - a) * 0.5 return scalar * (x + 1) + a, scalar * w
def gauss(f: Call[[float], float], a: float, b: float, n: int) -> float: def p2v(p: float, c: float, d: float) -> float: return (d + c) / 2 + (d - c) * p / 2 x, w = roots_legendre(n) return sum([(b - a) / 2 * w[i] * f(p2v(x[i], a, b)) for i in range(n)])
def make_contour(emin=-20,emax=0.0,enum=42,p=150): ''' A more sophisticated contour generator ''' x,wl = roots_legendre(enum) R = (emax-emin)/2 z0 = (emax+emin)/2 y1 = -np.log(1+np.pi*p) y2 = 0 y = (y2-y1)/2*x+(y2+y1)/2 phi = (np.exp(-y)-1)/p ze = z0+R*np.exp(1j*phi) we = -(y2-y1)/2*np.exp(-y)/p*1j*(ze-z0)*wl class ccont: #just an empty container class pass cont = ccont() cont.R = R cont.z0 = z0 cont.ze = ze cont.we = we cont.enum = enum return cont
def get_coords(self): ''' Compute samples on sphere that are sufficient for lmax. Returns ------- thetas : (ntheta) array Theta coordinates. ct_weights : (ntheta) array Quadrature weights for cos(theta). nphi : int Number of phi samples on each isolatitude ring. Notes ----- We use Gauss-Legendre weights for isolatitude rings, see astro-ph/0305537. ''' cos_thetas, ct_weights = roots_legendre( int(np.floor(1.5 * self.lmax) + 1)) thetas = np.arccos(cos_thetas) nphi_min = 3 * self.lmax + 1 nphi = utils.compute_fftlen_fftw(nphi_min, even=True) return thetas, ct_weights, nphi
def _erfcx_integral(a, b, order): """Fixed order Gauss-Legendre quadrature of erfcx from a to b.""" assert np.all(a >= 0) and np.all(b >= 0) x, w = roots_legendre(order) x = x[:, np.newaxis] w = w[:, np.newaxis] return (b - a) * np.sum(w * erfcx((b - a) * x / 2 + (b + a) / 2), axis=0) / 2
def rsd(l, ngauss=50, beta=.6): x, wx = scs.roots_legendre(ngauss) px = scs.legendre(l)(x) rsd_int = 0.0 for i in range(ngauss): rsd_int += wx[i] * px[i] * ((1.0 + beta * x[i]*x[i])**2) rsd_int *= (l + 0.5) return rsd_int
def __init__(self, mesh, materialData, method="SI", stepMethod='diamond', loud=False, acceleration='none', relaxationFactor=1, diagnostic=False, LaTeX=False, epsilon=1E-8, quadSetOrder=8, out="Slab.out", maxIter=10000, transmission=True): """ Mandatory inputs are a mesh object and material object """ if loud == True: print("Intializing slab!") # initialize general parameters self.loud = loud self.diagnostic = diagnostic self.LaTeX = LaTeX self.out = out self.maxIter = maxIter # set numerical settings self.relaxationFactor = relaxationFactor self.epsilon = epsilon self.quadSetOrder = quadSetOrder self.setDifferencingScheme(stepMethod) self.setAccelerationMethod(acceleration) self.transmission = transmission # initialize slab material self.mesh = mesh self.initializeSlab(materialData) # intialize diagnostic parameters self.currentEps = 1000 # a big number self.rho = 0 self.epsilons = [] self.rhos = [] self.its = [] # initialize quad set weights , make sure they're normalized self.mu, self.weights = roots_legendre(self.quadSetOrder, mu=False) self.weights = np.array(self.weights) self.weights = self.weights / sum(self.weights) # initialize plotting axes if self.loud == True: self.initializeFigure()
def main_1(): midpoint_rule(f, -1, 1, 1e-3) for n in (1, 2, 3, 4, 5, 6): #в условии просят взять первые 6 roots, weights = roots_legendre(n) print('Estimated: {}, number_of_the_roots: {}'.format( sum(weights * f(roots)), n)) I_calculated_with_the_estimated_formula = abs( integrate.quad(f_2, -1, 1)[0]) #следует отметить # что в действительности без приближения интеграла от f, # значение будет равно примерно тому, что ниже (I_REAL), но мы его не используем: I_REAL = abs(integrate.quad(f, 0, 10)[0]) print('Answer with estimation: {}, ' 'definite answer with scipy.integrate: {} '.format( I_calculated_with_the_estimated_formula, I_REAL)) eps = 1e-10 n = 1 I = np.inf while eps < abs(I_calculated_with_the_estimated_formula - I): roots, weights = roots_legendre(n) I = sum(weights * f_2(roots)) print('Estimated: {}, number_of_the_roots_on_Legendre: {}'.format( I, n)) n += 1 eps = 1e-10 n = 1 I_0 = np.inf I = 0 checker = True while checker == True: roots, weights = roots_chebyt(n) I = sum(weights * f_3(roots)) checker = abs(I_0 - I) != 0 I_0 = I n += 1 print('Estimated: {}, number_of_the_roots_on_Chebyshev: {}'.format( I, n - 1))
def gauss1d(npoints): # points and weights are np arrays, convert them into tuple p1d, w1d = roots_legendre(npoints) # need to get data structure right for consistency # pts must be an array of [x,y,z] # an elegant way is to use newaxis points = p1d[:, np.newaxis] weights = w1d return Integ(pts=points, wts=weights)
def _cached_roots_legendre(n): """ Cache roots_legendre results to speed up calls of the fixed_quad function. """ if n in _cached_roots_legendre.cache: return _cached_roots_legendre.cache[n] _cached_roots_legendre.cache[n] = roots_legendre(n) return _cached_roots_legendre.cache[n]
def test_quadrature_points(self): """Testing the creation of quadrtature points""" n_points = 11 # A smoke test to make sure it's running properly quad_points = _get_quadrature_points(n_points, -1, 1) x, _ = roots_legendre(n_points) np.testing.assert_allclose(x, quad_points)
def __init__(self, z, n_node=8, method='krylov'): """ z = vertices as complex numbers on boundary n_node = number of nodes for gaussian quadrature method = used for root finding """ if len(z)<2: print('there must be 2 or more vertices'); exit() if len(z)==2: z.insert(1, (z[0]+z[1])/2) n = len(z) - 1 beta = np.empty(n+1) node = np.empty([n+1, n_node]) weight = np.empty_like(node) (node[n], weight[n]) = roots_legendre(n_node) (node[0], weight[0]) = (node[n], weight[n]) gamma = np.angle(z[1] - z[0])/np.pi for k in range(1,n): beta[k] = np.angle(z[k+1] - z[k])/np.pi - gamma beta[k] = (beta[k] + 1)%2 - 1 if beta[k]-1 > 1.e-8: beta[k] = -1 gamma += beta[k] (node[k], weight[k]) = roots_jacobi(n_node, 0, -beta[k]) self.prevertex = np.empty(n+1, dtype=np.complex) self.prevertex[0] = -1 self.vertex = np.array(z, dtype=np.complex) self.angle = beta self.node = node self.weight = weight self.reflect = False self.map = np.vectorize(self.map) y = np.zeros(n-1) f = np.empty_like(y) def kfun(y): x = self.yxtran(y) C = (z[1] - z[0])/self.xquad(x[0], x[1], 0, 1) for k in range(1,n): q = self.xquad(x[k], x[k+1], k, k+1) f[k-1] = np.abs(z[k+1] - z[k]) - np.abs(C*q) self.C = C return f sol = root(kfun, y, method=method, options={'disp': True}) self.yxtran(sol.x)
def test_gausslegendre(): """ compar own implementation aginst scipy.special """ N = 20 w, r = L_function(N) r_e, w_e = roots_legendre(N) res_w = np.abs(w - w_e) res_r = np.abs(r - r_e) assert np.max(res_w) == pytest.approx(0) assert np.max(res_r) == pytest.approx(0)
def __init__(self, polygon, n_node=8, method='krylov'): """ polygon = target polygon of SC transformation n_node = number of nodes for gaussian quadrature method = used for root finding """ if np.any(np.isinf(polygon.vertex)): print('infinite vertex is not allowed'); exit() p = polygon.copy() p.flip() p.roll(1) w = p.vertex b = p.angle b[b==-1] = 1 n = len(w) node = np.empty([n+1, n_node]) weight = np.empty_like(node) for k in range(n): if np.isfinite(w[k]): (node[k], weight[k]) = roots_jacobi(n_node, 0, b[k]) (node[n], weight[n]) = roots_legendre(n_node) self.prevertex = np.empty(n, dtype=np.complex) self.vertex = w self.angle = b self.node = node self.weight = weight self.map = np.vectorize(self.map) y = np.zeros(n-1) f = np.empty_like(y) def scfun(y): z = self.yztran(y) C = (w[-1] - w[0])/self.zquad(z[0], z[-1], 0, n-1) for k in range(n-3): q = self.zquad(z[k], z[k+1], k, k+1) f[k] = np.abs(w[k+1] - w[k]) - np.abs(C*q) r = np.sum(b/z) f[n-3] = np.real(r) f[n-2] = np.imag(r) self.C = C return f sol = root(scfun, y, method=method, options={'disp': True}) self.yztran(sol.x)
def gauss_legendre(n, lower=-1, upper=1): ''' Gauss-Legendre quadrature: A rule of order 2*n-1 on the interval [lower, upper] with respect to the weight function w(x) = 1. ''' nodes, weights = special.roots_legendre(n) if lower != -1 or upper != 1: nodes = (upper+lower)/2 + (upper-lower)/2*nodes weights = (upper-lower)/2*weights return nodes, weights
def test_gauss_legendre_quadrature(): """ Ensure that Gauss-Legendre quadrature nodes and weights are the same as when computed using scipy. """ n = np.random.randint(10, 100) q = GaussLegendreQuadrature(n) nodes = q.get_nodes() weights = q.get_weights() nodes_ref, weights_ref = roots_legendre(n) assert np.all(np.isclose(nodes, nodes_ref)) assert np.all(np.isclose(weights, weights_ref))
def gaussian_quad(func, a, b, n_sub_interval=8, n_order=32): ''' 1D function Gaussian qaudrature integration from a to b ''' L = b - a dL = L / n_sub_interval X0, W0 = roots_legendre(n_order) X = dL * (X0 + 1.) / 2. y = 0. for i in range(n_sub_interval): x_min = a + i * dL y = y + np.sum(W0 * func(X + x_min), axis=-1) return y * dL / 2.0
def _compute_logpdf_quadrature(self, alpha0, beta0, alpha1, beta1, z): def _log_integrand(y): # Pad the axes to allow for vectorized computation return (np.log(y) + sp_stats.beta.logpdf( y * z[..., np.newaxis], alpha0[..., np.newaxis], beta0[..., np.newaxis]) + sp_stats.beta.logpdf( y, alpha1[..., np.newaxis], beta1[..., np.newaxis])) roots, weights = sp_special.roots_legendre(8000) # We need to account for the change of interval from [-1, 1] to [0, 1] shifted_roots = 0.5 * roots + 0.5 return -np.log(2.) + sp_special.logsumexp( _log_integrand(shifted_roots) + np.log(weights), axis=-1)
def integrate_scattering_angles(self): """Numerical integration over scattering angles using Gauss-Legendre quadrature. """ _, weights = roots_legendre(self.lat_scat.size) weights = np.broadcast_to(np.copy(weights.reshape(-1, 1)), (1, ) * 5 + (weights.size, ) + (1, )) latitude_integrals = np.sum(weights * self.data, axis=5) remainder = 0.0 if self.lon_scat[-1] < 2 * np.pi: dx = self.lon_scat[0] + 2 * np.pi - self.lon_scat[-1] remainder = 0.5 * dx * (latitude_integrals[:, :, :, :, -1, :] + latitude_integrals[:, :, :, :, 0, :]) return np.trapz(latitude_integrals, x=self.lon_scat, axis=4) + remainder
def h1_seminorm_error(self, u_sol_der, u_true_der): B_l = self.mesh.compute_affine_transformation_matrices() det_B = self.mesh.affine_trans_det() # quadrature weights in 1D # 4 th order ensures quadratic inner product accuracy order = 4 original_roots, weights = roots_legendre(4) n = len(weights) # shift to unit interval [0, 1] x_roots = (original_roots + 1) / 2 # mesh together x_roots_mat, y_roots_mat = np.meshgrid(x_roots, x_roots) # shift y roots according to reference element y_roots_mat *= (1 - x_roots) paired_coords = np.array( list(zip(list(x_roots_mat.ravel()), list(y_roots_mat.ravel())))) integration_nodes_per_element = [ (B_l[el] @ paired_coords.T).T + self.mesh.coordinates[self.mesh.elements[el, 0], :] for el in range(len(self.mesh.elements)) ] # get true values at each node u_true_values = [ u_true_der([node_set[:, 0], node_set[:, 1]]) for node_set in integration_nodes_per_element ] # solution gradient values # are piecewise constant u_sol_values = np.tile(u_sol_der, (np.shape(u_true_values)[1], 1)).T difference = u_sol_values - u_true_values # apply integration tmp = np.tile(det_B, [np.shape(difference)[1], 1]).T difference *= tmp l2_error = sum([ np.dot(weights, np.reshape(np.power(diff_val, 2), (n, n)) @ weights) for diff_val in list(difference) ]) return l2_error
def gauss2d(fun, x0, x1, y0, y1, nx, ny): """Gauss quadrature for a rectangle in 2D Parameters ---------- fun : callable Function to integrate. x0 : float Initial point for the integration interval in x. x1 : float End point for the integration interval in x. y0 : float Initial point for the integration interval in y. y1 : float End point for the integration interval in y. nx : int Number of points to take in the interval in x. ny : int Number of points to take in the interval in y. Returns ------- inte : float Approximation of the integral """ xi, wi = roots_legendre(nx) yj, wj = roots_legendre(ny) inte = 0 hx = 0.5 * (x1 - x0) hy = 0.5 * (y1 - y0) xm = 0.5 * (x0 + x1) ym = 0.5 * (y0 + y1) for cont_x in range(nx): for cont_y in range(ny): f = fun(hx * xi[cont_x] + xm, hy * yj[cont_y] + ym) inte = inte + hx* hy * f * wi[cont_x] * wj[cont_y] return inte
def test_double_gauss_quadrature(): """ Ensure that nodes and weights of the double Gauss quadrature match those of a scaled and shifted Gauss-Legendre quadrature. """ n = 2 * np.random.randint(10, 100) q = DoubleGaussQuadrature(n) nodes = q.get_nodes() weights = q.get_weights() nodes_ref, weights_ref = roots_legendre(n // 2) assert np.all(np.isclose(-0.5 + 0.5 * nodes_ref, nodes[:n // 2])) assert np.all(np.isclose(0.5 * weights_ref, weights[:n // 2])) assert np.all(np.isclose(0.5 + 0.5 * nodes_ref, nodes[n // 2:])) assert np.all(np.isclose(0.5 * weights_ref, weights[n // 2:]))
def get_grid(nphi=256, ntheta=128): phi = np.linspace(0., 2 * np.pi, nphi) x, w = sp.roots_legendre(ntheta) theta = np.sort(np.arccos(x)) p2D = np.zeros([nphi, ntheta]) th2D = np.zeros([nphi, ntheta]) for i in range(nphi): p2D[i, :] = phi[i] for j in range(ntheta): th2D[:, j] = theta[j] return p2D, th2D
def build_path_legendre(self, npoints, endpoint=True): p = 13 x, w = roots_legendre(npoints) R = (self.emax - self.emin) / 2.0 R0 = (self.emin + self.emax) / 2.0 y1 = -np.log(1 + np.pi * p) y2 = 0 y = (y2 - y1) / 2 * x + (y2 + y1) / 2 phi = (np.exp(-y) - 1) / p path = R0 + R * np.exp(1.0j * phi) #weight= -(y2-y1)/2*np.exp(-y)/p*1j*(path-R0)*w if endpoint: self.path = path self.de = np.diff(path) else: self.path = (path[:-1] + path[1:]) / 2 self.de = path[1:] - path[:-1]
def gaussian_quadrature(num_of_points, integral_max, integral_min, f_function): """ Quadratura Gaussiana """ x_array, w_array = roots_legendre(num_of_points) # pylint: disable=unbalanced-tuple-unpacking result = 0 for i in range(len(x_array)): t = x_array[i] * (integral_max - integral_min) / 2 + (integral_max + integral_min) / 2 result += w_array[i] * f_function(t) result *= ((integral_max - integral_min) / 2) return result
def test_roots_jacobi(): rf = lambda a, b: lambda n, mu: sc.roots_jacobi(n, a, b, mu) ef = lambda a, b: lambda n, x: orth.eval_jacobi(n, a, b, x) wf = lambda a, b: lambda x: (1 - x)**a * (1 + x)**b vgq = verify_gauss_quad vgq(rf(-0.5, -0.75), ef(-0.5, -0.75), wf(-0.5, -0.75), -1., 1., 5) vgq(rf(-0.5, -0.75), ef(-0.5, -0.75), wf(-0.5, -0.75), -1., 1., 25, atol=1e-12) vgq(rf(-0.5, -0.75), ef(-0.5, -0.75), wf(-0.5, -0.75), -1., 1., 100, atol=1e-11) vgq(rf(0.5, -0.5), ef(0.5, -0.5), wf(0.5, -0.5), -1., 1., 5) vgq(rf(0.5, -0.5), ef(0.5, -0.5), wf(0.5, -0.5), -1., 1., 25, atol=1.5e-13) vgq(rf(0.5, -0.5), ef(0.5, -0.5), wf(0.5, -0.5), -1., 1., 100, atol=1e-12) vgq(rf(1, 0.5), ef(1, 0.5), wf(1, 0.5), -1., 1., 5, atol=2e-13) vgq(rf(1, 0.5), ef(1, 0.5), wf(1, 0.5), -1., 1., 25, atol=2e-13) vgq(rf(1, 0.5), ef(1, 0.5), wf(1, 0.5), -1., 1., 100, atol=1e-12) vgq(rf(0.9, 2), ef(0.9, 2), wf(0.9, 2), -1., 1., 5) vgq(rf(0.9, 2), ef(0.9, 2), wf(0.9, 2), -1., 1., 25, atol=1e-13) vgq(rf(0.9, 2), ef(0.9, 2), wf(0.9, 2), -1., 1., 100, atol=2e-13) vgq(rf(18.24, 27.3), ef(18.24, 27.3), wf(18.24, 27.3), -1., 1., 5) vgq(rf(18.24, 27.3), ef(18.24, 27.3), wf(18.24, 27.3), -1., 1., 25) vgq(rf(18.24, 27.3), ef(18.24, 27.3), wf(18.24, 27.3), -1., 1., 100, atol=1e-13) vgq(rf(47.1, -0.2), ef(47.1, -0.2), wf(47.1, -0.2), -1., 1., 5, atol=1e-13) vgq(rf(47.1, -0.2), ef(47.1, -0.2), wf(47.1, -0.2), -1., 1., 25, atol=2e-13) vgq(rf(47.1, -0.2), ef(47.1, -0.2), wf(47.1, -0.2), -1., 1., 100, atol=1e-11) vgq(rf(2.25, 68.9), ef(2.25, 68.9), wf(2.25, 68.9), -1., 1., 5) vgq(rf(2.25, 68.9), ef(2.25, 68.9), wf(2.25, 68.9), -1., 1., 25, atol=1e-13) vgq(rf(2.25, 68.9), ef(2.25, 68.9), wf(2.25, 68.9), -1., 1., 100, atol=1e-13) # when alpha == beta == 0, P_n^{a,b}(x) == P_n(x) xj, wj = sc.roots_jacobi(6, 0.0, 0.0) xl, wl = sc.roots_legendre(6) assert_allclose(xj, xl, 1e-14, 1e-14) assert_allclose(wj, wl, 1e-14, 1e-14) # when alpha == beta != 0, P_n^{a,b}(x) == C_n^{alpha+0.5}(x) xj, wj = sc.roots_jacobi(6, 4.0, 4.0) xc, wc = sc.roots_gegenbauer(6, 4.5) assert_allclose(xj, xc, 1e-14, 1e-14) assert_allclose(wj, wc, 1e-14, 1e-14) x, w = sc.roots_jacobi(5, 2, 3, False) y, v, m = sc.roots_jacobi(5, 2, 3, True) assert_allclose(x, y, 1e-14, 1e-14) assert_allclose(w, v, 1e-14, 1e-14) muI, muI_err = integrate.quad(wf(2,3), -1, 1) assert_allclose(m, muI, rtol=muI_err) assert_raises(ValueError, sc.roots_jacobi, 0, 1, 1) assert_raises(ValueError, sc.roots_jacobi, 3.3, 1, 1) assert_raises(ValueError, sc.roots_jacobi, 3, -2, 1) assert_raises(ValueError, sc.roots_jacobi, 3, 1, -2) assert_raises(ValueError, sc.roots_jacobi, 3, -2, -2)