How to integrate within a loop with an interpolating function?

9 views (last 30 days)
Im trying to integrate the Z function in both a numerical and sybolic way but everything I try isnt working, any ideas?
x=(-4:0.05:4);
y=(-4:0.05:4);
[X,Y]=meshgrid(x,y);
Z1=3*(1-X).^2.*exp(-(X.^2)-(Y+1).^2)...
- 10*(X/5-X.^3-Y.^5).*exp(-X.^2-Y.^2)...
- 1/3*exp(-(X+1).^2-Y.^2);
Z2=Zscale*exp(-((X.*X)+(Y.*Y))/(2*sigma.^2));
figure;
for t=0:0.05:1
Z=Z1*(1-t)+Z2*(t);
surf(X,Y,Z)
axis([-4 4 -4 4 -8 8]);
fun=@(X,Y) (Z1*(1-t)+Z2*(t));
num_area=integral2(fun,-4,4,-4,4);
grid on
box on
pause(1.5);
drawnow;
end % for t
  2 Comments
Walter Roberson
Walter Roberson on 17 Mar 2019
Use trapz() twice on Z, once for X and once for Y, to get a numeric estimate of the integral, without doing the integral2() or fun= at all.

Sign in to comment.

Answers (1)

Walter Roberson
Walter Roberson on 18 Mar 2019
You have
x=(-4:0.05:4);
y=(-4:0.05:4);
[X,Y]=meshgrid(x,y);
those put specific numeric arrays into X and Y.
Z1=3*(1-X).^2.*exp(-(X.^2)-(Y+1).^2)...
- 10*(X/5-X.^3-Y.^5).*exp(-X.^2-Y.^2)...
- 1/3*exp(-(X+1).^2-Y.^2);
That does not establish a relationship between X, Y, and Z1: that takes a copy of the specific numeric X and Y as of the time the command is executed, and uses those to calculate specific numeric array Z1 . Z1 will just be a plain numeric array: there will not be any kind of history attached to it of how it was calculated.
Z2=Zscale*exp(-((X.*X)+(Y.*Y))/(2*sigma.^2));
Likewise, that does not establish a relationship between X, Y, and Z2: that takes a copy of the specific numeric X and Y and Zscale and sigma as of the time the command is executed and uses those to calculate specific numeric array Z2 . Z2 will just be a plain numeric array: there will not be any kind of history attached to it of how it was calculated.
figure;
for t=0:0.05:1
Z=Z1*(1-t)+Z2*(t);
The specific numeric Z1 and Z2 will be copied as of the time the command is executed, multiplied by appropriate fractions, generating a specific numeric array Z. Z will just be a plain numeric array: there will not be any kind of history attached to it of how it was calculated.
surf(X,Y,Z)
axis([-4 4 -4 4 -8 8]);
fun=@(X,Y) (Z1*(1-t)+Z2*(t));
When the anonymous function is constructed, the specific numeric Z1 and Z2 and t will be copied as of the time the command is executed, and stored internally inside the function handle along with the formula. If Z1 or Z2 were to change after the anonymous function where created, then there would not be any affect on the function handle, which will continue to use the versions that were saved with the function handle. There will not be any kind of history attached to the saved Z1, Z2, t, or function handle as to how the values were arrived at before that point.
When the anonymous function is executed, the copied Z1, Z2, and t will be retrieved and the calculation will be done, always getting the same result since the two input arguments X and Y are not present in the formula.
In particular, the X and Y parameters that the user passes to the function handle will not refer back to the X and Y used to calculate Z1 and Z2. Z1 and Z2 will not be implicitly recalculated based upon the X and Y values passed in. The Z1 and Z2 you constructed are not formulas, they are plain numeric!
num_area=integral2(fun,-4,4,-4,4);
Because the function handle you constructed ignores the input values, the best you could hope for in the above integral2 call would be for it to be effectively integrating a constant. However, the value it calculates, (Z1*(1-t)+Z2*(t)) is 2D of fixed size, and the function called by integral2 needs to accept two arrays of varying size and calculate results for each corresponding location, so integral2 would notice that the fixed array size would not match the varying size of the arrays it passed in, and would error out.
You are trying to take the integral of a numeric array of fixed size. You cannot do that. You have several choices:
  1. Use trapz() or other similar numeric integration technique (e.g., Simpson's rule) to do a numeric integration. This would calculate the volume for the exact same surface that was displayed; or
  2. rewrite your code so that it uses symbolic variables to create formula for Z1, Z2, and do symbolic integration, possibly using fsurf() instead of surf(). This would potentially integrate indefinitely precisely, at higher resolution than the surface that is displayed; or
  3. rewrite your code so it uses function handles to create formula for Z1 and Z2, and used integral2() to calculate the integral, and alter the way you generate the graphics for display. This woul integrate to numeric tolerances, at higher resolution than the surface is displayed; or
  4. Recognized that integration is a linear process. integral A*X + B*Y is A*integral(X) + B*integral(Y) . Therefore you do not need to repeatedly integral2. You can integral2 once for Z1 and once for Z2, and then inside your loop you would just calculate the area of the current display as (1-t)*integral_of_Z1 + t*integral_of_Z2

Community Treasure Hunt

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

Start Hunting!