TransWikia.com

Use of ParallelDo with an iterative or recursive calculation

Mathematica Asked on December 28, 2020

Is it possible to use ParallelDo (or any similar parallelization method) to speed up the calculation of an iterative calculation, which takes a previous calculation result as input to new calculation? It seems to me not possible conceptually, since each round will have to wait for the first to get its input, but I wonder if there are ways around this?

For example, if f1[r] is some predefined arbitrary continuous input function and f2[r] is some output function (over the r variable that runs from 0 to some number a, with some step called step, e.g. say step=a/100), then a calculation like this example

f1=1;
Do[
Do[
f2[r2]=NIntegrate[r1 f1[r1] BesselJ[0, r1 r2] E^(-I (r1^2 + r2^2)/2),{r1,0,a}],
(r2,0,a,step)];
f1=Interpolation[Table[{r2,f2[r2]},{r2,0,a,step}]],
{kk,100}]

would be difficult to speed up by parallelization (e.g. using ParallelDo), right?

Are there any suggestions to speed this up by parallel methods or other methods that are not to too difficult for a beginner in Mathematica to understand?

One Answer

The only thing that can be parallelized here is the generation of the interpolation points. For example:

Clear[integrate, interpolate];
integrate[f_, r2_?NumericQ, a_?NumericQ] := NIntegrate[
   r1 f[r1] BesselJ[0, r1 r2] E^(-I (r1^2 + r2^2)/2),
   {r1, 0, a}
];
interpolate[f_, a_?NumericQ, step_?NumericQ] := Interpolation[
  ParallelTable[
    {r2, integrate[f, r2, a]},
    {r2, 0, a, step}
  ]
];

Iterate the procedure twice, starting with a constant function:

results = NestList[
   interpolate[#, 1, 0.01] &,
   1 &,
   2
];

Plot the obtained functions at each iteration:

ReImPlot[Evaluate[Through[results[r2]]],
  {r2, 0, 1},
  PlotLegends -> Range[0, Length[results] - 1]
]

enter image description here

Edit

I don't think that with NIntegrate you can speed this up any further. The free parameter r2 appears in the body of the integral, so I don't think that interpolation is going to help you too much here. You could make an interpolation over both r1 and r2 of which you then take the antiderivative over r1, but you also risk introducing numerical error that way. There's probably a reason why NIntegrate isn't faster here.

I do have another idea for speeding this up, though. We can use ParametricNDSolveValue to do the integration instead by re-phrasing the problem and considering r2 to be a parameter. This should reduce the top-level overhead involved in calling NIntegrate multiple times. Here's how to do it:

Clear[integrate, interpolate];
integrate[f_, a_?NumericQ] := ParametricNDSolveValue[
   {y'[r1] == r1 f[r1] BesselJ[0, r1 r2] E^(-I (r1^2 + r2^2)/2), y[0] == 0},
   y[a],
   {r1, 0, a},
   {{r2, 0, a}}
];
interpolate[f_, a_?NumericQ, step_?NumericQ] := With[{
  int = integrate[f, a]
},
  Interpolation[
    ParallelTable[
      {r2, int[r2]},
      {r2, 0, a, step},
      Method -> "CoarsestGrained"
    ]
  ]
];
results = NestList[interpolate[#, 1, 0.01]&, 1&, 20];

ReImPlot[
  Evaluate[Through[results[r2]]],
  {r2, 0, 1},
  PlotLegends -> Range[0, Length[results] - 1], PlotRange -> All
]

This should be significantly faster than the method based on NIntegrate. You can also take a look at FunctionInterpolation to do the Interpolation step, since this might save you from having to sub-sample the integral more than you really need. For example:

int = Quiet @ FunctionInterpolation[
   integrate[1&, 1][r2],
   {r2, 0, 1}, 
   InterpolationPoints -> 50
]
ReImPlot[int[r2], {r2, 0, 1}]

FunctionInterpolation cannot be parallelized, though, so it's a trade-off

Correct answer by Sjoerd Smit on December 28, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP