-
Notifications
You must be signed in to change notification settings - Fork 105
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
System of units #783
Comments
Also consider CALIFA: experimental calibrations always seem to be keV, while simulations are GeV. |
My 25 cents (value+unit) would be to use the Geant4 style of doing units. It is not too hard to work with, and not very verbose (only if one would start to spell things out, like It also provides small inline comments about the unit, without comment delimiters. And since quantities do have both a value and a unit (unless dimensionless), bare-word land02 uses some compile-time type-system for units (very crude though). That turned out to be very clumsy, and a real hindrance all over the place. Based on that experience, I'd recommend to go for the not-perfect (i.e. no static compile-time checking) Geant4-style, which still should get things much closer to easily checked code than having no unit specifiers at all. At least it is a starting point, much better than bare-word unitless values, and should be hard to argue against introducing. Another nice thing with the Geant4 style is that it does not really hard-code the basic units used internally. E.g. 1 mm could be changed to 1 m without having to change anything but the definition. All other code just needs a recompile. It also does not force a particular base in print-out or plotting. Since one anyhow has to (or at least should!) do And the Geant4-style should work rather well in a C-code as well, given a suitable header. |
Geant4-style units are cool for me. It would be better to have them in the framework (with external maintenance) instead in a flavour (our r3b flavour). Any volunteer to perform the modification? It would require the revision of several thousands of code lines to adapt, in many classes ... |
It can hopefully be done in pieces - as long as thing stay consistent. One problem with not having the compiler nag about things, is that the chance for mistakes is not much reduced. And even increased during the transition, which may take a long time. One way to at least hint someone reading code would be to use some typedefs:
This would not catch any errors, but at least act as a note to a user that the variable is to be handled with the CLHEP units. A way to try to make consistent changes is to do just start with one or a few variables at a time, and then also whatever things interact with it. Interactions can be found by temporarily (i.e. during edit+compile cycle, but not committing) changing names of the affected variable and function, e.g. |
There is user defined suffix operator in C++ (check this). And we can write values like: 1_m, 2_ns, 3_MeV |
At least SI units do not suffer that much from inflation :-) I meant "verbose" (at the level in my original comment) a good thing, actually. I agree that having to spell out keV would be overly verbose. I think it would be helpful to distinguish enforcing dimensional analysis within classes/functions and at interfaces. Within a class/function, the spatial, temporal and interpersonal difference between the setting a double in some unit and using it is typically small:
Also, there are all sorts of ways to calculate the wrong result which would not be detected by dimensional analysis, so the function has to be manually checked anyhow. Forcing devs to convince the compiler that all the units match will waste a lot of time for little benefit. On the other hand, the distance between the caller of a method and the method can easily span multiple software projects and decades. The person writing the call might not even have met the author of the called code. Enforcing units in such a context seems like a sensible precaution. To that end, I would propose having two namespaces.
strong_unit types would be implicitly convertible to corresponding weak_unit types (with the value getting automatically adjusted by division through base). weak_unit types would be implicitly convertible to double.
This would allow us to:
(Mostly tangential rambling following) I have to say that I am bitterly disappointed that the suffix has to be explicitly spelled out in the definition. The very least they could have done is to allow
works. This opens up the possibility of building a _pdg prefix. Instead of having to refer to a class proton by name we could just use the literal 2212_pdg. ) Just kidding. Using 42.0_m over 42.0*m has the advantage that the result does not depend on a variable called m being in scope or not, so it is probably a good idea. |
Do you think following usage is good?
With suffix operator, I don't think we can do something like "1_m<2>". |
This should be a proposal for FairRoot, we could then use it directly in R3BRoot. |
ROOT says:
I think following the lead of the LHC experiments here and adopt the Geant4 units. This has the additional advantage that we can use Geant4 unit prefixes.
I think writing
task->SetThreshold(20*MeV)
task->SetMaxTheta(10*degree)
task->SetRadius(20*cm)
hist->Fill(hit->GetEnergy() / keV )
is very verbose.
(Of course, it what would be even better would be dimensionality checking at compile time (so that
20*cm+1*MeV
orhist->Fill(hit->GetEnergy())
will not even compile, but this would require more work.The text was updated successfully, but these errors were encountered: