Search code examples
matlabnumerical-integrationintegralfunction-handle

Nested call to integral fails


Try this piece of code, which works fine.

a=1;b=2;
% A two-variate function 
f2= @(x,y) x+y;
derivedF2=@(x) integral(@(y) f2(x,y), a,b);
% Test the evaluation of the derived function handle
derivedF2(0);
% Test the integration of the derived function handle
% integralVal=integral(derivedF2,a,b);
% integralVal=integral(@(x) derivedF2(x),a,b);
% Test plotting of the derived function handle
figure(11);
ezplot(derivedF2);

But if you uncomment the lines starting with integralVal. The code breaks.

Apparently, the derived function handle does not support integration operation, or have I missed something?


Solution

  • Short answer: you should add the 'ArrayValued' option:

    integralVal=integral(derivedF2,a,b, 'ArrayValued', true);
    

    Explanation

    You should read your error message:

    Output of the function must be the same size as the input. If FUN is an array-valued integrand, set the 'ArrayValued' option to true.

    Because derivedF2 is evaluated in a vectorised way, i.e. it evaluates f at different y coordinates at once by supplying a y vector instead of a single scalar, MATLAB is unable to evaluate the outer integral in a vectorised way too. Therefore you should add the 'ArrayValued' option to the outer integral, i.e.:

    integralVal=integral(derivedF2,a,b, 'ArrayValued', true);
    

    Note that ezplot also generate the following related warning:

    Warning: Function failed to evaluate on array inputs; vectorizing the function may speed up its evaluation and avoid the need to loop over array elements.

    Note that the problem is purely related to nested calls to integral, also the following code will result in the same error:

    integralVal=integral(@(x) integral(@(y) f2(x,y), a,b),a,b);
    

    What is an Array Valued function?

    ... a function that accepts a scalar input and returns a vector, matrix, or N-D array output.

    So, @(y) f2(x, y) is an array valued function if x is an array, i.e. it returns an array for a scalar input of y.

    Two possibilities exist to avoid array valued problem:

    • Avoid that @(y) f2(x, y) is an array valued function, i.e. avoid that x is an array. This can be done by indicating that derivedF2 is an array valued function as elaborated above, although - strictly speaking - it is not an array valued function, i.e. the integral should have the same number of outputs and inputs. However, it uses internally an array valued function, i.e. @(x) f2(x, y) is an array valued function as Matlab evaluates by default the integrand in a vectorised way, i.e. it uses a vector for y.

    • Tell Matlab that @(y) f2(x, y) is an array valued function:

      derivedF2=@(x) integral(@(y) f2(x,y), a,b, 'ArrayValued', true);
      

      This may be a more intuitive approach, but is slower as the internal integral is called much often than the external integral.

    An alternative interpretation of Array Valued is that you tell matlab to not use vectorisation, but for this interpretation the name Array Valued is somewhat misleading.