# Product manifold

Product manifold $\mathcal M = \mathcal{M}_1 × \mathcal{M}_2 × … × \mathcal{M}_n$ of manifolds $\mathcal{M}_1, \mathcal{M}_2, …, \mathcal{M}_n$. Points on the product manifold can be constructed using `ProductRepr`

with canonical projections $Π_i : \mathcal{M} → \mathcal{M}_i$ for $i ∈ 1, 2, …, n$ provided by `submanifold_component`

.

`Manifolds.InverseProductRetraction`

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

Product inverse retraction of `inverse retractions`

. Works on `ProductManifold`

.

`Manifolds.ProductBasisData`

— Type`ProductBasisData`

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

.

`Manifolds.ProductFVectorDistribution`

— Type`ProductFVectorDistribution([type::VectorBundleFibers], [x], distrs...)`

Generates a random vector at point `x`

from vector space (a fiber of a tangent bundle) of type `type`

using the product distribution of given distributions.

Vector space type and `x`

can be automatically inferred from distributions `distrs`

.

`Manifolds.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`

.

`Manifolds.ProductMetric`

— Type`ProductMetric <: AbstractMetric`

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

.

`Manifolds.ProductPointDistribution`

— Type`ProductPointDistribution(M::ProductManifold, distributions)`

Product distribution on manifold `M`

, combined from `distributions`

.

`Manifolds.ProductRetraction`

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

Product retraction of `retractions`

. Works on `ProductManifold`

.

`Manifolds.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(p, M::ProductManifold, i::Union{Integer,Colon,AbstractVector})
p[M::ProductManifold, i]
```

Access the element(s) at index `i`

of a point `p`

on a `ProductManifold`

`M`

by linear indexing. See also Array Indexing in Julia.

`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.

`Base.rand`

— Method`rand(M::ProductManifold; parts_kwargs = map(_ -> (;), M.manifolds))`

Return a random point on `ProductManifold`

`M`

. `parts_kwargs`

is a tuple of keyword arguments for `rand`

on each manifold in `M.manifolds`

.

`Base.setindex!`

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

set the element `[i...]`

of a point `q`

on a `ProductManifold`

by linear indexing to `q`

. See also Array Indexing in Julia.

`LinearAlgebra.cross`

— Method```
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.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.

`Manifolds.flat`

— Method`flat(M::ProductManifold, p, X::FVector{TangentSpaceType})`

use the musical isomorphism to transform the tangent vector `X`

from the tangent space at `p`

on the `ProductManifold`

`M`

to a cotangent vector. This can be done elementwise for every entry of `X`

(with respect to the corresponding entry in `p`

) separately.

`Manifolds.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`

.

`Manifolds.sharp`

— Method`sharp(M::ProductManifold, p, ξ::FVector{CotangentSpaceType})`

Use the musical isomorphism to transform the cotangent vector `ξ`

from the tangent space at `p`

on the `ProductManifold`

`M`

to a tangent vector. This can be done elementwise for every entry of `ξ`

(and `p`

) separately

`Manifolds.submanifold`

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

Extract the `i`

th factor of the product manifold `M`

.

`Manifolds.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.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::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.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.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.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 an `ProductVectorTransport`

`m`

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

has to be implemented on the base manifold.