|
SpECTRE
v2025.08.19
|
A composition of coordinate maps at runtime. More...
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:
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.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).| Frames | The 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. |
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.
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.