3
$\begingroup$

Let me start with a short preamble. I have a large function (defined through other functions) which I need to integrate numerically. This works. Trying to speed up the process, I played with Compiled version. This also works. Trying to speed up more, I started to include inside Compile as much as possible to avoid calls of external functions and expressions. This stopped to work. Then I realised that the problem is not with Compile itself but with that I was needed to use nesting modules.

Below is a minimal example where I can reproduce the error. Surely, the code below looks senseless, but my question is why an error appeared and whether is possible to avoid it without creating external functions.

Thank you very much in advance for any ideas.

In[1]:= ClearAll[good, bad];
good[u_?NumericQ] := Module[
   {func},
   func[v_?NumericQ] = Module[{y},
     y = u v 
     ];
   NIntegrate[func[k], {k, 0, 1}]];

bad[u_?NumericQ] := Module[
   {func},
   func[v_?NumericQ] = Module[{y},
     y = u v;
     Switch[Sign[y], 1, y, -1, y + 1, 0, 1] 
     ];
   NIntegrate[func[k], {k, 0, 1}]];

In[4]:= good[2]

Out[4]= 1.

In[5]:= bad[2]

During evaluation of In[5]:= NIntegrate::inumr: The integrand func$14934[k] has evaluated to non-numerical values for all sampling points in the region with boundaries {{0,1}}.

During evaluation of In[5]:= NIntegrate::inumr: The integrand func$14934[k] has evaluated to non-numerical values for all sampling points in the region with boundaries {{0,1}}.

During evaluation of In[5]:= NIntegrate::inumr: The integrand func$14934[k] has evaluated to non-numerical values for all sampling points in the region with boundaries {{0,1}}.

During evaluation of In[5]:= General::stop: Further output of NIntegrate::inumr will be suppressed during this calculation.

Out[5]= NIntegrate[func$14934[k], {k, 0, 1}]
$\endgroup$

1 Answer 1

5
$\begingroup$

Use := and not =

bad[u_?NumericQ] := Module[{func},
   func[v_?NumericQ] := Module[{y}, y = u v;
     Switch[Sign[y], 1, y, -1, y + 1, 0, 1]
     ];
   NIntegrate[func[k], {k, 0, 1}]
   ];

bad[2]
(* 1 *)

Without delay, func[k] evaluated right away, and hence it had no numerical values for the Switch to behave as expected. For the good example, you had no Switch there, so the problem did not show itself.

$\endgroup$
2
  • $\begingroup$ Thanks! Is it possible to do something else? If I want to create a compiled version of 'bad', delays inside will be forbidden I guess. $\endgroup$
    – Dmitri
    Apr 26, 2020 at 23:09
  • $\begingroup$ @Dmitri sorry, I do not know as I do not use Compile much myself. It is a good question. May be you could ask separate question on that and I am sure someone would know. $\endgroup$
    – Nasser
    Apr 26, 2020 at 23:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.