This is the most difficult of the nearly two dozen nonlinear ODE separatrix computations that I have encountered on Mathematica.SE. Nonetheless, it can be can be solved by a systematically refined search for initial conditions that maximize the range in r
over which the ODE system can be integrated before clearly departing from the separatrix.
Series expansion at r == 0
To begin, we need the behavior of the dependent variables at very small r
. The leading term for each is given by the OP in a comment above, and the next terms can be obtained by expanding the ODEs as power series at r == 0
, equating the coefficients of each power of r
to zero, and solving the resulting polynomial equations. (The next order term in the series expansions is desired for precision consistency with the high WorkingPrecision
needed to integrate the ODEs.) These steps can be packaged as a simple function.
params[n_] := Module[{ser, sereq},
ser = Series[Unevaluated[{r D[1/r D[A[r], r], r] - ξ^2 F[r]^2 (A[r] - 1),
1/r D[r D[F[r], r], r] - n^2/r^2 F [r] (A[r] - 1)^2 - 1/2 F[r] (F[r]^2 - 1)}] /.
{A[r] -> Sum[ca[i] r^i, {i, 2, n + 4}],
F[r] -> Sum[cf[i] r^i, {i, n, n + 4}]}, {r, 0, n + 2}] // Normal;
sereq = Thread[DeleteCases[Flatten@(Most /@ (CoefficientList[#, r] & /@ ser)), 0] == 0];
{Sum[ca[i] r^i, {i, 2, n + 3}], Sum[cf[i] r^i, {i, n, n + 3}]} /.
Factor@Flatten@Solve[sereq, Flatten@{Table[ca[i], {i, 3, n + 3}],
Table[cf[i], {i, n + 1, n + 3}]}] /. {ca[2] -> a, cf[n] -> f}]
where a
and f
are free parameters to be determined to obtain the separatrix. params[]
yields for the first four values of n
,
params /@ Range[4]
(* {{a r^2 - 1/8 f^2 r^4 ξ^2, f r - 1/16 (1 + 4 a) f r^3},
{a r^2, f r^2 - 1/24 (1 + 16 a) f r^4},
{a r^2, f r^3 - 1/32 (1 + 36 a) f r^5},
{a r^2, f r^4 - 1/40 (1 + 64 a) f r^6}} *)
By observation the general term is
{a r^2 - If[n == 1, f^2 r^4 ξ^2/8, 0], f r^n (1 - (1 + 4 a n^2) r^2/(8 (n + 1)))}
Solution for n == 1
, ξ == 1
The question provides a solution for n == 1
, ξ == 1
. Although the code in the question does not yield the plot shown for Mathematica 11.1.1, probably because NDSolve
has changed over the past four years, the plot does provide a useful point of comparison. (A similar situation occurred for the answer by xzczd to question 110626, as described in its associated comments.)
Define the solution to the ODE system as
r0 = 1/10000; inf = 15; ξ = 1; n = 1;
numSol = ParametricNDSolveValue[
{r D[1/r D[A[r], r], r] - ξ^2 F[r]^2 (A[r] - 1) == 0,
1/r D[r D[F[r], r], r] - n^2/r^2 F [r] (A[r] - 1)^2 - 1/2 F[r] (F[r]^2 - 1) == 0,
A[r0] == a r0^2 - If[n == 1, f^2 r0^n ξ^2/8, 0],
F[r0] == f r0^n (1 - (1 + 4 a n^2) r0^2/(8 (n + 1))),
A'[r0] == 2 a r0 - If[n == 1, r0^3 f^2 ξ^2/2, 0],
F'[r0] == f r0^(n - 1) (n - (2 + n) (1 + 4 a n^2) r0^2/(8 (1 + n))),
WhenEvent[A'[r] < 0 || F'[r] < 0 || A[r] > 1 || F[r] > 1, "StopIntegration"]},
{A, F}, {r, r0, inf}, {a, f}, WorkingPrecision -> 30, MaxSteps -> 20000];
Because the desired solutions monotonically approach A == 1
and F == 1
at large r
, WhenEvent[]
is used to terminate a calculation not doing so. The systematic search and refinement of the parameters a
and f
is accomplished by
dist[a_?NumericQ, f_?NumericQ] := (First@numSol[a, f])["Domain"][[1, 2]]
which determines how far in r
an integration proceeds before stopping, and
Clear[paramFind];
paramFind[a1_, a2_, f1_, f2_, inc_, lp_, nm_: 1, ft_: 0] :=
Module[{mx = {{a1 + a2, f1 + f2, 0}/2}, ahw = (a2 - a1)/2, fhw = (f2 - f1)/2},
Do[mx = First[mx];
tab = Flatten[ParallelTable[{a, f, dist[a, f + ft]}, {a, mx[[1]] - ahw,
mx[[1]] + ahw, 2 ahw/inc}, {f, mx[[2]] - fhw, mx[[2]] + fhw, 2 fhw/inc}], 1];
ahw = 2 ahw/inc; fhw = 2 fhw/inc;
mx = TakeLargestBy[tab, Last, nm], {i, lp}]; mx]
It generates a Table
of integration distances for the specified ranges of a
and f
, determines the maximum distance, and if requested repeats this process lp
times, increasing the accuracy of the desired parameters by of order 1/inc
with each iteration. It returns the final tab
(as a side effect), and the largest nm
distances and their parameters. For instance,
mmm = paramFind[1/10, 5/10, 3/10, 9/10, 50, 1, 20]
searches a large range of parameters, returning a
, f
, and the maximum distance integrated (as well as the next nineteen largest values in tab
).
(* {63/250, 3/5, 3.61273127329305003526188484581} *)
The corresponding integration curves are given by
s = numSol @@ Most[First@mmm];
Plot[{(First@s)[r], (Last@s)[r]}, {r, r0, (First@s)["Domain"][[1, 2]]},
PlotRange -> {0, 1}, PlotStyle -> {{Black, Thick}, {Red, Thick}},
PlotLegends -> Placed[{"A(r)", "F(r)"}, {.9, .5}], AxesLabel -> {r, "A, F"}]
which, not surprisingly, is not very close to the desired result. tab
itself can be visualized with
ListDensityPlot[tab, ColorFunction -> "Rainbow", PlotRange -> All]
The topology of dist
in {a, f}
space is a narrow ridge. It is much easier to find the peak on this ridge by aligning one axis of the search Table
with the ridge. This is accomplished by
pltlim = MinMax[First /@ mmm];
ffit = Rationalize[LinearModelFit[Most /@ mmm, a, a, Weights -> Last /@ mmm] // Normal, 0]
Show[
ListPlot[Table[Style[Most[mmm[[i]]], ColorData[
"Rainbow", (Last[mmm[[i]]] - Last[mmm[[-1]]])/(Last[mmm[[1]]] -
Last[mmm[[-1]]])]], {i, Length[mmm]}], DataRange -> pltlim],
Plot[ffit, Flatten@{a, pltlim}]]
(* 49771269/224512015 + (76623081 a)/51020704 *)
Returning ffit
to paramFind[]
then give a much more useful result for tab
.
mmm = paramFind[57/250, 67/250, -1/100, 1/100, 50, 1, 1, ffit];
mmm = (# + {0, ffit /. a -> First@#, 0}) & /@ mmm
ListDensityPlot[tab, ColorFunction -> "Rainbow", PlotRange -> All]
which easily accommodates systematic refinement.
mmm = paramFind[57/250, 67/250, -1/100, 1/100, 10, 15, 1, ffit];
mmm = (# + {0, ffit /. a -> First@#, 0}) & /@ mmm
(* {{381469726561/1525878906250, 301261684232301644236719949/499387950864892578125000000,
15.0000000000000000000000000000}} *)
Plotting the integration results for this parameter set, using the code given above, yields
The desired asymptotic values are reached at about r == 8
. This entire calculation required less than five minutes of computer time. For completeness, here is another depiction of the ridge, this time using Plot3D
. Although prettier, it required a good initial guess and a large fraction of an hour of computer time to obtain a less accurate result than that above.
Plot3D[dist[a, f], {a, 2499/10000, 2501/10000}, {f, 60316/100000, g0336/100000},
PlotPoints -> 51, MaxRecursion -> 3, PlotRange -> All, Mesh -> None]
TakeLargestBy[(% // InputForm)[[1, 1, 1]], Last, 1]
(* {{0.25, 0.603262, 8.80276}} *)
Solution for n == 1
, ξ == 3
Increasing ξ
makes the computation more challenging, because the ridge becomes much narrower. Using the same code as above yields an initial plot of tab
(after a bit of searching),
from which ffit
is obtained after an iteration as
(* 11817596/452896041 + (92677142 a)/127177533 *)
with the final result,
(* {{47443/40000, 34190793340749568069048951/38398800799897902000000000,
4.54199136850410415171442304534}} *)
Perhaps, the integration could have been carried farther with WorkingPrecision ->45
, but the curve seems good enough.
Incidentally, the corresponding optimum parameters for ξ == 3/2
(computed as a test case) are,
(* {{172416/390625, 5298661942732265830186933/7730236542592271015625000,
7.46251057225238295282438028696}} *)
Solution for n == 5
, ξ == 1
Increasing n
instead of ξ
relative to the base case does not so much narrow the ridge as increase the needed values of WorkingPrecision -> 45, MaxSteps -> 30000
in numSol
at n == 5
even to find the ridge. So, the computations become somewhat slower. In addition, "LocationMethod" -> "LinearInterpolation"
is added to WhenEvent[]
to eliminate warning messages. The final result, obtain using otherwise the same code as above, is
(* {{1/20, 26918753177298531983608529/5975307063483195750000000000,
15.0000000000000000000000000000000000000000000}} *)
Parameters for n
between 2
and 4
are,
(* {{1/8, 26137069653429078458702681/110681880730882350000000000,
15.0000000000000000000000000000}} *)
(* {{8333333333/100000000000, 13767675775706146512163493/
188286666204471770000000000, 15.0000000000000000000000000000}} *)
(* {{3124999999/50000000000, 374053654379840009082877269/
19447580662313216000000000000, 15.0000000000000000000000000000}} *)
It is curious that optimal values of a
are simple rational numbers for ξ == 1
, namely,
{1/4, 1/8, 1/12, 1/16, 1/20}
for n == Range[5]
. If this observation generally is true, solving ξ == 1
problems becomes much easier.