Plotting modes of circular waveguide in Matlab - matlab

I'm having some trouble with a script that I need to plot the TE and TM modes of a circular waveguide.
Everything is based on these formulas:
Right now I'm focused on the TE modes and what I have to plot is the field vector e_mn'' inside a squared-mesh equal to the radius of the waveguide.
To do it I need to compute the bessel function of the first kind and extract x_mn that correspond to the n-th root in which the function is equal to zero. These points are supposed to be real but positive.
I followed this example
https://www.mathworks.com/examples/matlab/community/22719-roots-of-a-bessel-function
but I get an error:
Undefined function 'isfinite' for input arguments of type> 'function_handle'. Error in roots (line 26) if ~all(isfinite(c)) Error
in circular (line 20)
x_mn=roots(J0)
This is my code. Can you help me?
clc
clear all
close all
a=20; %radius
m=0;
n=1;
%%
if m==0
ki_m=1;
else
ki_m=sqrt(2);
end
r=0:0.1:a;
J0 = #(r) besselj(0,r);
%J0 = besselj(m,r);
%plot(J0)
x_mn=roots(J0)
%plot(J0(x_mn))
%x_mn=abs(x_mn);
k_mn=x_mn./a;
F_mn=(ki_m*k_mn)./(J0(x_mn)*sqrt(pi*(x_mn^2-m^2)));
for r=0:1:a
for phi=0:1*pi/180:2*pi
e_mnR=-F_mn.*(J0(k_mn*r)/(k_mn.*r))*sin(m*phi);
e_mnPHI=F_mn.*J0(k_mn*r)*cos(m*phi);
end
end
e_mnR=abs(e_mnR);
e_mnPHI=abs(e_mnPHI);
X=0:1:a;
[X,Y] = meshgrid(1:1:a);
quiver(X,Y,e_mnR,e_mnPHI);
hold on

This is not my area of expertise so take this with a grain of salt, but I did some googling and think I know what's going on:
The code you are working from in the provided link defines:
J0 = chebfun(#(x) besselj(0,x),[0 100]);
Note the link from your reference to a Chebfun example is dead, but I read here that:
Chebfun is an open-source package for computing with functions to about 15-digit accuracy. Most Chebfun commands are overloads of familiar MATLAB commands...
The only reason the example you cited works is because J0 is defined using Chebfun, which overloads the matlab command roots with its own version that works on a function handle. Maybe read more here and try using this tool if you want to replicate that code example. Hope this helps...

You can use fzero instead of roots, but you confused polar and cartesian coordinates in the plot section and dimensions of vectors don't agree

Related

Minimizing Function with vector valued input in MATLAB

I want to minimize a function like below:
Here, n can be 5,10,50 etc. I want to use Matlab and want to use Gradient Descent and Quasi-Newton Method with BFGS update to solve this problem along with backtracking line search. I am a novice in Matlab. Can anyone help, please? I can find a solution for a similar problem in that link: https://www.mathworks.com/help/optim/ug/unconstrained-nonlinear-optimization-algorithms.html .
But, I really don't know how to create a vector-valued function in Matlab (in my case input x can be an n-dimensional vector).
You will have to make quite a leap to get where you want to be -- may I suggest to go through some basic tutorial first in order to digest basic MATLAB syntax and concepts? Another useful read is the very basic example to unconstrained optimization in the documentation. However, the answer to your question touches only basic syntax, so we can go through it quickly nevertheless.
The absolute minimum to invoke the unconstraint nonlinear optimization algorithms of the Optimization Toolbox is the formulation of an objective function. That function is supposed to return the function value f of your function at any given point x, and in your case it reads
function f = objfun(x)
f = sum(100 * (x(2:end) - x(1:end-1).^2).^2 + (1 - x(1:end-1)).^2);
end
Notice that
we select the indiviual components of the x vector by matrix indexing, and that
the .^ notation effects that the operand is to be squared elementwise.
For simplicity, save this function to a file objfun.m in your current working directory, so that you have it available from the command window.
Now all you have to do is to call the appropriate optimization algorithm, say, the quasi Newton method, from the command window:
n = 10; % Use n variables
options = optimoptions(#fminunc,'Algorithm','quasi-newton'); % Use QM method
x0 = rand(n,1); % Random starting guess
[x,fval,exitflag] = fminunc(#objfun, x0, options); % Solve!
fprintf('Final objval=%.2e, exitflag=%d\n', fval, exitflag);
On my machine I see that the algorithm converges:
Local minimum found.
Optimization completed because the size of the gradient is less than
the default value of the optimality tolerance.
Final objval=5.57e-11, exitflag=1

Q on plotting function against t and trajectory in phase space(matlab)

I am very beginner for matlab and try to solve this question. But so far it is not successful. I have spent quite a time and I think I need some help. I would appreciate any help!!!
I need to plot v against time and trajectory of v and w in phase space. The whole question is below and my code for previous question connected to this question is also below. I can go with subplot(2,1,1) for the first graph and subplot(2,1,2) for the next graph. But I am not sure what I have to do other than this. I kind of found ode45 command. But not sure how to use it and if it is the right one to use here. I have tried to use ode45. But it shows many errors that I don't understand.....Please help me on this. Thanks a lot!
'Create a figure which contains two graphs, using subplot. In the first graph, plot the temporal evolution of the membrane potential v(t) against time t. In the second graph, plot the corresponding trajectory (v(t); w (t)) in (the so-called) phase space.'
% my code is below.
a=0.08;
b=3.6;
c=0.7;
T=2; % this can be any number
I_ext=20; % this can be any number
dt=0.01; % this can be any number
function [ v,w ] = fhnn( a,b,c,I_ext,T,dt)
v=zeros(1,numel(T/dt));
w=zeros(1,numel(T/dt));
for n=1:numel(T/dt)
v(n+1)=(v(n)-v(n)^3/3-w(n)+I_ext)*dt+v(n);
w(n+1)=a*(v(n)-b*w(n)+c)*dt+w(n);
end
I gather you have a differential equation and are trying to directly plot that. You might find a better approach would be to actually solve the equation if that is possible.
Either way, recognising that:
numel returns the length of an array and dT/dt is always a scalar so the length is always one.
fhnn is not used here.
You still need a vector t.
If what is in your for loop is correct, the following should work:
a=0.08; b=3.6; c=0.7; T=2; I_ext=20; dt=0.01;
t = 0:dt:T;
v = zeros(1,round(T/dt));
w = zeros(1,round(T/dt));
for n=1:round(T/dt)-1
v(n+1)=(v(n)-v(n)^3/3-w(n)+I_ext)*dt+v(n);
w(n+1)=a*(v(n)-b*w(n)+c)*dt+w(n);
end
subplot(2,1,1)
plot(t,v)
xlabel('t')
ylabel('v')
subplot(2,1,2)
plot(v,w)
xlabel('v')
ylabel('w')

Matlab : Intersect point of curves

Say for example I have data which forms the parabolic curve y=x^2, and I want to read off the x value for a given y value. How do I go about doing this in MATLAB?
If it were a straight line, I could just use the equation of the line of best fit to calculate easily, however I can't do this with a curved line. If I can't find a solution, I'll solve for roots
Thanks in advance.
If all data are arrays (not analytical expressions), I usually do that finding minimal absolute error
x=some_array;
[~,ind]=min(abs(x.^2-y0))
Here y0 is a given y value
If your data are represented by a function, you can use fsolve:
function y = myfun(x)
y=x^2-y0
[x,fval] = fsolve(#myfun,x0,options)
For symbolic computations, one can use solve
syms x
solve(x^2 - y0)
Assuming your two curves are just two vectors of data, I would suggest you use Fast and Robust Curve Intersections from the File Exchange. See also these two similar questions: how to find intersection points when lines are created from an array and Finding where plots may cross with octave / matlab.

Plotting complex function in MATLAB (polar)?

I have tried to plot this function:
t=linspace(0,2*pi,100);
a=input('a= ');
b=input('b= ');
c=input('c= ');
k = a*(1-(sin(3*t)).^(2*b))+c;
polar(t,k)
% a=2.6
% b=0.4
% c=5
Each time, I get the following message:
Warning: Imaginary parts of complex X and/or Y arguments ignored.
I have tried the pol2cart method as such:
t=linspace(0,2*pi,100);
a=input('a= ');
b=input('b= ');
c=input('c= ');
k = a*(1-(sin(3*t)).^(2*b))+c;
[x,y] = pol2cart(t,k);
plot(x,y)
I got the same message again.
I have tried to convert it to spherical coordinates, it didn't work. I have also tried the arrayfun method as suggested in a forum answer, it didn't work as well.
Can someone please help me?
Thank you!
Your problem is in your function. k contains imaginary numbers, because of this:
sin(3*t).^(0.8)
If you want to make sure it doesn't contain imaginary numbers, you need to increase b. Bottom line is, fix your formula. I can only suppose you mean something like this, but there could be other solutions. Essentially, I think you mean to take the exponent of 1-sin, not sin.
k=a*((1-sin(3*t)).^(2*b))+c;
This gives the following plot (From Octave, but it should be the same)
I figured this out by `plot(k). If k contains imaginary, it will plot the real vs imaginary components. If it is purely real, it will plot the line vs time.

Plotting and finding roots of bessel functions

I am trying to plot roots of a function that is composed of multiple bessel functions being added and multiplied in Matlab. The equation is Jm(omega)*Ik(omega)+Im(omega)*Jk(omega) where Jm is the bessel function of the first kind of order m (besselj). Im is the modified bessel function of the first kind of order m (besseli). For each mode m=o,1,2,...and n=1,2,3... The frequency omega(mn) is the corresponding root of the listed equation. m=0,1,2 n-1,2,3,4. I need to solve the equation for the 12 roots. I am new to Matlab and this is a little out of my league. So far I have this code but I wasn't sure if I needed the variable omega in the script or not. I have also looked at other people's questions on the suject but didn't see any quite like this. The plots I have seen look nothing like mine which tells me I am probably wrong. Thanks for any help.
m=(0:2); k=(1:3); n=(1:4);
Jm=besselj(m,n');
Ik=besseli(k,n');
Jk=besselj(k,n');
Im=besseli(m,n');
g=Jm.*Ik+Im.*Jk
plot(g)
Plotting
besselj and besseli take what you call omega as their second parameter, so to plot your function you should try something like
m=0; k=1; omega=0:0.02:10;
Jm=besselj(m,omega);
Ik=besseli(k,omega);
Jk=besselj(k,omega);
Im=besseli(m,omega);
g=Jm.*Ik+Im.*Jk;
plot(omega,g);
hold all;
plot(omega,0,'k');
axis([min(omega) max(omega) -100 100]);
This shows you that for m=1, k=1 the first zeros are around 3.2, 6.3 and 9.4:
Finding the roots numerically
You could implement Halley's method for your function g, similar to how the roots of besselj are determined in the MatlabCentral file linked by Cheery.