I try making it short. I got a problem involving numerical simulation of a flow withing a gas pipe. I simulate using different models for the air flow (transport equations) travelling from one boundary to the other (i.e. from right to left). The question is, since I am using different models to represent said gas flow and boundary conditions I got a lot of functions like:
boundary_left_model_1
boundary_right_model_1
boundary_left_model_2
boundary_right_model_2
boundary_left_model_2b
boundary_right_model_2b
....
flux_model_1
flux_model_2
....
source_model_1
source_model_2
.....
I allocate the needed function before the numerical scheme via (e.g.):
boundary_left = @[needed function];
boundary_right=@ [needed function];
flux = @[needed function];
source=@ [needed function];
What follows is something like:
Solution = numerical_scheme_#1(boundary_left,boundary_right,flux,source,parameters);
you get the point.
Now, what is the most efficient way (while being structured) to build the program? As far as I can tell I have three options:
1) I define every function in a matlab function file (will result in a lot of files)
2) I define every function in the script for the numerical scheme (will result in long file, which is less clear to adjust/read)
3) I create a class for boundary conditions with methods containing all the models, one class for fluxes and sources containing corresponding functions. In my function allocation for the numerical scheme I then call the methods I need. (seems complicated and inefficient, not sure about the time needed calling methods in matlab, but is for me the most structured way)
I should probably note that I am relatively new to matlab and numerical simulation (student) and I am also asking on how this kind of problem is generally solved. Thanks in advance! Also as a bonus: if someone is fond of practical simulation of PDE systems with matlab - I got questions like "How do I decide on a numerical scheme - which criteria should I consider?"
Thanks again, I wish all of you a pleasent day!
Assuming that the methods associated to model 1 are always used together, and not mixed with those for model 2 or 3, then you could set up your code with all functions for one model in one file:
% MODEL1 Methods that implement model 1
function [boundary_left,boundary_right,flux,source] = model1
boundary_left = @boundary_left_method;
boundary_right = @boundary_right_method;
flux = @flux_method;
source = @source_method;
function [out, args] = boundary_left_method(input, args)
% [implementation]
end
function [out, args] = boundary_right_method(input, args)
% [implementation]
end
function [out, args] = flux_method(input, args)
% [implementation]
end
function [out, args] = source_method(input, args)
% [implementation]
end
end
Basically, here you have a function that returns the handles to a set of functions that implement one method. boundary_left_method
is a private function, so cannot be accessed directly, but model1
can return handles to these functions, which makes them accessible.
You can now do:
[boundary_left,boundary_right,flux,source] = model1;
Solution = numerical_scheme_1(boundary_left,boundary_right,flux,source,parameters);
This solution is fairly similar to the custom class solution suggested by OP, but somewhat simpler. I don't think there would be a big difference in performance, but the only way to know for sure is implementing and timing the various options. What is most efficient changes over time as MATLAB's JIT improves.
Note that the scheme proposed here also allows for data (parameters
) to be included in these functions:
% MODEL1 Methods that implement model 1
function [boundary_left,boundary_right,flux,source] = model1(parameters)
boundary_left = @boundary_left_method;
boundary_right = @boundary_right_method;
flux = @flux_method;
source = @source_method;
function [out, args] = boundary_left_method(input, args)
out = input * parameters; % You can use PARAMETERS here, note that it is not
% an input argument to this nested function, it is
% found in the parent scope.
end
% ...
end % This end here is important now, this way `boundary_left_method` is an
% nested function, not simply a separate function within the same file.
Now the function handle boundary_left
returned has the data of parameters
embedded in it. See the relevant documentation.
If you control also the code to the numerical scheme functions that take these function handles, you could write method1
et al. to return a cell array of handles instead, and the numerical_scheme_1
et al. functions to take a cell array of handles. Then you can simply do:
numerical_scheme_1(method1,parameters);
numerical_scheme_1(method2,parameters);
numerical_scheme_1(method3,parameters);
numerical_scheme_2(method1,parameters);
numerical_scheme_2(method2,parameters);
numerical_scheme_2(method3,parameters);
% etc.
You could then use a loop to go through all combinations:
schemes = {@numerical_scheme_1, @numerical_scheme_2, ... };
methods = {method1, method2, method3, ... };
for ii=1:numel(schemes)
for jj=1:numel(methods)
schemes{ii}(methods{jj},parameters);
end
end
[Disclaimer: this code not tested, but I don't see why it wouldn't work...]