I have an equation that contains parameters. I want to use it in a function like NDSolve, but I can't seem to figure out how to do so. Here's an example:

I define my equation like so:

L := T - V
T := 1/2 m z'[t]^2
V := m g z[t]
eqn := Dt[D[L, z'[t]], t] - D[L, z[t]] == 0

Then, I want to use it in NDSolve, so I write the following:

solution[m_, g_] := NDSolve[{Evaluate[eqn], z[0] == 0, z'[0] == 0}, z[t], {t, 0, 10}]

This doesn't work as expected, though, and solution[1, 1] fails to output a result.

I also note that

theEqn[m_, g_] := Evaluate[eqn]
theEqn[1, 1]

works fine, and outputs

1 + z''[t] == 0

Furthermore, the following code (where I have just copied and pasted the definitions into the code) does work:

solution[m_, g_] := 
 NDSolve[{Dt[D[1/2 m z'[t]^2 - m g z[t], z'[t]], t] - 
     D[1/2 m z'[t]^2 - m g z[t], z[t]] == 0, z[0] == 0, z'[0] == 0}, 
  z[t], {t, 0, 10}]

I feel there ought to be some way that I'm missing to do that substitution automatically. How do I do this?


marked as duplicate by m_goldberg, Mr.Wizard Feb 27 '15 at 8:05

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ (I can also get it working by making L, T, V, and eqn explicit functions of m and g, but this looks awful, isn't easily modified, and seems overly complicated.) $\endgroup$ – Matthew Feb 27 '15 at 1:22
  • $\begingroup$ Proposed duplicates: (11461), (69590). Also related: (3864) $\endgroup$ – Mr.Wizard Feb 27 '15 at 1:37
  • $\begingroup$ Evaluate only works when applied to items at level 1 in an argument sequence. Your eqn appears at level 2. $\endgroup$ – m_goldberg Feb 27 '15 at 1:37
  • $\begingroup$ Ah, cool. How can I fix that, then? $\endgroup$ – Matthew Feb 27 '15 at 1:40
  • 1
    $\begingroup$ The following works. With[{eqn = eqn /. {m -> 1, g -> 1}}, NDSolve[{eqn, z[0] == 0, z'[0] == 0}, z[t], {t, 0, 10}]]. Perhaps you can adapt it to your needs. $\endgroup$ – m_goldberg Feb 27 '15 at 1:53

The thing that made this work in the end was using dummy variables as the function parameters. This then allowed me to use /. to replace variables.

solution[mm_, gg_] := 
 NDSolve[{eqn /. {m -> mm, g -> gg}, z[0] == 0, z'[0] == 0}, 
  z[t], {t, 0, 10}]

I think this is a pretty unintrusive solution, since it only affects one line of code and I can write the rest as usual.

  • $\begingroup$ Did you try blockSet? It does something much like this but in a more generalized way. $\endgroup$ – Mr.Wizard Feb 27 '15 at 2:16
  • $\begingroup$ No, I didn't, but I'll try it for a future problem - I can see why it's useful, but the way I've got my problem set up, I think this works better. $\endgroup$ – Matthew Feb 27 '15 at 10:53

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