-
Notifications
You must be signed in to change notification settings - Fork 396
/
Copy pathIntegralCurve.lean
574 lines (491 loc) · 28.6 KB
/
IntegralCurve.lean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
/-
Copyright (c) 2023 Winston Yin. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Winston Yin
-/
import Mathlib.Analysis.ODE.Gronwall
import Mathlib.Analysis.ODE.PicardLindelof
import Mathlib.Geometry.Manifold.InteriorBoundary
import Mathlib.Geometry.Manifold.MFDeriv.Atlas
/-!
# Integral curves of vector fields on a manifold
Let `M` be a manifold and `v : (x : M) → TangentSpace I x` be a vector field on `M`. An integral
curve of `v` is a function `γ : ℝ → M` such that the derivative of `γ` at `t` equals `v (γ t)`. The
integral curve may only be defined for all `t` within some subset of `ℝ`.
## Main definitions
Let `v : M → TM` be a vector field on `M`, and let `γ : ℝ → M`.
* `IsIntegralCurve γ v`: `γ t` is tangent to `v (γ t)` for all `t : ℝ`. That is, `γ` is a global
integral curve of `v`.
* `IsIntegralCurveOn γ v s`: `γ t` is tangent to `v (γ t)` for all `t ∈ s`, where `s : Set ℝ`.
* `IsIntegralCurveAt γ v t₀`: `γ t` is tangent to `v (γ t)` for all `t` in some open interval
around `t₀`. That is, `γ` is a local integral curve of `v`.
For `IsIntegralCurveOn γ v s` and `IsIntegralCurveAt γ v t₀`, even though `γ` is defined for all
time, its value outside of the set `s` or a small interval around `t₀` is irrelevant and considered
junk.
## Main results
* `exists_isIntegralCurveAt_of_contMDiffAt_boundaryless`: Existence of local integral curves for a
$C^1$ vector field. This follows from the existence theorem for solutions to ODEs
(`exists_forall_hasDerivAt_Ioo_eq_of_contDiffAt`).
* `isIntegralCurveOn_Ioo_eqOn_of_contMDiff_boundaryless`: Uniqueness of local integral curves for a
$C^1$ vector field. This follows from the uniqueness theorem for solutions to ODEs
(`ODE_solution_unique_of_mem_set_Ioo`). This requires the manifold to be Hausdorff (`T2Space`).
## Implementation notes
For the existence and uniqueness theorems, we assume that the image of the integral curve lies in
the interior of the manifold. The case where the integral curve may lie on the boundary of the
manifold requires special treatment, and we leave it as a TODO.
We state simpler versions of the theorem for boundaryless manifolds as corollaries.
## TODO
* The case where the integral curve may venture to the boundary of the manifold. See Theorem 9.34,
Lee. May require submanifolds.
## Reference
* Lee, J. M. (2012). _Introduction to Smooth Manifolds_. Springer New York.
## Tags
integral curve, vector field, local existence, uniqueness
-/
open scoped Manifold Topology
open Function Set
variable
{E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E]
{H : Type*} [TopologicalSpace H] {I : ModelWithCorners ℝ E H}
{M : Type*} [TopologicalSpace M] [ChartedSpace H M] [SmoothManifoldWithCorners I M]
/-- If `γ : ℝ → M` is $C^1$ on `s : Set ℝ` and `v` is a vector field on `M`,
`IsIntegralCurveOn γ v s` means `γ t` is tangent to `v (γ t)` for all `t ∈ s`. The value of `γ`
outside of `s` is irrelevant and considered junk. -/
def IsIntegralCurveOn (γ : ℝ → M) (v : (x : M) → TangentSpace I x) (s : Set ℝ) : Prop :=
∀ t ∈ s, HasMFDerivAt 𝓘(ℝ, ℝ) I γ t ((1 : ℝ →L[ℝ] ℝ).smulRight <| v (γ t))
/-- If `v` is a vector field on `M` and `t₀ : ℝ`, `IsIntegralCurveAt γ v t₀` means `γ : ℝ → M` is a
local integral curve of `v` in a neighbourhood containing `t₀`. The value of `γ` outside of this
interval is irrelevant and considered junk. -/
def IsIntegralCurveAt (γ : ℝ → M) (v : (x : M) → TangentSpace I x) (t₀ : ℝ) : Prop :=
∀ᶠ t in 𝓝 t₀, HasMFDerivAt 𝓘(ℝ, ℝ) I γ t ((1 : ℝ →L[ℝ] ℝ).smulRight <| v (γ t))
/-- If `v : M → TM` is a vector field on `M`, `IsIntegralCurve γ v` means `γ : ℝ → M` is a global
integral curve of `v`. That is, `γ t` is tangent to `v (γ t)` for all `t : ℝ`. -/
def IsIntegralCurve (γ : ℝ → M) (v : (x : M) → TangentSpace I x) : Prop :=
∀ t : ℝ, HasMFDerivAt 𝓘(ℝ, ℝ) I γ t ((1 : ℝ →L[ℝ] ℝ).smulRight (v (γ t)))
variable {γ γ' : ℝ → M} {v : (x : M) → TangentSpace I x} {s s' : Set ℝ} {t₀ : ℝ}
lemma IsIntegralCurve.isIntegralCurveOn (h : IsIntegralCurve γ v) (s : Set ℝ) :
IsIntegralCurveOn γ v s := fun t _ ↦ h t
lemma isIntegralCurve_iff_isIntegralCurveOn : IsIntegralCurve γ v ↔ IsIntegralCurveOn γ v univ :=
⟨fun h ↦ h.isIntegralCurveOn _, fun h t ↦ h t (mem_univ _)⟩
lemma isIntegralCurveAt_iff :
IsIntegralCurveAt γ v t₀ ↔ ∃ s ∈ 𝓝 t₀, IsIntegralCurveOn γ v s := by
simp_rw [IsIntegralCurveOn, ← Filter.eventually_iff_exists_mem, IsIntegralCurveAt]
/-- `γ` is an integral curve for `v` at `t₀` iff `γ` is an integral curve on some interval
containing `t₀`. -/
lemma isIntegralCurveAt_iff' :
IsIntegralCurveAt γ v t₀ ↔ ∃ ε > 0, IsIntegralCurveOn γ v (Metric.ball t₀ ε) := by
simp_rw [IsIntegralCurveOn, ← Metric.eventually_nhds_iff_ball, IsIntegralCurveAt]
lemma IsIntegralCurve.isIntegralCurveAt (h : IsIntegralCurve γ v) (t : ℝ) :
IsIntegralCurveAt γ v t := isIntegralCurveAt_iff.mpr ⟨univ, Filter.univ_mem, fun t _ ↦ h t⟩
lemma isIntegralCurve_iff_isIntegralCurveAt :
IsIntegralCurve γ v ↔ ∀ t : ℝ, IsIntegralCurveAt γ v t :=
⟨fun h ↦ h.isIntegralCurveAt, fun h t ↦ by
obtain ⟨s, hs, h⟩ := isIntegralCurveAt_iff.mp (h t)
exact h t (mem_of_mem_nhds hs)⟩
lemma IsIntegralCurveOn.mono (h : IsIntegralCurveOn γ v s) (hs : s' ⊆ s) :
IsIntegralCurveOn γ v s' := fun t ht ↦ h t (mem_of_mem_of_subset ht hs)
lemma IsIntegralCurveOn.of_union (h : IsIntegralCurveOn γ v s) (h' : IsIntegralCurveOn γ v s') :
IsIntegralCurveOn γ v (s ∪ s') := fun _ ↦ fun | .inl ht => h _ ht | .inr ht => h' _ ht
lemma IsIntegralCurveAt.hasMFDerivAt (h : IsIntegralCurveAt γ v t₀) :
HasMFDerivAt 𝓘(ℝ, ℝ) I γ t₀ ((1 : ℝ →L[ℝ] ℝ).smulRight (v (γ t₀))) :=
have ⟨_, hs, h⟩ := isIntegralCurveAt_iff.mp h
h t₀ (mem_of_mem_nhds hs)
lemma IsIntegralCurveOn.isIntegralCurveAt (h : IsIntegralCurveOn γ v s) (hs : s ∈ 𝓝 t₀) :
IsIntegralCurveAt γ v t₀ := isIntegralCurveAt_iff.mpr ⟨s, hs, h⟩
/-- If `γ` is an integral curve at each `t ∈ s`, it is an integral curve on `s`. -/
lemma IsIntegralCurveAt.isIntegralCurveOn (h : ∀ t ∈ s, IsIntegralCurveAt γ v t) :
IsIntegralCurveOn γ v s := by
intros t ht
obtain ⟨s, hs, h⟩ := isIntegralCurveAt_iff.mp (h t ht)
exact h t (mem_of_mem_nhds hs)
lemma isIntegralCurveOn_iff_isIntegralCurveAt (hs : IsOpen s) :
IsIntegralCurveOn γ v s ↔ ∀ t ∈ s, IsIntegralCurveAt γ v t :=
⟨fun h _ ht ↦ h.isIntegralCurveAt (hs.mem_nhds ht), IsIntegralCurveAt.isIntegralCurveOn⟩
lemma IsIntegralCurveOn.continuousAt (hγ : IsIntegralCurveOn γ v s) (ht : t₀ ∈ s) :
ContinuousAt γ t₀ := (hγ t₀ ht).1
lemma IsIntegralCurveOn.continuousOn (hγ : IsIntegralCurveOn γ v s) :
ContinuousOn γ s := fun t ht ↦ (hγ t ht).1.continuousWithinAt
lemma IsIntegralCurveAt.continuousAt (hγ : IsIntegralCurveAt γ v t₀) :
ContinuousAt γ t₀ :=
have ⟨_, hs, hγ⟩ := isIntegralCurveAt_iff.mp hγ
hγ.continuousAt <| mem_of_mem_nhds hs
lemma IsIntegralCurve.continuous (hγ : IsIntegralCurve γ v) : Continuous γ :=
continuous_iff_continuousAt.mpr fun _ ↦ (hγ.isIntegralCurveOn univ).continuousAt (mem_univ _)
/-- If `γ` is an integral curve of a vector field `v`, then `γ t` is tangent to `v (γ t)` when
expressed in the local chart around the initial point `γ t₀`. -/
lemma IsIntegralCurveOn.hasDerivAt (hγ : IsIntegralCurveOn γ v s) {t : ℝ} (ht : t ∈ s)
(hsrc : γ t ∈ (extChartAt I (γ t₀)).source) :
HasDerivAt ((extChartAt I (γ t₀)) ∘ γ)
(tangentCoordChange I (γ t) (γ t₀) (γ t) (v (γ t))) t := by
-- turn `HasDerivAt` into comp of `HasMFDerivAt`
have hsrc := extChartAt_source I (γ t₀) ▸ hsrc
rw [hasDerivAt_iff_hasFDerivAt, ← hasMFDerivAt_iff_hasFDerivAt]
apply (HasMFDerivAt.comp t
(hasMFDerivAt_extChartAt I hsrc) (hγ _ ht)).congr_mfderiv
rw [ContinuousLinearMap.ext_iff]
intro a
rw [ContinuousLinearMap.comp_apply, ContinuousLinearMap.smulRight_apply, map_smul,
← ContinuousLinearMap.one_apply (R₁ := ℝ) a, ← ContinuousLinearMap.smulRight_apply,
mfderiv_chartAt_eq_tangentCoordChange I hsrc]
rfl
lemma IsIntegralCurveAt.eventually_hasDerivAt (hγ : IsIntegralCurveAt γ v t₀) :
∀ᶠ t in 𝓝 t₀, HasDerivAt ((extChartAt I (γ t₀)) ∘ γ)
(tangentCoordChange I (γ t) (γ t₀) (γ t) (v (γ t))) t := by
apply eventually_mem_nhds.mpr
(hγ.continuousAt.preimage_mem_nhds (extChartAt_source_mem_nhds I _)) |>.and hγ |>.mono
rintro t ⟨ht1, ht2⟩
have hsrc := mem_of_mem_nhds ht1
rw [mem_preimage, extChartAt_source I (γ t₀)] at hsrc
rw [hasDerivAt_iff_hasFDerivAt, ← hasMFDerivAt_iff_hasFDerivAt]
apply (HasMFDerivAt.comp t (hasMFDerivAt_extChartAt I hsrc) ht2).congr_mfderiv
rw [ContinuousLinearMap.ext_iff]
intro a
rw [ContinuousLinearMap.comp_apply, ContinuousLinearMap.smulRight_apply, map_smul,
← ContinuousLinearMap.one_apply (R₁ := ℝ) a, ← ContinuousLinearMap.smulRight_apply,
mfderiv_chartAt_eq_tangentCoordChange I hsrc]
rfl
/-! ### Translation lemmas -/
section Translation
lemma IsIntegralCurveOn.comp_add (hγ : IsIntegralCurveOn γ v s) (dt : ℝ) :
IsIntegralCurveOn (γ ∘ (· + dt)) v { t | t + dt ∈ s } := by
intros t ht
rw [comp_apply, ← ContinuousLinearMap.comp_id (ContinuousLinearMap.smulRight 1 (v (γ (t + dt))))]
apply HasMFDerivAt.comp t (hγ (t + dt) ht)
refine ⟨(continuous_add_right _).continuousAt, ?_⟩
simp only [mfld_simps, hasFDerivWithinAt_univ]
exact HasFDerivAt.add_const (hasFDerivAt_id _) _
lemma isIntegralCurveOn_comp_add {dt : ℝ} :
IsIntegralCurveOn γ v s ↔ IsIntegralCurveOn (γ ∘ (· + dt)) v { t | t + dt ∈ s } := by
refine ⟨fun hγ ↦ hγ.comp_add _, fun hγ ↦ ?_⟩
convert hγ.comp_add (-dt)
· ext t
simp only [Function.comp_apply, neg_add_cancel_right]
· simp only [mem_setOf_eq, neg_add_cancel_right, setOf_mem_eq]
lemma IsIntegralCurveAt.comp_add (hγ : IsIntegralCurveAt γ v t₀) (dt : ℝ) :
IsIntegralCurveAt (γ ∘ (· + dt)) v (t₀ - dt) := by
rw [isIntegralCurveAt_iff'] at *
obtain ⟨ε, hε, h⟩ := hγ
refine ⟨ε, hε, ?_⟩
convert h.comp_add dt
ext t
rw [mem_setOf_eq, Metric.mem_ball, Metric.mem_ball, dist_sub_eq_dist_add_right]
lemma isIntegralCurveAt_comp_add {dt : ℝ} :
IsIntegralCurveAt γ v t₀ ↔ IsIntegralCurveAt (γ ∘ (· + dt)) v (t₀ - dt) := by
refine ⟨fun hγ ↦ hγ.comp_add _, fun hγ ↦ ?_⟩
convert hγ.comp_add (-dt)
· ext t
simp only [Function.comp_apply, neg_add_cancel_right]
· simp only [sub_neg_eq_add, sub_add_cancel]
lemma IsIntegralCurve.comp_add (hγ : IsIntegralCurve γ v) (dt : ℝ) :
IsIntegralCurve (γ ∘ (· + dt)) v := by
rw [isIntegralCurve_iff_isIntegralCurveOn] at *
exact hγ.comp_add _
lemma isIntegralCurve_comp_add {dt : ℝ} :
IsIntegralCurve γ v ↔ IsIntegralCurve (γ ∘ (· + dt)) v := by
refine ⟨fun hγ ↦ hγ.comp_add _, fun hγ ↦ ?_⟩
convert hγ.comp_add (-dt)
ext t
simp only [Function.comp_apply, neg_add_cancel_right]
end Translation
/-! ### Scaling lemmas -/
section Scaling
lemma IsIntegralCurveOn.comp_mul (hγ : IsIntegralCurveOn γ v s) (a : ℝ) :
IsIntegralCurveOn (γ ∘ (· * a)) (a • v) { t | t * a ∈ s } := by
intros t ht
rw [comp_apply, Pi.smul_apply, ← ContinuousLinearMap.smulRight_comp]
refine HasMFDerivAt.comp t (hγ (t * a) ht) ⟨(continuous_mul_right _).continuousAt, ?_⟩
simp only [mfld_simps, hasFDerivWithinAt_univ]
exact HasFDerivAt.mul_const' (hasFDerivAt_id _) _
lemma isIntegralCurveOn_comp_mul_ne_zero {a : ℝ} (ha : a ≠ 0) :
IsIntegralCurveOn γ v s ↔ IsIntegralCurveOn (γ ∘ (· * a)) (a • v) { t | t * a ∈ s } := by
refine ⟨fun hγ ↦ hγ.comp_mul a, fun hγ ↦ ?_⟩
convert hγ.comp_mul a⁻¹
· ext t
simp only [Function.comp_apply, mul_assoc, inv_mul_eq_div, div_self ha, mul_one]
· simp only [smul_smul, inv_mul_eq_div, div_self ha, one_smul]
· simp only [mem_setOf_eq, mul_assoc, inv_mul_eq_div, div_self ha, mul_one, setOf_mem_eq]
lemma IsIntegralCurveAt.comp_mul_ne_zero (hγ : IsIntegralCurveAt γ v t₀) {a : ℝ} (ha : a ≠ 0) :
IsIntegralCurveAt (γ ∘ (· * a)) (a • v) (t₀ / a) := by
rw [isIntegralCurveAt_iff'] at *
obtain ⟨ε, hε, h⟩ := hγ
refine ⟨ε / |a|, by positivity, ?_⟩
convert h.comp_mul a
ext t
rw [mem_setOf_eq, Metric.mem_ball, Metric.mem_ball, Real.dist_eq, Real.dist_eq,
lt_div_iff (abs_pos.mpr ha), ← abs_mul, sub_mul, div_mul_cancel₀ _ ha]
lemma isIntegralCurveAt_comp_mul_ne_zero {a : ℝ} (ha : a ≠ 0) :
IsIntegralCurveAt γ v t₀ ↔ IsIntegralCurveAt (γ ∘ (· * a)) (a • v) (t₀ / a) := by
refine ⟨fun hγ ↦ hγ.comp_mul_ne_zero ha, fun hγ ↦ ?_⟩
convert hγ.comp_mul_ne_zero (inv_ne_zero ha)
· ext t
simp only [Function.comp_apply, mul_assoc, inv_mul_eq_div, div_self ha, mul_one]
· simp only [smul_smul, inv_mul_eq_div, div_self ha, one_smul]
· simp only [div_inv_eq_mul, div_mul_cancel₀ _ ha]
lemma IsIntegralCurve.comp_mul (hγ : IsIntegralCurve γ v) (a : ℝ) :
IsIntegralCurve (γ ∘ (· * a)) (a • v) := by
rw [isIntegralCurve_iff_isIntegralCurveOn] at *
exact hγ.comp_mul _
lemma isIntegralCurve_comp_mul_ne_zero {a : ℝ} (ha : a ≠ 0) :
IsIntegralCurve γ v ↔ IsIntegralCurve (γ ∘ (· * a)) (a • v) := by
refine ⟨fun hγ ↦ hγ.comp_mul _, fun hγ ↦ ?_⟩
convert hγ.comp_mul a⁻¹
· ext t
simp only [Function.comp_apply, mul_assoc, inv_mul_eq_div, div_self ha, mul_one]
· simp only [smul_smul, inv_mul_eq_div, div_self ha, one_smul]
/-- If the vector field `v` vanishes at `x₀`, then the constant curve at `x₀`
is a global integral curve of `v`. -/
lemma isIntegralCurve_const {x : M} (h : v x = 0) : IsIntegralCurve (fun _ ↦ x) v := by
intro t
rw [h, ← ContinuousLinearMap.zero_apply (R₁ := ℝ) (R₂ := ℝ) (1 : ℝ),
ContinuousLinearMap.smulRight_one_one]
exact hasMFDerivAt_const ..
end Scaling
/-! ### Existence and uniqueness -/
section ExistUnique
variable (t₀) {x₀ : M}
/-- Existence of local integral curves for a $C^1$ vector field at interior points of a smooth
manifold. -/
theorem exists_isIntegralCurveAt_of_contMDiffAt [CompleteSpace E]
(hv : ContMDiffAt I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)) x₀)
(hx : I.IsInteriorPoint x₀) :
∃ γ : ℝ → M, γ t₀ = x₀ ∧ IsIntegralCurveAt γ v t₀ := by
-- express the differentiability of the vector field `v` in the local chart
rw [contMDiffAt_iff] at hv
obtain ⟨_, hv⟩ := hv
-- use Picard-Lindelöf theorem to extract a solution to the ODE in the local chart
obtain ⟨f, hf1, hf2⟩ := exists_forall_hasDerivAt_Ioo_eq_of_contDiffAt t₀
(hv.contDiffAt (range_mem_nhds_isInteriorPoint hx)).snd
simp_rw [← Real.ball_eq_Ioo, ← Metric.eventually_nhds_iff_ball] at hf2
-- use continuity of `f` so that `f t` remains inside `interior (extChartAt I x₀).target`
have ⟨a, ha, hf2'⟩ := Metric.eventually_nhds_iff_ball.mp hf2
have hcont := (hf2' t₀ (Metric.mem_ball_self ha)).continuousAt
rw [continuousAt_def, hf1] at hcont
have hnhds : f ⁻¹' (interior (extChartAt I x₀).target) ∈ 𝓝 t₀ :=
hcont _ (isOpen_interior.mem_nhds ((I.isInteriorPoint_iff).mp hx))
rw [← eventually_mem_nhds] at hnhds
-- obtain a neighbourhood `s` so that the above conditions both hold in `s`
obtain ⟨s, hs, haux⟩ := (hf2.and hnhds).exists_mem
-- prove that `γ := (extChartAt I x₀).symm ∘ f` is a desired integral curve
refine ⟨(extChartAt I x₀).symm ∘ f,
Eq.symm (by rw [Function.comp_apply, hf1, PartialEquiv.left_inv _ (mem_extChartAt_source ..)]),
isIntegralCurveAt_iff.mpr ⟨s, hs, ?_⟩⟩
intros t ht
-- collect useful terms in convenient forms
let xₜ : M := (extChartAt I x₀).symm (f t) -- `xₜ := γ t`
have h : HasDerivAt f (x := t) <| fderivWithin ℝ (extChartAt I x₀ ∘ (extChartAt I xₜ).symm)
(range I) (extChartAt I xₜ xₜ) (v xₜ) := (haux t ht).1
rw [← tangentCoordChange_def] at h
have hf3 := mem_preimage.mp <| mem_of_mem_nhds (haux t ht).2
have hf3' := mem_of_mem_of_subset hf3 interior_subset
have hft1 := mem_preimage.mp <|
mem_of_mem_of_subset hf3' (extChartAt I x₀).target_subset_preimage_source
have hft2 := mem_extChartAt_source I xₜ
-- express the derivative of the integral curve in the local chart
refine ⟨(continuousAt_extChartAt_symm'' _ hf3').comp h.continuousAt,
HasDerivWithinAt.hasFDerivWithinAt ?_⟩
simp only [mfld_simps, hasDerivWithinAt_univ]
show HasDerivAt ((extChartAt I xₜ ∘ (extChartAt I x₀).symm) ∘ f) (v xₜ) t
-- express `v (γ t)` as `D⁻¹ D (v (γ t))`, where `D` is a change of coordinates, so we can use
-- `HasFDerivAt.comp_hasDerivAt` on `h`
rw [← tangentCoordChange_self (I := I) (x := xₜ) (z := xₜ) (v := v xₜ) hft2,
← tangentCoordChange_comp (x := x₀) ⟨⟨hft2, hft1⟩, hft2⟩]
apply HasFDerivAt.comp_hasDerivAt _ _ h
apply HasFDerivWithinAt.hasFDerivAt (s := range I) _ <|
mem_nhds_iff.mpr ⟨interior (extChartAt I x₀).target,
subset_trans interior_subset (extChartAt_target_subset_range ..),
isOpen_interior, hf3⟩
rw [← (extChartAt I x₀).right_inv hf3']
exact hasFDerivWithinAt_tangentCoordChange ⟨hft1, hft2⟩
/-- Existence of local integral curves for a $C^1$ vector field on a smooth manifold without
boundary. -/
lemma exists_isIntegralCurveAt_of_contMDiffAt_boundaryless
[CompleteSpace E] [BoundarylessManifold I M]
(hv : ContMDiffAt I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)) x₀) :
∃ γ : ℝ → M, γ t₀ = x₀ ∧ IsIntegralCurveAt γ v t₀ :=
exists_isIntegralCurveAt_of_contMDiffAt t₀ hv (BoundarylessManifold.isInteriorPoint I)
variable {t₀}
/-- Local integral curves are unique.
If a $C^1$ vector field `v` admits two local integral curves `γ γ' : ℝ → M` at `t₀` with
`γ t₀ = γ' t₀`, then `γ` and `γ'` agree on some open interval containing `t₀`. -/
theorem isIntegralCurveAt_eventuallyEq_of_contMDiffAt (hγt₀ : I.IsInteriorPoint (γ t₀))
(hv : ContMDiffAt I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)) (γ t₀))
(hγ : IsIntegralCurveAt γ v t₀) (hγ' : IsIntegralCurveAt γ' v t₀) (h : γ t₀ = γ' t₀) :
γ =ᶠ[𝓝 t₀] γ' := by
-- first define `v'` as the vector field expressed in the local chart around `γ t₀`
-- this is basically what the function looks like when `hv` is unfolded
set v' : E → E := fun x ↦
tangentCoordChange I ((extChartAt I (γ t₀)).symm x) (γ t₀) ((extChartAt I (γ t₀)).symm x)
(v ((extChartAt I (γ t₀)).symm x)) with hv'
-- extract a set `s` on which `v'` is Lipschitz
rw [contMDiffAt_iff] at hv
obtain ⟨_, hv⟩ := hv
obtain ⟨K, s, hs, hlip⟩ : ∃ K, ∃ s ∈ 𝓝 _, LipschitzOnWith K v' s :=
(hv.contDiffAt (range_mem_nhds_isInteriorPoint hγt₀)).snd.exists_lipschitzOnWith
have hlip (t : ℝ) : LipschitzOnWith K ((fun _ ↦ v') t) ((fun _ ↦ s) t) := hlip
-- internal lemmas to reduce code duplication
have hsrc {g} (hg : IsIntegralCurveAt g v t₀) :
∀ᶠ t in 𝓝 t₀, g ⁻¹' (extChartAt I (g t₀)).source ∈ 𝓝 t := eventually_mem_nhds.mpr <|
continuousAt_def.mp hg.continuousAt _ <| extChartAt_source_mem_nhds I (g t₀)
have hmem {g : ℝ → M} {t} (ht : g ⁻¹' (extChartAt I (g t₀)).source ∈ 𝓝 t) :
g t ∈ (extChartAt I (g t₀)).source := mem_preimage.mp <| mem_of_mem_nhds ht
have hdrv {g} (hg : IsIntegralCurveAt g v t₀) (h' : γ t₀ = g t₀) : ∀ᶠ t in 𝓝 t₀,
HasDerivAt ((extChartAt I (g t₀)) ∘ g) ((fun _ ↦ v') t (((extChartAt I (g t₀)) ∘ g) t)) t ∧
((extChartAt I (g t₀)) ∘ g) t ∈ (fun _ ↦ s) t := by
apply Filter.Eventually.and
· apply (hsrc hg |>.and hg.eventually_hasDerivAt).mono
rintro t ⟨ht1, ht2⟩
rw [hv', h']
apply ht2.congr_deriv
congr <;>
rw [Function.comp_apply, PartialEquiv.left_inv _ (hmem ht1)]
· apply ((continuousAt_extChartAt I (g t₀)).comp hg.continuousAt).preimage_mem_nhds
rw [Function.comp_apply, ← h']
exact hs
have heq {g} (hg : IsIntegralCurveAt g v t₀) :
g =ᶠ[𝓝 t₀] (extChartAt I (g t₀)).symm ∘ ↑(extChartAt I (g t₀)) ∘ g := by
apply (hsrc hg).mono
intros t ht
rw [Function.comp_apply, Function.comp_apply, PartialEquiv.left_inv _ (hmem ht)]
-- main proof
suffices (extChartAt I (γ t₀)) ∘ γ =ᶠ[𝓝 t₀] (extChartAt I (γ' t₀)) ∘ γ' from
(heq hγ).trans <| (this.fun_comp (extChartAt I (γ t₀)).symm).trans (h ▸ (heq hγ').symm)
exact ODE_solution_unique_of_eventually hlip
(hdrv hγ rfl) (hdrv hγ' h) (by rw [Function.comp_apply, Function.comp_apply, h])
theorem isIntegralCurveAt_eventuallyEq_of_contMDiffAt_boundaryless [BoundarylessManifold I M]
(hv : ContMDiffAt I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)) (γ t₀))
(hγ : IsIntegralCurveAt γ v t₀) (hγ' : IsIntegralCurveAt γ' v t₀) (h : γ t₀ = γ' t₀) :
γ =ᶠ[𝓝 t₀] γ' :=
isIntegralCurveAt_eventuallyEq_of_contMDiffAt (BoundarylessManifold.isInteriorPoint I) hv hγ hγ' h
variable [T2Space M] {a b : ℝ}
/-- Integral curves are unique on open intervals.
If a $C^1$ vector field `v` admits two integral curves `γ γ' : ℝ → M` on some open interval
`Ioo a b`, and `γ t₀ = γ' t₀` for some `t ∈ Ioo a b`, then `γ` and `γ'` agree on `Ioo a b`. -/
theorem isIntegralCurveOn_Ioo_eqOn_of_contMDiff (ht₀ : t₀ ∈ Ioo a b)
(hγt : ∀ t ∈ Ioo a b, I.IsInteriorPoint (γ t))
(hv : ContMDiff I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)))
(hγ : IsIntegralCurveOn γ v (Ioo a b)) (hγ' : IsIntegralCurveOn γ' v (Ioo a b))
(h : γ t₀ = γ' t₀) : EqOn γ γ' (Ioo a b) := by
set s := {t | γ t = γ' t} ∩ Ioo a b with hs
-- since `Ioo a b` is connected, we get `s = Ioo a b` by showing that `s` is clopen in `Ioo a b`
-- in the subtype topology (`s` is also non-empty by assumption)
-- here we use a slightly weaker alternative theorem
suffices hsub : Ioo a b ⊆ s from fun t ht ↦ mem_setOf.mp ((subset_def ▸ hsub) t ht).1
apply isPreconnected_Ioo.subset_of_closure_inter_subset (s := Ioo a b) (u := s) _
⟨t₀, ⟨ht₀, ⟨h, ht₀⟩⟩⟩
· -- is this really the most convenient way to pass to subtype topology?
-- TODO: shorten this when better API around subtype topology exists
rw [hs, inter_comm, ← Subtype.image_preimage_val, inter_comm, ← Subtype.image_preimage_val,
image_subset_image_iff Subtype.val_injective, preimage_setOf_eq]
intros t ht
rw [mem_preimage, ← closure_subtype] at ht
revert ht t
apply IsClosed.closure_subset (isClosed_eq _ _)
· rw [continuous_iff_continuousAt]
rintro ⟨_, ht⟩
apply ContinuousAt.comp _ continuousAt_subtype_val
rw [Subtype.coe_mk]
exact hγ.continuousAt ht
· rw [continuous_iff_continuousAt]
rintro ⟨_, ht⟩
apply ContinuousAt.comp _ continuousAt_subtype_val
rw [Subtype.coe_mk]
exact hγ'.continuousAt ht
· rw [isOpen_iff_mem_nhds]
intro t₁ ht₁
have hmem := Ioo_mem_nhds ht₁.2.1 ht₁.2.2
have heq : γ =ᶠ[𝓝 t₁] γ' := isIntegralCurveAt_eventuallyEq_of_contMDiffAt
(hγt _ ht₁.2) hv.contMDiffAt (hγ.isIntegralCurveAt hmem) (hγ'.isIntegralCurveAt hmem) ht₁.1
apply (heq.and hmem).mono
exact fun _ ht ↦ ht
theorem isIntegralCurveOn_Ioo_eqOn_of_contMDiff_boundaryless [BoundarylessManifold I M]
(ht₀ : t₀ ∈ Ioo a b)
(hv : ContMDiff I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)))
(hγ : IsIntegralCurveOn γ v (Ioo a b)) (hγ' : IsIntegralCurveOn γ' v (Ioo a b))
(h : γ t₀ = γ' t₀) : EqOn γ γ' (Ioo a b) :=
isIntegralCurveOn_Ioo_eqOn_of_contMDiff
ht₀ (fun _ _ ↦ BoundarylessManifold.isInteriorPoint I) hv hγ hγ' h
/-- Global integral curves are unique.
If a continuously differentiable vector field `v` admits two global integral curves
`γ γ' : ℝ → M`, and `γ t₀ = γ' t₀` for some `t₀`, then `γ` and `γ'` are equal. -/
theorem isIntegralCurve_eq_of_contMDiff (hγt : ∀ t, I.IsInteriorPoint (γ t))
(hv : ContMDiff I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)))
(hγ : IsIntegralCurve γ v) (hγ' : IsIntegralCurve γ' v) (h : γ t₀ = γ' t₀) : γ = γ' := by
ext t
obtain ⟨T, ht₀, ht⟩ : ∃ T, t ∈ Ioo (-T) T ∧ t₀ ∈ Ioo (-T) T := by
obtain ⟨T, hT₁, hT₂⟩ := exists_abs_lt t
obtain ⟨hT₂, hT₃⟩ := abs_lt.mp hT₂
obtain ⟨S, hS₁, hS₂⟩ := exists_abs_lt t₀
obtain ⟨hS₂, hS₃⟩ := abs_lt.mp hS₂
exact ⟨T + S, by constructor <;> constructor <;> linarith⟩
exact isIntegralCurveOn_Ioo_eqOn_of_contMDiff ht (fun t _ ↦ hγt t) hv
((hγ.isIntegralCurveOn _).mono (subset_univ _))
((hγ'.isIntegralCurveOn _).mono (subset_univ _)) h ht₀
theorem isIntegralCurve_Ioo_eq_of_contMDiff_boundaryless [BoundarylessManifold I M]
(hv : ContMDiff I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)))
(hγ : IsIntegralCurve γ v) (hγ' : IsIntegralCurve γ' v) (h : γ t₀ = γ' t₀) : γ = γ' :=
isIntegralCurve_eq_of_contMDiff (fun _ ↦ BoundarylessManifold.isInteriorPoint I) hv hγ hγ' h
/-- For a global integral curve `γ`, if it crosses itself at `a b : ℝ`, then it is periodic with
period `a - b`. -/
lemma IsIntegralCurve.periodic_of_eq [BoundarylessManifold I M]
(hγ : IsIntegralCurve γ v)
(hv : ContMDiff I I.tangent 1 (fun x => (⟨x, v x⟩ : TangentBundle I M)))
(heq : γ a = γ b) : Periodic γ (a - b) := by
intro t
apply congrFun <|
isIntegralCurve_Ioo_eq_of_contMDiff_boundaryless (t₀ := b) hv (hγ.comp_add _) hγ _
rw [comp_apply, add_sub_cancel, heq]
/-- A global integral curve is injective xor periodic with positive period. -/
lemma IsIntegralCurve.periodic_xor_injective [BoundarylessManifold I M]
(hγ : IsIntegralCurve γ v)
(hv : ContMDiff I I.tangent 1 (fun x => (⟨x, v x⟩ : TangentBundle I M))) :
Xor' (∃ T > 0, Periodic γ T) (Injective γ) := by
rw [xor_iff_iff_not]
refine ⟨fun ⟨T, hT, hf⟩ ↦ hf.not_injective (ne_of_gt hT), ?_⟩
intro h
rw [Injective] at h
push_neg at h
obtain ⟨a, b, heq, hne⟩ := h
refine ⟨|a - b|, ?_, ?_⟩
· rw [gt_iff_lt, abs_pos, sub_ne_zero]
exact hne
· by_cases hab : a - b < 0
· rw [abs_of_neg hab, neg_sub]
exact hγ.periodic_of_eq hv heq.symm
· rw [not_lt] at hab
rw [abs_of_nonneg hab]
exact hγ.periodic_of_eq hv heq
end ExistUnique
section Naturality
variable
{E' : Type*} [NormedAddCommGroup E'] [NormedSpace ℝ E']
{H' : Type*} [TopologicalSpace H'] {I' : ModelWithCorners ℝ E' H'}
{M' : Type*} [TopologicalSpace M'] [ChartedSpace H' M'] [SmoothManifoldWithCorners I' M']
{v' : (x : M') → TangentSpace I' x}
/-- Let `v` and `v'` be vector fields on `M` and `M'`, respectively, and let `f : M → M'` be a
differentiable map. If `v` and `v'` are `f`-related, then `f` maps integral curves of `v` to
integral curves of `v'`. -/
lemma IsIntegralCurveAt.of_mdifferentiable_related (h : IsIntegralCurveAt γ v t₀)
{f : M → M'} (hf : MDifferentiable I I' f) (hv : ∀ x : M, v' (f x) = mfderiv I I' f x (v x)) :
IsIntegralCurveAt (f ∘ γ) v' t₀ := by
apply h.mono
intros t ht
apply (HasMFDerivAt.comp t (hf (γ t)).hasMFDerivAt ht).congr_mfderiv
rw [Function.comp_apply, hv, ContinuousLinearMap.comp_smulRight]
/-- Let `v` and `v'` be vector fields on `M` and `M'`, respectively, and let `f : M → M'` be a
differentiable map. If `f` maps integral curves of `v` to integral curves of `v'`, then `v` and
`v'` are `f`-related. -/
lemma mdifferentiable_related_of_isIntegralCurveAt [BoundarylessManifold I M] [CompleteSpace E]
(hv : ContMDiff I I.tangent 1 (fun x ↦ (⟨x, v x⟩ : TangentBundle I M)))
{f : M → M'} (hf : MDifferentiable I I' f)
(h : ∀ (γ : ℝ → M) (t₀ : ℝ), IsIntegralCurveAt γ v t₀ → IsIntegralCurveAt (f ∘ γ) v' t₀)
(x : M) : v' (f x) = mfderiv I I' f x (v x) := by
obtain ⟨γ, h0, hγ⟩ : ∃ γ : ℝ → M, γ 0 = x ∧ IsIntegralCurveAt γ v 0 :=
exists_isIntegralCurveAt_of_contMDiffAt_boundaryless 0 hv.contMDiffAt
have hγ' := (h γ 0 hγ).hasMFDerivAt
have hγ := hγ.hasMFDerivAt
rw [Function.comp_apply, h0] at hγ'
rw [h0] at hγ
have := hasMFDerivAt_unique hγ' <| (hf (γ 0)).hasMFDerivAt.comp 0 hγ
rw [ContinuousLinearMap.comp_smulRight, ContinuousLinearMap.smulRight_one_eq_iff, h0] at this
exact this
end Naturality