Source code for polynomials_on_simplices.piecewise_polynomial.continuous_piecewise_polynomial

r"""Functionality for Lagrange (continuous Galerkin) finite elements (continuous piecewise polynomials) on a simplicial
domain (triangulation) :math:`\mathcal{T}`.

The space of continuous piecewise polynomials of degree r on :math:`\mathcal{T}, C\mathcal{P}_r (\mathcal{T})
= C\mathcal{P}_r (\mathcal{T}, \mathbb{R}^n) \subset H^1(\mathcal{T}, \mathbb{R}^n)` is defined as

.. math::

    C\mathcal{P}_r (\mathcal{T}) = \{ v \in C(\mathcal{T}, \mathbb{R}^n) \big| v|_T \in
    \mathcal{P}_r(T, \mathbb{R}^n) \, \forall T \in \mathcal{T} \}.

Correspondingly the space of continuous piecewise polynomials of degree r on :math:`\mathcal{T}` which are zero on
specified set of simplices or subsimplices of :math:`\mathcal{T}, C\mathcal{P}_{r, 0} (\mathcal{T}))` is defined as

.. math::

    C\mathcal{P}_{r, 0} (\mathcal{T}) = \{ v \in C_0(\mathcal{T}, \mathbb{R}^n) \big| v|_T \in
    \mathcal{P}_r(T, \mathbb{R}^n) \, \forall T \in \mathcal{T} \}.
"""

import abc

import polynomials_on_simplices.algebra.multiindex as multiindex
from polynomials_on_simplices.geometry.mesh.simplicial_complex import simplex_sub_simplices
from polynomials_on_simplices.piecewise_polynomial.piecewise_polynomial import PiecewisePolynomialBase
from polynomials_on_simplices.polynomial.polynomials_unit_simplex_lagrange_basis import get_associated_sub_simplex


[docs]def generate_local_to_global_map(triangles, r, boundary_simplices=None, keep_boundary_dofs_last=False): r""" Generate a local-to-global map :math:`\tau` for the space of continuous piecewise polynomial functions of degree r on a triangulation :math:`\mathcal{T}, C \mathcal{P}_r (\mathcal{T})` or :math:`C \mathcal{P}_{r, 0} (\mathcal{T})`. We have :math:`\tau : \{ 0, 1, \ldots, | \mathcal{T} | - 1 \} \times \mathbb{N}_0^m \to \mathbb{N}_0 \cup \{ -1 \}`. A local-to-global map maps a local polynomial basis function on a simplex in the triangulation to a global basis index for a basis for the space of continuous piecewise polynomials. The value -1 is used to indicate that a local basis function has no corresponding global basis function (see later). Let :math:`d = \dim \mathcal{P}_r (\Delta_c^m)`, and let the triangles in :math:`\mathcal{T}` be enumerated so that we have :math:`\mathcal{T} = \{ T_0, T_1, \ldots, T_{| \mathcal{T} | - 1} \}`. Given a basis :math:`\{ \bar{\varphi}_{\nu} \}_{\substack{\nu \in \mathbb{N}_0^m \\ | \nu | \leq r}}` for :math:`\mathcal{P}_r (\Delta_c^m)`, the functions :math:`\{ \varphi_{\nu, j} = \bar{\varphi}_{\nu} \circ \Phi_{T_j}^{-1} \}_{\substack{\nu \in \mathbb{N}_0^m \\ | \nu | \leq r}}` is a basis for :math:`\mathcal{P}_r(T_j)`, where :math:`\Phi_{T_j}, j = 0, 1, \ldots, | \mathcal{T} | - 1` is the unique affine map which maps the unit simplex :math:`\Delta_c^m` to the simplex :math:`T_j`. From these local bases and the local-to-global map :math:`\tau` a basis :math:`\{ \phi_i \}_{i = 1}^N` for :math:`C \mathcal{P}_r (\mathcal{T})` is constructed, with .. math:: \phi_i(x) = \sum_{(j, \nu) \in \operatorname{preim}_{\tau}(i)} \chi_{T_j}(x) \cdot \varphi_{\nu, j}(x). For each triangle :math:`T_j` a basis function :math:`\phi_i` either agrees with a basis function :math:`\varphi_{\nu, j}` or it's zero. I.e. the set :math:`v_j = \{ (k, \nu) \in \operatorname{preim}_{\tau}(i) \big| k = j \}` either contains zero or one element. .. math:: \phi_i(x) = \begin{cases} \bar{\varphi}_{\nu} \circ \Phi_{T_j}^{-1}(x), & (\nu, j) \text{ unique element in } v_j \\ 0, & v_j \text{ is empty} \end{cases}. Optionally a set of boundary simplices can be prescribed where the piecewise polynomial function should vanish. This is achieved by associating an invalid global index (-1) for all local basis functions supported on any of the boundary simplices). Alternatively local basis functions supported on boundary simplices can be associated with global indices placed last in the enumeration of global basis functions (by setting the `keep_boundary_dofs_last` to true). :param triangles: Triangles (or in general simplices) in the mesh (num_triangles by n + 1 list of indices, where n is the dimension of each simplex). :param int r: Polynomial degree for the continuous piecewise polynomial functions. :param boundary_simplices: List of simplices or subsimplices on which the continuous piecewise polynomial functions should vanish (for an element of :math:`C\mathcal{P}_{r, 0} (\mathcal{T})`) or which should be treated separately (if `keep_boundary_dofs_last` is set to True). Each simplex or subsimplex is specified as a list of vertex indices of the vertices that form the simplex. :type boundary_simplices: List[List[int]] :param bool keep_boundary_dofs_last: Whether or not to collect all global basis functions associated with any boundary simplex last in the enumeration of all basis functions. Enumerating basis functions associated with boundary simplices last makes :math:`C\mathcal{P}_{r, 0} (\mathcal{T})` a subset of :math:`C\mathcal{P}_r (\mathcal{T})` in a practical way. :return: Tuple containing the local to global map :math:`\tau` and the number of global basis functions. If `keep_boundary_dofs_last` is true then the number of global basis functions not supported on the boundary is also returned. :rtype: Tuple[Callable :math:`\tau(j, \nu)`, int, Optional[int]]. """ num_non_boundary_basis_fns = 0 if keep_boundary_dofs_last: local_to_global_map, global_basis_fn_counter, num_non_boundary_basis_fns\ = generate_local_to_global_map_as_dictionaries(triangles, r, boundary_simplices, keep_boundary_dofs_last) else: local_to_global_map, global_basis_fn_counter\ = generate_local_to_global_map_as_dictionaries(triangles, r, boundary_simplices, keep_boundary_dofs_last) # Create callable local-to-global map (tau) def tau(j, nu): assert j >= 0 assert j < len(triangles) if nu in local_to_global_map[j]: return local_to_global_map[j][nu] else: # No corresponding global basis index for local basis function return -1 if keep_boundary_dofs_last: return tau, global_basis_fn_counter, num_non_boundary_basis_fns else: return tau, global_basis_fn_counter
[docs]def generate_local_to_global_map_as_dictionaries(triangles, r, boundary_simplices=None, keep_boundary_dofs_last=False): r""" Generate a local-to-global map for the space of continuous piecewise polynomial functions of degree r on a triangulation :math:`\mathcal{T}, C \mathcal{P}_r (\mathcal{T})` or :math:`C \mathcal{P}_{r, 0} (\mathcal{T})`. For details see :func:`generate_local_to_global_map`. This function differs from that function in that a list of dictionaries (one for each triangle in the mesh) with multi-indices (second function argument) as keys and global DOF indices (function value) as values is returned instead of a callable, which might be preferable in some cases. :param triangles: Triangles (or in general simplices) in the mesh (num_triangles by n + 1 list of indices, where n is the dimension of each simplex). :param int r: Polynomial degree for the piecewise polynomial functions. :param boundary_simplices: List of simplices or subsimplices on which the piecewise polynomial functions should vanish (for an element of :math:`D\mathcal{P}_{r, 0} (\mathcal{T})`) or which should be treated separately (if `keep_boundary_dofs_last` is set to True). Each simplex or subsimplex is specified as a list of vertex indices of the vertices that form the simplex. :type boundary_simplices: List[List[int]] :param bool keep_boundary_dofs_last: Whether or not to collect all global basis functions associated with any boundary simplex last in the enumeration of all basis functions. Enumerating basis functions associated with boundary simplices last is useful for handling :math:`D\mathcal{P}_{r, 0} (\mathcal{T})` as a subset of :math:`D\mathcal{P}_r (\mathcal{T})` in a practical way. :return: Tuple containing the local to global map dictionaries, one for each triangle, and the number of global basis functions. If `keep_boundary_dofs_last` is true then the number of global basis functions not supported on the boundary is also returned. :rtype: Tuple[List[dict[Tuple[int], int]], int, Optional[int]] """ assert r >= 1 n = len(triangles[0]) - 1 # Map containing global basis function associated with each sub simplex of the mesh sub_simplex_basis_fns = {} boundary_sub_simplices = set() if boundary_simplices is not None: for boundary_simplex in boundary_simplices: boundary_sub_simplices = boundary_sub_simplices.union(simplex_sub_simplices(boundary_simplex)) global_basis_fn_counter = 0 boundary_basis_fn_counter = -1 local_to_global_map = [] mis = multiindex.generate_all(n, r) for triangle in triangles: # Triangle local-to-global mapping tri_local_to_global = {} # Iterate over all multi-indices for mi in mis: # Compute sub simplex associated with the multi-index sub_simplex, sub_mi = get_associated_sub_simplex(mi, r, triangle) # Sort sub simplex and the associated multi-index to be able to compare simplices # regardless of orientation sub_simplex_sorted, mi_sorted = zip(*sorted(zip(sub_simplex, sub_mi))) if sub_simplex_sorted in boundary_sub_simplices and not keep_boundary_dofs_last: continue if len(sub_simplex) == n + 1: # Interior basis function, hence cannot be associated with an existing global basis function tri_local_to_global[tuple(mi)] = global_basis_fn_counter global_basis_fn_counter += 1 else: # Add sub simplex to simplex basis function dict if it doesn't already exist if sub_simplex_sorted not in sub_simplex_basis_fns: sub_simplex_basis_fns[sub_simplex_sorted] = {} # Check if the simplex and multi-index have already been associated with a global basis function if mi_sorted in sub_simplex_basis_fns[sub_simplex_sorted]: tri_local_to_global[tuple(mi)] = sub_simplex_basis_fns[sub_simplex_sorted][mi_sorted] else: if sub_simplex_sorted not in boundary_sub_simplices: # Associate simplex and multi-index with the next available global basis fn tri_local_to_global[tuple(mi)] = global_basis_fn_counter sub_simplex_basis_fns[sub_simplex_sorted][mi_sorted] = global_basis_fn_counter global_basis_fn_counter += 1 else: # Degree of freedom associated with a boundary simplex, so we give it a placeholder # enumeration for now, which later will be updated to make sure that these DOFs are # enumerated last tri_local_to_global[tuple(mi)] = boundary_basis_fn_counter sub_simplex_basis_fns[sub_simplex_sorted][mi_sorted] = boundary_basis_fn_counter boundary_basis_fn_counter -= 1 local_to_global_map.append(tri_local_to_global) # Handle boundary basis functions which should be placed last num_non_boundary_basis_fns = None if keep_boundary_dofs_last: num_non_boundary_basis_fns = global_basis_fn_counter num_boundary_basis_fns = 0 for tri_idx in range(len(triangles)): for key, value in local_to_global_map[tri_idx].items(): if value < 0: local_to_global_map[tri_idx][key] = num_non_boundary_basis_fns + (-value) - 1 num_boundary_basis_fns = max(num_boundary_basis_fns, -value) global_basis_fn_counter += num_boundary_basis_fns if num_non_boundary_basis_fns is not None: return local_to_global_map, global_basis_fn_counter, num_non_boundary_basis_fns else: return local_to_global_map, global_basis_fn_counter
[docs]def generate_vector_valued_local_to_global_map(triangles, r, n, boundary_simplices=None, keep_boundary_dofs_last=False, ordering="interleaved"): r""" Generate a local-to-global map :math:`\tau` for the space of vector valued continuous piecewise polynomial functions of degree r on a triangulation :math:`\mathcal{T}, C \mathcal{P}_r (\mathcal{T}, \mathbb{R}^n)` or :math:`C \mathcal{P}_{r, 0} (\mathcal{T}, \mathbb{R}^n)`. We have :math:`\tau : \{ 0, 1, \ldots, | \mathcal{T} | - 1 \} \times \mathbb{N}_0^m \times \{ 0, 1, \ldots, n - 1\} \to \mathbb{N}_0 \cup \{ -1 \}`. A local-to-global map maps a local polynomial basis function on a simplex in the triangulation to a global basis index for a basis for the space of vector valued continuous piecewise polynomials. The value -1 is used to indicate that a local basis function has no corresponding global basis function (see later). Let :math:`d = \dim \mathcal{P}_r (\Delta_c^m, \mathbb{R}^n)`, and let the triangles in :math:`\mathcal{T}` be enumerated so that we have :math:`\mathcal{T} = \{ T_0, T_1, \ldots, T_{| \mathcal{T} | - 1} \}`. Given a basis :math:`\{ \bar{\varphi}_{\nu, i} \}_{\substack{\nu \in \mathbb{N}_0^m \\ | \nu | \leq r \\ i \in \{ 0, 1, \ldots, n - 1 \}}}` for :math:`\mathcal{P}_r (\Delta_c^m, \mathbb{R}^n)`, the functions :math:`\{ \varphi_{\nu, j, i} = \bar{\varphi}_{\nu, i} \circ \Phi_{T_j}^{-1} \}_{\substack{\nu \in \mathbb{N}_0^m \\ | \nu | \leq r \\ i \in \{ 0, 1, \ldots, n - 1 \}}}` is a basis for :math:`\mathcal{P}_r(T_j, \mathbb{R}^n)`, where :math:`\Phi_{T_j}, j = 0, 1, \ldots, | \mathcal{T} | - 1` is the unique affine map which maps the unit simplex :math:`\Delta_c^m` to the simplex :math:`T_j`. From these local bases and the local-to-global map :math:`\tau` a basis :math:`\{ \phi_i \}_{i = 1}^N` for :math:`C \mathcal{P}_r (\mathcal{T}, \mathbb{R}^n)` is constructed, with .. math:: \phi_i(x) = \sum_{(j, \nu, k) \in \operatorname{preim}_{\tau}(i)} \chi_{T_j}(x) \cdot \varphi_{\nu, j, k}(x). For each triangle :math:`T_j` a basis function :math:`\phi_i` either agrees with a basis function :math:`\varphi_{\nu, j, k}` or it's zero. I.e. the set :math:`v_j = \{ (l, \nu, k) \in \operatorname{preim}_{\tau}(i) \big| l = j \}` either contains zero or one element. .. math:: \phi_i(x) = \begin{cases} \bar{\varphi}_{\nu, k} \circ \Phi_{T_j}^{-1}(x), & (j, \nu, k) \text{ unique element in } v_j \\ 0, & v_j \text{ is empty} \end{cases}. Optionally a set of boundary simplices can be prescribed where the piecewise polynomial function should vanish. This is achieved by associating an invalid global index (-1) for all local basis functions supported on any of the boundary simplices). Alternatively local basis functions supported on boundary simplices can be associated with global indices placed last in the enumeration of global basis functions (by setting the `keep_boundary_dofs_last` to true). :param triangles: Triangles (or in general simplices) in the mesh (num_triangles by n + 1 list of indices, where n is the dimension of each simplex). :param int r: Polynomial degree for the continuous piecewise polynomial functions. :param int n: Dimension of the target. :param boundary_simplices: List of simplices or subsimplices on which the continuous piecewise polynomial functions should vanish (for an element of :math:`C\mathcal{P}_{r, 0} (\mathcal{T}, \mathbb{R}^n)`) or which should be treated separately (if `keep_boundary_dofs_last` is set to True). Each simplex or subsimplex is specified as a list of vertex indices of the vertices that form the simplex. :type boundary_simplices: List[List[int]] :param bool keep_boundary_dofs_last: Whether or not to collect all global basis functions associated with any boundary simplex last in the enumeration of all basis functions. Enumerating basis functions associated with boundary simplices last makes :math:`C\mathcal{P}_{r, 0} (\mathcal{T}, \mathbb{R}^n)` a subset of :math:`C\mathcal{P}_r (\mathcal{T}, \mathbb{R}^n)` in a practical way. :param str ordering: How the vector valued basis functions are ordered. Can be "sequential" or "interleaved". For sequential, sorting is first done on the index of the component that is non-zero, and then the non-zero component is sorted in the same way as the scalar valued basis functions. For "interleaved" basis functions are first sorted on their non-zero component in the same way as scalar valued basis functions, and then they are sorted on the index of the component that is non-zero. :return: Tuple containing the local to global map :math:`\tau` and the number of global basis functions. If `keep_boundary_dofs_last` is true then the number of global basis functions not supported on the boundary is also returned. :rtype: Tuple[Callable :math:`\tau(j, \nu, k)`, int, Optional[int]]. """ # For a scalar valued piecewise polynomial, generate_local_to_global_map should be used instead assert n > 1 # Create callable local-to-global map (tau_scalar) for a scalar valued continuous piecewise polynomial num_scalar_non_boundary_basis_fns = 0 if keep_boundary_dofs_last: tau_scalar, global_scalar_basis_fn_counter, num_scalar_non_boundary_basis_fns = \ generate_local_to_global_map(triangles, r, boundary_simplices, keep_boundary_dofs_last) else: tau_scalar, global_scalar_basis_fn_counter = generate_local_to_global_map(triangles, r, boundary_simplices, keep_boundary_dofs_last) # Create callable local-to-global map (tau) for a vector valued continuous piecewise polynomial from the # local-to-global map for a scalar valued piecewise polynomial and the specified ordering of vector valued # basis functions if ordering == "interleaved": def tau(j, nu, k): assert j >= 0 assert j < len(triangles) assert k >= 0 assert k < n vs = tau_scalar(j, nu) if vs == -1: return -1 return n * vs + k else: def tau(j, nu, k): assert j >= 0 assert j < len(triangles) assert k >= 0 assert k < n vs = tau_scalar(j, nu) if vs == -1: return -1 return k * global_scalar_basis_fn_counter + vs if keep_boundary_dofs_last: return tau, n * global_scalar_basis_fn_counter, n * num_scalar_non_boundary_basis_fns else: return tau, n * global_scalar_basis_fn_counter
[docs]def generate_local_to_global_preimage_map(tau, num_triangles, num_dofs, r, m): r""" Generate the preimage map of a local-to-global map. Let :math:`\tau : \{ 0, 1, \ldots, | \mathcal{T} | - 1 \} \times \mathbb{N}_0^m \to \mathbb{N}_0 \cup \{ -1 \}` be a local-to-global map (see :func:`generate_local_to_global_map`). Then the preimage map of :math:`\tau` is the map .. math:: \operatorname{preim}_{\tau} : \mathcal{P} \mathbb{N}_0 \to \mathcal{P} \left( \{ 0, 1, \ldots, |\mathcal{T}| - 1 \} \times \mathbb{N}_0^N \right) such that .. math:: \tau(j, \nu) = i \quad \forall \, (j, \nu) \in \operatorname{preim}_{\tau}(\{i\}). :param tau: Local-to-global map that we want to create the preimage for. :type tau: Callable :math:`\tau(j, \nu)` :param int num_triangles: Number of triangles in the triangulation :math:`\mathcal{T}` on which the continuous piecewise polynomials associated with the local-to-global map are defined. :param int num_dofs: Number of degrees of freedom (dimension) for the space of continuous piecewise polynomials. :param int r: Polynomial degree for the continuous piecewise polynomials. :param int m: Dimension of the domain of the continuous piecewise polynomials. :return: Preimage of the local-to-global map. :rtype: Callable :math:`\operatorname{preim}_{\tau}(A)`. """ preimage_map_dict = {} mis = multiindex.generate_all(m, r) for j in range(num_triangles): for nu in mis: dof = tau(j, nu) if dof == -1: continue if dof in preimage_map_dict: preimage_map_dict[dof].add((j, nu)) else: preimage_map_dict[dof] = {(j, nu)} # Create callable preimage map def preimage_map(si): value = set() for i in si: assert i >= 0 assert i < num_dofs value = value.union(preimage_map_dict[i]) return value return preimage_map
[docs]def generate_vector_valued_local_to_global_preimage_map(tau, num_triangles, num_dofs, r, m, n): r""" Generate the preimage map of a local-to-global map. Let :math:`\tau : \{ 0, 1, \ldots, | \mathcal{T} | - 1 \} \times \mathbb{N}_0^m \times \{ 0, 1, \ldots, n - 1\} \to \mathbb{N}_0 \cup \{ -1 \}` be a local-to-global map (see :func:`generate_vector_valued_local_to_global_map`). Then the preimage map of :math:`\tau` is the map .. math:: \operatorname{preim}_{\tau} : \mathcal{P} \mathbb{N}_0 \to \mathcal{P} \left( \{ 0, 1, \ldots, |\mathcal{T}| - 1 \} \times \mathbb{N}_0^N \times \{ 0, 1, \ldots, n - 1 \} \right) such that .. math:: \tau(j, \nu, k) = i \quad \forall \, (j, \nu, k) \in \operatorname{preim}_{\tau}(\{i\}). :param tau: Local-to-global map that we want to create the preimage for. :type tau: Callable :math:`\tau(j, \nu, k)` :param int num_triangles: Number of triangles in the triangulation :math:`\mathcal{T}` on which the continuous piecewise polynomials associated with the local-to-global map are defined. :param int num_dofs: Number of degrees of freedom (dimension) for the space of continuous piecewise polynomials. :param int r: Polynomial degree for the continuous piecewise polynomials. :param int m: Dimension of the domain of the continuous piecewise polynomials. :param int n: Dimension of the domain of the continuous piecewise polynomials. :return: Preimage of the local-to-global map. :rtype: Callable :math:`\operatorname{preim}_{\tau}(A)`. """ preimage_map_dict = {} mis = multiindex.generate_all(m, r) for j in range(num_triangles): for nu in mis: for k in range(n): dof = tau(j, nu, k) if dof == -1: continue if dof in preimage_map_dict: preimage_map_dict[dof].add((j, nu, k)) else: preimage_map_dict[dof] = {(j, nu, k)} # Create callable preimage map def preimage_map(si): value = set() for i in si: assert i >= 0 assert i < num_dofs value = value.union(preimage_map_dict[i]) return value return preimage_map
[docs]class ContinuousPiecewisePolynomialBase(PiecewisePolynomialBase, abc.ABC): r""" Abstract base class for a continuous piecewise polynomial function of degree r on a triangulation :math:`\mathcal{T}`, i.e. an element of :math:`C\mathcal{P}_r (\mathcal{T})` or :math:`C\mathcal{P}_{r, 0} (\mathcal{T})`. The space of continuous piecewise polynomials is a subspace of the space of piecewise polynomials, see :mod:`polynomials_on_simplices.piecewise_polynomial.piecewise_polynomial` and in particular :class:`~polynomials_on_simplices.piecewise_polynomial.piecewise_polynomial.PiecewisePolynomialBase`. .. rubric:: Differentiable structure Besides the basic algebraic structures of the space of piecewise polynomials this class also defines the (weakly) differentiable structure of the space of continuous piecewise polynomials. `i`:th partial weak derivative: :math:`\partial_i : C\mathcal{P}_r (\mathcal{T}) \to D\mathcal{P}_{r - 1} (\mathcal{T})`. """ def __init__(self, coeff, triangles, vertices, r, tau=None, boundary_simplices=None, keep_boundary_dofs_last=False, support=None, bsp_tree=None): r""" :param coeff: Coefficients for the piecewise polynomial in the :math:`\{ \phi_i \}_{i = 1}^N` basis derived from the basis for :math:`\mathcal{P}_r (\Delta_c^m)` used (see :meth:`polynomials_on_simplices.piecewise_polynomial.piecewise_polynomial.PiecewisePolynomialBase.basis`) and the local-to-global map :math:`\tau`. :type coeff: List[Union[Scalar, Vector]] :param triangles: Triangles (or in general simplices) in the mesh :math:`\mathcal{T}` (num_triangles by m + 1 array of indices). :param vertices: Vertices in the mesh :math:`\mathcal{T}` (num_vertices by m array of scalars). :param int r: Degree of each polynomial in the piecewise polynomial. :param tau: Local-to-global map for mapping local basis functions to the index of the corresponding global basis function, in a way that makes sure that the piecewise polynomial is continuous. Will be generated if not supplied. :type tau: Callable :math:`\tau(j, \nu)` :param boundary_simplices: List of simplices or subsimplices on which the continuous piecewise polynomial function should vanish (for an element of :math:`C\mathcal{P}_{r, 0} (\mathcal{T})`) or which should be treated separately (if `keep_boundary_dofs_last` is set to True). Each simplex or subsimplex is specified as a list of vertex indices of the vertices that form the simplex. :type boundary_simplices: List[List[int]] :param bool keep_boundary_dofs_last: Whether or not to collect all global basis functions associated with any boundary simplex last in the enumeration of all basis functions. Enumerating basis functions associated with boundary simplices last is useful for handling :math:`C\mathcal{P}_{r, 0} (\mathcal{T})` as a subset of :math:`C\mathcal{P}_r (\mathcal{T})` in a practical way. :param Optional[Set[int]] support: Indices of the triangles in the triangulation where the continuous piecewise polynomial is supported. Will be generated if not supplied. :param bsp_tree: Optional implementation detail. A binary space partitioning tree built around the triangulation for quicker lookup of triangle a point lies in. Will be generated if not supplied. """ # TODO: Verify that the local-to-global map generates a single-valued (continuous) piecewise polynomial? if tau is None: tau, num_dofs = generate_local_to_global_map(triangles, r, boundary_simplices, keep_boundary_dofs_last) assert num_dofs == len(coeff) PiecewisePolynomialBase.__init__(self, coeff, triangles, vertices, r, tau, boundary_simplices, keep_boundary_dofs_last, support, bsp_tree)
[docs] @abc.abstractmethod def weak_partial_derivative(self, i=0): """ Compute the i:th weak partial derivative of the continuous piecewise polynomial. :param int i: Index of partial derivative. :return: i:th weak partial derivative of this continuous piecewise polynomial. """ pass
[docs] @staticmethod def generate_local_to_global_map(triangles, r, boundary_simplices=None, keep_boundary_dofs_last=False): r""" Generate a local-to-global map :math:`\tau` for the space of continuous piecewise polynomial functions of degree r on a triangulation :math:`\mathcal{T}, C \mathcal{P}_r (\mathcal{T})` or :math:`C \mathcal{P}_{r, 0} (\mathcal{T})`. See :func:`generate_local_to_global_map`. """ return generate_local_to_global_map(triangles, r, boundary_simplices, keep_boundary_dofs_last)