I have a function which outputs a vector of complex eigenvalues. It takes a single argument, rho
. I need to find a rho
for which the complex eigenvalues lie on the imaginary axis. In other words, the real parts have to be 0.
When I run fzero()
it throws the following error
Operands to the || and && operators must be convertible to logical scalar values.
Whereas fsolve()
simply solves for the imaginary part = 0, which is exactly the oposite of what I want.
This is the function I wrote
function lambda = eigLorenz(rho)
beta = 8/3;
sigma = 10;
eta = sqrt(beta*(rho-1));
A = [ -beta 0 eta;0 -sigma sigma;-eta rho -1];
y = [rho-1; eta; eta];
% Calculate eigenvalues of jacobian
J = A + [0 y(3) 0; 0 0 0; 0 -y(1) 0]
lambda = eig(J)
It outputs 3 eigenvalues, 2 complex conjugates and 1 real eigenvalue (with complex part = 0).
I need to find rho
for which the complex eigenvalues lie on the imaginary axis so that the real parts are 0.
Two problems:
fzero
is only suited for scalar-valued functions (f: ℝ → ℝ)So, one possible workaround is to take the real part of the first complex eigenvalue:
function [output, lambda] = eigLorenz(rho)
% Constants
beta = 8/3;
sigma = 10;
eta = sqrt(beta*(rho-1));
A = [-beta 0 eta
0 -sigma sigma
-eta rho -1];
y = [rho-1
eta
eta];
% Calculate eigenvalues of jacobian
J = A + [0 y(3) 0
0 0 0
0 -y(1) 0];
lambda = eig(J);
% Make it all work for all rho with FZERO(). Check whether:
% - the complex eigenvalues are indeed each other's conjugates
% - there are exactly 2 eigenvalues with nonzero imaginary part
complex = lambda(imag(lambda) ~= 0);
if numel(complex) == 2 && ...
( abs(complex(1) - conj(complex(2))) < sqrt(eps) )
output = real(complex(1));
else
% Help FZERO() get out of this hopeless valley
output = -norm(lambda);
end
end
Call like this:
rho = fzero(@eigLorenz, 0);
[~, lambda] = eigLorenz(rho);