# 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"]

• 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. Aug 26, 2015 at 23:52
• On that note, you'll be interested in the "InlineCompiledFunctions" and "InlineExternalDefinitions" suboptions of CompilationOptions. Aug 27, 2015 at 1:52

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.