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

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

Related

MATLAB Class Efficiency

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

Change a constant in ODE calculations under particular conditions with a flag

I have an ODE for calculating how acidicity changes. Everything is working just fine, only I would like to change a constant whenever acidicity reaches a critical point. It is supposed to be some kind of irreversible effect I wish to simulate.
My constants are coming from a structure file (c) I load once in the ODE function.
[Time,Results] = ode15s(#(x, c) f1(x, c),[0 c.length],x0,options);
The main problem I have here is not telling Matlab to change the constant but remember if it happened already during the simulation once. so Matlab should take the irreversibly changed constant rather than the one I supply at the beginning.
I would like to write a flag that is saved while the ODE is running and an if condition, "if flag exists, change constant". How to do that?
UPDATE I:
PROBLEM SOLVED
Here a first own solution, it is not polished and requires a structure file approach. Which means, the constants which should suddenly changed upon an event, must be struct files which are handed in the ODE function into the function that should be evaluated (look above for the ODE syntax). The function accepts the inputs like this:
function [OUTPUT] = f1(t, x, c)
% So here, the constants all start with c. followed by the variable name. (because they are structs instead of globals)
%% write a flag when that event happens
if c.someODEevent <= 999 && exist ('flag.txt') == 0
dlmwrite ('flag.txt',1);
end
%% next iteration will either write the flag again or not. more importantly, if it exists, the constant will change because of this.
if exist ('flag.txt') == 2
c.changingconstant = c.changingconstant/2;
end
end
Please look into Horchlers kind answer where you have to take care that such a step may introduce inaccuracies and you have to be careful to check if your code does what it is supposed to do.
To do this accurately, you should use event detection within the ODE solver. I can't give you a specific answer because you've only provided the ode15s call it in your question, but you'll need to write an events function and then specify it via odeset. Something like this:
function acidity_main
% load c data
...
x0 = ...
options = odeset('Events',#events); % add any other options too
% integrate until critical value and stop
[Time1,Results1] = ode15s(#(x,c)f1(x,c),[0 c.length],x0,options);
x0 = Results(end,:); % set new initial conditions
% pass new parameters -it's not clear how you're passing parameters
% if desired, change options to turn off events for faster integration
[Time2,Results2] = ode15s(#(x,c)f1(x,c),[0 c.length],x0,options);
% append outputs, last of 1 is same as first of 2
Time = [Time1;Time2(2:end)];
Results = [Results1;Results2(2:end,:)];
...
function y=f1(x,c)
% your integration function
...
function [value,isterminal,direction] = events(x,c)
value = ... % crossing condition, evaluates to zero at event condition
isterminal = 1; % stop integration when event detected
direction = ... % see documentation
You'll want to use the events to integrate right to the point where the "acidicity reaches a critical point" and stop the integration. Then call ode15s again with the new value and continue the integration. This may seem crude, but it how this sort of thing can be done accurately.
You can see an example of basic event detection here. Type ballode in your command window to see the code for this. You can see a slightly more complex version of this demo in my answer here. Here's an example of using events to accurately change an ODE at specified times (rather than your case of specified state values).
Note: I find it strange that you're passing what you call "constants", c, as the second argument to ode15s. This function has strict input argument requirements: the first is the independent variable (often time), and the second is the array of state variables (same as your initial condition vector). Also if f1 only takes two arguments, #(x,c)f1(x,c) is superfluous ā€“ it's sufficient to pass in #f1.

Calling functions & scripts in Matlab/Octave

How do call a script to a function and vica versa in Matlab/Octave?
function mean_DNA_Microarray = Calc_mean_DNA_Microarray(M)
M = DNA_Microarray
mean_DNA_Microarray = M - ones(5,25)*mean(M(:,25))
end
The response is
error: invalid call to script
C:\Users\Nacho\Documents\Matlab\DNA_Microarray.m error: called from:
error: C:\Users\Nacho\Documents\Matlab\Calc_mean_DNA_Microarray.m at
line 3, column 3
Now this will work if I call DNA_Microarray a function, but the problem requires that it remain as a script.
First of all, you are not defining your function correctly, as the function does not know what M is (unless it is a global vairable, but I doubt so).
In ANY programming language, you need to tell a function which variables it is going to work with. This is not Matlab specific. In Matlab you will do it so:
function mean_DNA_Microarray = Calc_mean_DNA_Microarray(M) % Look! we are telling him what M is!
mean_DNA_Microarray = M - ones(5,25)*mean(M(:,25))
end
Then you want to all the function from somewhere else you would need to just type its name and pass in the arguments, in this case what inside the function is going to be called M
clear;
clc;
% Test code
Mnameoutofthefunction=rand(100,100);
DNAmean = DNA_Microarray(Mnameoutofthefunction); % here we are calling it!
Remember to save the function as functionname.m , in your case DNA_Microarray.m , else Matlab wont know which one it is.
But I HIGHLY recommend you to read a book about Matlab or just about programming in general, as it seems like you could benefit from some basic introduction.
Following #am304 suggestion, here you can find nice tutorials:
http://www.mathworks.co.uk/academia/student_center/tutorials/
EDIT What you want to do is create a function as follows:
function mean_DNA_Microarray = Calc_mean_DNA_Microarray(M) % Look! we are telling him what M is!
mean_DNA_Microarray = M - ones(5,25)*mean(M(:,25))
end
And then, inside your function DNA_Microarray call Calc_mean_DNA_Microarray with the input M

MATLAB Using fzero - returns error

I'm trying to use the MATLAB function fzero properly but my program keeps returning an error message. This is my code (made up of two m-files):
friction_zero.m
function fric_zero = friction_zero(reynolds)
fric_zero = 0.25*power(log10(5.74/(power(reynolds,0.9))),-2);
flow.m
function f = flow(fric)
f = 1/(sqrt(fric))-1.873*log10(reynolds*sqrt(fric))-233/((reynolds*sqrt(fric))^0.9)-0.2361;
f_initial = friction_zero(power(10,4));
z = fzero(#flow,f_initial)
The goal is to return z as the root for the equation specified by f when flow.m is run.
I believe I have the correct syntax as I have spent a couple of hours online looking at examples. What happens is that it returns the following error message:
"Undefined function or variable 'fric'."
(Of course it's undefined, it's the variable I'm trying to solve!)
Can someone point out to me what I've done wrong? Thanks
EDIT
Thanks to all who helped! You have assisted me to eventually figure out my problem.
I had to add another file. Here is a full summary of the completed code with output.
friction_zero.m
function fric_zero = friction_zero(re)
fric_zero = 0.25*power(log10(5.74/(power(re,0.9))),-2); %starting value for fric
flow.m
function z = flow(fric)
re = power(10,4);
z = 1/(sqrt(fric))-1.873*log10(re*sqrt(fric))-233/((re*sqrt(fric))^0.9)-0.2361;
flow2.m
f_initial = friction_zero(re); %arbitrary starting value (Reynolds)
x = #flow;
fric_root = fzero(x,f_initial)
This returns an output of:
fric_root = 0.0235
Which seems to be the correct answer (phew!)
I realised that (1) I didn't define reynolds (which is now just re) in the right place, and (2) I was trying to do too much and thus skipped out on the line x = #flow;, for some reason when I added the extra line in, MATLAB stopped complaining. Not sure why it wouldn't have just taken #flow straight into fzero().
Once again, thanks :)
You need to make sure that f is a function in your code. This is simply an expression with reynolds being a constant when it isn't defined. As such, wrap this as an anonymous function with fric as the input variable. Also, you need to make sure the output variable from your function is z, not f. Since you're solving for fric, you don't need to specify this as the input variable into flow. Also, you need to specify f as the input into fzero, not flow. flow is the name of your main function. In addition, reynolds in flow is not defined, so I'm going to assume that it's the same as what you specified to friction_zero. With these edits, try doing this:
function z = flow()
reynolds = power(10,4);
f = #(fric) 1/(sqrt(fric))-1.873*log10(reynolds*sqrt(fric))-233/((reynolds*sqrt(fric))^0.9)-0.2361;
f_initial = friction_zero(reynolds);
z = fzero(#f, f_initial); %// You're solving for `f`, not flow. flow is your function name
The reason that you have a problem is because flow is called without argument I think. You should read a little more about matlab functions. By the way, reynolds is not defined either.
I am afraid I cannot help you completely since I have not been doing fluid mechanics. However, I can tell you about functions.
A matlab function definition looks something like this:
function x0 = f(xGuess)
a = 2;
fcn =#(t) a*t.^3+t; % t must not be an input to f.
disp(fcn);
a = 3;
disp(fcn);
x0 = fsolve(fcn1,xGuess); % x0 is calculated here
The function can then ne called as myX0 = f(myGuess). When you define a matlab function with arguments and return values, you must tell matlab what to do with them. Matlab cannot guess that. In this function you tell matlab to use xGuess as an initial guess to fsolve, when solving the anonymous function fcn. Notice also that matlab does not assume that an undefined variable is an independent variable. You need to tell matlab that now I want to create an anonymous function fcn which have an independent variable t.
Observation 1: I use .^. This is since the function will take an argument an evaluate it and this argument can also be a vector. In this particulat case I want pointwise evaluation. This is not really necessary when using fsolve but it is good practice if f is not a matrix equation, since "vectorization" is often used in matlab.
Observation 2: notice that even if a changes its value the function does not change. This is since matlab passes the value of a variable when defining a function and not the variable itself. A c programmer would say that a variable is passed by its value and not by a pointer. This means that fcn is really defined as fcn = #(x) 2*t.^3+t;. Using the variable a is just a conveniance (constants can may also be complicated to find, but when found they are just a value).
Armed with this knowledge, you should be able to tackle the problem in front of you. Also, the recursive call to flow in your function will eventuallt cause a crash. When you write a function that calls itself like this you must have a stopping criterium, something to tell the program when to stop. As it is now, flow will call ifself in the last row, like z = fzero(#flow,f_initial) for 500 times and then crash. Alos it is possible as well to define functions with zero inputs:
function plancksConstant = h()
plancksConstant = 6.62606957eāˆ’34;
Where the call h or h() will return Plancks constant.
Good luck!

How to wrap an already existing function with a new function of the same name

Is it possible to create a wrapper around a function that has the exact same name as the original function?
This would be very useful in circumstances where the user wants to do some additional checks on input variables before they are passed on to the built in function How to interrupt MATLAB IDE when it hangs on displaying very large array?
Actually alternatively to slayton's answer you don't need to use openvar. If you define a function with the same name as a matlab function, it will shadow that function (i.e. be called instead).
To then avoid recursively calling your own function, you can call the original function from within the wrapper by using builtin.
e.g.
outputs = builtin(funcname, inputs..);
Simple example, named rand.m and in the matlab path:
function out = main(varargin)
disp('Test wrapping rand... calling rand now...');
out = builtin('rand', varargin{:});
Note that this only works for functions that are found by builtin. For those that are not, slayton's approach is likely necessary.
Yes this is possible but it requires a bit of hacking. It requires that you copy around some function handles.
Using the example provided in the question I will show how to wrap the function openvar in a user defined function that checks the size of the input variable and then allows the user to cancel any open operation for variables that are too large.
Additionally, this should work when the user double clicks a variable in the Workspace pane of the Matlab IDE.
We need to do three things.
Get a handle to the original openvar function
Define the wrapper function that calls openvar
Redirect the original openvar name to our new function.
Example Function
function openVarWrapper(x, vector)
maxVarSize = 10000;
%declare the global variable
persistent openVarHandle;
%if the variable is empty then make the link to the original openvar
if isempty(openVarHandle)
openVarHandle = #openvar;
end
%no variable name passed, call was to setup connection
if narargin==0
return;
end
%get a copy of the original variable to check its size
tmpVar = evalin('base', x);
%if the variable is big and the user doesn't click yes then return
if prod( size( tmpVar)) > maxVarSize
resp = questdlg(sprintf('Variable %s is very large, open anyway?', x));
if ~strcmp(resp, 'Yes')
return;
end
end
if ischar(x) && ~isempty(openVarHandle);
openVarHandle(x);
end
end
Once this function is defined then you simply need to execute a script that
Clears any variables named openvar
run the openVarWrapper script to setup the connection
point the original openVar to openVarWrapper
Example Script:
clear openvar;
openVarWrapper;
openvar = #openVarWrapper;
Finally when you want to clean everything up you can simply call:
clear openvar;
I prefer jmetz's approach using builtin() when it can be applied, because it is clean and to the point. Unfortunately, many many functions are not found by builtin().
I found that I was able to wrap a function using a combination of the which -all and cd commands. I suspect that this approach can be adapted to a wide variety of applications.
In my example case, I wanted to (temporarily) wrap the interp1 function so that I could check for NaN output values. (The interp1 function will, by default, return a NaN under some conditions, such as if a query point is larger than the largest sample point.) Here's what I came up with:
function Vq = interp1(varargin)
persistent interp1_builtin;
if (isempty(interp1_builtin)) % first call: handle not set
toolbox = 'polyfun';
% get a list of all known instances of the function, and then
% select the first such instance that contains the toolbox name
% in its path
which_list = which('interp1','-all');
for ii = 1:length(which_list)
if (strfind(which_list{ii}, [filesep, toolbox, filesep]))
base_path = fileparts(which_list{ii}); % path to the original function
current_path = pwd;
cd(base_path); % go to the original function's directory
interp1_builtin = #interp1; % create a function handle to the original function
cd(current_path); % go back to the working directory
break
end
end
end
Vq = interp1_builtin(varargin{:}); % call the original function
% test if the output was NaN, and print a message
if (any(isnan(Vq)))
dbstack;
disp('ERROR: interp1 returned a NaN');
keyboard
end
end
See also: How to use MATLAB toolbox function which has the same name of a user defined function