??? Attempt to reference field of non-structure array. Error - matlab

So far from what I have read this error can be caused by confusing or redundant naming within the program but I don't think that is the issue here since everything is declared clearly. From what I can see in this my issue is coming from the declaration of piecewise that is then being run through integration below and therefor the program is attempting to access a array cell that doesn't exist. If this is the case I have so far been stumped at how to fix this issue. Any assistance with this problem would be greatly appreciated.
syms t k n
fct = #(t)evalin(symengine,['subs(piecewise([0 <= t and t < 2,',...
'sin((Pi*t^2)/4)],[t <= 2 and t < 3, 5*t-t^2-6], [t <=3 and t < 4, 0],',...
'[Otherwise, t-4]),t=',regexprep(mat2str(x),' ',','),')']);
evalin(symengine,'assume(k,Type::Integer)');
a = #(fct,t,k) int(fct*cos(k*pi*t/4)/4,t,-2,8);
b = #(fct,t,k) int(fct*sin(k*pi*t/4)/4,t,-2,8);
FourierSeries = #(fct,t,n) a(fct,t,0)/4 + ...
symsum(a(fct,t,k)*cos(k*pi*t/4) + b(fct,t,k)*sin(k*pi*t/4),k,1,n);
pretty(FourierSeries(t,25,1))
ezplot(FourierSeries(t,25,1),-2,8)
hold on
ezplot(fct,-2,8)
hold off
title('Partial sum with n=25')
The complete error text is as follows:
??? Attempt to reference field of non-structure array.
Error in ==> sym.int at 56
r = mupadmex('symobj::intdef',f.s,x.s,a.s,b.s);
Error in ==> #(fct,t,k)int(fct*cos(k*pi*t/4)/4,t,-2,8)
Error in ==>
#(fct,t,n)a(fct,t,0)/4+symsum(a(fct,t,k)*cos(k*pi*t/4)+b(fct,t,k)*sin(k*pi*t/4),k,1,n)
Error in ==> FourierProgram at 16 pretty(FourierSeries(t,25,1))

This was asked long ago, but I'll provide an answer since one was never given.
As your error indicates, the issue is with this line and how the anonymous function a is called:
a = #(fct,t,k) int(fct*cos(k*pi*t/4)/4,t,-2,8);
The sym/int function expects the second argument (the variable with which the integration is performed with respect to) to be a symbolic variable. However, you're calling FourierSeries(t,25,1), which passes the value 25 as the integration variable.
This bit of code should replicate the issue in your version of Matlab (back in 2011 when this was asked):
syms t k;
int(t*cos(k*pi*t/4)/4,25,-2,8)
However, in R2015a I now get a different (and a bit clearer) error message:
Cannot integrate with respect to ''. The integration variable must be a symbolic variable.

Related

Can't access Range method of Range object; COM limitations?

In the Excel VBA Editor's Immediate Window, I can do the following:
?ActiveSheet.Range("C3:D4").Range("C3:D4").Address
$E$5:$F$6
According to some simple tests, this doesn't seem to respond the same in Matlab. Here is the code to set up the COM interface for the tests:
excel = actxserver('Excel.Application');
excel.Visible=1;
wbks = excel.Workbooks;
wbks.Add
sht = wbks.Item(1).Sheets.Item(1)
%
% Run some range tests
%
try
excel.DisplayAlerts = 0; % Forgo save prompt on Close
end; try
wbk.Close
end; try
excel.Quit % Excel process still present
end; try
delete(excel) % Excel process disappears
end % try
Now, with sht being a Worksheet object, I get the following error instead:
K>> o=sht.Range('C3:D4')
o = Interface.Microsoft_Excel_14.0_Object_Library.Range
K>> o.Range('C3:D4').Address
Cannot find an exact (case-sensitive) match for 'Range'
The closest match is: range in C:\Program Files\MATLAB\Single_R2015b\toolbox\stats\stats\range.m
Did you mean: K>> o.range('C3:D4').Address
This is the wrong function, since range with an uncapitalized r is the internal Matab function. Hence, I pressed Ctrl-C to break out (otherwise, it complains about the incompatible argument).
To troubleshoot why Range is not recognized, check whether is is a method or property. When accessed via COM, Range is a method rather than a property:
K>> methods(o)
Methods for class Interface.Microsoft_Excel_14.0_Object_Library.Range:
<...snip...>
PrintPreview Table
Range TextToColumns
RemoveDuplicates UnMerge
<...snip...>
This further shows that Range is not a property (even though it is in VBA):
K>> get(o)
<...snip...>
QueryTable: 'Error: Object returned error code: 0x800A03EC'
Resize: [1x1 Interface.Microsoft_Excel_14.0_Object_Library.Range]
Row: 3
<...snip...>
Since properties are listed alphabetically, Range would show up after QueryTable if it was recognized as a property. However, it isn't listed in the above results.
As an alternative diagnostic step, I tried accessing Range using the dot notation (o.Range). Unfortunately, Matlab seems to got for its own native function range, which has nothing to do with an Excel Range.
So after all that diagnostic work....
THE QUESTION
For a given Range object, how does one access the Range method (as recognized by COM) or the Range property (as it is described in the VBA documentation)?
AFTERNOTE
There seem to be many discrepancies with in accessing Range properties and methods via the COM interface. In the Immediate Window, one can use the Offset property (it is desribed as a property):
? ActiveSheet.Range("C3:D4").Offset(2,3).Address
$F$5:$G$6
Over COM, not so much, even though get(o) shows Offset to be a valid property that returns a range:
K>> o=sht.Range('C3:D4')
o = Interface.Microsoft_Excel_14.0_Object_Library.Range
K>> o=o.Offset(2,2)
Index exceeds matrix dimensions.
Here is a solution I've reached by trial and error, refined with some help with Matlab technical support:
Invoke get as a method, then supply the desired property name. It works for property Offset.
K>> o = sht.Range('C3:D4')
o = Interface.Microsoft_Excel_14.0_Object_Library.Range
K>> o.get('Offset',2,3).Address
ans = $F$5:$G$6
It works for Range, too.
K>> o = sht.Range('C3:E5')
o = Interface.Microsoft_Excel_14.0_Object_Library.Range
K>> o.get('Range','B2:C3').Address
ans = $D$4:$E$5
The strange thing is that Range is a method according to COM (but a property according to the Excel VBA documentation). Despite being seen as a method when accessed via COM, it needs to be invoked using get rather than invoke. The latter yields an error:
K>> o.invoke('Range','B2:C3').Address
Error using Interface.Microsoft_Excel_14.0_Object_Library.Range/invoke.
Cannot find an exact (case-sensitive) match for 'Range'.
The closest match is: range in C:\Program Files\MATLAB\Single_R2015b\toolbox\stats\stats\range.m

How to plot a parabola by getting its parameters from the gui using MATLAB

I've tried to do it like this:
I've found this https://www.quora.com/How-do-I-draw-a-parabola-in-MATLAB and tried to use it like that:
a=str2double(get(handles.InputA,'string'));
b=str2double(get(handles.InputB,'string'));
c=str2double(get(handles.InputC,'string'));
xLine=[(-b)/2*a-5:0.01:(-b)/2*a+5];
yToPlot= a*x.^2 + b.x+c;
plot(xLine,yToPlot);
but I keep getting errors...any help would be appreciated
You define the variable xLine, but use the variable x in yToPlot. That's why you get an error saying x is not defined. Also in yToPlot you have b.x. MATLAB then thinks that b is a struct and that you want to access the field named x of b. Since b is not a struct, and doesn't have a field x, you'll get the error 'Attempt to reference field of non-structure array.'. If you fix these two, it should work, according to the code you've given:
xLine=[(-b)/2*a-5:0.01:(-b)/2*a+5];
yToPlot= a*xLine.^2 + b*xLine+c;
plot(xLine,yToPlot);

Error while passing arguments to events function

I have a function called initial which takes an argument funname and performs some integration. I wanted to pass multiple arguments to events function. So I did this:
odeopt=odeset('RelTol',1e-5,'AbsTol',1e-5,'Events',#(t,y) events(t,y,prm,funname));
fun=str2func(funname);
[t,y]=ode15s(fun,[0 3600],z,odeopt,prm);
prm is a structure and funname is a string.
This is the events function:
function [value,isterminal,direction] = events(t,y,prm,funname)
isterminal=1;
direction=0;
v=feval(funname,1,y,prm);
value=~all(v<1e-10);
funname is basically the ode function.
It still says too many input arguments.:
??? Error using ==> initial>#(t,y)events(t,y,prm,funname)
Too many input arguments.
Error in ==> odeevents at 29
eventValue = feval(eventFcn,t0,y0,eventArgs{:});
Error in ==> ode15s at 263
[haveEventFcn,eventFcn,eventArgs,valt,teout,yeout,ieout] = ...
Error in ==> initial at 10
[t,y]=ode15s(fun,[0 3600],z,odeopt,prm);
Can't be a problem of version (was using 7.6) because this post which addresses this issue was on 2006.
Any Idea?
Since prm is passed as the last argument in ode15s, it will result in the eventArgs cell passing the value to the event handle. In other words, the line
eventValue = feval(eventFcn,t0,y0,eventArgs{:});
is really doing
eventValue = eventFcn(t,y,prm);
So if prm is needed as an extra parameter in the ODE system, just make prm an input in the event handle:
odeopt=odeset(..., #(t,y,prm) events(t,y,prm,funname));
Also, since the events function is design to locate solutions passing through zeros, the value should be a double such that MATLAB's sign function works properly.

Error with struct2table command

I am getting the following error while running a program.
??? Undefined function or method 'struct2table' for input arguments of type 'struct'.
Error in ==> cellarray at 13
T=struct2table(parameter,'AsArray',true);
The program is as under
a=10;
b=15;
parameter(a).alpha_star=0;
parameter(b).gamma_star=0;
x=5;
for j=1:b
for i=1:a
parameter(i).alpha_star=x+i;
end
parameter(j).gamma_star = x^2+j;
end
T=struct2table(parameter,'AsArray',true);
Can you please tell me, where am I wrong?
I am guessing you have a matlab older than R2013b, and since do not have this function (you can check that via which struct2table).
you can try to work around it by using struct2array and reshape.
you can also use
alp=[];
gam =[];
for i=1:length(parameter)
if ~isempty(parameter(i).alpha_star)
alp(end+1)=(parameter(i).alpha_star);
end
if ~isempty(parameter(i).gamma_star)
gam(end+1)=(parameter(i).gamma_star);
end
end
to extract the values to seperate arrays and
fieldnames(parameter);
to get the fieldnames, this is dirty but if it is only needed for presentation...

an error in Matlab: Input argument undefined, although variable is existing

I have written this function, and I have already defined values for rg and Lp, but still when I run this function it returns the error : (Input argument "Lr" is undefined.
Error in ==> Bis at 12
if f(Lr,rg,Xo)*f(Lr,rg,Xf)>0)
here is the function :
function[Lp,Xo,Xf]=Bis(Lr,rg)
Xo=0;
Xf=10;
Err=0.01;
syms x;
f=inline('(sqrt((2/3)*(((x*Lr)/3)-(x*x)+((2*x*x*x)/Lr)-((2*x*x*x*x)/(Lr*Lr))+(((2*x*x*x*x)/(Lr*Lr))*exp(-Lr/x))))-rg)');
if f(Lr,rg,Xo)*f(Lr,rg,Xf)>0
disp('The values you entered are not apropriate !')
PlotLpFunction;
Lp='unknown';
elseif f(Lr,rg,Xo)*f(Lr,rg,Xf)==0
if f(Lr,rg,Xo)==0
Lp=Xo;
elseif f(Lr,rg,Xf)==0
Lp=Xf;
end
elseif f(Lr,rg,Xo)*f(Lr,rg,Xf)<0
xi=(Xf-Xo)/2;
while abs(f(Lr,rg,xi))>Err
if f(Lr,rg,xi)*f(Lr,rg,Xf)<0
Xo=xi;
xi=(Xo+Xf)/2;
elseif f(Lr,rg,xi)*f(Lr,rg,Xf)>0
Xf=xi;
xi=(Xo+Xf)/2;
end
end
Lp=xi;
end
The code executes for me on the newest version of Matlab, other than the fact that I don't have the PlotLpFunction.
My initial impression was that you forgot to send the Lr (and all other argument) into you're inlined f function, very easy to fix by adding them as arguments to the inline function. You'll find the full usage in the official documentation.
The relevant part being
inline(expr,arg1,arg2,...) constructs an inline function whose input
arguments are specified by the strings arg1, arg2,.... Multicharacter
symbol names may be used.
but it seems to form the inline just fine by itself on both Matlab 2011b and 2008b, from context presumably. Answer is accepted now, so presumably that was the problem. Can anyone else reproduce his problem? If so please provide your Matlab version or other circumstances.