How to do numerical multiple integral (more than triple) by using Matlab?
For example, I have a function,Y = Func. It has 5 var. Hence, Y= func(a,b,c,d,e). If I want to do the integration with respect to a,b,c,d,e. (var a is the first one, e is the last one.) And region of a = [0 ,b] (this is a function handle), b = [0,c], c= [0.d], d= [0,e], e=[0, Inf].
Now, here is my 'real' question. The code is below
%%%==== just some parameters ====
a=4;
la1=1/(pi*500^2); la2= la1*5;
p1=25; p2=p1/25;
sgma2=10^(-11);
index=1;
g=2./a;
syms r u1 u2 u3 u4 u5
index = -2;
powe= index ;
seta= 10^powe;
xNor = ( (u5./u1).^(a./2)+ (u5./u2).^(a./2) + (u5./u3).^(a./2)+ (u5./u4).^(a./2) + 1 ).^(2./a);
x = (xNor).^(0.5) * seta^(-1/a);
q=pi.*(la1.*p1.^(2./a)+la2.*p2.^(2./a));
%%%==== parameters end ====
fun1 = r./(1+ r.^a );
out1 = int(fun1, x, Inf) ;
out1fcn = matlabFunction(out1); %%===Convert symbolicto function handle
y = #(u5,u4,u3,u2,u1) exp(-u3.*(1+2.*... %%<== in method 3, replace as 'y= exp(-u3.*(1+2.*...'
( out1fcn )./... %%<== in method 3, replace as '( out1 )./...'
( (( (u5./u1).^(a./2)+ (u5./u2).^(a./2) + (u5./u3).^(a./2)+ (u5./u4).^(a./2) + 1 ).^(2./a)).*seta.^(-2./a)))).*...
exp(-sgma2.*q.^(-a./2).* seta.*u3.^(a./2)./...
((( (u5./u1).^(a./2)+ (u5./u2).^(a./2) + (u5./u3).^(a./2)+ (u5./u4).^(a./2) + 1 ).^(2./a)).^(a./2)) );
%%%=== method 1, not working ============ upper ,lower bound should be a number
% y1 = integral( y ,0,#(u2) u2);
% y2 = integral( y1 ,0,#(u3) u3);
% y3 = integral( y2 ,0,#(u4) u4);
% y4 = integral( y3 ,0, Inf);
%%%=== method 2, not working, y1 is already wrong ===============
%%%Undefined function 'minus' for input arguments of type 'function_handle'.
% y1 = quad( y ,0,#(u2) u2);
% y2 = quad( y1 ,0,#(u3) u3);
% y3 = quad( y2 ,0,#(u4) u4);
% y4 = quad( y3 ,0, Inf);
%%%=== method 3. not working, DOUBLE cannot convert the input expression into a double array. ==============
% y1 = int( y ,0,#(u2) u2);
% y2 = int( y1 ,0,#(u3) u3);
% y3 = int( y2 ,0,#(u4) u4);
% y4 = int( y3 ,0, Inf);
% y5 = double(y4)
A Google search showed that it is possible that by 2011 there was no standard numerical option available. This is a library you could consider. Finally, how about using Monte Carlo?
It would depend on if your function is defined symbolically or otherwise. However, if it is defined symbolically then five nested int functions would do the trick.
Related
I am not able to integrate heaviside(y-f) for x= 0 to pi/2 and y = 0 to pi/2 (only syms integration "int"). After running the code, output is shown in below and I am not able to get the numerical answer. Can you give some ideas on how to proceed?
code:
syms x y
f = sin(x);
integ = int( int(heaviside(y-f), x, 0, pi/2),y, 0, pi/2)
Result:
integ =
int(int(heaviside(y - sin(x)), x, 0, pi/2), y, 0, pi/2)
Avoid symbolic calculation whenever possible.
Notice the heaviside function can be defined as:
hvsd = #(x) (x > 0) + 0.5*(x == 0); % another name to do not overshadow heaviside
You can use either integral2 or trapz to evaluate the numerical integral.
heaviside = #(x) (x > 0) + 0.5*(x == 0);
fun = #(x,y) heaviside(y-sin(x));
% using integral2
I1 = integral2(fun,0,pi/2,0,pi/2)
nx = 100; ny = 100;
x = linspace(0,pi/2,nx);
y = linspace(0,pi/2,ny);
[X,Y] = meshgrid(x,y);
Z = fun(X,Y);
% using trapz
I2 = trapz(y,trapz(x,Z.*(Z>0),2))
I1 =
1.4674
I2 =
1.4695
I have written MATLAB code to solve the following systems of differential equations.
with
where
and z2 = x2 + (1+a)x1
a = 2;
k = 1+a;
b = 3;
ca = 5;
cb = 2;
theta1t = 0:.1:10;
theta1 = ca*normpdf(theta1t-5);
theta2t = 0:.1:10;
theta2 = cb*ones(1,101);
h = 0.05;
t = 1:h:10;
y = zeros(2,length(t));
y(1,1) = 1; % <-- The initial value of y at time 1
y(2,1) = 0; % <-- The initial value of y' at time 1
f = #(t,y) [y(2)+interp1(theta1t,theta1,t,'spline')*y(1)*sin(y(2));
interp1(theta2t,theta2,t,'spline')*(y(2)^2)+y(1)-y(1)-y(1)-(1+a)*y(2)-k*(y(2)+(1+a)*y(1))];
for i=1:(length(t)-1) % At each step in the loop below, changed y(i) to y(:,i) to accommodate multi results
k1 = f( t(i) , y(:,i) );
k2 = f( t(i)+0.5*h, y(:,i)+0.5*h*k1);
k3 = f( t(i)+0.5*h, y(:,i)+0.5*h*k2);
k4 = f( t(i)+ h, y(:,i)+ h*k3);
y(:,i+1) = y(:,i) + (1/6)*(k1 + 2*k2 + 2*k3 + k4)*h;
end
plot(t,y(:,:),'r','LineWidth',2);
legend('RK4');
xlabel('Time')
ylabel('y')
Now what is want to do is define the interpolations/extrapolations outside the function definition like
theta1_interp = interp1(theta1t,theta1,t,'spline');
theta2_interp = interp1(theta2t,theta2,t,'spline');
f = #(t,y) [y(2)+theta1_interp*y(1)*sin(y(2));
theta2_interp*(y(2)^2)+y(1)-y(1)-y(1)-(1+a)*y(2)-k*(y(2)+(1+a)*y(1))];
But this gives the error
Please suggest a solution to this issue.
Note that in your original code:
f = #(t,y) [y(2)+interp1(theta1t,theta1,t,'spline')*y(1)*sin(y(2));
interp1(theta2t,theta2,t,'spline')*(y(2)^2)+y(1)-y(1)-y(1)-(1+a)*y(2)-k*(y(2)+(1+a)*y(1))];
the call to interp1 uses the input variable t. t inside this anonymous function is not the same as the t outside of it, where it is defined as a vector.
This means that, when you do
theta1_interp = interp1(theta1t,theta1,t,'spline');
then theta1_interp is a vector containing interpolated values for all your ts, not just one. One way around this is to create more anonymous functions:
theta1_interp = #(t) interp1(theta1t,theta1,t,'spline');
theta2_interp = #(t) interp1(theta2t,theta2,t,'spline');
f = #(t,y) [y(2)+theta1_interp(t)*y(1)*sin(y(2));
theta2_interp(t)*(y(2)^2)+y(1)-y(1)-y(1)-(1+a)*y(2)-k*(y(2)+(1+a)*y(1))];
Though this doesn't really improve your code in any way over the original.
Assume we have three equations:
eq1 = x1 + (x1 - x2) * t - X == 0;
eq2 = z1 + (z1 - z2) * t - Z == 0;
eq3 = ((X-x1)/a)^2 + ((Z-z1)/b)^2 - 1 == 0;
while six of known variables are:
a = 42 ;
b = 12 ;
x1 = 316190;
z1 = 234070;
x2 = 316190;
z2 = 234070;
So we are looking for three unknown variables that are:
X , Z and t
I wrote two method to solve it. But, since I need to run these code for 5.7 million data, it become really slow.
Method one (using "solve"):
tic
S = solve( eq1 , eq2 , eq3 , X , Z , t ,...
'ReturnConditions', true, 'Real', true);
toc
X = double(S.X(1))
Z = double(S.Z(1))
t = double(S.t(1))
results of method one:
X = 316190;
Z = 234060;
t = -2.9280;
Elapsed time is 0.770429 seconds.
Method two (using "fsolve"):
coeffs = [a,b,x1,x2,z1,z2]; % Known parameters
x0 = [ x2 ; z2 ; 1 ].'; % Initial values for iterations
f_d = #(x0) myfunc(x0,coeffs); % f_d considers x0 as variables
options = optimoptions('fsolve','Display','none');
tic
M = fsolve(f_d,x0,options);
toc
results of method two:
X = 316190; % X = M(1)
Z = 234060; % Z = M(2)
t = -2.9280; % t = M(3)
Elapsed time is 0.014 seconds.
Although, the second method is faster, but it still needs to be improved. Please let me know if you have a better solution for that. Thanks
* extra information:
if you are interested to know what those 3 equations are, the first two are equations of a line in 2D and the third equation is an ellipse equation. I need to find the intersection of the line with the ellipse. Obviously, we have two points as result. But, let's forget about the second answer for simplicity.
My suggestion it's to use the second approce,which it's the recommended by matlab for nonlinear equation system.
Declare a M-function
function Y=mysistem(X)
%X(1) = X
%X(2) = t
%X(3) = Z
a = 42 ;
b = 12 ;
x1 = 316190;
z1 = 234070;
x2 = 316190;
z2 = 234070;
Y(1,1) = x1 + (x1 - x2) * X(2) - X(1);
Y(2,1) = z1 + (z1 - z2) * X(2) - X(3);
Y(3,1) = ((X-x1)/a)^2 + ((Z-z1)/b)^2 - 1;
end
Then for solving use
x0 = [ x2 , z2 , 1 ];
M = fsolve(#mysistem,x0,options);
If you may want to reduce the default precision by changing StepTolerance (default 1e-6).
Also for more increare you may want to use the jacobian matrix for greater efficencies.
For more reference take a look in official documentation:
fsolve Nonlinear Equations with Analytic Jacobian
Basically giving the solver the Jacobian matrix of the system(and special options) you can increase method efficency.
i have to do an assignment where i have to find the depth of how much the ball is under water depending on the water's density, then i have to plot it. i don't have matlab at home but i'm using octave and for some reason it's not compiling, and it's not saying any errors. here is my code
function my_script()
% weight function
function func = weight(x,p)
func = p *pi* 4- 3 * pi*x ^2 + pi* x ^3;
% make the secant method
function root = secant(func , p, x0, x1, tol, count)
while count ~= 0
y1 = func(x0,p);
y2 = func(x1, p);
k = (x1 - x0)/(y2 - y1);
R = y2 * k;
root = x1 - R;
if abs(func(root,p)) < tol
break;
end
x0 = x1;
x1 = root;
count = count - 1;
end
%create array for depth values
y_val = [];
%input the roots into the array with a loop
for p = 0:0.01:1
t = secant(#weight, p, 0, 1, 0.000001, 1000000);
disp (t);
y_val = [y_val t];
end
% create the x - axis
x_val = 0 : 0.01 : 1;
%plotting the graph
figure;
plot (x_val, y_val)
xlabel('Density');
ylabel('Depth ');
title('Floating Sphere vs Density ');
Another way of creating what you have written is to split it into three different functions.
You'd have the weight function, weight.m,
% weight function
function func = weight(x,p)
func = p *pi* 4- 3 * pi*x ^2 + pi* x ^3;
and the secant method function, secant.m,
% make the secant method
function root = secant(func , p, x0, x1, tol, count)
while count ~= 0
y1 = func(x0,p);
y2 = func(x1, p);
k = (x1 - x0)/(y2 - y1);
R = y2 * k;
root = x1 - R;
if abs(func(root,p)) < tol
break;
end
x0 = x1;
x1 = root;
count = count - 1;
end
%create array for depth values
y_val = [];
%input the roots into the array with a loop
for p = 0:0.01:1
t = secant(#weight, p, 0, 1, 0.000001, 1000000);
disp (t);
y_val = [y_val t];
end
% create the x - axis
x_val = 0 : 0.01 : 1;
%plotting the graph
figure;
plot (x_val, y_val)
xlabel('Density');
ylabel('Depth ');
title('Floating Sphere vs Density ');
Then you'd have my_script():
function my_script()
but it is an empty function, so the output is correct! You have to have all the commands for each function finished before you define the next function.
I have a feeling that you want to take out everything from the end of the while loop onwards from the secant function and put it into the main my_script() function.
Here's your code, Octave style. Observe that I temporarily commented the "disp(t);" statement to avoid a long listing of values. This way, the plot is plotted immediately. Hopefully this helps.
function my_script
%create array for depth values
y_val = [];
%input the roots into the array with a loop
for p = 0:0.01:1
t = secant(#weight, p, 0, 1, 0.000001, 1000000);
%disp (t);
y_val = [y_val t];
endfor
% create the x - axis
x_val = 0 : 0.01 : 1;
%plotting the graph
figure(1)
plot (x_val, y_val)
xlabel('Density');
ylabel('Depth ');
title('Floating Sphere vs Density ');
endfunction
% make the secant method
function root = secant(func , p, x0, x1, tol, count)
while count ~= 0
y1 = func(x0,p);
y2 = func(x1, p);
k = (x1 - x0)/(y2 - y1);
R = y2 * k;
root = x1 - R;
if abs(func(root,p)) < tol
break;
end
x0 = x1;
x1 = root;
count = count - 1;
endwhile
endfunction
% weight function
function func = weight(x,p)
func = p *pi* 4- 3 * pi*x ^2 + pi* x ^3;
endfunction
Got one more problem with matrix multiplication in Matlab. I have to plot Taylor polynomials for the given function. This question is similar to my previous one (but this time, the function is f: R^2 -> R^3) and I can't figure out how to make the matrices in order to make it work...
function example
clf;
M = 40;
N = 20;
% domain of f(x)
x1 = linspace(0,2*pi,M).'*ones(1,N);
x2 = ones(M,1)*linspace(0,2*pi,N);
[y1,y2,y3] = F(x1,x2);
mesh(y1,y2,y3,...
'facecolor','w',...
'edgecolor','k');
axis equal;
axis vis3d;
axis manual;
hold on
% point for our Taylor polynom
xx1 = 3;
xx2 = 0.5;
[yy1,yy2,yy3] = F(xx1,xx2);
% plots one discrete point
plot3(yy1,yy2,yy3,'ro');
[y1,y2,y3] = T1(xx1,xx2,x1,x2);
mesh(y1,y2,y3,...
'facecolor','w',...
'edgecolor','g');
% given function
function [y1,y2,y3] = F(x1,x2)
% constants
R=2; r=1;
y1 = (R+r*cos(x2)).*cos(x1);
y2 = (R+r*cos(x2)).*sin(x1);
y3 = r*sin(x2);
function [y1,y2,y3] = T1(xx1,xx2,x1,x2)
dy = [
-(R + r*cos(xx2))*sin(xx1) -r*cos(xx1)*sin(xx2)
(R + r*cos(xx2))*cos(xx1) -r*sin(xx1)*sin(xx2)
0 r*cos(xx2) ];
y = F(xx1, xx2) + dy.*[x1-xx1; x2-xx2];
function [y1,y2,y3] = T2(xx1,xx2,x1,x2)
% ?
I know that my code is full of mistakes (I just need to fix my T1 function). dy represents Jacobian matrix (total derivation of f(x) - I hope I got it right...). I am not sure how would the Hessian matrix in T2 look, by I hope I will figure it out, I'm just lost in Matlab...
edit: I tried to improve my formatting - here's my Jacobian matrix
[-(R + r*cos(xx2))*sin(xx1), -r*cos(xx1)*sin(xx2)...
(R + r*cos(xx2))*cos(xx1), -r*sin(xx1)*sin(xx2)...
0, r*cos(xx2)];
function [y1,y2,y3]=T1(xx1,xx2,x1,x2)
R=2; r=1;
%derivatives
y1dx1 = -(R + r * cos(xx2)) * sin(xx1);
y1dx2 = -r * cos(xx1) * sin(xx2);
y2dx1 = (R + r * cos(xx2)) * cos(xx1);
y2dx2 = -r * sin(xx1) * sin(xx2);
y3dx1 = 0;
y3dx2 = r * cos(xx2);
%T1
[f1, f2, f3] = F(xx1, xx2);
y1 = f1 + y1dx1*(x1-xx1) + y1dx2*(x2-xx2);
y2 = f2 + y2dx1*(x1-xx1) + y2dx2*(x2-xx2);
y3 = f3 + y3dx1*(x1-xx1) + y3dx2*(x2-xx2);