Solving time-dependent Schrodinger equation using MATLAB ode45 - matlab

The Schrodinger equation for a time-dependent Hamiltonian is:
I try to implement a solver for the Schrodinger equation for a time-dependent Hamiltonian in ode45. However, because the Hamiltonian $H(t)$ is dependent on time. I do not know how to do interpolation in ode45. Can you give me some hints?
psi0 = [0 1];
H = [1 0;0 1]*cos(t); %this is wrong, I do not know how to implement this and pass it to ode45
hbar = 1;
t = [0:1:100];
[T, psi] = ode45(dpsi, t, psi);
function dpsi = f(t, psi, H, psi0)
dpsi = (1/i)*H*psi;
I also try to come up with a solution of matrix interpolation in
MATLAB: Interpolation that involve a matrix.

H is just an identity matrix in your case, so we can just multiply it with the psi vector to get back the psi vector itself. Then, we bring i*hbar to the right-hand-side of the equation so that the final equation is in a form that ode45 accepts. Finally, we use the following code to solve for psi:
function schrodinger_equation
psi0 = [0;1];
hbar = 1;
t = [0 100];
[T,psi] = ode45(#(t,psi)dpsi(t,psi,hbar),t,psi0);
for i = 1:length(psi0)
figure
plot(T,real(psi(:,i)),T,imag(psi(:,i)))
xlabel('t')
ylabel('Re(\psi) or Im(\psi)')
title(['\psi_0 = ' num2str(psi0(i))])
legend('Re(\psi)','Im(\psi)','Location','best')
end
end
function rhs = dpsi(t,psi,hbar)
rhs = 1/(1i*hbar)*cos(t).*ones(2,1);
end
Note that I have plotted the two components of psi separately and for each such plot, I have also plotted the real and imaginary components separately. Here are the plots for two different values of psi0:

Related

How to miss out matrix elements in pcolor plot?

I'm solving a set of nonlinear simultaneous equations using Matlab's fsolve to find unknown parameters x1 and x2. The simultaneous equations have two independent parameters a and b, as defined in the root2d function:
function F = root2d(x,a,b)
F(1) = exp(-exp(-(x(1)+x(2)))) - x(2)*(a+x(1)^2);
F(2) = x(1)*cos(x(2)) + x(2)*sin(x(1)) - b;
end
I use the following code to solve the simultaneous equations, and plot the results as a 2d figure using pcolor.
alist = linspace(0.6,1.2,10);
blist = linspace(0.4,0.8,5);
% results
x1list = zeros(length(blist),length(alist));
x2list = zeros(length(blist),length(alist));
% solver options
options = optimoptions('fsolve','Display','None');
for ii = 1:length(blist)
b = blist(ii);
for jj = 1:length(alist)
a = alist(jj);
x0 = [0 0]; % init guess
[xopt,yopt,exitflag] = fsolve(#(x0)root2d(x0,a,b),x0,options);
% optimised values
x1list(ii,jj) = xopt(1);
x2list(ii,jj) = xopt(2);
success(ii,jj) = exitflag; % did solver succeed?
end
end
% plotting
figure
s = pcolor(alist(success>0),blist(success>0),x1list(success>0));
xlabel('a')
ylabel('b')
title('my data x_1')
figure
s = pcolor(alist(success>0),blist(success>0),x2list(success>0));
xlabel('a')
ylabel('b')
title('my data x_2')
However I only want to plot the x1 and x2 where the solver has successfully converged to a solution. This is where the success matrix element (or exitflag) has a value greater than 0. Usually you just write x1list(success>0) when using the plot function and Matlab omits any solutions where (success<=0), but pcolor doesn't have that functionality.
Is there a way around this? For example, displaying all (success<=0) solutions as a black area.
Yes there is!
The easiest way is to make them NaN, so they are simply not drawn.
just do
x1list(~success)=NaN;
pcolor(alist,blist,x1list)

Finding solution to Cauchy prob. in Matlab

I need some help with finding solution to Cauchy problem in Matlab.
The problem:
y''+10xy = 0, y(0) = 7, y '(0) = 3
Also I need to plot the graph.
I wrote some code but, I'm not sure whether it's correct or not. Particularly in function section.
Can somebody check it? If it's not correct, where I made a mistake?
Here is separate function in other .m file:
function dydx = funpr12(x,y)
dydx = y(2)+10*x*y
end
Main:
%% Cauchy problem
clear all, clc
xint = [0,5]; % interval
y0 = [7;3]; % initial conditions
% numerical solution using ode45
sol = ode45(#funpr12,xint,y0);
xx = [0:0.01:5]; % vector of x values
y = deval(sol,xx); % vector of y values
plot(xx,y(1,:),'r', 'LineWidth',3)
legend('y1(x)')
xlabel('x')
ylabel('y(x)')
I get this graph:
ode45 and its related ilk are only designed to solve first-order differential equations which are of the form y' = .... You need to do a bit of work if you want to solve second-order differential questions.
Specifically, you'll have to represent your problem as a system of first-order differential equations. You currently have the following ODE:
y'' + 10xy = 0, y(0) = 7, y'(0) = 3
If we rearrange this to solve for y'', we get:
y'' = -10xy, y(0) = 7, y'(0) = 3
Next, you'll want to use two variables... call it y1 and y2, such that:
y1 = y
y2 = y'
The way you have built your code for ode45, the initial conditions that you specified are exactly this - the guess using y and its first-order guess y'.
Taking the derivative of each side gives:
y1' = y'
y2' = y''
Now, doing some final substitutions we get this final system of first-order differential equations:
y1' = y2
y2' = -10*x*y1
If you're having trouble seeing this, simply remember that y1 = y, y2 = y' and finally y2' = y'' = -10*x*y = -10*x*y1. Therefore, you now need to build your function so that it looks like this:
function dydx = funpr12(x,y)
y1 = y(2);
y2 = -10*x*y(1);
dydx = [y1 y2];
end
Remember that the vector y is a two element vector which represents the value of y and the value of y' respectively at each time point specified at x. I would also argue that making this an anonymous function is cleaner. It requires less code:
funpr12 = #(x,y) [y(2); -10*x*y(1)];
Now go ahead and solve it (using your code):
%%// Cauchy problem
clear all, clc
funpr12 = #(x,y) [y(2); -10*x*y(1)]; %// Change
xint = [0,5]; % interval
y0 = [7;3]; % initial conditions
% numerical solution using ode45
sol = ode45(funpr12,xint,y0); %// Change - already a handle
xx = [0:0.01:5]; % vector of x values
y = deval(sol,xx); % vector of y values
plot(xx,y(1,:),'r', 'LineWidth',3)
legend('y1(x)')
xlabel('x')
ylabel('y(x)')
Take note that the output when simulating the solution to the differential equation by deval will be a two column matrix. The first column is the solution to the system while the second column is the derivative of the solution. As such, you'll want to plot the first column, which is what the plot syntax is doing.
I get this plot now:

Plot symbolic equation using standard plot function in Matlab

In order to obtain a graphical representation of the behaviour of a fluid it is common practice to plot its streamlines.
For a given two-dimensional fluid with speed components u = Kx and v = -Ky (where K is a constant, for example: K = 5), the streamline equation can be obtained integrating the flow velocity field components as follows:
Streamline equation: ∫dx/u = ∫dy/v
The solved equation looks like this: A = B + C (where A is the solution of the first integral, B is the solution of the second integral and C is an integration constant).
Once we have achieved this, we can start plotting a streamline by simply assigning a value to C, for example: C = 1, and plotting the resulting equation. That would generate a single streamline, so in order to get more of them you need to iterate this last step assigning a different value of C each time.
I have successfully plotted the streamlines of this particular flow by letting matlab integrate the equation symbolically and using ezplot to produce a graphic as follows:
syms x y
K = 5; %Constant.
u = K*x; %Velocity component in x direction.
v = -K*y; %Velocity component in y direction.
A = int(1/u,x); %First integral.
B = int(1/v,y); %Second integral.
for C = -10:0.1:10; %Loop. C is assigned a different value in each iteration.
eqn = A == B + C; %Solved streamline equation.
ezplot(eqn,[-1,1]); %Plot streamline.
hold on;
end
axis equal;
axis([-1 1 -1 1]);
This is the result:
The problem is that for some particular regions of the flow ezplot is not accurate enough and doesn't handle singularities very well (asymptotes, etc.). That's why a standard "numeric" plot seems desirable, in order to obtain a better visual output.
The challenge here is to convert the symbolic streamline solution into an explicit expression that would be compatible with the standard plot function.
I have tried to do it like this, using subs and solve with no success at all (Matlab throws an error).
syms x y
K = 5; %Constant.
u = K*x; %Velocity component in x direction.
v = -K*y; %Velocity component in y direction.
A = int(1/u,x); %First integral.
B = int(1/v,y); %Second integral.
X = -1:0.1:1; %Array of x values for plotting.
for C = -10:0.1:10; %Loop. C is assigned a different value in each iteration.
eqn = A == B + C; %Solved streamline equation.
Y = subs(solve(eqn,y),x,X); %Explicit streamline expression for Y.
plot(X,Y); %Standard plot call.
hold on;
end
This is the error that is displayed on the command window:
Error using mupadmex
Error in MuPAD command: Division by zero.
[_power]
Evaluating: symobj::trysubs
Error in sym/subs>mupadsubs (line 139)
G =
mupadmex('symobj::fullsubs',F.s,X2,Y2);
Error in sym/subs (line 124)
G = mupadsubs(F,X,Y);
Error in Flow_Streamlines (line 18)
Y = subs(solve(eqn,y),x,X); %Explicit
streamline expression for Y.
So, how should this be done?
Since you are using subs many times, matlabFunction is more efficient. You can use C as a parameter, and solve for y in terms of both x and C. Then the for loop is very much faster:
syms x y
K = 5; %Constant.
u = K*x; %Velocity component in x direction.
v = -K*y; %Velocity component in y direction.
A = int(1/u,x); %First integral.
B = int(1/v,y); %Second integral.
X = -1:0.1:1; %Array of x values for plotting.
syms C % C is treated as a parameter
eqn = A == B + C; %Solved streamline equation.
% Now solve the eqn for y, and make it into a function of `x` and `C`
Y=matlabFunction(solve(eqn,y),'vars',{'x','C'})
for C = -10:0.1:10; %Loop. C is assigned a different value in each iteration.
plot(X,Y(X,C)); %Standard plot call, but using the function for `Y`
hold on;
end

Computing an ODE in Matlab

Given a system of the form y' = A*y(t) with solution y(t) = e^(tA)*y(0), where e^A is the matrix exponential (i.e. sum from n=0 to infinity of A^n/n!), how would I use matlab to compute the solution given the values of matrix A and the initial values for y?
That is, given A = [-2.1, 1.6; -3.1, 2.6], y(0) = [1;2], how would I solve for y(t) = [y1; y2] on t = [0:5] in matlab?
I try to use something like
t = 0:5
[y1; y2] = expm(A.*t).*[1;2]
and I'm finding errors in computing the multiplication due to dimensions not agreeing.
Please note that matrix exponential is defined for square matrices. Your attempt to multiply the attenuation coefs with the time vector doesn't give you what you'd want (which should be a 3D matrix that should be exponentiated slice by slice).
One of the simple ways would be this:
A = [-2.1, 1.6; -3.1, 2.6];
t = 0:5;
n = numel(t); %'number of samples'
y = NaN(2, n);
y(:,1) = [1;2];
for k =2:n
y(:,k) = expm(t(k)*A) * y(:,1);
end;
figure();
plot(t, y(1,:), t, y(2,:));
Please note that in MATLAB array are indexed from 1.

How do you plot nonlinear differential equations in matlab

Dx=y
Dy=-k*y-x^3+9.8*cos(t)
inits=('x(0)=0,y(0)=0')
these are the differential equations that I wanted to plot.
first, I tried to solve the differential equation and then plot the graph.
Dsolve('Dx=y','Dy=-k*y-x^3+9.8*cos(t)', inits)
like this, however, there was no explicit solution for this system.
now i am stuck :(
how can you plot this system without solving the equations?
First define the differential equation you want to solve. It needs to be a function that takes two arguments - the current time t and the current position x, and return a column vector. Instead of x and y, we'll use x(1) and x(2).
k = 1;
f = #(t,x) [x(2); -k * x(2) - x(1)^3 + 9.8 * cos(t)];
Define the timespan you want to solve over, and the initial condition:
tspan = [0, 10];
xinit = [0, 0];
Now solve the equation numerically using ode45:
ode45(f, tspan, xinit)
which results in this plot:
If you want to get the values of the solution at points in time, then just ask for some output arguments:
[t, y] = ode45(f, tspan, xinit);
You can plot the phase portrait x against y by doing
plot(y(:,1), y(:,2)), xlabel('x'), ylabel('y'), grid
which results in the following plot