I am trying to use ParametricNDSolve
to find a desired value for a parameter in an ODE, and the output seems to misbehave.
First, consider the following example given in the documentation:
sol1 = ParametricNDSolve[{x''[t] - x'[t] + x[t] == 0, x[0] == 1, x'[0] == s}, x, {t, 0, 30}, {s}]
(* ::Output:: *) (*
{x -> ParametricFunction[ <> ]}
*)
root1 = FindRoot[Evaluate[x[s][10] /. sol1], {s, 6}]
(* ::Output:: *) (*
{s -> 1.40296}
*)
Secondly, my equation with the Automatic
ally chosen method:
sol2 = ParametricNDSolve[{X'[t] == t + (Sqrt[3] / Pi) Log[a/(1 - a)] Abs[t X[t]] - X[t], X[0] == 1}, {X}, {t, 0, 2}, a]
(* ::Output:: *) (*
{x -> ParametricFunction[ <> ]}
*)
root2 = FindRoot[Evaluate[X[a][2] /. sol2] == 3, {a, .5}]
(* ::Output:: *) (*
[!] InterpolatingFunction: Input {2} lies outside the range of data... (InterpolatingFunction::dmval)
{a -> 0.812787}
*)
In which I don't understand how the range is exceeded. Furthermore, specifying a method in the call yields:
sol3 = = ParametricNDSolve[{X'[t] == t + (Sqrt[3] / Pi) Log[a/(1 - a)] Abs[t X[t]] - X[t], X[0] == 1}, {X}, {t, 0, 2}, a, Method -> {"TimeIntegration" -> "ExplicitEuler"}]
(* ::Output:: *) (*
{x -> ParametricFunction[ <> ]}
*)
X[.7][2] /. sol3
(* ::Output:: *) (*
2.01701
*)
root3 = FindRoot[Evaluate[X[a][2] /. sol3] == 3, {a, .5}]
(* ::Output:: *) (*
[!] ParametricNDSolve: Encountered invalid NDSolve`SensitivityMethod method data object at point t=0.` (ParametricNDSolve::mdata)
[!] FindRoot: At {a}={0.5}, function value {-3+ParametricFunction[1,Internal`Bag[<1>],1,1,False,{{a$71966},<<5>>,{0}},{NDSolve`base$71973,NDSolve`NDSolveParametricFunction[0,{ParametricNDSolve,Internal`Bag[<2>],None,ParametricNDSolve},{{{<<9>>},{<<9>>}},{0,{<<3>>},{<<2>>},{<<3>>}},None,{{<<7>>},{<<1>>},None,{}}},{X},<<4>>,{Cache->True,CacheTableLength->19,CacheTableWidth->7,CacheKeyMaxBytes->1000000,CacheResultMaxBytes->1000000,KeyComparison->None,ResultComparison->LessEqual},{},<<1>>]}][0.5][2]} is not a {1} dimensional list of numbers (FindRoot::nlnum)
{a -> 0.5}
*)
X[.7][2] /. sol3
(* ::Output:: *) (*
ParametricFunction[ <> ][0.7][2]
*)
Note that t=2
is indeed in the interpolation range, and the call to the ParametricFunction
instance fails after the unsuccessful FindRoot
run.
How to understand this behavior, and is there a current workaround if it's a bug?
Related:
ParametricFunction
, however I am not sure if the behavior in the current post is of the same origin. Root solving is a large numeric topic, and I haven't finished all the tech notes and SE QA's just yet; do be kind enough and point me to anything that I am supposed to read. $\endgroup$FindRoot[Evaluate[X[a][2] /. sol1] == 3, {a, .7}]
$\endgroup$ParametricFunction
from being spoiled $\endgroup$Plot
, i.e.,Plot[(X[a][2] - 3) /. sol3, {a, 0, 1}]
indicates the solution is in the vicinity of0.8
Alternatively, avoid derivatives by using "FindRoot[lhs == rhs, {x, Subscript[x, 0], Subscript[x, 1]}] searches for a solution using Subscript[x, 0] and Subscript[x, 1] as the first two values of x, avoiding the use of derivatives." $\endgroup$