Zulip Chat Archive

Stream: Natural sciences

Topic: physical units


Tomas Skrivan (Aug 06 2023 at 17:00):

I got interested in physical units again and wanted to see if I can state Navier-Stokes equation with units. Hopefully someone will find this interesting :) so here is what I got:

Let's start with a simple kinematics, let's introduce time, velocity and acceleration:

variable
  (t : second)
  (v : meter*second^(-1:Int))
  (a : meter*second^(-2:Int))

now some simple formulas from kinematics do typecheck

#check (v*t) + ((1/2:)*a*t*t)  -- ℝ⟦meter⟧

To do Navier-Stoke equation we need differentiation. The type of differentiation respecting units would look like this:

def uderiv {X Y : Type} {u v w : PhysicalUnit} (f : Xu  Yv) (x : Xu) (dx : Xw) : Y(v*w)/u := sorry

now we can state Navier-Stokes equation(in one dimension) as

variable
  (u : second  meter  meter*second^(-1:Int))
  (p : second  meter  pascal)
  (density : second  meter  kilogram*meter^(-3:Int))
  (ν : (meter^(2:Int)) * second^(-1:Int))

#check fun t x => (uderiv (u · x) t (1:1))                              -- ∂u/∂t
                + (uderiv (u t ·) x (u t x))                               -- (u⬝∇)u
                + (((1:1) / density t x) * uderiv (p t ·) x (1:1))   -- 1/ρ ∇p
                + ν * uderiv ((uderiv (u t ·)) · (1:1)) x (1:1)      -- ν Δu
                =
                0

How does this work? The key piece is to have a custom elaborator of x * y and x + y which calls norm_num on the types of x and y and then checks if the units are the same. Have a look at the code here. The unfortunate thing is that the elaborators adds lots of cast to the expressions which will probably be quite painful to work with later on but I was unable to figure out how to do it without casts.

Max Bobbin (Aug 07 2023 at 14:34):

is X⟦u⟧ an actual Lean thing or did you define a notation to get this? I was having a discussion in another channel about defining physical units. Can you send how you define PhysicalUnit?

Max Bobbin (Aug 07 2023 at 14:40):

The basic idea that was recommended was def PhysicalUnits (α) := monoid_algebra ℝ (dimension α) and this makes use of the dimensional analysis already defined and just adds a value to a dimension.

Eric Wieser (Aug 07 2023 at 15:16):

Can you send how you define

It's line 10 of the link above

Eric Wieser (Aug 07 2023 at 15:17):

I prefer Tomas Skrivan's approach of discarding nonsense like 1m + 2s in the type system

Tomas Skrivan (Aug 07 2023 at 15:30):

Max Bobbin said:

The basic idea that was recommended was def PhysicalUnits (α) := monoid_algebra ℝ (dimension α) and this makes use of the dimensional analysis already defined and just adds a value to a dimension.

Yes I will generalize it like that at some point. Right now, it is just a proof of concept. I was mainly interested in how to do some complicated reduction in the types to check that two terms have the same units.

Tomas Skrivan (Aug 07 2023 at 15:33):

The notation X⟦u⟧ is defined on the line 131

Eric Wieser (Aug 07 2023 at 15:43):

Can you outline what makes the reduction complicated? Isn't everything just defeq in your example?

Tomas Skrivan (Aug 07 2023 at 15:47):

I explicitly call norm_num and I was having a hard time replying purely on defeq. I will have to think for some time to give you a concrete example where it is obvious that defeq is not enough.

Eric Wieser (Aug 07 2023 at 15:49):

It stops being defeq as soon as your powers are free variables

Tomas Skrivan (Aug 07 2023 at 15:51):

Yes that is the exact problem I got when I tried to define an adjoint of differential with units. I had to prove a * b * c / b / a = c.

Tomas Skrivan (Aug 07 2023 at 15:51):

But even with concrete units it didn't work very well.

Tomas Skrivan (Aug 07 2023 at 15:53):

Ohh I know, synthesizing HAdd A[u] A[v] ?? is kind of problematic if u and v are defeq.

Eric Wieser (Aug 07 2023 at 15:54):

HAdd strikes again

Tomas Skrivan (Aug 07 2023 at 15:56):

But that can be solved with a custom elaborator, however there is still the issue with writing functions polymorphic in units. There units appear as free variables and you can't rely on defeq.

Tomas Skrivan (Aug 07 2023 at 16:28):

Ohh the main problem is that operations over rationals are not defeq, 3+2 is not defeq 5 or 3*2/3 is not defeq to 2 over rationals.

You can probably rely on defeq when checking dimensions where you are dealing only with integer powers. If you want do to units, you have to deal with the scaling which has to be at least rational number.

Eric Wieser (Aug 07 2023 at 16:32):

This is because docs#Rat.ofScientific is an irreducible_def because apparently you don't want to unfold it

Eric Wieser (Aug 07 2023 at 16:33):

In fact pretty much all of the rationals are built this way

Tomas Skrivan (Aug 07 2023 at 16:34):

1+1 =?= 2 does not contain any ofScientific and still fails

open Lean Meta Qq in
#eval show MetaM Unit from do
  let a := q((1:) + (1:))
  let b := q((2:))
  IO.println s!"Is {← ppExpr a} defeq to {b}: {← isDefEq a b}"

Eric Wieser (Aug 07 2023 at 16:35):

Right, https://github.com/leanprover/std4/commit/04b3c9831e0c141713a70e68af7e40973ec9a1ff is what's really to blame

Tomas Skrivan (Aug 07 2023 at 16:38):

Hmm, anyway I can't rely on defeq because I need to deal with units as free variables.

Tomas Skrivan (Aug 07 2023 at 16:40):

Btw. I got interested in physical units again because of the latest talk at Topos Institute.

Tomas Skrivan (Aug 07 2023 at 16:57):

Max Bobbin said:

The basic idea that was recommended was def PhysicalUnits (α) := monoid_algebra ℝ (dimension α) and this makes use of the dimensional analysis already defined and just adds a value to a dimension.

I do not like the idea of using monoid_algebra. As Eric mentioned, I don't want the type system to allow nonsense like 1m + 2s. I even want to restrict stuff like 1m + 1cm and probably require an explicit cast to meters or centimeters.

Adomas Baliuka (Sep 26 2023 at 03:02):

I'd like to add that many people use units like √Hz. That's also not in monoid_algebra and I think should be allowed, if only to be inclusive.

Eric Wieser (Sep 26 2023 at 07:16):

That works just fine with MonoidAlgebra ℚ Real


Last updated: Dec 20 2023 at 11:08 UTC