How to use integration limits correctly (Matlab) - matlab

I've made a script that calculates a given integral with the limits:
0 <= x <= 2 and 0 <= y <= 1
But now I want to change the limits to:
0 <= x <= 2 and 0 <= y <= sin((pi*x)/2)
Function:
function f = inte(x,y)
dz = 10;
f = exp(-dz*((x-1.25).^2+y.^2)).*cos(y.*(x-1.25));
end
This is my script for the earlier limits:
L = 100; M = L/2;
hx = (2)/L; hy = (1)/M;
x=[0:L]*hx;
y=[0:M]*hy;
Fx=[];
for i = 1:L+1
Fy=[];
for j = 1:M+1
f = inte(x(i),y(j));
Fy = [Fy f];
end
ycor = hy*(sum(Fy) - Fy(1)/2 - Fy(end)/2);
Fx = [Fx ycor];
end
ans = hx*(sum(Fx) - Fx(1)/2 - Fx(end)/2);
disp (ans)
I can't seem to get the right answer when I try to change the code. The correct answer should be 0.1560949...
L is amount of steps in x direction, M in y direction. hx and hy are step lengths.
This is really bugging me. And no I can only use the commands integral2 or traps as reference.
Thanks in advance!

In your present code, the lines
hy = (1)/M;
y=[0:M]*hy;
refer to the y-variable. When the limits for y depend on x, these lines cannot stay outside of the loop over x: they should be moved in and use the value x(i). Like this:
for i = 1:L+1 % as in your code
hy = (sin(pi*x(i)/2))/M;
y = [0:M]*hy;
Fy=[]; % this and the rest as in your code
I get output 0.1561, as you wanted.

Related

Matlab Error: Index in Position 1 exceeds array bounds

I am attempting to create a gamma distribution in MATLAB; however, I keep receiving the error:
Index in Position 1 exceeds array bounds (must not exceed 100).
Assuming I am reading this correctly, it is referring to variable M that is simply = 2500 (the number of pseudo-random variables I am using for this project).
I was hoping someone can explain what is wrong with my logic and possibly a solution.
alpha = 0.5;
w = gamma_rdn(M,alpha);
x1 = (0.0001:0.001:1); % For plot
figure(5)
subplot(2,1,1);hist(w);title('Histogram of Gamma RDN');
subplot(2,1,2);plot(x1,pdf('gam',x1,alpha,1));title('Theoretical Gamma Density with \alpha = 0.5');
axis([0 1 0 100]);
% The gamma_rdn function is implemented as follows:
function[w] = gamma_rdn(M,alpha)
% Generate random numbers from the gamma distribution with parameter
% alpha <= 1, beta = 1
pe = exp(1);
w = zeros(M,1);
u = rand(100,1);
b = (alpha + pe)/pe;
i = 0;
j = 0;
while j < M
i = i+1;
y = b*u(i,1);
if y <= 1
z = y^(1/alpha);
i = i+1;
if u(i,1) <= exp(-z)
j = j+1;
w(j,1) = z;
else
i = i+1;
end
else
z = -log((b-y)/alpha);
i = i+1;
if u(i,1) <= z^(alpha - 1)
j = j+1;
w(j,1) = z;
else
i = i+1;
end
end
end
if i > 95
u = rand(100,1);
i = 0;
end
end
Is there a particular reason you chose u = rand(100,1)?
The problem is coming because in while loop, as soon as variable i exceeds 100 (say i=101), y = b*u(i,1) becomes invalid. That is, you are trying to access u(101,1) while the size of u is (100,1).
If there's not particular reason, try a large enough size, like, u = rand(10000,1).

Solving a piecewise function for a given intercept in Matlab

I'm trying to solve a piecewise function, but I am getting an error. The following is the code.
script:
syms x
y_intercept = 2;
answerr = solve(pw_f(x) == y_intercept, x);
piecewise function (in a separate file within the same folder):
function y = pw_f(x)
if x < 0
y = x;
elseif (x >=0) && (x <= 20)
y = 2*x;
elseif x > 20
y = 4*x - 40;
else
end
end
The error I'm getting after running the script is:
Conversion to logical from sym is not possible.
Error in pw_f (line 3)
if x < 0
Error in solve_test
answerr = fsolve(pw_f(x) == y_intercept, x);
I know that the error is because Matlab can't perform the comparison x < 0 because x is a symbolic variable, so it does not know what x is yet. I also tried using fsolve, and vpasolve but I'm still getting the same error. Do you know how to solve this in Matlab or get around this error?
Of course, this is an easy problem that I can do in my head (x = 1 is the solution) so Matlab should be able to do this!! However, I want to make this generic for any y-intercept (maybe some random number that is not such a nice whole number) that I choose. PLEASE HELP!!!! Thanks :)
FYI, I am using Matlab R2013a.
In file called pw_f.m
function y = pw_f(x)
if x < 0
y = x;
elseif (x >=0) && (x <= 20)
y = 2*x;
elseif x > 20
y = 4*x - 40;
else
end
end
In command window
>> y_intercept = 2; % set object value
>> x0 = 0; % initial guess
>> answerr = fzero(#(x)pw_f(x) - y_intercept, x0) % solve
answerr =
1
>> pw_f(answerr) % test solution
ans =
2

Matlab solution for non-homogenous heat equation using finite differences

Given the following PDE (non-homogenous heat equation):
ut(x,t) = c2uxx(x,t) + f(x,t)
u(0,t) = u(l,t) = 0
u(x,0) = g(x)
0 < x < l ; t > 0 ; c > 0
I wrote the following code in Matlab, to solve the problem using finite differences:
syms xj tk
% Manually define this values
c = 9;
f(xj,tk) = xj;
g(xj) = 0*xj;
l = 1;
Tmax = 0.1;
% Grid definition
Nx = 50;
Nt = 50;
hx = 1/Nx;
ht = 1/Nt;
x = 0:hx:l;
t = 0:ht:Tmax;
lambda = c^2*ht/hx^2;
% Our target
u = zeros(Nx+1,Nt+1);
% Initial values
for j=1:Nx,
u(j,1) = g(x(j)); % u(x,0) = g(x)
end
for k=1:Nx,
u(1,k+1) = 0; % border condition u(0,t) = 0
for j=2:Nt,
u(j,k+1) = u(j,k) + lambda*(u(j+1,k)-2*u(j,k)+u(j-1,k)) + ht*f(j,k); % the formula here is ok
end
u(Nt,k+1) = 0; % border condition u(l,t) = 0
end
contour3(u)
For some reason that I cant't figure out, data is only appearing in the last columns and in a very strange way.
I'm guessing the implementation of the BC's are doing something nasty. But I don't see it.
Is there something that I'm missing?
Thanks in advance!

Not sure what this 'histogram code' is doing in MATLAB

I have following code that was given to me, but I am not sure at all as to what the logic here is. The idea, I believe, is that this will histogram/quantize my data. Here is the code:
The input:
x = 180.*rand(1,1000); %1000 points from 0 to 180 degrees.
binWidth = 20; %I want the binWidth to be 20 degrees.
The main function:
% -------------------------------------------------------------------------
% Compute the closest bin center x1 that is less than or equal to x
% -------------------------------------------------------------------------
function [x1, b1] = computeLowerHistBin(x, binWidth)
% Bin index
bin = floor(x./binWidth - 0.5);
% Bin center x1
x1 = binWidth * (bin + 0.5);
% add 2 to get to 1-based indexing
b1 = bin + 2;
end
Finally, the final 'quantized' data:
w = 1 - (x - x1)./binWidth
Here is what I do not get: I do not understand - at all - just why exactly x1 is computed the way it is, and also why/how w is computed the way it is. In fact, of all the things, w confuses me the most. I literally cannot understand the logic here, or what is really intended. Would appreciate a detailed elucidation of this logic. Thanks.
He is binning with lb <= x < up and splitting the interval [0,180] in [-10,10), [10, 30), [30,40) ..., [150,170), [170,190).
Suppose x = 180, then:
bin = floor(180/20-0.5) = floor(9-0.5) = floor(8.5) = 8;
while if x = 0:
bin = floor(`0/20-0.5) = floor(-0.5) = floor(-1) = -1;
which respectively translate into x1 = 20 * (8+0.5) = 170 and x1 = -10 which seems like what the function suggests lowerHistBin().
In the end, w simply measures how far the point x is from the corresponding lower bin x1. Notice that w is in (0,1], with w being 1 when x = x1 and approaching 0 when x -> x1+binWidth. So, if x say approaches 170, then w will approach 1 - (170-150)/20 = 0.

conditional statement with for loop

Not sure what I am doing wrong here;
I am trying to make a for loop with conditional statements for the following functions. I want to make it though so h is not a vector. I am doing this for 1 through 5 with increment 0.1.
Y = f(h) = h^2 if h <= 2 or h >= 3
Y = f(h) = 45 otherwise
my code is
for h = 0:0.1:5
if h <= 2;
Y = h^2;
elseif h >= 3;
Y = h^2;
else;
h = 45;
end
end
This could be done easier, but with a for loop i think you could use:
h=0:0.1:5;
y=zeros(1,length(h));
for i=1:length(h)
if or(h(i) <= 2, h(i) >= 3)
y(i) = h(i)^2;
else
y(i) = 45;
end
end
Why do you want to avoid making h an array? MATLAB specializes in operations on arrays. In fact, vectorized operations in MATLAB are generally faster than for loops, which I found counter-intuitive having started coding in C++.
An example of a vectorized verison of your code could be:
h = 0:0.1:5;
inds = find(h > 2 & h < 3); % grab indices where Y = 45
Y = h.^2; % set all of Y = h^2
Y(inds) = 45; % set only those entries for h between 2 and 3 to 45
The period in the .^2 operator broadcasts that operator to every element in the h array. This means that you end up squaring each number in h individually. In general, vectorized operation like this are more efficient in MATLAB, so it is probably best to get in the habit of vectorizing your code.
Finally, you could reduce the above code a bit by not storing your indices:
h = 0:0.1:5;
Y = h.^2; % set all of Y = h^2
Y(find(h > 2 & h < 3)) = 45; % set only those entries for h between 2 and 3 to 45
This blog series seems to be a good primer on vectorizing your MATLAB code.