nutofem / nuto

NuTo - yet another finite element library
https://nuto.readthedocs.io
Boost Software License 1.0
17 stars 5 forks source link

Using literals for measurement units #226

Open vhirtham opened 6 years ago

vhirtham commented 6 years ago

I recently stumbled about user defined literals:

http://en.cppreference.com/w/cpp/language/user_literal

We can use them to define physical measurement units, so you can write something like

std::cout << 12._MPa << std::endl;

which returns "1.2e+07".

To be clear: They don't provide any kind of type safety. So you can pass a Newton as a parameter into a function that is supposed to take a time unit. The only benefit would be a better readability for the "user" and maybe the avoidance of typos. Personal neural network failures like mixing values in mm with values in m would also be a little bit more obvious than raw numbers. The implementation is quiet simple:

constexpr long double operator""_N(long double input)
{
    return 1.0 * input;
};

constexpr long double operator""_m(long double input)
{
    return 1. * input;
};

constexpr long double operator""_MPa(long double input)
{
    return 1._N / (1._m * 1._m) * 1.e6 * input;
};

As long as you use them consistently, you should only run into unit related issues, if your law uses an own unit measurement system internally. We can collect all of the literals in a single header "nutoLiterals.h". Nobody would be forced to use them because they are just replacing scaling factors.

So what do you think?

joergfunger commented 6 years ago

If you output something, this is then in the scaled SI-units, i.e. you put in the strength in MPa, and in your visualization file in paraview, the result is scaled be 1e-6? I see the beauty for the inputs, but I'm not sure, if this automatic conversion is clear for a user.

vhirtham commented 6 years ago

You are right. It is only for the inputs and if you use SI units as base your results are always in SI too. I don't think it is a real problem, since this feature would be totally optional to the user. If he uses it, he hopefully read a well documented tutorial which tells him about this issue before. To be sure, we can also name the header something like SIScalingLiterals.h or SIFactorLiterals.h so that it is more obvious that you are just dealing with factors. Additionally use a extra namespace to make it absolutely clear.

In my opinion this feature could help you in several ways.

Psirus commented 6 years ago

If we want help with units, then why not just use Boost units?

vhirtham commented 6 years ago

Just had a short look at it, but aren't those own types which requires to provide corresponding interfaces? The thing about the literals is, that its just a scaling factor, so no adjustments are needed and you are not forced to use them.

TTitscher commented 6 years ago

So our libnuto still runs on simple doubles and the user may (or may not) define some units. I personally, as a user, deviate from SI units and calculate in millimetres in all my applications/tests. And, thus, pressure is in MPa. So E = 20000 (MPa), instead of E = 20000 * 1e6(Pa). Maybe, for someone that calculates bigger structures, meters will be the preference. Or an imperial guy uses pound force or poundal per square inch. But there are always parts of the lib that may not be useful for others, like PhysicalConstants.h or IGA or voronoi visualization or history data or whatever. So if that is helpful for you, put it in.