Skip to content

feat(ClassicalMechanics): add rotational kinetic energy and prove T = ½ω·Iω#1377

Merged
jstoobysmith merged 3 commits into
leanprover-community:masterfrom
giuseppesorge:rigidbody-rotational-kinetic-energy
Jul 8, 2026
Merged

feat(ClassicalMechanics): add rotational kinetic energy and prove T = ½ω·Iω#1377
jstoobysmith merged 3 commits into
leanprover-community:masterfrom
giuseppesorge:rigidbody-rotational-kinetic-energy

Conversation

@giuseppesorge

Copy link
Copy Markdown
Contributor

This PR adds the rotational kinetic energy of a rigid body and proves T = ½ ω · I ω = ½ ∫ |ω × r|² dm. It is the rotational half of König's theorem (Landau–Lifshitz §32) and the natural sequel to the merged L = I ω (#1366).

A rigid body spinning with angular velocity ω about its reference point carries the point at r with velocity ω × r, so its kinetic energy is T = ½ ∫ |ω × r|² dm. Since |ω × r|² = ω · (r × (ω × r)) and the angular momentum is L = ∫ r × (ω × r) dm = I ω, this is the quadratic form T = ½ ω · L = ½ ω · (I ω).

Physlib/ClassicalMechanics/RigidBody/KineticEnergy.lean (new)

  • RigidBody.rotationalKineticEnergy ω½ (ω ⬝ᵥ inertiaTensor *ᵥ ω), the rotational kinetic energy about the reference point;
  • rotationalKineticEnergy_eq_angularMomentumT = ½ ω · L (contraction of ω with the angular momentum);
  • rotationalKineticEnergy_eq_integralT = ½ ∫ |ω × r|² dm, the physical form justifying the quadratic form as the rotational kinetic energy.

Physlib/Mathematics/CrossProduct.lean

  • Matrix.dotProduct_cross_cross_self — the scalar triple-product identity w · (v × (w × v)) = (w × v) · (w × v) (over , |w × v|²) for v w : Fin 3 → R over any CommRing R, the algebraic core relating the ω·L contraction to the local speed |ω × r|². Sits alongside the existing cross_cross_self_apply in the general cross-product file.

Notes:

  • |ω × r|² is written as the self-dot-product (ω ⨯₃ x) ⬝ᵥ (ω ⨯₃ x): on Fin 3 → ℝ the mathlib norm ‖·‖ is the sup norm, so ‖ω ⨯₃ x‖² would be the wrong quantity.
  • The inertia tensor here is about the reference-frame origin, so rotationalKineticEnergy is the kinetic energy of rotation about that fixed reference point — no centre of mass = origin assumption is made. König's full decomposition T = ½M|V|² + ½ω·Iω (which specialises the reference point to the centre of mass) is the next step.
  • All four declarations reduce to [propext, Classical.choice, Quot.sound].

Toward #893.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Thank you for this PR, which will now be reviewed. If submitting to ./Physlib or ./QuantumInfo, please see our review guidelines if you are not familiar with the process. You should expect a back and forth with a reviewer before your PR is merged. See also that link for how to add appropriate labels to your PR. The PR will also go through a number of automated checks. You can learn more about these here, including how to run them locally.

If you are submitting to ./PhyslibAlpha there will be a lighter review process, though your PR must still pass the automated checks.

If you want to bring attention to this PR, please write a message on this thread of the Lean Zulip.

Important: If a reviewer adds an awaiting-author label to your PR, once you have addressed the review comments, please remove that label by adding a comment with -awaiting-author. This helps us keep track of reviews.

@gloges gloges left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few minor comments/suggestions.

For my own understanding, why is Fin 3 → ℝ favored over EuclideanSpace ℝ (Fin 3)? The latter would address the point you raise about the sup norm.

Comment on lines +50 to +52
simp only [dotProduct, angularMomentum]
rw [Finset.sum_congr rfl (fun i (_ : i ∈ Finset.univ) =>
(smul_eq_mul (ω i) _).symm.trans (map_smul R.ρ (ω i) _).symm), ← map_sum]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
simp only [dotProduct, angularMomentum]
rw [Finset.sum_congr rfl (fun i (_ : i ∈ Finset.univ) =>
(smul_eq_mul (ω i) _).symm.trans (map_smul R.ρ (ω i) _).symm), ← map_sum]
simp_rw [dotProduct, angularMomentum, ← smul_eq_mul, ← map_smul, ← map_sum]

Comment on lines +13 to +14
A rigid body rotating with angular velocity `ω` about its reference point carries the point at
position `r` with velocity `ω × r`, so its kinetic energy is `T = ½ ∫ |ω × r|² dm`. Since

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A rigid body rotating with angular velocity ` about its reference point carries the point at
position `r` with velocity × r`, so its kinetic energy is `T = ½ ∫ |ω × r|² dm`. Since
For a rigid body rotating with angular velocity ` about its reference point the point at
position `r` has velocity × r`, so its kinetic energy is `T = ½ ∫ |ω × r|² dm`. Since

ContDiff.contMDiff <| by
simp only [dotProduct, Fin.sum_univ_three, cross_apply, Matrix.cons_val_zero,
Matrix.cons_val_one, Matrix.head_cons, Matrix.cons_val_two, Matrix.tail_cons]
fun_prop⟩ := by

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend extracting out this ContDiff statement about the cross/dot product into a separate lemma.

giuseppesorge and others added 2 commits July 7, 2026 17:00
… ½ω·Iω

The rotational kinetic energy of a rigid body spinning with angular velocity ω
about its reference point is T = ½ ∫ |ω × r|² dm. Since |ω × r|² = ω·(r×(ω×r))
and the angular momentum is L = ∫ r×(ω×r) dm = I ω, this is the quadratic form
T = ½ ω·L = ½ ω·(I ω). This is the rotational half of König's theorem (§32).

- RigidBody.rotationalKineticEnergy ω := ½ (ω ⬝ᵥ inertiaTensor *ᵥ ω)
- rotationalKineticEnergy_eq_angularMomentum: T = ½ ω·L
- rotationalKineticEnergy_eq_integral: T = ½ ∫ |ω × r|² dm (physical form)
- Matrix.dotProduct_cross_cross_self (CrossProductMatrix.lean): the scalar
  triple-product identity w·(v×(w×v)) = |w×v|²

Toward leanprover-community#893.

Co-authored-by: Claude Opus 4.8 <no-reply+claude-opus-4-8@anthropic.com>
…ess lemma

Per @gloges review of the rotational kinetic energy:
- reword the module docstring
- extract the integrand smoothness into `contDiff_rotationalSpeedSq`
- golf the ω pull-through to a single `simp_rw` in
  rotationalKineticEnergy_eq_integral

Co-authored-by: Claude Opus 4.8 <no-reply+claude-opus-4-8@anthropic.com>
@giuseppesorge giuseppesorge force-pushed the rigidbody-rotational-kinetic-energy branch from ed5a7fa to 3adcc35 Compare July 7, 2026 15:56
@giuseppesorge

Copy link
Copy Markdown
Contributor Author

Thanks! Applied all three — reworded the docstring, extracted the integrand smoothness into contDiff_rotationalSpeedSq, and golfed the ω pull-through to your simp_rw one-liner. On Fin 3 → ℝ vs EuclideanSpace ℝ (Fin 3): the whole rigid-body cross-product API is on Fin 3 → ℝ — mathlib's ⨯₃, RigidBody.inertiaTensor : Matrix (Fin 3) (Fin 3) ℝ acting via *ᵥ, and angularMomentum ω : Fin 3 → ℝ are all there. Switching to EuclideanSpace ℝ (Fin 3) (= PiLp 2) would add WithLp/coercion friction at every ⨯₃ / *ᵥ / ⬝ᵥ site. The sup-norm caveat only affects how |·|² is written, and the explicit self-⬝ᵥ sidesteps it without changing the API — so Fin 3 → ℝ keeps consistency with the existing inertia-tensor / angular-momentum layer.


/-- The local rotational speed squared `|ω × r|² = (ω × r) · (ω × r)` is a smooth function of the
position `r`. -/
lemma contDiff_rotationalSpeedSq (ω : Fin 3 → ℝ) :

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would now move to the CrossProduct file

@jstoobysmith

Copy link
Copy Markdown
Member

awaiting-author

@github-actions github-actions Bot added the awaiting-author A reviewer has asked the author a question or requested changes label Jul 8, 2026
…ssProduct

Per review: generalize contDiff_rotationalSpeedSq from Space 3 to Fin 3 → ℝ
(as Matrix.contDiff_cross_dotProduct_cross) and move it to the CrossProduct
file; the kinetic-energy integrand's smoothness is now obtained by composing
with the coordinate coercion of Space 3.

Co-authored-by: Claude Opus 4.8 <no-reply+claude-opus-4-8@anthropic.com>
@giuseppesorge

Copy link
Copy Markdown
Contributor Author

Done — generalized it to Fin 3 → ℝ as Matrix.contDiff_cross_dotProduct_cross and moved it to the CrossProduct file (adding the ContDiff import there); the kinetic-energy integrand now composes it with the coordinate coercion of Space 3.

@giuseppesorge

Copy link
Copy Markdown
Contributor Author

-awaiting-author

@github-actions github-actions Bot removed the awaiting-author A reviewer has asked the author a question or requested changes label Jul 8, 2026
@jstoobysmith jstoobysmith added the ready-to-merge This PR is approved and will be merged shortly label Jul 8, 2026

@jstoobysmith jstoobysmith left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good - approved.

@jstoobysmith jstoobysmith merged commit f111ede into leanprover-community:master Jul 8, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge This PR is approved and will be merged shortly

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants