MATLAB simplification functions divide by common factors problem - matlab

I have a complicated expression H which is derived from several other complicated intermediate step. I want to get the [N D] = numden(H).
The problem is that the expression H, N and D is not being "evaluated" and they are also not simplified and divided by common factors.
I am using syms x.
For example, I get
H = (27+81*(x^2-987605098534947/1125899906842624*x-...
That is just so crazy.. but clearly,
H = (27+81*(x^2-0.8772*x-...
how can I get it to evaluate to simplest form?
Thanks in advance!
EDIT: I found out the closest bet is using VPA

My own workaround:
[num den] = numden(H)
num = vpa(num, 4);
den = vpa(den, 4);
H = num/den;
repeat from 1 until desired num and den are obtained.

Related

Why I am getting matrix dimension error in the line while calculating n?

Can you please tell me what's wrong with the following code?
function [n]=calculate_n(p,delta)
e = 1.6*power(10,-19);
k = 1.38*power(10,-23);
T = 298;
co = 3.25*power(10,13)*e*power(10,4);
er=12.5;
eo=1.0;
Nv=3*power(10,13);
us = log((p*e)/sqrt(2*k*T*er*eo*Nv))*2*k*T;
tmp = delta+(e*e*p)/co+us;
n = 1/(exp((tmp))+1);
end
I am getting matrix dimension error while calculating n. Please help me.
Caller:
e = 1.6*power(10,-19);
x = logspace(13,18);
y=calculate_n(x,0.2*e);
semilogx(x,y,'-s');
grid on;
Just replace n = 1/(exp((tmp))+1); with n = 1./(exp(tmp)+1);. But beware, tmp is so small for these values that exp(tmp) will always be 1. Also, there is a surplus bracket around tmp, you might want to check if you put them correctly.
Edit:
The reason is that A/B tries to solve the system of linear equations A*x = B for x which is not what you wanted. It threw an error because it requires both variables to have the same number of columns. A./B performs element-wise matrix division which is what you wanted. However, if A and B are singular A/B = A./B. See the documentation for more info.

MATLAB: How to plot a cubic expression for certain range of input pressure

I have a cubic expression here
I am trying to determine and plot δ𝛿 in the expression for P values of 0.0 to 5000. I'm really struggling to get the expression for δ in terms of the pressure P.
clear all;
close all;
t = 0.335*1e-9;
r = 62*1e-6;
delta = 1.2*1e+9;
E = 1e+12;
v = 0.17;
P = 0:100:5000
P = (4*delta*t)*w/r^2 + (2*E*t)*w^3/((1-v)*r^4);
I would appreciate if anyone could provide pointers.
I suggest two simple methods.
You evaluate P as a function of delta then you plot(P,delta). This is quick and dirty but if all you need is a plot it will do. The inconvenience is that you may to do some guess-and-trial to find the correct interval of P values, but you can also take a large enough value of delta_max and then restrict the x-axis limit of the plot.
Your function is a simple cubic, which you can solve analytically (see here if you are lost) to invert P(delta) into delta(P).
What you want is the functional inverse of your expression, i.e., δ𝛿 as a function of P. Since it's a cubic polynomial, you can expect up to three solutions (roots) for a give value of P. However, I'm guessing that you're only interested in real-valued solutions and nonnegative values of P. In that case there's just one real root for each value of P.
Given the values of your parameters, it makes most sense to solve this numerically using fzero. Using the parameter names in your code (different from equations):
t = 0.335*1e-9;
r = 62*1e-6;
delta = 1.2*1e9;
E = 1e12;
v = 0.17;
f = #(w,p)2*E*t*w.^3/((1-v)*r^4)+4*delta*t*w/r^2-p;
P = 0:100:5000;
w0 = [0 1]; % Bounded initial guess, valid up to very large values of P
w_sol = zeros(length(P),1);
for i = 1:length(P)
w_sol(i) = fzero(#(w)f(w,P(i)),w0); % Find solution for each P
end
figure;
plot(P,w_sol);
You could also solve this using symbolic math:
syms w p
t = 0.335*sym(1e-9);
r = 62*sym(1e-6);
delta = 1.2*sym(1e9);
E = sym(1e12);
v = sym(0.17);
w_sol = solve(p==2*E*t*w^3/((1-v)*r^4)+4*delta*t*w/r^2,w);
P = 0:100:5000;
w_sol = double(subs(w_sol(1),p,P)); % Plug in P values and convert to floating point
figure;
plot(P,w_sol);
Because of your numeric parameter values, solve returns an answer in terms of three RootOf objects, the first of which is the real one you want.

How do I solve exponential equation in symbolic form using Lambertw

Assume that A, B and C are positive constants. I need to solve the following equation in symbolic form as W(A,B,C).
solve(x-(exp(log(2)*x*A)-B)*C==0)
Any help is appreciated.
Since the equation mixes polynomials and transcendentals, my first thought was simply that it may not have an analytical solution. However, the form reminded me of the Lambert W function (Wikipedia and Mathworks blog post), so I tried the variable substitution u = x/c+b which yields the simplified problem
solve(u == alpha * exp(beta * u) , u);
where alpha = exp(-log(2)*a*b*c) and beta = log(2)*a*c. Running this through Matlab gives me
>> syms alpha beta u
>> solve(u == alpha * exp(beta * u) , u)
ans =
-lambertw(0, -alpha*beta)/beta
which indeed showcases a Lambert W function call. With this knowledge, we can get the solution in terms of xsol like so:
syms a b c alpha beta x u xsol usol
usol = solve(u == alpha * exp(beta*u),u);
log2 = log(sym(2));
xsol = subs(c*(usol-b),[alpha,beta],[exp(-log2*a*b*c),log2*a*c]);
Let's make sure the Symbolic Engine didn't make a mistake by checking the analytical solution against a numeric one:
anum = rand();
bnum = rand();
cnum = rand();
xana = double(subs(xsol,[a,b,c],[anum,bnum,cnum]));
xnum = vpasolve(x-(exp(log2*x*anum)-bnum)*cnum,x);
fprintf('%15.10e\n%15.10e\n%15.10e\n',xana,xnum,xana-xnum);
which displays
8.0171933677e-02
8.0171933677e-02
1.7453177064e-19
Note: certain combinations of a, b, and c may result in an equation with no real solution. In such situations, the analytical solution may give a complex number whose veracity should be highly questioned.

Matlab: Finding two unknown constants/parameters in an equation

I've read up on fsolve and solve, and tried various methods of curve fitting/regression but I feel I need a bit of guidance here before I spend more time trying to make something work that might be the wrong approach.
I have a series of equations I am trying to fit to a data set (x) separately:
for example:
(a+b*c)*d = x
a*(1+b*c)*d = x
x = 1.9248
3.0137
4.0855
5.0097
5.7226
6.2064
6.4655
6.5108
6.3543
6.0065
c= 0.0200
0.2200
0.4200
0.6200
0.8200
1.0200
1.2200
1.4200
1.6200
1.8200
d = 1.2849
2.2245
3.6431
5.6553
8.3327
11.6542
15.4421
19.2852
22.4525
23.8003
I know c, d and x - they are observations. My unknowns are a and b, and should be constant.
I could do it manually for each x observation but there must be an automatic and far superior way or at least another approach.
Very grateful if I could receive some guidance. Thanks for the time!
Given your two example equations; let y=x./d, then
y = a+b*c
y = a+a*b*c
The first case is just a line, for which you can obtain a least squares fit (values for a and b) with polyfit(). In the second case, you can just say k=a*b (since these are both fitted anyway), then rewrite it as:
y = a+k*c
Which is exactly the same line as the first problem, except now b = k/a. In fact, b=b1/a is the solution to the second problem where b1 is the fit from the first problem. In short, to solve them both, you need one call to polyfit() and a couple of divisions.
Will that work for you?
I see two different equations to fit here. To spell out the code:
For (a+b*c)*d = x
p = polyfit(c, x./d, 1);
a = p(2);
b = p(1);
For a*(1+b*c)*d = x
p = polyfit(c, x./d, 1);
a = p(2);
b = p(1) / a;
No need for polyfit; this is just a linear least squares problem, which is best solved with MATLAB's slash operator:
>> ab = [ones(size(c)) c] \ (x./d)
ans =
1.411437211703194e+000 % 'a'
-7.329687661579296e-001 % 'b'
Faster, cleaner, more educative :)
And, as Emmet already said, your second equation is nothing more than a different form of your first equation, the difference being that the b in your first equation, is equal to a*b in your second one.

Getting numerator and denominator without using numden() in MATLAB

Is there anyway of obtaining the numerator and denominator in MATLAB without using numden() function? For example:
format rational
x=5/2;
I want to obtain 5 as num and 2 as den. Can you help me with this tricky problem.
How about
[N,D] = rat(2.5)
Otherwise, if you insist on doing it yourself, you can do something like
N = 2.5;
D=1; while (int64(N)~=N), N=N*10; D=D*10; end
g = gcd(N,D);
D = D/g;
N = N/g;