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.Units.WithDim.Speed public import Physlib.Units.FDeriv

Examples of units in Physlib

In this module we give some examples of how to use the units system in Physlib. This module should not be imported into any other module, and the results here should not be used in the proofs of any other results other then those in this file.

@[expose] public section

Defining a length dependent on units

Changing that length to miles. 400 meters is very almost a quarter of a mile.

example : meters400 {SI with length := LengthUnit.miles} = 1/4 - 73/50292 := meters400 (let __src := SI; { length := LengthUnit.miles, time := __src.time, mass := __src.mass, charge := __src.charge, temperature := __src.temperature }) = { val := 1 / 4 - 73 / 50292 } 1609.344⁻¹, { val := 400 } = { val := 4⁻¹ - 73 / 50292 } (1609.344⁻¹, { val := 400 }).val = { val := 4⁻¹ - 73 / 50292 }.val 1609.344⁻¹ * 400 = { val := 4⁻¹ - 73 / 50292 }.val All goals completed! 🐙

Proving propositions are dimensionally correct

Cases with only WithDim

An example of dimensions corresponding to E = m c^2 using WithDim.

def EnergyMassWithDim' (m : WithDim M𝓭 ) (E : WithDim (M𝓭 * L𝓭 * L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) ) (c : WithDim (L𝓭 * T𝓭⁻¹) ) : Prop := E = cast (m * c * c)
lemma energyMassWithDim'_isDimensionallyCorrect : IsDimensionallyCorrect EnergyMassWithDim' := IsDimensionallyCorrect EnergyMassWithDim' All goals completed! 🐙

An example of dimensions corresponding to F = m a using WithDim.

def NewtonsSecondWithDim' (m : WithDim M𝓭 ) (F : WithDim (M𝓭 * L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) ) (a : WithDim (L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) ) : Prop := F = cast (m * a)
lemma newtonsSecondWithDim'_isDimensionallyCorrect : IsDimensionallyCorrect NewtonsSecondWithDim' := IsDimensionallyCorrect NewtonsSecondWithDim' All goals completed! 🐙

An example of dimensions corresponding to s = d/t using WithDim.

def SpeedEq (s : WithDim (L𝓭 * T𝓭⁻¹) ) (d : WithDim L𝓭 ) (t : WithDim T𝓭 ) : Prop := s = cast (d / t)
lemma speedEq_isDimensionallyCorrect : IsDimensionallyCorrect SpeedEq := IsDimensionallyCorrect SpeedEq All goals completed! 🐙

An example with complicated dimensions.

def OddDimensions (m1 m2 : WithDim (M𝓭) ) (θ : WithDim Θ𝓭 ) (I1 I2 : WithDim (C𝓭/T𝓭) ) (d : WithDim L𝓭 ) (t : WithDim T𝓭 ) (X : WithDim (L𝓭 * T𝓭⁻¹ ^ 3 * Θ𝓭⁻¹ * C𝓭 ^2) ) : Prop := X = cast (m1 * (d / t) / (m2 * θ) * I2 * I1)
lemma oddDimensions_isDimensionallyCorrect : IsDimensionallyCorrect OddDimensions := IsDimensionallyCorrect OddDimensions All goals completed! 🐙

An example of dimensions corresponding to E = m c^2 using WithDim with .val.

def EnergyMassWithDim (m : WithDim M𝓭 ) (E : WithDim (M𝓭 * L𝓭 * L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) ) (c : WithDim (L𝓭 * T𝓭⁻¹) ) : Prop := E.1 = m.1 * c.1 ^ 2
All goals completed! 🐙

An example of dimensions corresponding to F = m a using WithDim with .val.

def NewtonsSecondWithDim (m : WithDim M𝓭 ) (F : WithDim (M𝓭 * L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) ) (a : WithDim (L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) ) : Prop := F.1 = m.1 * a.1
All goals completed! 🐙

An example of dimensions corresponding to E = m c using WithDim with .val, which is not dimensionally correct.

def EnergyMassWithDimNot (m : WithDim M𝓭 ) (E : WithDim (M𝓭 * L𝓭 * L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) ) (c : WithDim (L𝓭 * T𝓭⁻¹) ) : Prop := E.1 = m.1 * c.1
set_option backward.isDefEq.respectTransparency false in lemma energyMassWithDimNot_not_isDimensionallyCorrect : ¬ IsDimensionallyCorrect EnergyMassWithDimNot := ¬IsDimensionallyCorrect EnergyMassWithDimNot x x_1 x_2 x_3 x_4, ¬scaleUnit x x_1 (EnergyMassWithDimNot (scaleUnit x_1 x x_2) (scaleUnit x_1 x x_3)) x_4 = EnergyMassWithDimNot x_2 x_3 x_4 /- We show that `EnergyMassWithDimNot` is not dimensionally correct by changing from `SI` to `SIPrimed` with values of `E`, `m` and `c` all equal to `1`. -/ ¬scaleUnit SI SIPrimed (EnergyMassWithDimNot (scaleUnit SIPrimed SI { val := 1 }) (scaleUnit SIPrimed SI { val := 1 })) { val := 1 } = EnergyMassWithDimNot { val := 1 } { val := 1 } { val := 1 } ¬scaleUnit SI SIPrimed (fun c => (scaleUnit SIPrimed SI { val := 1 }).val = (scaleUnit SIPrimed SI { val := 1 }).val * c.val) { val := 1 } = ({ val := 1 }.val = { val := 1 }.val * { val := 1 }.val) All goals completed! 🐙

Cases with Dimensionful

The equation E = m c^2, in this equation we E and m are implicitly in the units u, while the speed of light is explicitly written in those units.

def EnergyMass (m : WithDim M𝓭 ) (E : WithDim (M𝓭 * L𝓭 * L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) ) (u : UnitChoices) : Prop := E.1 = m.1 * (speedOfLight u).1 ^ 2

The equation E = m c^2, in this version everything is written explicitly in terms of a choice of units.

def EnergyMass' (m : Dimensionful (WithDim M𝓭 )) (E : Dimensionful (WithDim (M𝓭 * L𝓭 * L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) )) (u : UnitChoices) : Prop := (E.1 u).1 = (m.1 u).1 * (speedOfLight u).1 ^ 2

The lemma that the proposition EnergyMass is dimensionally correct

lemma energyMass_isDimensionallyCorrect : IsDimensionallyCorrect EnergyMass := IsDimensionallyCorrect EnergyMass /- Scale such that the unit u1 is taken to u2. -/ u1:UnitChoicesu2:UnitChoicesscaleUnit u1 u2 EnergyMass = EnergyMass /- Let `m` be the mass, `E` be the energy and `u` be the actual units we start with. -/ u1:UnitChoicesu2:UnitChoicesm:WithDim M𝓭 E:WithDim (M𝓭 * L𝓭 * L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) u:UnitChoicesscaleUnit u1 u2 EnergyMass m E u = EnergyMass m E u u1:UnitChoicesu2:UnitChoicesm:WithDim M𝓭 E:WithDim (M𝓭 * L𝓭 * L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) u:UnitChoicesscaleUnit u1 u2 (fun m E u => E.val = m.val * (speedOfLight u).val ^ 2) m E u = (E.val = m.val * (speedOfLight u).val ^ 2) u1:UnitChoicesu2:UnitChoicesm:WithDim M𝓭 E:WithDim (M𝓭 * L𝓭 * L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) u:UnitChoices((u2.dimScale u1) M𝓭) * ((u2.dimScale u1) L𝓭) * ((u2.dimScale u1) L𝓭) * ((u2.dimScale u1) T𝓭⁻¹) * ((u2.dimScale u1) T𝓭⁻¹) * E.val = ((u2.dimScale u1) M𝓭) * m.val * (((u2.dimScale u1) L𝓭) ^ 2 * ((u2.dimScale u1) T𝓭⁻¹) ^ 2 * (speedOfLight u).val ^ 2) E.val = m.val * (speedOfLight u).val ^ 2 u1:UnitChoicesu2:UnitChoicesm:WithDim M𝓭 E:WithDim (M𝓭 * L𝓭 * L𝓭 * T𝓭⁻¹ * T𝓭⁻¹) u:UnitChoices((u2.dimScale u1) M𝓭) * ((u2.dimScale u1) L𝓭) ^ 2 * ((u2.dimScale u1) T𝓭⁻¹) ^ 2 * E.val = ((u2.dimScale u1) M𝓭) * ((u2.dimScale u1) L𝓭) ^ 2 * ((u2.dimScale u1) T𝓭⁻¹) ^ 2 * m.val * (speedOfLight u).val ^ 2 E.val = m.val * (speedOfLight u).val ^ 2 All goals completed! 🐙

Examples of using isDimensionallyCorrect

We now explore the consequences of energyMass_isDimensionallyCorrect and how we can use it.

lemma example1_energyMass : EnergyMass 2 2 * 299792458 ^ 2 SI := EnergyMass { val := 2 } { val := 2 * 299792458 ^ 2 } SI All goals completed! 🐙u:UnitChoicesscaleUnit SI u EnergyMass (scaleUnit SI u { val := 2 }) (scaleUnit SI u { val := 2 * 299792458 ^ 2 }) (scaleUnit SI u SI) u:UnitChoicesEnergyMass { val := 2 } { val := 2 * 299792458 ^ 2 } SI All goals completed! 🐙

## Examples with other functions

An example of a dimensionally correct result using functions.

def CosDim (t : WithDim T𝓭 ) (ω : WithDim T𝓭⁻¹ ) (a : ) : Prop := Real.cos (ω.1 * t.1) = a
lemma cosDim_isDimensionallyCorrect : IsDimensionallyCorrect CosDim := IsDimensionallyCorrect CosDim All goals completed! 🐙

## An example involving derivatives

example {M1 M2 : Type} [NormedAddCommGroup M1] [NormedSpace M1] [ContinuousConstSMul M1] [HasDim M1] [NormedAddCommGroup M2] [NormedSpace M2] [SMulCommClass M2] [ContinuousConstSMul M2] [HasDim M2] (f : M1 M2) (hf : IsDimensionallyCorrect f) (f_diff : Differentiable f) : IsDimensionallyCorrect (fderiv f) := fderiv_isDimensionallyCorrect f hf f_diffexample {M1 M2 : Type} [NormedAddCommGroup M1] [NormedSpace M1] [ContinuousConstSMul M1] [HasDim M1] [NormedAddCommGroup M2] [NormedSpace M2] [SMulCommClass M2] [ContinuousConstSMul M2] [HasDim M2] (dm : M1) (f : M1 M2) (hf : IsDimensionallyCorrect f) (f_diff : Differentiable f) : IsDimensionallyCorrect (fun x (v : WithDim (dim M2 * (dim M1)⁻¹) M2) => fderiv f x dm = v.1) := fderiv_dimension_const_direction dm f hf f_diff