From 4dc88feaedf5a155498d2922797bad98856a234e Mon Sep 17 00:00:00 2001 From: Patrick Massot Date: Thu, 5 Mar 2026 23:59:10 +0100 Subject: [PATCH 01/33] feat: FiberBundle.extend Extend an element of a fiber at a point to a local section. --- .../Geometry/Manifold/VectorBundle/Basic.lean | 2 +- .../VectorBundle/MDifferentiable.lean | 59 +++++++++++++++++++ Mathlib/Topology/FiberBundle/Basic.lean | 20 +++++++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean b/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean index 5a9508233dce83..4b5bb3c3a8d11b 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/Basic.lean @@ -139,7 +139,7 @@ protected theorem FiberBundle.extChartAt (x : TotalSpace F E) : extChartAt (IB.prod 𝓘(𝕜, F)) x = (trivializationAt F E x.proj).toPartialEquiv ≫ (extChartAt IB x.proj).prod (PartialEquiv.refl F) := by - simp_rw [extChartAt, FiberBundle.chartedSpace_chartAt, extend] + simp_rw [extChartAt, FiberBundle.chartedSpace_chartAt, OpenPartialHomeomorph.extend] simp only [PartialEquiv.trans_assoc, mfld_simps] -- Porting note: should not be needed rw [PartialEquiv.prod_trans, PartialEquiv.refl_trans] diff --git a/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean b/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean index b5a94c91b7bf3f..7272b00faa9d64 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean @@ -665,3 +665,62 @@ lemma MDifferentiableAt.clm_apply_of_inCoordinates exact MDifferentiableWithinAt.clm_apply_of_inCoordinates hϕ hv hb₂ end + +section extend + +namespace FiberBundle +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] + (F : Type*) [NormedAddCommGroup F] + {V : M → Type*} [TopologicalSpace (TotalSpace F V)] [(x : M) → AddCommGroup (V x)] + [(x : M) → TopologicalSpace (V x)] + [FiberBundle F V] [NormedSpace 𝕜 F] {k : WithTop ℕ∞} + +lemma exists_contMDiffOn_extend [(x : M) → Module 𝕜 (V x)] [VectorBundle 𝕜 F V] + [ContMDiffVectorBundle k F V I] {x₀ : M} (σ₀ : V x₀) : + ∃ s ∈ 𝓝 x₀, ContMDiffOn I (I.prod 𝓘(𝕜, F)) k (T% (extend F σ₀)) s := by + set t := trivializationAt F V x₀ + refine ⟨t.baseSet, ?_, ?_⟩ + · refine t.open_baseSet.mem_nhds ?_ + exact FiberBundle.mem_baseSet_trivializationAt' x₀ + suffices ContMDiffOn I 𝓘(𝕜, F) k (fun x ↦ (t ⟨x, extend F σ₀ x⟩).2) t.baseSet by + intro x hx + rw [t.contMDiffWithinAt_section _ hx] + exact this x hx + let w : F := (t ⟨x₀, σ₀⟩).2 + have : ContMDiffOn I 𝓘(𝕜, F) k (fun x_1 ↦ w) t.baseSet := contMDiffOn_const + refine this.congr ?_ + intro x hx + dsimp only + unfold extend + rw [t.mk_symm hx, t.apply_symm_apply' hx] + +lemma contMDiffAt_extend' {x : M} (σ₀ : V x) : + CMDiffAt k (T% (extend F σ₀)) x := by + rw [contMDiffAt_section] + set t := trivializationAt F V x + let w : F := (t ⟨x, σ₀⟩).2 + have : CMDiffAt k (fun (_x : M) ↦ w) x := contMDiffAt_const + refine this.congr_of_eventuallyEq ?_ + apply eventually_nhds_iff.mpr + refine ⟨t.baseSet, ?_, t.open_baseSet, ?_⟩ + · intro x hx + dsimp only + unfold extend + simp [t, hx, w] + · exact FiberBundle.mem_baseSet_trivializationAt' x + +lemma exists_mdifferentiableOn_extend [IsManifold I 1 M] [∀ x, Module 𝕜 (V x)] [VectorBundle 𝕜 F V] + [ContMDiffVectorBundle 1 F V I] {x₀ : M} (σ₀ : V x₀) : + ∃ s ∈ 𝓝 x₀, MDifferentiableOn I (I.prod 𝓘(𝕜, F)) (T% (extend F σ₀)) s := by + obtain ⟨s, hs, hsσ⟩ := exists_contMDiffOn_extend (k := 1) I F σ₀ + exact ⟨s, hs, hsσ.mdifferentiableOn one_ne_zero⟩ + +lemma mdifferentiableAt_extend [IsManifold I 1 M] {x : M} (σ₀ : V x) : + MDiffAt (T% (extend F σ₀)) x := + (contMDiffAt_extend' (k := 1) I F σ₀).mdifferentiableAt one_ne_zero + +end FiberBundle +end extend diff --git a/Mathlib/Topology/FiberBundle/Basic.lean b/Mathlib/Topology/FiberBundle/Basic.lean index 7fa939fc53336e..84c4dcfa472b8c 100644 --- a/Mathlib/Topology/FiberBundle/Basic.lean +++ b/Mathlib/Topology/FiberBundle/Basic.lean @@ -856,3 +856,23 @@ theorem continuousOn_of_comp_right {X : Type*} [TopologicalSpace X] {f : TotalSp exact a.mem_base_pretrivializationAt z.proj end FiberPrebundle + +namespace FiberBundle +section extend + +variable {E} [(x : B) → Zero (E x)] [TopologicalSpace (TotalSpace F E)] [FiberBundle F E] + +/-- Extend a vector `v ∈ V x` to a section of the bundle `V`, whose value at `x` is `v`. +The details of the extension are mostly unspecified: for covariant derivatives, the value of +`s` at points other than `x` will not matter (except for shorter proofs). +-/ +noncomputable def extend {x : B} (v₀ : E x) (x' : B) : E x' := + letI t := trivializationAt F E x + letI w : F := (t ⟨x, v₀⟩).2 + t.symm x' w + +@[simp] lemma extend_apply_self {x : B} (v : E x) : extend F v x = v := by + simp [extend, FiberBundle.mem_baseSet_trivializationAt' x] + +end extend +end FiberBundle From 419199f5f6f8f2457c2cd93dc3f02a5ffca874ef Mon Sep 17 00:00:00 2001 From: Patrick Massot Date: Fri, 6 Mar 2026 09:40:14 +0100 Subject: [PATCH 02/33] Lint --- Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean b/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean index 7272b00faa9d64..46eaf6002c3117 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean @@ -712,15 +712,16 @@ lemma contMDiffAt_extend' {x : M} (σ₀ : V x) : simp [t, hx, w] · exact FiberBundle.mem_baseSet_trivializationAt' x -lemma exists_mdifferentiableOn_extend [IsManifold I 1 M] [∀ x, Module 𝕜 (V x)] [VectorBundle 𝕜 F V] +lemma exists_mdifferentiableOn_extend [∀ x, Module 𝕜 (V x)] [VectorBundle 𝕜 F V] [ContMDiffVectorBundle 1 F V I] {x₀ : M} (σ₀ : V x₀) : ∃ s ∈ 𝓝 x₀, MDifferentiableOn I (I.prod 𝓘(𝕜, F)) (T% (extend F σ₀)) s := by obtain ⟨s, hs, hsσ⟩ := exists_contMDiffOn_extend (k := 1) I F σ₀ exact ⟨s, hs, hsσ.mdifferentiableOn one_ne_zero⟩ -lemma mdifferentiableAt_extend [IsManifold I 1 M] {x : M} (σ₀ : V x) : +lemma mdifferentiableAt_extend {x : M} (σ₀ : V x) : MDiffAt (T% (extend F σ₀)) x := (contMDiffAt_extend' (k := 1) I F σ₀).mdifferentiableAt one_ne_zero end FiberBundle end extend + From 9cc0d58b66c6da4b4119afec3df4d63babde439f Mon Sep 17 00:00:00 2001 From: Patrick Massot Date: Fri, 6 Mar 2026 09:43:28 +0100 Subject: [PATCH 03/33] Some cleanup suggested by Michael --- Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean b/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean index 46eaf6002c3117..3175de88ae7a3f 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean @@ -693,7 +693,6 @@ lemma exists_contMDiffOn_extend [(x : M) → Module 𝕜 (V x)] [VectorBundle have : ContMDiffOn I 𝓘(𝕜, F) k (fun x_1 ↦ w) t.baseSet := contMDiffOn_const refine this.congr ?_ intro x hx - dsimp only unfold extend rw [t.mk_symm hx, t.apply_symm_apply' hx] @@ -707,9 +706,7 @@ lemma contMDiffAt_extend' {x : M} (σ₀ : V x) : apply eventually_nhds_iff.mpr refine ⟨t.baseSet, ?_, t.open_baseSet, ?_⟩ · intro x hx - dsimp only - unfold extend - simp [t, hx, w] + simp [extend, t, hx, w] · exact FiberBundle.mem_baseSet_trivializationAt' x lemma exists_mdifferentiableOn_extend [∀ x, Module 𝕜 (V x)] [VectorBundle 𝕜 F V] From a412b42329ac6d5fb877f3fa726bff738572be78 Mon Sep 17 00:00:00 2001 From: Patrick Massot Date: Fri, 6 Mar 2026 11:15:21 +0100 Subject: [PATCH 04/33] lint --- Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean | 1 - 1 file changed, 1 deletion(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean b/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean index 3175de88ae7a3f..ba49ea51dd3f52 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean @@ -721,4 +721,3 @@ lemma mdifferentiableAt_extend {x : M} (σ₀ : V x) : end FiberBundle end extend - From 54895bae09d68de67e9f1d42a3a06f7e62a1043a Mon Sep 17 00:00:00 2001 From: Michael Rothgang Date: Fri, 6 Mar 2026 10:38:22 +0000 Subject: [PATCH 05/33] Golfs and docs --- .../Geometry/Manifold/VectorBundle/MDifferentiable.lean | 7 ++----- Mathlib/Topology/FiberBundle/Basic.lean | 1 + 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean b/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean index ba49ea51dd3f52..aec2e6a784de3f 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/MDifferentiable.lean @@ -690,11 +690,8 @@ lemma exists_contMDiffOn_extend [(x : M) → Module 𝕜 (V x)] [VectorBundle rw [t.contMDiffWithinAt_section _ hx] exact this x hx let w : F := (t ⟨x₀, σ₀⟩).2 - have : ContMDiffOn I 𝓘(𝕜, F) k (fun x_1 ↦ w) t.baseSet := contMDiffOn_const - refine this.congr ?_ - intro x hx - unfold extend - rw [t.mk_symm hx, t.apply_symm_apply' hx] + have : ContMDiffOn I 𝓘(𝕜, F) k (fun _x ↦ w) t.baseSet := contMDiffOn_const + exact this.congr (fun x hx ↦ by simp [extend, t, w, hx]) lemma contMDiffAt_extend' {x : M} (σ₀ : V x) : CMDiffAt k (T% (extend F σ₀)) x := by diff --git a/Mathlib/Topology/FiberBundle/Basic.lean b/Mathlib/Topology/FiberBundle/Basic.lean index 84c4dcfa472b8c..5930fa04c7b7a6 100644 --- a/Mathlib/Topology/FiberBundle/Basic.lean +++ b/Mathlib/Topology/FiberBundle/Basic.lean @@ -869,6 +869,7 @@ The details of the extension are mostly unspecified: for covariant derivatives, noncomputable def extend {x : B} (v₀ : E x) (x' : B) : E x' := letI t := trivializationAt F E x letI w : F := (t ⟨x, v₀⟩).2 + -- TODO: use the `funToSec` helper from #36036 once available t.symm x' w @[simp] lemma extend_apply_self {x : B} (v : E x) : extend F v x = v := by From 9c8186dec7fb860b4c66be7f0ed9f4d097f5d398 Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:07:13 +0000 Subject: [PATCH 06/33] tensoriality --- .../Manifold/VectorBundle/Tensoriality.lean | 290 ++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 Mathlib/Geometry/Manifold/VectorBundle/Tensoriality.lean diff --git a/Mathlib/Geometry/Manifold/VectorBundle/Tensoriality.lean b/Mathlib/Geometry/Manifold/VectorBundle/Tensoriality.lean new file mode 100644 index 00000000000000..9b19b5306f8811 --- /dev/null +++ b/Mathlib/Geometry/Manifold/VectorBundle/Tensoriality.lean @@ -0,0 +1,290 @@ +/- +Copyright (c) 2025 Patrick Massot. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Patrick Massot, Michael Rothgang, Heather Macbeth +-/ +module + +public import Mathlib.Geometry.Manifold.VectorBundle.MDifferentiable +public import Mathlib.Topology.Algebra.Module.FiniteDimensionBilinear +import Mathlib.Geometry.Manifold.Notation +import Mathlib.Geometry.Manifold.VectorBundle.LocalFrame + +/-! +# The tensoriality criterion + +Given vector bundles `V` and `W` over a manifold `M`, one can construct a section of the hom-bundle +`Π x, V x →L[𝕜] W x` from a *tensorial* operation sending sections of `V` to sections of `W`. +This file provides this construction. + +In fact, we define tensoriality, and provide the above criterion, in slightly greater generality: +for operations sending sections of `V` to a vector space `A` (which in the above application is the +fibre `W x`), the construction produces a continuous linear map `V x →L[𝕜] A`. + +## Main definitions + +* `TensorialAt`: Propositional structure stating that an operation on sections of a vector bundle + `V` is tensorial. + +* `TensorialAt.mkHom`: An operation on sections of `V` which is tensorial at `x` defines a + continuous linear map out of `V x`. + +* `TensorialAt.mkHom₂`: An operation on sections of `V` and `V'` which is tensorial at `x` in both + arguments defines a continuous bilinear map out of `V x` and `V' x`. + +-/ +open Bundle FiberBundle Topology Module + +open scoped Manifold ContDiff + +@[expose] public section + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] + +variable + (F : Type*) [NormedAddCommGroup F] [NormedSpace 𝕜 F] + {V : M → Type*} [TopologicalSpace (TotalSpace F V)] + [∀ x, AddCommGroup (V x)] [∀ x, Module 𝕜 (V x)] + [∀ x : M, TopologicalSpace (V x)] + [FiberBundle F V] + +variable + (F' : Type*) [NormedAddCommGroup F'] [NormedSpace 𝕜 F'] + {V' : M → Type*} [TopologicalSpace (TotalSpace F' V')] + [∀ x, AddCommGroup (V' x)] [∀ x, Module 𝕜 (V' x)] [∀ x : M, TopologicalSpace (V' x)] + [FiberBundle F' V'] + +variable {A : Type*} [AddCommGroup A] [Module 𝕜 A] + +/-- An operation `Φ` on sections of a vector bundle `V` over `M` is *tensorial* at `x : M`, if it +respects addition and scalar multiplication by germs of diffentiable functions at `f`. -/ +structure TensorialAt (Φ : (Π x : M, V x) → A) (x : M) : Prop where + smul : ∀ {f : M → 𝕜} {σ : Π x : M, V x}, MDiffAt f x → MDiffAt (T% σ) x → Φ (f • σ) = f x • Φ σ + add : ∀ {σ σ'}, MDiffAt (T% σ) x → MDiffAt (T% σ') x → Φ (σ + σ') = Φ σ + Φ σ' + +variable {Φ : (Π x : M, V x) → A} {x : M} +variable {I F F'} + +namespace TensorialAt + +/-- If the operation `Φ` on sections of a vector bundle `V` is tensorial at `x`, then it depends +only on the germ of the section at `x`. + +This is later superseded by `TensorialAt.pointwise`, showing that `Φ` depends only on the value at +`x` itself. -/ +protected theorem «local» (hΦ : TensorialAt I F Φ x) {σ σ' : Π x : M, V x} + (hσ : MDiffAt (T% σ) x) (hσ' : MDiffAt (T% σ') x) (hσσ' : ∀ᶠ x' in 𝓝 x, σ x' = σ' x') : + Φ σ = Φ σ' := by + classical + rw [eventually_nhds_iff] at hσσ' + -- Introduce the indicator function of a neighbourhood `t` of `x` on which equality holds, + -- and cut off the two sections `σ` and `σ'` using this indicator function. + obtain ⟨t, htσσ', ht, hxt⟩ := hσσ' + let ψ (x' : M) : 𝕜 := if x' ∈ t then 1 else 0 + have hψx : ψ x = 1 := by simp [ψ, hxt] + have (x' : M) : (ψ • σ) x' = (ψ • σ') x' := by + dsimp [ψ] + split_ifs with hx't + · simpa using htσσ' _ hx't + · simp + have hψ' : MDiffAt ψ x := by + have : MDiffAt (fun (_x : M) ↦ (1 : 𝕜)) x := mdifferentiableAt_const + refine this.congr_of_eventuallyEq ?_ + apply eventually_nhds_iff.mpr + exact ⟨t, by simp [ψ], ht, hxt⟩ + calc Φ σ + _ = Φ (ψ • σ) := by simp [hΦ.smul hψ' hσ, hψx] + _ = Φ (ψ • σ') := by rw [funext this] + _ = Φ σ' := by simp [hΦ.smul hψ' hσ', hψx] + +variable [VectorBundle 𝕜 F V] [VectorBundle 𝕜 F' V'] + +/-- A tensorial operation on sections of a vector bundle respects sums (since it respects binary +addition). -/ +theorem sum (hΦ : TensorialAt I F Φ x) {ι : Type*} {s : Finset ι} (σ : ι → Π x : M, V x) + (hσ : ∀ i, MDiffAt (T% (σ i)) x) : + Φ (fun x' ↦ ∑ i ∈ s, σ i x') = ∑ i ∈ s, Φ (σ i) := by + classical + induction s using Finset.induction_on with + | empty => + simp only [Finset.sum_empty] + have h₁ : MDiffAt (fun x' : M ↦ (0 : 𝕜)) x := mdifferentiableAt_const + rw [show (fun x' : M ↦ (0 : V x')) = (0 : M → 𝕜) • fun x' ↦ 0 by simp; rfl, hΦ.smul] + · simp + · exact h₁ + · exact mdifferentiable_zeroSection .. + | insert a s ha h => + change Φ (fun x' : M ↦ ∑ i ∈ (insert a s : Finset ι), σ i x') = _ + simp only [Finset.sum_insert ha, ← h] + exact hΦ.add (hσ a) (.sum_section hσ) + +variable [CompleteSpace 𝕜] [FiniteDimensional 𝕜 F] [FiniteDimensional 𝕜 F'] + [ContMDiffVectorBundle 1 F V I] [ContMDiffVectorBundle 1 F' V' I] + +/-- If the operation `Φ` on sections of a vector bundle `V` is tensorial at `x`, then it depends +only on the value of the section at `x`. -/ +lemma pointwise (hΦ : TensorialAt I F Φ x) {σ σ' : Π x : M, V x} + (hσ : MDiffAt (T% σ) x) (hσ' : MDiffAt (T% σ') x) (hσσ' : σ x = σ' x) : + Φ σ = Φ σ' := by + -- Select a local frame `s` for the bundle `V` near `x`, + -- and let `c` be the family of linear maps evaluating the coefficients of a section relative to + -- this frame + let t := trivializationAt F V x + have x_mem : x ∈ t.baseSet := FiberBundle.mem_baseSet_trivializationAt F V x + let b := Basis.ofVectorSpace 𝕜 F + let s := t.localFrame b + let c := t.localFrame_coeff I b + have hs (i) : MDiffAt (T% (s i)) x := + (contMDiffAt_localFrame_of_mem 1 _ b i x_mem).mdifferentiableAt (by simp) + have hc {σ : (x : M) → V x} (hσ : MDiffAt (T% σ) x) (i) : + MDiffAt (LinearMap.piApply (c i) σ) x := + mdifferentiableAt_localFrame_coeff b x_mem hσ i + -- By the locality of the operation `(Φ · x)`, its value on `σ` agrees with the value of `Φ` on + -- the expansion of `σ` into coefficients relative to the frame. + have hΦ_eq {σ : (x : M) → V x} (hσ : MDiffAt (T% σ) x) : + Φ σ = Φ (fun x' ↦ ∑ i, c i x' (σ x') • s i x') := + hΦ.local hσ + (.sum_section fun i ↦ (hc hσ i).smul_section (hs i)) + (t.eventually_eq_localFrame_sum_coeff_smul b x_mem) + -- Now evaluate using the tensoriality properties. + rw [hΦ_eq hσ, hΦ_eq hσ', hΦ.sum, hΦ.sum] + · congr! 1 with i + calc Φ ((LinearMap.piApply (c i) σ) • (s i)) + = c i x (σ x) • Φ (s i) := hΦ.smul (hc hσ i) (hs i) + _ = c i x (σ' x) • Φ (s i) := by rw [hσσ'] + _ = Φ ((LinearMap.piApply (c i) σ') • (s i)) := + hΦ.smul (hc hσ' i) (hs i) |>.symm + · exact fun i ↦ (hc hσ' i).smul_section (hs i) + · exact fun i ↦ (hc hσ i).smul_section (hs i) + +/-- If the operation `Φ` on sections of vector bundles `V` and `V'` is tensorial at `x` in each +argument, then it depends only on the value of the sections at `x`. -/ +lemma pointwise₂ + {Φ : (Π x : M, V x) → (Π x : M, V' x) → A} {x} + (hΦ₁ : ∀ τ, MDiffAt (T% τ) x → TensorialAt I F (Φ · τ) x) + (hΦ₂ : ∀ σ, MDiffAt (T% σ) x → TensorialAt I F' (Φ σ ·) x) + {σ σ' : Π x : M, V x} {τ τ' : Π x : M, V' x} + (hσ : MDiffAt (T% σ) x) (hσ' : MDiffAt (T% σ') x) + (hτ : MDiffAt (T% τ) x) (hτ' : MDiffAt (T% τ') x) + (hσσ' : σ x = σ' x) (hττ' : τ x = τ' x) : + Φ σ τ = Φ σ' τ' := by + trans Φ σ' τ + · exact (hΦ₁ _ hτ).pointwise hσ hσ' hσσ' + · exact (hΦ₂ _ hσ').pointwise hτ hτ' hττ' + +variable + -- TODO prove transport lemmas `ContinuousLinearEquiv.IsTopologicalAddGroup` and + -- `ContinuousLinearEquiv.continuousSMul`, then the next four hypotheses can be removed + -- (and the appropriate instances constructed in the proof of `TensorialAt.mkHom` by transport + -- from the model fibre.) + [∀ x, IsTopologicalAddGroup (V x)] [∀ x, ContinuousSMul 𝕜 (V x)] + [∀ x, IsTopologicalAddGroup (V' x)] [∀ x, ContinuousSMul 𝕜 (V' x)] + [TopologicalSpace A] [IsTopologicalAddGroup A] [ContinuousSMul 𝕜 A] + +/-- Given an `A`-valued operation `Φ` on sections of a vector bundle `V` which is tensorial at `x`, +the construction `TensorialAt.mkHom` provides the associated continuous linear map `V x →L[𝕜] A`. -/ +noncomputable def mkHom + -- `Φ` and `x` explicit to make it easier to generate the side condition at point of use + (Φ : (Π x : M, V x) → A) (x : M) (hΦ : TensorialAt I F (Φ) x) : + V x →L[𝕜] A := + let Ψ : V x ≃L[𝕜] F := (trivializationAt F V x).continuousLinearEquivAt 𝕜 x + (FiberBundle.mem_baseSet_trivializationAt' x) + have : T2Space (V x) := Ψ.symm.toHomeomorph.t2Space + have : FiniteDimensional 𝕜 (V x) := Ψ.symm.toLinearEquiv.finiteDimensional + LinearMap.toContinuousLinearMap { + toFun v := Φ (extend F v) + map_add' v₁ v₂ := by + rw [← hΦ.add (mdifferentiableAt_extend ..) (mdifferentiableAt_extend ..)] + apply hΦ.pointwise (mdifferentiableAt_extend ..) <| + mdifferentiableAt_add_section (mdifferentiableAt_extend ..) (mdifferentiableAt_extend ..) + simp + map_smul' c v := by + dsimp + rw [← hΦ.smul (f := fun _ ↦ c) (mdifferentiable_const ..) (mdifferentiableAt_extend ..)] + apply hΦ.pointwise (mdifferentiableAt_extend ..) <| + mdifferentiableAt_const.smul_section (mdifferentiableAt_extend ..) + simp } + +theorem mkHom_apply {Φ : (Π x : M, V x) → A} {x} (hΦ : TensorialAt I F (Φ ·) x) + {σ : Π x : M, V x} (hσ : MDiffAt (T% σ) x) : + mkHom Φ x hΦ (σ x) = Φ σ := + hΦ.pointwise (mdifferentiableAt_extend ..) hσ (by simp) + +theorem mkHom_apply_eq_extend {Φ : (Π x : M, V x) → A} {x} (hΦ : TensorialAt I F Φ x) (σ : V x) : + mkHom Φ x hΦ σ = Φ (extend F σ) := + rfl + +/-- Given an `A`-valued operation `Φ` on sections of vector bundles `V` and `V'` which is tensorial +at `x` in each argument, the construction `TensorialAt.mkHom₂` provides the associated continuous +linear map `V x →L[𝕜] V' x →L[𝕜] A`. -/ +noncomputable def mkHom₂ + -- `Φ` and `x` explicit to make it easier to generate the side conditions at point of use + (Φ : (Π x : M, V x) → (Π x : M, V' x) → A) (x : M) + (hΦ₁ : ∀ τ, MDiffAt (T% τ) x → TensorialAt I F (Φ · τ) x) + (hΦ₂ : ∀ σ, MDiffAt (T% σ) x → TensorialAt I F' (Φ σ) x) : + V x →L[𝕜] V' x →L[𝕜] A := + let Ψ : V x ≃L[𝕜] F := (trivializationAt F V x).continuousLinearEquivAt 𝕜 x + (FiberBundle.mem_baseSet_trivializationAt' x) + have : T2Space (V x) := Ψ.symm.toHomeomorph.t2Space + have : FiniteDimensional 𝕜 (V x) := Ψ.symm.toLinearEquiv.finiteDimensional + let Ψ' : V' x ≃L[𝕜] F' := (trivializationAt F' V' x).continuousLinearEquivAt 𝕜 x + (FiberBundle.mem_baseSet_trivializationAt' x) + have : T2Space (V' x) := Ψ'.symm.toHomeomorph.t2Space + have : FiniteDimensional 𝕜 (V' x) := Ψ'.symm.toLinearEquiv.finiteDimensional + have H : IsBilinearMap 𝕜 + (fun (v : V x) (w : V' x) ↦ Φ (extend F v) (extend F' w)) := + { add_left v₁ v₂ w := by + rw [← (hΦ₁ _ (mdifferentiableAt_extend ..)).add (mdifferentiableAt_extend ..) + (mdifferentiableAt_extend ..)] + apply TensorialAt.pointwise₂ hΦ₁ hΦ₂ (mdifferentiableAt_extend ..) _ + (mdifferentiableAt_extend ..) (mdifferentiableAt_extend ..) _ rfl + · exact mdifferentiableAt_add_section (mdifferentiableAt_extend ..) + (mdifferentiableAt_extend ..) + · simp + smul_left c v w := by + rw [← (hΦ₁ _ (mdifferentiableAt_extend ..)).smul (f := fun _ ↦ c) (mdifferentiable_const ..) + (mdifferentiableAt_extend ..)] + apply TensorialAt.pointwise₂ hΦ₁ hΦ₂ (mdifferentiableAt_extend ..) + (mdifferentiableAt_const.smul_section (mdifferentiableAt_extend ..)) + (mdifferentiableAt_extend ..) (mdifferentiableAt_extend ..) + · simp + · rfl + add_right v w₁ w₂ := by + rw [← (hΦ₂ _ (mdifferentiableAt_extend ..)).add (mdifferentiableAt_extend ..) + (mdifferentiableAt_extend ..)] + apply TensorialAt.pointwise₂ hΦ₁ hΦ₂ (mdifferentiableAt_extend ..) + (mdifferentiableAt_extend ..) (mdifferentiableAt_extend ..) <| + mdifferentiableAt_add_section (mdifferentiableAt_extend ..) (mdifferentiableAt_extend ..) + · rfl + · simp + smul_right c v w := by + rw [← (hΦ₂ _ (mdifferentiableAt_extend ..)).smul (f := fun _ ↦ c) (mdifferentiable_const ..) + (mdifferentiableAt_extend ..)] + apply TensorialAt.pointwise₂ hΦ₁ hΦ₂ (mdifferentiableAt_extend ..) + (mdifferentiableAt_extend ..) (mdifferentiableAt_extend ..) <| + mdifferentiableAt_const.smul_section (mdifferentiableAt_extend ..) + · rfl + · simp } + H.toLinearMap.toContinuousBilinearMap + +theorem mkHom₂_apply + {Φ : (Π x : M, V x) → (Π x : M, V' x) → A} {x} + (hΦ₁ : ∀ τ, MDiffAt (T% τ) x → TensorialAt I F (Φ · τ) x) + (hΦ₂ : ∀ σ, MDiffAt (T% σ) x → TensorialAt I F' (Φ σ) x) + {σ : Π x : M, V x} (hσ : MDiffAt (T% σ) x) {τ : Π x : M, V' x} (hτ : MDiffAt (T% τ) x) : + mkHom₂ Φ x hΦ₁ hΦ₂ (σ x) (τ x) = Φ σ τ := + TensorialAt.pointwise₂ hΦ₁ hΦ₂ (mdifferentiableAt_extend ..) hσ (mdifferentiableAt_extend ..) hτ + (by simp) (by simp) + +theorem mkHom₂_apply_eq_extend + {Φ : (Π x : M, V x) → (Π x : M, V' x) → A} {x} + (hΦ₁ : ∀ τ, MDiffAt (T% τ) x → TensorialAt I F (Φ · τ) x) + (hΦ₂ : ∀ σ, MDiffAt (T% σ) x → TensorialAt I F' (Φ σ) x) + (σ : V x) (τ : V' x) : + mkHom₂ Φ x hΦ₁ hΦ₂ σ τ = Φ (extend F σ) (extend F' τ) := + rfl + +end TensorialAt From 72147d507c6b7fef185a19c8d2340fe50aa1b7db Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:40:42 +0000 Subject: [PATCH 07/33] fix imports --- Mathlib.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/Mathlib.lean b/Mathlib.lean index c9ce6709d155fb..486171780c0cd6 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4424,6 +4424,7 @@ public import Mathlib.Geometry.Manifold.VectorBundle.Pullback public import Mathlib.Geometry.Manifold.VectorBundle.Riemannian public import Mathlib.Geometry.Manifold.VectorBundle.SmoothSection public import Mathlib.Geometry.Manifold.VectorBundle.Tangent +public import Mathlib.Geometry.Manifold.VectorBundle.Tensoriality public import Mathlib.Geometry.Manifold.VectorField.LieBracket public import Mathlib.Geometry.Manifold.VectorField.Pullback public import Mathlib.Geometry.Manifold.WhitneyEmbedding From efdc73f50b66e214e571ed3ff56ad7331cc731fb Mon Sep 17 00:00:00 2001 From: Patrick Massot Date: Fri, 6 Mar 2026 17:21:12 +0100 Subject: [PATCH 08/33] feat: Covariant derivatives on a vector bundle --- Mathlib.lean | 2 + .../Geometry/Manifold/IsManifold/Basic.lean | 10 + Mathlib/Geometry/Manifold/MfDerivSMul.lean | 81 +++ .../CovariantDerivative/Basic.lean | 481 ++++++++++++++++++ 4 files changed, 574 insertions(+) create mode 100644 Mathlib/Geometry/Manifold/MfDerivSMul.lean create mode 100644 Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Basic.lean diff --git a/Mathlib.lean b/Mathlib.lean index 486171780c0cd6..beaa1f520c3ce4 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4404,6 +4404,7 @@ public import Mathlib.Geometry.Manifold.MFDeriv.SpecificFunctions public import Mathlib.Geometry.Manifold.MFDeriv.Tangent public import Mathlib.Geometry.Manifold.MFDeriv.UniqueDifferential public import Mathlib.Geometry.Manifold.Metrizable +public import Mathlib.Geometry.Manifold.MfDerivSMul public import Mathlib.Geometry.Manifold.Notation public import Mathlib.Geometry.Manifold.PartitionOfUnity public import Mathlib.Geometry.Manifold.PoincareConjecture @@ -4416,6 +4417,7 @@ public import Mathlib.Geometry.Manifold.SmoothApprox public import Mathlib.Geometry.Manifold.SmoothEmbedding public import Mathlib.Geometry.Manifold.StructureGroupoid public import Mathlib.Geometry.Manifold.VectorBundle.Basic +public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Basic public import Mathlib.Geometry.Manifold.VectorBundle.FiberwiseLinear public import Mathlib.Geometry.Manifold.VectorBundle.Hom public import Mathlib.Geometry.Manifold.VectorBundle.LocalFrame diff --git a/Mathlib/Geometry/Manifold/IsManifold/Basic.lean b/Mathlib/Geometry/Manifold/IsManifold/Basic.lean index ac045c3fe72876..b27fd1c76a3ce7 100644 --- a/Mathlib/Geometry/Manifold/IsManifold/Basic.lean +++ b/Mathlib/Geometry/Manifold/IsManifold/Basic.lean @@ -1061,6 +1061,16 @@ variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners 𝕜 E H) {M : Type*} [TopologicalSpace M] [ChartedSpace H M] {x : M} +set_option backward.isDefEq.respectTransparency false in +/-- Identifying the tangent space at a normed space with the normed space itself. +This canonical identification (which, in mathlib, is implemented using an abuse of definitional +equality) is very prevalent in a number of places: this device allows making it explicit. -/ +def NormedSpace.fromTangentSpace (v : E) : TangentSpace 𝓘(𝕜, E) v ≃L[𝕜] E where + toFun v := v + invFun v := v + map_add' := by simp + map_smul' := by simp + instance : Inhabited (TangentSpace I x) := ⟨0⟩ variable (M) in diff --git a/Mathlib/Geometry/Manifold/MfDerivSMul.lean b/Mathlib/Geometry/Manifold/MfDerivSMul.lean new file mode 100644 index 00000000000000..5c21e2705c6d62 --- /dev/null +++ b/Mathlib/Geometry/Manifold/MfDerivSMul.lean @@ -0,0 +1,81 @@ +/- +Copyright (c) 2025 Patrick Massot. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Patrick Massot, Michael Rothgang +-/ +module + +public import Mathlib.Geometry.Manifold.MFDeriv.Atlas +public import Mathlib.Geometry.Manifold.MFDeriv.NormedSpace +public import Mathlib.Geometry.Manifold.Notation + +/-! +# Auxiliary lemmas about mfderiv and scalar multiplication + +-/ + +open Bundle Filter Module Topology Set +open scoped Bundle Manifold ContDiff + +@[expose] public section mfderiv + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] + {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] + +set_option backward.isDefEq.respectTransparency false in +-- cleaned up and PRed in #34262 +lemma mfderiv_const_smul (s : M → F) {x : M} (a : 𝕜) (v : TangentSpace I x) : + mfderiv% (a • s) x v = a • mfderiv% s x v := by + by_cases hs : MDiffAt s x + · have hs' := hs.const_smul a + suffices + (fderivWithin 𝕜 ((a • s) ∘ (chartAt H x).symm ∘ I.symm) (range I) (I ((chartAt H x) x))) v = + a • (fderivWithin 𝕜 (s ∘ (chartAt H x).symm ∘ I.symm) (range I) + (I ((chartAt H x) x))) v by simpa [mfderiv, hs, hs'] + change fderivWithin 𝕜 (a • (s ∘ ↑(chartAt H x).symm ∘ ↑I.symm)) _ _ _ = _ + rw [fderivWithin_const_smul_field _ I.uniqueDiffWithinAt_image ] + rfl + · by_cases ha : a = 0 + · have : a • s = 0 := by ext; simp [ha] + rw [this, ha] + change (mfderiv I 𝓘(𝕜, F) (fun _ ↦ 0) x) v = _ + simp + have hs' : ¬ MDiffAt (a • s) x := + fun h ↦ hs (by simpa [ha] using h.const_smul a⁻¹) + rw [mfderiv_zero_of_not_mdifferentiableAt hs, mfderiv_zero_of_not_mdifferentiableAt hs'] + simp + rfl + +-- PRed and cleaned up in #34263 +set_option linter.flexible false in -- FIXME +lemma mfderiv_smul [IsManifold I 1 M] {f : M → F} {s : M → 𝕜} {x : M} (hf : MDiffAt f x) + (hs : MDiffAt s x) (v : TangentSpace I x) : + letI dsxv : 𝕜 := mfderiv% s x v + letI dfxv : F := mfderiv% f x v + mfderiv% (s • f) x v = (s x) • dfxv + dsxv • f x := by + set φ := chartAt H x + -- TODO: the next two have should be special cases of the same lemma + have hs' : DifferentiableWithinAt 𝕜 (s ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := by + have hφ := mdifferentiableWithinAt_extChartAt_symm (mem_extChartAt_target x) (I := I) + have : (extChartAt I x).symm (extChartAt I x x) = x := extChartAt_to_inv x + rw [← this] at hs + have := hs.comp_mdifferentiableWithinAt (extChartAt I x x) hφ + exact mdifferentiableWithinAt_iff_differentiableWithinAt.mp this + have hf' : DifferentiableWithinAt 𝕜 (f ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := by + have hφ := mdifferentiableWithinAt_extChartAt_symm (mem_extChartAt_target x) (I := I) + have : (extChartAt I x).symm (extChartAt I x x) = x := extChartAt_to_inv x + rw [← this] at hf + have := hf.comp_mdifferentiableWithinAt (extChartAt I x x) hφ + exact mdifferentiableWithinAt_iff_differentiableWithinAt.mp this + have hsf : MDiffAt (s • f) x := hs.smul hf + simp [mfderiv, hsf, hs, hf] + have uniq : UniqueDiffWithinAt 𝕜 (range I) (I (φ x)) := + ModelWithCorners.uniqueDiffWithinAt_image I + erw [fderivWithin_smul uniq hs' hf'] + simp [φ.left_inv (ChartedSpace.mem_chart_source x)] + rfl + +end mfderiv diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Basic.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Basic.lean new file mode 100644 index 00000000000000..7adc295e80677a --- /dev/null +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Basic.lean @@ -0,0 +1,481 @@ +/- +Copyright (c) 2025 Patrick Massot. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Patrick Massot, Michael Rothgang, Heather Macbeth +-/ +module + +public import Mathlib.Geometry.Manifold.VectorBundle.Hom +public import Mathlib.Geometry.Manifold.VectorBundle.SmoothSection +public import Mathlib.Geometry.Manifold.VectorBundle.Tensoriality +public import Mathlib.Geometry.Manifold.MfDerivSMul + +/-! +# Covariant derivatives + +This file defines covariant derivatives (aka Koszul connections) on vector bundles over manifolds. + +There are versions of the story: a local unbundled one and a global bundled one. +The local version is used by the global version but also (in other files) when +seeing a global object in a local trivialization. + +In the whole file `M` is a manifold over any nontrivially normed field `𝕜` and `V` is +a vector bundle over `M` with model fiber `F`. + +## Main definitions and constructions + +* `IsCovariantDerivativeOn`: A function from sections of a vector bundle `V` over a manifold `M` to + sections of $Hom(TM, V)$ is a *covariant derivative* on a set `s` in `M` if it is additive and + satisfies the Leibniz rule when applied to sections that are differentiable at a point of `s`. +* `ContMDiffCovariantDerivativeOn`: A covariant derivative ∇ on some set is called *of class* `C^k` + iff, whenever `X` is a `C^k` section and `σ` a `C^{k+1}` section, the result `∇_X σ` is a `C^k` + section. This is a class so typeclass inference can deduce this automatically. +* `IsCovariantDerivativeOn.add_one_form`: Adding a one-form taking values in the endomorphisms of + the vector bundle to a covariant derivative on a set gives a covariant derivative on that set. +* `IsCovariantDerivativeOn.difference`: The difference of two covariant derivatives on a set, + as a one-form taking values in the endomorphism bundle. +* `CovariantDerivative`: a globally defined covariant derivative on a vector bundle, as a bundled + object. +* `ContMDiffCovariantDerivative`: A covariant derivative ∇ is called *of class* `C^k` + iff, whenever `X` is a `C^k` section and `σ` a `C^{k+1}` section, the result `∇_X σ` is a `C^k` + section. This is a class so typeclass inference can deduce this automatically. +* `CovariantDerivative.addOneForm`: Adding a one-form taking values in the endomorphisms of the + vector bundle to a covariant derivative gives a covariant derivative. +* `CovariantDerivative.difference`: The difference of two covariant derivatives, as a one-form + taking values in the endomorphism bundle. + +## Implementation notes + +On paper there are several equivalent ways to define covariant derivatives on a vector bundle +`V → M`. The most common one starts with a function `∇` taking as input a global smooth vector field +`X` and a global smooth section `σ` and giving as output a global smooth section `∇_X σ`, before +proving the result `(∇_X σ) x` at a point `x` only depends on the value of the vector field at that +point and the 1-jet of the section at that point. + +Here we ask for a map sending a global section `σ` to a section `∇ σ` of `Hom(TM, End(V))`. +So the fact that `(∇_X σ) x` depends only on `X x` is baked into the definition. +Note also that we don’t put any differentiability restriction on `σ` and `X`, the type of +the covariant derivative map is simply `(Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x))`. +But the conditions on this map involve differentiability, see the definition of +`IsCovariantDerivativeOn`. + +This file proves that `(∇_X σ) x` depends only on the germ of `σ` at `x`, but not the stronger +statement that it depends only the 1-jet of `σ` at `x`. This will be proved in a later file. +-/ + +open Bundle NormedSpace +open scoped Manifold ContDiff Topology + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] + +@[expose] public section + +/-! ## Local unbundled theory -/ + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] + (F : Type*) [NormedAddCommGroup F] [NormedSpace 𝕜 F] + {V : M → Type*} [TopologicalSpace (TotalSpace F V)] + [∀ x, AddCommGroup (V x)] [∀ x, Module 𝕜 (V x)] + [∀ x : M, TopologicalSpace (V x)] + [∀ x, IsTopologicalAddGroup (V x)] [∀ x, ContinuousSMul 𝕜 (V x)] + [FiberBundle F V] + +/-- A function from sections of a vector bundle `V` on a manifold `M` to sections of $Hom(TM, E)$ +is a *covariant derivative* over a set `s` in `M` if it is additive and satisfies the Leibniz rule +when applied to sections that are differentiable at a point of `s`. + +Caution, the argument order is nonstandard: `cov σ x (X x)` corresponds to `∇_X σ x` on paper. +-/ +structure IsCovariantDerivativeOn + (cov : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)) + (s : Set M := Set.univ) : Prop where + add {σ σ' : Π x : M, V x} {x} + (hσ : MDiffAt (T% σ) x) (hσ' : MDiffAt (T% σ') x) (hx : x ∈ s := by trivial) : + cov (σ + σ') x = cov σ x + cov σ' x + leibniz {σ : Π x : M, V x} {g : M → 𝕜} {x} + (hσ : MDiffAt (T% σ) x) (hg : MDiffAt g x) (hx : x ∈ s := by trivial) : + cov (g • σ) x = g x • cov σ x + + .toSpanSingleton 𝕜 (σ x) ∘L (fromTangentSpace <| g x).toContinuousLinearMap ∘L (mfderiv% g x) + +/-- +A covariant derivative ∇ is called of class `C^k` iff, whenever `X` is a `C^k` section and `σ` a +`C^{k+1}` section, the result `∇_X σ` is a `C^k` section. This is a class so typeclass inference can +deduce this automatically. +-/ +class ContMDiffCovariantDerivativeOn [IsManifold I 1 M] [VectorBundle 𝕜 F V] (k : ℕ∞) + (cov : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)) + (u : Set M) where + contMDiff : ∀ {σ : Π x : M, V x}, CMDiff[u] (k + 1) (T% σ) → + letI cov (x : M) : TotalSpace (E →L[𝕜] F) fun x ↦ TangentSpace I x →L[𝕜] V x := ⟨x, cov σ x⟩ + ContMDiffOn I (I.prod 𝓘(𝕜, E →L[𝕜] F)) k cov u + -- TODO elaborators are not working here. We want to use `T% (cov σ)` and CMDiff[u] k f + +variable {F} + +namespace IsCovariantDerivativeOn + +-- TODO: prove that `cov σ x` depends on `σ` only via the 1-jet of `σ` at `x`. +-- This should be easy using the projection formula in `CovariantDerivative.Ehresmann`. +-- In the mean time we use the following weaker result (which is convenient to apply anyway). + +set_option backward.isDefEq.respectTransparency false in +/-- Given a covariant derivative `cov` on a neighborhood `s` of a point `x`, if sections `σ` and +`σ'` agree on `s` and are differentiable at `x`, then `cov σ x = cov σ x'`. -/ +lemma congr_of_eqOn + {cov : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)} + {s : Set M} (hcov : IsCovariantDerivativeOn F cov s) + {σ σ' : Π x : M, V x} {x : M} + (hσ : MDiffAt (T% σ) x) (hσ' : MDiffAt (T% σ') x) + (hxs : s ∈ 𝓝 x) (hσσ' : ∀ x ∈ s, σ x = σ' x) : + cov σ x = cov σ' x := by + classical + have hxs' : x ∈ s := mem_of_mem_nhds hxs + let ψ (x' : M) : 𝕜 := if x' ∈ s then 1 else 0 + have hψx : ψ x = 1 := by simp [ψ, hxs'] + -- Observe that `ψ • σ = ψ • σ'` as dependent functions. + have H (x' : M) : ((ψ : M → 𝕜) • σ) x' = ((ψ : M → 𝕜) • σ') x' := by + dsimp [ψ] + split_ifs with hx's + · simpa using hσσ' _ hx's + · simp + have hψ' : HasMFDerivAt I 𝓘(𝕜) ψ x 0 := by + have : HasMFDerivAt I 𝓘(𝕜, 𝕜) (fun (_x : M) ↦ (1 : 𝕜)) x 0 := hasMFDerivAt_const .. + refine this.congr_of_eventuallyEq ?_ + apply Filter.eventuallyEq_of_mem hxs + intro t ht + simp [ψ, ht] + have := hcov.leibniz hσ hψ'.mdifferentiableAt + -- Then, it's a chain of (dependent) equalities. + calc cov σ x + _ = cov ((ψ : M → 𝕜) • σ) x := by + simp [hcov.leibniz hσ hψ'.mdifferentiableAt, hψx, hψ'.mfderiv] + _ = cov ((ψ : M → 𝕜) • σ') x := by rw [funext H] + _ = cov σ' x := by + simp [hcov.leibniz hσ' hψ'.mdifferentiableAt, hψx, hψ'.mfderiv] + +/-! ### Changing set + +In this section, we change `s` in `IsCovariantDerivativeOn F cov s`, proving the condition is +monotone and local. +-/ + +section changing_set + +lemma mono + {cov : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)} {s t : Set M} + (hcov : IsCovariantDerivativeOn F cov t) (hst : s ⊆ t) : IsCovariantDerivativeOn F cov s where + add hσ hσ' hx := hcov.add hσ hσ' (hst hx) + leibniz hσ hcov' hx := hcov.leibniz hσ hcov' (hst hx) + +lemma iUnion {ι : Type*} {cov : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)} + {s : ι → Set M} (hcov : ∀ i, IsCovariantDerivativeOn F cov (s i)) : + IsCovariantDerivativeOn F cov (⋃ i, s i) where + add hσ hσ' hx := by + obtain ⟨si, ⟨i, rfl⟩, hxsi⟩ := hx + exact (hcov i).add hσ hσ' + leibniz hσ hf' hx := by + obtain ⟨si, ⟨i, rfl⟩, hxsi⟩ := hx + exact (hcov i).leibniz hσ hf' + +end changing_set + +/-! ### Computational properties -/ + +section computational_properties + +variable {cov : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)} {s : Set M} + +lemma zero [VectorBundle 𝕜 F V] (hcov : IsCovariantDerivativeOn F cov s) + {x} (hx : x ∈ s := by trivial) : + cov 0 x = 0 := by + simpa using (hcov.add (mdifferentiableAt_zeroSection ..) + (mdifferentiableAt_zeroSection ..) : cov (0 + 0) x = _) + +theorem smul_const (hcov : IsCovariantDerivativeOn F cov s) + {σ : Π x : M, V x} {x} (a : 𝕜) + (hσ : MDiffAt (T% σ) x) (hx : x ∈ s := by trivial) : + cov (a • σ) x = a • cov σ x := by + simpa using hcov.leibniz (g := fun _ ↦ a) hσ mdifferentiableAt_const + +end computational_properties + +/-! ### Operations + +In this section we prove that: + +* affine combinations of covariant derivatives are covariant derivatives +* adding a one-form taking values in the endomorphisms of the vector bundle to a covariant + derivative gives a covariant derivative. See `IsCovariantDerivativeOn.add_one_form`. +* subtracting two covariant derivatives on some set gives a one-form taking values in + the endomorphisms of the vector bundle. See `IsCovariantDerivativeOn.difference`. + +Note: morally this means covariant derivatives form an affine space over the vector space of +one-forms taking values in the endomorphisms of the bundle, but we don’t package it that way yet. +-/ +section operations + +variable {s : Set M} {cov : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)} + +/-- An affine combination of covariant derivatives is a covariant derivative. -/ +@[simps] +lemma affine_combination (hcov : IsCovariantDerivativeOn F cov s) + {cov' : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)} + (hcov' : IsCovariantDerivativeOn F cov' s) (g : M → 𝕜) : + IsCovariantDerivativeOn F (fun σ ↦ (g • (cov σ)) + (1 - g) • (cov' σ)) s where + add hσ hσ' hx := by + simp [hcov.add hσ hσ', hcov'.add hσ hσ'] + module + leibniz hσ hφ hx := by + simp [hcov.leibniz hσ hφ, hcov'.leibniz hσ hφ] + module + +/-- An affine combination of two `C^k` connections is a `C^k` connection. -/ +lemma _root_.ContMDiffCovariantDerivativeOn.affine_combination [IsManifold I 1 M] + [VectorBundle 𝕜 F V] + {cov cov' : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)} + {u: Set M} {f : M → 𝕜} {n : ℕ∞} (hf : CMDiff[u] n f) + (Hcov : ContMDiffCovariantDerivativeOn (F := F) n cov u) + (Hcov' : ContMDiffCovariantDerivativeOn (F := F) n cov' u) : + ContMDiffCovariantDerivativeOn F n (fun σ ↦ (f • (cov σ)) + (1 - f) • (cov' σ)) u where + contMDiff hσ := by + apply ContMDiffOn.add_section + · exact hf.smul_section <| Hcov.contMDiff hσ + · exact (contMDiffOn_const.sub hf).smul_section <| Hcov'.contMDiff hσ + +/-- A finite affine combination of covariant derivatives is a covariant derivative. -/ +lemma finite_affine_combination {ι : Type*} {s : Finset ι} + {u : Set M} {cov : ι → (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)} + (h : ∀ i, IsCovariantDerivativeOn F (cov i) u) {f : ι → M → 𝕜} (hf : ∑ i ∈ s, f i = 1) : + IsCovariantDerivativeOn F (fun σ x ↦ ∑ i ∈ s, (f i x) • (cov i) σ x) u where + add hσ hσ' hx := by + rw [← Finset.sum_add_distrib] + congr + ext i + rw [← smul_add, (h i).add hσ hσ' hx] + leibniz {σ g x} hσ hg hx := by + set B := (ContinuousLinearMap.toSpanSingleton 𝕜 (σ x) ∘L + ((fromTangentSpace (g x)).toContinuousLinearMap ∘L (mfderiv% g x))) + calc ∑ i ∈ s, f i x • cov i (g • σ) x + _ = ∑ i ∈ s, (g x • f i x • cov i σ x + f i x • B) := by + congr! 1 with i hi + rw [(h i).leibniz hσ hg] + module + _ = g x • ∑ i ∈ s, f i x • cov i σ x + (∑ i ∈ s, f i) x • B := by + rw [Finset.sum_add_distrib, Finset.smul_sum, Finset.sum_apply, Finset.sum_smul] + _ = g x • ∑ i ∈ s, f i x • cov i σ x + B := by rw [hf]; simp + +/-- An affine combination of finitely many `C^k` connections on `u` is a `C^k` connection on `u`. -/ +lemma _root_.ContMDiffCovariantDerivativeOn.finite_affine_combination [IsManifold I 1 M] {n : ℕ∞} + [VectorBundle 𝕜 F V] {ι : Type*} {s : Finset ι} {u : Set M} + {cov : ι → (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)} + (hcov : ∀ i ∈ s, ContMDiffCovariantDerivativeOn F n (cov i) u) + {f : ι → M → 𝕜} (hf : ∀ i ∈ s, CMDiff[u] n (f i)) : + ContMDiffCovariantDerivativeOn F n (fun σ x ↦ ∑ i ∈ s, (f i x) • (cov i) σ x) u where + contMDiff {σ} hσ := by + simpa using ContMDiffOn.sum_section + (fun i hi ↦ (hf i hi).smul_section <| (hcov i hi).contMDiff hσ) + +/-- Adding a one-form taking values in the endomorphisms of the vector bundle to a covariant + derivative gives a covariant derivative. -/ +lemma add_one_form (hcov : IsCovariantDerivativeOn F cov s) + (A : Π x : M, V x →L[𝕜] TangentSpace I x →L[𝕜] V x) : + IsCovariantDerivativeOn F (fun σ x ↦ cov σ x + A x (σ x)) s where + add hσ hσ' hx := by + simp [hcov.add hσ hσ'] + abel + leibniz hσ hg hx := by + simp [hcov.leibniz hσ hg] + module + +section difference + +/-- The difference of two covariant derivatives, as a function `Γ(V) → Γ(Hom(TM, V))`. +Future lemmas will upgrade this to a one-form taking values in the endomorphisms of `V`. -/ +noncomputable def differenceAux + (cov cov' : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)) : + (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x) := + fun σ ↦ cov σ - cov' σ + +variable + {cov' : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)} + {s : Set M} + (hcov : IsCovariantDerivativeOn F cov s) + (hcov' : IsCovariantDerivativeOn F cov' s) + +theorem differenceAux_tensorial (hcov : IsCovariantDerivativeOn F cov s) + (hcov' : IsCovariantDerivativeOn F cov' s) + (x : M) (hx : x ∈ s) : TensorialAt I F (differenceAux cov cov' · x) x where + smul hf hσ := by + simp [differenceAux, hcov.leibniz hσ hf, hcov'.leibniz hσ hf] + module + add hσ hσ' := by + simp [differenceAux, hcov.add hσ hσ', hcov'.add hσ hσ'] + abel + +-- We need more assumptions to use the tensoriality criterion in order to build the difference +-- operation. +variable [CompleteSpace 𝕜] [FiniteDimensional 𝕜 F] + [VectorBundle 𝕜 F V] [ContMDiffVectorBundle 1 F V I] + +open scoped Classical in +/-- The difference of two covariant derivatives, as a one-form taking values in the +endomorphisms of `V`. -/ +noncomputable def difference (x : M) : V x →L[𝕜] TangentSpace I x →L[𝕜] V x := + if hxs : x ∈ s then + TensorialAt.mkHom _ x (differenceAux_tensorial hcov hcov' _ hxs) + else + 0 + +@[simp] +lemma difference_apply {x : M} (hx : x ∈ s := by trivial) {σ : Π x, V x} (hσ : MDiffAt (T% σ) x) : + difference hcov hcov' x (σ x) = cov σ x - cov' σ x := by + simp only [difference, hx, reduceDIte] + rw [TensorialAt.mkHom_apply _ hσ] + rfl + +end difference + +end operations + +end IsCovariantDerivativeOn + +/-! ## Bundled global covariant derivatives -/ + +variable (I F V) in +/-- +Bundled global covariant derivative on a vector bundle. +Caution, the argument order is nonstandard: `cov σ x (X x)` corresponds to `∇_X σ x` on paper. +-/ +@[ext] +structure CovariantDerivative where + /-- The covariant derivative as a function. -/ + toFun : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x) + isCovariantDerivativeOnUniv : IsCovariantDerivativeOn F toFun Set.univ + +namespace CovariantDerivative + +attribute [coe] toFun + +/-- Coercion of a `CovariantDerivative` to function -/ +instance : CoeFun (CovariantDerivative I F V) + fun _ ↦ (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x) := + ⟨fun e ↦ e.toFun⟩ + +lemma isCovariantDerivativeOn (cov : CovariantDerivative I F V) {s : Set M} : + IsCovariantDerivativeOn F cov s := + cov.isCovariantDerivativeOnUniv.mono (fun _ _ ↦ trivial) + +@[simp] +lemma zero [VectorBundle 𝕜 F V] (cov : CovariantDerivative I F V) : cov 0 = 0 := by + ext1 x + simp [cov.isCovariantDerivativeOnUniv.zero] + +/-- If `cov` is a covariant derivative on each set in an open cover, it is a covariant derivative. +-/ +def of_isCovariantDerivativeOn_of_open_cover {ι : Type*} {s : ι → Set M} + {cov : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)} + (hcov : ∀ i, IsCovariantDerivativeOn F cov (s i)) (hs : ⋃ i, s i = Set.univ) : + CovariantDerivative I F V := + ⟨cov, hs ▸ IsCovariantDerivativeOn.iUnion hcov⟩ + +@[simp] +lemma of_isCovariantDerivativeOn_of_open_cover_coe {ι : Type*} {s : ι → Set M} + {cov : (Π x : M, V x) → (Π x : M, TangentSpace I x →L[𝕜] V x)} + (hcov : ∀ i, IsCovariantDerivativeOn F cov (s i)) (hs : ⋃ i, s i = Set.univ) : + of_isCovariantDerivativeOn_of_open_cover hcov hs = cov := rfl + +/-- +A covariant derivative ∇ is called of class `C^k` iff, whenever `X` is a `C^k` section and `σ` a +`C^{k+1}` section, the result `∇_X σ` is a `C^k` section. +This is a class so typeclass inference can deduce this automatically. +-/ +class ContMDiffCovariantDerivative [IsManifold I 1 M] [VectorBundle 𝕜 F V] + (cov : CovariantDerivative I F V) (k : ℕ∞) where + contMDiff : ContMDiffCovariantDerivativeOn F k cov.toFun Set.univ + +@[simp] +lemma contMDiffCovariantDerivativeOn_univ_iff [IsManifold I 1 M] [VectorBundle 𝕜 F V] + {cov : CovariantDerivative I F V} {k : ℕ∞} : + ContMDiffCovariantDerivativeOn F k cov.toFun Set.univ ↔ ContMDiffCovariantDerivative cov k := + ⟨fun h ↦ ⟨h⟩, fun h ↦ h.contMDiff⟩ + +section operations + +/-! ### Operations + +In this section we prove that: + +* affine combinations of covariant derivatives are covariant derivatives +* adding a one-form taking values in the endomorphisms of the vector bundle to a covariant + derivative gives a covariant derivative. See `CovariantDerivative.addOneForm`. +* subtracting two covariant derivatives on some set gives a one-form taking values in the + endomorphisms of the vector bundle. See `CovariantDerivative.difference`. + +Note: morally this means covariant derivatives form an affine space over the vector space of +one-forms taking values in the endomorphisms of the bundle, but we don’t package it that way yet. +-/ + +/-- An affine combination of covariant derivatives as a covariant derivative. -/ +@[simps] +def affine_combination (cov cov' : CovariantDerivative I F V) (g : M → 𝕜) : + CovariantDerivative I F V where + toFun := fun σ ↦ (g • (cov σ)) + (1 - g) • (cov' σ) + isCovariantDerivativeOnUniv := + cov.isCovariantDerivativeOn.affine_combination cov'.isCovariantDerivativeOn _ + +/-- A finite affine combination of covariant derivatives as a covariant derivative. -/ +def finite_affine_combination {ι : Type*} {s : Finset ι} + (cov : ι → CovariantDerivative I F V) {f : ι → M → 𝕜} (hf : ∑ i ∈ s, f i = 1) : + CovariantDerivative I F V where + toFun t x := ∑ i ∈ s, (f i x) • (cov i) t x + isCovariantDerivativeOnUniv := IsCovariantDerivativeOn.finite_affine_combination + (fun i ↦ (cov i).isCovariantDerivativeOn) hf + +/-- An affine combination of two `C^k` connections is a `C^k` connection. -/ +lemma ContMDiffCovariantDerivative.affine_combination [IsManifold I 1 M] [VectorBundle 𝕜 F V] + (cov cov' : CovariantDerivative I F V) + {f : M → 𝕜} {n : ℕ∞} (hf : ContMDiff I 𝓘(𝕜) n f) + (hcov : ContMDiffCovariantDerivative cov n) (hcov' : ContMDiffCovariantDerivative cov' n) : + ContMDiffCovariantDerivative (affine_combination cov cov' f) n where + contMDiff := + ContMDiffCovariantDerivativeOn.affine_combination hf.contMDiffOn hcov.contMDiff hcov'.contMDiff + +/-- An affine combination of finitely many `C^k` connections is a `C^k` connection. -/ +lemma ContMDiffCovariantDerivative.finite_affine_combination [IsManifold I 1 M] [VectorBundle 𝕜 F V] + {ι : Type*} {s : Finset ι} (cov : ι → CovariantDerivative I F V) + {f : ι → M → 𝕜} (hf : ∑ i ∈ s, f i = 1) {n : ℕ∞} (hf' : ∀ i ∈ s, ContMDiff I 𝓘(𝕜) n (f i)) + (hcov : ∀ i ∈ s, ContMDiffCovariantDerivative (cov i) n) : + ContMDiffCovariantDerivative (finite_affine_combination cov hf) n where + contMDiff := + ContMDiffCovariantDerivativeOn.finite_affine_combination + (fun i hi ↦ (hcov i hi).contMDiff) (fun i hi ↦ (hf' i hi).contMDiffOn) + +-- TODO: prove a version with a locally finite sum, and deduce that C^k connections always +-- exist (using a partition of unity argument) + +/-- Adding a one-form taking values in the endomorphisms of the vector bundle to a covariant + derivative gives a covariant derivative. -/ +def addOneForm (cov : CovariantDerivative I F V) + (A : Π (x : M), V x →L[𝕜] TangentSpace I x →L[𝕜] V x) : CovariantDerivative I F V where + toFun := fun σ x ↦ cov σ x + A x (σ x) + isCovariantDerivativeOnUniv := cov.isCovariantDerivativeOnUniv.add_one_form A + +section difference + +-- We need more assumptions to use the tensoriality criterion in order to build the difference +-- operation. +variable [CompleteSpace 𝕜] [IsManifold I 1 M] [FiniteDimensional 𝕜 F] + [VectorBundle 𝕜 F V] [ContMDiffVectorBundle 1 F V I] + +/-- The difference of two covariant derivatives, as a one-form taking values in the +endomorphisms of `V`. -/ +noncomputable def difference (cov cov' : CovariantDerivative I F V) : + Π (x : M), V x →L[𝕜] TangentSpace I x →L[𝕜] V x := + cov.isCovariantDerivativeOnUniv.difference cov'.isCovariantDerivativeOnUniv + +end difference +end operations + +end CovariantDerivative From c76b33707004beca650b3b57612c41cf6159adab Mon Sep 17 00:00:00 2001 From: Michael Rothgang Date: Fri, 6 Mar 2026 16:44:32 +0000 Subject: [PATCH 09/33] chore: add more bar! --- Mathlib/Geometry/Manifold/VectorField/LieBracket.lean | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorField/LieBracket.lean b/Mathlib/Geometry/Manifold/VectorField/LieBracket.lean index c5ba9c17cd84b1..79fd6cdac7dbbb 100644 --- a/Mathlib/Geometry/Manifold/VectorField/LieBracket.lean +++ b/Mathlib/Geometry/Manifold/VectorField/LieBracket.lean @@ -360,6 +360,7 @@ Product rule for Lie brackets: given two vector fields `V` and `W` on `M` and a lemma mlieBracketWithin_smul_right {f : M → 𝕜} (hf : MDiffAt[s] f x) (hW : MDiffAt[s] (fun x ↦ (W x : TangentBundle I M)) x) (hs : UniqueMDiffWithinAt I s x) : + -- TODO: add fromTangentSpace mlieBracketWithin I V (f • W) s x = (mfderivWithin I 𝓘(𝕜) f s x) (V x) • (W x) + (f x) • mlieBracketWithin I V W s x := by simp only [mlieBracketWithin, mpullbackWithin_smul] @@ -390,7 +391,9 @@ Product rule for Lie brackets: given two vector fields `V` and `W` on `M` and a -/ lemma mlieBracket_smul_right {f : M → 𝕜} (hf : MDiffAt f x) (hW : MDiffAt (fun x ↦ (W x : TangentBundle I M)) x) : - mlieBracket I V (f • W) x = (mfderiv% f x) (V x) • (W x) + (f x) • mlieBracket I V W x := by + mlieBracket I V (f • W) x = + NormedSpace.fromTangentSpace (f x) (mfderiv% f x (V x)) • (W x) + + (f x) • mlieBracket I V W x := by rw [← mdifferentiableWithinAt_univ] at hf hW rw [← mlieBracketWithin_univ, ← mfderivWithin_univ] exact mlieBracketWithin_smul_right hf hW (uniqueMDiffWithinAt_univ I) @@ -404,6 +407,7 @@ lemma mlieBracketWithin_smul_left {f : M → 𝕜} (hf : MDiffAt[s] f x) (hV : MDiffAt[s] (fun x ↦ (V x : TangentBundle I M)) x) (hs : UniqueMDiffWithinAt I s x) : mlieBracketWithin I (f • V) W s x = + -- TODO: add fromTangentSpace! -(mfderivWithin I 𝓘(𝕜) f s x) (W x) • (V x) + (f x) • mlieBracketWithin I V W s x := by rw [mlieBracketWithin_swap, Pi.neg_apply, mlieBracketWithin_smul_right hf hV (V := W) hs, mlieBracketWithin_swap] @@ -417,7 +421,8 @@ Product rule for Lie brackets: given two vector fields `V` and `W` on `M` and a lemma mlieBracket_smul_left {f : M → 𝕜} (hf : MDiffAt f x) (hV : MDiffAt (fun x ↦ (V x : TangentBundle I M)) x) : mlieBracket I (f • V) W x = - -(mfderiv% f x) (W x) • (V x) + (f x) • mlieBracket I V W x := by + - (NormedSpace.fromTangentSpace (f x) (mfderiv% f x (W x))) • (V x) + + (f x) • mlieBracket I V W x := by rw [← mdifferentiableWithinAt_univ] at hf hV rw [← mlieBracketWithin_univ, ← mfderivWithin_univ] exact mlieBracketWithin_smul_left hf hV (uniqueMDiffWithinAt_univ I) From ff0a1bf90fb99126d8f30095fce12c652d1a0d98 Mon Sep 17 00:00:00 2001 From: Michael Rothgang Date: Fri, 6 Mar 2026 17:10:05 +0000 Subject: [PATCH 10/33] feat: torsion of an affine connection We define the torsion tensor of an affine connection, i.e. a covariant derivative on the tangent bundle `TM` of some manifold `M`. --- Mathlib.lean | 1 + .../CovariantDerivative/Torsion.lean | 159 ++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Torsion.lean diff --git a/Mathlib.lean b/Mathlib.lean index c7dcc67dd82997..d87f8f9e8123d8 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4427,6 +4427,7 @@ public import Mathlib.Geometry.Manifold.SmoothEmbedding public import Mathlib.Geometry.Manifold.StructureGroupoid public import Mathlib.Geometry.Manifold.VectorBundle.Basic public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Basic +public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Torsion public import Mathlib.Geometry.Manifold.VectorBundle.FiberwiseLinear public import Mathlib.Geometry.Manifold.VectorBundle.Hom public import Mathlib.Geometry.Manifold.VectorBundle.LocalFrame diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Torsion.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Torsion.lean new file mode 100644 index 00000000000000..7de77b1bff7dcb --- /dev/null +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Torsion.lean @@ -0,0 +1,159 @@ +/- +Copyright (c) 2025 Patrick Massot. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Patrick Massot, Michael Rothgang, Heather Macbeth +-/ +module + +public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Basic +public import Mathlib.Geometry.Manifold.VectorField.LieBracket + +/-! # Torsion of an affine connection + +We define the torsion tensor of an affine connection, i.e. a covariant derivative on the tangent +bundle `TM` of some manifold `M`. + +## Main definitions and results + +* `IsCovariantDerivativeOn.torsion`: the torsion tensor of an unbundled covariant derivative + on `TM` on some set `s` in `M` +* `CovariantDerivative.torsion`: the torsion tensor of a bundled covariant derivative on `TM` +* `CovariantDerivative.torsion_eq_zero_iff`: the torsion tensor of a bundled covariant derivative + `∇` vanishes if and only if `∇_X Y - ∇_Y X = [X, Y]` for all differentiable vector fields + `X` and `Y`. + +-/ + +@[expose] public section + +open Bundle Set NormedSpace +open scoped Manifold ContDiff + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] {x : M} + +/-! ## Torsion tensor of an unbundled covariant derivative on `TM` on a set `s` -/ +namespace IsCovariantDerivativeOn + +/-- The torsion of a covariant derivative on the tangent bundle `TM`, as a bare function. +Prefer to use `IsCovariantDerivativeOn.torsion` (which is a 2-tensor) instead. -/ +noncomputable def torsionAux + (cov : (Π x : M, TangentSpace I x) → (Π x : M, TangentSpace I x →L[𝕜] TangentSpace I x)) : + (Π x : M, TangentSpace I x) → (Π x : M, TangentSpace I x) → (Π x : M, TangentSpace I x) := + fun X Y x ↦ cov Y x (X x) - cov X x (Y x) - VectorField.mlieBracket I X Y x + +variable [IsManifold I 2 M] [CompleteSpace E] + {cov cov' : (Π x : M, TangentSpace I x) → (Π x : M, TangentSpace I x →L[𝕜] TangentSpace I x)} + {X X' Y : Π x : M, TangentSpace I x} + +theorem torsionAux_tensorial₁ (hcov : IsCovariantDerivativeOn E cov) (x : M) + (Y : Π x, TangentSpace I x) : + TensorialAt I E (torsionAux cov · Y x) x where + smul hf hX := by + simp [torsionAux, hcov.leibniz hX hf, VectorField.mlieBracket_smul_left hf hX] + module + add hX hX' := by + simp [torsionAux, hcov.add hX hX', VectorField.mlieBracket_add_left hX hX'] + module + +theorem torsionAux_tensorial₂ (hcov : IsCovariantDerivativeOn E cov) (x : M) + (X : Π x, TangentSpace I x) : + TensorialAt I E (torsionAux cov X · x) x where + smul hf hY := by + simp [torsionAux, hcov.leibniz hY hf, VectorField.mlieBracket_smul_right hf hY] + module + add hY hY' := by + simp [torsionAux, hcov.add hY hY', VectorField.mlieBracket_add_right hY hY'] + module + +variable [CompleteSpace 𝕜] [FiniteDimensional 𝕜 E] + +/-- The torsion tensor of an unbundled covariant derivative on `TM`. -/ +noncomputable def torsion (hcov : IsCovariantDerivativeOn E cov univ) (x : M) : + TangentSpace I x →L[𝕜] TangentSpace I x →L[𝕜] TangentSpace I x := + TensorialAt.mkHom₂ (torsionAux cov · · x) _ + (fun τ _ ↦ hcov.torsionAux_tensorial₁ x τ) + (fun σ _ ↦ hcov.torsionAux_tensorial₂ x σ) + +theorem torsion_apply (hcov : IsCovariantDerivativeOn E cov univ) {x} + {X : Π x : M, TangentSpace I x} (hX : MDiffAt (T% X) x) + {Y : Π x : M, TangentSpace I x} (hY : MDiffAt (T% Y) x) : + torsion hcov x (X x) (Y x) = cov Y x (X x) - cov X x (Y x) - VectorField.mlieBracket I X Y x := + TensorialAt.mkHom₂_apply _ _ hX hY + +theorem torsion_apply_eq_extend (hcov : IsCovariantDerivativeOn E cov univ) {x} + (X₀ Y₀ : TangentSpace I x) : + torsion hcov x X₀ Y₀ = + cov (extend E Y₀) x X₀ - cov (extend E X₀) x Y₀ + - VectorField.mlieBracket I (extend E X₀) (extend E Y₀) x := by + simp [torsion, torsionAux, TensorialAt.mkHom₂_apply_eq_extend] + +variable (X) in +@[simp] +lemma torsion_self (hcov : IsCovariantDerivativeOn E cov univ) (X₀ : TangentSpace I x) : + hcov.torsion x X₀ X₀ = 0 := by + simp [torsion_apply_eq_extend] + +variable (X Y) in +lemma torsion_antisymm (hcov : IsCovariantDerivativeOn E cov univ) (X₀ Y₀ : TangentSpace I x) : + hcov.torsion x X₀ Y₀ = - hcov.torsion x Y₀ X₀ := by + simp only [torsion_apply_eq_extend, neg_sub] + rw [VectorField.mlieBracket_swap] + dsimp + module + +end IsCovariantDerivativeOn + +/-! ## Torsion tensor of a bundled covariant derivative on `TM` -/ +namespace CovariantDerivative + +open VectorField + +variable + {cov cov' : (Π x : M, TangentSpace I x) → (Π x : M, TangentSpace I x →L[𝕜] TangentSpace I x)} + {X X' Y : Π x : M, TangentSpace I x} + +variable [CompleteSpace 𝕜] [CompleteSpace E] [FiniteDimensional 𝕜 E] [IsManifold I 2 M] +variable (cov : CovariantDerivative I E (TangentSpace I : M → Type _)) + +/-- The torsion tensor of a covariant derivative on the tangent bundle of a manifold. -/ +noncomputable def torsion := cov.isCovariantDerivativeOn.torsion + +lemma torsion_apply (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) : + cov.torsion x (X x) (Y x) = cov Y x (X x) - cov X x (Y x) - mlieBracket I X Y x := by + unfold torsion IsCovariantDerivativeOn.torsion + apply TensorialAt.mkHom₂_apply + exacts [hX, hY] + +lemma torsion_apply_eq_extend (X₀ Y₀ : TangentSpace I x) : + cov.torsion x X₀ Y₀ = + cov (extend E Y₀) x (extend E X₀ x) - cov (extend E X₀) x (extend E Y₀ x) + - mlieBracket I (extend E X₀) (extend E Y₀) x := by + unfold torsion IsCovariantDerivativeOn.torsion + apply TensorialAt.mkHom₂_apply_eq_extend + +@[simp] +lemma torsion_self (X₀ : TangentSpace I x) : cov.torsion x X₀ X₀ = 0 := + cov.isCovariantDerivativeOn.torsion_self .. + +lemma torsion_antisymm (X₀ Y₀ : TangentSpace I x) : cov.torsion x X₀ Y₀ = - cov.torsion x Y₀ X₀ := + cov.isCovariantDerivativeOn.torsion_antisymm .. + +lemma torsion_eq_zero_iff : cov.torsion = 0 ↔ + ∀ {X Y x}, MDiffAt (T% X) x → MDiffAt (T% Y) x → + cov Y x (X x) - cov X x (Y x) = mlieBracket I X Y x := by + constructor + · intro h X Y x hX hY + replace h := congr($h x (X x) (Y x)) + rw [cov.torsion_apply hX hY] at h + simpa [sub_eq_iff_eq_add'] using h + · intro h + ext x u v + rw [torsion_apply_eq_extend, h] + · simp + · apply mdifferentiableAt_extend + · apply mdifferentiableAt_extend + +end CovariantDerivative From ba399a07c0d00318ab0f5bb941250ce9cae8ea6c Mon Sep 17 00:00:00 2001 From: Michael Rothgang Date: Fri, 6 Mar 2026 17:25:14 +0000 Subject: [PATCH 11/33] Fix the build --- .../Manifold/VectorBundle/CovariantDerivative/Torsion.lean | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Torsion.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Torsion.lean index 7de77b1bff7dcb..64318342cc0ec4 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Torsion.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Torsion.lean @@ -5,6 +5,7 @@ Authors: Patrick Massot, Michael Rothgang, Heather Macbeth -/ module +public import Mathlib.Topology.FiberBundle.Basic public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Basic public import Mathlib.Geometry.Manifold.VectorField.LieBracket @@ -26,7 +27,7 @@ bundle `TM` of some manifold `M`. @[expose] public section -open Bundle Set NormedSpace +open Bundle Set NormedSpace FiberBundle open scoped Manifold ContDiff variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] From 03cb39f0968f49b21edc94be31fb9c475a894d2d Mon Sep 17 00:00:00 2001 From: Michael Rothgang Date: Fri, 6 Mar 2026 17:29:23 +0000 Subject: [PATCH 12/33] chore: add missing bar; and use mfderiv% and mfderiv[s] slightly more --- .../Geometry/Manifold/VectorField/LieBracket.lean | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorField/LieBracket.lean b/Mathlib/Geometry/Manifold/VectorField/LieBracket.lean index 79fd6cdac7dbbb..5e94cd34d8716b 100644 --- a/Mathlib/Geometry/Manifold/VectorField/LieBracket.lean +++ b/Mathlib/Geometry/Manifold/VectorField/LieBracket.lean @@ -29,7 +29,7 @@ The main results are the following: @[expose] public section -open Set Function Filter +open Set Function Filter NormedSpace open scoped Topology Manifold ContDiff noncomputable section @@ -360,9 +360,9 @@ Product rule for Lie brackets: given two vector fields `V` and `W` on `M` and a lemma mlieBracketWithin_smul_right {f : M → 𝕜} (hf : MDiffAt[s] f x) (hW : MDiffAt[s] (fun x ↦ (W x : TangentBundle I M)) x) (hs : UniqueMDiffWithinAt I s x) : - -- TODO: add fromTangentSpace mlieBracketWithin I V (f • W) s x = - (mfderivWithin I 𝓘(𝕜) f s x) (V x) • (W x) + (f x) • mlieBracketWithin I V W s x := by + (fromTangentSpace (f x) (mfderiv[s] f x (V x))) • (W x) + + (f x) • mlieBracketWithin I V W s x := by simp only [mlieBracketWithin, mpullbackWithin_smul] -- Simplify local notation a bit. set V' := mpullbackWithin 𝓘(𝕜, E) I (extChartAt I x).symm V (range I) @@ -392,7 +392,7 @@ Product rule for Lie brackets: given two vector fields `V` and `W` on `M` and a lemma mlieBracket_smul_right {f : M → 𝕜} (hf : MDiffAt f x) (hW : MDiffAt (fun x ↦ (W x : TangentBundle I M)) x) : mlieBracket I V (f • W) x = - NormedSpace.fromTangentSpace (f x) (mfderiv% f x (V x)) • (W x) + (fromTangentSpace (f x) (mfderiv% f x (V x))) • (W x) + (f x) • mlieBracket I V W x := by rw [← mdifferentiableWithinAt_univ] at hf hW rw [← mlieBracketWithin_univ, ← mfderivWithin_univ] @@ -407,8 +407,8 @@ lemma mlieBracketWithin_smul_left {f : M → 𝕜} (hf : MDiffAt[s] f x) (hV : MDiffAt[s] (fun x ↦ (V x : TangentBundle I M)) x) (hs : UniqueMDiffWithinAt I s x) : mlieBracketWithin I (f • V) W s x = - -- TODO: add fromTangentSpace! - -(mfderivWithin I 𝓘(𝕜) f s x) (W x) • (V x) + (f x) • mlieBracketWithin I V W s x := by + -(fromTangentSpace (f x) (mfderiv[s] f x (W x))) • (V x) + + (f x) • mlieBracketWithin I V W s x := by rw [mlieBracketWithin_swap, Pi.neg_apply, mlieBracketWithin_smul_right hf hV (V := W) hs, mlieBracketWithin_swap] simp; abel @@ -421,7 +421,7 @@ Product rule for Lie brackets: given two vector fields `V` and `W` on `M` and a lemma mlieBracket_smul_left {f : M → 𝕜} (hf : MDiffAt f x) (hV : MDiffAt (fun x ↦ (V x : TangentBundle I M)) x) : mlieBracket I (f • V) W x = - - (NormedSpace.fromTangentSpace (f x) (mfderiv% f x (W x))) • (V x) + - (fromTangentSpace (f x) (mfderiv% f x (W x))) • (V x) + (f x) • mlieBracket I V W x := by rw [← mdifferentiableWithinAt_univ] at hf hV rw [← mlieBracketWithin_univ, ← mfderivWithin_univ] From 98bd8bb29e535dc94c363712b715dea54d0f7c72 Mon Sep 17 00:00:00 2001 From: Michael Rothgang Date: Fri, 6 Mar 2026 18:35:07 +0000 Subject: [PATCH 13/33] chore: don't need mfderiv_smul and friends just yet --- Mathlib.lean | 1 - Mathlib/Geometry/Manifold/MfDerivSMul.lean | 81 ------------------- .../CovariantDerivative/Basic.lean | 2 +- 3 files changed, 1 insertion(+), 83 deletions(-) delete mode 100644 Mathlib/Geometry/Manifold/MfDerivSMul.lean diff --git a/Mathlib.lean b/Mathlib.lean index d87f8f9e8123d8..359e23eb09b300 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4413,7 +4413,6 @@ public import Mathlib.Geometry.Manifold.MFDeriv.SpecificFunctions public import Mathlib.Geometry.Manifold.MFDeriv.Tangent public import Mathlib.Geometry.Manifold.MFDeriv.UniqueDifferential public import Mathlib.Geometry.Manifold.Metrizable -public import Mathlib.Geometry.Manifold.MfDerivSMul public import Mathlib.Geometry.Manifold.Notation public import Mathlib.Geometry.Manifold.PartitionOfUnity public import Mathlib.Geometry.Manifold.PoincareConjecture diff --git a/Mathlib/Geometry/Manifold/MfDerivSMul.lean b/Mathlib/Geometry/Manifold/MfDerivSMul.lean deleted file mode 100644 index 5c21e2705c6d62..00000000000000 --- a/Mathlib/Geometry/Manifold/MfDerivSMul.lean +++ /dev/null @@ -1,81 +0,0 @@ -/- -Copyright (c) 2025 Patrick Massot. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Michael Rothgang --/ -module - -public import Mathlib.Geometry.Manifold.MFDeriv.Atlas -public import Mathlib.Geometry.Manifold.MFDeriv.NormedSpace -public import Mathlib.Geometry.Manifold.Notation - -/-! -# Auxiliary lemmas about mfderiv and scalar multiplication - --/ - -open Bundle Filter Module Topology Set -open scoped Bundle Manifold ContDiff - -@[expose] public section mfderiv - -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] - {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] - {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} - {M : Type*} [TopologicalSpace M] [ChartedSpace H M] - {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] - -set_option backward.isDefEq.respectTransparency false in --- cleaned up and PRed in #34262 -lemma mfderiv_const_smul (s : M → F) {x : M} (a : 𝕜) (v : TangentSpace I x) : - mfderiv% (a • s) x v = a • mfderiv% s x v := by - by_cases hs : MDiffAt s x - · have hs' := hs.const_smul a - suffices - (fderivWithin 𝕜 ((a • s) ∘ (chartAt H x).symm ∘ I.symm) (range I) (I ((chartAt H x) x))) v = - a • (fderivWithin 𝕜 (s ∘ (chartAt H x).symm ∘ I.symm) (range I) - (I ((chartAt H x) x))) v by simpa [mfderiv, hs, hs'] - change fderivWithin 𝕜 (a • (s ∘ ↑(chartAt H x).symm ∘ ↑I.symm)) _ _ _ = _ - rw [fderivWithin_const_smul_field _ I.uniqueDiffWithinAt_image ] - rfl - · by_cases ha : a = 0 - · have : a • s = 0 := by ext; simp [ha] - rw [this, ha] - change (mfderiv I 𝓘(𝕜, F) (fun _ ↦ 0) x) v = _ - simp - have hs' : ¬ MDiffAt (a • s) x := - fun h ↦ hs (by simpa [ha] using h.const_smul a⁻¹) - rw [mfderiv_zero_of_not_mdifferentiableAt hs, mfderiv_zero_of_not_mdifferentiableAt hs'] - simp - rfl - --- PRed and cleaned up in #34263 -set_option linter.flexible false in -- FIXME -lemma mfderiv_smul [IsManifold I 1 M] {f : M → F} {s : M → 𝕜} {x : M} (hf : MDiffAt f x) - (hs : MDiffAt s x) (v : TangentSpace I x) : - letI dsxv : 𝕜 := mfderiv% s x v - letI dfxv : F := mfderiv% f x v - mfderiv% (s • f) x v = (s x) • dfxv + dsxv • f x := by - set φ := chartAt H x - -- TODO: the next two have should be special cases of the same lemma - have hs' : DifferentiableWithinAt 𝕜 (s ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := by - have hφ := mdifferentiableWithinAt_extChartAt_symm (mem_extChartAt_target x) (I := I) - have : (extChartAt I x).symm (extChartAt I x x) = x := extChartAt_to_inv x - rw [← this] at hs - have := hs.comp_mdifferentiableWithinAt (extChartAt I x x) hφ - exact mdifferentiableWithinAt_iff_differentiableWithinAt.mp this - have hf' : DifferentiableWithinAt 𝕜 (f ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := by - have hφ := mdifferentiableWithinAt_extChartAt_symm (mem_extChartAt_target x) (I := I) - have : (extChartAt I x).symm (extChartAt I x x) = x := extChartAt_to_inv x - rw [← this] at hf - have := hf.comp_mdifferentiableWithinAt (extChartAt I x x) hφ - exact mdifferentiableWithinAt_iff_differentiableWithinAt.mp this - have hsf : MDiffAt (s • f) x := hs.smul hf - simp [mfderiv, hsf, hs, hf] - have uniq : UniqueDiffWithinAt 𝕜 (range I) (I (φ x)) := - ModelWithCorners.uniqueDiffWithinAt_image I - erw [fderivWithin_smul uniq hs' hf'] - simp [φ.left_inv (ChartedSpace.mem_chart_source x)] - rfl - -end mfderiv diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Basic.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Basic.lean index 7adc295e80677a..6c9f0915725643 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Basic.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Basic.lean @@ -7,8 +7,8 @@ module public import Mathlib.Geometry.Manifold.VectorBundle.Hom public import Mathlib.Geometry.Manifold.VectorBundle.SmoothSection +public import Mathlib.Geometry.Manifold.VectorBundle.Tangent public import Mathlib.Geometry.Manifold.VectorBundle.Tensoriality -public import Mathlib.Geometry.Manifold.MfDerivSMul /-! # Covariant derivatives From 5ef0c9be6889c20d8c9f5ae303dd9fff2ade7370 Mon Sep 17 00:00:00 2001 From: Michael Rothgang Date: Fri, 6 Mar 2026 21:57:40 +0000 Subject: [PATCH 14/33] chore: cherry-pick #34263 --- Mathlib.lean | 1 + Mathlib/Geometry/Manifold/MfDerivSMul.lean | 81 ++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 Mathlib/Geometry/Manifold/MfDerivSMul.lean diff --git a/Mathlib.lean b/Mathlib.lean index 359e23eb09b300..d87f8f9e8123d8 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4413,6 +4413,7 @@ public import Mathlib.Geometry.Manifold.MFDeriv.SpecificFunctions public import Mathlib.Geometry.Manifold.MFDeriv.Tangent public import Mathlib.Geometry.Manifold.MFDeriv.UniqueDifferential public import Mathlib.Geometry.Manifold.Metrizable +public import Mathlib.Geometry.Manifold.MfDerivSMul public import Mathlib.Geometry.Manifold.Notation public import Mathlib.Geometry.Manifold.PartitionOfUnity public import Mathlib.Geometry.Manifold.PoincareConjecture diff --git a/Mathlib/Geometry/Manifold/MfDerivSMul.lean b/Mathlib/Geometry/Manifold/MfDerivSMul.lean new file mode 100644 index 00000000000000..e2d4a52ac8b2ff --- /dev/null +++ b/Mathlib/Geometry/Manifold/MfDerivSMul.lean @@ -0,0 +1,81 @@ +/- +Copyright (c) 2025 Patrick Massot. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Patrick Massot, Michael Rothgang +-/ +module + +public import Mathlib.Geometry.Manifold.MFDeriv.Atlas +public import Mathlib.Geometry.Manifold.MFDeriv.NormedSpace +public import Mathlib.Geometry.Manifold.Notation + +/-! +# Auxiliary lemmas about mfderiv and scalar multiplication + +-/ + +open Bundle Filter Module Topology Set +open scoped Bundle Manifold ContDiff + +@[expose] public section mfderiv + +variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] + {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] + {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] + +set_option backward.isDefEq.respectTransparency false in +-- cleaned up and PRed in #34262 +lemma mfderiv_const_smul (s : M → F) {x : M} (a : 𝕜) (v : TangentSpace I x) : + mfderiv% (a • s) x v = a • mfderiv% s x v := by + by_cases hs : MDiffAt s x + · have hs' := hs.const_smul a + suffices + (fderivWithin 𝕜 ((a • s) ∘ (chartAt H x).symm ∘ I.symm) (range I) (I ((chartAt H x) x))) v = + a • (fderivWithin 𝕜 (s ∘ (chartAt H x).symm ∘ I.symm) (range I) + (I ((chartAt H x) x))) v by simpa [mfderiv, hs, hs'] + change fderivWithin 𝕜 (a • (s ∘ ↑(chartAt H x).symm ∘ ↑I.symm)) _ _ _ = _ + rw [fderivWithin_const_smul_field _ I.uniqueDiffWithinAt_image ] + rfl + · by_cases ha : a = 0 + · have : a • s = 0 := by ext; simp [ha] + rw [this, ha] + change (mfderiv I 𝓘(𝕜, F) (fun _ ↦ 0) x) v = _ + simp + have hs' : ¬ MDiffAt (a • s) x := + fun h ↦ hs (by simpa [ha] using h.const_smul a⁻¹) + rw [mfderiv_zero_of_not_mdifferentiableAt hs, mfderiv_zero_of_not_mdifferentiableAt hs'] + simp + rfl + +-- PRed and cleaned up in #34263 +set_option linter.flexible false in -- FIXME +lemma mfderiv_smul [IsManifold I 1 M] {f : M → F} {s : M → 𝕜} {x : M} (hf : MDiffAt f x) + (hs : MDiffAt s x) (v : TangentSpace I x) : + letI dsxv := NormedSpace.fromTangentSpace (s x) (mfderiv% s x v) + letI dfxv := NormedSpace.fromTangentSpace (f x) (mfderiv% f x v) + mfderiv% (s • f) x v = (s x) • dfxv + dsxv • f x := by + set φ := chartAt H x + -- TODO: the next two have should be special cases of the same lemma + have hs' : DifferentiableWithinAt 𝕜 (s ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := by + have hφ := mdifferentiableWithinAt_extChartAt_symm (mem_extChartAt_target x) (I := I) + have : (extChartAt I x).symm (extChartAt I x x) = x := extChartAt_to_inv x + rw [← this] at hs + have := hs.comp_mdifferentiableWithinAt (extChartAt I x x) hφ + exact mdifferentiableWithinAt_iff_differentiableWithinAt.mp this + have hf' : DifferentiableWithinAt 𝕜 (f ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := by + have hφ := mdifferentiableWithinAt_extChartAt_symm (mem_extChartAt_target x) (I := I) + have : (extChartAt I x).symm (extChartAt I x x) = x := extChartAt_to_inv x + rw [← this] at hf + have := hf.comp_mdifferentiableWithinAt (extChartAt I x x) hφ + exact mdifferentiableWithinAt_iff_differentiableWithinAt.mp this + have hsf : MDiffAt (s • f) x := hs.smul hf + simp [mfderiv, hsf, hs, hf] + have uniq : UniqueDiffWithinAt 𝕜 (range I) (I (φ x)) := + ModelWithCorners.uniqueDiffWithinAt_image I + erw [fderivWithin_smul uniq hs' hf'] + simp [φ.left_inv (ChartedSpace.mem_chart_source x)] + rfl + +end mfderiv From 711c1412e4d16a9d2ac940f5349efc6e5bba199f Mon Sep 17 00:00:00 2001 From: Michael Rothgang Date: Fri, 6 Mar 2026 22:08:26 +0000 Subject: [PATCH 15/33] chore: transplant improvements from PR --- Mathlib/Geometry/Manifold/MfDerivSMul.lean | 89 +++++++++------------- 1 file changed, 34 insertions(+), 55 deletions(-) diff --git a/Mathlib/Geometry/Manifold/MfDerivSMul.lean b/Mathlib/Geometry/Manifold/MfDerivSMul.lean index e2d4a52ac8b2ff..0e0da7381379b8 100644 --- a/Mathlib/Geometry/Manifold/MfDerivSMul.lean +++ b/Mathlib/Geometry/Manifold/MfDerivSMul.lean @@ -7,75 +7,54 @@ module public import Mathlib.Geometry.Manifold.MFDeriv.Atlas public import Mathlib.Geometry.Manifold.MFDeriv.NormedSpace -public import Mathlib.Geometry.Manifold.Notation +public import Mathlib.Geometry.Manifold.MFDeriv.SpecificFunctions +import Mathlib.Geometry.Manifold.Notation -/-! -# Auxiliary lemmas about mfderiv and scalar multiplication +/-! # `mfderiv` and scalar multiplication -/ --/ - -open Bundle Filter Module Topology Set -open scoped Bundle Manifold ContDiff +open Set +open scoped Manifold ContDiff @[expose] public section mfderiv variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} - {M : Type*} [TopologicalSpace M] [ChartedSpace H M] + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [IsManifold I 1 M] {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] - -set_option backward.isDefEq.respectTransparency false in --- cleaned up and PRed in #34262 -lemma mfderiv_const_smul (s : M → F) {x : M} (a : 𝕜) (v : TangentSpace I x) : - mfderiv% (a • s) x v = a • mfderiv% s x v := by - by_cases hs : MDiffAt s x - · have hs' := hs.const_smul a - suffices - (fderivWithin 𝕜 ((a • s) ∘ (chartAt H x).symm ∘ I.symm) (range I) (I ((chartAt H x) x))) v = - a • (fderivWithin 𝕜 (s ∘ (chartAt H x).symm ∘ I.symm) (range I) - (I ((chartAt H x) x))) v by simpa [mfderiv, hs, hs'] - change fderivWithin 𝕜 (a • (s ∘ ↑(chartAt H x).symm ∘ ↑I.symm)) _ _ _ = _ - rw [fderivWithin_const_smul_field _ I.uniqueDiffWithinAt_image ] - rfl - · by_cases ha : a = 0 - · have : a • s = 0 := by ext; simp [ha] - rw [this, ha] - change (mfderiv I 𝓘(𝕜, F) (fun _ ↦ 0) x) v = _ - simp - have hs' : ¬ MDiffAt (a • s) x := - fun h ↦ hs (by simpa [ha] using h.const_smul a⁻¹) - rw [mfderiv_zero_of_not_mdifferentiableAt hs, mfderiv_zero_of_not_mdifferentiableAt hs'] - simp - rfl - --- PRed and cleaned up in #34263 -set_option linter.flexible false in -- FIXME -lemma mfderiv_smul [IsManifold I 1 M] {f : M → F} {s : M → 𝕜} {x : M} (hf : MDiffAt f x) + {f : M → F} {s : M → 𝕜} {x : M} + +theorem MDifferentiableAt.differentiableAt_comp_chartAt_symm + (hs : MDiffAt f x) : + letI φ := chartAt H x; + DifferentiableWithinAt 𝕜 (f ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := by + have hφ := mdifferentiableWithinAt_extChartAt_symm (mem_extChartAt_target x) (I := I) + rw [← extChartAt_to_inv x (I := I)] at hs + have := hs.comp_mdifferentiableWithinAt (extChartAt I x x) hφ + exact mdifferentiableWithinAt_iff_differentiableWithinAt.mp this + +lemma mfderiv_smul (hf : MDiffAt f x) (hs : MDiffAt s x) (v : TangentSpace I x) : letI dsxv := NormedSpace.fromTangentSpace (s x) (mfderiv% s x v) letI dfxv := NormedSpace.fromTangentSpace (f x) (mfderiv% f x v) mfderiv% (s • f) x v = (s x) • dfxv + dsxv • f x := by set φ := chartAt H x - -- TODO: the next two have should be special cases of the same lemma - have hs' : DifferentiableWithinAt 𝕜 (s ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := by - have hφ := mdifferentiableWithinAt_extChartAt_symm (mem_extChartAt_target x) (I := I) - have : (extChartAt I x).symm (extChartAt I x x) = x := extChartAt_to_inv x - rw [← this] at hs - have := hs.comp_mdifferentiableWithinAt (extChartAt I x x) hφ - exact mdifferentiableWithinAt_iff_differentiableWithinAt.mp this - have hf' : DifferentiableWithinAt 𝕜 (f ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := by - have hφ := mdifferentiableWithinAt_extChartAt_symm (mem_extChartAt_target x) (I := I) - have : (extChartAt I x).symm (extChartAt I x x) = x := extChartAt_to_inv x - rw [← this] at hf - have := hf.comp_mdifferentiableWithinAt (extChartAt I x x) hφ - exact mdifferentiableWithinAt_iff_differentiableWithinAt.mp this + -- TODO: inlining hs' or hf' breaks the proof, why? + have hs' : DifferentiableWithinAt 𝕜 (s ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := + hs.differentiableAt_comp_chartAt_symm + have aux := hs.differentiableAt_comp_chartAt_symm + have hf' : DifferentiableWithinAt 𝕜 (f ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := + hf.differentiableAt_comp_chartAt_symm + -- `have := hs.differentiableAt_comp_chartAt_symm` looks identical apart from unfolding φ have hsf : MDiffAt (s • f) x := hs.smul hf - simp [mfderiv, hsf, hs, hf] - have uniq : UniqueDiffWithinAt 𝕜 (range I) (I (φ x)) := - ModelWithCorners.uniqueDiffWithinAt_image I - erw [fderivWithin_smul uniq hs' hf'] + simp? [mfderiv, hsf, hs, hf] says + simp only [Pi.smul_apply', mfderiv, hsf, ↓reduceIte, writtenInExtChartAt, extChartAt, + OpenPartialHomeomorph.extend, modelWithCornersSelf_partialEquiv, PartialEquiv.trans_refl, + PartialEquiv.coe_trans_symm, OpenPartialHomeomorph.coe_coe_symm, + ModelWithCorners.toPartialEquiv_coe_symm, PartialEquiv.coe_trans, + ModelWithCorners.toPartialEquiv_coe, OpenPartialHomeomorph.toFun_eq_coe, Function.comp_apply, + hf, hs] + -- Use the defeq that `chartAt (s x)` and `chartAt (f x)` are the identity. + erw [fderivWithin_smul I.uniqueDiffWithinAt_image hs' hf'] simp [φ.left_inv (ChartedSpace.mem_chart_source x)] rfl - -end mfderiv From b0a39e77ecd895dfae835c572d03cadafa6edfe5 Mon Sep 17 00:00:00 2001 From: Michael Rothgang Date: Fri, 6 Mar 2026 22:19:10 +0000 Subject: [PATCH 16/33] feat: metric connections TODO: file is still unreviewed; will need further tweaks --- .../CovariantDerivative/Metric.lean | 374 ++++++++++++++++++ 1 file changed, 374 insertions(+) create mode 100644 Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean new file mode 100644 index 00000000000000..b867ac7aafff7d --- /dev/null +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -0,0 +1,374 @@ +/- +Copyright (c) 2025 Michael Rothgang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Patrick Massot, Michael Rothgang, Heather Macbeth +-/ +module + +public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Basic +public import Mathlib.Geometry.Manifold.VectorBundle.Riemannian +public import Mathlib.Geometry.Manifold.MfDerivSMul + +/-! # Metric connections + +This file defines connections on a Riemannian manifold which are compatible with the ambient metric. +A bundled connection `∇` on `(M, g)` is compatible with the metric `g` if and only if the metric +tensor `∇ g` (defined by `(X, Y, Z) ↦ ∇ₓ g(Y, Z) - g(∇ₓ Y, Z) - g(Y, ∇ₓ Z)`) +vanishes on all differentiable vector fields. + +## Main definitions and results + +* `CovariantDerivative.compatibilityTensor`: the tensor + `(X, Y, Z) ↦ ∇ₓ g(Y, Z) - g(∇ₓ Y, Z) - g(Y, ∇ₓ Z)` defining when a connection `∇` on a Riemannian + manifold `(M, g)` is compatible with the metric `g`. +* `CovariantDerivative.compatibilityTensor_apply` and + `CovariantDerivative.compatibilityTensor_apply` give formulas for applying the compatibility + tensor at `x` to vector fields which are differentiable at `x`, + resp. to extensions of tangent vectors at `x` to differentiable vector fields near `x`. +* `CovariantDerivative.IsCompatible`: predicate for a connection to be metric + `∇` is metric iff its `compatibilityTensor` vanishes + +## TODO +* when mathlib has a notion of parallel transport, define metric connections on general + Riemannian bundles (characterised by parallel transport being an isometry) and prove the + equivalence to this definition + +-/ + +open Bundle Function NormedSpace +open scoped Manifold ContDiff + +@[expose] public section + +-- TODO: revisit and fix this once the dust has settled +set_option backward.isDefEq.respectTransparency false + +-- Let `M` be a `C^k` real manifold modeled on `(E, H)`, endowed with a Riemannian metric. +variable {n : WithTop ℕ∞} + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H) + {M : Type*} [EMetricSpace M] [ChartedSpace H M] [IsManifold I 2 M] + [RiemannianBundle (fun (x : M) ↦ TangentSpace I x)] + +variable {E' : Type*} [NormedAddCommGroup E'] [NormedSpace ℝ E'] + +/-! Compatible connections: a connection on `TM` is compatible with the metric on `M` iff +`∇ X ⟨Y, Z⟩ = ⟨∇ X Y, Z⟩ + ⟨Y, ∇ X Z⟩` holds for all sufficiently nice vector fields `X`, `Y` and +`Z` on `M`. In our definition, we ask for this identity to at each `x : M`, whenever `X`, `Y` and +`Z` are differentiable at `x`. +The left hand side is the pushforward of the function `⟨Y, Z⟩` along the vector field `X`: +the left hand side at `x` is `df(X x)`, where `f := ⟨Y, Z⟩`. -/ + +variable {X X' X'' Y Y' Y'' Z Z' : Π x : M, TangentSpace I x} + +/-- The scalar product of two vector fields -/ +noncomputable abbrev product (X Y : Π x : M, TangentSpace I x) : M → ℝ := + fun x ↦ inner ℝ (X x) (Y x) + +-- `product` is C^k if X and Y are: this is shown in `Riemannian.lean` + +local notation "⟪" X ", " Y "⟫" => product I X Y + +-- Basic API for the product of two vector fields. +section product + +omit [IsManifold I 2 M] +lemma product_apply (x) : ⟪X, Y⟫ x = inner ℝ (X x) (Y x) := rfl + +variable (X X' Y) + +lemma product_swap : ⟪Y, X⟫ = ⟪X, Y⟫ := by + ext x + apply real_inner_comm + +@[simp] +lemma product_zero_left : ⟪0, X⟫ = 0 := by + ext x + simp [product] + +@[simp] +lemma product_zero_right : ⟪X, 0⟫ = 0 := by rw [product_swap, product_zero_left] + +lemma product_add_left : ⟪X + X', Y⟫ = ⟪X, Y⟫ + ⟪X', Y⟫ := by + ext x + simp [product, InnerProductSpace.add_left] + +@[simp] +lemma product_add_left_apply (x) : ⟪X + X', Y⟫ x = ⟪X, Y⟫ x + ⟪X', Y⟫ x := by + simp [product, InnerProductSpace.add_left] + +lemma product_add_right : ⟪X, Y + Y'⟫ = ⟪X, Y⟫ + ⟪X, Y'⟫ := by + rw [product_swap, product_swap _ Y, product_swap _ Y', product_add_left] + +@[simp] +lemma product_add_right_apply (x) : ⟪X, Y + Y'⟫ x = ⟪X, Y⟫ x + ⟪X, Y'⟫ x := by + rw [product_swap, product_swap _ Y, product_swap _ Y', product_add_left_apply] + +@[simp] lemma product_neg_left : ⟪-X, Y⟫ = -⟪X, Y⟫ := by ext x; simp [product] + +@[simp] lemma product_neg_right : ⟪X, -Y⟫ = -⟪X, Y⟫ := by ext x; simp [product] + +lemma product_sub_left : ⟪X - X', Y⟫ = ⟪X, Y⟫ - ⟪X', Y⟫ := by + ext x + simp [product, inner_sub_left] + +lemma product_sub_right : ⟪X, Y - Y'⟫ = ⟪X, Y⟫ - ⟪X, Y'⟫ := by + ext x + simp [product, inner_sub_right] + +lemma product_smul_left (f : M → ℝ) : product I (f • X) Y = f • product I X Y := by + ext x + simp [product, real_inner_smul_left] + +@[simp] +lemma product_smul_const_left (a : ℝ) : product I (a • X) Y = a • product I X Y := by + ext x + simp [product, real_inner_smul_left] + +lemma product_smul_right (f : M → ℝ) : product I X (f • Y) = f • product I X Y := by + ext x + simp [product, real_inner_smul_right] + +@[simp] +lemma product_smul_const_right (a : ℝ) : product I X (a • Y) = a • product I X Y := by + ext x + simp [product, real_inner_smul_right] + +end product + +-- These lemmas are necessary as my Lie bracket identities (assuming minimal differentiability) +-- only hold point-wise. They abstract the expanding and unexpanding of `product`. +omit [IsManifold I 2 M] in +lemma product_congr_left {x} (h : X x = X' x) : product I X Y x = product I X' Y x := by + rw [product_apply, h, ← product_apply] + +omit [IsManifold I 2 M] in +lemma product_congr_left₂ {x} (h : X x = X' x + X'' x) : + product I X Y x = product I X' Y x + product I X'' Y x := by + rw [product_apply, h, inner_add_left, ← product_apply] +omit [IsManifold I 2 M] in +lemma product_congr_right {x} (h : Y x = Y' x) : product I X Y x = product I X Y' x := by + rw [product_apply, h, ← product_apply] + +omit [IsManifold I 2 M] in +lemma product_congr_right₂ {x} (h : Y x = Y' x + Y'' x) : + product I X Y x = product I X Y' x + product I X Y'' x := by + rw [product_apply, h, inner_add_right, ← product_apply] + +/- TODO: writing `hY.inner_bundle hZ` or writing `by apply MDifferentiable.inner_bundle hY hZ` +yields an error +synthesized type class instance is not definitionally equal to expression inferred by typing rules, +synthesized + fun x ↦ instNormedAddCommGroupOfRiemannianBundle x +inferred + fun b ↦ inst✝⁷ +Diagnose and fix this, and then replace the below by `MDifferentiable(At).inner_bundle! -/ + +variable [IsContMDiffRiemannianBundle I 1 E (fun (x : M) ↦ TangentSpace I x)] {I} in +lemma MDifferentiable.inner_bundle' (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : MDiff ⟪Y, Z⟫ := + MDifferentiable.inner_bundle hY hZ + +variable [IsContMDiffRiemannianBundle I 1 E (fun (x : M) ↦ TangentSpace I x)] {I} in +lemma MDifferentiableAt.inner_bundle' {x} (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + MDiffAt ⟪Y, Z⟫ x := + MDifferentiableAt.inner_bundle hY hZ + +namespace CovariantDerivative + +-- Let `cov` be a covariant derivative on `TM`. +-- TODO: include in cheat sheet! +variable (cov : CovariantDerivative I E (TangentSpace I : M → Type _)) + +/-- Local notation for a connection. Caution: `∇ Y, X` corresponds to `∇ₓ Y` in textbooks -/ +local notation "∇" Y "," X => fun (x:M) ↦ cov Y x (X x) + +/-- The function defining the compatibility tensor for `∇` w.r.t. `g`: +prefer using `compatibilityTensor` instead -/ +noncomputable def compatibilityTensorAux (Y Z : Π x : M, TangentSpace I x) : + Π (x : M), TangentSpace I x →L[ℝ] ℝ := fun x ↦ + letI b : TangentSpace I x →L[ℝ] ℝ := mfderiv% ⟪Y, Z⟫ x + b - ((innerSL ℝ (Z x)) ∘L (cov Y x)) - ((innerSL ℝ (Y x)) ∘L (cov Z x)) + +lemma compatibilityTensorAux_apply (Y Z : Π x : M, TangentSpace I x) + {x : M} (X₀ : TangentSpace I x) : + compatibilityTensorAux I cov Y Z x X₀ = + NormedSpace.fromTangentSpace _ (mfderiv% ⟪Y, Z⟫ x X₀) + - innerSL ℝ (Z x) (cov Y x X₀) - innerSL ℝ (Y x) (cov Z x X₀) := by + unfold compatibilityTensorAux + simp + congr 1 + +variable [IsContMDiffRiemannianBundle I 1 E (fun (x : M) ↦ TangentSpace I x)] {x : M} + +variable {I} in +private lemma aux1 {f : M → ℝ} {σ τ : (x : M) → TangentSpace I x} + (hf : MDiffAt f x) (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : + compatibilityTensorAux I cov (f • σ) τ x = f x • compatibilityTensorAux I cov σ τ x := by + ext X₀ + rw [compatibilityTensorAux_apply, ContinuousLinearMap.coe_smul', Pi.smul_apply, + compatibilityTensorAux_apply] + rw [product_smul_left, cov.isCovariantDerivativeOn.leibniz hσ hf] + simp only [Pi.smul_apply', ContinuousLinearMap.add_apply, ContinuousLinearMap.coe_smul', + Pi.smul_apply, ContinuousLinearMap.coe_comp', ContinuousLinearEquiv.coe_coe, comp_apply, + ContinuousLinearMap.toSpanSingleton_apply, coe_innerSL_apply, map_smul] + erw [mfderiv_smul (hσ.inner_bundle' hτ) hf] -- identifying different tangent spaces + rw [inner_add_right, inner_smul_right, inner_smul_right, real_inner_comm (σ x) (τ x)] + simp only [← smul_eq_mul] + module + +variable {I} in +private lemma aux2 (σ σ' τ : (x : M) → TangentSpace I x) + (hσ : MDiffAt (T% σ) x) (hσ' : MDiffAt (T% σ') x) (hτ : MDiffAt (T% τ) x) : + compatibilityTensorAux I cov (σ + σ') τ x = + compatibilityTensorAux I cov σ τ x + compatibilityTensorAux I cov σ' τ x := by + simp only [compatibilityTensorAux] + ext X + simp only [ContinuousLinearMap.coe_sub', ContinuousLinearMap.coe_comp', coe_innerSL_apply, + Pi.sub_apply, comp_apply, ContinuousLinearMap.add_apply] + rw [product_add_left, + mfderiv_add (hσ.inner_bundle' hτ) (hσ'.inner_bundle' hτ), + cov.isCovariantDerivativeOn.add hσ hσ', + ContinuousLinearMap.comp_add] + erw [ContinuousLinearMap.coe_sub'] + rw [Pi.sub_apply] + erw [ContinuousLinearMap.add_apply, Pi.add_apply, inner_add_left] + -- set A := mfderiv I 𝓘(ℝ, ℝ) ⟪σ, τ⟫ x + -- set A' := mfderiv I 𝓘(ℝ, ℝ) ⟪σ', τ⟫ x + -- set B := ((innerSL ℝ) (τ x)).comp (cov σ x) + -- set B' := ((innerSL ℝ) (τ x)).comp (cov σ' x) + -- set C := inner ℝ (σ x) ((cov τ x) X) + -- set C' := inner ℝ (σ' x) ((cov τ x) X) + erw [ContinuousLinearMap.add_apply, ContinuousLinearMap.sub_apply, + ContinuousLinearMap.sub_apply] + -- bug: abel fails, but module works + -- hypothesis: B, B', C, C' are in ℝ, while A and A' are in the tangent space at ℝ instead + module + +variable {I} in +private lemma aux3 {f : M → ℝ} {σ τ : (x : M) → TangentSpace I x} + (hf : MDiffAt f x) (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : + compatibilityTensorAux I cov σ (f • τ) x = f x • compatibilityTensorAux I cov σ τ x := by + unfold compatibilityTensorAux + rw [product_smul_right, cov.isCovariantDerivativeOn.leibniz hτ hf] + ext X + simp only [smul_eq_mul, Pi.smul_apply', map_smul, ContinuousLinearMap.smul_comp, + ContinuousLinearMap.comp_add, ContinuousLinearMap.comp_smulₛₗ, RingHom.id_apply, + ContinuousLinearMap.coe_sub', Pi.sub_apply, ContinuousLinearMap.add_apply, + ContinuousLinearMap.coe_smul', ContinuousLinearMap.coe_comp', coe_innerSL_apply, Pi.smul_apply, + comp_apply, ContinuousLinearEquiv.coe_coe, ContinuousLinearMap.toSpanSingleton_apply] + erw [ContinuousLinearMap.sub_apply, ContinuousLinearMap.sub_apply, ContinuousLinearMap.comp_apply] + --set A := inner ℝ (σ x) ((cov τ x) X) + conv => + enter [1, 1, 2] + erw [ContinuousLinearMap.smul_apply] + conv => + enter [1, 1, 2, 2] + erw [ContinuousLinearMap.comp_apply] + dsimp + --set B := inner ℝ (τ x) ((cov σ x) X) + erw [mfderiv_smul (hσ.inner_bundle' hτ) hf] + --set C := (mfderiv I 𝓘(ℝ, ℝ) ⟪σ, τ⟫ x) X + --set D := (mfderiv I 𝓘(ℝ, ℝ) f x) X + simp only [smul_eq_mul, fromTangentSpace, ContinuousLinearEquiv.coe_mk, LinearEquiv.coe_mk, + LinearMap.coe_mk, AddHom.coe_mk, inner_smul_right] + -- would be nice to finish by a tactic now! + erw [mul_add, mul_add] + rw [Pi.mul_apply, mul_neg, mul_neg, + ← sub_eq_add_neg, ← sub_eq_add_neg, sub_add_eq_sub_sub] + match_scalars <;> all_goals simp + +variable {I} in +private lemma aux4 (σ τ τ' : (x : M) → TangentSpace I x) + (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) (hτ' : MDiffAt (T% τ') x) : + compatibilityTensorAux I cov σ (τ + τ') x = + compatibilityTensorAux I cov σ τ x + compatibilityTensorAux I cov σ τ' x := by + ext X₀ + rw [compatibilityTensorAux_apply]; dsimp + rw [compatibilityTensorAux_apply, compatibilityTensorAux_apply]; dsimp + rw [product_add_right, mfderiv_add (hσ.inner_bundle' hτ) (hσ.inner_bundle' hτ'), + cov.isCovariantDerivativeOn.add hτ hτ'] + simp only [Pi.add_apply, ContinuousLinearMap.add_apply, inner_add_left, inner_add_right, + fromTangentSpace, -- this line is slightly fishy + ContinuousLinearEquiv.coe_mk, LinearEquiv.coe_mk, LinearMap.coe_mk, AddHom.coe_mk] + erw [ContinuousLinearMap.add_apply] + module + +theorem compatibilityTensorAux_tensorial₁ (τ : Π x, TangentSpace I x) (hτ : MDiffAt (T% τ) x) : + TensorialAt I E (compatibilityTensorAux I cov · τ x) x where + smul hf hσ := aux1 cov hf hσ hτ + add hσ hσ' := aux2 cov _ _ _ hσ hσ' hτ + +theorem compatibilityTensorAux_tensorial₂ (σ : Π x, TangentSpace I x) (hσ : MDiffAt (T% σ) x) : + TensorialAt I E (compatibilityTensorAux I cov σ · x) x where + smul hf hτ := aux3 cov hf hσ hτ + add hτ hτ' := aux4 cov _ _ _ hσ hτ hτ' + +variable {I} in +/-- The tensor `(X, Y, Z) ↦ ∇ₓ g(Y, Z) - g(∇ₓ Y, Z) - g(Y, ∇ₓ Z)` defining when a connection +`∇` on a Riemannian manifold `(M, g)` is compatible with the metric `g`. -/ +@[no_expose] noncomputable def compatibilityTensor [FiniteDimensional ℝ E] (x : M) : + TangentSpace I x →L[ℝ] TangentSpace I x →L[ℝ] (TangentSpace I x →L[ℝ] ℝ) := + TensorialAt.mkHom₂ (compatibilityTensorAux I cov · · x) _ + (compatibilityTensorAux_tensorial₁ I cov) (compatibilityTensorAux_tensorial₂ I cov) + +variable {I} in +theorem compatibilityTensor_apply [FiniteDimensional ℝ E] (x : M) + (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + compatibilityTensor cov x (Y x) (Z x) (X x) = + fromTangentSpace _ (mfderiv% ⟪Y, Z⟫ x (X x)) - ⟪∇ Y, X, Z⟫ x - ⟪Y, ∇ Z, X⟫ x := by + unfold compatibilityTensor + rw [TensorialAt.mkHom₂_apply _ _ hY hZ] + --rw [compatibilityTensorAux_apply] + simp only [compatibilityTensorAux, ContinuousLinearMap.coe_sub', ContinuousLinearMap.coe_comp', + coe_innerSL_apply, Pi.sub_apply, comp_apply] + conv => + enter [1, 1] + erw [ContinuousLinearMap.sub_apply] + conv => + enter [1, 1, 2] + erw [ContinuousLinearMap.comp_apply] + simp [product, real_inner_comm, fromTangentSpace] + +variable {I} in +theorem compatibilityTensor_apply_eq_extend [FiniteDimensional ℝ E] (X₀ Y₀ Z₀ : TangentSpace I x) : + compatibilityTensor cov x Y₀ Z₀ X₀ = + fromTangentSpace _ (mfderiv% ⟪(extend E Y₀), (extend E Z₀)⟫ x X₀) + - ⟪∇ extend E Y₀, (extend E X₀), extend E Z₀⟫ x + - ⟪extend E Y₀, ∇ extend E Z₀, (extend E X₀)⟫ x := by + simpa [extend_apply_self] using compatibilityTensor_apply cov x + (X := extend E X₀) (mdifferentiableAt_extend I E Y₀) (mdifferentiableAt_extend I E Z₀) + +/-- Predicate saying for a connection `∇` on a Riemannian manifold `(M, g)` to be compatible with +the ambient metric, i.e. for all differentiable` vector fields `X`, `Y` and `Z` on `M`, we have +`X ⟨Y, Z⟩ = ⟨∇ X Y, Z⟩ + ⟨Y, ∇ X Z⟩`. -/ +def IsCompatible [FiniteDimensional ℝ E] : Prop := compatibilityTensor cov = 0 + +-- Auxiliary computation for `IsCompatible_apply`. +-- TODO: inlining this lemma does not work +private lemma isCompatible_apply_aux {A B C : ℝ} (h : A - B - C = 0) : A = B + C := by grind + +-- TODO: give a better name; maybe inline? +variable {I} in +lemma isCompatible_apply [FiniteDimensional ℝ E] (hcov : cov.IsCompatible) + (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + mfderiv% ⟪Y, Z⟫ x (X x) = ⟪∇ Y, X, Z⟫ x + ⟪Y, ∇ Z, X⟫ x := by + rw [IsCompatible] at hcov + have : compatibilityTensor cov x (Y x) (Z x) (X x) = 0 := by simp [hcov] + rw [compatibilityTensor_apply cov x hY hZ] at this + change (fromTangentSpace _ ((mfderiv I 𝓘(ℝ, ℝ) ⟪Y, Z⟫ x) (X x))) = _ + exact isCompatible_apply_aux this + +lemma isCompatible_iff [FiniteDimensional ℝ E] : + cov.IsCompatible ↔ ∀ {x : M} {X Y Z : (x : M) → TangentSpace I x} + (_hX : MDiffAt (T% X) x) (_hY : MDiffAt (T% Y) x) (_hZ : MDiffAt (T% Z) x), + mfderiv% ⟪Y, Z⟫ x (X x) = ⟪∇ Y, X, Z⟫ x + ⟪Y, ∇ Z, X⟫ x := by + refine ⟨fun hcov x X Y Z hX hY hZ ↦ cov.isCompatible_apply hcov hY hZ, fun h ↦ ?_⟩ + unfold IsCompatible + ext x X₀ Y₀ Z₀ + rw [compatibilityTensor_apply_eq_extend, sub_sub, sub_eq_iff_eq_add'] + simp only [Pi.zero_apply, ContinuousLinearMap.zero_apply, add_zero] + have h' := h (mdifferentiableAt_extend I E Z₀) (mdifferentiableAt_extend I E X₀) + (mdifferentiableAt_extend I E Y₀) + simpa [fromTangentSpace, extend_apply_self] using h' + +end CovariantDerivative From 7f7b5d80afad5f1181c12ed0b151293736ee7598 Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Sat, 7 Mar 2026 10:49:32 +0000 Subject: [PATCH 17/33] generalize to a riemannian bundle --- .../CovariantDerivative/Metric.lean | 169 ++++++++++-------- 1 file changed, 95 insertions(+), 74 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index b867ac7aafff7d..c308e08ea9a841 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -11,27 +11,30 @@ public import Mathlib.Geometry.Manifold.MfDerivSMul /-! # Metric connections -This file defines connections on a Riemannian manifold which are compatible with the ambient metric. -A bundled connection `∇` on `(M, g)` is compatible with the metric `g` if and only if the metric -tensor `∇ g` (defined by `(X, Y, Z) ↦ ∇ₓ g(Y, Z) - g(∇ₓ Y, Z) - g(Y, ∇ₓ Z)`) -vanishes on all differentiable vector fields. +This file defines connections on a Riemannian vector bundle which are compatible with the ambient +metric. A bundled connection `∇` on a Riemannian vector bundle `(V, g)` is compatible with the +metric `g` if and only if the differentiated metric tensor `∇ g` (defined by +`(X, Y, Z) ↦ ∇ₓ g(Y, Z) - g(∇ₓ Y, Z) - g(Y, ∇ₓ Z)`) vanishes on all differentiable vector fields `X` +and differentiable sections `Y`, `Z`. ## Main definitions and results * `CovariantDerivative.compatibilityTensor`: the tensor `(X, Y, Z) ↦ ∇ₓ g(Y, Z) - g(∇ₓ Y, Z) - g(Y, ∇ₓ Z)` defining when a connection `∇` on a Riemannian - manifold `(M, g)` is compatible with the metric `g`. + vector bundle `(V, g)` is compatible with the metric `g`. * `CovariantDerivative.compatibilityTensor_apply` and `CovariantDerivative.compatibilityTensor_apply` give formulas for applying the compatibility - tensor at `x` to vector fields which are differentiable at `x`, - resp. to extensions of tangent vectors at `x` to differentiable vector fields near `x`. -* `CovariantDerivative.IsCompatible`: predicate for a connection to be metric + tensor at `x` to vector fields and sections which are differentiable at `x`, + resp. to extensions of tangent vectors and sections at `x` to differentiable vector fields and + sections near `x`. +* `CovariantDerivative.IsCompatible`: predicate for a connection to be metric, namely that `∇` is metric iff its `compatibilityTensor` vanishes ## TODO -* when mathlib has a notion of parallel transport, define metric connections on general - Riemannian bundles (characterised by parallel transport being an isometry) and prove the - equivalence to this definition + +* when mathlib has a notion of parallel transport, prove the equivalence of + `CovariantDerivative.IsCompatible` with the characterisation that parallel transport be an + isometry. -/ @@ -43,36 +46,43 @@ open scoped Manifold ContDiff -- TODO: revisit and fix this once the dust has settled set_option backward.isDefEq.respectTransparency false --- Let `M` be a `C^k` real manifold modeled on `(E, H)`, endowed with a Riemannian metric. -variable {n : WithTop ℕ∞} +variable + -- Let `M` be a `C^k` real manifold modeled on `(E, H)` {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H) - {M : Type*} [EMetricSpace M] [ChartedSpace H M] [IsManifold I 2 M] - [RiemannianBundle (fun (x : M) ↦ TangentSpace I x)] + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [IsManifold I 2 M] + -- Let `V` be a bundle over `M`, endowed with a Riemannian metric. + (F : Type*) [NormedAddCommGroup F] [NormedSpace ℝ F] + {V : M → Type*} [TopologicalSpace (TotalSpace F V)] + [∀ x, AddCommGroup (V x)] [∀ x, Module ℝ (V x)] + [∀ x : M, TopologicalSpace (V x)] + [∀ x, IsTopologicalAddGroup (V x)] [∀ x, ContinuousSMul ℝ (V x)] + [FiberBundle F V] [RiemannianBundle V] variable {E' : Type*} [NormedAddCommGroup E'] [NormedSpace ℝ E'] -/-! Compatible connections: a connection on `TM` is compatible with the metric on `M` iff -`∇ X ⟨Y, Z⟩ = ⟨∇ X Y, Z⟩ + ⟨Y, ∇ X Z⟩` holds for all sufficiently nice vector fields `X`, `Y` and -`Z` on `M`. In our definition, we ask for this identity to at each `x : M`, whenever `X`, `Y` and -`Z` are differentiable at `x`. +/-! Compatible connections: a connection on `V` is compatible with the metric on `M` iff +`∇ X ⟨Y, Z⟩ = ⟨∇ X Y, Z⟩ + ⟨Y, ∇ X Z⟩` holds for all sufficiently nice vector fields `X` on `M` and +sections `Y`, `Z` of `V`. In our definition, we ask for this identity to at each `x : M`, whenever +`X`, `Y` and `Z` are differentiable at `x`. The left hand side is the pushforward of the function `⟨Y, Z⟩` along the vector field `X`: the left hand side at `x` is `df(X x)`, where `f := ⟨Y, Z⟩`. -/ -variable {X X' X'' Y Y' Y'' Z Z' : Π x : M, TangentSpace I x} +variable {X X' X'' Y Y' Y'' Z Z' : Π x : M, V x} /-- The scalar product of two vector fields -/ -noncomputable abbrev product (X Y : Π x : M, TangentSpace I x) : M → ℝ := +noncomputable abbrev product (X Y : Π x : M, V x) : M → ℝ := fun x ↦ inner ℝ (X x) (Y x) -- `product` is C^k if X and Y are: this is shown in `Riemannian.lean` -local notation "⟪" X ", " Y "⟫" => product I X Y +local notation "⟪" X ", " Y "⟫" => product X Y -- Basic API for the product of two vector fields. section product -omit [IsManifold I 2 M] +omit [TopologicalSpace M] [IsManifold I 2 M] + lemma product_apply (x) : ⟪X, Y⟫ x = inner ℝ (X x) (Y x) := rfl variable (X X' Y) @@ -98,11 +108,11 @@ lemma product_add_left_apply (x) : ⟪X + X', Y⟫ x = ⟪X, Y⟫ x + ⟪X', Y simp [product, InnerProductSpace.add_left] lemma product_add_right : ⟪X, Y + Y'⟫ = ⟪X, Y⟫ + ⟪X, Y'⟫ := by - rw [product_swap, product_swap _ Y, product_swap _ Y', product_add_left] + rw [product_swap, product_swap Y, product_swap Y', product_add_left] @[simp] lemma product_add_right_apply (x) : ⟪X, Y + Y'⟫ x = ⟪X, Y⟫ x + ⟪X, Y'⟫ x := by - rw [product_swap, product_swap _ Y, product_swap _ Y', product_add_left_apply] + rw [product_swap, product_swap Y, product_swap Y', product_add_left_apply] @[simp] lemma product_neg_left : ⟪-X, Y⟫ = -⟪X, Y⟫ := by ext x; simp [product] @@ -116,21 +126,21 @@ lemma product_sub_right : ⟪X, Y - Y'⟫ = ⟪X, Y⟫ - ⟪X, Y'⟫ := by ext x simp [product, inner_sub_right] -lemma product_smul_left (f : M → ℝ) : product I (f • X) Y = f • product I X Y := by +lemma product_smul_left (f : M → ℝ) : product (f • X) Y = f • product X Y := by ext x simp [product, real_inner_smul_left] @[simp] -lemma product_smul_const_left (a : ℝ) : product I (a • X) Y = a • product I X Y := by +lemma product_smul_const_left (a : ℝ) : product (a • X) Y = a • product X Y := by ext x simp [product, real_inner_smul_left] -lemma product_smul_right (f : M → ℝ) : product I X (f • Y) = f • product I X Y := by +lemma product_smul_right (f : M → ℝ) : product X (f • Y) = f • product X Y := by ext x simp [product, real_inner_smul_right] @[simp] -lemma product_smul_const_right (a : ℝ) : product I X (a • Y) = a • product I X Y := by +lemma product_smul_const_right (a : ℝ) : product X (a • Y) = a • product X Y := by ext x simp [product, real_inner_smul_right] @@ -138,21 +148,21 @@ end product -- These lemmas are necessary as my Lie bracket identities (assuming minimal differentiability) -- only hold point-wise. They abstract the expanding and unexpanding of `product`. -omit [IsManifold I 2 M] in -lemma product_congr_left {x} (h : X x = X' x) : product I X Y x = product I X' Y x := by +omit [TopologicalSpace M] [IsManifold I 2 M] in +lemma product_congr_left {x} (h : X x = X' x) : product X Y x = product X' Y x := by rw [product_apply, h, ← product_apply] -omit [IsManifold I 2 M] in +omit [TopologicalSpace M] [IsManifold I 2 M] in lemma product_congr_left₂ {x} (h : X x = X' x + X'' x) : - product I X Y x = product I X' Y x + product I X'' Y x := by + product X Y x = product X' Y x + product X'' Y x := by rw [product_apply, h, inner_add_left, ← product_apply] -omit [IsManifold I 2 M] in -lemma product_congr_right {x} (h : Y x = Y' x) : product I X Y x = product I X Y' x := by +omit [TopologicalSpace M] [IsManifold I 2 M] in +lemma product_congr_right {x} (h : Y x = Y' x) : product X Y x = product X Y' x := by rw [product_apply, h, ← product_apply] -omit [IsManifold I 2 M] in +omit [TopologicalSpace M] [IsManifold I 2 M] in lemma product_congr_right₂ {x} (h : Y x = Y' x + Y'' x) : - product I X Y x = product I X Y' x + product I X Y'' x := by + product X Y x = product X Y' x + product X Y'' x := by rw [product_apply, h, inner_add_right, ← product_apply] /- TODO: writing `hY.inner_bundle hZ` or writing `by apply MDifferentiable.inner_bundle hY hZ` @@ -164,32 +174,34 @@ inferred fun b ↦ inst✝⁷ Diagnose and fix this, and then replace the below by `MDifferentiable(At).inner_bundle! -/ -variable [IsContMDiffRiemannianBundle I 1 E (fun (x : M) ↦ TangentSpace I x)] {I} in +variable {F} [VectorBundle ℝ F V] [IsContMDiffRiemannianBundle I 1 F V] {I} in lemma MDifferentiable.inner_bundle' (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : MDiff ⟪Y, Z⟫ := MDifferentiable.inner_bundle hY hZ -variable [IsContMDiffRiemannianBundle I 1 E (fun (x : M) ↦ TangentSpace I x)] {I} in +variable {F} [VectorBundle ℝ F V] [IsContMDiffRiemannianBundle I 1 F V] {I} in lemma MDifferentiableAt.inner_bundle' {x} (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : MDiffAt ⟪Y, Z⟫ x := MDifferentiableAt.inner_bundle hY hZ namespace CovariantDerivative --- Let `cov` be a covariant derivative on `TM`. +-- Let `cov` be a covariant derivative on `V`. -- TODO: include in cheat sheet! -variable (cov : CovariantDerivative I E (TangentSpace I : M → Type _)) +variable (cov : CovariantDerivative I F V) /-- Local notation for a connection. Caution: `∇ Y, X` corresponds to `∇ₓ Y` in textbooks -/ local notation "∇" Y "," X => fun (x:M) ↦ cov Y x (X x) +variable {F} + /-- The function defining the compatibility tensor for `∇` w.r.t. `g`: prefer using `compatibilityTensor` instead -/ -noncomputable def compatibilityTensorAux (Y Z : Π x : M, TangentSpace I x) : +noncomputable def compatibilityTensorAux (Y Z : Π x : M, V x) : Π (x : M), TangentSpace I x →L[ℝ] ℝ := fun x ↦ letI b : TangentSpace I x →L[ℝ] ℝ := mfderiv% ⟪Y, Z⟫ x b - ((innerSL ℝ (Z x)) ∘L (cov Y x)) - ((innerSL ℝ (Y x)) ∘L (cov Z x)) -lemma compatibilityTensorAux_apply (Y Z : Π x : M, TangentSpace I x) +lemma compatibilityTensorAux_apply (Y Z : Π x : M, V x) {x : M} (X₀ : TangentSpace I x) : compatibilityTensorAux I cov Y Z x X₀ = NormedSpace.fromTangentSpace _ (mfderiv% ⟪Y, Z⟫ x X₀) @@ -198,10 +210,10 @@ lemma compatibilityTensorAux_apply (Y Z : Π x : M, TangentSpace I x) simp congr 1 -variable [IsContMDiffRiemannianBundle I 1 E (fun (x : M) ↦ TangentSpace I x)] {x : M} +variable [VectorBundle ℝ F V] [IsContMDiffRiemannianBundle I 1 F V] {x : M} variable {I} in -private lemma aux1 {f : M → ℝ} {σ τ : (x : M) → TangentSpace I x} +private lemma aux1 {f : M → ℝ} {σ τ : (x : M) → V x} (hf : MDiffAt f x) (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : compatibilityTensorAux I cov (f • σ) τ x = f x • compatibilityTensorAux I cov σ τ x := by ext X₀ @@ -217,7 +229,7 @@ private lemma aux1 {f : M → ℝ} {σ τ : (x : M) → TangentSpace I x} module variable {I} in -private lemma aux2 (σ σ' τ : (x : M) → TangentSpace I x) +private lemma aux2 (σ σ' τ : (x : M) → V x) (hσ : MDiffAt (T% σ) x) (hσ' : MDiffAt (T% σ') x) (hτ : MDiffAt (T% τ) x) : compatibilityTensorAux I cov (σ + σ') τ x = compatibilityTensorAux I cov σ τ x + compatibilityTensorAux I cov σ' τ x := by @@ -245,7 +257,7 @@ private lemma aux2 (σ σ' τ : (x : M) → TangentSpace I x) module variable {I} in -private lemma aux3 {f : M → ℝ} {σ τ : (x : M) → TangentSpace I x} +private lemma aux3 {f : M → ℝ} {σ τ : (x : M) → V x} (hf : MDiffAt f x) (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : compatibilityTensorAux I cov σ (f • τ) x = f x • compatibilityTensorAux I cov σ τ x := by unfold compatibilityTensorAux @@ -278,7 +290,7 @@ private lemma aux3 {f : M → ℝ} {σ τ : (x : M) → TangentSpace I x} match_scalars <;> all_goals simp variable {I} in -private lemma aux4 (σ τ τ' : (x : M) → TangentSpace I x) +private lemma aux4 (σ τ τ' : (x : M) → V x) (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) (hτ' : MDiffAt (T% τ') x) : compatibilityTensorAux I cov σ (τ + τ') x = compatibilityTensorAux I cov σ τ x + compatibilityTensorAux I cov σ τ' x := by @@ -293,26 +305,28 @@ private lemma aux4 (σ τ τ' : (x : M) → TangentSpace I x) erw [ContinuousLinearMap.add_apply] module -theorem compatibilityTensorAux_tensorial₁ (τ : Π x, TangentSpace I x) (hτ : MDiffAt (T% τ) x) : - TensorialAt I E (compatibilityTensorAux I cov · τ x) x where +theorem compatibilityTensorAux_tensorial₁ (τ : Π x, V x) (hτ : MDiffAt (T% τ) x) : + TensorialAt I F (compatibilityTensorAux I cov · τ x) x where smul hf hσ := aux1 cov hf hσ hτ add hσ hσ' := aux2 cov _ _ _ hσ hσ' hτ -theorem compatibilityTensorAux_tensorial₂ (σ : Π x, TangentSpace I x) (hσ : MDiffAt (T% σ) x) : - TensorialAt I E (compatibilityTensorAux I cov σ · x) x where +theorem compatibilityTensorAux_tensorial₂ (σ : Π x, V x) (hσ : MDiffAt (T% σ) x) : + TensorialAt I F (compatibilityTensorAux I cov σ · x) x where smul hf hτ := aux3 cov hf hσ hτ add hτ hτ' := aux4 cov _ _ _ hσ hτ hτ' -variable {I} in +variable {I} [ContMDiffVectorBundle 1 F V I] in /-- The tensor `(X, Y, Z) ↦ ∇ₓ g(Y, Z) - g(∇ₓ Y, Z) - g(Y, ∇ₓ Z)` defining when a connection -`∇` on a Riemannian manifold `(M, g)` is compatible with the metric `g`. -/ -@[no_expose] noncomputable def compatibilityTensor [FiniteDimensional ℝ E] (x : M) : - TangentSpace I x →L[ℝ] TangentSpace I x →L[ℝ] (TangentSpace I x →L[ℝ] ℝ) := +`∇` on a Riemannian bundle `(M, V)` is compatible with the metric `g`. -/ +@[no_expose] noncomputable def compatibilityTensor [FiniteDimensional ℝ F] (x : M) : + V x →L[ℝ] V x →L[ℝ] (TangentSpace I x →L[ℝ] ℝ) := TensorialAt.mkHom₂ (compatibilityTensorAux I cov · · x) _ (compatibilityTensorAux_tensorial₁ I cov) (compatibilityTensorAux_tensorial₂ I cov) -variable {I} in -theorem compatibilityTensor_apply [FiniteDimensional ℝ E] (x : M) +variable {X : Π x : M, TangentSpace I x} + +variable {I} [ContMDiffVectorBundle 1 F V I] in +theorem compatibilityTensor_apply [FiniteDimensional ℝ F] (x : M) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : compatibilityTensor cov x (Y x) (Z x) (X x) = fromTangentSpace _ (mfderiv% ⟪Y, Z⟫ x (X x)) - ⟪∇ Y, X, Z⟫ x - ⟪Y, ∇ Z, X⟫ x := by @@ -329,27 +343,32 @@ theorem compatibilityTensor_apply [FiniteDimensional ℝ E] (x : M) erw [ContinuousLinearMap.comp_apply] simp [product, real_inner_comm, fromTangentSpace] -variable {I} in -theorem compatibilityTensor_apply_eq_extend [FiniteDimensional ℝ E] (X₀ Y₀ Z₀ : TangentSpace I x) : +open FiberBundle in +variable {I} [ContMDiffVectorBundle 1 F V I] in +theorem compatibilityTensor_apply_eq_extend [FiniteDimensional ℝ F] (X₀ : TangentSpace I x) + (Y₀ Z₀ : V x) : compatibilityTensor cov x Y₀ Z₀ X₀ = - fromTangentSpace _ (mfderiv% ⟪(extend E Y₀), (extend E Z₀)⟫ x X₀) - - ⟪∇ extend E Y₀, (extend E X₀), extend E Z₀⟫ x - - ⟪extend E Y₀, ∇ extend E Z₀, (extend E X₀)⟫ x := by + fromTangentSpace _ (mfderiv% ⟪(extend F Y₀), (extend F Z₀)⟫ x X₀) + - ⟪∇ extend F Y₀, (extend E X₀), extend F Z₀⟫ x + - ⟪extend F Y₀, ∇ extend F Z₀, (extend E X₀)⟫ x := by simpa [extend_apply_self] using compatibilityTensor_apply cov x - (X := extend E X₀) (mdifferentiableAt_extend I E Y₀) (mdifferentiableAt_extend I E Z₀) + (X := extend E X₀) (mdifferentiableAt_extend I F Y₀) (mdifferentiableAt_extend I F Z₀) -/-- Predicate saying for a connection `∇` on a Riemannian manifold `(M, g)` to be compatible with -the ambient metric, i.e. for all differentiable` vector fields `X`, `Y` and `Z` on `M`, we have +variable {I} [ContMDiffVectorBundle 1 F V I] in +/-- Predicate saying for a connection `∇` on a Riemannian bundle `(V, g)` to be compatible with +the ambient metric, i.e. for all differentiable vector fields `X` on `M` and sections `Y` and `Z` +of `V`, we have `X ⟨Y, Z⟩ = ⟨∇ X Y, Z⟩ + ⟨Y, ∇ X Z⟩`. -/ -def IsCompatible [FiniteDimensional ℝ E] : Prop := compatibilityTensor cov = 0 +def IsCompatible [FiniteDimensional ℝ F] : Prop := compatibilityTensor cov = 0 -- Auxiliary computation for `IsCompatible_apply`. -- TODO: inlining this lemma does not work private lemma isCompatible_apply_aux {A B C : ℝ} (h : A - B - C = 0) : A = B + C := by grind +variable {I} [ContMDiffVectorBundle 1 F V I] in -- TODO: give a better name; maybe inline? -variable {I} in -lemma isCompatible_apply [FiniteDimensional ℝ E] (hcov : cov.IsCompatible) +-- variable {I} in +lemma isCompatible_apply [FiniteDimensional ℝ F] (hcov : cov.IsCompatible) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : mfderiv% ⟪Y, Z⟫ x (X x) = ⟪∇ Y, X, Z⟫ x + ⟪Y, ∇ Z, X⟫ x := by rw [IsCompatible] at hcov @@ -358,17 +377,19 @@ lemma isCompatible_apply [FiniteDimensional ℝ E] (hcov : cov.IsCompatible) change (fromTangentSpace _ ((mfderiv I 𝓘(ℝ, ℝ) ⟪Y, Z⟫ x) (X x))) = _ exact isCompatible_apply_aux this -lemma isCompatible_iff [FiniteDimensional ℝ E] : - cov.IsCompatible ↔ ∀ {x : M} {X Y Z : (x : M) → TangentSpace I x} +open FiberBundle in +variable {I} [ContMDiffVectorBundle 1 F V I] in +lemma isCompatible_iff [FiniteDimensional ℝ F] : + cov.IsCompatible ↔ ∀ {x : M} {X : Π x, TangentSpace I x} {Y Z : (x : M) → V x} (_hX : MDiffAt (T% X) x) (_hY : MDiffAt (T% Y) x) (_hZ : MDiffAt (T% Z) x), mfderiv% ⟪Y, Z⟫ x (X x) = ⟪∇ Y, X, Z⟫ x + ⟪Y, ∇ Z, X⟫ x := by refine ⟨fun hcov x X Y Z hX hY hZ ↦ cov.isCompatible_apply hcov hY hZ, fun h ↦ ?_⟩ unfold IsCompatible - ext x X₀ Y₀ Z₀ + ext x Y₀ Z₀ X₀ rw [compatibilityTensor_apply_eq_extend, sub_sub, sub_eq_iff_eq_add'] simp only [Pi.zero_apply, ContinuousLinearMap.zero_apply, add_zero] - have h' := h (mdifferentiableAt_extend I E Z₀) (mdifferentiableAt_extend I E X₀) - (mdifferentiableAt_extend I E Y₀) + have h' := h (mdifferentiableAt_extend I E X₀) (mdifferentiableAt_extend I F Y₀) + (mdifferentiableAt_extend I F Z₀) simpa [fromTangentSpace, extend_apply_self] using h' end CovariantDerivative From 3de90433e4704fe64ee5b650962fd26c47db2eca Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Sat, 7 Mar 2026 10:59:09 +0000 Subject: [PATCH 18/33] update notation after generalisation --- .../CovariantDerivative/Metric.lean | 167 +++++++++--------- 1 file changed, 82 insertions(+), 85 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index c308e08ea9a841..84edd402ac5a33 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -14,13 +14,13 @@ public import Mathlib.Geometry.Manifold.MfDerivSMul This file defines connections on a Riemannian vector bundle which are compatible with the ambient metric. A bundled connection `∇` on a Riemannian vector bundle `(V, g)` is compatible with the metric `g` if and only if the differentiated metric tensor `∇ g` (defined by -`(X, Y, Z) ↦ ∇ₓ g(Y, Z) - g(∇ₓ Y, Z) - g(Y, ∇ₓ Z)`) vanishes on all differentiable vector fields `X` -and differentiable sections `Y`, `Z`. +`(X, σ, τ) ↦ ∇ₓ g(σ, τ) - g(∇ₓ σ, τ) - g(σ, ∇ₓ τ)`) vanishes on all differentiable vector fields `X` +and differentiable sections `σ`, `τ`. ## Main definitions and results * `CovariantDerivative.compatibilityTensor`: the tensor - `(X, Y, Z) ↦ ∇ₓ g(Y, Z) - g(∇ₓ Y, Z) - g(Y, ∇ₓ Z)` defining when a connection `∇` on a Riemannian + `(X, σ, τ) ↦ ∇ₓ g(σ, τ) - g(∇ₓ σ, τ) - g(σ, ∇ₓ τ)` defining when a connection `∇` on a Riemannian vector bundle `(V, g)` is compatible with the metric `g`. * `CovariantDerivative.compatibilityTensor_apply` and `CovariantDerivative.compatibilityTensor_apply` give formulas for applying the compatibility @@ -59,88 +59,86 @@ variable [∀ x, IsTopologicalAddGroup (V x)] [∀ x, ContinuousSMul ℝ (V x)] [FiberBundle F V] [RiemannianBundle V] -variable {E' : Type*} [NormedAddCommGroup E'] [NormedSpace ℝ E'] +/-! Compatible connections: a connection on `V` is compatible with the metric on `V` iff +`∇ X ⟨σ, τ⟩ = ⟨∇ X σ, τ⟩ + ⟨σ, ∇ X τ⟩` holds for all sufficiently nice vector fields `X` on `M` and +sections `σ`, `τ` of `V`. In our definition, we ask for this identity to at each `x : M`, whenever +`X`, `σ` and `τ` are differentiable at `x`. +The left hand side is the pushforward of the function `⟨σ, τ⟩` along the vector field `X`: +the left hand side at `x` is `df(X x)`, where `f := ⟨σ, τ⟩`. -/ -/-! Compatible connections: a connection on `V` is compatible with the metric on `M` iff -`∇ X ⟨Y, Z⟩ = ⟨∇ X Y, Z⟩ + ⟨Y, ∇ X Z⟩` holds for all sufficiently nice vector fields `X` on `M` and -sections `Y`, `Z` of `V`. In our definition, we ask for this identity to at each `x : M`, whenever -`X`, `Y` and `Z` are differentiable at `x`. -The left hand side is the pushforward of the function `⟨Y, Z⟩` along the vector field `X`: -the left hand side at `x` is `df(X x)`, where `f := ⟨Y, Z⟩`. -/ +variable {σ σ' σ'' τ τ' τ'' : Π x : M, V x} -variable {X X' X'' Y Y' Y'' Z Z' : Π x : M, V x} +/-- The scalar product of two sections. -/ +noncomputable abbrev product (σ τ : Π x : M, V x) : M → ℝ := + fun x ↦ inner ℝ (σ x) (τ x) -/-- The scalar product of two vector fields -/ -noncomputable abbrev product (X Y : Π x : M, V x) : M → ℝ := - fun x ↦ inner ℝ (X x) (Y x) +-- `product` is C^k if σ and τ are: this is shown in `Riemannian.lean` --- `product` is C^k if X and Y are: this is shown in `Riemannian.lean` +local notation "⟪" σ ", " τ "⟫" => product σ τ -local notation "⟪" X ", " Y "⟫" => product X Y - --- Basic API for the product of two vector fields. +-- Basic API for the product of two sections. section product omit [TopologicalSpace M] [IsManifold I 2 M] -lemma product_apply (x) : ⟪X, Y⟫ x = inner ℝ (X x) (Y x) := rfl +lemma product_apply (x) : ⟪σ, τ⟫ x = inner ℝ (σ x) (τ x) := rfl -variable (X X' Y) +variable (σ σ' τ) -lemma product_swap : ⟪Y, X⟫ = ⟪X, Y⟫ := by +lemma product_swap : ⟪τ, σ⟫ = ⟪σ, τ⟫ := by ext x apply real_inner_comm @[simp] -lemma product_zero_left : ⟪0, X⟫ = 0 := by +lemma product_zero_left : ⟪0, σ⟫ = 0 := by ext x simp [product] @[simp] -lemma product_zero_right : ⟪X, 0⟫ = 0 := by rw [product_swap, product_zero_left] +lemma product_zero_right : ⟪σ, 0⟫ = 0 := by rw [product_swap, product_zero_left] -lemma product_add_left : ⟪X + X', Y⟫ = ⟪X, Y⟫ + ⟪X', Y⟫ := by +lemma product_add_left : ⟪σ + σ', τ⟫ = ⟪σ, τ⟫ + ⟪σ', τ⟫ := by ext x simp [product, InnerProductSpace.add_left] @[simp] -lemma product_add_left_apply (x) : ⟪X + X', Y⟫ x = ⟪X, Y⟫ x + ⟪X', Y⟫ x := by +lemma product_add_left_apply (x) : ⟪σ + σ', τ⟫ x = ⟪σ, τ⟫ x + ⟪σ', τ⟫ x := by simp [product, InnerProductSpace.add_left] -lemma product_add_right : ⟪X, Y + Y'⟫ = ⟪X, Y⟫ + ⟪X, Y'⟫ := by - rw [product_swap, product_swap Y, product_swap Y', product_add_left] +lemma product_add_right : ⟪σ, τ + τ'⟫ = ⟪σ, τ⟫ + ⟪σ, τ'⟫ := by + rw [product_swap, product_swap τ, product_swap τ', product_add_left] @[simp] -lemma product_add_right_apply (x) : ⟪X, Y + Y'⟫ x = ⟪X, Y⟫ x + ⟪X, Y'⟫ x := by - rw [product_swap, product_swap Y, product_swap Y', product_add_left_apply] +lemma product_add_right_apply (x) : ⟪σ, τ + τ'⟫ x = ⟪σ, τ⟫ x + ⟪σ, τ'⟫ x := by + rw [product_swap, product_swap τ, product_swap τ', product_add_left_apply] -@[simp] lemma product_neg_left : ⟪-X, Y⟫ = -⟪X, Y⟫ := by ext x; simp [product] +@[simp] lemma product_neg_left : ⟪-σ, τ⟫ = -⟪σ, τ⟫ := by ext x; simp [product] -@[simp] lemma product_neg_right : ⟪X, -Y⟫ = -⟪X, Y⟫ := by ext x; simp [product] +@[simp] lemma product_neg_right : ⟪σ, -τ⟫ = -⟪σ, τ⟫ := by ext x; simp [product] -lemma product_sub_left : ⟪X - X', Y⟫ = ⟪X, Y⟫ - ⟪X', Y⟫ := by +lemma product_sub_left : ⟪σ - σ', τ⟫ = ⟪σ, τ⟫ - ⟪σ', τ⟫ := by ext x simp [product, inner_sub_left] -lemma product_sub_right : ⟪X, Y - Y'⟫ = ⟪X, Y⟫ - ⟪X, Y'⟫ := by +lemma product_sub_right : ⟪σ, τ - τ'⟫ = ⟪σ, τ⟫ - ⟪σ, τ'⟫ := by ext x simp [product, inner_sub_right] -lemma product_smul_left (f : M → ℝ) : product (f • X) Y = f • product X Y := by +lemma product_smul_left (f : M → ℝ) : product (f • σ) τ = f • product σ τ := by ext x simp [product, real_inner_smul_left] @[simp] -lemma product_smul_const_left (a : ℝ) : product (a • X) Y = a • product X Y := by +lemma product_smul_const_left (a : ℝ) : product (a • σ) τ = a • product σ τ := by ext x simp [product, real_inner_smul_left] -lemma product_smul_right (f : M → ℝ) : product X (f • Y) = f • product X Y := by +lemma product_smul_right (f : M → ℝ) : product σ (f • τ) = f • product σ τ := by ext x simp [product, real_inner_smul_right] @[simp] -lemma product_smul_const_right (a : ℝ) : product X (a • Y) = a • product X Y := by +lemma product_smul_const_right (a : ℝ) : product σ (a • τ) = a • product σ τ := by ext x simp [product, real_inner_smul_right] @@ -149,23 +147,23 @@ end product -- These lemmas are necessary as my Lie bracket identities (assuming minimal differentiability) -- only hold point-wise. They abstract the expanding and unexpanding of `product`. omit [TopologicalSpace M] [IsManifold I 2 M] in -lemma product_congr_left {x} (h : X x = X' x) : product X Y x = product X' Y x := by +lemma product_congr_left {x} (h : σ x = σ' x) : product σ τ x = product σ' τ x := by rw [product_apply, h, ← product_apply] omit [TopologicalSpace M] [IsManifold I 2 M] in -lemma product_congr_left₂ {x} (h : X x = X' x + X'' x) : - product X Y x = product X' Y x + product X'' Y x := by +lemma product_congr_left₂ {x} (h : σ x = σ' x + σ'' x) : + product σ τ x = product σ' τ x + product σ'' τ x := by rw [product_apply, h, inner_add_left, ← product_apply] omit [TopologicalSpace M] [IsManifold I 2 M] in -lemma product_congr_right {x} (h : Y x = Y' x) : product X Y x = product X Y' x := by +lemma product_congr_right {x} (h : τ x = τ' x) : product σ τ x = product σ τ' x := by rw [product_apply, h, ← product_apply] omit [TopologicalSpace M] [IsManifold I 2 M] in -lemma product_congr_right₂ {x} (h : Y x = Y' x + Y'' x) : - product X Y x = product X Y' x + product X Y'' x := by +lemma product_congr_right₂ {x} (h : τ x = τ' x + τ'' x) : + product σ τ x = product σ τ' x + product σ τ'' x := by rw [product_apply, h, inner_add_right, ← product_apply] -/- TODO: writing `hY.inner_bundle hZ` or writing `by apply MDifferentiable.inner_bundle hY hZ` +/- TODO: writing `hσ.inner_bundle hτ` or writing `by apply MDifferentiable.inner_bundle hσ hτ` yields an error synthesized type class instance is not definitionally equal to expression inferred by typing rules, synthesized @@ -175,13 +173,13 @@ inferred Diagnose and fix this, and then replace the below by `MDifferentiable(At).inner_bundle! -/ variable {F} [VectorBundle ℝ F V] [IsContMDiffRiemannianBundle I 1 F V] {I} in -lemma MDifferentiable.inner_bundle' (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : MDiff ⟪Y, Z⟫ := - MDifferentiable.inner_bundle hY hZ +lemma MDifferentiable.inner_bundle' (hσ : MDiff (T% σ)) (hτ : MDiff (T% τ)) : MDiff ⟪σ, τ⟫ := + MDifferentiable.inner_bundle hσ hτ variable {F} [VectorBundle ℝ F V] [IsContMDiffRiemannianBundle I 1 F V] {I} in -lemma MDifferentiableAt.inner_bundle' {x} (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : - MDiffAt ⟪Y, Z⟫ x := - MDifferentiableAt.inner_bundle hY hZ +lemma MDifferentiableAt.inner_bundle' {x} (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : + MDiffAt ⟪σ, τ⟫ x := + MDifferentiableAt.inner_bundle hσ hτ namespace CovariantDerivative @@ -189,23 +187,23 @@ namespace CovariantDerivative -- TODO: include in cheat sheet! variable (cov : CovariantDerivative I F V) -/-- Local notation for a connection. Caution: `∇ Y, X` corresponds to `∇ₓ Y` in textbooks -/ -local notation "∇" Y "," X => fun (x:M) ↦ cov Y x (X x) +/-- Local notation for a connection. Caution: `∇ σ, X` corresponds to `∇ₓ σ` in textbooks -/ +local notation "∇" σ "," X => fun (x:M) ↦ cov σ x (X x) variable {F} /-- The function defining the compatibility tensor for `∇` w.r.t. `g`: prefer using `compatibilityTensor` instead -/ -noncomputable def compatibilityTensorAux (Y Z : Π x : M, V x) : +noncomputable def compatibilityTensorAux (σ τ : Π x : M, V x) : Π (x : M), TangentSpace I x →L[ℝ] ℝ := fun x ↦ - letI b : TangentSpace I x →L[ℝ] ℝ := mfderiv% ⟪Y, Z⟫ x - b - ((innerSL ℝ (Z x)) ∘L (cov Y x)) - ((innerSL ℝ (Y x)) ∘L (cov Z x)) + letI b : TangentSpace I x →L[ℝ] ℝ := mfderiv% ⟪σ, τ⟫ x + b - ((innerSL ℝ (τ x)) ∘L (cov σ x)) - ((innerSL ℝ (σ x)) ∘L (cov τ x)) -lemma compatibilityTensorAux_apply (Y Z : Π x : M, V x) +lemma compatibilityTensorAux_apply (σ τ : Π x : M, V x) {x : M} (X₀ : TangentSpace I x) : - compatibilityTensorAux I cov Y Z x X₀ = - NormedSpace.fromTangentSpace _ (mfderiv% ⟪Y, Z⟫ x X₀) - - innerSL ℝ (Z x) (cov Y x X₀) - innerSL ℝ (Y x) (cov Z x X₀) := by + compatibilityTensorAux I cov σ τ x X₀ = + NormedSpace.fromTangentSpace _ (mfderiv% ⟪σ, τ⟫ x X₀) + - innerSL ℝ (τ x) (cov σ x X₀) - innerSL ℝ (σ x) (cov τ x X₀) := by unfold compatibilityTensorAux simp congr 1 @@ -316,7 +314,7 @@ theorem compatibilityTensorAux_tensorial₂ (σ : Π x, V x) (hσ : MDiffAt (T% add hτ hτ' := aux4 cov _ _ _ hσ hτ hτ' variable {I} [ContMDiffVectorBundle 1 F V I] in -/-- The tensor `(X, Y, Z) ↦ ∇ₓ g(Y, Z) - g(∇ₓ Y, Z) - g(Y, ∇ₓ Z)` defining when a connection +/-- The tensor `(X, σ, τ) ↦ ∇ₓ g(σ, τ) - g(∇ₓ σ, τ) - g(σ, ∇ₓ τ)` defining when a connection `∇` on a Riemannian bundle `(M, V)` is compatible with the metric `g`. -/ @[no_expose] noncomputable def compatibilityTensor [FiniteDimensional ℝ F] (x : M) : V x →L[ℝ] V x →L[ℝ] (TangentSpace I x →L[ℝ] ℝ) := @@ -327,11 +325,11 @@ variable {X : Π x : M, TangentSpace I x} variable {I} [ContMDiffVectorBundle 1 F V I] in theorem compatibilityTensor_apply [FiniteDimensional ℝ F] (x : M) - (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : - compatibilityTensor cov x (Y x) (Z x) (X x) = - fromTangentSpace _ (mfderiv% ⟪Y, Z⟫ x (X x)) - ⟪∇ Y, X, Z⟫ x - ⟪Y, ∇ Z, X⟫ x := by + (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : + compatibilityTensor cov x (σ x) (τ x) (X x) = + fromTangentSpace _ (mfderiv% ⟪σ, τ⟫ x (X x)) - ⟪∇ σ, X, τ⟫ x - ⟪σ, ∇ τ, X⟫ x := by unfold compatibilityTensor - rw [TensorialAt.mkHom₂_apply _ _ hY hZ] + rw [TensorialAt.mkHom₂_apply _ _ hσ hτ] --rw [compatibilityTensorAux_apply] simp only [compatibilityTensorAux, ContinuousLinearMap.coe_sub', ContinuousLinearMap.coe_comp', coe_innerSL_apply, Pi.sub_apply, comp_apply] @@ -346,19 +344,18 @@ theorem compatibilityTensor_apply [FiniteDimensional ℝ F] (x : M) open FiberBundle in variable {I} [ContMDiffVectorBundle 1 F V I] in theorem compatibilityTensor_apply_eq_extend [FiniteDimensional ℝ F] (X₀ : TangentSpace I x) - (Y₀ Z₀ : V x) : - compatibilityTensor cov x Y₀ Z₀ X₀ = - fromTangentSpace _ (mfderiv% ⟪(extend F Y₀), (extend F Z₀)⟫ x X₀) - - ⟪∇ extend F Y₀, (extend E X₀), extend F Z₀⟫ x - - ⟪extend F Y₀, ∇ extend F Z₀, (extend E X₀)⟫ x := by + (σ₀ τ₀ : V x) : + compatibilityTensor cov x σ₀ τ₀ X₀ = + fromTangentSpace _ (mfderiv% ⟪(extend F σ₀), (extend F τ₀)⟫ x X₀) + - ⟪∇ extend F σ₀, (extend E X₀), extend F τ₀⟫ x + - ⟪extend F σ₀, ∇ extend F τ₀, (extend E X₀)⟫ x := by simpa [extend_apply_self] using compatibilityTensor_apply cov x - (X := extend E X₀) (mdifferentiableAt_extend I F Y₀) (mdifferentiableAt_extend I F Z₀) + (X := extend E X₀) (mdifferentiableAt_extend I F σ₀) (mdifferentiableAt_extend I F τ₀) variable {I} [ContMDiffVectorBundle 1 F V I] in -/-- Predicate saying for a connection `∇` on a Riemannian bundle `(V, g)` to be compatible with -the ambient metric, i.e. for all differentiable vector fields `X` on `M` and sections `Y` and `Z` -of `V`, we have -`X ⟨Y, Z⟩ = ⟨∇ X Y, Z⟩ + ⟨Y, ∇ X Z⟩`. -/ +/-- Predicate saying that a connection `∇` on a Riemannian bundle `(V, g)` is compatible with the +ambient metric, i.e. for all differentiable vector fields `X` on `M` and sections `σ` and `τ` of +`V`, we have `X ⟨σ, τ⟩ = ⟨∇ X σ, τ⟩ + ⟨σ, ∇ X τ⟩`. -/ def IsCompatible [FiniteDimensional ℝ F] : Prop := compatibilityTensor cov = 0 -- Auxiliary computation for `IsCompatible_apply`. @@ -369,27 +366,27 @@ variable {I} [ContMDiffVectorBundle 1 F V I] in -- TODO: give a better name; maybe inline? -- variable {I} in lemma isCompatible_apply [FiniteDimensional ℝ F] (hcov : cov.IsCompatible) - (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : - mfderiv% ⟪Y, Z⟫ x (X x) = ⟪∇ Y, X, Z⟫ x + ⟪Y, ∇ Z, X⟫ x := by + (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : + mfderiv% ⟪σ, τ⟫ x (X x) = ⟪∇ σ, X, τ⟫ x + ⟪σ, ∇ τ, X⟫ x := by rw [IsCompatible] at hcov - have : compatibilityTensor cov x (Y x) (Z x) (X x) = 0 := by simp [hcov] - rw [compatibilityTensor_apply cov x hY hZ] at this - change (fromTangentSpace _ ((mfderiv I 𝓘(ℝ, ℝ) ⟪Y, Z⟫ x) (X x))) = _ + have : compatibilityTensor cov x (σ x) (τ x) (X x) = 0 := by simp [hcov] + rw [compatibilityTensor_apply cov x hσ hτ] at this + change (fromTangentSpace _ ((mfderiv I 𝓘(ℝ, ℝ) ⟪σ, τ⟫ x) (X x))) = _ exact isCompatible_apply_aux this open FiberBundle in variable {I} [ContMDiffVectorBundle 1 F V I] in lemma isCompatible_iff [FiniteDimensional ℝ F] : - cov.IsCompatible ↔ ∀ {x : M} {X : Π x, TangentSpace I x} {Y Z : (x : M) → V x} - (_hX : MDiffAt (T% X) x) (_hY : MDiffAt (T% Y) x) (_hZ : MDiffAt (T% Z) x), - mfderiv% ⟪Y, Z⟫ x (X x) = ⟪∇ Y, X, Z⟫ x + ⟪Y, ∇ Z, X⟫ x := by - refine ⟨fun hcov x X Y Z hX hY hZ ↦ cov.isCompatible_apply hcov hY hZ, fun h ↦ ?_⟩ + cov.IsCompatible ↔ ∀ {x : M} {X : Π x, TangentSpace I x} {σ τ : (x : M) → V x} + (_hX : MDiffAt (T% X) x) (_hσ : MDiffAt (T% σ) x) (_hτ : MDiffAt (T% τ) x), + mfderiv% ⟪σ, τ⟫ x (X x) = ⟪∇ σ, X, τ⟫ x + ⟪σ, ∇ τ, X⟫ x := by + refine ⟨fun hcov x X σ τ hX hσ hτ ↦ cov.isCompatible_apply hcov hσ hτ, fun h ↦ ?_⟩ unfold IsCompatible - ext x Y₀ Z₀ X₀ + ext x σ₀ τ₀ X₀ rw [compatibilityTensor_apply_eq_extend, sub_sub, sub_eq_iff_eq_add'] simp only [Pi.zero_apply, ContinuousLinearMap.zero_apply, add_zero] - have h' := h (mdifferentiableAt_extend I E X₀) (mdifferentiableAt_extend I F Y₀) - (mdifferentiableAt_extend I F Z₀) + have h' := h (mdifferentiableAt_extend I E X₀) (mdifferentiableAt_extend I F σ₀) + (mdifferentiableAt_extend I F τ₀) simpa [fromTangentSpace, extend_apply_self] using h' end CovariantDerivative From 4dcac6ec1224f7032a4b14b74deadd7ab4819278 Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:29:22 +0000 Subject: [PATCH 19/33] adjust after rewrite of mfderiv_sul --- Mathlib.lean | 1 - .../Manifold/MFDeriv/NormedSpace.lean | 139 +++++++++++++++++- Mathlib/Geometry/Manifold/MfDerivSMul.lean | 60 -------- .../CovariantDerivative/Metric.lean | 51 ++----- 4 files changed, 146 insertions(+), 105 deletions(-) delete mode 100644 Mathlib/Geometry/Manifold/MfDerivSMul.lean diff --git a/Mathlib.lean b/Mathlib.lean index d87f8f9e8123d8..359e23eb09b300 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4413,7 +4413,6 @@ public import Mathlib.Geometry.Manifold.MFDeriv.SpecificFunctions public import Mathlib.Geometry.Manifold.MFDeriv.Tangent public import Mathlib.Geometry.Manifold.MFDeriv.UniqueDifferential public import Mathlib.Geometry.Manifold.Metrizable -public import Mathlib.Geometry.Manifold.MfDerivSMul public import Mathlib.Geometry.Manifold.Notation public import Mathlib.Geometry.Manifold.PartitionOfUnity public import Mathlib.Geometry.Manifold.PoincareConjecture diff --git a/Mathlib/Geometry/Manifold/MFDeriv/NormedSpace.lean b/Mathlib/Geometry/Manifold/MFDeriv/NormedSpace.lean index 27834bd6e59b25..7b8495ffe9dec6 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/NormedSpace.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/NormedSpace.lean @@ -283,22 +283,151 @@ theorem MDifferentiable.clm_prodMap {g : M → F₁ →L[𝕜] F₃} {f : M → /-! ### Differentiability of scalar multiplication -/ -variable {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] +section smul + +open NormedSpace ContinuousLinearMap -theorem MDifferentiableWithinAt.smul {f : M → 𝕜} {g : M → V} +variable {V : Type*} [NormedAddCommGroup V] [NormedSpace 𝕜 V] +variable {f : M → 𝕜} {g : M → V} + +/-- Given maps `f`, `g` from a manifold into a field `𝕜` and `𝕜`-vector space `V`, respectively, if +at some point `x`, `f` has differential `f' : TangentSpace I x →L[𝕜] 𝕜` and `g` has differential +`g' : TangentSpace I x →L[𝕜] V` (both phrased using the predicate `HasMFDerivAt`), it follows that +their scalar multiplication `f • g` has differential `f x • g' + toSpanSingleton 𝕜 (g x) ∘L f'`. + +In fact, the statement above is not literally true, because, for example, the differential of `g` +really takes values in the tangent space to `V` at `g x`, rather than in `V` itself. Of course, this +tangent space can be canonically identified with `V`. + +This lemma phrases the formula using the equiv `NormedSpace.fromTangentSpace`, which provides this +canonical identification. (It would also be possible to phrase the formula without this equiv, +instead using casting and definitional abuse.) -/ +lemma HasMFDerivAt.smul + {f' : TangentSpace I x →L[𝕜] 𝕜} + (hs : HasMFDerivAt I 𝓘(𝕜, 𝕜) f x ((fromTangentSpace _).symm.toContinuousLinearMap ∘L f')) + {g' : TangentSpace I x →L[𝕜] V} + (hg : HasMFDerivAt I 𝓘(𝕜, V) g x ((fromTangentSpace _).symm.toContinuousLinearMap ∘L g')) : + -- canonically identify `g'` with a linear map into the tangent space at `(f • g) x` + letI g'_ : TangentSpace I x →L[𝕜] TangentSpace 𝓘(𝕜, V) ((f • g) x) := + (fromTangentSpace _).symm.toContinuousLinearMap ∘L g' + -- canonically identify `g x` with a linear map into a tangent space at `(f • g) x` + letI gx : 𝕜 →L[𝕜] TangentSpace 𝓘(𝕜, V) ((f • g) x) := + toSpanSingleton 𝕜 ((fromTangentSpace _).symm (g x)) + -- now the main statement typechecks + HasMFDerivAt I 𝓘(𝕜, V) (f • g) x (f x • g'_ + gx ∘L f') := by + constructor + · exact hs.1.smul hg.1 + · simpa using hs.2.smul hg.2 + +theorem MDifferentiableWithinAt.smul (hf : MDifferentiableWithinAt I 𝓘(𝕜) f s x) (hg : MDifferentiableWithinAt I 𝓘(𝕜, V) g s x) : MDifferentiableWithinAt I 𝓘(𝕜, V) (fun p => f p • g p) s x := ((contMDiff_smul.of_le le_top).mdifferentiable one_ne_zero _).comp_mdifferentiableWithinAt x (hf.prodMk hg) -theorem MDifferentiableAt.smul {f : M → 𝕜} {g : M → V} (hf : MDifferentiableAt I 𝓘(𝕜) f x) +theorem MDifferentiableAt.smul (hf : MDifferentiableAt I 𝓘(𝕜) f x) (hg : MDifferentiableAt I 𝓘(𝕜, V) g x) : MDifferentiableAt I 𝓘(𝕜, V) (fun p => f p • g p) x := ((contMDiff_smul.of_le le_top).mdifferentiable one_ne_zero _).comp x (hf.prodMk hg) -theorem MDifferentiableOn.smul {f : M → 𝕜} {g : M → V} (hf : MDifferentiableOn I 𝓘(𝕜) f s) +theorem MDifferentiableOn.smul (hf : MDifferentiableOn I 𝓘(𝕜) f s) (hg : MDifferentiableOn I 𝓘(𝕜, V) g s) : MDifferentiableOn I 𝓘(𝕜, V) (fun p => f p • g p) s := fun x hx => (hf x hx).smul (hg x hx) -theorem MDifferentiable.smul {f : M → 𝕜} {g : M → V} (hf : MDifferentiable I 𝓘(𝕜) f) +theorem MDifferentiable.smul (hf : MDifferentiable I 𝓘(𝕜) f) (hg : MDifferentiable I 𝓘(𝕜, V) g) : MDifferentiable I 𝓘(𝕜, V) fun p => f p • g p := fun x => (hf x).smul (hg x) + +/-- Given maps `f`, `g` from a manifold into a field `𝕜` and `𝕜`-vector space `V`, respectively, the +formula for the `mfderiv` (differential) of their scalar multiplication `f • g`. + +Mathematically speaking the formula is `d(f • g) = f • dg + df ⊗ g`, i.e. +`mfderiv% (f • g) x = f x • mfderiv% g x + toSpanSingleton 𝕜 (g x) ∘L mfderiv% f x`, +but this doesn't typecheck because `mfderiv% (f • g) x` and `mfderiv% g x` take values in different +tangent spaces -- respectively the tangent spaces to `V` at `(f • g) x` and `g x`. Of course, both +these tangent spaces can be canonically identified with `V`. + +This lemma phrases the formula using the equiv `NormedSpace.fromTangentSpace`, which provides this +canonical identification. (It would also be possible to phrase the formula without this equiv, +instead using casting and definitional abuse.) + +It is good practice to use the equiv `NormedSpace.fromTangentSpace` throughout a computation. If +this is done, typically `mfderiv% (f • g) x` will only turn up paired with this equiv (i.e., in an +expression `(fromTangentSpace _) ∘L mfderiv% (f • g) x`), and the more convenient lemma +`fromTangentSpace_mfderiv_smul` (see below) can be used instead. -/ +lemma mfderiv_smul (hf : MDiffAt f x) (hg : MDiffAt g x) : + mfderiv% (f • g) x + = f x • (fromTangentSpace _).symm.toContinuousLinearMap ∘L + ((fromTangentSpace (g x)).toContinuousLinearMap ∘L mfderiv% g x) + + toSpanSingleton 𝕜 ((fromTangentSpace _).symm (g x)) ∘L + ((fromTangentSpace (f x)).toContinuousLinearMap ∘L mfderiv% f x) := + (hf.hasMFDerivAt.smul hg.hasMFDerivAt).mfderiv + +/-- Given maps `f`, `g` from a manifold into a field `𝕜` and `𝕜`-vector space `V`, respectively, the +formula for the `mfderiv` (differential) of their scalar multiplication `f • g`. + +Mathematically speaking the formula is `d(f • g) = f • dg + df ⊗ g`, i.e. +`mfderiv% (f • g) x = f x • mfderiv% g x + toSpanSingleton 𝕜 (g x) ∘L mfderiv% f x`, +but this doesn't typecheck because `mfderiv% (f • g) x` and `mfderiv% g x` take values in different +tangent spaces -- respectively the tangent spaces to `V` at `(f • g) x` and `g x`. Of course, both +these tangent spaces can be canonically identified with `V`. + +This lemma phrases the formula using the equiv `NormedSpace.fromTangentSpace`, which provides this +canonical identification. (It would also be possible to phrase the formula without this equiv, +instead using casting and definitional abuse.) -/ +lemma fromTangentSpace_mfderiv_smul (hf : MDiffAt f x) (hg : MDiffAt g x) : + (fromTangentSpace ((f • g) x)).toContinuousLinearMap ∘L mfderiv% (f • g) x + = f x • (fromTangentSpace _).toContinuousLinearMap ∘L mfderiv% g x + + toSpanSingleton 𝕜 (g x) ∘L (fromTangentSpace _).toContinuousLinearMap ∘L mfderiv% f x := by + rw [mfderiv_smul hf hg] + rfl + +/-- Given maps `f`, `g` from a manifold into a field `𝕜` and `𝕜`-vector space `V`, respectively, the +formula for the `mfderiv` (differential) of their scalar multiplication `f • g`. + +Mathematically speaking the formula is `d(f • g) = f • dg + df ⊗ g`, but to get it to typecheck +we need a phrasing involving the canonical identification `NormedSpace.fromTangentSpace` between +the vector space `V` and the tangent space to this vector space at any point. This is because two +different tangent spaces (at `(f • g) x` and `g x`) appear in the equation. + +This is a defeq variant of the main lemma `fromTangentSpace_mfderiv_smul`, in which we work in the +tangent space at `f x • g x` (the simp-normal form) rather than at `(f • g) x`. -/ +lemma fromTangentSpace_mfderiv_smul' (hf : MDiffAt f x) (hg : MDiffAt g x) : + (fromTangentSpace (f x • g x)).toContinuousLinearMap ∘L mfderiv% (f • g) x + = f x • (fromTangentSpace _).toContinuousLinearMap ∘L mfderiv% g x + + toSpanSingleton 𝕜 (g x) ∘L (fromTangentSpace _).toContinuousLinearMap ∘L mfderiv% f x := + fromTangentSpace_mfderiv_smul hf hg + +/-- Given maps `f`, `g` from a manifold into a field `𝕜` and `𝕜`-vector space `V`, respectively, the +formula for the `mfderiv` (differential) of their scalar multiplication `f • g` in the direction of +the tangent vector `v`. + +Mathematically speaking the formula is `d(f • g)(v) = f • dg(v) + df(v) • g`, but to get it to +typecheck we need a phrasing involving the canonical identification `NormedSpace.fromTangentSpace` +between the vector space `V` and the tangent space to this vector space at any point. This is +because two different tangent spaces (at `(f • g) x` and `g x`) appear in the equation. -/ +lemma fromTangentSpace_mfderiv_smul_apply (hf : MDiffAt f x) (hg : MDiffAt g x) + (v : TangentSpace I x) : + fromTangentSpace _ (mfderiv% (f • g) x v) + = f x • fromTangentSpace _ (mfderiv% g x v) + + fromTangentSpace _ (mfderiv% f x v) • g x := by + simpa using congr($(fromTangentSpace_mfderiv_smul hf hg) v) + +/-- Given maps `f`, `g` from a manifold into a field `𝕜` and `𝕜`-vector space `V`, respectively, the +formula for the `mfderiv` (differential) of their scalar multiplication `f • g` in the direction of +the tangent vector `v`. + +Mathematically speaking the formula is `d(f • g)(v) = f • dg(v) + df(v) • g`, but to get it to +typecheck we need a phrasing involving the canonical identification `NormedSpace.fromTangentSpace` +between the vector space `V` and the tangent space to this vector space at any point. This is +because two different tangent spaces (at `(f • g) x` and `g x`) appear in the equation. + +This is a defeq variant of the main lemma `fromTangentSpace_mfderiv_smul_apply`, in which we work in +the tangent space at `f x • g x` (the simp-normal form) rather than at `(f • g) x`. -/ +lemma fromTangentSpace_mfderiv_smul_apply' (hf : MDiffAt f x) (hg : MDiffAt g x) + (v : TangentSpace I x) : + fromTangentSpace (f x • g x) (mfderiv% (f • g) x v) + = f x • fromTangentSpace _ (mfderiv% g x v) + + fromTangentSpace _ (mfderiv% f x v) • g x := + fromTangentSpace_mfderiv_smul_apply hf hg v + +end smul diff --git a/Mathlib/Geometry/Manifold/MfDerivSMul.lean b/Mathlib/Geometry/Manifold/MfDerivSMul.lean deleted file mode 100644 index 0e0da7381379b8..00000000000000 --- a/Mathlib/Geometry/Manifold/MfDerivSMul.lean +++ /dev/null @@ -1,60 +0,0 @@ -/- -Copyright (c) 2025 Patrick Massot. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Michael Rothgang --/ -module - -public import Mathlib.Geometry.Manifold.MFDeriv.Atlas -public import Mathlib.Geometry.Manifold.MFDeriv.NormedSpace -public import Mathlib.Geometry.Manifold.MFDeriv.SpecificFunctions -import Mathlib.Geometry.Manifold.Notation - -/-! # `mfderiv` and scalar multiplication -/ - -open Set -open scoped Manifold ContDiff - -@[expose] public section mfderiv - -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] - {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] - {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} - {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [IsManifold I 1 M] - {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] - {f : M → F} {s : M → 𝕜} {x : M} - -theorem MDifferentiableAt.differentiableAt_comp_chartAt_symm - (hs : MDiffAt f x) : - letI φ := chartAt H x; - DifferentiableWithinAt 𝕜 (f ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := by - have hφ := mdifferentiableWithinAt_extChartAt_symm (mem_extChartAt_target x) (I := I) - rw [← extChartAt_to_inv x (I := I)] at hs - have := hs.comp_mdifferentiableWithinAt (extChartAt I x x) hφ - exact mdifferentiableWithinAt_iff_differentiableWithinAt.mp this - -lemma mfderiv_smul (hf : MDiffAt f x) - (hs : MDiffAt s x) (v : TangentSpace I x) : - letI dsxv := NormedSpace.fromTangentSpace (s x) (mfderiv% s x v) - letI dfxv := NormedSpace.fromTangentSpace (f x) (mfderiv% f x v) - mfderiv% (s • f) x v = (s x) • dfxv + dsxv • f x := by - set φ := chartAt H x - -- TODO: inlining hs' or hf' breaks the proof, why? - have hs' : DifferentiableWithinAt 𝕜 (s ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := - hs.differentiableAt_comp_chartAt_symm - have aux := hs.differentiableAt_comp_chartAt_symm - have hf' : DifferentiableWithinAt 𝕜 (f ∘ φ.symm ∘ I.symm) (range I) (I (φ x)) := - hf.differentiableAt_comp_chartAt_symm - -- `have := hs.differentiableAt_comp_chartAt_symm` looks identical apart from unfolding φ - have hsf : MDiffAt (s • f) x := hs.smul hf - simp? [mfderiv, hsf, hs, hf] says - simp only [Pi.smul_apply', mfderiv, hsf, ↓reduceIte, writtenInExtChartAt, extChartAt, - OpenPartialHomeomorph.extend, modelWithCornersSelf_partialEquiv, PartialEquiv.trans_refl, - PartialEquiv.coe_trans_symm, OpenPartialHomeomorph.coe_coe_symm, - ModelWithCorners.toPartialEquiv_coe_symm, PartialEquiv.coe_trans, - ModelWithCorners.toPartialEquiv_coe, OpenPartialHomeomorph.toFun_eq_coe, Function.comp_apply, - hf, hs] - -- Use the defeq that `chartAt (s x)` and `chartAt (f x)` are the identity. - erw [fderivWithin_smul I.uniqueDiffWithinAt_image hs' hf'] - simp [φ.left_inv (ChartedSpace.mem_chart_source x)] - rfl diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index 84edd402ac5a33..d0dbe9c1ec14c1 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -7,7 +7,7 @@ module public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Basic public import Mathlib.Geometry.Manifold.VectorBundle.Riemannian -public import Mathlib.Geometry.Manifold.MfDerivSMul +public import Mathlib.Geometry.Manifold.MFDeriv.NormedSpace /-! # Metric connections @@ -215,16 +215,11 @@ private lemma aux1 {f : M → ℝ} {σ τ : (x : M) → V x} (hf : MDiffAt f x) (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : compatibilityTensorAux I cov (f • σ) τ x = f x • compatibilityTensorAux I cov σ τ x := by ext X₀ - rw [compatibilityTensorAux_apply, ContinuousLinearMap.coe_smul', Pi.smul_apply, - compatibilityTensorAux_apply] - rw [product_smul_left, cov.isCovariantDerivativeOn.leibniz hσ hf] - simp only [Pi.smul_apply', ContinuousLinearMap.add_apply, ContinuousLinearMap.coe_smul', - Pi.smul_apply, ContinuousLinearMap.coe_comp', ContinuousLinearEquiv.coe_coe, comp_apply, - ContinuousLinearMap.toSpanSingleton_apply, coe_innerSL_apply, map_smul] - erw [mfderiv_smul (hσ.inner_bundle' hτ) hf] -- identifying different tangent spaces - rw [inner_add_right, inner_smul_right, inner_smul_right, real_inner_comm (σ x) (τ x)] - simp only [← smul_eq_mul] - module + rw [compatibilityTensorAux_apply, product_smul_left, + fromTangentSpace_mfderiv_smul_apply hf (hσ.inner_bundle' hτ)] + simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.leibniz hσ hf, inner_add_right, + inner_smul_right, real_inner_comm] + ring variable {I} in private lemma aux2 (σ σ' τ : (x : M) → V x) @@ -258,34 +253,12 @@ variable {I} in private lemma aux3 {f : M → ℝ} {σ τ : (x : M) → V x} (hf : MDiffAt f x) (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : compatibilityTensorAux I cov σ (f • τ) x = f x • compatibilityTensorAux I cov σ τ x := by - unfold compatibilityTensorAux - rw [product_smul_right, cov.isCovariantDerivativeOn.leibniz hτ hf] - ext X - simp only [smul_eq_mul, Pi.smul_apply', map_smul, ContinuousLinearMap.smul_comp, - ContinuousLinearMap.comp_add, ContinuousLinearMap.comp_smulₛₗ, RingHom.id_apply, - ContinuousLinearMap.coe_sub', Pi.sub_apply, ContinuousLinearMap.add_apply, - ContinuousLinearMap.coe_smul', ContinuousLinearMap.coe_comp', coe_innerSL_apply, Pi.smul_apply, - comp_apply, ContinuousLinearEquiv.coe_coe, ContinuousLinearMap.toSpanSingleton_apply] - erw [ContinuousLinearMap.sub_apply, ContinuousLinearMap.sub_apply, ContinuousLinearMap.comp_apply] - --set A := inner ℝ (σ x) ((cov τ x) X) - conv => - enter [1, 1, 2] - erw [ContinuousLinearMap.smul_apply] - conv => - enter [1, 1, 2, 2] - erw [ContinuousLinearMap.comp_apply] - dsimp - --set B := inner ℝ (τ x) ((cov σ x) X) - erw [mfderiv_smul (hσ.inner_bundle' hτ) hf] - --set C := (mfderiv I 𝓘(ℝ, ℝ) ⟪σ, τ⟫ x) X - --set D := (mfderiv I 𝓘(ℝ, ℝ) f x) X - simp only [smul_eq_mul, fromTangentSpace, ContinuousLinearEquiv.coe_mk, LinearEquiv.coe_mk, - LinearMap.coe_mk, AddHom.coe_mk, inner_smul_right] - -- would be nice to finish by a tactic now! - erw [mul_add, mul_add] - rw [Pi.mul_apply, mul_neg, mul_neg, - ← sub_eq_add_neg, ← sub_eq_add_neg, sub_add_eq_sub_sub] - match_scalars <;> all_goals simp + ext X₀ + rw [compatibilityTensorAux_apply, product_smul_right, + fromTangentSpace_mfderiv_smul_apply hf (hσ.inner_bundle' hτ)] + simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.leibniz hτ hf, inner_add_right, + inner_smul_right, real_inner_comm] + ring variable {I} in private lemma aux4 (σ τ τ' : (x : M) → V x) From 91d1d2a9eb3b846105c7569c49ea7f0a581e40f2 Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:33:10 +0000 Subject: [PATCH 20/33] docs --- .../VectorBundle/CovariantDerivative/Metric.lean | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index d0dbe9c1ec14c1..a28e9ce426cce9 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -32,10 +32,15 @@ and differentiable sections `σ`, `τ`. ## TODO -* when mathlib has a notion of parallel transport, prove the equivalence of - `CovariantDerivative.IsCompatible` with the characterisation that parallel transport be an +* When Mathlib has a notion of parallel transport, prove the equivalence of + `CovariantDerivative.IsCompatible` with the characterisation that parallel transport be an isometry. +* Given connections on bundles `V` and `W`, there is an induced connnection on bundle Hom(V, W). + When this induced connection has been defined in Mathlib, rephrase the definition of + `CovariantDerivative.compatibilityTensor`, to be simply the covariant derivative of the metric + tensor. + -/ open Bundle Function NormedSpace From dcbeacfec803758b53d0fa0d37cf7607381181d1 Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Sat, 7 Mar 2026 16:35:49 +0000 Subject: [PATCH 21/33] import new file --- Mathlib.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/Mathlib.lean b/Mathlib.lean index 359e23eb09b300..a8b4fda8d99ea1 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4426,6 +4426,7 @@ public import Mathlib.Geometry.Manifold.SmoothEmbedding public import Mathlib.Geometry.Manifold.StructureGroupoid public import Mathlib.Geometry.Manifold.VectorBundle.Basic public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Basic +public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Metric public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Torsion public import Mathlib.Geometry.Manifold.VectorBundle.FiberwiseLinear public import Mathlib.Geometry.Manifold.VectorBundle.Hom From 072c4b884bb0096fc85ff61dc8ba832a23204ec3 Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Sat, 7 Mar 2026 16:42:40 +0000 Subject: [PATCH 22/33] clean up proofs a bit --- .../Manifold/MFDeriv/SpecificFunctions.lean | 14 +++++ .../CovariantDerivative/Metric.lean | 56 ++++++------------- 2 files changed, 30 insertions(+), 40 deletions(-) diff --git a/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean b/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean index b93c5a81d2bbaf..7ed84dacbe9868 100644 --- a/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean +++ b/Mathlib/Geometry/Manifold/MFDeriv/SpecificFunctions.lean @@ -796,6 +796,20 @@ theorem mfderiv_add (hf : MDiffAt f z) (hg : MDiffAt g z) : (by exact mfderiv% f z) + (by exact mfderiv% g z) := (hf.hasMFDerivAt.add hg.hasMFDerivAt).mfderiv +open NormedSpace in +theorem fromTangentSpace_mfderiv_add (hf : MDiffAt f z) (hg : MDiffAt g z) : + (fromTangentSpace _).toContinuousLinearMap ∘L (mfderiv% (f + g) z) + = (fromTangentSpace _).toContinuousLinearMap ∘L (mfderiv% f z) + + (fromTangentSpace _).toContinuousLinearMap ∘L (mfderiv% g z) := + (hf.hasMFDerivAt.add hg.hasMFDerivAt).mfderiv + +open NormedSpace in +theorem fromTangentSpace_mfderiv_add_apply (hf : MDiffAt f z) (hg : MDiffAt g z) + (v : TangentSpace I x) : + fromTangentSpace _ (mfderiv% (f + g) z v) + = fromTangentSpace _ (mfderiv% f z v) + fromTangentSpace _ (mfderiv% g z v) := + congr($(fromTangentSpace_mfderiv_add hf hg) v) + section sum variable {ι : Type} {t : Finset ι} {f : ι → M → E'} {f' : ι → TangentSpace I z →L[𝕜] E'} diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index a28e9ce426cce9..ae0e79c24af68e 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -201,17 +201,15 @@ variable {F} prefer using `compatibilityTensor` instead -/ noncomputable def compatibilityTensorAux (σ τ : Π x : M, V x) : Π (x : M), TangentSpace I x →L[ℝ] ℝ := fun x ↦ - letI b : TangentSpace I x →L[ℝ] ℝ := mfderiv% ⟪σ, τ⟫ x - b - ((innerSL ℝ (τ x)) ∘L (cov σ x)) - ((innerSL ℝ (σ x)) ∘L (cov τ x)) + (NormedSpace.fromTangentSpace _).toContinuousLinearMap ∘L mfderiv% ⟪σ, τ⟫ x + - ((innerSL ℝ (τ x)) ∘L (cov σ x)) - ((innerSL ℝ (σ x)) ∘L (cov τ x)) lemma compatibilityTensorAux_apply (σ τ : Π x : M, V x) {x : M} (X₀ : TangentSpace I x) : compatibilityTensorAux I cov σ τ x X₀ = NormedSpace.fromTangentSpace _ (mfderiv% ⟪σ, τ⟫ x X₀) - - innerSL ℝ (τ x) (cov σ x X₀) - innerSL ℝ (σ x) (cov τ x X₀) := by - unfold compatibilityTensorAux - simp - congr 1 + - innerSL ℝ (τ x) (cov σ x X₀) - innerSL ℝ (σ x) (cov τ x X₀) := + rfl variable [VectorBundle ℝ F V] [IsContMDiffRiemannianBundle I 1 F V] {x : M} @@ -222,7 +220,7 @@ private lemma aux1 {f : M → ℝ} {σ τ : (x : M) → V x} ext X₀ rw [compatibilityTensorAux_apply, product_smul_left, fromTangentSpace_mfderiv_smul_apply hf (hσ.inner_bundle' hτ)] - simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.leibniz hσ hf, inner_add_right, + simp [compatibilityTensorAux, cov.isCovariantDerivativeOn.leibniz hσ hf, inner_add_right, inner_smul_right, real_inner_comm] ring @@ -231,28 +229,11 @@ private lemma aux2 (σ σ' τ : (x : M) → V x) (hσ : MDiffAt (T% σ) x) (hσ' : MDiffAt (T% σ') x) (hτ : MDiffAt (T% τ) x) : compatibilityTensorAux I cov (σ + σ') τ x = compatibilityTensorAux I cov σ τ x + compatibilityTensorAux I cov σ' τ x := by - simp only [compatibilityTensorAux] - ext X - simp only [ContinuousLinearMap.coe_sub', ContinuousLinearMap.coe_comp', coe_innerSL_apply, - Pi.sub_apply, comp_apply, ContinuousLinearMap.add_apply] - rw [product_add_left, - mfderiv_add (hσ.inner_bundle' hτ) (hσ'.inner_bundle' hτ), - cov.isCovariantDerivativeOn.add hσ hσ', - ContinuousLinearMap.comp_add] - erw [ContinuousLinearMap.coe_sub'] - rw [Pi.sub_apply] - erw [ContinuousLinearMap.add_apply, Pi.add_apply, inner_add_left] - -- set A := mfderiv I 𝓘(ℝ, ℝ) ⟪σ, τ⟫ x - -- set A' := mfderiv I 𝓘(ℝ, ℝ) ⟪σ', τ⟫ x - -- set B := ((innerSL ℝ) (τ x)).comp (cov σ x) - -- set B' := ((innerSL ℝ) (τ x)).comp (cov σ' x) - -- set C := inner ℝ (σ x) ((cov τ x) X) - -- set C' := inner ℝ (σ' x) ((cov τ x) X) - erw [ContinuousLinearMap.add_apply, ContinuousLinearMap.sub_apply, - ContinuousLinearMap.sub_apply] - -- bug: abel fails, but module works - -- hypothesis: B, B', C, C' are in ℝ, while A and A' are in the tangent space at ℝ instead - module + ext X₀ + rw [compatibilityTensorAux_apply, product_add_left, + fromTangentSpace_mfderiv_add_apply (hσ.inner_bundle' hτ) (hσ'.inner_bundle' hτ)] + simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.add hσ hσ', inner_add_right] + abel variable {I} in private lemma aux3 {f : M → ℝ} {σ τ : (x : M) → V x} @@ -261,7 +242,7 @@ private lemma aux3 {f : M → ℝ} {σ τ : (x : M) → V x} ext X₀ rw [compatibilityTensorAux_apply, product_smul_right, fromTangentSpace_mfderiv_smul_apply hf (hσ.inner_bundle' hτ)] - simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.leibniz hτ hf, inner_add_right, + simp [compatibilityTensorAux, cov.isCovariantDerivativeOn.leibniz hτ hf, inner_add_right, inner_smul_right, real_inner_comm] ring @@ -271,15 +252,10 @@ private lemma aux4 (σ τ τ' : (x : M) → V x) compatibilityTensorAux I cov σ (τ + τ') x = compatibilityTensorAux I cov σ τ x + compatibilityTensorAux I cov σ τ' x := by ext X₀ - rw [compatibilityTensorAux_apply]; dsimp - rw [compatibilityTensorAux_apply, compatibilityTensorAux_apply]; dsimp - rw [product_add_right, mfderiv_add (hσ.inner_bundle' hτ) (hσ.inner_bundle' hτ'), - cov.isCovariantDerivativeOn.add hτ hτ'] - simp only [Pi.add_apply, ContinuousLinearMap.add_apply, inner_add_left, inner_add_right, - fromTangentSpace, -- this line is slightly fishy - ContinuousLinearEquiv.coe_mk, LinearEquiv.coe_mk, LinearMap.coe_mk, AddHom.coe_mk] - erw [ContinuousLinearMap.add_apply] - module + rw [compatibilityTensorAux_apply, product_add_right, + fromTangentSpace_mfderiv_add_apply (hσ.inner_bundle' hτ) (hσ.inner_bundle' hτ')] + simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.add hτ hτ', inner_add_right] + abel theorem compatibilityTensorAux_tensorial₁ (τ : Π x, V x) (hτ : MDiffAt (T% τ) x) : TensorialAt I F (compatibilityTensorAux I cov · τ x) x where @@ -308,7 +284,7 @@ theorem compatibilityTensor_apply [FiniteDimensional ℝ F] (x : M) fromTangentSpace _ (mfderiv% ⟪σ, τ⟫ x (X x)) - ⟪∇ σ, X, τ⟫ x - ⟪σ, ∇ τ, X⟫ x := by unfold compatibilityTensor rw [TensorialAt.mkHom₂_apply _ _ hσ hτ] - --rw [compatibilityTensorAux_apply] + --rw [compatibilityTensorAux] simp only [compatibilityTensorAux, ContinuousLinearMap.coe_sub', ContinuousLinearMap.coe_comp', coe_innerSL_apply, Pi.sub_apply, comp_apply] conv => From 1025438b13af891a9af987522c7cd747ccb6fe06 Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Sat, 7 Mar 2026 17:18:58 +0000 Subject: [PATCH 23/33] clean up proofs --- .../CovariantDerivative/Metric.lean | 131 ++++++------------ 1 file changed, 43 insertions(+), 88 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index ae0e79c24af68e..02b71dfa86ff7c 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -204,68 +204,48 @@ noncomputable def compatibilityTensorAux (σ τ : Π x : M, V x) : (NormedSpace.fromTangentSpace _).toContinuousLinearMap ∘L mfderiv% ⟪σ, τ⟫ x - ((innerSL ℝ (τ x)) ∘L (cov σ x)) - ((innerSL ℝ (σ x)) ∘L (cov τ x)) +omit [IsManifold I 2 M] in lemma compatibilityTensorAux_apply (σ τ : Π x : M, V x) {x : M} (X₀ : TangentSpace I x) : compatibilityTensorAux I cov σ τ x X₀ = NormedSpace.fromTangentSpace _ (mfderiv% ⟪σ, τ⟫ x X₀) - - innerSL ℝ (τ x) (cov σ x X₀) - innerSL ℝ (σ x) (cov τ x X₀) := + - inner ℝ (cov σ x X₀) (τ x) - inner ℝ (σ x) (cov τ x X₀) := by + rw [real_inner_comm] rfl variable [VectorBundle ℝ F V] [IsContMDiffRiemannianBundle I 1 F V] {x : M} -variable {I} in -private lemma aux1 {f : M → ℝ} {σ τ : (x : M) → V x} - (hf : MDiffAt f x) (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : - compatibilityTensorAux I cov (f • σ) τ x = f x • compatibilityTensorAux I cov σ τ x := by - ext X₀ - rw [compatibilityTensorAux_apply, product_smul_left, - fromTangentSpace_mfderiv_smul_apply hf (hσ.inner_bundle' hτ)] - simp [compatibilityTensorAux, cov.isCovariantDerivativeOn.leibniz hσ hf, inner_add_right, - inner_smul_right, real_inner_comm] - ring - -variable {I} in -private lemma aux2 (σ σ' τ : (x : M) → V x) - (hσ : MDiffAt (T% σ) x) (hσ' : MDiffAt (T% σ') x) (hτ : MDiffAt (T% τ) x) : - compatibilityTensorAux I cov (σ + σ') τ x = - compatibilityTensorAux I cov σ τ x + compatibilityTensorAux I cov σ' τ x := by - ext X₀ - rw [compatibilityTensorAux_apply, product_add_left, - fromTangentSpace_mfderiv_add_apply (hσ.inner_bundle' hτ) (hσ'.inner_bundle' hτ)] - simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.add hσ hσ', inner_add_right] - abel - -variable {I} in -private lemma aux3 {f : M → ℝ} {σ τ : (x : M) → V x} - (hf : MDiffAt f x) (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : - compatibilityTensorAux I cov σ (f • τ) x = f x • compatibilityTensorAux I cov σ τ x := by - ext X₀ - rw [compatibilityTensorAux_apply, product_smul_right, - fromTangentSpace_mfderiv_smul_apply hf (hσ.inner_bundle' hτ)] - simp [compatibilityTensorAux, cov.isCovariantDerivativeOn.leibniz hτ hf, inner_add_right, - inner_smul_right, real_inner_comm] - ring - -variable {I} in -private lemma aux4 (σ τ τ' : (x : M) → V x) - (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) (hτ' : MDiffAt (T% τ') x) : - compatibilityTensorAux I cov σ (τ + τ') x = - compatibilityTensorAux I cov σ τ x + compatibilityTensorAux I cov σ τ' x := by - ext X₀ - rw [compatibilityTensorAux_apply, product_add_right, - fromTangentSpace_mfderiv_add_apply (hσ.inner_bundle' hτ) (hσ.inner_bundle' hτ')] - simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.add hτ hτ', inner_add_right] - abel - theorem compatibilityTensorAux_tensorial₁ (τ : Π x, V x) (hτ : MDiffAt (T% τ) x) : TensorialAt I F (compatibilityTensorAux I cov · τ x) x where - smul hf hσ := aux1 cov hf hσ hτ - add hσ hσ' := aux2 cov _ _ _ hσ hσ' hτ + smul hf hσ := by + ext X₀ + rw [compatibilityTensorAux_apply, product_smul_left, + fromTangentSpace_mfderiv_smul_apply hf (hσ.inner_bundle' hτ)] + simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.leibniz hσ hf, inner_add_left, + inner_smul_left] + ring + add hσ hσ' := by + ext X₀ + rw [compatibilityTensorAux_apply, product_add_left, + fromTangentSpace_mfderiv_add_apply (hσ.inner_bundle' hτ) (hσ'.inner_bundle' hτ)] + simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.add hσ hσ', inner_add_left] + abel theorem compatibilityTensorAux_tensorial₂ (σ : Π x, V x) (hσ : MDiffAt (T% σ) x) : TensorialAt I F (compatibilityTensorAux I cov σ · x) x where - smul hf hτ := aux3 cov hf hσ hτ - add hτ hτ' := aux4 cov _ _ _ hσ hτ hτ' + smul hf hτ := by + ext X₀ + rw [compatibilityTensorAux_apply, product_smul_right, + fromTangentSpace_mfderiv_smul_apply hf (hσ.inner_bundle' hτ)] + simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.leibniz hτ hf, inner_add_right, + inner_smul_right] + ring + add hτ hτ' := by + ext X₀ + rw [compatibilityTensorAux_apply, product_add_right, + fromTangentSpace_mfderiv_add_apply (hσ.inner_bundle' hτ) (hσ.inner_bundle' hτ')] + simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.add hτ hτ', inner_add_right] + abel variable {I} [ContMDiffVectorBundle 1 F V I] in /-- The tensor `(X, σ, τ) ↦ ∇ₓ g(σ, τ) - g(∇ₓ σ, τ) - g(σ, ∇ₓ τ)` defining when a connection @@ -280,31 +260,20 @@ variable {X : Π x : M, TangentSpace I x} variable {I} [ContMDiffVectorBundle 1 F V I] in theorem compatibilityTensor_apply [FiniteDimensional ℝ F] (x : M) (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : - compatibilityTensor cov x (σ x) (τ x) (X x) = + cov.compatibilityTensor x (σ x) (τ x) (X x) = fromTangentSpace _ (mfderiv% ⟪σ, τ⟫ x (X x)) - ⟪∇ σ, X, τ⟫ x - ⟪σ, ∇ τ, X⟫ x := by unfold compatibilityTensor - rw [TensorialAt.mkHom₂_apply _ _ hσ hτ] - --rw [compatibilityTensorAux] - simp only [compatibilityTensorAux, ContinuousLinearMap.coe_sub', ContinuousLinearMap.coe_comp', - coe_innerSL_apply, Pi.sub_apply, comp_apply] - conv => - enter [1, 1] - erw [ContinuousLinearMap.sub_apply] - conv => - enter [1, 1, 2] - erw [ContinuousLinearMap.comp_apply] - simp [product, real_inner_comm, fromTangentSpace] + rw [TensorialAt.mkHom₂_apply _ _ hσ hτ, compatibilityTensorAux_apply] open FiberBundle in variable {I} [ContMDiffVectorBundle 1 F V I] in theorem compatibilityTensor_apply_eq_extend [FiniteDimensional ℝ F] (X₀ : TangentSpace I x) (σ₀ τ₀ : V x) : - compatibilityTensor cov x σ₀ τ₀ X₀ = + cov.compatibilityTensor x σ₀ τ₀ X₀ = fromTangentSpace _ (mfderiv% ⟪(extend F σ₀), (extend F τ₀)⟫ x X₀) - - ⟪∇ extend F σ₀, (extend E X₀), extend F τ₀⟫ x - - ⟪extend F σ₀, ∇ extend F τ₀, (extend E X₀)⟫ x := by - simpa [extend_apply_self] using compatibilityTensor_apply cov x - (X := extend E X₀) (mdifferentiableAt_extend I F σ₀) (mdifferentiableAt_extend I F τ₀) + - inner ℝ (cov (extend F σ₀) x X₀) τ₀ + - inner ℝ σ₀ (cov (extend F τ₀) x X₀) := by + simp [compatibilityTensor, TensorialAt.mkHom₂_apply_eq_extend, compatibilityTensorAux_apply] variable {I} [ContMDiffVectorBundle 1 F V I] in /-- Predicate saying that a connection `∇` on a Riemannian bundle `(V, g)` is compatible with the @@ -312,35 +281,21 @@ ambient metric, i.e. for all differentiable vector fields `X` on `M` and section `V`, we have `X ⟨σ, τ⟩ = ⟨∇ X σ, τ⟩ + ⟨σ, ∇ X τ⟩`. -/ def IsCompatible [FiniteDimensional ℝ F] : Prop := compatibilityTensor cov = 0 --- Auxiliary computation for `IsCompatible_apply`. --- TODO: inlining this lemma does not work -private lemma isCompatible_apply_aux {A B C : ℝ} (h : A - B - C = 0) : A = B + C := by grind - -variable {I} [ContMDiffVectorBundle 1 F V I] in --- TODO: give a better name; maybe inline? --- variable {I} in -lemma isCompatible_apply [FiniteDimensional ℝ F] (hcov : cov.IsCompatible) - (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : - mfderiv% ⟪σ, τ⟫ x (X x) = ⟪∇ σ, X, τ⟫ x + ⟪σ, ∇ τ, X⟫ x := by - rw [IsCompatible] at hcov - have : compatibilityTensor cov x (σ x) (τ x) (X x) = 0 := by simp [hcov] - rw [compatibilityTensor_apply cov x hσ hτ] at this - change (fromTangentSpace _ ((mfderiv I 𝓘(ℝ, ℝ) ⟪σ, τ⟫ x) (X x))) = _ - exact isCompatible_apply_aux this - open FiberBundle in variable {I} [ContMDiffVectorBundle 1 F V I] in lemma isCompatible_iff [FiniteDimensional ℝ F] : cov.IsCompatible ↔ ∀ {x : M} {X : Π x, TangentSpace I x} {σ τ : (x : M) → V x} (_hX : MDiffAt (T% X) x) (_hσ : MDiffAt (T% σ) x) (_hτ : MDiffAt (T% τ) x), - mfderiv% ⟪σ, τ⟫ x (X x) = ⟪∇ σ, X, τ⟫ x + ⟪σ, ∇ τ, X⟫ x := by - refine ⟨fun hcov x X σ τ hX hσ hτ ↦ cov.isCompatible_apply hcov hσ hτ, fun h ↦ ?_⟩ - unfold IsCompatible + fromTangentSpace _ (mfderiv% ⟪σ, τ⟫ x (X x)) = ⟪∇ σ, X, τ⟫ x + ⟪σ, ∇ τ, X⟫ x := by + refine ⟨fun hcov x X σ τ hX hσ hτ ↦ ?_, fun h ↦ ?_⟩ + · have H := congr($hcov x (σ x) (τ x) (X x)) + simp [compatibilityTensor_apply _ _ hσ hτ] at H + linear_combination H ext x σ₀ τ₀ X₀ - rw [compatibilityTensor_apply_eq_extend, sub_sub, sub_eq_iff_eq_add'] - simp only [Pi.zero_apply, ContinuousLinearMap.zero_apply, add_zero] + rw [compatibilityTensor_apply_eq_extend] have h' := h (mdifferentiableAt_extend I E X₀) (mdifferentiableAt_extend I F σ₀) (mdifferentiableAt_extend I F τ₀) - simpa [fromTangentSpace, extend_apply_self] using h' + simp [product] at h' ⊢ + linear_combination h' end CovariantDerivative From 34c13ed6a78d8e4a6556d8ee83e004412b60197a Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Sat, 7 Mar 2026 18:30:01 +0000 Subject: [PATCH 24/33] defer MDifferentiable.inner_bundle issue --- .../CovariantDerivative/Metric.lean | 42 ++++++------------- 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index 02b71dfa86ff7c..4084b41324525c 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -55,7 +55,7 @@ variable -- Let `M` be a `C^k` real manifold modeled on `(E, H)` {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H) - {M : Type*} [TopologicalSpace M] [ChartedSpace H M] [IsManifold I 2 M] + {M : Type*} [TopologicalSpace M] [ChartedSpace H M] -- Let `V` be a bundle over `M`, endowed with a Riemannian metric. (F : Type*) [NormedAddCommGroup F] [NormedSpace ℝ F] {V : M → Type*} [TopologicalSpace (TotalSpace F V)] @@ -84,7 +84,7 @@ local notation "⟪" σ ", " τ "⟫" => product σ τ -- Basic API for the product of two sections. section product -omit [TopologicalSpace M] [IsManifold I 2 M] +omit [TopologicalSpace M] lemma product_apply (x) : ⟪σ, τ⟫ x = inner ℝ (σ x) (τ x) := rfl @@ -151,41 +151,23 @@ end product -- These lemmas are necessary as my Lie bracket identities (assuming minimal differentiability) -- only hold point-wise. They abstract the expanding and unexpanding of `product`. -omit [TopologicalSpace M] [IsManifold I 2 M] in +omit [TopologicalSpace M] in lemma product_congr_left {x} (h : σ x = σ' x) : product σ τ x = product σ' τ x := by rw [product_apply, h, ← product_apply] -omit [TopologicalSpace M] [IsManifold I 2 M] in +omit [TopologicalSpace M] in lemma product_congr_left₂ {x} (h : σ x = σ' x + σ'' x) : product σ τ x = product σ' τ x + product σ'' τ x := by rw [product_apply, h, inner_add_left, ← product_apply] -omit [TopologicalSpace M] [IsManifold I 2 M] in +omit [TopologicalSpace M] in lemma product_congr_right {x} (h : τ x = τ' x) : product σ τ x = product σ τ' x := by rw [product_apply, h, ← product_apply] -omit [TopologicalSpace M] [IsManifold I 2 M] in +omit [TopologicalSpace M] in lemma product_congr_right₂ {x} (h : τ x = τ' x + τ'' x) : product σ τ x = product σ τ' x + product σ τ'' x := by rw [product_apply, h, inner_add_right, ← product_apply] -/- TODO: writing `hσ.inner_bundle hτ` or writing `by apply MDifferentiable.inner_bundle hσ hτ` -yields an error -synthesized type class instance is not definitionally equal to expression inferred by typing rules, -synthesized - fun x ↦ instNormedAddCommGroupOfRiemannianBundle x -inferred - fun b ↦ inst✝⁷ -Diagnose and fix this, and then replace the below by `MDifferentiable(At).inner_bundle! -/ - -variable {F} [VectorBundle ℝ F V] [IsContMDiffRiemannianBundle I 1 F V] {I} in -lemma MDifferentiable.inner_bundle' (hσ : MDiff (T% σ)) (hτ : MDiff (T% τ)) : MDiff ⟪σ, τ⟫ := - MDifferentiable.inner_bundle hσ hτ - -variable {F} [VectorBundle ℝ F V] [IsContMDiffRiemannianBundle I 1 F V] {I} in -lemma MDifferentiableAt.inner_bundle' {x} (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : - MDiffAt ⟪σ, τ⟫ x := - MDifferentiableAt.inner_bundle hσ hτ - namespace CovariantDerivative -- Let `cov` be a covariant derivative on `V`. @@ -204,7 +186,6 @@ noncomputable def compatibilityTensorAux (σ τ : Π x : M, V x) : (NormedSpace.fromTangentSpace _).toContinuousLinearMap ∘L mfderiv% ⟪σ, τ⟫ x - ((innerSL ℝ (τ x)) ∘L (cov σ x)) - ((innerSL ℝ (σ x)) ∘L (cov τ x)) -omit [IsManifold I 2 M] in lemma compatibilityTensorAux_apply (σ τ : Π x : M, V x) {x : M} (X₀ : TangentSpace I x) : compatibilityTensorAux I cov σ τ x X₀ = @@ -220,14 +201,14 @@ theorem compatibilityTensorAux_tensorial₁ (τ : Π x, V x) (hτ : MDiffAt (T% smul hf hσ := by ext X₀ rw [compatibilityTensorAux_apply, product_smul_left, - fromTangentSpace_mfderiv_smul_apply hf (hσ.inner_bundle' hτ)] + fromTangentSpace_mfderiv_smul_apply hf (hσ.inner_bundle hτ)] simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.leibniz hσ hf, inner_add_left, inner_smul_left] ring add hσ hσ' := by ext X₀ rw [compatibilityTensorAux_apply, product_add_left, - fromTangentSpace_mfderiv_add_apply (hσ.inner_bundle' hτ) (hσ'.inner_bundle' hτ)] + fromTangentSpace_mfderiv_add_apply (hσ.inner_bundle hτ) (hσ'.inner_bundle hτ)] simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.add hσ hσ', inner_add_left] abel @@ -236,14 +217,14 @@ theorem compatibilityTensorAux_tensorial₂ (σ : Π x, V x) (hσ : MDiffAt (T% smul hf hτ := by ext X₀ rw [compatibilityTensorAux_apply, product_smul_right, - fromTangentSpace_mfderiv_smul_apply hf (hσ.inner_bundle' hτ)] + fromTangentSpace_mfderiv_smul_apply hf (hσ.inner_bundle hτ)] simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.leibniz hτ hf, inner_add_right, inner_smul_right] ring add hτ hτ' := by ext X₀ rw [compatibilityTensorAux_apply, product_add_right, - fromTangentSpace_mfderiv_add_apply (hσ.inner_bundle' hτ) (hσ.inner_bundle' hτ')] + fromTangentSpace_mfderiv_add_apply (hσ.inner_bundle hτ) (hσ.inner_bundle hτ')] simp [compatibilityTensorAux_apply, cov.isCovariantDerivativeOn.add hτ hτ', inner_add_right] abel @@ -281,8 +262,9 @@ ambient metric, i.e. for all differentiable vector fields `X` on `M` and section `V`, we have `X ⟨σ, τ⟩ = ⟨∇ X σ, τ⟩ + ⟨σ, ∇ X τ⟩`. -/ def IsCompatible [FiniteDimensional ℝ F] : Prop := compatibilityTensor cov = 0 +variable {I} [IsManifold I 1 M] [ContMDiffVectorBundle 1 F V I] + open FiberBundle in -variable {I} [ContMDiffVectorBundle 1 F V I] in lemma isCompatible_iff [FiniteDimensional ℝ F] : cov.IsCompatible ↔ ∀ {x : M} {X : Π x, TangentSpace I x} {σ τ : (x : M) → V x} (_hX : MDiffAt (T% X) x) (_hσ : MDiffAt (T% σ) x) (_hτ : MDiffAt (T% τ) x), From 33e330890ddaecaf673319d10b4758fad1fac172 Mon Sep 17 00:00:00 2001 From: Patrick Massot Date: Sat, 7 Mar 2026 22:27:25 +0100 Subject: [PATCH 25/33] Some cleanup --- .../CovariantDerivative/Metric.lean | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index 4084b41324525c..5aba8af1d22da5 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -14,13 +14,13 @@ public import Mathlib.Geometry.Manifold.MFDeriv.NormedSpace This file defines connections on a Riemannian vector bundle which are compatible with the ambient metric. A bundled connection `∇` on a Riemannian vector bundle `(V, g)` is compatible with the metric `g` if and only if the differentiated metric tensor `∇ g` (defined by -`(X, σ, τ) ↦ ∇ₓ g(σ, τ) - g(∇ₓ σ, τ) - g(σ, ∇ₓ τ)`) vanishes on all differentiable vector fields `X` -and differentiable sections `σ`, `τ`. +`(X, σ, τ) ↦ ∇_X g(σ, τ) - g(∇_X σ, τ) - g(σ, ∇_X τ)`) vanishes on all differentiable vector fields +`X` and differentiable sections `σ`, `τ`. ## Main definitions and results * `CovariantDerivative.compatibilityTensor`: the tensor - `(X, σ, τ) ↦ ∇ₓ g(σ, τ) - g(∇ₓ σ, τ) - g(σ, ∇ₓ τ)` defining when a connection `∇` on a Riemannian + `(X, σ, τ) ↦ X g(σ, τ) - g(∇_X σ, τ) - g(σ, ∇_X τ)` defining when a connection `∇` on a Riemannian vector bundle `(V, g)` is compatible with the metric `g`. * `CovariantDerivative.compatibilityTensor_apply` and `CovariantDerivative.compatibilityTensor_apply` give formulas for applying the compatibility @@ -42,7 +42,6 @@ and differentiable sections `σ`, `τ`. tensor. -/ - open Bundle Function NormedSpace open scoped Manifold ContDiff @@ -64,15 +63,22 @@ variable [∀ x, IsTopologicalAddGroup (V x)] [∀ x, ContinuousSMul ℝ (V x)] [FiberBundle F V] [RiemannianBundle V] -/-! Compatible connections: a connection on `V` is compatible with the metric on `V` iff -`∇ X ⟨σ, τ⟩ = ⟨∇ X σ, τ⟩ + ⟨σ, ∇ X τ⟩` holds for all sufficiently nice vector fields `X` on `M` and -sections `σ`, `τ` of `V`. In our definition, we ask for this identity to at each `x : M`, whenever -`X`, `σ` and `τ` are differentiable at `x`. +/-! # Compatible connections + +A connection on `V` is compatible with the metric on `V` iff `X ⟨σ, τ⟩ = ⟨∇_X σ, τ⟩ + ⟨σ, ∇_X τ⟩` +holds for all sufficiently nice vector fields `X` on `M` and sections `σ`, `τ` of `V`. The left hand side is the pushforward of the function `⟨σ, τ⟩` along the vector field `X`: -the left hand side at `x` is `df(X x)`, where `f := ⟨σ, τ⟩`. -/ +the left hand side at `x` is `df(X x)`, where `f := ⟨σ, τ⟩` (ie. `X` is seen a derivation on +the algebra of function on the base manifold acting on the function `⟨σ, τ⟩`). +In our definition, we ask for this identity to at each `x : M`, whenever `X`, `σ` and `τ` are +differentiable at `x`. +-/ variable {σ σ' σ'' τ τ' τ'' : Π x : M, V x} +-- set_option trace.profiler true +-- set_option profiler.threshold 500 + /-- The scalar product of two sections. -/ noncomputable abbrev product (σ τ : Π x : M, V x) : M → ℝ := fun x ↦ inner ℝ (σ x) (τ x) @@ -97,7 +103,7 @@ lemma product_swap : ⟪τ, σ⟫ = ⟪σ, τ⟫ := by @[simp] lemma product_zero_left : ⟪0, σ⟫ = 0 := by ext x - simp [product] + simp only [product, Pi.zero_apply, inner_zero_left] @[simp] lemma product_zero_right : ⟪σ, 0⟫ = 0 := by rw [product_swap, product_zero_left] @@ -174,8 +180,11 @@ namespace CovariantDerivative -- TODO: include in cheat sheet! variable (cov : CovariantDerivative I F V) -/-- Local notation for a connection. Caution: `∇ σ, X` corresponds to `∇ₓ σ` in textbooks -/ -local notation "∇" σ "," X => fun (x:M) ↦ cov σ x (X x) + +/-- Local notation for a covariant derivative on a vector bundle acting on a vector field and a +section. -/ +local syntax "∇" term:arg term : term +local macro_rules | `(∇ $X $σ) => `(fun (x : M) ↦ cov $σ x ($X x)) variable {F} @@ -229,7 +238,7 @@ theorem compatibilityTensorAux_tensorial₂ (σ : Π x, V x) (hσ : MDiffAt (T% abel variable {I} [ContMDiffVectorBundle 1 F V I] in -/-- The tensor `(X, σ, τ) ↦ ∇ₓ g(σ, τ) - g(∇ₓ σ, τ) - g(σ, ∇ₓ τ)` defining when a connection +/-- The tensor `(X, σ, τ) ↦ X g(σ, τ) - g(∇_X σ, τ) - g(σ, ∇_X τ)` defining when a connection `∇` on a Riemannian bundle `(M, V)` is compatible with the metric `g`. -/ @[no_expose] noncomputable def compatibilityTensor [FiniteDimensional ℝ F] (x : M) : V x →L[ℝ] V x →L[ℝ] (TangentSpace I x →L[ℝ] ℝ) := @@ -242,7 +251,7 @@ variable {I} [ContMDiffVectorBundle 1 F V I] in theorem compatibilityTensor_apply [FiniteDimensional ℝ F] (x : M) (hσ : MDiffAt (T% σ) x) (hτ : MDiffAt (T% τ) x) : cov.compatibilityTensor x (σ x) (τ x) (X x) = - fromTangentSpace _ (mfderiv% ⟪σ, τ⟫ x (X x)) - ⟪∇ σ, X, τ⟫ x - ⟪σ, ∇ τ, X⟫ x := by + fromTangentSpace _ (mfderiv% ⟪σ, τ⟫ x (X x)) - ⟪∇ X σ, τ⟫ x - ⟪σ, ∇ X τ⟫ x := by unfold compatibilityTensor rw [TensorialAt.mkHom₂_apply _ _ hσ hτ, compatibilityTensorAux_apply] @@ -259,16 +268,16 @@ theorem compatibilityTensor_apply_eq_extend [FiniteDimensional ℝ F] (X₀ : Ta variable {I} [ContMDiffVectorBundle 1 F V I] in /-- Predicate saying that a connection `∇` on a Riemannian bundle `(V, g)` is compatible with the ambient metric, i.e. for all differentiable vector fields `X` on `M` and sections `σ` and `τ` of -`V`, we have `X ⟨σ, τ⟩ = ⟨∇ X σ, τ⟩ + ⟨σ, ∇ X τ⟩`. -/ +`V`, we have `X ⟨σ, τ⟩ = ⟨∇_X σ, τ⟩ + ⟨σ, ∇_X τ⟩`. -/ def IsCompatible [FiniteDimensional ℝ F] : Prop := compatibilityTensor cov = 0 variable {I} [IsManifold I 1 M] [ContMDiffVectorBundle 1 F V I] open FiberBundle in lemma isCompatible_iff [FiniteDimensional ℝ F] : - cov.IsCompatible ↔ ∀ {x : M} {X : Π x, TangentSpace I x} {σ τ : (x : M) → V x} - (_hX : MDiffAt (T% X) x) (_hσ : MDiffAt (T% σ) x) (_hτ : MDiffAt (T% τ) x), - fromTangentSpace _ (mfderiv% ⟪σ, τ⟫ x (X x)) = ⟪∇ σ, X, τ⟫ x + ⟪σ, ∇ τ, X⟫ x := by + cov.IsCompatible ↔ ∀ {x : M} {X : Π x, TangentSpace I x} {σ τ : (x : M) → V x}, + MDiffAt (T% X) x → MDiffAt (T% σ) x → MDiffAt (T% τ) x → + fromTangentSpace _ (mfderiv% ⟪σ, τ⟫ x (X x)) = ⟪∇ X σ, τ⟫ x + ⟪σ, ∇ X τ⟫ x := by refine ⟨fun hcov x X σ τ hX hσ hτ ↦ ?_, fun h ↦ ?_⟩ · have H := congr($hcov x (σ x) (τ x) (X x)) simp [compatibilityTensor_apply _ _ hσ hτ] at H @@ -281,3 +290,4 @@ lemma isCompatible_iff [FiniteDimensional ℝ F] : linear_combination h' end CovariantDerivative +#lint From 5ae6c25248d06a572451b7a63c7fbe8d499ceb1d Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Sat, 7 Mar 2026 22:37:59 +0000 Subject: [PATCH 26/33] stray #lint --- .../Manifold/VectorBundle/CovariantDerivative/Metric.lean | 1 - 1 file changed, 1 deletion(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index 5aba8af1d22da5..06f2a720c2212a 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -290,4 +290,3 @@ lemma isCompatible_iff [FiniteDimensional ℝ F] : linear_combination h' end CovariantDerivative -#lint From c14dfac525b3dc82aca55c29e6262a9f9bbd8a06 Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Sat, 7 Mar 2026 22:58:08 +0000 Subject: [PATCH 27/33] namespaces --- .../Manifold/VectorBundle/CovariantDerivative/Metric.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index 06f2a720c2212a..6ba0375e9cbf85 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -42,7 +42,7 @@ metric `g` if and only if the differentiated metric tensor `∇ g` (defined by tensor. -/ -open Bundle Function NormedSpace +open Bundle NormedSpace open scoped Manifold ContDiff @[expose] public section From 8241b095ed675b6b69d95ffef61b00eb798e53c8 Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Sat, 7 Mar 2026 23:06:11 +0000 Subject: [PATCH 28/33] doc --- .../Manifold/VectorBundle/CovariantDerivative/Metric.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index 6ba0375e9cbf85..4b11954eff5eae 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -39,7 +39,7 @@ metric `g` if and only if the differentiated metric tensor `∇ g` (defined by * Given connections on bundles `V` and `W`, there is an induced connnection on bundle Hom(V, W). When this induced connection has been defined in Mathlib, rephrase the definition of `CovariantDerivative.compatibilityTensor`, to be simply the covariant derivative of the metric - tensor. + tensor (considered as a section of Hom(V, Hom(V, ℝ))). -/ open Bundle NormedSpace From 099d8959ea2cb738cc1503f085a1701344d1b81d Mon Sep 17 00:00:00 2001 From: Heather Macbeth <25316162+hrmacbeth@users.noreply.github.com> Date: Sat, 7 Mar 2026 23:07:39 +0000 Subject: [PATCH 29/33] typo --- .../Manifold/VectorBundle/CovariantDerivative/Metric.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index 4b11954eff5eae..560c29e93f4b4d 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -36,7 +36,7 @@ metric `g` if and only if the differentiated metric tensor `∇ g` (defined by `CovariantDerivative.IsCompatible` with the characterisation that parallel transport be an isometry. -* Given connections on bundles `V` and `W`, there is an induced connnection on bundle Hom(V, W). +* Given connections on bundles `V` and `W`, there is an induced connnection on the bundle Hom(V, W). When this induced connection has been defined in Mathlib, rephrase the definition of `CovariantDerivative.compatibilityTensor`, to be simply the covariant derivative of the metric tensor (considered as a section of Hom(V, Hom(V, ℝ))). From 9b3f66f5d0562efce86e3759110679609d406907 Mon Sep 17 00:00:00 2001 From: Michael Rothgang Date: Thu, 12 Mar 2026 21:11:44 +0100 Subject: [PATCH 30/33] chore: remove change not necessary for this PR --- Mathlib.lean | 1 - .../CovariantDerivative/Torsion.lean | 160 ------------------ 2 files changed, 161 deletions(-) delete mode 100644 Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Torsion.lean diff --git a/Mathlib.lean b/Mathlib.lean index 439527a5266026..9cfc4f217bd4de 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4452,7 +4452,6 @@ public import Mathlib.Geometry.Manifold.StructureGroupoid public import Mathlib.Geometry.Manifold.VectorBundle.Basic public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Basic public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Metric -public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Torsion public import Mathlib.Geometry.Manifold.VectorBundle.FiberwiseLinear public import Mathlib.Geometry.Manifold.VectorBundle.Hom public import Mathlib.Geometry.Manifold.VectorBundle.LocalFrame diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Torsion.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Torsion.lean deleted file mode 100644 index 64318342cc0ec4..00000000000000 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Torsion.lean +++ /dev/null @@ -1,160 +0,0 @@ -/- -Copyright (c) 2025 Patrick Massot. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Patrick Massot, Michael Rothgang, Heather Macbeth --/ -module - -public import Mathlib.Topology.FiberBundle.Basic -public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Basic -public import Mathlib.Geometry.Manifold.VectorField.LieBracket - -/-! # Torsion of an affine connection - -We define the torsion tensor of an affine connection, i.e. a covariant derivative on the tangent -bundle `TM` of some manifold `M`. - -## Main definitions and results - -* `IsCovariantDerivativeOn.torsion`: the torsion tensor of an unbundled covariant derivative - on `TM` on some set `s` in `M` -* `CovariantDerivative.torsion`: the torsion tensor of a bundled covariant derivative on `TM` -* `CovariantDerivative.torsion_eq_zero_iff`: the torsion tensor of a bundled covariant derivative - `∇` vanishes if and only if `∇_X Y - ∇_Y X = [X, Y]` for all differentiable vector fields - `X` and `Y`. - --/ - -@[expose] public section - -open Bundle Set NormedSpace FiberBundle -open scoped Manifold ContDiff - -variable {𝕜 : Type*} [NontriviallyNormedField 𝕜] - {E : Type*} [NormedAddCommGroup E] [NormedSpace 𝕜 E] - {H : Type*} [TopologicalSpace H] {I : ModelWithCorners 𝕜 E H} - {M : Type*} [TopologicalSpace M] [ChartedSpace H M] {x : M} - -/-! ## Torsion tensor of an unbundled covariant derivative on `TM` on a set `s` -/ -namespace IsCovariantDerivativeOn - -/-- The torsion of a covariant derivative on the tangent bundle `TM`, as a bare function. -Prefer to use `IsCovariantDerivativeOn.torsion` (which is a 2-tensor) instead. -/ -noncomputable def torsionAux - (cov : (Π x : M, TangentSpace I x) → (Π x : M, TangentSpace I x →L[𝕜] TangentSpace I x)) : - (Π x : M, TangentSpace I x) → (Π x : M, TangentSpace I x) → (Π x : M, TangentSpace I x) := - fun X Y x ↦ cov Y x (X x) - cov X x (Y x) - VectorField.mlieBracket I X Y x - -variable [IsManifold I 2 M] [CompleteSpace E] - {cov cov' : (Π x : M, TangentSpace I x) → (Π x : M, TangentSpace I x →L[𝕜] TangentSpace I x)} - {X X' Y : Π x : M, TangentSpace I x} - -theorem torsionAux_tensorial₁ (hcov : IsCovariantDerivativeOn E cov) (x : M) - (Y : Π x, TangentSpace I x) : - TensorialAt I E (torsionAux cov · Y x) x where - smul hf hX := by - simp [torsionAux, hcov.leibniz hX hf, VectorField.mlieBracket_smul_left hf hX] - module - add hX hX' := by - simp [torsionAux, hcov.add hX hX', VectorField.mlieBracket_add_left hX hX'] - module - -theorem torsionAux_tensorial₂ (hcov : IsCovariantDerivativeOn E cov) (x : M) - (X : Π x, TangentSpace I x) : - TensorialAt I E (torsionAux cov X · x) x where - smul hf hY := by - simp [torsionAux, hcov.leibniz hY hf, VectorField.mlieBracket_smul_right hf hY] - module - add hY hY' := by - simp [torsionAux, hcov.add hY hY', VectorField.mlieBracket_add_right hY hY'] - module - -variable [CompleteSpace 𝕜] [FiniteDimensional 𝕜 E] - -/-- The torsion tensor of an unbundled covariant derivative on `TM`. -/ -noncomputable def torsion (hcov : IsCovariantDerivativeOn E cov univ) (x : M) : - TangentSpace I x →L[𝕜] TangentSpace I x →L[𝕜] TangentSpace I x := - TensorialAt.mkHom₂ (torsionAux cov · · x) _ - (fun τ _ ↦ hcov.torsionAux_tensorial₁ x τ) - (fun σ _ ↦ hcov.torsionAux_tensorial₂ x σ) - -theorem torsion_apply (hcov : IsCovariantDerivativeOn E cov univ) {x} - {X : Π x : M, TangentSpace I x} (hX : MDiffAt (T% X) x) - {Y : Π x : M, TangentSpace I x} (hY : MDiffAt (T% Y) x) : - torsion hcov x (X x) (Y x) = cov Y x (X x) - cov X x (Y x) - VectorField.mlieBracket I X Y x := - TensorialAt.mkHom₂_apply _ _ hX hY - -theorem torsion_apply_eq_extend (hcov : IsCovariantDerivativeOn E cov univ) {x} - (X₀ Y₀ : TangentSpace I x) : - torsion hcov x X₀ Y₀ = - cov (extend E Y₀) x X₀ - cov (extend E X₀) x Y₀ - - VectorField.mlieBracket I (extend E X₀) (extend E Y₀) x := by - simp [torsion, torsionAux, TensorialAt.mkHom₂_apply_eq_extend] - -variable (X) in -@[simp] -lemma torsion_self (hcov : IsCovariantDerivativeOn E cov univ) (X₀ : TangentSpace I x) : - hcov.torsion x X₀ X₀ = 0 := by - simp [torsion_apply_eq_extend] - -variable (X Y) in -lemma torsion_antisymm (hcov : IsCovariantDerivativeOn E cov univ) (X₀ Y₀ : TangentSpace I x) : - hcov.torsion x X₀ Y₀ = - hcov.torsion x Y₀ X₀ := by - simp only [torsion_apply_eq_extend, neg_sub] - rw [VectorField.mlieBracket_swap] - dsimp - module - -end IsCovariantDerivativeOn - -/-! ## Torsion tensor of a bundled covariant derivative on `TM` -/ -namespace CovariantDerivative - -open VectorField - -variable - {cov cov' : (Π x : M, TangentSpace I x) → (Π x : M, TangentSpace I x →L[𝕜] TangentSpace I x)} - {X X' Y : Π x : M, TangentSpace I x} - -variable [CompleteSpace 𝕜] [CompleteSpace E] [FiniteDimensional 𝕜 E] [IsManifold I 2 M] -variable (cov : CovariantDerivative I E (TangentSpace I : M → Type _)) - -/-- The torsion tensor of a covariant derivative on the tangent bundle of a manifold. -/ -noncomputable def torsion := cov.isCovariantDerivativeOn.torsion - -lemma torsion_apply (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) : - cov.torsion x (X x) (Y x) = cov Y x (X x) - cov X x (Y x) - mlieBracket I X Y x := by - unfold torsion IsCovariantDerivativeOn.torsion - apply TensorialAt.mkHom₂_apply - exacts [hX, hY] - -lemma torsion_apply_eq_extend (X₀ Y₀ : TangentSpace I x) : - cov.torsion x X₀ Y₀ = - cov (extend E Y₀) x (extend E X₀ x) - cov (extend E X₀) x (extend E Y₀ x) - - mlieBracket I (extend E X₀) (extend E Y₀) x := by - unfold torsion IsCovariantDerivativeOn.torsion - apply TensorialAt.mkHom₂_apply_eq_extend - -@[simp] -lemma torsion_self (X₀ : TangentSpace I x) : cov.torsion x X₀ X₀ = 0 := - cov.isCovariantDerivativeOn.torsion_self .. - -lemma torsion_antisymm (X₀ Y₀ : TangentSpace I x) : cov.torsion x X₀ Y₀ = - cov.torsion x Y₀ X₀ := - cov.isCovariantDerivativeOn.torsion_antisymm .. - -lemma torsion_eq_zero_iff : cov.torsion = 0 ↔ - ∀ {X Y x}, MDiffAt (T% X) x → MDiffAt (T% Y) x → - cov Y x (X x) - cov X x (Y x) = mlieBracket I X Y x := by - constructor - · intro h X Y x hX hY - replace h := congr($h x (X x) (Y x)) - rw [cov.torsion_apply hX hY] at h - simpa [sub_eq_iff_eq_add'] using h - · intro h - ext x u v - rw [torsion_apply_eq_extend, h] - · simp - · apply mdifferentiableAt_extend - · apply mdifferentiableAt_extend - -end CovariantDerivative From 5b47b0431ddb0b42f18fafc5413222b510a10ece Mon Sep 17 00:00:00 2001 From: Michael Rothgang Date: Thu, 19 Mar 2026 01:03:44 +0100 Subject: [PATCH 31/33] cherry-pick levi-civita file --- Mathlib.lean | 1 + .../CovariantDerivative/LeviCivita.lean | 860 ++++++++++++++++++ 2 files changed, 861 insertions(+) create mode 100644 Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/LeviCivita.lean diff --git a/Mathlib.lean b/Mathlib.lean index e53c55cdca5df5..78f45ec60efc07 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -4467,6 +4467,7 @@ public import Mathlib.Geometry.Manifold.SmoothEmbedding public import Mathlib.Geometry.Manifold.StructureGroupoid public import Mathlib.Geometry.Manifold.VectorBundle.Basic public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Basic +public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.LeviCivita public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Metric public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Torsion public import Mathlib.Geometry.Manifold.VectorBundle.FiberwiseLinear diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/LeviCivita.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/LeviCivita.lean new file mode 100644 index 00000000000000..38b8450d10b69e --- /dev/null +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/LeviCivita.lean @@ -0,0 +1,860 @@ +/- +Copyright (c) 2025 Michael Rothgang. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Patrick Massot, Michael Rothgang, Heather Macbeth +-/ +module + +public import Mathlib.Analysis.InnerProductSpace.Dual +public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Metric +public import Mathlib.Geometry.Manifold.VectorBundle.CovariantDerivative.Torsion + +/-! +# The Levi-Civita connection on a Riemannian manifold + +To be continued and polished! + +This file defines the Levi-Civita connection on a (finite-dimensional) Riemannian manifold `(M, g)`. +connection `∇` on the tangent bundle of a Riemannian manifold `(M, g)` is called a +*Levi-Civita connection* if and only if it is both compatible with the metric `g` and torsion-free. +Any two such connections are equal (on differentiable vector fields), which is why one speaks of +*the* Levi-Civita connection on `TM`. +We construct a Levi-Civita connection and prove that is defines a compatible torsion-free +connection. + + +## Main definitions and results + +* `CovariantDerivative.IsLeviCivitaConnection`: a covariant derivative `∇` on `(M, g)` is a + Levi-Civita connection if and only if it is both torsion-free and compatible with `g` + +* `CovariantDerivative.IsLeviCivitaConnection.uniqueness`: a Levi-Civita connection on `(M, g)` is + uniquely determined on differentiable vector fields. + +* `CovariantDerivative.LeviCivitaConnection`: a choice of Levi-Civita connection on the tangent + bundle `TM` of a Riemannian manifold `(M, g)`: this is unique up to the value on + non-differentiable vector fields. + If you know the Levi-Civita connection already, you can use `IsLeviCivitaConnection` instead. +* `CovariantDerivative.leviCivitaConnection_isLeviCivitaConnection`: + `LeviCivitaConnection` is a Levi-Civita connection (i.e., compatible and torsion-free) + +## Implementation notes +* construction of LC using a tensoriality argument, and the musical isomorphism + (avoids the use of local frames and trivialisations) + +-/ + +open Bundle FiberBundle Function NormedSpace +open scoped Manifold ContDiff + +@[expose] public section -- TODO: think if we want to expose all definitions! + +-- TODO: revisit and fix this once the dust has settled +set_option backward.isDefEq.respectTransparency false + +-- Let `(M, g)` be a `C^k` real manifold modeled on `(E, H)`, endowed with a Riemannian metric `g`. +variable {n : WithTop ℕ∞} + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H) + {M : Type*} [EMetricSpace M] [ChartedSpace H M] [IsManifold I 2 M] + [RiemannianBundle (fun (x : M) ↦ TangentSpace I x)] + {X X' X'' Y Y' Y'' Z Z' : Π x : M, TangentSpace I x} + +namespace CovariantDerivative + +-- Let `cov` be a covariant derivative on `TM`. +-- TODO: include in cheat sheet! +variable (cov : CovariantDerivative I E (TangentSpace I : M → Type _)) + +/-- Local notation for a connection. Caution: `∇ Y, X` corresponds to `∇ₓ Y` in textbooks -/ +local notation "∇" Y "," X => fun (x:M) ↦ cov Y x (X x) + +variable [IsContMDiffRiemannianBundle I 1 E (fun (x : M) ↦ TangentSpace I x)] + +/-- A covariant derivative on a Riemannian bundle `TM` is called the **Levi-Civita connection** +iff it is torsion-free and compatible with `g`. +Note that the bundle metric on `TM` is implicitly hidden in this definition. See `TODO` for a +version depending on a choice of Riemannian metric on `M`. +-/ +def IsLeviCivitaConnection [FiniteDimensional ℝ E] : Prop := cov.IsCompatible ∧ cov.torsion = 0 + +local notation "⟪" X ", " Y "⟫" => product X Y + +/- TODO: writing `hσ.inner_bundle hτ` or writing `by apply MDifferentiable.inner_bundle hσ hτ` +yields an error +synthesized type class instance is not definitionally equal to expression inferred by typing rules, +synthesized + fun x ↦ instNormedAddCommGroupOfRiemannianBundle x +inferred + fun b ↦ inst✝⁷ +Diagnose and fix this, and then replace the below by `MDifferentiable(At).inner_bundle! -/ + +variable {I} in +lemma _root_.MDifferentiable.inner_bundle' {X Y : Π x : M, TangentSpace I x} + (hX : MDiff (T% X)) (hY : MDiff (T% Y)) : MDiff ⟪X, Y⟫ := + MDifferentiable.inner_bundle hX hY + +variable {I} in +lemma _root_.MDifferentiableAt.inner_bundle' {x : M} {X Y : Π x : M, TangentSpace I x} + (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) : + MDiffAt ⟪X, Y⟫ x := + MDifferentiableAt.inner_bundle hX hY + +variable (X Y Z) in +/-- The first term in the definition of the candidate Levi-Civita connection: +`rhs_aux I X Y Z = X ⟨Y, Z⟩ = x ↦ d(⟨Y, Z⟩)_x (X x)`. + +This definition contains mild defeq abuse, which is invisible on paper: +The function `⟨Y, Z⟩` maps `M` into `ℝ`, hence its differential at a point `x` maps `T_p M` +to an element of the tangent space of `ℝ`. A summand `⟨Y, [X, Z]⟩`, however, yields an honest +real number: Lean complains that these have different types. +Fortunately, `ℝ` is defeq to its own tangent space; casting `rhs_aux` to the real numbers +allows the addition to type-check. -/ +noncomputable abbrev rhs_aux : M → ℝ := fun x ↦ (mfderiv% ⟪Y, Z⟫ x (X x)) + +section rhs_aux + +variable (Y Z) in +omit [IsManifold I 2 M] in +lemma rhs_aux_swap : rhs_aux I X Y Z = rhs_aux I X Z Y := by + ext x + simp only [rhs_aux] + congr 2 + exact product_swap Z Y + +omit [IsManifold I 2 M] in +variable (X X' Y Z) in +lemma rhs_aux_addX : rhs_aux I (X + X') Y Z = rhs_aux I X Y Z + rhs_aux I X' Y Z := by + ext x + simp [rhs_aux] + +variable {x : M} + +variable (X) in +@[simp] +lemma rhs_aux_addY_apply (hY : MDiffAt (T% Y) x) (hY' : MDiffAt (T% Y') x) (hZ : MDiffAt (T% Z) x) : + rhs_aux I X (Y + Y') Z x = rhs_aux I X Y Z x + rhs_aux I X Y' Z x := by + simp only [rhs_aux] + rw [product_add_left, mfderiv_add (hY.inner_bundle' hZ) (hY'.inner_bundle' hZ)] + simp; congr + +variable (X) in +lemma rhs_aux_addY (hY : MDiff (T% Y)) (hY' : MDiff (T% Y')) (hZ : MDiff (T% Z)) : + rhs_aux I X (Y + Y') Z = rhs_aux I X Y Z + rhs_aux I X Y' Z := by + ext x + exact rhs_aux_addY_apply I X (hY x) (hY' x) (hZ x) + +variable (X) in +@[simp] +lemma rhs_aux_addZ_apply (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) (hZ' : MDiffAt (T% Z') x) : + rhs_aux I X Y (Z + Z') x = rhs_aux I X Y Z x + rhs_aux I X Y Z' x := by + unfold rhs_aux + rw [product_add_right, mfderiv_add (hY.inner_bundle' hZ) (hY.inner_bundle' hZ')]; simp; congr + +variable (X) in +lemma rhs_aux_addZ (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) (hZ' : MDiff (T% Z')) : + rhs_aux I X Y (Z + Z') = rhs_aux I X Y Z + rhs_aux I X Y Z' := by + ext x + exact rhs_aux_addZ_apply I X (hY x) (hZ x) (hZ' x) + +omit [IsManifold I 2 M] in +variable (X Y Z) in +lemma rhs_aux_smulX_apply (f : M → ℝ) (x) : rhs_aux I (f • X) Y Z x = f x * rhs_aux I X Y Z x := by + simp [rhs_aux] + +omit [IsManifold I 2 M] in +variable (X Y Z) in +lemma rhs_aux_smulX (f : M → ℝ) : rhs_aux I (f • X) Y Z = f * rhs_aux I X Y Z := by + ext x + exact rhs_aux_smulX_apply .. + +variable (X) in +lemma rhs_aux_smulY_apply {f : M → ℝ} + (hf : MDiffAt f x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + letI A (x) := fromTangentSpace _ ((mfderiv% f x) (X x)) + rhs_aux I X (f • Y) Z x = f x * rhs_aux I X Y Z x + A x * ⟪Y, Z⟫ x := by + rw [rhs_aux, product_smul_left, mfderiv_smul hf (hY.inner_bundle' hZ)] + rfl + +variable (X) in +lemma rhs_aux_smulY {f : M → ℝ} (hf : MDiff f) (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : + letI A (x) := fromTangentSpace _ ((mfderiv% f x) (X x)) + rhs_aux I X (f • Y) Z = f * rhs_aux I X Y Z + A * ⟪Y, Z⟫ := by + ext x + simp [rhs_aux_smulY_apply I X (hf x) (hY x) (hZ x)] + +variable (X) in +lemma rhs_aux_smulY_const_apply {a : ℝ} (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + rhs_aux I X (a • Y) Z x = a * rhs_aux I X Y Z x := by + let f : M → ℝ := fun _ ↦ a + have h1 : rhs_aux I X (a • Y) Z x = rhs_aux I X (f • Y) Z x := by simp only [f]; congr + rw [h1, rhs_aux_smulY_apply I X mdifferentiableAt_const hY hZ] + simp [mfderiv_const] + +variable (X) in +lemma rhs_aux_smulY_const {a : ℝ} (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : + rhs_aux I X (a • Y) Z = a • rhs_aux I X Y Z := by + ext x + apply rhs_aux_smulY_const_apply I X (hY x) (hZ x) + +variable (X) in +lemma rhs_aux_smulZ_apply {f : M → ℝ} + (hf : MDiffAt f x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + letI A (x) := fromTangentSpace _ ((mfderiv% f x) (X x)) + rhs_aux I X Y (f • Z) x = f x * rhs_aux I X Y Z x + A x * ⟪Y, Z⟫ x := by + rw [rhs_aux_swap, rhs_aux_smulY_apply, rhs_aux_swap, product_swap] + exacts [hf, hZ, hY] + +variable (X) in +lemma rhs_aux_smulZ {f : M → ℝ} (hf : MDiff f) (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : + letI A (x) := fromTangentSpace _ ((mfderiv% f x) (X x)) + rhs_aux I X Y (f • Z) = f * rhs_aux I X Y Z + A * ⟪Y, Z⟫ := by + rw [rhs_aux_swap, rhs_aux_smulY, rhs_aux_swap, product_swap] + exacts [hf, hZ, hY] + +variable (X) in +lemma rhs_aux_smulZ_const_apply {a : ℝ} (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + rhs_aux I X Y (a • Z) x = a * rhs_aux I X Y Z x := by + let f : M → ℝ := fun _ ↦ a + have h1 : rhs_aux I X Y (a • Z) x = rhs_aux I X Y (f • Z) x := by simp only [f]; congr + rw [h1, rhs_aux_smulZ_apply I X mdifferentiableAt_const hY hZ] + simp [mfderiv_const] + +variable (X) in +lemma rhs_aux_smulZ_const {a : ℝ} (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : + rhs_aux I X Y (a • Z) = a • rhs_aux I X Y Z := by + ext x + exact rhs_aux_smulZ_const_apply I X (hY x) (hZ x) + +end rhs_aux + +variable {x : M} + +variable (X Y Z) in +/-- Auxiliary quantity used in the uniqueness proof of the Levi-Civita connection: +If ∇ is a Levi-Civita connection on `TM`, then +`2 ⟨∇ X Y, Z⟩ = leviCivitaRhs' I X Y Z` for all vector fields `Z`. -/ +noncomputable def leviCivitaRhs' : M → ℝ := + rhs_aux I X Y Z + rhs_aux I Y Z X - rhs_aux I Z X Y + - ⟪Y ,(VectorField.mlieBracket I X Z)⟫ + - ⟪Z, (VectorField.mlieBracket I Y X)⟫ + + ⟪X, (VectorField.mlieBracket I Z Y)⟫ + +variable (X Y Z) in +/-- Auxiliary quantity used in the uniqueness proof of the Levi-Civita connection: +If `∇` is a Levi-Civita connection on `TM`, then +`⟨∇ X Y, Z⟩ = leviCivitaRhs I X Y Z` for all smooth vector fields `X`, `Y` and `Z`. -/ +noncomputable def leviCivitaRhs : M → ℝ := (1 / 2 : ℝ) • leviCivitaRhs' I X Y Z + +omit [IsManifold I 2 M] in +lemma leviCivitaRhs_apply : leviCivitaRhs I X Y Z x = (1 / 2 : ℝ) • leviCivitaRhs' I X Y Z x := + rfl + +section leviCivitaRhs + +@[simp] +lemma leviCivitaRhs'_addX_apply [CompleteSpace E] + (hX : MDiffAt (T% X) x) (hX' : MDiffAt (T% X') x) + (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + leviCivitaRhs' I (X + X') Y Z x = + leviCivitaRhs' I X Y Z x + leviCivitaRhs' I X' Y Z x := by + simp only [leviCivitaRhs', rhs_aux_addX, Pi.add_apply, Pi.sub_apply] + -- We have to rewrite back and forth: the Lie bracket is only additive at x, + -- as we are only asking for differentiability at x. + -- Fortunately, the `product_congr_right₂` lemma abstracts this very well. + rw [product_congr_right₂ (VectorField.mlieBracket_add_right (V := Y) hX hX'), + product_congr_right₂ (VectorField.mlieBracket_add_left (W := Z) hX hX'), + product_add_left_apply, rhs_aux_addY_apply, rhs_aux_addZ_apply] <;> try assumption + abel + +lemma leviCivitaRhs'_addX [CompleteSpace E] + (hX : MDiff (T% X)) (hX' : MDiff (T% X')) (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : + leviCivitaRhs' I (X + X') Y Z = + leviCivitaRhs' I X Y Z + leviCivitaRhs' I X' Y Z := by + ext x + simp [leviCivitaRhs'_addX_apply _ (hX x) (hX' x) (hY x) (hZ x)] + +lemma leviCivitaRhs_addX_apply [CompleteSpace E] + (hX : MDiffAt (T% X) x) (hX' : MDiffAt (T% X') x) + (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + leviCivitaRhs I (X + X') Y Z x = leviCivitaRhs I X Y Z x + leviCivitaRhs I X' Y Z x := by + simp [leviCivitaRhs, leviCivitaRhs'_addX_apply I hX hX' hY hZ, left_distrib] + +lemma leviCivitaRhs_addX [CompleteSpace E] + (hX : MDiff (T% X)) (hX' : MDiff (T% X')) (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : + leviCivitaRhs I (X + X') Y Z = leviCivitaRhs I X Y Z + leviCivitaRhs I X' Y Z := by + ext x + simp [leviCivitaRhs_addX_apply _ (hX x) (hX' x) (hY x) (hZ x)] + +open VectorField NormedSpace + +variable {I} in +lemma leviCivitaRhs'_smulX_apply [CompleteSpace E] {f : M → ℝ} + (hf : MDiffAt f x) (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + leviCivitaRhs' I (f • X) Y Z x = f x • leviCivitaRhs' I X Y Z x := by + unfold leviCivitaRhs' + simp only [Pi.add_apply, Pi.sub_apply] + rw [rhs_aux_smulX, rhs_aux_smulY_apply, rhs_aux_smulZ_apply] <;> try assumption + -- TODO: add the right congr_right lemma to avoid the product_apply, ← product_apply dance! + simp only [product_apply, mlieBracket_smul_left (W := Z) hf hX, + mlieBracket_smul_right (V := Y) hf hX, inner_add_right] + -- Combining this line with the previous one fails. + simp only [← product_apply, neg_smul, inner_neg_right] + have h1 : + inner ℝ (Y x) ((fromTangentSpace _ (mfderiv% f x (Z x))) • X x) = + fromTangentSpace (f x) (mfderiv% f x (Z x)) * ⟪X, Y⟫ x := by + simp only [product] + rw [← real_inner_smul_left, real_inner_smul_right, real_inner_smul_left, real_inner_comm] + have h2 : + inner ℝ (Z x) (fromTangentSpace (f x) ((mfderiv% f x (Y x))) • X x) = + (fromTangentSpace (f x) (mfderiv% f x (Y x))) * ⟪Z, X⟫ x := by + simp only [product] + rw [← real_inner_smul_left, real_inner_smul_right, real_inner_smul_left] + rw [h1, h2] + --set dfY := fromTangentSpace (f x) ((mfderiv% f x (Y x)))--(mfderiv% f x) (Y x) + --set dfZ : ℝ := (mfderiv% f x) (Z x) + have h3 : ⟪f • X, mlieBracket I Z Y⟫ x = f x * ⟪X, mlieBracket I Z Y⟫ x := by + rw [product_apply, Pi.smul_apply', real_inner_smul_left] + have h4 : inner ℝ (Z x) (f x • mlieBracket I Y X x) = f x * ⟪Z, mlieBracket I Y X⟫ x := by + rw [product_apply, real_inner_smul_right] + rw [real_inner_smul_right (Y x), h3, h4] + -- Push all applications of `x` inwards, then it's indeed obvious. + simp + -- set A := ⟪Y, mlieBracket I X Z⟫ with hA + -- set B := ⟪Z, mlieBracket I X Y⟫ + -- set C := ⟪X, mlieBracket I Z Y⟫ + -- set R := dfZ * ⟪X, Y⟫ x with hR + -- set R' := dfY * ⟪Z, X⟫ x with hR' + -- set E := rhs_aux I X Y Z x + -- set F := rhs_aux I Y Z X x + -- set G := rhs_aux I Z X Y x + ring_nf + +variable {I} in +lemma leviCivitaRhs_smulX_apply [CompleteSpace E] {f : M → ℝ} + (hf : MDiffAt f x) (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + leviCivitaRhs I (f • X) Y Z x = f x • leviCivitaRhs I X Y Z x := by + simp only [leviCivitaRhs, one_div, Pi.smul_apply, smul_eq_mul] + simp_rw [leviCivitaRhs'_smulX_apply (I := I) hf hX hY hZ] + rw [← mul_assoc, mul_comm (f x), smul_eq_mul] + ring + +variable {I} in +lemma leviCivitaRhs_smulX [CompleteSpace E] {f : M → ℝ} + (hf : MDiff f) (hX : MDiff (T% X)) (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : + leviCivitaRhs I (f • X) Y Z = f • leviCivitaRhs I X Y Z := by + ext x + exact leviCivitaRhs_smulX_apply (hf x) (hX x) (hY x) (hZ x) + +lemma leviCivitaRhs'_addY_apply [CompleteSpace E] + (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) + (hY' : MDiffAt (T% Y') x) (hZ : MDiffAt (T% Z) x) : + leviCivitaRhs' I X (Y + Y') Z x = leviCivitaRhs' I X Y Z x + leviCivitaRhs' I X Y' Z x := by + simp only [leviCivitaRhs', Pi.add_apply, Pi.sub_apply, product_add_left_apply] + rw [rhs_aux_addX, rhs_aux_addY_apply, rhs_aux_addZ_apply] <;> try assumption + -- We have to rewrite back and forth: the Lie bracket is only additive at x, + -- as we are only asking for differentiability at x. + rw [product_congr_right₂ (mlieBracket_add_left (W := X) hY hY')] + rw [product_congr_right₂ (VectorField.mlieBracket_add_right (V := Z) hY hY')] + simp only [Pi.add_apply] + abel + +lemma leviCivitaRhs_addY_apply [CompleteSpace E] + (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) + (hY' : MDiffAt (T% Y') x) (hZ : MDiffAt (T% Z) x) : + leviCivitaRhs I X (Y + Y') Z x = leviCivitaRhs I X Y Z x + leviCivitaRhs I X Y' Z x := by + simp [leviCivitaRhs, leviCivitaRhs'_addY_apply I hX hY hY' hZ, left_distrib] + +lemma leviCivitaRhs_addY [CompleteSpace E] + (hX : MDiff (T% X)) (hY : MDiff (T% Y)) (hY' : MDiff (T% Y')) (hZ : MDiff (T% Z)) : + leviCivitaRhs I X (Y + Y') Z = leviCivitaRhs I X Y Z + leviCivitaRhs I X Y' Z := by + ext x + simp [leviCivitaRhs_addY_apply I (hX x) (hY x) (hY' x) (hZ x)] + +variable {I} in +lemma leviCivitaRhs'_smulY_const_apply [CompleteSpace E] {a : ℝ} + (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + leviCivitaRhs' I X (a • Y) Z x = a • leviCivitaRhs' I X Y Z x := by + simp only [leviCivitaRhs'] + simp only [product_smul_const_left, Pi.add_apply, Pi.sub_apply, Pi.smul_apply] + rw [rhs_aux_smulY_const_apply I X hY hZ] + -- TODO: clean up this proof! + let f : M → ℝ := fun _ ↦ a + have : rhs_aux I (a • Y) Z X x = a • rhs_aux I Y Z X x := by + trans rhs_aux I (f • Y) Z X x + · rfl + rw [rhs_aux_smulX I Y (f := f) (Y := Z) (Z := X)] + rfl + rw [this, rhs_aux_smulZ_const_apply I _ hX hY] + -- is there a better abstraction for "Lie bracket conv mode"? + have : ⟪Z, mlieBracket I (a • Y) X⟫ x = a • ⟪Z, mlieBracket I Y X⟫ x := by + simp_rw [product_apply, mlieBracket_const_smul_left (W := X) hY, inner_smul_right_eq_smul] + rw [this] + have aux2 : ⟪X, mlieBracket I Z (a • Y)⟫ x = a • ⟪X, mlieBracket I Z Y⟫ x := by + simp_rw [product_apply, mlieBracket_const_smul_right (V := Z) hY, inner_smul_right_eq_smul] + rw [aux2] + simp + ring + +variable {I} in +lemma leviCivitaRhs_smulY_const_apply [CompleteSpace E] {a : ℝ} + (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + leviCivitaRhs I X (a • Y) Z x = a • leviCivitaRhs I X Y Z x := by + simp_rw [leviCivitaRhs, Pi.smul_apply]; rw [smul_comm] + congr + exact leviCivitaRhs'_smulY_const_apply hX hY hZ + +variable {I} in +lemma leviCivitaRhs_smulY_const [CompleteSpace E] {a : ℝ} + (hX : MDiff (T% X)) (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : + leviCivitaRhs I X (a • Y) Z = a • leviCivitaRhs I X Y Z := by + ext x + exact leviCivitaRhs_smulY_const_apply (hX x) (hY x) (hZ x) + +lemma leviCivitaRhs'_smulY_apply [CompleteSpace E] {f : M → ℝ} + (hf : MDiffAt f x) (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + leviCivitaRhs' I X (f • Y) Z x = + f x • leviCivitaRhs' I X Y Z x + + ((fromTangentSpace _).toFun <| mfderiv% f x (X x)) • 2 * ⟪Y, Z⟫ x := by + simp only [leviCivitaRhs'] + simp_rw [rhs_aux_smulX I Y Z X f] + simp only [product_smul_left, Pi.add_apply, Pi.sub_apply, smul_eq_mul, Pi.mul_apply] + rw [rhs_aux_smulY_apply I X hf hY hZ, rhs_aux_smulZ_apply I Z hf hX hY] + -- TODO: is there a better abstraction for this kind of "Lie bracket conv mode"? + have h1 : ⟪Z, mlieBracket I (f • Y) X⟫ x = + - (fromTangentSpace _).toFun (((mfderiv% f x) (X x))) • ⟪Z, Y⟫ x + + f x • ⟪Z, mlieBracket I Y X⟫ x := by + simp_rw [product_apply, mlieBracket_smul_left (W := X) hf hY, inner_add_right] + congr + · simp only [neg_smul, inner_neg_right, fromTangentSpace, AddHom.toFun_eq_coe, AddHom.coe_mk, + smul_eq_mul, neg_mul, neg_inj] + rw [real_inner_smul_right] + rfl + · rw [inner_smul_right_eq_smul] + have h2 : ⟪X, mlieBracket I Z (f • Y)⟫ x = + (fromTangentSpace _).toFun (((mfderiv% f x) (Z x))) • ⟪X, Y⟫ x + + f x • ⟪X, mlieBracket I Z Y⟫ x := by + simp_rw [product_apply, mlieBracket_smul_right (V := Z) hf hY, inner_add_right] + congr + · simp only [fromTangentSpace, AddHom.toFun_eq_coe, AddHom.coe_mk, smul_eq_mul] + rw [real_inner_smul_right] + rfl + · rw [inner_smul_right_eq_smul] + rw [h1, h2, product_swap Y Z] + set A := rhs_aux I X Y Z x + set B := rhs_aux I Y Z X x + set C := rhs_aux I Z X Y x + set D := ⟪Y, mlieBracket I X Z⟫ x + set E := ⟪Z, mlieBracket I Y X⟫ x + set F := ⟪X, mlieBracket I Z Y⟫ x + set G1 := ⟪Y, Z⟫ x + set G2 := ⟪X, Y⟫ x + set dfx := (mfderiv I 𝓘(ℝ, ℝ) f x) + set H := (fromTangentSpace (f x)) (dfx (X x)) with H_eq + set K := (fromTangentSpace (f x)) (dfx (Z x)) with K_eq + change f x * A + (fromTangentSpace _).toFun (dfx (X x)) * G1 + f x * B + - (f x * C + (fromTangentSpace _).toFun (dfx (Z x)) * G2) + - f x * D - (-H * G1 + f x * E) + (K * G2 + f x * F) = _ + dsimp + rw [← H_eq, ← K_eq] + ring + +lemma leviCivitaRhs_smulY_apply [CompleteSpace E] {f : M → ℝ} + (hf : MDiffAt f x) (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + leviCivitaRhs I X (f • Y) Z x = + f x • leviCivitaRhs I X Y Z x + + ((fromTangentSpace _).toFun <| mfderiv% f x (X x)) • ⟪Y, Z⟫ x := by + simp only [leviCivitaRhs, Pi.smul_apply, leviCivitaRhs'_smulY_apply I hf hX hY hZ] + rw [smul_add, smul_comm] + congr 1 + rw [← smul_eq_mul] + dsimp + field_simp + +lemma leviCivitaRhs'_addZ_apply [CompleteSpace E] + (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) + (hZ : MDiffAt (T% Z) x) (hZ' : MDiffAt (T% Z') x) : + leviCivitaRhs' I X Y (Z + Z') x = + leviCivitaRhs' I X Y Z x + leviCivitaRhs' I X Y Z' x := by + simp only [leviCivitaRhs', rhs_aux_addX, Pi.add_apply, Pi.sub_apply, product_add_left_apply] + rw [product_congr_right₂ (VectorField.mlieBracket_add_right (V := X) hZ hZ'), + product_congr_right₂ (VectorField.mlieBracket_add_left (W := Y) hZ hZ'), + rhs_aux_addY_apply, rhs_aux_addZ_apply] <;> try assumption + abel + +lemma leviCivitaRhs'_addZ [CompleteSpace E] + (hX : MDiff (T% X)) (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) (hZ' : MDiff (T% Z')) : + leviCivitaRhs' I X Y (Z + Z') = + leviCivitaRhs' I X Y Z + leviCivitaRhs' I X Y Z' := by + ext x + exact leviCivitaRhs'_addZ_apply I (hX x) (hY x) (hZ x) (hZ' x) + +lemma leviCivitaRhs_addZ_apply [CompleteSpace E] + (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) + (hZ : MDiffAt (T% Z) x) (hZ' : MDiffAt (T% Z') x) : + leviCivitaRhs I X Y (Z + Z') x = leviCivitaRhs I X Y Z x + leviCivitaRhs I X Y Z' x := by + simp [leviCivitaRhs, leviCivitaRhs'_addZ_apply I hX hY hZ hZ', left_distrib] + +lemma leviCivitaRhs_addZ [CompleteSpace E] + (hX : MDiff (T% X)) (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) (hZ' : MDiff (T% Z')) : + leviCivitaRhs I X Y (Z + Z') = leviCivitaRhs I X Y Z + leviCivitaRhs I X Y Z' := by + ext x + exact leviCivitaRhs_addZ_apply I (hX x) (hY x) (hZ x) (hZ' x) + +lemma leviCivitaRhs'_smulZ_apply [CompleteSpace E] {f : M → ℝ} + (hf : MDiffAt f x) (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + leviCivitaRhs' I X Y (f • Z) x = f x • leviCivitaRhs' I X Y Z x := by + simp only [leviCivitaRhs', rhs_aux_smulX, Pi.add_apply, Pi.sub_apply] + rw [rhs_aux_smulY_apply _ _ hf hZ hX, rhs_aux_smulZ_apply _ _ hf hY hZ] + -- Apply the product rule for the lie bracket. + -- Let's encapsulate the going into the product and back out again. + have h1 : ⟪Y, mlieBracket I X (f • Z)⟫ x = + f x • ⟪Y, mlieBracket I X Z⟫ x + ⟪Y, fromTangentSpace _ (mfderiv% f x (X x)) • Z⟫ x := by + rw [product_apply, VectorField.mlieBracket_smul_right hf hZ, inner_add_right, add_comm, + inner_smul_right] + congr + have h2 : letI dfY := fromTangentSpace _ ((mfderiv% f x) (Y x)); + ⟪X, mlieBracket I (f • Z) Y⟫ x = - dfY • ⟪X, Z⟫ x + f x • ⟪X, mlieBracket I Z Y⟫ x := by + rw [product_apply, VectorField.mlieBracket_smul_left hf hZ, inner_add_right, inner_smul_right, + inner_smul_right] + congr + rw [h1, h2, product_smul_left, product_swap X Z] + erw [product_smul_right] + simp + -- set A := rhs_aux I X Y Z x + -- set B := rhs_aux I Y Z X x + -- set C := rhs_aux I Z X Y x + -- set D := ⟪Y, mlieBracket I X Z⟫ x + -- set E := ⟪Z, mlieBracket I Y X⟫ x with E_eq + -- set F := ⟪X, mlieBracket I Z Y⟫ x + -- letI dfX : ℝ := (mfderiv I 𝓘(ℝ, ℝ) f x) (X x) + -- set G := dfX * ⟪Y, Z⟫ x + -- letI dfY : ℝ := (mfderiv I 𝓘(ℝ, ℝ) f x) (Y x) + -- set H := dfY * ⟪X, Z⟫ x + ring + +lemma leviCivitaRhs'_smulZ [CompleteSpace E] {f : M → ℝ} + (hf : MDiff f) (hX : MDiff (T% X)) (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : + leviCivitaRhs' I X Y (f • Z) = f • leviCivitaRhs' I X Y Z := by + ext x + exact leviCivitaRhs'_smulZ_apply I (hf x) (hX x) (hY x) (hZ x) + +lemma leviCivitaRhs_smulZ [CompleteSpace E] {f : M → ℝ} + (hf : MDiff f) (hX : MDiff (T% X)) (hY : MDiff (T% Y)) (hZ : MDiff (T% Z)) : + leviCivitaRhs I X Y (f • Z) = f • leviCivitaRhs I X Y Z := by + simp only [leviCivitaRhs] + rw [smul_comm, leviCivitaRhs'_smulZ I hf hX hY hZ] + +lemma leviCivitaRhs_smulZ_apply [CompleteSpace E] {f : M → ℝ} + (hf : MDiffAt f x) (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + leviCivitaRhs I X Y (f • Z) x = f x * leviCivitaRhs I X Y Z x := by + simp [leviCivitaRhs, leviCivitaRhs'_smulZ_apply I hf hX hY hZ] + ring + +end leviCivitaRhs + +variable [FiniteDimensional ℝ E] in +lemma aux (h : cov.IsLeviCivitaConnection) {x : M} + (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : rhs_aux I X Y Z x = + ⟪∇ Y, X, Z⟫ x + ⟪Y, ∇ X, Z⟫ x + ⟪Y, VectorField.mlieBracket I X Z⟫ x := by + trans ⟪∇ Y, X, Z⟫ x + ⟪Y, ∇ Z, X⟫ x + · exact cov.isCompatible_iff.mp h.1 hX hY hZ + · simp [← cov.torsion_eq_zero_iff.mp h.2 hX hZ, product, inner_sub_right] + +variable {cov} in +/-- Auxiliary lemma towards the uniquness of the Levi-Civita connection: expressing the term +⟨∇ X Y, Z⟩ for all differentiable vector fields X, Y and Z, without reference to ∇. -/ +lemma IsLeviCivitaConnection.eq_leviCivitaRhs [FiniteDimensional ℝ E] + (h : cov.IsLeviCivitaConnection) + {x : M} (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : + ⟪∇ Y, X, Z⟫ x = leviCivitaRhs I X Y Z x := by + unfold leviCivitaRhs leviCivitaRhs' + have eq1 := aux I cov h hX hY hZ + have eq2 := aux I cov h hY hZ hX + have eq3 := aux I cov h hZ hX hY + simp [real_inner_comm, smul_eq_mul] at * + linear_combination - (eq1 + eq2 - eq3) / 2 + +section + +omit [IsManifold I 2 M] [IsContMDiffRiemannianBundle I 1 E (TangentSpace I (M := M))] in +variable {I} in +lemma congr_of_forall_product_apply [FiniteDimensional ℝ E] {Y Y' : TangentSpace I x} + (h : ∀ Z : TangentSpace I x, inner ℝ Y Z = inner ℝ Y' Z) : Y = Y' := by + have : FiniteDimensional ℝ (TangentSpace I x) := inferInstanceAs (FiniteDimensional ℝ E) + have : CompleteSpace (TangentSpace I x) := FiniteDimensional.complete ℝ _ + set Φ := InnerProductSpace.toDual ℝ (TangentSpace I x) + apply Φ.injective + ext Z₀ + simpa [Φ, product] using h Z₀ + +omit [IsContMDiffRiemannianBundle I 1 E (TangentSpace I (M := M))] in +variable {I} in +/-- If two vector fields `X` and `X'` on `M` satisfy the relation `⟨X, Z⟩ = ⟨X', Z⟩` for all +vector fields `Z`, then `X = X'`. XXX up to differentiability? -/ +-- TODO: is this true if E is infinite-dimensional? trace the origin of the `Fintype` assumptions! +lemma congr_of_forall_product [FiniteDimensional ℝ E] + (h : ∀ Z : Π x : M, TangentSpace I x, ⟪X, Z⟫ = ⟪X', Z⟫) : X = X' := by + ext1 x + apply congr_of_forall_product_apply + intro Z₀ + simpa [product] using congr($(h (extend E Z₀)) x) + +/-- The Levi-Civita connection on `(M, g)` is uniquely determined, +at least on differentiable vector fields. -/ +-- (probably not everywhere, as addition rules apply only for differentiable vector fields?) +theorem IsLeviCivitaConnection.uniqueness [FiniteDimensional ℝ E] + {cov cov' : CovariantDerivative I E (TangentSpace I : M → Type _)} + (hcov : cov.IsLeviCivitaConnection) (hcov' : cov'.IsLeviCivitaConnection) + {X Y : Π x : M, TangentSpace I x} {x : M} + (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) : + cov Y x (X x) = cov' Y x (X x) := by + have : FiniteDimensional ℝ (TangentSpace I x) := inferInstanceAs (FiniteDimensional ℝ E) + have : CompleteSpace (TangentSpace I x) := FiniteDimensional.complete ℝ _ + set Φ := InnerProductSpace.toDual ℝ (TangentSpace I x) + apply Φ.injective + ext Z₀ + let Z := extend E Z₀ + have hZ := mdifferentiableAt_extend I E Z₀ + suffices inner ℝ (cov Y x (X x)) (Z x) = inner ℝ (cov' Y x (X x)) (Z x) by simpa [Φ, Z] + trans leviCivitaRhs I X Y Z x + · rw [← hcov.eq_leviCivitaRhs I hX hY hZ] + · rw [← hcov'.eq_leviCivitaRhs I hX hY hZ] + +open Classical in +noncomputable def lcAux₀' (Y : Π x : M, TangentSpace I x) (x : M) + (X Z : Π x : M, TangentSpace I x) := + if MDiffAt (T% X) x then if MDiffAt (T% Z) x then + leviCivitaRhs I X Y Z + else 0 else 0 + +theorem leviCivitaRhs_tensorial₁ [FiniteDimensional ℝ E] + {Y : Π x : M, TangentSpace I x} (x : M) (hY : MDiffAt (T% Y) x) (Z : Π x, TangentSpace I x) : + TensorialAt I E (lcAux₀' I Y x · Z x) x where + smul hf hX := by + dsimp [lcAux₀'] + rw [if_pos hX, if_pos] + · split_ifs with hZ + · exact leviCivitaRhs_smulX_apply hf hX hY hZ + · simp + · exact hf.smul_section hX + add hX₁ hX₂ := by + dsimp [lcAux₀'] + rw [if_pos hX₁, if_pos hX₂, if_pos] + · split_ifs with hZ + · exact leviCivitaRhs_addX_apply I hX₁ hX₂ hY hZ + · simp + · exact mdifferentiableAt_add_section hX₁ hX₂ + +theorem leviCivitaRhs_tensorial₂ [FiniteDimensional ℝ E] + {Y : Π x : M, TangentSpace I x} (x : M) (hY : MDiffAt (T% Y) x) (X : Π x, TangentSpace I x) + (hX : MDiffAt (T% X) x) : + TensorialAt I E (lcAux₀' I Y x X · x) x where + smul hf hZ := by + dsimp [lcAux₀'] + rw [if_pos hX, if_pos hZ, if_pos, if_pos hX] + · exact leviCivitaRhs_smulZ_apply I hf hX hY hZ + · exact hf.smul_section hZ + add hZ₁ hZ₂ := by + dsimp [lcAux₀'] + rw [if_pos hZ₁, if_pos hZ₂, if_pos hX, if_pos, if_pos hX, if_pos hX] + · exact leviCivitaRhs_addZ_apply I hX hY hZ₁ hZ₂ + · exact mdifferentiableAt_add_section hZ₁ hZ₂ + +open Classical in +noncomputable def lcAux₀ [FiniteDimensional ℝ E] + {Y : Π x : M, TangentSpace I x} (x : M) (hY : MDiffAt (T% Y) x) : + TangentSpace I x →L[ℝ] TangentSpace I x →L[ℝ] ℝ := + TensorialAt.mkHom₂ _ (x := x) + (fun Z _ ↦ leviCivitaRhs_tensorial₁ _ _ hY Z) + (fun X hX ↦ leviCivitaRhs_tensorial₂ _ _ hY X hX) + +theorem lcAux₀_apply [FiniteDimensional ℝ E] {x : M} + {X : Π x : M, TangentSpace I x} (hX : MDiffAt (T% X) x) + {Y : Π x : M, TangentSpace I x} (hY : MDiffAt (T% Y) x) + {Z : Π x : M, TangentSpace I x} (hZ : MDiffAt (T% Z) x) : + lcAux₀ I x hY (X x) (Z x) = leviCivitaRhs I X Y Z x := by + unfold lcAux₀ + rw [TensorialAt.mkHom₂_apply _ _ hX hZ, lcAux₀', if_pos hX, if_pos hZ] + +noncomputable def lcAux₁ [FiniteDimensional ℝ E] + {Y : Π x : M, TangentSpace I x} (x : M) (hY : MDiffAt (T% Y) x) : + TangentSpace I x →L[ℝ] TangentSpace I x := + -- use the musical isomorphism to produce a candidate ∇ Y as a (1,1)-tensor + -- (rather than a 2-tensor) + have : FiniteDimensional ℝ (TangentSpace I x) := inferInstanceAs (FiniteDimensional ℝ E) + have : CompleteSpace (TangentSpace I x) := FiniteDimensional.complete ℝ _ + (InnerProductSpace.toDual ℝ _).symm.toContinuousLinearEquiv.toContinuousLinearMap ∘L + (lcAux₀ I x hY) + +theorem lcAux₁_apply [FiniteDimensional ℝ E] {x : M} + {X : Π x : M, TangentSpace I x} (hX : MDiffAt (T% X) x) + {Y : Π x : M, TangentSpace I x} (hY : MDiffAt (T% Y) x) + {Z : Π x : M, TangentSpace I x} (hZ : MDiffAt (T% Z) x) : + inner ℝ (lcAux₁ I x hY (X x)) (Z x) = leviCivitaRhs I X Y Z x := by + simpa [lcAux₁] using lcAux₀_apply I hX hY hZ + +open Classical in +noncomputable def lcAux [FiniteDimensional ℝ E] + (Y : Π x : M, TangentSpace I x) (x : M) : + TangentSpace I x →L[ℝ] TangentSpace I x := + if hY : MDiffAt (T% Y) x then lcAux₁ I x hY else 0 + +theorem lcAux_apply [FiniteDimensional ℝ E] {x : M} + {X : Π x : M, TangentSpace I x} (hX : MDiffAt (T% X) x) + {Y : Π x : M, TangentSpace I x} (hY : MDiffAt (T% Y) x) + {Z : Π x : M, TangentSpace I x} (hZ : MDiffAt (T% Z) x) : + inner ℝ (lcAux I Y x (X x)) (Z x) = leviCivitaRhs I X Y Z x := by + unfold lcAux + rw [dif_pos hY] + simpa [lcAux] using lcAux₁_apply I hX hY hZ + +lemma isCovariantDerivativeOn_lcAux [FiniteDimensional ℝ E] : + IsCovariantDerivativeOn E (lcAux I (M := M)) where + add {Y Y'} x hY hY' _ := by + unfold lcAux + rw [dif_pos hY, dif_pos hY', dif_pos (mdifferentiableAt_add_section hY hY')] + unfold lcAux₁ + dsimp + rw [← ContinuousLinearMap.comp_add] + congr! 1 + simp only [lcAux₀] + ext X₀ Y₀ + simp only [TensorialAt.mkHom₂_apply_eq_extend, ContinuousLinearMap.add_apply, lcAux₀'] + rw [if_pos, if_pos, if_pos, if_pos, if_pos, if_pos] + · exact leviCivitaRhs_addY_apply _ (FiberBundle.mdifferentiableAt_extend ..) + hY hY' (FiberBundle.mdifferentiableAt_extend ..) + · exact FiberBundle.mdifferentiableAt_extend .. + · exact FiberBundle.mdifferentiableAt_extend .. + · exact FiberBundle.mdifferentiableAt_extend .. + · exact FiberBundle.mdifferentiableAt_extend .. + · exact FiberBundle.mdifferentiableAt_extend .. + · exact FiberBundle.mdifferentiableAt_extend .. + leibniz {Y f x} hY hf _ := by + dsimp [lcAux] + rw [dif_pos hY, dif_pos] + · unfold lcAux₁ + dsimp + rw [← ContinuousLinearMap.comp_smul] + have : FiniteDimensional ℝ (TangentSpace I x) := inferInstanceAs (FiniteDimensional ℝ E) + have : CompleteSpace (TangentSpace I x) := FiniteDimensional.complete ℝ _ + set Φ := InnerProductSpace.toDual ℝ (TangentSpace I x) + ext X₀ + apply Φ.injective + simp only [ContinuousLinearMap.coe_comp', ContinuousLinearEquiv.coe_coe, + LinearIsometryEquiv.coe_symm_toContinuousLinearEquiv, comp_apply, + LinearIsometryEquiv.apply_symm_apply, ContinuousLinearMap.comp_smulₛₗ, RingHom.id_apply, + ContinuousLinearMap.add_apply, ContinuousLinearMap.coe_smul', Pi.smul_apply, + map_add, map_smul] + ext Z₀ + simp only [lcAux₀, lcAux₀', TensorialAt.mkHom₂_apply_eq_extend, + ContinuousLinearMap.add_apply, ContinuousLinearMap.coe_smul', Pi.smul_apply, smul_eq_mul] + rw [if_pos, if_pos, if_pos, if_pos] + · convert leviCivitaRhs_smulY_apply I hf (FiberBundle.mdifferentiableAt_extend I E X₀) hY + (FiberBundle.mdifferentiableAt_extend I E Z₀) + simp [Φ, product] + · exact FiberBundle.mdifferentiableAt_extend .. + · exact FiberBundle.mdifferentiableAt_extend .. + · exact FiberBundle.mdifferentiableAt_extend .. + · exact FiberBundle.mdifferentiableAt_extend .. + exact MDifferentiableAt.smul_section hf hY + +end + +-- TODO: make g part of the notation! +variable (M) in +/-- A choice of Levi-Civita connection on the tangent bundle `TM` of a Riemannian manifold `(M, g)`: +this is unique up to the value on non-differentiable vector fields. +If you know the Levi-Civita connection already, you can use `IsLeviCivitaConnection` instead. -/ +noncomputable def LeviCivitaConnection [FiniteDimensional ℝ E] : + CovariantDerivative I E (TangentSpace I : M → Type _) where + toFun := lcAux I + isCovariantDerivativeOnUniv := isCovariantDerivativeOn_lcAux I + +theorem leviCivitaConnection_apply [FiniteDimensional ℝ E] {x : M} + {X : Π x : M, TangentSpace I x} (hX : MDiffAt (T% X) x) + {Y : Π x : M, TangentSpace I x} (hY : MDiffAt (T% Y) x) + {Z : Π x : M, TangentSpace I x} (hZ : MDiffAt (T% Z) x) : + inner ℝ (LeviCivitaConnection I M Y x (X x)) (Z x) = leviCivitaRhs I X Y Z x := + lcAux_apply _ hX hY hZ + +-- Side computation for `leviCivitaConnection_isCompatible`. +omit [IsManifold I 2 M] in +lemma leviCivitaConnection_isCompatible_aux + {x : M} {X Y Z : (x : M) → TangentSpace I x} : + leviCivitaRhs I X Y Z x + leviCivitaRhs I X Z Y x = + fromTangentSpace _ ((mfderiv% fun x ↦ inner ℝ (Y x) (Z x)) x (X x)) := by + simp only [leviCivitaRhs, Pi.smul_apply, ← smul_add, leviCivitaRhs'] + -- Normalise the expressions by swapping arguments for rhs_aux and mlieBracket, + -- until the swappable arguments are in order X < Y < Z. + rw [rhs_aux_swap I Z Y, rhs_aux_swap I Z X, rhs_aux_swap I Y X, + VectorField.mlieBracket_swap (V := Z) (W := Y), + VectorField.mlieBracket_swap (V := Y) (W := X), + VectorField.mlieBracket_swap (V := Z) (W := X)] + -- Observe that the right hand side is rhx_aux X Y Z; then we just need to simplify and rearrange. + trans 1 / 2 * (rhs_aux I X Y Z x + rhs_aux I X Y Z x) + · simp + abel + · rw [← two_mul, ← mul_assoc, one_div, inv_mul_cancel₀ (by simp), one_mul] + rfl + +-- Why is everything so slow? +lemma leviCivitaConnection_isCompatible [FiniteDimensional ℝ E] : + (LeviCivitaConnection I M).IsCompatible := by + rw [isCompatible_iff] + intro x X Y Z hX hY hZ + symm + unfold product + dsimp + rw [leviCivitaConnection_apply I hX hY hZ] + have : inner ℝ (Y x) (((LeviCivitaConnection I M) Z x) (X x)) = + inner ℝ (((LeviCivitaConnection I M) Z x) (X x)) (Y x) := by + rw [real_inner_comm] + -- TODO: why does the following line not work, but `rw [this]` does? + --rw [real_inner_comm] + rw [this] + have : inner ℝ (((LeviCivitaConnection I M) Z x) (X x)) (Y x) = leviCivitaRhs I X Z Y x := by + rw [leviCivitaConnection_apply I hX hZ hY] + rw [leviCivitaConnection_apply I hX hZ hY, leviCivitaConnection_isCompatible_aux] + +lemma leviCivitaConnection_torsion_eq_zero [FiniteDimensional ℝ E] : + (LeviCivitaConnection I M).torsion = 0 := by + have a := (LeviCivitaConnection I M).isCovariantDerivativeOnUniv + rw [CovariantDerivative.torsion_eq_zero_iff] + intro X Y x hX hY + apply congr_of_forall_product_apply + intro Z + trans (inner ℝ (((LeviCivitaConnection I M) Y x) (X x)) Z) - + (inner ℝ (((LeviCivitaConnection I M) X x) (Y x)) Z) + · apply inner_sub_left + have hZ' : extend E Z x = Z := extend_apply_self E Z + rw [← hZ'] + rw [leviCivitaConnection_apply I hY hX (mdifferentiableAt_extend ..)] + rw [leviCivitaConnection_apply I hX hY (mdifferentiableAt_extend ..)] + simp only [leviCivitaRhs_apply] + -- XXX: should there be leviCivitaRhs'_apply? + simp only [leviCivitaRhs', Pi.add_apply, Pi.sub_apply, product_apply] + simp only [VectorField.mlieBracket_swap (V := Y) (W := X)] + simp only [Pi.neg_apply, inner_neg_right, sub_neg_eq_add] + set C := inner ℝ Z (VectorField.mlieBracket I X Y x) + set Z' := extend E Z + simp only [VectorField.mlieBracket_swap (V := Z') (W := X)] + simp only [VectorField.mlieBracket_swap (V := Z') (W := Y)] + simp only [Pi.neg_apply, inner_neg_right] + rw [rhs_aux_swap (Y := Z'), rhs_aux_swap (Y := Z'), rhs_aux_swap (X := Z')] + rw [real_inner_comm (Z' x) (VectorField.mlieBracket I X Y x)] + -- set A := inner ℝ (Z' x) (VectorField.mlieBracket I X Y x) + -- set B := inner ℝ (Y x) (VectorField.mlieBracket I X Z' x) + -- set C := inner ℝ (X x) (VectorField.mlieBracket I Y Z' x) + -- set D := rhs_aux I X Y Z' x + -- set E := rhs_aux I Y X Z' x + -- set F := rhs_aux I Z' X Y x + match_scalars <;> simp + norm_num + +/-- `LeviCivitaConnection` is a Levi-Civita connection (i.e., compatible and torsion-free) -/ +lemma leviCivitaConnection_isLeviCivitaConnection [FiniteDimensional ℝ E] : + (LeviCivitaConnection I M).IsLeviCivitaConnection := + ⟨leviCivitaConnection_isCompatible I, leviCivitaConnection_torsion_eq_zero I⟩ + +end CovariantDerivative From faf2547d50c7d3d41a90d0b967a3c6dcf90df731 Mon Sep 17 00:00:00 2001 From: sgouezel Date: Mon, 23 Mar 2026 16:54:40 +0100 Subject: [PATCH 32/33] better typeclass formulation --- .../CovariantDerivative/Metric.lean | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index 560c29e93f4b4d..190e00b51d20f2 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -47,21 +47,15 @@ open scoped Manifold ContDiff @[expose] public section --- TODO: revisit and fix this once the dust has settled -set_option backward.isDefEq.respectTransparency false - variable -- Let `M` be a `C^k` real manifold modeled on `(E, H)` {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H) - {M : Type*} [TopologicalSpace M] [ChartedSpace H M] + {M : Type*} -- Let `V` be a bundle over `M`, endowed with a Riemannian metric. (F : Type*) [NormedAddCommGroup F] [NormedSpace ℝ F] {V : M → Type*} [TopologicalSpace (TotalSpace F V)] - [∀ x, AddCommGroup (V x)] [∀ x, Module ℝ (V x)] - [∀ x : M, TopologicalSpace (V x)] - [∀ x, IsTopologicalAddGroup (V x)] [∀ x, ContinuousSMul ℝ (V x)] - [FiberBundle F V] [RiemannianBundle V] + [∀ x, NormedAddCommGroup (V x)] [∀ x, InnerProductSpace ℝ (V x)] /-! # Compatible connections @@ -90,8 +84,6 @@ local notation "⟪" σ ", " τ "⟫" => product σ τ -- Basic API for the product of two sections. section product -omit [TopologicalSpace M] - lemma product_apply (x) : ⟪σ, τ⟫ x = inner ℝ (σ x) (τ x) := rfl variable (σ σ' τ) @@ -157,19 +149,16 @@ end product -- These lemmas are necessary as my Lie bracket identities (assuming minimal differentiability) -- only hold point-wise. They abstract the expanding and unexpanding of `product`. -omit [TopologicalSpace M] in lemma product_congr_left {x} (h : σ x = σ' x) : product σ τ x = product σ' τ x := by rw [product_apply, h, ← product_apply] -omit [TopologicalSpace M] in lemma product_congr_left₂ {x} (h : σ x = σ' x + σ'' x) : product σ τ x = product σ' τ x + product σ'' τ x := by rw [product_apply, h, inner_add_left, ← product_apply] -omit [TopologicalSpace M] in + lemma product_congr_right {x} (h : τ x = τ' x) : product σ τ x = product σ τ' x := by rw [product_apply, h, ← product_apply] -omit [TopologicalSpace M] in lemma product_congr_right₂ {x} (h : τ x = τ' x + τ'' x) : product σ τ x = product σ τ' x + product σ τ'' x := by rw [product_apply, h, inner_add_right, ← product_apply] @@ -178,8 +167,8 @@ namespace CovariantDerivative -- Let `cov` be a covariant derivative on `V`. -- TODO: include in cheat sheet! -variable (cov : CovariantDerivative I F V) - +variable [TopologicalSpace M] [ChartedSpace H M] [FiberBundle F V] + (cov : CovariantDerivative I F V) /-- Local notation for a covariant derivative on a vector bundle acting on a vector field and a section. -/ From b7b1ec0d9c22e58357a8812ba9943ba952111d9a Mon Sep 17 00:00:00 2001 From: Michael Rothgang Date: Sun, 29 Mar 2026 18:04:15 +0200 Subject: [PATCH 33/33] Workaround bumping failures; need to investigate --- .../CovariantDerivative/LeviCivita.lean | 16 ++++++++++++---- .../VectorBundle/CovariantDerivative/Metric.lean | 3 --- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/LeviCivita.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/LeviCivita.lean index 38b8450d10b69e..afd52db1688b2b 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/LeviCivita.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/LeviCivita.lean @@ -76,11 +76,13 @@ iff it is torsion-free and compatible with `g`. Note that the bundle metric on `TM` is implicitly hidden in this definition. See `TODO` for a version depending on a choice of Riemannian metric on `M`. -/ -def IsLeviCivitaConnection [FiniteDimensional ℝ E] : Prop := cov.IsCompatible ∧ cov.torsion = 0 +def IsLeviCivitaConnection [FiniteDimensional ℝ E] : Prop := + -- adaptation note: V used to be not required + cov.IsCompatible (V := (fun (x : M) ↦ TangentSpace I x)) ∧ cov.torsion = 0 local notation "⟪" X ", " Y "⟫" => product X Y -/- TODO: writing `hσ.inner_bundle hτ` or writing `by apply MDifferentiable.inner_bundle hσ hτ` +/- TODO: writing `hX.inner_bundle hY` or writing `by apply MDifferentiable.inner_bundle hX hY` yields an error synthesized type class instance is not definitionally equal to expression inferred by typing rules, synthesized @@ -558,7 +560,12 @@ lemma aux (h : cov.IsLeviCivitaConnection) {x : M} (hX : MDiffAt (T% X) x) (hY : MDiffAt (T% Y) x) (hZ : MDiffAt (T% Z) x) : rhs_aux I X Y Z x = ⟪∇ Y, X, Z⟫ x + ⟪Y, ∇ X, Z⟫ x + ⟪Y, VectorField.mlieBracket I X Z⟫ x := by trans ⟪∇ Y, X, Z⟫ x + ⟪Y, ∇ Z, X⟫ x - · exact cov.isCompatible_iff.mp h.1 hX hY hZ + · -- adaptation note: the following line fails with an error + /- synthesized type class instance is not definitionally equal to expression inferred by typing rules, synthesized + fun x ↦ instNormedAddCommGroupOfRiemannianBundleOfIsTopologicalAddGroupOfContinuousConstSMulReal x + inferred + fun b ↦ inst✝⁸ -/ + sorry -- exact cov.isCompatible_iff.mp h.1 hX hY hZ · simp [← cov.torsion_eq_zero_iff.mp h.2 hX hZ, product, inner_sub_right] variable {cov} in @@ -800,7 +807,8 @@ lemma leviCivitaConnection_isCompatible_aux -- Why is everything so slow? lemma leviCivitaConnection_isCompatible [FiniteDimensional ℝ E] : - (LeviCivitaConnection I M).IsCompatible := by + -- adaptation note: specifying V used to be not necessary + (LeviCivitaConnection I M).IsCompatible (V := (fun (x : M) ↦ TangentSpace I x)) := by rw [isCompatible_iff] intro x X Y Z hX hY hZ symm diff --git a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean index 190e00b51d20f2..300fc559a33d70 100644 --- a/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean +++ b/Mathlib/Geometry/Manifold/VectorBundle/CovariantDerivative/Metric.lean @@ -70,9 +70,6 @@ differentiable at `x`. variable {σ σ' σ'' τ τ' τ'' : Π x : M, V x} --- set_option trace.profiler true --- set_option profiler.threshold 500 - /-- The scalar product of two sections. -/ noncomputable abbrev product (σ τ : Π x : M, V x) : M → ℝ := fun x ↦ inner ℝ (σ x) (τ x)