0
$\begingroup$

I am having a problem with $ sign in the name of a parameter to a temporary function. The functions I have should compute the angular sum (or turning angle) for some expression generated by function fMakeExpr[], which here is just a simplified version of the complex sine expression generated in the actual code. The angular sum is then computed by the integral in function fSum[] and returned to the calling function. The wrapper fSumForSine[] take as parameter an integer > 0 which determines the particular sine function generated, calls on fMakeExpr[] to generate the sine expression, and then calls on fSum[] to do the computation and returns the numeric result.

The problem I have is the parameter name for the temporary expression f[x_ ], which Mathematica changes into f[x$_ ] in order to make it unique, but which is not recognized by the integral in fSum[]. If in fSumForSine[] the parameter n in the the line f[x_] := Evaluate[fMakeExpr[n]]; is replaced by a constant, so the line instead is: f[x_] := Evaluate[fMakeExpr[1]]; , then the param to the temporary function remains [x_ ] and everything works as it should. It also works if I with param as n call the functions directly from input line in the notebook, se more on that after the code below.

This is my code:

fMakeExpr[n_ ?NumericQ] := Module[{strBase, strSine, tmp},
   strBase := "(Sqrt[§] Sin[x]) + ((Sqrt[§+1]-1) Sin[§ x])";  (* 
   Example pattern for complex sine *)
   strSine := StringReplace[strBase, "§" -> ToString[n]];
   tmp := Evaluate[ToExpression[StringJoin[strSine]]];
   Return[Evaluate[ToExpression[ToString[tmp, InputForm]]]];
   ];

ClearAll[fSum];
fSum[f_ , from_ ?NumericQ, to_ ?NumericQ, dbg_ ] := (
   If[(dbg == True), (
     Print["fSum:f = ", Definition[f]];
     Print["fSum:ArcTan[f'[x]] = ", ArcTan[f'[x]]];
     Print["fSum:D[ArcTan[f'[x]],x] = ", D[ArcTan[f'[x]], x]];)
    ];
   Return[NIntegrate[Abs[D[ArcTan[f'[x]], x]], {x, from, to}]];
   );

ClearAll[fSumForSine];
fSumForSine[n_ ?NumericQ, dbg_ ] := Module[{f},
   f[x_] := Evaluate[fMakeExpr[n]];  (*<<< Param n = problem, constant = OK *)
   If[(dbg == True), Print["fSumForSine:f = ", Definition[f]]];
   Return[fSum[f, 0, 2 π, dbg]];
   ];  

You can see the problem by executing this in the notebook (param should be n):

fSumForSine[1, False]

You should get an error message and no value for angular sum. You can se the problem by activating debug printouts, like this:

fSumForSine[1, True]

Note the parameter name [x_ ] has been changed to [x$_ ], and that is what seems to cause the problems later on in the integral. Change the parameter n in the line to a constant 1 like I described above the code and see the difference and that it now works.

It also works, with param as n, if I execute the calls directly from the notebook input line like this:

f[x_] = fMakeExpr[1]

fSum[f, 0 , 2 π, False]

I really hope someone can help me fix this problem, because I have been banging my head against this for days now.

$\endgroup$

2 Answers 2

1
$\begingroup$

You could pass x to fMakeExpr and use it to replace a dummy variable in your string.

fMakeExpr[n_?NumericQ, x_] := 
  Module[{strBase, strSine, tmp}, 
   strBase := "(Sqrt[§] Sin[xx]) + ((Sqrt[§+1]-1) Sin[§ xx])"; 
   strSine := StringReplace[strBase, "§" -> ToString[n]];
   tmp = ToExpression[StringJoin[strSine]] /. xx -> x;
   ToExpression[ToString[tmp, InputForm]]];

fSumForSine[n_?NumericQ, dbg_] := 
  Module[{f}, f[x_] := Evaluate[fMakeExpr[n, x]];
   If[(dbg == True), Print["fSumForSine:f = ", Definition[f]]];
   fSum[f, 0, 2 \[Pi], dbg]];

fSumForSine[1, False]
 (* 3.82127 *)
$\endgroup$
1
  • $\begingroup$ Thank you very much MelaGo, that was the right medicine! I would never have been able to come up with that solution to the problem myself. I think I understand what it does: by forcing MMA to replace the xx with x, MMA appends a $ to indicate it should at final evaluation be substituted with the variable used at that time, which is x. Right? $\endgroup$
    – Mikl
    Commented Mar 14 at 11:01
0
$\begingroup$

Rather than work with symbolic "function bodies", maybe you could just work with Function.

fMakeFn[n_?NumericQ] := Function[x, (Sqrt[n]  Sin[x]) + ((Sqrt[n + 1] - 1)  Sin[n  x])];
fSumForSineNew[n_?NumericQ, dbg_] := fSum[fMakeFn[n], 0, 2  \[Pi], dbg];

fSumForSineNew[1, False]
(* 3.82127 *)
$\endgroup$
1
  • $\begingroup$ Thank you lericr for that elegant construct. I could only make it work with a hardcoded expression like in your example, not sure why. Therefore, I have combined it with the solution provided by MelaGo above. Together these solutions finally made my code work $\endgroup$
    – Mikl
    Commented Mar 14 at 11:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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