octave: No function and no method found error - matlab

I get the following error trying to solve a non linear system in Octave:
error: #Jfun: no function and no method found
error: called from
voc at line 4 column 13
I'm using 4 scripts and I couldn't find the source of the error. The ffun, jfun and newtonsys files have been tested before and I am almost sure the issue is not there (I don't know if it could be an issue with the naming of variables though), but I have included them all below just in case.
file voc.m
x0=[9;8;0.5];
tol=10^-3;
nmax=1000;
[z,res,niter]=newtonsys(#Ffun,#Jfun,x0,tol,nmax)
File Ffun.m
q=1.602E-19;
k=1.381E-23;
Ncs=12;
Tc=329.25;
gamma=1.35;
Isc=9.14;
Rsh=94.5;
Vmp=37.8;
Imp=8.74;
function F=Ffun(x)
F(1,1)=Isc+x(2)*[exp((q*Isc*x(3))/(gamma*k*Tc*Ncs))-1]-(Isc*x(3))/Rsh-x(1);
F(2,1)=x(2)*[exp(q*(Voc)/(gamma*k*Tc*Ncs))-1]+(Voc/Rsh)-x(1);
F(3,1)=Imp+x(2)*[exp(q*(Vmp+Imp*x(3))/(gamma*k*Tc*Ncs))-1]+(Vmp+(Imp*x(3)))/Rsh-x(1);
endfunction
File JFun.m
q=1.602E-19;
k=1.381E-23;
Ncs=12;
Tc=329.25;
gamma=1.35;
Isc=9.14;
Rsh=94.5;
Vmp=37.8;
Imp=8.74;
function J=Jfun(x)
J(1,1)=-1;
J(1,2)=exp((q*Isc*x(3))/(gamma*k*Tc*Ncs))-1;
J(1,3)=x(2)*[exp((q*Isc*x(3))/(gamma*k*Tc*Ncs))]*(q*Isc/(gamma*k*Tc*Ncs))-(Isc/Rsh);
J(2,1)=-1;
J(2,2)=exp(q*(Voc)/(gamma*k*Tc*Ncs))-1;
J(2,3)=0;
J(3,1)=-1;
J(3,2)=exp(q*(Vmp+Imp*x(3))/(gamma*k*Tc*Ncs))-1;
J(3,3)=x(2)*[exp(q*(Vmp+Imp*x(3))/(gamma*k*Tc*Ncs))]*(q*Imp/(gamma*k*Tc*Ncs))+(Imp/Rsh);
endfunction
file newtonsys.m
function [x,res,niter] = newtonsys(Ffun,Jfun,x0,tol,...
nmax, varargin)
niter = 0;
err = tol + 1;
x = x0;
while err >= tol & niter < nmax
J = Jfun(x,varargin{:});
F = Ffun(x,varargin{:});
delta = - J\F;
x = x + delta;
err = norm(delta);
niter = niter + 1;
end
res = norm(Ffun(x,varargin{:}));
if (niter==nmax & err> tol)
fprintf(['Il metodo non converge nel massimo ',...
'numero di iterazioni. L''ultima iterata\n',...
'calcolata ha residuo relativo pari a %e\n'],F);
else
fprintf(['Il metodo converge in %i iterazioni',...
' con un residuo pari a %e\n'],niter,F);
end
return

The problem is your JFun.m file is NOT a function file, it is a script file which happens to define an 'on-the-spot' function JFun within it. If the voc.m script happens to call that function before it has been defined (i.e. before the JFun.m script has had a chance to be run and therefore end up defining that function in the current environment) then it will complain it's not there.
The solution in your case is to move all those variable definitions inside the function block, making it a proper 'function file', which will then be accessible from voc (as long as it's on the same directory / in the octave path).
Alternatively, if you still prefer JFun.m to be a script, (e.g. maybe you do want all those variables to end up being defined at global scope), then simply make sure you run it as a script first, such that it first defines the function you need; however, in that case, it is a good idea to change the name of your script to something else, so that its name doesn't conflict with the on-the-spot function defined inside it.
Have a quick look at the respective section in the manual, and in particular this part.

Related

MATLAB: How to automatically abort failed unit test

I am wondering how I can make a unit test to automatically stop, once an error in the system under test (sut) occurs?
Let's assume, the unit test runs some 1,000 different input combinations, and is supposed to verify that the results are equal to the expectations. Now, let's further assume there is a simple syntax error in sut, which causes an error. In this case I would like the unit test to automatically stop and invoke the tear down method.
Is that possible?
Edit:
I am borrowing a MATLAB example from their help site (https://de.mathworks.com/help/matlab/matlab_prog/create-basic-parameterized-test.html) in order to show more clearly what I mean:
Here you can see the test class:
classdef TestCarpet < matlab.unittest.TestCase
properties (TestParameter)
type = {'single','double','uint16'};
level = struct('small', 2,'medium', 4, 'large', 6);
side = struct('small', 9, 'medium', 81,'large', 729);
end
methods (Test)
function testRemainPixels(testCase, level)
% expected number pixels equal to 1
expPixelCount = 8^level;
% actual number pixels equal to 1
actPixels = find(sierpinski(level));
testCase.verifyNumElements(actPixels,expPixelCount)
end
function testClass(testCase, type, level)
testCase.verifyClass(...
sierpinski(level,type), type)
end
function testDefaultL1Output(testCase)
exp = single([1 1 1; 1 0 1; 1 1 1]);
testCase.verifyEqual(sierpinski(1), exp)
end
end
methods (Test, ParameterCombination='sequential')
function testNumel(testCase, level, side)
import matlab.unittest.constraints.HasElementCount
testCase.verifyThat(sierpinski(level),...
HasElementCount(side^2))
end
end
end
Here's the system under test:
function carpet = sierpinski(nLevels,classname)
if nargin == 1
classname = 'single';
end
% original line: mSize = 3^nLevels;
mSize = "That's clearly wrong here";
carpet = ones(mSize,classname);
cutCarpet(1,1,mSize,nLevels) % begin recursion
function cutCarpet(x,y,s,cL)
if cL
ss = s/3; % define subsize
for lx = 0:2
for ly = 0:2
if lx == 1 && ly == 1
% remove center square
carpet(x+ss:x+2*ss-1,y+ss:y+2*ss-1) = 0;
else
% recurse
cutCarpet(x + lx*ss, y + ly*ss, ss, cL-1)
end
end
end
end
end
end
I changed the definition of mSize to a string to produce an error. Now, if I run the tests, all tests will result in an error. I am wondering if it is possible to stop the tests as soon as possible, i.e. after the occurence of the first error?
The problem that I see is that the test code won't even reach the last line of testRemainPixels (testCase.verifyNumElements(actPixels,expPixelCount)). A fatalAssert does not help at this point, right?
Assuming you are using the test framework built into MATLAB, take a look at the types of qualifications, in particular the bulleted list at the top of this page:
https://www.mathworks.com/help/matlab/matlab_prog/types-of-qualifications.html
If you want to stop the entire testing session you can use fatal assertions. If you want other tests to continue you can use assertions. If you want to skip all the test methods (and parameterizations) in a single file you can use an assertion in TestClassSetup or just add a basic "smoke" level exercise step of the code in TestClassSetup and if it errors it will behave like an assertion.
Hope that helps.

Function 'subsindex' is not defined for values of class 'struct'

I am using the matlab to solve a simple model in economics. But I came across an error
Function 'subsindex' is not defined for values of class 'struct'
when I run the last line of code.
omega=mkt_share(Par,w,Grid);
It appears wired to me as I call this function repeatedly in the code before reaching the last line, it works fine. Could anyone inform me how to solve the problem? Thanks!
I post the full code of my program as following
clear all
Par.theta = 1.5;
Par.gamma = 6;
Par.beta = 0.1;
Par.zeta = 15;
Par.n = 100;
Grid.q = sort( gprnd(1/Par.zeta,1/Par.zeta,1,Par.n,1));
Grid.q = Grid.q./Grid.q(1);
w0=0.0001;
We0=tot_mkt_share(Par,w0,Grid);
mkt_share=mkt_share(Par,w0,Grid);
w1=0.01;
We1=tot_mkt_share(Par,w1,Grid);
while(We0*We1>0)
if We0<0
w0=w0*0.5;
We0=tot_mkt_share(Par,w0,Grid);
end
if We1>0
w1=w1*1.5;
We1=tot_mkt_share(Par,w1,Grid);
end
end
iconv2=0;
tol2=0.0000001;
maxit2=1000;
it2=1;
while(iconv2==0 && it2<=maxit2)
w=(w0+w1)/2;
We=tot_mkt_share(Par,w,Grid);
if abs(We)<tol2
iconv2=1;
disp('wage has converged in')
it2
else
if We*We1>0
w1=w;
else
w0=w;
end
it2=it2+1;
end
end
if it2>=maxit2
disp('Warning: Zero profit condition not satisfied')
end
omega=mkt_share(Par,w,Grid);
The code for function mkt_share
function omega=mkt_share(Par,w0,Grid)
omega=w0;
for i=2:Par.n
rel_q=Grid.q(i);
fcn=#(omega) (rel_q)^(-Par.gamma)*(omega/w0)^(1-Par.beta*Par.gamma)*((1-
((1-w0)/Par.gamma+w0/Par.theta))/(1-
((1omega)/Par.gamma+omega/Par.theta)))^(Par.gamma-1)-1;
omega_i=fsolve(fcn,w0);
omega=[omega',omega_i]';
end
The code for function tot_mkt_share, which calls function mkt_share
function tot_mkt_share=tot_mkt_share(Par,w0,Grid)
tot_mkt_share=sum(mkt_share(Par,w0,Grid))-1;
When you do:
mkt_share=mkt_share(Par,w0,Grid);
you create a variable with the same name as the function. From this point on, the function is no longer accessible, it is shadowed. The last line attempts to index into this variable, rather than call the function as you intend, because the function is shadowed.

How can I run a MATLAB script on .csv files in two separate folders at the same time?

So I have an iterative loop that extracts data from .csv files in MATLAB's active folder and plots it. I would like to take it one step further and run the script on two folders, each with their own .csv files.
One folder is called stress and the other strain. As the name implies, they contain .csv files for stress and strain data for several samples, each of which is called E3-01, E3-02, E3-03, etc. In other words, both folders have the same number of files and the same names.
The way I see it, the process would have the following steps:
Look in the stress folder, look inside file E3-01, extract the data in the column labelled Stress
Look in the strain folder, look inside file E3-01, extract the data in the column labelled Strain
Combine the data together for sample E3-01 and plot it
Repeat steps 1-3 for all files in the folders
Like I said, I already have a script that can find the right column and extract the data. What I'm not sure about is how to tell MATLAB to alternate the folder that the script is being run on.
Instead of a script, would a function be better? Something that accepts 4 inputs: the names of the two folders and the columns to extract?
EDIT: Apologies, here's the code I have so far:
clearvars;
files = dir('*.csv');
prompt = {'Plot name:','x label:','y label:','x values:','y values:','Points to eliminate:'};
dlg_title = 'Input';
num_lines = 1;
defaultans = {'Title','x label','y label','Surface component 1.avg(epsY) [True strain]','Stress','0'};
answer = inputdlg(prompt,dlg_title,num_lines,defaultans);
name_plot = answer{1};
x_label = answer{2};
y_label = answer{3};
x_col = answer{4};
y_col = answer{5};
des_cols = {y_col,x_col};
smallest_n = 100000;
points_elim = answer{6};
avg_x_values = [];
avg_y_values = [];
for file = files'
M=xlsread(file.name);
[row,col]=size(M);
if smallest_n > row
smallest_n = row;
end
end
smallest_n=smallest_n-points_elim;
avg_x_values = zeros(smallest_n,size(files,1));
avg_y_values = zeros(smallest_n,size(files,1));
hold on;
set(groot, 'DefaultLegendInterpreter', 'none');
set(gca,'FontSize',20);
ii = 0;
for file = files'
ii = ii + 1;
[n,s,r] = xlsread(file.name);
colhdrs = s(1,:);
[row, col] = find(strcmpi(s,x_col));
x_values = n(1:end-points_elim,col);
[row, col] = find(strcmpi(s,y_col));
y_values = n(1:end-points_elim,col);
plot(x_values,y_values,'DisplayName',s{1,1});
avg_x_values(:,ii)=x_values(1:smallest_n);
avg_y_values(:,ii)=y_values(1:smallest_n);
end
ylabel({y_label});
xlabel({x_label});
title({name_plot});
colormap(gray);
hold off;
avg_x_values = mean(avg_x_values,2);
avg_y_values = mean(avg_y_values,2);
plot(avg_x_values,avg_y_values);
set(gca,'FontSize',20);
ylabel({y_label});
xlabel({x_label});
title({name_plot});
EDIT 2: #Adriaan I tried to write the following function to get a column from a file:
function [out_col] = getcolumn(col,file)
file = dir(file);
[n,s,r] = xlsread(file.name);
colhdrs = s(1,:);
[row, col] = find(strcmpi(s,col));
out_col = n(1:end,col);
end
but I get the error
Function 'subsindex' is not defined for values of class 'struct'.
Error in getcolumn (line 21)
y = x(:,n);
not sure why.
You can do both, of course, and it depends on preference mainly, provided you're the sole user of the script. If others are going to use it as well, use functions instead, as they can contain a proper help file and calling help functionname will then give you that help.
For instance:
folders1 = dir(../strain/*)
folders2 = dir(../stress/*)
for ii 1 = 1:numel(folders)
operand1 = folders1{ii};
operand2 = folders2{ii};
%... rest of script
%
% Or function:
data = YourFunction(folders1{ii},folders2{ii})
end
So all in all you can use both, although from experience I find functions easier to use in the end, as you just pass parameters and don't need to trawl through the complete code to change the parameters each run.
Additionally you can partition off small parts of your program which do a fix task. If you nest your functions, and finally call just a single function in your scripts, you don't have to look at hundreds of lines of code each time you run the script, but rather can just run a single function (which can also be inside a script or function, ad infinitum).
Finally, a function has its own scope; meaning that any variables that are in that function stay within that function unless you explicitly set them as output (apart from global variables, but those are problematic anyway). This can be a good thing, or a bad thing, depending on the rest of your code. If you function would output ~20 variables for further processing, the function probably should include more steps. It'd be a good thing if you create lots of intermediate variables (I always do), because when the function's finished running, the scope of that function will be removed from memory, saving you clear tmpVar1 tmpVar2 tmpVar3 etc every few lines in your script.
For the script the argument in favour would be that it is easier to debug; you don't need dbstop on error and can step a bit easier through the script, keeping check of all your variables. But, after the debugging has been completed, this argument becomes moot, and thus in general I'd start with writing a script, and once it performs as desired, I rework it to a function at minimal extra effort.

Call a script with definitions in a function

We have a script that defines values to names similar to #define in c. For example:
script.m:
ERR_NOERROR = 0;
ERR_FATAL = 1;
This script already exists and is used for value replacement when reading data from files.
Now we have a function (or more) that does some analysis and we would like to use the same definition in this function to avoid magic numbers. But when the script is called from the function we get an error.
Attempt to add "ERR_NOERROR" to a static workspace.
See MATLAB Programming, Restrictions on Assigning to Variables for details.
And this does not help much in the understanding of the problem.
The question is how can we make these definitions visible/usable in the functions with having to copying it every time.
Example:
function foo = bar(a)
run(script.m) %also tried running it without the run command
if a == ERR_NOERROR
foo = 5;
else
foo = 6;
end
end
edit:
There was a nested function,below in the function which I was not aware of. This explains the problem.
This kind of scoping error happens when you use nested or anonymous function within a function. The solution is well documented.
To your case, you can avoid nested function, or "Convert the script to a function and pass the variable using arguments", as the documentation suggests.
EDIT: I should have made it clear that the error occurs even if the script is not called within the nested function. Similar scenario is that, in debug mode (by setting up a break point), it will be an error if one tries to create a temporal variable to test something.
This is not a direct answer, rather a recommendation to switch to another method, which will not be mixing scope and workspace.
Instead of defining your constant in a script, you could make a class containing only constant properties. ex: code for error_codes.m:
classdef error_codes
% ---------------------------------------------------------------------
% Constant error code definition
% ---------------------------------------------------------------------
properties (Constant = true)
noerror = 0 ;
fatal = 1 ;
errorlvl2 = 2 ;
errorlvl3 = 3 ;
warning = -1 ;
% etc ...
end
end
I use this style for many different type of constants. For tidiness, I groups them all in a Matlab package directory (The directories which starts with a + character.
The added benefit of using constant class properties is the safety that the values cannot be changed in the middle of the code (your variables defined in a script could easily be overwritten by a careless user).
So assuming my file error_codes.m is placed in a folder:
\...somepath...\+Constants\error_codes.m
and of course the folder +Constants is on the MATLAB path, then to use it as in your example, instead of calling the script, just initialise an instance of the class, then use the constant values when you need them:
function foo = bar(a)
ERR = Constants.error_codes ;
if a == ERR.noerror
foo = 5;
else
foo = 6;
end
or it can works in switch statement too:
switch a
case ERR.noerror
foo = 5 ;
case ERR.warning
foo = 42 ;
case ERR.fatal
foo = [] ;
end

Using both strings and functions in Matlab UnitTest diagnostics?

Please refer to the documentation for the testCase.verifyEqual method here. The documentation says that only one of the diagnostic features can be used. My requirement is I need two diagnostics at the same time - strings and function handle. The following is simple example of what I'm trying to achieve,
classdef testArrays < matlab.unittest.TestCase
methods (Test)
function testArraysEquality(testCase)
a = 1:10;
b = 1:10;
incrementFunc = #(x)x+1;
failureCount;
for i=1:length(a)
testCase.verifyEqual(a(i),b(i),'AbsTol',10e-3,['Test failed array element# ' num2str(i) ' failure count ' num2str(incrementFunc(failureCount))]);
end
disp([num2str(failureCount) ' out of ' num2str(length(a)) ' test cases failed']);
end
end
end
The problem is Anonymous function don't store values. On the other hand with the 'assignin' feature shown below, the value can be incremented and stored, but cannot be returned for use inside disp(). Is there any work around for this?
incrementFunc1 = #(x) assignin('caller', inputname(1), x+1);
You can include more than one (as well as more than one type) of diagnostic in the MATLAB Unit Test Framework by simply providing a diagnostic array to verifyEqual. You can actually do this explicitly as follows:
import matlab.unittest.diagnostics.StringDiagnostic;
import matlab.unittest.diagnostics.FunctionHandleDiagnostic;
testCase.verifyEqual(a,e, [StringDiagnostic('some string'), FunctionHandleDiagnostic(#() someFunction)]);
However, the Diagnostic.join method is provided to make that easier:
import matlab.unittest.diagnostics.Diagnostic;
testCase.verifyEqual(a,e, Diagnostic.join('some string', #() someFunction));
In order to do the increment call you are probably going to want to add a failed listener to the testCase in order to increment properly. Note that people/plugins can actually add listeners and execute these diagnostics in passing cases in addition to failing cases. As such your diagnostic messages should not assume that every time they are invoked it is in a failure condition. This not only applies to your incrementing code but also to just the message you are providing. I would suggest that instead of saying:
Test failed array element# 3 failure count 2
you should say:
Tested array element# 3 failure count 2
The framework diagnostic will let you know whether it failed or not. Anyway, takeaway, don't rely on invoking the diagnostics to determine failure count. What then? Take a look at the Events section here. You should listen explicitly for verification failed events in order to add that information to your diagnostics.
For the first solution, I am not sure why you need to provide the failure count for every failure. It seems like that would be very verbose. If you don't need that then you can do something like this:
classdef testArrays < matlab.unittest.TestCase
methods (Test)
function testArraysEquality(testCase)
a = 1:10;
b = 1:10;
failureCount = 0;
testCase.addlistener('VerificationFailed', #incrementFailureCount);
function incrementFailureCount(varargin)
% This is a nested function & has the scope and can see/modify
% the failureCount variable. This could also be done with a
% property on the class ans a method that increments it
failureCount = failureCount + 1;
end
for i=1:length(a)
testCase.verifyEqual(a(i),b(i),'AbsTol',10e-3,['Tested array element # ' num2str(i)]);
end
% I suggest using log instead of disp. If you want it to show up most of the time you can
% log it at Terse (1) verbosity. However, if you don't want to see it you can turn it off.
testCase.log(1, sprintf('%d out of %d test cases failed', failureCount, length(a)));
end
end
end
Is that good enough? If you really want to show the failure count in the diagnostics for each failure you can its just a bit more complicated and requires another nested function (or property access).
classdef testArrays < matlab.unittest.TestCase
methods (Test)
function testArraysEquality(testCase)
import matlab.unittest.diagnostics.Diagnostic;
a = 1:10;
b = 1:10;
failureCount = 0;
testCase.addlistener('VerificationFailed', #incrementFailureCount);
function incrementFailureCount(varargin)
failureCount = failureCount + 1;
end
function displayFailureCount
fprintf(1, 'Failure Count: %d', failureCount);
end
for i=1:length(a)
testCase.verifyEqual(a(i),b(i),'AbsTol',10e-3, ...
Diagnostic.join(...
['Tested array element #' num2str(i)], ...
#displayFailureCount));
end
testCase.log(1, sprintf('%d out of %d test cases failed', failureCount, length(a)));
end
end
end
Does that help you accomplish what you are trying to do?