## 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…

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:

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

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!

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.

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.

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.

Here is 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:

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"] 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.

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

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.

`SimplifyUnits` will try to find simpler equivalents to composite units.

Most operators, for which unit-based quantities make sense, 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`.

Or 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`.

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

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

You can convert quantities to specific units.

Or to the most appropriate unit from a list.

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

The available named unit sets is given by:

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

You can declare new units.

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

But their different origins are respected using `ConvertTemperature`.

## 87 Comments

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

Hi Morton,

You can go to http://library.wolfram.com/infocenter/MathSource/7655/ and download the notebook. The link is also near the beginning of the post for your convenience.

Thank you!

Wolfram Blog Team

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.

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!

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?

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.

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”).

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?

@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

@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”

@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.

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.

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?

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

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

@ 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.

@ 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.

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.

@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.

Same problem with “VectorAnalisys package”:

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

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

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]

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.

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

@VincentH

I have corrected this for a new version coming shortly.

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?

@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.

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

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

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

@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.

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

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

Thanks

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?

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

@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.

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 ;-)

@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.

I found a bug with the temperature conversion:

20 Celsius + 5 Kelvin should be 25 Celsius.

Instead, AutomaticUnits calculates 25 Kelvin.

@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

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…).

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”…

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.

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.

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}

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.

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.

…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”

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?

@Sam McCandlish

See my response to Pawel further up the comments.

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

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

@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.

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,

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]

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?

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};

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.

@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.

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.

Thank you so much for this awesome package

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.

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}}]

@ 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.

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

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

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

For others that have problems installing the package:

Ensure that it is placed in the Applications folder of $UserAddOnsDirectory, and not inside $InstallationDirectory

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

@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.

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.

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

Subscript[a, 0] = 53 Pico Meter;

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

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.

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

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.

Jon,

Thanks for a very useful package.

I have one set of problems with the package. AvogadroConstant, MolarGasConstant, FaradayConstant, and MolarVolume all have the wrong value. Specifically, the value given by the package is the correct value divided by Avogadro’s Number.

For example, AvogadroConstant has the value of 1 rather than approximately 6.022×10^23

In[6]:= AvogadroConstant

Out[6]= 1.

Apparently these errors all stem from the definition of Mole in the AutomaticUnits package

line 67: Percent = 1/100;Gross = 144;Dozen = 12; BakersDozen = 13;

Mole = 6.0221367*10.^23;Yotta = 10^24;

line 71: Gross=144; Dozen=12; BakersDozen=13; Mole=6.0221415*^23

A possibly related problem is that expressions like Convert[ElectronVolt, Kilo Joule / Mole] do not work correctly with AutomaticUnits

With the old units package

In[8]:= Convert[ElectronVolt, Kilo Joule / Mole]

Out[8]= (96.4853 Joule Kilo)/Mole

With automatic units

In[8]:= Convert[ElectronVolt, Kilo Joule / Mole]

Out[8]= AutomaticUnits`Unit[1.602176487*^-19, "Joule"]

Can you suggest a fix?

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.

Thanks for the quick reply and suggestions.

Removing the lines with Mole=6.022*10^23 fixes the problem of AvogadroConstant etc. having the wrong value.

However, the idea of declaring Mole to be a unit of type “Dimensionless” breaks converstions to units like kJ / Mole (Kilo Joule / Mole). For example Convert (ElectronVolt, Kilo Joule / Mole) now fails because the units are incompatible. They both should be units of energy but with the definition of Mole as Dimensionless, Kilo Joule / Mole is of type energy / dimentionless.

It seems what is needed is the concept of a real dimensionless unit that would be a type of unit that doesn’t change the type of the unit. I thought a little about modifying the CompatibleUnitQ function so that “Dimensionless” was treated as a special case. I suspect you might have better ideas about how to do the design and look forward to your comment.

By the way, Molar specific units like kJ / mole or kCal / mole are commonly used in physical chemistry. I hope you can find a design that will accomodate these commonly used units.

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.

Interesting and subtle points. In SI

1. The mole is the amount of substance of a system which contains as many elementary entities as there are atoms in 0.012 kilogram of carbon 12; its symbol is “mol.”

2. When the mole is used, the elementary entities must be specified and may be atoms, molecules, ions, electrons, other particles, or specified groups of such particles.

In chemistry molar equivalents are commonly used. For eV, 1 mole (Avogadro’s number) of charge passing through potential difference of 1 volt is 96.485 … kJ / mol. You might express this as 1 eV / particle = 96.485 … kJ/mol.

Conventional usage shortens this and says simplye 1 eV == 96.485… kJ / mol.

Note that the Mathematic units package follows this convention. It treats ElectronVolt to Kilo Joule / Mole as compatible units. It treats Mole like a multiplier (like Kilo)

In[1]:= << PhysicalConstants`

<< Units`

In[3]:= Convert[ElectronVolt, Kilo Joule / Mole]

Out[3]= (96.4853 Joule Kilo)/Mole

I also checked how mathcad handles this. It too the conventional usage. If I take the electron charge and multiply by 1 volt and Avogadro's number it converts to 96.465 kJ / mol.

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.

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.

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.

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.

Your package doesn’t work when I try to compute “9 Degree + 9 ArcMinute”. It works with “9 ArcSecond + 9 ArcMinute”

9 ArcSecond + 9 ArcMinute

Out[3]= AutomaticUnits`Unit[

Rational[183, 20], “ArcMinute”]

In[6]:= 9 Degree + 9 ArcMinute

During evaluation of In[6]:= Unit::incomp: Unit ArcMinute cannot be added to a number >>

Out[6]= 9 \[Degree] + AutomaticUnits`Unit[9, "ArcMinute"]

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