Problem with _plus() and symbolic differentiation

조회 수: 1 (최근 30일)
Hendrik Lorenz
Hendrik Lorenz 2019년 7월 2일
답변: Stefanie Schwarz 2019년 7월 8일
I define a symbolic expression (dx_3dt) and make an assumption that reduces that expression to one term. By this the function _plus(...) appears in my expression (Output dx_3dt) which is apparently not differentiable by Matlabs definition leading to NaN value. Differentiating the same expression "manually" allows me to obtain the correct solution.
Any advice how to handle this?
MWE:
clear all;
reset(symengine)
theta = sym('theta_%d', [5, 1], {'positive', 'real'}); % physical parameters of system dynamics
x = sym('x_%d', [6, 1], {'positive', 'real'}); % system states
grav = 9810; % gravitation accelaration [mm/s^2]
eps = 1e-10;
outflow = piecewise(x(3) <= eps, 0, -theta(5)*sqrt(2*grav*x(3)));
dx_3dt = theta(4)*sign(x(2)-x(3))*sqrt(2*grav*abs(x(2)-x(3)))+theta(2)*x(5)+outflow;
simplify(diff(dx_3dt, x(2)))
assumeAlso(x(2) == x(3))
simplify(dx_3dt)
Output dx_3dt in command window:
piecewise(x_3 <= 1/10000000000, _plus(theta_2*x_5), theta_2*x_5 - 6*545^(1/2)*theta_5*x_3^(1/2) + 6*545^(1/2)*theta_4*abs(x_2 - x_3)^(1/2)*sign(x_2 - x_3))
Expected result:
simplify(diff(dx_3dt, x(2)))
diff(theta(2)*x(5), x(2))
First ideas
The problem seems to be the piecewise function since omitting piecewise gives the expected result:
clear all;
reset(symengine)
theta = sym('theta_%d', [5, 1]); % physical parameters of system dynamics
x = sym('x_%d', [6, 1]); % system states
grav = 9810; % gravitation accelaration [mm/s^2]
eps = 1e-10;
% outflow = piecewise(x(3) <= eps, 0, -theta(5)*sqrt(2*grav*x(3)));
dx_3dt = theta(4)*sign(x(2)-x(3))*sqrt(2*grav*abs(x(2)-x(3)))+theta(2)*x(5)-theta(5)*sqrt(2*grav*x(3));
simplify(diff(dx_3dt, x(2)))
assumeAlso(x(2) == x(3))
simplify(dx_3dt)
simplify(diff(dx_3dt, x(2)))
diff(theta(2)*x(5), x(2))
Problem with diff and assumptions
Furhtermore if I apply the following workaround with replacing the critical term with a symbolic function of x_3 and assume that x_3 == x_2 and differentiate with respect to x_2 it is zero! So the diff function appears to also not consider assumptions here:
clear all;
reset(symengine)
theta = sym('theta_%d', [5, 1], {'positive', 'real'}); % physical parameters of system dynamics
x = sym('x_%d', [6, 1], {'positive', 'real'}); % system states
grav = 9810; % gravitation accelaration [mm/s^2]
eps = 1e-10;
% outflow = symfun(x_3, x_3)
syms x_3 outflow(x_3)
% outflow = piecewise(x(3) <= eps, 0, -theta(5)*sqrt(2*grav*x(3)));
dx_2dt = theta(3)*x(6)*sign(x(1) - x(2))*sqrt(2*grav*abs(x(1)-x(2)))-theta(4)*sign(x(2)-x(3))*sqrt(2*grav*abs(x(2)-x(3)))
dx_3dt = theta(4)*sign(x(2)-x(3))*sqrt(2*grav*abs(x(2)-x(3)))+theta(2)*x(5)+outflow(x_3)
f = [dx_2dt; dx_3dt];
simplify(diff(dx_3dt, x(2)))
simplify(diff(dx_3dt, x(3)))
assumeAlso(x(2) == x(3))
simplify(dx_3dt)
assumptions(x(2))
assumptions(x(3))
simplify(dx_3dt)
simplify(diff(dx_3dt, x(2)))
simplify(diff(dx_3dt, x(3)))
jac = simplify(jacobian(f, x))

답변 (1개)

Stefanie Schwarz
Stefanie Schwarz 2019년 7월 8일
Thank you for bringing this to our attention. I have alerted our developers to this issue, as of course, there should appear no "_plus" in the output.
The workaround is, as you noticed, to use "simplify" or any other operation that triggers a re-evaluation, such as dx_3dt * 1.
Please note that an assumption x(2) == x(3) does not make x(2) "depend" on x(3), and it does not have the effect of an assignment . I.e., even if you assume x == 42, the derivative of x^2 is 2*x while the derivative of 42^2 is 0 and the derivative diff(42^2, 42) makes no sense. This is similar for integrals and other cases of bound variables (summation variables etc.).

카테고리

Help CenterFile Exchange에서 Assumptions에 대해 자세히 알아보기

태그

제품


릴리스

R2019a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by