MATLAB Class Efficiency - matlab

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...]

Related

"Undefined" error for rewriting but not redefining an already defined function

This works (plots an "empty" figure):
function testme
plot(1)
This works (returns 1):
function testme
plot = #(x)x;
plot(1)
This does not (Error: "Undefined function or variable 'plot'."):
function testme
if 0
plot = #(x)x;
end
plot(1)
What's going on here? Why does rewriting but not redefining an already defined function render the function undefined?
Note 1: this is not specific for builtin functions; the following code returns the same error:
function testme
if 0
myfun = #(x)x;
end
myfun(1)
function x=myfun(x)
x=x*2;
Note 2: the error occurs in a function environment, not in a script; the following code does not return an error (and plots the same empty figure as in the first example):
if 0
plot = #(x)x;
end
plot(1)
Update: For the interested reader, here is some background information
on my original problem. The above examples are just minimum working
samples to illustrate the main issue (which indeed feature dead end if
statements). In practice, I was trying to make a function useable for
colleagues who did not have certain library/toolbox functions
available, by overwriting those functions for simplified custom ones
if they did not exist, as a quick fix. In particular, it concerned
imdilate (and imerode). The function looked something like the
following:
function [myoutputs] = myfunction(myinputs)
% if the images toolbox is not available, use the following simplified
% replacement function
if ~exist('imdilate','file')
imdilate = #(IM,SE)vecdilate(IM,SE);
end
%% The original function goes here, which uses a lot of imdilate(IM,SE).
%% local functions
function M = vecdilate(IM,SE)
% simplified version of imdilate (can only process 1-D vertical arrays)
nSE = size(SE);
nIM = size(IM);
SE = logical(SE); % make logical if it isn't yet
% copy and shift xth column x down. new border entries are 0:
M = repmat([IM;zeros(nSE)],nSE);
M = M(1:end-nSE(1));
M = reshape(M,[size(M,1)/nSE(1) nSE(1)]);
% shrink back to column by taking max of every row:
M = max(M(:,SE),[],2);
M = M(ceil(nSE(1)/2)-1+(1:nIM(1))); % clip to obtain correct size
You might see that the replacement function covers some
functionality of imdilate, but not all, and it might not be as
efficient. The purpose simply was to use function A if it was available, and
function B if it was not. To my surprise however, the former case
returned an error, which eventually resulted in this question. For your interest, I solved the practical problem by renaming the function in the
original code, and by using an if/else statement:
function [myoutputs] = myfunction(myinputs)
% if the images toolbox is not available, use the following simplified
% replacement function
if ~exist('imdilate','file')
mydilate = #(IM,SE)vecdilate(IM,SE);
else
mydilate = #(IM,SE)imdilate(IM,SE);
end
%% The original function goes here, which uses a lot of mydilate(IM,SE).
%% local functions
function M = vecdilate(IM,SE)
etc. etc. etc.
Just-in-time-compilation (JIT) does not mean that there is no compilation and that every line is interpreted separately, so you can still mess with the code;)
The error would also appear if you use a not-defined function, where you woun't even expect the code to run, like
function [] = test()
if false
a = #(x)x;
end
a(1)
end
Scripts are stored command line entries, i.e. the compiler has no choice but to handle every line separately (you may want to think of it as a keyboard macro).
Functions in contrast are encapsulated pieces of code. The compiler (in general) does not expect anything unknown + it thinks that this encapsulated piece of code might be reused. Therefore, it makes sure to do a proper job compile all code once beforehand (if the compile would do this all the time, it is called ahead-of-time compilation).
This becomes in particular obvious when your clear the variables in between:
function [] = test()
if false
plot = #(x)x;
else
clear all % clear vs clear all
end
plot(1)
end
(Note that clear clears all variables but clear all would also clear excising code (see MATLAB Execution Engine))
Have a look at this interesting blog post from Loren
MATLAB provides the best of both worlds by compiling MATLAB code on-the-fly, or just-in-time. MATLAB code is compiled whether it be in classes, functions, scripts, or simply at the command line. There is no explicit compile step for the user to initiate and MATLAB code can be executed in blocks as small as one line at a time. The MATLAB JIT compiler generates native machine level code that is optimized for the MATLAB code being executed and for the specific hardware platform.
Anyway, you should not write dead ends in your code or overwrite (native) functions. It is good to use function handles to overcome this problem, but make sure that you define it for all cases
function [] = test()
if false % dead end definition
fnc = #(x)x;
else
fnc = #plot;
end
fnc(1)
end

Built-in function for assignment in Matlab

I was having a doubt today :).
For
A=1;
is there any function f that does the same? like following
f(A,1);
It could help me in some cases like in cellfun or something like that.
You can do this easily if your variable A is a handle class object, thus giving it reference behavior. You could then create a method f for the class that accepts a class object A and a new value for it to store. See Object-Oriented Programming for more information.
For data types like double or cell there are no built-in functions that work this way. You could make your own function using assignin and inputname like so:
function f(var, value)
assignin('caller', inputname(1), value);
end
And call it as follows, with A already defined:
A = 0;
f(A, 1); % Changes the value of A to 1
However, this would generally be considered bad practice as it makes the code harder to follow, as call-by-value behavior is the expected norm.
In general no, MATLAB functions cannot change their input.
But, if you are brave, you can create a MEX-file that breaks that promise and does change the input. In a MEX-file you can write to the input array, but doing so carelessly causes havoc. For example,
B = A;
f(A,1); % <- modifies A
would cause B to also be modified, because MATLAB delays copying the data when you do B = A. That is, the two variables point to the same data until you modify one, at which point the data is copied. But in a MEX-file you can write to a matrix without doing this check, thereby modifying B also. The link I provided shows how to modify A carefully.

How to write multiple test functions in a single file in Matlab (TDD implementation)

I have different test cases to test the different functions. I want to write all the different functions in one .m file and one test file to check all the different test cases.
https://www.mathworks.com/help/matlab/matlab_prog/write-simple-test-case-with-functions.html#zmw57dd0e66668
I followed the above link but I can see only one function implemented quadraticsolver but I want to implement multiple functions along with that for example calculating are of square, area of circle. can anyone help me in implementing multiple functions ?
More detailed about function-based tests can be found here.
Briefly, to implement multiple tests within the same .m file, you'll need one main function that shares it's name with the file and this main function should aggregate all local test functions within the file (using localfunctions) and then create an array of tests from these functions using functiontests. Each local test function should accept one input (a matlab.unittest.TestCase object).
my_tests.m
function tests = my_tests()
tests = functiontests(localfunctions);
end
% One test
function test_one(testCase)
testCase.assertTrue(true)
end
% Another test
function test_two(testCase)
testCase.assertFalse(true);
end
Then in order to run these tests, you'll want to use runtests and pass the filename or use run and pass the output of your function.
runtests('my_tests.m')
% or
run(my_tests)
Based on the help section linked above, you can also create setup and teardown functions that will act as setup and teardown functions, respectively.
Update
Based upon your comments, if you now have your tests all within one file but you want all of your other functions (the ones you are testing) to also be in one file, you can do this but it's important to note that any local function defined within an .m file that isn't the main function will only be accessible to other functions within that same file. There is more information in the documentation for local functions.
If you are interested in grouping related functions into a single cohesive file, then you may want to look into making your function a class. Using a class you can create separate methods instead of multiple functions as you say. If you haven't written a lot of object oriented code, then this is the beginning of many great and wonderful (and also frightful and terrible) things you can do in your software.
For example you can do something like this (note this is in three separate *.m files):
% Shape.m
classdef Shape
properties(Abstract)
Area
Circumference
end
end
% Circle.m
classdef Circle < Shape
properties(Dependent)
Area
Circumference
end
properties
Radius
end
methods
function circle = Circle(radius)
circle.Radius = radius;
end
function area = get.Area(circle)
area = pi*circle.Radius^2;
end
function circumference = get.Circumference(circle)
circumference = 2*pi*circle.Radius;
end
end
end
% Rectangle.m
classdef Rectangle < Shape
properties(Dependent)
Area
Circumference
end
properties
Length
Height
end
methods
function rectangle = Rectangle(length, height)
rectangle.Length = length;
rectangle.Height = height;
end
function area = get.Area(rectangle)
area = rectangle.Length*rectangle.Height;
end
function circumference = get.Circumference(rectangle)
circumference = 2*(rectangle.Length+rectangle.Height);
end
end
end
Note I showed the use of multiple properties, but since they are dependent they actually act like functions. Each time you ask for the property the function get.PropertyName is called just like a function. Also, note I showed multiple functions (properties) in these classes, but I didn't just lump everything together in one. I put them together into two cohesive classes. This cohesion is important for software design and keeping the code maintainable.
That said, these shapes can then be interacted with as follows:
>> c = Circle(5);
>> c.Area % calls the get.Area "function"
ans =
78.5398
>> c.Circumference
ans =
31.4159
>> r = Rectangle(4,5);
>> r.Area
ans =
20
>> r.Circumference
ans =
18
>>
Get started here and here.

How to store results from a callback function?

I have created a MATLAB gui in order to run a certain simulation.
In this gui is one button to start the simulation. This button callback function will then excecute the calculations. This will off course result in a dataset with the results.
Furthermore in the interface is a plot area, and a selectbox to switch between different graphs, in order to show different aspects of the simulation results. Therefore the results must be available for other functions in the gui as well. This is a problem, since the callback function has no output
Two solutions I can think of are storing the dataset in a MAT-file, or using global variables. The first solution seems not really correct to me, and furthermore I learned that global variabeles must be avoided if possible. So what is the best solution here?
you could create a user defined class inheriting from the handle class that defines your callbacks, your callbacks then execute from "inside" the handle class instance
classdef mySimulation < handle
properties
hFigure
mySimResults
end
methods
function this = mySimulation(varargin)
hFigure = figure;
...
<build figure components>
...
end
function myButtonCallback(this, src, evnt)
this.mySimResults = runMySimulation;
...
<update plot etc>
end
function mySelectBoxCallback(this, src, evnt)
...
<update plots>
end
end
end
MATLAB offers certain functions for this. There is the function guidata, which can store one variable. This can for instance be used to pass around your gui handles. Furthermore there are the functions setappdata and getappdata. These functions are the way to transfer data between functions, and couple variables to a figure handle.
More information on the different methods can be read here.
This is supposed to be semantically more correct then using global variables. However, I am still curious why. Any comments?

What is a function handle and how is it useful?

Can somebody explain to me the meaning of the # (function handle) operator and why to use it?
The function handle operator in MATLAB acts essentially like a pointer to a specific instance of a function. Some of the other answers have discussed a few of its uses, but I'll add another use here that I often have for it: maintaining access to functions that are no longer "in scope".
For example, the following function initializes a value count, and then returns a function handle to a nested function increment:
function fHandle = start_counting(count)
disp(count);
fHandle = #increment;
function increment
count = count+1;
disp(count);
end
end
Since the function increment is a nested function, it can only be used within the function start_counting (i.e. the workspace of start_counting is its "scope"). However, by returning a handle to the function increment, I can still use it outside of start_counting, and it still retains access to the variables in the workspace of start_counting! That allows me to do this:
>> fh = start_counting(3); % Initialize count to 3 and return handle
3
>> fh(); % Invoke increment function using its handle
4
>> fh();
5
Notice how we can keep incrementing count even though we are outside of the function start_counting. But you can do something even more interesting by calling start_counting again with a different number and storing the function handle in another variable:
>> fh2 = start_counting(-4);
-4
>> fh2();
-3
>> fh2();
-2
>> fh(); % Invoke the first handle to increment
6
>> fh2(); % Invoke the second handle to increment
-1
Notice that these two different counters operate independently. The function handles fh and fh2 point to different instances of the function increment with different workspaces containing unique values for count.
In addition to the above, using function handles in conjunction with nested functions can also help streamline GUI design, as I illustrate in this other SO post.
Function handles are an extremely powerful tool in matlab. A good start is to read the online help, which will give you far more than I can. At the command prompt, type
doc function_handle
A function handle is a simple way to create a function in one line. For example, suppose I wished to numerically integrate the function sin(k*x), where k has some fixed, external value. I could use an inline function, but a function handle is much neater. Define a function
k = 2;
fofx = #(x) sin(x*k);
See that I can now evaluate the function fofx at the command line. MATLAB knows what k is, so we can use fofx as a function now.
fofx(0.3)
ans =
0.564642473395035
In fact, we can pass fofx around, effectively as a variable. For example, lets call quad to do the numerical integration. I'll pick the interval [0,pi/2].
quad(fofx,0,pi/2)
ans =
0.999999998199215
As you can see, quad did the numerical integration. (By the way, an inline function would have been at least an order of magitude slower, and far less easy to work with.)
x = linspace(0,pi,1000);
tic,y = fofx(x);toc
Elapsed time is 0.000493 seconds.
By way of comparison, try an inline function.
finline = inline('sin(x*k)','x','k');
tic,y = finline(x,2);toc
Elapsed time is 0.002546 seconds.
A neat thing about a function handle is you can define it on the fly. Minimize the function cos(x), over the interval [0,2*pi]?
xmin = fminbnd(#(x) cos(x),0,2*pi)
xmin =
3.14159265358979
There are many, many other uses for function handles in MATLAB. I've only scratched the surface here.
Disclaimer: code not tested...
The function handle operator allows you to create a reference to a function and pass it around just like any other variable:
% function to add two numbers
function total = add(first, second)
total = first + second;
end
% this variable now points to the add function
operation = #add;
Once you've got a function handle, you can invoke it just like a regular function:
operation(10, 20); % returns 30
One nice thing about function handles is that you can pass them around just like any other data, so you can write functions that act on other functions. This often allows you to easily separate out business logic:
% prints hello
function sayHello
disp('hello world!');
end
% does something five times
function doFiveTimes(thingToDo)
for idx = 1 : 5
thingToDo();
end
end
% now I can say hello five times easily:
doFiveTimes(#sayHello);
% if there's something else I want to do five times, I don't have to write
% the five times logic again, only the operation itself:
function sayCheese
disp('Cheese');
end
doFiveTimes(#sayCheese);
% I don't even need to explicitly declare a function - this is an
% anonymous function:
doFiveTimes(#() disp('do something else'));
The Matlab documentation has a fuller description of the Matlab syntax, and describes some other uses for function handles like graphics callbacks.