I am trying to perform a numerical triple integral over s, gamma1, gamma2. The limits are (-inf +int), (0,+inf) and (gamma1,+inf) respectively. Please dont be scared from the shape of my function (its just a function of gamma1, gamma2, s)
The following is my code
syms s
syms gamma1
syms gamma2
fun=-(exp(-(28035689158432973*pi*gamma2^(2/3))/2305843009213693952)*
exp(-(pi*s*7120816246010697*i)/112589990684262400)*
(1/((pi*s*(4194304/gamma1^2 + 4194304/gamma2^2)*i)/(50*
(6144/gamma1 + 6144/gamma2)) + 1)^((3*(2048/gamma1 + 2048/gamma2)^2)
/(4194304/gamma1^2 + 4194304/gamma2^2)) - 1)
*(exp(-(pi^2*s*(log((-(gamma2*25*i)/(1024*pi*s))^(1/3) + 1)/3;
y=#(s,gamma1,gamma2)fun;
gamma2min=#(s,gamma1) gamma1;
prob=integral3(y,-inf,+inf,0,+inf,gamma2min,+inf)
I get the following error
Error using integralCalc/finalInputChecks (line 511)
Input function must return 'double' or 'single' values. Found 'sym'.
Any advice?
Thank you very much!
You can use quadgk to numerically integrate functions defined like
y=#(a,b,c) 1/abs(a^2+b^2+c^2+1);
(which I used to test my answer).
It's tricky because quadgk expects a function that takes vector input and returns a vector of function values, but you can get around it by using a lot of arrayfun's:
R=#(s,gamma1) quadgk(#(gamma2) arrayfun(#(k) y(s,gamma1,k),gamma2),gamma1,Inf)
S=#(s) quadgk(#(gamma1) arrayfun(#(k) R(s,k),gamma1),0,Inf)
T=quadgk(#(s) arrayfun(#(k) S(k),s),-Inf,Inf)
But! It's very slow, I wasn't patient enough to wait for the answer. So, replace the Inf and -Inf limits with 100 and -100, for example, and you will get an answer. Maybe try with 50 and -50 and see how much the solution changes by, if it changes very little then you can be confident the answer is quite accurate, otherwise you'll have to increase the number and wait longer! The faster your function decays the smaller the bounds you will be ale to get away with.
Related
I'm using Matlab 2014b. I've tried:
clear all
syms x real
assumeAlso(x>=5)
This returned:
ans =
[ 5 <= x, in(x, 'real')]
Then I tried:
int(sqrt(x^2-25)/x,x)
But this still returned a complex answer:
(x^2 - 25)^(1/2) - log(((x^2 - 25)^(1/2) + 5*i)/x)*5*i
I tried the simplify command, but still a complex answer. Now, this might be fixed in the latest version of Matlab. If so, can people let me know or offer a suggestion for getting the real answer?
The hand-calculated answer is sqrt(x^2-25)-5*asec(x/5)+C.
This behavior is present in R2017b, though when converted to floating point the imaginary components are different.
Why does this occur?
This occurs because Matlab's int function returns the full general solution when you ask for the indefinite integral. This solution is valid over the entire domain of of real values, including your restricted domain of x>=5.
With a bit of math you can show that the solution is always real for x>=5 (see complex logarithm). Or you can use more symbolic math via the isAlways function to show this:
syms x real
assume(x>=5)
y = int(sqrt(x^2-25)/x, x)
isAlways(imag(y)==0)
This returns true (logical 1). Unfortunately, Matlab's simplification routines appear to not be able to reduce this expression when assumptions are included. You might also submit this case to The MathWorks as a service request in case they'd consider improving the simplification for this and similar equations.
How can this be "fixed"?
If you want to get rid of the zero-valued imaginary part of the solution you can use sym/real:
real(y)
which returns 5*atan2(5, (x^2-25)^(1/2)) + (x^2-25)^(1/2).
Also, as #SardarUsama points out, when the full solution is converted to floating point (or variable precision) there will sometimes numeric imprecision when converting from exact symbolic form. Using the symbolic real form above should avoid this.
The answer is not really complex.
Take a look at this:
clear all; %To clear the conditions of x as real and >=5 (simple clear doesn't clear that)
syms x;
y = int(sqrt(x^2-25)/x, x)
which, as we know, gives:
y =
(x^2 - 25)^(1/2) - log(((x^2 - 25)^(1/2) + 5i)/x)*5i
Now put some real values of x≥5 to check what result it gives:
n = 1004; %We'll be putting 1000 values of x in y from 5 to 1004
yk = zeros(1000,1); %Preallocation
for k=5:n
yk(k-4) = subs(y,x,k); %Putting the value of x
end
Now let's check the imaginary part of the result we have:
>> imag(yk)
ans =
1.0e-70 *
0
0
0
0
0.028298997121333
0.028298997121333
0.028298997121333
%and so on...
Notice the multiplier 1e-70.
Let's check the maximum value of imaginary part in yk.
>> max(imag(yk))
ans =
1.131959884853339e-71
This implies that the imaginary part is extremely small and it is not a considerable amount to be worried about. Ideally it may be zero and it's coming due to imprecise calculations. Hence, it is safe to call your result real.
I am trying to numerically solve an equation using fzero in Matlab. It is part of a bigger exercise. I haven't posted much here so not sure how much background information you need about this exercise so will try to keep it short.
This is my code:
fun = #(a)log(a/xBar) + (1/n) * log(dataProd) + diff(gamma(a))/gamma(a);
x0 = 0.8014;
x = fzero(fun,x0)
These are the values:
n = 209
xBar is 0.6078
dataProd = 3.1554e-77
I get the following error message in Matlab:
Operands to the || and && operators must be convertible to logical
scalar values.
Error in fzero (line 306)
elseif ~isfinite(fx) || ~isreal(fx)
Any idea why I get this error message?
I would guess that, during the search for a solution, fzero tries to evaluate your function at a=0, leading to an infinity. To check if this is the case, either look and see if you can set the optimization parameter 'display' to 'iter', or something similar in your version of Matlab. Otherwise, you can simply move your function to a separate m-file and call disp(a) on the first line. That way you will be able to see what fzero is doing and which value of a is causing the problem.
I'm trying to write some code which would find the limit of a function as x approaches positive and negative infinity. The code I have so far is as follows:
pos = limit(exp(atan(x)), x = infinity)
neg = limit(exp(atan(x)), x = -infinity)
However, it gives me an error saying "invalid syntax at =. Possibly, a ), }, or ] is missing. When I looked at the Matlab documentation for how to compute a limit, they had this as their example:
limit((1 + 1/n)^n, n = infinity)
and this returned an answer of e. When I put this into my own Matlab, it gave me the same error, could anyone help? Is it possibly an error with my Matlab?
You've been looking at the wrong help. Such notation (and limit function) is used in MuPAD interface, not in the simple Matlab Command Window.
To use limit() in Matlab environment, you have to use symbolic variables and this is the correct help page.
In other words, to compute
limit((1 + 1/n)^n, n = infinity)
you have to declare a symbolic variable n
syms n
and then provide the correct syntax (ref. help)
limit((1 + 1/n)^n, n, inf)
and the result is (of course) exp(1), that is e.
I am working on my thesis and running in some programming problems in Matlab. I am trying to implement the ''golden Bisection Method'' to speed up my code. To this end, I've consulted the build in function FZERO.
So I am determining the difference between two vectors which are both (1x20).
Difference = Clmax_dist-cl_vec;
Clmax_dist comes from a semi-empirical method and cl_vec comes from the excecution of an external AVL.exe file.
Essentially, this difference depends only on one single variable AOA because the Clmax_dist vector is a constant. Hence, I am constantly feeding a new AOA value to the AVL.exe to obtain a new cl_vec and compare this again to the constant Clmax_dist.
I am iterating this until one of the element in the vector becomes either zero or negative. My loop stops and reveals the final AOA. This is a time consuming method and I wanted to use FZERO to speed this up.
However, the FZERO documentation reveals that it only works on function which has a scalar as input. Hence, my question is: How can I use FZERO with a function which has a vector as an output. Or do i need to do something totally different?
I've tried the following:
[Difference] = obj.DATCOMSPANLOADING(AOA);
fun=#obj.DATCOMSPANLOADING;
AOA_init = [1 20];
AOA_root = fzero(fun,AOA_init,'iter');
this gave me the following error:
Operands to the || and && operators must be convertible to logical scalar values.
Error in fzero (line 423)
while fb ~= 0 && a ~= b
Error in CleanCLmax/run (line 11)
AOA_root = fzero(fun,AOA_init,'iter');
Error in InitiatorController/moduleRunner (line 11)
ModuleHandle.run;
Error in InitiatorController/runModule (line 95)
obj.moduleRunner(ModuleHandle);
Error in RunSteps (line 7)
C.runModule('CleanCLmax');
The DATCOMSPANDLOADING function contains the following:
function [Difference] = DATCOMSPANLOADING(obj,AOA)
[Input]= obj.CLmaxInput; % Creates Input structure and airfoil list
obj.writeAirfoils(Input); % Creates airfoil coordinate files in AVL directory
[Clmax_dist,YClmax,Cla_mainsections] = obj.Clmax_spanwise(Input); % Creates spanwise section CLmax with ESDU method
[CLa] = obj.WingLiftCurveSlope(Input,Cla_mainsections); % Wing lift curve slope
[Yle_wing,cl_vec] = obj.AVLspanloading(Input,CLa,AOA); % Creates spanloading with AVL
Difference = Clmax_dist-cl_vec;
end
If I need to elaborate further, feel free to ask. And of course, Thank you very much.
fzero indeed only works on scalars. However, you can turn your criterion into a scalar: You are interested in AOA where any of the elements in the vector becomes zero, in which case you rewrite your objective function to return two output arguments: minDifference, which is min(Difference), and Difference. The first output, minDifference is the minimum of the difference, i.e. what fzero should try to optimize (from your question, I'm assuming all values start positive). The second output you'd use to inspect your difference vector in the end.
UPDATE
I am trying to find the Lyapunov Exponents given in link LE. I am trying to figure it out and understand it by taking the following eqs for my case. These are a set of ordinary differential equations (these are just for testing how to work with cos and sin as ODE)
f(1)=ALPHA*(y-x);
f(2)=x*(R-z)-y;
f(3) = 10*cos(x);
and x=X(1); y=X(2); cos(y)=X(3);
f1 means dx/dt;f2 dy/dt and f3 in this case would be -10sinx. However,when expressing as x=X(1);y=X(2);i am unsure how to express for cos.This is just a trial example i was doing so as to know how to work with equations where we have a cos,sin etc terms as a function of another variable.
When using ode45 to solve these Eqs
[T,Res]=sol(3,#test_eq,#ode45,0,0.01,20,[7 2 100 ],10);
it throws the following error
??? Attempted to access (2); index must be a positive integer or logical.
Error in ==> Eq at 19
x=X(1); y=X(2); cos(x)=X(3);
Is my representation x=X(1); y=X(2); cos(y)=X(3); alright?
How to resolve the error?
Thank you
No your representation is completely wrong.
You can't possibly set values in this way!
For a start, you are trying to assign a value X(3) to a function.
first I am not sure you understand the difference between
x=4
and
4=x
which are completely different meanings. If you understand this, you'll see that you can't possibly assign using cos(x)=X(3).
Second: what is the function sol() you are calling? have you defined it?
Third, to solve or evaluate ODEs you should be using deval or solve functions in matlab. Their help files should give you examples.