Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'm trying to take a formula, take it's integral which yields a formula with logarithms, and then directly plug in values with units and get an answer. However if the units go into any of the logarithms I get conditional expressions. Is it possible to set up the equations so I can just plug in units?

Here's my code:

Pideal[n_, T_, V_] := (n*R*T)/V
PvdW[n_, T_, V_, a_: a, b_: b] := (n*R*T)/(V - n*b) - (n^2*a)/V^2
W[V1_, V2_, P_] := Integrate[P, {V, V1, V2}]
Wideal[V1_, V2_, n_: n, T_: T] = W[V1, V2, Pideal[n, T, V]]

Here's the problem spot:

Wideal[5 Liters, 10 Liters, 1 Mols, 298 Kelvins]

I can work around this fairly easily, just leave out the Liters because they cancel out anyway. (Liters = Quantity["Liters"], etc)

However when I get to a more complicated equation that doesn't work so easily without making sure to put back in what I leave out.

WvdW[V1_, V2_, n_: n, T_: T, a_: a, b_: b] = 
    W[V1, V2, PvdW[n, T, V, a, b]]
WvdW[5*Liters, 10*Liters, 1 Mols, 298 Kelvins, 0, 0]

This doesn't work for the same reason, even though the Liters cancel out Mathematica doesn't assume that. However if I leave them out, I still have problems with the Mols, which appear in and outside of Logarithms, even though they're multiplied by 0.

WvdW[5, 10, 1 Mols, 298 Kelvins, 0, 0]

Finally, I haven't even gotten to using b which also appears in the logarithm, and even though the volumes add up and cancel out, Mathematica doesn't assume so.

WvdW[V1*Liters, V2*Liters, 1 Mols, 298 Kelvins, 0, 0 Mols Liters^(-1)]
share|improve this question
    
Side note: You should not use custom function names beginning with capital letters, which might conflict with the built-in function names. –  Silvia Feb 24 '13 at 3:11
    
If you define your functions with SetDelayed ( := ) instead of Set ( =) you don't appear to have a problem whatsoever. –  Sjoerd C. de Vries Feb 24 '13 at 13:26
    
@SjoerdC.deVries The calculation goes through, however then the units come out wrong. For example Wideal should be in units of Joules, and using SetDelayed gives an answer in units of meters^2 Joules. –  dmikalova Feb 24 '13 at 17:19
1  
Perhaps you didn't define the units of R? With R = Quantity["MolarGasConstant"] and UnitConvert[ Wideal[Quantity [5, "Liters"], Quantity [10, "Liters"], Quantity [1, "Moles"], Quantity[ 298, "Kelvins"]], "Joules"] I get Quantity[1.71742, "Joules"]. –  Sjoerd C. de Vries Feb 24 '13 at 17:50

3 Answers 3

You might use Assumptions in one form or another.

Block[{$Assumptions = Liters > 0 && Mols > 0 && Kelvins > 0}, 
 Simplify[Wideal[5 Liters, 10 Liters, 1 Mols, 298 Kelvins]]
 ]
(* -> 298 Kelvins Mols R Log[2] *)

One disappointment for me is that the following doesn't work:

Block[{$Assumptions = Liters > 0 && Mols > 0 && Kelvins > 0}, 
 Wideal[5 Liters, 10 Liters, 1 Mols, 298 Kelvins]
 ]
(* -> ConditionalExpression[298 Kelvins Mols R (-Log[5 Liters] + Log[10 Liters]), Liters != 0] *)

Nor does putting the assumptions directly in the Integrate:

W[V1_, V2_, P_] := Integrate[P, {V, V1, V2}, Assumptions :> Liters > 0 && Mols > 0 && Kelvins > 0];
Wideal[5 Liters, 10 Liters, 1 Mols, 298 Kelvins]
(* -> ConditionalExpression[298 Kelvins Mols R (-Log[5 Liters] + Log[10 Liters]), Liters != 0] *)

It seems using Simplify is necessary. See this answer for more on Integrate and assumptions.

Update

I think Silvia has made the best point, that the units should be canceled out first. Simply using SetDelayed lets Integrate cancel the units in the given example. If there are cases where one might have to use Simplify or FullSimplify first, then remove the comments.

Pideal[n_, T_, V_] := (n*R*T)/V;
PvdW[n_, T_, V_, a_: a, b_: b] := (n*R*T)/(V - n*b) - (n^2*a)/V^2;
W[V1_, V2_, P_] := Integrate[(*Simplify@*)P, {V, V1, V2}];
Wideal[V1_, V2_, n_: n, T_: T] := W[V1, V2, Pideal[n, T, V]];

Wideal[5 Liters, 10 Liters, 1 Mols, 298 Kelvins]
(* -> 298 Kelvins Mols R Log[2] *)
share|improve this answer
2  
If I ever see one of my students writing Liters > 0 I swear s/he'd be better starting to run away very fast (+1) –  belisarius Feb 24 '13 at 7:34
    
@belisarius, @teratoma My reaction to the title question was you can't plug units into a logarithm, but in fact the units cancel out. I do have a historical/philosophical reason for choosing Liters > 0, although it stretches a point and does not quite fit with modern concepts. As magnitudes, units are more than nothing, and real numbers were invented, at least in part, to represent ratios of magnitudes. To work with expressions such as Sqrt[Meter^2], one (implicitly) assumes that units behave as if they're positive real numbers. –  Michael E2 Feb 24 '13 at 13:37
1  
Just in case, that wasn't a critic but pretended to be an hilarious comment. Sometimes I keep the emoticons out because "a buen entendedor, pocas palabras" –  belisarius Feb 26 '13 at 3:08
    
@belisarius Thanks. That's how I understood it. But also I had thought about that issue already. Having taught courses in ancient mathematics - before real numbers were invented to measure magnitudes - I did have some reasons for thinking Liters > 0 is the best choice. Much less absurd than, say, Liters \[Element] Reals. And, you know, when one has thought about something, it's hard not to tell it. Call it "sharing" or "showing off", it doesn't matter much to me. If we didn't do it, we wouldn't learn as much from each other. –  Michael E2 Feb 26 '13 at 3:51
    
That's the pleasure we most enjoy here: hearing thoughts :) –  belisarius Feb 26 '13 at 3:58

Your problem seems to be the Integrate result: as usual it assumes all variables could be complex which results in a complicated ConditionalExpression which will not evaluate correctly when fed with variables that have units. The trick is, as Michael has shown to use assumptions, but I think it is much better to use the assumptions for the formal variables than for the units, it's not only belisarius students who probably shouldn't do that :-). To see the problem evaluate this:

Integrate[Pideal[n, T, V], {V, V1, V2}

Now if you are not working in very unusual conditions it might be safe to assume that V1 and V2 both are real valued and larger than zero:

Integrate[Pideal[n, T, V], {V, V1, V2}, Assumptions -> {V1 > 0, V2 > 0}]

which makes the result already a lot simpler, but still is a ConditionalExpression which should also evaluate for variables with units. For some reasons out of my understanding Mathematica seems to be too restrictive here, as it only returns a result for V1 < V2, but of course we know that the result is exactly the same for V2 < V1, and Mathematica also knows that:

Integrate[Pideal[n, T, V], {V, V1, V2},Assumptions -> {V1 > 0, 0 < V2 < V1}]
Integrate[Pideal[n, T, V], {V, V1, V2},Assumptions -> {V1 > 0, 0 < V1 < V2}]

so for this case you wouldn't actually need a ConditionalExpression at all (I think that Log will even give the correct results for most "academic corner cases", that is when one or two of V1,V2 will be zero). Putting all this together you could use something like the following:

Liters = Quantity["Liters"];
Kelvins = Quantity["Kelvins"];
Mols = Quantity["Moles"];
Pideal[n_, T_, V_] := (n*R*T)/V
PvdW[n_, T_, V_, a_: a, b_: b] := (n*R*T)/(V - n*b) - (n^2*a)/V^2
W[V1_, V2_, P_] := Piecewise[{
   {Integrate[P, {V, V1, V2}, Assumptions -> V1 > V2 > 0], V1 > V2},
   {Integrate[P, {V, V1, V2}, Assumptions -> V2 > V1 > 0], V2 > V1}
   }, Indeterminate]
Wideal[V1_, V2_, n_: n, T_: T] = W[V1, V2, Pideal[n, T, V]];

Wideal[5 Liters, 10 Liters, 1 Mols, 298 Kelvins]

Given the above definitions you'll receive an answer which does evaluate correctly and I don't think it is a problem to feed quantities (with units) to those expressions: if the units don't match and the argument to the Log isn't dimensionless, you'll get a partially unevaluated result and some messages, which might even help you to find problems related to wrong units... There remains one problem: if you need to use another definition for the equation of state you might need to check whether and which assumptions you have to give to Integrate...

share|improve this answer

Try this:

Clear[Wideal]
Wideal[V1_, V2_, n_: n, T_: T] := Evaluate[W[V1, V2, Pideal[n, T, V]]] // FullSimplify

Wideal[5 Liters, 10 Liters, 1 Mols, 298 Kelvins]
298 Kelvins Mols R Log[2]
Clear[WvdW]
WvdW[V1_, V2_, n_ : n, T_ : T, a_ : a, b_ : b] := 
 Evaluate[(Integrate[PvdW[n, T, V, a, b], V] /. {{V -> V1}, {V -> V2}}).{-1, 1}] // FullSimplify

WvdW[5 Liters, 10 Liters, 1 Mols, 298 Kelvins, 0, 0]
298 Kelvins Mols R Log[2]

(Don't know why, Integrate[-((a n^2)/V^2) + (n R T)/(-b n + V), {V, V1, V2}] feels taking forever on my laptop..)

Like Michael pointed out, additional assumptions may be needed for more complex expressions.

comment

I think a better way is to cancel the units before the quantity is feed to logarithm, because it's ill-defined of a logarithm with a parameter whose unit is other than $1$. (Think of the Taylor expansion of logarithm!) So the built-in Units functions might be a better choice than custom definitions. (Or simply do not involve units in calculations.)

share|improve this answer
    
I tried Units and the answer has a factor -Log[Quantity[5, "Liters"]] + Log[Quantity[10, "Liters"]], so Mathematica doesn't mind taking Log of a liter. Any fix? –  Michael E2 Feb 24 '13 at 13:45
    
@MichaelE2 Sjoerd's comment looks working for me. But for simplifying Log[...] + Log[...], maybe one has to define some custom TransformationFunctions. –  Silvia Feb 24 '13 at 19:58
    
It works with SetDelayed (Wideal[...]:=...) instead of the original Set. I had tried it with the original code. –  Michael E2 Feb 24 '13 at 20:57
    
(+1) For the very last sentence in parentheses. I remember this units business in logarithms was very common in chemistry labs. But it's an ugly thing to have in any calculation. –  Jens Feb 25 '13 at 0:11
    
@MichaelE2 I ended with something like this: Log[Quantity[5, "Liters"]] (Quantity[-298, "Kelvins" "MolarGasConstant" "Moles"]) + Quantity[0, ("Kilograms" ("Meters")^5)/("Liters" ("Seconds")^2)] + Log[Quantity[10, "Liters"]] (Quantity[298, "Kelvins" "MolarGasConstant" "Moles"]) /. Plus[c1_ Log[a_], c2_ Log[b_]] /; Abs[QuantityMagnitude[c1]] == Abs[QuantityMagnitude[c2]] :> Plus[Quantity[Abs[QuantityMagnitude[c1]], QuantityUnit[c1]] Log[ a^Sign[QuantityMagnitude[c1]] b^Sign[QuantityMagnitude[c2]]]] // UnitConvert[#, "Joules"] &, very ugly.. –  Silvia Feb 25 '13 at 0:36

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.