I am now trying to solve an exponential equation in MATLAB as a part of my assignment. It is easy to see that the equation
exp(-t)+t*exp(-t)-n=0
would have two solutions, one greater than zero and one smaller.
However, using just the solve function, MATLAB returns something called lambertw function and it can only eval() to the solution below zero, which happens not to be the one I want for the answer. Could anyone help me here?
Thanks in advance for all the answers and comments!
p.s. As an alternative, I am thinking about using Newton-Raphson method to solve it, but I wonder how is the speed comparing to solve()?
Ziyao Wei
In the code below, I am numerically solving the equation for n=0.5 (the constant), but you it should be similar for other values you choose.
Note how the SOLVE function only returned the first solution found. Therefore I am calling the MuPAD engine directly, and specifying each time an interval in which to search for the solution:
%# lets plot the function: f(x) = exp(-x)+x*exp(-x)
h(1) = ezplot('0.5', [-1.5 10]); hold on
h(2) = ezplot('exp(-x)+x.*exp(-x)', [-1.5 10]);
set(h(1), 'LineStyle',':', 'Color','r')
legend(h, 'y = 0.5', 'y = exp(-x)+x.*exp(-x)')
%# The numeric solver only returns the first solution that it finds
x = solve('exp(-x)+x*exp(-x)=0.5')
x = vpa(x)
%# we can call the MuPAD solver and give the interval where solution can be found
x1 = evalin(symengine, 'numeric::solve(exp(-x)+x*exp(-x)=0.5, x = -1..0)')
x2 = evalin(symengine, 'numeric::solve(exp(-x)+x*exp(-x)=0.5, x = 0..3)')
%# show the solutions on the plot
plot([x1 x2], 0.5, 'ro')
The solution returned by SOLVE:
x =
- 1.0*lambertw(0, -1/(2*exp(1))) - 1.0
x =
-0.76803904701346556525568352607755
MuPAD numeric solutions:
x1 =
-0.76803904701346556525568352607755
x2 =
1.6783469900166606534128845120945
lambertw is the function that you need. However, it is a multivalued function and has several branches. You need to choose the right branch for your answer. See my answer to another question on how to choose a different branch for the solution.
The answer provided by matlab is correct but it gives you only one branch.
To get another branch, use the answer provided but replace lambertw(x) by lambertw(k,x) for different values of k.
See the doc of lambertw for more details.
You can have a look at the Lambert W function on mathworld to learn more and visualize the different branches.
Related
I would like to use numerical approach to calculate the differential with singularities.
For instance, y'=y^2+1 with y(0)=0. The analytical solution is not hard to find, y=tan(x).
The problem arises when I apply the numeric method, see the code in Matlab
tspan = [0 6];
y0 = [0; 0];
ode = #(t, y) y.^2+1;
[t, y] = ode45(ode, tspan, y0);
plot(t, y(:,1))
axis([0 6 -20 20])
which gives the plot below, i.e., it missed the part of solution after the first singularity.
My question: how to find the full numeric solution of a differential equation with singularities?
Thanks in advance!
This is impossible in general. An ODE solution ends where it diverges to infinity (or leaves the domain of the ODE function in any other way).
What you can do is apply domain knowledge. This equation is a Riccati DE. If one knows one solution, one can transform it into a Bernoulli DE that has a solution formula. There is a second transform without knowledge of a particular solution, it works always but is not always helpful. Set y=p/q and select their relationship so that a system of linear equations results. Here p'q-q'p=p^2+q^2 resolves nicely to p'=q, q'=-p, or as second order DE u''+u=0, the harmonic oscillator, for u=q or u=p. This system now has no singularities and the poles of the original solution y are the roots of the denominator q.
The prompt is to develop a program to evaluate convolutions. This is to be done without using MATLAB's built in conv function. Therefore utilizing the Fourier transform, multiplying the two functions together and then inverse Fourier transforming the product. The transform is done by using direct integration. The trapz function is recommended form of integration to accomplish this goal.
I would appreciate ANY feedback on how to improve my code, please thoroughly explain what the improvements and link an reference as to how they work.
Given the code:
t = -5:.1:5;
w = pi;
X = zeros(101,1);
H = zeros(101,1);
Y = zeros(101,1);
y = zeros(101,1);
if t >= 0
x = 0;
h = 0;
else
x = exp((-3.*t)+(-1i*w.*t));
h = exp((-2*t)+(-1i*w.*t));
end
for k=2:101
X(k)=trapz(t(1:k),x(1:k));
H(k)=trapz(t(1:k),h(1:k));
Y = (X.*H)*exp(1i*w.*t);
y(k) = (1/(2*pi))*trapz(t(1:k),Y(1:k));
end
disp (length(x))
disp (length(X))
disp (length(Y))
disp (length(y))
disp (y)
figure(1);
subplot(1,2,1),plot(t,real(y));grid on;
As I do not have enough reputation to directly post images, the actual output and desired output are as follows:
The actual plot is this.
The desired plot is this.
My primary question is this: why is my plot not working?
Secondarily: What is unneeded in this code? What could make this code more efficient?
I won't do your entire homework, but I'll give you a few clues:
Skip the if t < 0 part, it doesn't work. For your exam, try to understand why. If you can't figure it out, come with your best guess and you might get an explanation =)
Try the following instead (no loops or ifs needed:
x = exp((-3.*t)+(-1i*pi.*t)).*(t>0);
And the same for h. Try to understand what .*(t<0) does in this context.
This one: Y = (X.*H)*exp(1i*w.*t); should be outside the loop. Why? Make a guess and you might get guidance if you're wrong.
Also Y is a 101x101 matrix. I guess you want it to be 101x1? You probably need to transform one of the vectors in the expression used to create Y. Before you do, you should figure out the difference between ' and .' (an important difference in this case).
You are using subplot, but only plotting one graph. If you want to graphs in the same plot, use hold on. If you want to plots beside each other, remember to plot the second one too.
And why use w = pi;, when you can just as well use pi in the equations?
J(x)= 1/π integral cos(xsintheta). limits are from 0 to π.
Plot J(2pid/λ) as a function of d/λ in MATLAB for d/λ ranging between
0 and 2. At what distance of separation (in wavelengths) is the
correlation between the antennas 0.7, 0 ?
I do not understand how to integrate it in matlab, when i define syms theta and use
J_=integral(J,0,pi); there appears an error. secondly, when i integrate it manually, the answer appears 0. Kindly help me with it.
Unless you really need to calculate this manually, you should use Matlab's built-in besselj function to calculate the zeroth order Bessel function of the first kind:
dlam = 0:0.01:2;
x = 2*pi*dlam;
y = besselj(0,x)
figure;
plot(x,y)
This will be faster and more accurate the performing quadrature.
If you wish to determine the to a high degree of accuracy the points at which y is 0.7 or 0, as opposed to reading them from a plot, you can use symbolic math in conjunction with solve and sym/besselj. Assuming that this is what that part of the question is about (I know nothing about antennas), you can use something like:
syms x;
double(solve(besselj(0,x) == 0.7,x))
The integral command does not work on syms, it works on functions. For symbolic integration, the command is int.
I don’t have MATLAB at hand right now to check for typos etc., but something like this should work:
x = 0.1;
integral(#(theta) cos(x.*sin(theta)), 0, pi)/pi
Or even
bessel = #(x) integral(#(theta) cos(x.*sin(theta)), 0, pi)/pi;
bessel(0.1)
I'm trying to use ode45 to solve a system of ODE's:
[X,Y]= ode45(#sys,[0, T],y0);
where,
function dy = sys(t,y)
dy(1) = f_1(y)
dy(2) = f_2(y)
dy(3) = f_3(y)
end
The problem is that the function ode45 requires that y0 be initial values [y_1(0), y_2(0), y_3(0)], while in my system, I only have the values [y_2(0), y_3(0), y_3(T)] available.
Mathematically, this set of initial/terminal conditions should be enough to pin down the system, but is there any way I can work with that by ode45 or any other functions in MATLAB?
Thanks!
After digging in the Matlab documentation for a little bit, I think the more elegant way is to use the bvp4c function. bvp4c is a function specifically designed to handle boundary value problems like this, as opposed to ode**, which are really for initial value problems only. In fact, there's a whole set of other functions such as deval and bvpinit in Matlab that really facilitate the use of bvp4c. Here's the link to the Matlab documentation.
I'll post a brief (and perhaps a bit contrived) example here:
function [y1, y2, y3] = test(start,T)
solinit = bvpinit(linspace(0,3,10), [1,1,0]);
sol = bvp4c(#odefun,#bvpbc,solinit);
tspan = linspace(start,T,100);
S = deval(sol, tspan);
y1 = S(1,:);
y2 = S(2,:);
y3 = S(3,:);
plot (tspan,y1)
figure
plot (tspan,y2)
figure
plot (tspan,y3)
%% system definition & BVCs
function dydx = odefun(t,y)
dydx(1) = y(1) + y(2) + t;
dydx(2) = 2*y(1) + y(2);
dydx(3) = 3 * y(1) - y(2);
end
function res = bvpbc(y0,yT)
res= [y0(3) yT(2) yT(3)];
end
end
The test function outputs 3 vectors of solutions points for y1, y2 and y3 respectively, and also plots them.
Here are the variable paths plotted by Matlab:
Also, I found this video by professor Jake Blanchard from WMU to be very helpful.
One approach is to use the shooting method to iteratively solve for the unknown initial state y_1(0) such that the desired final state y_3(T) is satisfied.
The iteration proceeds by solving a nonlinear equation F = 0:
F(y_1(0)) = Y_3(T) - y_3(T)
where the uppercase function Y is the solution obtained by integrating the ODE's forward in time from a set of initial conditions. The task is to guess the value of y_1(0) to obtain F = 0.
Since we're now solving a nonlinear equation, all of the usual approaches apply. Specifically you could use either bisection or Newton's method to update your guess for the unknown initial state y_1(0). Note a couple of things:
The ODE's are integrated on [0,T] at each iteration of the nonlinear solve.
There may be multiple solutions for F = 0, depending on the structure of your ODE's.
Newton's method may converge faster than bisection, but may also be numerically unstable unless you can provide a good starting guess for y_1(0).
Using existing MATLAB functions, the bounded scalar nonlinear solver FMINBND might be a good choice as a nonlinear solver.
Hope this helps.
I know there must be a really simple answer to this question, but I just can't seem to find it. (Guess I'm probably Googling the wrong terms.)
I am plotting some data in Matlab using the plot(x, data) function.
I want to find the x-intercept(s) of the line, i.e. the point(s) where y = 0.
In some cases, it may be that the data vector doesn't actually contain values equal to zero, so it's not just a matter of finding the indexes of the elements in data which are equal to zero, and then finding the corresponding elements in the x vector.
Like I said, it's a really simple problem and I'd think there's already some in-built function in Matlab...
Thank you for your help.
If you want to find X-intercept as interpolate between 2 closest points around X axes you can use INTERP1 function:
x0 = interp1(y,x,0);
It will work if x and y are monotonically increasing/decreasing.
x=-1.999:0.001:1.999;
y=(x-1).*(x+1);
plot(x,y)
hold on
plot(x,zeros(length(x),1),'--r')
find(abs(y)<1e-3)
So the last part will guarantee that even there is not exact y-intercept, you will still get a close value. The result of this code are the indices that satisfy the condition.
You can make a linear fit (1st order polynomial) to your data, then, from the slope and Y intercept of the fitted line, you'll be able to find X intercept. Here is an example:
x1 = 1:10;
y1 = x1 + randn(1,10);
P = polyfit(x1,y1,1);
xint = -P(2)/P(1);
if you want to know what is the slope and y_int, here it is:
Slope = P(1); % if needed
yint = P(2); % if need