2
$\begingroup$

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

1 Answer 1

6
$\begingroup$

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.

$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.