Not enough input arguments for ode45 function - matlab

I am setting up a function that can solve the following differential equation for a laser system with the listed parameters. Whenever I run my code though, I keep getting errors that there are not enough input arguments for the equation (dydt). I am unsure where the fault in the code is occurring, but I believe it may have something to do with how I defined y. I expect to get a gaussian distribution in a plot, but the code keeps stopping at dydt. It does not process the variables. Thank you!
function dydt = 4_Lasers(t,y)
beta=1;
p0=10;
tau2=1e-7;
t = 1;
taupulse=tau2*100000;
taup=tau2/100;
p=p0*exp(-(t/taupulse)^2);
dydt = [(1/tau2)*(p-y(1)-y(1)*y(2)); (y(2)/taup)*
(y(1)-1)+beta*y(1)/tau2];
end
clear; close all;
[t,y] = ode45(#4_Lasers,[0 1e-6],[0; 0]);
plot(t,y(:,1),'r',t,y(:,2),'b')
title('p0=10,taupulse/tau2=1.5,tau2/taup=100');
xlabel('Time t');
ylabel('Amplitude');
legend('Photodensity','population inversion')

Cannot reproduce with this code:
clear; close all;
[t,y] = ode45(#Lasers,[0 1e-6],[0 0]);
plot(t,y(:,1),'r',t,y(:,2),'b')
title('p0=10,taupulse/tau2=1.5,tau2/taup=100');
xlabel('Time t');
ylabel('Amplitude');
legend('Photodensity','population inversion')
function dydt = Lasers(t,y)
beta=1;
p0=10;
tau2=1e-7;
t = 1;
taupulse=tau2*100000;
taup=tau2/100;
p=p0*exp(-(t/taupulse)^2);
dydt = [(1/tau2)*(p-y(1)-y(1)*y(2)); (y(2)/taup)*(y(1)-1)+beta*y(1)/tau2];
end

Related

How to solve Harmonic oscillator numerically?

I am trying to solve, using MATLAB, the time dependent Harmonic oscillator equation numerically. But I have no idea how to even get started as I have never learned this method in university:
X'' + w(t)^2 X = 0
with boundary conditions X_0 = 1, X_0' = 0 and Y_0 = 0, Y'_0 = 1
ode45 is a good start point.
Basic examples :
clear;close all;clc
tspan=[0 100]; % time
x_init=[5;0]; % known initial conditions
[t,y] = ode45(#vdp1,tspan,x_init);
figure(1)
plot(t,y(:,1),'r',t,y(:,2),'b')
grid on
title('Solution with ODE45');
xlabel('Time t');
ylabel('Solution y');
legend('y_1','y_2')
f=.5
[t,y] = ode45(#(t,y) vdp2(t,y,f),tspan,x_init);
figure(2)
plot(t,y(:,1),'r',t,y(:,2),'b')
grid on
title(['Solution with ODE45 and f = ' num2str(f)]);
xlabel('Time t');
ylabel('Solution y');
legend('y_1','y_2')
support functions:
function dydt = vdp1(t,y)
%
f=.1;
dydt = [y(2); sin(2*pi*f*t)*y(1)];
function dydt = vdp2(t,y,f)
%
dydt = [y(2); sin(2*pi*f*t)*y(1)];
This: https://uk.mathworks.com/matlabcentral/fileexchange/69951-runge-kutta-fixed-step-solvers?s_tid=srchtitle_harmonic%2520oscillator_81 among other examples has example1 solving damped and driven harmonic oscillators
And another harmonic oscillator solution with ODE solver:
https://uk.mathworks.com/matlabcentral/fileexchange/83233-matlab_program_solving_odes_harmonic_oscillators?s_tid=srchtitle_harmonic%20oscillator_9
You can also solve with symbolic expressions, this is Loren's post comparing symbolic and numerical solving
https://blogs.mathworks.com/loren/2010/04/08/odes-from-symbolic-to-numeric-code/?s_tid=srchtitle_harmonic%2520oscillator_105
I find the following concise introduction to ODE solving by Cleve Moler more useful than some full year university modules.
https://blogs.mathworks.com/cleve/2016/11/14/my-favorite-ode/?s_tid=srchtitle_harmonic%2520oscillator_131
When solving oscillators in polar coordinates you may need to have a look at
https://blogs.mathworks.com/cleve/2017/11/06/three-term-recurrence-relations-and-bessel-functions/?s_tid=srchtitle_harmonic%2520oscillator_140
In point 6 there's a wonderful introduction to Bessel functions and their zeros.

MATLAB ode45 OutputFcn to monitor changing value of if loop

I try to save/see my variable m that is changed by an if loop during an ode45 differential equation solving process.
%Some parameter setting above
myfun=fprintf('m', num2str(m))
options = odeset('NonNegative',[1:3],'RelTol',1e-5,'AbsTol',1e-8, 'OutputFcn', #myfun);
[t,x] = ode45('myfunction', tspan, x0, options); %calculation
the if loop is in the equation file before all the other equations follows:
if x(1)>=threshold
m=1 ;
return
else
m=0 ;
end
I already took a look at the matlab description for the OutputFcn Option for ode45 and also read
https://de.mathworks.com/help/deeplearning/ug/customize-output-during-deep-learning-training.html
without understanding it properly. I am also open to other solutions to "see" which value m during the ode calculation has.
Create a separate file, and call this myOutputFcn.m, with the following code
function status = myOutputFcn(t,y,flag,threshold)
switch(flag)
case 'init' % code to run before integration
;
case '' % code to run after each integration step
% act on state
if y(1)>=threshold
m = 1;
else
m = 0;
end
% print m
fprintf('% 4.3f\t%i, t, m\n',t,m);
case 'done' % code to run when integation is finished
;
end
status = 0; % need to set status, otherwise integration will halt
end
Then to call this output function every iteration with the right threshold, you will have to do the following
threshold = 10; % idk, your threshold
options = odeset('NonNegative',[1:3],'RelTol',1e-5,'AbsTol',1e-8, 'OutputFcn', #(t,y,flag) myOutputFcn(t,y,flag,threshold));
[t,x] = ode45('myfunction', tspan, x0, options); %calculation

How to generate a triangulation for FEM 1D - MATLAB?

I'm trying to plot Exact VS FEM solution for this equation:
with boundary condition:
I followed this code for example: Example Code
It's fine for its case, but in my case I don't know about how to get the triangulation (for my case) for this line:
x(1)=0; x(2)=0.1; x(3)=0.3; x(4)=0.333; x(5)=0.5; x(6)=0.75;x(7)=1;
Here is my code:
clear all; close all;
x(1)=0*pi; x(2)=0.1*pi; x(3)=0.3*pi; x(4)=0.333*pi; x(5)=0.5*pi; x(6)=0.75*pi;x(7)=1*pi;
U = fem1d(x);
x2 = 0:0.01:pi; k2 = length(x2);
for i=1:k2,
u_exact(i) = soln(x2(i));
u_fem(i) = fem_soln(x,U,x2(i));
end
error = norm(u_fem-u_exact,inf)
plot(x2,u_fem,':',x2,u_exact)
hold; plot(x,U,'o')
xlabel('x'); ylabel('u(x) & u_{fem}(x)');
title('Solid line: Exact solution, Dotted line: FEM solution')
figure(2); plot(x2,u_fem-u_exact); title('Error plot')
xlabel('x'); ylabel('u-u_{fem}'); title('Error plot')
How to generate the triangulation values? Does anyone know?
Thank you

How to display Matlab's ode45 results in real time?

Let's suppose that we have the following solver for a system of first-order ODEs:
% func.m
function dydt = func(t,y)
dydt = [y(2); (1-y(1)^2)*y(2)-y(1)];
and the main code:
% solver.m
tspan=0:1:10;
[t,y] = ode45(#func,tspan,[2; 0]);
How to display in real-time the results, y1(t) and y2(t), for each time step t that the ode45 makes (t=0,1,2,...,10), without waiting for the whole code to finish?
The OutputFcn ode solver option should be used. For example, to plot the solution vs time, the built-in output function odeplot can be used:
options= odeset('OutputFcn',#odeplot);
[t,y] = ode45(#func,[0 200],[2; 0],options);
You can use your own output function. Here is an example:
myOutputFcn= #(t,y,flag)fprintf('t= %s y= %s\n',mat2str(t),mat2str(y))*0;
options= odeset('OutputFcn',myOutputFcn);
[t,y] = ode45(#f,0:1:10,[2; 0],options);

Instead of creating two m.files in matlab when solving ODEs, how could I use anonymous functions to pass parameters?

i want these two files to combine into one m.file, instead of using function to define the "monod" with passing parameters, i want to use anonymous functions passing the parameters. So to achieve in combining both two files.
%(file 1)
function dcdt = monod(t,c,k,ks,y,b)
dcdt = zeros(2,1);
dcdt(1) = -k*c(2)*c(1)/(ks+c(1));
dcdt(2) = y*k*c(2)*c(1)/(ks+c(1))-b*c(2);
% (file 2) ODE45
k = 3.7;ks=30;y=0.03;b=0.01;
options = odeset('Reltol',1.e-10,'AbsTol',1.e-10);
[t,c] = ode45(#monod, [0,200],[200,1],options,k,ks,y,b);
% plot
C = c(:,1);
Xa = c(:,2);
figure(1);
grid on;
subplot(2,1,1);
plot(t,C);
title('Substrate aqueous concentration vs time(ODE45)');
xlabel('time');ylabel('Substrate aqueous concentration C')
subplot(2,1,2);
plot(t,Xa);
title('Active-cell concentration vs time');
xlabel('time');ylabel('Active-cell concentration Xa(ODE45)');
You can simply define a nested function within your file. Perfectly acceptable syntax. However, you will need to make File #2 an actual function as you can't define nested functions with a script file. To do this, just make it a function that accepts no inputs and returns nothing. :
function run_ode %// Change here
%// Include monod function here - watch the end keyword
function dcdt = monod(t,c,k,ks,y,b)
dcdt = zeros(2,1);
dcdt(1) = -k*c(2)*c(1)/(ks+c(1));
dcdt(2) = y*k*c(2)*c(1)/(ks+c(1))-b*c(2);
end %<----
%// Begin File #2
k = 3.7;ks=30;y=0.03;b=0.01;
options = odeset('Reltol',1.e-10,'AbsTol',1.e-10);
[t,c] = ode45(#monod, [0,200],[200,1],options,k,ks,y,b);
% plot
C = c(:,1);
Xa = c(:,2);
figure(1);
grid on;
subplot(2,1,1);
plot(t,C);
title('Substrate aqueous concentration vs time(ODE45)');
xlabel('time');ylabel('Substrate aqueous concentration C')
subplot(2,1,2);
plot(t,Xa);
title('Active-cell concentration vs time');
xlabel('time');ylabel('Active-cell concentration Xa(ODE45)');
end %// Take note of this end too as we now have nested functions
Copy and paste the above code into a file called run_ode.m, then in the MATLAB Command Prompt, type in run_ode and push ENTER.
>> run_ode
You should get your desired results.
Alternatively, if you want to make use of anonymous functions as referenced in your question title, you can do this instead:
%// Change here
monod = #(t,c,k,ks,y,b) [-k*c(2)*c(1)/(ks+c(1)); y*k*c(2)*c(1)/(ks+c(1))-b*c(2)];
k = 3.7;ks=30;y=0.03;b=0.01;
options = odeset('Reltol',1.e-10,'AbsTol',1.e-10);
[t,c] = ode45(monod, [0,200],[200,1],options,k,ks,y,b); %// Change here too
% plot
C = c(:,1);
Xa = c(:,2);
figure(1);
grid on;
subplot(2,1,1);
plot(t,C);
title('Substrate aqueous concentration vs time(ODE45)');
xlabel('time');ylabel('Substrate aqueous concentration C')
subplot(2,1,2);
plot(t,Xa);
title('Active-cell concentration vs time');
xlabel('time');ylabel('Active-cell concentration Xa(ODE45)');
monod is now an anonymous function that takes in the 6 inputs, and outputs a two element column vector for use in ode45. Take note that ode45 is now changed so that the # is removed. monod is now already a handle to an anonymous function and so using # is not required.