This is a follow-up on a previous question by myself: Laplace transform of numerical data in MATLAB
I have experimentally collected data, and want to take a Laplace transformation of that. However, laplace() needs a model/equation. I find a fit equation to model my data from:
[up,lo] = envelope(dat);
x = 1:length(up);
x = x';
f = fit(x,up,'poly3');
Then for my Laplace transform I need to I pass the output of
f = fit(x,up,'poly3');
into
syms f
laplace(f)
However at the moment this spits out the transform of f:
laplace(f)
ans =
1/s^2
If this is f
f =
Linear model Poly3:
f(x) = p1*x^3 + p2*x^2 + p3*x + p4
Coefficients (with 95% confidence bounds):
p1 = 1.772e-12 (1.593e-12, 1.951e-12)
p2 = -2.211e-08 (-2.483e-08, -1.939e-08)
p3 = 2.847e-05 (1.676e-05, 4.017e-05)
p4 = 0.2762 (0.2627, 0.2897)
How do I find the Laplace transform of f?
I'm not familiar with the output of fit, but your symbolic variable at least should be x, as that's your dependent variable. You can then build up the f yourself:
p1 = 1.772e-12;
p2 = -2.211e-08;
p3 = 2.847e-05;
p4 = 0.2762;
syms x
f = p1*x.^3 + p2*x.^2 + p3*x + p4;
laplace(f)
ans =
(8402860860456175*((50949907131585781563392*s)/5251788037785109375 + 1))/(295147905179352825856*s^2) - 6682337467919863/(151115727451828646838272*s^3) + 26323556995364325/(2475880078570760549798248448*s^4)
fit() gives you a fitobject type variable, which, if I understand its documentation correctly, can be accessed as a structure. This means that you should be able to programmatically use the fitted parameters to build your function of symbolic x.
Related
I am trying the find the inverse Laplace voltage of a circuit, but when I compute it MATLAB output contains sinh and cosh. Is there a way to make MATLAB compute it?
Here is my code:
syms s
F=((s^2)+12*s+20)/(s*((s^2)+10*s+4))
f=ilaplace(F)
f=vpa(f,5)
The expression for f contains the t symbol, you have to substitute a value for t before you can compute the output at that time t; the error message directs you precisely to that solution. I chose t = 5, you can change that as you wish.
syms s
F = (s^2 + 12*s + 20) / (s*(s^2 + 10*s + 4));
f = ilaplace(F);
% 5 - 4*exp(-5*t)*(cosh(21^(1/2)*t) + (3*21^(1/2)*sinh(21^(1/2)*t))/14)
f = subs(f, 5);
double(f)
ans =
4.5083
I need to use the polyfit command to determine the best exponential coefficients for the following 2nd order two-terms equation:
y= a1 * exp(b1*x1^2+b2*x2^2+b3*x1*x2+b4*x1+b5*x2)
For the simplest situation (y= a* exp(kx)) I would proceed like this:
yeqn = #(coefs, x) coefs(1).*exp(coefs(2).*x);
xi = x;
eta = log(y);
P = polyfit(xi, eta, 1);
MyCoefs(1) = exp(P(2));
MyCoefs(2) = P(1)
Is there any chance to do the same thing for my situation, or should I use another approach?
I am trying to solve a differential equation with the ode solver ode45 with MATLAB. I have tried using it with other simpler functions and let it plot the function. They all look correct, but when I plug in the function that I need to solve, it fails. The plot starts off at y(0) = 1 but starts decreasing at some point when it should have been an increasing function all the way up to its critical point.
function [xpts,soln] = diffsolver(p1x,p2x,p3x,p1rr,y0)
syms x y
yp = matlabFunction((p3x/p1x) - (p2x/p1x) * y);
[xpts,soln] = ode45(yp,[0 p1rr],y0);
p1x, p2x, and p3x are polynomials and they are passed into this diffsolver function as parameters.
p1rr here is the critical point. The function should diverge after the critical point, so i want to integrate it up to that point.
EDIT: Here is the code that I have before using diffsolver, the above function. I do pade approximation to find the polynomials p1, p2, and p3. Then i find the critical point, which is the root of p1 that is closest to the target (target is specified by user).
I check if the critical point is empty (sometimes there might not be a critical point in some functions). If its not empty, then it uses the above function to solve the differential equation. Then it plots the x- and y- points returned from the above function basically.
function error = padeapprox(m,n,j)
global f df p1 p2 p3 N target
error = 0;
size = m + n + j + 2;
A = zeros(size,size);
for i = 1:m
A((i + 1):size,i) = df(1:(size - i));
end
for i = (m + 1):(m + n + 1)
A((i - m):size,i) = f(1:(size + 1 - i + m));
end
for i = (m + n + 2):size
A(i - (m + n + 1),i) = -1;
end
if det(A) == 0
error = 1;
fprintf('Warning: Matrix is singular.\n');
end
V = -A\df(1:size);
p1 = [1];
for i = 1:m
p1 = [p1; V(i)];
end
p2 = [];
for i = (m + 1):(m + n + 1)
p2 = [p2; V(i)];
end
p3 = [];
for i = (m + n + 2):size
p3 = [p3; V(i)];
end
fx = poly2sym(f(end:-1:1));
dfx = poly2sym(df(end:-1:1));
p1x = poly2sym(p1(end:-1:1));
p2x = poly2sym(p2(end:-1:1));
p3x = poly2sym(p3(end:-1:1));
p3fullx = p1x * dfx + p2x * fx;
p3full = sym2poly(p3fullx); p3full = p3full(end:-1:1);
p1r = roots(p1(end:-1:1));
p1rr = findroots(p1r,target); % findroots eliminates unreal roots and chooses the one closest to the target
if ~isempty(p1rr)
[xpts,soln] = diffsolver(p1x,p2x,p3fullx,p1rr,f(1));
if rcond(A) >= 1e-10
plot(xpts,soln); axis([0 p1rr 0 5]); hold all
end
end
I saw some examples using another function to generate the differential equation but i've tried using the matlabFunction() method with other simpler functions and it seems like it works. Its just that when I try to solve this function, it fails. The solved values start becoming negative when they should all be positive.
I also tried using another solver, dsolve(). But it gives me an implicit solution all the time...
Does anyone have an idea why this is happening? Any advice is appreciated. Thank you!
Since your code seems to work for simpler functions, you could try to increase the accuracy options of the ode45 solver.
This can be achieved by using odeset:
options = odeset('RelTol',1e-10,'AbsTol',1e-10);
[T,Y] = ode45(#function,[tspan],[y0],options);
Was wondering how I could achieve this in Matlab:
T(s) = 1/(s+1) -> T(jw) = 1/(jw+1)
Setting s = jw doesn't help.
For better understanding:
R(s) = some transfer function
L(s) = some transfer function
T(s) = R(s) * L(s)
value_at_jw = T(jw)
You basically want to evaluate your transfer function at a certain frequency.
The result would be a complex number.
You can't just substitute s with a frequency, you would need to create a polynomial or an anonymous function out from your denominator and numerator. Which is one way, an interesting one. Another very simple way is to use the outputs of the bode function:
Imagine a transfer function G and a frequency value jw you want to insert for 's':
G = tf([2 1 ], [1 1 1])
jw = 1i*2000 % or easier without the complex "i"
G =
2 s + 1
-----------
s^2 + s + 1
Now you want to know magnitude and phase for the frequency s = jw
[mag,phase] = bode( G, imag(jw) ) % or just w
The rest is math, you now have magnitude and phase=angle of your complex result. A complex number of form z = a + bi can be created as follows:
z = mag*( cos(phase)+1i*sin(phase) )
returns:
z = -4.3522e-04 - 9.0032e-04i
If you have Matlab's control systems toolbox installed ($$$), you can do a sort of symbolic computations by defining transfer functions, either by giving the polynomial coefficients with tf or as a system factored in poles and zeros using zpk:
>> R = tf([1], [1, 1])
Transfer function:
1
-----
s + 1
>> L = zpk([1,2],[3,4,5], 6)
Zero/pole/gain:
6 (s-1) (s-2)
-----------------
(s-3) (s-4) (s-5)
You can convert between these two formats, and they can be used for simple math:
>> R * L
Zero/pole/gain:
6 (s-1) (s-2)
-----------------------
(s+1) (s-3) (s-4) (s-5)
A complex frequency response, finally, can be obtained using freqresp:
>> f = logspace(-2, 2, 200);
>> frequency_response = squeeze(freqresp(T, f, 'Hz'));
>> subplot(211)
>> loglog(f, abs(frequency_response))
>> subplot(212)
>> semilogx(f, angle(frequency_response))
Here are two ways.
wmax = 20;
dw = 0.1;
w = -wmax:dw:wmax;
T = 1./(1 + j*w);
subplot(2,1,1)
hold on
grid on
p = plot(w, abs(T))
title('Magnitude')
subplot(2,1,2)
hold on
grid on
p = plot(w, angle(T))
title('Phase')
// or
H = freqs(1, [1 1], w);
figure
subplot(2,1,1)
hold on
grid on
p = plot(w, abs(H))
title('Magnitude')
subplot(2,1,2)
hold on
grid on
p = plot(w, angle(H))
title('Phase')
The result is, of course, identical
Hope that helps.
Solving coupled non linear differential equation by Mat-lab or by calculations
equation 1: x'(t) = -a* x(t) /(x(t) + y(t))
equation 2: y'(t) = -b* y(t) /(x(t) + y(t))
I tried in mathematica but got a very comlicated solution.
Solve[{x'[t] == -a* x[t] /(x[t] + y[t]), y'[t] == -b* y[t] /(x[t] + y[t])}, {x, y}, t]
How can I plot it?
My initial conditions are
x(0) = xo
y(0) = yo
Also, a and b are constants.
I have to plot x and y wrt t after inserting values of a and b . ( a= 2 , b =5 say )
A lot of things to note in this situation:
You need to create a function that contains both a and b:
function dy =soProblem(t,y,a,b)
dy=[-a*y(1)/(y(1)+y(2)); -b*y(2)/(y(1)+y(2))];
end
Call the standard ode function:
a = 2;
b = 5; tend = 10; x0 = 1; y0 = 2;
[T,Y] = ode45(#(t,y)soProblem(t,y,a,b),[0 tend],[x0 y0]);
plot (T,Y)
Realize you may have a stiff equation on your hands.
Have fun identifying the ideal function call:
[T15,Y15] = ode15s(#(t,y)soProblem(t,y,a,b),[0 tend],[x0 y0]);
[T23t,Y23t] = ode23t(#(t,y)soProblem(t,y,a,b),[0 tend],[x0 y0]);
[T23tb,Y23tb] = ode23tb(#(t,y)soProblem(t,y,a,b),[0 tend],[x0 y0]);
%note ode23s doesn't converge (or at least takes forever)
plot (T,Y,T15,Y15,T23t,Y23t,T23tb,Y23tb)
Understand why mathematica becomes restless
In mathematica:
Try ndsolve
In matlab:
Create a function file yourfunction.m:
function [Y_prime]=yourfunction(t, Y)
Y_prime=[-2*Y(1)./(Y(1) + Y(2)) -5*Y(2)./(Y(1) + Y(2))];
end
and then
[T,Y] = ode45(yourfunction,[0 t_end],[x0 y0]);
plot(T,Y(:,1));
hold on
plot(T,Y(:,2));