Why receive error Integrand output size does not match the input size?

Where is the problem?
clear
syms x y
f=0*x*y;
Hf = matlabFunction(f,'Vars',[x y])
Hf = function_handle with value:
@(x,y)0.0
integral2(Hf,-1,1,-1,1);
Error using integral2Calc>integral2t/tensor
Integrand output size does not match the input size.

Error in integral2Calc>integral2t (line 55)
[Qsub,esub] = tensor(thetaL,thetaR,phiB,phiT);

Error in integral2Calc (line 9)
[q,errbnd] = integral2t(fun,xmin,xmax,ymin,ymax,optionstruct);

Error in integral2 (line 105)
Q = integral2Calc(fun,xmin,xmax,yminfun,ymaxfun,opstruct);

 Accepted Answer

x and y that are inputs to Hf from integral2 are usually matrices (of the same size).
The output of Hf is expected to be of the same size as x (or y).
Thus if you only return 0 (a scalar value which is usually not of the same size as x (or y)), you get an error message.
Since I saw the typical functions you want to integrate are that complicated that this problem would never occur, I didn't include this simple case in my answer.
But if you want to cover the special case of a constant function, too, use
syms x y
f=0*x*y;
Hf = matlabFunction(f,'Vars',[x y])
Hf = function_handle with value:
@(x,y)0.0
Hf = @(x,y)Hf(x,y).*ones(size(x))
Hf = function_handle with value:
@(x,y)Hf(x,y).*ones(size(x))
integral2(Hf,-1,1,-1,1)
ans = 0

4 Comments

what about if f is a N*1 vector??
syms x y
f=[0*x*y;0*x;0*y;0];
Hf = matlabFunction(f,'Vars',[x y])
Hf = function_handle with value:
@(x,y)[0.0;0.0;0.0;0.0]
Hf = @(x,y)Hf(x,y).*ones(size(x))
Hf = function_handle with value:
@(x,y)Hf(x,y).*ones(size(x))
integral2(Hf,-1,1,-1,1)
Arrays have incompatible sizes for this operation.

Error in solution (line 4)
Hf = @(x,y)Hf(x,y).*ones(size(x))

Error in integral2Calc>integral2t/tensor (line 228)
Z = FUN(X,Y); NFE = NFE + 1;

Error in integral2Calc>integral2t (line 55)
[Qsub,esub] = tensor(thetaL,thetaR,phiB,phiT);

Error in integral2Calc (line 9)
[q,errbnd] = integral2t(fun,xmin,xmax,ymin,ymax,optionstruct);

Error in integral2 (line 105)
Q = integral2Calc(fun,xmin,xmax,yminfun,ymaxfun,opstruct);
Suppose integral2() was exploring a fine detail and got down to the point where it only needed to know one more value, so it called Hf(0.8342,-0.35) . Then by the rules of integral2() the function must return something the same size as the inputs; with the inputs being scalar the function must return a scalar. But you want the function to return a vector of four elements. That is not compatible with using integral2.
Now suppose that the input was a 2 x 1 array for xx and yy. When expressions are converted, * converts to .* so 0*x*y would be treated like 0.*x.*y and if that were not optimized out of existence ahead of time, with the 2 x 1 input that component would generate a 2 x 1 result, as would 0*x and 0*y . But the 0 you have for the last component would return a scalar 0. [2 x 1; 2 x 1; 2 x 1; 1 x 1] is an error.
I wonder why you go into these specialities and make things so complicated.
If you want to apply integral2 to each component of a vector-values function, use a (parfor) loop over its components.
I used a (parfor) loop over its components, but receved error when the components are zero valued.

Sign in to comment.

More Answers (1)

If you have f, a symbolic expression nominally in x and y, but which might in practice turn out to be independent of both x and y and so matlabFunction() will not vectorize, then you have three options.
First, you can do what @Torsten showed, of multiplying the output by ones() to do implicit expansion.
Second, you can use
Hf = matlabFunction(f,'Vars',[x y]);
wrapper = @(X,Y) arrayfun(Hf, X, Y);
result = integral2(wrapper, -1, 1, -1, 1);
Third, you can use
xlow = -1; xhigh = 1;
ylow = -1; yhigh = 1;
if isempty(symvar(f))
result = double(f) .* (xhigh - xlow) .* (yhigh - ylow);
else
Hf = matlabFunction(f, 'vars', [x, y]);
result = integral2(Hf, xlow, xhigh, ylow, yhigh);
end
as there is no need to call an integration function for a result so simple.

9 Comments

If you are looping over multiple expressions then (xhigh - xlow) .* (yhigh - ylow) could be pre-computed, making the calculation even more simple.
using your first method I faced error:
function kdl = ali(M)
syms x y
H=[0*x*y;0*x;0*y;0];
parfor i=1:M
Hf = matlabFunction(H(i),'Vars',[x y]);
wrapper = @(x,y) arrayfun(Hf, x, y);
kdl (i)= integral2(wrapper,-1,1,-1,1);
end
run
ali(4)
Analyzing and transferring files to the workers ...done.
Error using ali (line 4)
The source code (E:\...\ali.m) for the parfor-loop that is trying to execute on the
worker could not be found.
Caused by:
Unrecognized function or variable 'x'.
Error using remoteParallelFunction (line 94)
Worker unable to find file.
Unrecognized function or variable 'x'.
Hf = matlabFunction(H(i),'Vars',[xx yy]);
According to your question, your variables are named x and y not xx and yy
you do not need to use the same variable names there as you use in the
wrapper = @(xx,yy) arrayfun(Hf, xx, yy);
line. The inputs to the wrapper functions will be entire arrays, and the arrayfun will cause Hf to be invoked on individual values selected out of xx and yy . So your Hf will be passed scalar values x, y, whereas wrapper will be passed arrays.
If this is not sufficiently clear you could write
wrapper = @(xx,yy) arrayfun(@(x,y)Hf(x,y), xx, yy);
but that would be less efficient than
wrapper = @(xx,yy) arrayfun(Hf, xx, yy);
when I put parfor loop in ali function I faced error. Without defining function it works well, but within function faced error
Please post code the reproduces the problem -- code that we can execute.
Here the code you can execute:
function kdl = ali(M)
syms xy
H=[0*x*y;0*x;0*y;0];
parfor i=1:M
Hf = matlabFunction(H(i), 'Vars' ,[xy]);
wrapper = @(x,y) arrayfun(Hf, x, y);
kdl(i)= integral2(wrapper,-1,1,-1,1);
end
just call and faced error:
ali(4)
Maybe this serves your purpose since all the functions you considered until now were complicated functions of x and y.
I don't know the MATLAB internals and the cause of the error if the x and/or y argument to integral2 come into play.
kdl = ali(3)
Starting parallel pool (parpool) using the 'Processes' profile ... Connected to the parallel pool (number of workers: 2).
kdl = 1×3
1.0e-13 * 0 -0.0002 0.7602
function kdl = ali(M)
syms x y
H=[x*y;x*y^2;x^2*y];
parfor i=1:M
Hf = matlabFunction(H(i));
kdl(i)= integral2(Hf,-1,1,-1,1);
end
end
Do not use syms within a parfor loop. syms is not a "keyword", it is a MATLAB function, and it creates variables by using assignin('caller'), not through MATLAB having any special knowledge. That is a problem in parfor because parfor needs to see clearly where variables are created, but parfor does not know that syms creates variables.
ali()
function kdl = ali()
x = sym('x');
y = sym('y');
H=[0*x*y;0*x;0*y;0;x*y];
parfor i=1:length(H)
Hf = matlabFunction(H(i), 'Vars' ,[x y]);
wrapper = @(x,y) arrayfun(Hf, x, y);
kdl(i)= integral2(wrapper,-1,1,-1,1);
end
end

Sign in to comment.

Products

Release

R2021b

Asked:

on 20 Jan 2023

Commented:

on 22 Jan 2023

Community Treasure Hunt

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

Start Hunting!