I'm trying to find an as efficient as possible way to store and call my matlab shape-functions. I have an interval x=linspace(0,20) and a position-vector
count = 10;
for i=1:count
pos(i)=rand()*length(x);
end
And now, I want to put on every position pos(j) shape functions like Gauss-kernels with compact support or hat-functions or something similar (it should be possible to change the prototype function easily). The support of the function is controlled by a so-called smoothing length h.
So I constructed a function in a .m-file like (e.g. a cubic spline)
function y = W_shape(x,pos,h)
l=length(x);
y=zeros(1,l);
if (h>0)
for i=1:l
if (-h <= x(i)-pos && x(i)-pos < -h/2)
y(i) = (x(i)-pos+h)^2;
elseif (-h/2 <= x(i)-pos && x(i)-pos <= h/2)
y(i) = -(x(i)-pos)^2 + h^2/2;
elseif (h/2 < x(i)-pos && x(i)-pos <=h)
y(i) = (x(i)-pos-h)^2;
end
end
else
error('h must be positive')
end
And then construct my functions on the interval x like
w = zeros(count,length(x));
for j=1:count
w(j,:)=W_shape(x,pos(j),h);
end
So far so good, but when I make x=linspace(0,20,10000) and count=1000, it takes my computer (Intel Core-i7) several minutes to calculate the whole stuff.
Since it should be some kind of PDE-Solver, this procedure has to be done in every time-step (under particular circumstances).
I think my problem is, that I use x as an argument for my function-call and store every function instead of store just one and shift it, but my matlab-knowledge is not that good, so any advices? Fyi: I need the integral of the areas, where two or more function-supports intersect...and when I'm done with this in 1D, I wanna do it for 2D-functions, so it has to be efficient anyways
One initial vectorization would be to remove the for loop in the W_shape function:
for i=1:l
if (-h <= x(i)-pos && x(i)-pos < -h/2)
y(i) = (x(i)-pos+h)^2;
elseif (-h/2 <= x(i)-pos && x(i)-pos <= h/2)
y(i) = -(x(i)-pos)^2 + h^2/2;
elseif (h/2 < x(i)-pos && x(i)-pos <=h)
y(i) = (x(i)-pos-h)^2;
end
end
Could become
xmpos=x-pos; % compute once and store instead of computing numerous times
inds1=(-h <= xmpos) & (xmpos < -h/2);
y(inds1) = (xmpos(inds1)+h).^2;
inds2=(-h/2 < xmpos) & (xmpos <= h/2);
y(inds2) = -(xmpos(inds2).^2 + h^2/2;
inds3=(h/2 < xmpos) & (xmpos <=h);
y(inds3) = (xmpos(inds3)-h).^2;
There is probably better optimisations than this.
EDIT:
I forgot to mention, you should use the profiler to find out what is actually slow!
profile on
run_code
profile viewer
Related
Solve the following nonlinear system of equations in the interval 0 ≤ 𝑥, 𝑦 ≤ 5 by using the
Box Evolutionary optimization algorithm.
Take, the initial point 𝑋=(x,y)T=(1,1)T and size of reduction parameter delta=(2,2)T
x^2+y=11
x+y^2=7
after running my code it is getting into infinite loop,can anyone help me out?
clc
clear
syms x y
e=1;
a=2;
f(x,y)=(x^2+y-11)^2;
g(x,y)=(x+y^2-7)^2;
k=1;
while(k~=0)
d1=2;
d2=2;
D=(d1^2+d2^2)^(0.5);
x0=1;
y0=1;
xb1=x0;
xb2=y0;
x1=xb1+d1/2;
y1=xb2+d2/2;
x2=xb1+d1/2;
y2=xb2-d2/2;
x3=xb1-d1/2;
y3=xb2+d2/2;
x4=xb1-d1/2;
y4=xb2-d2/2;
f1=f(x1,y1)+g(x1,y1);
f2=f(x2,y2)+g(x2,y2);
f3=f(x3,y3)+g(x3,y3);
f4=f(x4,y4)+g(x4,y4);
if f1<f2 && f1<f3 && f1<f4
xb1=x1;
xb2=y1;
elseif f2<f1 && f2<f3 && f2<f4
xb1=x2;
xb2=y2;
elseif f3<f1 && f3<f2 && f3<f4
xb1=x3;
xb2=y3;
elseif f4<f1 && f4<f2 && f4<f3
xb1=x4;
xb2=y4;
end
if xb1==x0 && xb2==y0
d1=d1/a;
d2=d2/a;
if D<e
disp("x value is")
disp(xb1)
k=0;
break
end
else
x0=xb1;
y0=xb2;
end
end
i am using k as condition for while loop
I am trying to run the following MATLAB code but a problem occurs. The two lines below the 'while statement':
theta_test = theta - alpha_step*abs(grad_th); % linear descent
[log_marglik_test,grad_th_test] = log_marg(theta_test,grad_th,x,y,n);
keep iterating, but I want the whole piece of code to keep cycling until (testy > 0.5 && alpha_step > 0.1).
It appears the program is 'stuck' cycling between the second and third line and never actually reaches the 'if statement'. If anyone can help it will be much appreciated!
while (testy > 0.5 && alpha_step > 0.1)
theta_test = theta - alpha_step*abs(grad_th); % linear descent
[log_marglik_test,grad_th_test] = log_marg(theta_test,grad_th,x,y,n);
% strong wolfe conditions
if (log_marglik_test <= log_marglik - c1*alpha_step*(grad_th'*grad_th)) && (abs(grad_th_test'*grad_th) <= c2*abs(grad_th'*grad_th))
theta = theta_test; testy = 0;
else
alpha_step = alpha_step * tau;
end
end
I implemented the following user defined function in MATLAB:
function Q = Calc_Q(Head, freq)
b6 = [3.7572E-07 -1.5707E-05 6.0490E-03 5.0018E-02 2.1180E-01];
b5 = [-9.0927E-06 8.9033E-04 -3.2415E-02 5.4525E-01 -8.1649E+00] / 10e2;
b4 = [7.5172E-06 -5.6565E-04 1.0024E-02 3.5888E-01 3.8894E-02] / 10e5;
b3 = [-4.8767E-06 4.8787E-04 -1.3311E-02 -1.2189E-01 -5.3522E+00] / 10e8;
b2 = [5.9227E-06 -8.1716E-04 3.5392E-02 -4.5413E-01 1.9547E+00] / 10e11;
b1 = [-2.0004E-06 2.9027E-04 -1.3754E-02 2.3490E-01 -1.2363E+00] / 10e14;
a = [polyval(b1,abs(freq)), polyval(b2, abs(freq)), polyval(b3, abs(freq)), polyval(b4, abs(freq)), polyval(b5, abs(freq)), polyval(b6, abs(freq)) - Head];
Q_roots = roots(a);
%Delete roots with imaginary part
i = 1;
while i <= length(Q_roots)
if(imag(Q_roots(i)) ~= 0)
Q_roots(i) = [];
i = i - 1;
end
i = i + 1;
end
%Delete roots with real part greater then 3100
i = 1;
while i <= length(Q_roots)
if(Q_roots(i) >= 3100 || Q_roots(i) < 0)
Q_roots(i) = [];
i = i - 1;
end
i = i +1;
end
if freq < 0
Q = real(Q_roots(1)) * -1;
else
Q = real(Q_roots(1));
end
end
When I Call this function in Matlab it works fine. However if I use this exact code as a MATLAB function in simulink it stop's working. (actually it works, but the ouput is always zero.)
I do have a suspicion of what the problem might be. When running the script in de-bugging mode, I cannot view a result for Q_roots (It just doesn't display anything).
Q_roots = roots(a);
Any ideas ?
The problem is most likely due to your logic that eliminates any roots that do not have exactly zero in the imaginary part. This is a mathematical way of thinking that does not really work well numerically, at least not in general. All the roots are probably being found in both cases (there is no limitation that implies otherwise), but in Simulink and in code generation the problem is treated as a complex one, and some roots might be coming back with tiny imaginary parts. Instead of deleting roots if their imaginary parts are not exactly zero, eliminate the roots with imaginary parts that are numerically insignificant, either very small relative to the real part or very small altogether. Something like
tol = 10*eps(class(Q_roots));
keepers = abs(imag(Q_roots)) < tol*max(abs(real(Q_roots)),1) & ...
real(Q_roots) >= 0 & real(Q_roots) <= 3100;
Q_roots = Q_roots(keepers);
would take care of all the deletions in one fell swoop. I used 10*eps as a tolerance here.
But if you only need the first qualifying root, then you could just do this:
Q = nan('like',a);
tol = 10*eps(class(a));
for k = 1:numel(Q_roots)
r = real(Q_roots(k));
if abs(imag(Q_roots(k))) < tol*max(abs(r),1) && r >= 0 && r <= 3100;
Q = r;
break
end
end
if freq < 0
Q = -Q;
end
Oke I found the problem.
From a different forum:
Hi Cosmin,
I took a look at the implementation of roots for the Embedded MATLAB
Function block (\toolbox\eml\lib\matlab\polyfun\roots.m).
It's stated there:
% Limitations: % Output is always variable size. % Output is
always complex. % Roots may not be in the same order as MATLAB. %
Roots of poorly conditioned polynomials may not match MATLAB. The last
sentence is what makes you the headache (and yes, your polynomial is
badly conditioned!). If you take a look at the plot you will see, that
the curve hardly touches the x-axis.
I have a suggestion though: the value -z/b is a (very) good
approximation of the root you are looking for ...?
Titus
http://www.mathworks.com/matlabcentral/answers/25624-roots-in-simulink
Apparently the root function in simulink does not always found all the roots of a given polynominal.
This is unfortunate and not easily solvable. I did however found a solution.
For all the different polynomials I have to solve, I know the interval of the root I am interested in ( [-3000, 3000]).
I just basically takes steps of 50 from -3000 to 3000, until the function drops below 0. I then know the approximate solution of the root. I use this approximation as seed for the Newton-Raphson method.
Straight implementation of the Newton raphson method with a given seed for all the polynomials I have to solve did not work because sometimes it iterated to a different root (one which i was not interested in.)
Here's the code:
function Q = Calc_Q(Head, freq)
b6 = [3.7572E-07 -1.5707E-05 6.0490E-03 5.0018E-02 2.1180E-01];
b5 = [-9.0927E-06 8.9033E-04 -3.2415E-02 5.4525E-01 -8.1649E+00] / 10e2;
b4 = [7.5172E-06 -5.6565E-04 1.0024E-02 3.5888E-01 3.8894E-02] / 10e5;
b3 = [-4.8767E-06 4.8787E-04 -1.3311E-02 -1.2189E-01 -5.3522E+00] / 10e8;
b2 = [5.9227E-06 -8.1716E-04 3.5392E-02 -4.5413E-01 1.9547E+00] / 10e11;
b1 = [-2.0004E-06 2.9027E-04 -1.3754E-02 2.3490E-01 -1.2363E+00] / 10e14;
%coeff for the polynominal
a = [polyval(b1,abs(freq)), polyval(b2, abs(freq)), polyval(b3, abs(freq)), polyval(b4, abs(freq)), polyval(b5, abs(freq)), polyval(b6, abs(freq)) - Head];
%coeff for the derrivative of polynominal
da = [5*a(1) 4*a(2) 3*a(3) 2*a(4) a(5)];
Q = -3000;
%Search for point where function goes below 0
while (polyval(a, Q) > 0)
Q = Q + 25;
end
error_max = 0.01
iter_counter = 1;
while abs(polyval(a,Q)) >= error_max && iter_counter <= 1000
Q = Q - polyval(a, Q)/polyval(da, Q);
iter_counter = iter_counter + 1;
error = abs(polyval(a,Q));
end
if(freq < 0)
Q = Q * - 1;
end
end
I have a small piecewise function that profiling reveals is taking 60% of the runtime of the program. It is called very often because it goes within some integrals that I perform quite a lot in my code.
According to profiling, it is called 213560 times, taking 47.786 s in total, corresponding to ~220 microseconds per call.
I want to pass it an array, and it should return an array, operating element wise.
I know that using loops in Matlab is very slow and should be avoided, but I'm not sure how to vectorise this sort of function.
function bottleradius = aux_bottle_radius(z_array)
%AUXBOTTLERADIUS Radius of aux bottle
% This returns the radius of the aux bottle as a function of z. It works for all
% heights of aux bottle, just remember to integrate over the right height
% range
bottleradius = zeros(size(z_array));
for i = 1 : max(size(z_array))
if z_array(i)<-30e-3
%door cavity
bottleradius(i) = 34e-3;
elseif z_array(i)>=-30e-3 && z_array(i)<-20e-3
%radiussing door cavity
bottleradius(i) = 34e-3 + 10e-3 - sqrt((10e-3).^2 - (z_array(i)+30e-3).^2);
elseif z_array(i)>=-20e-3 && z_array(i)<-10e-3
%aluminium plate
bottleradius(i) = 46e-3;
elseif z_array(i)>=-10e-3 && z_array(i)<0e-3
%radiussing aluminium plate to main bottle
bottleradius(i) = 46e-3 + 10e-3 - sqrt((10e-3).^2 - (z_array(i)+10e-3).^2);
elseif z_array(i)>=0e-3
%top of Al plate, bottom of main bottle
bottleradius(i) = 185e-3;
else
bottleradius(i) = 0;
end
end
end
You can do that completely vectorized with logical operators. You can essentially replace that code with:
function bottleradius = aux_bottle_radius(z_array)
%// Declare initial output array of all zeroes
bottleradius = zeros(size(z_array));
%// Condition #1 - Check for all values < -30e-3 and set accordingly
bottleradius(z_array < -30e-3) = 34e-3;
%// Condition #2 - Check for all values >= -30e-3 and < -20e-3 and set accordingly
ind = z_array >= -30e-3 & z_array < -20e-3;
bottleradius(ind) = 34e-3 + 10e-3 - sqrt((10e-3).^2 - (z_array(ind)+30e-3).^2);
%// Condition #3 - Check for all values >= -20e-3 and < -10e-3 and set accordingly
bottleradius(z_array >=-20e-3 & z_array < -10e-3) = 46e-3;
%// Condition #4 - Check for all values >= -10e-3 and < 0 and set accordingly
ind = z_array >=-10e-3 & z_array < 0;
bottleradius(ind) = 46e-3 + 10e-3 - sqrt((10e-3).^2 - (z_array(ind)+10e-3).^2);
%// Condition #5 - Check for all values >= 0 and set accordingly
bottleradius(z_array >= 0) = 185e-3;
end
Minor comments
0e-3 doesn't make any sense precision wise. This is essentially the same as 0 and I've changed that in your code.
Note that for conditions #2 and #4, I precompute a logical array that indicates where we would need to access the corresponding values in z_array to make things easier and set those same locations in bottleradius to be the desired computed outputs. I don't do this for the other conditions because you're just setting them to a single constant.
Thankfully, you use element-wise operators for conditions #2 and #4 so there wasn't a need to change the expressions for those conditions.
I am Beginner in Matlab, i would like to plot system concentration vs time plot at a certain time interval following is the code that i have written
%Input function of 9 samples with activity and time calibrated with Well
%counter value approx : 1.856 from all 9 input values of 3 patients
function c_o = Sample_function(td,t_max,A,B)
t =(0 : 100 :5000); % time of the sample post injection in mins
c =(0 : 2275.3 :113765);
A_max= max(c); %Max value of Concentration (Peak of the curve)
if (t >=0 && t <= td)
c_o(t)=0;
else if(td <=t && t<=t_max)
c_o(t)= A_max*(t-td);
else if(t >= t_max)
c_o(t)=(A(1)*exp(-B(1)*(t-t_max)))+(A(2)*exp(-B(2)*(t- t_max)))+...
(A(3)*exp(-B(3)*(t-t_max)));
end
fprintf('plotting Data ...\n');
hold on;
figure;
plot(c_o);
xlabel('Activity of the sample Ba/ml ');
ylabel('time of the sample in minutes');
title (' Input function: Activity sample VS time ');
pause;
end
I am getting following error
Operands to the || and && operators must be convertible to logical scalar values.
Error in Sample_function (line 18)
if (t >=0 && t <= td)
Kindly .Let me know if my logic is incorrect
Your t is not a single value to compare with 0 so it cannot evaluate to true or false.
You want to do this with logical indexing
c_o = zeros(size(t));
c_o(t>=0 & t<=td) = 0; % this line is actually redundant and unnecessary since we initialized the vector to zeros
c_o(t>td & t<=t_max) = A_max*(t(t>td & t<=t_max)-td);
c_o(t>t_max) = (A(1)*exp(-B(1)*(t(t>t_max)-t_max)))+(A(2)*exp(-B(2)*(t(t>t_max)- t_max)))...
+ (A(3)*exp(-B(3)*(t(t>t_max)-t_max)));
You could also make this a little prettier (and easier to read) by assigning the logical indexes to variables:
reg1 = (t>=0 & t<=td);
reg2 = (t>td & t<=t_max);
reg3 = (t>t_max);
Then, for instance, the second assignment becomes the much more readable:
c_o(reg2) = A_max*(t(reg2)-td);
t is written as a array of numbers. So, it can't be compared with a scalar value ex. 0.
Try it in a for loop
for i=1:length(t)
if (t(i) >=0 && t(i) <= td)
c_o(t(i))=0;
else if(td <=t(i) && t(i)<=t_max)
c_o(t(i)))= A_max*(t(i)-td);
else if(t(i) >= t_max)
c_o(t)=(A(1)*exp(-B(1)*(t(i)-t_max)))+(A(2)*exp(-B(2)*(t(i)- t_max)))...
+ (A(3)*exp(-B(3)*(t(i)-t_max)));
end
end