Metric manifold
A Riemannian manifold always consists of a topological manifold together with a smoothly varying metric tensor $g$. This metric tensor defines an inner product on each tangent space of the manifold. In Manifolds.jl, a concrete implementation of an AbstractManifold has an implicit metric, which we refer to as the default metric. For example on Euclidean space, this is the usual inner product. For the Sphere, this default metric is the metric induced by the embedding in the ambient Euclidean space, restricted to the tangent spaces of the sphere.
Such a default metric is usually not the only possible metric on a manifold.
The MetricManifold decorator allows to introduce further metrics for a manifold by acting as a wrapper. This allows to define further metrics for an existing manifold, while only having to implement functions that depend on the metric. All functions that are independent of the metric are automatically forwarded to the underlying manifold. When wrapping a manifold M with a MetricManifold together with the default metric(M), this wrapper acts completely transparent and passes all function calls to the underlying manifold M.
Implement Different Metrics on the same Manifold
In order to distinguish different metrics on one manifold, one can introduce two AbstractMetrics and use this type to dispatch on the metric, see SymmetricPositiveDefinite. To avoid overhead, one AbstractMetric can then be marked as being the default, i.e. the one that is used, when no MetricManifold decorator is present. This avoids reimplementation of the first existing metric, access to the metric-dependent functions that were implemented using the undecorated manifold, as well as the transparent fallback of the corresponding MetricManifold with default metric to the undecorated implementations. This does not cause any runtime overhead. Introducing a default AbstractMetric serves a better readability of the code when working with different metrics.
Implementation of Metrics
For the case that a local_metric is implemented as a bilinear form that is positive definite, the following further functions are provided, unless the corresponding AbstractMetric is marked as default – then the fallbacks mentioned in the last section are used for e.g. the exponential map.
Manifolds.flat — Method
flat(N::MetricManifold{M,G}, p, X::TFVector)Compute the musical isomorphism to transform the tangent vector X from the AbstractManifold M equipped with AbstractMetric G to a cotangent by computing
\[X^♭= G_p X,\]
where $G_p$ is the local matrix representation of G, see local_metric
Manifolds.sharp — Method
sharp(N::MetricManifold{M,G}, p, ξ::CoTFVector)Compute the musical isomorphism to transform the cotangent vector ξ from the AbstractManifold M equipped with AbstractMetric G to a tangent by computing
\[ξ^♯ = G_p^{-1} ξ,\]
where $G_p$ is the local matrix representation of G, i.e. one employs inverse_local_metric here to obtain $G_p^{-1}$.
If a metric provides a closed-form inner for arbitrary tangent vectors, the following macros define inner and norm for tangent vectors given as coefficients in a basis.
Manifolds.@tfvector_inner_via_get_vector — Macro
@tfvector_inner_via_get_vector TDefine inner(M::T, p, X::TFVector, Y::TFVector), which converts both coefficient vectors to tangent vectors using get_vector and calls inner on them.
This resolves the ambiguity between inner(::MetricManifold, p, ::TFVector, ::TFVector) and a closed-form inner(::T, p, X, Y) of a metric manifold type T, so it should be used after each such method. T can be a UnionAll written as (T where {...}).
Manifolds.@tfvector_norm_via_get_vector — Macro
@tfvector_norm_via_get_vector TDefine norm(M::T, p, X::TFVector), which converts the coefficient vector to a tangent vector using get_vector and calls norm on it.
This resolves the ambiguity between norm(::MetricManifold, p, ::TFVector) and a closed-form norm(::T, p, X) of a metric manifold type T, so it should be used after each such method. T can be a UnionAll written as (T where {...}).
Metrics, charts and bases of vector spaces
Metric-related functions, similarly to connection-related functions, need to operate in a basis of a vector space, see here.
Metric-related functions can take bases of associated tangent spaces as arguments. For example local_metric can take the basis of the tangent space it is supposed to operate on instead of a custom basis of the space of symmetric bilinear operators.