Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: prelude with dimensionful angles #167

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
3 changes: 2 additions & 1 deletion examples/consistency_others.nbt
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ assert_eq(1 calorie, 4.184 J)
assert_eq(1 BTU, 1055.05585262 J)
assert_eq(1 lbf, 4.448222 N)
assert_eq(1 ozf, (4.448222 / 16.0) N, 1e-5 N)
assert_eq(60 RPM, 1 Hz)
assert_eq(60 RPM, 1 rev / s)
assert_eq(60 RPM, 360° / s)
assert_eq(1 fortnight, 2 week)
assert_eq(1 mmHg, 133.322387415 Pa, 1e-5 Pa)
assert_eq(1 PSI, 6.894757 kPa)
Expand Down
34 changes: 34 additions & 0 deletions examples/dimensionful_angles.nbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# This file uses the dimensionful_angles prelude

print("h = {planck_constant}")
print("ℏ = {ℏ}")
print("ȟ = {ȟ}")

# harmonic oscillation
let ω = 2π rad / s
let t = 0.4 s
let amplitude = Sin(ω·t)
print("Amplitude: {amplitude}")

# Tangential velocity
let r = 20 cm
let v: Velocity = r ω / θC # This is one of the "text book formulas" that needs adaptation
print("Linear velocity: {v}")

# Rotational motion
assert_eq(60 rpm, 360° / s)

# Arc length
fn arc_length(radius: Length, θ: Angle) -> Length = radius × θ / θC
print(arc_length(1 m, 45°))

# Rotational energy
let mass = 1 kg
let radius = 1 m
let I: MomentOfInertia = mass × radius^2 / θC^2
let ω_rot: AngularFrequency = 180° / 5 s
let E_rot: Energy = 1/2 * I * ω_rot^2
print("E_rot = {E_rot -> J}")

# Cyclotron frequency
let ω_cyc: AngularFrequency = electron_charge/electron_mass × 50 µT × θC
6 changes: 3 additions & 3 deletions examples/projectile_motion.nbt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# https://en.wikipedia.org/wiki/Projectile_motion

fn max_height(v: Velocity, θ: Angle) -> Length = v² · sin(θ)^2 / (2 · g0)
fn max_distance(v: Velocity, θ: Angle) -> Length = v² · sin(2 θ) / g0
fn time_of_flight(v: Velocity, θ: Angle) -> Time = 2 v · sin(θ) / g0
fn max_height(v: Velocity, θ: Angle) -> Length = v² · Sin(θ)^2 / (2 · g0)
fn max_distance(v: Velocity, θ: Angle) -> Length = v² · Sin(2 θ) / g0
fn time_of_flight(v: Velocity, θ: Angle) -> Time = 2 v · Sin(θ) / g0

assert_eq(max_height(10 m/s, 45 deg), 2.55 m, 1 cm)
assert_eq(max_distance(10 m/s, 45 deg), 10.20 m, 1 cm)
Expand Down
4 changes: 2 additions & 2 deletions examples/readme-demo.nbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ use units::currencies

8 km / (1 h + 25 min)
140 € -> GBP
atan2(30 cm, 1 m) -> deg
let ω = 2π c / 660 nm
ATan2(30 cm, 1 m) -> deg
let ω = 2π θC c / 660 nm
print("Energy of red photon: {ℏ ω -> eV}")
2 changes: 1 addition & 1 deletion examples/unicode.nbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ let ν = c / λ

assert_eq(ν, 499.7 GHz, 0.1 GHz)

let ω = 2 π ν
let ω = 2 π θC ν
let E = ℏ ω

assert_eq(E, 2 meV, 0.1 meV)
7 changes: 1 addition & 6 deletions numbat-wasm/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ set -euo pipefail

current_branch=$(git rev-parse --abbrev-ref HEAD)

if [[ "$current_branch" != "master" ]]; then
echo "You are currently on the '$current_branch' branch, not 'master'."
exit 1
fi

bash build.sh

rsync --archive --stats --progress --human-readable -r www/ shark.fish:numbat.dev/
rsync --archive --stats --progress --human-readable -r www/ shark.fish:numbat.dev/angles/
8 changes: 5 additions & 3 deletions numbat/modules/core/dimensions.nbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
### Physical dimensions

dimension Angle = 1 # SI: plane angle
dimension Angle # SI: plane angle
dimension SolidAngle = Angle^2

dimension Length
Expand All @@ -14,6 +14,8 @@ dimension Velocity = Length / Time
dimension Acceleration = Length / Time^2
dimension Jerk = Length / Time^3
dimension FlowRate = Volume / Time
dimension AngularFrequency = Angle / Time
dimension AngularAcceleration = Angle / Time^2

dimension Mass
dimension Momentum = Mass × Velocity
Expand All @@ -24,7 +26,7 @@ dimension Pressure = Force / Area = Energy / Volume # also: stress
dimension Action = Energy × Time
dimension MassDensity = Mass / Length^3
dimension MomentOfInertia = Mass × Length^2 / Angle^2
dimension AngularMomentum = MomentOfInertia × Angle / Time = Mass × Length^2 / Time / Angle
dimension AngularMomentum = MomentOfInertia × AngularFrequency = Mass × Length^2 / Time / Angle
dimension Torque = Length × Force / Angle # also: moment of force
dimension EnergyDensity = Energy / Volume
dimension MassFlow = Mass / Time
Expand All @@ -45,7 +47,7 @@ dimension ElectricChargeDensity = ElectricCharge / Volume
dimension CurrentDensity = Current / Area
dimension ElectricDipoleMoment = ElectricCharge × Length
dimension ElectricQuadrupoleMoment = ElectricCharge × Length^2
dimension MagneticDipoleMoment = Current × Area = Torque / MagneticFluxDensity
dimension MagneticDipoleMoment = Current × Area = Torque / MagneticFluxDensity * Angle
dimension ElectricFieldStrength = Voltage / Length
dimension ElectricDisplacementFieldStrength = ElectricCharge / Area
dimension ElectricPermittivity = Time^4 × Current^2 / Mass / Length^3 × Angle = ElectricDisplacementFieldStrength / ElectricFieldStrength × Angle
Expand Down
38 changes: 20 additions & 18 deletions numbat/modules/physics/constants.nbt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ let planck_constant: Action = 6.626_070_15e-34 J / Hz
@name("Reduced Planck constant")
@url("https://en.wikipedia.org/wiki/Planck_constant#Reduced_Planck_constant_%E2%84%8F")
@aliases(h_bar)
let ℏ: AngularMomentum = planck_constant / 2π
let ℏ: AngularMomentum = planck_constant / 2π θC
let h_bar = ℏ
let ȟ: Action = planck_constant / 2π

@name("Electron mass")
@url("https://en.wikipedia.org/wiki/Electron_mass")
Expand All @@ -38,22 +40,22 @@ let elementary_charge: ElectricCharge = 1.602_176_634e-19 C
@name("Vacuum permeability / magnetic constant")
@url("https://en.wikipedia.org/wiki/Vacuum_permeability")
@aliases(µ0,μ0,mu0)
let magnetic_constant: MagneticPermeability = 1.256_637_062_12e-6 N / A²
let magnetic_constant: MagneticPermeability = 1.256_637_062_12e-6 N / A² / rad

@name("Vacuum electric permittivity / electric constant")
@url("https://en.wikipedia.org/wiki/Vacuum_permittivity")
@aliases(ε0,eps0)
let electric_constant: ElectricPermittivity = 1 / (µ0 c²) -> F/m
let electric_constant: ElectricPermittivity = 1 / (µ0 c²) -> F/m × rad

@name("Bohr magneton")
@aliases(µ_B,μ_B)
@url("https://en.wikipedia.org/wiki/Bohr_magneton")
let bohr_magneton: Energy / MagneticFluxDensity = electron_charge ℏ / 2 electron_mass -> J/T
#@name("Bohr magneton")
#@aliases(µ_B,μ_B)
#@url("https://en.wikipedia.org/wiki/Bohr_magneton")
#let bohr_magneton: Energy / MagneticFluxDensity = electron_charge ℏ / 2 electron_mass -> J/T

@name("Fine structure constant")
@url("https://en.wikipedia.org/wiki/Fine-structure_constant")
@aliases(α, alpha)
let fine_structure_constant: Scalar = electron_charge^2 / (2 eps0 c)
#@name("Fine structure constant")
#@url("https://en.wikipedia.org/wiki/Fine-structure_constant")
#@aliases(α, alpha)
#let fine_structure_constant: Scalar = electron_charge^2 / (2 eps0 ȟ c)

@name("Proton mass")
@url("https://en.wikipedia.org/wiki/Proton")
Expand Down Expand Up @@ -85,15 +87,15 @@ let gas_constant: Energy / (AmountOfSubstance × Temperature) = k_B × N_A
@name("Bohr radius")
@url("https://en.wikipedia.org/wiki/Bohr_radius")
@aliases(a0)
let bohr_radius: Length = 4 pi ε0 ℏ^2 / (electron_charge^2 electron_mass)
let bohr_radius: Length / Angle = 4 pi ε0 ℏ^2 / (electron_charge^2 electron_mass) -> m/rad

@name("Rydberg constant")
@url("https://en.wikipedia.org/wiki/Rydberg_constant")
let rydberg_constant: Wavenumber = (electron_mass electron_charge^4) / (8 ε0^2 ℎ^3 c)
#@name("Rydberg constant")
#@url("https://en.wikipedia.org/wiki/Rydberg_constant")
#let rydberg_constant: Wavenumber = (electron_mass electron_charge^4) / (8 ε0^2 ℎ^3 c)

@name("Rydberg unit of energy")
@url("https://en.wikipedia.org/wiki/Rydberg_constant")
unit Ry: Energy = ℎ c × rydberg_constant
#@name("Rydberg unit of energy")
#@url("https://en.wikipedia.org/wiki/Rydberg_constant")
#unit Ry: Energy = ℎ c × rydberg_constant

@name("Atomic Mass constant")
@url("https://en.wikipedia.org/wiki/Atomic_mass_constant")
Expand Down
31 changes: 31 additions & 0 deletions numbat/modules/prelude.nbt
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
# The following prelude is based on a proposal to treat angles
# as dimensionful quantities [1].
#
#
# Literature
# ----------
#
# Pro:
# - [1] Angles in the SI: a detailed proposal for solving the problem, https://arxiv.org/abs/2108.05704
# - [2] Angles are inherently neither length ratios nor dimensionless, https://arxiv.org/abs/1909.08389
# - [3] Brownstein K R, Angles—let’s treat them squarely, Am. J. Phys. 65 605–14 (1997).
# - [4] Dimensionless units in the SI, https://arxiv.org/abs/1409.2794
#
# Contra:
# - [4] Dimensional angles and universal constants, https://doi.org/10.1119/1.18964
# - [5] M. Grötschel, H. Hanche-Olsen, H. Holden, Comment on ‘Angles are inherently neither length ratios nor dimensionless’.
# (and companion paper https://arxiv.org/abs/2011.05779v4)
# - [6] Comment on 'Angles in the SI: a detailed proposal for solving the problem', B P Leonard, https://iopscience.iop.org/article/10.1088/1681-7575/ac5433/meta
# (and reply to comment: https://iopscience.iop.org/article/10.1088/1681-7575/ac5434)
#
# Review:
# - [7] Implications of adopting plane angle as a base quantity in the SI, https://arxiv.org/pdf/1604.02373.pdf

use core::scalar
use core::quantities
use core::dimensions
Expand Down Expand Up @@ -36,3 +59,11 @@ use chemistry::elements

use datetime::functions
use datetime::human

fn Sin(θ: Angle) -> Scalar = sin(θ / θC)
fn Cos(θ: Angle) -> Scalar = cos(θ / θC)
fn Tan(θ: Angle) -> Scalar = tan(θ / θC)
fn ASin(x: Scalar) -> Angle = asin(x) × θC
fn ACos(x: Scalar) -> Angle = acos(x) × θC
fn ATan(x: Scalar) -> Angle = atan(x) × θC
fn ATan2<Q: Dim>(y: Q, x: Q) -> Angle = atan2(y, x) × θC
2 changes: 1 addition & 1 deletion numbat/modules/units/hartree.nbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ unit hartree: Energy = ℏ^2 / (electron_mass a0^2)

@name("Bohr")
@url("https://en.wikipedia.org/wiki/Hartree_atomic_units")
unit bohr: Length = a0
unit bohr: Length = a0 × θC
2 changes: 1 addition & 1 deletion numbat/modules/units/misc.nbt
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ unit revolution: Angle = 360°
@name("Revolutions per minute")
@url("https://en.wikipedia.org/wiki/Revolutions_per_minute")
@aliases(RPM: short)
unit rpm: Frequency = 1 / minute
unit rpm: AngularFrequency = revolutions per minute

@name("Millimeter of mercury")
@url("https://en.wikipedia.org/wiki/Millimeter_of_mercury")
Expand Down
10 changes: 5 additions & 5 deletions numbat/modules/units/planck.nbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ use physics::constants

@name("Planck length")
@url("https://en.wikipedia.org/wiki/Planck_length")
unit planck_length: Length = sqrt( G / c^3) -> m
unit planck_length: Length = sqrt(ȟ G / c^3) -> m

@name("Planck mass")
@url("https://en.wikipedia.org/wiki/Planck_mass")
unit planck_mass: Mass = sqrt( c / G) -> kg
unit planck_mass: Mass = sqrt(ȟ c / G) -> kg

@name("Planck time")
@url("https://en.wikipedia.org/wiki/Planck_time")
unit planck_time: Time = sqrt( G / c^5) -> s
unit planck_time: Time = sqrt(ȟ G / c^5) -> s

@name("Planck temperature")
@url("https://en.wikipedia.org/wiki/Planck_temperature")
unit planck_temperature: Temperature = sqrt( c^5 / (G k_B^2)) -> K
unit planck_temperature: Temperature = sqrt(ȟ c^5 / (G k_B^2)) -> K

@name("Planck energy")
@url("https://en.wikipedia.org/wiki/Planck_energy")
unit planck_energy: Energy = sqrt( c^5 / G) -> J
unit planck_energy: Energy = sqrt(ȟ c^5 / G) -> J
6 changes: 5 additions & 1 deletion numbat/modules/units/si.nbt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ unit candela: LuminousIntensity
@url("https://en.wikipedia.org/wiki/Radian")
@metric_prefixes
@aliases(radians, rad: short)
unit radian: Angle = meter / meter
unit radian: Angle

# The "Cotes angle"
let theta_C = 1 rad
let θC = theta_C

@name("Steradian")
@url("https://en.wikipedia.org/wiki/Steradian")
Expand Down
18 changes: 9 additions & 9 deletions numbat/modules/units/stoney.nbt
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use physics::constants

@name("Stoney length")
@url("https://en.wikipedia.org/wiki/Stoney_units")
unit stoney_length: Length = sqrt(G × electron_charge^2 / 4 π ε0 c^4)
#@name("Stoney length")
#@url("https://en.wikipedia.org/wiki/Stoney_units")
#unit stoney_length: Length = sqrt(G × electron_charge^2 / 4 π ε0 c^4)

@name("Stoney mass")
@url("https://en.wikipedia.org/wiki/Stoney_units")
unit stoney_mass: Mass = sqrt(electron_charge^2 / 4 π ε0 G)
#@name("Stoney mass")
#@url("https://en.wikipedia.org/wiki/Stoney_units")
#unit stoney_mass: Mass = sqrt(electron_charge^2 / 4 π ε0 G)

@name("Stoney time")
@url("https://en.wikipedia.org/wiki/Stoney_units")
unit stoney_time: Time = sqrt(G × electron_charge^2 / 4 π ε0 c^6)
#@name("Stoney time")
#@url("https://en.wikipedia.org/wiki/Stoney_units")
#unit stoney_time: Time = sqrt(G × electron_charge^2 / 4 π ε0 c^6)
12 changes: 6 additions & 6 deletions numbat/tests/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,8 @@ fn test_algebra() {

#[test]
fn test_math() {
expect_output("sin(90°)", "1");
expect_output("sin(30°)", "0.5");
expect_output("Sin(90°)", "1");
expect_output("Sin(30°)", "0.5");
expect_output("sin(pi/2)", "1");

expect_output("atan2(10, 0) / (pi / 2)", "1");
Expand All @@ -283,7 +283,7 @@ fn test_incompatible_dimension_errors() {
get_error_message("kg m / s^2 + kg m^2"),
@r###"
left hand side: Length × Mass × Time⁻² [= Force]
right hand side: Length² × Mass [= MomentOfInertia]
right hand side: Length² × Mass
"###
);

Expand Down Expand Up @@ -420,14 +420,14 @@ fn test_misc_examples() {
expect_output("2min + 30s -> sec", "150 s");
expect_output("4/3 * pi * (6000km)³", "9.04779e+11 km³");
expect_output("40kg * 9.8m/s^2 * 150cm", "588 kg·m²/s²");
expect_output("sin(30°)", "0.5");
expect_output("Sin(30°)", "0.5");

expect_output("60mph -> m/s", "26.8224 m/s");
expect_output("240km/day -> km/h", "10 km/h");
expect_output("1mrad -> °", "0.0572958°");
expect_output("52weeks -> days", "364 day");
expect_output("5in + 2ft -> cm", "73.66 cm");
expect_output("atan(30cm / 2m) -> deg", "8.53077°");
expect_output("ATan(30cm / 2m) -> deg", "8.53077°");
expect_output("6Mbit/s * 1.5h -> GB", "4.05 GB");
expect_output("6Mbit/s * 1.5h -> GiB", "3.77186 GiB");

Expand All @@ -439,7 +439,7 @@ fn test_misc_examples() {
#[test]
fn test_bohr_radius_regression() {
// Make sure that the unit is 'm', and not 'F·J²/(C²·kg·m·Hz²)', like we had before
expect_output("bohr_radius", "5.29177e-11 m");
expect_output("bohr_radius", "5.29177e-11 m/rad");
}

#[test]
Expand Down
Loading