how to importing m-file with internal function to simulink? - matlab

my problem is some hard to describe, but I try to express in the best.
I have a model with a main file by the name 'main.m' with some codes.
in 'main.m' file I used ode45 to solve differential equations.
here's my 'main.m' codes:
[t,x]=ode45(#vdp,[0 100],[0 0 -15 0]);
subplot(2,1,1);
plot(t,x(:,1),'r-',t,x(:,3),'b-');
title('Positions');
legend('Loco','Wagon');
xlabel('Time');
ylabel('Distance');
grid;
subplot(2,1,2);
plot(t,x(:,2),'r-',t,x(:,4),'b-');
title('Velocities');
legend('Loco','Wagon');
xlabel('Time');
ylabel('Velocity');
grid;
as you know, with ode45 we need a function to describe the differential equations and for this, I used another file by the name of 'vdp.m'.
my 'vdp.m' codes: Note that my input is "u" variable and outputs are "dx(1),dx(2),dx(3),dx(4)"?
function dx = vdp(t,x)
%% Setting Parameters
c0 = 7.6658*10^-3; % unit = Nkg^-1
cv = 1.08*10^-4; % unit = Ns(mkg)^-1
ca = 2.06*10^-5; % unit = Ns^2(m^2 kg)^-1
m1 = 50000; % unit = kg
m2 = 48500; % unit = kg
k1 = 85*10^2; % unit = Nm^-1
d1 = 85*10^4; % unit = kgs^-1
% Force Input
u = 3000; % unit = N 48750
%u2 = 0;
teta1 = 0;
teta2 = 0;
D1 = 0;
D2 = 0;
% dx=zeros(6,1); % a column vector
%% Generate Control Input
if t>=0 && t<=10
a=0;
u1=u*a;
elseif t>10 && t<=15
a=1;
u1=u*a;
elseif t>15 && t<=55
a=50;
u1=u*a;
elseif t>55 && t<=75
a=-97;
u1=u*a;
else
a=0;
u1=u*a;
end
%% State Equations
% x1 -> position of loco
% x2 -> velocity of loco
% x3 -> position of wagon
% x4 -> velocity of wagon
if t>=0 && t<=10
dx(1)=0; dx(2)=0; dx(3)=0; dx(4)=0;
dx = [dx(1);dx(2);dx(3);dx(4)];
elseif t>10 && t<=75
dx(1)=x(2);
dx(2)=(1/m1)*(u1-k1*(x(1)-x(3))-d1*(x(2)-x(4))-(c0+cv*x(2))*m1- ...
ca*((x(2))^2)*(m1+m2)-9.98*(sin(teta1))*m1-0.004*D1*m1);
dx(3)=x(4);
dx(4)=(1/m2)*(-k1*(x(3)-x(1))-d1*(x(4)-x(2))-(c0+cv*x(4))*m2- ...
9.98*(sin(teta2))*m2-0.004*D2*m2);
dx = [dx(1);dx(2);dx(3);dx(4)];
else
dx(1)=0; dx(2)=0; dx(3)=0; dx(4)=0;
dx = [dx(1);dx(2);dx(3);dx(4)];
end
Now I wanna use 'main.m' file program as a block in Simulink, because this codes are describing my model behavior.
Is there any way to import 'main.m' file to a block and use the block within my simulink model or a way to combining both two m-file to one file and making a function for using MATLAB Function Block?
Thanks all :)

I don't believe that you really want to do what your question says you want to do. Your main.m file is equivalent to the Simulink user interface, i.e. the bit where the solver and model run time (amongst other things) is specified. It doesn't make sense to want to use it within Simulink.
However, your second block of code, vdp, where the model functionality is defined, can certainly be used within Simulink. It (at least superficially) looks as if it can be dropped directly into a model using the MATLAB Function block. You'd feed its output (i.e. xdot) directly into a Continuous Time Integrator block, then feed the output of the integrator (which will be x) back into the second input of the MATLAB Function block. You'd feed a Clock block into the first input of the MATLAB Function block.
Of course you could also implement the vdp functionality using Simulink blocks rather than within m-code.

Related

MATLAB's lsim() vs for-loop Simulation // Different results for the same system

I've spent quite some time trying to simulate a simple SISO system using two approaches:
1) Using lsim() in MATLAB
2) By writing down the difference equations myself and iterate over them in a loop.
I was never able to get the same simulation results from both approaches, and I have no idea what I am doing wrong.
I stacked my code in a single m-file so it's easier to follow. Here is the code:
function main()
clear all
clc
simulateUsing_lsim()
simulateUsing_loop()
end
%%%%%% Simulating using lsim %%%%%%%
function simulateUsing_lsim()
% Define the continuous-time closed-loop system
P = getContPlant();
[Kp,Ki,Kd] = get_PIDgains();
C = pid(Kp,Ki,Kd);
clSys_cont = feedback(C*P,1);
% Define the discrete-time closed-loop system
hk = get_sampling_time();
clSys_disc = c2d(clSys_cont,hk);
% Generate the reference signal and the time vector
[r,t] = getReference(hk);
%% Simulate and plot using lsim
figure
lsim(clSys_disc,r,t)
%% Finding and plotting the error
y = lsim(clSys_disc,r);
e = r - y;
figure
p = plot(t,e,'b--');
set(p,'linewidth',2)
legend('error')
xlabel('Time (seconds)')
ylabel('error')
% xlim([-.1 10.1])
end
%%%%%% Simulating using loop iteration (difference equations) %%%%%%%
function simulateUsing_loop()
% Get the cont-time ol-sys
P = getContPlant();
% Get the sampling time
hk = get_sampling_time();
% Get the disc-time ol-sys in SS representation
P_disc = ss(c2d(P,hk));
Ad = P_disc.A;
Bd = P_disc.B;
Cd = P_disc.C;
% Get the PID gains
[Kp,Ki,Kd] = get_PIDgains();
% Generate the reference signal and the time vector
[r,t] = getReference(hk);
%% Perform the system simulation
x = [0 0]'; % Set initial states
e = 0; % Set initial errors
integral_sum = 0; % Set initial integral part value
for i=2:1:length(t)
% Calculate the output signal "y"
y(:,i) = Cd*x;
% Calculate the error "e"
e(:,i) = y(:,i) - r(i);
% Calculate the control signal vector "u"
integral_sum = integral_sum + Ki*hk*e(i);
u(:,i) = Kp*e(i) + integral_sum + (1/hk)*Kd*(e(:,i)-e(:,i-1));
% Saturation. Limit the value of u withing the range [-tol tol]
% tol = 100;
% if abs(u(:,i)) > tol
% u(:,i) = tol * abs(u(:,i))/u(:,i);
% else
% end
% Calculate the state vector "x"
x = Ad*x + Bd*u(:,i); % State transitions to time n
end
%% Subplots
figure
plot(t,y,'b',t,r,'g--')
%% Plotting the error
figure
p = plot(t,e,'r');
set(p,'linewidth',2)
legend('error')
xlabel('Time (seconds)')
ylabel('error')
end
function P = getContPlant()
s = tf('s');
P = 1/(s^2 + 10*s + 20);
end
function [Kp,Ki,Kd] = get_PIDgains()
Kp = 350;
Ki = 300;
Kd = 50;
end
function hk = get_sampling_time()
hk = 0.01;
end
function [r,t] = getReference(hk)
[r,t] = gensig('square',4,10,hk);
end
I got the plant model P and its PID controller from this page (see equation 10), where the system is simulated against a step reference and the result looks pretty much exactly like the lsim() result (just for a single step peak).
However, the result of simulating the system using lsim() is this:
whereas, using the for loop, I got this performance:
I would highly appreciate any help or clarification why I am getting different results.

ode45 for Langevin equation

I have a question about the use of Matlab to compute solution of stochastic differentials equations. The equations are the 2.2a,b, page 3, in this paper (PDF).
My professor suggested using ode45 with a small time step, but the results do not match with those in the article. In particular the time series and the pdf. I also have a doubt about the definition of the white noise in the function.
Here the code for the integration function:
function dVdt = R_Lang( t,V )
global sigma lambda alpha
W1=sigma*randn(1,1);
W2=sigma*randn(1,1);
dVdt=[alpha*V(1)+lambda*V(1)^3+1/V(1)*0.5*sigma^2+W1;
sigma/V(1)*W2];
end
Main script:
clear variables
close all
global sigma lambda alpha
sigma=sqrt(2*0.0028);
alpha=3.81;
lambda=-5604;
tspan=[0,10];
options = odeset('RelTol',1E-6,'AbsTol',1E-6,'MaxStep',0.05);
A0=random('norm',0,0.5,[2,1]);
[t,L]=ode45(#(t,L) R_Lang(t,L),tspan,A0,options);
If you have any suggestions I'd be grateful.
Here the new code to confront my EM method and 'sde_euler'.
lambda = -5604;
sigma=sqrt(2*0.0028) ;
Rzero = 0.03; % problem parameters
phizero=-1;
dt=1e-5;
T = 0:dt:10;
N=length(T);
Xi1 = sigma*randn(1,N); % Gaussian Noise with variance=sigma^2
Xi2 = sigma*randn(1,N);
alpha=3.81;
Rem = zeros(1,N); % preallocate for efficiency
Rtemp = Rzero;
phiem = zeros(1,N); % preallocate for efficiency
phitemp = phizero;
for j = 1:N
Rtemp = Rtemp + dt*(alpha*Rtemp+lambda*Rtemp^3+sigma^2/(2*Rtemp)) + sigma*Xi1(j);
phitemp=phitemp+sigma/Rtemp*Xi2(j);
phiem(j)=phitemp;
Rem(j) = Rtemp;
end
f = #(t,V)[alpha*V(1)+lambda*V(1)^3+0.5*sigma^2/V(1)/2;
0]; % Drift function
g = #(t,V)[sigma;
sigma/V(1)]; % Diffusion function
A0 = [0.03;0]; % 2-by-1 initial condition
opts = sdeset('RandSeed',1,'SDEType','Ito'); % Set random seed, use Ito formulation
L = sde_euler(f,g,T,A0,opts);
plot(T,Rem,'r')
hold on
plot(T,L(:,1),'b')
Thanks again for the help !
ODEs and SDEs are very different and one should not use tools for ODEs, like ode45, to try to solve SDEs. Looking at the paper you linked to, they used a basic Euler-Maruyama scheme to integrate the system. This a very simple solver to implement yourself.
Before proceeding, you (and your professor!) should take some time to read up on SDEs and how to solve them numerically. I recommend this paper, which includes many Matlab examples:
Desmond J. Higham, 2001, An Algorithmic Introduction to Numerical Simulation of Stochastic Differential Equations, SIAM Rev. (Educ. Sect.), 43 525–46. http://dx.doi.org/10.1137/S0036144500378302
The URL to the Matlab files in the paper won't work; use this one. Note, that as this a 15-year old paper, some of the code related to random number generation is out of date (use rng(1) instead of randn('state',1) to seed the generator).
If you are familiar with ode45 you might look at my SDETools Matlab toolbox on GitHub. It was designed to be fast and has an interface that works very similarly to Matlab's ODE suite. Here is how you might code up your example using the Euler-Maruyma solver:
sigma = 1e-1*sqrt(2*0.0028);
lambda = -5604;
alpha = 3.81;
f = #(t,V)[alpha*V(1)+lambda*V(1)^3+0.5*sigma^2/V(1);
0]; % Drift function
g = #(t,V)[sigma;
sigma/V(1)]; % Diffusion function
dt = 1e-3; % Time step
t = 0:dt:10; % Time vector
A0 = [0.03;-2]; % 2-by-1 initial condition
opts = sdeset('RandSeed',1,'SDEType','Ito'); % Set random seed, use Ito formulation
L = sde_euler(f,g,t,A0,opts); % Integrate
figure;
subplot(211);
plot(t,L(:,2));
ylabel('\phi');
subplot(212);
plot(t,L(:,1));
ylabel('r');
xlabel('t');
I had to reduce the size of sigma or the noise was so large that it could cause the radius variable to go negative. I'm not sure if the paper discusses how they handle this singularity. You can try the 'NonNegative' option within sdeset to try to handle this or you may need to construct your own solver. I also couldn't find what integration time step the paper used. You should also consider contacting the authors of the paper directly.
UPDATE
Here's an Euler-Maruyama implementation that matches the sde_euler code above:
sigma = 1e-1*sqrt(2*0.0028);
lambda = -5604;
alpha = 3.81;
f = #(t,V)[alpha*V(1)+lambda*V(1)^3+0.5*sigma^2/V(1);
0]; % Drift function
g = #(t,V)[sigma;
sigma/V(1)]; % Diffusion function
dt = 1e-3; % Time step
t = 0:dt:10; % Time vector
A0 = [0.03;-2]; % 2-by-1 initial condition
% Create and initialize state vector (L here is transposed relative to sde_euler output)
lt = length(t);
n = length(A0);
L = zeros(n,lt);
L(:,1) = A0;
% Set seed and pre-calculate Wiener increments with order matching sde_euler
rng(1);
r = sqrt(dt)*randn(lt-1,n).';
% General Euler-Maruyama integration loop
for i = 1:lt-1
L(:,i+1) = L(:,i)+f(t(i),L(:,i))*dt+r(:,i).*g(t(i),L(:,i));
end
figure;
subplot(211);
plot(t,L(2,:));
ylabel('\phi');
subplot(212);
plot(t,L(1,:));
ylabel('r');
xlabel('t');

Can I use two separate ODE call functions for a system of two differential equations in MatLab?

I am trying to code a system of ODE's shown below.
As seen, the second ODE completely depends on the value of the first ODE.
How can I code the second ode?
I am using ode45.
Yes, that's quite possible. Define x as [c;ce], then you have something like:
function dx = my_ode(t,x)
% parameters definition
kf = ...; % whatever value you are using
P0 = ...; % whatever value you are using
Jer = ...; % whatever value you are using
J_serca = ...; % whatever value you are using
gamma = ...; % whatever value you are using
% differential equations
dc = (kf*P0+Jer)*(x(2)-x(1)) - J_serca;
dce = -gamma*dc;
dx = [dc;dce];
and then you can call the ode solver as:
tspan = [0 10]; % or whatever time interval you want to solve the odes on
x_init = [0;0]; % ot whatever initial conditions you want to use
[T,Y] = ode45(#my_ode,tspan,x_init);

Matlab plot in loop error

I am creating figures in a for loop. The figure is a 2D mesh plot, which is supposed to be updated every iteration. The value to be plotted in a 200x200 array.
My problem is: It seems the calculation is running every iteration, but the plot is always the first one created, no matter I just plot or save to file.
Here is my code:
x = 1:200;
y = x;
for i = 1:100000
c = calculate(stuff, c); % value to be created, nothing to do with x and y
h = figure;
mesh(x,y,c);
saveas(h, sprintf('FIG%d.jpg',i);
drawnow; % did not work with or without this command
close(h);
end
First, thank you for all your inputs and suggestions! I didn't expect to get so many help within such a short time!
Then, I can answer some of the confusions here.
To Daniel: yes the c is changing. The program is calculating c based on its previous value. And there is sufficient step for c to change.
To R.Schifini: I tried pause(.1) but it didn't help unfortunately
To Andrew: thanks for pointing it. The complete program is attached now. And as to Daniel, the program calculate the value of c based on its previous values.
To The-Duck: I tried clf(h, 'reset') but unfortunately it didn't help.
Complete code:
Main program: please refer to wikipedia for the physical equation if you are interested
http://en.wikipedia.org/wiki/Cahn%E2%80%93Hilliard_equation
% Program to calculate composition evolution for nucleation and growth
% by solving Cahn-Hilliard equation - Time dependent non-linear
% differential equation
% Parameter
sig = 0.1; % J/m^2
delta = 10E-9; % m
D = 1E-9; %m^2/s
A = 10*sig/delta; % J/m
K = 3*sig*delta; % J/m^3
M = D/(2*A); % m^2/s
N = 200; % mesh size
dt = 1E-12; %s
h = delta/10;
% Rng control
r = -1+2.*rand(N);
beta = 1E-3;
n = 10000;
% initialization
c0 = zeros(200);
c0 = c0+ 0.1+beta.*r;
c = c0;
x = h.*linspace(-N/2,N/2,N);
y=x;
% Iteration
for i = 1:n
LP_c = laplacian(c,h);
d_f = A*(4*(c.^3)-6*(c.^2)+2*c);
sub = d_f - (2*K)*LP_c;
LP_RHS = laplacian(sub,h);
RHS = M*LP_RHS;
c = c + dt.*RHS;
% Save image every 2000 steps
% if ( i==1000 || i==10000 || i==100000)
% h = mesh(x,y,c);
% pause(.1);
% saveas(h, sprintf('FIG%d.jpg',i));
% clf(h,'reset');
% end
end
%h = figure;
mesh(x,y,c);
Laplacian function:
function LP_c = laplacian(c,h)
v1 = circshift(c,[0 -1]);
v2 = circshift(c,[0 1]);
v3 = circshift(c,[-1 0]);
v4 = circshift(c,[1 0]);
LP_c = (v1+v2+v3+v4-4.*c)./(h^2);
end
Result:
You can see the commented part in main program is for plotting periodically. They all give the same plots for each iteration. I tried the current OR version, also tried if ( mod(i,2000) == 0) to plot more pics. There is no difference. Shown:
However, if I comment out the periodic plotting, just run the program for different values of n, I got different plots, and they obey physical laws (evolving structure), shown in time order
Therefore I excluded the possibility that c might not update itself. It has to be some misuse of the plotting function of matlab. Or maybe some memory issue?
An interesting point I discovered during edition session: If I put the command h = figure in front of the loop and plot after the loop end, like this:
h = figure;
% Iteration
for i = 1:n
LP_c = laplacian(c,h);
d_f = A*(4*(c.^3)-6*(c.^2)+2*c);
sub = d_f - (2*K)*LP_c;
LP_RHS = laplacian(sub,h);
RHS = M*LP_RHS;
c = c + dt.*RHS;
end
mesh(x,y,c);
It seems all value of c calculated during the loop will overlap and give a figure shown below: I guess this indicates some facts about the plotting function of matlab, but I am not sure
Btw, can I answer directly to each comment and high light the new added section in my post? Sorry I am not as familiar with Stack Overlow as I should have :)
I ran your routine and with the following changes it works for me:
% Iteration
for i = 1:n
LP_c = laplacian(c,h);
d_f = A*(4*(c.^3)-6*(c.^2)+2*c);
sub = d_f - (2*K)*LP_c;
LP_RHS = laplacian(sub,h);
RHS = M*LP_RHS;
c = c + dt.*RHS;
% Save image every 2000 steps
if ( mod(i,2000)==0)
h1 = mesh(x,y,c);
drawnow;
saveas(h1, sprintf('FIG%d.jpg',i));
end
end
The main change is the figure handle variable from h to h1. Why? You are already using variable h in your equations.
Regards,

Dimpulse Function in Matlab

Im working with Signals and i need to determine the impulse of a Discrete Signal using Matlab dimpulse function.
For some reason i dont have dimpulse function on my Matlab...
Does anyone knows if its really an Matlab function or a custom made function? if its an Matlab one which toolbox is it?
i tried the commands which dimpulse and it says it doesn't find it....I need this function for Discret Signals...
I´m running Matlab 2012b on a Mac if that helps ...
Thanks ...
Dimpulse is not an official Matlab function. However, Google turned up a few universities that have written the function, such as here:
function [yout,x,n] = dimpulse(a,b,c,d,iu,n)
%DIMPULSE Impulse response of discrete-time linear systems.
% DIMPULSE(A,B,C,D,IU) plots the response of the discrete system:
%
% x[n+1] = Ax[n] + Bu[n]
% y[n] = Cx[n] + Du[n]
%
% to an unit sample applied to the inputs IU. The number of
% points is determined automatically.
%
% DIMPULSE(NUM,DEN) plots the impulse response of the polynomial
% transfer function G(z) = NUM(z)/DEN(z) where NUM and DEN contain
% the polynomial coefficients in descending powers of z.
%
% DIMPULSE(A,B,C,D,IU,N) or DIMPULSE(NUM,DEN,N) uses the user-
% supplied number of points, N. When invoked with left hand
% arguments,
% [Y,X] = DIMPULSE(A,B,C,D,...)
% [Y,X] = DIMPULSE(NUM,DEN,...)
% returns the output and state time history in the matrices Y and X.
% No plot is drawn on the screen. Y has as many columns as there
% are outputs and X has as many columns as there are states.
%
% See also IMPULSE, STEP, INITIAL, LSIM.
% J.N. Little 4-21-85
% Revised CMT 7-31-90, ACWG 5-30-91, AFP 10-1-94
% Copyright 1986-2002 The MathWorks, Inc.
% $Revision: 1.15 $ $Date: 2002/04/04 15:15:36 $
%warning(['This calling syntax for ' mfilename ...
% ' will not be supported in the future: use IMPULSE(SYS,...) instead.'])
ni = nargin;
no = nargout;
if ni==0,
eval('exresp(''dimpulse'')')
return
end
error(nargchk(2,6,ni))
Ts = -1;
% Determine which syntax is being used
switch ni
case 2
if size(a,1)>1,
% SIMO syntax
a = num2cell(a,2);
den = b;
b = cell(size(a,1),1);
b(:) = {den};
end
sys = tf(a,b,Ts);
n = [];
case 3
% Transfer function form with time vector
if size(a,1)>1,
% SIMO syntax
a = num2cell(a,2);
den = b;
b = cell(size(a,1),1);
b(:) = {den};
end
sys = tf(a,b,Ts);
n = c;
case 4
% State space system without iu or time vector
sys = ss(a,b,c,d,Ts);
n = [];
otherwise
% State space system, with iu but w/o time vector
if min(size(iu))>1,
error('IU must be a vector.');
elseif isempty(iu),
iu = 1:size(d,2);
end
sys = ss(a,b(:,iu),c,d(:,iu),Ts);
if ni<6,
n = [];
end
end
if no==1,
yout = impulse(sys,n);
yout = yout(:,:);
elseif no>1,
[yout,t,x] = impulse(sys,n);
yout = yout(:,:);
x = x(:,:);
n = length(t);
else
impulse(sys,n)
end
% end dimpulse