trying to use the following code to evaluate a triple integral which is a function of q,u. getting the error,
Warning: Maximum function count exceeded; singularity likely.
In quad at 107
In test1>Inner at 12
In test1>#(x)Inner(x) at 5
In quad at 76
In test1 at 5
Does anyone know what's wrong with this code?
function [r] = test1(q,u)
b = u;
r = zeros(1);
for i = 1 : length(q);
r(i) = quad(#(x)Inner(x),-2,q);
end;
function [w] = Inner(k)
w = zeros(1);
for i = 1 : length(k);
w(i) = quad(#(n)InnerIntegral(n).*unifpdf(k(i)-n,-1,1),0,k(i)-1,k(i)+1);
end;
function [y] = InnerIntegral(n)
y = zeros(1);
for i = 1 : length(n);
y(i) = quad(#(m)unifpdf(n(i)-m, -b, b).*unifpdf(m,-b,b), n(i)-b,n(i)+b);
end;
end
end
end
When you define multiple functions like this, each function's end statement must precede the next call to function. Currently, it looks like this is one giant function with a subfunction called Inner and that subfunction has yet another subfunction called InnerIntegral. So test1 is trying to call Inner, but `Inner's definition doesn't occur until later inside of the definition of test1.
I was having the same problem and then I came across a solution which worked or me.
Try using quadgk(Function,lowerlimit,upperlimit) instead of quad(Function,lowerlimit,upperlimit)
hth
the problem is in :
function [w] = Inner(k)
w = zeros(1);
for i = 1 : length(k);
w(i) = quad(#(n)InnerIntegral(n).*unifpdf(k(i)-n,-1,1),0,k(i)-1,k(i)+1);
end
the way it's set-up:
w(i) = quad(#(n)fcc(n),0,k(i)-1 , k(i)+1);
the last value of quad is set as the tolerance. I think you want to get rid of the 0 term:
w(i) = quad(#(n)InnerIntegral(n).*unifpdf(k(i)-n,-1,1),k(i)-1,k(i)+1);
Related
I'm using Matlab R2018a. This has a "memoize" function, which works at top level, but I don't see how to use it for recursive functions.
For example, I tried this:
function z = recfib(n)
if n == 1
z = 1;
else
z = memfib(n-1)+memfib(n-2);
end
fprintf('computed f(%d)=%d',n,z);
end
and then
memfib = memoize(#recfib);
But this doesn't work, as calls to memfib or recfib produce an error:
Undefined function or variable 'memfib'.
You need to stick that memfib somewhere that the calls inside the function can see it. If you just do memfib = memoize(#recfib) at the command line or in calling code, you end up with a memfib variable in the base/caller workspace, not a globally-visible memfib function.
I think you can do this with a persistent variable inside the recfib function. This works for me in R2019b.
function z = recfib(n)
persistent memfib
if isempty(memfib)
memfib = memoize(#recfib);
end
if n <= 1
z = 1;
else
z = memfib(n-1)+memfib(n-2);
end
fprintf('computed f(%d)=%d\n',n,z);
end
Running it twice shows the memoization happening:
>> recfib(8)
computed f(1)=1
computed f(0)=1
computed f(2)=2
computed f(3)=3
computed f(4)=5
computed f(5)=8
computed f(6)=13
computed f(7)=21
computed f(8)=34
ans =
34
>> recfib(8)
computed f(8)=34
ans =
34
>>
(Also, you've got a bug in the base case test; it needs to be n <= 1, not n == 1, to catch the 0 and -1 cases, because that memfib(n-2) line ends up calling memfib(0) when n = 2.)
I am currently trying to use parfor to sweep across a range of initial conditions for a set of differential equations solved by ode45. The code works fine using two nested for loops but I was hoping parfor could make the process more efficient. Unfortunately, I have run into an issue where the solver is able to solve one of the combinations in the matrix representing initial conditions across a range of variables, but the others seem to have their initial values all set at 0, instead of the values specified by the initial conditions. It may have something to do with the fact that I need to create a matrix of zeros ('P') that the results will be written into, perhaps overwriting the initial conditions(?) Any help would be greatly appreciated.
Thanks,
Kyle
function help(C, R)
A = 0.01;
B = 0.00;
C = [0.001,0.01];
D = 0.00;
R = [1e-10,1e-9];
[CGrid,RGrid] = meshgrid(C,R);
parfor ij = 1 : numel(CGrid)
c2 = [A; B; CGrid(ij); D; RGrid(ij)];
[t,c] = ode45('ode_sys',[0:1:300],c2);
for k=1:length([0:1:300])
for l=1:length(c2)
if c(k,l)<0
c(k,l)=0;
end
end
end
P = zeros(301,5,numel(R),numel(C));
temp = zeros(301,5);
temp(:,1) = c(:,1);
temp(:,2) = c(:,2);
temp(:,3) = c(:,3);
temp(:,4) = c(:,4);
temp(:,5) = c(:,5);
P(:,:,ij)=temp;
parsave('data.mat', P);
end
end
You have one error, and a few opportunities to simplify the code.
In the parfor loop, you have this line P = zeros(301,5,numel(R),numel(C)); which overwrites P with all zeros at each iteration. Put this before the parfor loop.
The first double-for loop that makes negative elements of c zero can be done using max(c,0), which should be more efficient. You can also do P(:,:,ij)=c(:,1:5) directly.
So you can replace your parfor loop with
P = zeros(301,5,numel(R),numel(C));
for ij = 1 : numel(CGrid)
c2 = [A; B; CGrid(ij); D; RGrid(ij)];
[t,c] = ode45('ode_sys',0:300,c2);
c = max(c,0);
P(:,:,ij) = c(:,1:5);
parsave('data.mat',P);
end
I have a Mechanical system with following equation:
xdot = Ax+ Bu
I want to solve this equation in a loop because in every step I need to update u but solvers like ode45 or lsim solving the differential equation for a time interval.
for i = 1:10001
if x(i,:)>= Sin1 & x(i,:)<=Sout2
U(i,:) = Ueq - (K*(S/Alpha))
else
U(i,:) = Ueq - (K*S)
end
% [y(i,:),t,x(i+1,:)]=lsim(sys,U(i,:),(time=i/1000),x(i,:));
or %[t,x] = ode45(#(t,x)furuta(t,x,A,B,U),(time=i/1000),x)
end
Do I have another ways to solve this equation in a loop for a single time(Not single time step).
There are a number of methods for updating and storing data across function calls.
For the ODE suite, I've come to like what is called "closures" for doing that.
A closure is basically a nested function accessing or modifying a variable from its parent function.
The code below makes use of this feature by wrapping the right-hand side function passed to ode45 and the 'OutputFcn' in a parent function called odeClosure().
You'll notice that I am using logical-indexing instead of an if-statement.
Vectors in if-statements will only be true if all elements are true and vice-versa for false.
Therefore, I create a logical array and use it to make the denominator either 1 or Alpha depending on the signal value for each row of x/U.
The 'OutputFcn' storeU() is called after a successful time step by ode45.
The function grows the U storage array and updates it appropriately.
The array U will have the same number of columns as the number of solution points requested by tspan (12 in this made-up example).
If a successful full step leaps over any requested points, the function is called with intermediate all requested times and their associated solution values (so x may be rectangular and not just a vector); this is why I used bsxfun in storeU and not in rhs.
Example function:
function [sol,U] = odeClosure()
% Initilize
% N = 10 ;
A = [ 0,0,1.0000,0; 0,0,0,1.0000;0,1.3975,-3.7330,-0.0010;0,21.0605,-6.4748,-0.0149];
B = [0;0;0.6199;1.0752 ] ;
x0 = [11;11;0;0];
K = 100;
S = [-0.2930;4.5262;-0.5085;1.2232];
Alpha = 0.2 ;
Ueq = [0;-25.0509;6.3149;-4.5085];
U = Ueq;
Sin1 = [-0.0172;-4.0974;-0.0517;-0.2993];
Sout2 = [0.0172 ; 4.0974; 0.0517; 0.2993];
% Solve
options = odeset('OutputFcn', #(t,x,flag) storeU(t,x,flag));
sol = ode45(#(t,x) rhs(t,x),[0,0.01:0.01:0.10,5],x0,options);
function xdot = rhs(~,x)
between = (x >= Sin1) & (x <= Sout2);
uwork = Ueq - K*S./(1 + (Alpha-1).*between);
xdot = A*x + B.*uwork;
end
function status = storeU(t,x,flag)
if isempty(flag)
% grow array
nAdd = length(t) ;
iCol = size(U,2) + (1:nAdd);
U(:,iCol) = 0 ;
% update U
between = bsxfun(#ge,x,Sin1) & bsxfun(#le,x,Sout2);
U(:,iCol) = Ueq(:,ones(1,nAdd)) - K*S./(1 + (Alpha-1).*between);
end
status = 0;
end
end
I have my code working using the integral function but I'm looking to implement it using the trapz function instead.
fc = 5*10^6;
fb = 0.2*10^6;
F = [0:10000:10^7];
Tb = 1/fb;
Sequence = [0 1 0 1 1 0 1 1 1 0 0 0 1 0 1 ];
A = sqrt(9/Tb);
w = 2*pi*fc;
I = zeros(1,length(F));
for counter1 = 1:length(Sequence)
if Sequence ( 1, counter1) == 1
s_of_t = #(t) A*cos(w*t)*exp(-1i*2*pi*t*F);
else
s_of_t = #(t) -A*cos(w*t)*exp(-1i*2*pi*t*F);
end
S_of_f = integral(s_of_t,((counter1-1)*Tb),(counter1*Tb),'ArrayValued', true);
for counter2 = 1:length(S_of_f)
I( 1, counter2) = I(1,counter2)+S_of_f(1,counter2);
end
clear S_of_f s_of_t;
end
figure(1)
plot(F,abs(I));
What I want to do is use the trapz function instead of the integral function like this:
for n = 1 : length(F)
S_of_f(n) = trapz(F,s_of_t);
end
instead of:
S_of_f = integral(s_of_t,((counter1-1)*Tb),(counter1*Tb),'ArrayValued', true);
I am having trouble implementing my code using this function so if you have any advice I'd appreciate it.
Errors include:
Undefined function 'max' for input arguments of type 'function_handle'.
Error in trapz (line 43)
perm = [dim:max(ndims(y),dim) 1:dim-1];
I'm not sure which function handles I'm missing.
(Yes I'm taking the Fourier Transform however my attempts to utilize the FFT function took up way too much memory).
trapz expects a vector of function evaluations, not a function handle, which is what integral expects.
if Sequence ( 1, counter1) == 1
s_of_t = #(t,F) A*cos(w*t).*exp(-1i*2*pi*t*F);
else
s_of_t = #(t,F) -A*cos(w*t).*exp(-1i*2*pi*t*F);
end
for i=1:length(F)
r=linspace(((counter1-1)*Tb),(counter1*Tb),100);
S_of_f(i) = trapz(r,s_of_t(r,F(i)));
end
...
I arbitrarily chose 100 evaluation points for the integral using trapz; you will want to modify this to an appropriate value depending on how you are using this code.
So I'm trying to write a function for a triple integral which depends ultimately on variable q which is a final limit of integration, and also a variable b which helps parameterize the function. However, this code isn't working and I'm not entirely sure what to do. I think it probably involves doing something to pass down the value of b to the nested functions, but I'm pretty new at matlab, any help is appreciated.
function [r] = test1(q,u)
b = u;
r = quad(#(k)Inner(k),-0.5.*(1-b)-b-1,q);
function [w] = Inner(k)
w = zeros(1);
for i = 1 : length(k);
w(i) = quad(#(n)InnerIntegral(n,b).*unifpdf(k(i)-n,-1,1),0,k(i)-1,k(i)+1);
end;
function [y] = InnerIntegral(n)
y = zeros(1);
for i = 1 : length(n);
y(i) = quad(#(m)unifpdf(n(i)-m, -b, b).*unifpdf(m,-0.5.*b,0.5.*b), n(i)-b,n(i)+b);
end;
end
end
end
Look at the little orange tick marks on the right side of the editor. In my copy, hovering over one says "Outer loop index 'i' is set inside a child function."
I don't know what the inputs or expected outputs of this function should be, but you should try to avoid confusing MATLAB. It has weird scoping rules. Use a different variable in the second nested function, perhaps j instead of i.