SpECTRE  v2025.08.19
domain::CoordinateMaps::Composition< Frames, Dim, Is > Struct Template Reference

A composition of coordinate maps at runtime. More...

Detailed Description

template<typename Frames, size_t Dim, typename Is = std::make_index_sequence<tmpl::size<Frames>::value - 1>>
struct domain::CoordinateMaps::Composition< Frames, Dim, Is >

A composition of coordinate maps at runtime.

Composes a sequence of domain::CoordinateMapBase that step through the Frames. The result is another domain::CoordinateMapBase. This is different to domain::CoordinateMap, which does the composition at compile time. The use cases are different:

  • Use domain::CoordinateMap to compose maps at compile time to go from one (named) frame to another using any number of coordinate transformation. The coordinate transformations are concatenated to effectively form a single map, and intermediate frames have no meaning. This has the performance benefit that looking up pointers and calling into virtual member functions of intermediate maps is avoided, and it has the semantic benefit that intermediate frames without meaning are not named or even accessible. Example: A static BlockLogical -> Grid map that deforms the logical cube to a wedge, applies a radial redistribution of grid points, and translates + rotates the wedge.
  • Use domain::CoordinateMaps::Composition (this class) to compose maps at runtime to step through a sequence of (named) frames. Example: A time-dependent ElementLogical -> BlockLogical -> Grid -> Inertial map that applies an affine transformation between the ElementLogical and BlockLogical frames (see domain::element_to_block_logical_map), then deforms the logical cube to a wedge using the map described above (Grid frame), and then rotates the grid with a time-dependent rotation map (Inertial frame).
Warning
Think about performance implications before using this Composition class. In an evolution it's usually advantageous to keep at least some of the maps separate, e.g. to avoid reevaluating the static maps in every time step. You can also access individual components of the composition in this class.
Template Parameters
FramesThe list of frames in the composition, as a tmpl::list<>. The first entry in the list is the source frame, and the last entry is the target frame of the composition. Maps in the composition step through the Frames. For example, if Frames = tmpl::list<Frame::ElementLogical, Frame::BlockLogical, Frame::Inertial>, then the composition has two maps: ElementLogical -> BlockLogical and BlockLogical -> Inertial.

Note on inverse Hessian computation

Below we work out the algebra for computing the inverse Hessian used in this struct (if SPECTRE_AUTODIFF=ON). Suppose we have a composition of maps \( \xi^i \longrightarrow \cdots \longrightarrow x^i \longrightarrow y^i \), where \( \xi^i \) are the source coordinates, \( x^i \) are some intermediate coordinates, and \( y^i \) are the final target coordinates, We compute inverse Hessian by first propagating autodiff dual types through the composed call_impl function to automatically get the Hessian \( \frac{\partial^2 y^i}{\partial\xi^j \partial\xi^k} \) Then the inverse Hessian is computed by the identity

\[ \frac{\partial^2\xi^i}{\partial y^m \partial y^n} = -\frac{\partial\xi^i}{\partial y^j}\frac{\partial\xi^k}{\partial y^m} \frac{\partial\xi^l}{\partial y^n}\frac{\partial^2 y^j}{\partial\xi^k \partial\xi^l}, \]

where the inverse Jacobian is passed in as a function argument.

See Test_Composition.cpp for a different implementation. The current implementation is chosen in production as it is faster when we have the inverse Jacobian already, and in most cases we do.

Note on auto differentiation

We use forward mode autodiff here as it is simpler to implement and has better optimization than the reverse mode. Reverse mode in the Autodiff library has higher cost per propagation and does not support taping. Also see this github issue.


The documentation for this struct was generated from the following file: