Contents:
Created on Thu Mar 29 11:33:32 2012
@author: Daniele Bigoni (dabi@imm.dtu.dk)
Implementation of Spectral Methods in 1 dimension.
Jacobi polynomials are defined on the domain \(\Omega=[-1,1]\) by the recurrence relation
with weight function
Note
In probability theory, the Beta distribution is defined on \(\Psi=[0,1]\) and its the Probability Distribution Function is
The relation betwen \(w(x;\alpha,\beta)\) and \(\rho_B(x;\alpha,\beta)\) for \(x \in \Psi\) is
For example:
>>> from scipy import stats
>>> plot(xp,stats.beta(3,5).pdf(xp))
>>> plot(xp,2.*Bx(xx,4,2),'--')
>>> plot(xp,stats.beta(3,8).pdf(xp))
>>> plot(xp,2.*Bx(xx,7,2),'--')
[1] | (1, 2, 3, 4) “Implemenenting Spectral Methods for Partial Differential Equations” by David A. Kopriva, Springer, 2009 |
[2] |
|
[3] | W.H. Press, Numerical Recipes: “The Art of Scientific Computing”. Cambridge University Press, 2007 |
[4] | (1, 2, 3, 4)
|
[5] | Y.Shi-jun, “Gauss-Radau and Gauss-Lobatto formulae for the Jacobi weight and Gori-Micchelli weight functions”. Journal of Zhejiang University Science, vol. 3, issue 4, pp. 455-460 |
Initialization of the Polynomial instance.
This method generates an instance of the Poly1D class, to be used in order to generate orthogonal basis of the polynomial type selected. Avaliable polynomial types can be selected using their string name or by predefined attributes
- ‘Jacobi’ or Spectral1D.JACOBI
- ‘HermiteP’ or Spectral1D.HERMITEP
- ‘HermiteF’ or Spectral1D.HERMITEF
- ‘HermitePprob’ or Spectral1D.HERMITEP_PROB
- ‘LaguerreP’ or Spectral1D.LAGUERREP
- ‘LaguerreF’ or Spectral1D.LAGUERREF
- ‘ORTHPOL’ or Spectral1D.ORTHPOL
Additional parameters are required for some polynomials.
Polynomial | Parameters |
---|---|
Jacobi | (alpha,beta) |
HermiteP | None |
HermiteF | None |
HermitePprob | None |
LaguerreP | alpha |
LaguerreF | alpha |
ORTHPOL | see notes |
Note
The ORTHPOL polynomials are built up using the “Multiple-Component Discretization Procedure” described in [4]. The following parameters describing the measure function are required in order to use the procedure for finding the recursion coefficients (alpha,beta) and have to be provided at construction time:
- ncapm: (int) maximum integer N0 (default = 500)
- mc: (int) number of component intervals in the continuous part of the spectrum
- mp: (int) number of points in the discrete part of the spectrum. If the measure has no discrete part, set mp=0
- xp, yp: (Numpy 1d-array) of dimension mp, containing the abscissas and the jumps of the point spectrum
- mu: (function) measure function that returns the mass (float) with arguments: x (float) absissa, i (int) interval number in the continuous part
- irout: (int) selects the routine for generating the recursion coefficients from the discrete inner product; irout=1 selects the routine sti, irout!=1 selects the routine lancz
- finl, finr: (bool) specify whether the extreme left/right interval is finite (false for infinite)
- endl, endr: (Numpy 1d-array) of dimension mc containing the left and right endpoints of the component intervals. If the first of these extends to -infinity, endl[0] is not being used by the routine.
Parameters iq, quad, idelta in [4] are suppressed. Instead the routine qgp of ORTHPOL [4] is used by default (iq=0 and idelta=2)
AssemblyDerivativeMatrix(): Assemble the k-th derivative matrix using polynomials of order N.
ChebyshevDerivativeCoefficients(): computes the Chebyshev coefficients of the derivative of a function
DiscretePolynomialTransform(): computes the Discrete Polynomial Transform of function values f
See also
FastChebyshevTransform
FastChebyshevTransform(): Returns the coefficients of the Fast Chebyshev Transform.
Warning
It is assumed that the values f are computed at Chebyshev-Gauss-Lobatto points.
Note
If f is odd, the vector is interpolated to even Chebyshev-Gauss-Lobatto points.
Note
Modification of algorithm (29) from [1]
Gamma(): returns the normalization constant for the N-th polynomial
GaussLobattoQuadrature(): Generates list of nodes for the Gauss-Lobatto quadrature rule using selected Polynomial basis
Note
Available only for Jacobi Polynomials and ORTHPOL
GaussQuadrature(): Generates list of nodes and weights for the Gauss quadrature rule using the selected Polynomial basis
GaussRadauQuadrature(): Generates list of nodes for the Gauss-Radau quadrature rule using selected Polynomial basis
Note
Available only for Laguerre Polynomials/Functions and ORTHPOL
GradEvaluate(): evaluate the k-th derivative of the N-th order polynomial at points r
GradVandermonde1D(): Initialize the k-th gradient of the modal basis N at r
GramSchmidt(): creates a Generalized Vandermonde Matrix of orthonormal polynomials with respect to the weights w
InverseDiscretePolynomialTransform(): computes the nodal values from the modal form fhat.
See also
InverseFastChebyshevTransform
InverseFastChebyshevTransform(): Returns the coefficients of the Inverse Fast Chebyshev Transform.
Note
If f is odd, the vector is padded with a zero value (highest freq.)
Note
Modification of algorithm (29) from [1]
LegendreDerivativeCoefficients(): computes the Legendre coefficients of the derivative of a function
PolyInterp(): Interpolate function values f from points x to points xi using Forward and Backward Polynomial Transform
Notes:
Quadrature(): Generates list of nodes and weights for the quadType quadrature rule using the selected Polynomial basis
Created on Mon Jul 9 11:35:12 2012
@author: Daniele Bigoni (dabi@imm.dtu.dk)
Implementation of Spectral Methods in n dimension.
It uses the package Spectral1D as basic polynomials in order to construct higher dimensional rules by tensor product.
Initialization of the N-dimensional Polynomial instance
See also
Spectral1D.Poly1D
GaussLobattoQuadrature(): computes the tensor product of the Guass Lobatto Points and weights
Warning
The lengths of Ns has to be conform to the number of polynomials with which you have instantiated PolyND
GaussQuadrature(): computes the tensor product of the Guass Points and weights
Warning
The lengths of Ns has to be conform to the number of polynomials with which you have instantiated PolyND
GradVandermonde(): initialize the tensor product of the k-th gradient of the modal basis.
Warning
The lengths of Ns , rs , ks , norms has to be conform to the number of polynomials with which you have instantiated PolyND
GradVandermondePascalSimplex(): initialize k-th gradient of the modal basis up to the total order N
Warning
The lengths of rs , ks , norms has to be conform to the number of polynomials with which you have instantiated PolyND
GaussQuadrature(): computes the tensor product of the Guass Points and weights
Warning
The lengths of Ns has to be conform to the number of polynomials with which you have instantiated PolyND
Created on Mon Jul 9 14:08:30 2012
@author: Daniele Bigoni (dabi@imm.dtu.dk)
Implementation of Sparse Grid (Smolyak) methods for numerical integration.
This implementation is a porting of the Sparse-Grid package developped in MatLab(R) at http://www.sparse-grids.de The code is extended with Clenshaw-Curtis and Fejer quadrature rules [1]
@copyright: 2007 Florian Heiss, Viktor Winschel
@copyright: 2012-2014 Daniele Bigoni
Initialization of the Sparse Grid instance.
Several 1D integration rules are available to be chosen for the qrule input parameter
sparseGrid(): main function for generating nodes & weights for sparse grids intergration
KPU(): function for generating 1D Nested rule for unweighted integral over [0,1] Syntax:
(n,w) = GQU(l)
KPN(): function for generating 1D Nested rule for integral with Gaussian weight Syntax:
(n,w) = GQU(l)
Created on Wed Feb 27
@author: Daniele Bigoni (dabi@dtu.dk)
Collection of miscellaneous functions used in the SpectralToolbox
ExpandingArray is used for the dynamic allocation of memory in applications where the total allocated memory needed cannot be predicted. Memory is preallocated with increases of 50% all the time data exceed the allocated memory.
Initialization of the Expanding Array.
>>> EA = ExpandingArray(initData,[allocInitDim=None,[dtype=np.float64,[maxIncrement=None]]])
Parameters: |
|
---|
Concatenate data to the existing array. If needed the array is resized in the axis direction by a factor of 50%.
Parameters: |
|
---|
>>> import numpy as np
>>> EA = Misc.ExpandingArray(np.random.rand(25,4))
>>> EA.shape()
(25, 4)
>>> EA.getAllocArray().shape
(25, 4)
>>> EA.concatenate(np.random.rand(13,4))
>>> EA.shape()
(38, 4)
Return the allocated array.
Returns: | allocated array |
---|---|
Return type: | ndarray |
>>> import numpy as np
>>> EA = Misc.ExpandingArray(np.random.rand(25,4))
>>> EA.shape()
(25, 4)
>>> EA.getAllocArray().shape
(25, 4)
>>> EA.concatenate(np.random.rand(13,4))
>>> EA.shape()
(38, 4)
>>> EA.getAllocArray().shape
(45, 4)
Get the view of the array with data.
Returns: | allocated array |
---|---|
Return type: | ndarray |
>>> EA.shape()
(38, 4)
>>> EA.getAllocArray().shape
(45, 4)
>>> EA.getDataArray().shape
(38, 4)
Returns the shape of the data inside the array. Note that the allocated memory is always bigger or equal to shape().
Returns: | shape of the data |
---|---|
Return type: | tuple of integer |
>>> import numpy as np
>>> EA = Misc.ExpandingArray(np.random.rand(25,4))
>>> EA.shape()
(25, 4)
>>> EA.getAllocArray().shape
(25, 4)
>>> EA.concatenate(np.random.rand(13,4))
>>> EA.shape()
(38, 4)
>>> EA.getAllocArray().shape
(45, 4)
Trim the axis dimension of N elements. The allocated data is not reinitialized or deallocated. Only the dimensions of the view are redefined.
Parameters: |
|
---|
>>> EA = Misc.ExpandingArray(np.random.rand(4,2))
>>> EA.getDataArray()
array([[ 0.42129746, 0.76220921],
[ 0.9238783 , 0.11256142],
[ 0.42031437, 0.87349243],
[ 0.83187297, 0.555708 ]])
>>> EA.trim(2,axis=0)
>>> EA.getDataArray()
array([[ 0.42129746, 0.76220921],
[ 0.9238783 , 0.11256142]])
>>> EA.getAllocArray()
array([[ 0.42129746, 0.76220921],
[ 0.9238783 , 0.11256142],
[ 0.42031437, 0.87349243],
[ 0.83187297, 0.555708 ]])
Generates the multi index ordering for the construction of multidimensional Generalized Vandermonde matrices
Parameters: |
|
---|---|
Returns: | array containing the ordered multi-indices |
Return type: | 2d-array of integer |
>>> Misc.MultiIndex(2,3)
array([[0, 0],
[1, 0],
[0, 1],
[2, 0],
[1, 1],
[0, 2],
[3, 0],
[2, 1],
[1, 2],
[0, 3]])
Check equality of two arrays objects up to a certain tolerance
Parameters: |
|
---|---|
Returns: | true if equal, false otherwise |
Return type: | bool |
>>> eps2 = 2.*Misc.machineEpsilon(np.float64)
>>> Misc.almostEqual(np.array([2.]),np.array([2.+0.5*eps2]),eps2)
True
>>> Misc.almostEqual(np.array([2.]),np.array([2.+2.*eps2]),eps2)
False
Check equality of a list of floats against an iterable value up to certain tolerance
Parameters: |
|
---|---|
Returns: | array of booleans containing true where equal, false elsewhere. |
Return type: | 1d-array of bool |
>>> eps2 = 2.*Misc.machineEpsilon(np.float64)
>>> X = np.random.rand(4,2)
>>> Misc.almostEqualList(X,X[1,:],eps2)
array([False, True, False, False], dtype=bool)
Implements the insertion sort with binary_search. Returns permutation indices.
Parameters: |
|
---|---|
Returns: | permutation indices |
Return type: | 1d-array of integers |
>>> X = np.random.rand(5,2)
>>> X
array([[ 0.56865133, 0.18490129],
[ 0.01411459, 0.46076606],
[ 0.64384365, 0.24998971],
[ 0.47840414, 0.32554137],
[ 0.12961966, 0.43712056]])
>>> perm = Misc.argsort_insertion(X,eps2)
>>> X[perm,:]
array([[ 0.01411459, 0.46076606],
[ 0.12961966, 0.43712056],
[ 0.47840414, 0.32554137],
[ 0.56865133, 0.18490129],
[ 0.64384365, 0.24998971]])
Search for the minimum X bigger than val
Parameters: |
|
---|---|
Returns: | index pointing to the maximum X smaller than val. If perm is provided, perm[idx] points to the maximum X smaller than val |
Return type: | integer |
>>> X = np.arange(1,5).reshape((4,1))
>>> X
array([[1],
[2],
[3],
[4]])
>>> Misc.binary_search(X,np.array([2.5]),0,4,eps2)
>>> idx = Misc.binary_search(X,np.array([2.5]),0,4,eps2)
>>> idx
2
>>> X[idx,:]
array([3])
Compares two iterable objects up to a certain tolerance
Parameters: |
|
---|---|
Returns: | -1 if (x-y) < tol, 1 if (x-y) > tol, 0 otherwise |
Return type: | integer |
>>> eps2 = 2.*Misc.machineEpsilon(np.float64)
>>> Misc.compare(np.array([2.]),np.array([2.+0.5*eps2]),eps2)
0
>>> Misc.compare(np.array([2.]),np.array([2.+2.*eps2]),eps2)
-1
Finds overlapping points of XF on X grids of points. The two grids are ordered with respect to Misc.compare().
Parameters: |
|
---|---|
Returns: | true values for overlapping points of XF on X, false for not overlapping points. Note: the overlapping return argument is a true-false indexing for XF. |
Return type: | 1d-array of bool |
Example
>>> XF
array([[ -1.73205081e+00, 0.00000000e+00],
[ -1.00000000e+00, -1.00000000e+00],
[ -1.00000000e+00, 0.00000000e+00],
[ -1.00000000e+00, 1.00000000e+00],
[ 0.00000000e+00, -1.73205081e+00],
[ 0.00000000e+00, -1.00000000e+00],
[ 0.00000000e+00, 2.16406754e-16],
[ 0.00000000e+00, 1.00000000e+00],
[ 0.00000000e+00, 1.73205081e+00],
[ 1.00000000e+00, -1.00000000e+00],
[ 1.00000000e+00, 0.00000000e+00],
[ 1.00000000e+00, 1.00000000e+00],
[ 1.73205081e+00, 0.00000000e+00]])
>>> X
array([[ -1.73205081e+00, 0.00000000e+00],
[ -1.00000000e+00, -1.00000000e+00],
[ -1.00000000e+00, 0.00000000e+00],
[ -1.00000000e+00, 1.00000000e+00],
[ 0.00000000e+00, -1.00000000e+00],
[ 2.16406754e-16, 0.00000000e+00],
[ 0.00000000e+00, 1.00000000e+00],
[ 1.00000000e+00, -1.00000000e+00],
[ 1.00000000e+00, 0.00000000e+00],
[ 1.00000000e+00, 1.00000000e+00],
[ 1.73205081e+00, 0.00000000e+00]])
>>> tol = 2. * Misc.machineEpsilon()
>>> bool_idx_over = Misc.findOverlapping(XF,X,tol)
>>> XF[np.logical_not(bool_idx_over),:]
array([[ 0. , -1.73205081],
[ 0. , 1.73205081]])
Returns the abolute machine precision for the type passed as argument
Parameters: | func (dtype) – type |
---|---|
Returns: | absolute machine precision |
Return type: | float |
>>> Misc.machineEpsilon(np.float64)
2.2204460492503131e-16
>>> Misc.machineEpsilon(np.float128)
1.084202172485504434e-19
Compute the power set of an iterable object.
Returns the unique values and a list of arrays of boolean indicating the positions of the unique values. If retIdx is true, then it returns the group of indices with the same values as a indicator function (true-false array)
Created on Wed Feb 27
@author: Daniele Bigoni (dabi@dtu.dk)
The types of polynomials available are all the ones included in the module Spectral1D. The rules don’t need to be symmetric and the accuracy per each direction can vary.
For rules with Heterogeneous accuracy, two sparse grids will be construced: one partial sparse grid and one full sparse grid (up to the maximum accuracy). The values computed for the partial sparse grid can then be used to interpolate on the points of the full sparse grid. This latter rule can then be used to compute the integral.
[6] |
|
Let’s consider the following space \(\Omega = [-\infty,\infty] imes[0,1]\) with the associated measures \(\mu_1(x)=\frac{1}{\sqrt{2\pi}} e^{-\frac{x^2}{2}}\) and \(\mu_2(x)=1\) for each dimension. The product measure is given by \(\mu(\bar{x})=\prod_{i=1}^n \mu_i(x_i)\). We will consider the function
>>> f_mult = lambda x,y,xp,yp: x**xp * y**yp
with exact value of the integral given by
>>> def I_mult(q,p):
>>> return 2.**(-.5+.5*(-1.+q)) * (1.+(-1.)**q) * scipy.special.gamma((1.+q)/2.) / ((1.+p)*np.sqrt(np.pi))
Let \(p_1=2\) and \(p_2=4\). We can obtain a sparse grid composed using Hermite basis (Spectral1D.HERMITEP_PROB) and Legendre basis (Spectral1D.JACOBI) with orders 2 and 4 respectively.
>>> from SpectralToolbox import HeterogeneousSparseGrids as HSG
>>> pH = Spectral1D.Poly1D(Spectral1D.HERMITEP_PROB,None)
>>> pL = Spectral1D.Poly1D(Spectral1D.JACOBI,[0.0,0.0])
>>> polys = [pH,pL]
>>> Ns = [2,4]
>>> sg = HSG.HSparseGrid(polys,Ns)
>>> (XF,W,X) = sg.sparseGrid()
[SG] Sparse Grid Generation [============================================] 100%
[SG] Sparse Grid Generation: 0.01s
>>> XF[:,1] = (XF[:,1]+1.)/2.
>>> X[:,1] = (X[:,1]+1.)/2.
>>> plt.figure()
>>> plt.plot(XF[:,0],XF[:,1],'o')
>>> plt.plot(X[:,0],X[:,1],'or')
The resulting partial and full sparse grids are shown in the following figure.
Partial (red) and full (blue) sparse grid. The full sparse grid is overlapping over the partial sparse grid.
The values on the partial grid can be computed and then the interpolation is taken over the full sparse grid.
>>> fX = f_mult(X[:,0],X[:,1],Q,P)
>>> fXF = sg.sparseGridInterp(X,fX,XF)
[SG] Sparse Grid Interpolation [=========================================] 100%
[SG] Sparse Grid Interpolation: 0.00s
Finally the error of the quadrature rule is
>>> IErr = np.abs(0.5*np.dot(fXF,W)-I_mult(Q,P))
>>> print IErr
3.33066907388e-16
Heterogeneous Sparse Grid class
Constructor of Heterogeneous Sparse Grid object (this does not allocate the sparse grid)
Parameters: |
|
---|
Note
one of the following must hold: len(polys)==len(Ns) or len(Ns)==1, in which case the same order is used for all the directions.
Example
>>> from SpectralToolbox import HeterogeneousSparseGrids as HSG
>>> pH = Spectral1D.Poly1D(Spectral1D.HERMITEP_PROB,None)
>>> pL = Spectral1D.Poly1D(Spectral1D.JACOBI,[0.0,0.0])
>>> polys = [pH,pL]
>>> Ns = [2,4]
>>> sg = HSG.HSparseGrid(polys,Ns)
Generates the full and partial sparse grids
Parameters: | heter (bool) – if Ns is homogeneous, this parameter will force the output of the partial sparse grid as well |
---|---|
Returns: | tuple (XF,WF,X) containing:
|
Example
>>> (XF,W,X) = sg.sparseGrid()
[SG] Sparse Grid Generation [============================================] 100%
[SG] Sparse Grid Generation: 0.01s
Interpolate values of the Sparse Grid using 1D Polynomial interpolation along cuts.
Parameters: |
|
---|---|
Returns: | fXF the interpolated values on the full grid |
Return type: | 1d-array of floats |
..note:: The partial and full grid must be overlapping
Example
>>> fXF = sg.sparseGridInterp(X,fX,XF)
[SG] Sparse Grid Interpolation [=========================================] 100%
[SG] Sparse Grid Interpolation: 0.00s