I'm working on some code that numerically integrates a function, let's call it G, which calls another function, F, that can be defined according to any of several models. In one model, there is an analytic expression for F. In the other models, F needs to be defined by loading data from a file and interpolating it. There is a different data file for each model (other than the analytic one).
One way I tried to do this was to have a Switch statement in F, and get it to choose whether to use the analytic expression or to take data from a file each time it's called based on the options provided.
(* load data from a file and Interpolate it *)
FFromFile[filename_] := FFromFile[filename] = Module[{...}, ...]
FAnalytic[a_,b_,c_] := a^2+b^2+c^2
F[a_,b_,c_,OptionsPattern[]] := Switch[OptionValue[Model],
"File",FFromFile[OptionValue[Source]][a,b,c],
"Expr",FAnalytic[a,b,c]
]
G[d_,e_,f_,phi_,opts:OptionsPattern[]] := Block[{g,h,i},
(* do a bunch of calculations to figure out g and h *)
i = F[g, h, 5, opts];
(* do more calculations involving i *)
]
GenerateData[phi_,opts:OptionsPattern[]] := NIntegrate[G[x,y,z,phi,opts],
{x,2,10}, {y,0,x}, {z,0,3}, Method->"QuasiMonteCarlo", PrecisionGoal->3]
Unsurprisingly, that turned out to be too slow. So, another method I tried was to predefine F, since the same model is used throughout an integration.
(* load data from a file and Interpolate it *)
FFromFile[a_,b_,c_] = Module[{v,...}, v=ReadList[filename, ...]; ...];
FAnalytic[a_,b_,c_] = a^2+b^2+c^2;
Switch[TheModel,
"File",F=FFromFile,
"Expr",F=FAnalytic
]
G[d_,e_,f_,phi_] := Block[{g,h,i},
(* do a bunch of calculations to figure out g and h *)
i = F[g, h, 5];
(* do more calculations involving i *)
]
GenerateData[phi_] := NIntegrate[G[x,y,z,phi],
{x,2,10}, {y,0,x}, {z,0,3}, Method->"QuasiMonteCarlo", PrecisionGoal->3]
filename and TheModel would be defined prior to running this code snippet. This way is faster, though it turns out to be kind of inconvenient because sometimes I want to run calculations that compare two different models (for example, from two different files), which requires me to run one, save the data to a file, quit the kernel to ensure that all the definitions are cleared, start it up again and run the other. Plus, this method of passing information to the function by defining variables in advance (filename and TheModel) makes me kind of queasy ;-)
Is there some way I can get the best of both worlds, namely be able to specify the model by passing options to GenerateData, while still retaining the speed benefits of predefining F?