%feature("docstring") OT::IteratedQuadrature
"Multivariate integration algorithm.

Parameters
----------
univariateQuadrature : :class:`~openturns.IntegrationAlgorithm`
    By default, the integration algorithm is the Gauss-Kronrod algorithm (:class:`~openturns.GaussKronrod`)  with the following parameters: maximumSubIntervals=32, maximumError= :math:`1e-7` and GKRule = G3K7. 
    Note that the default parametrisation of the :class:`~openturns.GaussKronrod` class leads to a more precise evaluation of the integral but the cost is greater. It is recommended to increase the order of the quadratic rule and the number of sub intervals if the integrand or one of the bound functions is smooth but with many oscillations. 

Notes
-----
This class enables to approximate the following integral:

.. math::

    I_f = \int_{a}^{b}\, \int_{l_1(x_0)}^{u_1(x_0)}\, \int_{l_2(x_0, x_1)}^{u_2(x_0,x_1)}\, \int_{l_{n-1}(x_0, \dots, x_{n-2})}^{u_{n-1}(x_0, \dots, x_{n-2})} \, f(x_0, \dots, x_{n-1})\di{x_{n-1}}\dots\di{x_0}

with :math:`f: \Rset^n \mapsto \Rset^p`, :math:`l_k, u_k: \Rset^k \mapsto \Rset` and :math:`n\geq 1`. For :math:`n=1`, there is no bound functions :math:`l_k` and :math:`u_k`.


Examples
--------
Create an iterated quadrature algorithm:

>>> import openturns as ot
>>> import math as m
>>> a = -m.pi
>>> b = m.pi
>>> f = ot.SymbolicFunction(['x', 'y'], ['1+cos(x)*sin(y)'])
>>> l = [ot.SymbolicFunction(['x'], [' 2+cos(x)'])]
>>> u = [ot.SymbolicFunction(['x'], ['-2-cos(x)'])]

Draw the graph of the integrand and the bounds:

>>> g = ot.Graph('Integration nodes', 'x', 'y', True, 'topright')
>>> g.add(f.draw([a,a],[b,b]))
>>> curve = l[0].draw(a, b).getDrawable(0)
>>> curve.setLineWidth(2)
>>> curve.setColor('red')
>>> g.add(curve)
>>> curve = u[0].draw(a, b).getDrawable(0)
>>> curve.setLineWidth(2)
>>> curve.setColor('red')
>>> g.add(curve)

Evaluate the integral with high precision:

>>> Iref = ot.IteratedQuadrature(ot.GaussKronrod(100000, 1e-13, ot.GaussKronrodRule(ot.GaussKronrodRule.G11K23))).integrate(f, a, b, l, u)

Evaluate the integral with the default GaussKronrod algorithm:

>>> f.enableHistory()
>>> I1 = ot.IteratedQuadrature(ot.GaussKronrod()).integrate(f, a, b, l, u)
>>> sample1 = f.getHistoryInput().getSample()
>>> print(I1)
[-25.132...]
>>> n_evals = sample1.getSize()
>>> print(n_evals)
2116
>>> err = abs(100.0*(1.0-I1[0]/Iref[0]))
>>> print(err)
2.2...e-14
>>> cloud = ot.Cloud(sample1)
>>> cloud.setPointStyle('fcircle')
>>> cloud.setColor('green')
>>> g.add(cloud)
>>> f.clearHistory()

Evaluate the integral with the default IteratedQuadrature algorithm:

>>> I2 = ot.IteratedQuadrature().integrate(f, a, b, l, u)
>>> sample2 = f.getHistoryInput().getSample()
>>> print(I2)
[-25.132...]
>>> n_evals = sample2.getSize()
>>> print(n_evals)
5236
>>> err = abs(100.0*(1.0-I2[0]/Iref[0]))
>>> print(err)
4.6...e-10
>>> cloud = ot.Cloud(sample2)
>>> cloud.setPointStyle('fcircle')
>>> cloud.setColor('gold')
>>> g.add(cloud)"

// ---------------------------------------------------------------------

%feature("docstring") OT::IteratedQuadrature::integrate
"Evaluation of the integral of :math:`f` on a domain.

Available usages:
    integrate(*f, interval*)

    integrate(*f, a, b, lowerBoundFunctions, upperBoundFunctions*)

Parameters
----------
f : :class:`~openturns.Function`, :math:`f: \Rset^n \mapsto \Rset^p`
    The integrand function.
interval : :class:`~openturns.Interval`, :math:`interval \in \Rset^n` 
    The integration domain. 
a,b : float 
    Bounds of the integration interval of the first scalar input :math:`x_0`
lowerBoundFunctions, upperBoundFunctions : list of :class:`~openturns.Function`
    List of :math:`n` functions :math:`(l_0, \dots, l_{n-1})` and :math:`(u_0, \dots, u_{n-1})` where :math:`l_k, u_k: \Rset^k \mapsto \Rset` defining the integration domain as defined above.
    The bound functions can cross each other. 

Returns
-------
value : :class:`~openturns.Point`
    Approximation of the integral."

