Replies: 2 comments
-
| First, I am sorry to answering you so late. I approached this a few times before, but I never had enough time to read more about this domain in order to better understand your domain. This looks like an interesting challenge. I don't think that the affine space and I think that the bese we can do is to model those two quantities as two siblings in a hierarchy tree, but strictly for the purpose of type safety, not for mixed arithmetic: flowchart TD length["<b>length</b><br>[m]"] length --- height height --- fluid_head height --- water_head inline constexpr struct fluid_head final : quantity_spec<isq::height> {} fluid_head; inline constexpr struct water_head final : quantity_spec<isq::height> {} water_head;quantity h1 = fluid_head(2 * m); quantity h2 = water_head(4 * m);Witht the above, both get distinct types that can't be mixed without a Crucial Warning: While this design separates the types, you must be very careful with comparison and addition.
Recommendation: Use these distinct types to prevent accidental mixing. When you need to perform calculations involving both, you should implement a conversion function that accepts the Once converted to the common See this for more info: https://godbolt.org/z/4hMYch6sb |
Beta Was this translation helpful? Give feedback.
-
| For a moment I thought that introducing custom units could help here but then I realize that there is an even better solution here. Let's make those two quantities subkinds: inline constexpr struct fluid_head final : quantity_spec<isq::height, is_kind> {} fluid_head; inline constexpr struct water_head final : quantity_spec<isq::height, is_kind> {} water_head;This design is similar to how we prevent mixing frequency and activity or plane and solid angles in the library. With the above: void use_fluid_head(quantity<fluid_head[si::metre]> fluid) {} void use_water_head(QuantityOf<water_head> auto water) {} void use_height(QuantityOf<isq::height> auto height) {} int main() { using namespace mp_units::si::unit_symbols; quantity fluid = fluid_head(2 * m); quantity water = water_head(4 * m); use_fluid_head(fluid); // OK // use_fluid_head(water); // Error // use_water_head(fluid); // Error use_water_head(water); // OK // quantity q1 = fluid + water; // Error // quantity<water_head[m]> q2 = q1; // Error // if (fluid == water) {} // Error // quantity q3 = water_head(4 * fluid_metre); // Error // use_height(fluid); // Error // use_height(water); // Error use_height(isq::height(fluid)); // OK use_height(isq::height(water)); // OK }Please note that now both quantities are not automatically considered to be lengths so if you want to use them like so you need to explicitly convert them to the desired length quantity like I did in the last 2 lines of code. @oZed, I hope that is a solution that you were looking for? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I am trying to use mp-units for some hydraulic calculations and so wanted to implement the hydraulic head as a new quantity. It is somewhat common to calculate the head in terms of either the fluid in question (sometimes called the 'fluid' head) or normalised against the specific gravity to give the head in terms of water (sometimes called the 'water' head). I want to make these two quantity types distinct to prevent them being mixed up, however since the fluid head really acts like a tuple of quantities (a head and a specific gravity value) it isn't really modelled by the ISQ character types. I thought about trying to use a quantity_point with the specific gravity being somewhat like an origin, but currently the library requires the origin and delta to have the same quantity type. Am I better off just implementing a custom type in such a case? Please let me know if I've missed something and this can be implemented with the current library types!
Beta Was this translation helpful? Give feedback.
All reactions