I have a simple function as below:
function dz = statespace(t,z)
dz = A*z + B*k*z
end
My main script is :
clear all;close all;format short;clc;
% step 1 -- input system parameters
% structure data
M1 = 1; M2= 1; M3= 1; %Lumped Mass(Tons)
M= diag([M1,M2,M3]);
k(1)= 980; k(2)= 980; k(3)= 980; %Stiffness Coefficient(KN/M)
K = zeros(3,3);
for i=1:2
K(i,i)=k(i)+k(i+1);
end
K(3,3)=k(3);
for i=1:2
K(i,i+1)=-k(i+1);
end
for i=2:3
K(i,i-1)=-k(i);
end %Stiffness Matrix(KN/M)
c(1)= 1.407; c(2)= 1.407; c(3)= 1.407; %Damping Coefficient(KN.sec/M)
C = zeros(3,3);
for i=1:2
C(i,i)=c(i)+c(i+1);
end
C(3,3)=c(3);
for i=1:2
C(i,i+1)=-c(i+1);
end
for i=2:3
C(i,i-1)=-c(i);
end %Damping Matrix(KN.sec/M)
A = [zeros(3) eye(3);-inv(M)*K -inv(M)*C]
H = [1;0;0]
B = [0;0;0;inv(M)*H]
k = [-1 -1 -1 -1 -1 -1]
t = 0:0.004:10;
[t,z] = ode45(statespace,t);
When I run my main script it comes with following error:
Undefined function or variable 'A'.
Error in statespace (line 2)
dz = A*z + B*k*z
As you can see I defined A in main script. Why this problem happening?
There multiple things wrong with your code. First, you need to supply the values of A and B to your function but as you are invoking it (incorrectly without the # and additional parameter y0 as I commented below) in the toolbox ode45, you have to keep just two parameters so you cannot supply A and B as additional parameters. If you define A and B within your function or share them via global variables you will get further. However, as noted below the definitions don't seem to be correct as A * z and B * k * z don't have the same dimensions. z is a scalar so B * k needs to be same size and shape as A which currently it is not.
Edit from:
As Jubobs suggested change your function's parameters to include A, B and k. Also you don't need t as it is never used in the function. So:
function dz = statespace(A, B, k, z)
dz = A*z + B*k*z
end
As others have pointed out, A, B and k are not defined in the function workspace, so you either need to define them again (ugly, not recommended), declare them as global variables (slightly better, but still not good practice), or pass them as arguments to your function (the better solution). However, because you then want to use the function with ode45, you need to be a bit careful with how you do it:
function dz = statespace(t,z,A,B,k)
dz = A*z + B*k*z
end
and then the call to ode45 would like this:
[t,z] = ode45(#(t,z)statespace(t,z,A,B,k),[0 Tf],z0); % where Tf is your final time and z0 your initial conditions
See Error using ode45 and deval for a similar problem.
Related
I have a pulse shape that is a function of t, call it h(t), that is in the form of:
h = #(t) function of t
I want to create a pulse train that is consisted of N pulses h(t).
I did this by:
for n=0:N-1
comb = comb + h(t - n);
end
However, once I do that I can't change t in the train.
How can I create this train so that it will also be a function of t?
Thanks.
You just need to make comb an anonymous function too. You can initialise it to some trivial function (i.e. it always outputs 0), and then repeatedly modify it. Since variables declared before an anonymous function declaration, including anonymous functions, are kind of "frozen" to the definition at that point this will work.
h = #(t) _______ % some function of 't'
comb = #(t) 0;
for n = 0:N-1
comb = #(t) comb(t) + h(t - n);
end
We can test this with h = #(t) sin(t) and N=3:
>> comb(pi/2)
ans = 1.1242
>> h(pi/2) + h(pi/2-1) + h(pi/2-2)
ans = 1.1242
Note that just displaying comb can be a bit misleading, since information about the recursive definition is somewhat lost
disp(comb)
#(t)comb(t)+h(t-n)
I have a differential equation that is as follows:
%d/dt [x;y] = [m11 m12;m11 m12][x;y]
mat = #(t) sin(cos(w*t))
m11 = mat(t) + 5 ;
m12 = 5;
m21 = -m12 ;
m22 = -m11 ;
So I have that my matrix is specifically dependent on t. For some reason, I am having a super difficult time solving this with ode45. My thoughts were to do as follows ( I want to solve for x,y at a time T that was defined):
t = linspace(0,T,100) ; % Arbitrary 100
x0 = (1 0); %Init cond
[tf,xf] = ode45(#ddt,t,x0)
function xprime = ddt(t,x)
ddt = [m11*x(1)+m12*x(2) ; m12*x(1)+m12*x(2) ]
end
The first error I get is that
Undefined function or variable 'M11'.
Is there a cleaner way I could be doing this ?
I'm assuming you're running this within a script, which means that your function ddt is a local function instead of a nested function. That means it doesn't have access to your matrix variables m11, etc. Another issue is that you will want to be evaluating your matrix variables at the specific value of t within ddt, which your current code doesn't do.
Here's an alternative way to set things up that should work for you:
% Define constants:
w = 1;
T = 10;
t = linspace(0, T, 100);
x0 = [1 0];
% Define anonymous functions:
fcn = #(t) sin(cos(w*t));
M = {#(t) fcn(t)+5, 5; -5 #(t) -fcn(t)-5};
ddt = #(t, x) [M{1, 1}(t)*x(1)+M{2, 1}*x(2); M{1, 2}*x(1)+M{2, 2}(t)*x(2)];
% Solve equations:
[tf, xf] = ode45(ddt, t, x0);
One glaring error is that the return value of function ddt is xprime, not ddt. Then as mentioned in the previous answer, mm1 at the time of definition should give an error as t is not defined. But even if there is a t value available at definition, it is not the same t the procedure ddt is called with.
mat = #(t) sin(cos(w*t))
function xprime = ddt(t,x)
a = mat(t) + 5 ;
b = 5;
ddt = [ a, b; -b, -a]*x
end
should work also as inner procedure.
I have an ODE to be integrated with ode113. Inside the function that describes the derivatives I compute some variables that I would like to "save" (either store into a file or into an array). How can I do that?
Here is an example (adapted from the documentation). Run the following script:
global number_of_calls
number_of_calls = 0;
[t, y] = ode113(#myfunc, [0 10], 0);
plot(t,y,'-o')
fprintf('Number of calls of ''myfunc'': %d\n', number_of_calls)
fprintf('Number of elements of ''t'' : %d\n', length(t))
which calls the function containing the ODE to be integrated:
function dydt = myfunc(t, y)
global number_of_calls
dydt = 2*t;
a = 2*y; % <--- how can I save a?
number_of_calls = number_of_calls + 1;
end
I thought of writing to file the values of a from inside myfunc, but as you can see myfunc is called multiple times before actually storing the current value for the independent variable, t, and in the end I would have two arrays a and t of different size.
Here's one way you can write myfunc to do this. It saves the results to a global vector a, which must be set to [] before each call to ode113. It uses a persistent variable to keep track of the previous time step:
function dydt = myfunc(t, y)
dydt = 2*t;
temp = 2*y; % Extra value to save
global a
persistent tPrevious
if isempty(a) % Initialize
a = temp;
elseif (t > tPrevious) % Moving to a new time step, so add an element
a = [a; temp];
else % Refining time step downwards or recomputing at the same time step
a(end) = temp;
end
tPrevious = t; % Store prior time step
end
And you can check that it's working like so:
global a;
a = [];
[t, y] = ode113(#myfunc, [0 10], 0);
isequal(2.*y, a)
ans =
logical
1 % a exactly equals 2.*y
I am trying to compute the value of this integral using Matlab
Here the other parameters have been defined or computed in the earlier part of the program as follows
N = 2;
sigma = [0.01 0.1];
l = [15];
meu = 4*pi*10^(-7);
f = logspace ( 1, 6, 500);
w=2*pi.*f;
for j = 1 : length(f)
q2(j)= sqrt(sqrt(-1)*2*pi*f(j)*meu*sigma(2));
q1(j)= sqrt(sqrt(-1)*2*pi*f(j)*meu*sigma(1));
C2(j)= 1/(q2(j));
C1(j)= (q1(j)*C2(j) + tanh(q1(j)*l))/(q1(j)*(1+q1(j)*C2(j)*tanh(q1(j)*l)));
Z(j) = sqrt(-1)*2*pi*f(j)*C1(j);
Apprho(j) = meu*(1/(2*pi*f(j))*(abs(Z(j))^2));
Phi(j) = atan(imag(Z(j))/real(Z(j)));
end
%integration part
c1=w./(2*pi);
rho0=1;
fun = #(x) log(Apprho(x)/rho0)/(x.^2-w^2);
c2= integral(fun,0,Inf);
phin=pi/4-c1.*c2;
I am getting an error like this
could anyone help and tell me where i am going wrong.thanks in advance
Define Apprho in a separate *.m function file, instead of storing it in an array:
function [ result ] = Apprho(x)
%
% Calculate f and Z based on input argument x
%
% ...
%
meu = 4*pi*10^(-7);
result = meu*(1/(2*pi*f)*(abs(Z)^2));
end
How you calculate f and Z is up to you.
MATLAB's integral works by calling the function (in this case, Apprho) repeatedly at many different x values. The x values called by integral don't necessarily correspond to the 1: length(f) values used in your original code, which is why you received errors.
Here's the simpson function
%Simpsons 1/3 rule
function y = simpson(f,x1,x2,n)
global h
%global x1
%global x2
%h = (x2-x1)/n;
x(1) = x1;
sum = f(x1);
for i=2:n+1
x(i)=x(i-1)+h;
if mod(i,2)==0
sum=sum+4*f(x(i));
else
sum=sum+2*f(x(i));
end
end
sum = sum + f(x2);
int = sum*h/3;
disp(int);
end
here's the code in which i'm caliing:
CAo = 0.0625;
x1=0;
x2=0.8;
h=0.2;
n=(x2-x1)/h;
ep=2;
f=inline('(1+2*x)/((1-x)*0.0625)');
y = simpson(f,x1,x1,n);
disp(y)
On running the code, it's giving this error:
In an assignment A(I) = B, the number
of elements in B and I must be the
same.
Error in simpson (line 12)
x(i)=x(i-1)+h;
Error in tut_4_1 (line 8)
y = simpson(f,x1,x1,n);
i tried debugging, it showed my h is of 0 and my x(i-1) is 1X1. How to solve this. ?
The problem is the following line of code:
global h;
This deals with the scope of h. The global keyword only affects the variable h during the lifetime of the function. If you set h in the command window, then try to run Simpson's rule, the scope of h is different than what is seen in the function itself. In fact, the variable h in file is NOT the same as what is seen in the command window.
You also have a mistake in your function. You are returning y, but the output is stored in int. You need to change this to y.
As such, there are two ways for you to fix this:
Place the actual code for calling Simpson's rule inside a function, and the Simpson's rule code as a nested function itself. You would need to remove the call to global h and place it outside of the Simpson's rule code. Something like this:
function [] = test_simpsons()
global h;
function y = simpson(f,x1,x2,n)
x(1) = x1;
sum = f(x1);
for i=2:n+1
x(i)=x(i-1)+h;
if mod(i,2)==0
sum=sum+4*f(x(i));
else
sum=sum+2*f(x(i));
end
end
sum = sum + f(x2);
y = sum*h/3;
end
CAo = 0.0625;
x1=0;
x2=0.8;
h=0.2;
n=(x2-x1)/h;
ep=2;
f=inline('(1+2*x)/((1-x)*0.0625)');
y = simpson(f,x1,x1,n);
disp(y);
end
You would then call test_simpsons.
This is the approach I recommend. Simply make h an input parameter to your Simpson's rule code:
%Simpsons 1/3 rule
function y = simpson(f,x1,x2,n,h)
x(1) = x1;
sum = f(x1);
for i=2:n+1
x(i)=x(i-1)+h;
if mod(i,2)==0
sum=sum+4*f(x(i));
else
sum=sum+2*f(x(i));
end
end
sum = sum + f(x2);
y = sum*h/3;
end
The way you'd call your testing code is now:
CAo = 0.0625;
x1=0;
x2=0.8;
h=0.2;
n=(x2-x1)/h;
ep=2;
f=inline('(1+2*x)/((1-x)*0.0625)');
y = simpson(f,x1,x1,n,h);
disp(y)