Why I am not getting the same result for an integral of a piecewise function?

1 vue (au cours des 30 derniers jours)
I set the following piecewise function to integrate it:
function lambda = weight(x,L1,L2,M)
% L1, L2, M are constants
if x < L1
lambda = (M ./ (4 .* (L1 + L2))) + ((3 .* M) / (2 .* L2 .^ 2)) .* (L1 - x);
else
lambda = M ./ (4 .* (L1 + L2)) .* ones(size(x));
end
end
Now, I am trying to integrate lambda between 0 and 15. Everything looks okay, but the results are different when I try to integrate the whole interval than when I do it by sections. In the following code, check should be 0 or near to 0, but I am getting 5.1042e+03.
lambda = @(x) weight(x,5,10,35000);
aux1 = integral(lambda,0,15)
aux2 = integral(lambda,0,5)
aux3 = integral(lambda,5,15)
check1 = aux1 - aux2 + aux3
Does anyone know what is the issue here?
I know it work fine by sections but I would like it to do it as a whole.

Réponse acceptée

Dyuman Joshi
Dyuman Joshi le 29 Mai 2024
Modifié(e) : Dyuman Joshi le 29 Mai 2024
1 - It should be aux1 - (aux2 + aux3)
2 - The function is not vectorized properly, which provides incorrect results. I have modified the function to include vectorization, see below -
lambda = @(x) weightvec(x,5,10,35000);
aux1 = integral(lambda,0,15)
aux1 = 1.5313e+04
aux2 = integral(lambda,0,5)
aux2 = 9.4792e+03
aux3 = integral(lambda,5,15)
aux3 = 5.8333e+03
check1 = aux1 - (aux2 + aux3)
check1 = 0.0027
This is a numerical answer with relatively low accuracy i.e. the value is near 0. (You can increase the accuracy, but only upto a certain value/limit - Refer to the documentation of integral for more information regarding this)
Let's try it symbolically utilizing the piecewise function -
L1 = 5; L2 = 10; M = 35000;
syms x
y = piecewise(x<L1, (M ./ (4 .* (L1 + L2))) + ((3 .* M) / (2 .* L2 .^ 2)) .* (L1 - x), ...
M ./ (4 .* (L1 + L2)));
aux1 = int(y,x,0,15);
aux2 = int(y,x,0,5);
aux3 = int(y,x,5,15);
out = aux1 - (aux2+aux3)
out = 
0
Well, as expected.
%Function with vectorization
function lambda = weightvec(x,L1,L2,M)
lambda = zeros(size(x));
idx = x < L1;
lambda(idx) = (M ./ (4 .* (L1 + L2))) + ((3 .* M) / (2 .* L2 .^ 2)) .* (L1 - x(idx));
lambda(~idx) = M ./ (4 .* (L1 + L2)) .* ones(1,nnz(~idx));
end

Plus de réponses (1)

the cyclist
the cyclist le 29 Mai 2024
You have two mistakes in this code. First, you got the signs wrong on the check. It should be
check1 = aux1 - (aux2 + aux3)
Second, the syntax
if x < L1
is probably not doing what you expect. If x is a vector, this is not going to check each element of x against L1, and calculate the corresponding lambda accordingly. It will only go into the "if" portion of the code when all the elements of x are less than L1.
  2 commentaires
the cyclist
the cyclist le 29 Mai 2024
The following is not the most efficient, but I wanted to show that looping over x will give the correct result. (I also changed the relative tolerance, to show that you get very close to zero.)
lambda = @(x) weight(x,5,10,35000);
aux1 = integral(lambda,0,15,"RelTol",1e-12)
aux1 = 1.5312e+04
aux2 = integral(lambda,0,5,"RelTol",1e-12)
aux2 = 9.4792e+03
aux3 = integral(lambda,5,15,"RelTol",1e-12)
aux3 = 5.8333e+03
check1 = aux1 - (aux2 + aux3)
check1 = -1.7499e-09
function lambda = weight(x,L1,L2,M)
lambda = zeros(size(x));
for n = 1:numel(x)
if x(n) < L1
lambda(n) = (M ./ (4 .* (L1 + L2))) + ((3 .* M) ./ (2 .* L2 .^ 2)) .* (L1 - x(n));
else
lambda(n) = M ./ (4 .* (L1 + L2));
end
end
end
the cyclist
the cyclist le 29 Mai 2024
Here is a more efficient version of your function:
function lambda = weight(x,L1,L2,M)
% L1, L2, M are constants
lambda = (M ./ (4 .* (L1 + L2))) + (x<L1).*((3 .* M) ./ (2 .* L2 .^ 2)) .* (L1 - x);
end

Connectez-vous pour commenter.

Catégories

En savoir plus sur Install Products dans Help Center et File Exchange

Produits


Version

R2024a

Community Treasure Hunt

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

Start Hunting!

Translated by