How to include piecewise defined functions in bvp4c solver in Matlab - matlab

I am having trouble using the bvp4c with piecewise defined functions.
I tested the code and it works fine when the piecewise defined functions are constant.
The problem is that I get wrong results in the graph (that I know for sure) in the area where the piecewise defined functions are not constant.
Any ideas or suggestions on how to handle this problem?
Thanks
function bvp4
xlow=0;
xhigh=0.30;
solinit=bvpinit(linspace(xlow,xhigh,1000),[0 0]);
sol = bvp4c(#bvp4ode,#bvp4bc,solinit);
xint=[xlow:0.0001:xhigh];
Sxint=deval(sol,xint);
Sxint1=abs(sqrt(Sxint));
xint=[xlow:0.0001:xhigh];
plot(xint,Sxint1(1,:),'r')
function dydx = bvp4ode(x,y)
So=0.00125;
s=1.5;
dydx = [y(2);
((G(x)+125*f(x)*y(1)*(1+1/s^2)^0.5-1000*9.81*So*H(x))/(1000*0.5*l(x)*(f(x)/8)^0.5)-y(2)*2*(-2/3*x+0.071+2/3*0.08)*(-2/3)*b(x))/H(x)/H(x)];
function res = bvp4bc(ya,yb)
res = [ya(1); yb(1)];
function fval = f(x)
if (x >= 0) && (x <= 0.08)
fval = 0.0187;
elseif (x > 0.08) && (x <= 0.17)
fval = 0.0298;
elseif (x > 0.17) && (x <= 0.3)
fval= 0.0408;
end
function Gval = G(xint)
if (xint >= 0) && (xint <= 0.08)
Gval = 0.1306;
elseif (xint > 0.08) && (xint <= 0.17)
Gval = 0.1306;
elseif (xint > 0.17) && (xint <= 0.3)
Gval = -0.0337;
end
function Hval = H(xint)
if (xint >= 0) && (xint < 0.08)
Hval = 0.071;
elseif (xint >= 0.08) && (xint <= 0.17)
Hval = -2/3*xint+(0.071+2/3*0.08);
elseif (xint >0.17) && (xint <= 0.3)
Hval = 0.011;
end
function bval = b(xint)
if (xint >= 0) && (xint < 0.08)
bval = 0;
elseif (xint >= 0.08) && (xint <= 0.17)
bval = 1;
elseif (xint > 0.17) && (xint <= 0.3)
bval= 0;
end
function lval = l(xint)
if (xint >= 0) && (xint <= 0.08)
lval = 0.067;
elseif (xint > 0.08) && (xint <= 0.17)
lval = 0.134;
elseif (xint > 0.17) && (xint <= 0.3)
lval= 1.165;
end

Thou shalt not surprise your fragile solver with sudden jumps.
Any order p solver expects an ODE function that is at least p times continuously differentiable to sensibly adapt the mesh of gridpoints resp. the local step size. Any deviation leads to excessive and possibly oscillating adaptation near the singular points, resulting in long computation times or underflow in the step size.
I see two possibilities to work around this problem, use events (if supported for BVP) to switch models/ODE functions or use the provided multipoint mechanism to split the integration interval into sections where your parameter functions are constant. Then you can also use simple arrays for the parameters instead of functions with many branchings.

Related

How to define a peicewise function in a function file - Matlab

I made a funnction file and defined a peicewise function inside it using conditionals and a for loop. I tried calling the function in a seperate m.file but the variables 't' and 'v' aren't showing in the workspace, rather it is just outputting a vector with the t values called 'ans.
I tried putting the exact code (without the function definition) into a regular m file and it worked just fine showing both variables t and v
#function file
function [t, v] = VPieceWise(t_start, t_end);
t = t_start:0.01:t_end;
for i = 1:length(t);
if (t(i) >= 0) && (t(i) <= 10);
v(i) = 11.*(t(i).^2) - (5.*t(i));
elseif (t(i) >= 10) && (t(i) <= 20);
v(i) = 1100 - 5.*t(i);
elseif (t(i) >= 20) && (t(i) <= 30);
v(i) = 50.*t(i) + 2*((t(i)-20).^2.5);
elseif (t(i) >= 30) && (t(i) <= 100);
v(i) = 1520.*exp(-0.1.*(t(i)-30));
elseif (t(i) >= -100) && (t(i) <= 0);
v(i) = 0;
end
end
end
#m file
clear all; clc; close all
t_start = input('enter the start time');
t_end = input('enter the end time');
VPieceWise(t_start,t_end)
plot(t,v)
Since your function has two outputs, you should also assign them when calling the function. If you do not do that, only the first output will be put in the ans variable.
So call your function as follows:
clear all; clc; close all
t_start = input('enter the start time');
t_end = input('enter the end time');
[t,v] = VPieceWise(t_start,t_end);
plot(t,v)

An array for multiple LHS assignment cannot contain LEX_TS_STRING error

New to programing in matlab. I am currently trying to make a MATLAB program that will find the critical values of a multi-variable function and tell me whether each are a minimum, maximum, or saddle point. Unfortunately I always get the error : An array for multiple LHS assignment cannot contain LEX_TS_STRING
Any help will be very appreciated.
here's the code:
function [c,d] = critcalpoints(f)
syms x y
f(x,y)=x^3-3*x^2+5*x*y-7*y^2;
gradf = jacobian(f(x,y));
hessmatf = jacobian(gradf,[x,y]);
[xcr,ycr]=solve(gradf(1),gradf(2));
H1=subs(hessmatf,[x,y],[xcr(1),ycr(1)]);
H2=subs(hessmatf,[x,y],[xcr(2),ycr(2)]);
eig(H1);
eig(H2);
c = double(eig(H1));
d = double(eig(H2));
if (c(1) > 0 && d(1) > 0) || (c(2) > 0 && d(2) > 0)
print([xcr,ycr],' is a minimum')
elseif (c(1) < 0 && d(1) < 0) || (c(2) < 0 && d(2) < 0)
print( [xcr, ycr], ' is a maximum')
elseif (c(1) < 0 && d(1) > 0) || (c(1) > 0 && d(1) < 0)
print( [xcr, ycr], ' is a saddle point')
elseif (c(2) < 0 && d(2) > 0) || (c(2) > 0 && d(2) < 0)
print( [xcr, ycr], ' is a saddle point')
elseif (c(1)==0 || d(1)==0)
print( [xcr, ycr], ' is degenerate')
elseif (c(2)==0 || d(2)==0)
print( [xcr, ycr], ' is degenerate')
end
Cannot reproduce your error. The code can work but you need to change print to something else as print doesn't do what you think it does. The print function prints a figure that is open to file. Change it so that you display xcr and ycr first then display the right condition to satisfy after. Use disp instead:
syms x y
f(x,y)=x^3-3*x^2+5*x*y-7*y^2;
gradf = jacobian(f(x,y));
hessmatf = jacobian(gradf,[x,y]);
[xcr,ycr]=solve(gradf(1),gradf(2));
H1=subs(hessmatf,[x,y],[xcr(1),ycr(1)]);
H2=subs(hessmatf,[x,y],[xcr(2),ycr(2)]);
eig(H1);
eig(H2);
c = double(eig(H1));
d = double(eig(H2));
disp([xcr, ycr]); % Display the solutions first
if (c(1) > 0 && d(1) > 0) || (c(2) > 0 && d(2) > 0)
disp('is a minimum')
elseif (c(1) < 0 && d(1) < 0) || (c(2) < 0 && d(2) < 0)
disp('is a maximum')
elseif (c(1) < 0 && d(1) > 0) || (c(1) > 0 && d(1) < 0)
disp('is a saddle point')
elseif (c(2) < 0 && d(2) > 0) || (c(2) > 0 && d(2) < 0)
disp('is a saddle point')
elseif (c(1)==0 || d(1)==0)
disp('is degenerate')
elseif (c(2)==0 || d(2)==0)
disp('is degenerate')
end
I get:
[ 0, 0]
[ 59/42, 295/588]
is a maximum

plot a piecewise parametric function in maple

How to plot a piecewise parametric function in maple ?
An example :
f := proc (t) if t <= .2 and 0 <= t then -t, 2*t elif t <= .4 then 8*t-1.8, 2*t elif t <= .6 then 3*t+.2, -2*t+1.6 elif t <= .8 then 2*t+.8, -t+1 elif t <= 1 then -12*t+12, -t+1 end if end proc;
I found the answer.
In case someone needs it :
> X := piecewise(`and`(t <= .2, t >= 0), -t, t <= .4, 8*t-1.8, t <= .6, 3*t+.2, t <= .8, 10*t-4, t <= 1, -20*t+20);
Y := piecewise(`and`(t <= .2, t >= 0), 2*t, t <= .4, 2*t, t <= .6, -2*t+1.6, t <= .8, 1-t, t <= 1, 1-t);
> plot([X(t), Y(t), t = 0 .. 1]);

Best Fit Line with logarithmic axes (MATLAB)

I am trying to plot a best fit line on a probability density function with logarithmic axes. The Y-axis (PDF) is 10^-12 to 10^-28, while the X-axis is 10^10 to 10^20. I've tried polyfit, with no luck. Any ideas? Attached is my code.
Thanks,
Kevin
clc;
clear all;
load Aug2005_basin_variables.mat
% Initialize
j_len = length(W_SH);
prob_dens_all = zeros(j_len,30);
ii = 1 : j_len;
count(1:30) = 0;
bin(1:30) = 0;
for i = 1 : 30
bin(i) = 10^(11 + (0.3*i));
end
% Bin the Watts
for i = 1 : j_len
if((log10(W_SH(i)) >= 11) && (log10(W_SH(i)) < 11.3))
count(1) = count(1) + 1;
end
if((log10(W_SH(i)) >= 11.3) && (log10(W_SH(i)) < 11.6))
count(2) = count(2) + 1;
end
if((log10(W_SH(i)) >= 11.6) && (log10(W_SH(i)) < 11.9))
count(3) = count(3) + 1;
end
if((log10(W_SH(i)) >= 11.9) && (log10(W_SH(i)) < 12.2))
count(4) = count(4) + 1;
end
if((log10(W_SH(i)) >= 12.2) && (log10(W_SH(i)) < 12.5))
count(5) = count(5) + 1;
end
if((log10(W_SH(i)) >= 12.5) && (log10(W_SH(i)) < 12.8))
count(6) = count(6) + 1;
end
if((log10(W_SH(i)) >= 12.8) && (log10(W_SH(i)) < 13.1))
count(7) = count(7) + 1;
end
if((log10(W_SH(i)) >= 13.1) && (log10(W_SH(i)) < 13.4))
count(8) = count(8) + 1;
end
if((log10(W_SH(i)) >= 13.4) && (log10(W_SH(i)) < 13.7))
count(9) = count(9) + 1;
end
if((log10(W_SH(i)) >= 13.7) && (log10(W_SH(i)) < 14.0))
count(10) = count(10) + 1;
end
if((log10(W_SH(i)) >= 14.0) && (log10(W_SH(i)) < 14.3))
count(11) = count(11) + 1;
end
if((log10(W_SH(i)) >= 14.3) && (log10(W_SH(i)) < 14.6))
count(12) = count(12) + 1;
end
if((log10(W_SH(i)) >= 14.6) && (log10(W_SH(i)) < 14.9))
count(13) = count(13) + 1;
end
if((log10(W_SH(i)) >= 14.9) && (log10(W_SH(i)) < 15.2))
count(14) = count(14) + 1;
end
if((log10(W_SH(i)) >= 15.2) && (log10(W_SH(i)) < 15.5))
count(15) = count(15) + 1;
end
if((log10(W_SH(i)) >= 15.5) && (log10(W_SH(i)) < 15.8))
count(16) = count(16) + 1;
end
if((log10(W_SH(i)) >= 15.8) && (log10(W_SH(i)) < 16.1))
count(17) = count(17) + 1;
end
if((log10(W_SH(i)) >= 16.1) && (log10(W_SH(i)) < 16.4))
count(18) = count(18) + 1;
end
if((log10(W_SH(i)) >= 16.4) && (log10(W_SH(i)) < 16.7))
count(19) = count(19) + 1;
end
if((log10(W_SH(i)) >= 16.7) && (log10(W_SH(i)) < 17.0))
count(20) = count(20) + 1;
end
if((log10(W_SH(i)) >= 17.3) && (log10(W_SH(i)) < 17.6))
count(21) = count(21) + 1;
end
if((log10(W_SH(i)) >= 17.6) && (log10(W_SH(i)) < 17.9))
count(22) = count(22) + 1;
end
if((log10(W_SH(i)) >= 17.9) && (log10(W_SH(i)) < 18.2))
count(23) = count(23) + 1;
end
if((log10(W_SH(i)) >= 18.2) && (log10(W_SH(i)) < 18.5))
count(24) = count(24) + 1;
end
if((log10(W_SH(i)) >= 18.5) && (log10(W_SH(i)) < 18.8))
count(25) = count(25) + 1;
end
if((log10(W_SH(i)) >= 18.8) && (log10(W_SH(i)) < 19.1))
count(26) = count(26) + 1;
end
if((log10(W_SH(i)) >= 19.1) && (log10(W_SH(i)) < 19.4))
count(27) = count(27) + 1;
end
if((log10(W_SH(i)) >= 19.4) && (log10(W_SH(i)) < 19.7))
count(28) = count(28) + 1;
end
if((log10(W_SH(i)) >= 19.7) && (log10(W_SH(i)) < 20.0))
count(29) = count(29) + 1;
end
if((log10(W_SH(i)) >= 20.0) && (log10(W_SH(i)) < 20.3))
count(30) = count(30) + 1;
end
end
for i=1:30
prob(i) = count(i)/sum(count);
prob_dens(i) = prob(i)/bin(i);
end
% Check
sum(prob_dens.*bin);
prob_dens_all(i,:) = prob_dens(:);
%end
prob_dens_mean = zeros(1,30);
for i = 1 : 30
prob_dens_mean(1,i) = mean(prob_dens_all(:,i));
%prob_dens_std(1,i) = std(prob_dens_all(:,i));
end
% Plot
best_fit = polyfit(bin,log10(prob_dens_mean),11)
h = figure;
loglog(bin,prob_dens_mean,'ro','MarkerSize',10)
hold on;
plot(best_fit,'b')
t = title('Event Power Distribution, SHem, August 2005');
set(t, 'FontWeight', 'bold', 'FontSize', 12)
set(gca, 'FontWeight', 'bold', 'FontSize', 12)
xlabel('Event Power (W)');
ylabel('Probability Density');
print -dpng SHem_Wattage_PDF_AUG2005.png
I don't have your data, but here is an example using some random normally-distributed random data
x=randn(1000,1)+5; % create some data, keep numbers positive by adding 5
[n,xb]=hist(x); % Create the histogram
n = n/sum(n); % convert counts to a pdf
p=polyfit(log(xb), log(n), 3); % Do a 3rd order fit
loglog(xb,n, '*-', xb, exp(polyval(p, log(xb))), 'r')
grid on
legend('PDF', 'Fit', 0)

How to chose random lines that hit a rectangular in MatLab

I am creating random starting and ending points. I want to plot those who cross/intersect with a rectangular which is placed at the origin. I found out that my code misses some lines, as shown in the figure. After that, I want to count were the tracks hit the rectangle. For expample the track came from top side and exited from right side etc.
My code is
function [hot, cold, h] = MuonTracks(tracks)%#eml
% NOTE: no variables larger than 1x1 are initialized
width = 1e-4;
height = 2e-4;
% constant used for Laplacian noise distribution
bL = 15 / sqrt(2);
% Loop through all tracks
X = [];
bhit= [];
hot = 0;
ii = 0;
TopBottom= 0;
LeftRight= 0;
TopRight= 0;
TopLeft= 0;
LeftBottom= 0;
RightBottom= 0;
ihit= 0;
while ii <= tracks
ii = ii + 1;
% Note that I've inlined (== copy-pasted) the original laprnd()
% function call. This was necessary to work around limitations
% in loops in Matlab, and prevent the nececessity of those HUGE
% variables.
%
% Of course, you can still easily generalize all of this:
% the new data
u = rand-0.5;
Ystart = 15;
Xstart = 80*rand-40;
Xend = Xstart - bL*sign(u)*log(1-2*abs(u));
%Xend=laprnd(tracks,1,Xstart,15);
b = (Ystart*Xend)/(Xend-Xstart);
% the test
if ((b < height && b > 0)) ||...
(Xend < width/2 && Xend > -width/2)
hot = hot+1;
% growing an array is perfectly fine when the chances of it
% happening are so slim
X = [X [Xstart; Xend]]; %#ok
bhit=b;
end
end
% This is trivial to do here, and prevents an 'else'
cold = tracks - hot;
% Now plot the chosen ones
h = figure;
hold all
%Y = bsxfun(#times, 15, ones(size(X)));
if (size(X)==0)
%Disp('No hits were found');
msgbox('No tracks were found','Result','warn');
elseif (size(X)>1)
Y = bsxfun(#times, [15; 0], ones(size(X)));
plot(X, Y, 'r');
msgbox( [num2str(hot) ' tracks were found'],'Result','help',num2str(hot));
else
Y = bsxfun(#times, [15; 0], ones(size(X)));
plot(X, Y, 'r');
msgbox( [num2str(hot) ' track was found'],'Result','help',num2str(hot));
end
%X;
%Y;
%size(X,2)
while ihit<size(X,2)
ihit=ihit+1
%X(2,ihit)
if ((X(2,ihit)==-width && (bhit<=0 && bhit<=height))&&(bhit==0 && (X(2,ihit)>=-width && X(2,ihit)>=width)))
LeftBottom=LeftBottom+1;
elseif ((bhit==height && (X(2,ihit)>=-width && X(2,ihit)>=width)) && (X(2,ihit)==width && (bhit<=0 && bhit<=height)))
TopRight=TopRight+1;
elseif ((bhit==height && (X(2,ihit)>=-width && X(2,ihit)>=width)) && (bhit==0 && (X(2,ihit)>=-width && X(2,ihit)>=width)))
TopBottom=TopBottom+1;
elseif ((X(2,ihit)==-width && (bhit<=0 && bhit<=height)) && (X(2,ihit)==width && (bhit<=0 && bhit<=height)))
LeftRight=LeftRight+1;
elseif ((X(2,ihit)==-width && (bhit<=0 && bhit<=height)) && (bhit==height && (X(2,ihit)>=-width && X(2,ihit)>=width)))
TopLeft=TopLeft+1;
elseif ((X(2,ihit)==width && (bhit<=0 && bhit<=height)) && (bhit==0 && (X(2,ihit)>=-width && X(2,ihit)>=width)))
RightBottom=RightBottom+1;
else
display('sth is wrong');
end
X(2,ihit)
end
%X(1,:);
%Y(1,:);
LeftBottom
TopRight
TopBottom
LeftRight
TopLeft
RightBottom
%display('sdfghjk');
end
Any ideas would be more than welcome!
Here you have a function that is capable of intersecting whole groups of segments and returning the intersection points. I hope it helps.