Need help plotting this function in Matlab - matlab

I recently started using Matlab and I am trying to plot Imaginary part of a function. I can see I am making a mistake somewhere because I have the graph showing what I need to get and I am getting something else. Here is the link of the graph that I need to get, that I am getting and a function that I am plotting:
I know that this function has a singularity at frequency around 270 Hz and I don't know if a 'quadgk' can solve integral then. You guys probably know but theta function inside the integral is a heaviside and I don't know if that is causing problem maybe? Is there something wrong I am doing here? Here is the matlab code I wrote:
clear all
clc
ff=1:10:1000;
K1=(2*3)*log(2*cosh(135/6))/pi;
theta1=ones(size(ff));
theta1(ff<270)=0;
I1=zeros(size(ff));
for n = 1:numel(ff)
f = ff(n);
I1(n)= K1/f + (f/pi)*quadgk(#(x)(sinh(x/3)/(cosh(135/3)+cosh(x/3))-theta1(n))./((f^2)-4*(x.^2)), 0, inf);
end
plot(ff,I1, 'b');
hold on
axis([0 1000 -0.3 1])

First, I altered the expression for your heaviside function to what I think is the correct form.
Second, I introduced the definitions of mu and T explicitly.
Third, I broke down the integral into 4 components, as follows, and evaluated them individually (along the lines of what Fraukje proposed)
Fourth, I use quadl, although this is prob. of minor importance.
(edit) Changed the range of ff
Here's the code with changes:
fstep=1;
ff=[1:fstep:265 275:fstep:1000];
T = 3;
mu = 135;
df = 0.01;
xmax = 10;
K1=(2*T/pi)*log(2*cosh(mu/(2*T)));
theta1=ones(size(ff));
theta1(ff-2*mu<0)=0;
I1=zeros(size(ff));
for n = 1:numel(ff)
f = ff(n);
sigm1 = #(x) sinh(x/T)./((f^2-4*x.^2).*(cosh(mu/T)+cosh(x/T)));
sigm2 = #(x) -theta1(n)./(f^2-4*x.^2);
I1(n) = K1/f + (f/pi)*quadl(sigm1,0,f/2-df); % term #1
% I1(n) = I1(n) + (f/pi)*quadl(sigm1,f/2+df,xmax); % term #2
% I1(n) = I1(n) + (f/pi)*quadl(sigm2,0,f/2-df); % term #3
% I1(n) = I1(n) + (f/pi)*quadl(sigm2,f/2+df,xmax); % term #4
end
I selected to split the integrals around x=f/2 since there is clearly a singularity there (division by 0). But additional problems occur for terms #2 and #4, that is when the integrals are evaluated for x>f/2, presumably due to all of the trigonometric terms.
If you keep only terms 1 and 3 you get something reasonably similar to the plot you show:
However you should probably inspect your function more closely and see what can be done to evaluate the integrals for x>f/2.
EDIT
I inspected the code again and redefined the auxiliary integrals:
I1=zeros(size(ff));
I2=zeros(size(ff));
I3=zeros(size(ff));
for n = 1:numel(ff)
f = ff(n);
sigm3 = #(x) sinh(x/T)./((f^2-4*x.^2).*(cosh(mu/T)+cosh(x/T))) -theta1(n)./(f^2-4*x.^2);
I1(n) = K1/f + (f/pi)*quadl(sigm3,0,f/2-df);
I2(n) = (f/pi)*quadl(sigm3,f/2+df,10);
end
I3=I2;
I3(isnan(I3)) = 0;
I3 = I3 + I1;
This is how the output looks like now:
The green line is the integral of the function over 0<x<f/2 and seems ok. The red line is the integral over Inf>x>f/2 and clearly fails around f=270. The blue curve is the sum (the total integral) excluding the NaN contribution when integrating over Inf>x>f/2.
My conclusion is that there might be something wrong with the curve as you expect it to look.

So far I'd proceed this way:
clc,clear
T = 3;
mu = 135;
f = 1E-04:.1:1000;
theta = ones(size(f));
theta(f < 270)= 0;
integrative = zeros(size(f));
for ii = 1:numel(f)
ff = #(x) int_y(x, f(ii), theta(ii));
integrative(ii) = quad(ff,0,2000);
end
Imm = ((2*T)./(pi*f)).*log(2*cosh(mu/(2*T))) + (f/pi).*integrative;
Imm1 = exp(interp1(log(f(1:2399)),log(Imm(1:2399)),log(f(2400):.001:f(2700)),'linear','extrap'));
Imm2 = exp(interp1(log(f(2985:end)),log(Imm(2985:end)),log(f(2701):.001:f(2984)),'linear','extrap'));
plot([(f(2400):.001:f(2700)) (f(2701):.001:f(2984))],[Imm1 Imm2])
hold on
axis([0 1000 -1.0 1])
plot(f,Imm,'g')
grid on
hold off
with
function rrr = int_y(x,f,theta)
T = 3;
mu = 135;
rrr = ( (sinh(x./T)./(cosh(mu/T) + cosh(x/T))) - theta ) ./ (f.^2 - 4.*(x.^2));
end
I've come up with this plot:

Related

Recursive difference equation MATLAB

I have a simple recursive equation, and the idea is for a given starting value of x, trace the future value of x, to see if there any convergence. I wrote a MATLAB code below which is simple, and obviously, x converges to a steady-state value 0.0292 pretty fast.
x(1) = 0.2;
for t = 1:1:100
x(t+1) = 0.12*x(t).^0.40;
end
However, for more complex equations I do not think I can apply the above code. What if, for example, I have:
x(t+1) = 0.12*(x(t)./(x(t+1)+x(t))).^0.40
How do I “solve” it to see (without trying to do any algebraic manipulations to isolate x(t+1) on the right-hand-side) to see what the path of x is?
Thank you.
As mentioned in the comments a simple approach would be give an initial guess for x(t+1) and try to converge to a solution for x(t+1) and then continue iterating.
recEq = #(p,q) 0.12 * (p ./ (q+p))^0.4;
x = nan(1, 100);
x(1) = 0.2;
for t = 1:100
kold = x(t);
k = recEq(x(t), kold);
while abs(k-kold) > 1e-8
kold = k;
k = recEq(x(t), kold);
end
x(t+1) = k;
end

How to avoid tf() command using State-space models in Matlab

I'm trying to avoid the function tf() from Matlab since it requires specific toolboxes to run.
The transfer function that I'm using is quite simple. Is the model for a heatsink temperature.
H(s) = (Rth/Tau)/(s + 1/Tau)
In order to avoid the tf() function, I've tried to substitute the transfer function with a state space model coded in Matlab.
I've used the function ss() to get te values of A,B,C and D. And I've tried to compare the results from tf() and my function.
Here's the code that I've used:
Rth = 8.3220e-04; % ºC/W
Tau = 0.0025; % s
P = rand(1,10)*1000; % Losses = input
t = 0:1:length(P)-1; % Time array
%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Transfer function %%%
%%%%%%%%%%%%%%%%%%%%%%%%%
H = tf([0 Rth/Tau],[1 1/Tau]);
Transfer_func = lsim(H,P,t);
figure, plot(Transfer_func),grid on,grid minor, title('Transfer func')
%%%%%%%%%%%%%%%%%%%%%%%%%
%%% My función ss %%%
%%%%%%%%%%%%%%%%%%%%%%%%%
% Preallocate for speed
x(1:length(P)) = 0;
y(1:length(P)) = 0;
u = P;
sys = ss(H);
A = sys.A;
B = sys.B;
C = sys.C;
D = sys.D;
for k = 1:length(u)
x(k+1) = A*x(k) + B*u(k);
y(k) = C*x(k) + D*u(k);
end
figure, plot(y), grid on,grid minor, title('With my función')
I know that the values from A,B,C and D are ok, since I've checked them using
H = tf([0 Rth/Tau],[1 1/Tau]);
sys = ss(H);
state_space_sys = ss(sys.A,sys.B,sys.C,sys.D);
state_space = lsim(state_space_sys,P,t);
figure, plot(state_space),grid on,grid minor, title('State space')
As you can see, the results obtained from my funtion and the function tf() are very different.
Is there any mistakes on the approach?
If it's not possible to avoid the tf() function in this way, is there any other way?
At the end, I found another solution. I'm posting this here, so if someone has the same problem, can use this approach.
If you take the transfer function, and develop it, we reach to the following expresion
H(s) = deltaT(s)/P(s) = (Rth/Tau)/(s + 1/Tau)
deltaT(s) * (s + 1/Tau) = (Rth/Tau) * P(s)
deltaT(s) * s = (Rth/Tau) * P(s) - deltaT(s)/Tau
Now, we know that 1/s is equal to integrate. So in the end, we have to integrate the right side of the equation. The code would be like this.
Cth = Tau/Rth;
deltaT = zeros(size(P));
for i = 2:length(P)
deltaT(i) = (1/Cth * (P(i)-deltaT(i-1)/Rth))*(time(i)-time(i-1)) + deltaT(i-1);
end
This integral has the same output as the function tf().

How to implement an guess correcting algorithm when solving a BVP with shooting method?

I have a boundary value problem (specified in the picture below) that is supposed to be solved with shooting method. Note that I am working with MATLAB when doing this question. I'm pretty sure that I have rewritten the differential equation from a 2nd order differential equation to a system of 1st order differential equations and also approximated the missed value for the derivative of this differential equation when x=0 using the secant method correctly, but you could verify this so you'll be sure.
I have done solving this BVP with shooting method and my codes currently for this problem is as follows:
clear, clf;
global I;
I = 0.1; %Strength of the electricity on the wire
L = 0.400; %The length of the wire
xStart = 0; %Start point
xSlut = L/2; %End point
yStart = 10; %Function value when x=0
err = 5e-10; %Error tolerance in calculations
g1 = 128; %First guess on y'(x) when x=0
g2 = 89; %Second guess on y'(x) when x=0
state = 0;
X = [];
Y = [];
[X,Y] = ode45(#calcWithSec,[xStart xSlut],[yStart g1]');
F1 = Y(end,2);
iter = 0;
h = 1;
currentY = Y;
while abs(h)>err && iter<100
[X,Y] = ode45(#calcWithSec,[xStart xSlut],[yStart g2]');
currentY = Y;
F2 = Y(end,2);
Fp = (g2-g1)/(F2-F1);
h = -F2*Fp;
g1 = g2;
g2 = g2 + h;
F1 = F2;
iter = iter + 1;
end
if iter == 100
disp('No convergence')
else
plot(X,Y(:,1))
end
calcWithSec:
function fp = calcWithSec(x,y)
alpha = 0.01; %Constant
beta = 10^13; %Constant
global I;
fp = [y(2) alpha*(y(1)^4)-beta*(I^2)*10^(-8)*(1+y(1)/32.5)]';
end
My problem with this program is that for different given I's in the differential equation, I get strange curves that does not make any sense in physical meaning. For instance, the only "good" graph I get is when I=0.1. The graph to such differential equations is as follows:
But when I set I=0.2, then I get a graph that looks like this:
Again, in physical meaning and according to the given assignment, this should not happen since it gets hotter you closer you get to the middle of the mentioned wire. I want be able to calculate all I between 0.1 and 20, where I is the strength of the electricity.
I have a theory that it has something to do with my guessing values and therefore, my question is about if there is possible to implement an algorithm that forces the program to adjust the guessing values so I can get a graph that is "correct" in physical meaning? Or is it impossible to achieve this? If so, then explain why.
I have struggled with this assignment many days in row now, so all help I can get with this assignment is worth gold to me now.
Thank you all in advance for helping me out of this!

MATLAB How to vectorize these for loops?

I've searched a lot but didn't find any solution to my problem, could you please help me vectorizing (or just a way to make it way faster) these loops ?
% n is the size of C
h = 1/(n-1)
dt = 1e-6;
a = 1e-2;
F=zeros(n,n);
F2=zeros(n,n);
C2=zeros(n,n);
t = 0.0;
for iter=1:12000
F2=F.^3-F;
for i=1:n
for j=1:n
F2(i,j)=F2(i,j)-(C(ij(i-1),j)+C(ij(i+1),j)+C(i,ij(j-1))+C(i,ij(j+1))-4*C(i,j)).*(a.^2)./(h.^2);
end
end
F=F2;
for i=1:n
for j=1:n
C2(i,j)=C(i,j)+(F(ij(i-1),j)+F(ij(i+1),j)+F(i,ij(j-1))+F(i,ij(j+1))-4*F(i,j)).*dt./(h^2);
end
end
C=C2;
t = t + dt;
end
function i=ij(i) %Just to have a matrix as loop (the n+1 th cases are the 1 th and 0 the 0th are nth)
if i==0
i=n;
return
elseif i==n+1
i=1;
end
return
end
thanks a lot
EDIT: Found an answer, it was totally ridiculous and I was searching way too far
%n is still the size of C
h = 1/((n-1))
dt = 1e-6;
a = 1e-2;
F=zeros(n,n);
var1=(a^2)/(h^2); %to make a bit less calculus
var2=dt/(h^2); % the same
t = 0.0;
for iter=1:12000
F=C.^3-C-var1*(C([n 1:n-1],1:n) + C([2:n 1], 1:n) + C(1:n, [n 1:n-1]) + C(1:n, [2:n 1]) - 4*C);
C = C + var2*(F([n 1:n-1], 1:n) + F([2:n 1], 1:n) + F(1:n, [n 1:n-1]) + F(1:n,[2:n 1]) - 4*F);
t = t + dt;
end
Found an answer, it was totally ridiculous and I was searching way too far
%n is still the size of C
h = 1/((n-1))
dt = 1e-6;
a = 1e-2;
F=zeros(n,n);
var1=(a^2)/(h^2); %to make a bit less calculus
var2=dt/(h^2); % the same
prev = [n 1:n-1];
next = [2:n 1];
t = 0.0;
for iter=1:12000
F = C.*C.*C - C - var1*(C(:,next)+C(:,prev)+C(next,:)+C(prev,:)-4*C);
C = C + var2*(F(:,next)+F(:,prev)+F(next,:)+F(prev,:)-4*F);
t = t + dt;
end
The behavior of the inner loop looks like a 2-dimensional circular convolution. That's the same as multiplication in the FFT domain. Subtraction is invariant across a linear operation such as FFT.
You'll want to use the fft2 and ifft2 functions.
Once you do that, I think you'll find that the repeated convolution can be eliminated by raising the convolution kernel (element-wise) to the power iter. If that optimization is correct, I'm predicting a speedup of 5 orders of magnitude.
You can replace for example C(ij(i-1),j) by using circshift(C,[1,0]) or circshift(C,[1,0]) (i can't figure out witch one of two is correct)
http://www.mathworks.com/help/matlab/ref/circshift.htm

“dumb” version of Euler’s method using Matlab

I tried to write the 'dumb' version of Euler's method using Matlab but I always came up with nothing. My code was trash :-(
See this pseudocode for this method :
‘set integration range
xi = 0
xf = 0
‘initialize variables
x = xi
y = 1
‘set step size and determine
‘number of calculation steps
dx = 0.5
nc = (xf – xi) / dx
‘ output initial condition
PRINT x, y
‘Loop to implement Euler’s method
‘and display results
DOFOR I = 1, nc
dydx = -(2X**3) + (12X**2) - (20X) + 8.5
y = y + dydx . dx
x = x + dx
PRINT x, y
END DO
I'm pretty sure that this pseudocode is what I need to implement, but I failed to convert it into Matlab code.
Any help please ?
I am not sure where you're failing, it would really help to know how you're failing or what's a complication. Otherwise this just seems like doing your homework.
Here's my attempt at the MATLAB code. (Note: I do not have MATLAB on this computer and have not tested it)
i = 0;
stepsize = .1; % Define as what you want it to be
y = 1; % Initial value condition given
t = 0; % Initial time value
yout = [zeros(1,20)]; % Assuming you want 20 outputs, can change
fvec = [zeros(1,20)];
for i = 1:20 % Time range, can change to correspond to what you want
fvec(i) = 2 - exp(-4*t) - 2*yout(i); % Just loops calculating based on Euler's method
yout(i+1) = yout(i) + stepsize*fvec(i)
t = t+stepsize % Time has passed, increment the time.
end
I'm not entirely sure this code, but it should give you an example of how to go about this. Please comment if something is wrong.