shenfun.forms package¶
Submodules¶
shenfun.forms.arguments module¶
- class shenfun.forms.arguments.Array(space, val=0, buffer=None, reltol=1e-12, abstol=1e-15)[source]¶
Bases:
ShenfunBaseArray
Numpy array for
TensorProductSpace
The Array is the result of a
Function
evaluated on its quadrature mesh.The Function represents in 1D
\[u(x) = \sum_{k \in \mathcal{K}} \hat{u}_k \psi_k(x),\]where \(\psi_k(x)\) are the trial functions and \(\{\hat{u}_k\}_{k\in\mathcal{K}}\) are the expansion coefficients. Here an index set \(\mathcal{K}=0, 1, \ldots, N\) is used to simplify notation.
For an M+1-dimensional TensorProductSpace with coordinates \(x_0, x_1, \ldots, x_M\) we get
\[u(x_{0}, x_{1}, \ldots, x_{M}) = \sum_{k_0 \in \mathcal{K}_0}\sum_{k_1 \in \mathcal{K}_1} \ldots \sum_{k_M \in \mathcal{K}_M} \hat{u}_{k_0, k_1, \ldots k_M} \psi_{k_0}(x_0) \psi_{k_1}(x_1) \ldots \psi_{k_M}(x_M),\]where \(\mathcal{K}_j\) is the index set for the wavenumber mesh along axis \(j\).
Note that for a Cartesian mesh in 3D it would be natural to use coordinates \((x, y, z) = (x_0, x_1, x_2)\) and the expansion would be the simpler and somewhat more intuitive
\[u(x, y, z) = \sum_{l \in \mathcal{K}_0}\sum_{m \in \mathcal{K}_1} \sum_{n \in \mathcal{K}_2} \hat{u}_{l, m, n} \psi_{l}(x) \psi_{m}(y) \psi_{n}(z).\]The Array’s values (the Numpy array) represent the left hand side, evaluated on the Cartesian quadrature mesh. With this we mean the \(u(x_i, y_j, z_k)\) array, where \(\{x_i\}_{i=0}^{N_0}\), \(\{y_j\}_{j=0}^{N_1}\) and \(\{z_k\}_{k=0}^{N_2}\) represent the mesh along the three directions. The quadrature mesh is then
\[(x_i, y_j, z_k) \quad \forall \, (i, j, k) \in [0, 1, \ldots, N_0] \times [0, 1, \ldots, N_1] \times [0, 1, \ldots, N_2]\]The entire spectral Galerkin function can be obtained using the
Function
class.- Parameters:
space (
TensorProductSpace
orSpectralBase
)val (int or float) – Value used to initialize array
buffer (Numpy array,
Function
or sympy Expr) – If array it must be of correct shape. A sympy expression is evaluated on the quadrature mesh and the result is used as buffer.
Note
For more information, see numpy.ndarray
Examples
>>> from shenfun import comm, FunctionSpace, TensorProductSpace, Array >>> K0 = FunctionSpace(8, 'F', dtype='D') >>> K1 = FunctionSpace(8, 'F', dtype='d') >>> FFT = TensorProductSpace(comm, [K0, K1]) >>> u = Array(FFT)
- forward(output_array=None, kind=None)[source]¶
Return Function used to evaluate Array
- Parameters:
output_array (array, optional) – Expansion coefficients
kind (str, optional) –
‘fast’ - use fast transform if implemented
‘vandermonde’ - Use Vandermonde matrix
- property forward_output¶
Return whether
self
is the result of a forward transform
- get_cartesian_vector()[source]¶
Return self as a Cartesian vector.
Note
This method is only relevant for curvilinear coordinates, where the vector uses different basis functions from the Cartesian.
- offset()[source]¶
Return offset of this basis
The offset is the number of scalar
TensorProductSpace
es ahead of this Arrays space in aCompositeSpace
.
- class shenfun.forms.arguments.BasisFunction(space, index=0, offset=0, base=None)[source]¶
Bases:
object
Base class for arguments to shenfun’s
Expr
- Parameters:
space (
TensorProductSpace
,CompositeSpace
or) –SpectralBase
index (int) – Local component of basis in
CompositeSpace
offset (int) – The number of scalar spaces (i.e.,
TensorProductSpace
) ahead of this spacebase (The base
BasisFunction
)
- property argument¶
Return argument of basis
- property base¶
Return base
- property dimensions¶
Return dimensions of function space
- offset()[source]¶
Return offset of this basis
The offset is the number of scalar
TensorProductSpace
es ahead of this space in aCompositeSpace
.
- property tensor_rank¶
Return tensor rank of basis
- class shenfun.forms.arguments.Expr(basis, terms=None, scales=None, indices=None)[source]¶
Bases:
object
Class for spectral Galerkin forms
An Expression that is linear in
TestFunction
,TrialFunction
orFunction
. Exprs are used as input toinner()
orproject()
.- Parameters:
basis (
BasisFunction
) –TestFunction
,TrialFunction
orFunction
terms (list of list of lists of length dimension) – Describes the differential operations performed on the basis function in the Expr
The triply nested terms lists are such that
the outermost list represents a tensor component. There is one item for each tensor component. If the Expr is a scalar with rank = 0, then len(terms) = 1. For vectors it equals ndim, which is the number of dimensions, and for second order tensors it equals ndim*ndim.
the second nested list represents the different terms in the form, that may be more than one. For example, the scalar valued div(grad(u)) has three terms in 3D:
\[\partial^2u/\partial x^2 + \partial^2u/\partial y^2 + \partial^2u/\partial z^2\]the last inner list represents the differential operations for each term and each tensor component, stored for each as a list of length = dim
The Expr div(grad(u)), where u is a scalar, is as such represented as a nested list of shapes (1, 3, 3), 1 meaning it’s a scalar, the first 3 because the Expr consists of the sum of three terms, and the last 3 because it is 3D. The entire representation is:
[[[2, 0, 0], [0, 2, 0], [0, 0, 2]]]
where the first [2, 0, 0] term has two derivatives in first direction and none in the others, the second [0, 2, 0] has two derivatives in second direction, and the last [0, 0, 2] has two derivatives in the last direction and none in the others.
scales (list of lists) – Representing a scalar multiply of each inner product. Note that the scalar can also be a function of coordinates (using sympy). There is one scale for each term in each tensor component, and as such it is a list of lists.
indices (list of lists) – Index into
CompositeSpace
. Only used when the basis of the form is composite. There is one index for each term in each tensor component, and as such it is a list of lists.
Examples
>>> from shenfun import * >>> from mpi4py import MPI >>> comm = MPI.COMM_WORLD >>> C0 = FunctionSpace(16, 'F', dtype='D') >>> C1 = FunctionSpace(16, 'F', dtype='D') >>> R0 = FunctionSpace(16, 'F', dtype='d') >>> T = TensorProductSpace(comm, (C0, C1, R0)) >>> v = TestFunction(T) >>> e = div(grad(v)) >>> e.terms() [[[2, 0, 0], [0, 2, 0], [0, 0, 2]]] >>> e2 = grad(v) >>> e2.terms() [[[1, 0, 0]], [[0, 1, 0]], [[0, 0, 1]]]
Note that e2 in the example has shape (3, 1, 3). The first 3 because it is a vector, the 1 because each vector item contains one term, and the final 3 since it is a 3-dimensional tensor product space.
- property argument¶
Return argument of Expr’s basis
- property base¶
Return base BasisFunction used in Expr
- property dimensions¶
Return ndim of Expr
- eval(x, output_array=None)[source]¶
Return expression evaluated on x
- Parameters:
x (float or array of floats) – Array must be of shape (D, N), for N points in D dimensions
- get_contravariant_component(i, j=None)[source]¶
Return contravariant vector component
- Parameters:
i (int or None) – First vector component. In 1D set i to None
j (int, optional) – Second component of tensor
Note
The contravariant vector components are the components to the covariant basisvectors. If the basis vectors are normalized, i.e., if the setting is config[‘basisvectors’] == ‘normal’, then the normal vector components must be scaled in order to get to the contravariant components.
- property is_basis_function¶
- property tensor_rank¶
Return rank of Expr’s
BasisFunction
- tosympy(basis=None, psi=(x, y, z, r, s))[source]¶
Return self evaluated with a sympy basis
- Parameters:
basis (sympy Expr or string) – if sympy Expr, then use this directly if str, then use that as name for a generic sympy Function
psi (tuple of sympy Symbols)
Examples
>>> from shenfun import FunctionSpace, TensorProductSpace >>> import sympy as sp >>> theta, r = psi = sp.symbols('x,y', real=True, positive=True) >>> rv = (r*sp.cos(theta), r*sp.sin(theta)) >>> F0 = FunctionSpace(8, 'F', dtype='d') >>> T0 = FunctionSpace(8, 'C') >>> T = TensorProductSpace(comm, (F0, T0), coordinates=(psi, rv)) >>> u = TrialFunction(T) >>> ue = r*sp.cos(theta) >>> du = div(grad(u)) >>> du.tosympy() Derivative(u(x, y), (y, 2)) + Derivative(u(x, y), y)/y + Derivative(u(x, y), (x, 2))/y**2 >>> du.tosympy(basis=ue, psi=psi) 0
- class shenfun.forms.arguments.Function(space, val=0, buffer=None, reltol=1e-12, abstol=1e-15)[source]¶
Bases:
ShenfunBaseArray
,BasisFunction
Spectral Galerkin function for given
TensorProductSpace
orSpectralBase
The Function in one dimension is
\[u(x) = \sum_{k \in \mathcal{K}} \hat{u}_k \psi_k(x),\]where \(\psi_k(x)\) are the trial functions and \(\{\hat{u}_k\}_{k\in\mathcal{K}}\) are the expansion coefficients. Here an index set \(\mathcal{K}=0, 1, \ldots, N\) is used to simplify notation.
For an M+1-dimensional TensorProductSpace with coordinates \(x_0, x_1, \ldots, x_M\) we get
\[u(x_{0}, x_{1}, \ldots, x_{M}) = \sum_{k_0 \in \mathcal{K}_0}\sum_{k_1 \in \mathcal{K}_1} \ldots \sum_{k_M \in \mathcal{K}_M} \hat{u}_{k_0, k_1, \ldots k_M} \psi_{k_0}(x_0) \psi_{k_1}(x_1) \ldots \psi_{k_M}(x_M),\]where \(\mathcal{K}_j\) is the index set for the wavenumber mesh along axis \(j\).
Note that for a Cartesian mesh in 3D it would be natural to use coordinates \((x, y, z) = (x_0, x_1, x_2)\) and the expansion would be the simpler and somewhat more intuitive
\[u(x, y, z) = \sum_{l \in \mathcal{K}_0}\sum_{m \in \mathcal{K}_1} \sum_{n \in \mathcal{K}_2} \hat{u}_{l, m, n} \psi_{l}(x) \psi_{m}(y) \psi_{n}(z).\]The Function’s values (the Numpy array) represent the \(\hat{u}\) array. The trial functions \(\psi\) may differ in the different directions. They are chosen when creating the TensorProductSpace.
- Parameters:
space (
TensorProductSpace
orFunctionSpace()
)val (int or float) – Value used to initialize array
buffer (Numpy array,
Function
or sympy Expr) – If array it must be of correct shape. A sympy expression is evaluated on the quadrature mesh and forward transformed to create the buffer array.reltol (number, optional) – Relative tolerance for adaptively finding dimension of space from the buffer.
abstol (number, optional) – Absolute tolerance for adaptively finding dimension of space from the buffer
Note
For more information, see numpy.ndarray
Example
>>> from shenfun import comm, FunctionSpace, TensorProductSpace, Function >>> K0 = FunctionSpace(8, 'F', dtype='D') >>> K1 = FunctionSpace(8, 'F', dtype='d') >>> T = TensorProductSpace(comm, [K0, K1]) >>> u = Function(T) >>> K2 = FunctionSpace(8, 'C', bc=(0, 0)) >>> T2 = TensorProductSpace(comm, [K0, K1, K2]) >>> v = Function(T2)
You get the array the space is planned for. This is probably what you expect:
>>> u = Function(K0) >>> print(u.shape) (8,)
But make the TensorProductSpace change K0 and K1 inplace:
>>> T = TensorProductSpace(comm, [K0, K1], modify_spaces_inplace=True) >>> u = Function(K0) >>> print(u.shape) (8, 5)
If you want to preserve K0 as a 1D function space, then use modify_spaces_inplace=False, which is the default behaviour.
Note
The array returned will have the same shape as the arrays space is planned for. So if you want a Function on a 1D FunctionSpace, then make sure that FunctionSpace is not planned for a TensorProductSpace.
- assign(u_hat)[source]¶
Assign self to u_hat of possibly different size
- Parameters:
u_hat (Function) – Function of possibly different shape than self. Must have the same function_space
- backward(output_array=None, kind=None, mesh=None, padding_factor=None)[source]¶
Return Function evaluated on some quadrature mesh
- Parameters:
output_array (array, optional) – Return array, Function evaluated on mesh
kind (dict or str, optional) – Can be used to overload config[‘transforms’][‘kind’], using a dictionary with family as key and values either one of the strings - ‘fast’ - ‘recursive’ - ‘vandermonde’ For example kind={‘chebyshev’: ‘vandermonde’} Note that for one-dimensional problems one can use just the string value and no dict
mesh (str, list or functionspace, optional) –
‘quadrature’ - use quadrature mesh of self
‘uniform’ - use uniform mesh
A function space with the same mesh distribution as self
padding_factor (None or number or tuple, optional) – If padding_factor is a number different from 1, then perform a padded backward transform, using a padded work array ‘self._backward_work_array’. Use a tuple for different padding in different directions.
Note
If output_array is not provided, then a new Array is created and returned. If padding_factor is used, then the returned Array is cached and reused for subsequent calls using the same padding_factor.
- property base¶
Base object if memory is from some other object.
Examples
The base of an array that owns its memory is None:
>>> x = np.array([1,2,3,4]) >>> x.base is None True
Slicing creates a view, whose memory is shared with x:
>>> y = x[2:] >>> y.base is x True
- copy_from_flattened(f, j=(), dims=None, sl=None)[source]¶
Copy dofs to self from a flattened array
- Parameters:
f (array 1D) – The array to copy from
j (int or tuple, optional) – Index into diagonal axes (Fourier)
dims (array 1D, optional) – The flat dim of each variable in the composite basis
sl (sequence of slices, optional) – list of slices into non-diagonal axes
Note
All Functions have allocated Numpy arrays assuming all dofs are being used. However, for non-orthogonal bases with boundary conditions we use only the first N-nb dofs, where nb is the number of boundary conditions. This function does not copy the boundary dofs.
- copy_to_flattened(f=None, j=(), dims=None, sl=None)[source]¶
Copy dofs of self to a flattened array
- Parameters:
f (array 1D, optional) – The array to copy to
j (int or tuple, optional) – Index into diagonal axes (Fourier). Not used if sl is provided
dims (array 1D, optional) – The dim of each variable in the composite basis
sl (sequence of slices, optional) – list of slices into non-diagonal axes
Note
All Functions have allocated Numpy arrays assuming all dofs are being used. However, for non-orthogonal bases with boundary conditions we use only the first N-nb dofs, where nb is the number of boundary conditions. This function does not copy the boundary dofs.
- eval(x, output_array=None)[source]¶
Evaluate Function at points x
- Parameters:
x (float or array of floats)
output_array (array, optional) – Return array, function values at points
Examples
>>> import sympy as sp >>> K0 = FunctionSpace(9, 'F', dtype='D') >>> K1 = FunctionSpace(8, 'F', dtype='d') >>> T = TensorProductSpace(MPI.COMM_WORLD, [K0, K1], axes=(0, 1)) >>> X = T.local_mesh() >>> x, y = sp.symbols("x,y") >>> ue = sp.sin(2*x) + sp.cos(3*y) >>> ul = sp.lambdify((x, y), ue, 'numpy') >>> ua = Array(T, buffer=ul(*X)) >>> points = np.random.random((2, 4)) >>> u = ua.forward() >>> u0 = u.eval(points).real >>> assert np.allclose(u0, ul(*points))
- property forward_output¶
Return whether
self
is the result of a forward transform
- get_dealiased_space(padding_factor)[source]¶
Return a function space to be used for padded transforms
- Parameters:
padding_factor (number or tuple) – The padding factor of the backward transform A tuple can be used for padding differently in each direction.
- refine(N, output_array=None)[source]¶
Return self with new number of quadrature points
- Parameters:
N (number or sequence of numbers) – The new number of quadrature points
Note
If N is smaller than for self, then a truncated array is returned. If N is greater than before, then the returned array is padded with zeros.
- shenfun.forms.arguments.FunctionSpace(N, family='Fourier', bc=None, dtype='d', quad=None, domain=None, scaled=None, padding_factor=1, basis=None, dealias_direct=False, coordinates=None, **kw)[source]¶
Return function space
- Parameters:
N (int) – Number of quadrature points
family (str, optional) – Choose one of
Chebyshev
orC
,Chebyshevu
orU
,Legendre
orL
,Fourier
orF
,Laguerre
orLa
,Hermite
orH
Jacobi
orJ
Ultraspherical
orQ
bc (tuple or dict, optional) – See
BoundaryConditions
dtype (str or np.dtype, optional) – The datatype of physical space (input to forward transforms)
quad (str, optional) – Type of quadrature
For family=Chebyshev:
GL - Chebyshev-Gauss-Lobatto
GC - Chebyshev-Gauss
For family=Chebyshevu:
GU - Chebyshevu-Gauss
GC - Chebyshev-Gauss
For family=Legendre:
LG - Legendre-Gauss
GL - Legendre-Gauss-Lobatto
For family=Laguerre:
LG - Laguerre-Gauss
For family=Hermite:
HG - Hermite-Gauss
For family=Jacobi:
JG - Jacobi-Gauss
For family=Ultraspherical:
QG - Jacobi-Gauss
domain (two-tuple of floats, optional) – The computational domain
scaled (bool) – Whether to use scaled basis
basis (str) – Name of basis to use, if there are more than one possible basis for a given boundary condition. For example, there are three Dirichlet bases for the Chebyshev family:
Heinrichs
,ShenDirichlet
andPhi1
padding_factor (float, optional) – For padding backward transform (for dealiasing)
dealias_direct (bool, optional) – Use 2/3-rule dealiasing
coordinates (2- or 3-tuple (coordinate, position vector (, sympy assumptions)), optional) – Map for curvilinear coordinates. Used for curves parametrized with one parameter in \(\mathbb{R}^2\) or \(\mathbb{R}^3\). The parameter is the first item. Second item is a tuple of length 2 or 3 (for \(\mathbb{R}^2\) or \(\mathbb{R}^3\)) for the Cartesian position vector. The sympy assumptions are there to help Sympy compute basis vectors and metrics, see
Coordinates
for options. Example circle of radius 1:theta = sp.Symbol('x', real=True) rv = (sp.cos(theta), sp.sin(theta)) FunctionSpace(16, 'L', coordinates=(theta, rv), domain=(0, 2*np.pi))
Examples
>>> from shenfun import FunctionSpace >>> F0 = FunctionSpace(16, 'F') >>> C1 = FunctionSpace(32, 'C', quad='GC')
- class shenfun.forms.arguments.TestFunction(space, index=0, offset=0, base=None)[source]¶
Bases:
BasisFunction
Test function - BasisFunction with argument = 0
- Parameters:
space (
TensorProductSpace
orCompositeSpace
)index (int, optional) – Component of basis in
CompositeSpace
offset (int) – The number of scalar spaces (i.e.,
TensorProductSpace
) ahead of this spacebase (The base
TestFunction
)
- property argument¶
Return argument of basis
- class shenfun.forms.arguments.TrialFunction(space, index=0, offset=0, base=None)[source]¶
Bases:
BasisFunction
Trial function - BasisFunction with argument = 1
- Parameters:
space (
TensorProductSpace
orCompositeSpace
)index (int, optional) – Component of basis in
CompositeSpace
offset (int) – The number of scalar spaces (i.e.,
TensorProductSpace
) ahead of this spacebase (The base
TrialFunction
)
- property argument¶
Return argument of basis
shenfun.forms.inner module¶
- class shenfun.forms.inner.Inner(v, uh)[source]¶
Bases:
object
Return an instance of a class that can perform the inner product of the linear form efficiently through a matrix-vector product
- Parameters:
v (
TestFunction
)uh (Instance of either one of) –
Note
This is an optimization only for linear forms, not bilinear. There is no need to use this class for regular scalar products, where uh is simply an Array.
- shenfun.forms.inner.inner(expr0, expr1, output_array=None, assemble=None, kind=None, fixed_resolution=None, return_matrices=False)[source]¶
Return (weighted or unweighted) discrete inner product
\[(f, g)_w^N = \sum_{i\in\mathcal{I}}f(x_i) \overline{g}(x_i) w_i \approx \int_{\Omega} f\, \overline{g}\, w\, dx\]where \(\mathcal{I}=0, 1, \ldots, N-1, N \in \mathbb{Z}^+\), \(f\) is a number or an expression linear in a
TestFunction
, and \(g\) is an expression that is linear inTrialFunction
orFunction
, or it is simply anArray
(a solution interpolated on the quadrature mesh in physical space). \(w\) is a weight associated with chosen basis, and \(w_i\) are quadrature weights.Note
If \(f\) is a number (typically one) and \(g\) an
Array
, then inner represents an unweighted, regular integral over the domain.If the expressions are created in a multidimensional
TensorProductSpace
, then the sum above is over all dimensions. In 2D it becomes:\[(f, g)_w^N = \sum_{i\in\mathcal{I}}\sum_{j\in\mathcal{J}} f(x_i, y_j) \overline{g}(x_i, y_j) w_j w_i\]where \(\mathcal{J}=0, 1, \ldots, M, M \in \mathbb{Z}^+\).
- Parameters:
expr0, expr1 (
Expr
,BasisFunction
,Array
, number) – Either one can be an expression involving a BasisFunction (TestFunction
,TrialFunction
orFunction
) an Array or a number. With expressions (Expr) on a BasisFunction we typically mean terms like div(u) or grad(u), where u is any one of the different types of BasisFunction. If one ofexpr0
/expr1
involves a TestFunction and the other one involves a TrialFunction, then a tensor product matrix (or a list of tensor product matrices) is returned. If one ofexpr0
/expr1
involves a TestFunction and the other one involves a Function, or a plain Array, then a linear form is assembled and a Function is returned. If one ofexpr0
/expr1
is a number (typically 1), or a tuple of numbers for a vector, then the inner product represents a non-weighted integral over the domain. If a single number, then the other expression must be a scalar Array or a Function. If a tuple of numbers, then the Array/Function must be a vector.output_array (Function) – Optional return array for linear form.
assemble (None or str, optional) – Determines how to perform the integration
‘quadrature’ (default)
‘exact’
‘adaptive’
Exact and adaptive should result in the same matrix. Exact computes the integral using Sympy integrate, whereas adaptive makes use of adaptive quadrature through scipy. For most bilinear forms quadrature will also return the same matrix as exact. With non-constant measures (like for curvilinear coordinates) there is more likely to be differences.
kind (None, str or dict, optional) – Alternative methods.
For bilinear forms (matrices) kind is a string:
‘implemented’ - Hardcoded implementations
‘stencil’ - Use orthogonal bases and stencil-matrices
‘vandermonde’ - Use Vandermonde matrix
The default (for kind=None) is to first try to look for implemented kind, and if that fails try first ‘stencil’ and then finally fall back on vandermonde. Vandermonde creates a dense matrix of size NxN, so it should be avoided (e.g., by implementing the matrix) for large N.
For linear forms (vectors) the kind keyword can be used to overload the default methods for transforms set in config[‘transforms’][‘kind’]. Hence, kind is a dictionary with family as key and values either one of the possible methods
‘fast’ - Use FFT (only Fourier and Chebyshev first and second kind)
‘recursive’ - Low-memory implementation (only for Jacobi polynomials)
‘vandermonde’ - Use Vandermonde matrix
E.g., kind={‘chebyshev’: ‘recursive’}. Note that for one-dimensional problems it is enough to use just the value of the dictionary.
fixed_resolution (Number or sequence of integers, optional) – A fixed number of quadrature points used to compute the inner product along each dimension of the domain. If ‘fixed_resolution’ is set, then assemble is set to ‘quadrature’ and kind is set to ‘vandermonde’. fixed_resolution is argument to
TensorProductSpace.get_refined()
.return_matrices (bool, optional) – For linear forms, whether to simply return the matrices that are used to compute the result with matrix-vector products.
Note
For most matrices all methods will lead to the same result. For bilinear forms with polynomial coefficients regular quadrature will become inaccurate and a ‘fixed_resolution’ higher than the regular number of quadrature points should be considered.
- Returns:
Function
for linear forms.SparseMatrix
for bilinear 1D forms.TPMatrix
or list ofTPMatrix
for bilinear multidimensional forms.Number, for non-weighted integral where either one of the arguments is a number.
- Return type:
Depending on dimensionality and the arguments to the forms
See also
Example
Compute mass matrix of Shen’s Chebyshev Dirichlet basis:
>>> from shenfun import FunctionSpace, TensorProductSpace >>> from shenfun import TestFunction, TrialFunction, Array >>> SD = FunctionSpace(6, 'Chebyshev', bc=(0, 0)) >>> u = TrialFunction(SD) >>> v = TestFunction(SD) >>> B = inner(v, u) >>> d = {-2: np.array([-np.pi/2]), ... 0: np.array([ 1.5*np.pi, np.pi, np.pi, np.pi]), ... 2: np.array([-np.pi/2])} >>> [np.all(abs(B[k]-v) < 1e-7) for k, v in d.items()] [True, True, True]
# Compute unweighted integral >>> F = FunctionSpace(10, ‘F’, domain=(0, 2*np.pi)) >>> T = TensorProductSpace(comm, (SD, F)) >>> area = inner(1, Array(T, val=1)) >>> print(‘Area of domain =’, area) Area of domain = 12.56637061435917
shenfun.forms.operators module¶
- shenfun.forms.operators.Dx(test, x, k=1)[source]¶
Return k’th order partial derivative in direction x
- Parameters:
test (Expr or BasisFunction)
x (int) – axis to take derivative over
k (int) – Number of derivatives
- shenfun.forms.operators.curl(test)[source]¶
Return curl of test
- Parameters:
test (Expr or BasisFunction)
shenfun.forms.project module¶
- class shenfun.forms.project.Project(uh, T, output_array=None)[source]¶
Bases:
object
Return an instance of a class that can perform projections efficiently
- Parameters:
uh (Instance of either one of) –
Example
>>> from shenfun import TestFunction, Function, Dx, Project, FunctionSpace >>> T = FunctionSpace(8, 'C') >>> u = Function(T) >>> u[1] = 1 >>> dudx = Project(Dx(u, 0, 1), T) >>> dudx() Function([1., 0., 0., 0., 0., 0., 0., 0.])
Note that u[1] = 1 sets the coefficient of the second Chebyshev polynomial (i.e., x) to 1. Hence the derivative of u is dx/dx=1, which is the result of dudx().
- shenfun.forms.project.project(uh, T, output_array=None, fill=True, use_to_ortho=True, use_assign=True)[source]¶
Project
uh
to tensor product spaceT
Find \(u \in T\), such that
\[(u - u_h, v)_w^N = 0 \quad \forall v \in T\]- Parameters:
uh (Instance of either one of) –
A sympy function
output_array (
Function
, optional) – Return arrayfill (bool, optional) – Whether to fill the output_array with zeros before projection
use_to_ortho (bool, optional) – Whether to use fast to_ortho method for projection of Functions to orthogonal space.
use_assign (bool, optional) – Whether to use fast assign method for projection of Function to a denser space of the same kind.
- Returns:
The projection of
uh
in T- Return type:
See also
Example
>>> import numpy as np >>> from mpi4py import MPI >>> from shenfun import FunctionSpace, project, TensorProductSpace, Array, \ ... Function, Dx >>> N = 16 >>> comm = MPI.COMM_WORLD >>> T0 = FunctionSpace(N, 'C') >>> K0 = FunctionSpace(N, 'F', dtype='d') >>> T = TensorProductSpace(comm, (T0, K0)) >>> uj = Array(T) >>> uj[:] = np.random.random(uj.shape) >>> u = Function(T) >>> u = project(uj, T, output_array=u) # Same as u = T.forward(uj, u) >>> du = project(Dx(u, 0, 1), T)