2
$\begingroup$

This is a follow-up to my question Root finding for holomorphic functions. I am trying to compute $10^6$ zeros of the derivative of the Riemann zeta function $\zeta(s)$ in the critical strip near height $t=5\cdot 10^6$. I've implemented the elegant solution of @azerbajdzan, but I need a slightly more sophisticated algorithm.

By what is known as 'the argument principle' for a holomorphic function like $\zeta^\prime(s)$, the change in Arg[$\zeta^\prime(s)$] around the boundary of a box, divided by $2\pi$, gives the number of zeros of $\zeta^\prime(s)$ inside the box. It is efficient to check this first before calling FindRoot: although each corner of the box requires a function evaluation, if we save the values, we can use them on an additional three boxes. Thus (neglecting boundary), we can determine if there's a zero in the box with about a single function evaluation. It will also be more accurate: if FindRoot returns an error FindRoot::reged because the algorithm converges to a root outside the box, I know not to ignore it but to recompute with a smaller step size.

Now, finally, to my question. I'm trying to write a recursive function to implement this idea, and I can't see what's wrong. Here's some code

ZetaPrime[s0_?NumericQ] := 
  ZetaPrime[s0] = 
   N[-(100/21) (315 Zeta[s0] - 512 Zeta[1/800 + s0] + 
       224 Zeta[1/400 + s0] - 28 Zeta[1/200 + s0] + Zeta[1/100 + s0])];

This computes $\zeta^\prime(s)$ by Richardson extrapolation, just like ND in the NumericalCalculus package, for computing the arguments.

ZetaPrimeFine[
   s0_?NumericQ] := -(100/21) (315 Zeta[s0] - 512 Zeta[1/800 + s0] + 
       224 Zeta[1/400 + s0] - 28 Zeta[1/200 + s0] + Zeta[1/100 + s0]);

The same but in symbolic form, not saved and without a specific number of digits, to pass to FindRoot.

argchange[a_, b_, zetaa_, zetab_] := 
  Module[{argdif = Arg[zetab/zetaa], c, d}, 
   If[Abs[argdif] < .75, argdif, c = (a + b)/2; d = ZetaPrime[c]; 
    argchange[a, c, zetaa, d] + argchange[c, b, d, zetab]]];

This computes the change in Arg[$\zeta^\prime(s)$] from a to b.

SmartFindRoot[box_] := 
  Module[{ll = box[[1]], ur = box[[2]], 
    lr = Re[box[[2]]] + I*Im[box[[1]]], 
    ul = Re[box[[1]]] + I*Im[box[[2]]]}, 
   If[Round[(argchange[ll, lr, ZetaPrime[ll], ZetaPrime[lr]] + 
         argchange[lr, ur, ZetaPrime[lr], ZetaPrime[ur]] + 
         argchange[ur, ul, ZetaPrime[ur], ZetaPrime[ul]] + 
         argchange[ul, ll, ZetaPrime[ul], ZetaPrime[ll]])/(2 Pi)] > 0,
    Check[
     FindRoot[ZetaPrimeFine[s], {s, Mean[box], Sequence @@ box}, 
                       WorkingPrecision -> 30, AccuracyGoal -> 5] ,
     Print[{Re[box[[1]]], Re[box[[2]]]}, 
      " ", {Im[box[[1]]], Im[box[[2]]]}];
     Flatten[
      Table[{ii + I jj, ii + step/10 + I (jj + step/10)}, 
       Evaluate@{ii, 
         Sequence @@ ({Re[box[[1]]], Re[box[[2]]]} - {0, step/10}), 
         step/10}, 
       Evaluate@{jj, 
         Sequence @@ ({Im[box[[1]]], Im[box[[2]]]} - {0, step/10}), 
         step/10}], 1];
     Map[SmartFindRoot, %] // Flatten, {FindRoot::reged}], {}]];

This function takes the lower left and upper right corners of the box, checks if there is a root in the box, and tries to find it with FindRoot. If a FindRoot::reged error occurs, Check calls SmartFindRoot with a smaller step size.

It works just fine when no FindRoot::reged error occurs. But when it does, the SmartRoot variable box_ does not seem to change in the recursion, and I go into an infinite loop:

step = 1/10;
re = {1/2, 3};
im = {45*10^5 + 30, 45*10^5 + 40};

Flatten[Table[{ii + I jj, ii + step + I (jj + step)}, 
   Evaluate@{ii, Sequence @@ (re - {0, step}), step}, 
   Evaluate@{jj, Sequence @@ (im - {0, step}), step}], 1];

Map[SmartFindRoot, %] // Flatten

results in

FindRoot::reged: The point {0.640762736317106198242023358404+4.50003870000000000000000000000\[CenterDot]10^6 I} is at the edge of the search region {0.60000000000000000000000+4.50003870000000000000000000000\[CenterDot]10^6 I,0.70000000000000000000000+4.50003880000000000000000000000\[CenterDot]10^6 I} in coordinate 1 and the computed search direction points outside the region.

{3/5,7/10} {45000387/10,22500194/5}

FindRoot::reged: The point {0.640762736317106198242023358404+4.50003870000000000000000000000\[CenterDot]10^6 I} is at the edge of the search region {0.60000000000000000000000+4.50003870000000000000000000000\[CenterDot]10^6 I,0.70000000000000000000000+4.50003880000000000000000000000\[CenterDot]10^6 I} in coordinate 1 and the computed search direction points outside the region.

{3/5,7/10} {45000387/10,22500194/5}

FindRoot::reged: The point {0.640762736317106198242023358404+4.50003870000000000000000000000\[CenterDot]10^6 I} is at the edge of the search region {0.60000000000000000000000+4.50003870000000000000000000000\[CenterDot]10^6 I,0.70000000000000000000000+4.50003880000000000000000000000\[CenterDot]10^6 I} in coordinate 1 and the computed search direction points outside the region.

General::stop: Further output of FindRoot::reged will be suppressed during this calculation.

{3/5,7/10} {45000387/10,22500194/5}

$Aborted

What am I doing wrong? I tried Block and With instead of Module but was unsuccessful.


Edit: In response to the comment, I can apply the SmartFindRoot function with a smaller step size to the the box causing the FindRoot::reged error, and it successfully finds the root:

step = 1/100;

re = {3/5, 7/10};
im = {45*10^5 + 38 + 7/10, 45*10^5 + 38 + 8/10};

Flatten[Table[{ii + I jj, ii + step + I (jj + step)}, 
   Evaluate@{ii, Sequence @@ (re - {0, step}), step}, 
   Evaluate@{jj, Sequence @@ (im - {0, step}), step}], 1];

Map[SmartFindRoot, %] // Flatten

{s -> 0.600152422567210509655436583395 + 
   4.50003870332967275482674049111\[CenterDot]10^6 I}

Second edit: I have a solution in my answer below; but I don't understand why it works or what the problem was. Happy to accept any answer that can enlighten me.

$\endgroup$
2
  • $\begingroup$ I've not looked at this in detail, but the error message suggests that either 1) there is not a root inside the box or 2) FindRoot is converging towards a root just outside the box. From the documentation, I understand that FindRoot will stop if condition 2 happens. Perhaps you need to restart from somewhere else in the box in this case. $\endgroup$
    – mikado
    Commented Jan 8 at 22:01
  • $\begingroup$ @mikado see edit to post $\endgroup$
    – stopple
    Commented Jan 8 at 23:22

1 Answer 1

1
$\begingroup$

Instead of creating the table inside SmartFindRoot, and then executing Map[SmartFindRoot, %], I assign the table to a variable tt, and execute Map[SmartFindRoot,tt]. This works, but I don't understand why.

SmartFindRoot[box_] := 
  Module[{ll = box[[1]], ur = box[[2]], 
    lr = Re[box[[2]]] + I*Im[box[[1]]], 
    ul = Re[box[[1]]] + I*Im[box[[2]]], tt}, 
   If[Round[(argchange[ll, lr, ZetaPrime[ll], ZetaPrime[lr]] + 
         argchange[lr, ur, ZetaPrime[lr], ZetaPrime[ur]] + 
         argchange[ur, ul, ZetaPrime[ur], ZetaPrime[ul]] + 
         argchange[ul, ll, ZetaPrime[ul], ZetaPrime[ll]])/(2 Pi)] > 
     0,
    Check[
     FindRoot[ZetaPrimeFine[s], {s, Mean[box], Sequence @@ box}, 
                       WorkingPrecision -> 30, AccuracyGoal -> 5] ,
     Print[{Re[box[[1]]], Re[box[[2]]]}, 
      " ", {Im[box[[1]]], Im[box[[2]]]}];
     tt = 
      Flatten[
       Table[{ii + I jj, ii + step/10 + I (jj + step/10)}, 
        Evaluate@{ii, 
          Sequence @@ ({Re[box[[1]]], Re[box[[2]]]} - {0, step/10}), 
          step/10}, 
        Evaluate@{jj, 
          Sequence @@ ({Im[box[[1]]], Im[box[[2]]]} - {0, step/10}), 
          step/10}], 1];
     Map[SmartFindRoot, tt] // Flatten, {FindRoot::reged}], {}]];

step = 1/10;
re = {1/2, 3};
im = {45*10^5 + 30, 45*10^5 + 40};


Flatten[Table[{ii + I jj, ii + step + I (jj + step)}, 
   Evaluate@{ii, Sequence @@ (re - {0, step}), step}, 
   Evaluate@{jj, Sequence @@ (im - {0, step}), step}], 1];

Map[SmartFindRoot, %] // Flatten

FindRoot::reged: The point {0.640762736317106198242023358404+4.50003870000000000000000000000\[CenterDot]10^6 I} is at the edge of the search region {0.60000000000000000000000+4.50003870000000000000000000000\[CenterDot]10^6 I,0.70000000000000000000000+4.50003880000000000000000000000\[CenterDot]10^6 I} in coordinate 1 and the computed search direction points outside the region.

{3/5,7/10} {45000387/10,22500194/5}

{s -> 
  0.542915929680714123605430978460 + 
   4.50003265105426578427240151767\[CenterDot]10^6 I, 
 s -> 0.581126387811184420735223836539 + 
   4.50003297590797456115337513971\[CenterDot]10^6 I, 
 s -> 0.536567047631278842314598405371 + 
   4.50003657318775515840164335203\[CenterDot]10^6 I, 
 s -> 0.546093436755693529515698394200 + 
   4.50003788478199538643017646634\[CenterDot]10^6 I, 
 s -> 0.608714199005176551156512392326 + 
   4.50003036520813239676030910552\[CenterDot]10^6 I, 
 s -> 0.658197294945752919072095529554 + 
   4.50003128861238569340951191078\[CenterDot]10^6 I, 
 s -> 0.649202050165163332997788716801 + 
   4.50003351211114718069224756309\[CenterDot]10^6 I, 
 s -> 0.651314297319985585761392757843 + 
   4.50003557657689633449164482998\[CenterDot]10^6 I, 
 s -> 0.600152422567210509655436583395 + 
   4.50003870332967275482674049111\[CenterDot]10^6 I, 
 s -> 0.778598324432867566268482710654 + 
   4.50003208522841256256607622839\[CenterDot]10^6 I, 
 s -> 0.713880151024384919415292914110 + 
   4.50003442862522681008395838694\[CenterDot]10^6 I, 
 s -> 0.747350614502083231595182481282 + 
   4.50003478377380320414204917162\[CenterDot]10^6 I, 
 s -> 0.724907813124177169611694534372 + 
   4.50003700822729562702265408281\[CenterDot]10^6 I, 
 s -> 0.756849165407385665393396011291 + 
   4.50003833262488102872706782053\[CenterDot]10^6 I, 
 s -> 0.719433486771795436096502343781 + 
   4.50003955664930829860752335641\[CenterDot]10^6 I, 
 s -> 0.821420370933760361344136259987 + 
   4.50003582956602076022525727135\[CenterDot]10^6 I, 
 s -> 1.00319113755581037354716288629 + 
   4.50003096569533480947024272655\[CenterDot]10^6 I, 
 s -> 1.02691010374256399896057786903 + 
   4.50003180635594246114919160879\[CenterDot]10^6 I, 
 s -> 1.00956476686781512201073363746 + 
   4.50003725302695360454299882963\[CenterDot]10^6 I, 
 s -> 2.37128170375532209299268054889 + 
   4.50003914340854735689796938698\[CenterDot]10^6 I}
```
$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.