# NDSolve with one parameter

This is a copyable minimal example to illustrate the problem that occours when I include one parameter U into a differential equation which I want to solve with NDSolve. If I do not include a parameter into my differential equation, the following code works just fine to solve the equation, and evaluates the solution to the equation at some point:

ClearAll[H, v, es, eiginst, sol, hope, newhope]

H[t_] := {{0, 1}, {1, t}}
v[t_] := Table[Subscript[v, i][t], {i, 1, 2}]
es[t_] := Eigensystem[N[(H[t])]]
eiginst[t_] := Sort[Transpose[es[t]]]

sol = NDSolve[LogicalExpand[
I*v'[t] == H[t].v[t] && v == eiginst[][]],
v[t], {t, 0, 10}];

hope[t_] := Evaluate[v[t] /. sol]
hope
(* {-0.215432 - 0.94635 I, 0.0773099 + 0.228111 I}} *)


However, if I include one parameter U into the exact same code I get errors, which I do not understand since it is the same code:

ClearAll[H, v, es, eiginst, sol, hope, newhope]

H[t_, U_] := U*{{0, 1}, {1, t}}
v[t_] := Table[Subscript[v, i][t], {i, 1, 2}]
es[t_, U_] := Eigensystem[N[(H[t, U])]]
eiginst[t_, U_] := Sort[Transpose[es[t, U]]]

sol[U_] := NDSolve[LogicalExpand[
I*v'[t] == H[t, U].v[t] && v ==eiginst[0, U][][]],
v[t], {t, 0, 10}];

newhope[t_, U_] := Evaluate[v[t] /. sol[U]]
newhope[2, 1]


NDSolve::ndnum: Encountered non-numerical value for a derivative at t == 0.. >>

ReplaceAll::reps: ... >>

NDSolve::dsvar: ... >>

ReplaceAll::reps: .. >>

• Use ParametricNDSolve instead of NDSolve – bbgodfrey Dec 4 '15 at 23:30
• Thank you! But will the runtime of ParametricNDSolve be the same? This is just a minimal example. In the end I want to include multiple parameters and the dimensions of the vectors and matrices will be very large. – Falafel Dec 4 '15 at 23:36
• I can get ParametricNDSolve to work in a simple example, but when I apply it to my problem It wont solve the equation. I am really frustrated, since I have been stuck on this problem for almost 2 days. – Falafel Dec 5 '15 at 0:03
• I have posted how you might solve your sample problem with ParametricNDSolveValue (a variant of ParametricNDSolve). It is no slower than creating a function that, in effect, replicates ParametricNDSolve and may be more reliable and convenient. – bbgodfrey Dec 5 '15 at 0:10

Problems of the sort described typically are treated with ParametricNDSolve.

ClearAll[v, H, hope, newhope, sol, es, eiginst]
H[t_, U_] := U*{{0, 1}, {1, t}}
v[t_] := Table[Subscript[v, i][t], {i, 1, 2}]
es[t_, U_] := Eigensystem[N[(H[t, U])]];
eiginst[t_, U_] := Sort[Transpose[es[t, U]]]
sol = ParametricNDSolveValue[LogicalExpand[I*v'[t] == H[t, U].v[t] &&
v == eiginst[0, U][][]], v[t], {t, 0, 10}, {U}];
newhope[u_][t0_] := sol[u] /. t -> t0


Then, for instance,

newhope
(* {-0.304667 - 1.33834 I, 0.109333 + 0.322597 I} *)

• Thank you alot! Your answer solves the minimal problem. The only issue I have is, that it seems to me, that the eigenvector eiginst[0,U] which occours as initial condition in the ParametricNDSolveValue will be calculated universally for the parameter U, and only later the parameter is inserted. But for large matrices calculating the eigenvectors universally in dependence of the parameter U is impossible. Do you now how to solve this issue? – Falafel Dec 5 '15 at 2:28
• @Falafel I would need to see an example to address this last issue. – bbgodfrey Dec 5 '15 at 7:43

You can also keep NDSolve in the second code, but then you need to change the two last lines

newhope[t_, U_] := Evaluate[v[t] /. sol[U]]
newhope[2, 1]


to

newhope[t_, U_] := v[t] /. sol[U]
newhope[t, 1] /. t -> 2


You will end up with the same output as the first code.

The issue is that by doing Evaluate[v[t] /. sol[U]], you are forcing the evaluation of sol[U] and hence of NDSolve with an unknown argument that should have a numerical value. This results in an error from NDSolve. Another way to notice this is to evaluate sol[U] on its own.

By removing Evaluate, NDSolve will evaluate only when called by newhope. Since a numerical value is now given (newhope[t, 1]`) there is no more issue.