Skip to main content

numerics - Eisenstein Series in Mathematica?


Mathematica doesn't seem to have built-in tools to deal with the Eisenstein series:


$$\begin{align*} E_{2}(\tau)&= 1-24 \sum_{n=1}^{\infty} \frac{n e^{2 \pi i n \tau}}{1-e^{2 \pi i n \tau}}\\ E_{4}(\tau)&= 1+240 \sum_{n=1}^{\infty} \frac{n^{3} e^{2 \pi i n \tau}}{1-e^{2 \pi i n \tau}} \end{align*}$$


I'm wondering what is the best way to deal with this. Just messing around, informally, on Wolfram, it seems like these series all converge pretty fast. Can I carry out the sums manually in Mathematica including a small number of terms? Or is there a better way? I'm worried this is prone to severe inaccuracy for $\Im(\tau)$ either large or small, both cases I'm interested in.


If it simplifies anything, I only need the cases $\Re(\tau) \in \mathbb{Z}$ where the series outputs real numbers.



Answer



Since EllipticTheta[] is a built-in function, and since the Eisenstein series $E_4(q)$ and $E_6(q)$ are expressible in terms of theta functions (I use the nome $q$ as the argument in this answer, but you can convert to your convention by using the relation with the period ratio $\tau$: $q=\exp(2\pi i \tau)$), and since the higher-order Eisenstein series (note that they are only defined for even orders!) can be generated from $E_4(q)$ and $E_6(q)$ through a recurrence (see e.g. Apostol's book), it is relatively straightforward to write Mathematica routines for these functions:



SetAttributes[EisensteinE, {Listable, NHoldFirst}];

EisensteinE[4, q_] := (EllipticTheta[2, 0, q]^8 + EllipticTheta[3, 0, q]^8 +
EllipticTheta[4, 0, q]^8)/2

EisensteinE[6, q_] := With[{q2 = EllipticTheta[2, 0, q]^4,
q3 = EllipticTheta[3, 0, q]^4,
q4 = EllipticTheta[4, 0, q]^4},
(q2 + q3) (q3 + q4) (q4 - q2)/2


EisensteinE[n_Integer?EvenQ, q_] /; n > 2 := (6/((6 - n) (n^2 - 1) BernoulliB[n]))
Sum[Binomial[n, 2 k + 4] (2 k + 3) (n - 2 k - 5)
BernoulliB[2 k + 4] BernoulliB[n - 2 k - 4]
EisensteinE[2 k + 4, q] EisensteinE[n - 2 k - 4, q], {k, 0, n/2 - 4}]

Here are a few examples:


(* "equianharmonic case" *)
{ω1, ω3} = {1, (1 + I Sqrt[3])/2};
N[WeierstrassInvariants[{ω1, ω3}]] // Quiet // Chop
{0, 12.825381829368068}


2 {60, 140} Zeta[{4, 6}] EisensteinE[{4, 6}, Exp[I π ω3/ω1]]/(2 ω1)^{4, 6}
// N // Chop
{0, 12.825381829368068}

(* "lemniscatic case" *)
{ω1, ω3} = {1, I};
N[WeierstrassInvariants[{ω1, ω3}]] // Quiet // Chop
{11.817045008077123, 0}


2 {60, 140} Zeta[{4, 6}] EisensteinE[{4, 6}, Exp[I π ω3/ω1]]/(2 ω1)^{4, 6}
// N // Chop
{11.817045008077123, 0}

Using techniques similar to the one used in this answer, here are domain-colored plots of $E_4(q)$ (left) and $E_6(q)$ (right) over the unit disk, using the DLMF coloring scheme:


domain-colored plots of the Eisenstein series




Now, one may ask: what about $E_2(q)$? This function is what is termed as a "quasi-modular" form, whose behavior with respect to modular transformations is completely different from the other $E_{2k}(q)$. Due to this unusual state of affairs (i.e. not expressible entirely in terms of theta functions), one needs a different formula for $E_2(q)$; one useful formula can be found hidden deep within Abramowitz and Stegun:


EisensteinE[2, q_] := With[{q3 = EllipticTheta[3, 0, q]^2}, 6/π
EllipticE[InverseEllipticNomeQ[q]] q3 -

q3^2 - EllipticTheta[4, 0, q]^4]

Test:


Series[EisensteinE[2, q], {q, 0, 12}]
1 - 24 q^2 - 72 q^4 - 96 q^6 - 168 q^8 - 144 q^10 - 288 q^12 + O[q]^13

1 - Sum[24 DivisorSigma[1, k] q^(2 k), {k, 1, 6}]
1 - 24 q^2 - 72 q^4 - 96 q^6 - 168 q^8 - 144 q^10 - 288 q^12

Unfortunately, altho this version is great for symbolic use, it is not too good for numerical evaluation, as can be seen from the following attempt to generate a domain-colored plot from it:



wrong domain-colored plot of E2


The relatively complicated branch cut structure is apparently inherited from the branch cuts of the complete elliptic integral of the second kind $E(m)$ not being canceled out by the inverse nome.


Thus, I shall present another routine for numerically evaluating $E_2(q)$, based on recursing the quasi-modular relation (note the use of $\tau$ instead of $q$)


$$E_2\left(-\frac1{\tau}\right)=\tau^2 E_2(\tau)-\frac{6i\tau}{\pi}$$


before the actual numerical evaluation of the series:


e2[zz_ /; (InexactNumberQ[zz] && Im[zz] > 0)] :=
Block[{τ = SetPrecision[zz, 1. Precision[zz]], r = False, f, k, pr, q, qp, s},
τ -= Round[Re[τ]]; pr = Precision[τ];
If[7 Im[τ] < 6,
r = True; f = e2[SetPrecision[-1/τ, pr]],

q = SetPrecision[Exp[2 π I τ], pr]; f = s = 0; qp = 1;
k = 0;
While[k++; qp *= q; f = s + k qp/(1 - qp); s != f, s = f];
f = 1 - 24 f];
If[r, (f/τ + 6 I/π)/τ, f] /; NumberQ[f]]

EisensteinE[2, q_?InexactNumberQ] :=
If[q == 0, N[1, Internal`PrecAccur[q]], e2[Log[q]/(I π)]]

(Note that the subroutine e2[] actually takes the period ratio $\tau$ as the argument; if your preferred convention is to use $\tau$ instead of $q$, you can make that the main routine and skip the conversion to $q$ altogether.)



This now gives a proper-looking plot:


domain-colored plot of E2


(Thanks to მამუკა ჯიბლაძე for convincing me to look further into this.)




Finally, if you prefer the function $G_{2k}(q)$, here is the corresponding formula:


EisensteinG[n_Integer?EvenQ, q_] := 2 Zeta[n] EisensteinE[n, q]

Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...

list manipulation - Selecting multiple columns from a matrix?

Sample data: data = { {{2013, 1, 1}, 24.13, 167.67, 231.82}, {{2013, 1, 2}, 32.15, 170.92, 225.99}, {{2013, 1, 3}, 35.43, 172.68, 221.67}, {{2013, 1, 4}, 36.73, 173.05, 218.32}, {{2013, 1, 5}, 58.19, 165.96, 197.05}, {{2013, 1, 6}, 69.99, 163.50, 187.52}, {{2013, 1, 7}, 71.37, 154.21, 175.58}, {{2013, 1, 8}, 72.51, 149.66, 163.25}}; I want a DateListPlot with three graphs, so for a matrix formed by columns 1 and 2, one for columns 1 and 3, and 1 for columns 1 and 4. At the moment I'm using this code: data2 = Transpose[{data[[All, 1]], data[[All, 2]]}]; data3 = Transpose[{data[[All, 1]], data[[All, 3]]}]; data4 = Transpose[{data[[All, 1]], data[[All, 4]]}]; DateListPlot[{data2, data3, data4}, Joined -> True, Filling -> {3 -> {1}}] but I have a hunch that this can be done more efficiently. I don't like the Transpose s in particular. Any ideas? edit (for extra credit) What if I need to multiply the second column by 2, which in my solution is simp...