When implementing the Numerov method solving Schrodinger equation, I encountered this problem. In order to show the order of the evaluation, Print
is added.
calU=Compile[{{x,_Real,1},{energy,_Real},{m,_Real},{a,_Real}},
Module[{i,node,xn,nn,phi,V,h,f,temp},
Print["begin ini"];
h=x[[3]];
xn=Range[x[[1]],x[[2]],h];
nn=Length@xn;
phi=Table[0.0,{nn}];
V=1/2 m a^2 xn^2;
f=2m(energy-V);
phi[[-2]]=h;
node=0;
Print["end ini"];
Print["begin cal"];
For[i=nn-2,i>1,i--,
phi[[i]]=1/(1+h^2/12 f[[i]]) (2(1-(5h^2)/12 f[[i+1]])phi[[i+1]]-(1+h^2/12 f[[i+2]])phi[[i+2]]);
If[phi[[i]]*phi[[i+1]]<0,node++];
];
Print["end cal"];
Print["begin renormalize"];
temp=Total[phi^2];
Print[temp];
phi=phi/Sqrt[temp h];
Print["end renormalize"];
{node-1,Transpose[{xn,phi}]}
]];
Evaluating Timing[calU[{0, 14, 0.0001}, 1.5001128419302405, 3.707412760373, 1.0];]
gives
begin ini
end ini
begin cal
end cal
begin renormalize (* <==weird happens here *)
begin ini
end ini
begin cal
end cal
begin renormalize
1.124558754621281*10^312
end renormalize
{2.468750, Null}
Please be noted that when comes to the "normalize" part, the process jump to the initialization without warning of overflow (it actually happens, since the maximum number in double precission is about 1.8*10^308) or using uncompiled one to preceed.
The output becomes weirder when evaluate Timing[calU[{0, 10, 0.0001}, 1.5001128419302405, 3.707412760374, 1.0];]
three times, the first two give
begin ini
end ini
begin cal
end cal
begin renormalize
1.16629*10^158
end renormalize
CompiledFunction::cfex: Could not complete external evaluation at instruction 114; proceeding with uncompiled evaluation. >>
begin ini
end ini
begin cal
end cal
begin renormalize
1.16629*10^158
end renormalize
{1.765625, Null}
even the "normalize" part is worked out they still jump to the "initialization" again; the third one gives the normal output as I expected (not the evaluation time)
So how to understand these?
Update
As blochwave point it out, the time cost is due to returning multiple results in compile and overflow.
Here comes two more related questions:
It seems that if overflow happens (it's turned off in default), Mathematica will drop the data already get and start over, why not taking over the data and using the main evaluation routine to do it?
I just find out that even if I set the RuntimeOptions -> "Quality" or turn on the "CatchMachineOverflow" , still there aren't any warnings. While "RuntimeErrorHandler" -> Function[Throw[\$Failed]] and catch it will get \$Failed. This inconsistence beats me again.
Print
? It's worth noting thatPrint
is not a compilable function in Mathematica, and so the function callsMainEvaluate
each time it encountersPrint
. You can check this byNeeds["CompiledFunctionTools`"]; CompilePrint@calU
. $\endgroup$Print
, I can only tell that the evaluation time is very close to the above. So my guess is yes. BTW, thank you for the link :) $\endgroup$