— Clayton Shonkwiler
Originally created December, 2022, updated November, 2023. Supported by NSF DMS–2107700.
This animation was inspired by Daniel Piker and Etienne Jacob. The math behind it is explained well in this post on the n-Category Café by Simon Willerton.
One way to think about what’s going on is that the the group
G=
t
e
0
0
-t
e

is acting on the plane (in the picture the plane is
2

and
t∈
, but I’m really thinking about the action on
2

when
t∈
). This action is pretty much the simplest possible action which motivates the notion of a Geometric Invariant Theory quotient (see Thomas' very nice survey [arXiv version]): if this group acts on points of the form
(x,y)
, then the product
xy
is conserved, so each nonzero number
λ
corresponds to an orbit which is just the hyperbola
xy=λ
. However, there are three different orbits for which
xy=0
, namely the two axes (with the origin removed) and the origin itself. Unfortunately, the closures of these three orbits intersect, so the orbit space is non-Hausdorff unless we do something slightly more sophisticated. In GIT, the upshot is to identify the three orbits and then the quotient is just a copy of the line (i.e.,

in the complex case). We can also projectivize and think of a


action on
2

, with GIT quotient isomorphic to
1

, as in this talk.
However, there’s rather more going on here. If we think of a lattice
Λ
in the plane
2

, then we can think of
G
as acting on
Λ
. Of course, this will generally change the lattice, but if we choose the lattice very carefully, we can get a periodic action: after some finite
t
0
, the lattice comes back to itself (even though the individual points have of course moved). That is the modular flow, and getting the lattice right is the hard part of the visualization.
First, we grab a good color palette developed by Fabio Crameri:
In[]:=
ColorMapSuitePath=NotebookDirectory[]<>"../colors/ScientificColourMaps7";​​ColorMapSuite[name_String]:=ColorMapSuite[name,-1]​​ColorMapSuite[name_String,el_]:=With[{list=Transpose@{Subdivide[0,1,255],RGBColor@@@First@Import[ColorMapSuitePath<>"/"<>name<>"/"<>name<>".mat"]}},Blend[list,{##}[[el]]]&]
Now, our lattice will be points of the form
P
x
y

, where
P=
-1
-
2
1
-
2
and

x
y
∈
2

is an integer point in the plane. Our final view will be the square
2
[-10,10]
, so we need to keep track of all the points that will enter that square at some point in the animation, which is what pts is doing.
In[]:=
P=-1,-
2
,1,-
2
;​​ct[{x_,y_}]:=
1
2
Log
2
x
-2
2
xy+2
2
y
2
x
+2
2
xy+2
2
y
;​​pts=SelectFlatten[Table[{x,y},{x,-30,30},{y,-30,30}],1],AbsDiagonalMatrix
ct[#]
E
,
-ct[#]
E
.P.#[[1]]<=10.5&;
In the final animation, the points have tails on them. Since the tails will overlap other points, we need to sort the points appropriately to make sure that the points are layered in an appropriate way.
In[]:=
sort=DeleteDuplicates[SortBy[pts,Abs[N[(P.#)][[2]]]&]];
Now we build the table of frames in the animation:
In[]:=
flow=With{cols=Append[#[[2]],#[[1]]]&/@ColorMapSuite["oslo"][[1,1]]},​​ParallelTable​​Show[​​Table[​​ParametricPlot[DiagonalMatrix[{
s
E
,
-s
E
}].P.Append[sort,{0,0}][[i]],{s,t-.5,t},PlotRange->10,ColorFunction(If[i==Length[pts]+1,cols[[-1]],Blend[cols,2(#3-t+.5)]]&),ColorFunctionScalingFalse,Axes->False,PlotStyleDirective[Thickness[.02],CapForm["Round"]]],​​{i,1,Length[pts]+1}],​​ImageSize270,Backgroundcols[[1,;;-2]]],​​t,0.,2Log[1+
2
]-#,#&2
Log[1+
2
]
70.
​​;
Which we can export to a GIF:
Export[NotebookDirectory[]<>"flow.gif",flow,"AnimationRepetitions"->Infinity,"DisplayDurations"->1/50];
Or visualize directly in Mathematica using ListAnimate:
In[]:=
ListAnimate[flow,50]

CITE THIS NOTEBOOK

Modular Flow​
by Clayton Shonkwiler​
Wolfram Community, STAFF PICKS, November 7, 2023
​https://community.wolfram.com/groups/-/m/t/3061781