Evaluate a vector in a piecewise function - matlab

I want to evaluate the vector xdata in a piecewise function like this:
dat=load('k2.txt');
xdata = dat(:,1);
ydata = dat(:,2);
n=length(xdata);
p0=[0.0821 6.6 0.4];
y(p0,xdata)
function y_hat = y(p,t)
P=4.885;
T0 = 134.27426;
omega=2*pi/P;
gamma1=0.3539 ;gamma2=0.2851;
c1=0;c2=gamma1+2*gamma2;c3=0;c4=-gamma2;
c0=1-c1-c2-c3-c4;
z= p(2).*((sin(omega.*(t-T0))).^2+((p(3)/p(2)).*cos(omega.*(t-T0))).^2).^(1/2);
lambda1= 0;
lambda3=p(1).^2;
if ((1-p(1)<z) & (z<1+p(1)))
k1 = acos((1-p(1).^2 + z.^2)./(2*z));
k0 = acos(((p(1)).^2+z.^2-1)./(2.*z.*p(1)));
y_hat = 1-1./pi*(p(1).^2.*k0+k1-sqrt((4*z.^2-(1+z.^2-p(1).^2).^2)/4));
end
if (1+p(1)<=z)
y_hat=1-lambda1;
end
if (z<=1-p(1))
y_hat=1-lambda3;
end
end
The problem is that the code doesn't enter none of the if loops and returns nothing. Maybe the reason is that the function tries to fulfill the conditions for all the vector at once? How should I proceed so that y(p0,xdata) returns something?
By the way, I need this because I have to fit a model to data like this:
[theta] = lsqcurvefit(#y, p0, xdata, ydata);

Your code doesn't work, because when you write something like this:
if [1 3 -1] > 0
%code
end
Then "%code" won't be evaluated because it's checking, if the condition holds for every value in the vector.
Let's say you want to define the Heaviside function and evaluate a vector of it. Then, what you do is using a for loop:
x_vals = [-1 1 5];
heav(x_vals)
function y = heav(x)
y = zeros(size(x));
for i = 1:length(x)
if x(i) >= 0
y(i) = 1;
else
y(i) = 0;
end
end
end

Related

Attempting Tridiagonal Gauss-Jordan Elimination Matlab

As you probably guessed from the title, I'm attempting to do tridiagonal GaussJordan elimination. I'm trying to do it without the default solver. My answers aren't coming out correct and I need some assistance as to where the error is in my code.
I'm getting different values for A/b and x, using the code I have.
n = 4;
#Range for diagonals
ranged = [15 20];
rangesd = [1 5];
#Vectors for tridiagonal matrix
supd = randi(rangesd,[1,n-1]);
d = randi(ranged,[1,n]);
subd = randi(rangesd,[1,n-1]);
#Creates system Ax+b
A = diag(supd,1) + diag(d,0) + diag(subd,-1)
b = randi(10,[1,n])
#Uses default solver
y = A/b
function x = naive_gauss(A,b);
#Forward elimination
for k=1:n-1
for i=k+1:n
xmult = A(i,k)/A(k,k);
for j=k+1:n
A(i,j) = A(i,j)-xmult*A(k,j);
end
b(i) = b(i)-xmult*b(k);
end
end
#Backwards elimination
x(n) = b(n)/A(n,n);
for i=n-1:-1:1
sum = b(i);
for j=i+1:n
sum = sum-A(i,j)*x(j);
end
x(i) = sum/A(i,i)
end
end
x
Your algorithm is correct. The value of y that you compare against is wrong.
you have y=A/b, but the correct syntax to get the solution of the system should be y=A\b.

How to write function correctly

I'm making a Matlab program for cell growth,
I have a problem with some function in main.m and I found some functions that I thought are written wrong way:
function y = f(c)
y = 0.5*(1-tanh(4*c-2));
function y = h(c)
y = 0.5*f(c);
function y = g(c)
global beta
y = beta*exp(beta*c);
%y=1+0.2*c;
main.m
%%main program
clear; clc;
global alpha beta gamma
%set parameter values
alpha = 0.9; beta = 0.5; gamma = 10;
dx = 1; X = 210; dt = 0.04; T = 16;
c0 = 1;
%set up arrays
x = [dx:dx:X]; Nx = round(X/dx); Nt = round(T/dt);
p = zeros(1,Nx); nextp = zeros(1,Nx);
q = zeros(1,Nx); nextq = zeros(1,Nx);
n = zeros(1,Nx); nextn = zeros(1,Nx);
u = zeros(1,Nx); v = zeros(1,Nx); r = zeros(1,Nx); c = zeros(1,Nx);
P = zeros(Nt,Nx); Q = zeros(Nt,Nx); N = zeros(Nt,Nx);
%set initial values
p = exp(-0.1.*x);
function y = f(c)
y = 0.5*(1-tanh(4*c-2));
function y = h(c)
y = 0.5*f(c);
function y = g(c)
global beta
y = beta*exp(beta*c);
%y=1+0.2*c;
%start FDM time-stepping
for k=1:Nt
r = p + q;
c = (c0.*gamma./(gamma+p)).*(1-alpha.*(p+q+n));
for i=2:Nx-1
u(i)=((p(i+1)-p(i-1))*r(i)*(r(i+1)-r(i-1))+ 4*p(i)*r(i)*...
(r(i+1)-2*r(i)+r(i-1))-p(i)*(r(i+1)-r(i-1))^2)/(2*...
(dx*r(i))^2);
v(i)=((q(i+1)-q(i-1))*r(i)*(r(i+1)-r(i-1))+ 4*q(i)*r(i)*...
(r(i+1)-2*r(i)+r(i-1))-q(i)*(r(i+1)-r(i-1))^2)/(2*...
(dx*r(i))^2);
end
nextp=p+dt.*(u+g(c).*p.*(1-(p+q+n))-f(c).*p);
nextq=q+dt.*(v+f(c).*p-h(c).*q);
nextn=n+dt.*(h(c).*q);
p=nextp;
q=nextq;
n=nextn;
P(k,:)=p; Q(k,:)=q; N(k,:)=n;
end
figure(1)
for n=1:500:Nt
plot(P(n,:),'LineWidth',1.2); hold on;
end
axis([0 270 0 0.6]);
figure(2)
for n=1:500:Nt
plot(Q(n,:),'LineWidth',1.2); hold on;
end
axis([0 270 0 0.6]);
figure(3)
for n=1:500:Nt
plot(N(n,:),'LineWidth',1.2); hold on;
end
axis([0 270 0 1]);
animation.m
%create image for cells
rand('state', sum(100*clock));
prefix='t';
Nm=0;
figure(1)
for n=1:250:Nt
Nm=Nm+1;
for i=1:Nx
tP=round(P(n,i)),tQ=round(Q(n,i)),tN=round(N(n,i));
for m=1:tP
theta=2*pi*rand();
plot(i*sin(theta),i*cos(theta),'b.'); hold on;
end
for m=1:tQ
theta=2*pi*rand();
plot(i*sin(theta),i*cos(theta),'r.'); hold on;
end
for m=1:tN
theta=2*pi*rand();
plot(i*sin(theta),i*cos(theta),'k.'); hold on;
end
axis square
axis([-300 300 -300 300])
end
print('-djpeg','-r100',sprintf('%s_%s',prefix,num2str(Nm)));
end
clear MM
for i=1:Nm
[XX,map]=imread(sprintf('%s_%s',prefix,num2str(i)),'jpeg');
imagesc(XX);
MM(i)=getframe;
pause(0.1);
end
Please help me solve this problem..
You're main.m is a script, not a function (it doesn't start with the word function), see function and Scripts vs. Functions).
In short: function declaration is not allowed in command-line or scripts only in function files.
Do as oro777 advises,
create a seperate file for each function.
Another way is to turn your main.m into a function too, by starting it with function main. Then decleration of additional functions is allowed in the same file, but these are all local functions which means they will only be available from within that file. You can not call them from outside the file they were declared in.
You should write the output error so we can see which function is badly written. At first view, I would say you should use longer function names because with only one letter, it may easily shadow with a variable name and I would advise not to use global variables.
I see that your functions are defined in the same file as the main program, I would advise to create one function per file. For example a f_function m-file with the following code.
function y = f_function(c)
y = 0.5*(1-tanh(4*c-2));
Do the same for your two other functions and place your newly created m-files in the same folder as your main program.

Jacobi solver going into an infinite loop

I can't seem to find a fix to my infinite loop. I have coded a Jacobi solver to solve a system of linear equations.
Here is my code:
function [x, i] = Jacobi(A, b, x0, TOL)
[m n] = size(A);
i = 0;
x = [0;0;0];
while (true)
i =1;
for r=1:m
sum = 0;
for c=1:n
if r~=c
sum = sum + A(r,c)*x(c);
else
x(r) = (-sum + b(r))/A(r,c);
end
x(r) = (-sum + b(r))/A(r,c);
xxx end xxx
end
if abs(norm(x) - norm(x0)) < TOL;
break
end
x0 = x;
i = i + 1;
end
When I terminate the code it ends at the line with xxx
The reason why your code isn't working is due to the logic of your if statements inside your for loops. Specifically, you need to accumulate all values for a particular row that don't belong to the diagonal of that row first. Once that's done, you then perform the division. You also need to make sure that you're dividing by the diagonal coefficient of A for that row you're concentrating on, which corresponds to the component of x you're trying to solve for. You also need to remove the i=1 statement at the beginning of your loop. You're resetting i each time.
In other words:
function [x, i] = Jacobi(A, b, x0, TOL)
[m n] = size(A);
i = 0;
x = [0;0;0];
while (true)
for r=1:m
sum = 0;
for c=1:n
if r==c %// NEW
continue;
end
sum = sum + A(r,c)*x(c); %// NEW
end
x(r) = (-sum + b(r))/A(r,r); %// CHANGE
end
if abs(norm(x) - norm(x0)) < TOL;
break
end
x0 = x;
i = i + 1;
end
Example use:
A = [6 1 1; 1 5 3; 0 2 4]
b = [1 2 3].';
[x,i] = Jacobi(A, b, [0;0;0], 1e-10)
x =
0.048780487792648
-0.085365853612062
0.792682926806031
i =
20
This means it took 20 iterations to achieve a solution with tolerance 1e-10. Compare this with MATLAB's built-in inverse:
x2 = A \ b
x2 =
0.048780487804878
-0.085365853658537
0.792682926829268
As you can see, I specified a tolerance of 1e-10, which means we are guaranteed to have 10 decimal places of accuracy. We can certainly see 10 decimal places of accuracy between what Jacobi gives us with what MATLAB gives us built-in.

How to program Gauss-Seidel Method from Jacobian since when it hits the j-loop it throws an error when doesn't recognize the element location 0?

So here is the code that I wrote for the Gauss-Seidel Method that is actually derived from the Jacobi code. The problem is that once it hits the j-loop, that is the error. Since MATLAB does not recognize element location 0 in an array, this is technically an error. How can I compensate for this?
This represents the Ax = b matrix function.
function result = GaussSeidel(A,b,x)
kmax = 100; sigma = 0.5e-4;
n = size(A);
for k=1:kmax
y = x;
for i=1:n
sum = b(i);
diag = A(i,i);
for j=1:(i-1)
sum = sum - (A(i,j)*x(j));
end
for j=(i+1):n
sum = sum - (A(i,j)*x(j));
end
x(i) = sum/diag;
end
result = x(k);
if norm(x-y) < sigma
result = x(k);
return
end
return
end

Matlab Differential Equations Euler’s method

I need help plotting a differential equation ... it keeps coming out all funky and the graph is not what it's supposed to look like.
function [dydt] = diff(y,t)
dydt = (-3*y)+(t*(exp(-3*t)));
end
tI = 0;
yI = -0.1;
tEnd = 5;
dt = 0.5;
t = tI:dt:tEnd;
y = zeros(size(t));
y(1) = yI;
for k = 2:numel(y)
yPrime = diff(t(k-1),y(k-1));
y(k) = y(k-1) + dt*yPrime;
end
plot(t,y)
grid on
title('Engr')
xlabel('Time')
ylabel('y(t)')
legend(['dt = ' num2str(dt)])
That's my code, but the graph is not anything like what it's supposed to look like. Am I missing something like an index for the for statement?
Edit
I am getting an error:
Error using diff
Difference order N must be a positive integer scalar.
Error in diff3 (line 12)
yPrime = diff(t(k-1),y(k-1));
After fixing the errors pointed out by Danil Asotsky and horchler in the comments:
avoiding name conflict with built-in function 'diff'
changing the order of arguments to t,y.
decreasing the time-step dt to 0.1
converting ODE right-hand side to an anonymous function
(and removing unnecessary parentheses in the function definition), your code could look like this:
F = #(t,y) -3*y+t*exp(-3*t);
tI = 0;
yI = -0.1;
tEnd = 5;
dt = 0.1;
t = tI:dt:tEnd;
y = zeros(size(t));
y(1) = yI;
for k = 2:numel(y)
yPrime = F(t(k-1),y(k-1));
y(k) = y(k-1) + dt*yPrime;
end
plot(t,y)
grid on
title('Engr')
xlabel('Time')
ylabel('y(t)')
legend(['dt = ' num2str(dt)])
which performs as expected: