hermit.transfer =============== .. py:module:: hermit.transfer .. autoapi-nested-parse:: ``interpolate`` / ``project`` -- transfer a :class:`hermit.Field` between spaces on the same mesh. ``interpolate`` is collocation: the source basis evaluated at the target dofs' *reference* coordinates, a constant sparse matrix and therefore a plain ``csdl.sparse.matvec``. It is fully differentiable in the coefficients and independent of the geometry. This holds for identity-mapped, point-evaluation elements -- Lagrange, DG, DQ and Quadrature, which covers every space these builders produce. Piola-mapped families such as RT and Nedelec are rejected, as is the Crouzeix-Raviart rotation space of the ``CG2CR1`` element. ``project`` is the L2 alternative, ``M c = int(phi_target . src) dx``. Both sides carry ``dx``, so it depends on the geometry: it is a custom operation with the mass-matrix quotient-rule VJP, reverse mode only. Its optional ``geometry=`` argument defaults to the domain's reference coordinates, which keeps the mass factorization cached; passing a live geometry enables the shape-derivative branch. .. !! processed by numpydoc !! Functions --------- .. autoapisummary:: hermit.transfer.interpolate hermit.transfer.project Module Contents --------------- .. py:function:: interpolate(src_field, space) -> hermit._field.Field Collocate a field at another space's dof points -- the default transfer. :Parameters: **src_field** : Field .. **space** : tuple Target space; its value shape must match the source's. :Returns: Field On the target space, or ``src_field`` itself if already there. :Raises: ValueError If the value shapes differ, or if either space is not point-evaluation (Lagrange, DG, DQ or Quadrature). Piola-mapped families such as RT and Nedelec drag in the geometric Jacobian and are rejected, as does Crouzeix-Raviart. A Quadrature *source* has no basis to tabulate -- use :func:`project`. .. seealso:: :obj:`project` the geometry-dependent L2 alternative. .. rubric:: Notes A constant sparse matrix, memoized per source/target pair, so this is a plain ``csdl.sparse.matvec``: fully differentiable in the coefficients and independent of the geometry, because the target dofs' reference coordinates never move. .. !! processed by numpydoc !! .. py:function:: project(src_field, space, *, geometry=None) -> hermit._field.Field L2-project a field onto another space, ``M c = int(phi_target . src) dx``. :Parameters: **src_field** : Field .. **space** : tuple Target space; its value shape must match the source's. **geometry** : Geometry, ndarray or csdl.Variable, optional Defaults to the domain's reference coordinates, which lets the mass-matrix factorization be cached across calls. Passing a live geometry enables the shape-derivative branch. :Returns: Field On the target space. Projecting onto the same space is the identity up to solver round-off. :Raises: ValueError If the value shapes differ, if ``geometry`` belongs to another domain, or if the source and target Quadrature degrees disagree. .. rubric:: Notes Both sides carry ``dx``, so unlike :func:`interpolate` this depends on the geometry. It is a custom operation with a mass-matrix quotient-rule VJP, reverse mode only: one cotangent solve per call, never a dense Jacobian. .. !! processed by numpydoc !!