# Avoiding MainEvaluate in a CompiledFunction to fetch global variables

I'm trying to write a simulation using Mathematica 8.0. Since I will most likely be doing the same operation over and over again, I'm trying to Compile whatever I can. However, I've been having problems avoiding MainEvaluate calls when I define CompiledFunction objects which refer to global variables. A simplified sample of what I'm trying to use is:

g = 4.49*^3;
m = 1.;
s = 1.;
ϵ = 2.;
sAcceleration = Compile[{{sPosition, _Real, 1}},
(-g (m + s))/(sPosition.sPosition + ϵ*ϵ)^(3/2) sPosition];


I have also tried wrapping the whole thing inside a Module, to no avail:

sAcceleration2 =  Compile[{{sPosition, _Real, 1}},
Module[{gg = g, mm = m,  ss = s, ϵϵ = ϵ^2},
(-gg (mm + ss))/(sPosition.sPosition + ϵϵ)^(3/2) sPosition]];


They seem to run just fine. However, when I take a look at what the CompiledFunction is trying to do internally using CompilePrint

<< CompiledFunctionTools
CompilePrint[sAcceleration]
CompilePrint[sAcceleration2]


I get, respectively

1 R1 = MainEvaluate[ Function[{sPosition}, g][ T(R1)0]]

...

3 R1 = MainEvaluate[ Function[{sPosition}, m][ T(R1)0]]

4 R4 = MainEvaluate[ Function[{sPosition}, s][ T(R1)0]]

...

7 R6 = MainEvaluate[ Function[{sPosition}, ϵ][ T(R1)0]]

8 R7 = MainEvaluate[ Function[{sPosition}, ϵ][ T(R1)0]]

...

and

1 R1 = MainEvaluate[ Function[{sPosition}, g][ T(R1)0]]

2 R3 = MainEvaluate[ Function[{sPosition}, m][ T(R1)0]]

3 R4 = MainEvaluate[ Function[{sPosition}, s][ T(R1)0]]

4 R6 = MainEvaluate[ Function[{sPosition}, ϵ][ T(R1)0]]

...

Since I will most likely be toying with different values for these variables in different simulation runs, but they will be held constant within a given run, can I avoid both MainEvaluate and feeding these variables to my function as additional arguments? Thanks in advance.

• you might want to wait a bit longer before accepting the answer, in case someone else comes up with something better than I did. You can remove the checkmark for a while to encourage others to look at the question. – acl Jun 29 '12 at 10:58

## 2 Answers

Try this:

g = 4.49*^3;
m = 1.;
s = 1.;
ϵ = 2.;
With[{g = g, m = m, s = s, ϵ = ϵ},
sAcceleration = Compile[{{sPosition, _Real, 1}},
(-g (m + s))/(sPosition.sPosition + ϵ*ϵ)^(3/2) sPosition];
sAcceleration2 = Compile[{{sPosition, _Real, 1}},
Module[{gg = g, mm = m, ss = s, ϵϵ = ϵ^2},
(-gg (mm + ss))/(sPosition.sPosition + ϵ)^(3/2) sPosition]];
]


that is, inject the values before evaluation with With.

By the way, if you do SetSystemOptions["CompileOptions" -> {"CompileReportExternal" -> True}] then you'll be warned of calls to the main evaluator at compile time (i.e. without using CompilePrint).

• Works as intended! Thanks! – Editortoise-Composerpent Jun 29 '12 at 10:35
• By the way, using capitalized variable names can lead to conflicts. For instance, N and K are reserved. I use things like thisIsAVar to avoid this. Of course nothing will happen to you if you keep using G and so on, but you can sometimes end up with hard to diagnose bugs. – acl Jun 29 '12 at 11:28
• I know, thanks. I usually use longer names for variables, but just this time I gave in to laziness. – Editortoise-Composerpent Jun 29 '12 at 12:42

You could go even further than @acl's answer with something like this:

mkCF[g_, m_, s_, e_] := Module[{body, SPosition},
body = (-g (m + s))/(SPosition.SPosition + e*e)^(3/2) SPosition;
With[{body = body}, Compile[{{SPosition, _Real, 1}}, body]]
]
`

This has the advantage that body has seen an evaluation which in this cases means a simplification and consequently less to compute.