Imports
/-
Copyright (c) 2025 Joseph Tooby-Smith. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Joseph Tooby-Smith
-/
module
public import Physlib.SpaceAndTime.Time.TimeUnit
public import Physlib.SpaceAndTime.Space.LengthUnit
public import Physlib.ClassicalMechanics.Mass.MassUnit
public import Physlib.Electromagnetism.Charge.ChargeUnit
public import Physlib.Thermodynamics.Temperature.TemperatureUnits
public import Physlib.Units.LTMCTDimensionBase
public import Physlib.Meta.TODO.Basic
public import Mathlib.Analysis.SpecialFunctions.Pow.NNRealDimensions and unit
A unit in physics arises from choice of something in physics which is non-canonical.
An example is the choice of translationally-invariant metric on the time manifold TimeMan.
A dimension is a property of a quantity related to how it changes with respect to a change in the unit.
The fundamental choices one has in physics are related to:
Time
Length
Mass
Charge
Temperature
(In fact temperature is not really a fundamental choice, however we leave this as a TODO.)
From these fundamental choices one can construct all other units and dimensions.
Implementation details
Units within Physlib are implemented with the following convention:
The fundamental units, and the choices they correspond to, are defined within the appropriate physics directory, in particular:
Physlib/SpaceAndTime/Time/TimeUnit.lean
Physlib/SpaceAndTime/Space/LengthUnit.lean
Physlib/ClassicalMechanics/Mass/MassUnit.lean
Physlib/Electromagnetism/Charge/ChargeUnit.lean
Physlib/Thermodynamics/Temperature/TemperatureUnit.lean
In this Units directory, we define the necessary structures and properties
to work derived units and dimensions.
References
Zulip chats discussing units:
https://leanprover.zulipchat.com/#narrow/channel/479953-Physlib/topic/physical.20units
https://leanprover.zulipchat.com/#narrow/channel/116395-maths/topic/Dimensional.20Analysis.20Revisited/with/530238303
Note
A lot of the results around units is still experimental and should be adapted based on needs.
Other implementations of units
There are other implementations of units in Lean, in particular:
https://github.com/ATOMSLab/LeanDimensionalAnalysis/tree/main
https://github.com/teorth/analysis/blob/main/analysis/Analysis/Misc/SI.lean
https://github.com/ecyrbe/lean-units
Each of these have their own advantages and specific use-cases.
For example both (1) and (3) allow for or work in Floats, allowing computability and the use
of #eval. This is currently not possible with the more theoretical implementation here
in Physlib which is based exclusively on Reals.
@[expose] public sectionUnits
The choice of units.
The length unit.
The time unit.
The mass unit.
The charge unit.
The temperature unit.
@[ext]
structure UnitChoices where length : LengthUnit time : TimeUnit mass : MassUnit charge : ChargeUnit temperature : TemperatureUnitlemma dimScale_apply (u1 u2 : UnitChoices) (d : Dimension LTMCTDimensionBase) :
dimScale u1 u2 d =
(u1.length / u2.length) ^ (d.length : ℝ) *
(u1.time / u2.time) ^ (d.time : ℝ) *
(u1.mass / u2.mass) ^ (d.mass : ℝ) *
(u1.charge / u2.charge) ^ (d.charge : ℝ) *
(u1.temperature / u2.temperature) ^ (d.temperature : ℝ) := rfl@[simp]
lemma dimScale_self (u : UnitChoices) (d : Dimension LTMCTDimensionBase) :
dimScale u u d = 1 := u:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u.dimScale u) d = 1
All goals completed! 🐙@[simp]
lemma dimScale_one (u1 u2 : UnitChoices) :
dimScale u1 u2 1 = 1 := u1:UnitChoicesu2:UnitChoices⊢ (u1.dimScale u2) 1 = 1
All goals completed! 🐙u1:UnitChoicesu2:UnitChoicesu3:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (↑⟨u1.length.val / u2.length.val, ⋯⟩ * ↑⟨u2.length.val / u3.length.val, ⋯⟩) ^ ↑d.length *
(↑⟨u1.time.val / u2.time.val, ⋯⟩ * ↑⟨u2.time.val / u3.time.val, ⋯⟩) ^ ↑d.time *
(↑⟨u1.mass.val / u2.mass.val, ⋯⟩ * ↑⟨u2.mass.val / u3.mass.val, ⋯⟩) ^ ↑d.mass *
(↑⟨u1.charge.val / u2.charge.val, ⋯⟩ * ↑⟨u2.charge.val / u3.charge.val, ⋯⟩) ^ ↑d.charge *
(↑⟨u1.temperature.val / u2.temperature.val, ⋯⟩ * ↑⟨u2.temperature.val / u3.temperature.val, ⋯⟩) ^ ↑d.temperature =
↑⟨u1.length.val / u3.length.val, ⋯⟩ ^ ↑d.length * ↑⟨u1.time.val / u3.time.val, ⋯⟩ ^ ↑d.time *
↑⟨u1.mass.val / u3.mass.val, ⋯⟩ ^ ↑d.mass *
↑⟨u1.charge.val / u3.charge.val, ⋯⟩ ^ ↑d.charge *
↑⟨u1.temperature.val / u3.temperature.val, ⋯⟩ ^ ↑d.temperature
field_simp All goals completed! 🐙
@[simp]
lemma dimScale_mul_symm (u1 u2 : UnitChoices) (d : Dimension LTMCTDimensionBase) :
dimScale u1 u2 d * dimScale u2 u1 d = 1 := by u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.dimScale u2) d * (u2.dimScale u1) d = 1
rw [dimScale_transitive, u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.dimScale u1) d = 1 All goals completed! 🐙 dimScale_self u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ 1 = 1 All goals completed! 🐙] All goals completed! 🐙
@[simp]
lemma dimScale_coe_mul_symm (u1 u2 : UnitChoices) (d : Dimension LTMCTDimensionBase) :
(toReal (dimScale u1 u2 d)) * (toReal (dimScale u2 u1 d)) = 1 := by u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ ↑((u1.dimScale u2) d) * ↑((u2.dimScale u1) d) = 1
trans toReal (dimScale u1 u2 d * dimScale u2 u1 d) u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ ↑((u1.dimScale u2) d) * ↑((u2.dimScale u1) d) = ↑((u1.dimScale u2) d * (u2.dimScale u1) d)u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ ↑((u1.dimScale u2) d * (u2.dimScale u1) d) = 1
· u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ ↑((u1.dimScale u2) d) * ↑((u2.dimScale u1) d) = ↑((u1.dimScale u2) d * (u2.dimScale u1) d) rw [NNReal.coe_mul u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ ↑((u1.dimScale u2) d) * ↑((u2.dimScale u1) d) = ↑((u1.dimScale u2) d) * ↑((u2.dimScale u1) d) All goals completed! 🐙] All goals completed! 🐙
simp All goals completed! 🐙@[simp]
lemma dimScale_ne_zero (u1 u2 : UnitChoices) (d : Dimension LTMCTDimensionBase) :
dimScale u1 u2 d ≠ 0 := by u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.dimScale u2) d ≠ 0
simp [dimScale] All goals completed! 🐙
lemma dimScale_symm (u1 u2 : UnitChoices) (d : Dimension LTMCTDimensionBase) :
dimScale u1 u2 d = (dimScale u2 u1 d)⁻¹ := by u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.dimScale u2) d = ((u2.dimScale u1) d)⁻¹
simp only [dimScale_apply, mul_inv] u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.length / u2.length) ^ ↑d.length * (u1.time / u2.time) ^ ↑d.time * (u1.mass / u2.mass) ^ ↑d.mass *
(u1.charge / u2.charge) ^ ↑d.charge *
(u1.temperature / u2.temperature) ^ ↑d.temperature =
((u2.length / u1.length) ^ ↑d.length)⁻¹ * ((u2.time / u1.time) ^ ↑d.time)⁻¹ * ((u2.mass / u1.mass) ^ ↑d.mass)⁻¹ *
((u2.charge / u1.charge) ^ ↑d.charge)⁻¹ *
((u2.temperature / u1.temperature) ^ ↑d.temperature)⁻¹
congr e_a.e_a.e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.length / u2.length) ^ ↑d.length = ((u2.length / u1.length) ^ ↑d.length)⁻¹e_a.e_a.e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.time / u2.time) ^ ↑d.time = ((u2.time / u1.time) ^ ↑d.time)⁻¹e_a.e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.mass / u2.mass) ^ ↑d.mass = ((u2.mass / u1.mass) ^ ↑d.mass)⁻¹e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.charge / u2.charge) ^ ↑d.charge = ((u2.charge / u1.charge) ^ ↑d.charge)⁻¹e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.temperature / u2.temperature) ^ ↑d.temperature = ((u2.temperature / u1.temperature) ^ ↑d.temperature)⁻¹
· e_a.e_a.e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.length / u2.length) ^ ↑d.length = ((u2.length / u1.length) ^ ↑d.length)⁻¹ rw [LengthUnit.div_symm, e_a.e_a.e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u2.length / u1.length)⁻¹ ^ ↑d.length = ((u2.length / u1.length) ^ ↑d.length)⁻¹ All goals completed! 🐙 inv_rpow e_a.e_a.e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ ((u2.length / u1.length) ^ ↑d.length)⁻¹ = ((u2.length / u1.length) ^ ↑d.length)⁻¹ All goals completed! 🐙] All goals completed! 🐙
· e_a.e_a.e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.time / u2.time) ^ ↑d.time = ((u2.time / u1.time) ^ ↑d.time)⁻¹ rw [TimeUnit.div_symm, e_a.e_a.e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u2.time / u1.time)⁻¹ ^ ↑d.time = ((u2.time / u1.time) ^ ↑d.time)⁻¹ All goals completed! 🐙 inv_rpow e_a.e_a.e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ ((u2.time / u1.time) ^ ↑d.time)⁻¹ = ((u2.time / u1.time) ^ ↑d.time)⁻¹ All goals completed! 🐙] All goals completed! 🐙
· e_a.e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.mass / u2.mass) ^ ↑d.mass = ((u2.mass / u1.mass) ^ ↑d.mass)⁻¹ rw [MassUnit.div_symm, e_a.e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u2.mass / u1.mass)⁻¹ ^ ↑d.mass = ((u2.mass / u1.mass) ^ ↑d.mass)⁻¹ All goals completed! 🐙 inv_rpow e_a.e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ ((u2.mass / u1.mass) ^ ↑d.mass)⁻¹ = ((u2.mass / u1.mass) ^ ↑d.mass)⁻¹ All goals completed! 🐙] All goals completed! 🐙
· e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.charge / u2.charge) ^ ↑d.charge = ((u2.charge / u1.charge) ^ ↑d.charge)⁻¹ rw [ChargeUnit.div_symm, e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u2.charge / u1.charge)⁻¹ ^ ↑d.charge = ((u2.charge / u1.charge) ^ ↑d.charge)⁻¹ All goals completed! 🐙 inv_rpow e_a.e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ ((u2.charge / u1.charge) ^ ↑d.charge)⁻¹ = ((u2.charge / u1.charge) ^ ↑d.charge)⁻¹ All goals completed! 🐙] All goals completed! 🐙
· e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.temperature / u2.temperature) ^ ↑d.temperature = ((u2.temperature / u1.temperature) ^ ↑d.temperature)⁻¹ rw [TemperatureUnit.div_symm, e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u2.temperature / u1.temperature)⁻¹ ^ ↑d.temperature = ((u2.temperature / u1.temperature) ^ ↑d.temperature)⁻¹ All goals completed! 🐙 inv_rpow e_a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ ((u2.temperature / u1.temperature) ^ ↑d.temperature)⁻¹ = ((u2.temperature / u1.temperature) ^ ↑d.temperature)⁻¹ All goals completed! 🐙] All goals completed! 🐙lemma dimScale_of_inv_eq_swap (u1 u2 : UnitChoices) (d : Dimension LTMCTDimensionBase) :
dimScale u1 u2 d⁻¹ = dimScale u2 u1 d := by u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ (u1.dimScale u2) d⁻¹ = (u2.dimScale u1) d
simp only [map_inv] u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ ((u1.dimScale u2) d)⁻¹ = (u2.dimScale u1) d
conv_rhs => rw[dimScale_symm] u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase| ((u1.dimScale u2) d)⁻¹@[simp]
lemma smul_dimScale_injective {M : Type} [MulAction ℝ≥0 M] (u1 u2 : UnitChoices)
(d : Dimension LTMCTDimensionBase) (m1 m2 : M) :
(u1.dimScale u2 d) • m1 = (u1.dimScale u2 d) • m2 ↔ m1 = m2:= by M:Typeinst✝:MulAction ℝ≥0 Mu1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBasem1:Mm2:M⊢ (u1.dimScale u2) d • m1 = (u1.dimScale u2) d • m2 ↔ m1 = m2
refine IsUnit.smul_left_cancel ?_ M:Typeinst✝:MulAction ℝ≥0 Mu1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBasem1:Mm2:M⊢ IsUnit ((u1.dimScale u2) d)
refine isUnit_iff_exists_inv.mpr ?_ M:Typeinst✝:MulAction ℝ≥0 Mu1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBasem1:Mm2:M⊢ ∃ b, (u1.dimScale u2) d * b = 1
use u1.dimScale u2 d⁻¹ h M:Typeinst✝:MulAction ℝ≥0 Mu1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBasem1:Mm2:M⊢ (u1.dimScale u2) d * (u1.dimScale u2) d⁻¹ = 1
simp All goals completed! 🐙@[simp]
lemma dimScale_pos (u1 u2 : UnitChoices) (d : Dimension LTMCTDimensionBase) :
0 < (dimScale u1 u2 d) := by u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ 0 < (u1.dimScale u2) d
apply lt_of_le_of_ne a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ 0 ≤ (u1.dimScale u2) da u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ 0 ≠ (u1.dimScale u2) d
· a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ 0 ≤ (u1.dimScale u2) d simp All goals completed! 🐙
· a u1:UnitChoicesu2:UnitChoicesd:Dimension LTMCTDimensionBase⊢ 0 ≠ (u1.dimScale u2) d exact Ne.symm (dimScale_ne_zero u1 u2 d) All goals completed! 🐙TODO "Make SI : UnitChoices computable, probably by
replacing the axioms defining the units. See here:
https://leanprover.zulipchat.com/#narrow/channel/479953-Physlib/topic/physical.20units/near/534914807"@[simp]
lemma SI_length : SI.length = LengthUnit.meters := rfl@[simp]
lemma SI_time : SI.time = TimeUnit.seconds := rfl@[simp]
lemma SI_mass : SI.mass = MassUnit.kilograms := rfl@[simp]
lemma SI_charge : SI.charge = ChargeUnit.coulombs := rfl@[simp]
lemma SI_temperature : SI.temperature = TemperatureUnit.kelvin := rfl@[simp]
lemma dimScale_SI_SIPrimed (d : Dimension LTMCTDimensionBase) :
dimScale SI SIPrimed d =
(2⁻¹ : ℝ≥0) ^ (d.length : ℝ) *
(3⁻¹ : ℝ≥0) ^ (d.time : ℝ) *
(5⁻¹ : ℝ≥0) ^ (d.mass : ℝ) *
(7⁻¹ : ℝ≥0) ^ (d.charge : ℝ) *
(11⁻¹ : ℝ≥0) ^ (d.temperature : ℝ) := by d:Dimension LTMCTDimensionBase⊢ (SI.dimScale SIPrimed) d = 2⁻¹ ^ ↑d.length * 3⁻¹ ^ ↑d.time * 5⁻¹ ^ ↑d.mass * 7⁻¹ ^ ↑d.charge * 11⁻¹ ^ ↑d.temperature
simp [dimScale, SI, SIPrimed] d:Dimension LTMCTDimensionBase⊢ ⟨2⁻¹, ⋯⟩ ^ ↑d.length * ⟨3⁻¹, ⋯⟩ ^ ↑d.time * ⟨5⁻¹, ⋯⟩ ^ ↑d.mass * ⟨7⁻¹, ⋯⟩ ^ ↑d.charge * ⟨11⁻¹, ⋯⟩ ^ ↑d.temperature =
2⁻¹ ^ ↑d.length * 3⁻¹ ^ ↑d.time * 5⁻¹ ^ ↑d.mass * 7⁻¹ ^ ↑d.charge * 11⁻¹ ^ ↑d.temperature
rfl All goals completed! 🐙@[simp]
lemma dimScale_SIPrimed_SI (d : Dimension LTMCTDimensionBase) :
dimScale SIPrimed SI d =
(2 : ℝ≥0) ^ (d.length : ℝ) *
(3 : ℝ≥0) ^ (d.time : ℝ) *
(5 : ℝ≥0) ^ (d.mass : ℝ) *
(7 : ℝ≥0) ^ (d.charge : ℝ) *
(11 : ℝ≥0) ^ (d.temperature : ℝ) := by d:Dimension LTMCTDimensionBase⊢ (SIPrimed.dimScale SI) d = 2 ^ ↑d.length * 3 ^ ↑d.time * 5 ^ ↑d.mass * 7 ^ ↑d.charge * 11 ^ ↑d.temperature
simp [dimScale, SI, SIPrimed] d:Dimension LTMCTDimensionBase⊢ ⟨2, ⋯⟩ ^ ↑d.length * ⟨3, ⋯⟩ ^ ↑d.time * ⟨5, ⋯⟩ ^ ↑d.mass * ⟨7, ⋯⟩ ^ ↑d.charge * ⟨11, ⋯⟩ ^ ↑d.temperature =
2 ^ ↑d.length * 3 ^ ↑d.time * 5 ^ ↑d.mass * 7 ^ ↑d.charge * 11 ^ ↑d.temperature
rfl All goals completed! 🐙Types carrying dimensions
Dimensions are assigned to types with the following type-classes
HasDim for any type M with an associated dimension
CarriesDimension for a type that also has an instance of MulAction ℝ≥0 M
This typeclass indicates that there is a dimension dim M : Dimension
associated with the type M.
The dimension associated with a type M.
class HasDim (M : Type) where d : Dimension LTMCTDimensionBasealias dim := HasDim.d
A type M carries a dimension d if every element of M is supposed to have
this dimension. For example, the type Time will carry a dimension T𝓭.
class abbrev CarriesDimension (M : Type) := HasDim M, MulAction ℝ≥0 MTerms of the current dimension
Given a type M which carries a dimension d,
we are interested in elements of M which depend on a choice of units, i.e. functions
UnitChoices → M.
We define both a proposition
HasDimension f which says that f scales correctly with units,
and a type
Dimensionful M which is the subtype of functions which HasDimension.
A quantity of type M which depends on a choice of units UnitChoices is said to be
of dimension d if it scales by UnitChoices.dimScale u1 u2 d under a change in units.
def HasDimension {M : Type} [CarriesDimension M] (f : UnitChoices → M) : Prop :=
∀ u1 u2 : UnitChoices, f u2 = UnitChoices.dimScale u1 u2 (dim M) • f u1lemma hasDimension_iff {M : Type} [CarriesDimension M] (f : UnitChoices → M) :
HasDimension f ↔ ∀ u1 u2 : UnitChoices, f u2 =
UnitChoices.dimScale u1 u2 (dim M) • f u1 := by M:Typeinst✝:CarriesDimension Mf:UnitChoices → M⊢ HasDimension f ↔ ∀ (u1 u2 : UnitChoices), f u2 = (u1.dimScale u2) (dim M) • f u1
rfl All goals completed! 🐙
The subtype of functions UnitChoices → M, for which M carries a dimension,
which HasDimension.
def Dimensionful (M : Type) [CarriesDimension M] := Subtype (HasDimension (M := M))instance {M : Type} [CarriesDimension M] : CoeFun (Dimensionful M) (fun _ => UnitChoices → M) where
coe := Subtype.val@[ext]
lemma Dimensionful.ext {M : Type} [CarriesDimension M] (f1 f2 : Dimensionful M)
(h : f1.val = f2.val) : f1 = f2 := by M:Typeinst✝:CarriesDimension Mf1:Dimensionful Mf2:Dimensionful Mh:↑f1 = ↑f2⊢ f1 = f2
cases f1 mk M:Typeinst✝:CarriesDimension Mf2:Dimensionful Mval✝:UnitChoices → Mproperty✝:HasDimension val✝h:↑⟨val✝, property✝⟩ = ↑f2⊢ ⟨val✝, property✝⟩ = f2
cases f2 mk.mk M:Typeinst✝:CarriesDimension Mval✝¹:UnitChoices → Mproperty✝¹:HasDimension val✝val✝:UnitChoices → Mproperty✝:HasDimension val✝h:↑⟨val✝¹, property✝¹⟩ = ↑⟨val✝, property✝⟩⊢ ⟨val✝¹, property✝¹⟩ = ⟨val✝, property✝⟩
simp_all All goals completed! 🐙
instance {M : Type} [CarriesDimension M] : MulAction ℝ≥0 (Dimensionful M) where
smul a f := ⟨fun u => a • f.1 u, fun u1 u2 => by M:Typeinst✝:CarriesDimension Ma:ℝ≥0f:Dimensionful Mu1:UnitChoicesu2:UnitChoices⊢ (fun u => a • ↑f u) u2 = (u1.dimScale u2) (dim M) • (fun u => a • ↑f u) u1
simp only M:Typeinst✝:CarriesDimension Ma:ℝ≥0f:Dimensionful Mu1:UnitChoicesu2:UnitChoices⊢ a • ↑f u2 = (u1.dimScale u2) (dim M) • a • ↑f u1
rw [f.2 u1 u2 M:Typeinst✝:CarriesDimension Ma:ℝ≥0f:Dimensionful Mu1:UnitChoicesu2:UnitChoices⊢ a • (u1.dimScale u2) (dim M) • ↑f u1 = (u1.dimScale u2) (dim M) • a • ↑f u1 M:Typeinst✝:CarriesDimension Ma:ℝ≥0f:Dimensionful Mu1:UnitChoicesu2:UnitChoices⊢ a • (u1.dimScale u2) (dim M) • ↑f u1 = (u1.dimScale u2) (dim M) • a • ↑f u1] M:Typeinst✝:CarriesDimension Ma:ℝ≥0f:Dimensionful Mu1:UnitChoicesu2:UnitChoices⊢ a • (u1.dimScale u2) (dim M) • ↑f u1 = (u1.dimScale u2) (dim M) • a • ↑f u1
rw [smul_comm M:Typeinst✝:CarriesDimension Ma:ℝ≥0f:Dimensionful Mu1:UnitChoicesu2:UnitChoices⊢ (u1.dimScale u2) (dim M) • a • ↑f u1 = (u1.dimScale u2) (dim M) • a • ↑f u1 All goals completed! 🐙] All goals completed! 🐙⟩
one_smul f := by M:Typeinst✝:CarriesDimension Mf:Dimensionful M⊢ 1 • f = f
ext u M:Typeinst✝:CarriesDimension Mf:Dimensionful Mu:UnitChoices⊢ ↑(1 • f) u = ↑f u
change (1 : ℝ≥0) • f.1 u = f.1 u M:Typeinst✝:CarriesDimension Mf:Dimensionful Mu:UnitChoices⊢ 1 • ↑f u = ↑f u
simp All goals completed! 🐙
mul_smul a b f := by M:Typeinst✝:CarriesDimension Ma:ℝ≥0b:ℝ≥0f:Dimensionful M⊢ (a * b) • f = a • b • f
ext u M:Typeinst✝:CarriesDimension Ma:ℝ≥0b:ℝ≥0f:Dimensionful Mu:UnitChoices⊢ ↑((a * b) • f) u = ↑(a • b • f) u
change (a * b) • f.1 u = a • (b • f.1 u) M:Typeinst✝:CarriesDimension Ma:ℝ≥0b:ℝ≥0f:Dimensionful Mu:UnitChoices⊢ (a * b) • ↑f u = a • b • ↑f u
rw [smul_smul M:Typeinst✝:CarriesDimension Ma:ℝ≥0b:ℝ≥0f:Dimensionful Mu:UnitChoices⊢ (a * b) • ↑f u = (a * b) • ↑f u All goals completed! 🐙] All goals completed! 🐙@[simp]
lemma Dimensionful.smul_apply {M : Type} [CarriesDimension M]
(a : ℝ≥0) (f : Dimensionful M) (u : UnitChoices) :
(a • f).1 u = a • f.1 u := rfllemma CarriesDimension.toDimensionful_apply_apply
{M : Type} [CarriesDimension M] (u1 u2 : UnitChoices) (m : M) :
(toDimensionful u1 m).1 u2 = (u1.dimScale u2 (dim M)) • m := by M:Typeinst✝:CarriesDimension Mu1:UnitChoicesu2:UnitChoicesm:M⊢ ↑((toDimensionful u1) m) u2 = (u1.dimScale u2) (dim M) • m rfl All goals completed! 🐙