MATLAB not evaluating integral - matlab

MATLAB gives me the same expression back.
Here's my code
syms tau alpha phi
f = sign(alpha*cos(phi))*(abs(alpha*cos(phi)) - 2.5*(alpha*cos(phi))^2);
F=f*sin(phi);
int(F,phi, [pi/2, acos(tau/alpha)])
I did plug in the values of variables tau and alpha but it still gives me the same expression back. Anyone know how to solve it? Or some other numerical method which could give me answer in these symbols? Will wolfram-mathematica help?

Mathematica
Integrate[(Sign[alpha*Cos[phi]]*(Abs[alpha*Cos[phi]] - 5/2*
(alpha*Cos[phi])^2))*Sin[phi], {phi, Pi/2, ArcCos[tau/alpha]}]
(* ConditionalExpression[-(tau^2/(2 alpha)) + (5 alpha^3 Abs[tau]^3)/
(6 Abs[alpha]^4), ArcCos[tau/alpha] \[Element] Reals] *)
Thus the result is the expression inside the ConditionalExpression if the ArcCos[tau/alpha] is an element of the reals.
If you could specify something like -1<=tau/alpha<=1 && 0<=tau then it can provide an even simpler result, (tau^2 (-3 + 5 tau))/(6 alpha)
Please verify this before you depend on it.

Something like
syms tau alpha phi
f = sign(alpha*cos(phi))*(abs(alpha*cos(phi)) - 2.5*(alpha*cos(phi))^2);
will just generate another symbolic variable. Your goal however is to specify a symbolic function and for that you have to specify the function arguments:
syms tau alpha phi
f(tau,alpha,phi) = sign(alpha*cos(phi))*(abs(alpha*cos(phi)) - 2.5*(alpha*cos(phi))^2);
F(tau,alpha,phi) =f*sin(phi);
Then you can calculate the integral with
R = int(F,phi, [pi/2, acos(tau/alpha)])
Since your integral is dependent on tau and alpha, R is again a symbolic function R(tau,alpha).
Alternatively you could just specify the arguments at the end, e.g.
syms tau alpha phi
f = sign(alpha*cos(phi))*(abs(alpha*cos(phi)) - 2.5*(alpha*cos(phi))^2);
F=f*sin(phi);
R(tau,alpha) = int(F,phi, [pi/2, acos(tau/alpha)])
But I personally find that less clean.
Note that you could also write F directly as
F(tau,alpha,phi) = sin(phi)*(sign(alpha*cos(phi))*(abs(alpha*cos(phi)) - 2.5*(alpha*cos(phi))^2));

Related

Octave integration does not evaluate definite integral with symbolic variables

I am trying to evaluate a convolution integral using the symbolic int() function and instead of returning a useful answer, my program is returning the integral itself. Here is my code
clc; clear;
pkg load symbolic
syms t tau Wn % Declare symbolic variables
f = tau^2 * sin( Wn *(t-tau) );
convolution = int( f, tau, [0 t] ); % Specify tau as the integration variable
% and integration limits are from 0 to t
pretty(convolution)
The code runs, but does not return something useful. Instead of returning an answer, it returns this:
t
⌠
⎮ 2
⎮ τ ⋅sin(Wn⋅t - Wn⋅τ) dτ
⌡
0
i.e. the original integral with the function inside of it.
I've tried troubleshooting the problem in the following ways:
Copy/pasting example code from the Octave int() help page, this works and evaluates the definite integral
Changing the integration syntax from 0, t to [0, t] this changes nothing
Making variable f and storing the function there, instead of the function being inside of int(). This changes nothing
I know the symbolic package is working, because the example code returns the correct definite integral.
Thanks.
You can use eval in order to "evaluate" (duh) the integral. E.g. with your code above, I get:
octave:9> eval( convolution )
ans = (sym)
⎧ 2
⎪t 2⋅cos(Wn⋅t) 2
⎪── + ─────────── - ─── for Wn > -∞ ∧ Wn < ∞ ∧ Wn ≠ 0
⎨Wn 3 3
⎪ Wn Wn
⎪
⎩ 0 otherwise
Note that if you actually 'define' some of those symbols on the workspace, then these get taken into account:
octave:10> Wn = 1; % or preferably `sym('1')` ...
octave:11> eval( convolution )
ans = (sym)
2
t + 2⋅cos(t) - 2

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.

Solve Lognormal equation for mu and sigma given fixed y and x in Matlab

I have the equation of the lognormal:
y = 1/(3.14*x*sig)*exp(-(log(x)-mu)^2/(2*sig^2))
and for fixed
y = a
x = b
I need to find the values of mu and sig. I can set mu in Matlab like:
mu = [0 1 1.1 1.2...]
and find all the values corresponding sig values, but I can't make it with solve or subs. Any ideas please???
Thanks!
Here's a proof of concept to use fzero to numerically search for a sigma(x,y,mu) function.
Assuming you have x,y fixed, you can set
mu = 1; %or whatever
myfun = #(sig) y-1./(3.14*x*sig).*exp(-(log(x)-mu)^2./(2*sig.^2)); %x,y,mu from workspace
sigma = fzero(myfun,1);
This will solve the equation
y-1/(3.14*x*sig)*exp(-(log(x)-mu)^2/(2*sig^2))==0
for sig starting from sig==1 and return it into sigma.
You can generalize it to get a function of mu:
myfun2 = #(mu,sig) y-1./(3.14*x*sig).*exp(-(log(x)-mu).^2./(2*sig.^2));
sigmafun=#(mu) fzero(#(sig)myfun2(mu,sig),1);
then sigmafun will give you a sigma for each value of mu you put into it. The parameters x and y are assumed to be set before the first anonymous function declaration.
Or you could get reaaally general, and define
myfun3 = #(x,y,mu,sig) y-1./(3.14*x*sig).*exp(-(log(x)-mu).^2./(2*sig.^2));
sigmafun2 = #(x,y,mu) fzero(#(sig)myfun3(x,y,mu,sig),1);
The main difference here is that x and y are fed into the function of sigmafun2 each time, so they can change. In the earlier cases the values of x and y were fixed in the anonymous functions at the time of their definition, i.e. when we issued myfun = #(sig).... Depending on your needs you can find out what you want to use.
As a proof of concept, I didn't check how well it behaved for the actual problem. You should definitely have an initial idea of what kind of parameters you expect, since there will be many cases where there's no solution, and fzero will return a NaN.
Update by Oliver Amundsen: the resulting sig(mu) function with x=100, y=0.001 looks like this:

Implementing iterative solution of integral equation in Matlab

We have an equation similar to the Fredholm integral equation of second kind.
To solve this equation we have been given an iterative solution that is guaranteed to converge for our specific equation. Now our only problem consists in implementing this iterative prodedure in MATLAB.
For now, the problematic part of our code looks like this:
function delta = delta(x,a,P,H,E,c,c0,w)
delt = #(x)delta_a(x,a,P,H,E,c0,w);
for i=1:500
delt = #(x)delt(x) - 1/E.*integral(#(xi)((c(1)-c(2)*delt(xi))*ms(xi,x,a,P,H,w)),0,a-0.001);
end
delta=delt;
end
delta_a is a function of x, and represent the initial value of the iteration. ms is a function of x and xi.
As you might see we want delt to depend on both x (before the integral) and xi (inside of the integral) in the iteration. Unfortunately this way of writing the code (with the function handle) does not give us a numerical value, as we wish. We can't either write delt as two different functions, one of x and one of xi, since xi is not defined (until integral defines it). So, how can we make sure that delt depends on xi inside of the integral, and still get a numerical value out of the iteration?
Do any of you have any suggestions to how we might solve this?
Using numerical integration
Explanation of the input parameters: x is a vector of numerical values, all the rest are constants. A problem with my code is that the input parameter x is not being used (I guess this means that x is being treated as a symbol).
It looks like you can do a nesting of anonymous functions in MATLAB:
f =
#(x)2*x
>> ff = #(x) f(f(x))
ff =
#(x)f(f(x))
>> ff(2)
ans =
8
>> f = ff;
>> f(2)
ans =
8
Also it is possible to rebind the pointers to the functions.
Thus, you can set up your iteration like
delta_old = #(x) delta_a(x)
for i=1:500
delta_new = #(x) delta_old(x) - integral(#(xi),delta_old(xi))
delta_old = delta_new
end
plus the inclusion of your parameters...
You may want to consider to solve a discretized version of your problem.
Let K be the matrix which discretizes your Fredholm kernel k(t,s), e.g.
K(i,j) = int_a^b K(x_i, s) l_j(s) ds
where l_j(s) is, for instance, the j-th lagrange interpolant associated to the interpolation nodes (x_i) = x_1,x_2,...,x_n.
Then, solving your Picard iterations is as simple as doing
phi_n+1 = f + K*phi_n
i.e.
for i = 1:N
phi = f + K*phi
end
where phi_n and f are the nodal values of phi and f on the (x_i).

Cross characteristics of a non-linear equation in Matlab

I'd like to create a Matlab plot of propeller angular velocity in terms of applied current. The point is, this requires combining two interdependent sets of data.
Firstly, drag coefficient c_d depends on angular velocity omega (I have no formula, just data) as seen on the plot below - the characteristics c_d(omega) could be easily linearised as c_d(omega) = p*omega + p_0.
Secondly, omega depends not only on applied current i, but also on the drag coefficient c_d(omega).
A script that solves the case, where c_d is constant below. It must be somehow possible to join those two using Matlab commands. Thanks for any help.
%%Lookup table for drag coefficient c_d
c_d_lookup = [248.9188579 0.036688351; %[\omega c_d]
280.2300647 0.037199094;
308.6091183 0.037199094;
338.6636881 0.03779496;
365.8908244 0.038305703;
393.9557188 0.039156941;
421.9158934 0.039667683;
452.2846224 0.040348674;
480.663676 0.041199911;
511.032405 0.042051149;
538.9925796 0.042561892;
567.2669135 0.043242882;
598.4734005 0.043668501;
624.1297405 0.044264368;
651.9851954 0.044604863;
683.6105614 0.045200729];
subplot(2,1,1)
plot(c_d_lookup(:,1), c_d_lookup(:,2))
title('This is how c_d depends on \omega')
ylabel('c_d')
xlabel('\omega [rad/s]')
%%Calculate propeller angular speed in terms of applied current. omega
%%depends on c_d, which in turn depends on omega. The formula is:
% omega(i) = sqrt(a*i / (b * c_d(omega)))
% Where:
% i - applied current
% omega - propeller angular velocity
% a,b - coefficients
i = [1:15];
a = 0.0718;
b = 3.8589e-005;
%If c_d was constant, I'd do:
omega_i = sqrt(a .* i / (b * 0.042));
subplot(2,1,2)
plot(i, omega_i)
ylabel({'Propeller ang. vel.', '\omega [rad/s]'})
xlabel('Applied current i[A]')
title('Propeller angular velocity in terms of applied current')
EDIT:
Trying to follow bdecaf's solution. So I created a function c_d_find, like so:
function c_d = c_d_find(omega, c_d_lookup)
c_d = interp1(c_d_lookup(:,1), c_d_lookup(:,2), omega, 'linear', 'extrap');
end
I don't know anything about Matlab function handles, but seem to understand the idea... In Matlab command window I typed:
f = #(omega) omega - sqrt(a .* i / (b * c_d_find(omega, c_d_lookup)))
which I hope created the correct function handle. What do I do next? Executing the below doesn't work:
>> omega_consistent = fzero(f,0)
??? Operands to the || and && operators must be convertible to logical scalar
values.
Error in ==> fzero at 333
elseif ~isfinite(fx) || ~isreal(fx)
hmmm...
Wonder if I understand correctly - but looks like you are looking for a consistent solution.
Your equations don't look to complicated I would outline the solution like this:
Write a function function c_d = c_d_find(omega) that does some interpolation or so
make a function handle like f = #(omega) omega - sqrt(a .* i / (b * c_d_find(omega))) - this is zero for consistent omega
calculate a consistent omega with omega_consistent =fzero(f,omega_0)