Integral of a 2D function with parameters in Matlab - matlab

I have a function in Matlab which takes four arguments:
function result = my_function(par1, x, y, par2)
// some code
end
I want to integrate it in 2D (along the x and y dimentions), for a chosen values of par1 and par2. Here is how I do it:
par1 = 1;par2 =2;
result = integral2(#(x,y)my_function(par1, x, y, par2), xmin, xmax, ymin, ymax);
However, when I ran this code and display the size of variables x and y inside my function, it is big. The integral2 function executes my function on arrays of arguments at once.
How can I force matlab to execute the function my_function for one value of x and y at a time?
Of course, I can check the size of x and y inside my function and then manually create an array of results:
function result = my_function(par1, x, y, par2)
result = zeros(size(x));
for i=1:size(result(:))
% do the work here
end
reshape(result, size(x))
end
But this isn't a very elegant solution.
Update: I agree that the integer is a scalar and I like it that way. The problem is that my function work only when the arguments (x and y) are scalars.
Matlab needs an array of values of my function to calculate the integral, so it evaluates my function once when x and y are arrays. And I want it to evaluate my function many times for x and y which are scalars.

Related

how to know the size of the vectors you are assigningto?

i wrote a function y(x) , in this function a check is the input value abs(x(t))<= 2 then i want the output y=x; but i get an error
"Unable to perform assignment because the left and right sides have a
different number of elements."
, but i didn't define the size of y ! is it suppoosed to have a default size similar to the x size ?
function y = my_f(x)
y(abs(x)<=2)=x;
y(x<-2)=-2;
y(x>2)=2;
end
N=1000;
t=linspace(0,10,N+1);
t(end)=[];
x1=(3*sin(2*pi*t/4)+0.5*cos(2*pi*6*t));
y= my_f(x1);
figure;hold on; grid on;
plot(t,y,':r','LineWidth',2)
In your function my_f(x), with y(abs(x)<=2)=x; you are setting only a portion of y to the full vector x, which does not fit. Furthermore, you did not initialize y yet, so indexing before its existence is a bit weird.
Since you want y to be equal to x, for the specified condition, you can just do this:
function y = my_f(x)
y = x;
y(x<-2)=-2;
y(x>2)=2;
end
Funny enough, you don't need to define y to be a copy of x, as long as you assign the same number of elements. Hence, this also works (unrecommended though!)
function y = my_f(x)
y(abs(x)<=2) = x(abs(x)<=2);
y(x<-2)=-2;
y(x>2)=2;
end
If you inspect y, you will see that the other indices, for which abs(x)<=2 does not hold, will be set to zero.

Symbolic differentiation

Well, I know, for a normal case, if I define
syms x,y
K = f(x,y)
as an explicit expression on x and y, we can do diff(K, x) or diff(K, y) to obtain what we want.
But right now, if I have another function
J = g(K)
And I want to do
diff(J, K)
then error occurs as:
'The second argument must be a variable or a non negative integer specifying the number of differentiations.'
So, in a nutshell, how to solve this kind of 'chained expression differentiation'? (Sorry for this ambiguous description.)
According to the diff function in Matlab,
The first argument should be the function you want to differentiate
and the remaining arguments must be either the symbolic variables or a
non-negative number which represents the number of differentiation.
So, the error.
The second argument must be a variable or a non negative integer specifying the number of differentiations.
In the code diff(J, K) is saying that K is a symbolic variable to the Matlab but in actual case, K is an expression in the terms of x and y. So, this is the reason why Matlab is throwing that error.
So if you want to differentiate a chained function with variables x, y then you need to mention each symbolic variables explicitly within the diff() function whenever you want to differentiate that expression. The code to do so is below.
% define the symbolic functions
% as f(x,y) and g(K)
syms f(x,y) g(K)
% create the functions
K = f(x,y)
J = g(K)
% differentiate the functions with
% respect to x and y respectively.
% ------------------------
% differentiate w.r.t x
diff_K_x = diff(K, x)
% differentiate w.r.t y
diff_K_y = diff(K, y)
% -----------------------
% differentiate the function J with respect to x and y both
diff_K_xy = diff(J,x,y)

How to plot function of 3 variables with Octave?

I am new to Octave (and matlab for that matter). I have a function that looks like this
I would like to plot g(x,0.5,5) say.
Here it is what I tried in Octave
I defined an anonymous function
f=#(n,x,t) 1./n.*log(n.*pi.*t).*sin(n.*pi.*x);
then another anonymous function
g=#(m,x,t)x.^2+sum(f([1:m],x,t));
Finally defined
x=-1:0.1:1;
plot(x,g(5,x,0.5))
but I get an error. Is this the right way of plotting this function? I must be doing a simple beginner error?
When you call f(n,x,t), you are passing a 1-by-5 vector for n and a 1-by-21 vector for x. These have different numbers of elements, and therefore can't be multiplied element-by-element. However, you can rewrite f to accommodate vectors for each and perform the sum from g by using matrix multiplication:
f = #(n, x, t) (1./n.*log(n.*pi.*t))*sin(pi.*n(:)*x);
g = #(m, x, t) x.^2 + f(1:m, x, t);
And now your plot will work:
x = -1:0.1:1;
plot(x, g(5, x, 0.5));

Trouble with exponentiation in Octave's ezmesh function

I made the following function handler:
fhapprox1 = #(x, y) sum ([1:x] .^ y)
This works fine when called with arguments like fhapprox1(3,5). However, when passing this function to ezmesh (using ezmesh(fhapprox1)), I get the following error:
error: operator .^: nonconformant arguments (op1 is 1x0, op2 is 60x60)
What is happening here? How can I rewrite this to get the 3d graph I'm expecting?
This is because your function is only designed to handle single values of x and y. ezmesh uses a grid of co-ordinates and x and y are actually 2D matrices when you use ezmesh. You get undefined behaviour when trying to call up ezmesh this way. In addition, ezmesh plots between -2*pi <= (x,y) <= 2*pi by default.
Because x can be < 0, doing 1:x when x is negative will give you an empty array, which is why you get that error. You need to rethink how your function can be defined so that it takes in a grid of co-ordinates and outputs the values you want. I can't provide anything further because I don't know how your function would be defined for negative values of x. Once I get this information, I'll update my answer.
Edit
We can modify your fhapprox1 function so that it can take in a grid of values. I can't think of a way to vectorize this code right now other than doing nested for loops, but let's try and get something working first. Basically, make a separate M-file that's called fhapprox1.m. After, put this into the file:
function [Z] = fhapprox1(X, Y)
Z = zeros(size(X));
for x = 1 : size(X,1)
for y = 1 : size(X,2)
Z(x,y) = sum((1:X(x,y)) .^ Y(x,y));
end
end
The above code will do what you were doing for single values of (x,y), but now it can take in a grid of (x,y) co-ordinates. By doing this, then calling ezmesh in the way you specified in your comments, this is what we get:
ezmesh(#fhapprox1, [1,1000,1,3])

Numerically integrate a function f(x) over x using MATLAB where f(x) has another argument y which is a vector

I would like to numerically integrate a vector which represents a function f(x) over the range of x specified by bounds x0 and x1 in Matlab. I would like to check that the output of the integration is correct and that it converges.
There are the quad and quadl functions that serve well in identifying the required error tolerance, but they need the input argument to be a function and not the resulting vector of the function. There is also the trapz function where we can enter the two vectors x and f(x), but then it computes the integral of f(x) with respect to x depending on the spacing used by vector x. However, there is no given way using trapz to adjust the tolerance as in quad and quadl and make sure the answer is converging.
The main problem why I can't use quad and quadl functions is that f(x) is the following equation:
f(x) = sum(exp(-1/2 *(x-y))), the summation is over y, where y is a vector of length n and x is an element that is given each time to the function f(x). Therefore, all elements in vector y are subtracted from element x and then the summation over y is calculated to give us the value f(x). This is done for m values of x, where m is not equal to n.
When I use quadl as explained in the Matlab manual, where f(x) is defined in a separate function .m file and then in the main calling file, I use Q = quadl(#f,x0,x1,tolerance,X,Y); here X is a vector of length m and Y is a vector of length L. Matlab gives an error: "??? Error using ==> minus
Matrix dimensions must agree." at the line where I define the function f(x) in the .m function file. f(x) = sum(exp(-1/2 *(x-y)))
I assume the problem is that Matlab treats x and y as vectors that should be of the same length when they are subtracted from each other, whereas what's needed is to subtract the vector Y each time from a single element from the vector X.
Would you please recommend a way to solve this problem and successfully numerically integrate f(x) versus x with a method to control the tolerance?
From the documentationon quad it says:
The function y = fun(x) should accept a vector argument x and return a vector result y, the integrand evaluated at each element of x.
So every time we call the function, we need to evaluate the integrand at each given x.
Also, to parameterize the function call with the constant vector Y, I recommend an anonymous function call. There's a reasonable demo here. Here's how I implemented your problem in Matlab:
function Q = test_num_int(x0,x1,Y)
Q = quad(#(x) myFun(x,Y),x0,x1);
end
function fx = myFun(x,Y)
fy = zeros(size(Y));
fx = zeros(size(x));
for jj=1:length(fx)
for ii=1:length(Y)
fy(ii) = exp(-1/2 *(x(jj)-Y(ii)));
end
fx(jj) = sum(fy);
end
end
Then I called the function and got the following output:
Y = 0:0.1:1;
x0 = 0;
x1 = 1;
Q = test_num_int(x0,x1,Y)
Q =
11.2544
The inputs for the lower and upper bound and the constant array are obviously just dummy values, but the integral converges very quickly, almost immediately. Hope this helps!
I believe the following would also work:
y = randn(10,1);
func = #(x) sum(exp(-1/2 *(x-y)));
integral(func,0,1,'ArrayValued',true)