1
$\begingroup$

I will try to give a minimal example of my problem. Say I define the following function, spitting out an NDSolve result, using Module:

f[case : True | False] := Module[{x, rhs},

  If[case,
   rhs[x_] = y[x] Cos[x + y[x]],
   rhs[x_] = y[x]
   ];

  NDSolve[{y'[x] == rhs[x], y[0] == 1}, y, {x, 0, 30}]

  ]

The argument of f thereby specifies the right hand side of the differential equation: If the argument it True, the right hand side is y[x] Cos[x + y[x]], if it is False, it is just y[x].

Now, the way I defined it above, everything works fine, and the result is displayed as the usual

{{y → InterpolatingFunction[...]}}

output of NDSolve. However y is a global variable, so I would like to protect it inside my function by adding y to the set of local variables:


f[case : True | False] := Module[{x, y, rhs},

  If[case,
   rhs[x_] = y[x] Cos[x + y[x]],
   rhs[x_] = y[x]
   ];

  NDSolve[{y'[x] == rhs[x], y[0] == 1}, y, {x, 0, 30}]

  ]

If I run the function now, it would still produce the correct solution curves. However the output is now displayed for example as

{{y$25947 → InterpolatingFunction[...]}}

where the concrete number after the dollar sign changes every time I execute.

So something is going wrong. I am not sure what, and how to fix it.

Thanks for help!

$\endgroup$
  • $\begingroup$ "However y is a global variable, so I would like to protect it inside my function..." Just curious, but what problem does y being a global variable cause? $\endgroup$ – Chris K Apr 8 at 15:28
  • $\begingroup$ No problem, as long as one keeps the overview of what variables are used inside ones functions. In order of not having to keep this overview, I wanted to make it a local variable. $\endgroup$ – Britzel Apr 8 at 16:29
2
$\begingroup$

Try this

ClearAll[f];
f[case : True | False] := 
 Module[{x, y, rhs}, 
  If[case, rhs[x_] = y[x] Cos[x + y[x]], rhs[x_] = y[x]];
  y /. First@NDSolve[{y'[x] == rhs[x], y[0] == 1}, y, {x, 0, 30}]]

Then if you run

intp = f[True]

you will get an interpolation function you can use elsewhere

Plot[intp[x], {x, 0, 30}]

enter image description here

Hope that helps

Edit to answer question

The variables that you make local to the module, y in this case, are changed to have a unique number attached to them. This stops them interfering with variables outside the module. If you output the variable then you see how it was formulated within the module.

| improve this answer | |
$\endgroup$
  • $\begingroup$ I suppose that works, thanks! Do you know by any chance what exactly went wrong? It would be good to understand, so I can avoid making similar mistakes. $\endgroup$ – Britzel Apr 8 at 15:05
  • $\begingroup$ @Britzel I have added a comment to show how it works. Let me know if you need more . You can also look up Block and With which are variants on Module handling internal variables in different manners. $\endgroup$ – Hugh Apr 8 at 15:25
  • $\begingroup$ This makes a lot of sense. Thanks for the explanation! Also, I will check Block and With indeed. I was not aware of those. Cheers! $\endgroup$ – Britzel Apr 8 at 16:27
  • $\begingroup$ With any newer version of Mathematica you could also use NDSolveValue which would make your could a bit shorter and probably clearer. It seems to be made for exactly that use-case... $\endgroup$ – Albert Retey Apr 9 at 23:44
3
$\begingroup$

You could use a formal symbol inside f to avoid problems, since it can't be assigned a value.

f[case : True | False] := Module[{x, rhs}, 
  If[case, rhs[x_] = \[FormalY][x] Cos[x + \[FormalY][x]], rhs[x_] = \[FormalY][x]];
  NDSolve[{\[FormalY]'[x] == rhs[x], \[FormalY][0] == 1}, \[FormalY], {x, 0, 30}]]

(* trying to break it -- fails! *)
\[FormalY] = 1;
f[True]
(* Set::wrsym Symbol \[FormalY] is Protected. *)

Mathematica graphics

| improve this answer | |
$\endgroup$
  • $\begingroup$ Good solution! Thanks a lot! $\endgroup$ – Britzel Apr 9 at 15:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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