Simplifying the solution of differential equations in Matlab - matlab

I tried various methods to simplify the solution to the following differential equation, but was unable to fully simplify it to 0.01e^(-0.15t)sin(9.999t+1.556) and expressions with radicals were not properly simplified either. Can someone please explain how the solution can be fully simplified with the number of terms reduced as much as possible?
syms y(t) m k x c
Dy = diff(y,t);
Dy2 = diff(y,t,2);
m = 10; c = 3; k = 1000;
ode = m*Dy2 +c*Dy + k*y == 0;
eqns = [ode]
cond = [y(0) == 0.01,Dy(0) == 0];
ySol(t) = dsolve(eqns,cond)
ySol(t) = simplify(ySol(t),'steps',500)
pretty(ySol(t))
vpa(ySol(t), 5)
simplify(ySol(t))

Pass output of vpa function into simplify function, as follows:
vpa(simplify(vpa(ySol(t), 3)),3)

Related

solve equation using MATLAB solve

I have the following equation that I want to solve using MATLAB:
X is the unknown variable. I am trying to solve it using MATLAB solve, but I find it hard to code the left part of the equation.
Is it possible to use solve? Are there any other options?
EDIT
Since A and B depends respectively on j and i I have tried to put them in vectors as follows:
A = [A(1) ... A(j) ... A(N)]
B = [B(1) ... B(i) ... B(N)]
I was trying to have something that looks like this:
eqn = sum(A ./ sum(B .* D)) == C;
solve(eqn);
but the whole difficulty is in this part:
because it depends on both i and j.
To write equation you can use this code:
syms x real
C = 1;
beta = 10;
alph = 0.5;
N = 10;
lenA = N;
lenB = N;
A = rand(1,N);
B = rand(1,N);
eq = 0;
for j=2:N
eqaux = 0;
for i=1:N
eqaux = eqaux+B(i)/((alph+beta*x)^(i+j+1));
end
eq = eq+A(j)/eqaux;
end
eq = simplify(eq==C);
If x must be a complex number, delete real of syms x real.
To solve the equation use this code:
sol = solve(eq,x);
sol = vpa(sol);
Of course yu must use your own values of C, alph, beta, A, B and N.

Non-linear constrained optimization in Matlab

Given a function f(k',w') = ((k'-k)^2+(w'-w)^2)^(1/2), where k and w are known real parameters. The objective is to find a couple (k',w') such that f(k',w') is minimal under the following constraints
b(v,s,w') < 10s <=> w'< 10s
b(v,s,w')< a(v,s,k')^2 <=> (w'-10s)-(k'-3)^2/s < 0
q( a(v,s,k'),b(v,s,w')) < s[v^(1/2)]
where b(v,s,w') = (v/s)(w'-10s) and a(v,s,k') = (1/s)(k'-3)v^(1/2). Above that, v (=vari) > 0 and s (=skew) < 0 are known parameters. Furthermore q(a,b) is a root of the quartic polynomial:
(48a^2 + 16b)x^4 + (-40a^3 - 168ab)x^3 + (-45a^4 + 225a^2b + 72b^2)x^2 + (27a^3b - 162ab^2)x + 27b^3.
To be more precise, whenever the quartic has four real roots then q is the second greatest root. If the quartic has two real and two complex roots then q is the greatest real root. The problem is that the algebraic expressions for q are quite monstrous. Ideally, I would like an analytical solution for the above non-linear constrained optimization problem. However, I think that might turn out quite ugly. Therefore, I thought it was better to do it numerically with Matlab by using constrained optimizers such as fmincon.
f = #(x) sqrt((x(1)-hyp_skew)^2+(x(2)-kurt)^2);
A = [1,0];
d = 10*skew;
Aeq = [];
beq = [];
ub = [];
lb = [];
[x,fval,exitflag] = fmincon(f,[w,k],A,d,Aeq,beq,lb,ub,#(x)quarticcondition2(x,skew,vari),options);
where the (non-linear) optimization function is given by
function [c, ceq] = quarticcondition2(x,skew,vari)
av = ((x(2)-3)*sqrt(vari))/skew;
bv = (vari/skew)*(x(1)-10*skew);
A = (-40*av^3-168*av*bv)/(48*av^2+16*bv);
B = (-45*av^4+225*av^2*bv+72*bv^2)/(48*av^2+16*bv);
C = (27*av^3*bv-162*av*bv^2)/(48*av^2+16*bv);
D = (27*bv^3)/(48*av^2+16*bv);
roots_quartic = roots([1,A,B,C,D]);
z = imag(roots_quartic);
in = find(z ~= 0);
if isempty(in)
r = sort(roots_quartic);
c2 = r(2)-skew*sqrt(vari);
else
index = find(z == 0);
c2 = max(roots_quartic(index))-skew*sqrt(vari);
end
c1 = ((x(2)-3)^2/skew)-(x(1)-10*skew);
c = [c1 c2];
ceq = [];
end
My code works for some initial parameter sets [w,k]. However, finding this initial parameter set turns out to be quite difficult (since the constraints are hard to handle). I need to run the program for quite some possible scenarios, hence it would be nice to have some logic in choosing my starting values. I know this is a well known issue when using optimization solvers. However, is there a good/proper way to find start values?
Thanks!
Cheers

Matlab - Unexpected Results from Differential Equation Solver Ode45

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);

Matlab: 1D Numerical PDEs without Loops

So, currently I am trying to find the numerical solutions for the berger equation, $u_t+u∗u_x=0$. The numerical solution to this equation is:
$u^{n+1}_j=u_n^j−\frac{Δx}{Δt}u^n_j(u^n_j−u^n_{j−1})$
I wrote code on Matlab that computes this. As you can see, there is only one for-loop in the code. However, my u matrix extremely large, the algorithm becomes slow. Is there a way for me to use no loops at all. I was thinking about using the command cumsum, but I am not sure how to integrate that to my program. Please look at my code. Thanks.
dx = 0.9;
dt = 0.9;
tf = 10;
l = 10;
xstep = [-1:dx:l];
tstep = [0:dt:tf];
uinit = zeros(length(tstep),length(xstep));
%%Setting Initial and Boundary Conditions
bc.left = #(t) 2;
bc.right = #(t) -1;
ic = #(x) ...
2*(x<=0) ...
-1*(x>0);
uinit(1, :) = ic(xstep);
uinit(:, 1) = bc.left(tstep);
uinit(:, end) = bc.right(tstep);
%% Numerical method part
for c=1:(length(tstep)-1)
uinit(2:end -1, c+1) = uinit(2:end -1, c) - dx/dt*(uinit(2:end -1, c).*(uinit(2:end-1, c) - uinit(1:end-2, c)));
end
surf(xstep,tstep,uinit)

Trapezoidal Numerical Integration in MATLAB without using a FOR loop?

I'm following a Numerical Methods course and I made a small MATLAB script to compute integrals using the trapezoidal method. However my script uses a FOR loop and my friend told me I'm doing something wrong if I use a FOR loop in Matlab. Is there a way to convert this script to a Matlab-friendly one?
%Number of points to use
N = 4;
%Integration interval
a = 0;
b = 0.5;
%Width of the integration segments
h = (b-a) / N;
F = exp(a);
for i = 1:N-1
F = F + 2*exp(a+i*h);
end
F = F + exp(b);
F = h/2*F
Vectorization is important speed and clarity, but so is using built-in functions whenever possible. Matlab has a built in function for trapezoidal numerical integration called trapz. Here is an example.
x = 0:.125:.5
y = exp(x)
F = trapz(x,y)
It is recommended to vectorize your code.
%Number of points to use
N = 4;
%Integration interval
a = 0;
b = 0.5;
%Width of the integration segments
h = (b-a) / N;
x = 1:1:N-1;
F = h/2*(exp(a) + sum(2*exp(a+x*h)) + exp(b));
However, I've read that Matlab is no longer slow at for loops.