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

Show your Numbat programs #610

Open
sharkdp opened this issue Oct 9, 2024 · 5 comments
Open

Show your Numbat programs #610

sharkdp opened this issue Oct 9, 2024 · 5 comments

Comments

@sharkdp
Copy link
Owner

sharkdp commented Oct 9, 2024

It would be great to get more feedback on how Numbat is being used. If you have any Numbat calculations / programs to show, I'd be very interested to see them. I think it could help move the language design forward if we see what kind of features are being used, how they are used, what kind of features are not used (and why), etc.

All kinds of programs are welcome. Everything from simple one-line expressions to larger computations. Polished or unpolished.

The numbat repository contains a lot of examples, if you are looking for inspiration.

@joshop
Copy link

joshop commented Oct 10, 2024

Here is a module I made for using Numbat with GregTech, a Minecraft mod that adds some technological systems. This includes a simplified system of electric energy distribution. This was fun and easy to make, it really seems like Numbat is best in these sort of applications.

@Exidex
Copy link

Exidex commented Oct 17, 2024

Gauntlet Application Launcher uses Numbat for quick dynamic calculator, currency conversion is also frequently used feature. It only uses one line throw away expressions that are interpreted right as they are written, so context modification between calls is not desirable. It is also a long running program, potentially multiple days or even weeks, so online features like currency exchange rates have to be refreshed regularly. The use case may not be a perfect fit for Numbat's because it prioritizes correctness of expression, where for Gauntlet the ease of writing expressions is a priority, Gauntlet does some very simple pre-processing now but in future I planed on looking into writing custom parser on top of Numbat's very solid base. There's bunch of feature requests here, which I didn't yet had time to create proper issues, but even without those Numbat has been a solid choice so far

@sharkdp
Copy link
Owner Author

sharkdp commented Oct 23, 2024

Here is a module I made for using Numbat with GregTech, a Minecraft mod that adds some technological systems. This includes a simplified system of electric energy distribution. This was fun and easy to make, it really seems like Numbat is best in these sort of applications.

This is so cool — thank you for sharing!

Gauntlet Application Launcher uses Numbat for quick dynamic calculator, currency conversion is also frequently used feature.

Cool. Not really the topic of this thread, but thank you for sharing 😄.

The use case may not be a perfect fit for Numbat's because it prioritizes correctness of expression, where for Gauntlet the ease of writing expressions is a priority, Gauntlet does some very simple pre-processing now but in future I planed on looking into writing custom parser on top of Numbat's very solid base.

Also, please let us know if you think that Numbat can improve to better support your use cases.

There's bunch of feature requests here, which I didn't yet had time to create proper issues, but even without those Numbat has been a solid choice so far

Thank you for the feedback. Please feel free to file feature requests once you have the time.

@mihirmanna
Copy link

Here is some (very unpolished, lol) code that I've developed for my astrodynamics course, to convert between Cartesian components and the classical orbital elements. Both scripts make use of a customvector3 module that I'm writing at the same time, which handles the details of 3-vector and 3x3 matrix operations.

vector3 Module
struct Vec3 {
    x: Scalar,
    y: Scalar,
    z: Scalar,
}

struct Matrix3 {
    col1: Vec3,
    col2: Vec3,
    col3: Vec3,
}


fn rows(M: Matrix3) -> List<Vec3> = [row1, row2, row3]
    where row1 = Vec3 { x: M.col1.x, y: M.col2.x, z: M.col3.x }
    and   row2 = Vec3 { x: M.col1.y, y: M.col2.y, z: M.col3.y }
    and   row3 = Vec3 { x: M.col1.z, y: M.col2.z, z: M.col3.z }

fn cross3(u: Vec3, v: Vec3) -> Vec3 = Vec3 { x: cross_x, y: cross_y, z: cross_z }
    where cross_x = u.y v.z - u.z v.y
    and   cross_y = u.z v.x - u.x v.z
    and   cross_z = u.x v.y - u.y v.x

fn dot3(u: Vec3, v: Vec3) -> Scalar = u.x v.x + u.y v.y + u.z v.z

fn sq_norm(v: Vec3) -> Scalar = dot3(v,v)

fn norm(v: Vec3) -> Scalar = sqrt( sq_norm(v) )

fn scale(v: Vec3, λ: Scalar) -> Vec3 = Vec3 { x: λ v.x, y: λ v.y, z: λ v.z }

fn add(u: Vec3, v: Vec3) -> Vec3 = Vec3 { x: u.x + v.x, y: u.y + v.y, z: u.z + v.z }

fn sub(u: Vec3, v: Vec3) -> Vec3 = add( u, scale(v,-1) )

fn mat_vec_mul(M: Matrix3, v: Vec3) -> Vec3 = Vec3 { x: dot3(row1,v), y: dot3(row2,v), z: dot3(row3,v) }
    where row1 = element_at(0, rows(M))
    and   row2 = element_at(1, rows(M))
    and   row3 = element_at(2, rows(M))

fn mat_mat_mul(P: Matrix3, Q: Matrix3) -> Matrix3 = Matrix3 { 
    col1: mat_vec_mul(P, Q.col1), 
    col2: mat_vec_mul(P, Q.col2), 
    col3: mat_vec_mul(P, Q.col3),
}

let x̂ = Vec3 { x: 1, y: 0, z: 0 }
let ŷ = Vec3 { x: 0, y: 1, z: 0 }
let ẑ = Vec3 { x: 0, y: 0, z: 1 }
Conversion from Cartesian components to orbital elements
use custom::vector3

let µ = 3.986e5 # Gravitational parameter, measured in km³/s²

# Cartesian components
let r = Vec3 { x: -6045, y: -3490, z: 2500 } # Measured in km
let v = Vec3 { x: -3.457, y: 6.618, z: 2.533 } # Measured in km/s

# Angular momentum, line of nodes (intermediate steps)
let h_ = cross3(r,v)
let n  = cross3(ẑ,h_)

# Eccentricity vector, inclination angle, semimajor axis
let ecc = sub( scale( r, (sq_norm(v)/µ - 1/norm(r)) ), scale( v, dot3(r,v)/µ ) )
let i   = acos( h_.z / norm(h_) )
let a   = sq_norm(h_) / ( µ × (1 - sq_norm(ecc)) )

# Right ascension of ascending node
let Ω_ = acos( n.x / norm(n) )
let Ω_ = if n.y ≥ 0
            then Ω_
            else 2π - Ω_

# Argument of periapsis
let ω = acos( dot3(n,ecc) / (norm(n) × norm(ecc)) )
let ω = if ecc.z ≥ 0
            then ω
            else 2π - ω

# True anomaly
let θ = acos( dot3(ecc,r) / (norm(ecc) × norm(r)) )
let θ = if dot3(v,r) ≥ 0
            then θ
            else 2π - θ

print("h: {norm(h_)}")
print("a: {a}")
print("e: {norm(ecc)}")
print("i: {i -> °}")
print("Ω: {Ω_ -> °}")
print("ω: {ω -> °}")
print("θ: {θ -> °}")
Conversion from orbital elements to Cartesian components
use custom::vector3

let µ = 3.986e5 # Gravitational parameter, measured in km³/s²

# Classical orbital elements
let a   = 8000 # Measured in km
let ecc = 0.01
let i   = 28.5°
let Ω_  = 20°
let ω   = 50°
let θ   = 60°

# 1. Determine orbital radius at the given point
let r = a × (1 - ecc²) / (1 + ecc cos(θ))

# 2. Calculate r_pqw and v_pqw in perifocal coordinates
let γ = sqrt(µ / (a × (1 - ecc²)))
let r_pqw = Vec3 { x: r cos(θ), y: r sin(θ), z: 0 }
let v_pqw = Vec3 { x: -γ sin(θ), y: γ × (ecc + cos(θ)), z: 0 }

# 3.1 Rotation matrices to transform from perifocal to Cartesian coordinates
let T1 = Matrix3 { 
    col1: Vec3 { x:  cos(ω), y: sin(ω), z: 0 },
    col2: Vec3 { x: -sin(ω), y: cos(ω), z: 0 },
    col3: Vec3 { x:  0,      y: 0,      z: 1 }
}
let T2 = Matrix3 { 
    col1: Vec3 { x: 1, y:  0,      z: 0 },
    col2: Vec3 { x: 0, y:  cos(i), z: sin(i) },
    col3: Vec3 { x: 0, y: -sin(i), z: cos(i) }
}
let T3 = Matrix3 { 
    col1: Vec3 { x:  cos(Ω_), y: sin(Ω_), z: 0 },
    col2: Vec3 { x: -sin(Ω_), y: cos(Ω_), z: 0 },
    col3: Vec3 { x:  0,       y: 0,       z: 1 }
}
let rotation_matrix = mat_mat_mul( T3, mat_mat_mul(T2, T1) )

# 3.2 Calculate r_xyz and v_xyz in Cartesian coordinates
let r_xyz = mat_vec_mul(rotation_matrix, r_pqw)
let v_xyz = mat_vec_mul(rotation_matrix, v_pqw)

print("r: {r_xyz}")
print("v: {v_xyz}")

I wish that I could assign types to structs (e.g. Vec3 and Matrix3), since that would allow me to automatically handle unit conversions and not worry about inputting my parameters in particular units. Either way, Numbat has been a game-changer for me as a physics student, so keep it up!

@sharkdp
Copy link
Owner Author

sharkdp commented Mar 9, 2025

I wish that I could assign types to structs (e.g. Vec3 and Matrix3), since that would allow me to automatically handle unit conversions and not worry about inputting my parameters in particular units. Either way, Numbat has been a game-changer for me as a physics student, so keep it up!

Yes, absolutely. Let's discuss this further in #452. Thank you for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants