MathGroup Archive 2008

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Calculating with Units

  • To: mathgroup at smc.vnet.net
  • Subject: [mg94090] Re: [mg93997] Calculating with Units
  • From: Daniel Lichtblau <danl at wolfram.com>
  • Date: Thu, 4 Dec 2008 07:17:45 -0500 (EST)
  • References: <200812011202.HAA05923@smc.vnet.net> <493467F2.3020709@wolfram.com>

Nikolaus Rath wrote:
 > Hello,
 >
 > Until now, I have always defined my units manually in terms of
 > the 4 base units Kilogram, Meter, Coulomb and Second:
 >
 > Newton = Kg Meter / Second^2;
 > Joule = Newton Meter;
 > Henry = Weber / Ampere;
 > Weber = Volt Second;
 > etc.
 >
 > This allows me to evaluate expressions like
 >
 > B = (\[Mu] Ii)/(2 \[Pi] r);
 >
 > B /. { r -> 20 Meter, \[Mu] -> 4 \[Pi]  * 10^-7 Henry/Meter,
 >   Ii -> 2 Ampere}
 >
 > % / Tesla
 >
 > and directly see if the units in the final result are correct.
 >
 > But since all these units (and many more) are already defined in the
 > Mathematica Units package, I was wondering if there isn't a way to use
 > that package in the same way. Unfortunately, it doesn't seem to
 > simplify the units, i.e. when I enter
 >
 > (Ampere Henry)/(Meter Meter) // Simplify // SI
 >
 > I get the same expression back. What I would like to get is either
 > "Tesla" or "Kilo Gram / (Coulomb Second)".  Is there a way to
 > accomplish this?
 >
 >
 > Best,
 >
 >
 >    -Nikolaus
 > [...]

My first reply, in private email, was to the effect that GroebnerBasis 
and PolynomialReduce could be used. This was correct, but after further 
  prodding I realized it needs considerable elaboration.

In looking over some slides from a 2007 talk I realized I had more or 
less done this once before, and the fact that a similar question has 
appeared on MathGroup suggest that it is not a completely obscure thing 
to want. It might be almost completely obscure (ACO), but all the same 
I'm using this as an excuse to post a response.

We start with a list of units and a generating set of defining 
relations. I also use some one and two letter abbreviations for brevity.

units = {Farads, Ohms, Pascals, Watts, Webers, Teslas, Henries,
        Newtons, Joules, Volts, Amperes, Coulombs, Seconds,
        Kilograms, Meters};
{f, o, p, wa, we, t, h, n, j, v, a, c, s, k, m} = units;

relations = {f - (c^2*s^2)/(k*m^2), o - (k*m^2)/(c^2*s),
        p - k/(m*s^2), -((k*m^2)/s^3) + wa, -((k*m^2)/(c*s)) + we,
        -(k/(c*s)) + t, h - (k*m^2)/c^2, n - (k*m)/s^2,
        j - (k*m^2)/s^2, -((k*m^2)/(c*s^2)) + v, a - c/s};

Put each over a common denominator and extract the numerator. This gives 
polynomial (rather than rational function) relations. This will be 
important because Groebnerbasis and PolynomialReduce behave best when 
handling legitimate polynomial input.

polyrelations = Numerator[Together[relations]]

Here is a problem. We want to sensibly handle denominators. That is 
solved by creating the reciprocal variables and corresponding relations.

recipunits = Map[recip, units];
reciprels = Map[#*recip[#] - 1 &, units];
allrelations = Join[Numerator[Together[relations]], reciprels];
allvars = Flatten[Transpose[{recipunits, units}]];

Since the question involves representing units monomials in terms of a 
core set of charge, time, mass, and length (a typical scenario), we 
ordered those last. Also we ordered their corresponding reciprocals 
after other variables.

With all this we can compute a Groebner basis, using the ordered 
variables to define the (lexicographic) term order.

There is a catch here. The input defines what is called a toric ideal. 
GroebnerBasis has reasonably fast special case code for that. It also 
has code that attempts to recognize such input. But that recognition 
code is a bit simple and fails in this example. And the general case 
code is quite slow in this case (several minutes thus far, and still no 
joy). So we resort to an explicit invocation of the special case code.

gbt = GroebnerBasis`ToricGroebnerBasis[allrelations, allvars];

Now we look at the given example. I've pluralized the units to 
correspond with my version.

B = (\[Mu]*Ii)/(2*Pi*r);

B2 = B /.
  {r->20*Meters, \[Mu]->(4*Pi*(Henries/Meters))/10^7, Ii->2*Amperes}

Out[29]= (Amperes*Henries)/(50000000*Meters^2)

We want to show that B2/Teslas is dimensionless, that is, it is a 
numerical constant. We start by converting to an explicit polynomial. 
This is done by a replacement rule that changes units with negative 
exponents into their reciprocals, with corresponding positive exponents. 
We then use PolynomialReduce with respect to gbt (keeping the same 
variable ordering as from computing gbt). Finally we convert explicit 
reciprocal variables to units with negative exponents.

Last[PolynomialReduce[
   B2/Teslas /. (z_)^(n_Integer) /; n < 0 :> recip[z]^(-n),
   gbt, allvars]] /. recip[z_] -> 1/z

Out[33]//InputForm= 1/50000000

This did give a constant, as we wanted.

To see what are the "fundamental" units of B2, we could simply do

In[36]:= InputForm[ Last[PolynomialReduce[
          B2 /. (z_)^(n_Integer) /; n < 0 :> recip[z]^(-n),
          gbt, allvars]] /. recip[z_] -> 1/z]
Out[36]//InputForm= Kilograms/(50000000*Coulombs*Seconds)

This, and other methods, can can be used to rewrite units monomials in 
terms of equivalent ones that minimize total degree, or minimize the 
maximal degree of numerator vs denominator, or minimize the number of 
units that appears (possibly making the degree large in this scenario). 
The starting point for all methods of which I am aware is to augment 
with reciprocal variables and relations.

Daniel Lichtblau
Wolfram Research


  • Prev by Date: functions: compiled vs. uncompiled version
  • Next by Date: Re: Plotting Vector Fields in Mathematica 7
  • Previous by thread: Calculating with Units
  • Next by thread: Re: Calculating with Units