Is there a way to simplify the random functions and their calls, in the code below?

size = 30;
Nwaves = 50;

angle[n_] = Table[RandomReal[{0, 2Pi}], {k, 1, Nwaves}][[n]];
amplitude[n_] = Table[RandomReal[{0.5, 1}], {k, 1, Nwaves}][[n]];
frequency[n_] = Table[RandomReal[{0.5, 1.5}], {k, 1, Nwaves}][[n]];
phase[n_] = Table[RandomReal[{0, 2Pi}], {k, 1, Nwaves}][[n]];

randomBumps[t_, x_, y_] := Sum[amplitude[n]Sin[frequency[n](t - Cos[angle[n]]x - Sin[angle[n]]y) + phase[n]], {n, 1, Nwaves}];

randomBumps[t, x, y],
{x, -10, 10}, {y, -10, 10},
 PlotPoints -> ControlActive[20, 60],
  PlotRange -> {{-10, 10}, {-10, 10}, {-3, 3}},
  Axes -> True,
  AxesOrigin -> {0, 0},
  AxesStyle -> Directive[GrayLevel[0.5]],
  AxesLabel -> {
    Style["X",  Bold, 14],
    Style["Y",  Bold, 14]
  ColorFunction -> "Rainbow",
  MeshFunctions -> {(#3&)},
  MeshStyle -> GrayLevel[0.25],
  ImageSize -> 600
{t, 0, 40, 0.01, 
  ImageSize -> Large,
  Appearance -> {"Labeled", "Closed"}, 
  AppearanceElements -> {"InputField", "Slider"}
 ControlPlacement -> Bottom,
 FrameMargins -> True, 
 FrameLabel -> {None, None, 
   Style["Title", Bold, 14, FontFamily -> "Helvetica"]}

My problem here is that I want to define a sum of random traveling waves, with random orientations in the plane, so the angles used should stay the same in a given sin wave (the angle is called two times in the sinus), while the angle should be variable over all the waves. Currently, what I've done above (using Table) appears to work well, but I find my code a bit clumsy and heavy just for that task.

So is there a simpler way in doing this?


To make it more Mathematica-y, we don't even need to define functions to call the parameters/the parts of the individual parameter lists. Instead we can create all the parameters at the same time and group them together per wave. After that, we can Apply the summand to each of the sets of wave-parameters, then total the list.

nwaves = 50;
params = RandomReal[#, nwaves] & /@ {(*angs*){0, 2 Pi},(*amps*){0.5, 1},(*freqs*){0.5, 1.5},(*phases*){0, 2 Pi}} // Transpose;
randomBumps[t_, x_, y_] = #2 Sin[#3 (t - AngleVector[#1].{x, y}) + #4] & @@@ params // Total

I also changed Nwaves to nwaves to keep with the convention of not having user defined variables begin with capital letters (cause the system expressions do), and -Cos[angle[n]]x - Sin[angle[n]]y to -AngleVector[#1].{x, y} to further compactify the code and possibly illuminate the motivation behind the computation.

  • $\begingroup$ The problem with this code is that it's very hard to read and understand (at least to me), and to edit the parameters if we're not sure of what they're doing. It's just too compact and obscure! $\endgroup$
    – Cham
    Dec 15 '20 at 14:43

Here's a way which is just a bit simpler, and closer to what I like. I believe that it makes the code clear about what it's doing:

angle = Table[RandomReal[{0, 2Pi}], {k, 1, Nwaves}];
amplitude = Table[RandomReal[{0.5, 1}], {k, 1, Nwaves}];
frequency = Table[RandomReal[{0.5, 1.5}], {k, 1, Nwaves}];
phase = Table[RandomReal[{0, 2Pi}], {k, 1, Nwaves}];

randomBumps[t_, x_, y_] := Sum[amplitude[[n]]Sin[frequency[[n]](t - Cos[angle[[n]]]x - Sin[angle[[n]]]y) + phase[[n]]], {n, 1, Nwaves}];

The vector scalar product idea from NonDairyNeutrino's answer is also a good thing.

EDIT: From the comment, here's a much better way:

angle = RandomReal[{0, 2Pi}, Nwaves];
amplitude = RandomReal[{0.5, 1}, Nwaves];
frequency = RandomReal[{0.5, 1.5}, Nwaves];
phase = RandomReal[{0, 2Pi}, Nwaves];
  • 1
    $\begingroup$ Cham, stuff like Table[RandomReal[{0, 2Pi}], {k, 1, Nwaves}] may be clearer to you, but it's pretty bad practice performance-wise. RandomReal will give you what you want directly, as in: RandomReal[{0, 2Pi}, Nwaves]. For large numbers of points being generated, initializing the random number generators only once and generating multiple points at once is far faster. $\endgroup$
    – MarcoB
    Dec 15 '20 at 17:14
  • $\begingroup$ @MarcoB, so you suggest for example angle = RandomReal[{0, 2Pi}, Nwaves]; instead? $\endgroup$
    – Cham
    Dec 15 '20 at 17:18
  • $\begingroup$ @MarcoB, indeed, it's much better. This is the kind of Mathematica stuff for which I'm very rusty, since I didn't used Mma since a pretty long time. $\endgroup$
    – Cham
    Dec 15 '20 at 17:32
  • $\begingroup$ @Cham if it makes it less obscure for you, you should be able to take the answer that is too compact for you, and replace params with {angles, amplitudes, frequencies, phases} and this may be better for your to understand. $\endgroup$ Dec 17 '20 at 23:59

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.