-
Notifications
You must be signed in to change notification settings - Fork 2
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
dimensional order of operations / moderately complex formulas #64
Comments
@td002 - many thanks for trying this module and for the feedback. I did indeed have an early version of the code that synthesized "artificial" units for intermediate results where there is no predefined unit to be found, this did not make it to the current release I agree that this is a worthwhile new feature and therefore will leave this issue open and aim to implement in the next major release I am struggling a bit with tuits on this right now, so please feel welcome to make the change yourself and submit a PR Since you have knowledge of the wider range of unit libraries, perhaps I should consider refactoring this module around a more widely used lib - which one would you say is the best target (mainly for linux type systems for now)? |
I'm learning Raku (from Perl) --- I'll see if I can follow the logic to see if there's a quick fix I have the skill to implement. wrt unit libraries or libraries that could be used for refactoring, here's what I know that might be useful to you. UDUNITS-2In terms of a well-tested pure unit library that has an API that could be accessed through NativeCall, AFAIK there's only UDUNITS-2. It provides basic math operators (+,-,*,/,**,root,log) for right-side-only calculations. There's a perl module (Physics::Udunits2) that uses XS to access the API that would probably give you a head start if you wanted to use this. GNU UnitsGNU Units is also very good, but no official API. GiacI'm a practicing civil engineer and haven't the skill to make even a partial NativeCall port of this system --- but I do often use the Xcas/Giac computer algebra system for these sorts of calculations. Giac is the CAS engine, and has a C++ API. It also supports a wide array of units that you can tag to values. Giac is used as the CAS in HP Prime and Numworks calculators. In a lot of ways unit management is a problem for a CAS to solve. So with Xcas/Giac you can supply an equation, and then substitute values with whatever units you have without the need for conversion, then solve for the missing variable on either side of the equation, and get the answer in whatever (dimensionally consistent) unit you need. e.g.
It is difficult to overstate how much mental overhead it saves an engineer to be able to do something like this. And yet, most other engineers I know are still using fixed-unit formulas with spreadsheets or calculators to do these sorts of quick calculations. They just rearrange the equation by hand to get the function they need. Most of the time it's fine because they're working with the same units all of the time and the physical constants and unit conversions get compressed into a constant that saves some time --- at the cost of flexibility. There is a python interface for Giac. If I had the time to try to understand how they make the bridge from python variables to Giac variables, and I also somehow suddenly acquired the skill to do that in Raku, I'd give it a go with NativeCall. But alas, I don't have enough jar for all of my rocks, nevermind the sand. There's a simple perl module (Math::Giac) that basically just gives you a way to assign values to variables with a hashref and then builds a script that gets passed to the Giac executable --- it doesn't use the API. It works for what it does, but it looks like something I would write. |
I suspect this may be a difficult fix for the fixed-dimension-type design model, but I like the intent of this module, and ran into the problem pretty quickly, so I'll let you know.
I could also be wrong --- and it's an easy fix --- or wrong in that I'm using the module incorrectly.
The problem seems to be related to order of operations and comparison to the pre-defined types. It seems like if any part of an operation doesn't match one of the predefined types --- even if the dimensions will later cancel to match --- the units get dropped and calculation proceeds without units.
Impractical illustrative simple test case
my $a = 1kg;
my $b = 1kg;
my $c = ♎️<1 m/s^2>;
this works fine:
my $d = $a * $c;
say $d.in('N');
output: 1N
something like this should also work, but it doesn't. Seems to choke on the
idea of a square kilogram before the dimension-canceling takes place.
my $e = $a * $b * $c / $b ;
say $e.in('N');
output: No such symbol in method multiply at (Physics::Measure) line 254
say $e;
output: 1
Practical test case
Calculation of hydraulic power
my Flow $Q = Flow.new( value => 1, units => 'm^3/s' );
my Length $h = Length.new( value => 10, units => 'm' );
my Density $d = Density.new( value => 1000, units => 'kg/m^3' );
my Acceleration $g = Acceleration.new( value => 9.81, units => 'm/s^2' );
my $P = $Q × $h × $d × $g;
say $P;
output: 98100
say $P.in( 'kW' );
output: No such method 'in' for invocant of type 'Rat'.`
Other program examples
gnu units, udunits2, orpie, hp calculators can usually do this type of thing, as long as the end result is dimensionally consistent with whatever unit you're trying to express/convert after the operation is complete.
gnu units
units -t -v "(1 m^3/s)*(10 m)*(1000 kg/m^3)*(9.81 m/s^2)" kW
output: 9.81 kW
mixed-unit systems also work fine, as long as result is consistent
units -t -v "(100 gallons/min)*(10 ft)*(9.81 m/s^2)*(62.4 lb/ft^3)" horsepower
output: 0.25286413 horsepower
udunits2
udunits2 -H "(1 m^3/s)*(10 m)*(1000 kg/m^3)*(9.81 m/s^2)" -W kW
output: 9.81 kW
The text was updated successfully, but these errors were encountered: