Module inside module in `Compile`

How can I make compilation to go through with a module inside module? I tried this, failed, a few other ways failed too.

f = Compile[
{{σt, _Real, 1}, {sρ, _Complex, 1}, {dt, _Real, 1}, {x, _Real}, {nnt, _Integer},
{dqt, _Real}, {divt, _Integer}},
Module[{temp, dq = dqt, div = divt, j, h},
temp[x_] :=
Module[{kz = 1/2 x, σ = σt, d = dt, i, kp, c, β, r, k, ρ = sρ * 10^-6, nn = nnt},
kp = kz + 0. I;
k = Sqrt[kz^2 – 4 π (ρ[[2]] – ρ[[1]])];
r = (kp – k)/(kp + k) E^(-2 kp k σ[[1]]^2);
c = {{1 + 0. I, r }, {r , 1}};
kp = k;
For[i = 2, i < 2 nn + 2, i++, If[EvenQ[i], k = Sqrt[kz^2 - 4 π (ρ[[3]] - ρ[[1]])]; r = (kp - k)/(kp + k) E^(-2 kp k σ[[2]]^2); β = I kp d[[1]], k = Sqrt[kz^2 - 4 π (ρ[[2]] - ρ[[1]])]; r = (kp - k)/(kp + k) E^(-2 kp k σ[[3]]^2); β = I kp d[[2]] ]; c = c.{{E^β, r E^β}, {r E^-β, E^-β}}; (*previous k*) kp = k ]; Abs[c[[2, 1]]/c[[1, 1]]]^2]; h = 0.0; For[j = 1, j < div + 1, j++, h = h + temp[x - dq/2 + dq/div*j] ]; h/div ] , CompilationTarget -> “C”]

=================

1

 

You should probably compile the more computation-intensive temp function on its own. You will also want to look at more efficient and idiomatic Mathematica alternatives to explicit For loops.
– MarcoB
Aug 26 ’15 at 23:52

3

 

On that note, you’ll be interested in the “InlineCompiledFunctions” and “InlineExternalDefinitions” suboptions of CompilationOptions.
– J. M.♦
Aug 27 ’15 at 1:52

=================

1 Answer
1

=================

There are two issues with your code. The first is that you have a variable name clash when using x as the argument in the definition of temp. Changing it to something else, e.g. q, will work in an uncompiled version of your code.

fff[σt : {__Real}, sρ : {__?NumericQ}, dt : {__Real},
x_Real, nnt_Integer, dqt_Real, divt_Integer] :=
Module[{temp, dq = dqt, div = divt, j, h},
temp[q_] :=
Module[{kz = 1/2 q, σ = σt, d = dt, i, kp,
c, β, r, k, ρ = sρ*10^-6, nn = nnt},
kp = kz + 0. I;
k = Sqrt[kz^2 – 4 π (ρ[[2]] – ρ[[1]])];
r = (kp – k)/(kp + k) E^(-2 kp k σ[[1]]^2);
c = {{1 + 0. I, r}, {r, 1}}; kp = k;
For[i = 2, i < 2 nn + 2, i++, If[EvenQ[i], k = Sqrt[kz^2 - 4 π (ρ[[3]] - ρ[[1]])]; r = (kp - k)/(kp + k) E^(-2 kp k σ[[2]]^2); β = I kp d[[1]], k = Sqrt[kz^2 - 4 π (ρ[[2]] - ρ[[1]])]; r = (kp - k)/(kp + k) E^(-2 kp k σ[[3]]^2); β = I kp d[[2]]]; c = c.{{E^β, r E^β}, {r E^-β, E^-β}}; (*previous k*)kp = k]; Abs[c[[2, 1]]/c[[1, 1]]]^2]; h = 0.0; For[j = 1, j < div + 1, j++, h = h + temp[x - dq/2 + dq/div*j]]; h/div] fff[{0.1, 0.2, 0.3}, {0.3 + 0.4 I, 0.4 - I, 1.2 + 0.6 I}, {0.2, 0.4, 0.6}, 0.3, 5, 0.8, 3] (* 7.65573*10^-8 *) The second is that SetDelayed doesn't work inside Compile. This error message comes up once you make the above change to the compiled version. You will need to find a different way to write the code (probably shuffling it so that the function defined by temp is part of the code rather than being defined as a separate sub-function). Alternatively create the temp function outside the main function. There is a good example in the documentation (under "Neat Examples") of a function that involves many sub-functions. As a small side note, you have defined β twice in your function but don't call it in between. This looks unintentional. There might be other problems with your code. I would strongly suggest testing an uncompiled version for correctness before moving to compilation.