Strange error when trying to compute cotangent - matlab

I'm new to MATLAB, and I'm trying to make sense of some scripts I have. In one, I have an expression for computing short-circuit impedance (within the context of other expressions):
Z=tan(2*p*f*d/vp)
That's fine and dandy, but when I want to change from tangent to the negative cotangent (for an open-circuit) like this:
Z=-1/tan(2*p*f*d/vp)
It gives me an error at that line as follows:
?? Error using ==> mldivide
Matrix dimensions must agree
Now, AFAIK none of the subexpressions in computing Z are matrices. What makes it more confusing is that if I change 1/tan with cot then it works (independently of whether I add a - sign in front of it or not):
Z=-cot(2*p*f*d/vp)
Any ideas? I've done my googling on the mldivide error, but I just don't see how that applies to computing the cotangent as literally the inverse of the tangent.
Am I missing a MATLAB peculiarity here? Thanks.
-- EDIT --
I think I should have included the entire source code (originally for calculating input impedance for a short-circuit line, and attempted a chance from tan to -cot for an open-circuit line)
close all; % close all opened graphs
figure; % open new graph
% define distributed line parameters
L=209.410e-9; % line inductance in H/m
C=119.510e-12; % line capacitance in F/m
vp=1/sqrt(L*C); % phase velocity
Z0=sqrt(L/C); % characteristic line impedance
d=0.1; % line length
N=5000; % number of sampling points
f=1e9+3e9*(0:N)/N; % set frequency range
%Z=tan(2*pi*f*d/vp); % short circuit impedance
Z= -1/tan(2*pi*f*d/vp); % open circuit impedance
plot(f/1e9,abs(Z0*Z));
title('Input impedance of a short-circuit transmission line');
xlabel('Frequency {\itf}, GHz');
ylabel('Input impedance |Z|, {\Omega}');
axis([1 4 0 500]);
% print -deps 'fig2_28.eps' % if uncommented -> saves a copy of plot in EPS format

I guess one of p, f, or d is a matrix, so tan(2*p*f*d/vp) will be a matrix as well. 1/matrix won't work because that is defined to be the inverse of a matrix multiplication, where you have restrictions to the dimensions of your matrices.
Try
Z=-1./tan(2*p*f*d/vp)
This is the element-wise division. (I assume that's what you want.)

That code works fine so long as p, f, d and vp are all scalar. Therefore, one of your inputs must be non-scalar.

The / sign is matrix division (i.e. multiplication by the inverse from the right), which needs same-sized arrays. Normally, all works well with scalars, but sometimes, the interpreter will cough so that you have to use ./, i.e. element-wise division, instead.

>> p = 0.1;
>> f = 0.2;
>> d = 0.01;
>> vp =0.2;
>> Z=-1/tan(2*p*f*d/vp)
Z =
-499.9993
It would seem that you are passing a matrix as Matlab tells you.

Related

spline interpolation and its (exact) derivatives

Suppose I have the following data and commands:
clc;clear;
t = [0:0.1:1];
t_new = [0:0.01:1];
y = [1,2,1,3,2,2,4,5,6,1,0];
p = interp1(t,y,t_new,'spline');
plot(t,y,'o',t_new,p)
You can see they work quite fine, in the sense interpolating function matches the data points at the nodes fine. But my problem is, I need to compute the exact derivative of y (i.e., p function) w.r.t. time and plot it against the t vector. How can it be done? I shall not use diff commands, because I need to make sure the derivative function has the same length as t vector. Thanks a lot.
Method A: Using the derivative
This method calculates the actual derivative of the polynomial. If you have the curve fitting toolbox you can use:
% calculate the polynominal
pp = interp1(t,y,'spline','pp')
% take the first order derivative of it
pp_der=fnder(pp,1);
% evaluate the derivative at points t (or any other points you wish)
slopes=ppval(pp_der,t);
If you don't have the curve fitting toolbox you can replace the fnderline with:
% piece-wise polynomial
[breaks,coefs,l,k,d] = unmkpp(pp);
% get its derivative
pp_der = mkpp(breaks,repmat(k-1:-1:1,d*l,1).*coefs(:,1:k-1),d);
Source: This mathworks question. Thanks to m7913d for linking it.
Appendix:
Note that
p = interp1(t,y,t_new,'spline');
is a shortcut for
% get the polynomial
pp = interp1(t,y,'spline','pp');
% get the height of the polynomial at query points t_new
p=ppval(pp,t_new);
To get the derivative we obviously need the polynomial and can't just work with the new interpolated points. To avoid interpolating the points twice which can take quite long for a lot of data, you should replace the shortcut with the longer version. So a fully working example that includes your code example would be:
t = [0:0.1:1];
t_new = [0:0.01:1];
y = [1,2,1,3,2,2,4,5,6,1,0];
% fit a polynomial
pp = interp1(t,y,'spline','pp');
% get the height of the polynomial at query points t_new
p=ppval(pp,t_new);
% plot the new interpolated curve
plot(t,y,'o',t_new,p)
% piece-wise polynomial
[breaks,coefs,l,k,d] = unmkpp(pp);
% get its derivative
pp_der = mkpp(breaks,repmat(k-1:-1:1,d*l,1).*coefs(:,1:k-1),d);
% evaluate the derivative at points t (or any other points you wish)
slopes=ppval(pp_der,t);
Method B: Using finite differences
A derivative of a continuous function is at its base just the difference of f(x) to f(x+infinitesimal difference) divided by said infinitesimal difference.
In matlab, eps is the smallest difference possible with a double precision. Therefore after each t_new we add a second point which is eps larger and interpolate y for the new points. Then the difference between each point and it's +eps pair divided by eps gives the derivative.
The problem is that if we work with such small differences the precision of the output derivatives is severely limited, meaning it can only have integer values. Therefore we add values slightly larger than eps to allow for higher precisions.
% how many floating points the derivatives can have
precision = 10;
% add after each t_new a second point with +eps difference
t_eps=[t_new; t_new+eps*precision];
t_eps=t_eps(:).';
% interpolate with those points and get the differences between them
differences = diff(interp1(t,y,t_eps,'spline'));
% delete all differences wich are not between t_new and t_new + eps
differences(2:2:end)=[];
% get the derivatives of each point
slopes = differences./(eps*precision);
You can of course replace t_new with t (or any other time you want to get the differential of) if you want to get the derivatives at the old points.
This method is slightly inferior to method a) in your case, as it is slower and a bit less precise. But maybe it's useful to somebody else who is in a different situation.

MATLAB: Residual error in Cramer's rule

I am quite familiar with Cramer's rule and I know why it is "useless". However, I got curious when the residual using the code below gives something like xxxxE-016 where xxxx represent numbers. I have tried the code below with 3 to 10 matrix sizes of floating system of linear equation.
Why is the residual error minimal?
Am I missing the right syntax for disp(['norm of Cramer's rule residual = ' num2str(norm(A*x-b),4)]) in the code for getting such minimal error?
The code I provided is working perfectly, only doubting the syntax I used for the norm
function x=cramerr(A,b)
A=input('matrix A =');
b=input('vector b =');
n=size(A,1);
m=size(A,2);
tic;
if n~=m
Error ('The matrix is not square!');
x=[];
else
detA=det(A);
if det(A)~=0
x=zeros(n,1);
for j=1:n
if j~=1 & j~=n
Ab=[A(:,1:j-1) b A(:,j+1:n)];
elseif j==1
Ab=[b A(:,2:n)];
elseif j==n
Ab=[A(:,1:n-1) b];
end
x(j)=det(Ab)/detA;
end %for j=1:n
else
Error('The matrix A has a zero determinant');
x=[];
end % if det(A)~=0
toc;
disp(['norm of Cramer's rule residual = ' num2str(norm(A*x-b),4)]);
end % if n~=m
Please you can use this as an example
A =[0.373,0.296;0.326,0.260];
b =[0.521;0.456];
Thanks
I wouldn't say this is a problem per se. What you do when you use Cramer's rule is solve the linear system of equations. In Matlab, you can simply do that with x=inv(A)*b, which uses a different algorithm to calculate the inverse (LU decomposition). In the Matlab page on Inverses and Determinants it says:
If A is square and nonsingular, the equations AX = I and XA = I have
the same solution, X. This solution is called the inverse of A, is
denoted by A-1, and is computed by the function inv. The determinant
of a matrix is useful in theoretical considerations and some types of
symbolic computation, but its scaling and round-off error properties
make it far less satisfactory for numeric computation. Nevertheless,
the function det computes the determinant of a square matrix.
If you want to check the precision of both you could do this:
format long
built_in=inv(A)*b
own_function=r(A,b)
and compare the results. What I got was:
built_in= [1.000000000000000;0.500000000000000]
own_function= [1.000000000000054;0.500000000000000]
You can see where the small norm comes from. With this in mind such an error is most likely due to rounding off errors.
As for the formatting of disp(['norm of Cramer's rule residual = ' num2str(norm(A*x-b),4)]) I would skip the apostrophe (') in Cramer's as this will cause errors.

Simple script that computes a solution of linear ODEs giving wrong result

this a question that envolves both programming and mathematics. So, I'm trying to write a code that computes the general solution of a system of linear ODEs described by . The mathematical formula it's shown above:
where the greek symbol \PHI that appers in the equation is the expm(A*t)
clear all
A=[-2]; %system matrix
t0=1; %initial time of simulation
tf=2; %final time of simulation
syms t x_0
x0=x_0;
hom=expm(A*t); %hom means "homogeneous solution"
hom_initialcond=hom*x0;%this is the homogeneous solution multiplied by the initial conditon
invhom=inv(hom); %this is the inverse of the greek letter at which, multiplied by the input of the system, composes the integrand of the integral
g=5*cos(2*t); %system input
integrand=invhom*g; %computation of the integrand
integral=int(integrand,t0,t); %computation of the definite integral from t0 to t, as shown by the math formula
partsol=hom*integral; %this is the particular solution
gen_sol=partsol+hom_initialcond %this is the general solution
x_0=1; %this is the initial condition
t=linspace(t0,tf); %vector of time from t0 to tf
y=double(subs(gen_sol)); %here I am evaluating my symbolic expression
plot(t,y)
The problem is that my plot of the ODE's solution it's not looking well, as you can see:
The solution it's wrong because the curve shown in the graph doesnt start at the initial value equals 1. But the shape it's very similar from the plot gave by the MATLAB ODE solver:
However, if I set t0=0 then the plot gave by my code and by MATLAB solver it's exacly equal to each other. So, my code it's fine for t0=0 but with any other values my code goes wrong.
The general solution in terms of fundamental matrices is
or more often seen as
But since the initial time is often taken to be zero, the inverse of the fundamental matrix is often omitted since it is the identity for linear, constant coefficient problems at zero (i.e., expm(zeros(n)) == eye(n)) and the c vector is equivalent to the initial condition vector.
Swapping some of the lines around near your symbolic declaration to this
syms t x_0 c_0
hom = expm(A*t) ;
invhom = inv(hom) ;
invhom_0 = subs(invhom,t,sym(t0)) ;
c_0 = invhom_0 * x_0 ;
hom_initialcond = hom * c_0 ;
should provide the correct solution for non-zero initial time.

Matlab: Differential equation (ode45): Can I reverse tspan for better initial conditions?

I'm using ode45 to solve/plot a second-order differential equation in Matlab. My tspan is from 0 to 0.25. But the initial conditions near zero are ill-defined (slope goes to infinity, complex values). The conditions near 0.25 are well defined (both slope and value are zero).
Questions:
Can I reverse tspan, and use the "final conditions" as initial conditions?
Well, I know I can do it (see code below), and I get a plot that looks like what I expect, but is this a valid thing to do in general? Am I getting lucky in this one case?
ode45 provides numerical solutions and is not exact. Am I likely to have larger error after reversing tspan?
Here's my code, which should run standalone:
function ReverseTspan()
% solve diff-eq backward from tspan end to tspan start using ode45()
% - Good initial conditions at the end, but not start.
% - Is this a valid thing to do?
% clean slate
clc; clear all; close all;
% tspan - reversed!
R = 0.25:-0.001:0;
% initial values
hinits=[0.0000001;0];
% solve
[R,v] = ode45(#equ7,R,hinits);
% strip imaginary values (can't plot 'em)
v(find(real(v)~=v)) = NaN;
% plot first column
plot(R,v(:,1));
function vprime = equ7(R,v);
% Solve second order non-linear differential equation 7:
% v''(R) + 2/R*v'(R) = K_plus/(R^2)*( v^(-1/2) - lamda_plus*(1-v)^(-1/2)
%
% Matlab ode45 only likes first derivatives, so let:
% v_1(R) = v(R)
% v_2(R) = v'(R)
%
% And create a system of first order diff eqs:
% v_1'(R) = v_2(R)
% v_2'(R) = -2/R*v_2(R) + K_plus/(R^2)*( v_1(R)^(-1/2) - lamda_plus*(1-v_1(R))^(-1/2)
%
% Constant Parameters:
K_plus = 0.0859;
lambda_plus = 3.7;
% Build result in pieces for easier debugging of problematic terms
int1 = 1 - v(1);
int2 = int1^(-1/2);
int3 = v(1)^(-1/2);
int4 = K_plus/(R^2);
vprime2 = -2/R*v(2);
vprime2 = vprime2 + int4*( int3 - lambda_plus*(int2) );
vprime=[v(2); vprime2 ];
Numerically, you're never going to be able to start at (or get to) R=0 with that ODE. NaN will be returned for the first step after your initial condition, thus corrupting any future results. It might be possible to rescale your system to get rid of the singularity, but that's a mathematics issue. You could also try starting your integration at a time just a bit larger than zero, provided you specify initial conditions that are valid (satisfy your ODE).
Can I reverse tspan, and use the "final conditions" as initial conditions?
Yes. This is a standard procedure. In particular, it's often used to find unstable manifolds and unstable equilibria.
Well, I know I can do it (see code below), and I get a plot that looks like what I expect, but is this a valid thing to do in general? Am I getting lucky in this one case?
It's hard to generalize across all possible systems. There are likely cases where this won't work for reasons of stability or numerical error.
ode45 provides numerical solutions and is not exact. Am I likely to have larger error after reversing tspan?
I can't see why it would necessarily be larger, but again this will depend on the system and solver used. Try using other solvers (e.g., ode15s or ode113) and/or varying the absolute and relative tolerances via odeset.

Octave equivalent of MATLAB ltitr.m function

I am trying to get some MATLAB scripts to run in Octave, but have a problem with the following line of code:
x = ltitr( a, b, u, x0 ) ;
which throws an error in Octave.
Online research shows that the ltitr function is an internal MATLAB function that returns the Linear time-invariant time response kernel for the given inputs. This sounds as if it should be a common DSP requirement, so I feel that this must be implemented directly in Octave, or in the latest Control package from Source Forge. However, I can't seem to find an Octave equivalent. I've read the documentation for the latest Octave Control package and maybe I should be using the functions lsim.m or ss.m or dss.m or impulse.m but I'm not really sure.
Can anyone enlighten me? If it's not implemented in Octave, maybe some online reference to code that I could use to write my own ltitr function?
If you actually type in help ltitr in the MATLAB command prompt, you come up with this documentation:
%LTITR Linear time-invariant time response kernel.
%
% X = LTITR(A,B,U) calculates the time response of the
% system:
% x[n+1] = Ax[n] + Bu[n]
%
% to input sequence U. The matrix U must have as many columns as
% there are inputs u. Each row of U corresponds to a new time
% point. LTITR returns a matrix X with as many columns as the
% number of states x, and with as many rows as in U.
%
% LTITR(A,B,U,X0) can be used if initial conditions exist.
% Here is what it implements, in high speed:
%
% for i=1:n
% x(:,i) = x0;
% x0 = a * x0 + b * u(i,:).';
% end
% x = x.';
% Copyright 1984-2007 The MathWorks, Inc.
% $Revision: 1.1.6.4 $ $Date: 2007/05/23 18:54:41 $
% built-in function
As such, they pretty much already give you the code for it. However, I'm assuming that this is written in MEX and so that's why it's built-in and is super fast. As such, if you want to port this over to Octave, you just have to use the code they reference above. It won't be as fast as MATLAB's version though, but that for loop is essentially the basic way to implement it.
However, for the sake of completeness, let's write our own Octave function for it:
function x = ltitr(A, B, U, x0)
%// Number of rows in U is the number of time points
num_points = size(U, 1);
%// Number of columns in U is how many inputs we have
num_inputs = size(U, 2);
x = zeros(num_inputs, num_points); %// Pre-allocate output
%// For each time point we have ...
for idx = 1 : num_points
x(:,idx) = x0; %// Output the corresponding time point
x0 = A*x0 + B*U(idx,:).'; %// Compute next time point
end
x = x.';
The above function is almost similar to the code you see in MATLAB, but there are some additional steps I did, such as pre-allocating the matrix for efficiency, as well as getting some relevant variables to help with the computation. Also, take note that the output matrix x is defined with the dimensions flipped. The reason why is because the computation of the output at each point in time is more easier to compute in this state. If you don't, then you'll have to do unnecessary transposing for the other variables defined in the x0 = ... statement. As such, it's easier to do the calculations in the transposed matrix. When you're done, you transpose the resulting matrix to give you the final output matrix x.
The default state for x0 I'm assuming is going to be all zeroes, so if you want to use this as the default state, specify x0 = zeros(n,1); where n is the total number of inputs for your LTI system.