1

My problem is related to the previous post Passing a function as an argument to another function using the same variables. I don't understand why in the following example the conversion of units does not work:

ClearAll[Ttrho]

ConstanteQ[f_] :=
  NumberQ[f] == True ||
    (QuantityQ[f] == True && (Head@f[[1]] === Function) == False);

QuantityFunctionQ[f_] := QuantityQ[f] == True && Head@f[[1]] === Function;

Options[Ttrho] = {DefaultUnit -> <|"T" -> "Kelvins"|>};
blockSet[
   Ttrho[T_, ρ_, pTt_: 1, OptionsPattern[]] := 
     With[{kb = Quantity["BoltzmannConstant"],
       Tt =
         If[QuantityQ[T],
           UnitConvert[T, Lookup[OptionValue[DefaultUnit], "T"]],
           Quantity[T, Lookup[OptionValue[DefaultUnit], "T"]]],
       fpTt =
         If[ConstanteQ[pTt], pTt,
           If[
             QuantityFunctionQ[pTt],
             Quantity[Last@pTt[[1]], pTt[[2]]], pTt[[2]]]]},
     Print[N @ Tt];
     UnitSimplify @ ((fpTt*kb*5 0.069/ρ) /. T -> Tt)]];

With the following examples, I do not obtain the same values:

 Ttrho[Quantity[2, "DegreesCelsius"], 0.1, Function[{T, ρ}, 2 T]]
 Ttrho[Quantity[275.15, "Kelvins"], 0.1, Function[{T, ρ}, 2 T]]
 Ttrho[275.15, 0.1, Function[{T, ρ}, 2 T]]

During evaluation of

In[1]:= 275.15K

Out[1]= Quantity[5.22337*10^-20, "Joules"]

During evaluation of

In[2]:= 275.15K

Out[2]= Quantity[2.62121*10^-20, "Joules"]

During evaluation of

In[3]:= 275.15K

Out[3]= Quantity[1898.54, "BoltzmannConstant"]
F. Aitken
  • 111
  • 5
  • What is blockSet? – m_goldberg Feb 10 '17 at 12:30
  • @m_goldberg mine, I believe: http://mathematica.stackexchange.com/a/69595/121 – Mr.Wizard Feb 10 '17 at 12:33
  • F. Aitken, since you are (I believe) building on my code I should try to answer this, but I am too sleepy right now. If someone doesn't answer sooner I'll try to remember to revisit this tomorrow. – Mr.Wizard Feb 10 '17 at 12:35
  • The problem comes from the fact that the function pTt is evaluated before the transformation T to Tt occured ? – F. Aitken Feb 10 '17 at 14:09
  • @F.Aitken I don't fully understand the use of blockset here; however, I notice that, if you do NOT use blockset in the definition, the three expressions do return the same value. It might be better if you specified what you are ultimately trying to accomplish, rather than trying to fix your current approach. It may be that a much simpler solution exists. – MarcoB Feb 10 '17 at 23:44
  • No without using blockSet it does not work because the function pTt remains not evaluated. This issue is a continuation of my previous post but now I would like to have a contol on the units without imposing a type on the variables because it can be tedious to write if you have lots of calculations to do. So I need some flexibility. – F. Aitken Feb 12 '17 at 08:17

1 Answers1

1

In order to obtain a control on the units of the parameters, the function Ttrho must simply be rewritten on the following form:

ClearAll[Ttrho]

ConstanteQ[f_] := NumberQ[f] == True || (QuantityQ[f] == True && (Head@f[[1]] === Function)== False);
QuantityFunctionQ[f_] := QuantityQ[f] == True && Head@f[[1]] === Function;
ListVarf[f_] := Flatten@List@First@If[QuantityFunctionQ[f], First@f, f];

Options[Ttrho] = {DefaultUnit -> <|"T" -> "Kelvins"|>};
blockSet[
Ttrho[T_, \[Rho]_, pTt_: 1, OptionsPattern[]] := 
 With[{kb = Quantity["BoltzmannConstant"], 
 Tt = N@If[QuantityQ[T], 
    UnitConvert[T, Lookup[OptionValue[DefaultUnit], "T"]], 
    Quantity[T, Lookup[OptionValue[DefaultUnit], "T"]]]}, 
 With[{fpTt = 
   If[ConstanteQ[pTt], pTt, 
    If[QuantityFunctionQ[pTt], 
     Quantity[pTt[[1]] @@ (ListVarf[pTt] /. {T -> First@Tt}), 
      pTt[[2]]], pTt @@ (ListVarf[pTt] /. {T -> Tt})]]},
 UnitSimplify@((fpTt*UnitConvert@kb*5* 0.069/\[Rho]))]
 ]
 ];

With the following examples, we obtain the same value:

Ttrho[Quantity[275.15, "Kelvins"], 0.1, Function[{T, \[Rho]}, 2 T]]
Ttrho[Quantity[275.15, "Kelvins"], 0.1, Function[{\[Rho], T}, 2 T]]
Ttrho[Quantity[275.15, "Kelvins"], 0.1, Function[T, 2 T]]
Ttrho[Quantity[2, "DegreesCelsius"], 0.1, Function[{T, \[Rho]}, 2 T]]
Ttrho[275.15, 0.1, Function[{T, \[Rho]}, 2 T]]
Ttrho[275.15, 0.1, Quantity[Function[T, 2 T], "Kelvins"]]
Ttrho[275.15, 0.1, Quantity[Function[{T, \[Rho]}, 2 T], "Kelvins"]]
Ttrho[275.15, 0.1, Quantity[Function[{\[Rho], T}, 2 T], "Kelvins"]]
Ttrho[275.15, 0.1, Function[{\[Rho],T}, 2 T]]

The common value is Quantity[2.62121*10^-20, "Joules"].

With this form of the function Ttrho, it is important to notice that the function pTt cannot contain a Quantity alone like this:

Ttrho[275.15, 0.1, Function[T, Quantity[2 T, "Kelvins"]]]

except if it is a constant:

 Ttrho[275.15, 0.1, Function[T, Quantity[2, "Kelvins"]]]
F. Aitken
  • 111
  • 5