Different behaviour when using symbolic simplification on norm() for scalars and vectors?
I’m building quite a lengthy differential equation (through many substitutions, etc) that involves a norm of the difference between two vectors. I am then trying to use odeToVectorField() and matlabFunction() to convert it into an integration problem. I run into the following error:
Error using symengine
Unable to generate code for piecewise for use in anonymous functions.
Error in sym/matlabFunction>mup2mat (line 431)
res1 = mupadmex(‘symobj::generateMATLAB’,r.s,ano,spa,splitIt);
I don’t think I can write the equation out here because it is far, far too long, but while trying to debug the issue, I found that if I change the following term (which is used several times for different eta and a in constructing the equation):
d_eta = norm(eta-a); %Both eta and a are defined as real vectors, e.g. syms eta [N 1] real
into
d_eta = ( ((eta(1)-a(1))^2) + ((eta(2)-a(2))^2) ) ^ (0.5);
then matlabFunction() is able to finish execution and the subsequent integration works fine (well, at least it runs, I’m still trying to come up with a verification case). This is obviously not an ideal solution as I’d like to be able to handle the n-dimensional case, so I’m trying to understand what is happening under the hood in the norm function.
I think the abs() function that is used in the norm() function is what is causing the issue – MATLAB is trying to create piecewise functions for it. What is the best way to have MATLAB understand that eta and a are real, and it can remove the abs() function?
For instance, why does the following work in simplifying norm:
>> syms a b real
>> c = norm(a-b)
c =
(abs(a – b)^2)^(1/2)
>> simplify(c)
ans =
abs(a – b)
But not this?:
>> syms a [2 1] real
>> syms b [2 1] real
>> c = norm(a-b)
c =
(abs(a1 – b1)^2 + abs(a2 – b2)^2)^(1/2)
>> simplify(c)
ans =
(abs(a1 – b1)^2 + abs(a2 – b2)^2)^(1/2)
However, this works:
>> syms a [2 1] real
>> syms b [2 1] real
>> syms c
>> c = norm(a-b)
c =
(abs(a1 – b1)^2 + abs(a2 – b2)^2)^(1/2)
>> rewrite(c,"sqrt")
ans =
((a1 – b1)^2 + (a2 – b2)^2)^(1/2)
Would it be "safe" to use rewrite to overcome this issue? Are there any nuanced differences between these (particularly which could impact the subsequent integration)?I’m building quite a lengthy differential equation (through many substitutions, etc) that involves a norm of the difference between two vectors. I am then trying to use odeToVectorField() and matlabFunction() to convert it into an integration problem. I run into the following error:
Error using symengine
Unable to generate code for piecewise for use in anonymous functions.
Error in sym/matlabFunction>mup2mat (line 431)
res1 = mupadmex(‘symobj::generateMATLAB’,r.s,ano,spa,splitIt);
I don’t think I can write the equation out here because it is far, far too long, but while trying to debug the issue, I found that if I change the following term (which is used several times for different eta and a in constructing the equation):
d_eta = norm(eta-a); %Both eta and a are defined as real vectors, e.g. syms eta [N 1] real
into
d_eta = ( ((eta(1)-a(1))^2) + ((eta(2)-a(2))^2) ) ^ (0.5);
then matlabFunction() is able to finish execution and the subsequent integration works fine (well, at least it runs, I’m still trying to come up with a verification case). This is obviously not an ideal solution as I’d like to be able to handle the n-dimensional case, so I’m trying to understand what is happening under the hood in the norm function.
I think the abs() function that is used in the norm() function is what is causing the issue – MATLAB is trying to create piecewise functions for it. What is the best way to have MATLAB understand that eta and a are real, and it can remove the abs() function?
For instance, why does the following work in simplifying norm:
>> syms a b real
>> c = norm(a-b)
c =
(abs(a – b)^2)^(1/2)
>> simplify(c)
ans =
abs(a – b)
But not this?:
>> syms a [2 1] real
>> syms b [2 1] real
>> c = norm(a-b)
c =
(abs(a1 – b1)^2 + abs(a2 – b2)^2)^(1/2)
>> simplify(c)
ans =
(abs(a1 – b1)^2 + abs(a2 – b2)^2)^(1/2)
However, this works:
>> syms a [2 1] real
>> syms b [2 1] real
>> syms c
>> c = norm(a-b)
c =
(abs(a1 – b1)^2 + abs(a2 – b2)^2)^(1/2)
>> rewrite(c,"sqrt")
ans =
((a1 – b1)^2 + (a2 – b2)^2)^(1/2)
Would it be "safe" to use rewrite to overcome this issue? Are there any nuanced differences between these (particularly which could impact the subsequent integration)? I’m building quite a lengthy differential equation (through many substitutions, etc) that involves a norm of the difference between two vectors. I am then trying to use odeToVectorField() and matlabFunction() to convert it into an integration problem. I run into the following error:
Error using symengine
Unable to generate code for piecewise for use in anonymous functions.
Error in sym/matlabFunction>mup2mat (line 431)
res1 = mupadmex(‘symobj::generateMATLAB’,r.s,ano,spa,splitIt);
I don’t think I can write the equation out here because it is far, far too long, but while trying to debug the issue, I found that if I change the following term (which is used several times for different eta and a in constructing the equation):
d_eta = norm(eta-a); %Both eta and a are defined as real vectors, e.g. syms eta [N 1] real
into
d_eta = ( ((eta(1)-a(1))^2) + ((eta(2)-a(2))^2) ) ^ (0.5);
then matlabFunction() is able to finish execution and the subsequent integration works fine (well, at least it runs, I’m still trying to come up with a verification case). This is obviously not an ideal solution as I’d like to be able to handle the n-dimensional case, so I’m trying to understand what is happening under the hood in the norm function.
I think the abs() function that is used in the norm() function is what is causing the issue – MATLAB is trying to create piecewise functions for it. What is the best way to have MATLAB understand that eta and a are real, and it can remove the abs() function?
For instance, why does the following work in simplifying norm:
>> syms a b real
>> c = norm(a-b)
c =
(abs(a – b)^2)^(1/2)
>> simplify(c)
ans =
abs(a – b)
But not this?:
>> syms a [2 1] real
>> syms b [2 1] real
>> c = norm(a-b)
c =
(abs(a1 – b1)^2 + abs(a2 – b2)^2)^(1/2)
>> simplify(c)
ans =
(abs(a1 – b1)^2 + abs(a2 – b2)^2)^(1/2)
However, this works:
>> syms a [2 1] real
>> syms b [2 1] real
>> syms c
>> c = norm(a-b)
c =
(abs(a1 – b1)^2 + abs(a2 – b2)^2)^(1/2)
>> rewrite(c,"sqrt")
ans =
((a1 – b1)^2 + (a2 – b2)^2)^(1/2)
Would it be "safe" to use rewrite to overcome this issue? Are there any nuanced differences between these (particularly which could impact the subsequent integration)? symbolic, mathematics, differential equations MATLAB Answers — New Questions