Wolfram Blog
Jon McLoone

Automatic Physical Units in Mathematica

December 9, 2010 — Jon McLoone, International Business & Strategic Development

I just published a Mathematica package that provides an alternative, richer implementation of units and dimensional analysis than the built-in units package. You can get it here. Aside from being a really nice extension to Mathematica, it is also an interesting case study in adding a custom data “type” to Mathematica and extending the knowledge of the built-in functions to handle the new “type”.

First I have to explain the point by answering the question, “What’s wrong with the built-in units package?” Well, there is nothing actually wrong with it, it just doesn’t apply Mathematica‘s automation principles. It can convert between several hundred units and warn if a requested conversion is dimensionally inconsistent. But give it an input like…

3.5 Inch + 2 Meter

and it does nothing with it until you specify that you want the result in a specific unit. The core reason is that it doesn’t teach the system, as a whole, anything about units, or even that the symbol “Meter” is any different than the symbol “x”. All of the knowledge about units and Meter in particular is contained in the Convert command.

So in this package I want as many of Mathematica‘s commands as possible to do sensible things automatically when they encounter unit-based quantities. In order to do this in an extensible way, I don’t want to teach all these commands about Meter specifically, but I will create a new data type for units, so that I can teach the Mathematica commands about units abstractly. Just as in the existing version, the only function that needs to know about the ratio of Meter to, say, Inch, is Convert, though that might be invoked, in an abstracted way, by other commands.

My new data type is going to look (internally) like this:

Unit[10, "Meter"]

And I am going to represent composite units with composites of the name in the second argument. For example:

Unit[10, "Mile"/"Hour"]

So having created this type in my mind, what do I need to do to make it available to Mathematica? Well, nothing. Really, nothing! I can already enter and store data in that type and write functions that recognize that type because “type” is just an arbitrary symbol used as a wrapper for a collection of contents, and Mathematica eats symbolic data for breakfast!

Enter and store data in that type

We can proceed directly to teaching Mathematica what is special about the new type. Here is a typical rule to teach it what happens when you get powers of units.

A typical rule to teach it what happens when you get powers of units

The TagSetDelayed (shortcut notation /:) associates the rule with the symbol Unit. Generally it is good organization to keep the rules together, but it is also more efficient. More practically, it means that I don’t need to Unprotect Power. The rest is a pretty straightforward pattern that says if we apply a numeric power to a unit, the operation slips inside the Unit object and applies to each of the components of the object. The PowerExpand prevents us getting into silly units like Sqrt[Meter^2]], which is correct for complex variables, but not useful for positive real valued units.

Once evaluated, powers of unit data simplify automatically.

Powers of unit data simplify automatically

When you think about the range of mathematical functions that can be applied to units, they mostly fall into a fairly small number of categories that are roughly all the permutations of: single vs. multiple argument, unit discarding or preserving, operate on quantity or quantity and unit type, and so on. Once you collect them into groups of the same type, then you can usually come up with a single rule that can be used for each function in the group. Here is the collection for “functions of one argument that apply directly to the quantity only and remain in the original unit.” I use it to extend each function in this group (Abs through to Round) to handle units in the same way.

Functions of one argument that apply directly to the quantity only and remain in the original unit

Here is one such example in action:

One such example in action

Of course, rules such as how the automatic axes labels work on visualizations of a grid of data in different units compatible only by column are a bit more complicated. None of these rules need any knowledge of the actual units; they can just make abstracted references to whether the input units are compatible and to a “common” unit for the output. For example, Min can only operate on units if they are all dimensionally compatible:

Min can only operate on units if they are all dimensionally compatible

Once you have taught all the relevant functions in Mathematica how to handle Unit data in general, you are just left with the relatively simple task of describing how each unit behaves individually. That comes down to establishing a relationship chain between the definitions. In practice this can be simplified to a set of rules for each unit to and from a base unit representation, for example, that Unit[1, "Atmosphere"] arrow Unit[101325, "Kilogram"/("Meter"*"Second"^2)]. Then any conversion can be reduced to converting to the base unit and then back to the new unit. Since unit values are now abstracted from all the logical code, we can just keep adding data. Over the course of a couple of very tedious days I added over 1,000 units, and you can add your own to the system too.

Finally, the internal structure isn’t necessarily what we want to enter or see. Fortunately, the parser and form matter in Mathematica are just two more commands that can be given rules for our new data type. We can hide the object structure in the same way that you never look at the copious data hidden inside InterpolatingFunction or CompiledFunction. So with a couple of rules for MakeBoxes and MakeExpression, any symbol for which there is a unit value will be parsed as a Unit expression, for example, the input “Meter” parses as Unit[1, "Meter"], but displays as “Meter”.

There are lots of details to doing a good job: efficiency considerations, syntactic sugar, auto-error correction or graceful fails under misuse, coverage of reals vs. exact numbers, and so on that take the package up to about 1,000 lines of code plus the 1,000 lines of unit definitions. But all of that is essentially handled in the same way as the three examples above—with additional rules for using this newly imagined symbolic data object under different circumstances.

I think the result is the most automated handling of units in any system. If it isn’t, let me know and I will add whatever rules are missing.

Here are some examples of the package in action.

<< AutomaticUnits`

Calculations involving units will automatically convert arguments into a suitable common default unit. In most cases the default is SI units.

The default is SI units

Where input units are not compatible, no computation will be performed.

Where input units are not compatible, no computation will be performed

Composite units can be used by multiplying powers of units, and will also be handled automatically.

Composite units will also be handled automatically

SimplifyUnits will try to find simpler equivalents to composite units.

SimplifyUnits will try to find simpler equivalents to composite units

Most operators, for which unit-based quantities make sense, will automatically handle units.

Most operators will automatically handle units

Some data constructors can support ranges or intervals using unit-based quantities. For example, here we generate 10 random quantities between 1 Yard and 1 Meter.

10 random quantities between 1 Yard and 1 Meter

Or generate values between 10 Meters and 13 Yards in 1 Foot steps.

Generate values between 10 Meters and 13 Yards in 1 Foot steps

Many plotting routines will handle units, and will usually display the resulting units as AxesLabel.

Plotting routines will handle units
Plotting routines will handle units

Unit-based quantities have a head Unit, which is not shown in StandardForm.

Unit-based quantities have a head Unit

In TraditionalForm, traditional short labels, with full-name tooltips, are used for the units.

TraditionalForm[10 Meter]

You can convert quantities to specific units.

Convert quantities to specific units

Or to the most appropriate unit from a list.

The most appropriate unit from a list

A large collection of pre-defined sets of units is available.

A large collection of pre-defined sets of units is available

The available named unit sets is given by:

The available named unit sets

You can see or change the members of a particular set or create new sets.

See or change the members of a particular set

You can declare new units.

Declare new units

Temperatures are assumed to represent temperature differences for standard unit conversions.

Temperatures are assumed to represent temperature differences

But their different origins are respected using ConvertTemperature.

Their different origins are respected using ConvertTemperature.

Leave a Comment

87 Comments


Morton Goldberg

Looks to be really useful in all kinds of engineering problems. How can I obtain a copy of the package AutomaticUnits?

Posted by Morton Goldberg    December 9, 2010 at 2:26 pm
Luboš Motl

Very good. I was playing exactly with this problem in Mathematica – usually converting everyday-life units into Planck units as the canonical intermediate step of the conversion.

Posted by Luboš Motl    December 9, 2010 at 3:42 pm
Joshua Lake

Fantastic! If I can get this working with my high school physics students, we’ll be able to do some excellent problems with deeper dimensional analysis with confidence. Thanks!

Posted by Joshua Lake    December 9, 2010 at 9:22 pm
Brian Geyer

Sweet package, but it seems to be a one way street. I can get MMA to take Meter Second^-2 Kilogram and give me Newton, but i cannot get it to take Newton Kilogram^-1 and return Meter Second^-2. Thoughts?

Posted by Brian Geyer    December 9, 2010 at 9:38 pm
Peter Aronsson

Impressive. I am specially fond of the fact that you also added some Swedish units like skålpund ;)

I think that since engineers are typically lazy they don’t want to specify units everywhere, so I think dimensional analysis with unit inference is a really nice feature. Keep up the good work.

Posted by Peter Aronsson    December 10, 2010 at 8:56 am
Oscar Chavez

A trivial question: where should I save Mathematica packages so that Mathematica can find them? I’m using Mac OS 10.6 and I saved this package in ~/Library/Mathematica/Packages and Mathematica says it can find it (“$Failed”).

Posted by Oscar Chavez    December 10, 2010 at 10:41 am
Morton Goldberg

I downloaded the AutomaticUnits zip file and installed it as a Mathematica application on my system. It seems to work as advertised. Thank you very much for making this package available to Mathematica users.

One problem has surfaced with the installation. Documentation for automatic units topics appear in the Documentation Center when I search, but I can’t open any of the references. For example, if I search on “UnitSet”, I get hits for UnitSet, $DefaultUnitSet, Automatic unit conversion, Convert, Working with units, and Unit. However, when I click on any of these, I get an error dialog. Say I click on UnitSet, then Mathematica message window reports:

Documentation`HelpLookupPacletURI::link: Could not resolve paclet URL paclet:AutomaticUnits/ref/UnitSet to a document.

Is there anything I can do to fix this?

Posted by Morton Goldberg    December 10, 2010 at 10:43 am
Jon McLoone

@Brian Geyer
You can explicitly request a conversion with
Convert[Newton/Kilogram, Meter/Second^2]

More automatically, you can create your own UnitSet with that unit listed in it eg
UnitSet["MyUnits"]=Append[UnitSet["SI"],Meter/Second^2]
The Convert[...,"MyUnits"] will use that when appropriate.

Then if you set
$DefaultUnitSet=”MyUnits”
It will use that unit when forced to change units. eg
Newton/Kilogram+PoundForce/Pound

Posted by Jon McLoone    December 10, 2010 at 11:06 am
Jon McLoone

@Oscar
Unzip the file to get the AutomaticUnits folder that it contains and place it in one of the locations listed by evaluating $Path

On Windows 7 my preferred location is
“C:\\Users\\jonm\\AppData\\Roaming\\Mathematica\\Autoload”

Posted by Jon McLoone    December 10, 2010 at 11:57 am
Jon McLoone

@Morton Goldberg
This is related to the Paclet system failing to register the various PacletInfo.m files or their relative locations has changed.

1) Make sure that the contents of the AutomaticUnits zip file are all in the same relative positions.
2) If you have installed other Paclet extensions, make sure there is not a faulty one interrupting registration by temporarily removing them (and any PacletInfo.m files that don’t belong.)

If it doesn’t sound like any of that applies to you, then give our technical support guys a call and they can talk you through the problem.

Posted by Jon McLoone    December 10, 2010 at 12:09 pm
Syd Geraghty

Thanks very much for this package Jon and the very informative blog article.

This once again proves the value of the consistent architecture of Mathematica and the (relative) ease and power of it’s user extensibility.

Posted by Syd Geraghty    December 10, 2010 at 4:02 pm
Dudley Burns

This is very good but why hasn’t this been part of Mma for years? I’ve been using another product for this type of work. I know of two products that have this built in. Why is it that Mma is always playing catch up with features that already exists elsewhere?

Posted by Dudley Burns    December 10, 2010 at 6:17 pm
morris pearl

Hello,

This is really cool. It’s both useful in and of itself, and as an example of how to integrate something into the existing Mathematica framework.

Thank you for sharing it.

I was just wondering, when you are developing a large package like this, do you generally use the notebook interface all of the time, or do you edit the .m files and re-evaluate the cells which load them each time you want to make a change and test it?

Please feel free to direct me to anything published on the testing and debugging workflow (I haven’t found very much in the documentation).

Morris

Posted by morris pearl    December 12, 2010 at 9:18 am
Drago Ganic

Dear John,
Excellent work! Will this be the replacement for Units?

I miss some two things to make it perfect (for business use):-)
One is date arithmetic, the other is currency arithmetic.

Ad1) Date arithemtic
——————————–
DatePlus and DateDifference should be overloaded to include “time periods” (like 10 Day, 1 Month etc.). In my opinion we need a date type Date[] for “time points”, so we could i.e. use Subtract instead of DateDifference for d1 – d2 to get “time periods” as result (e.g. 25 Days).
Also, 1 Week + 2 Day should not (only) result in Seconds. It would be nice to have a “set of units” as a single result (e.g. {Year, Day} to print as: n Year + m Month).

Ad2) Currency arithmetic
————————————–
Are there plans to include the Money dimension, like in W|A? I mean not only to calculate within one currency like 100 USD + 25 USCents, but to calculate between currencies like 30 USD + 10 EUR in MMA, not only W|A.

All of this could/should be used in the new v8 Finance functions.

Greetings from Croatia,
Drago

Posted by Drago Ganic    December 13, 2010 at 5:31 am
Jon McLoone

@ Morris
Most of the work was done in the Wolfram Workbench
http://www.wolfram.com/products/workbench/
It automatically reloads the package as you save changes allowing you to test them in the notebook immediately. Though most of the testing I did was via the automatic test suites feature of Workbench, It is very reassuring to make an important change (eg Plus or Times) and immediately see that 1000 tests have not broken.

Posted by Jon McLoone    December 13, 2010 at 9:11 am
Jon McLoone

@ Drago Ganic
1) I didn’t really consider the mixed return units n Year+ m Month (it is the same issue wanting a length in feet and inches. You would need a function to return the mixed units as a list not a sum since 1 Foot+2 Inch is designed to resolve automatically to 14 Inch.
eg
ToMixedUnits[1 Meter, {Foot,Inch}]->{3 Foot, 3.3 Inch}
I might implement that in a future update.
2) There are no pre-defined dimensions, so you can use it for money right now. Do
DeclareUnit["USD"];
DeclareUnit["Euro",1.33 USD];
DelcareUnit["GBP",1.58 USD];
Then
Euro+GBP-> 2.91 USD
Convert[Euro, GBP]->0.84 GBP
Of course, you will need to change the values in your definitions daily, so probably would not want to hard-code the values like this example, but define them dynamically with calls to the new WolframAlpha command, or FinancialData.

Posted by Jon McLoone    December 13, 2010 at 9:24 am
Vincent

Very nice package. I’ve been using a similar approach though reduced to only “my” units implemented in a more ad hoc way.

I’ve been wondering if there was a way to have the syntax highlighter recognize certain symbols in different colors, such that you could more easily distinguish the “units-symbols” from the other symbols in input? For example highligting Meter in bronw instead of black as it does for Plot.

Posted by Vincent    December 13, 2010 at 11:23 am
Jon McLoone

@Vincent
For output that is easy. Just put style information in the MakeBoxes definitions. In TraditionalForm, I used that to put the units in italics with tooltips.

For input, the closest you can get is
SyntaxInformation
Which lets you decide when the built-in syntax coloring applies to your functions.

Posted by Jon McLoone    December 13, 2010 at 11:40 am
Catya

Same problem with “VectorAnalisys package”:

to sum a vector in cartesian coordinates and a vector in spherical coordinates return always a vector!

Posted by Catya    December 14, 2010 at 12:09 am
Thor

The package doesn’t seem to work properly with values contained in a list. In the following formula, where d is a list out of two components, the units in the output list are not converted:

vmean = (Rey * nu)/(rho*d)

{0.00133333 Pascal Second Meter^2 Kilogram^-1,0.00133333 Pascal Second Meter^2 Kilogram^-1}

Is this a bug or a feature :D ?
And how to work around.

Thanks a lot.

Thor

Posted by Thor    December 14, 2010 at 10:12 am
Jon McLoone

Division and Power do not automatically trigger a simplification except in the case of direct cancellation. Otherwise it would be impossible for you to use Pascal Second Meter^2/Kilogram should you wish to. Should you add it (for example) to another velocity (in this case) the unit would be converted. You can force it out of this unit with Convert[%,"SI"] or Convert[%,"Imperial"] etc

SimplifyUnits should clean it up too, but there is a rather careless bug which I will fix shortly, In the meantime you apply the fix with
SimplifyUnits[AutomaticUnits`private`a_] :=
AutomaticUnits`private`a /.
AutomaticUnits`private`expr_Unit :>
SimplifyUnits[AutomaticUnits`private`expr]

Posted by Jon McLoone    December 14, 2010 at 10:45 am
VincentH

It is incorrect to put the units in italics (in TraditionalForm). According to international standards such as the SI, the unit symbols should be upright. Variables and quantity symbols are in italic type.

Posted by VincentH    December 14, 2010 at 11:15 am
cipri

BUGGGGGG.
I think i found a bug.

try this code

x = 4.5323 Millimeter;
y = 23.221 Micrometer;
x + y // SimplifyUnits
x = NumberForm[x, 3];
y = NumberForm[y, 3];
x + y // SimplifyUnits

Posted by cipri    December 14, 2010 at 5:16 pm
Jon McLoone

@VincentH
I have corrected this for a new version coming shortly.

Posted by Jon McLoone    December 15, 2010 at 4:39 am
    Faith

    Hi Jon,
    Thanks for the package, it did help most of my units problem Ive been dealing with. However there were a few bugs it must’ve missed.

    Bugs for example :
    Kilo Meter/ (Giga Meter)^2
    Kilo Parsec/ Giga Meter)

    I notice you mentioned you’re fixing the bug in one of the post, I wonder have you posted it up somewhere?

    Posted by Faith    May 23, 2012 at 1:50 pm
Jon McLoone

@cipri
Not a “bug” but a consequence of the design of NumberForm (and all the *Form commands for that matter). One could argue about whether it is a good design, but that is a different question!

You get the same effect with
NumberForm[4, 3] + NumberForm[2, 3]
The reason is that the Head NumberForm remains invisibly wrapped around each of the quantities, and there are no rules for the behaviour of NumberForm under Plus (or any other function).

Generally you want to use any *Form command as the very last step for display, and not introduce them early into the computation.

Posted by Jon McLoone    December 15, 2010 at 4:44 am
Cottin

Hello,
This package is now essential to my use of Mathematica. I added the unit “RPM” (revolution per minute) in “alternative.m” and maybe you should add it in the next version.
However, when I work with dimensionless numbers (in fluid mechanics for instance), Mathematica doesn’t simplify the result and I have to use SimplifyUnits to see that in fact the number is dimensionless.
Could you make it automatic in the next version of this package?
Thank you again for this package!
C Cottin

Posted by Cottin    December 19, 2010 at 4:19 am
Cottin

An other problem I encountered
I define
omega= 130 RPM
r=1 Meter
V=omega*r is in m/s so no problem so far!
Now if V2=V Tan[Beta]
and Beta=30 Degree
I have V2 in Meter*Radian/Second…
Could you look at it for the next version!
Keep up the good work!!!
C Cottin

Posted by Cottin    December 19, 2010 at 12:08 pm
Cottin

I defined RMP=2 PI Unit["Radian"]/60 Unit["Second"]

Posted by Cottin    December 19, 2010 at 12:09 pm
Jon McLoone

@Cottin
I have added RPM to a future version.

In my design I have taken the slightly controversial decision that angle is a dimension rather than a dimensionless multiplier. This means that you need to divide through by the appropriate angle to make the
velocity = angular velocity x length
formula work. But doing so should make it more robust to angular velocity being provided in something other than RPM and avoids consistency confusion between things like radians and steradians.

Posted by Jon McLoone    December 20, 2010 at 9:56 am
Cottin

Thank you for your answer!
I understand your choice so I will divide the result by Radian.
I have now a problem with Plot!
I defined a function:
Hi[x_] := 8 (U2 (U2 – (0.88 x)/(2 \[Pi] r2 b2 Tan[\[Beta]2])))/g
This function works without problem:
Convert[Hi[0 Liter/Second], Meter]
yields
3220.54 Meter.
But when I type:
Plot[Hi[x], {x , 0 Liter/Second, 1000 Liter/Second}]
it yields

Plot::plln: Limiting value 0 l/s / Unit(liter/second) in {AutomaticUnits`private`newvar$1898,0 l/s / Unit(liter/second),1000 l/s / Unit(liter/second)} is not a machine-sized real number.

Have you got any idea to make it work because I am really stuck… I already tried (more simple) examples with plots (with units) and it worked perfectly.(I appreciated the plot label, congratulations!)

Thanks again
Regards

Posted by Cottin    December 21, 2010 at 5:23 pm
B.S.

How do you install this package? I have Mathematica 8 on a Mac system.

Thanks

Posted by B.S.    December 28, 2010 at 7:58 pm
Steffen

I have a problem with the Round function. While rounding to integers works with Round[x], I cannot round to real numbers with a specific number of digits, e.g. Round[x,0.1]. Is there a solution to this problem?

Posted by Steffen    January 6, 2011 at 2:42 pm
Pawel

Very nice package. Unfortunately it’s not compatible with
another package PhysicalConstans (is it possible to make
them work together),
Besides this I found a small bug in Planck units –
PlancTemperature has dimension of Meter after converting
to SI units.
Regards

Posted by Pawel    January 8, 2011 at 6:31 am
Jon McLoone

@Pawel
My pacakge was designed to be an alternative to the built in units, and unfortunately PhysicalConstants explicitly loads the built in package.

You can make AutomaticUnits mostly play nicely with PhysicalConstants by editing the first non-comment line of
$TopDirectory\AddOns\Packages\PhysicalConstants\PhysicalConstants.m
From
BeginPackage["PhysicalConstants`", "Units`"]
to
BeginPackage["PhysicalConstants`", "AutomaticUnits`"]

It generates several errors for several physical constants which I have added as units to my package, but otherwise works fine. (Though I have done only very basic testing).

I am just about to submit an update to the package which will fix the Planck bug along with all the other fixes and suggestions that appear in these blog comments.

Posted by Jon McLoone    January 10, 2011 at 12:14 pm
Darren

I though the SI unit was Metre ?

A meter is something you measure with. ( Had this beaten into me by my mechanics lecturer many years ago.)

Being pedantic ;-)

Posted by Darren    January 11, 2011 at 10:02 am
Maccara

@Darren: “Only” outside US. But yes, otherwise correct.

Personally, I don’t care (I’m not American or English), as long as it is consistent.

Meter is used in original Units pkg etc, so same should be used here – you can define a new unit/alias if you really want to.

Posted by Maccara    January 12, 2011 at 4:11 pm
Steffen

I found a bug with the temperature conversion:

20 Celsius + 5 Kelvin should be 25 Celsius.
Instead, AutomaticUnits calculates 25 Kelvin.

Posted by Steffen    January 17, 2011 at 11:00 am
Jon McLoone

@Steffan
Plus in Mathematica is orderless and so 20C+5K is the same as 5K+20C. The choice of unit when mixed units are added is governed by the value of $DefaultUnitSet which is set to “SI” by default. And the SI unit of temperature is Kelvin. You can change either the value of $DefaultUnitSet to a custom UnitSet which has Celsius as a member rather than Kelvin to get the behaviour you want.

Jon

Posted by Jon McLoone    January 17, 2011 at 1:24 pm
Steffen

You should consider that Kelvin is not only the unit of the absolute temperature, but also the unit of a temperature difference. So if I add a 5K temperature difference to 20Celsius, the result should be 25Celsius.
This is the standard nomenclature in any thermodynamic calculation. It would be a problem if AutomaticUnits cannot deal with it (e.g. Mathcad can…).

Posted by Steffen    January 18, 2011 at 2:56 pm
Steffen

I think the bug is already in the standard Units package. Try “SI[20 Celsius]“. Mathematica calculates “20 Kelvin” as a result, whereby “293.15 Kelvin” is correct. “SI[0Celsius]” even yields “0″ without unit, and “SI[-5 Celsius]” yields “-5 Kelvin”…

Posted by Steffen    January 20, 2011 at 2:47 am
Jon McLoone

There is a basic conflict of meaning for the units with non-zero origin. While the natural interpretation of 0C is 273K, when you look at, for example temperature gradiate 1 C/Meter is probably understood to be the same as 1 K/Meter. Both the original Units package and my update deal with the by providing two convertions. Most (Convert, SI, etc) assume only scale conversion 1K=1C and the command ConvertTemperature is provided to respect the non-zero origins of some temperature units. There are probably other designs that could work, but this felt more natural to me than attempting to automatically spot special cases giving conversion behaviour that depended on the unit.

Posted by Jon McLoone    January 20, 2011 at 10:15 am
Steffen

I think Mathematica should treat the units physically correct, i.e. 0C is 273.15K. A temperature gradient is always expressed in K/m, C/m should yield an error. In the same way, 0C + 0C should yield an error, as it has no physical meaning (the result in Mathcad is 273.15C!). Probably, some “hard” programming is inevitable in this case.

Posted by Steffen    January 21, 2011 at 8:15 am
Jon McLoone

The updated version of the package is now available at
http://library.wolfram.com/infocenter/MathSource/7655
It addresses, most of the issues discussed in the comments.
Drago Ganic’s suggestion is implemented as a command UnitList eg
In[2]:= UnitList[2. Kilometer, {Mile, Yard, Foot, Inch}]

Out[2]= {Mile, 427 Yard, 8.15 Inch}

Posted by Jon McLoone    January 21, 2011 at 12:17 pm
Joe

Is it possible to specify the in what units you want the result? For example, let’s say I added had;

6 Inch + 20 Feet

and wanted the output to be in feet.

Posted by Joe    January 25, 2011 at 9:12 pm
Jon McLoone

The easiest way is to change the defaults is to evaluate
$DefaultUnitSet = “Imperial”
All mixed unit calculations will then default to Imperial units, Foot being the Imperial length.

For a list of other pre-defined defaults choices evaluate
UnitSet[]

I should probably have mentioned in the blog piece that the package comes with documentation. Search for AutomaticUnits in the Documentation Center to get to the guide page.

Posted by Jon McLoone    January 26, 2011 at 9:06 am
Jon McLoone

…you can also change the defaults using the palette that comes with the package. You can find that on the Palettes menu once the package is installed.

I should correct the last comment. Using “Imperial” will choose the most appropriate unit out of the set, which is only Foot for lengths around a Foot, it will switch to Yard for larger lengths and Inch for smaller. To ensure Foot is always used do
UnitSet["MySet"]={Foot, Second, … the other dimensions…};
$DefaultUnitSet=”MySet”

Posted by Jon McLoone    January 26, 2011 at 9:44 am
Sam McCandlish

Hey all – I have a minor problem if I load the PhysicalConstants package and this awesome AutomaticUnits package. I get errors that BohrRadius, EarthMass, EarthRadius, and PlanckMass are redefined. Is there an easy remedy for this?

Posted by Sam McCandlish    February 14, 2011 at 9:32 pm
Jon McLoone

@Sam McCandlish
See my response to Pawel further up the comments.

Posted by Jon McLoone    February 15, 2011 at 10:18 am
B.S.

Hi, When I use the Solve command and I have variables assigned with units, a=2Feet for example, I never seem to get the results I expect. I was wondering if you had any suggestions?

Thanks

Posted by B.S.    February 27, 2011 at 5:23 pm
Alex

This is a fantastic package! It really helps in validating my equations when I see the right units coming out.

I wonder if you have looked at the open source DesignerUnits Mathematica package. I have not used it, but it appears to have the same goal. (http://designerunits.com/overview)

I am using AutomaticUnits 1.0.1, and I believe I have found a hole in the package’s definition for either Joule or Kilogram.
Try this input:
BoltzmannConstant = Unit[1.3806504`*^-23, Joule/Kelvin]
v[T_, m_] := ((8*BoltzmannConstant*T)/(Pi*m))^(1/2)
SimplifyUnits[v[300 Kelvin, 6.64648*10^-27 Kilogram ]]
I would expect an output of Meter/Second. Instead I get (Joule^1/2)/(Kilogram^1/2). Indeed these units can be simplified to Meter/Second, but AutomaticUnits does not see this.

Thanks

Posted by Alex    April 24, 2011 at 2:42 pm
Jon McLoone

@Alex
For SimplifyUnits, I attempted to minimize the number of unit names only. As such (Joule^1/2)/(Kilogram^1/2) is considered as simple as Meter/Second. Your example is good motivation for considering exponents as well, and perhaps also giving preference to base units. I may add that to a future version.

Posted by Jon McLoone    May 3, 2011 at 5:48 am
Arun

Hi,
First, thanks for this excellent package. When I try to use units like Joule/Mole (common in Chemistry), the package automatically provides the answer in Joule. Is there a way to stop this conversion from happening? I tried to multiply this by the Avogadro Number, however in the definition, there is per Mole and whatever I define as Avogadro Number becomes 1.0. Is there a way to work around this?
Thanks,

Posted by Arun    September 16, 2011 at 4:39 am
Jon McLoone

The package defines Mole to be dimensionless, and so just a number. You can declare your own units
eg

DeclareUnit["Atom"]
DeclareUnit["MoleUnit", 6.0221415*^23 Atom]

If you first use
Remove[Mole]
Then you can re-define the name
DeclareUnit["Mole", 6.0221415*^23 Atom]

Posted by Jon McLoone    September 16, 2011 at 12:13 pm
Wade

I like AutomaticUnits, but had to use PhysicalConstants too. As a work-around hack to make them play nicely, I temporarily added a definition to the BeginPackage command:

(*Force PhysicalConstants to use the correct units package.*)
Unprotect[BeginPackage];
BeginPackage["PhysicalConstants`", "Units`"] =
BeginPackage["PhysicalConstants`", "AutomaticUnits`"];
< 1, Meter -> 1, Second -> 1, Kelvin -> 1,
Kilogram -> 1};
Then when I have to do some numerical integration, I use
var /. noUnits to get a dimensionless quantity that can be integrated (I have to figure out the resulting units myself, but that’s okay).
Is there an existing list that I could use already, or a function that can do the replacement for me?

Finally, AutomaticUnits takes a fairly long time to load (a couple of seconds). Would removing/disabling some of the more esoteric units help speed things up? How would I do this?

Posted by Wade    September 27, 2011 at 5:50 am
Wade

My apologies, it looks like part of my last comment was eaten (treating something like html tags maybe?). I’ll try again:

Here is the fix:
(*Force PhysicalConstants to use the correct units package.*)
Unprotect[BeginPackage];
BeginPackage["PhysicalConstants`", "Units`"] =
BeginPackage["PhysicalConstants`", "AutomaticUnits`"];
< 1, Meter -> 1, Second -> 1, Kelvin -> 1,
Kilogram -> 1};

Posted by Wade    September 27, 2011 at 5:53 am
Wade

Okay, did it again. I’ll just put the fix on pastebin:
http://pastebin.com/E1CSserR

You can probably guess what I was doing with the constants replacement rule.

Posted by Wade    September 27, 2011 at 5:55 am
Jon McLoone

@Wade
My comment to Pawel, further up the comments, addresses the Physical Constants issue.

Faster loading you can remove all of the Get statements near the bottom of AutomaticUnits.m
You can load each of those later, if you need them. Be aware that there are some dependencies, so best to leave the first 5-10 even if you think you don’t need them.

I did do some optimization on the initialization of units, so loading them later will take more total time than loading them at the start.

For super fast, use DumpSave to make an .mx file version of the package.

Posted by Jon McLoone    September 27, 2011 at 12:12 pm
Bob Rasmussen

Thanks for providing this package. Something like it has been needed for a long time.

I’d like to note a couple documentation issues. Tutorial links to “AutomaticUnits Package” or “Units Package” in documentation for this package produce the following error:

Documentation`HelpLookupPacletURI::link:
Could not resolve paclet URL paclet:AutomaticUnits/tutorial/Units to a document.

Also, one of the items found when searching for “AutomaticUnits” is “Automatic unit conversion (Automatic Units Guide)”, but this link produces the following error:

Documentation`HelpLookupPacletURI::link:
Could not resolve paclet URL paclet:AutomaticUnits/guide/AutomaticUnitConversion to a document.

I think these must be errors in the documentation files, because there are no files named “Units” of “AutomaticUnitConversion” in the AutomaticUnits folder or subfolders. However, there are files named “WorkingWithUnits” and “AutomaticUnits”, which seem to be the ones intended, respectively.

Posted by Bob Rasmussen    October 1, 2011 at 7:36 pm
John

Thank you so much for this awesome package

Posted by John    October 4, 2011 at 8:28 am
Bob Gosselin

I can’t seem to get it to work with Manipulate. Has anyone had any success using parameters with units using Manipulate. It generates an error because it seems to be trying to add a dimensionless number to one with units.

Posted by Bob Gosselin    October 20, 2011 at 7:00 pm
Michelle M

Is there a way to have multiple sets of data with units on the same plot? I appreciate that it works for a single set but I can’t seem to get it to work with more.

Modified example from the post:

ListLinePlot[{{300 Inch, 10 Meter, 10 Yard}, {200 Inch, 8 Meter, 8 Yard}}]

Posted by Michelle M    October 31, 2011 at 4:17 pm
Jon McLoone

@ Michelle M
At the moment, it only supports the single data set. You can get what you want with

Show[ListLinePlot[{300 Inch, 10 Meter, 10 Yard}],
ListLinePlot[{200 Inch, 8 Meter, 8 Yard}]]

However, that will only work if both data sets covert naturally to the same unit.

Posted by Jon McLoone    November 2, 2011 at 5:45 am
Michelle M

It gets the job done, that helps a lot… Thank you

Posted by Michelle M    November 7, 2011 at 4:44 pm
Jens Nieswandt

Thank you for this nice tool!
The Unit tool work fine and I have integrated the palette, this work also fine.
But i have a problem with the help document…
Documation Center can find the main document without any problems, when I click to a link in the main document I receive a error message…
“The file you tried to open was not found or could not be opened.”

“Documentation`HelpLookupPacletURI::link: Could not resolve paclet URL paclet:AutomaticUnits/ref/UnitSet to a document.”
but I don’t change any path in the automatic unit folder…
I hope, you can help me….

Thank you

Posted by Jens Nieswandt    November 15, 2011 at 5:23 am
Jon McLoone

@Jens Nieswandt – see the comment that I wrote to Morton Goldberg further up the comments.

Posted by Jon McLoone    November 15, 2011 at 12:01 pm
Jon McLoone

For others that have problems installing the package:
Ensure that it is placed in the Applications folder of $UserAddOnsDirectory, and not inside $InstallationDirectory

Posted by Jon McLoone    November 18, 2011 at 12:53 pm
Michelle M

Pertaining to my comment a few weeks back, is there a way to add a legend when using Show[] to plot with units? So say measurement1={300 Inch, 10 Meter, 10 Yard}; and measurement2={200 Inch, 8 Meter, 8 Yard} and I want those names to appear on my ListLinePlot

Posted by Michelle M    November 22, 2011 at 8:33 am
Jon McLoone

@Michelle M

I’m afraid that I didn’t add support for Tooltips or PlotLegend. So at the moment, you could use the PlotLegend package but you would have to manually calculate what to place in the legend.

Posted by Jon McLoone    November 28, 2011 at 12:00 pm
Kevin Ausman

I love this package, though it still seems to have some bugs. For example, using the original Units package, the following works:

\[Psi][r_] := Sqrt[1/(\[Pi] Subscript[a, 0]^3)] E^(-r/Subscript[a, 0])
\!\(
\*SubsuperscriptBox[\(\[Integral]\), \(0\), \(2\ \[Pi]\)]\(
\*SubsuperscriptBox[\(\[Integral]\), \(0\), \(\[Pi]\)]\(
\*SubsuperscriptBox[\(\[Integral]\), \(0\ Pico\ Meter\), \(1.0\ Pico\ \
Meter\)]
\*SuperscriptBox[\(\[Psi][r]\), \(2\)]
\*SuperscriptBox[\(r\), \(2\)] Sin[\[Theta]] \[DifferentialD]r\ \
\[DifferentialD]\[Theta]\ \[DifferentialD]\[Phi]\)\)\)

But doing it with the AutomaticUnits package incorrectly gives a complex number as a result.

Posted by Kevin Ausman    January 6, 2012 at 12:35 pm
Kevin Ausman

Sorry, I left out the following statement in my earlier code:

Subscript[a, 0] = 53 Pico Meter;

Posted by Kevin Ausman    January 6, 2012 at 12:37 pm
Michelle M

Is there a way to use FindRoot with units? I’m solving the radiation equation with a Temp^4. Solve takes too long/doesn’t finish the system of equations solution. It gives the error that {T,10Celsius} is not a number or array of numbers.

Is the only way to resolve this to divide by the units for each parameter? Thank you

Posted by Michelle M    January 20, 2012 at 1:12 pm
Jon McLoone

FindRoot is not ‘units aware’ in my package, which makes the best option to discard the units completely with something like
FindRoot[DropUnits[x Meter], {x, 3}]
If I do another update to the package, I will try and add support for this function.

Posted by Jon McLoone    January 23, 2012 at 8:25 am
Paul McHale

Could you post a small set of instructions on installation? If it is included in the package, I have overlooked it.

Posted by Paul McHale    January 23, 2012 at 9:24 am
Jon McLoone

To install the package follow these steps
1) Download the .zip file from
http://library.wolfram.com/infocenter/MathSource/7655/
2) Launch Mathematica and go the File menu and select “Install”
3) In the dialog select “Type of Item”=”Application”, “Source”=”From file” and locate the downloaded zip file.
4) Click OK
5) Evaluate
<<AutomaticUnits`
to run load the application.

Posted by Jon McLoone    January 27, 2012 at 6:06 am
    Jon McLoone

    I did not treat dimensionless units as units in this package, except for angles. Doing so may give you the functionality you want. Try commenting out the line
    Mole = 6.0221367*10.^23
    And add in to the SI.m declarations
    DeclareUnit["Mole", Unit[ 6.0221367*10.^23,"Molecule"]
    Instead of “Molecule” one could do this more generally and use “Dimensionless”, eg if you did the same with Dozen, BakersDozen etc the conversions like
    Convert[3 Dozen, BakersDozen] would work- which they don’t now. But you would lose the ability to do
    Dozen+10
    That would have to be entered
    Dozen+Unit[10,"Dimensionless"]
    I never thought through a good design for that, so left them as pure numbers.

    Posted by Jon McLoone    May 9, 2012 at 9:24 am
        Jon McLoone

        Some feedback, I got from the Wolfram Alpha team is that Mole is not dimensionless in the official SI, but is a base dimension itself. As such ElectronVolt should not be compatible with Kilojoule
        / Mole

        There is apparently discussion of adding another quanity unit – tentatively called the “Uno” to SI to deal with this.

        Posted by Jon McLoone    May 18, 2012 at 7:37 am
Richard Phillips

It would still be nice to handle units more like MathCad does. There, I can take any *output* result, append it with millimetre, metre, kilometre, etc. and the numrerical result is changed accordingly. Saves a lot of the Convert, Reduce, … functions that do nothing but clutter up an otherwise readable worksheet.

Posted by Richard Phillips    September 16, 2012 at 6:55 pm
    Jon McLoone

    You can append a unit, after the event using this package eg
    x=RandomReal[]
    returns a number, you can then just use
    x Meter
    as a unit based quantity.

    If however, you are suggesting that editing the result should automatically change the stored value, then I would have to disagree that that is a good idea. That would hide the process by which the answer was arrived at and reduce reproducibility. It is for this reason that editing output changes it into a new input cell – so that you can see that it there was manual intervention.

    Posted by Jon McLoone    September 17, 2012 at 10:55 am
Jessie Petricka

Thank you so much for this package. When using it for the first time I, like a couple of others above, wanted the units to stand out. Thank you for pointing us to the makeboxes declarations to do this change. For those of us that do not do serious coding, I might take a day or more to figure out exactly what to do. Since I have no qualms about italics, and I almost exclusively use standardform, I would like to point out to others the change you can do to make this happen. I commented out the line,

MakeBoxes[UnitString[x_String], form_] := x;

in favor of

MakeBoxes[UnitString[x_String], form_] := StyleBox[x/.$TraditionalUnitNameRules,ShowAutoStyles -> False,FontSlant->Italic,FontColor->Purple];

OK, the color purple might be overboard, but I like it. As you notice I also like the traditional form unit names so I make the replacement even for standardform. It changes the palette buttons as well, but as a physicist I’m OK with that.

For Richard who wants more MathCad like functionality (and ridding myself of this program is why I came here in the first place), I wholeheartedly agree that the readability can suffer when adding unit handling. But I agree with Jon that the base paradigm of Mathematica over MathCad is the way to go. I offer this tip, make an input alias for an operator without meaning in Mathematica. I actually put

x_ \[Congruent] y_:=Convert[x,y]

in the package so that it loads at the same time. Now conversions are accomplished in a postfix way, improving readability, with only the use of two keys (in the case of congruent, esc === esc)!

For Jon, perhaps a checkbox in the palette to do the italics and traditional form output would appeal to more than only me. Also, and this may be addressed above, when I have exactly 1 of a quantity (1 Meter) I seem to lose the interactive output ability to click and change units.

Thanks again for this wonderful package.

Posted by Jessie Petricka    September 20, 2012 at 8:53 am
Jon McLoone

This package is now largely obsolete as similar functionality is included in Mathematica 9.
http://www.wolfram.com/mathematica/new-in-9/units/

It has also become incompatible with 9 due to a name conflict, though there is an easy fix: Open the file AutomaticUnits.m and do a search and replace on all occurrences of “CompatibleUnitQ” change it to a different word, I suggest “DimensionCompatibleUnitQ”. Replace the file with the modified version.

Posted by Jon McLoone    December 3, 2012 at 10:31 am
    Jon McLoone

    Because Degree was a pre-existing symbol, my package declares its dimensioned value using the option CreateSymbol->False, to prevent existing code which uses the symbol being broken. This means that you must enter degrees using the InputForm version IE
    Unit[9,"Degree"]+9ArcMinute
    There are several other units that have this type of name conflict eg Circle, Span, Last, Drop, Gamma, Gray etc

    Posted by Jon McLoone    December 19, 2012 at 4:33 am


Leave a comment

Loading...

Or continue as a guest (your comment will be held for moderation):