# [SciPy-dev] design of a physical quantities package: seeking comments

Jonathan Guyer guyer@nist....
Sun Aug 3 10:35:47 CDT 2008

```On Aug 3, 2008, at 9:22 AM, Darren Dale wrote:

>> More, what happens when you have a quantity in Newton-metres (say)
>> and
>> you ask it to convert to feet? Do you get Newton-feet, or do all the
>> occurrences of "feet" in the Newtons get converted?
>
> They all get converted.

I'm with Anne. I'm having a really hard time seeing when I would want
this as a default behavior, whereas I frequently want to be able
automatically convert BTUs to Joules and atmospheres to Pascals, but I
want an exception if somebody tries to give me a pressure when I ask
for an energy. Having it possible to do what you suggest seems like it
might be useful sometimes, but I don't think it should be the default
behavior.

>> I think the hard part will be getting the ufuncs to behave correctly.
>> As you say, if you can get addition, multiplication, and fractional
>> powers working, you're pretty much there.
>>
>> The key question for me is what units quantities are kept in
>> internally. Keep in mind that some arrays are large, so conversions
>> of
>> quantities between units can be expensive. If I'm doing many
>> calculations with quantities expressed in pc/cm^3, I would hope that
>> they are not constantly being converted to m^{-2} on input and back
>> to
>> pc/cm^3 on output. In fact I can imagine cases where both these
>> conversions happen inside a loop. That could get expensive.
>
> The values would not be stored in some standard internal
> representation like
> SI, but rather in the units specified, decomposed into fundamental
> dimensions. I do not know how a compound unit like pc/cm^3 would
> work, but
> Frink doesnt know how to do it either. There is an example from my
> field too:
> How much surface-area can you pack into a given volume? This is often
> expressed in m^2/cm^3. What a headache. Maybe I could come up with a
> method
> that returns an alternate string representation of the quantity:
> q.in_units_of("pc/cm^3"). But it would not effect the internal
> representation.

ScientificPython) to work with the large fields of numbers we needed
for FiPy. It's largely Konrad's code; the primary difference is that a
1000x1000 array gets one unit, not a million of them.

Using this scheme:

>>> from fipy import PhysicalField
>>> PhysicalField("12 lyr/cm**3")
PhysicalField(12.0,'lyr/cm**3')
>>> PhysicalField("1 lyr") / "7.3 cm**2"
PhysicalField(0.13698630136986301,'lyr/cm**2')
>>> PhysicalField("12 lyr/cm**3").inUnitsOf("m**-2")
PhysicalField(1.1352876567096959e+23,'1/m**2')

so the compound unit that Anne wants is supported and conversion to
canonical units happens only when requested.

Note: I had to use light years because parsecs aren't predefined, and
adding new units & constants is one of the weaknesses of Konrad's
design.

I urge a long look at Konrad's code (or our adaptation of it: http://matforge.org/fipy/browser/trunk/fipy/tools/dimensions)
, as it already does a lot of what you want. It was written in Numeric
days, so I think a re-implementation as a subclass of ndarray with
tighter integration with ufuncs [*] would be a big improvement, but
the basic design is a good one, IMO.

[*] Actually, I don't know if the ufunc integration needs to be any
tighter:

>>> from fipy import PhysicalField
>>> import numpy
>>> numpy.exp(PhysicalField("1 m**2"))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/guyer/Documents/research/FiPy/trunk/fipy/tools/
dimensions/physicalField.py", line 595, in __array__
raise TypeError, 'Numeric array value must be dimensionless'
TypeError: Numeric array value must be dimensionless
>>> numpy.exp(-PhysicalField("1. eV") / "300 K * kB")
1.587664463548766e-17

We presently have a "numerix" abstraction layer to make sure that
numerix.exp() calls the methods we want, because Numeric didn't do
this, but with numpy I think a lot of that can go away.

```