# Map of an expression in a 3D grid is very slow

I have a quite large expression as function of $$R$$, $$\phi$$ and $$Z$$ as you can see:

expression = (0. + 1/10 (5/R^6 + 5 R^4) Z (0. + 1.5 Cos[5 \[Phi]]) + ((
30 R + 90 R^9 - 120 R^11)/(
480 R^5) - (-14 + 15 R^2 + 9 R^10 - 10 R^12)/(96 R^6) +
1/4 (-(5/R^6) + 5 R^4) Z^2) (0. +
1.5 Sin[5 \[Phi]]) + (((-1 + R^2)^4 (46 R + 76 R^3 + 60 R^5))/(
26880 R^5) + ((-1 + R^2)^3 (18 + 23 R^2 + 19 R^4 + 10 R^6))/(
3360 R^4) - ((-1 + R^2)^4 (18 + 23 R^2 + 19 R^4 + 10 R^6))/(
5376 R^6) +
1/2 ((30 R + 90 R^9 - 120 R^11)/(
480 R^5) - (-14 + 15 R^2 + 9 R^10 - 10 R^12)/(96 R^6)) Z^2 +
1/48 (-(5/R^6) + 5 R^4) Z^4) (0. +
10. Sin[5 \[Phi]]))/(\[Sqrt]((0. + 1/R + (
5 ((-14 + 15 R^2 + 9 R^10 - 10 R^12)/(480 R^5) +
1/4 (1/R^5 + R^5) Z^2) (0. + 1.5 Cos[5 \[Phi]]))/R + (
5 (((-1 + R^2)^4 (18 + 23 R^2 + 19 R^4 + 10 R^6))/(
26880 R^5) + ((-14 + 15 R^2 + 9 R^10 - 10 R^12) Z^2)/(
960 R^5) + 1/48 (1/R^5 + R^5) Z^4) (0. +
10. Cos[5 \[Phi]]))/
R + ((-(1/R^5) + R^5) Z (0. - 1.5 Sin[5 \[Phi]]))/(
2 R))^2 + (0. +
1/10 (-(1/R^5) + R^5) (0. + 1.5 Cos[5 \[Phi]]) +
1/2 (1/R^5 + R^5) Z (0. +
1.5 Sin[5 \[Phi]]) + (((-14 + 15 R^2 + 9 R^10 -
10 R^12) Z)/(480 R^5) + 1/12 (1/R^5 + R^5) Z^3) (0. +
10. Sin[5 \[Phi]]))^2 + (0. +
1/10 (5/R^6 + 5 R^4) Z (0. + 1.5 Cos[5 \[Phi]]) + ((
30 R + 90 R^9 - 120 R^11)/(
480 R^5) - (-14 + 15 R^2 + 9 R^10 - 10 R^12)/(96 R^6) +
1/4 (-(5/R^6) + 5 R^4) Z^2) (0. +
1.5 Sin[5 \[Phi]]) + (((-1 + R^2)^4 (46 R + 76 R^3 +
60 R^5))/(
26880 R^5) + ((-1 + R^2)^3 (18 + 23 R^2 + 19 R^4 +
10 R^6))/(
3360 R^4) - ((-1 + R^2)^4 (18 + 23 R^2 + 19 R^4 + 10 R^6))/(
5376 R^6) +
1/2 ((30 R + 90 R^9 - 120 R^11)/(
480 R^5) - (-14 + 15 R^2 + 9 R^10 - 10 R^12)/(
96 R^6)) Z^2 + 1/48 (-(5/R^6) + 5 R^4) Z^4) (0. +
10. Sin[5 \[Phi]]))^2))


I need to evaluate this expression in the following 3D grid

grid = Table[{(i+1/2)*5,(j+1/2)*5,k*0.0785},{i,0,119},{j,0,159},{k,0,79}]


and I'm doing that with the ParallelMap:

result = ParallelMap[expression /. {R -> #[[1]], \[Phi] -> #[[2]], Z -> #[[3]]} &, grid, {3}]


However this takes about 4min which is quite a lot since I have to do this for a bunch of other large expressions. Is there any way to speed it up?

• Without expression, we cannot tell you anything. Place the code in place of the picture. Commented Mar 31, 2020 at 16:32
• I just added the code for the expression.
– AJHC
Commented Mar 31, 2020 at 17:45
• Thank you. It looks like expression is periodic on $\phi$ with a period $2\pi /5$. Why do you use (j+1/2)*5,{j,0,159} to map it? Commented Mar 31, 2020 at 17:58
• Yes, indeed this particular expression has period of 5 in $\phi$, but I have a few more expressions which I need to evaluate, and which are not $\phi$ periodic...
– AJHC
Commented Mar 31, 2020 at 18:03
• What are these huge result for? Commented Mar 31, 2020 at 19:21

We can reduce the time by 100 times using Compile[] and ParallelTable[]

cf = Compile[{{R, _Real}, {\[Phi], _Real}, {Z, _Real}}, (0. +
1/10 (5/R^6 + 5 R^4) Z (0. +
1.5 Cos[5 \[Phi]]) + ((30 R + 90 R^9 -
120 R^11)/(480 R^5) - (-14 + 15 R^2 + 9 R^10 -
10 R^12)/(96 R^6) + 1/4 (-(5/R^6) + 5 R^4) Z^2) (0. +
1.5 Sin[5 \[Phi]]) + (((-1 + R^2)^4 (46 R + 76 R^3 +
60 R^5))/(26880 R^5) + ((-1 + R^2)^3 (18 + 23 R^2 +
19 R^4 + 10 R^6))/(3360 R^4) - ((-1 + R^2)^4 (18 +
23 R^2 + 19 R^4 + 10 R^6))/(5376 R^6) +
1/2 ((30 R + 90 R^9 - 120 R^11)/(480 R^5) - (-14 + 15 R^2 +
9 R^10 - 10 R^12)/(96 R^6)) Z^2 +
1/48 (-(5/R^6) + 5 R^4) Z^4) (0. +
10. Sin[5 \[Phi]]))/(Sqrt[((0. +
1/R + (5 ((-14 + 15 R^2 + 9 R^10 - 10 R^12)/(480 R^5) +
1/4 (1/R^5 + R^5) Z^2) (0. + 1.5 Cos[5 \[Phi]]))/
R + (5 (((-1 + R^2)^4 (18 + 23 R^2 + 19 R^4 +
10 R^6))/(26880 R^5) + ((-14 + 15 R^2 + 9 R^10 -
10 R^12) Z^2)/(960 R^5) +
1/48 (1/R^5 + R^5) Z^4) (0. + 10. Cos[5 \[Phi]]))/
R + ((-(1/R^5) + R^5) Z (0. -
1.5 Sin[5 \[Phi]]))/(2 R))^2 + (0. +
1/10 (-(1/R^5) + R^5) (0. + 1.5 Cos[5 \[Phi]]) +
1/2 (1/R^5 + R^5) Z (0. +
1.5 Sin[
5 \[Phi]]) + (((-14 + 15 R^2 + 9 R^10 -
10 R^12) Z)/(480 R^5) +
1/12 (1/R^5 + R^5) Z^3) (0. +
10. Sin[5 \[Phi]]))^2 + (0. +
1/10 (5/R^6 + 5 R^4) Z (0. +
1.5 Cos[
5 \[Phi]]) + ((30 R + 90 R^9 -
120 R^11)/(480 R^5) - (-14 + 15 R^2 + 9 R^10 -
10 R^12)/(96 R^6) + 1/4 (-(5/R^6) + 5 R^4) Z^2) (0. +
1.5 Sin[
5 \[Phi]]) + (((-1 + R^2)^4 (46 R + 76 R^3 +
60 R^5))/(26880 R^5) + ((-1 + R^2)^3 (18 + 23 R^2 +
19 R^4 + 10 R^6))/(3360 R^4) - ((-1 + R^2)^4 (18 +
23 R^2 + 19 R^4 + 10 R^6))/(5376 R^6) +
1/2 ((30 R + 90 R^9 - 120 R^11)/(480 R^5) - (-14 +
15 R^2 + 9 R^10 - 10 R^12)/(96 R^6)) Z^2 +
1/48 (-(5/R^6) + 5 R^4) Z^4) (0. +
10. Sin[5 \[Phi]]))^2)])]
result = ParallelTable[
cf[(i + 1/2)*5., (j + 1/2)*5, k*0.0785], {i, 0, 119}, {j, 0,
159}, {k, 0, 79}]; // AbsoluteTiming


It takes few seconds with 4 kernels.

• I didn't know this Compile function of Mathematica. Great! With two kernels it takes me now 3s. Thanks!
– AJHC
Commented Apr 1, 2020 at 6:27
• @AJHC You are welcome! Commented Apr 1, 2020 at 10:17

Another option is to use FunctionCompile (I also called Simplify on expression first):

cf=FunctionCompile[Function[{}, Table[With[{R = (i + 0.5)*5, \[Phi] = (j + 0.5)*5, Z = k*0.0785},
((5. + 5.*R^10)*Z*Cos[5*\[Phi]] + (1.2351190476190474 - 0.08680555555555555*R^4 + 0.22321428571428573*R^14 - 7.6388888888888875*Z^2 -
6.944444444444444*Z^4 + R^12*(-1.8229166666666667 - 4.861111111111111*Z^2) + R^2*(-0.5729166666666666 - 3.125*Z^2) +
R^10*(1.0243055555555556 + 15.624999999999998*Z^2 + 6.944444444444444*Z^4))*Sin[5*\[Phi]])/
(R^6*Sqrt[(1/R^12)*(44.444444444444436*(R^5 + (-0.18526785714285715 + 0.06510416666666667*R^4 + 0.018601190476190476*R^14 +
1.1458333333333333*Z^2 + 1.0416666666666667*Z^4 + R^12*(-0.1953125 - 0.5208333333333334*Z^2) + R^2*(0.14322916666666666 + 0.78125*Z^2) +
R^10*(0.15364583333333334 + 2.34375*Z^2 + 1.0416666666666667*Z^4))*Cos[5*\[Phi]] + (0.75 - 0.75*R^10)*Z*Sin[5*\[Phi]])^2 +
1.*R^2*((1. - 1.*R^10)*Cos[5*\[Phi]] + Z*(-3.055555555555555 - 2.083333333333333*R^2 + 1.3888888888888886*R^12 - 5.5555555555555545*Z^2 +
R^10*(-6.249999999999999 - 5.5555555555555545*Z^2))*Sin[5*\[Phi]])^2 + 48.22530864197531*
((0.72 + 0.72*R^10)*Z*Cos[5*\[Phi]] + (0.17785714285714285 - 0.0125*R^4 + 0.03214285714285714*R^14 - 1.0999999999999999*Z^2 - 1.*Z^4 +
R^12*(-0.2625 - 0.7000000000000001*Z^2) + R^2*(-0.08250000000000002 - 0.45*Z^2) + R^10*(0.1475 + 2.2500000000000004*Z^2 + 1.*Z^4))*Sin[
5*\[Phi]])^2)])], {i, 0, 119}, {j, 0, 159}, {k, 0, 79}]]];


This gives me:

In[.]:= (res=cf[];)//AbsoluteTiming
Out[.]= {0.126522,Null}


The downside is that FunctionCompile itself can take a significant amount of time.

Edit: Same code with with the upper limits as parameters:

cf=FunctionCompile[Function[{Typed[ii,"MachineInteger"],Typed[jj,"MachineInteger"],Typed[kk,"MachineInteger"]},Table[With[{R=(i+0.5)*5,\[Phi]=(j+0.5)*5,Z=k*0.0785},((5.+5.*R^10)*Z*Cos[5*\[Phi]]+(1.2351190476190474-0.08680555555555555*R^4+0.22321428571428573*R^14-7.6388888888888875*Z^2-6.944444444444444*Z^4+R^12*(-1.8229166666666667-4.861111111111111*Z^2)+R^2*(-0.5729166666666666-3.125*Z^2)+R^10*(1.0243055555555556+15.624999999999998*Z^2+6.944444444444444*Z^4))*Sin[5*\[Phi]])/(R^6*Sqrt[(1/R^12)*(44.444444444444436*(R^5+(-0.18526785714285715+0.06510416666666667*R^4+0.018601190476190476*R^14+1.1458333333333333*Z^2+1.0416666666666667*Z^4+R^12*(-0.1953125-0.5208333333333334*Z^2)+R^2*(0.14322916666666666+0.78125*Z^2)+R^10*(0.15364583333333334+2.34375*Z^2+1.0416666666666667*Z^4))*Cos[5*\[Phi]]+(0.75-0.75*R^10)*Z*Sin[5*\[Phi]])^2+1.*R^2*((1.-1.*R^10)*Cos[5*\[Phi]]+Z*(-3.055555555555555-2.083333333333333*R^2+1.3888888888888886*R^12-5.5555555555555545*Z^2+R^10*(-6.249999999999999-5.5555555555555545*Z^2))*Sin[5*\[Phi]])^2+48.22530864197531*((0.72+0.72*R^10)*Z*Cos[5*\[Phi]]+(0.17785714285714285-0.0125*R^4+0.03214285714285714*R^14-1.0999999999999999*Z^2-1.*Z^4+R^12*(-0.2625-0.7000000000000001*Z^2)+R^2*(-0.08250000000000002-0.45*Z^2)+R^10*(0.1475+2.2500000000000004*Z^2+1.*Z^4))*Sin[5*\[Phi]])^2)])],{i,0,ii},{j,0,jj},{k,0,kk}]]];

• I have tested this code and it runs on my computer several minutes to compile and 3.64 s to calculate res . How did you get 0.126522 s? Commented Oct 26, 2020 at 21:06
• You're right, in a production version (12.1) I get 1.8 seconds to compute res, and 78 seconds to compile. In the upcoming version (unrelease 12.2) the function evaluation will get a lot faster (but the compilation time goes up a bit). Sorry for the confusion. Commented Oct 26, 2020 at 21:25
• Ok! Now I have same time with v.12.1. But if we change parameters like  {i, 0, 110}, {j, 0, 150}, {k, 0, 100} then we should compile again and spend time, while with my code we just using same cf[] with new parameters. Could you prepare version with parameters? Commented Oct 26, 2020 at 21:38