5

Note: This question is for those chaotic systems where the order of maximal Lyapunov exponent is around $10^{-3}$. So it's different from normal chaotic systems like Hénon–Heiles system, Yang-Mills-Higgs System, Double Pendulum or the famous Lorenz Attractor.

The related problem: I am trying to reproduce my results for the Poincaré section published here (Specifically one of the sub-figures in Figure $8$ on page $15$ given below), which I plotted by making use of an algorithm developed by @Alex Trounev. I am trying to plot the same this time by a different interactive algorithm of @E. Chan-López.

poincare-string

The code being used is as follows:

lagrangian = (8 x[t]^2)/3 + (4 x[t]^3)/3 - 6 y[t]^2 + 
   148/7 x[t] y[t]^2 + Derivative[1][x][t]^2 + 
   1/3 y[t] Derivative[1][x][t] Derivative[1][y][t] + 
   Derivative[1][y][t]^2 + 1/5  x[t]  Derivative[1][y][t]^2;

Px = D[lagrangian, x'[t]]; Py = D[lagrangian, y'[t]]; hamiltonian = ((Px x'[t] + Py y'[t]) - lagrangian) /. (Solve[{px[t] == Px, py[t] == Py}, {x'[t], y'[t]}] // Last) // FullSimplify;

{a1, b1, c1, d1} = {D[hamiltonian, px[t]], D[hamiltonian, py[t]], -D[hamiltonian, x[t]], -D[hamiltonian, y[t]]}; hameqns = {x'[t] == a1, px'[t] == c1, y'[t] == b1, py'[t] == d1};

constraint = FullSimplify[ Last[(py0 /. Solve[e == (hamiltonian /. {x[t] -> x0, px[t] -> px0, y[t] -> 0, py[t] -> py0}), py0])]]

PoincareSections[{x0_, px0_, y0_, py0_}, e_, tmax_] := Block[{constraint, x, px, y, py}, constraint = ( I Sqrt[5 + x0] Sqrt[-12 e + 3 px0^2 - 16 x0^2 (2 + x0)])/Sqrt[15]; If[Head[N[constraint]] === Complex, Nothing, If[# == {}, {}, First[#]] &@ Last[Reap[ NDSolve[{hameqns, x[0] == x0, px[0] == px0, y[0] == y0, py[0] == constraint, WhenEvent[y[t], Sow[{x[t], px[t]}, "LocationMethod" -> "EvenLocator"]]}, {x, px, y, py}, {t, 0, tmax}, MaxSteps -> ∞, MaxStepSize -> 0.1]]]]]

style = {PlotStyle -> {{AbsolutePointSize[1], Opacity[0.4]}}, AspectRatio -> 1, ImageSize -> 420, PlotHighlighting -> None};

DynamicModule[{f = {}}, Column[{Dynamic[ MatrixForm@{MousePosition["Graphics", "Mouse not in graphics!"]}], Row[{ClickPane[ Dynamic@ListPlot[f, style], (AppendTo[f, PoincareSections[{#[[1]], #[[2]], 0, 0}, 10^-5, 3000]]) &], Button[Style["Copy orbit list", 12], CopyToClipboard[Iconize[f, "Orbit list"]], ImageSize -> Automatic, Alignment -> Center, Appearance -> {"Palette", "Pressed"}]}, " "]}, Alignment -> Center]]

Now, the above algorithm doesn't work simply because the Head of the constraint turns out to be complex. But if we calculate it, technically, it's not a complex number. A simple example can explain the reason:

The issue:

a = N[constraint] /. x0 -> -1/1000 /. px0 -> 1/1000 /. e -> 10^-5

(-0.007046375030231264+0. I)

Head[a]

(Complex)

The number is Real, but the Head turns out to be Complex only because it is in the form of a+Ib.

If I comment out the condition If[Head[N[constraint]] === Complex in the code, it works, but the system hangs after 3 or 4 mouse clicks. How to rectify this issue?

Edit: Issue resolved Thanks to @BobHanlon, the issue is solved.

    PoincareSections[{x0_, px0_, y0_, py0_}, e_, tmax_] := 
     Block[{constraint, x, px, y, py}, 
      constraint = 
       N[(I   Sqrt[
             5 + x0]   Sqrt[-12   e + 3   px0^2 - 16   x0^2   (2 + x0)])/
          Sqrt[15]] // Chop;
      If[Head[N[constraint]] === Complex, Nothing, 
       If[# == {}, {}, First[#]] &@
        Last[Reap[
          NDSolve[{hameqns, x[0] == x0, px[0] == px0, y[0] == y0, 
            py[0] == constraint, 
            WhenEvent[y[t], 
             Sow[{x[t], px[t]}, "LocationMethod" -> "EvenLocator"]]}, {x, 
            px, y, py}, {t, 0, tmax}, MaxSteps -> ∞, 
           MaxStepSize -> 0.1]]]]]

style = {PlotStyle -> {{PointSize[.005], Opacity[0.9]}}, AspectRatio -> 1, ImageSize -> 420, PlotHighlighting -> None};

DynamicModule[{f = {}}, 
 Column[{Dynamic[
    MatrixForm@{MousePosition["Graphics", "Mouse not in graphics!"]}],
    Row[{ClickPane[
      Dynamic@ListPlot[f, 
        style], (AppendTo[f, 
         PoincareSections[{#[[1]], #[[2]], 0, 0}, 10^-5, 3000]]) &], 
     Button[Style["Copy orbit list", 12], 
      CopyToClipboard[Iconize[f, "Orbit list"]], 
      ImageSize -> Automatic, Alignment -> Center, 
      Appearance -> {"Palette", "Pressed"}]}, "  "]}, 
  Alignment -> Center]]

Choosing the best NDSolve Method

Rectified code used for a close up:

par = {9.07, 11.73, 5.80, 2.18, 4.36, -2.645, 6.023}; {K1, K2, K3, K4,
   K5, ωsq[0], ωsq[1]} = Rationalize[par, 10^-30];
lagrangianold = 
  Sum[c[n]'[t]^2 - c[n][t]^2  ωsq[n], {n, {0, 1}}] + 
   K1  c[0][t]^3 + K2  c[0][t]  c[1][t]^2 + K3  c[0][t]  c[0]'[t]^2 + 
   K4  c[0][t]  c[1]'[t]^2 + K5  c[0]'[t]  c[1][t]  c[1]'[t];
c[0][t_] := 
  OverTilde[c][0][t] + α1*OverTilde[c][0][t]^2 + α2*
    OverTilde[c][1][t]^2; 
c[1][t_] := 
  OverTilde[c][1][t] + α3*OverTilde[c][0][t]*OverTilde[c][1][t];
α1 = -29/20; α2 = -1/2; α3 = -1;
n = Expand[lagrangianold];
vars = {OverTilde[c][0][t], OverTilde[c][1][t], 
   Derivative[1][OverTilde[c][0]][t], 
   Derivative[1][OverTilde[c][1]][t]};
lagrangianew = 
  Normal[Series[n /. Thread[vars -> m*vars], {m, 0, 3}]] /. m -> 1;
    lagrangian = 
  Simplify[
   lagrangianew /. OverTilde[c][0] -> x /. OverTilde[c][1] -> y];

Px = D[lagrangian, x'[t]]; Py = D[lagrangian, y'[t]]; hamiltonian = ((Px x'[t] + Py y'[t]) - lagrangian) /. (Solve[{px[t] == Px, py[t] == Py}, {x'[t], y'[t]}] // Last) // FullSimplify;

{a1, b1, c1, d1} = {D[hamiltonian, px[t]], D[hamiltonian, py[t]], -D[hamiltonian, x[t]], -D[hamiltonian, y[t]]}; hameqns = {x'[t] == a1, px'[t] == c1, y'[t] == b1, py'[t] == d1};

constraint = FullSimplify[ Last[(py0 /. Solve[e == (hamiltonian /. {x[t] -> x0, px[t] -> px0, y[t] -> 0, py[t] -> py0}), py0])]]

PoincareSections[{x0_, px0_, y0_, py0_}, e_, tmax_] := Block[{constraint, x, px, y, py}, constraint = Chop[N[1/50 Sqrt[-5 - (9 x0)/10] Sqrt[-2000 e + 500 px0^2 - x0^2 (5290 + 2799 x0)]]]; If[Head[N[constraint]] === Complex, Nothing, If[# == {}, {}, First[#]] &@ Last[Reap[ NDSolve[{hameqns, x[0] == x0, px[0] == px0, y[0] == y0, py[0] == constraint, WhenEvent[y[t], Sow[{x[t], px[t]}, "LocationMethod" -> "EvenLocator"]]}, {x, px, y, py}, {t, 0, tmax}, MaxSteps -> ∞, MaxStepSize -> 0.1, Method -> "StiffnessSwitching"]]]]]

style = {PlotStyle -> {{PointSize[.005], Opacity[0.9]}}, AspectRatio -> 1, ImageSize -> 300, PlotRange -> {{-0.0001, 0}, {-0.0001, 0.0001}}, PlotHighlighting -> None};

Off[NDSolve::ndsz]

DynamicModule[{f = {}}, Column[{Dynamic[ MatrixForm@{MousePosition["Graphics", "Mouse not in graphics!"]}], Row[{ClickPane[ Dynamic@ListPlot[f, style], (AppendTo[f, PoincareSections[{#[[1]], #[[2]], 0, 0}, 10^-5, 2000]]) &], Button[Style["Copy orbit list", 12], CopyToClipboard[Iconize[f, "Orbit list"]], ImageSize -> Automatic, Alignment -> Center, Appearance -> {"Palette", "Pressed"}]}, " "]}, Alignment -> Center]]

I have one minor problem now for a close-up of the above section: I get an NDSolve warning message, which I turn off. Still, the plot I get differs from the original when I use Method -> "ImplicitRungeKutta" instead of Automatic or some other like "StiffnessSwitching".

Here is a result found using two different methods for comparison:

comparison

Why is it that the results are scaled in the y-axis, and which method should be considered the best in such a case? The methods that I used are also not easily seen in the documentation. Also, any help in making the code more elegant(like avoiding warnings) would be genuinely beneficial!

codebpr
  • 2,233
  • 1
  • 7
  • 26
  • 4
    In the definition of PoincareSections change the definition of constraint to read constraint = N[(I Sqrt[5 + x0] Sqrt[-12 e + 3 px0^2 - 16 x0^2 (2 + x0)])/ Sqrt[15]] // Chop; The Chop will remove imaginary artifacts. – Bob Hanlon Mar 05 '24 at 05:25
  • @BobHanlon, thanks a lot. It works now. Can you see the updated question for a minor query? – codebpr Mar 05 '24 at 07:50
  • @codebpr It could be better to reproduce known results, maybe from your paper as well. – Alex Trounev Mar 05 '24 at 14:20
  • @AlexTrounev should I ask a new question for that or just update this one to reflect the comparison for reproduced results? – codebpr Mar 05 '24 at 15:19
  • @codebpr There is no answer on your topic. Could you add some picture to reproduce with new code? – Alex Trounev Mar 05 '24 at 18:09
  • @AlexTrounev ok, I am going to add them now. – codebpr Mar 06 '24 at 04:00
  • You can use SPRK methods or ImplicitRungeKutta with ImplicitRungeKuttaGaussCoefficients which is also symplectic. Projection method can be usefull too – I.M. Mar 06 '24 at 06:19
  • 1
    @I.M. thanks for the useful response. I was just wondering why the Wolfram guys have not kept them in the Options section of NDSolve but hidden inside the Tutorials? Also, one query? Why is the result rescaled when I use Hamilton equations of motion instead of Euler- Lagrange? – codebpr Mar 06 '24 at 06:23
  • The scales seems to match, the integration method for the last left fig is off, I would expect StiffnessSwitching to produce wrong result for chaotic systems (got no prove for it thou); I would use Projection with Lagrangian eqs (energy conservation) and SPRK/ImplicitRungeKutta with Hamiltonian eqs – I.M. Mar 06 '24 at 06:53
  • @I.M. actually, I meant the scale of the original compared to the recent ones. – codebpr Mar 06 '24 at 07:27
  • Also, it gives me lots of errors when I use your suggested SPRK method: Method -> {"SymplecticPartitionedRungeKutta", "DifferenceOrder" -> 10, "PositionVariables" -> {x[t], y[t]}} – codebpr Mar 06 '24 at 07:49

1 Answers1

6

We don't know what method is most efficient, since to answer this question we need too much test performed. We can only suggest code without some NDSolve messages concerning solution behaver and WhenEvent. It seems impossible to exclude all messages. We can't avoid, for example, message which appears when we put mouse on an axis

General::munfl: -(1./9.49657*10^307) is too small to represent as a normalized machine number; precision may be lost. 

First, note, that for chaotic system research we should exclude any Automatic option, like automatic step size. Second, note, that all implicit scheme working in this case like averaging, and therefore depresses chaotic mode. Third, note, that WhenEvent with some DetectionMethod make code unstable. Taken into account all these notes we proposed next options

par = {9.07, 11.73, 5.80, 2.18, 4.36, -2.645, 6.023}; {K1, K2, K3, K4,
   K5, \[Omega]sq[0], \[Omega]sq[1]} = Rationalize[par, 10^-30];
lagrangianold = 
  Sum[c[n]'[t]^2 - c[n][t]^2   \[Omega]sq[n], {n, {0, 1}}] + 
   K1   c[0][t]^3 + K2   c[0][t]   c[1][t]^2 + 
   K3   c[0][t]   c[0]'[t]^2 + K4   c[0][t]   c[1]'[t]^2 + 
   K5   c[0]'[t]   c[1][t]   c[1]'[t];
c[0][t_] := 
  OverTilde[c][0][t] + \[Alpha]1*OverTilde[c][0][t]^2 + \[Alpha]2*
    OverTilde[c][1][t]^2;
c[1][t_] := 
  OverTilde[c][1][t] + \[Alpha]3*OverTilde[c][0][t]*OverTilde[c][1][t];
\[Alpha]1 = -29/20; \[Alpha]2 = -1/2; \[Alpha]3 = -1;
n = Expand[lagrangianold];
vars = {OverTilde[c][0][t], OverTilde[c][1][t], 
   Derivative[1][OverTilde[c][0]][t], 
   Derivative[1][OverTilde[c][1]][t]};
lagrangianew = 
  Normal[Series[n /. Thread[vars -> m*vars], {m, 0, 3}]] /. m -> 1;
lagrangian = 
  Simplify[
   lagrangianew /. OverTilde[c][0] -> x /. OverTilde[c][1] -> y];

Px = D[lagrangian, x'[t]]; Py = D[lagrangian, y'[t]]; hamiltonian = ((Px x'[t] + Py y'[t]) - lagrangian) /. (Solve[{px[t] == Px, py[t] == Py}, {x'[t], y'[t]}] // Last) // FullSimplify;

{a1, b1, c1, d1} = {D[hamiltonian, px[t]], D[hamiltonian, py[t]], -D[hamiltonian, x[t]], -D[hamiltonian, y[t]]}; hameqns = {x'[t] == a1, px'[t] == c1, y'[t] == b1, py'[t] == d1};

constraint = FullSimplify[ Last[(py0 /. Solve[e == (hamiltonian /. {x[t] -> x0, px[t] -> px0, y[t] -> 0, py[t] -> py0}), py0])]];

PoincareSections[{x0_, px0_, y0_, py0_}, e_, tmax_] := Block[{constraint, x, px, y, py}, constraint = Chop[N[1/ 50 Sqrt[-5 - (9 x0)/10] Sqrt[-2000 e + 500 px0^2 - x0^2 (5290 + 2799 x0)]]]; If[Head[N[constraint]] === Complex, Nothing, If[# == {}, {}, First[#]] &@ Last[Reap[ NDSolve[{hameqns, x[0] == x0, px[0] == px0, y[0] == y0, py[0] == constraint, WhenEvent[y[t], Sow[{x[t], px[t]}], "DetectionMethod" -> "Interpolation"]}, {x, px, y, py}, {t, 0, tmax}, MaxSteps -> [Infinity], StartingStepSize -> 0.1, Method -> {"FixedStep", Method -> {"ExplicitRungeKutta", "DifferenceOrder" -> 8}}]]]]]

style = {PlotStyle -> {{PointSize[.005], Opacity[0.5]}}, AspectRatio -> 1, ImageSize -> 500, PlotRange -> {{-0.0001, 0}, {-0.0001, 0.0001}}, PlotHighlighting -> None, Frame -> True, Background -> Black};

(Off[NDSolve::ndsz])

DynamicModule[{f = {}}, Column[{Dynamic[ MatrixForm@{MousePosition["Graphics", "Mouse not in graphics!"]}], Row[{ClickPane[ Dynamic@ListPlot[f, style], (AppendTo[f, PoincareSections[{#[[1]], #[[2]], 0, 0}, 10^-5, 2000]]) &], Button[Style["Copy orbit list", 12], CopyToClipboard[Iconize[f, "Orbit list"]], ImageSize -> Automatic, Alignment -> Center, Appearance -> {"Palette", "Pressed"}]}, " "]}, Alignment -> Center]]

Figure 1

Using this code we can performed research with step size decreasing.

Alex Trounev
  • 44,369
  • 3
  • 48
  • 106
  • Many thanks for this! Just a small query, when I tried testing with SPRK method, I don't get any points. Here's what I used: Method -> {"SymplecticPartitionedRungeKutta", "DifferenceOrder" -> 8, "PositionVariables" -> {x[t], y[t]}} – codebpr Mar 08 '24 at 04:19
  • 1
    @codebpr Hamiltonian hamiltonian is not separable. Therefore SPRK has been replaced in this case by Automatic method. In turn Automatic method is optimized for variable step size that leads to "StiffnessSwitching" and automatic Stop. – Alex Trounev Mar 08 '24 at 12:39