Poincaré maps

for Mathematica version 6 or later

By Gianluca Gorni, Department of Mathematics and Computer Science, University of Udine, Italy. Latest revision: June 16, 2009.
Thanks to Murray Eisenberg (University of Massachusetts) for his suggestions.

Description: The Poincaré map at time t associated with a (vector) differential equation x'(t)=f(x(t),t) is the map that associates to each starting point (Subscript[x, 0]) the state of the associated solution at the time t. The Poincaré map is important for example in the study of long-term behaviour of solutions, the existence of periodic solutions, and chaos. The package contained in this notebook file defines the following functions:

PoincareMap, PoincareMapPlot and InteracivePoincareMapPlot to help visualize the Poincaré map of a two-dimensional system;

PoincareMapFixedPointDensityPlot, PoincareMapFixedPointPlot3D and FindPoincareMapFixedPoint will assist in locating candidate fixed points of the Poincaré map.

The package is embedded in this notebook file. You load the package by clicking on the following button (whose effect is just to "Evaluate Initialization"), and then you can evaluate the tutorial examples, and make your own variations. Read on for instruction on how to make a more permanent installation.

Button["Click here to load package!",FrontEndTokenExecute["EvaluateInitialization"]]

I wrote the package for myself and for anybody interested. I make no guarantee of any kind. I expect the package to work with Mathematica version 6, but I only tested it with version 7.  A version of the package, called PoincareMaps, is available for Mathematica 5.2 or earlier.

Instructions: load the package by clicking on the button below, then evaluate the examples. This notebook is not meant for absolute beginners of Mathematica. It assumes some familiarity with notebooks and with the syntax of basic standard Mathematica commands such as Plot and ParametricPlot.

If you wish to be able to load this package from other notebooks, you can generate a package file by resetting the notebook option  AutoGeneratedPackage to Automatic. The next time you save this notebook, Mathematica will generate a new package file called PoincareMaps.m inside the same directory as this notebook file. Then you should place this new PoincareMaps.m file somewhere Mathematica will find it, for example in the directory that you will get from evaluating the following command:

ToFileName[{$UserAddOnsDirectory,"Applications"}]

Mathematica package

This is the program. It is meant to be read only by Mathematica programmers.

Preliminaries and usage documentation

Off[General::"spell"]

Off[General::"spell1"]

BeginPackage["PoincareMaps6`"];

Unprotect["`*"];
ClearAll["`*"];

PoincareMap::usage=
"PoincareMap[{{x,y},{fx,fy}},{t,t0,t1},{{uMin,uMax},{vMin,vMax}},options] calculates the Poincare map at time t1 starting at time t0 of the differential system x'=fx, y'=fy on on the region uMin<u<uMax, vMin<v<vMax, where u,v are parameters, and the default parameterization is cartesian (i.e., u=x, v=y). If you want (u,v) to be the polar parameters (r,theta) use the option GridParameterization->Polar. You can specify as GridParameterization any function that takes two variables and gives back a 2-element list, like GridParameterization->Function[{u,v},{u^2,v+u}]. PoincareMap will numerically solve the differential system in a rectangular grid of (u,v) points. The number of points in the two directions is governed by the option GridPoints (that behaves like PlotPoints in ParametricPlot3D), that defaults to 5 in each direction. The Poincaré map in the rest of the region is obtained by ListInterpolation.\nExample: PoincareMap[{{x,y},{y,-2x}},{t,0,Pi},{{0,1},{-Pi,Pi}},GridParameterization->Polar].";

PoincareMapPlot::usage=
"PoincareMapPlot[{{x,y},{fx,fy}},{t,t0,t1},{{uMin,uMax},{vMin,vMax}},options] makes a plot of PoincareMap. The syntax for the non-optional arguments is the same as for PoincareMap. The style of the grid lines is governed by the option GridStyle. Normally you get two plots side-by-side: on the left there is the map at time t0 and on the right the map at time t1. With OnlyEndGrid->True you only get the map at time t1. With StackVertical->True you get the two plots stacked vertically instead of horizontally. With Superimposed->True you get the two plots superimposed.\nExample: PoincareMapPlot[{{x,y},{y,-2x}},{t,0,Pi},{{0,1},{-Pi,Pi}},GridParameterization->Polar].";

InteractivePoincareMapPlot::usage=
"InteractivePoincareMapPlot[{{x,y},{fx,fy}},{t,t0,t1},{{uMin,uMax},{vMin,vMax}},options] makes a plot of PoincareMap where you can move the locator in the initial space and see the final position in the final space.";

PoincareMapFixedPointDensityPlot::usage=
"PoincareMapFixedPointDensityPlot[{{x,y},{fx,fy}},{t,t0,t1},{{uMin,uMax},{vMin,vMax}},epsilon,options] helps in visually searching for fixed points in the PoincareMap. It calculates first the PoincareMap phi, then the function d(x,y)=|phi(x,y)-(x,y)|^2, and makes a DensityPlot of Min[d(x,y),epsilon]. This way the regions where d(x,y) is less than epsilon will be highlighted in grey-black, while the rest of the plot will be white. The plot will be parameterized with (u,v), not with (x,y).\nExample: PoincareMapFixedPointDensityPlot[{{x,y},{y,-(x/(1+x^2)+3x(x^2/(1+x^2)))}},{t,0,Pi},{{0,1},{-Pi,Pi}},1/100,GridParameterization->Polar].";

PoincareMapFixedPointPlot3D::usage=
"PoincareMapFixedPointPlot3D[{{x,y},{fx,fy}},{t,t0,t1},{{uMin,uMax},{vMin,vMax}},{u,u0},{v,v0},options] is similar to PoincareMapFixedPointDensityPlotm, but it makes a ParametricPlot3D instead of a DensityPlot. You will have to adjust PlotRange and BoxRatios to see the minima.\nExample: PoincareMapFixedPointPlot3D[{{x,y},{y,-(x/(1+x^2)+3x(x^2/(1+x^2)))}},{t,0,Pi},{{0,1},{-Pi,Pi}},1/100,GridParameterization->Polar].";

FindPoincareMapFixedPoint::usage=
"FindPoincareMapFixedPoint[{{x,y},{fx,fy}},{t,t0,t1},{{uMin,uMax},{vMin,vMax}},{u,u0},{v,v0},options] applies a FindMinimum to PoincareMap with starting point (u0,v0).\nExample: FindPoincareMapFixedPoint[{{x,y},{y,-(x/(1+x^2)+3x(x^2/(1+x^2)))}},{t,0,5},{{.65,.85},{-.1,.1}},{r,.76},{θ,0},GridPoints->{40,11},GridParameterization->Polar].";

PoincareMapGridPoints::usage=
"PoincareMapGridPoints is an option for PhasePlot, PoincareMap, PoincareMapPlot, PoincareMapFixedPointDensityPlot, PoincareMapFixedPointPlot3D and FindPoincareMapFixedPoint. It specifies how many divisions there will be in the u,v directions, just like PlotPoints does for ParametricPlot3D. The default is 5 in each direction.";

GridParameterization::usage=
"GridParameterization is an option for PoincareMap, PoincareMapPlot, PoincareMapFixedPointDensityPlot, PoincareMapFixedPointPlot3D and FindPoincareMapFixedPoint. It specifies how the parameters (u,v) are mapped to (x,y). The default is the identity, that is, ({##}&). A predefined value is GridParameterization->Polar, which is shorthand for GridParameterization->Function[{r,theta},r{Cos[theta],Sin[theta]}]. In general as a value for GridParameterizationyou can give any object c that when in the pattern c[x,y], with numeric x,y, gives a list of two numbers {x,y}.";

Polar::usage=
"Polar is a possible value for the option GridParameterization to be used for PoincareMap, PoincareMapPlot, PoincareMapFixedPointDensityPlot, PoincareMapFixedPointPlot3D and FindPoincareMapFixedPoint. It is shorthand for Function[{r,theta},r{Cos[theta],Sin[theta]}].";

GridStyle::usage=
"GridStyle is an option for PoincareMapPlot and PoincareMapFixedPointDensityPlot. It specifies the style of the grid lines. The default is a hue from 0 to 1/2 in one direction and from 1/2 to 1 in the other direction. With GridStyle->None all lines will be black. To make your own style, just make a list {styleU,styleV} where styleU and styleV are each in the format required by ParametricPlot.";

OnlyEndGrid::usage=
"OnlyEndGrid is an option for PoincareMapPlot. With the default OnlyEndGrid->False you will get two grids, one at the initial and one at the final time. With OnlyEndGrid->True you only get the grid at the final time.";

Superimposed::usage=
"Superimposed is an option for PoincareMapPlot. With the default Superimposed->False you will get two grids, one at the initial and one at the final time in separate plots. With Superimposed->True you only get the two grid superimposed in one plot.";

StackVertical::usage=
"StackVertical is an option for PoincareMapPlot. With the default StackVertical->False you will get two grids, one at the initial and one at the final time, side by side. With StackVertical->True you get the two grid one below the other.";

SamePlotRange::usage=
"SamePlotRange is an option for PoincareMapPlot. With the default SamePlotRange->True you will get two grids, one at the initial and one at the final time, with the same PlotRange. With SamePlotRange->False you get Automatic settings for the PlotRange in each plot separately.";

ParameterSpaceExclusions::usage=
"ParameterSpaceExclusions is an option to specify what exclusions are to be made in plotting. The parameters are here #1 and #2. Example: ParameterSpaceExclusions->{#1==0,#2==3}";

tail

Begin["`Private`"];

Poincaré map and fixed point thereof

Default options and error messages

Options[PoincareMap]={PoincareMapGridPoints->5,GridParameterization->({##}&)};

Options[PoincareMapPlot]={GridStyle->Automatic,OnlyEndGrid->False,Superimposed->False,StackVertical->False,SamePlotRange->True};

PoincareMap::"BadGridPoints"="Bad GridPoints";PoincareMap::"BadParameterization"="Bad GridParameterization";

This utility processes the grid data given by the user into a form more readily usable by the other functions.

baseGrid[{GridUMin_?NumericQ,gridUMax_?NumericQ}/;GridUMin<gridUMax,{GridVMin_?NumericQ,gridVMax_?NumericQ}/;GridVMin<gridVMax,opts___?OptionQ]:=
Module[{hm,grdPrmtrzt,ptsU,ptsV,grdPtsU,grdPtsV,r,θ},
{hm,grdPrmtrzt}={PoincareMapGridPoints,GridParameterization}/.{opts}/.Options[PoincareMap];
{ptsU,ptsV}=Which[MatchQ[hm,{_Integer?Positive,__Integer?Positive}],hm,MatchQ[hm,_Integer?Positive],{hm,hm},True,Message[PoincareMap::"BadGridPoints"];Abort[]];
grdPtsU=GridUMin+(gridUMax-GridUMin)Range[0,ptsU-1]/(ptsU-1);
grdPtsV=GridVMin+(gridVMax-GridVMin)Range[0,ptsV-1]/(ptsV-1);
Which[
grdPrmtrzt===Polar,grdPrmtrzt=Function[{r,θ},r{Cos[θ],Sin[θ]}],grdPrmtrzt===Identity,grdPrmtrzt=({##}&),Not[And[Map[NumericQ,grdPrmtrzt[GridUMin,GridVMin]]]],Message[PoincareMapPlot::"BadParameterization";Abort[]]];
{grdPtsU,grdPtsV,grdPrmtrzt}];

This utility plots a parametric grid.

gridPlot[grdPtsU_List,grdPtsV_List,grdPrmtrzt_,opts___?OptionQ]:=Module[{grdstl,ptsU,ptsV,stlU,stlV,a,b,trajU,trajV},grdstl=GridStyle/.{opts}/.Options[PoincareMapPlot];{ptsU,ptsV}=Length/@{grdPtsU,grdPtsV};stlU=Which[grdstl===Automatic,({Hue[#1]}&)/@((Range[0,ptsV])/(2 ptsV)),grdstl==None,Array[{}&,grdPtsV],True,grdstl[[1]]];stlV=Which[grdstl===Automatic,({Hue[#1]}&)/@(-((Range[1,ptsU])/(2 ptsU))),grdstl==None,Array[{}&,grdPtsU],True,grdstl[[2]]];trajU=ParametricPlot[Evaluate[(grdPrmtrzt[a,#1]&)/@grdPtsV],{a,Min[grdPtsU],Max[grdPtsU]},PlotStyle->stlU,Evaluate[Sequence@@FilterRules[Flatten[{opts}],Options[ParametricPlot]]]];trajV=ParametricPlot[Evaluate[(grdPrmtrzt[#1,b]&)/@grdPtsU],{b,Min[grdPtsV],Max[grdPtsV]},PlotStyle->stlV,Evaluate[Sequence@@FilterRules[Flatten[{opts}],Options[ParametricPlot]]]];Show[{trajU,trajV},Sequence@@FilterRules[Flatten[{opts}],Options[Graphics]],Sequence@@FilterRules[Flatten[{Sequence@@Options[PoincareMapPlot]}],Options[Graphics]]]];

This function calculates the Poincaré map on a grid of points and interpolates between the values.

PoincareMap[data___]=internalPoincareMap[data];

Clear[internalPoincareMap];

internalPoincareMap[{{x_Symbol,y_Symbol},{xprime_,yprime_}},{t_Symbol,t0_?NumericQ,tMax_?NumericQ},{{GridUMin_?NumericQ,gridUMax_?NumericQ}/;GridUMin<gridUMax,{GridVMin_?NumericQ,gridVMax_?NumericQ}/;GridVMin<gridVMax},opts___?OptionQ]:=internalPoincareMap[{{x,y},{xprime,yprime}},{t,t0,tMax},{{GridUMin,gridUMax},{GridVMin,gridVMax}},opts]=Module[{grdPtsU,grdPtsV,grdPrmtrzt,strtPtsGrid,endPt,x0,y0,u,v,endPtsGrid,pairOfInterp},{grdPtsU,grdPtsV,grdPrmtrzt}=baseGrid[{GridUMin,gridUMax},{GridVMin,gridVMax},opts];strtPtsGrid=Apply[grdPrmtrzt,Outer[List,grdPtsU,grdPtsV],{2}];endPt[x0_,y0_]:={u[tMax],v[tMax]}/.NDSolve[{u'[t]==xprime,v'[t]==yprime,u[0]==x0,v[0]==y0}/.{x->u[t],y->v[t]},{u,v},{t,t0,tMax},Sequence@@FilterRules[Flatten[{opts}],Options[NDSolve]]][[1]];endPtsGrid=Apply[endPt,strtPtsGrid,{2}];pairOfInterp=(ListInterpolation[#1,{{GridUMin,gridUMax},{GridVMin,gridVMax}}]&)/@Transpose[endPtsGrid,{2,3,1}];Evaluate[Through[pairOfInterp[#1,#2]]]&];

This function plots the Poincaré map.

PoincareMapPlot[{{x_Symbol,y_Symbol},{xprime_,yprime_}},{t_Symbol,t0_?NumericQ,tMax_?NumericQ},{{GridUMin_?NumericQ,gridUMax_?NumericQ}/;GridUMin<gridUMax,{GridVMin_?NumericQ,gridVMax_?NumericQ}/;GridVMin<gridVMax},opts___?OptionQ]:=Module[{onlyEndQ,superImpQ,stkVertQ,samePR,grdPtsU,grdPtsV,grdPrmtrzt,baseGridPlot,poinc,poincPlot,plRng},{onlyEndQ,superImpQ,stkVertQ,samePR}={OnlyEndGrid,Superimposed,StackVertical,SamePlotRange}/.{opts}/.Options[PoincareMapPlot];{grdPtsU,grdPtsV,grdPrmtrzt}=baseGrid[{GridUMin,gridUMax},{GridVMin,gridVMax},opts];baseGridPlot:=gridPlot[grdPtsU,grdPtsV,grdPrmtrzt,opts];poinc=PoincareMap[{{x,y},{xprime,yprime}},{t,t0,tMax},{{GridUMin,gridUMax},{GridVMin,gridVMax}},opts];poincPlot=gridPlot[grdPtsU,grdPtsV,poinc,opts];plRng:=If[samePR==True,If[$VersionNumber<4,PlotRange->FullOptions[Show[{baseGridPlot,poincPlot}],PlotRange],AbsoluteOptions[Show[{baseGridPlot,poincPlot}],PlotRange]],Sequence@@{}];Show[Which[onlyEndQ===True,poincPlot,superImpQ,{baseGridPlot,poincPlot},stkVertQ,GraphicsGrid[{{Show[baseGridPlot,plRng]},{Show[poincPlot,plRng]}}],True,GraphicsRow[{Show[baseGridPlot,plRng],Show[poincPlot,plRng]}]],Sequence@@FilterRules[Flatten[{opts}],Options[Graphics]]]];

PoincareMaps6`PoincareMapPlot[{{0.9999998571428571`,y},{y,-1.9999995714285814`}},{t,0,5},{{0,2},{-π,π}}]

InteractivePoincareMapPlot[{{x_Symbol,y_Symbol},{xprime_,yprime_}},{t_Symbol,t0_?NumericQ,tMax_?NumericQ},{{GridUMin_?NumericQ,gridUMax_?NumericQ}/;GridUMin<gridUMax,{GridVMin_?NumericQ,gridVMax_?NumericQ}/;GridVMin<gridVMax},opts___?OptionQ]:=Module[{onlyEndQ,superImpQ,stkVertQ,samePR,grdPtsU,grdPtsV,grdPrmtrzt,baseGridPlot,poinc,poincPlot,plRng},{onlyEndQ,superImpQ,stkVertQ,samePR}={OnlyEndGrid,Superimposed,StackVertical,SamePlotRange}/.{opts}/.Options[PoincareMapPlot];{grdPtsU,grdPtsV,grdPrmtrzt}=baseGrid[{GridUMin,gridUMax},{GridVMin,gridVMax},opts];baseGridPlot=gridPlot[grdPtsU,grdPtsV,grdPrmtrzt,opts];poinc=PoincareMap[{{x,y},{xprime,yprime}},{t,t0,tMax},{{GridUMin,gridUMax},{GridVMin,gridVMax}},opts];poincPlot=gridPlot[grdPtsU,grdPtsV,poinc,opts];plRng=AbsoluteOptions[Show[{baseGridPlot,poincPlot},PlotRange->All],PlotRange];
Manipulate[GraphicsRow[{Show[{baseGridPlot,Graphics[{PointSize[Large],Point[grdPrmtrzt@@p]}]},plRng,Sequence@@FilterRules[Flatten[{opts}],Options[Graphics]],ImageSize->300],Show[{poincPlot,Graphics[{PointSize[Large],Point[poinc@@p]}]},plRng,Sequence@@FilterRules[Flatten[{opts}],Options[Graphics]]]}],
{{p,{GridUMin,GridVMin},"Point in parameter space"},{GridUMin,GridVMin},{gridUMax,gridVMax}},Deployed->True]];

Let φ(x,y) be the Poincaré map at some time for some system. Consider the function ψ(x,y):=∥φ(x,y)-(x,y)(∥^2). The following function makes a DensityPlot of Min[ψ(x,y),ϵ] for a give tolerance ϵ. This way the point of the plot that are gray to black are candidates for being a fixed point for φ.

PoincareMapFixedPointDensityPlot[{{x_Symbol,y_Symbol},{xprime_,yprime_}},{t_Symbol,t0_?NumericQ,tMax_?NumericQ},{{GridUMin_?NumericQ,gridUMax_?NumericQ}/;GridUMin<gridUMax,{GridVMin_?NumericQ,gridVMax_?NumericQ}/;GridVMin<gridVMax},tolerance_:(1/100),opts___?OptionQ]/;tolerance>0:=
Module[{grdPtsU,grdPtsV,grdPrmtrzt,poinc,diff,u,v},{grdPtsU,grdPtsV,grdPrmtrzt}=baseGrid[{GridUMin,gridUMax},{GridVMin,gridVMax},opts];
excl=ParameterSpaceExclusions/.{opts}/.{Exclusions->Automatic}/.{#1->u,#2->v};
rectGrid=Last[baseGrid[{GridUMin,gridUMax},{GridVMin,gridVMax},GridParameterization->Identity,opts]];poinc=PoincareMap[{{x,y},{xprime,yprime}},{t,t0,tMax},{{GridUMin,gridUMax},{GridVMin,gridVMax}},opts];diff[u_,v_]:=(#1.#1&)[poinc[u,v]-grdPrmtrzt[u,v]];Show[{DensityPlot[Min[diff[u,v],tolerance],{u,GridUMin,gridUMax},{v,GridVMin,gridVMax},Exclusions->excl,Evaluate[Sequence@@FilterRules[Flatten[{opts}],Options[DensityPlot]]],Mesh->False],gridPlot[grdPtsU,grdPtsV,rectGrid,PlotPoints->2]},Sequence@@FilterRules[Flatten[{opts}],Options[Graphics]],PlotRange->All]];

The following function makes a 3D plot of the function ψ  instead of a DensityPlot as above.

PoincareMapFixedPointPlot3D[{{x_Symbol,y_Symbol},{xprime_,yprime_}},{t_Symbol,t0_?NumericQ,tMax_?NumericQ},{{GridUMin_?NumericQ,gridUMax_?NumericQ}/;GridUMin<gridUMax,{GridVMin_?NumericQ,gridVMax_?NumericQ}/;GridVMin<gridVMax},opts___?OptionQ]:=Module[{grdPtsU,grdPtsV,grdPrmtrzt,excl,poinc,diff,u,v},{grdPtsU,grdPtsV,grdPrmtrzt}=baseGrid[{GridUMin,gridUMax},{GridVMin,gridVMax},opts];
excl=ParameterSpaceExclusions/.{opts}/.{Exclusions->Automatic}/.{#1->u,#2->v};
poinc=PoincareMap[{{x,y},{xprime,yprime}},{t,t0,tMax},{{GridUMin,gridUMax},{GridVMin,gridVMax}},opts];diff[u_,v_]:=(#1.#1&)[poinc[u,v]-grdPrmtrzt[u,v]];ParametricPlot3D[Join[grdPrmtrzt[u,v],{diff[u,v]}],{u,GridUMin,gridUMax},{v,GridVMin,gridVMax},Exclusions->excl,Evaluate[Sequence@@FilterRules[Flatten[{opts}],Options[ParametricPlot3D]]],MeshFunctions->{#3&},Mesh->{Range[0,1,1/10]^2},MeshShading->Map[ColorData["CMYKColors"],Range[0,1,1/10]],AxesLabel->{"x","y","(d^2)"}]];

The following function tries to find a fixed point of the Poincaré map by minimizing the function ψ defined above near a point (u0,v0) given by the user.

FirstSmallest[x_,f_]:=x[[Position[#,Min[#],1,1][[1,1]]]]&[f/@x];

FindPoincareMapFixedPoint[{{x_Symbol,y_Symbol},{xprime_,yprime_}},{t_Symbol,t0_?NumericQ,tMax_?NumericQ},{{GridUMin_?NumericQ,gridUMax_?NumericQ}/;GridUMin<gridUMax,{GridVMin_?NumericQ,gridVMax_?NumericQ}/;GridVMin<gridVMax},{uFixed_Symbol,vFixed_Symbol},opts___?OptionQ]:=
Module[{grdPtsU,grdPtsV,grdPrmtrzt,poinc,diff,a,b},
{grdPtsU,grdPtsV,grdPrmtrzt}=baseGrid[{GridUMin,gridUMax},{GridVMin,gridVMax},opts];
poinc=PoincareMap[{{x,y},{xprime,yprime}},{t,t0,tMax},{{GridUMin,gridUMax},{GridVMin,gridVMax}},opts];
diff[{a_,b_}]:=(poinc[a,b][[1]]-grdPrmtrzt[a,b][[1]])^2+(poinc[a,b][[2]]-grdPrmtrzt[a,b][[2]])^2;
strtPts=Flatten[Outer[List,grdPtsU,grdPtsV],1];
fxdPt=FirstSmallest[strtPts,diff];
{diff[fxdPt],Thread[{uFixed,vFixed}->fxdPt]}];

Tail end

End[];

Protect["`*"];

EndPackage[];

On[General::"spell1"]

On[General::"spell"]

Examples

Clear[x,y,t]

Evaluate the input cells below to see the package in action and learn its usage.

Simple examples of Poincaré map plots

PoincareMapPlot takes a system of two differential equations of the form {({{x'=a(t,x,y)}, {y'=b(t,x,y)}})and draws the initial and final position of a user-specified grid under the Poincaré map at a given time. The system is specified with the syntax {{x,y},{a,b}}, where x,y are variable names and a,b the right-hand sides:

field={{x,y},{1/(1+x^2),-y+x}};

The grid is given as {{xmin,xmax},{ymin,ymax}}.

grid={{0,1},{0,1}};

Here is the graph of the Poincaré map at time 1/2 with all default settings. On the left is the original grid at time 0, and on the right where the grid has drifted at time 1/2

PoincareMapPlot[field,{t,0,1/2},grid]

With the option PoincareMapGridPoints you can control the number of lines in the grid. The default is 5 in each direction:

PoincareMapPlot[field,{t,0,1/2},grid,PoincareMapGridPoints->{3,5}]

The grid does not need to be cartesian. You can assign a polar grid, for example:

PoincareMapPlot[field,{t,0,1/2},{{0,1},{0,2π}},GridParameterization->Polar,AspectRatio->Automatic,PoincareMapGridPoints->{5,10}]

You can have an arbitrarily parameterized grid:

PoincareMapPlot[field,{t,0,1/2},{{0,1},{0,1}},GridParameterization->Function[{a,b},{a+b,a-b}],AspectRatio->Automatic,PoincareMapGridPoints->{5,10}]

You can stack the two plots vertically:

PoincareMapPlot[field,{t,0,1/2},{{0,1},{0,1}},GridParameterization->Function[{a,b},{a+b,a-b}],AspectRatio->Automatic,PoincareMapGridPoints->{5,10},StackVertical->True]

You can also decide to draw the final grid only:

PoincareMapPlot[field,{t,0,1/2},{{0,1},{0,1}},GridParameterization->Function[{a,b},{a+b,a-b}],AspectRatio->Automatic,PoincareMapGridPoints->{5,10},OnlyEndGrid->True,AxesOrigin->{0,0}]

You can also have the initial and final grid superimposed:

PoincareMapPlot[field,{t,0,1/2},{{0,1},{0,1}},GridParameterization->Function[{a,b},{a+b,a-b}],AspectRatio->Automatic,PoincareMapGridPoints->{5,10},Superimposed->True]

By default the initial and final grid are drawn with the same PlotRange. You can override this behaviour and let each plot go on its own with the option SamePlotRange->False.

PoincareMapPlot[field,{t,0,1},{{0,1},{0,1}},GridParameterization->Function[{a,b},{a+b,a-b}],PoincareMapGridPoints->{5,10},SamePlotRange->False]

Poincaré map of x''(t)=-f(x(t)), and search for periodic solutions of a given period.

Take the following function of one variable

f=x/(1+x^2)+3x(x^2/(1+x^2));

Here in red is the graph of f. Near x=0 we have f(x)≈x, while f(x)≈3x for large x.

Plot[{x,f,3 x},{x,0,4},PlotStyle->{Dashed,Directive[Thick,Red],Dashed},AspectRatio->1]

Solutions to x''(t)=-f(x(t)) that start with small values of (x^2)+(((x'))^2) will be periodic of period approximately  2π≈6.28, and those with (x^2)+(((x'))^2)large will have period approximately  ((2 π)/(Sqrt[3]))≈3.63. We will try to locate a solution with an intermediate period, namely 5.

The program wants the second-order differential equation x''(t)=-f(x(t)) to be framed as a system of first-order equation of the general form {({{x'=a(t,x,y)}, {y'=b(t,x,y)}}), and the data to be arranged as {{x,y},{a(t,x,y),b(t,x,y)}}:

field={{x,y},{y,-f}};

Let us take a polar grid with 0≤r≤2, -π≤θ≤π:

grid={{0,2},{-π,π}};

Here is the graph of the Poincaré map at time 5:

PoincareMapPlot[field,{t,0,5},grid,PoincareMapGridPoints->{10,41},GridParameterization->Polar,AspectRatio->Automatic]

The plot on the left is the starting grid, while on the right you see the position of the grid lines after the map is applied. If for any reason you only want the plot on the right just add the option OnlyEndGrid->True:

PoincareMapPlot[field,{t,0,5},grid,PoincareMapGridPoints->{10,41},GridParameterization->Polar,AspectRatio->Automatic,OnlyEndGrid->True]

You can also have the two grids on top of each other with the option Superimposed->True. You had better do that with less dense grids than the present one. You will se an example later.

If  ϕ(x,y) the Poincaré map at time 5, consider the real function d(x,y):=∥ϕ(x,y)-(x,y)(∥^2). A very small value for d means a solution pretty much periodic with period 5. Here is a 3D plot of  d(x,y):

PoincareMapFixedPointPlot3D[field,{t,0,5},grid,PoincareMapGridPoints->{10,41},GridParameterization->Polar,PlotRange->All,BoxRatios->{1, 1, 1/2}]

With a density plot of Min[d(x,y),ϵ] the regions where d(x,y)is smaller than ϵ will stand out as grey or black against a white background. In the following picture ϵ=1/100. The parameters on the two axes are not x, y but r,θ:

PoincareMapFixedPointDensityPlot[field,{t,0,5},grid,1/100,PoincareMapGridPoints->{20,41},PlotPoints->{50,50},GridParameterization->Polar,FrameLabel->{"r","θ"}]

You will see two distinct grey-black stripes: one around  r=0, which corresponds to the trivial periodic solution x(t)≡y(t)≡0, whilst the other seems to be the graph of a function from θ to r. Let us zoom around the gray point r=.75, θ=0:

PoincareMapFixedPointDensityPlot[field,{t,0,5},{{.65,.85},{-.2,.2}},1/1000,PoincareMapGridPoints->{20,21},PlotPoints->{20,20},GridParameterization->Polar,FrameLabel->{"r","θ"}]

Let us close in on the fixed point by minimizing the function  d near  r=.756, θ=0 with the built-in minimization routines:

{squareDistance,initialData}=FindPoincareMapFixedPoint[field,{t,0,5},{{.65,.85},{-.1,.1}},{r0,θ0},PoincareMapGridPoints->{40,11},GridParameterization->Polar]

Here is a plot of the solution corresponding the fixed point found above, seen as a function t↦x(t):

solutionX=NDSolve[{x''[t]==(-f/.x->x[t]),x[0]==r0 Cos[θ0]/.initialData,x'[0]==0},x,{t,0,5}];
Plot[x[t]/.solutionX,{t,0,5}]

A check to see how much the values at t=0 and t=5 are close to each other:

{x[5]-x[0],x'[5]-x'[0]}/.solutionX

A graph of our periodic solution in the phase space, i.e., seen as a function t↦(x(t),y(t)):

solutionXY=NDSolve[{x'[t]==y[t],y'[t]==(-f/.x->x[t]),x[0]==r0 Cos[θ0]/.initialData,y[0]==0},{x,y},{t,0,5}];
phaseSpacePlot=ParametricPlot[{x[t],y[t]}/.solutionXY,{t,0,5},AspectRatio->Automatic,PlotStyle->{Thickness[0.007],Dashing[{0.02,0.04}]}]

The following picture superimposes the 5-periodic solution to the Poincare map plot:

Show[{PoincareMapPlot[field,{t,0,5},grid,PoincareMapGridPoints->{10,41},GridParameterization->Polar,OnlyEndGrid->True,AspectRatio->Automatic,DisplayFunction->Identity],phaseSpacePlot}]

A zoom of Poincaré map around the starting point of the 5-periodic solution, with the initial and the final grids superimposed:

Show[{phaseSpacePlot,PoincareMapPlot[field,{t,0,5},{0.756650394233193`+{-0.1`,0.1`},{-0.05`,0.05`}},PoincareMapGridPoints->{7,5},GridParameterization->Polar,Superimposed->True,AspectRatio->Automatic]},PlotRange->{{0.62`,0.86`},{-0.282`,0.22`}},Frame->True,Axes->False]

Animated Poincaré maps

Plots of Poincaré maps at a sequence of times can be shown as a movie:

f=x/(1+x^2)+3x(x^2/(1+x^2));
field={{x,y},{y,-f}};
grid={{1/4,2},{-1,1}};
filmFrame[instant_]:=filmFrame[instant]=PoincareMapPlot[field,{t,0,instant},grid,OnlyEndGrid->True,PoincareMapGridPoints->{5,5},GridParameterization->Polar,AspectRatio->Automatic,PlotRange->{{-3,3},{-3,3}},AxesOrigin->{0,0}];

ListAnimate[Table[filmFrame[τ],{τ,0,5,1/5}]]

Poincaré map of x''(t)=-f(t,x(t)), and search for periodic solutions of period 2π.

Take a function f(t,x) that is 2π-periodic with respect to t and that is asymptotic to x/2 as x->0 and to 3x as x->+∞:

f=x/(2+x^2)+3x(x^2/(1+x^2))+x^2*Cos[t]/(3x^4+2);

Solutions to x''(t)=-f(t,x(t)) that start with small values of (x^2)+(((x'))^2) will be periodic of period approximately  (Sqrt[8])π≈8.9, and those with (x^2)+(((x'))^2)large will have period approximately  ((2 π)/(Sqrt[3]))≈3.63. We will try to locate solutions which are periodic with the same t-period as f(t,x), that is, 2π-periodic solutions. Any such solution will correspond to a fixed point for the Poincaré map at time 2π.

field={{x,y},{y,-f}};

grid={{0,2},{-π,π}};

Here is a plot of Poincaré map:

PoincareMapPlot[field,{t,0,2π},grid,PoincareMapGridPoints->{20,41},GridParameterization->Polar,AspectRatio->Automatic]

An interactive version of the previous plot, where you can move the initial point and the corresponding final point:

InteractivePoincareMapPlot[field,{t,0,2π},{{0,2},{-π,π}},PoincareMapGridPoints->{20,41},GridParameterization->Polar,AspectRatio->Automatic]

If  ϕ(x,y) the Poincaré map at time  2π, consider the real function d(x,y):=∥ϕ(x,y)-(x,y)(∥^2). A very small value for d means a solution pretty much periodic with period 2π. With a density plot of Min[d(x,y),ϵ] the regions where d(x,y)is smaller than ϵ will stand out as grey or black against a white background. In the following picture ϵ=1/1000. The parameters on the two axes are not x,y but r,θ:

PoincareMapFixedPointDensityPlot[field,{t,0,2π},grid,1/300,PoincareMapGridPoints->{40,81},GridParameterization->Polar,FrameLabel->{"r","θ"}]

We make out one grey stripe plus two grey spots. The stripe around r=0 corresponds to the trivial null solution. The two grey spots are approximately at the points (.45,0) and (.7,±π).

A 3D plot of d(x,y):=∥ϕ(x,y)-(x,y)(∥^2); we see three dips, one in the origin (corresponding to the trivial constant solution), an elongated one around (.4,0), and another elengated one around (-.6,0) (in cartesian coordinates):

PoincareMapFixedPointPlot3D[field,{t,0,2π},grid,PoincareMapGridPoints->{40,81},GridParameterization->Polar,PlotRange->{{-.91,.6},{-.8,1},{0,1/2}}]

A zoom around (.45,0) (polar coordinates):

PoincareMapFixedPointDensityPlot[field,{t,0,2π},{{.42,.48},{-.5,.5}},1/10000,PoincareMapGridPoints->{40,41},PlotPoints->{50,50},GridParameterization->Polar,FrameLabel->{"r","θ"}]

Minimizing d(x,y) we close in on the fixed point:

{squareDistance1,initialData1}=FindPoincareMapFixedPoint[field,{t,0,2π},{{.42,.48},{-.5,.5}},{r0,θ0},PoincareMapGridPoints->{40,11},GridParameterization->Polar]

Here is a plot of the solution corresponding the fixed point found above, seen as a function t↦x(t):

solutionX1=NDSolve[{x''[t]==(-f/.x->x[t]),x[0]==r0 Cos[θ0]/.initialData1,x'[0]==0},x,{t,0,2 π}];
Plot[x[t]/.solutionX1,{t,0,2 π},Ticks->{Range[0,2Pi,Pi/2],Automatic}]

A check to see how much the values at t=0 and t=2π are close to each other:

{x[2π]-x[0],x'[2π]-x'[0]}/.solutionX1

A graph of our periodic solution in the phase space, i.e., seen as a function t↦(x(t),y(t)):

solutionXY1=NDSolve[{x'[t]==y[t],y'[t]==(-f/.x->x[t]),x[0]==r0 Cos[θ0]/.initialData1,y[0]==0},{x,y},{t,0,2 π}];
ParametricPlot[{x[t],y[t]}/.solutionXY1,{t,0,2 π},AspectRatio->Automatic]

A zoom of Poincaré map around the starting point of this 2π-periodic solution, with the initial and the final grids superimposed:

PoincareMapPlot[field,{t,0,2π},{{0.44404-.1,0.44404+.1},{-.1,.1}},PoincareMapGridPoints->{5,5},GridParameterization->Polar,AspectRatio->Automatic,Superimposed->True,Frame->True,Axes->False]

A zoom of the density plot around the second grey spot, the one near (.7,±π):

PoincareMapFixedPointDensityPlot[field,{t,0,2π},{{.6,.8},{π-.1,π+.1}},1/10000,PoincareMapGridPoints->{40,41},PlotPoints->{50,50},GridParameterization->Polar,FrameLabel->{"r","θ"}]

Minimize d(x,y) in that spot:

{squareDistance2,initialData2}=FindPoincareMapFixedPoint[field,{t,0,2π},{{.6,.8},{3,3.2}},{r0,θ0},PoincareMapGridPoints->{40,11},GridParameterization->Polar]

Here is a plot of the solution corresponding the second fixed point, seen as a function t↦x(t):

solutionX2=NDSolve[{x''[t]==(-f/.x->x[t]),x[0]==r0 Cos[θ0]/.initialData2,x'[0]==0},x,{t,0,2 π}];
Plot[x[t]/.solutionX2,{t,0,2 π},Ticks->{Range[0,2Pi,Pi/2],Automatic}]

A check to see how much the values at t=0 and t=2π are close to each other:

{x[2Pi]-x[0],x'[2Pi]-x'[0]}/.solutionX2

A graph of our second periodic solution in the phase space, i.e., seen as a function t↦(x(t),y(t)):

solutionXY2=NDSolve[{x'[t]==y[t],y'[t]==(-f/.x->x[t]),x[0]==r0 Cos[θ0]/.initialData2,y[0]==0},{x,y},{t,0,2 π}];
ParametricPlot[{x[t],y[t]}/.solutionXY2,{t,0,2 π},AspectRatio->Automatic]

The two periodic solutions together:

ParametricPlot[Evaluate[{x[t],y[t]}/.{solutionXY1,solutionXY2}],{t,0,2 π},AspectRatio->Automatic]

A zoom of Poincaré map around the starting point of the second 2π-periodic solution, with the initial and the final grids superimposed:

PoincareMapPlot[field,{t,0,2π},{{0.70769-.1,0.70769+.1},{π-.1,π+.1}},PoincareMapGridPoints->{5,5},GridParameterization->Polar,AspectRatio->Automatic,Superimposed->True,Frame->True,Axes->False]

Poincaré map of x''(t)=-f(x(t)) for which there is an invariant annulus

Consider this function of x:

f=2x^3;

The solutions of x''=-f(x) starting with small (x^2)+(((x'))^2) will have large period, while the ones starting with large (x^2)+(((x'))^2) will have small period. We set out to find periodic solutions with period 4.

The orbits of this system, seen as {({{x'=y}, {y'=-f(x)}}) lie on the level sets of the function (x,y)↦(x^4)+(y^2), which look somewhat like ellipses. What follows is a pseudo-polar parameterization of the plane where  θ is the usual argument but r=(Sqrt[(x^4)+(y^2)]). The advantage of this parameterization is that the sets r=constant coincide with the level sets of (x,y)↦(x^4)+(y^2). The main parameterization has a singularity along the y-axis, so that we need a separate formula for that case.

myParameterization[r_?NumericQ,θ_?NumericQ/;Abs[Cos[θ]]<$MachineEpsilon]={0,r*Sign[Sin[θ]]};
myParameterization[r_?NumericQ,θ_?NumericQ/;Abs[Cos[θ]]≥$MachineEpsilon]=Sign[Cos[θ]](Sqrt[-(1/2) ((Tan[θ])^2)+(1/2) (Sqrt[4 (r^2)+((Tan[θ])^4)])]){1,Tan[θ]};

Since the system is autonomous, if there is a solution with period 4, all points (x(t),y(t)) along its trajectory are starting points of a solution with period 4. Hence the fixed points of the Poincaré map are not isolated points, but a whole line. Actually, it will be a whole level set of the function (x,y)↦(x^4)+(y^2).

The data structure for the differential system:

field={{x,y},{y,-f}};

Let us take a pseudo-polar grid with 1≤r≤2, -π≤θ≤π:

grid={{1,2},{-π,π}};

A plot of the Poincaré map at time 4:

PoincareMapPlot[field,{t,0,4},grid,PoincareMapGridPoints->{7,25},GridParameterization->myParameterization,AspectRatio->Automatic]

InteractivePoincareMapPlot[field,{t,0,4},grid,PoincareMapGridPoints->{7,25},GridParameterization->myParameterization,AspectRatio->Automatic]

If  ϕ(x,y) the Poincaré map at time 4, consider the real function d(x,y):=∥ϕ(x,y)-(x,y)(∥^2). A very small value for d means a solution pretty much periodic with period 4. Here is a 3D plot of  d(x,y); we give Exclusions to avoid trouble at θ==±π/2:

PoincareMapFixedPointPlot3D[field,{t,0,4},grid,PoincareMapGridPoints->{10,41},PlotPoints->{20,41},GridParameterization->myParameterization,PlotRange->{{-1.5,1.5},{-2,2},{0,1/4}},ParameterSpaceExclusions->{#2==Pi/2,#2==-Pi/2}]

With a density plot of Min[d(x,y),ϵ] the regions where d(x,y)is smaller than ϵ will stand out as grey or black against a white background. In the following picture ϵ=1/100. The parameters on the two axes are not x,y but r,θ:

PoincareMapFixedPointDensityPlot[field,{t,0,4},grid,1/100,PoincareMapGridPoints->{20,41},PlotPoints->{50,50},GridParameterization->myParameterization,FrameLabel->{"r","θ"}]

We make out a grey-black stripe that looks like the graph of a set  r=constant. Let us zoom in on the point r=1.72, θ=0:

PoincareMapFixedPointDensityPlot[field,{t,0,4},{{1.6,1.8},{-.2,.2}},1/1000,PoincareMapGridPoints->{20,21},PlotPoints->{20,20},GridParameterization->myParameterization,FrameLabel->{"r","θ"}]

Let us minimize d on a grid of points in the rectangle 1.6≤r≤1.8, -.2≤θ≤.2:

{squareDistance,initialData}=FindPoincareMapFixedPoint[field,{t,0,4},{{1.6,1.8},{-.2,.2}},{r0,θ0},PoincareMapGridPoints->{40,21},GridParameterization->myParameterization]

Here is a plot of the solution corresponding the fixed point found above, seen as a function t↦x(t):

solutionX=NDSolve[{x''[t]==(-f/.x->x[t]),x[0]==(myParameterization[r0,θ0]/.initialData)[[1]],x'[0]==(myParameterization[r0,θ0]/.initialData)[[2]]},x,{t,0,4}];
Plot[x[t]/.solutionX,{t,0,4}]

A check to see how much the values at t=0 and t=4 are close to each other:

{x[4]-x[0],x'[4]-x'[0]}/.solutionX

A graph of our 4-periodic solution in the phase space, i.e., seen as a function t↦(x(t),y(t)):

solutionXY=NDSolve[{x'[t]==y[t],y'[t]==(-f/.x->x[t]),x[0]==(myParameterization[r0,θ0]/.initialData)[[1]],y[0]==(myParameterization[r0,θ0]/.initialData)[[2]]},{x,y},{t,0,4}];
ParametricPlot[{x[t],y[t]}/.solutionXY,{t,0,4},AspectRatio->Automatic]