Group Abstract Group Abstract

Message Boards Message Boards

1
|
5.7K Views
|
5 Replies
|
4 Total Likes
View groups...
Share
Share this post:

HOWTO Use Quantity and UnitConvert etc. without a huge performance penalty?

POSTED BY: Darren Kelly
5 Replies

I remain convinced that there is a massive performance problem with the Quantity system. I describe here how I am using it, and assert that this is a sensible and desirable way of using the Quantity system for physics applications, one that is consistent with the expectations one might reasonably have based on this Wolfram help page https://reference.wolfram.com/language/guide/Units.html:

The units framework integrates seamlessly with visualization, numeric and algebraic computation functions.

My real application (which includes highly customised heat exchanger calculations for air conditioners) uses progressive chaining of functions that each return a Quantity. I have a large application that progressively calculates Quantities, which are then used to calculate other Quantities, and then more Quantities, chained beautifully so that at each stage one can view Quantities with units, and use them in various contexts, always as a Quantity.

For example:

  • A specific heat capacity (with units) is computed, it returns a Quantity that is then used by a dozen other Quantity-aware functions.

  • A tube area (with units) is computed, it returns a Quantity that is then used by a dozen other Quantity-aware functions.

  • A function that computes a refrigerant heat transfer coefficient (from many other functions that return Quantity) automatically returns a Quantity with the correct units. It also uses the tube area (and other Quantity results).

  • That refrigerant heat transfer coefficient is then used to compute an overall heat transfer coefficient, which calculation also incorporates about a dozen other Quantity results, and automatically returns a Quantity with the correct unit.

  • The overall heat transfer coefficient is is then used, together with the air stream capacity rate (a Quantity) and the air-side- exchange area (a Quantity) to compute the number of transfer units (NTU), which becomes automatically dimensionless.

  • The NTU is then used together with the stream capacity rate ratio (computed via previously computed specific heat capacities) to compute the effectiveness (ϵ).

  • The effectiveness (ϵ) is then used together with the air inlet temperature (a Quantity), the refrigerant tube inlet temperature (a Quantity) and the stream capacity rate ratio to compute the heat transfer rate (returned as a Quantity with automatically computed units).

And so on. At each stage, each derived Quantity is available with automatically computed units.

Only the very initial Quantity inputs need to have the unit specified via a Quantity[value,”unit”] call.

From then on, I am relying on the units-aware MMA system to figure out the correct return Quantity. It is absolutely fantastic. At any stage, one can inspect a derived computed value, at any level of the system, and know that the unit is correct. It has been brilliant for development. But it is far too slow.

I assert that it is what any physicist would want (and expect) a units-aware system to be able to do.

(And please note that the air-conditioning industry is riddled with non-SI units.)

[EDIT: I've attached a MOCK instance Dependency diagram (using SysML) to show a small subset of the equation network used for a classic effectiveness-NTU heat exchanger calculation. It is NOT complete, it's just enough to show the inter-dependencies and chaining of Quantity returns. I in fact do this within on-the-fly accessor methods using MTools, but that's not relevant for now.]

MOCK Dependency diagram for heat exchanger calculation

Where unit conversion/scaling does come in: correlation functions

In heat exchanger physics there is a lot of use of correlation functions (a weird and wonderful collection of formulae based on rigorous testing, educated guesswork, and some voodoo). These usually assume Real input arguments that are scaled to correspond to some advertised units and return a Real, which is advertised to be in certain units. The formulae are not necessarily all SI.

In any case, because my heat exchanger application is otherwise completely based on Quantity, any inputs to the correlation formulae have to be scaled to a correct Real. The way I mostly do this is using predefined "unit Quantity" variables. For example, if the correlation function expects a temperature in Kelvin, I do this.

I have predefined "unit Quantities" in a large units Package library (not all are SI):

unit$K = Quantity[1, "Kelvins"]

The correlation functions take one or more Real and return a Real:

fCorrelation[tK_Real] := 0.1234 tK^2;

temp1 = Quantity[20., "Kelvins"]

20. K

To use the correlation function from one of the Quantity-based functions in the higher application I scale the argument(s) safely thus:

fCorrelation[temp1/unit$K]

49.36

Head[%]

Real 

In practice, the return from the correlation function then has to be converted to a Quantity for integration into the rest of the Quantity-based calculations (which can be done using UnitConvert or by multiplying by a "unit Quantity".


ASIDE: This is how I actually mostly "create" a Quantity. I just multiply by a "unit Quantity" from my library:

temp2 = 21. unit$K
21. K

This is very easy to use in code, and avoids the need for invoking Quantity each time.

POSTED BY: Darren Kelly

@Eric Rimbey

Many thx for your reply. I agree that using a Quantity (my predefined "unit Quantity" approach) as the 2nd argument to UnitConvert is clearly irregular and not a good idea, and as you showed it comes with some overhead. I tested also your version of this, where you use an explicit unit String "DegreesCelsius":

test$UnitConvertDirect2[n_, tK_] :=  Table[Quantity[((tK + i/n) - 273.15), "DegreesCelsius"], {i, 1, n}]

I also found it to be about 30 times faster. That's something I can easily address in my application. However it's still massively slower than not using a Quantity at all (Quantity creation and UnitConvert are still dreadfully slow), and it does not address the other main issue.

Here's another example, with no explicit use of UnitConvert (see also attached notebook and screenshots). Perform the classic distance calculation d = vt + (1/2) a t ^2 with and without Quantity arguments and Quantity return. The versions using Quantity are over 500 times slower.

EDIT: 2022-07-28 14:30 AEST I have removed completely a notebook screenshot that was causing confusing. I have replaced the notebook with a new one that only uses For in the timing tests, not Table, because it was causing confusion. (If you wish to help, please do not recommend use of QuantityArray, it is not relevant for the real world application example.) Consider instead a For loop over a complex network of physics functions, each of which returns a Quantity, computes the units internally automatically, and is then consumed in many other units-aware physics functions, which each returns a Quantity, and so on.

POSTED BY: Darren Kelly
Posted 3 years ago
POSTED BY: Rohit Namjoshi

@Rohit I've removed the screenshot and updated the Notebook to make it clearer and more consistent. I've removed any use of Table in the timing tests

POSTED BY: Darren Kelly
Posted 3 years ago
POSTED BY: Eric Rimbey
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard