# Meta Manifolds

While the interface does not provide concrete manifolds itself, it does provide several manifolds that can be build based on a given `AbstractManifold`

instance.

## (Abstract) power manifold

A power manifold is constructed like higher dimensional vector spaces are formed from the real line, just that for every point $p = (p_1,\ldots,p_n) ∈ \mathcal M^n$ on the power manifold $\mathcal M^n$ the entries of $p$ are points $p_1,\ldots,p_n ∈ \mathcal M$ on some manifold $\mathcal M$. Note that $n$ can also be replaced by multiple values, such that $p$ is not a vector but a matrix or a multi-index array of points.

`ManifoldsBase.AbstractPowerManifold`

— Type`AbstractPowerManifold{𝔽,M,TPR} <: AbstractManifold{𝔽}`

An abstract `AbstractManifold`

to represent manifolds that are build as powers of another `AbstractManifold`

`M`

with representation type `TPR`

, a subtype of `AbstractPowerRepresentation`

.

`ManifoldsBase.AbstractPowerRepresentation`

— Type`AbstractPowerRepresentation`

An abstract representation type of points and tangent vectors on a power manifold.

`ManifoldsBase.NestedPowerRepresentation`

— Type`NestedPowerRepresentation`

Representation of points and tangent vectors on a power manifold using arrays of size equal to `TSize`

of a `PowerManifold`

. Each element of such array stores a single point or tangent vector.

For modifying operations, each element of the outer array is modified in-place, differently than in `NestedReplacingPowerRepresentation`

.

`ManifoldsBase.NestedReplacingPowerRepresentation`

— Type`NestedReplacingPowerRepresentation`

Representation of points and tangent vectors on a power manifold using arrays of size equal to `TSize`

of a `PowerManifold`

. Each element of such array stores a single point or tangent vector.

For modifying operations, each element of the outer array is replaced using non-modifying operations, differently than for `NestedReplacingPowerRepresentation`

.

`ManifoldsBase.PowerBasisData`

— Type`PowerBasisData{TB<:AbstractArray}`

Data storage for an array of basis data.

`ManifoldsBase.PowerManifold`

— Type`PowerManifold{𝔽,TM<:AbstractManifold,TSize,TPR<:AbstractPowerRepresentation} <: AbstractPowerManifold{𝔽,TM}`

The power manifold $\mathcal M^{n_1× n_2 × … × n_d}$ with power geometry. `TSize`

defines the number of elements along each axis, either statically using `TypeParameter`

or storing it in a field.

For example, a manifold-valued time series would be represented by a power manifold with $d$ equal to 1 and $n_1$ equal to the number of samples. A manifold-valued image (for example in diffusion tensor imaging) would be represented by a two-axis power manifold ($d=2$) with $n_1$ and $n_2$ equal to width and height of the image.

While the size of the manifold is static, points on the power manifold would not be represented by statically-sized arrays.

**Constructor**

```
PowerManifold(M::PowerManifold, N_1, N_2, ..., N_d; parameter::Symbol=:field)
PowerManifold(M::AbstractManifold, NestedPowerRepresentation(), N_1, N_2, ..., N_d; parameter::Symbol=:field)
M^(N_1, N_2, ..., N_d)
```

Generate the power manifold $M^{N_1 × N_2 × … × N_d}$. By default, a `PowerManifold`

is expanded further, i.e. for `M=PowerManifold(N, 3)`

`PowerManifold(M, 2)`

is equivalent to `PowerManifold(N, 3, 2)`

. Points are then 3×2 matrices of points on `N`

. Providing a `NestedPowerRepresentation`

as the second argument to the constructor can be used to nest manifold, i.e. `PowerManifold(M, NestedPowerRepresentation(), 2)`

represents vectors of length 2 whose elements are vectors of length 3 of points on N in a nested array representation.

The third signature `M^(...)`

is equivalent to the first one, and hence either yields a combination of power manifolds to *one* larger power manifold, or a power manifold with the default representation.

Since there is no default `AbstractPowerRepresentation`

within this interface, the `^`

operator is only available for `PowerManifold`

s and concatenates dimensions.

`parameter`

: whether a type parameter should be used to store `n`

. By default size is stored in a field. Value can either be `:field`

or `:type`

.

`Base.copyto!`

— Method`copyto!(M::PowerManifoldNested, Y, p, X)`

Copy the values elementwise, i.e. call `copyto!(M.manifold, B, a, A)`

for all elements `A`

, `a`

and `B`

of `X`

, `p`

, and `Y`

, respectively.

`Base.copyto!`

— Method`copyto!(M::PowerManifoldNested, q, p)`

Copy the values elementwise, i.e. call `copyto!(M.manifold, b, a)`

for all elements `a`

and `b`

of `p`

and `q`

, respectively.

`Base.exp`

— Method`exp(M::AbstractPowerManifold, p, X)`

Compute the exponential map from `p`

in direction `X`

on the `AbstractPowerManifold`

`M`

, which can be computed using the base manifolds exponential map elementwise.

`Base.fill!`

— Method`fill!(P, p, M::AbstractPowerManifold)`

Fill a point `P`

on the `AbstractPowerManifold`

`M`

, setting every entry to `p`

.

while usually the manifold is the first argument in all functions in `ManifoldsBase.jl`

, we follow the signature of `fill!`

, where the power manifold serves are the size information.

`Base.fill`

— Method`fill(p, M::AbstractPowerManifold)`

Create a point on the `AbstractPowerManifold`

`M`

, where every entry is set to the point `p`

.

while usually the manifold is a first argument in all functions in `ManifoldsBase.jl`

, we follow the signature of `fill`

, where the power manifold serves are the size information.

`Base.getindex`

— Method```
getindex(p, M::AbstractPowerManifold, i::Union{Integer,Colon,AbstractVector}...)
p[M::AbstractPowerManifold, i...]
```

Access the element(s) at index `[i...]`

of a point `p`

on an `AbstractPowerManifold`

`M`

by linear or multidimensional indexing. See also Array Indexing in Julia.

`Base.getindex`

— Method```
getindex(M::TangentSpace{𝔽, AbstractPowerManifold}, i...)
TpM[i...]
```

Access the `i`

th manifold component from an `AbstractPowerManifold`

s' tangent space `TpM`

.

`Base.log`

— Method`log(M::AbstractPowerManifold, p, q)`

Compute the logarithmic map from `p`

to `q`

on the `AbstractPowerManifold`

`M`

, which can be computed using the base manifolds logarithmic map elementwise.

`Base.setindex!`

— Method```
setindex!(q, p, M::AbstractPowerManifold, i::Union{Integer,Colon,AbstractVector}...)
q[M::AbstractPowerManifold, i...] = p
```

Set the element(s) at index `[i...]`

of a point `q`

on an `AbstractPowerManifold`

`M`

by linear or multidimensional indexing to `q`

. See also Array Indexing in Julia.

`Base.view`

— Method`view(p, M::PowerManifoldNested, i::Union{Integer,Colon,AbstractVector}...)`

Get the view of the element(s) at index `[i...]`

of a point `p`

on an `AbstractPowerManifold`

`M`

by linear or multidimensional indexing.

`LinearAlgebra.norm`

— Method`norm(M::AbstractPowerManifold, p, X)`

Compute the norm of `X`

from the tangent space of `p`

on an `AbstractPowerManifold`

`M`

, i.e. from the element wise norms the Frobenius norm is computed.

`ManifoldsBase.Weingarten`

— Method```
Y = Weingarten(M::AbstractPowerManifold, p, X, V)
Weingarten!(M::AbstractPowerManifold, Y, p, X, V)
```

Since the metric decouples, also the computation of the Weingarten map $\mathcal W_p$ can be computed elementwise on the single elements of the `PowerManifold`

`M`

.

`ManifoldsBase._allocate_access_nested`

— Method`_allocate_access_nested(M::PowerManifoldNested, y, i)`

Helper function for `allocate_result`

on `PowerManifoldNested`

. In allocation `y`

can be a number in which case `_access_nested`

wouldn't work.

`ManifoldsBase._parameter_symbol`

— Method`_parameter_symbol(M::PowerManifold)`

Return `:field`

if size of `PowerManifold`

`M`

is stored in a field and `:type`

if in a `TypeParameter`

.

`ManifoldsBase.change_metric`

— Method`change_metric(M::AbstractPowerManifold, ::AbstractMetric, p, X)`

Since the metric on a power manifold decouples, the change of metric can be done elementwise.

`ManifoldsBase.change_representer`

— Method`change_representer(M::AbstractPowerManifold, ::AbstractMetric, p, X)`

Since the metric on a power manifold decouples, the change of a representer can be done elementwise

`ManifoldsBase.check_point`

— Method`check_point(M::AbstractPowerManifold, p; kwargs...)`

Check whether `p`

is a valid point on an `AbstractPowerManifold`

`M`

, i.e. each element of `p`

has to be a valid point on the base manifold. If `p`

is not a point on `M`

a `CompositeManifoldError`

consisting of all error messages of the components, for which the tests fail is returned.

The tolerance for the last test can be set using the `kwargs...`

.

`ManifoldsBase.check_power_size`

— Method```
check_power_size(M, p)
check_power_size(M, p, X)
```

Check whether `p`

`has the right size to represent points on`

M`` generically, i.e. just checking the overall sizes, not the individual ones per manifold.

`ManifoldsBase.check_vector`

— Method`check_vector(M::AbstractPowerManifold, p, X; kwargs... )`

Check whether `X`

is a tangent vector to `p`

an the `AbstractPowerManifold`

`M`

, i.e. atfer `check_point`

`(M, p)`

, and all projections to base manifolds must be respective tangent vectors. If `X`

is not a tangent vector to `p`

on `M`

a `CompositeManifoldError`

consisting of all error messages of the components, for which the tests fail is returned.

The tolerance for the last test can be set using the `kwargs...`

.

`ManifoldsBase.default_inverse_retraction_method`

— Method`default_inverse_retraction_method(M::PowerManifold)`

Use the default inverse retraction method of the internal `M.manifold`

also in defaults of functions defined for the power manifold, meaning that this is used elementwise.

`ManifoldsBase.default_retraction_method`

— Method`default_retraction_method(M::PowerManifold)`

Use the default retraction method of the internal `M.manifold`

also in defaults of functions defined for the power manifold, meaning that this is used elementwise.

`ManifoldsBase.default_vector_transport_method`

— Method`default_vector_transport_method(M::PowerManifold)`

Use the default vector transport method of the internal `M.manifold`

also in defaults of functions defined for the power manifold, meaning that this is used elementwise.

`ManifoldsBase.distance`

— Method`distance(M::AbstractPowerManifold, p, q)`

Compute the distance between `q`

and `p`

on an `AbstractPowerManifold`

, i.e. from the element wise distances the Forbenius norm is computed.

`ManifoldsBase.get_component`

— Method`get_component(M::AbstractPowerManifold, p, idx...)`

Get the component of a point `p`

on an `AbstractPowerManifold`

`M`

at index `idx`

.

`ManifoldsBase.injectivity_radius`

— Method`injectivity_radius(M::AbstractPowerManifold[, p])`

the injectivity radius on an `AbstractPowerManifold`

is for the global case equal to the one of its base manifold. For a given point `p`

it's equal to the minimum of all radii in the array entries.

`ManifoldsBase.inner`

— Method`inner(M::AbstractPowerManifold, p, X, Y)`

Compute the inner product of `X`

and `Y`

from the tangent space at `p`

on an `AbstractPowerManifold`

`M`

, i.e. for each arrays entry the tangent vector entries from `X`

and `Y`

are in the tangent space of the corresponding element from `p`

. The inner product is then the sum of the elementwise inner products.

`ManifoldsBase.inverse_retract`

— Method`inverse_retract(M::AbstractPowerManifold, p, q, m::AbstractInverseRetractionMethod)`

Compute the inverse retraction from `p`

with respect to `q`

on an `AbstractPowerManifold`

`M`

using an `AbstractInverseRetractionMethod`

. Then this method is performed elementwise, so the inverse retraction method has to be one that is available on the base `AbstractManifold`

.

`ManifoldsBase.is_flat`

— Method`is_flat(M::AbstractPowerManifold)`

Return true if `AbstractPowerManifold`

is flat. It is flat if and only if the wrapped manifold is flat.

`ManifoldsBase.manifold_dimension`

— Method`manifold_dimension(M::PowerManifold)`

Returns the manifold-dimension of an `PowerManifold`

`M`

$=\mathcal N = (\mathcal M)^{n_1,…,n_d}$, i.e. with $n=(n_1,…,n_d)$ the array size of the power manifold and $d_{\mathcal M}$ the dimension of the base manifold $\mathcal M$, the manifold is of dimension

\[\dim(\mathcal N) = \dim(\mathcal M)\prod_{i=1}^d n_i = n_1n_2⋅…⋅ n_d \dim(\mathcal M).\]

`ManifoldsBase.power_dimensions`

— Method`power_dimensions(M::PowerManifold)`

return the power of `M`

,

`ManifoldsBase.project`

— Method`project(M::AbstractPowerManifold, p, X)`

Project the point `X`

onto the tangent space at `p`

on the `AbstractPowerManifold`

`M`

by projecting all components.

`ManifoldsBase.project`

— Method`project(M::AbstractPowerManifold, p)`

Project the point `p`

from the embedding onto the `AbstractPowerManifold`

`M`

by projecting all components.

`ManifoldsBase.retract`

— Method`retract(M::AbstractPowerManifold, p, X, method::AbstractRetractionMethod)`

Compute the retraction from `p`

with tangent vector `X`

on an `AbstractPowerManifold`

`M`

using a `AbstractRetractionMethod`

. Then this method is performed elementwise, so the retraction method has to be one that is available on the base `AbstractManifold`

.

`ManifoldsBase.riemann_tensor`

— Method`riemann_tensor(M::AbstractPowerManifold, p, X, Y, Z)`

Compute the Riemann tensor at point from `p`

with tangent vectors `X`

, `Y`

and `Z`

on the `AbstractPowerManifold`

`M`

.

`ManifoldsBase.sectional_curvature`

— Method`sectional_curvature(M::AbstractPowerManifold, p, X, Y)`

Compute the sectional curvature of a power manifold manifold $\mathcal M$ at a point $p \in \mathcal M$ on two linearly independent tangent vectors at $p$. It may be 0 for if projections of `X`

and `Y`

on subspaces corresponding to component manifolds are not linearly independent.

`ManifoldsBase.sectional_curvature_max`

— Method`sectional_curvature_max(M::AbstractPowerManifold)`

Upper bound on sectional curvature of `AbstractPowerManifold`

`M`

. It is the maximum of sectional curvature of the wrapped manifold and 0 in case there are two or more component manifolds, as the sectional curvature corresponding to the plane spanned by vectors `(X_1, 0, ... 0)`

and `(0, X_2, 0, ..., 0)`

is 0.

`ManifoldsBase.sectional_curvature_min`

— Method`sectional_curvature_min(M::AbstractPowerManifold)`

Lower bound on sectional curvature of `AbstractPowerManifold`

`M`

. It is the minimum of sectional curvature of the wrapped manifold and 0 in case there are two or more component manifolds, as the sectional curvature corresponding to the plane spanned by vectors `(X_1, 0, ... 0)`

and `(0, X_2, 0, ..., 0)`

is 0.

`ManifoldsBase.set_component!`

— Method`set_component!(M::AbstractPowerManifold, q, p, idx...)`

Set the component of a point `q`

on an `AbstractPowerManifold`

`M`

at index `idx`

to `p`

, which itself is a point on the `AbstractManifold`

the power manifold is build on.

`ManifoldsBase.vector_transport_to`

— Method`vector_transport_to(M::AbstractPowerManifold, p, X, q, method::AbstractVectorTransportMethod)`

Compute the vector transport the tangent vector `X`

at `p`

to `q`

on the `PowerManifold`

`M`

using an `AbstractVectorTransportMethod`

`m`

. This method is performed elementwise, i.e. the method `m`

has to be implemented on the base manifold.

## Product Manifold

`ManifoldsBase.InverseProductRetraction`

— Type`InverseProductRetraction(retractions::AbstractInverseRetractionMethod...)`

Product inverse retraction of `inverse retractions`

. Works on `ProductManifold`

.

`ManifoldsBase.ProductBasisData`

— Type`ProductBasisData`

A typed tuple to store tuples of data of stored/precomputed bases for a `ProductManifold`

.

`ManifoldsBase.ProductManifold`

— Type`ProductManifold{𝔽,TM<:Tuple} <: AbstractManifold{𝔽}`

Product manifold $M_1 × M_2 × … × M_n$ with product geometry.

**Constructor**

`ProductManifold(M_1, M_2, ..., M_n)`

generates the product manifold $M_1 × M_2 × … × M_n$. Alternatively, the same manifold can be contructed using the `×`

operator: `M_1 × M_2 × M_3`

.

`ManifoldsBase.ProductMetric`

— Type`ProductMetric <: AbstractMetric`

A type to represent the product of metrics for a `ProductManifold`

.

`ManifoldsBase.ProductRetraction`

— Type`ProductRetraction(retractions::AbstractRetractionMethod...)`

Product retraction of `retractions`

. Works on `ProductManifold`

.

`ManifoldsBase.ProductVectorTransport`

— Type`ProductVectorTransport(methods::AbstractVectorTransportMethod...)`

Product vector transport type of `methods`

. Works on `ProductManifold`

.

`Base.exp`

— Method`exp(M::ProductManifold, p, X)`

compute the exponential map from `p`

in the direction of `X`

on the `ProductManifold`

`M`

, which is the elementwise exponential map on the internal manifolds that build `M`

.

`Base.getindex`

— Method```
getindex(M::ProductManifold, i)
M[i]
```

access the `i`

th manifold component from the `ProductManifold`

`M`

.

`Base.getindex`

— Method```
getindex(M::TangentSpace{𝔽,<:ProductManifold}, i::Integer)
TpM[i]
```

Access the `i`

th manifold component from a `ProductManifold`

s' tangent space `TpM`

.

`Base.log`

— Method`log(M::ProductManifold, p, q)`

Compute the logarithmic map from `p`

to `q`

on the `ProductManifold`

`M`

, which can be computed using the logarithmic maps of the manifolds elementwise.

`LinearAlgebra.cross`

— Method```
×(m, n)
cross(m, n)
cross(m1, m2, m3,...)
```

Return the `InverseProductRetraction`

For two or more `AbstractInverseRetractionMethod`

s, where for the case that one of them is a `InverseProductRetraction`

itself, the other is either prepended (if `r`

is a product) or appenden (if `s`

) is. If both `InverseProductRetraction`

s, they are combined into one keeping the order.

`LinearAlgebra.cross`

— Method```
×(M, N)
cross(M, N)
cross(M1, M2, M3,...)
```

Return the `ProductManifold`

For two `AbstractManifold`

s `M`

and `N`

, where for the case that one of them is a `ProductManifold`

itself, the other is either prepended (if `N`

is a product) or appenden (if `M`

) is. If both are product manifold, they are combined into one product manifold, keeping the order.

For the case that more than one is a product manifold of these is build with the same approach as above

`LinearAlgebra.cross`

— Method```
×(m, n)
cross(m, n)
cross(m1, m2, m3,...)
```

Return the `ProductRetraction`

For two or more `AbstractRetractionMethod`

s, where for the case that one of them is a `ProductRetraction`

itself, the other is either prepended (if `m`

is a product) or appenden (if `n`

) is. If both `ProductRetraction`

s, they are combined into one keeping the order.

`LinearAlgebra.cross`

— Method```
×(m, n)
cross(m, n)
cross(m1, m2, m3,...)
```

Return the `ProductVectorTransport`

For two or more `AbstractVectorTransportMethod`

s, where for the case that one of them is a `ProductVectorTransport`

itself, the other is either prepended (if `r`

is a product) or appenden (if `s`

) is. If both `ProductVectorTransport`

s, they are combined into one keeping the order.

`LinearAlgebra.norm`

— Method`norm(M::ProductManifold, p, X)`

Compute the norm of `X`

from the tangent space of `p`

on the `ProductManifold`

, i.e. from the element wise norms the 2-norm is computed.

`ManifoldsBase.Weingarten`

— Method```
Y = Weingarten(M::ProductManifold, p, X, V)
Weingarten!(M::ProductManifold, Y, p, X, V)
```

Since the metric decouples, also the computation of the Weingarten map $\mathcal W_p$ can be computed elementwise on the single elements of the `ProductManifold`

`M`

.

`ManifoldsBase.change_metric`

— Method`change_metric(M::ProductManifold, ::AbstractMetric, p, X)`

Since the metric on a product manifold decouples, the change of metric can be done elementwise.

`ManifoldsBase.change_representer`

— Method`change_representer(M::ProductManifold, ::AbstractMetric, p, X)`

Since the metric on a product manifold decouples, the change of a representer can be done elementwise

`ManifoldsBase.check_point`

— Method`check_point(M::ProductManifold, p; kwargs...)`

Check whether `p`

is a valid point on the `ProductManifold`

`M`

. If `p`

is not a point on `M`

a `CompositeManifoldError`

.consisting of all error messages of the components, for which the tests fail is returned.

The tolerance for the last test can be set using the `kwargs...`

.

`ManifoldsBase.check_size`

— Method`check_size(M::ProductManifold, p; kwargs...)`

Check whether `p`

is of valid size on the `ProductManifold`

`M`

. If `p`

has components of wrong size a `CompositeManifoldError`

.consisting of all error messages of the components, for which the tests fail is returned.

The tolerance for the last test can be set using the `kwargs...`

.

`ManifoldsBase.check_vector`

— Method`check_vector(M::ProductManifold, p, X; kwargs... )`

Check whether `X`

is a tangent vector to `p`

on the `ProductManifold`

`M`

, i.e. all projections to base manifolds must be respective tangent vectors. If `X`

is not a tangent vector to `p`

on `M`

a `CompositeManifoldError`

.consisting of all error messages of the components, for which the tests fail is returned.

The tolerance for the last test can be set using the `kwargs...`

.

`ManifoldsBase.distance`

— Method`distance(M::ProductManifold, p, q)`

Compute the distance between two points `p`

and `q`

on the `ProductManifold`

`M`

, which is the 2-norm of the elementwise distances on the internal manifolds that build `M`

.

`ManifoldsBase.get_component`

— Method`get_component(M::ProductManifold, p, i)`

Get the `i`

th component of a point `p`

on a `ProductManifold`

`M`

.

`ManifoldsBase.injectivity_radius`

— Method```
injectivity_radius(M::ProductManifold)
injectivity_radius(M::ProductManifold, x)
```

Compute the injectivity radius on the `ProductManifold`

, which is the minimum of the factor manifolds.

`ManifoldsBase.inner`

— Method`inner(M::ProductManifold, p, X, Y)`

compute the inner product of two tangent vectors `X`

, `Y`

from the tangent space at `p`

on the `ProductManifold`

`M`

, which is just the sum of the internal manifolds that build `M`

.

`ManifoldsBase.inverse_retract`

— Method`inverse_retract(M::ProductManifold, p, q, m::AbstractInverseRetractionMethod)`

Compute the inverse retraction from `p`

with respect to `q`

on the `ProductManifold`

`M`

using an `AbstractInverseRetractionMethod`

, which is used on each manifold of the product.

`ManifoldsBase.inverse_retract`

— Method`inverse_retract(M::ProductManifold, p, q, m::InverseProductRetraction)`

Compute the inverse retraction from `p`

with respect to `q`

on the `ProductManifold`

`M`

using an `InverseProductRetraction`

, which by default encapsulates a inverse retraction for each manifold of the product. Then this method is performed elementwise, so the encapsulated inverse retraction methods have to be available per factor.

`ManifoldsBase.is_flat`

— Method`is_flat(::ProductManifold)`

Return true if and only if all component manifolds of `ProductManifold`

`M`

are flat.

`ManifoldsBase.manifold_dimension`

— Method`manifold_dimension(M::ProductManifold)`

Return the manifold dimension of the `ProductManifold`

, which is the sum of the manifold dimensions the product is made of.

`ManifoldsBase.number_of_components`

— Method`number_of_components(M::ProductManifold{<:NTuple{N,Any}}) where {N}`

Calculate the number of manifolds multiplied in the given `ProductManifold`

`M`

.

`ManifoldsBase.retract`

— Method`retract(M::ProductManifold, p, X, m::AbstractRetractionMethod)`

Compute the retraction from `p`

with tangent vector `X`

on the `ProductManifold`

`M`

using the `AbstractRetractionMethod`

`m`

on every manifold.

`ManifoldsBase.retract`

— Method`retract(M::ProductManifold, p, X, m::ProductRetraction)`

Compute the retraction from `p`

with tangent vector `X`

on the `ProductManifold`

`M`

using an `ProductRetraction`

, which by default encapsulates retractions of the base manifolds. Then this method is performed elementwise, so the encapsulated retractions method has to be one that is available on the manifolds.

`ManifoldsBase.riemann_tensor`

— Method`riemann_tensor(M::ProductManifold, p, X, Y, Z)`

Compute the Riemann tensor at point from `p`

with tangent vectors `X`

, `Y`

and `Z`

on the `ProductManifold`

`M`

.

`ManifoldsBase.sectional_curvature`

— Method`sectional_curvature(M::ProductManifold, p, X, Y)`

Compute the sectional curvature of a manifold $\mathcal M$ at a point $p \in \mathcal M$ on two linearly independent tangent vectors at $p$. It may be 0 for a product of non-flat manifolds if projections of `X`

and `Y`

on subspaces corresponding to component manifolds are not linearly independent.

`ManifoldsBase.sectional_curvature_max`

— Method`sectional_curvature_max(M::ProductManifold)`

Upper bound on sectional curvature of `ProductManifold`

`M`

. It is the maximum of sectional curvatures of component manifolds and 0 in case there are two or more component manifolds, as the sectional curvature corresponding to the plane spanned by vectors `(X_1, 0)`

and `(0, X_2)`

is 0.

`ManifoldsBase.sectional_curvature_min`

— Method`sectional_curvature_min(M::ProductManifold)`

Lower bound on sectional curvature of `ProductManifold`

`M`

. It is the minimum of sectional curvatures of component manifolds and 0 in case there are two or more component manifolds, as the sectional curvature corresponding to the plane spanned by vectors `(X_1, 0)`

and `(0, X_2)`

is 0.

`ManifoldsBase.select_from_tuple`

— Method`select_from_tuple(t::NTuple{N, Any}, positions::Val{P})`

Selects elements of tuple `t`

at positions specified by the second argument. For example `select_from_tuple(("a", "b", "c"), Val((3, 1, 1)))`

returns `("c", "a", "a")`

.

`ManifoldsBase.set_component!`

— Method`set_component!(M::ProductManifold, q, p, i)`

Set the `i`

th component of a point `q`

on a `ProductManifold`

`M`

to `p`

, where `p`

is a point on the `AbstractManifold`

this factor of the product manifold consists of.

`ManifoldsBase.submanifold`

— Method`submanifold(M::ProductManifold, i::Integer)`

Extract the `i`

th factor of the product manifold `M`

.

`ManifoldsBase.submanifold`

— Method```
submanifold(M::ProductManifold, i::Val)
submanifold(M::ProductManifold, i::AbstractVector)
```

Extract the factor of the product manifold `M`

indicated by indices in `i`

. For example, for `i`

equal to `Val((1, 3))`

the product manifold constructed from the first and the third factor is returned.

The version with `AbstractVector`

is not type-stable, for better preformance use `Val`

.

`ManifoldsBase.submanifold_component`

— Method```
submanifold_component(M::AbstractManifold, p, i::Integer)
submanifold_component(M::AbstractManifold, p, ::Val{i}) where {i}
submanifold_component(p, i::Integer)
submanifold_component(p, ::Val{i}) where {i}
```

Project the product array `p`

on `M`

to its `i`

th component. A new array is returned.

`ManifoldsBase.submanifold_components`

— Method```
submanifold_components(M::AbstractManifold, p)
submanifold_components(p)
```

Get the projected components of `p`

on the submanifolds of `M`

. The components are returned in a Tuple.

`ManifoldsBase.vector_transport_to`

— Method`vector_transport_to(M::ProductManifold, p, X, q, m::AbstractVectorTransportMethod)`

Compute the vector transport the tangent vector `X`

at `p`

to `q`

on the `ProductManifold`

`M`

using an `AbstractVectorTransportMethod`

`m`

on each manifold.

`ManifoldsBase.vector_transport_to`

— Method`vector_transport_to(M::ProductManifold, p, X, q, m::ProductVectorTransport)`

Compute the vector transport the tangent vector `X`

at `p`

to `q`

on the `ProductManifold`

`M`

using a `ProductVectorTransport`

`m`

.

`ManifoldsBase.ziptuples`

— Method`ziptuples(a, b[, c[, d[, e]]])`

Zips tuples `a`

, `b`

, and remaining in a fast, type-stable way. If they have different lengths, the result is trimmed to the length of the shorter tuple.

## Fiber

`ManifoldsBase.Fiber`

— Type`Fiber{𝔽,TFiber<:FiberType,TM<:AbstractManifold{𝔽},TX} <: AbstractManifold{𝔽}`

A fiber of a fiber bundle at a point `p`

on the manifold.

This fiber itself is also a `manifold`

. For vector fibers it's by default flat and hence isometric to the `Euclidean`

manifold.

**Fields**

`manifold`

– base space of the fiber bundle`point`

– a point $p$ from the base space; the fiber corresponds to the preimage by bundle projection $\pi^{-1}(\{p\})$.

**Constructor**

`Fiber(M::AbstractManifold, p, fiber_type::FiberType)`

A fiber of type `fiber_type`

at point `p`

from the manifold `manifold`

.

`ManifoldsBase.FiberType`

— Type`abstract type FiberType end`

An abstract type for fiber types that can be used within `Fiber`

.

`ManifoldsBase.VectorSpaceFiber`

— Type```
VectorSpaceFiber{𝔽,M,TSpaceType} = Fiber{𝔽,TSpaceType,M}
where {𝔽,M<:AbstractManifold{𝔽},TSpaceType<:VectorSpaceType}
```

Alias for a `Fiber`

when the fiber is a vector space.

## Tangent Space

`ManifoldsBase.CotangentSpace`

— Type`CotangentSpace{𝔽,M} = Fiber{𝔽,CotangentSpaceType,M} where {𝔽,M<:AbstractManifold{𝔽}}`

A manifold for the Cotangent space $T^*_p\mathcal M$ at a point $p\in\mathcal M$. This is modelled as an alias for `VectorSpaceFiber`

corresponding to `CotangentSpaceType`

.

**Constructor**

`CotangentSpace(M::AbstractManifold, p)`

Return the manifold (vector space) representing the cotangent space $T^*_p\mathcal M$ at point `p`

, $p\in\mathcal M$.

`ManifoldsBase.TangentSpace`

— Type`TangentSpace{𝔽,M} = Fiber{𝔽,TangentSpaceType,M} where {𝔽,M<:AbstractManifold{𝔽}}`

A manifold for the tangent space $T_p\mathcal M$ at a point $p\in\mathcal M$. This is modelled as an alias for `VectorSpaceFiber`

corresponding to `TangentSpaceType`

.

**Constructor**

`TangentSpace(M::AbstractManifold, p)`

Return the manifold (vector space) representing the tangent space $T_p\mathcal M$ at point `p`

, $p\in\mathcal M$.

`Base.exp`

— Method`exp(TpM::TangentSpace, X, V)`

Exponential map of tangent vectors `X`

from `TpM`

and a direction `V`

, which is also from the `TangentSpace`

`TpM`

since we identify the tangent space of `TpM`

with `TpM`

. The exponential map then simplifies to the sum `X+V`

.

`Base.log`

— Method`log(TpM::TangentSpace, X, Y)`

Logarithmic map on the `TangentSpace`

`TpM`

, calculated as the difference of tangent vectors `q`

and `p`

from `TpM`

.

`ManifoldsBase.Weingarten`

— Method```
Y = Weingarten(TpM::TangentSpace, X, V, A)
Weingarten!(TpM::TangentSpace, Y, p, X, V)
```

Compute the Weingarten map $\mathcal W_X$ at `X`

on the `TangentSpace`

`TpM`

with respect to the tangent vector $V \in T_p\mathcal M$ and the normal vector $A \in N_p\mathcal M$.

Since this a flat space by itself, the result is always the zero tangent vector.

`ManifoldsBase.base_point`

— Method`base_point(TpM::TangentSpace)`

Return the base point of the `TangentSpace`

.

`ManifoldsBase.distance`

— Method`distance(M::TangentSpace, X, Y)`

Distance between vectors `X`

and `Y`

from the `TangentSpace`

`TpM`

. It is calculated as the `norm`

(induced by the metric on `TpM`

) of their difference.

`ManifoldsBase.injectivity_radius`

— Method`injectivity_radius(TpM::TangentSpace)`

Return the injectivity radius on the `TangentSpace`

`TpM`

, which is $∞$.

`ManifoldsBase.inner`

— Method`inner(M::TangentSpace, X, V, W)`

For any $X ∈ T_p\mathcal M$ we identify the tangent space $T_X(T_p\mathcal M)$ with $T_p\mathcal M$ again. Hence an inner product of $V,W$ is just the inner product of the tangent space itself. $⟨V,W⟩_X = ⟨V,W⟩_p$.

`ManifoldsBase.is_flat`

— Method`is_flat(::TangentSpace)`

The `TangentSpace`

is a flat manifold, so this returns `true`

.

`ManifoldsBase.manifold_dimension`

— Method`manifold_dimension(TpM::TangentSpace)`

Return the dimension of the `TangentSpace`

$T_p\mathcal M$ at $p∈\mathcal M$, which is the same as the dimension of the manifold $\mathcal M$.

`ManifoldsBase.parallel_transport_to`

— Method`parallel_transport_to(::TangentSpace, X, V, Y)`

Transport the tangent vector $Z ∈ T_X(T_p\mathcal M)$ from `X`

to `Y`

. Since we identify $T_X(T_p\mathcal M) = T_p\mathcal M$ and the tangent space is a vector space, parallel transport simplifies to the identity, so this function yields $V$ as a result.

`ManifoldsBase.project`

— Method`project(TpM::TangentSpace, X, V)`

Project the vector `V`

from the embedding of the tangent space `TpM`

(identified with $T_X(T_p\mathcal M)$), that is project the vector `V`

onto the tangent space at `TpM.point`

.

`ManifoldsBase.project`

— Method`project(TpM::TangentSpace, X)`

Project the point `X`

from embedding of the `TangentSpace`

`TpM`

onto `TpM`

.

`ManifoldsBase.zero_vector`

— Method`zero_vector(TpM::TangentSpace, X)`

Zero tangent vector at point `X`

from the `TangentSpace`

`TpM`

, that is the zero tangent vector at point `TpM.point`

, since we identify the tangent space $T_X(T_p\mathcal M)$ with $T_p\mathcal M$.

`ManifoldsBase.zero_vector`

— Method`zero_vector(TpM::TangentSpace)`

Zero tangent vector in the `TangentSpace`

`TpM`

, that is the zero tangent vector at point `TpM.point`

.