Then I think Eric's method (inverting the interpolation table) is probably best suited to your needs. InverseFunction[]
is much more accurate, about 700-800 times slower, and fails near uppertime
(because of the singularity developing in the solution, I would guess).
Here's another way to do the same thing:
tFN = t /. First@s;
inverseFN = tFN[{"ValuesOnGrid", "Grid"}] //
MapAt[Flatten, #, 2] & //
Transpose //
Interpolation;
(Note t["Methods"] /. First@s
will show what string arguments may be passed to an InterpolatingFunction
; not all methods are defined for every InterpolatingFunction
.)
The following is only 60 times slower than interpolating and highly accurate like InverseFunction[]
. We can bracket the solution if the interpolating function is monotonic, an implicit assumption in the code:
fInv[if_InterpolatingFunction][y_] := Module[{$x},
With[{idx = First@Nearest[if["ValuesOnGrid"] -> "Index", y]},
With[{xvals = Flatten@if["Grid"]},
$x /. FindRoot[y == if[$x],
{$x, xvals[[Max[1, idx - 1]]],
xvals[[Min[Length@xvals, idx + 1]]]}, Method -> "Brent"]
]]];
Usage:
fInv[tFN][0.1]
(* 0.057735 *)
If you want to check monotonicity, here's a simple way:
tdiff = DeleteDuplicates@Sign@Differences@tFN["ValuesOnGrid"];
MatchQ[tdiff, {1} | {-1}]
A slightly more rigorous check:
dtsign = DeleteDuplicates@Sign[tIFN'["ValuesOnGrid"]];
tdiff == dtsign && MatchQ[tdiff, {1} | {-1}]
Caveat: The following passes both tests but is not monotonic. It is unlikely for NDSolve
to produce such a pathological case.
foo = Interpolation[{{0, 0}, {1/100, 49/100}, {99/100, 51/100}, {1, 1}}];
foo'[0.5]
(* -23.7372 *)