5
$\begingroup$

I have run into an issue where I am getting nnum errors when I use ParallelTable, which I do not get when I use Table (and even though I have distributed the definitions to the kernels).

EDIT: As requested, here is a "more minimal" example:

Module1[n_] := Module[{y, x, s}, 
  s = NDSolve[{y'[x] == y[x] Cos[n*x + y[x]], y[0] == 1}, y, {x, 0, 30}];
  With[{X = (y /. s[[1]])[x] /. x -> #}, X &]
]

Module2[n_, x_] := Module[{Mys},
  Mys[X_] = Module1[n][X];
  First@NMaximize[{Mys[X], 0 < X < x}, X]
]

The following code runs fine:

test1 = Table[Module2[i, 20], {i, 1, 5}]

But this does not:

DistributeDefinitions["Global`"];
test2 = ParallelTable[Module2[i, 20], {i, 1, 5}]

The necessary ingredients to reproduce the problem seem to be:

1) A module which uses NDSolve and returns a pure function

2) A second module which uses NMinimize or NMaximize on that function.

In this toy example, there's no reason to introduce two modules (as compared to doing everything in one module); however, in my actual project this is not desirable.

ORIGINAL EXAMPLE: The problem makes use of the following modules:

mpl = 1/Sqrt[6.70837*10^-39]
gsT = 106.75

aANDρr[ΛI_, ΓI_, tf_] := Module[{s},
 s = NDSolve[{as'[t] == as[t]*Sqrt[(8 π)/(3 mpl^2)(ρrs[t] + ΛI^4/as[t]^3 Exp[-ΓI t])], 
   ρrs'[t] + 4*Sqrt[(8 π)/(3 mpl^2) (ρrs[t] + ΛI^4/as[t]^3 Exp[-ΓI t])] ρrs[t] == ΓI ΛI^4/as[t]^3 Exp[-ΓI t], 
             as[0] == 1, ρrs[0] == 0}, {as, ρrs}, {t, 0, tf}];
       Return[{With[{x = (as /. s[[1]])[t] /. t -> #1}, x &], 
       With[{x = (ρrs /. s[[1]])[t] /. t -> #1}, x &]}];
       ];

       UniverseEvolve[ΛI_, ΓI_, tfmini_: 0] := Module[{tfmin, HI, ti, tR, tf, s,(*ρI,*)H, Trad, T, TR, Tmax, aANDρrRESULTS, a, ρr},
          tfmin = tfmini;
          HI = Sqrt[(8 π*ΛI^4)/(3 mpl^2)];
          ti = 2/3 Sqrt[3/(8 π)] mpl/ΛI^2;
          tR = 1/ΓI;
          tf = Max[100 tR, 100 ti, tfmin]; 

          aANDρrRESULTS = aANDρr[ΛI, ΓI, tf];
          a[t_] = aANDρrRESULTS[[1]][t];
          ρr[t_] = aANDρrRESULTS[[2]][t];
          H[t_] = a'[t]/a[t];
          Trad[ρ_] = (30/(π^2 gsT) ρ)^(1/4);
          T[t_] = Trad[ρr[t]];
          TR = Trad[ρr[tR]] ;
          Tmax = NMaximize[{T[t], 0.1 ti < t < 10 ti}, t][[1]];

          Return[{HI,
             With[{x = H[t] /. t -> #1}, x &],
             With[{x = T[t] /. t -> #1}, x &],
             Tmax,
             TR,
             ti,
             tf}];
          ]

The following runs without any errors:

Table[UniverseEvolve[10^15, 10^i], {i, 6, 10}];

However, the following does not:

DistributeDefinitions["Global`"];
ParallelTable[UniverseEvolve[10^15, 10^i], {i, 6, 10}];

In particular, each kernel generates a large number of NMaximize::nnum errors, and I cannot figure out why. (Note that the notebook's context is indeed global.) Any insight would be appreciated.

$\endgroup$
  • $\begingroup$ Happens in Kubuntu 16.04 with Mma 11 too. $\endgroup$ – bobbym Sep 3 '16 at 4:22
  • $\begingroup$ Can you produce a minimal example please? See sscce.org for guidance. $\endgroup$ – Szabolcs Sep 5 '16 at 8:54
  • $\begingroup$ @Szabolcs, while the original code is well beneath the 100 lines suggested on that page, I've written an even more minimal example for you. $\endgroup$ – Lauren Pearce Sep 6 '16 at 13:36
  • $\begingroup$ @LaurenPearce It's not about me personally. The new example considerably increases the chance that someone will take the time to look at the problem and maybe find a solution. I reduced it a bit more. +1. $\endgroup$ – Szabolcs Sep 6 '16 at 13:39
2
$\begingroup$

The issue is due to that you assigned the slot # outside the Function ()&. You can avoid these issues by putting the slot # inside the Function[] as

Module1[n_] := Module[{y, x, s}, 
    s = NDSolve[{y'[x] == y[x] Cos[n*x + y[x]], y[0] == 1}, y, {x, 0, 30}];
    Function[Evaluate[(y /. s[[1]])[#]]] 
]

If you just want to return the interpolating function, you can also simply write

Module1[n_] := Module[{y, x, s}, 
    s = NDSolve[{y'[x] == y[x] Cos[n*x + y[x]], y[0] == 1}, y, {x, 0, 30}][[1]];
    y /. s
]

to avoid any confusion about #.

Both methods will run fine in the ParallelTable[].

DistributeDefinitions["Global`"];
test2 = ParallelTable[Module2[i, 20], {i, 1, 5}]
(* returns {1.12259, 1.0692, 1.04819, 1.03696, 1.02997} *)

For the longer example, you can do it by

aANDρr[ΛI_,ΓI_,tf_]:= Module[{s},
    s = NDSolve[{
    as'[t] == as[t]*Sqrt[(8 π)/(3 mpl^2)(ρrs[t] + ΛI^4/as[t]^3 Exp[-ΓI t])],
    ρrs'[t] + 4*Sqrt[(8 π)/(3 mpl^2) (ρrs[t] + ΛI^4/as[t]^3 Exp[-ΓI t])] 
        ρrs[t] == ΓI ΛI^4/as[t]^3 Exp[-ΓI t],
    as[0] == 1, ρrs[0] == 0}, {as, ρrs}, {t, 0, tf}][[1]];
    {as/.s, ρrs/.s}
]

and

UniverseEvolve[ΛI_, ΓI_, tfmini_: 0] := 
Module[{tfmin, HI, ti, tR, tf, s,(*ρI,*)H, Trad, T, TR, Tmax, aANDρrRESULTS, a, ρr}, 
    tfmin = tfmini;
    HI = Sqrt[(8 π*ΛI^4)/(3 mpl^2)];
    ti = 2/3 Sqrt[3/(8 π)] mpl/ΛI^2;
    tR = 1/ΓI;
    tf = Max[100 tR, 100 ti, tfmin];

    aANDρrRESULTS = aANDρr[ΛI, ΓI, tf];
    a[t_] = aANDρrRESULTS[[1]][t];
    ρr[t_] = aANDρrRESULTS[[2]][t];
    H[t_] = a'[t]/a[t];
    Trad[ρ_] = (30/(π^2 gsT) ρ)^(1/4);
    T[t_] = Trad[ρr[t]];
    TR = Trad[ρr[tR]];
    Tmax = NMaximize[{T[t], 0.1 ti < t < 10 ti}, t][[1]];
    {HI, Function[Evaluate[H[#]]], Function[Evaluate[T[#]]], Tmax, TR, ti, tf}
]
$\endgroup$
  • $\begingroup$ This works- thank you $\endgroup$ – Lauren Pearce Sep 7 '16 at 15:44
1
$\begingroup$

This is not an answer, just an extended comment. A smaller example demonstrating a closely related (though not entirely identical) problem is the following:

In[1]:= fun[] := f[x] & /. x -> #    

In[2]:= fun[][z]    
Out[2]= f[z]    

In[3]:= ParallelEvaluate[fun[][z], 1]    
Out[3]= f["KernelObject"[1, "local"]]

Out[3] should be identical to Out[2], but it isn't.

Hope fully this will help in debugging the issue.

A TracePrint reveals than when this expression is evaluated on a subkernel, the slot (#) is somehow replaced by this:

enter image description here

Compare TracePrint[fun[][x]] with ParallelEvaluate[TracePrint[fun[][x]], 1].

A more trivial example is

slot[] := #    
ParallelEvaluate[slot[], 1]

(* "KernelObject"[1, "local"] *)

or the TracePrint equivalent.

The root cause of all of this is very likely that the free # (i.e. slot not bound to a pure function) gets at some point injected into the expression of some pure function, which then replaces it with an argument. I seem to remember some StackExchange posts dealing with similar problems, and will try to search for them.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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