From c4f5df3906910ae523e79b3c32882e87f6fcebac Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Wed, 26 Jul 2023 16:00:15 +0200 Subject: [PATCH] fiber bundles pt. 1 --- src/Manifolds.jl | 2 + src/manifolds/Fiber.jl | 398 ++++++++++++++ src/manifolds/FiberBundle.jl | 433 +++++++++++++++ src/manifolds/PowerManifold.jl | 4 - src/manifolds/ProductManifold.jl | 2 +- src/manifolds/VectorBundle.jl | 865 +++--------------------------- test/manifolds/fiber.jl | 44 ++ test/manifolds/vector_bundle.jl | 45 +- test/runtests.jl | 1 + tutorials/rigid-body-dynamics.qmd | 9 +- 10 files changed, 968 insertions(+), 835 deletions(-) create mode 100644 src/manifolds/Fiber.jl create mode 100644 src/manifolds/FiberBundle.jl create mode 100644 test/manifolds/fiber.jl diff --git a/src/Manifolds.jl b/src/Manifolds.jl index 5c61f2a0d2..942ae06c94 100644 --- a/src/Manifolds.jl +++ b/src/Manifolds.jl @@ -334,6 +334,8 @@ include("manifold_fallbacks.jl") include("manifolds/ConnectionManifold.jl") include("manifolds/MetricManifold.jl") include("manifolds/QuotientManifold.jl") +include("manifolds/Fiber.jl") +include("manifolds/FiberBundle.jl") include("manifolds/VectorBundle.jl") include("groups/group.jl") diff --git a/src/manifolds/Fiber.jl b/src/manifolds/Fiber.jl new file mode 100644 index 0000000000..6f225ebb3f --- /dev/null +++ b/src/manifolds/Fiber.jl @@ -0,0 +1,398 @@ + +""" + TensorProductType(spaces::VectorSpaceType...) + +Vector space type corresponding to the tensor product of given vector space +types. +""" +struct TensorProductType{TS<:Tuple} <: VectorSpaceType + spaces::TS +end + +TensorProductType(spaces::VectorSpaceType...) = TensorProductType{typeof(spaces)}(spaces) + +""" + abstract type FiberType end + +An abstract type for fiber types. +""" +abstract type FiberType end + +struct VectorSpaceFiberType{TVS<:VectorSpaceType} <: FiberType + fiber::TVS +end + +function Base.show(io::IO, vsf::VectorSpaceFiberType) + return print(io, "VectorSpaceFiberType($(vsf.fiber))") +end + +const TangentFiberType = VectorSpaceFiberType{TangentSpaceType} + +const CotangentFiberType = VectorSpaceFiberType{CotangentSpaceType} + +const TangentFiber = VectorSpaceFiberType{TangentSpaceType}(TangentSpace) +const CotangentFiber = VectorSpaceFiberType{CotangentSpaceType}(CotangentSpace) + +""" + BundleFibers(fiber::FiberType, M::AbstractManifold) + +Type representing a family of vector spaces (fibers) of a vector bundle over `M` +with vector spaces of type `fiber`. In contrast with `FiberBundle`, operations +on `BundleFibers` expect point-like and vector-like parts to be +passed separately instead of being bundled together. It can be thought of +as a representation of vector spaces from a vector bundle but without +storing the point at which a vector space is attached (which is specified +separately in various functions). +""" +struct BundleFibers{TF<:FiberType,TM<:AbstractManifold} + fiber::TF + manifold::TM +end + +""" + VectorBundleFibers{TVS,TM} + +Alias for [`BundleFibers`](@ref) when the fiber is a vector space. +""" +const VectorBundleFibers{TVS,TM} = BundleFibers{ + VectorSpaceFiberType{TVS}, + TM, +} where {TVS<:VectorSpaceType,TM<:AbstractManifold} + +function VectorBundleFibers(fiber::VectorSpaceType, M::AbstractManifold) + return BundleFibers(VectorSpaceFiberType(fiber), M) +end + +const TangentBundleFibers{M} = BundleFibers{TangentFiberType,M} where {M<:AbstractManifold} + +TangentBundleFibers(M::AbstractManifold) = BundleFibers(TangentFiber, M) + +const CotangentBundleFibers{M} = + BundleFibers{CotangentFiberType,M} where {M<:AbstractManifold} + +CotangentBundleFibers(M::AbstractManifold) = BundleFibers(CotangentFiber, M) + +""" + FiberAtPoint{ + 𝔽, + TFiber<:BundleFibers{<:FiberType,<:AbstractManifold{𝔽}}, + TX, + } <: AbstractManifold{𝔽} + +A fiber of a [`FiberBundle`](@ref) at a point `p` on the manifold. +This is modelled using [`BundleFibers`](@ref) with only a fiber part +and fixing the point-like part to be just `p`. + +This fiber itself is also a `manifold`. For vector fibers it's by default flat and hence +isometric to the [`Euclidean`](@ref) manifold. + +# Constructor + + FiberAtPoint(fiber::BundleFibers, p) + +A fiber of type `fiber` at point `p` from the manifold `fiber.manifold`. +""" +struct FiberAtPoint{𝔽,TFiber<:BundleFibers{<:FiberType,<:AbstractManifold{𝔽}},TX} <: + AbstractManifold{𝔽} + fiber::TFiber + point::TX +end + +""" + VectorSpaceAtPoint{𝔽,TFiber} + +Alias for [`FiberAtPoint`](@ref) when the fiber is a vector space. +""" +const VectorSpaceAtPoint{𝔽,TFiber} = FiberAtPoint{ + 𝔽, + TFiber, +} where {TFiber<:VectorBundleFibers{<:FiberType,<:AbstractManifold{𝔽}}} + +function VectorSpaceAtPoint(M::AbstractManifold, fiber::VectorSpaceFiberType, p) + return FiberAtPoint(BundleFibers(fiber, M), p) +end +VectorSpaceAtPoint(fiber::BundleFibers{<:VectorSpaceFiberType}, p) = FiberAtPoint(fiber, p) + +""" + TangentSpaceAtPoint{𝔽,M} + +Alias for [`VectorSpaceAtPoint`](@ref) for the tangent space at a point. +""" +const TangentSpaceAtPoint{𝔽,M} = + FiberAtPoint{𝔽,TangentBundleFibers{M}} where {𝔽,M<:AbstractManifold{𝔽}} + +""" + TangentSpaceAtPoint(M::AbstractManifold, p) + +Return an object of type [`VectorSpaceAtPoint`](@ref) representing tangent +space at `p` on the [`AbstractManifold`](https://juliamanifolds.github.io/ManifoldsBase.jl/stable/types.html#ManifoldsBase.AbstractManifold) `M`. +""" +TangentSpaceAtPoint(M::AbstractManifold, p) = VectorSpaceAtPoint(M, TangentFiber, p) + +""" + TangentSpace(M::AbstractManifold, p) + +Return a [`TangentSpaceAtPoint`](@ref Manifolds.TangentSpaceAtPoint) representing tangent +space at `p` on the [`AbstractManifold`](https://juliamanifolds.github.io/ManifoldsBase.jl/stable/types.html#ManifoldsBase.AbstractManifold) `M`. +""" +TangentSpace(M::AbstractManifold, p) = TangentSpaceAtPoint(M, p) + +const CotangentSpaceAtPoint{𝔽,M} = + VectorSpaceAtPoint{CotangentBundleFibers{M}} where {𝔽,M<:AbstractManifold{𝔽}} + +""" + CotangentSpaceAtPoint(M::AbstractManifold, p) + +Return an object of type [`VectorSpaceAtPoint`](@ref) representing cotangent +space at `p`. +""" +function CotangentSpaceAtPoint(M::AbstractManifold, p) + return VectorSpaceAtPoint(M, CotangentFiber, p) +end + +""" + allocate_result(B::BundleFibers, f, x...) + +Allocates an array for the result of function `f` that is +an element of the vector space of type `B.fiber` on manifold `B.manifold` +and arguments `x...` for implementing the non-modifying operation +using the modifying operation. +""" +@inline function allocate_result(B::BundleFibers, f::TF, x...) where {TF} + if length(x) == 0 + # TODO: this may be incorrect when point and tangent vector representation are + # different for the manifold but there is no easy and generic way around that + return allocate_result(B.manifold, f) + else + T = allocate_result_type(B, f, x) + return allocate(x[1], T) + end +end + +""" + allocate_result_type(B::BundleFibers, f, args::NTuple{N,Any}) where N + +Return type of element of the array that will represent the result of +function `f` for representing an operation with result in the vector space `fiber` +for manifold `M` on given arguments (passed at a tuple). +""" +@inline function allocate_result_type( + ::BundleFibers, + f::TF, + args::NTuple{N,Any}, +) where {TF,N} + return typeof(mapreduce(eti -> one(number_eltype(eti)), +, args)) +end + +base_manifold(B::BundleFibers) = base_manifold(B.manifold) +base_manifold(B::FiberAtPoint) = base_manifold(B.fiber) + +""" + distance(M::TangentSpaceAtPoint, p, q) + +Distance between vectors `p` and `q` from the vector space `M`. It is calculated as the norm +of their difference. +""" +function distance(M::TangentSpaceAtPoint, p, q) + return norm(M.fiber.manifold, M.point, q - p) +end + +function embed!(M::TangentSpaceAtPoint, q, p) + return embed!(M.fiber.manifold, q, M.point, p) +end +function embed!(M::TangentSpaceAtPoint, Y, p, X) + return embed!(M.fiber.manifold, Y, M.point, X) +end + +@doc raw""" + exp(M::TangentSpaceAtPoint, p, X) + +Exponential map of tangent vectors `X` and `p` from the tangent space `M`. It is +calculated as their sum. +""" +exp(::TangentSpaceAtPoint, ::Any, ::Any) + +function exp!(M::TangentSpaceAtPoint, q, p, X) + copyto!(M.fiber.manifold, q, p + X) + return q +end + +function fiber_dimension(B::BundleFibers) + return fiber_dimension(B.manifold, B.fiber) +end +fiber_dimension(M::TangentBundleFibers) = manifold_dimension(M.manifold) +fiber_dimension(M::CotangentBundleFibers) = manifold_dimension(M.manifold) +fiber_dimension(M::AbstractManifold, ::CotangentSpaceType) = manifold_dimension(M) +fiber_dimension(M::AbstractManifold, ::TangentSpaceType) = manifold_dimension(M) + +function get_basis(M::TangentSpaceAtPoint, p, B::CachedBasis) + return invoke( + get_basis, + Tuple{AbstractManifold,Any,CachedBasis}, + M.fiber.manifold, + M.point, + B, + ) +end +function get_basis(M::TangentSpaceAtPoint, p, B::AbstractBasis{<:Any,TangentSpaceType}) + return get_basis(M.fiber.manifold, M.point, B) +end + +function get_coordinates(M::TangentSpaceAtPoint, p, X, B::AbstractBasis) + return get_coordinates(M.fiber.manifold, M.point, X, B) +end + +function get_coordinates!(M::TangentSpaceAtPoint, Y, p, X, B::AbstractBasis) + return get_coordinates!(M.fiber.manifold, Y, M.point, X, B) +end + +function get_vector(M::TangentSpaceAtPoint, p, X, B::AbstractBasis) + return get_vector(M.fiber.manifold, M.point, X, B) +end + +function get_vector!(M::TangentSpaceAtPoint, Y, p, X, B::AbstractBasis) + return get_vector!(M.fiber.manifold, Y, M.point, X, B) +end + +function get_vectors(M::TangentSpaceAtPoint, p, B::CachedBasis) + return get_vectors(M.fiber.manifold, M.point, B) +end + +@doc raw""" + injectivity_radius(M::TangentSpaceAtPoint) + +Return the injectivity radius on the [`TangentSpaceAtPoint`](@ref Manifolds.TangentSpaceAtPoint) `M`, which is $∞$. +""" +injectivity_radius(::TangentSpaceAtPoint) = Inf + +""" + inner(M::TangentSpaceAtPoint, p, X, Y) + +Inner product of vectors `X` and `Y` from the tangent space at `M`. +""" +function inner(M::TangentSpaceAtPoint, p, X, Y) + return inner(M.fiber.manifold, M.point, X, Y) +end + +""" + is_flat(::TangentSpaceAtPoint) + +Return true. [`TangentSpaceAtPoint`](@ref Manifolds.TangentSpaceAtPoint) is a flat manifold. +""" +is_flat(::TangentSpaceAtPoint) = true + +function _isapprox(M::TangentSpaceAtPoint, X, Y; kwargs...) + return isapprox(M.fiber.manifold, M.point, X, Y; kwargs...) +end + +""" + log(M::TangentSpaceAtPoint, p, q) + +Logarithmic map on the tangent space manifold `M`, calculated as the difference of tangent +vectors `q` and `p` from `M`. +""" +log(::TangentSpaceAtPoint, ::Any...) +function log!(::TangentSpaceAtPoint, X, p, q) + copyto!(X, q - p) + return X +end + +function manifold_dimension(M::FiberAtPoint) + return fiber_dimension(M.fiber) +end + +LinearAlgebra.norm(M::VectorSpaceAtPoint, p, X) = norm(M.fiber.manifold, M.point, X) + +function parallel_transport_to!(M::TangentSpaceAtPoint, Y, p, X, q) + return copyto!(M.fiber.manifold, Y, p, X) +end + +@doc raw""" + project(M::TangentSpaceAtPoint, p) + +Project the point `p` from the tangent space `M`, that is project the vector `p` +tangent at `M.point`. +""" +project(::TangentSpaceAtPoint, ::Any) + +function project!(M::TangentSpaceAtPoint, q, p) + return project!(M.fiber.manifold, q, M.point, p) +end + +@doc raw""" + project(M::TangentSpaceAtPoint, p, X) + +Project the vector `X` from the tangent space `M`, that is project the vector `X` +tangent at `M.point`. +""" +project(::TangentSpaceAtPoint, ::Any, ::Any) + +function project!(M::TangentSpaceAtPoint, Y, p, X) + return project!(M.fiber.manifold, Y, M.point, X) +end + +function Random.rand!(rng::AbstractRNG, M::TangentSpaceAtPoint, X; vector_at=nothing) + rand!(rng, M.fiber.manifold, X; vector_at=M.point) + return X +end + +function representation_size(B::TangentSpaceAtPoint) + return representation_size(B.fiber.manifold) +end + +function Base.show(io::IO, fiber::BundleFibers) + return print(io, "BundleFibers($(fiber.fiber), $(fiber.manifold))") +end +function Base.show(io::IO, ::MIME"text/plain", vs::FiberAtPoint) + summary(io, vs) + println(io, "\nFiber:") + pre = " " + sf = sprint(show, "text/plain", vs.fiber; context=io, sizehint=0) + sf = replace(sf, '\n' => "\n$(pre)") + println(io, pre, sf) + println(io, "Base point:") + sp = sprint(show, "text/plain", vs.point; context=io, sizehint=0) + sp = replace(sp, '\n' => "\n$(pre)") + return print(io, pre, sp) +end +function Base.show(io::IO, ::MIME"text/plain", TpM::TangentSpaceAtPoint) + println(io, "Tangent space to the manifold $(base_manifold(TpM)) at point:") + pre = " " + sp = sprint(show, "text/plain", TpM.point; context=io, sizehint=0) + sp = replace(sp, '\n' => "\n$(pre)") + return print(io, pre, sp) +end + +function vector_transport_to!( + M::TangentSpaceAtPoint, + Y, + p, + X, + q, + m::AbstractVectorTransportMethod, +) + return copyto!(M.fiber.manifold, Y, p, X) +end + +""" + zero_vector(B::BundleFibers, p) + +Compute the zero vector from the vector space of type `B.fiber` at point `p` +from manifold `B.manifold`. +""" +function zero_vector(B::BundleFibers, p) + X = allocate_result(B, zero_vector, p) + return zero_vector!(B, X, p) +end + +@doc raw""" + zero_vector(M::TangentSpaceAtPoint, p) + +Zero tangent vector at point `p` from the tangent space `M`, that is the zero tangent vector +at point `M.point`. +""" +zero_vector(::TangentSpaceAtPoint, ::Any...) + +function zero_vector!(M::TangentSpaceAtPoint, X, p) + return zero_vector!(M.fiber.manifold, X, M.point) +end diff --git a/src/manifolds/FiberBundle.jl b/src/manifolds/FiberBundle.jl new file mode 100644 index 0000000000..8aeaadaebe --- /dev/null +++ b/src/manifolds/FiberBundle.jl @@ -0,0 +1,433 @@ + +@doc raw""" + FiberBundleProductVectorTransport{ + TMP<:AbstractVectorTransportMethod, + TMV<:AbstractVectorTransportMethod, + } <: AbstractVectorTransportMethod + +Vector transport type on [`FiberBundle`](@ref). `method_point` is used for vector transport +of the point part and `method_fiber` is used for transport of the fiber part. + +The vector transport is derived as a product manifold-style vector transport. The considered +product manifold is the product between the manifold $\mathcal M$ and the topological vector +space isometric to the fiber. + +# Constructor + + FiberBundleProductVectorTransport( + method_point::AbstractVectorTransportMethod, + method_fiber::AbstractVectorTransportMethod, + ) + FiberBundleProductVectorTransport() + +By default both methods are set to `ParallelTransport`. +""" +struct FiberBundleProductVectorTransport{ + TMP<:AbstractVectorTransportMethod, + TMV<:AbstractVectorTransportMethod, +} <: AbstractVectorTransportMethod + method_point::TMP + method_fiber::TMV +end + +function FiberBundleProductVectorTransport() + return FiberBundleProductVectorTransport(ParallelTransport(), ParallelTransport()) +end +function FiberBundleProductVectorTransport(M::AbstractManifold) + m = default_vector_transport_method(M) + return FiberBundleProductVectorTransport(m, m) +end + +""" + FiberBundle{𝔽,TVS<:FiberType,TM<:AbstractManifold{𝔽},TVT<:FiberBundleProductVectorTransport} <: AbstractManifold{𝔽} + +Vector bundle on a [`AbstractManifold`](https://juliamanifolds.github.io/ManifoldsBase.jl/stable/types.html#ManifoldsBase.AbstractManifold) `M` of type [`VectorSpaceType`](https://juliamanifolds.github.io/ManifoldsBase.jl/stable/bases.html#ManifoldsBase.VectorSpaceType). + +# Constructor + + FiberBundle(M::AbstractManifold, type::FiberType) +""" +struct FiberBundle{ + 𝔽, + TF<:FiberType, + TM<:AbstractManifold{𝔽}, + TVT<:FiberBundleProductVectorTransport, +} <: AbstractManifold{𝔽} + type::TF + manifold::TM + fiber::BundleFibers{TF,TM} + vector_transport::TVT +end + +vector_bundle_transport(::FiberType, M::AbstractManifold) = ParallelTransport() + +function FiberBundle( + fiber::TVS, + M::TM, + vtm::FiberBundleProductVectorTransport, +) where {TVS<:FiberType,TM<:AbstractManifold{𝔽}} where {𝔽} + return FiberBundle{𝔽,TVS,TM,typeof(vtm)}(fiber, M, BundleFibers(fiber, M), vtm) +end +function FiberBundle(fiber::FiberType, M::AbstractManifold) + vtmm = vector_bundle_transport(fiber, M) + vtbm = FiberBundleProductVectorTransport(vtmm, vtmm) + return FiberBundle(fiber, M, vtbm) +end + +struct FiberBundleBasisData{BBasis<:CachedBasis,TBasis<:CachedBasis} + base_basis::BBasis + fiber_basis::TBasis +end + +@doc raw""" + struct FiberBundleInverseProductRetraction <: AbstractInverseRetractionMethod end + +Inverse retraction of the point `y` at point `p` from vector bundle `B` over manifold +`B.fiber` (denoted $\mathcal M$). The inverse retraction is derived as a product manifold-style +approximation to the logarithmic map in the Sasaki metric. The considered product manifold +is the product between the manifold $\mathcal M$ and the topological vector space isometric +to the fiber. + +Notation: + * The point $p = (x_p, V_p)$ where $x_p ∈ \mathcal M$ and $V_p$ belongs to the + fiber $F=Ο€^{-1}(\{x_p\})$ of the vector bundle $B$ where $Ο€$ is the + canonical projection of that vector bundle $B$. + Similarly, $q = (x_q, V_q)$. + +The inverse retraction is calculated as + +$\operatorname{retr}^{-1}_p q = (\operatorname{retr}^{-1}_{x_p}(x_q), V_{\operatorname{retr}^{-1}} - V_p)$ + +where $V_{\operatorname{retr}^{-1}}$ is the result of vector transport of $V_q$ to the point $x_p$. +The difference $V_{\operatorname{retr}^{-1}} - V_p$ corresponds to the logarithmic map in +the vector space $F$. + +See also [`FiberBundleProductRetraction`](@ref). +""" +struct FiberBundleInverseProductRetraction <: AbstractInverseRetractionMethod end + +@doc raw""" + struct FiberBundleProductRetraction <: AbstractRetractionMethod end + +Product retraction map of tangent vector $X$ at point $p$ from vector bundle `B` over +manifold `B.fiber` (denoted $\mathcal M$). The retraction is derived as a product manifold-style +approximation to the exponential map in the Sasaki metric. The considered product manifold +is the product between the manifold $\mathcal M$ and the topological vector space isometric +to the fiber. + +Notation: + * The point $p = (x_p, V_p)$ where $x_p ∈ \mathcal M$ and $V_p$ belongs to the + fiber $F=Ο€^{-1}(\{x_p\})$ of the vector bundle $B$ where $Ο€$ is the + canonical projection of that vector bundle $B$. + * The tangent vector $X = (V_{X,M}, V_{X,F}) ∈ T_pB$ where + $V_{X,M}$ is a tangent vector from the tangent space $T_{x_p}\mathcal M$ and + $V_{X,F}$ is a tangent vector from the tangent space $T_{V_p}F$ (isomorphic to $F$). + +The retraction is calculated as + +$\operatorname{retr}_p(X) = (\exp_{x_p}(V_{X,M}), V_{\exp})$ + +where $V_{\exp}$ is the result of vector transport of $V_p + V_{X,F}$ +to the point $\exp_{x_p}(V_{X,M})$. +The sum $V_p + V_{X,F}$ corresponds to the exponential map in the vector space $F$. + +See also [`FiberBundleInverseProductRetraction`](@ref). +""" +struct FiberBundleProductRetraction <: AbstractRetractionMethod end + +function get_basis(M::FiberBundle, p, B::AbstractBasis) + xp1 = submanifold_component(p, Val(1)) + base_basis = get_basis(M.manifold, xp1, B) + fiber_basis = get_basis(M.fiber, xp1, B) + return CachedBasis(B, FiberBundleBasisData(base_basis, fiber_basis)) +end +function get_basis(M::FiberBundle, p, B::CachedBasis) + return invoke(get_basis, Tuple{AbstractManifold,Any,CachedBasis}, M, p, B) +end + +function get_basis(M::FiberBundle, p, B::DiagonalizingOrthonormalBasis) + xp1 = submanifold_component(p, Val(1)) + bv1 = DiagonalizingOrthonormalBasis(submanifold_component(B.frame_direction, Val(1))) + b1 = get_basis(M.manifold, xp1, bv1) + bv2 = DiagonalizingOrthonormalBasis(submanifold_component(B.frame_direction, Val(2))) + b2 = get_basis(M.fiber, xp1, bv2) + return CachedBasis(B, FiberBundleBasisData(b1, b2)) +end + +function get_coordinates(M::FiberBundle, p, X, B::AbstractBasis) + px, Vx = submanifold_components(M.manifold, p) + VXM, VXF = submanifold_components(M.manifold, X) + n = manifold_dimension(M.manifold) + return vcat( + get_coordinates(M.manifold, px, VXM, B), + get_coordinates(M.fiber, px, VXF, B), + ) +end + +function get_coordinates!(M::FiberBundle, Y, p, X, B::AbstractBasis) + px, Vx = submanifold_components(M.manifold, p) + VXM, VXF = submanifold_components(M.manifold, X) + n = manifold_dimension(M.manifold) + get_coordinates!(M.manifold, view(Y, 1:n), px, VXM, B) + get_coordinates!(M.fiber, view(Y, (n + 1):length(Y)), px, VXF, B) + return Y +end + +function get_coordinates( + M::FiberBundle, + p, + X, + B::CachedBasis{𝔽,<:AbstractBasis{𝔽},<:FiberBundleBasisData}, +) where {𝔽} + px, Vx = submanifold_components(M.manifold, p) + VXM, VXF = submanifold_components(M.manifold, X) + return vcat( + get_coordinates(M.manifold, px, VXM, B.data.base_basis), + get_coordinates(M.fiber, px, VXF, B.data.fiber_basis), + ) +end + +function get_coordinates!( + M::FiberBundle, + Y, + p, + X, + B::CachedBasis{𝔽,<:AbstractBasis{𝔽},<:FiberBundleBasisData}, +) where {𝔽} + px, Vx = submanifold_components(M.manifold, p) + VXM, VXF = submanifold_components(M.manifold, X) + n = manifold_dimension(M.manifold) + get_coordinates!(M.manifold, view(Y, 1:n), px, VXM, B.data.base_basis) + get_coordinates!(M.fiber, view(Y, (n + 1):length(Y)), px, VXF, B.data.fiber_basis) + return Y +end + +function get_vector(M::FiberBundle, p, X, B::AbstractBasis) + n = manifold_dimension(M.manifold) + xp1 = submanifold_component(p, Val(1)) + return ArrayPartition( + get_vector(M.manifold, xp1, X[1:n], B), + get_vector(M.fiber, xp1, X[(n + 1):end], B), + ) +end + +function get_vector!(M::FiberBundle, Y, p, X, B::AbstractBasis) + n = manifold_dimension(M.manifold) + xp1 = submanifold_component(p, Val(1)) + get_vector!(M.manifold, submanifold_component(Y, Val(1)), xp1, X[1:n], B) + get_vector!(M.fiber, submanifold_component(Y, Val(2)), xp1, X[(n + 1):end], B) + return Y +end + +function get_vector( + M::FiberBundle, + p, + X, + B::CachedBasis{𝔽,<:AbstractBasis{𝔽},<:FiberBundleBasisData}, +) where {𝔽} + n = manifold_dimension(M.manifold) + xp1 = submanifold_component(p, Val(1)) + return ArrayPartition( + get_vector(M.manifold, xp1, X[1:n], B.data.base_basis), + get_vector(M.fiber, xp1, X[(n + 1):end], B.data.fiber_basis), + ) +end + +function get_vector!( + M::FiberBundle, + Y, + p, + X, + B::CachedBasis{𝔽,<:AbstractBasis{𝔽},<:FiberBundleBasisData}, +) where {𝔽} + n = manifold_dimension(M.manifold) + xp1 = submanifold_component(p, Val(1)) + get_vector!( + M.manifold, + submanifold_component(Y, Val(1)), + xp1, + X[1:n], + B.data.base_basis, + ) + get_vector!( + M.fiber, + submanifold_component(Y, Val(2)), + xp1, + X[(n + 1):end], + B.data.fiber_basis, + ) + return Y +end + +function get_vectors( + M::FiberBundle, + p::ProductRepr, + B::CachedBasis{𝔽,<:AbstractBasis{𝔽},<:FiberBundleBasisData}, +) where {𝔽} + xp1 = submanifold_component(p, Val(1)) + zero_m = zero_vector(M.manifold, xp1) + zero_f = zero_vector(M.fiber, xp1) + vs = typeof(ProductRepr(zero_m, zero_f))[] + for bv in get_vectors(M.manifold, xp1, B.data.base_basis) + push!(vs, ProductRepr(bv, zero_f)) + end + for bv in get_vectors(M.fiber, xp1, B.data.fiber_basis) + push!(vs, ProductRepr(zero_m, bv)) + end + return vs +end +function get_vectors( + M::FiberBundle, + p::ArrayPartition, + B::CachedBasis{𝔽,<:AbstractBasis{𝔽},<:Manifolds.FiberBundleBasisData}, +) where {𝔽} + xp1 = submanifold_component(p, Val(1)) + zero_m = zero_vector(M.manifold, xp1) + zero_f = zero_vector(M.fiber, xp1) + vs = typeof(ArrayPartition(zero_m, zero_f))[] + for bv in get_vectors(M.manifold, xp1, B.data.base_basis) + push!(vs, ArrayPartition(bv, zero_f)) + end + for bv in get_vectors(M.fiber, xp1, B.data.fiber_basis) + push!(vs, ArrayPartition(zero_m, bv)) + end + return vs +end +function get_vectors(M::BundleFibers, p, B::CachedBasis) + return get_vectors(M.manifold, p, B) +end + +""" + getindex(p::ProductRepr, M::FiberBundle, s::Symbol) + p[M::FiberBundle, s] + +Access the element(s) at index `s` of a point `p` on a [`FiberBundle`](@ref) `M` by +using the symbols `:point` and `:vector` or `:fiber` for the base and vector or fiber +component, respectively. +""" +@inline function Base.getindex(p::ProductRepr, M::FiberBundle, s::Symbol) + (s === :point) && return submanifold_component(M, p, Val(1)) + (s === :vector || s === :fiber) && return submanifold_component(M, p, Val(2)) + return throw(DomainError(s, "unknown component $s on $M.")) +end +""" + getindex(p::ArrayPartition, M::FiberBundle, s::Symbol) + p[M::FiberBundle, s] + +Access the element(s) at index `s` of a point `p` on a [`FiberBundle`](@ref) `M` by +using the symbols `:point` and `:vector` or `:fiber` for the base and vector or fiber +component, respectively. +""" +@inline function Base.getindex(p::ArrayPartition, M::FiberBundle, s::Symbol) + (s === :point) && return p.x[1] + (s === :vector || s === :fiber) && return p.x[2] + return throw(DomainError(s, "unknown component $s on $M.")) +end + +function _isapprox(B::FiberBundle, p, q; kwargs...) + xp, Vp = submanifold_components(B.manifold, p) + xq, Vq = submanifold_components(B.manifold, q) + return isapprox(B.manifold, xp, xq; kwargs...) && + isapprox(FiberAtPoint(B.fiber, xp), Vp, Vq; kwargs...) +end +function _isapprox(B::FiberBundle, p, X, Y; kwargs...) + px, Vx = submanifold_components(B.manifold, p) + VXM, VXF = submanifold_components(B.manifold, X) + VYM, VYF = submanifold_components(B.manifold, Y) + return isapprox(B.manifold, VXM, VYM; kwargs...) && + isapprox(FiberAtPoint(B.fiber, px), VXF, VYF; kwargs...) +end + +function manifold_dimension(B::FiberBundle) + return manifold_dimension(B.manifold) + fiber_dimension(B.fiber) +end + +function Random.rand!(rng::AbstractRNG, M::FiberBundle, pX; vector_at=nothing) + pXM, pXF = submanifold_components(M.manifold, pX) + if vector_at === nothing + rand!(rng, M.manifold, pXM) + rand!(rng, FiberAtPoint(M.fiber, pXM), pXF) + else + vector_atM, vector_atF = submanifold_components(M.manifold, vector_at) + rand!(rng, M.manifold, pXM; vector_at=vector_atM) + rand!(rng, FiberAtPoint(M.fiber, pXM), pXF; vector_at=vector_atF) + end + return pX +end + +""" + setindex!(p::ProductRepr, val, M::FiberBundle, s::Symbol) + p[M::VectorBundle, s] = val + +Set the element(s) at index `s` of a point `p` on a [`FiberBundle`](@ref) `M` to `val` by +using the symbols `:point` and `:fiber` or `:vector` for the base and fiber or vector +component, respectively. + +!!! note + + The *content* of element of `p` is replaced, not the element itself. +""" +@inline function Base.setindex!(x::ProductRepr, val, M::FiberBundle, s::Symbol) + if s === :point + return copyto!(submanifold_component(M, x, Val(1)), val) + elseif s === :vector || s === :fiber + return copyto!(submanifold_component(M, x, Val(2)), val) + else + throw(DomainError(s, "unknown component $s on $M.")) + end +end +""" + setindex!(p::ArrayPartition, val, M::FiberBundle, s::Symbol) + p[M::VectorBundle, s] = val + +Set the element(s) at index `s` of a point `p` on a [`FiberBundle`](@ref) `M` to `val` by +using the symbols `:point` and `:fiber` or `:vector` for the base and fiber or vector +component, respectively. + +!!! note + + The *content* of element of `p` is replaced, not the element itself. +""" +@inline function Base.setindex!(x::ArrayPartition, val, M::FiberBundle, s::Symbol) + if s === :point + return copyto!(x.x[1], val) + elseif s === :vector || s === :fiber + return copyto!(x.x[2], val) + else + throw(DomainError(s, "unknown component $s on $M.")) + end +end + +@inline function Base.view(x::ArrayPartition, M::FiberBundle, s::Symbol) + (s === :point) && return x.x[1] + (s === :vector || s === :fiber) && return x.x[2] + throw(DomainError(s, "unknown component $s on $M.")) +end + +@doc raw""" + zero_vector(B::FiberBundle, p) + +Zero tangent vector at point `p` from the fiber bundle `B` +over manifold `B.fiber` (denoted $\mathcal M$). The zero vector belongs to the space $T_{p}B$ + +Notation: + * The point $p = (x_p, V_p)$ where $x_p ∈ \mathcal M$ and $V_p$ belongs to the + fiber $F=Ο€^{-1}(\{x_p\})$ of the vector bundle $B$ where $Ο€$ is the + canonical projection of that vector bundle $B$. + +The zero vector is calculated as + +$\mathbf{0}_{p} = (\mathbf{0}_{x_p}, \mathbf{0}_F)$ + +where $\mathbf{0}_{x_p}$ is the zero tangent vector from $T_{x_p}\mathcal M$ and +$\mathbf{0}_F$ is the zero element of the vector space $F$. +""" +zero_vector(::FiberBundle, ::Any...) + +function zero_vector!(B::FiberBundle, X, p) + xp, Vp = submanifold_components(B.manifold, p) + VXM, VXF = submanifold_components(B.manifold, X) + zero_vector!(B.manifold, VXM, xp) + zero_vector!(B.fiber, VXF, Vp) + return X +end diff --git a/src/manifolds/PowerManifold.jl b/src/manifolds/PowerManifold.jl index bc5c3d6a9b..0acfe0caf5 100644 --- a/src/manifolds/PowerManifold.jl +++ b/src/manifolds/PowerManifold.jl @@ -290,10 +290,6 @@ end Distributions.support(tvd::PowerFVectorDistribution) = FVectorSupport(tvd.type, tvd.point) Distributions.support(d::PowerPointDistribution) = MPointSupport(d.manifold) -function vector_bundle_transport(fiber::VectorSpaceType, M::PowerManifold) - return ParallelTransport() -end - @inline function _write( ::PowerManifoldMultidimensional, rep_size::Tuple, diff --git a/src/manifolds/ProductManifold.jl b/src/manifolds/ProductManifold.jl index eec31d32d9..553ecc8532 100644 --- a/src/manifolds/ProductManifold.jl +++ b/src/manifolds/ProductManifold.jl @@ -1515,7 +1515,7 @@ function uniform_distribution(M::ProductManifold, p) ) end -function vector_bundle_transport(::VectorSpaceType, M::ProductManifold) +function vector_bundle_transport(::FiberType, M::ProductManifold) return ProductVectorTransport(map(_ -> ParallelTransport(), M.manifolds)) end diff --git a/src/manifolds/VectorBundle.jl b/src/manifolds/VectorBundle.jl index 774822760c..fbd02c4244 100644 --- a/src/manifolds/VectorBundle.jl +++ b/src/manifolds/VectorBundle.jl @@ -1,107 +1,4 @@ -""" - TensorProductType(spaces::VectorSpaceType...) - -Vector space type corresponding to the tensor product of given vector space -types. -""" -struct TensorProductType{TS<:Tuple} <: VectorSpaceType - spaces::TS -end - -TensorProductType(spaces::VectorSpaceType...) = TensorProductType{typeof(spaces)}(spaces) - -""" - VectorBundleFibers(fiber::VectorSpaceType, M::AbstractManifold) - -Type representing a family of vector spaces (fibers) of a vector bundle over `M` -with vector spaces of type `fiber`. In contrast with `VectorBundle`, operations -on `VectorBundleFibers` expect point-like and vector-like parts to be -passed separately instead of being bundled together. It can be thought of -as a representation of vector spaces from a vector bundle but without -storing the point at which a vector space is attached (which is specified -separately in various functions). -""" -struct VectorBundleFibers{TVS<:VectorSpaceType,TM<:AbstractManifold} - fiber::TVS - manifold::TM -end - -const TangentBundleFibers{M} = - VectorBundleFibers{TangentSpaceType,M} where {M<:AbstractManifold} - -TangentBundleFibers(M::AbstractManifold) = VectorBundleFibers(TangentSpace, M) - -const CotangentBundleFibers{M} = - VectorBundleFibers{CotangentSpaceType,M} where {M<:AbstractManifold} - -CotangentBundleFibers(M::AbstractManifold) = VectorBundleFibers(CotangentSpace, M) - -""" - VectorSpaceAtPoint{ - 𝔽, - TFiber<:VectorBundleFibers{<:VectorSpaceType,<:AbstractManifold{𝔽}}, - TX, - } <: AbstractManifold{𝔽} - -A vector space at a point `p` on the manifold. -This is modelled using [`VectorBundleFibers`](@ref) with only a vector-like part -and fixing the point-like part to be just `p`. - -This vector space itself is also a `manifold`. Especially, it's flat and hence isometric -to the [`Euclidean`](@ref) manifold. - -# Constructor - VectorSpaceAtPoint(fiber::VectorBundleFibers, p) - -A vector space (fiber type `fiber` of a vector bundle) at point `p` from -the manifold `fiber.manifold`. -""" -struct VectorSpaceAtPoint{ - 𝔽, - TFiber<:VectorBundleFibers{<:VectorSpaceType,<:AbstractManifold{𝔽}}, - TX, -} <: AbstractManifold{𝔽} - fiber::TFiber - point::TX -end - -""" - TangentSpaceAtPoint{M} - -Alias for [`VectorSpaceAtPoint`](@ref) for the tangent space at a point. -""" -const TangentSpaceAtPoint{M} = - VectorSpaceAtPoint{𝔽,TangentBundleFibers{M}} where {𝔽,M<:AbstractManifold{𝔽}} - -""" - TangentSpaceAtPoint(M::AbstractManifold, p) - -Return an object of type [`VectorSpaceAtPoint`](@ref) representing tangent -space at `p` on the [`AbstractManifold`](https://juliamanifolds.github.io/ManifoldsBase.jl/stable/types.html#ManifoldsBase.AbstractManifold) `M`. -""" -TangentSpaceAtPoint(M::AbstractManifold, p) = VectorSpaceAtPoint(TangentBundleFibers(M), p) - -""" - TangentSpace(M::AbstractManifold, p) - -Return a [`TangentSpaceAtPoint`](@ref Manifolds.TangentSpaceAtPoint) representing tangent space at `p` on the [`AbstractManifold`](https://juliamanifolds.github.io/ManifoldsBase.jl/stable/types.html#ManifoldsBase.AbstractManifold) `M`. -""" -TangentSpace(M::AbstractManifold, p) = VectorSpaceAtPoint(TangentBundleFibers(M), p) - -const CotangentSpaceAtPoint{M} = - VectorSpaceAtPoint{𝔽,CotangentBundleFibers{M}} where {𝔽,M<:AbstractManifold{𝔽}} - -""" - CotangentSpaceAtPoint(M::AbstractManifold, p) - -Return an object of type [`VectorSpaceAtPoint`](@ref) representing cotangent -space at `p`. -""" -function CotangentSpaceAtPoint(M::AbstractManifold, p) - return VectorSpaceAtPoint(CotangentBundleFibers(M), p) -end - @doc raw""" struct SasakiRetraction <: AbstractRetractionMethod end @@ -130,80 +27,33 @@ struct SasakiRetraction <: AbstractRetractionMethod L::Int end -@doc raw""" - VectorBundleProductVectorTransport{ - TMP<:AbstractVectorTransportMethod, - TMV<:AbstractVectorTransportMethod, - } <: AbstractVectorTransportMethod - -Vector transport type on [`VectorBundle`](@ref). `method_point` is used for vector transport -of the point part and `method_vector` is used for transport of the vector part. - -The vector transport is derived as a product manifold-style vector transport. The considered -product manifold is the product between the manifold $\mathcal M$ and the topological vector -space isometric to the fiber. - -# Constructor - - VectorBundleProductVectorTransport( - method_point::AbstractVectorTransportMethod, - method_vector::AbstractVectorTransportMethod, - ) - VectorBundleProductVectorTransport() - -By default both methods are set to `ParallelTransport`. """ -struct VectorBundleProductVectorTransport{ - TMP<:AbstractVectorTransportMethod, - TMV<:AbstractVectorTransportMethod, -} <: AbstractVectorTransportMethod - method_point::TMP - method_vector::TMV -end - -function VectorBundleProductVectorTransport() - return VectorBundleProductVectorTransport(ParallelTransport(), ParallelTransport()) -end + const VectorBundleVectorTransport = FiberBundleProductVectorTransport +Deprecated: an alias for `FiberBundleProductVectorTransport`. """ - const VectorBundleVectorTransport = VectorBundleProductVectorTransport - -Deprecated: an alias for `VectorBundleProductVectorTransport`. -""" -const VectorBundleVectorTransport = VectorBundleProductVectorTransport - -""" - VectorBundle{𝔽,TVS<:VectorSpaceType,TM<:AbstractManifold{𝔽}} <: AbstractManifold{𝔽} - -Vector bundle on a [`AbstractManifold`](https://juliamanifolds.github.io/ManifoldsBase.jl/stable/types.html#ManifoldsBase.AbstractManifold) `M` of type [`VectorSpaceType`](https://juliamanifolds.github.io/ManifoldsBase.jl/stable/bases.html#ManifoldsBase.VectorSpaceType). +const VectorBundleVectorTransport = FiberBundleProductVectorTransport -# Constructor - - VectorBundle(M::AbstractManifold, type::VectorSpaceType) -""" -struct VectorBundle{ +const VectorBundle{𝔽,TVS,TM,TVT} = FiberBundle{ 𝔽, + VectorSpaceFiberType{TVS}, + TM, + TVT, +} where { TVS<:VectorSpaceType, TM<:AbstractManifold{𝔽}, - TVT<:VectorBundleProductVectorTransport, -} <: AbstractManifold{𝔽} - type::TVS - manifold::TM - fiber::VectorBundleFibers{TVS,TM} - vector_transport::TVT -end + TVT<:FiberBundleProductVectorTransport, +} function VectorBundle( - fiber::TVS, - M::TM, - vtm::VectorBundleProductVectorTransport, -) where {TVS<:VectorSpaceType,TM<:AbstractManifold{𝔽}} where {𝔽} - return VectorBundle{𝔽,TVS,TM,typeof(vtm)}(fiber, M, VectorBundleFibers(fiber, M), vtm) + vst::VectorSpaceType, + M::AbstractManifold, + vtm::FiberBundleProductVectorTransport, +) + return FiberBundle(VectorSpaceFiberType(vst), M, vtm) end -function VectorBundle(fiber::VectorSpaceType, M::AbstractManifold) - vtmm = vector_bundle_transport(fiber, M) - vtbm = VectorBundleProductVectorTransport(vtmm, vtmm) - return VectorBundle(fiber, M, vtbm) +function VectorBundle(vst::VectorSpaceType, M::AbstractManifold) + return FiberBundle(VectorSpaceFiberType(vst), M) end """ @@ -211,9 +61,9 @@ end Tangent bundle for manifold of type `M`, as a manifold with the Sasaki metric [^Sasaki1958]. -Exact retraction and inverse retraction can be approximated using [`VectorBundleProductRetraction`](@ref), -[`VectorBundleInverseProductRetraction`](@ref) and [`SasakiRetraction`](@ref). -[`VectorBundleProductVectorTransport`](@ref) can be used as a vector transport. +Exact retraction and inverse retraction can be approximated using [`FiberBundleProductRetraction`](@ref), +[`FiberBundleInverseProductRetraction`](@ref) and [`SasakiRetraction`](@ref). +[`FiberBundleProductVectorTransport`](@ref) can be used as a vector transport. [^Sasaki1958]: > S. Sasaki, β€œOn the differential geometry of tangent bundles of Riemannian manifolds,” @@ -222,13 +72,13 @@ Exact retraction and inverse retraction can be approximated using [`VectorBundle # Constructors TangentBundle(M::AbstractManifold) - TangentBundle(M::AbstractManifold, vtm::VectorBundleProductVectorTransport) + TangentBundle(M::AbstractManifold, vtm::FiberBundleProductVectorTransport) """ const TangentBundle{𝔽,M} = VectorBundle{𝔽,TangentSpaceType,M} where {𝔽,M<:AbstractManifold{𝔽}} TangentBundle(M::AbstractManifold) = VectorBundle(TangentSpace, M) -function TangentBundle(M::AbstractManifold, vtm::VectorBundleProductVectorTransport) +function TangentBundle(M::AbstractManifold, vtm::FiberBundleProductVectorTransport) return VectorBundle(TangentSpace, M, vtm) end @@ -236,73 +86,10 @@ const CotangentBundle{𝔽,M} = VectorBundle{𝔽,CotangentSpaceType,M} where {𝔽,M<:AbstractManifold{𝔽}} CotangentBundle(M::AbstractManifold) = VectorBundle(CotangentSpace, M) -function CotangentBundle(M::AbstractManifold, vtm::VectorBundleProductVectorTransport) +function CotangentBundle(M::AbstractManifold, vtm::FiberBundleProductVectorTransport) return VectorBundle(CotangentSpace, M, vtm) end -struct VectorBundleBasisData{BBasis<:CachedBasis,TBasis<:CachedBasis} - base_basis::BBasis - vec_basis::TBasis -end - -@doc raw""" - struct VectorBundleInverseProductRetraction <: AbstractInverseRetractionMethod end - -Inverse retraction of the point `y` at point `p` from vector bundle `B` over manifold -`B.fiber` (denoted $\mathcal M$). The inverse retraction is derived as a product manifold-style -approximation to the logarithmic map in the Sasaki metric. The considered product manifold -is the product between the manifold $\mathcal M$ and the topological vector space isometric -to the fiber. - -Notation: - * The point $p = (x_p, V_p)$ where $x_p ∈ \mathcal M$ and $V_p$ belongs to the - fiber $F=Ο€^{-1}(\{x_p\})$ of the vector bundle $B$ where $Ο€$ is the - canonical projection of that vector bundle $B$. - Similarly, $q = (x_q, V_q)$. - -The inverse retraction is calculated as - -$\operatorname{retr}^{-1}_p q = (\operatorname{retr}^{-1}_{x_p}(x_q), V_{\operatorname{retr}^{-1}} - V_p)$ - -where $V_{\operatorname{retr}^{-1}}$ is the result of vector transport of $V_q$ to the point $x_p$. -The difference $V_{\operatorname{retr}^{-1}} - V_p$ corresponds to the logarithmic map in -the vector space $F$. - -See also [`VectorBundleProductRetraction`](@ref). -""" -struct VectorBundleInverseProductRetraction <: AbstractInverseRetractionMethod end - -@doc raw""" - struct VectorBundleProductRetraction <: AbstractRetractionMethod end - -Product retraction map of tangent vector $X$ at point $p$ from vector bundle `B` over -manifold `B.fiber` (denoted $\mathcal M$). The retraction is derived as a product manifold-style -approximation to the exponential map in the Sasaki metric. The considered product manifold -is the product between the manifold $\mathcal M$ and the topological vector space isometric -to the fiber. - -Notation: - * The point $p = (x_p, V_p)$ where $x_p ∈ \mathcal M$ and $V_p$ belongs to the - fiber $F=Ο€^{-1}(\{x_p\})$ of the vector bundle $B$ where $Ο€$ is the - canonical projection of that vector bundle $B$. - * The tangent vector $X = (V_{X,M}, V_{X,F}) ∈ T_pB$ where - $V_{X,M}$ is a tangent vector from the tangent space $T_{x_p}\mathcal M$ and - $V_{X,F}$ is a tangent vector from the tangent space $T_{V_p}F$ (isomorphic to $F$). - -The retraction is calculated as - -$\operatorname{retr}_p(X) = (\exp_{x_p}(V_{X,M}), V_{\exp})$ - -where $V_{\exp}$ is the result of vector transport of $V_p + V_{X,F}$ -to the point $\exp_{x_p}(V_{X,M})$. -The sum $V_p + V_{X,F}$ corresponds to the exponential map in the vector space $F$. - -See also [`VectorBundleInverseProductRetraction`](@ref). -""" -struct VectorBundleProductRetraction <: AbstractRetractionMethod end - -base_manifold(B::VectorBundleFibers) = base_manifold(B.manifold) -base_manifold(B::VectorSpaceAtPoint) = base_manifold(B.fiber) base_manifold(B::VectorBundle) = base_manifold(B.manifold) """ @@ -315,89 +102,29 @@ of `p` is attached. bundle_projection(B::VectorBundle, p) = submanifold_component(B.manifold, p, Val(1)) function default_inverse_retraction_method(::TangentBundle) - return VectorBundleInverseProductRetraction() + return FiberBundleInverseProductRetraction() end function default_retraction_method(::TangentBundle) - return VectorBundleProductRetraction() + return FiberBundleProductRetraction() end function default_vector_transport_method(B::TangentBundle) default_vt_m = default_vector_transport_method(B.manifold) - return VectorBundleProductVectorTransport(default_vt_m, default_vt_m) + return FiberBundleProductVectorTransport(default_vt_m, default_vt_m) end """ - distance(B::VectorBundleFibers, p, X, Y) + distance(B::BundleFibers, p, X, Y) Distance between vectors `X` and `Y` from the vector space at point `p` from the manifold `B.manifold`, that is the base manifold of `M`. """ distance(B::VectorBundleFibers, p, X, Y) = norm(B, p, X - Y) -""" - distance(M::TangentSpaceAtPoint, p, q) - -Distance between vectors `p` and `q` from the vector space `M`. It is calculated as the norm -of their difference. -""" -function distance(M::TangentSpaceAtPoint, p, q) - return norm(M.fiber.manifold, M.point, q - p) -end - -function embed!(M::TangentSpaceAtPoint, q, p) - return embed!(M.fiber.manifold, q, M.point, p) -end -function embed!(M::TangentSpaceAtPoint, Y, p, X) - return embed!(M.fiber.manifold, Y, M.point, X) -end - -@doc raw""" - exp(M::TangentSpaceAtPoint, p, X) - -Exponential map of tangent vectors `X` and `p` from the tangent space `M`. It is -calculated as their sum. -""" -exp(::TangentSpaceAtPoint, ::Any, ::Any) - -function exp!(M::TangentSpaceAtPoint, q, p, X) - copyto!(M.fiber.manifold, q, p + X) - return q -end - -function get_basis(M::VectorBundle, p, B::AbstractBasis) - xp1 = submanifold_component(p, Val(1)) - base_basis = get_basis(M.manifold, xp1, B) - vec_basis = get_basis(M.fiber, xp1, B) - return CachedBasis(B, VectorBundleBasisData(base_basis, vec_basis)) -end -function get_basis(M::VectorBundle, p, B::CachedBasis) - return invoke(get_basis, Tuple{AbstractManifold,Any,CachedBasis}, M, p, B) -end -function get_basis(M::TangentSpaceAtPoint, p, B::CachedBasis) - return invoke( - get_basis, - Tuple{AbstractManifold,Any,CachedBasis}, - M.fiber.manifold, - M.point, - B, - ) -end - -function get_basis(M::VectorBundle, p, B::DiagonalizingOrthonormalBasis) - xp1 = submanifold_component(p, Val(1)) - bv1 = DiagonalizingOrthonormalBasis(submanifold_component(B.frame_direction, Val(1))) - b1 = get_basis(M.manifold, xp1, bv1) - bv2 = DiagonalizingOrthonormalBasis(submanifold_component(B.frame_direction, Val(2))) - b2 = get_basis(M.fiber, xp1, bv2) - return CachedBasis(B, VectorBundleBasisData(b1, b2)) -end function get_basis(M::TangentBundleFibers, p, B::AbstractBasis{<:Any,TangentSpaceType}) return get_basis(M.manifold, p, B) end -function get_basis(M::TangentSpaceAtPoint, p, B::AbstractBasis{<:Any,TangentSpaceType}) - return get_basis(M.fiber.manifold, M.point, B) -end function get_coordinates(M::TangentBundleFibers, p, X, B::AbstractBasis) return get_coordinates(M.manifold, p, X, B) @@ -407,205 +134,13 @@ function get_coordinates!(M::TangentBundleFibers, Y, p, X, B::AbstractBasis) return get_coordinates!(M.manifold, Y, p, X, B) end -function get_coordinates(M::TangentSpaceAtPoint, p, X, B::AbstractBasis) - return get_coordinates(M.fiber.manifold, M.point, X, B) -end - -function get_coordinates!(M::TangentSpaceAtPoint, Y, p, X, B::AbstractBasis) - return get_coordinates!(M.fiber.manifold, Y, M.point, X, B) -end - -function get_coordinates(M::VectorBundle, p, X, B::AbstractBasis) - px, Vx = submanifold_components(M.manifold, p) - VXM, VXF = submanifold_components(M.manifold, X) - n = manifold_dimension(M.manifold) - return vcat( - get_coordinates(M.manifold, px, VXM, B), - get_coordinates(M.fiber, px, VXF, B), - ) -end - -function get_coordinates!(M::VectorBundle, Y, p, X, B::AbstractBasis) - px, Vx = submanifold_components(M.manifold, p) - VXM, VXF = submanifold_components(M.manifold, X) - n = manifold_dimension(M.manifold) - get_coordinates!(M.manifold, view(Y, 1:n), px, VXM, B) - get_coordinates!(M.fiber, view(Y, (n + 1):length(Y)), px, VXF, B) - return Y -end - -function get_coordinates( - M::VectorBundle, - p, - X, - B::CachedBasis{𝔽,<:AbstractBasis{𝔽},<:VectorBundleBasisData}, -) where {𝔽} - px, Vx = submanifold_components(M.manifold, p) - VXM, VXF = submanifold_components(M.manifold, X) - return vcat( - get_coordinates(M.manifold, px, VXM, B.data.base_basis), - get_coordinates(M.fiber, px, VXF, B.data.vec_basis), - ) -end - -function get_coordinates!( - M::VectorBundle, - Y, - p, - X, - B::CachedBasis{𝔽,<:AbstractBasis{𝔽},<:VectorBundleBasisData}, -) where {𝔽} - px, Vx = submanifold_components(M.manifold, p) - VXM, VXF = submanifold_components(M.manifold, X) - n = manifold_dimension(M.manifold) - get_coordinates!(M.manifold, view(Y, 1:n), px, VXM, B.data.base_basis) - get_coordinates!(M.fiber, view(Y, (n + 1):length(Y)), px, VXF, B.data.vec_basis) - return Y -end - -function get_vector(M::VectorBundle, p, X, B::AbstractBasis) - n = manifold_dimension(M.manifold) - xp1 = submanifold_component(p, Val(1)) - return ArrayPartition( - get_vector(M.manifold, xp1, X[1:n], B), - get_vector(M.fiber, xp1, X[(n + 1):end], B), - ) -end - -function get_vector!(M::VectorBundle, Y, p, X, B::AbstractBasis) - n = manifold_dimension(M.manifold) - xp1 = submanifold_component(p, Val(1)) - get_vector!(M.manifold, submanifold_component(Y, Val(1)), xp1, X[1:n], B) - get_vector!(M.fiber, submanifold_component(Y, Val(2)), xp1, X[(n + 1):end], B) - return Y -end - -function get_vector( - M::VectorBundle, - p, - X, - B::CachedBasis{𝔽,<:AbstractBasis{𝔽},<:VectorBundleBasisData}, -) where {𝔽} - n = manifold_dimension(M.manifold) - xp1 = submanifold_component(p, Val(1)) - return ArrayPartition( - get_vector(M.manifold, xp1, X[1:n], B.data.base_basis), - get_vector(M.fiber, xp1, X[(n + 1):end], B.data.vec_basis), - ) -end - -function get_vector!( - M::VectorBundle, - Y, - p, - X, - B::CachedBasis{𝔽,<:AbstractBasis{𝔽},<:VectorBundleBasisData}, -) where {𝔽} - n = manifold_dimension(M.manifold) - xp1 = submanifold_component(p, Val(1)) - get_vector!( - M.manifold, - submanifold_component(Y, Val(1)), - xp1, - X[1:n], - B.data.base_basis, - ) - get_vector!( - M.fiber, - submanifold_component(Y, Val(2)), - xp1, - X[(n + 1):end], - B.data.vec_basis, - ) - return Y -end - function get_vector(M::TangentBundleFibers, p, X, B::AbstractBasis) return get_vector(M.manifold, p, X, B) end -function get_vector(M::TangentSpaceAtPoint, p, X, B::AbstractBasis) - return get_vector(M.fiber.manifold, M.point, X, B) -end function get_vector!(M::TangentBundleFibers, Y, p, X, B::AbstractBasis) return get_vector!(M.manifold, Y, p, X, B) end -function get_vector!(M::TangentSpaceAtPoint, Y, p, X, B::AbstractBasis) - return get_vector!(M.fiber.manifold, Y, M.point, X, B) -end - -function get_vectors( - M::VectorBundle, - p::ProductRepr, - B::CachedBasis{𝔽,<:AbstractBasis{𝔽},<:VectorBundleBasisData}, -) where {𝔽} - xp1 = submanifold_component(p, Val(1)) - zero_m = zero_vector(M.manifold, xp1) - zero_f = zero_vector(M.fiber, xp1) - vs = typeof(ProductRepr(zero_m, zero_f))[] - for bv in get_vectors(M.manifold, xp1, B.data.base_basis) - push!(vs, ProductRepr(bv, zero_f)) - end - for bv in get_vectors(M.fiber, xp1, B.data.vec_basis) - push!(vs, ProductRepr(zero_m, bv)) - end - return vs -end -function get_vectors( - M::VectorBundle, - p::ArrayPartition, - B::CachedBasis{𝔽,<:AbstractBasis{𝔽},<:Manifolds.VectorBundleBasisData}, -) where {𝔽} - xp1 = submanifold_component(p, Val(1)) - zero_m = zero_vector(M.manifold, xp1) - zero_f = zero_vector(M.fiber, xp1) - vs = typeof(ArrayPartition(zero_m, zero_f))[] - for bv in get_vectors(M.manifold, xp1, B.data.base_basis) - push!(vs, ArrayPartition(bv, zero_f)) - end - for bv in get_vectors(M.fiber, xp1, B.data.vec_basis) - push!(vs, ArrayPartition(zero_m, bv)) - end - return vs -end -function get_vectors(M::VectorBundleFibers, p, B::CachedBasis) - return get_vectors(M.manifold, p, B) -end -function get_vectors(M::TangentSpaceAtPoint, p, B::CachedBasis) - return get_vectors(M.fiber.manifold, M.point, B) -end - -""" - getindex(p::ProductRepr, M::VectorBundle, s::Symbol) - p[M::VectorBundle, s] - -Access the element(s) at index `s` of a point `p` on a [`VectorBundle`](@ref) `M` by -using the symbols `:point` and `:vector` for the base and vector component, respectively. -""" -@inline function Base.getindex(p::ProductRepr, M::VectorBundle, s::Symbol) - (s === :point) && return submanifold_component(M, p, Val(1)) - (s === :vector) && return submanifold_component(M, p, Val(2)) - return throw(DomainError(s, "unknown component $s on $M.")) -end -""" - getindex(p::ArrayPartition, M::VectorBundle, s::Symbol) - p[M::VectorBundle, s] - -Access the element(s) at index `s` of a point `p` on a [`VectorBundle`](@ref) `M` by -using the symbols `:point` and `:vector` for the base and vector component, respectively. -""" -@inline function Base.getindex(p::ArrayPartition, M::VectorBundle, s::Symbol) - (s === :point) && return p.x[1] - (s === :vector) && return p.x[2] - return throw(DomainError(s, "unknown component $s on $M.")) -end - -@doc raw""" - injectivity_radius(M::TangentSpaceAtPoint) - -Return the injectivity radius on the [`TangentSpaceAtPoint`](@ref Manifolds.TangentSpaceAtPoint) `M`, which is $∞$. -""" -injectivity_radius(::TangentSpaceAtPoint) = Inf """ injectivity_radius(M::TangentBundle) @@ -623,12 +158,12 @@ function injectivity_radius(M::TangentBundle) end """ - inner(B::VectorBundleFibers, p, X, Y) + inner(B::BundleFibers, p, X, Y) Inner product of vectors `X` and `Y` from the vector space of type `B.fiber` at point `p` from manifold `B.manifold`. """ -function inner(B::VectorBundleFibers, p, X, Y) +function inner(B::BundleFibers, p, X, Y) return error( "inner not defined for vector space family of type $(typeof(B)), " * "point of type $(typeof(p)) and " * @@ -658,37 +193,27 @@ The inner product is calculated as $⟨X, Y⟩_p = ⟨V_{X,M}, V_{Y,M}⟩_{x_p} + ⟨V_{X,F}, V_{Y,F}⟩_{V_p}.$ """ -function inner(B::VectorBundle, p, X, Y) +function inner(B::FiberBundle, p, X, Y) px, Vx = submanifold_components(B.manifold, p) VXM, VXF = submanifold_components(B.manifold, X) VYM, VYF = submanifold_components(B.manifold, Y) # for tangent bundle Vx is discarded by the method of inner for TangentSpaceAtPoint # and px is actually used as the base point - return inner(B.manifold, px, VXM, VYM) + - inner(VectorSpaceAtPoint(B.fiber, px), Vx, VXF, VYF) + return inner(B.manifold, px, VXM, VYM) + inner(FiberAtPoint(B.fiber, px), Vx, VXF, VYF) end -""" - inner(M::TangentSpaceAtPoint, p, X, Y) - -Inner product of vectors `X` and `Y` from the tangent space at `M`. -""" -function inner(M::TangentSpaceAtPoint, p, X, Y) - return inner(M.fiber.manifold, M.point, X, Y) -end - -function _inverse_retract(M::VectorBundle, p, q, ::VectorBundleInverseProductRetraction) +function _inverse_retract(M::FiberBundle, p, q, ::FiberBundleInverseProductRetraction) return inverse_retract_product(M, p, q) end -function _inverse_retract!(M::VectorBundle, X, p, q, ::VectorBundleInverseProductRetraction) +function _inverse_retract!(M::FiberBundle, X, p, q, ::FiberBundleInverseProductRetraction) return inverse_retract_product!(M, X, p, q) end """ inverse_retract_product(M::VectorBundle, p, q) -Compute the allocating variant of the [`VectorBundleInverseProductRetraction`](@ref), +Compute the allocating variant of the [`FiberBundleInverseProductRetraction`](@ref), which by default allocates and calls `inverse_retract_product!`. """ function inverse_retract_product(M::VectorBundle, p, q) @@ -701,34 +226,11 @@ function inverse_retract_product!(B::VectorBundle, X, p, q) py, Vy = submanifold_components(B.manifold, q) VXM, VXF = submanifold_components(B.manifold, X) log!(B.manifold, VXM, px, py) - vector_transport_to!(B.fiber, VXF, py, Vy, px, B.vector_transport.method_vector) + vector_transport_to!(B.fiber, VXF, py, Vy, px, B.vector_transport.method_fiber) copyto!(VXF, VXF - Vx) return X end -function _isapprox(B::VectorBundle, p, q; kwargs...) - xp, Vp = submanifold_components(B.manifold, p) - xq, Vq = submanifold_components(B.manifold, q) - return isapprox(B.manifold, xp, xq; kwargs...) && - isapprox(VectorSpaceAtPoint(B.fiber, xp), Vp, Vq; kwargs...) -end -function _isapprox(B::VectorBundle, p, X, Y; kwargs...) - px, Vx = submanifold_components(B.manifold, p) - VXM, VXF = submanifold_components(B.manifold, X) - VYM, VYF = submanifold_components(B.manifold, Y) - return isapprox(B.manifold, VXM, VYM; kwargs...) && - isapprox(VectorSpaceAtPoint(B.fiber, px), VXF, VYF; kwargs...) -end -function _isapprox(M::TangentSpaceAtPoint, X, Y; kwargs...) - return isapprox(M.fiber.manifold, M.point, X, Y; kwargs...) -end - -""" - is_flat(::TangentSpaceAtPoint) - -Return true. [`TangentSpaceAtPoint`](@ref Manifolds.TangentSpaceAtPoint) is a flat manifold. -""" -is_flat(::TangentSpaceAtPoint) = true """ is_flat(::VectorBundle) @@ -737,37 +239,13 @@ Return true if the underlying manifold of [`VectorBundle`](@ref) `M` is flat. is_flat(M::VectorBundle) = is_flat(M.manifold) """ - log(M::TangentSpaceAtPoint, p, q) - -Logarithmic map on the tangent space manifold `M`, calculated as the difference of tangent -vectors `q` and `p` from `M`. -""" -log(::TangentSpaceAtPoint, ::Any...) -function log!(::TangentSpaceAtPoint, X, p, q) - copyto!(X, q - p) - return X -end - -function manifold_dimension(B::VectorBundle) - return manifold_dimension(B.manifold) + vector_space_dimension(B.fiber) -end -function manifold_dimension(M::VectorSpaceAtPoint) - return vector_space_dimension(M.fiber) -end - -""" - norm(B::VectorBundleFibers, p, q) + norm(B::BundleFibers, p, q) Norm of the vector `X` from the vector space of type `B.fiber` at point `p` from manifold `B.manifold`. """ LinearAlgebra.norm(B::VectorBundleFibers, p, X) = sqrt(inner(B, p, X, X)) LinearAlgebra.norm(B::TangentBundleFibers, p, X) = norm(B.manifold, p, X) -LinearAlgebra.norm(M::VectorSpaceAtPoint, p, X) = norm(M.fiber.manifold, M.point, X) - -function parallel_transport_to!(M::TangentSpaceAtPoint, Y, p, X, q) - return copyto!(M.fiber.manifold, Y, p, X) -end @doc raw""" project(B::VectorBundle, p) @@ -786,14 +264,6 @@ and then projecting the vector $V_p$ to the tangent space $T_{x_p}\mathcal M$. """ project(::VectorBundle, ::Any) -@doc raw""" - project(M::TangentSpaceAtPoint, p) - -Project the point `p` from the tangent space `M`, that is project the vector `p` -tangent at `M.point`. -""" -project(::TangentSpaceAtPoint, ::Any) - function project!(B::VectorBundle, q, p) px, pVx = submanifold_components(B.manifold, p) qx, qVx = submanifold_components(B.manifold, q) @@ -801,9 +271,6 @@ function project!(B::VectorBundle, q, p) project!(B.manifold, qVx, qx, pVx) return q end -function project!(M::TangentSpaceAtPoint, q, p) - return project!(M.fiber.manifold, q, M.point, p) -end @doc raw""" project(B::VectorBundle, p, X) @@ -824,13 +291,6 @@ The projection is calculated by projecting $V_{X,M}$ to tangent space $T_{x_p}\m and then projecting the vector $V_{X,F}$ to the fiber $F$. """ project(::VectorBundle, ::Any, ::Any) -@doc raw""" - project(M::TangentSpaceAtPoint, p, X) - -Project the vector `X` from the tangent space `M`, that is project the vector `X` -tangent at `M.point`. -""" -project(::TangentSpaceAtPoint, ::Any, ::Any) function project!(B::VectorBundle, Y, p, X) px, Vx = submanifold_components(B.manifold, p) @@ -840,16 +300,13 @@ function project!(B::VectorBundle, Y, p, X) project!(B.manifold, VYF, px, VXF) return Y end -function project!(M::TangentSpaceAtPoint, Y, p, X) - return project!(M.fiber.manifold, Y, M.point, X) -end """ - project(B::VectorBundleFibers, p, X) + project(B::BundleFibers, p, X) Project vector `X` from the vector space of type `B.fiber` at point `p`. """ -function project(B::VectorBundleFibers, p, X) +function project(B::BundleFibers, p, X) Y = allocate_result(B, project, p, X) return project!(B, Y, p, X) end @@ -857,41 +314,24 @@ end function project!(B::TangentBundleFibers, Y, p, X) return project!(B.manifold, Y, p, X) end -function project!(B::VectorBundleFibers, Y, p, X) +function project!(B::BundleFibers, Y, p, X) return error( "project! not implemented for vector space family of type $(typeof(B)), output vector of type $(typeof(Y)) and input vector at point $(typeof(p)) with type of w $(typeof(X)).", ) end -function Random.rand!(rng::AbstractRNG, M::VectorBundle, pX; vector_at=nothing) - pXM, pXF = submanifold_components(M.manifold, pX) - if vector_at === nothing - rand!(rng, M.manifold, pXM) - rand!(rng, VectorSpaceAtPoint(M.fiber, pXM), pXF) - else - vector_atM, vector_atF = submanifold_components(M.manifold, vector_at) - rand!(rng, M.manifold, pXM; vector_at=vector_atM) - rand!(rng, VectorSpaceAtPoint(M.fiber, pXM), pXF; vector_at=vector_atF) - end - return pX -end -function Random.rand!(rng::AbstractRNG, M::TangentSpaceAtPoint, X; vector_at=nothing) - rand!(rng, M.fiber.manifold, X; vector_at=M.point) - return X -end - -function _retract(M::VectorBundle, p, X, t::Number, ::VectorBundleProductRetraction) +function _retract(M::VectorBundle, p, X, t::Number, ::FiberBundleProductRetraction) return retract_product(M, p, X, t) end -function _retract!(M::VectorBundle, q, p, X, t::Number, ::VectorBundleProductRetraction) +function _retract!(M::VectorBundle, q, p, X, t::Number, ::FiberBundleProductRetraction) return retract_product!(M, q, p, X, t) end """ retract_product(M::VectorBundle, p, q, t::Number) -Compute the allocating variant of the [`VectorBundleProductRetraction`](@ref), +Compute the allocating variant of the [`FiberBundleProductRetraction`](@ref), which by default allocates and calls `retract_product!`. """ function retract_product(M::VectorBundle, p, X, t::Number) @@ -971,101 +411,25 @@ function retract_sasaki!(B::TangentBundle, q, p, X, t::Number, m::SasakiRetracti return q end -""" - setindex!(p::ProductRepr, val, M::VectorBundle, s::Symbol) - p[M::VectorBundle, s] = val - -Set the element(s) at index `s` of a point `p` on a [`VectorBundle`](@ref) `M` to `val` by -using the symbols `:point` and `:vector` for the base and vector component, respectively. - -!!! note - - The *content* of element of `p` is replaced, not the element itself. -""" -@inline function Base.setindex!(x::ProductRepr, val, M::VectorBundle, s::Symbol) - if s === :point - return copyto!(submanifold_component(M, x, Val(1)), val) - elseif s === :vector - return copyto!(submanifold_component(M, x, Val(2)), val) - else - throw(DomainError(s, "unknown component $s on $M.")) - end -end -""" - setindex!(p::ArrayPartition, val, M::VectorBundle, s::Symbol) - p[M::VectorBundle, s] = val - -Set the element(s) at index `s` of a point `p` on a [`VectorBundle`](@ref) `M` to `val` by -using the symbols `:point` and `:vector` for the base and vector component, respectively. - -!!! note - - The *content* of element of `p` is replaced, not the element itself. -""" -@inline function Base.setindex!(x::ArrayPartition, val, M::VectorBundle, s::Symbol) - if s === :point - return copyto!(x.x[1], val) - elseif s === :vector - return copyto!(x.x[2], val) - else - throw(DomainError(s, "unknown component $s on $M.")) - end -end - -function representation_size(B::VectorBundleFibers{<:TCoTSpaceType}) +function representation_size(B::CotangentBundleFibers) return representation_size(B.manifold) end -function representation_size(B::TangentSpaceAtPoint) - return representation_size(B.fiber.manifold) +function representation_size(B::TangentBundleFibers) + return representation_size(B.manifold) end function Base.show(io::IO, tpt::TensorProductType) return print(io, "TensorProductType(", join(tpt.spaces, ", "), ")") end -function Base.show(io::IO, fiber::VectorBundleFibers) - return print(io, "VectorBundleFibers($(fiber.fiber), $(fiber.manifold))") -end -function Base.show(io::IO, ::MIME"text/plain", vs::VectorSpaceAtPoint) - summary(io, vs) - println(io, "\nFiber:") - pre = " " - sf = sprint(show, "text/plain", vs.fiber; context=io, sizehint=0) - sf = replace(sf, '\n' => "\n$(pre)") - println(io, pre, sf) - println(io, "Base point:") - sp = sprint(show, "text/plain", vs.point; context=io, sizehint=0) - sp = replace(sp, '\n' => "\n$(pre)") - return print(io, pre, sp) +function Base.show(io::IO, vb::VectorBundle) + return print(io, "VectorBundle($(vb.type.fiber), $(vb.manifold))") end -function Base.show(io::IO, ::MIME"text/plain", TpM::TangentSpaceAtPoint) - println(io, "Tangent space to the manifold $(base_manifold(TpM)) at point:") - pre = " " - sp = sprint(show, "text/plain", TpM.point; context=io, sizehint=0) - sp = replace(sp, '\n' => "\n$(pre)") - return print(io, pre, sp) +function Base.show(io::IO, vbf::VectorBundleFibers) + return print(io, "VectorBundleFibers($(vbf.fiber.fiber), $(vbf.manifold))") end -Base.show(io::IO, vb::VectorBundle) = print(io, "VectorBundle($(vb.type), $(vb.manifold))") Base.show(io::IO, vb::TangentBundle) = print(io, "TangentBundle($(vb.manifold))") Base.show(io::IO, vb::CotangentBundle) = print(io, "CotangentBundle($(vb.manifold))") -""" - allocate_result(B::VectorBundleFibers, f, x...) - -Allocates an array for the result of function `f` that is -an element of the vector space of type `B.fiber` on manifold `B.manifold` -and arguments `x...` for implementing the non-modifying operation -using the modifying operation. -""" -@inline function allocate_result(B::VectorBundleFibers, f::TF, x...) where {TF} - if length(x) == 0 - # TODO: this may be incorrect when point and tangent vector representation are - # different for the manifold but there is no easy and generic way around that - return allocate_result(B.manifold, f) - else - T = allocate_result_type(B, f, x) - return allocate(x[1], T) - end -end @inline function allocate_result(B::TangentBundleFibers, f::typeof(zero_vector), x...) return allocate_result(B.manifold, f, x...) end @@ -1074,41 +438,32 @@ end end """ - allocate_result_type(B::VectorBundleFibers, f, args::NTuple{N,Any}) where N + fiber_bundle_transport(fiber::FiberType, M::AbstractManifold) -Return type of element of the array that will represent the result of -function `f` for representing an operation with result in the vector space `fiber` -for manifold `M` on given arguments (passed at a tuple). -""" -@inline function allocate_result_type( - ::VectorBundleFibers, - f::TF, - args::NTuple{N,Any}, -) where {TF,N} - return typeof(mapreduce(eti -> one(number_eltype(eti)), +, args)) -end - -""" - vector_bundle_transport(fiber::VectorSpaceType, M::AbstractManifold) - -Determine the vector tranport used for [`exp`](@ref exp(::VectorBundle, ::Any...)) and -[`log`](@ref log(::VectorBundle, ::Any...)) maps on a vector bundle with vector space type +Determine the vector tranport used for [`exp`](@ref exp(::FiberBundle, ::Any...)) and +[`log`](@ref log(::FiberBundle, ::Any...)) maps on a vector bundle with fiber type `fiber` and manifold `M`. """ -vector_bundle_transport(::VectorSpaceType, ::AbstractManifold) = ParallelTransport() - -function vector_space_dimension(B::VectorBundleFibers) - return vector_space_dimension(B.manifold, B.fiber) -end +fiber_bundle_transport(::VectorSpaceType, ::AbstractManifold) = ParallelTransport() function vector_space_dimension(M::AbstractManifold, V::TensorProductType) dim = 1 for space in V.spaces - dim *= vector_space_dimension(M, space) + dim *= fiber_dimension(M, space) end return dim end +function vector_space_dimension(B::TangentBundleFibers) + return manifold_dimension(B.manifold) +end +function vector_space_dimension(B::CotangentBundleFibers) + return manifold_dimension(B.manifold) +end +function vector_space_dimension(B::VectorBundleFibers) + return vector_space_dimension(B.manifold, B.fiber.fiber) +end + function vector_transport_direction(M::VectorBundle, p, X, d) return vector_transport_direction(M, p, X, d, M.vector_transport) end @@ -1127,14 +482,14 @@ function _vector_transport_direction( p, X, d, - m::VectorBundleProductVectorTransport, + m::FiberBundleProductVectorTransport, ) px, pVx = submanifold_components(M.manifold, p) VXM, VXF = submanifold_components(M.manifold, X) dx, dVx = submanifold_components(M.manifold, d) return ArrayPartition( vector_transport_direction(M.manifold, px, VXM, dx, m.method_point), - vector_transport_direction(M.fiber, px, VXF, dx, m.method_vector), + vector_transport_direction(M.fiber, px, VXF, dx, m.method_fiber), ) end @@ -1148,29 +503,29 @@ function _vector_transport_direction!( p, X, d, - m::VectorBundleProductVectorTransport, + m::FiberBundleProductVectorTransport, ) VYM, VYF = submanifold_components(M.manifold, Y) px, pVx = submanifold_components(M.manifold, p) VXM, VXF = submanifold_components(M.manifold, X) dx, dVx = submanifold_components(M.manifold, d) vector_transport_direction!(M.manifold, VYM, px, VXM, dx, m.method_point), - vector_transport_direction!(M.manifold, VYF, px, VXF, dx, m.method_vector), + vector_transport_direction!(M.manifold, VYF, px, VXF, dx, m.method_fiber), return Y end @doc raw""" - vector_transport_to(M::VectorBundle, p, X, q, m::VectorBundleProductVectorTransport) + vector_transport_to(M::VectorBundle, p, X, q, m::FiberBundleProductVectorTransport) Compute the vector transport the tangent vector `X`at `p` to `q` on the -[`VectorBundle`](@ref) `M` using the [`VectorBundleProductVectorTransport`](@ref) `m`. +[`VectorBundle`](@ref) `M` using the [`FiberBundleProductVectorTransport`](@ref) `m`. """ vector_transport_to( ::VectorBundle, ::Any, ::Any, ::Any, - ::VectorBundleProductVectorTransport, + ::FiberBundleProductVectorTransport, ) function _vector_transport_to( @@ -1178,14 +533,14 @@ function _vector_transport_to( p, X, q, - m::VectorBundleProductVectorTransport, + m::FiberBundleProductVectorTransport, ) px, pVx = submanifold_components(M.manifold, p) VXM, VXF = submanifold_components(M.manifold, X) qx, qVx = submanifold_components(M.manifold, q) return ArrayPartition( vector_transport_to(M.manifold, px, VXM, qx, m.method_point), - vector_transport_to(M.manifold, px, VXF, qx, m.method_vector), + vector_transport_to(M.manifold, px, VXF, qx, m.method_fiber), ) end @@ -1202,26 +557,16 @@ function vector_transport_to!( p, X, q, - m::VectorBundleProductVectorTransport, + m::FiberBundleProductVectorTransport, ) px, pVx = submanifold_components(M.manifold, p) VXM, VXF = submanifold_components(M.manifold, X) VYM, VYF = submanifold_components(M.manifold, Y) qx, qVx = submanifold_components(M.manifold, q) vector_transport_to!(M.manifold, VYM, px, VXM, qx, m.method_point) - vector_transport_to!(M.manifold, VYF, px, VXF, qx, m.method_vector) + vector_transport_to!(M.manifold, VYF, px, VXF, qx, m.method_fiber) return Y end -function vector_transport_to!( - M::TangentSpaceAtPoint, - Y, - p, - X, - q, - m::AbstractVectorTransportMethod, -) - return copyto!(M.fiber.manifold, Y, p, X) -end function vector_transport_to!( M::TangentBundleFibers, Y, @@ -1234,30 +579,13 @@ function vector_transport_to!( return Y end -@inline function Base.view(x::ArrayPartition, M::VectorBundle, s::Symbol) - (s === :point) && return x.x[1] - (s === :vector) && return x.x[2] - throw(DomainError(s, "unknown component $s on $M.")) -end - """ - zero_vector(B::VectorBundleFibers, p) - -Compute the zero vector from the vector space of type `B.fiber` at point `p` -from manifold `B.manifold`. -""" -function zero_vector(B::VectorBundleFibers, p) - X = allocate_result(B, zero_vector, p) - return zero_vector!(B, X, p) -end - -""" - zero_vector!(B::VectorBundleFibers, X, p) + zero_vector!(B::BundleFibers, X, p) Save the zero vector from the vector space of type `B.fiber` at point `p` from manifold `B.manifold` to `X`. """ -function zero_vector!(B::VectorBundleFibers, X, p) +function zero_vector!(B::BundleFibers, X, p) return error( "zero_vector! not implemented for vector space family of type $(typeof(B)).", ) @@ -1265,42 +593,3 @@ end function zero_vector!(B::TangentBundleFibers, X, p) return zero_vector!(B.manifold, X, p) end - -@doc raw""" - zero_vector(B::VectorBundle, p) - -Zero tangent vector at point `p` from the vector bundle `B` -over manifold `B.fiber` (denoted $\mathcal M$). The zero vector belongs to the space $T_{p}B$ - -Notation: - * The point $p = (x_p, V_p)$ where $x_p ∈ \mathcal M$ and $V_p$ belongs to the - fiber $F=Ο€^{-1}(\{x_p\})$ of the vector bundle $B$ where $Ο€$ is the - canonical projection of that vector bundle $B$. - -The zero vector is calculated as - -$\mathbf{0}_{p} = (\mathbf{0}_{x_p}, \mathbf{0}_F)$ - -where $\mathbf{0}_{x_p}$ is the zero tangent vector from $T_{x_p}\mathcal M$ and -$\mathbf{0}_F$ is the zero element of the vector space $F$. -""" -zero_vector(::VectorBundle, ::Any...) - -@doc raw""" - zero_vector(M::TangentSpaceAtPoint, p) - -Zero tangent vector at point `p` from the tangent space `M`, that is the zero tangent vector -at point `M.point`. -""" -zero_vector(::TangentSpaceAtPoint, ::Any...) - -function zero_vector!(B::VectorBundle, X, p) - xp, Vp = submanifold_components(B.manifold, p) - VXM, VXF = submanifold_components(B.manifold, X) - zero_vector!(B.manifold, VXM, xp) - zero_vector!(B.fiber, VXF, Vp) - return X -end -function zero_vector!(M::TangentSpaceAtPoint, X, p) - return zero_vector!(M.fiber.manifold, X, M.point) -end diff --git a/test/manifolds/fiber.jl b/test/manifolds/fiber.jl new file mode 100644 index 0000000000..ce052a0149 --- /dev/null +++ b/test/manifolds/fiber.jl @@ -0,0 +1,44 @@ +include("../utils.jl") + +using RecursiveArrayTools + +struct TestVectorSpaceType <: VectorSpaceType end + +@testset "spaces at point" begin + M = Sphere(2) + @testset "tangent and cotangent space" begin + p = [1.0, 0.0, 0.0] + t_p = TangentSpaceAtPoint(M, p) + t_p2 = TangentSpace(M, p) + @test t_p == t_p2 + ct_p = CotangentSpaceAtPoint(M, p) + t_ps = sprint(show, "text/plain", t_p) + sp = sprint(show, "text/plain", p) + sp = replace(sp, '\n' => "\n ") + t_ps_test = "Tangent space to the manifold $(M) at point:\n $(sp)" + @test t_ps == t_ps_test + @test base_manifold(t_p) == M + @test base_manifold(ct_p) == M + @test t_p.fiber.manifold == M + @test ct_p.fiber.manifold == M + @test t_p.fiber.fiber == Manifolds.TangentFiber + @test ct_p.fiber.fiber == Manifolds.CotangentFiber + @test t_p.point == p + @test ct_p.point == p + @test injectivity_radius(t_p) == Inf + @test representation_size(t_p) == representation_size(M) + X = [0.0, 0.0, 1.0] + @test embed(t_p, X) == X + @test embed(t_p, X, X) == X + # generic vector space at + fiber = VectorBundleFibers(TestVectorSpaceType(), M) + X_p = Manifolds.FiberAtPoint(fiber, p) + X_ps = sprint(show, "text/plain", X_p) + fiber_s = sprint(show, "text/plain", fiber) + X_ps_test = "$(typeof(X_p))\nFiber:\n $(fiber_s)\nBase point:\n $(sp)" + @test X_ps == X_ps_test + @test_throws ErrorException project(fiber, p, X) + @test_throws ErrorException norm(fiber, p, X) + @test_throws ErrorException distance(fiber, p, X, X) + end +end diff --git a/test/manifolds/vector_bundle.jl b/test/manifolds/vector_bundle.jl index b8d8018fd2..2660882ab0 100644 --- a/test/manifolds/vector_bundle.jl +++ b/test/manifolds/vector_bundle.jl @@ -6,8 +6,8 @@ struct TestVectorSpaceType <: VectorSpaceType end @testset "Tangent bundle" begin M = Sphere(2) - m_prod_retr = Manifolds.VectorBundleProductRetraction() - m_prod_invretr = Manifolds.VectorBundleInverseProductRetraction() + m_prod_retr = Manifolds.FiberBundleProductRetraction() + m_prod_invretr = Manifolds.FiberBundleInverseProductRetraction() m_sasaki = SasakiRetraction(5) @testset "Nice access to vector bundle components" begin @@ -62,7 +62,7 @@ struct TestVectorSpaceType <: VectorSpaceType end @test default_inverse_retraction_method(TB) === m_prod_invretr @test default_retraction_method(TB) == m_prod_retr @test default_vector_transport_method(TB) isa - Manifolds.VectorBundleProductVectorTransport + Manifolds.FiberBundleProductVectorTransport CTB = CotangentBundle(M) @test sprint(show, CTB) == "CotangentBundle(Sphere(2, ℝ))" @test sprint(show, VectorBundle(TestVectorSpaceType(), M)) == @@ -145,7 +145,7 @@ struct TestVectorSpaceType <: VectorSpaceType end pts_tb[1], Xir, pts_tb[2], - Manifolds.VectorBundleProductVectorTransport(), + Manifolds.FiberBundleProductVectorTransport(), ) @test is_vector(TB, pts_tb[2], Xir2) @@ -183,41 +183,6 @@ struct TestVectorSpaceType <: VectorSpaceType end VectorBundle{ℝ,Manifolds.CotangentSpaceType,Sphere{2,ℝ}} @test base_manifold(TangentBundle(M)) == M - @testset "spaces at point" begin - p = [1.0, 0.0, 0.0] - t_p = TangentSpaceAtPoint(M, p) - t_p2 = TangentSpace(M, p) - @test t_p == t_p2 - ct_p = CotangentSpaceAtPoint(M, p) - t_ps = sprint(show, "text/plain", t_p) - sp = sprint(show, "text/plain", p) - sp = replace(sp, '\n' => "\n ") - t_ps_test = "Tangent space to the manifold $(M) at point:\n $(sp)" - @test t_ps == t_ps_test - @test base_manifold(t_p) == M - @test base_manifold(ct_p) == M - @test t_p.fiber.manifold == M - @test ct_p.fiber.manifold == M - @test t_p.fiber.fiber == TangentSpace - @test ct_p.fiber.fiber == CotangentSpace - @test t_p.point == p - @test ct_p.point == p - @test injectivity_radius(t_p) == Inf - @test representation_size(t_p) == representation_size(M) - X = [0.0, 0.0, 1.0] - @test embed(t_p, X) == X - @test embed(t_p, X, X) == X - # generic vector space at - fiber = VectorBundleFibers(TestVectorSpaceType(), M) - X_p = VectorSpaceAtPoint(fiber, p) - X_ps = sprint(show, "text/plain", X_p) - fiber_s = sprint(show, "text/plain", fiber) - X_ps_test = "$(typeof(X_p))\nFiber:\n $(fiber_s)\nBase point:\n $(sp)" - @test X_ps == X_ps_test - @test_throws ErrorException project(fiber, p, X) - @test_throws ErrorException norm(fiber, p, X) - @test_throws ErrorException distance(fiber, p, X, X) - end @testset "tensor product" begin TT = Manifolds.TensorProductType(TangentSpace, TangentSpace) @@ -260,7 +225,7 @@ struct TestVectorSpaceType <: VectorSpaceType end ) ppt = ParallelTransport() - tbvt = Manifolds.VectorBundleProductVectorTransport(ppt, ppt) + tbvt = Manifolds.FiberBundleProductVectorTransport(ppt, ppt) @test TangentBundle(M, tbvt).vector_transport === tbvt @test CotangentBundle(M, tbvt).vector_transport === tbvt @test VectorBundle(TangentSpace, M, tbvt).vector_transport === tbvt diff --git a/test/runtests.jl b/test/runtests.jl index f9ff618ed4..455c6499f2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -176,6 +176,7 @@ include("utils.jl") include_test("manifolds/product_manifold.jl") include_test("manifolds/power_manifold.jl") include_test("manifolds/quotient_manifold.jl") + include_test("manifolds/fiber.jl") include_test("manifolds/vector_bundle.jl") include_test("manifolds/graph.jl") diff --git a/tutorials/rigid-body-dynamics.qmd b/tutorials/rigid-body-dynamics.qmd index 0828884419..6b65c5007a 100644 --- a/tutorials/rigid-body-dynamics.qmd +++ b/tutorials/rigid-body-dynamics.qmd @@ -201,7 +201,12 @@ There is, however, one small caveat: `X_X` was brought from the double tangent b So we may use the connection from $\operatorname{SE}(2)$ but we may also use the Levi-Civita connection of the Sasaki metric on $T\operatorname{SE}(2)$. We shall explore this choice later in the tutorial. -For simplicity again we will use a first order forward Euler discretization to solve our ODE (see [technical note](@sec-forward-euler) if you disapprove). +For simplicity again we will use a first order forward Euler discretization to solve our ODE (see `[technical note](@ref sec-forward-euler)`{=commonmark} if you disapprove). +For the initial conditions in our example we will use `p` and `X` from earlier examples and add `X_X`: +```{julia} +X_X = hat(SE2, se2_id, [0.5, -1.0, pi/6]) +``` + ## Technical notes @@ -241,6 +246,6 @@ In this way we get an isomorphism between tangent and cotangent bundles. Note that a generic description of a phase space doesn't require a Riemannian metric. Generic tools come from symplectic geometry which imposes a less rich structure. -### Forward Euler? Really? {#sec-forward-euler} +### `[Forward Euler? Really?](@id sec-forward-euler)`{=commonmark} Yes, for simplicity. For a start. I may try a higher order or a symplectic solver later. You can do that too!