mpusz / mp-units

The quantities and units library for C++
https://mpusz.github.io/mp-units/
MIT License
1.07k stars 85 forks source link

Distinguish Gray from Sievert #494

Closed chiphogg closed 1 year ago

chiphogg commented 1 year ago

Gray is straightforward: it's the absorbed radioactive dose. Joules per kilogram; energy per mass.

Sievert is also "equivalent" to joules per kilogram, but it refers to a biological effect. It's a qualitatively different category. See: https://en.wikipedia.org/wiki/Sievert#Definition

I normally view quantity kind support as a nice-to-have, but with diminishing returns. However, in this case, I was so worried about mixing up Gray and Sievert that I declined to add the latter to our library! aurora-opensource/au#157

In some sense, it feels as though Sievert is to Gray as Lumen is to Watt. That is, it's computed based on a spectral weighting function, but we think of what it measures as being qualitatively different. This analogy would suggest a new base dimension for Sievert. While this could be useful from a software point of view in preventing confusion, it's evidently not the route the SI took.

Probably the best approach is to use mp-units' excellent quantity kind support and make Sievert an incompatible kind of quantity with respect to Gray.

chiphogg commented 1 year ago

What precipitated this: I was browsing bfbc1785b8771ffe3a107b7a846023a5efaa3d69, and I noticed that gray and sievert were next to each other and appeared not to be distinguished.

mpusz commented 1 year ago

Resolved with https://github.com/mpusz/mp-units/commit/7a6b629218de45ecfa49ca073e46da2fb278b8b1

mpusz commented 1 year ago

I think this is as far as we can go here:

quantity q1 = 100 * J / (10 * kg);
quantity q2 = isq::absorbed_dose(q1);
quantity q3 = isq::dose_equivalent(q1);

std::cout << q1 << "\n";
std::cout << q1.in(Gy) << "\n";
std::cout << q1.in(Sv) << "\n";

std::cout << q2 << "\n";
std::cout << q2.in(Gy) << "\n";
// std::cout << q2.in(Sv) << "\n";  // ERROR

std::cout << q3 << "\n";
// std::cout << q3.in(Gy) << "\n";  // ERROR
std::cout << q3.in(Sv) << "\n";

quantity q4 = q2 + q1;
quantity q5 = q3 + q1;
// quantity q6 = q2 + q3;  // ERROR

std::cout << q4 << "\n";
std::cout << q5 << "\n";

https://godbolt.org/z/r6hfsjnrq.

Please let me know if it makes sense or if you have some ideas on how to improve it.