bernedom / SI

A header only C++ library that provides type safety and user defined literals for physical units
https://si.dominikberner.ch/doc/
MIT License
486 stars 40 forks source link

Handle implicit and intermediate dimensions #97

Closed spira-inhabitant closed 2 years ago

spira-inhabitant commented 2 years ago

Hello,

First, thank you for this great library :)

Maybe I miss some point here but, is there an easy way to handle these two cases:

SI::metre_t<double> dx;
SI::metre_t<double> dy;
SI::seconds_t<double> dt;
SI::seconds_t<double> total_duration;
auto surface_flow = dx * dy / dt;  // compile error because there is no type for m^2/s
auto total_surface = dx * dy / dt * total_duration;  // compile error but there is a type for m^2

Regards and thank you.

bernedom commented 2 years ago

Thank you for your question. There is currently no type for surface flow (m^2/s), which is why the operations fail. SI does not build the types dynamically, so they must be added manually. I will add surface flow in one of the next releases, but I will need a bit of time to implement and test it.

Until then you can either define it yourself by defining the type yourself like this:


#include <SI/area.h>
#include <SI/time.h>
#include <SI/detail/operator_helpers.h>

/// Type for surface flow a = m^2 / t 
template <typename _type, typename _ratio>
using surface_flow_t = detail::unit_t<'f', std::ratio<1>, _type, _ratio>;

namespace detail {
BUILD_UNIT_FROM_DIVISON(surface_flow_t, area_t, time_t)

} // namespace detail
spira-inhabitant commented 2 years ago

Thank you. Actually I did that already. I see two limitations:

BUILD_UNIT_FROM_DIVISON(surface_flow_t, area_t, time_t);

square_metre_t surface; seconds_t duration; auto surface_flow = surface / duration; // OK

metre_t width; metre_per_second_t speed; auto surface_flow_2 = width * speed; // compile error

bernedom commented 2 years ago

Dimensions are specified by their symbol (letter) and the exponent. For volume flow rate, this would either be Q, V` (I don't know what it is for surface flow). Currently, SI is limited to the ASCII chars, but I'm considering switching to Unicode or multi-letter identifiers for that, so that other mathematical symbols like "gamma"/(𝛾), "Ohm" (Ω) are supported.

You can combine multipleBUILD_UNIT_FROM_DIVISION or BUILD_UNIT_FROM_MULTIPLICATION calls. I.e. add the following to the code above:

BUILD_UNIT_FROM_MULTIPLICATION(surface_flow_t, length_t, velocity_t)

All the units, conversions, and operators in SI have to be explicitly specified, either manually or by using the BUILD_UNIT_FROM... macros. Apart from the availability of the operators, the types themselves do not know to which other types they might decay or be built from. I agree, that it would be nice if it would be awesome if such conversions would be automatically generated or if SI could support formal notation of how units converse to each other and then guess all the possible conversions, but so far I have not found a way to do that without making the library much more complex than it is now.

But if you have already implementations for missing units feel free to create a pull request. As there is no way that I know all the possible units out there contributions are highly welcome! Have a look at the Contributing guidelines

spira-inhabitant commented 2 years ago

That solves my problem. Thank you for you time.

We'll take a look to the contributing guidelines. Thank you.

bernedom commented 2 years ago

Surface flow and volumetric flow will be included in version 2.4.0 of SI.

spira-inhabitant commented 11 months ago

Thank you :)