Errors when using the Integral2 function in MATLAB - matlab

As far as I can tell, no one has asked this.
I've been asked to compute the double integral of a function, and also the same double integral but with the order of integration swapped (i.e: first integrate for dydx, then dxdy). Here is my code:
%Define function to be integrated
f = #(x,y) y^2*cos(x);
%First case. Integration order: dydx
ymin = #(x) cos(x);
I = integral2(f,ymin,1,0,2*pi)
%Second case. Integration order: dxdy
xmin = #(y) asin(y)+2*pi/2;
xmax = #(y) asin(y)-pi/2;
B = integral2(f,xmin,xmax,-1,1)
The error I'm getting is this:
Error using integral2 (line 71)
XMIN must be a floating point scalar.
Error in EngMathsA1Q1c (line 5)
I = integral2(f,ymin,1,0,2*pi)
I'm sure my mistake is something simple, but I've never used Integral2 before and I'm lost for answers. Thank you.

Per the integral2 documentation, the variable limits are given as the second pair of limits. So your first integral should be
% Define function to be integrated
f = #(x,y) y.^2.*cos(x);
% First case. Integration order: dydx
ymin = #(x) cos(x);
I = integral2(f,0,2*pi,ymin,1);
The set of constant limits always goes first, and Matlab assumes the first argument of f is associated with the first set of limits while the second argument of f is associated with the second set of limits, which may be a function of the first argument.
I point out that second part because if you wish to switch the order of integration, you also need to switch the order of the inputs of f accordingly. Consider the following example:
fun = #(x,y) 1./( sqrt(2*x + y) .* (1 + 2*x + y).^2 )
A nice little function that is not symmetric in its arguments (i.e., fun(x,y) ~= fun(y,x)). Let's integrate this over an elongated triangle in the first quadrant with vertices at (0,0), (2,0), and (0,1). Then integrating with dA == dy dx, we have
>> format('long');
>> ymax = #(x) 1 - x/2;
>> q = integral2(fun,0,2,0,ymax)
q =
0.220241017339352
Cool. Now let's integrate with dA == dx dy:
>> xmax = #(y) 2*(1-y);
>> q = integral2(fun,0,1,0,xmax)
q =
0.241956050772765
Oops, that's not equal to the first calculation! That's because fun is defined with x as the first argument and y as the second, but the previous call to integral2 is implying that y is the first argument to fun, and it has constant limits of 0 and 1. How do we fix this? Simply define a new function that flips the arguments:
>> fun2 = #(y,x) fun(x,y);
>> q = integral2(fun2,0,1,0,xmax)
q =
0.220241017706984
And all's right with the world. (Although you may notice small differences between the two correct answers due to the error tolerances of integral2, which can be adjusted via options per the documentation.)

The error states that you can't pass in a function for the limits of integration. You need to specify a scalar value for each limit of integration. Also, there are some errors in the dimensions/operations of the function. Try this:
%Define function to be integrated
f = #(x,y) y.^2.*cos(x);%changed to .^ and .*
%First case. Integration order: dydx
%ymin = #(x) cos(x);
I = integral2(f,-1,1,0,2*pi)%use scalar values for limits of integration
%Second case. Integration order: dxdy
%xmin = #(y) asin(y)+2*pi/2;
%xmax = #(y) asin(y)-pi/2;
B = integral2(f,0,2*pi,-1,1)% same issue, must use scalars

Related

Integral in Matlab

I have 3 equations:
f = (exp(-x.^2)).*(log(x)).^2
g = exp(-x.^2)
h = (log(x)).^2
The interval is:
x = 0.05:10
I am able to correctly plot the equations but when I try to find an integral, it says that there is an error.
The code I used to find an integral is:
integral(f,0,Inf)
integral(g,0,inf)
integral(h,0,10)
The integrals for f and g are from 0 to infinity and the integral for h is from 0 to 10. None of my code to find integrals works.
You need to define f,g,h as functions like shown below. See documentation of integral(), it takes a function as its first argument. Matlab integral documentation
x = 0.05:10
f = #(x) (exp(-x.^2)).*(log(x)).^2
g = #(x) exp(-x.^2)
h = #(x) (log(x)).^2
integral(f,0,Inf) % 1.9475
integral(g,0,inf) % 0.8862
integral(h,0,10) % 26.9673
h = #(x) (log(x)).^2
This syntax is called anonymous functions, basically they are nameless functions. In above case it takes x as input and returns log(x) squared.
From now on h is a function and it can be used like this.
h(1) % will be equal 0
For more on anonymous functions refer to matlab anonymous functions guide:
Anonymous Functions

Optimize a definite integral

In the integral
I want to optimize the function Dt, as I know the end result of the integral. I have expressions for k1 and k0 in terms of k2 and N, and it is k2 and N that I would like to optimize. They have constraints, needing to be between certain values. I have it all setup in my code, but I am just unaware of how to tell the genetic alogrithm to optimize an integral function? Is there something I'm missing here? The integral is usually evaluated numerically but I am trying to go backwards, and assuming I know an answer find the input parameters
EDIT:
All right, so here's my code. I know the integral MUST add up to a known value, and I know the value, so I need to optimize the variables with that given parameter. I have created an objective function y= integral - DT. I kept theta as syms because it is the thing being integrated to give DT.
function y = objective(k)
% Define constants
AU = astroConstants(2);
mu = astroConstants(4);
% Define start and finish parameters for the exponential sinusoid.
r1 = AU; % Initial radius
psi = pi/2; % Final polar angle of Mars/finish transfer
phi = pi/2;
r2 = 1.5*AU;
global k1
k1 = sqrt( ( (log(r1/r2) + sin(k(1)*(psi + 2*pi*k(2)))*tan(0)/k(1)) / (1-
cos(k(1)*(psi+2*pi*k(2)))) )^2 + tan(0)^2/k(1)^2 );
k0 = r1/exp(k1*sin(phi));
syms theta
R = k0*exp(k1*sin(k(1)*theta + phi));
syms theta
theta_dot = sqrt((mu/(R^3))*1/((tan(0))^2 + k1*(k(1))^2*sin(k(1)*theta +
phi) + 1));
z = 1/theta_dot;
y = int(z, theta, 0,(psi+2*pi*k(2))) - 1.3069e08;
global x
x=y;
end
my k's are constrained, and the following is the constraint function. I'm hoping what I have done here is tell it that the function MUST = 0.
function [c,c_eq] = myconstraints(k)
global k1 x
c = [norm(k1*(k(1)^2))-1 -norm(k1*(k(1)^2))];
c_eq =[x];
end
And finally, my ga code looks like this. Honestly, I've been playing with it all night and getting error messages after error messages - ranging from "constraint function must return real value" to "error in fcnvectorizer" and "unable to convert expression into double array", with the last two coming after i've removed the constraints.
clc; clear;
ObjFcn = #objective;
nvars = 2
LB = [0 2];
UB = [1 7];
ConsFcn = #myconstraints;
[k,fval] = ga(ObjFcn,nvars,[],[],[],[],LB,UB,ConsFcn);
I've been stuck on this problem for weeks and have gotten nowhere, even with searching through literature.

Computing integral with variable bounds in MATLAB

Consider the following MWE in MATLAB:
f = #(t) integral(#(x) x.^2,0,t);
integral(f,0,1);
This yields the error
Error using integral (line 85) A and B must be floating-point scalars.
(and a bit more). How do I fix this? Is this even possible? I think the problem is the variable upper bound.
If you want to use integral then set 'ArrayValued' to true otherwise t would be an invalid end point in integral(#(x) x.^2,0,t). So it would be:
f = #(t) integral(#(x) x.^2,0,t);
integral(f,0,1,'ArrayValued',true)
% ans =
% 0.0833
Alternately, since you're doing double integration, so use the function dedicated for this purpose i.e. integral2. For your example, it would be:
f = #(t,x) x.^2 ;
integral2(f,0,1,0, #(t) t)
% ans =
% 0.0833
If you have Symbolic Math Toolbox, you can also use int as int(expr,var,a,b) but it would be slower. For your case, it would be:
syms x t;
f = x.^2;
req = int(int(f,x,0,t),t,0,1); % It gives 1/12
req = double(req); % Convert to double if required

MATLAB solve Ordinary Differential Equations

How can I use matlab to solve the following Ordinary Differential Equations?
x''/y = y''/x = -( x''y + 2x'y' + xy'')
with two known points, such as t=0: x(0)= x0, y(0) = y0; t=1: x(1) = x1, y(1) = y1 ?
It doesn't need to be a complete formula if it is difficult. A numerical solution is ok, which means, given a specific t, I can get the value of x(t) and y(t).
If matlab is hard to do this, mathematica is also OK. But as I am not familiar with mathematica, so I would prefer matlab if possible.
Looking forward to help, thanks!
I asked the same question on stackexchange, but haven't get good answer yet.
https://math.stackexchange.com/questions/812985/matlab-or-mathematica-solve-ordinary-differential-equations
Hope I can get problem solved here!
What I have tried is:
---------MATLAB
syms t
>> [x, y] = dsolve('(D2x)/y = -(y*D2x + 2Dx*Dy + x*D2y)', '(D2y)/x = -(y*D2x + 2Dx*Dy + x*D2y)','t')
Error using sym>convertExpression (line 2246)
Conversion to 'sym' returned the MuPAD error: Error: Unexpected 'identifier'.
[line 1, col 31]
Error in sym>convertChar (line 2157)
s = convertExpression(x);
Error in sym>convertCharWithOption (line 2140)
s = convertChar(x);
Error in sym>tomupad (line 1871)
S = convertCharWithOption(x,a);
Error in sym (line 104)
S.s = tomupad(x,'');
Error in dsolve>mupadDsolve (line 324)
sys = [sys_sym sym(sys_str)];
Error in dsolve (line 186)
sol = mupadDsolve(args, options);
--------MATLAB
Also, I tried to add conditions, such as x(0) = 2, y(0)=8, x(1) = 7, y(1) = 18, and the errors are still similar. So what I think is that this cannot be solve by dsolve function.
So, again, the key problem is, given two known points, such as when t=0: x(0)= x0, y(0) = y0; t=1: x(1) = x1, y(1) = y1 , how I get the value of x(t) and y(t)?
Update:
I tried ode45 functions. First, in order to turn the 2-order equations into 1-order, I set x1 = x, x2=y, x3=x', x4=y'. After some calculation, the equation becomes:
x(1)' = x(3) (1)
x(2)' = x(4) (2)
x(3)' = x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)) (3)
x(4)' = -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2) (4)
So the matlab code I wrote is:
myOdes.m
function xdot = myOdes(t,x)
xdot = [x(3); x(4); x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)); -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)]
end
main.m
t0 = 0;
tf = 1;
x0 = [2 3 5 7]';
[t,x] = ode45('myOdes',[t0,tf],x0);
plot(t,x)
It can work. However, actually this is not right. Because, what I know is that when t=0, the value of x and y, which is x(1) and x(2); and when t=1, the value of x and y. But the ode functions need the initial value: x0, I just wrote the condition x0 = [2 3 5 7]' randomly to help this code work. So how to solve this problem?
UPDATE:
I tried to use the function bvp4c after I realized that it is a boundary value problem and the following is my code (Suppose the two boundry value conditions are: when t=0: x=1, y=3; when t=1, x=6, y=9. x is x(1), y is x(2) ):
1. bc.m
function res = bc(ya,yb)
res = [ ya(1)-1; ya(2)-3; yb(1) - 6; yb(2)-9];
end
2. ode.m
function dydx = ode(t,x)
dydx = [x(3); x(4); x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)); -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)];
end
3. mainBVP.m
solinit = bvpinit(linspace(0,6,10),[1 0 -1 0]);
sol = bvp4c(#ode,#bc,solinit);
t = linspace(0,6);
x = deval(sol,t);
plot(t,x(1,:));
hold on
plot(t,x(2,:));
plot(t,x(3,:));
plot(t,x(4,:));
x(1,:)
x(2,:)
It can work, but I don't know whether it is right. I will check it again to make sure it is the right code.
As mentioned, this isn't a math site, so try to give code or something showing some effort.
However, the first step you need to do is turn the DE into normal form (i.e., no 2nd derivatives). You do this by making a separate variable equal to the derivative. Then, you use
syms x y % or any variable instead of x or y
to define variables as symbolic. Use matlabfunction to create a symbolic function based on these variables. Finally, you can use the ode45 function to solve the symbolic function while passing variable values. I recommend you look up the full documentation in matlab in order to understand it better, but here is a very basic syntax:
MyFun= matlabFunction(eq,'vars',{x,y});
[xout,yout]=ode45(#(x,Y) MyFun(variables),[variable values],Options);
Hopefully this puts you in the right direction, so try messing around with it and provide code if you need more help.
EDIT:
This is how I would solve the problem. Note: I don't really like the matlabFunction creator but this is simply a personal preference for various reasons I won't go into.
% Seperate function of the first order state equations
function dz = firstOrderEqns(t,z)
dz(4,1) = 0;
dz(1) = -2.*z(3).*z(1).*z(4)./(1 + z(4).^2 + z(2).^2);
dz(2) = z(1);
dz(3) = -2.*z(2).*z(3).*z(1)./(1 + z(4).^2 + z(2).^2);
dz(4) = z(3);
end
% runfirstOrderEqns
%% Initial conditions i.e. # t=0
z1 = 5; % dy/dt = 5 (you didn't specify these initial conditions,
% these will depend on the system which you didn't really specify
z2 = 0; % y = 0
z3 = 5; % dx/dt = 5 (The same as for z1)
z4 = 0; % x = 0
IC = [z1, z2, z3, z4];
%% Run simulation
% Time vector: i.e closed interval [0,20]
t = [0,20]; % This is where you have to know about your system
% i.e what is it's time domain.
% Note: when a system has unstable poles at
% certain places the solver can crash you need
% to understand these.
% using default settings (See documentation ode45 for 'options')
[T,Y] = ode45(#firstOrderEqns,t,IC);
%% Plot function
plot(T,Y(:,1),'-',T,Y(:,2),'-.',T,Y(:,3),':',T,Y(:,4),'.');
legend('dy/dt','y','dx/dt','x')
As in my comments I have made a lot of assumtions that you need to fix for example, you didn't specify what the initial conditions for the first derivatives of the states are i.e. (z1, z3) which is important for the response of the system. Also you didn't specify the time interval your interested for the simulation etc.
Note: The second m file can be used with any state function in the correct format
The following is the answer we finally get #Chriso: use matlab bvp4c function to solve this boundary value problem (Suppose the two boundry value conditions are: when t=0: x=1, y=3; when t=1, x=6, y=9. x is x(1), y is x(2) ):
1. bc.m
function res = bc(ya,yb)
res = [ ya(1)-1; ya(2)-3; yb(1) - 6; yb(2)-9];
end
2. ode.m
function dydx = ode(t,x)
dydx = [x(3); x(4); x(2)/x(1)*(-2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)); -2*x(1)*x(3)*x(4)/(1+x(1)^2+x(2)^2)];
end
3. mainBVP.m
solinit = bvpinit(linspace(0,6,10),[1 0 -1 0]);
sol = bvp4c(#ode,#bc,solinit);
t = linspace(0,6);
x = deval(sol,t);
plot(t,x(1,:));
hold on
plot(t,x(2,:));
plot(t,x(3,:));
plot(t,x(4,:));
x(1,:)
x(2,:)

How to calculate the integral of the exp of the sum of function handles in a cell

I don't know how to calculate the integral of the sum of function handles in a cell. Please see the below examples:
f{1} = #(x) x;
f{2} = #(x) x^2;
g = #(x) sum(cellfun(#(y) y(x), f));
integral(#(x) exp(g), -3,3);
Error: Input function must return 'double' or 'single' values. Found 'function_handle'.
PS: please don't change the formula, because this is just an example. My real problem is far more complicated than this. It has log and exp of this sum (integral(log(sum), -inf, inf)). So I can't break them up to do the integral individually and sum the integrals.I need to use sum(cellfun). Thank you.
Version: Matlab R2012a
Can anyone help me? Really appreciate.
You cannot add function handles, so anything that tries f{1}+f{2}+... would give an error.
But you can compute the integral of the sums like this, evaluating the function values one at a time and adding up the results:
function cellsum
f{1} = #(x) x;
f{2} = #(x) x.^2;
integral(#(x)addfcn(f,x), -3, 3)
end
function s = addfcn(f,x)
s = zeros(size(x));
for k = 1:length(f)
s = s + f{k}(x);
end
end
Note that x will usually be a vector when the integral command calls your functions with it. So your function definitions should be vectorized, .i.e., x.^2 instead of x^2, etc.