def gauss_lobatto_quadrature(N,alpha=-1/2.,beta=-1/2.,r0=None,shift=0.,scale=1.) : # Returns the N-point Jacobi-Gauss-Lobatto(alpha,beta) quadrature rule over the interval # (-scale,scale)+shift # For nontrivial values of shift, scale, the weight function associated with # this quadrature rule is the directly-mapped Jacobi weight + the Jacobian # factor introduced by scale. from coeffs import recurrence_range from numpy import array from spyctral import chebyshev from spyctral.opoly1d.quad import glq as oglq from spyctral.common.maps import physical_scaleshift as pss from spyctral.common.maps import standard_scaleshift as sss if r0 is None: r0 = array([-scale,scale])+shift r0 = array(r0) tol = 1e-12; if (abs(alpha+1/2.)<tol) & (abs(beta+1/2.)<tol) : return chebyshev.quad.glq(N,shift=shift,scale=scale) else : [a,b] = recurrence_range(N,alpha,beta) sss(r0,scale=scale,shift=shift) temp = oglq(a,b,r0=r0) pss(r0,scale=scale,shift=shift) pss(temp[0],scale=scale,shift=shift) #temp[1] *= scale return temp
def dhermite_function(x,ns,mu=0.,scale=1.,shift=0.): from spyctral.hermite.weights import dsqrt_weight, sqrt_weight from numpy import array, zeros, exp,sqrt from spyctral.common.maps import physical_scaleshift as pss from spyctral.common.maps import standard_scaleshift as sss ns = array(ns) N = ns.size mu = float(mu) ps = hermite_polynomial(x,ns,mu,scale=scale,shift=shift) dps = hermite_polynomial(x,ns,mu,d=1,scale=scale,shift=shift) sss(x,shift=shift,scale=scale) #x = (x-shift)/scale #w = x**(mu)*exp(-1/2.*x**2) w = sqrt_weight(x,mu=mu) dw = dsqrt_weight(x,mu=mu) pss(x,shift=shift,scale=scale) #dw = dsqrt_weight(x,mu=mu,shift=shift,scale=scale) # yay product rule ps = (dps.T*w).T + (ps.T*dw).T # I DON'T UNDERSTAND THIS (part of hermite_function) #ps /= sqrt(scale) # WARNING: THIS CAUSES PROBLEMS FOR VERY VERY LARGE N: it eliminates # nan's wflags = (w==0) ps[wflags,:] = 0. return ps/scale
def gauss_radau_quadrature(N, alpha=0.0, r0=None, shift=0.0, scale=1.0): """ Returns the N-point Laguerre-Gauss-Radau(alpha) quadrature rule over the interval (shift,inf) For nontrivial values of shift, scale, the weight function associated with this quadrature rule is the directly-mapped Laguerre weight + the Jacobian factor introduced by scale. """ from numpy import array from spyctral.laguerre.coeffs import recurrence_range from spyctral.opoly1d.quad import grq as ogrq from spyctral.common.maps import physical_scaleshift as pss from spyctral.common.maps import standard_scaleshift as sss if r0 is None: r0 = 0 + shift r0 = array(r0) [a, b] = recurrence_range(N, alpha) sss(r0, scale=scale, shift=shift) temp = ogrq(a, b, r0=r0) pss(r0, scale=scale, shift=shift) pss(temp[0], scale=scale, shift=shift) return temp
def weight(r,alpha=-1/2.,beta=-1/2.,shift=0.,scale=1.): from spyctral.common.maps import standard_scaleshift as sss from spyctral.common.maps import physical_scaleshift as pss sss(r,shift=shift,scale=scale) wfun = (1-r)**alpha*(1+r)**beta wfun *= scale pss(r,shift=shift,scale=scale) return wfun
def weight(x,mu=0.,shift=0.,scale=1.): from numpy import abs, exp from spyctral.common.maps import physical_scaleshift as pss from spyctral.common.maps import standard_scaleshift as sss sss(x,shift=shift,scale=scale) #xt = (x-shift)/scale weight = abs(x)**(2*mu)*exp(-x**2) pss(x,shift=shift,scale=scale) return weight
def dsqrt_weight(x,mu=0.,shift=0.,scale=1.): from spyctral.common.maps import physical_scaleshift as pss from spyctral.common.maps import standard_scaleshift as sss from numpy import exp, abs sss(x,shift=shift,scale=scale) #xt = (x-shift)/scale w = exp(-x**2/2)*(mu*abs(x)**(mu-1) - x*abs(x)**mu) pss(x,shift=shift,scale=scale) return w/scale
def weight(theta,gamma=0.,delta=0.,shift=0.,scale=1.): from numpy import array, cos from spyctral.common.maps import standard_scaleshift as sss from spyctral.common.maps import physical_scaleshift as pss theta = array(theta) sss(theta,scale=scale,shift=shift) w = ((1-cos(theta))**delta)*((1+cos(theta))**gamma) pss(theta,scale=scale,shift=shift) return w
def gq(N,mu=0.,shift=0.,scale=1.): from spyctral.hermite.coeffs import recurrence_range from spyctral.opoly1d.quad import gq as ogq from spyctral.common.maps import physical_scaleshift as pss [a_s,b_s] = recurrence_range(N,mu) [x,w] = ogq(a_s,b_s) pss(x,scale=scale,shift=shift) w *= scale return [x,w]
def gq(N,s=1.,t=1.,scale=1.,shift=0.): from spyctral.common.maps import physical_scaleshift as pss from spyctral.mapjpoly.maps import st_to_ab, r_to_x from spyctral.jacobi.quad import gq [alpha,beta]=st_to_ab(s,t) [r,w] = gq(N,alpha=alpha,beta=beta) x = r_to_x(r) #x *= scale #x += shift pss(x,scale=scale,shift=shift) return [x,w]
def hermite_polynomial(x,n,mu=0.,d=0,shift=0.,scale=1.): from numpy import max, sqrt from spyctral.hermite.coeffs import recurrence_range from spyctral.opoly1d.eval import eval_normalized_opoly from spyctral.common.maps import physical_scaleshift as pss from spyctral.common.maps import standard_scaleshift as sss N = max(n) [a,b] = recurrence_range(N+1,mu) sss(x,shift=shift,scale=scale) temp = eval_normalized_opoly(x,n,a,b,d) pss(x,shift=shift,scale=scale) return temp/sqrt(scale)
def weight(x,alpha=0.,shift=0.,scale=1.): """ Returns the weight function for Laguerre orthogonal polynomials with parameter specifications alpha, shift, and scale. """ from spyctral.common.maps import standard_scaleshift as sss from spyctral.common.maps import physical_scaleshift as pss from numpy import exp sss(x,shift=shift,scale=scale) wfun = exp(-x)*x**alpha wfun *= scale pss(x,shift=shift,scale=scale) return wfun
def dfseries(theta,k,gamma=0.,delta=0.,shift=0.,scale=1.): """ Evaluates the derivative of the generalized Szego-Fourier functions at the locations theta \in [-pi,pi]. This function mods the inputs theta to lie in this interval and then evaluates them. The function class is (gamma,delta), and the function index is the vector of integers k """ from numpy import array, zeros, dot, any, sum from numpy import sin, cos, sqrt, abs, sign from scipy import pi from spyctral.jacobi.eval import jpoly, djpoly from spyctral.common.maps import standard_scaleshift as sss from spyctral.common.maps import physical_scaleshift as pss # Preprocessing: unravelling, etc. theta = array(theta) theta = theta.ravel() sss(theta,shift=shift,scale=scale) # Now theta \in [-pi,pi] theta = (theta+pi) % (2*pi) - pi k = array(k) k = k.ravel() kneq0 = k != 0 a = delta-1/2. b = gamma-1/2. r = cos(theta) # Term-by-term: first the even term dPsi = zeros([theta.size,k.size],dtype=complex) dPsi += 1/2.*djpoly(r,abs(k),a,b) dPsi = (-sin(theta)*dPsi.T).T dPsi[:,~kneq0] *= sqrt(2) # Now the odd term: if any(kneq0): term2 = zeros([theta.size,sum(kneq0)],dtype=complex) term2 += (cos(theta)*jpoly(r,abs(k[kneq0])-1,a+1,b+1).T).T term2 += (-sin(theta)**2*djpoly(r,abs(k[kneq0])-1,a+1,b+1).T).T term2 = 1./2*term2*(1j*sign(k[kneq0])) else: term2 = 0. dPsi[:,kneq0] += term2 # Transform theta back to original interval pss(theta,shift=shift,scale=scale) return dPsi/scale
def sqrt_weight_bias(theta,gamma=0.,delta=0.,shift=0.,scale=1.): from numpy import cos, sin, exp from spyctral.common.maps import standard_scaleshift as sss from spyctral.common.maps import physical_scaleshift as pss from scipy import pi from scipy import power as pw sss(theta,scale=scale,shift=shift) phase = exp(1j*(gamma+delta)/2.*(pi-theta)) w = phase*( pw(sin(theta/2.),delta) * \ pw(cos(theta/2.),gamma)) *\ 2**((gamma+delta)/2.) pss(theta,scale=scale,shift=shift) return w
def gauss_quadrature(N, alpha=0.0, shift=0.0, scale=1.0): """ Returns the N-point Laguerre-Gauss(alpha) quadrature rule over the interval (shift,inf). The quadrature rule is *not* normalized in the sense that the affine parameters shift and scale are built into the new weight function for which this quadrature rule is valid. """ from spyctral.laguerre.coeffs import recurrence_range from spyctral.opoly1d.quad import gq as ogq from spyctral.common.maps import physical_scaleshift as pss [a, b] = recurrence_range(N, alpha) temp = ogq(a, b) pss(temp[0], scale=scale, shift=shift) return temp
def fseries(theta,k,gamma=0.,delta=0.,shift=0.,scale=1.): """ Evaluates the generalized Szego-Fourier functions at the locations theta \in [-pi,pi]. This function mods the inputs theta to lie in this interval and then evaluates them. The function class is (g,d), and the function index is the vector of integers k """ from numpy import array, ndarray, abs, zeros from numpy import sin, cos, sqrt, sign from scipy import pi from spyctral.jacobi.eval import jpoly from spyctral.common.maps import standard_scaleshift as sss from spyctral.common.maps import physical_scaleshift as pss # Preprocessing: unravelling, etc. theta = array(theta) theta = theta.ravel() sss(theta,shift=shift,scale=scale) theta = (theta+pi) % (2*pi) - pi if type(k) != (ndarray or list): k = [k] k = array(k,dtype='int') k = k.ravel() kneq0 = k != 0 r = cos(theta) # Evaluate polynomials and multiplication factors p1 = jpoly(r,abs(k),delta-1/2.,gamma-1/2.).reshape([theta.size,k.size]) # Add things together Psi = zeros([theta.size,k.size],dtype=complex) Psi[:,~kneq0] = 1/sqrt(2)*p1[:,~kneq0] if k[kneq0].any(): p2 = jpoly(r,abs(k[kneq0])-1,delta+1/2.,gamma+1/2.).\ reshape([theta.size,k[kneq0].size]) kmat = sign(k[kneq0]) tmat = sin(theta) p2 = 1j*(p2.T*tmat).T*kmat Psi[:,kneq0] = 1/2.*(p1[:,kneq0] + p2) pss(theta,shift=shift,scale=scale) return Psi.squeeze()
def weighted_fseries(theta,k,gamma=0.,delta=0.,shift=0.,scale=1.): from spyctral.common.maps import standard_scaleshift as sss from spyctral.common.maps import physical_scaleshift as pss from numpy import sqrt, array from weights import sqrt_weight_bias as wsqrt_bias theta = array(theta) theta = theta.ravel() sss(theta,shift=shift,scale=scale) psi = fseries(theta,k,gamma=gamma,delta=delta,shift=0.,scale=1.) phi = (wsqrt_bias(theta,gamma=gamma,delta=delta,shift=0.,scale=1.)*psi.T).T pss(theta,shift=shift,scale=scale) # Scaling: return phi/sqrt(scale)
def dsqrt_weight_bias(theta,gamma=0.,delta=0.,shift=0.,scale=1.): from numpy import cos, sin, exp, abs from spyctral.common.maps import standard_scaleshift as sss from spyctral.common.maps import physical_scaleshift as pss from scipy import pi sss(theta,scale=scale,shift=shift) phase = exp(1j*(gamma+delta)/2.*(pi-theta))*\ 2**((gamma+delta-4)/2.) if delta != 0.: phase *= abs(sin(theta/2.))**(delta-1) if gamma != 0.: phase *= cos(theta/2.)**(gamma-1) w = phase*( delta*(1+exp(-1j*theta)) -\ gamma*(1+exp(1j*theta))) pss(theta,scale=scale,shift=shift) return w/scale
def jacobi_polynomial(x,n,alpha=-1/2.,beta=-1/2.,d=0, normalization='normal',scale=1., shift=0.) : """ Evaluates the Jacobi polynomials of class (alpha,beta), order n (list) at the points x (list/array). The normalization is specified by the keyword argument. Possibilities: 'normal', 'normalized': 'monic': """ from numpy import array, ndarray, ones, sqrt from coeffs import recurrence_range from spyctral.opoly1d.eval import eval_opoly, eval_normalized_opoly from spyctral.common.maps import physical_scaleshift as pss from spyctral.common.maps import standard_scaleshift as sss x = array(x) if all([type(n) != dtype for dtype in [list,ndarray]]): # Then it's probably an int n = array([n]) n = array(n) [a,b] = recurrence_range(max(n)+2,alpha=alpha,beta=beta) # dummy function for scaling def scale_ones(n,alpha,beta): return ones([1,len(n)]) # Set up different normalizations normal_fun = {'normal': eval_normalized_opoly, 'normalized': eval_normalized_opoly, 'monic': eval_opoly} normal_scale = {'normal': scale_ones, 'normalized': scale_ones, 'monic': scale_ones} # Shift to standard interval and use opoly 3-term recurrence normalization = normalization.lower() sss(x,scale=scale,shift=shift) temp = normal_fun[normalization](x,n,a,b,d=d) temp *= normal_scale[normalization](n,alpha,beta) pss(x,scale=scale,shift=shift) return temp
def gauss_quadrature(N,alpha=-1/2.,beta=-1/2.,shift=0.,scale=1.) : # Returns the N-point Jacobi-Gauss(alpha,beta) quadrature rule over the interval # (-scale,scale)+shift. # The quadrature rule is *not* normalized in the sense that the affine parameters # shift and scale are built into the new weight function for which this # quadrature rule is valid. from coeffs import recurrence_range from spyctral.opoly1d.quad import gq as ogq from spyctral import chebyshev from spyctral.common.maps import physical_scaleshift as pss tol = 1e-12; if (abs(alpha+1/2.)<tol) & (abs(beta+1/2.)<tol) : return chebyshev.quad.gq(N,shift=shift,scale=scale) else : [a,b] = recurrence_range(N,alpha,beta) temp = ogq(a,b) pss(temp[0],scale=scale,shift=shift) return temp
def dsqrt_weight(x,alpha=0., shift=0., scale=1.): """ Returns the derivative of the square root of the weight function for Laguerre orthogonal polynomials with parameter specifications alpha, shift, and scale. """ from spyctral.common.maps import standard_scaleshift as sss from spyctral.common.maps import physical_scaleshift as pss from numpy import exp, sqrt sss(x,shift=shift,scale=scale) if abs(alpha)<1e-8: dwfun = -1/2*exp(-x/2) else: dwfun = (alpha/2)*x**(alpha/2-1)*exp(-x/2) + \ x**(alpha/2)*-1/2*exp(-x/2) dwfun *= sqrt(scale) dwfun /= scale # Jacobian factor pss(x,shift=shift,scale=scale) return dwfun
def pgq(N,mu=0.,scale=1.,shift=0.): from numpy import array, zeros, exp from spyctral.common.maps import physical_scaleshift as pss from spyctral.common.maps import standard_scaleshift as sss mu = float(mu) # ??? #[x,w] = gq(N,mu,scale=scale,shift=shift) [x,w] = gq(N,mu=mu) #sss(x,shift=shift,scale=scale) #xt = (x-shift)/scale w /= x**(2*mu)*exp(-x**2) pss(x,shift=shift,scale=scale) # I DON'T UNDERSTAND THIS #w *= scale**2 w *= scale return [x,w]
def gq(N,gamma=0.,delta=0.,shift=0.,scale=1.): from numpy import arccos, hstack, isnan from spyctral.jacobi.quad import gq as jgq from spyctral.jacobi.quad import grq as jgrq from spyctral.common.maps import physical_scaleshift as pss N = int(N) tol = 1e-8 if (N%2)==0: [r,wr] = jgq(N/2,delta-1/2.,gamma-1/2.) r = r.squeeze() wr = wr.squeeze() temp = arccos(r[::-1]) wr = wr[::-1] theta = hstack((-temp[::-1],temp)) w = hstack((wr[::-1],wr)) pss(theta,scale=scale,shift=shift) return [theta,w] else: [r,wr] = jgrq((N+1)/2,delta-1/2.,gamma-1/2.,r0=1.) r = r.squeeze() wr = wr.squeeze() temp = arccos(r[::-1]) # Silly arccos machine epsilon crap temp[isnan(temp)] = 0. theta = hstack((-temp[::-1],temp[1:])) wr = wr[::-1] wr[0] *= 2 w = hstack((wr[::-1],wr[1:])) pss(theta,scale=scale,shift=shift) return [theta,w]
def r_to_x(r,scale=1.,shift=0.): from numpy import sqrt temp = r/sqrt(1-r**2) pss(temp,scale=scale,shift=shift) return temp