aurora-opensource / au

A C++14-compatible physical units library with no dependencies and a single-file delivery option. Emphasis on safety, accessibility, performance, and developer experience.
Apache License 2.0
309 stars 19 forks source link

Document angles #87

Open chiphogg opened 1 year ago

chiphogg commented 1 year ago

As with most every other mature units library, we've realized that angles should be included as first class participants in dimensional analysis. This conflicts with the widely held assumption that angles are "really" or "intrinsically" dimensionless. We owe it to our users to explain this situation. The specific deliverables should be:

  1. A "how-to" guide to explain precisely how to update equations with angular quantities. This should include a table with a column for the conventional formulae, and a column for each of the Leonard and Quincey conventions.

  2. A "discussion" page explaining:

    • Why the usual arguments that angles are "intrinsically" dimensionless are no good.
    • How to understand traditional equations: the "Quincey disclaimer".
    • In what sense we mean that angles are "intrinsically" dimensioned: not in any grand metaphysical sense, but in the same practical sense that justifies treating any other quantity as having dimension.
    • How to use the library if you insist on treating angles as dimensionless: "don't say radians if you don't mean radians".
adamleeper commented 1 month ago

Hi Chip -- RyanM pointed me at this while I was trying to find a clean way to handle the problem of calculating velocities of a point on a rigid body:

MetersPerSecond velocity_of_origin = meters_per_second(1);
Meters distance_to_other_point = meters(1);
RadiansPerSecond angular_velocity = radians_per_second(1);
MetersPerSecond velocity_of_other_point = velocity_of_origin + distance_to_other_point * angular_velocity;  // Compile error, cannot add m/s and m*radians/s.

I can of course get around this by dividing by radians(1):

MetersPerSecond velocity_of_other_point = velocity_of_origin + distance_to_other_point * angular_velocity / radians(1);

But, it looks messy to the physics folks, even if it's strictly correct from a units and typing standpoint.

Is there a convention / pattern to make this look nicer?

chiphogg commented 1 month ago

Is there a convention / pattern to make this look nicer?

There's two! :upside_down_face:

The first step is to confront the core question: if angles are "really" dimensioned, then why does basically-all-of-physics work? A good mental model for this is that setting radians to 1 is a kind of "natural units" system, akin to "setting" $c$ or $\hbar$ to 1 in high-energy physics. Everything still works, but only if you use a specific system of units; and, you give up (at least partially) on dimensional consistency.

On this mental model, if we restore angles' dimensions, then we should expect to see some constants pop up in our equations, just as $c$ and $\hbar$ do in order to make high energy physics equations correct in any unit system. Unlike the high-energy equations, we don't have common agreement on what the "right" full-equations are.

I know of two very serious attempts to reconcile the SI with dimensioned angles, both published in 2021. In no particular order:

There is no publicly freely available PDF for the latter, but I suspect if you emailed the author, he'd be glad to provide a copy. :slightly_smiling_face: Both papers are well worth a read.

There are various tradeoffs involved in choosing either system. For example, the Quincey approach seems to treat energy as being fundamental, and preserves the form of the torque/energy equation. From a programming point of view, it also makes it easy to distinguish energy from torque, as it uses J/rad for the latter instead of N*m (which is dimensionally equivalent to energy despite being a distinct concept). Leonard's approach, on the other hand, preserves the familiar definition of quantities such as torque and angular momentum. It also has a distinct practical advantage, in that the translation to dimensionally correct equations is much more mechanical: you simply replace any angular quantity $\theta$ (or $\omega$, or ...) with its ratio with the Cotes angle $\Theta_c$ (a constant of nature whose value is 1 radian), and then perform any cancellations.

In practice, what you do is:


Last point (in a separate section because it's unrelated): when you do your multiplying or dividing by 1 radian, I suggest using a constant, instead of radians(1), perhaps defining in a common location:

constexpr auto THETA_C = make_constant(Radians{});

This will give you maximum flexibility w.r.t. the underlying numeric types (the "rep").

Or, if it's more readable, you could use the built-in unit symbol for radians, rad, which will function in much the same way. So, in any .cc file (not .hh file, as you want to avoid namespace pollution):

// In a `.cc` file:
using ::au::symbols::rad;

Then you could just multiply or divide by rad.