The Weierstrass elliptic function
℘
is just about the simplest possible elliptic function, which means it is a doubly-periodic meromorphic function on the complex plane

.
A function
f
being doubly-periodic means that there exist
ω
1
,
ω
2
∈
with
ω
1
ω
2
∉
so that
f(z+
ω
1
)=f(z)
and
f(z+
ω
2
)=f(z)
for all
z∈
. More generally, this means that
f(z+m
ω
1
+n
ω
2
)=f(z)
for any
m,n∈
, and so the behavior of
f
is completely determined by what it does on the fundamental domain which is (any translate of) the parallelogram with corners at
0,
ω
1
,
ω
2
,
ω
1
+
ω
2
. Indeed, if
Λ={m
ω
1
+n
ω
2
:m,n∈}
is the lattice determined by
(
ω
1
,
ω
2
)
, then we can just as well think of
f
as a function on the quotient space
/Λ
, which a topologist or differential geometer would probably call a torus and a number theorist or algebraic geometer would probably call an elliptic curve. This is the source of the name elliptic function.
If a doubly-periodic function
f
is entire, then it must in particular be continuous and hence bounded on the fundamental domain, and therefore on the entire plane, so Liouville's theorem implies that it must be constant. Therefore, any non-constant doubly-periodic function must have singularities, and the ones with only isolated poles (i.e., the meromorphic ones) are the elliptic functions.
Let
γ
be the boundary of the fundamental domain of an elliptic function
f
, oriented clockwise. Then
0=
∮
γ
f=
n
∑
k=1
Res
z=
z
k
f(z)
, where the first equality follows from double-periodicity (since the values on opposite sides of the fundamental domain are the same, but traversed in opposite directions) and the second equality is the residue theorem (here the sum is over all poles in the fundamental domain). Since the sum of residues can’t be zero if
f
has a single simple pole, this proves:
Theorem. Any elliptic function has at least 2 poles (counting multiplicity) in its fundamental domain.
If you try to build an elliptic function with a single pole of order 2 at the origin (and hence also at all the lattice points) and so that the leading term in the Laurent series at the origin is
1
2
z
, you end up with the Weierstrass function​
℘(z):=
1
2
z
+
∑
ω∈Λ\{0}
1
2
(z-ω)
-
1
2
ω
.
(This is explained very well in sections 1.5–1.6 of Apostol’s Modular Functions and Dirichlet Series in Number Theory.)
Of course,
℘
depends on the periods
ω
1
and
ω
2
(or equivalently on the lattice
Λ
), so it is sometimes helpful to indicate it by
℘(z;
ω
1
,
ω
2
)
.
As in Mathematica’s definition WeierstrassP[z,
{
g
2
,
g
3
}]
, it is also common to write
℘(z;
g
2
,
g
3
)
, where the invariants
g
2
and
g
3
are functions of
(
ω
1
,
ω
2
)
(or really of
τ=
ω
2
ω
1
) that show up as coefficients in the Laurent series of
℘
and also in the differential equation
℘'
2
(z)
=4
3
℘(z)
-
g
2
℘(z)-
g
3
.
In any case, Mathematica can easily convert between (half-)periods and invariants using WeierstrassInvariants and WeierstrassHalfPeriods.
Here’s a visualization of
℘
on the square lattice using domain coloring, which shows phase as hue and modulus as brightness:
In[]:=
Module[{g2,g3},​​{g2,g3}=WeierstrassInvariants[{1/2,I/2}];​​Show[ComplexPlot[WeierstrassP[z,{g2,g3}],{z,-2-2I,2+2I},PlotRangePaddingNone,BoundaryStyleNone],Graphics[{Thickness[.005],Table[InfiniteLine[{{0,n},{1,n}}],{n,-5,5}],Table[InfiniteLine[{{n,0},{n,1}}],{n,-5,5}]}],PlotRange->2,ImageSize->Large]​​]
Out[]=
We can clearly see a double pole at the lattice points (since the colors appear twice in clockwise order) and a double zero in the center of the fundamental domain (again, colors appear twice, but now in counterclockwise order).
And here’s the Weierstrass function for the 60º rhombus:
In[]:=
Module{g2,g3},​​{g2,g3}=NWeierstrassInvariants
1
2
,
Iπ/3
E
2
;​​ShowComplexPlot[WeierstrassP[z,{g2,g3}],{z,-2-2I,2+2I},PlotRangePaddingNone,BoundaryStyleNone],GraphicsThickness[.005],TableInfiniteLine0,
3
2
n,1,
3
2
n,{n,-5,5},TableInfiniteLine{n,0},12+n,
3
2
,{n,-5,5},PlotRange->2,ImageSize->Large​​
Out[]=
Notice that we still have the double pole, but the double zero has now split into two simple zeros.
To get a looping animation out of domain coloring plots of Weierstrass functions, one strategy is to find a periodic path in the space of lattices. We can do that using the modular flow, which I previously used to produce this animation.
The idea is to let
Λ
be the lattice of points of the form
P
x
y

, where
P=
-1
-
2
1
-
2
and

x
y
∈
2

is an integer point in the plane.
In[]:=
P=-1,-
2
,1,-
2
;
Here’s a picture of
Λ
:
In[]:=
Graphics[{Thickness[.005],PointSize[Large],Table[Point[P.{x,y}],{x,-10,10},{y,-10,10}]},PlotRange->8]
Out[]=
And the corresponding tiling by copies of the fundamental domain:
In[]:=
Graphics[{Thickness[.005],Table[InfiniteLine[{P.{0,y},P.{1,y}}],{y,-10,10}],Table[InfiniteLine[{P.{x,0},P.{x,1}}],{x,-10,10}]},PlotRange->8]
Out[]=
Now we download the seasons color palette from Ellert van der Velden’s CMasher:
And build the frames of the animation (note that we’re rotating the color palette a quarter turn):
Which we can export to a GIF:
Or visualize directly using ListAnimate:

CITE THIS NOTEBOOK

Phase (periodic family of Weierstrass functions)​
by Clayton Shonkwiler​
Wolfram Community, STAFF PICKS, May 22, 2025
​https://community.wolfram.com/groups/-/m/t/3465926